diff --git a/.conform.yaml b/.conform.yaml new file mode 100644 index 0000000000..f96e4e0940 --- /dev/null +++ b/.conform.yaml @@ -0,0 +1,16 @@ +--- +policies: + - type: commit + spec: + header: + length: 80 + imperative: false + invalidLastCharacters: . + body: + required: false + dco: true + gpg: + required: true + spellcheck: + locale: US + maximumOfOneCommit: false diff --git a/.github/scripts/build-ipxe.sh b/.github/scripts/build-ipxe.sh new file mode 100755 index 0000000000..399fb3f31c --- /dev/null +++ b/.github/scripts/build-ipxe.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +export CROSS_COMPILE="x86_64-elf-" +make -C src bin-x86_64-efi-sb/ipxe.efi EMBED=$PWD/dasharo.ipxe BUILD_ID_CMD="echo 0x1234567890" \ + EXTRA_CFLAGS="-Wno-address-of-packed-member -m64 -fuse-ld=bfd \ + -Wl,--build-id=none -fno-delete-null-pointer-checks -Wlogical-op -march=nocona \ + -malign-data=abi -mcmodel=large -mno-red-zone -fno-pic" + diff --git a/.github/scripts/build-qemu.sh b/.github/scripts/build-qemu.sh new file mode 100755 index 0000000000..6c7abeb5c4 --- /dev/null +++ b/.github/scripts/build-qemu.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +make -C BaseTools +source ./edksetup.sh + +export EDK2_PLATFORMS_PATH="$WORKSPACE/edk2-platforms" +export PACKAGES_PATH="$WORKSPACE:\ +$WORKSPACE/ipxe/src/bin-x86_64-efi-sb:\ +$EDK2_PLATFORMS_PATH/Platform/Intel:\ +$EDK2_PLATFORMS_PATH/Silicon/Intel:\ +$EDK2_PLATFORMS_PATH/Features/Intel:\ +$EDK2_PLATFORMS_PATH/Features/Intel/Debugging:\ +$EDK2_PLATFORMS_PATH/Features/Intel/Network:\ +$EDK2_PLATFORMS_PATH/Features/Intel/OutOfBandManagement:\ +$EDK2_PLATFORMS_PATH/Features/Intel/PowerManagement:\ +$EDK2_PLATFORMS_PATH/Features/Intel/SystemInformation:\ +$EDK2_PLATFORMS_PATH/Features/Intel/UserInterface" + +build -a IA32 -a X64 -t GCC5 -b RELEASE -p OvmfPkg/OvmfPkgX64.dsc +build -a IA32 -a X64 -t GCC5 -b DEBUG -p OvmfPkg/OvmfPkgX64.dsc diff --git a/.github/scripts/run-qemu.sh b/.github/scripts/run-qemu.sh new file mode 100755 index 0000000000..4a2e44a38c --- /dev/null +++ b/.github/scripts/run-qemu.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +cp ./Build/OvmfX64/RELEASE_GCC5/FV/OVMF_VARS.fd /tmp/OVMF_VARS.fd + +q35_params="-machine q35,smm=on \ + -global driver=cfi.pflash01,property=secure,value=on \ + -drive if=pflash,format=raw,unit=0,file=Build/OvmfX64/RELEASE_GCC5/FV/OVMF_CODE.fd,readonly=on \ + -drive if=pflash,format=raw,unit=1,file=/tmp/OVMF_VARS.fd \ + -debugcon file:debug.log -global isa-debugcon.iobase=0x402 \ + -global ICH9-LPC.disable_s3=1 \ + -qmp unix:/tmp/qmp-socket,server,nowait \ + -net none \ + -serial telnet:localhost:1234,server,nowait" + +if [ "$1" == "nographic" ]; then + qemu-system-x86_64 $q35_params -nographic +else + qemu-system-x86_64 $q35_params +fi diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000000..b86b6d4193 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,95 @@ +name: Check EDK2 QEMU Build + +on: + push: + branches: + - dasharo + tags: + - 'qemu_q35_v*' + pull_request: + branches: + - dasharo + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout Code + uses: actions/checkout@v2 + with: + submodules: 'recursive' # Checkout submodules recursively. + + - name: Clone edk2-platforms Repository + run: | + git clone https://github.com/Dasharo/edk2-platforms.git && \ + cd edk2-platforms && \ + git checkout 3323ed481d35096fb6a7eae7b49f35eff00f86cf && \ + cd - + + - name: Clone iPXE Repository + run: | + git clone https://git.ipxe.org/ipxe.git && \ + cd ipxe && \ + git checkout e9a23a5b394f40c1525c40416105eaaa1787f749 && \ + sed -i 's|//#define\s*IMAGE_SCRIPT.*|#define IMAGE_SCRIPT|' "src/config/general.h" && \ + sed -i 's|.*DOWNLOAD_PROTO_HTTPS|#define DOWNLOAD_PROTO_HTTPS|g' "src/config/general.h" && \ + wget https://raw.githubusercontent.com/Dasharo/dasharo-blobs/main/dasharo/dasharo.ipxe && \ + cd - + + - name: Build iPXE + run: | + docker run --rm -i -v $PWD/ipxe:/home/coreboot/ipxe:rw \ + -v $PWD/.github:/home/coreboot/ipxe/.github \ + -u $(id -u):$(id -g) -w /home/coreboot/ipxe \ + coreboot/coreboot-sdk:2024-02-18_732134932b \ + ./.github/scripts/build-ipxe.sh + + - name: Build OVMF Firmware Image + run: | + docker run --rm -i -v $PWD:/home/coreboot/coreboot:rw \ + -u $(id -u):$(id -g) -w /home/coreboot/coreboot \ + coreboot/coreboot-sdk:2024-02-18_732134932b \ + ./.github/scripts/build-qemu.sh + + - name: Check RELEASE build Artifacts + run: | + if [ -f "Build/OvmfX64/RELEASE_GCC5/FV/OVMF_CODE.fd" ] && [ -f "Build/OvmfX64/RELEASE_GCC5/FV/OVMF_VARS.fd" ]; then + echo "RELEASE build successful. OVMF firmware image files found." + cp Build/OvmfX64/RELEASE_GCC5/FV/OVMF_CODE.fd OVMF_CODE_RELEASE.fd + cp Build/OvmfX64/RELEASE_GCC5/FV/OVMF_VARS.fd OVMF_VARS_RELEASE.fd + else + echo "RELEASE build failed. OVMF firmware image files not found." + exit 1 + fi + + - name: Check DEBUG build Artifacts + run: | + if [ -f "Build/OvmfX64/DEBUG_GCC5/FV/OVMF_CODE.fd" ] && [ -f "Build/OvmfX64/DEBUG_GCC5/FV/OVMF_VARS.fd" ]; then + echo "DEBUG build successful. OVMF firmware image files found." + cp Build/OvmfX64/DEBUG_GCC5/FV/OVMF_CODE.fd OVMF_CODE_DEBUG.fd + cp Build/OvmfX64/DEBUG_GCC5/FV/OVMF_VARS.fd OVMF_VARS_DEBUG.fd + else + echo "DEBUG build failed. OVMF firmware image files not found." + exit 1 + fi + + - name: Upload Artifacts + uses: actions/upload-artifact@v4 + with: + name: ovmf-artifacts # Name for the artifact + path: | + OVMF_CODE_RELEASE.fd + OVMF_VARS_RELEASE.fd + OVMF_CODE_DEBUG.fd + OVMF_VARS_DEBUG.fd + + - name: Create GitHub Release + uses: softprops/action-gh-release@v1 + if: startsWith(github.event.ref, 'refs/tags/qemu') + with: + files: | + OVMF_CODE_RELEASE.fd + OVMF_VARS_RELEASE.fd + OVMF_CODE_DEBUG.fd + OVMF_VARS_DEBUG.fd diff --git a/.github/workflows/dbx.yml b/.github/workflows/dbx.yml new file mode 100644 index 0000000000..d135c62081 --- /dev/null +++ b/.github/workflows/dbx.yml @@ -0,0 +1,33 @@ +name: Check if UEFI revocation list is up-to-date + +on: + push: + branches: + - dasharo + pull_request: + branches: + - dasharo + +jobs: + check: + runs-on: ubuntu-latest + + steps: + - name: Checkout Code + uses: actions/checkout@v2 + + - name: Check if DBX is up-to-date + run: | + echo 'Fetching DBX from Microsoft Secure Boot GitHub repository' + wget https://github.com/microsoft/secureboot_objects/raw/refs/heads/main/PostSignedObjects/DBX/amd64/DBXUpdate.bin -o /dev/null + if [ $? -ne 0 ]; then + echo 'Failed to fetch latest DBX.' + exit 1 + fi + diff <(sha256sum DBXUpdate.bin | awk '{ print $1 }') <(sha256sum DasharoPayloadPkg/SecureBootDefaultKeys/DBXUpdate.bin | awk '{ print $1 }') + if [ $? -ne 0 ]; then + echo 'UEFI DBX is out of date.' + exit 1 + else + echo 'UEFI DBX is up-to-date.' + fi diff --git a/.gitmodules b/.gitmodules index 60d54b45eb..3c42ac8b2c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,7 +16,7 @@ [submodule "BaseTools/Source/C/BrotliCompress/brotli"] path = BaseTools/Source/C/BrotliCompress/brotli url = https://github.com/google/brotli - ignore = untracked + ignore = untracked [submodule "RedfishPkg/Library/JsonLib/jansson"] path = RedfishPkg/Library/JsonLib/jansson url = https://github.com/akheron/jansson @@ -25,13 +25,16 @@ url = https://github.com/google/googletest.git [submodule "UnitTestFrameworkPkg/Library/SubhookLib/subhook"] path = UnitTestFrameworkPkg/Library/SubhookLib/subhook - url = https://github.com/Zeex/subhook.git -[submodule "MdePkg/Library/BaseFdtLib/libfdt"] - path = MdePkg/Library/BaseFdtLib/libfdt - url = https://github.com/devicetree-org/pylibfdt.git + url = https://github.com/Dasharo/subhook.git +[submodule "MdePkg/Library/BaseFdtLib/libfdt"] + path = MdePkg/Library/BaseFdtLib/libfdt + url = https://github.com/devicetree-org/pylibfdt.git [submodule "MdePkg/Library/MipiSysTLib/mipisyst"] path = MdePkg/Library/MipiSysTLib/mipisyst url = https://github.com/MIPI-Alliance/public-mipi-sys-t.git [submodule "CryptoPkg/Library/MbedTlsLib/mbedtls"] path = CryptoPkg/Library/MbedTlsLib/mbedtls url = https://github.com/ARMmbed/mbedtls +[submodule "CrScreenshotDxe"] + path = CrScreenshotDxe + url = https://github.com/LongSoft/CrScreenshotDxe.git diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000000..8995266e0e --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,40 @@ +--- +default_stages: [pre-commit] + +default_install_hook_types: [pre-commit, commit-msg] + +ci: + autoupdate_commit_msg: 'pre-commit: autoupdate hooks' + autofix_prs: false + +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: check-added-large-files + files: ^DasharoModulePkg/ + - id: check-merge-conflict + files: ^DasharoModulePkg/ + - id: check-symlinks + files: ^DasharoModulePkg/ + - id: detect-private-key + files: ^DasharoModulePkg/ + - id: end-of-file-fixer + files: ^DasharoModulePkg/ + - id: trailing-whitespace + files: ^DasharoModulePkg/ + - id: mixed-line-ending + files: ^DasharoModulePkg/ + + - repo: https://github.com/talos-systems/conform + rev: v0.1.0-alpha.30 + hooks: + - id: conform + stages: + - commit-msg + + - repo: https://github.com/codespell-project/codespell + rev: v2.4.1 + hooks: + - id: codespell + files: ^DasharoModulePkg/ diff --git a/BaseTools/Source/C/Makefiles/header.makefile b/BaseTools/Source/C/Makefiles/header.makefile index d369908a09..3f9999e820 100644 --- a/BaseTools/Source/C/Makefiles/header.makefile +++ b/BaseTools/Source/C/Makefiles/header.makefile @@ -104,7 +104,7 @@ else CFLAGS = -MD -fshort-wchar -fno-strict-aliasing -fwrapv \ -fno-delete-null-pointer-checks -Wall -Werror \ -Wno-deprecated-declarations -Wno-stringop-truncation -Wno-restrict \ --Wno-unused-result -nostdlib -g +-Wno-unused-result -nostdlib -g -Wno-vla-parameter -Wno-stringop-overflow -Wno-use-after-free -Wno-dangling-pointer endif endif ifneq ($(CLANG),) diff --git a/BaseTools/Source/Python/Capsule/GenerateCapsule.py b/BaseTools/Source/Python/Capsule/GenerateCapsule.py index 35435946c6..a773cfb2b3 100644 --- a/BaseTools/Source/Python/Capsule/GenerateCapsule.py +++ b/BaseTools/Source/Python/Capsule/GenerateCapsule.py @@ -513,11 +513,15 @@ def Validate(self, args): raise argparse.ArgumentTypeError ('JSON field MonotonicCount must be an integer in range 0x0..0xffffffffffffffff') else: raise argparse.ArgumentTypeError ('--monotonic-count must be an integer in range 0x0..0xffffffffffffffff') - if self.UpdateImageIndex >0xFF: + if self.UpdateImageIndex < 0x1 or self.UpdateImageIndex > 0xFF: if args.JsonFile: - raise argparse.ArgumentTypeError ('JSON field UpdateImageIndex must be an integer in range 0x0..0xff') + raise argparse.ArgumentTypeError ('JSON field UpdateImageIndex must be an integer in range 0x1..0xff') else: - raise argparse.ArgumentTypeError ('--update-image-index must be an integer in range 0x0..0xff') + raise argparse.ArgumentTypeError ('--update-image-index must be an integer in range 0x1..0xff') + + if args.Decode: + if args.OutputFile is None: + raise argparse.ArgumentTypeError ('--decode requires --output') if self.UseSignTool: if self.SignToolPfxFile is not None: @@ -576,7 +580,7 @@ def Encode (PayloadDescriptorList, EmbeddedDriverDescriptorList, Buffer): try: SinglePayloadDescriptor.Validate (args) except Exception as Msg: - print ('GenerateCapsule: error:' + str(Msg)) + print ('GenerateCapsule: error: ' + str(Msg)) sys.exit (1) for SinglePayloadDescriptor in PayloadDescriptorList: ImageCapsuleSupport = 0x0000000000000000 @@ -690,7 +694,7 @@ def Decode (PayloadDescriptorList, PayloadJsonDescriptorList, Buffer): args.HardwareInstance, args.UpdateImageIndex, args.SignToolPfxFile, - args.SignSubjectName, + args.SignToolSubjectName, args.OpenSslSignerPrivateCertFile, args.OpenSslOtherPublicCertFile, args.OpenSslTrustedPublicCertFile, @@ -704,7 +708,7 @@ def Decode (PayloadDescriptorList, PayloadJsonDescriptorList, Buffer): try: SinglePayloadDescriptor.Validate (args) except Exception as Msg: - print ('GenerateCapsule: error:' + str(Msg)) + print ('GenerateCapsule: error: ' + str(Msg)) sys.exit (1) try: Result = UefiCapsuleHeader.Decode (Buffer) @@ -827,7 +831,7 @@ def Decode (PayloadDescriptorList, PayloadJsonDescriptorList, Buffer): print ('--------') print ('No EFI_FIRMWARE_IMAGE_AUTHENTICATION') - PayloadSignature = struct.unpack (' len (self._EmbeddedDriverList): - raise ValueError + raise ValueError ('Invalid embedded driver index') return self._EmbeddedDriverList[Index] def AddPayload (self, UpdateImageTypeId, Payload = b'', VendorCodeBytes = b'', HardwareInstance = 0, UpdateImageIndex = 1, CapsuleSupport = 0): @@ -188,7 +188,7 @@ def AddPayload (self, UpdateImageTypeId, Payload = b'', VendorCodeBytes = b'', H def GetFmpCapsuleImageHeader (self, Index): if Index >= len (self._FmpCapsuleImageHeaderList): - raise ValueError + raise ValueError ('Invalid capsule image index') return self._FmpCapsuleImageHeaderList[Index] def Encode (self): @@ -234,14 +234,14 @@ def Encode (self): def Decode (self, Buffer): if len (Buffer) < self._StructSize: - raise ValueError + raise ValueError ('Buffer is too small for decoding') (Version, EmbeddedDriverCount, PayloadItemCount) = \ struct.unpack ( self._StructFormat, Buffer[0:self._StructSize] ) if Version < self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION: - raise ValueError + raise ValueError ('Incorrect capsule header version') self.Version = Version self.EmbeddedDriverCount = EmbeddedDriverCount @@ -258,7 +258,7 @@ def Decode (self, Buffer): for Index in range (0, EmbeddedDriverCount + PayloadItemCount): ItemOffset = struct.unpack (self._ItemOffsetFormat, Buffer[Offset:Offset + self._ItemOffsetSize])[0] if ItemOffset >= len (Buffer): - raise ValueError + raise ValueError ('Item offset is outside of buffer') self._ItemOffsetList.append (ItemOffset) Offset = Offset + self._ItemOffsetSize Result = Buffer[Offset:] @@ -297,7 +297,7 @@ def Decode (self, Buffer): def DumpInfo (self): if not self._Valid: - raise ValueError + raise ValueError ('Can not dump an invalid header') print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.Version = {Version:08X}'.format (Version = self.Version)) print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.EmbeddedDriverCount = {EmbeddedDriverCount:08X}'.format (EmbeddedDriverCount = self.EmbeddedDriverCount)) for EmbeddedDriver in self._EmbeddedDriverList: diff --git a/CrScreenshotDxe b/CrScreenshotDxe new file mode 160000 index 0000000000..cf2fc003bf --- /dev/null +++ b/CrScreenshotDxe @@ -0,0 +1 @@ +Subproject commit cf2fc003bf08a4badc3efe3540c109fa88fb0008 diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h index a52bd91ad6..4dc12346e9 100644 --- a/CryptoPkg/Include/Library/BaseCryptLib.h +++ b/CryptoPkg/Include/Library/BaseCryptLib.h @@ -2234,6 +2234,8 @@ Pkcs7FreeSigners ( unchained to the signer's certificates. The input signed data could be wrapped in a ContentInfo structure. + Pkcs7GetCertificatesList has not been implemented in BaseCryptoLibMbedTls. + @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 @@ -3022,6 +3024,8 @@ DhComputeKey ( If Seed is NULL, then default seed is used. If this interface is not supported, then return FALSE. + RandomSeed has not been implemented in BaseCryptoLibMbedTls. + @param[in] Seed Pointer to seed value. If NULL, default seed is used. @param[in] SeedSize Size of seed value. diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf index d10c83b53c..20297cd229 100644 --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf @@ -81,7 +81,6 @@ BaseMemoryLib MemoryAllocationLib DebugLib - OpensslLib IntrinsicLib PrintLib PeiServicesTablePointerLib diff --git a/CryptoPkg/Library/BaseCryptLib/SysCall/TimerWrapper.c b/CryptoPkg/Library/BaseCryptLib/SysCall/TimerWrapper.c index 2dfc6fe6c5..f51bf2caae 100644 --- a/CryptoPkg/Library/BaseCryptLib/SysCall/TimerWrapper.c +++ b/CryptoPkg/Library/BaseCryptLib/SysCall/TimerWrapper.c @@ -135,7 +135,8 @@ gmtime ( const time_t *timer ) { - struct tm *GmTime; + STATIC struct tm GmTime; + UINT64 DayNo; UINT64 DayRemainder; time_t Year; @@ -148,23 +149,18 @@ gmtime ( return NULL; } - GmTime = malloc (sizeof (struct tm)); - if (GmTime == NULL) { - return NULL; - } - - ZeroMem ((VOID *)GmTime, (UINTN)sizeof (struct tm)); + ZeroMem ((VOID *)&GmTime, (UINTN)sizeof (GmTime)); DayNo = (UINT64)DivS64x64Remainder (*timer, SECSPERDAY, &Remainder); DayRemainder = (UINT64)Remainder; DivS64x64Remainder (DayRemainder, SECSPERMIN, &Remainder); - GmTime->tm_sec = (int)Remainder; + GmTime.tm_sec = (int)Remainder; DivS64x64Remainder (DayRemainder, SECSPERHOUR, &Remainder); - GmTime->tm_min = (int)DivS64x64Remainder (Remainder, SECSPERMIN, NULL); - GmTime->tm_hour = (int)DivS64x64Remainder (DayRemainder, SECSPERHOUR, NULL); + GmTime.tm_min = (int)DivS64x64Remainder (Remainder, SECSPERMIN, NULL); + GmTime.tm_hour = (int)DivS64x64Remainder (DayRemainder, SECSPERHOUR, NULL); DivS64x64Remainder ((DayNo + 4), 7, &Remainder); - GmTime->tm_wday = (int)Remainder; + GmTime.tm_wday = (int)Remainder; for (Year = 1970, YearNo = 0; DayNo > 0; Year++) { TotalDays = (UINT32)(IsLeap (Year) ? 366 : 365); @@ -176,8 +172,8 @@ gmtime ( } } - GmTime->tm_year = (int)(YearNo + (1970 - 1900)); - GmTime->tm_yday = (int)DayNo; + GmTime.tm_year = (int)(YearNo + (1970 - 1900)); + GmTime.tm_yday = (int)DayNo; for (MonthNo = 12; MonthNo > 1; MonthNo--) { if (DayNo >= CumulativeDays[IsLeap (Year)][MonthNo]) { @@ -186,12 +182,12 @@ gmtime ( } } - GmTime->tm_mon = (int)MonthNo - 1; - GmTime->tm_mday = (int)DayNo + 1; + GmTime.tm_mon = (int)MonthNo - 1; + GmTime.tm_mday = (int)DayNo + 1; - GmTime->tm_isdst = 0; - GmTime->tm_gmtoff = 0; - GmTime->tm_zone = NULL; + GmTime.tm_isdst = 0; + GmTime.tm_gmtoff = 0; + GmTime.tm_zone = NULL; - return GmTime; + return &GmTime; } diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/BaseCryptLib.inf b/CryptoPkg/Library/BaseCryptLibMbedTls/BaseCryptLib.inf index 16def792c5..4ef40e81cf 100644 --- a/CryptoPkg/Library/BaseCryptLibMbedTls/BaseCryptLib.inf +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/BaseCryptLib.inf @@ -17,7 +17,8 @@ FILE_GUID = 693C5308-AF95-4CE5-ADE9-CA011C2FC642 MODULE_TYPE = DXE_DRIVER VERSION_STRING = 1.0 - LIBRARY_CLASS = BaseCryptLib|DXE_DRIVER DXE_CORE UEFI_APPLICATION UEFI_DRIVER + LIBRARY_CLASS = BaseCryptLib|DXE_DRIVER DXE_CORE DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER + DEFINE BASE_CRYPT_PATH = ../BaseCryptLib # # The following information is for reference only and not required by the build tools. @@ -27,33 +28,39 @@ [Sources] InternalCryptLib.h - Cipher/CryptAeadAesGcmNull.c - Cipher/CryptAes.c - Hash/CryptSha256.c - Hash/CryptSha512.c - Hash/CryptParallelHashNull.c - Hash/CryptSm3Null.c Hash/CryptMd5.c Hash/CryptSha1.c + Hash/CryptSha256.c + Hash/CryptSha512.c + $(BASE_CRYPT_PATH)/Hash/CryptCShake256.c + $(BASE_CRYPT_PATH)/Hash/CryptDispatchApDxe.c + $(BASE_CRYPT_PATH)/Hash/CryptParallelHash.c + $(BASE_CRYPT_PATH)/Hash/CryptSha3.c + $(BASE_CRYPT_PATH)/Hash/CryptSm3.c + $(BASE_CRYPT_PATH)/Hash/CryptXkcp.c Hmac/CryptHmac.c Kdf/CryptHkdf.c + Cipher/CryptAes.c + Cipher/CryptAeadAesGcm.c Pk/CryptRsaBasic.c - Pk/CryptRsaExtNull.c - Pk/CryptRsaPss.c - Pk/CryptRsaPssSignNull.c - Bn/CryptBnNull.c - Pem/CryptPemNull.c + Pk/CryptRsaExt.c + Pk/CryptPkcs1Oaep.c + Pk/CryptPkcs5Pbkdf2.c + Pk/CryptPkcs7Sign.c + Pk/CryptPkcs7VerifyCommon.c + Pk/CryptPkcs7VerifyBase.c + Pk/CryptPkcs7VerifyEku.c Pk/CryptDhNull.c + Pk/CryptX509.c + Pk/CryptAuthenticode.c + Pk/CryptTs.c + Pk/CryptRsaPss.c + Pk/CryptRsaPssSign.c Pk/CryptEcNull.c - Pk/CryptPkcs1OaepNull.c - Pk/CryptPkcs5Pbkdf2Null.c - Pk/CryptPkcs7SignNull.c - Pk/CryptPkcs7VerifyNull.c - Pk/CryptPkcs7VerifyEkuNull.c - Pk/CryptX509Null.c - Pk/CryptAuthenticodeNull.c - Pk/CryptTsNull.c - Rand/CryptRandNull.c + Pem/CryptPem.c + Bn/CryptBnNull.c + Rand/CryptRand.c + SysCall/CrtWrapper.c SysCall/TimerWrapper.c @@ -72,6 +79,7 @@ IntrinsicLib RngLib SynchronizationLib + MbedTlsCrtLib [Protocols] gEfiMpServiceProtocolGuid # diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Cipher/CryptAeadAesGcm.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Cipher/CryptAeadAesGcm.c new file mode 100644 index 0000000000..b49d6f9f87 --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Cipher/CryptAeadAesGcm.c @@ -0,0 +1,227 @@ +/** @file + AEAD (AES-GCM) Wrapper Implementation over MbedTLS. + + RFC 5116 - An Interface and Algorithms for Authenticated Encryption + NIST SP800-38d - Cipher Modes of Operation: Galois / Counter Mode(GCM) and GMAC + +Copyright (c) 2024, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "InternalCryptLib.h" +#include + +/** + Performs AEAD AES-GCM authenticated encryption on a data buffer and additional authenticated data (AAD). + + IvSize must be 12, otherwise FALSE is returned. + KeySize must be 16, 24 or 32, otherwise FALSE is returned. + TagSize must be 12, 13, 14, 15, 16, otherwise FALSE is returned. + + @param[in] Key Pointer to the encryption key. + @param[in] KeySize Size of the encryption key in bytes. + @param[in] Iv Pointer to the IV value. + @param[in] IvSize Size of the IV value in bytes. + @param[in] AData Pointer to the additional authenticated data (AAD). + @param[in] ADataSize Size of the additional authenticated data (AAD) in bytes. + @param[in] DataIn Pointer to the input data buffer to be encrypted. + @param[in] DataInSize Size of the input data buffer in bytes. + @param[out] TagOut Pointer to a buffer that receives the authentication tag output. + @param[in] TagSize Size of the authentication tag in bytes. + @param[out] DataOut Pointer to a buffer that receives the encryption output. + @param[out] DataOutSize Size of the output data buffer in bytes. + + @retval TRUE AEAD AES-GCM authenticated encryption succeeded. + @retval FALSE AEAD AES-GCM authenticated encryption failed. + +**/ +BOOLEAN +EFIAPI +AeadAesGcmEncrypt ( + IN CONST UINT8 *Key, + IN UINTN KeySize, + IN CONST UINT8 *Iv, + IN UINTN IvSize, + IN CONST UINT8 *AData, + IN UINTN ADataSize, + IN CONST UINT8 *DataIn, + IN UINTN DataInSize, + OUT UINT8 *TagOut, + IN UINTN TagSize, + OUT UINT8 *DataOut, + OUT UINTN *DataOutSize + ) +{ + mbedtls_gcm_context Ctx; + INT32 Ret; + + if (DataInSize > INT_MAX) { + return FALSE; + } + + if (ADataSize > INT_MAX) { + return FALSE; + } + + if (IvSize != 12) { + return FALSE; + } + + switch (KeySize) { + case 16: + case 24: + case 32: + break; + default: + return FALSE; + } + + if ((TagSize != 12) && (TagSize != 13) && (TagSize != 14) && (TagSize != 15) && (TagSize != 16)) { + return FALSE; + } + + if (DataOutSize != NULL) { + if ((*DataOutSize > INT_MAX) || (*DataOutSize < DataInSize)) { + return FALSE; + } + } + + mbedtls_gcm_init (&Ctx); + + Ret = mbedtls_gcm_setkey (&Ctx, MBEDTLS_CIPHER_ID_AES, Key, (UINT32)(KeySize * 8)); + if (Ret != 0) { + return FALSE; + } + + Ret = mbedtls_gcm_crypt_and_tag ( + &Ctx, + MBEDTLS_GCM_ENCRYPT, + (UINT32)DataInSize, + Iv, + (UINT32)IvSize, + AData, + (UINT32)ADataSize, + DataIn, + DataOut, + TagSize, + TagOut + ); + mbedtls_gcm_free (&Ctx); + if (Ret != 0) { + return FALSE; + } + + if (DataOutSize != NULL) { + *DataOutSize = DataInSize; + } + + return TRUE; +} + +/** + Performs AEAD AES-GCM authenticated decryption on a data buffer and additional authenticated data (AAD). + + IvSize must be 12, otherwise FALSE is returned. + KeySize must be 16, 24 or 32, otherwise FALSE is returned. + TagSize must be 12, 13, 14, 15, 16, otherwise FALSE is returned. + If additional authenticated data verification fails, FALSE is returned. + + @param[in] Key Pointer to the encryption key. + @param[in] KeySize Size of the encryption key in bytes. + @param[in] Iv Pointer to the IV value. + @param[in] IvSize Size of the IV value in bytes. + @param[in] AData Pointer to the additional authenticated data (AAD). + @param[in] ADataSize Size of the additional authenticated data (AAD) in bytes. + @param[in] DataIn Pointer to the input data buffer to be decrypted. + @param[in] DataInSize Size of the input data buffer in bytes. + @param[in] Tag Pointer to a buffer that contains the authentication tag. + @param[in] TagSize Size of the authentication tag in bytes. + @param[out] DataOut Pointer to a buffer that receives the decryption output. + @param[out] DataOutSize Size of the output data buffer in bytes. + + @retval TRUE AEAD AES-GCM authenticated decryption succeeded. + @retval FALSE AEAD AES-GCM authenticated decryption failed. + +**/ +BOOLEAN +EFIAPI +AeadAesGcmDecrypt ( + IN CONST UINT8 *Key, + IN UINTN KeySize, + IN CONST UINT8 *Iv, + IN UINTN IvSize, + IN CONST UINT8 *AData, + IN UINTN ADataSize, + IN CONST UINT8 *DataIn, + IN UINTN DataInSize, + IN CONST UINT8 *Tag, + IN UINTN TagSize, + OUT UINT8 *DataOut, + OUT UINTN *DataOutSize + ) +{ + mbedtls_gcm_context Ctx; + INT32 Ret; + + if (DataInSize > INT_MAX) { + return FALSE; + } + + if (ADataSize > INT_MAX) { + return FALSE; + } + + if (IvSize != 12) { + return FALSE; + } + + switch (KeySize) { + case 16: + case 24: + case 32: + break; + default: + return FALSE; + } + + if ((TagSize != 12) && (TagSize != 13) && (TagSize != 14) && (TagSize != 15) && (TagSize != 16)) { + return FALSE; + } + + if (DataOutSize != NULL) { + if ((*DataOutSize > INT_MAX) || (*DataOutSize < DataInSize)) { + return FALSE; + } + } + + mbedtls_gcm_init (&Ctx); + + Ret = mbedtls_gcm_setkey (&Ctx, MBEDTLS_CIPHER_ID_AES, Key, (UINT32)(KeySize * 8)); + if (Ret != 0) { + return FALSE; + } + + Ret = mbedtls_gcm_auth_decrypt ( + &Ctx, + (UINT32)DataInSize, + Iv, + (UINT32)IvSize, + AData, + (UINT32)ADataSize, + Tag, + (UINT32)TagSize, + DataIn, + DataOut + ); + mbedtls_gcm_free (&Ctx); + if (Ret != 0) { + return FALSE; + } + + if (DataOutSize != NULL) { + *DataOutSize = DataInSize; + } + + return TRUE; +} diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Hmac/CryptHmac.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Hmac/CryptHmac.c index c4cda57b4d..8083b3fef2 100644 --- a/CryptoPkg/Library/BaseCryptLibMbedTls/Hmac/CryptHmac.c +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Hmac/CryptHmac.c @@ -24,11 +24,14 @@ HmacMdNew ( { VOID *HmacMdCtx; - HmacMdCtx = AllocateZeroPool (sizeof (mbedtls_md_context_t)); + HmacMdCtx = calloc (sizeof (mbedtls_md_context_t), 1); if (HmacMdCtx == NULL) { return NULL; } + // XXX: No mbedtls_md_init()? mbedtls_md_free() shouldn't be called in this + // case. `HmacMdFree (HmacMdNew ())` can cause problems. + return HmacMdCtx; } @@ -44,9 +47,7 @@ HmacMdFree ( ) { mbedtls_md_free (HmacMdCtx); - if (HmacMdCtx != NULL) { - FreePool (HmacMdCtx); - } + free (HmacMdCtx); } /** diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h b/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h index 039aa32028..c9f19dd0cd 100644 --- a/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h @@ -22,4 +22,53 @@ SPDX-License-Identifier: BSD-2-Clause-Patent // #include +/** + The MbedTLS function f_rng, which MbedtlsRand implements. + + @param[in] RngState Not used, just for compatibility with mbedlts. + @param[out] Output Pointer to buffer to receive random value. + @param[in] Len Size of random bytes to generate. + + @retval 0 Pseudorandom byte stream generated successfully. + @retval Non-0 Pseudorandom number generator fails to generate due to lack of entropy. +**/ +INT32 +MbedtlsRand ( + VOID *RngState, + UINT8 *Output, + UINTN Len + ); + +/** + 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/CryptoPkg/Library/BaseCryptLibMbedTls/PeiCryptLib.inf b/CryptoPkg/Library/BaseCryptLibMbedTls/PeiCryptLib.inf index 72b22a24e8..479bb2f87d 100644 --- a/CryptoPkg/Library/BaseCryptLibMbedTls/PeiCryptLib.inf +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/PeiCryptLib.inf @@ -26,6 +26,7 @@ MODULE_TYPE = PEIM VERSION_STRING = 1.0 LIBRARY_CLASS = BaseCryptLib|PEIM PEI_CORE + DEFINE BASE_CRYPT_PATH = ../BaseCryptLib # # The following information is for reference only and not required by the build tools. @@ -38,30 +39,36 @@ Hash/CryptMd5.c Hash/CryptSha1.c Hash/CryptSha256.c - Hash/CryptSm3Null.c Hash/CryptSha512.c - Hash/CryptParallelHashNull.c + $(BASE_CRYPT_PATH)/Hash/CryptCShake256.c + $(BASE_CRYPT_PATH)/Hash/CryptDispatchApPei.c + $(BASE_CRYPT_PATH)/Hash/CryptParallelHash.c + $(BASE_CRYPT_PATH)/Hash/CryptSha3.c + $(BASE_CRYPT_PATH)/Hash/CryptSm3.c + $(BASE_CRYPT_PATH)/Hash/CryptXkcp.c Hmac/CryptHmac.c Kdf/CryptHkdf.c Cipher/CryptAes.c Cipher/CryptAeadAesGcmNull.c Pk/CryptRsaBasic.c Pk/CryptRsaExtNull.c - Pk/CryptRsaPss.c - Pk/CryptRsaPssSignNull.c - Bn/CryptBnNull.c - Pem/CryptPemNull.c - Pk/CryptDhNull.c - Pk/CryptEcNull.c Pk/CryptPkcs1OaepNull.c Pk/CryptPkcs5Pbkdf2Null.c Pk/CryptPkcs7SignNull.c - Pk/CryptPkcs7VerifyNull.c - Pk/CryptPkcs7VerifyEkuNull.c + Pk/CryptPkcs7VerifyCommon.c + Pk/CryptPkcs7VerifyBase.c + Pk/CryptPkcs7VerifyEku.c + Pk/CryptDhNull.c Pk/CryptX509Null.c Pk/CryptAuthenticodeNull.c Pk/CryptTsNull.c + Pk/CryptRsaPss.c + Pk/CryptRsaPssSignNull.c + Pk/CryptEcNull.c + Pem/CryptPemNull.c Rand/CryptRandNull.c + Bn/CryptBnNull.c + SysCall/CrtWrapper.c SysCall/ConstantTimeClock.c diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pem/CryptPem.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pem/CryptPem.c new file mode 100644 index 0000000000..ad26b57168 --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pem/CryptPem.c @@ -0,0 +1,136 @@ +/** @file + PEM (Privacy Enhanced Mail) Format Handler Wrapper Implementation over MbedTLS. + +Copyright (c) 2024, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "InternalCryptLib.h" +#include +#include +#include +#include +#include +#include + +/** + 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 + ) +{ + INT32 Ret; + mbedtls_pk_context Pk; + mbedtls_rsa_context *Rsa; + UINT8 *NewPemData; + UINTN PasswordLen; + + if ((PemData == NULL) || (RsaContext == NULL) || (PemSize > INT_MAX)) { + return FALSE; + } + + NewPemData = NULL; + if (PemData[PemSize - 1] != 0) { + NewPemData = calloc (PemSize + 1, 1); + if (NewPemData == NULL) { + return FALSE; + } + + CopyMem (NewPemData, PemData, PemSize + 1); + NewPemData[PemSize] = 0; + PemData = NewPemData; + PemSize += 1; + } + + mbedtls_pk_init (&Pk); + + if (Password != NULL) { + PasswordLen = AsciiStrLen (Password); + } else { + PasswordLen = 0; + } + + Ret = mbedtls_pk_parse_key (&Pk, PemData, PemSize, (CONST UINT8 *)Password, PasswordLen, NULL, NULL); + + free (NewPemData); + NewPemData = NULL; + + if (Ret != 0) { + mbedtls_pk_free (&Pk); + return FALSE; + } + + if (mbedtls_pk_get_type (&Pk) != MBEDTLS_PK_RSA) { + mbedtls_pk_free (&Pk); + return FALSE; + } + + Rsa = RsaNew (); + if (Rsa == NULL) { + mbedtls_pk_free (&Pk); + return FALSE; + } + + Ret = mbedtls_rsa_copy (Rsa, mbedtls_pk_rsa (Pk)); + if (Ret != 0) { + RsaFree (Rsa); + mbedtls_pk_free (&Pk); + return FALSE; + } + + mbedtls_pk_free (&Pk); + + *RsaContext = Rsa; + return TRUE; +} + +/** + Retrieve the EC 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] EcContext Pointer to new-generated EC DSA context which contain the retrieved + EC private key component. Use EcFree() function to free the + resource. + + If PemData is NULL, then return FALSE. + If EcContext is NULL, then return FALSE. + + @retval TRUE EC Private Key was retrieved successfully. + @retval FALSE Invalid PEM key data or incorrect password. + +**/ +BOOLEAN +EFIAPI +EcGetPrivateKeyFromPem ( + IN CONST UINT8 *PemData, + IN UINTN PemSize, + IN CONST CHAR8 *Password, + OUT VOID **EcContext + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptAuthenticode.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptAuthenticode.c new file mode 100644 index 0000000000..9d8301b2c0 --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptAuthenticode.c @@ -0,0 +1,214 @@ +/** @file + Authenticode Portable Executable Signature Verification which does not provide + real capabilities. + +Copyright (c) 2024, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "InternalCryptLib.h" +#include + +// +// OID ASN.1 Value for SPC_INDIRECT_DATA_OBJID +// +GLOBAL_REMOVE_IF_UNREFERENCED const 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". + + 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 + ) +{ + BOOLEAN Status; + CONST UINT8 *OrigAuthData; + UINT8 *SpcIndirectDataContent; + UINT8 Asn1Byte; + UINTN ContentSize; + CONST UINT8 *SpcIndirectDataOid; + UINT8 *Ptr; + UINT8 *End; + INT32 Len; + UINTN ObjLen; + + OrigAuthData = AuthData; + + // + // Check input parameters. + // + if ((AuthData == NULL) || (TrustedCert == NULL) || (ImageHash == NULL)) { + return FALSE; + } + + if ((DataSize > INT_MAX) || (CertSize > INT_MAX) || (HashSize > INT_MAX)) { + return FALSE; + } + + if (DataSize <= HashSize) { + return FALSE; + } + + Ptr = (UINT8 *)(UINTN)AuthData; + Len = (UINT32)DataSize; + End = Ptr + Len; + + // ContentInfo + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + // ContentType + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OID) != 0) { + return FALSE; + } + + Ptr += ObjLen; + // content + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) { + return FALSE; + } + + End = Ptr + ObjLen; + // signedData + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + // version + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) != 0) { + return FALSE; + } + + Ptr += ObjLen; + // digestAlgo + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET) != 0) { + return FALSE; + } + + Ptr += ObjLen; + + // encapContentInfo + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + End = Ptr + ObjLen; + // eContentType + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OID) != 0) { + return FALSE; + } + + Status = FALSE; + + SpcIndirectDataOid = Ptr; + if ((ObjLen != sizeof (mSpcIndirectOidValue)) || + (CompareMem ( + SpcIndirectDataOid, + mSpcIndirectOidValue, + sizeof (mSpcIndirectOidValue) + ) != 0)) + { + // + // Un-matched SPC_INDIRECT_DATA_OBJID. + // + goto _Exit; + } + + Ptr += ObjLen; + // eContent + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) { + return FALSE; + } + + SpcIndirectDataContent = Ptr; + + // + // 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 (ContentSize < HashSize) { + return FALSE; + } + + 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: + + return Status; +} diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs1Oaep.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs1Oaep.c new file mode 100644 index 0000000000..61ccdd78e6 --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs1Oaep.c @@ -0,0 +1,278 @@ +/** @file + This file contains UEFI wrapper functions for RSA PKCS1v2 OAEP encryption routines. + + SPDX-License-Identifier: BSD-2-Clause-Patent + + Copyright (c) 2024, Intel Corporation. All rights reserved.
+ +**/ + +#include "InternalCryptLib.h" +#include +#include +#include + +/** + Encrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the + encrypted message in a newly allocated buffer. + + Things that can cause a failure include: + - X509 key size does not match any known key size. + - Fail to parse X509 certificate. + - Fail to allocate an intermediate buffer. + - Null pointer provided for a non-optional parameter. + - Data size is too large for the provided key size (max size is a function of key size + and hash digest size). + + @param[in] PublicKey A pointer to the DER-encoded X509 certificate that + will be used to encrypt the data. + @param[in] PublicKeySize Size of the X509 cert buffer. + @param[in] InData Data to be encrypted. + @param[in] InDataSize Size of the data buffer. + @param[in] PrngSeed [Optional] If provided, a pointer to a random seed buffer + to be used when initializing the PRNG. NULL otherwise. + @param[in] PrngSeedSize [Optional] If provided, size of the random seed buffer. + 0 otherwise. + @param[out] EncryptedData Pointer to an allocated buffer containing the encrypted + message. + @param[out] EncryptedDataSize Size of the encrypted message buffer. + + @retval TRUE Encryption was successful. + @retval FALSE Encryption failed. + +**/ +BOOLEAN +EFIAPI +Pkcs1v2Encrypt ( + IN CONST UINT8 *PublicKey, + IN UINTN PublicKeySize, + IN UINT8 *InData, + IN UINTN InDataSize, + IN CONST UINT8 *PrngSeed OPTIONAL, + IN UINTN PrngSeedSize OPTIONAL, + OUT UINT8 **EncryptedData, + OUT UINTN *EncryptedDataSize + ) +{ + BOOLEAN Result; + UINT32 Ret; + UINT8 *OutData; + mbedtls_x509_crt CertContext; + mbedtls_rsa_context RsaContext; + + // + // Check input parameters. + // + if ((PublicKey == NULL) || (InData == NULL) || + (EncryptedData == NULL) || (EncryptedDataSize == NULL)) + { + return FALSE; + } + + // + // Check public key size. + // + if (PublicKeySize > UINT_MAX) { + // + // Public key size is too large for implementation. + // + return FALSE; + } + + *EncryptedData = NULL; + *EncryptedDataSize = 0; + Result = FALSE; + OutData = NULL; + + mbedtls_x509_crt_init (&CertContext); + + if (mbedtls_x509_crt_parse_der (&CertContext, PublicKey, (UINT32)PublicKeySize) != 0) { + goto _Exit; + } + + if (mbedtls_pk_get_type (&CertContext.pk) != MBEDTLS_PK_RSA) { + goto _Exit; + } + + mbedtls_rsa_init (&RsaContext); + if (mbedtls_rsa_set_padding (&RsaContext, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_NONE) != 0) { + goto _Exit; + } + + Ret = mbedtls_rsa_copy (&RsaContext, mbedtls_pk_rsa (CertContext.pk)); + if (Ret != 0) { + goto _Exit; + } + + *EncryptedDataSize = RsaContext.len; + + // + // Allocate a buffer for the output data. + // + OutData = AllocateZeroPool (*EncryptedDataSize); + if (OutData == NULL) { + // + // Fail to allocate the output buffer. + // + goto _Exit; + } + + Ret = mbedtls_rsa_pkcs1_encrypt ( + &RsaContext, + MbedtlsRand, + NULL, + InDataSize, + InData, + OutData + ); + if (Ret != 0) { + FreePool (OutData); + OutData = NULL; + goto _Exit; + } + + *EncryptedData = OutData; + Result = TRUE; + +_Exit: + // + // Release Resources + // + if (&CertContext != NULL) { + mbedtls_x509_crt_free (&CertContext); + } + + if (&RsaContext != NULL) { + mbedtls_rsa_free (&RsaContext); + } + + return Result; +} + +/** + Encrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the + encrypted message in a newly allocated buffer. + + Things that can cause a failure include: + - X509 key size does not match any known key size. + - Fail to allocate an intermediate buffer. + - Null pointer provided for a non-optional parameter. + - Data size is too large for the provided key size (max size is a function of key size + and hash digest size). + + @param[in] RsaContext A pointer to an RSA context created by RsaNew() and + provisioned with a public key using RsaSetKey(). + @param[in] InData Data to be encrypted. + @param[in] InDataSize Size of the data buffer. + @param[in] PrngSeed [Optional] If provided, a pointer to a random seed buffer + to be used when initializing the PRNG. NULL otherwise. + @param[in] PrngSeedSize [Optional] If provided, size of the random seed buffer. + 0 otherwise. + @param[in] DigestLen [Optional] If provided, size of the hash used: + SHA1_DIGEST_SIZE + SHA256_DIGEST_SIZE + SHA384_DIGEST_SIZE + SHA512_DIGEST_SIZE + 0 to use default (SHA1) + @param[out] EncryptedData Pointer to an allocated buffer containing the encrypted + message. + @param[out] EncryptedDataSize Size of the encrypted message buffer. + + @retval TRUE Encryption was successful. + @retval FALSE Encryption failed. + +**/ +BOOLEAN +EFIAPI +RsaOaepEncrypt ( + IN VOID *RsaContext, + IN UINT8 *InData, + IN UINTN InDataSize, + IN CONST UINT8 *PrngSeed OPTIONAL, + IN UINTN PrngSeedSize OPTIONAL, + IN UINT16 DigestLen OPTIONAL, + OUT UINT8 **EncryptedData, + OUT UINTN *EncryptedDataSize + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Decrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the + decrypted message in a newly allocated buffer. + + Things that can cause a failure include: + - Fail to parse private key. + - Fail to allocate an intermediate buffer. + - Null pointer provided for a non-optional parameter. + + @param[in] PrivateKey A pointer to the DER-encoded private key. + @param[in] PrivateKeySize Size of the private key buffer. + @param[in] EncryptedData Data to be decrypted. + @param[in] EncryptedDataSize Size of the encrypted buffer. + @param[out] OutData Pointer to an allocated buffer containing the encrypted + message. + @param[out] OutDataSize Size of the encrypted message buffer. + + @retval TRUE Encryption was successful. + @retval FALSE Encryption failed. + +**/ +BOOLEAN +EFIAPI +Pkcs1v2Decrypt ( + IN CONST UINT8 *PrivateKey, + IN UINTN PrivateKeySize, + IN UINT8 *EncryptedData, + IN UINTN EncryptedDataSize, + OUT UINT8 **OutData, + OUT UINTN *OutDataSize + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Decrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the + decrypted message in a newly allocated buffer. + + Things that can cause a failure include: + - Fail to parse private key. + - Fail to allocate an intermediate buffer. + - Null pointer provided for a non-optional parameter. + + @param[in] RsaContext A pointer to an RSA context created by RsaNew() and + provisioned with a private key using RsaSetKey(). + @param[in] EncryptedData Data to be decrypted. + @param[in] EncryptedDataSize Size of the encrypted buffer. + @param[in] DigestLen [Optional] If provided, size of the hash used: + SHA1_DIGEST_SIZE + SHA256_DIGEST_SIZE + SHA384_DIGEST_SIZE + SHA512_DIGEST_SIZE + 0 to use default (SHA1) + @param[out] OutData Pointer to an allocated buffer containing the encrypted + message. + @param[out] OutDataSize Size of the encrypted message buffer. + + @retval TRUE Encryption was successful. + @retval FALSE Encryption failed. + +**/ +BOOLEAN +EFIAPI +RsaOaepDecrypt ( + IN VOID *RsaContext, + IN UINT8 *EncryptedData, + IN UINTN EncryptedDataSize, + IN UINT16 DigestLen OPTIONAL, + OUT UINT8 **OutData, + OUT UINTN *OutDataSize + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs5Pbkdf2.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs5Pbkdf2.c new file mode 100644 index 0000000000..94f1fcfa3b --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs5Pbkdf2.c @@ -0,0 +1,100 @@ +/** @file + PBKDF2 Key Derivation Function Wrapper Implementation over MbedTLS. + +Copyright (c) 2024, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "InternalCryptLib.h" +#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 + ) +{ + mbedtls_md_type_t HashAlg; + + // + // 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 = MBEDTLS_MD_SHA1; + break; + case SHA256_DIGEST_SIZE: + HashAlg = MBEDTLS_MD_SHA256; + break; + default: + return FALSE; + break; + } + + // + // Perform password-based key derivation routines. + // + if (mbedtls_pkcs5_pbkdf2_hmac_ext ( + HashAlg, + (CONST UINT8 *)Password, + (int)PasswordLength, + (CONST UINT8 *)Salt, + (int)SaltLength, + (int)IterationCount, + (int)KeyLength, + (UINT8 *)OutKey + ) != 0) + { + return FALSE; + } else { + return TRUE; + } +} diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Internal.h b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Internal.h index 207f493cbb..cbdd1dc530 100644 --- a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Internal.h +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Internal.h @@ -4,7 +4,7 @@ RFC 2315 - PKCS #7: Cryptographic Message Syntax Version 1.5 -Copyright (c) 2023, Intel Corporation. All rights reserved.
+Copyright (c) 2023-2024, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -31,10 +31,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #define MBEDTLS_OID_PKCS7_DIGESTED_DATA MBEDTLS_OID_PKCS7 "\x05" #define MBEDTLS_OID_PKCS7_ENCRYPTED_DATA MBEDTLS_OID_PKCS7 "\x06" -typedef mbedtls_asn1_buf MBEDTLSPKCS7BUF; -typedef mbedtls_asn1_named_data MBEDTLSPKCS7NAME; -typedef mbedtls_asn1_sequence MBEDTLSPKCS7SEQUENCE; - /// /// PKCS7 SignerInfo type /// https://tools.ietf.org/html/rfc2315#section-9.2 @@ -48,8 +44,8 @@ typedef struct MbedtlsPkcs7SignerInfo { mbedtls_x509_buf SigAlgIdentifier; mbedtls_x509_buf AuthAttr; mbedtls_x509_buf Sig; - struct MBEDTLSPKCS7SIGNERINFO *Next; -} MBEDTLSPKCS7SIGNERINFO; + struct MbedtlsPkcs7SignerInfo *Next; +} MbedtlsPkcs7SignerInfo; /// /// PKCS7 signed data attached data format @@ -57,7 +53,7 @@ typedef struct MbedtlsPkcs7SignerInfo { typedef struct MbedtlsPkcs7Data { mbedtls_asn1_buf Oid; mbedtls_asn1_buf Data; -} MBEDTLSPKCS7DATA; +} MbedtlsPkcs7Data; /// /// Signed Data @@ -66,18 +62,27 @@ typedef struct MbedtlsPkcs7Data { typedef struct MbedtlsPkcs7SignedData { INT32 Version; mbedtls_asn1_buf DigestAlgorithms; - struct MBEDTLSPKCS7DATA ContentInfo; + struct MbedtlsPkcs7Data ContentInfo; mbedtls_x509_crt Certificates; mbedtls_x509_crl Crls; struct MbedtlsPkcs7SignerInfo SignerInfos; -} MBEDTLSPKCS7SIGNEDDATA; +} MbedtlsPkcs7SignedData; /// /// PKCS7 struct, only support SignedData /// typedef struct MbedtlsPkcs7 { mbedtls_asn1_buf ContentTypeOid; - struct MBEDTLSPKCS7SIGNEDDATA SignedData; -} MBEDTLSPKCS7; + struct MbedtlsPkcs7SignedData SignedData; +} MbedtlsPkcs7; + +#define EDKII_ASN1_CHK_ADD(g, f) \ + do \ + { \ + if( ( Ret = (f) ) < 0 ) \ + return( Ret ); \ + else \ + (g) += Ret; \ + } while( 0 ) #endif diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c new file mode 100644 index 0000000000..e3283dad48 --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c @@ -0,0 +1,635 @@ +/** @file + PKCS#7 SignedData Sign Wrapper and PKCS#7 SignedData Verification Wrapper + Implementation over mbedtls. + + RFC 8422 - Elliptic Curve Cryptography (ECC) Cipher Suites + FIPS 186-4 - Digital Signature Standard (DSS) + +Copyright (c) 2024, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "CryptPkcs7Internal.h" +#include + +/// +/// Enough to store any signature generated by PKCS7 +/// +#define MAX_SIGNATURE_SIZE 1024 + +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 MbedtlsOidDigestAlgSha256[] = MBEDTLS_OID_DIGEST_ALG_SHA256; +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 MbedtlsOidPkcs1Rsa[] = MBEDTLS_OID_PKCS1_RSA; + +/** + Write DigestAlgorithmIdentifier. + + @param[in, out] Ptr The reference to the current position pointer. + @param[in] Start The start of the buffer, for bounds-checking. + @param[in] DigestType Digest Type + + @retval number The number of bytes written to p on success. + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. +**/ +STATIC +INT32 +MbedTlsPkcs7WriteDigestAlgorithm ( + UINT8 **Ptr, + UINT8 *Start, + mbedtls_md_type_t DigestType + ) +{ + UINT8 *OidPtr; + UINTN OidLen; + INT32 Ret; + + Ret = mbedtls_oid_get_oid_by_md (DigestType, (CONST CHAR8 **)&OidPtr, &OidLen); + if (Ret == 0) { + return mbedtls_asn1_write_oid (Ptr, (CONST UINT8 *)Start, (CONST CHAR8 *)OidPtr, OidLen); + } + + return 0; +} + +/** + DigestAlgorithmIdentifiers ::= + SET OF DigestAlgorithmIdentifier. + + @param[in, out] Ptr The reference to the current position pointer. + @param[in] Start The start of the buffer, for bounds-checking. + @param[in] DigestTypes Digest Type array. + @param[in] Count The index for Digest Type. + + @retval number The number of bytes written to p on success. + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. +**/ +STATIC +INT32 +MbedTlsPkcs7WriteDigestAlgorithmSet ( + UINT8 **Ptr, + UINT8 *Start, + mbedtls_md_type_t *DigestTypes, + INTN Count + ) +{ + INTN Idx; + INT32 Len; + INT32 Ret; + + Len = 0; + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_null (Ptr, Start)); + + for (Idx = 0; Idx < Count; Idx++) { + EDKII_ASN1_CHK_ADD ( + Len, + MbedTlsPkcs7WriteDigestAlgorithm (Ptr, Start, DigestTypes[Idx]) + ); + } + + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, (UINTN)Len)); + + EDKII_ASN1_CHK_ADD ( + Len, + mbedtls_asn1_write_tag ( + Ptr, + Start, + (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) + ) + ); + + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, (UINTN)Len)); + + EDKII_ASN1_CHK_ADD ( + Len, + mbedtls_asn1_write_tag ( + Ptr, + Start, + (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET) + ) + ); + + return Len; +} + +/** + ContentInfo ::= SEQUENCE { + contentType ContentType, + content + [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }. + + @param[in, out] Ptr The reference to the current position pointer. + @param[in] Start The start of the buffer, for bounds-checking. + @param[in] Content ContentInfo. + @param[in] ContentLen Size of ContentInfo. + + @retval number The number of bytes written to p on success. + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. +**/ +STATIC +INT32 +MbedTlsPkcs7WriteContentInfo ( + UINT8 **Ptr, + UINT8 *Start, + UINT8 *Content, + INTN ContentLen + ) +{ + INT32 Ret; + INT32 Len; + + Len = 0; + if (Content != NULL) { + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_octet_string (Ptr, Start, Content, ContentLen)); + } + + EDKII_ASN1_CHK_ADD ( + Len, + mbedtls_asn1_write_oid ( + Ptr, + Start, + MBEDTLS_OID_PKCS7_DATA, + sizeof (MBEDTLS_OID_PKCS7_DATA) - 1 + ) + ); + + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, Len)); + + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (Ptr, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); + + return Len; +} + +/** + certificates :: SET OF ExtendedCertificateOrCertificate, + ExtendedCertificateOrCertificate ::= CHOICE { + certificate Certificate -- x509, + extendedCertificate[0] IMPLICIT ExtendedCertificate }. + + @param[in, out] Ptr The reference to the current position pointer. + @param[in] Start The start of the buffer, for bounds-checking. + @param[in] Cert Certificate. + @param[in] OtherCerts Ohter Certificate. + + @retval number The number of bytes written to p on success. + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. +**/ +STATIC +INT32 +MbedTlsPkcs7WriteCertificates ( + UINT8 **Ptr, + UINT8 *Start, + mbedtls_x509_crt *Cert, + mbedtls_x509_crt *OtherCerts + ) +{ + INT32 Ret; + INT32 Len; + mbedtls_x509_crt *TmpCert; + + Len = 0; + + /// Write OtherCerts + TmpCert = OtherCerts; + while (TmpCert != NULL) { + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_raw_buffer (Ptr, Start, TmpCert->raw.p, TmpCert->raw.len)); + TmpCert = TmpCert->next; + } + + /// Write Cert + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_raw_buffer (Ptr, Start, Cert->raw.p, Cert->raw.len)); + + /// Write NextContext + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, Len)); + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (Ptr, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)); + return Len; +} + +/** + write Pkcs7 Int. + + @param[in, out] Ptr The reference to the current position pointer. + @param[in] Start The start of the buffer, for bounds-checking. + @param[in] SerialRaw SerialRaw. + @param[in] SerialRawLen Size of SerialRaw. + + @retval number The number of bytes written to p on success. + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. +**/ +STATIC +INT32 +MbedTlsPkcs7WriteInt ( + UINT8 **Ptr, + UINT8 *Start, + UINT8 *SerialRaw, + INTN SerialRawLen + ) +{ + INT32 Ret; + UINT8 *Pt; + INT32 Len; + + Len = 0; + Pt = SerialRaw + SerialRawLen; + while (Pt > SerialRaw) { + *--(*Ptr) = *--Pt; + Len++; + } + + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, Len)); + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (Ptr, Start, MBEDTLS_ASN1_INTEGER)); + + return Len; +} + +/** + write Pkcs7 Issuer And SerialNumber. + + @param[in, out] Ptr The reference to the current position pointer. + @param[in] Start The start of the buffer, for bounds-checking. + @param[in] Serial Serial. + @param[in] SerialLen Size of Serial. + @param[in] IssuerRaw IssuerRawLen. + @param[in] IssuerRawLen Size of IssuerRawLen. + + @retval number The number of bytes written to p on success. + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. +**/ +STATIC +INT32 +MbedTlsPkcs7WriteIssuerAndSerialNumber ( + UINT8 **Ptr, + UINT8 *Start, + UINT8 *Serial, + INTN SerialLen, + UINT8 *IssuerRaw, + INTN IssuerRawLen + ) +{ + INT32 Ret; + INT32 Len; + + Len = 0; + EDKII_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteInt (Ptr, Start, Serial, SerialLen)); + + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_raw_buffer (Ptr, Start, IssuerRaw, IssuerRawLen)); + + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, Len)); + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (Ptr, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); + + return Len; +} + +/** + SignerInfo ::= SEQUENCE { + version Version; + issuerAndSerialNumber IssuerAndSerialNumber, + digestAlgorithm DigestAlgorithmIdentifier, + authenticatedAttributes + [0] IMPLICIT Attributes OPTIONAL, + digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier, + encryptedDigest EncryptedDigest, + unauthenticatedAttributes + [1] IMPLICIT Attributes OPTIONAL. + + @param[in, out] Ptr The reference to the current position pointer. + @param[in] Start The start of the buffer, for bounds-checking. + @param[in] SignerInfo SignerInfo. + + @retval number The number of bytes written to p on success. + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. +**/ +STATIC +INT32 +MbedTlsPkcs7WriteSignerInfo ( + UINT8 **Ptr, + UINT8 *Start, + MbedtlsPkcs7SignerInfo *SignerInfo + ) +{ + INT32 Ret; + INT32 Len; + + Len = 0; + + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_octet_string (Ptr, Start, SignerInfo->Sig.p, SignerInfo->Sig.len)); + + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_algorithm_identifier (Ptr, Start, (CONST CHAR8 *)SignerInfo->SigAlgIdentifier.p, SignerInfo->SigAlgIdentifier.len, 0)); + + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_algorithm_identifier (Ptr, Start, (CONST CHAR8 *)SignerInfo->AlgIdentifier.p, SignerInfo->AlgIdentifier.len, 0)); + + EDKII_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteIssuerAndSerialNumber (Ptr, Start, SignerInfo->Serial.p, SignerInfo->Serial.len, SignerInfo->IssuerRaw.p, SignerInfo->IssuerRaw.len)); + + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_int (Ptr, Start, SignerInfo->Version)); + + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, Len)); + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (Ptr, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); + + return Len; +} + +/** + write Pkcs7 Signers Info Set. + + @param[in, out] Ptr The reference to the current position pointer. + @param[in] Start The start of the buffer, for bounds-checking. + @param[in] SignersSet SignerInfo Set. + + @retval number The number of bytes written to p on success. + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. +**/ +STATIC +INT32 +MbedTlsPkcs7WriteSignersInfoSet ( + UINT8 **Ptr, + UINT8 *Start, + MbedtlsPkcs7SignerInfo *SignersSet + ) +{ + MbedtlsPkcs7SignerInfo *SignerInfo; + INT32 Ret; + INT32 Len; + + SignerInfo = SignersSet; + Len = 0; + + while (SignerInfo != NULL) { + EDKII_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteSignerInfo (Ptr, Start, SignerInfo)); + // move to next + SignerInfo = SignerInfo->Next; + } + + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, Len)); + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (Ptr, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)); + + return Len; +} + +/** + Signed Data Type + SignedData ::= SEQUENCE { + version Version, + digestAlgorithms DigestAlgorithmIdentifiers, + contentInfo ContentInfo, + certificates + [0] IMPLICIT ExtendedCertificatesAndCertificates + OPTIONAL, + crls + [1] IMPLICIT CertificateRevocationLists OPTIONAL, + signerInfos SignerInfos } + + DigestAlgorithmIdentifiers ::= + SET OF DigestAlgorithmIdentifier + + SignerInfos ::= SET OF SignerInfo. + + @param[in, out] Ptr The reference to the current position pointer. + @param[in] Start The start of the buffer, for bounds-checking. + @param[in] Pkcs7 MbedtlsPkcs7 + + @retval number The number of bytes written to p on success. + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. +**/ +STATIC +INT32 +MbedTlsPkcs7WriteDer ( + UINT8 **Ptr, + UINT8 *Start, + MbedtlsPkcs7 *Pkcs7 + ) +{ + INT32 Ret; + INT32 Len; + mbedtls_md_type_t DigestAlg[1]; + + DigestAlg[0] = MBEDTLS_MD_SHA256; + Len = 0; + + EDKII_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteSignersInfoSet (Ptr, Start, &(Pkcs7->SignedData.SignerInfos))); + + EDKII_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteCertificates (Ptr, Start, &(Pkcs7->SignedData.Certificates), Pkcs7->SignedData.Certificates.next)); + + EDKII_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteContentInfo (Ptr, Start, NULL, 0)); + + EDKII_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteDigestAlgorithmSet (Ptr, Start, DigestAlg, 1)); + + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_int (Ptr, Start, Pkcs7->SignedData.Version)); + + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, Len)); + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (Ptr, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); + + return Len; +} + +/** + 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 + ) +{ + BOOLEAN Status; + INT32 Ret; + mbedtls_pk_context Pkey; + UINT8 HashValue[SHA256_DIGEST_SIZE]; + UINT8 Signature[MAX_SIGNATURE_SIZE]; + UINTN SignatureLen; + UINT8 *NewPrivateKey; + mbedtls_x509_crt *Crt; + + MbedtlsPkcs7 Pkcs7; + MbedtlsPkcs7SignerInfo SignerInfo; + UINT8 *Buffer; + INTN BufferSize; + UINT8 *Ptr; + INT32 Len; + + // + // Check input parameters. + // + if ((PrivateKey == NULL) || (KeyPassword == NULL) || (InData == NULL) || + (SignCert == NULL) || (SignedData == NULL) || (SignedDataSize == NULL) || (InDataSize > INT_MAX)) + { + return FALSE; + } + + BufferSize = 4096; + + SignatureLen = MAX_SIGNATURE_SIZE; + Crt = (mbedtls_x509_crt *)SignCert; + + NewPrivateKey = NULL; + if (PrivateKey[PrivateKeySize - 1] != 0) { + NewPrivateKey = AllocateZeroPool (PrivateKeySize + 1); + if (NewPrivateKey == NULL) { + return FALSE; + } + + CopyMem (NewPrivateKey, PrivateKey, PrivateKeySize); + NewPrivateKey[PrivateKeySize] = 0; + PrivateKeySize++; + } else { + NewPrivateKey = AllocateZeroPool (PrivateKeySize); + if (NewPrivateKey == NULL) { + return FALSE; + } + + CopyMem (NewPrivateKey, PrivateKey, PrivateKeySize); + } + + mbedtls_pk_init (&Pkey); + Ret = mbedtls_pk_parse_key ( + &Pkey, + NewPrivateKey, + PrivateKeySize, + KeyPassword, + KeyPassword == NULL ? 0 : AsciiStrLen ((CONST CHAR8 *)KeyPassword), + NULL, + NULL + ); + if (Ret != 0) { + Status = FALSE; + goto Cleanup; + } + + /// Calculate InData Digest + ZeroMem (HashValue, SHA256_DIGEST_SIZE); + Status = Sha256HashAll (InData, InDataSize, HashValue); + if (!Status) { + goto Cleanup; + } + + /// Pk Sign + ZeroMem (Signature, MAX_SIGNATURE_SIZE); + Ret = mbedtls_pk_sign ( + &Pkey, + MBEDTLS_MD_SHA256, + HashValue, + SHA256_DIGEST_SIZE, + Signature, + MAX_SIGNATURE_SIZE, + &SignatureLen, + MbedtlsRand, + NULL + ); + if (Ret != 0) { + Status = FALSE; + goto Cleanup; + } + + ZeroMem (&Pkcs7, sizeof (MbedtlsPkcs7)); + Pkcs7.SignedData.Version = 1; + + Crt->next = (mbedtls_x509_crt *)OtherCerts; + Pkcs7.SignedData.Certificates = *Crt; + + SignerInfo.Next = NULL; + SignerInfo.Sig.p = Signature; + SignerInfo.Sig.len = SignatureLen; + SignerInfo.Version = 1; + SignerInfo.AlgIdentifier.p = MbedtlsOidDigestAlgSha256; + SignerInfo.AlgIdentifier.len = sizeof (MBEDTLS_OID_DIGEST_ALG_SHA256) - 1; + if (mbedtls_pk_get_type (&Pkey) == MBEDTLS_PK_RSA) { + SignerInfo.SigAlgIdentifier.p = MbedtlsOidPkcs1Rsa; + SignerInfo.SigAlgIdentifier.len = sizeof (MBEDTLS_OID_PKCS1_RSA) - 1; + } else { + Ret = mbedtls_oid_get_oid_by_sig_alg (MBEDTLS_PK_ECDSA, MBEDTLS_MD_SHA256, (CONST CHAR8 **)&SignerInfo.SigAlgIdentifier.p, &SignerInfo.SigAlgIdentifier.len); + if (Ret != 0) { + Status = FALSE; + goto Cleanup; + } + } + + SignerInfo.Serial = ((mbedtls_x509_crt *)SignCert)->serial; + SignerInfo.IssuerRaw = ((mbedtls_x509_crt *)SignCert)->issuer_raw; + Pkcs7.SignedData.SignerInfos = SignerInfo; + + Buffer = AllocateZeroPool (BufferSize); + if (Buffer == NULL) { + Status = FALSE; + goto Cleanup; + } + + Ptr = Buffer + BufferSize; + Len = MbedTlsPkcs7WriteDer (&Ptr, Buffer, &Pkcs7); + + /// Enlarge buffer if buffer is too small + while (Len == MBEDTLS_ERR_ASN1_BUF_TOO_SMALL) { + BufferSize = BufferSize * 2; + Ptr = Buffer + BufferSize; + FreePool (Buffer); + Buffer = AllocateZeroPool (BufferSize); + if (Buffer == NULL) { + Status = FALSE; + goto Cleanup; + } + + Ptr = Buffer + BufferSize; + Len = MbedTlsPkcs7WriteDer (&Ptr, Buffer, &Pkcs7); + } + + if (Len <= 0) { + Status = FALSE; + goto Cleanup; + } + + *SignedData = AllocateZeroPool (Len); + if (*SignedData == NULL) { + Status = FALSE; + goto Cleanup; + } + + *SignedDataSize = Len; + CopyMem (*SignedData, Ptr, Len); + Status = TRUE; + +Cleanup: + if (&Pkey != NULL) { + mbedtls_pk_free (&Pkey); + } + + if (NewPrivateKey != NULL) { + memset (NewPrivateKey, 0, PrivateKeySize); + FreePool (NewPrivateKey); + } + + if (Buffer != NULL) { + memset (Buffer, 0, BufferSize); + FreePool (Buffer); + } + + return Status; +} diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyBase.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyBase.c new file mode 100644 index 0000000000..6b62ee2618 --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyBase.c @@ -0,0 +1,113 @@ +/** @file + Non-runtime specific implementation of PKCS#7 SignedData Verification Wrapper. + +Copyright (c) 2024, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "InternalCryptLib.h" +#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; + UINT8 *SignedData; + UINTN SignedDataSize; + BOOLEAN Wrapped; + INTN Ret; + mbedtls_pkcs7 Pkcs7; + mbedtls_pkcs7_data *MbedtlsContent; + + mbedtls_pkcs7_init (&Pkcs7); + + // + // Check input parameter. + // + if ((P7Data == NULL) || (P7Length > INT_MAX) || (Content == NULL) || (ContentSize == NULL)) { + return FALSE; + } + + *Content = NULL; + SignedData = NULL; + + Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &SignedData, &SignedDataSize); + if (!Status || (SignedDataSize > INT_MAX)) { + goto _Exit; + } + + Status = FALSE; + + Ret = mbedtls_pkcs7_parse_der (&Pkcs7, SignedData, (INT32)SignedDataSize); + + // + // The type of Pkcs7 must be signedData + // + if (Ret != MBEDTLS_PKCS7_SIGNED_DATA) { + goto _Exit; + } + + // + // Check for detached or attached content + // + MbedtlsContent = &(Pkcs7.signed_data.content); + + if (MbedtlsContent == NULL) { + // + // No Content supplied for PKCS7 detached signedData + // + *Content = NULL; + *ContentSize = 0; + } else { + // + // Retrieve the attached content in PKCS7 signedData + // + if ((MbedtlsContent->data.len > 0) && (MbedtlsContent->data.p != NULL)) { + *ContentSize = MbedtlsContent->data.len; + *Content = AllocateZeroPool (*ContentSize); + if (*Content == NULL) { + *ContentSize = 0; + goto _Exit; + } + + CopyMem (*Content, MbedtlsContent->data.p, *ContentSize); + } + } + + Status = TRUE; + +_Exit: + // + // Release Resources + // + mbedtls_pkcs7_free (&Pkcs7); + + return Status; +} diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyCommon.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyCommon.c new file mode 100644 index 0000000000..0f80c3c080 --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyCommon.c @@ -0,0 +1,1362 @@ +/** @file + PKCS#7 SignedData Sign Wrapper and PKCS#7 SignedData Verification Wrapper + Implementation over mbedtls. + + RFC 8422 - Elliptic Curve Cryptography (ECC) Cipher Suites + FIPS 186-4 - Digital Signature Standard (DSS) + +Copyright (c) 2024, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "CryptPkcs7Internal.h" +#include + +/* Profile for backward compatibility. Allows RSA 1024, unlike the default + profile. */ +STATIC mbedtls_x509_crt_profile gCompatProfile = +{ + /* Hashes from SHA-256 and above. Note that this selection + * should be aligned with ssl_preset_default_hashes in ssl_tls.c. */ + + #ifndef DISABLE_SHA1_DEPRECATED_INTERFACES + MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA1) | + #endif + MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA256) | + MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA384) | + MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA512), + 0xFFFFFFF, /* Any PK alg */ + + /* Curves at or above 128-bit security level. Note that this selection + * should be aligned with ssl_preset_default_curves in ssl_tls.c. */ + MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_SECP256R1) | + MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_SECP384R1) | + MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_SECP521R1) | + MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_BP256R1) | + MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_BP384R1) | + MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_BP512R1) | + 0, + 1024, +}; + +/** + Init MbedtlsPkcs7. + + @param[in] Pkcs7 MbedtlsPkcs7. +**/ +STATIC +VOID +MbedTlsPkcs7Init ( + MbedtlsPkcs7 *Pkcs7 + ) +{ + ZeroMem (Pkcs7, sizeof (MbedtlsPkcs7)); +} + +/** + Get Pkcs7 Next Content Len. + + @param[in] Ptr The start of the buffer. + @param[in] End The end of the buffer. + @param[out] Len MbedtlsPkcs7 Content Len. + + @retval 0 Success. + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. +**/ +STATIC +INT32 +MbedTlsPkcs7GetNextContentLen ( + UINT8 **Ptr, + UINT8 *End, + UINTN *Len + ) +{ + INT32 Ret; + + Ret = mbedtls_asn1_get_tag (Ptr, End, Len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC); + return Ret; +} + +/** + Get Pkcs7 Version.. + + @param[in] Ptr The start of the buffer. + @param[in] End The end of the buffer. + @param[out] Ver MbedtlsPkcs7 Version. + + @retval 0 Success. + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. +**/ +STATIC +INT32 +MbedTlsPkcs7GetVersion ( + UINT8 **Ptr, + UINT8 *End, + INT32 *Ver + ) +{ + INT32 Ret; + + Ret = mbedtls_asn1_get_int (Ptr, End, Ver); + return Ret; +} + +/** + ContentInfo ::= SEQUENCE { + contentType ContentType, + content + [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }. + + @param[in] Ptr The start of the buffer. + @param[in] End The end of the buffer. + @param[out] Pkcs7 MbedtlsPkcs7. + + @retval 0 Success. + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. +**/ +STATIC +INT32 +Pkcs7GetContentInfoType ( + UINT8 **Ptr, + UINT8 *End, + mbedtls_asn1_buf *Pkcs7 + ) +{ + UINTN Len; + int Ret; + + Len = 0; + Ret = mbedtls_asn1_get_tag ( + Ptr, + End, + &Len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE + ); + + if (Ret == 0) { + Ret = mbedtls_asn1_get_tag (Ptr, End, &Len, MBEDTLS_ASN1_OID); + } + + if (Ret == 0) { + Pkcs7->tag = MBEDTLS_ASN1_OID; + Pkcs7->len = Len; + Pkcs7->p = *Ptr; + } + + return Ret; +} + +/** + DigestAlgorithmIdentifier ::= AlgorithmIdentifier. + + @param[in] Ptr The start of the buffer. + @param[in] End The end of the buffer. + @param[out] Alg MbedtlsPkcs7 AlgorithmIdentifier. + + @retval 0 Success. + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. +**/ +STATIC +INT32 +MbedTlsPkcs7GetDigestAlgorithm ( + UINT8 **Ptr, + UINT8 *End, + mbedtls_x509_buf *Alg + ) +{ + INT32 Ret; + + Ret = mbedtls_asn1_get_alg_null (Ptr, End, Alg); + return Ret; +} + +/** + DigestAlgorithmIdentifiers :: SET of DigestAlgorithmIdentifier. + + @param[in] Ptr The start of the buffer. + @param[in] End The end of the buffer. + @param[out] Alg MbedtlsPkcs7 AlgorithmIdentifier. + + @retval 0 Success. + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. +**/ +STATIC +INT32 +MbedTlsPkcs7GetDigestAlgorithmSet ( + UINT8 **Ptr, + UINT8 *End, + mbedtls_x509_buf *Alg + ) +{ + UINTN Len; + INT32 Ret; + + Len = 0; + Ret = mbedtls_asn1_get_tag ( + Ptr, + End, + &Len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET + ); + + if (Ret == 0) { + End = *Ptr + Len; + // assume only one digest algorithm + Ret = mbedtls_asn1_get_alg_null (Ptr, End, Alg); + } + + return Ret; +} + +/** + certificates :: SET OF ExtendedCertificateOrCertificate, + ExtendedCertificateOrCertificate ::= CHOICE { + certificate Certificate -- x509, + extendedCertificate[0] IMPLICIT ExtendedCertificate }. + + @param[in] Ptr The start of the buffer. + @param[in] Plen The buffer len. + @param[out] Certs mbedtls_x509_crt cert. + + @retval 0 Success. + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. +**/ +STATIC +INT32 +MbedTlsPkcs7GetCertificates ( + UINT8 **Ptr, + INTN Plen, + mbedtls_x509_crt *Certs + ) +{ + INT32 Ret; + + Ret = mbedtls_x509_crt_parse (Certs, *Ptr, Plen); + return Ret; +} + +/** + EncryptedDigest ::= OCTET STRING. + + @param[in] Ptr The start of the buffer. + @param[in] End The end of the buffer. + @param[out] Signature Signature. + + @retval 0 Success. + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. +**/ +STATIC +INT32 +Pkcs7GetSignature ( + UINT8 **Ptr, + UINT8 *End, + mbedtls_asn1_buf *Signature + ) +{ + INT32 Ret; + UINTN Len; + + Len = 0; + Ret = mbedtls_asn1_get_tag (Ptr, End, &Len, MBEDTLS_ASN1_OCTET_STRING); + if (Ret == 0) { + Signature->tag = MBEDTLS_ASN1_OCTET_STRING; + Signature->len = Len; + Signature->p = *Ptr; + } + + return Ret; +} + +/** + SignerInfo ::= SEQUENCE { + version Version; + issuerAndSerialNumber IssuerAndSerialNumber, + digestAlgorithm DigestAlgorithmIdentifier, + authenticatedAttributes + [0] IMPLICIT Attributes OPTIONAL, + digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier, + encryptedDigest EncryptedDigest, + unauthenticatedAttributes + [1] IMPLICIT Attributes OPTIONAL. + + @param[in] Ptr The start of the buffer. + @param[in] End The end of the buffer. + @param[out] SignersSet MbedtlsPkcs7SignerInfo. + + @retval 0 Success. + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. +**/ +STATIC +INT32 +MbedTlsPkcs7GetSignersInfoSet ( + UINT8 **Ptr, + UINT8 *End, + MbedtlsPkcs7SignerInfo *SignersSet + ) +{ + UINT8 *EndSet; + INT32 Ret; + UINTN Len; + UINT8 *TempP; + + Len = 0; + + Ret = mbedtls_asn1_get_tag ( + Ptr, + End, + &Len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET + ); + + if (Ret == 0) { + EndSet = *Ptr + Len; + + Ret = mbedtls_asn1_get_tag ( + Ptr, + EndSet, + &Len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE + ); + } + + if (Ret == 0) { + Ret = mbedtls_asn1_get_int (Ptr, EndSet, &SignersSet->Version); + } + + if (Ret == 0) { + Ret = mbedtls_asn1_get_tag ( + Ptr, + EndSet, + &Len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE + ); + } + + if (Ret == 0) { + SignersSet->IssuerRaw.p = *Ptr; + Ret = mbedtls_asn1_get_tag ( + Ptr, + EndSet, + &Len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE + ); + } + + if (Ret == 0) { + Ret = mbedtls_x509_get_name (Ptr, *Ptr + Len, &SignersSet->Issuer); + } + + if (Ret == 0) { + SignersSet->IssuerRaw.len = *Ptr - SignersSet->IssuerRaw.p; + + Ret = mbedtls_x509_get_serial (Ptr, EndSet, &SignersSet->Serial); + } + + if (Ret == 0) { + Ret = MbedTlsPkcs7GetDigestAlgorithm (Ptr, EndSet, &SignersSet->AlgIdentifier); + } + + // OPTIONAL AuthenticatedAttributes + if (Ret == 0) { + TempP = *Ptr; + if (mbedtls_asn1_get_tag (&TempP, EndSet, &Len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) == 0) { + SignersSet->AuthAttr.len = Len + (TempP - *Ptr); + SignersSet->AuthAttr.p = *Ptr; + *Ptr = TempP + Len; + } else { + SignersSet->AuthAttr.p = NULL; + } + } + + if (Ret == 0) { + Ret = MbedTlsPkcs7GetDigestAlgorithm (Ptr, EndSet, &SignersSet->SigAlgIdentifier); + } + + if (Ret == 0) { + Ret = Pkcs7GetSignature (Ptr, End, &SignersSet->Sig); + } + + if (Ret == 0) { + SignersSet->Next = NULL; + } + + return Ret; +} + +/** + SignedData ::= SEQUENCE { + version Version, + digestAlgorithms DigestAlgorithmIdentifiers, + contentInfo ContentInfo, + certificates + [0] IMPLICIT ExtendedCertificatesAndCertificates + OPTIONAL, + crls + [0] IMPLICIT CertificateRevocationLists OPTIONAL, + signerInfos SignerInfos }. + + @param[in] Buffer The start of the buffer. + @param[in] BufferLen The len the buffer. + @param[out] SignedData MbedtlsPkcs7SignedData. + + @retval 0 Success. + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. +**/ +STATIC +INT32 +Pkcs7GetSignedData ( + UINT8 *Buffer, + INTN BufferLen, + MbedtlsPkcs7SignedData *SignedData + ) +{ + UINT8 *Ptr; + UINT8 *End; + UINTN Len; + INT32 Ret; + UINT8 *CertP; + UINTN CertLen; + UINT8 *OldCertP; + UINTN TotalCertLen; + mbedtls_x509_crt *MoreCert; + UINT8 CertNum; + mbedtls_x509_crt *LastCert; + mbedtls_x509_crt *TempCrt; + + Len = 0; + Ptr = Buffer; + End = Buffer + BufferLen; + MoreCert = NULL; + + Ret = mbedtls_asn1_get_tag ( + &Ptr, + End, + &Len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE + ); + + if (Ret == 0) { + // version + Ret = MbedTlsPkcs7GetVersion (&Ptr, End, &SignedData->Version); + } + + if ((Ret == 0) && (SignedData->Version != 1)) { + Ret = -1; + } + + if (Ret == 0) { + // digest algorithm + Ret = MbedTlsPkcs7GetDigestAlgorithmSet ( + &Ptr, + End, + &SignedData->DigestAlgorithms + ); + } + + if (Ret == 0) { + if ( + #ifndef DISABLE_SHA1_DEPRECATED_INTERFACES + ((SignedData->DigestAlgorithms.len == sizeof (MBEDTLS_OID_DIGEST_ALG_SHA1) - 1) && + (CompareMem ( + SignedData->DigestAlgorithms.p, + MBEDTLS_OID_DIGEST_ALG_SHA1, + SignedData->DigestAlgorithms.len + ) == 0)) || + #endif + ((SignedData->DigestAlgorithms.len == sizeof (MBEDTLS_OID_DIGEST_ALG_SHA256) - 1) && + (CompareMem ( + SignedData->DigestAlgorithms.p, + MBEDTLS_OID_DIGEST_ALG_SHA256, + SignedData->DigestAlgorithms.len + ) == 0)) || + ((SignedData->DigestAlgorithms.len == sizeof (MBEDTLS_OID_DIGEST_ALG_SHA384) - 1) && + (CompareMem ( + SignedData->DigestAlgorithms.p, + MBEDTLS_OID_DIGEST_ALG_SHA384, + SignedData->DigestAlgorithms.len + ) == 0)) || + ((SignedData->DigestAlgorithms.len == sizeof (MBEDTLS_OID_DIGEST_ALG_SHA512) - 1) && + (CompareMem ( + SignedData->DigestAlgorithms.p, + MBEDTLS_OID_DIGEST_ALG_SHA512, + SignedData->DigestAlgorithms.len + ) == 0))) + { + Ret = 0; + } else { + Ret = -1; + } + } + + if (Ret == 0) { + Ret = Pkcs7GetContentInfoType (&Ptr, End, &SignedData->ContentInfo.Oid); + } + + if (Ret == 0) { + // move to next + Ptr = Ptr + SignedData->ContentInfo.Oid.len; + Ret = MbedTlsPkcs7GetNextContentLen (&Ptr, End, &Len); + CertP = Ptr + Len; + + // move to actual cert, if there are more [0] + if (MbedTlsPkcs7GetNextContentLen (&CertP, End, &CertLen) == 0) { + Len = CertLen; + Ptr = CertP; + } + } + + // certificates: may have many certs + CertP = Ptr; + + TotalCertLen = 0; + + MoreCert = &SignedData->Certificates; + CertNum = 0; + + while (TotalCertLen < Len) { + OldCertP = CertP; + + Ret = mbedtls_asn1_get_tag (&CertP, End, &CertLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (Ret != 0) { + goto Out; + } + + // cert total len + CertLen = CertLen + (CertP - OldCertP); + + // move to next cert + CertP = OldCertP + CertLen; + + // change TotalCertLen + TotalCertLen += CertLen; + + mbedtls_x509_crt_init (MoreCert); + Ret = MbedTlsPkcs7GetCertificates (&OldCertP, CertLen, MoreCert); + if (Ret != 0) { + goto Out; + } + + CertNum++; + MoreCert->next = mbedtls_calloc (1, sizeof (mbedtls_x509_crt)); + MoreCert = MoreCert->next; + } + + if (TotalCertLen != Len) { + Ret = -1; + goto Out; + } + + LastCert = &(SignedData->Certificates); + + while (CertNum--) { + if (CertNum == 0) { + LastCert->next = NULL; + break; + } else { + LastCert = LastCert->next; + } + } + + // signers info + if (Ret == 0) { + Ptr = Ptr + Len; + Ret = MbedTlsPkcs7GetSignersInfoSet (&Ptr, End, &SignedData->SignerInfos); + } + +Out: + if (Ret == 0) { + if (MoreCert != NULL) { + mbedtls_x509_crt_free (MoreCert); + MoreCert = NULL; + } + } else { + if (SignedData->Certificates.next != NULL) { + TempCrt = SignedData->Certificates.next; + mbedtls_x509_crt_free (TempCrt); + } + } + + return Ret; +} + +/** + Parse MbedtlsPkcs7 to Der format. + @param[in] Buffer The start of the buffer. + @param[in] BufferLen The len the buffer. + @param[out] Pkcs7 MbedtlsPkcs7. + + @retval 0 Success. + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. +**/ +STATIC +INT32 +MbedtlsPkcs7ParseDer ( + CONST UINT8 *Buffer, + INTN BufferLen, + MbedtlsPkcs7 *Pkcs7 + ) +{ + UINT8 *Ptr; + UINT8 *End; + UINTN Len; + INT32 Ret; + + if (Pkcs7 == NULL) { + return -1; + } + + Len = 0; + Ptr = (UINT8 *)Buffer; + End = Ptr + BufferLen; + + Ret = Pkcs7GetContentInfoType (&Ptr, End, &Pkcs7->ContentTypeOid); + if (Ret != 0) { + goto Out; + } + + if ((CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_DATA, Pkcs7->ContentTypeOid.len) == 0) || + (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, Pkcs7->ContentTypeOid.len) == 0) || + (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_ENVELOPED_DATA, Pkcs7->ContentTypeOid.len) == 0) || + (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA, Pkcs7->ContentTypeOid.len) == 0) || + (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_DIGESTED_DATA, Pkcs7->ContentTypeOid.len) == 0)) + { + // Invalid PKCS7 data type; + Ret = -1; + goto Out; + } + + if (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_SIGNED_DATA, Pkcs7->ContentTypeOid.len) != 0) { + // Invalid PKCS7 data type; + Ret = -1; + goto Out; + } + + // Content type is SignedData + Ptr = Ptr + Pkcs7->ContentTypeOid.len; + + Ret = MbedTlsPkcs7GetNextContentLen (&Ptr, End, &Len); + if (Ret != 0) { + goto Out; + } + + Ret = Pkcs7GetSignedData (Ptr, Len, &Pkcs7->SignedData); + if (Ret != 0) { + goto Out; + } + +Out: + return Ret; +} + +/** + MbedtlsPkcs7 verify MbedtlsPkcs7SignerInfo. + @param[in] SignerInfo MbedtlsPkcs7 SignerInfo. + @param[in] Cert cert. + @param[in] Data Pointer for data. + @param[in] DataLen The len the buffer. + + @retval 0 Success. + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. +**/ +STATIC +INT32 +MbedtlsPkcs7SignedDataVerifySigners ( + MbedtlsPkcs7SignerInfo *SignerInfo, + mbedtls_x509_crt *Cert, + CONST UINT8 *Data, + INTN DataLen + ) +{ + INT32 Ret; + UINT8 Hash[MBEDTLS_MD_MAX_SIZE]; + mbedtls_pk_context Pk; + CONST mbedtls_md_info_t *MdInfo; + INTN HashLen; + UINT8 TempAuthAttr; + + Pk = Cert->pk; + ZeroMem (Hash, MBEDTLS_MD_MAX_SIZE); + + // all the hash algo + #ifndef DISABLE_SHA1_DEPRECATED_INTERFACES + MdInfo = mbedtls_md_info_from_type (MBEDTLS_MD_SHA1); + HashLen = mbedtls_md_get_size (MdInfo); + mbedtls_md (MdInfo, Data, DataLen, Hash); + if (SignerInfo->AuthAttr.p != NULL) { + TempAuthAttr = *(SignerInfo->AuthAttr.p); + *(SignerInfo->AuthAttr.p) = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET; + mbedtls_md (MdInfo, SignerInfo->AuthAttr.p, SignerInfo->AuthAttr.len, Hash); + // Restore content + *(SignerInfo->AuthAttr.p) = TempAuthAttr; + } + + Ret = mbedtls_pk_verify (&Pk, MBEDTLS_MD_SHA1, Hash, HashLen, SignerInfo->Sig.p, SignerInfo->Sig.len); + + if (Ret == 0) { + return Ret; + } + + #endif + + MdInfo = mbedtls_md_info_from_type (MBEDTLS_MD_SHA256); + HashLen = mbedtls_md_get_size (MdInfo); + ZeroMem (Hash, MBEDTLS_MD_MAX_SIZE); + mbedtls_md (MdInfo, Data, DataLen, Hash); + if (SignerInfo->AuthAttr.p != NULL) { + TempAuthAttr = *(SignerInfo->AuthAttr.p); + *(SignerInfo->AuthAttr.p) = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET; + mbedtls_md (MdInfo, SignerInfo->AuthAttr.p, SignerInfo->AuthAttr.len, Hash); + // Restore content + *(SignerInfo->AuthAttr.p) = TempAuthAttr; + } + + Ret = mbedtls_pk_verify (&Pk, MBEDTLS_MD_SHA256, Hash, HashLen, SignerInfo->Sig.p, SignerInfo->Sig.len); + if (Ret == 0) { + return Ret; + } + + MdInfo = mbedtls_md_info_from_type (MBEDTLS_MD_SHA384); + HashLen = mbedtls_md_get_size (MdInfo); + ZeroMem (Hash, MBEDTLS_MD_MAX_SIZE); + mbedtls_md (MdInfo, Data, DataLen, Hash); + if (SignerInfo->AuthAttr.p != NULL) { + TempAuthAttr = *(SignerInfo->AuthAttr.p); + *(SignerInfo->AuthAttr.p) = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET; + mbedtls_md (MdInfo, SignerInfo->AuthAttr.p, SignerInfo->AuthAttr.len, Hash); + // Restore content + *(SignerInfo->AuthAttr.p) = TempAuthAttr; + } + + Ret = mbedtls_pk_verify (&Pk, MBEDTLS_MD_SHA384, Hash, HashLen, SignerInfo->Sig.p, SignerInfo->Sig.len); + if (Ret == 0) { + return Ret; + } + + MdInfo = mbedtls_md_info_from_type (MBEDTLS_MD_SHA512); + HashLen = mbedtls_md_get_size (MdInfo); + ZeroMem (Hash, MBEDTLS_MD_MAX_SIZE); + mbedtls_md (MdInfo, Data, DataLen, Hash); + if (SignerInfo->AuthAttr.p != NULL) { + TempAuthAttr = *(SignerInfo->AuthAttr.p); + *(SignerInfo->AuthAttr.p) = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET; + mbedtls_md (MdInfo, SignerInfo->AuthAttr.p, SignerInfo->AuthAttr.len, Hash); + // Restore content + *(SignerInfo->AuthAttr.p) = TempAuthAttr; + } + + Ret = mbedtls_pk_verify (&Pk, MBEDTLS_MD_SHA512, Hash, HashLen, SignerInfo->Sig.p, SignerInfo->Sig.len); + if (Ret == 0) { + return Ret; + } + + return Ret; +} + +/** + Find signer cert in MbedtlsPkcs7SignerInfo. + + @param[in] SignerInfo MbedtlsPkcs7 SignerInfo. + @param[in] Certs MbedtlsPkcs7 SignerInfo certs. + + @retval cert Signer Cert. +**/ +STATIC +mbedtls_x509_crt * +MbedTlsPkcs7FindSignerCert ( + MbedtlsPkcs7SignerInfo *SignerInfo, + mbedtls_x509_crt *Certs + ) +{ + mbedtls_x509_crt *Cert; + + Cert = Certs; + while (Cert != NULL) { + if ((Cert->serial.p == NULL) || (Cert->issuer_raw.p == NULL)) { + return NULL; + } + + if ((Cert->issuer_raw.len == SignerInfo->IssuerRaw.len) && + (CompareMem (Cert->issuer_raw.p, SignerInfo->IssuerRaw.p, Cert->issuer_raw.len) == 0) && + (Cert->serial.len == SignerInfo->Serial.len) && + (CompareMem (Cert->serial.p, SignerInfo->Serial.p, Cert->serial.len) == 0)) + { + break; + } + + Cert = Cert->next; + } + + return Cert; +} + +/** + verify cert. + + @param[in] Ca CA cert. + @param[in] CaCrl CRL. + @param[in] End Cert which need be verified. + + @retval TRUE Verify successfully. + @retval FALSE Verify failed. +**/ +STATIC +BOOLEAN +MbedTlsPkcs7VerifyCert ( + mbedtls_x509_crt *Ca, + mbedtls_x509_crl *CaCrl, + mbedtls_x509_crt *End + ) +{ + INT32 Ret; + UINT32 VFlag; + mbedtls_x509_crt_profile Profile; + + VFlag = 0; + CopyMem (&Profile, &gCompatProfile, sizeof (mbedtls_x509_crt_profile)); + + Ret = mbedtls_x509_crt_verify_with_profile (End, Ca, CaCrl, &Profile, NULL, &VFlag, NULL, NULL); + + return Ret == 0; +} + +/** + verify cert chain. + + @param[in] Pkcs7 MbedtlsPkcs7. + @param[in] Ca CA cert. + @param[in] End Cert which need be verified. + + @retval TRUE Verify successfully. + @retval FALSE Verify failed. +**/ +STATIC +BOOLEAN +MbedTlsPkcs7VerifyCertChain ( + MbedtlsPkcs7 *Pkcs7, + mbedtls_x509_crt *Ca, + mbedtls_x509_crt *End + ) +{ + mbedtls_x509_crt *AllCert; + mbedtls_x509_crt *InterCert; + + AllCert = &(Pkcs7->SignedData.Certificates); + InterCert = NULL; + + while (AllCert != NULL) { + if ((AllCert->next == End) && (MbedTlsPkcs7VerifyCert (AllCert, NULL, End))) { + InterCert = AllCert; + break; + } + + AllCert = AllCert->next; + } + + if (InterCert == NULL) { + return FALSE; + } + + if (MbedTlsPkcs7VerifyCert (Ca, &(Pkcs7->SignedData.Crls), InterCert)) { + return TRUE; + } else { + return MbedTlsPkcs7VerifyCertChain (Pkcs7, Ca, InterCert); + } +} + +/** + MbedTlsPkcs7 Verify SignedData. + + @param[in] Pkcs7 MbedtlsPkcs7. + @param[in] TrustCert CA cert. + @param[in] Data Pointer for data. + @param[in] DataLen The len the buffer. + + @retval TRUE Verify successfully. + @retval FALSE Verify failed. +**/ +STATIC +BOOLEAN +MbedTlsPkcs7SignedDataVerify ( + MbedtlsPkcs7 *Pkcs7, + mbedtls_x509_crt *TrustCert, + CONST UINT8 *Data, + INTN DataLen + ) +{ + MbedtlsPkcs7SignerInfo *SignerInfo; + mbedtls_x509_crt *Cert; + mbedtls_x509_crt *AllCert; + BOOLEAN Result; + + SignerInfo = &(Pkcs7->SignedData.SignerInfos); + Result = TRUE; + + // + // Traverse signers and verify each signers + // + while (SignerInfo != NULL) { + Result = FALSE; + // 1. Find signers cert + Cert = MbedTlsPkcs7FindSignerCert (SignerInfo, &(Pkcs7->SignedData.Certificates)); + if (Cert != NULL) { + // 2. Check signer cert is trusted by trustCert + if (MbedTlsPkcs7VerifyCert (TrustCert, &(Pkcs7->SignedData.Crls), Cert)) { + // root cert verify pass + Result = TRUE; + } else { + if (MbedTlsPkcs7VerifyCertChain (Pkcs7, TrustCert, Cert)) { + Result = TRUE; + } else { + Result = FALSE; + } + } + + if (Result == TRUE) { + // 3. Check signed data + AllCert = &(Pkcs7->SignedData.Certificates); + while (AllCert != NULL) { + if (MbedtlsPkcs7SignedDataVerifySigners (SignerInfo, AllCert, Data, DataLen) == 0) { + return TRUE; + } + + AllCert = AllCert->next; + } + + Result = FALSE; + } + } + + // move to next + SignerInfo = SignerInfo->Next; + } + + return Result; +} + +/** + 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] == MBEDTLS_ASN1_OID) && (P7Data[5] == sizeof (MBEDTLS_OID_PKCS7_SIGNED_DATA) - 1)) { + if (CompareMem (P7Data + 6, MBEDTLS_OID_PKCS7_SIGNED_DATA, sizeof (MBEDTLS_OID_PKCS7_SIGNED_DATA) - 1) == 0) { + if ((P7Data[15] == (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) && (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 = calloc (*WrapDataSize, 1); + if (*WrapData == NULL) { + *WrapFlag = Wrapped; + return FALSE; + } + + SignedData = *WrapData; + + // + // Part1: 0x30, 0x82. + // + SignedData[0] = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE; + 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] = MBEDTLS_ASN1_OID; + SignedData[5] = sizeof (MBEDTLS_OID_PKCS7_SIGNED_DATA) - 1; + + // + // Part4: OID value -- 0x2A 0x86 0x48 0x86 0xF7 0x0D 0x01 0x07 0x02. + // + CopyMem (SignedData + 6, MBEDTLS_OID_PKCS7_SIGNED_DATA, sizeof (MBEDTLS_OID_PKCS7_SIGNED_DATA) - 1); + + // + // Part5: 0xA0, 0x82. + // + SignedData[15] = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC; + 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; +} + +/** + 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 + ) +{ + BOOLEAN Status; + UINT8 *WrapData; + UINTN WrapDataSize; + BOOLEAN Wrapped; + MbedtlsPkcs7 Pkcs7; + INT32 Ret; + mbedtls_x509_crt Crt; + mbedtls_x509_crt *TempCrt; + + // + // Check input parameters. + // + if ((P7Data == NULL) || (TrustedCert == NULL) || (InData == NULL) || + (P7Length > INT_MAX) || (CertLength > INT_MAX) || (DataLength > INT_MAX)) + { + return FALSE; + } + + Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &WrapData, &WrapDataSize); + + if (!Status) { + return FALSE; + } + + Status = FALSE; + MbedTlsPkcs7Init (&Pkcs7); + mbedtls_x509_crt_init (&Crt); + + Ret = MbedtlsPkcs7ParseDer (WrapData, (INT32)WrapDataSize, &Pkcs7); + if (Ret != 0) { + goto Cleanup; + } + + Ret = mbedtls_x509_crt_parse_der (&Crt, TrustedCert, CertLength); + if (Ret != 0) { + goto Cleanup; + } + + Status = MbedTlsPkcs7SignedDataVerify (&Pkcs7, &Crt, InData, (INT32)DataLength); + +Cleanup: + if (!Wrapped) { + free (WrapData); + } + + if (&Crt != NULL) { + mbedtls_x509_crt_free (&Crt); + } + + if (Pkcs7.SignedData.Certificates.next != NULL) { + TempCrt = Pkcs7.SignedData.Certificates.next; + mbedtls_x509_crt_free (TempCrt); + } + + 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); +} + +/** + 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 + ) +{ + MbedtlsPkcs7SignerInfo *SignerInfo; + mbedtls_x509_crt *Cert; + MbedtlsPkcs7 Pkcs7; + BOOLEAN Status; + UINT8 *WrapData; + UINTN WrapDataSize; + BOOLEAN Wrapped; + mbedtls_x509_crt *TempCrt; + + UINTN CertSize; + UINT8 Index; + UINT8 *CertBuf; + UINT8 *OldBuf; + UINTN BufferSize; + UINTN OldSize; + + if ((P7Data == NULL) || (CertStack == NULL) || (StackLength == NULL) || + (TrustedCert == NULL) || (CertLength == NULL) || (P7Length > INT_MAX)) + { + return FALSE; + } + + Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &WrapData, &WrapDataSize); + + if (!Status) { + return FALSE; + } + + Status = FALSE; + CertBuf = NULL; + OldBuf = NULL; + Cert = NULL; + + MbedTlsPkcs7Init (&Pkcs7); + if (MbedtlsPkcs7ParseDer (WrapData, (INT32)WrapDataSize, &Pkcs7) != 0) { + goto _Exit; + } + + SignerInfo = &(Pkcs7.SignedData.SignerInfos); + + // + // Traverse each signers + // + // 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; + Index = 0; + + while (SignerInfo != NULL) { + // Find signers cert + Cert = MbedTlsPkcs7FindSignerCert (SignerInfo, &(Pkcs7.SignedData.Certificates)); + if (Cert == NULL) { + goto _Exit; + } + + CertSize = Cert->raw.len; + OldSize = BufferSize; + OldBuf = CertBuf; + BufferSize = OldSize + CertSize + sizeof (UINT32); + + CertBuf = calloc (BufferSize, 1); + if (CertBuf == NULL) { + goto _Exit; + } + + if (OldBuf != NULL) { + CopyMem (CertBuf, OldBuf, OldSize); + free (OldBuf); + OldBuf = NULL; + } + + WriteUnaligned32 ((UINT32 *)(CertBuf + OldSize), (UINT32)CertSize); + CopyMem (CertBuf + OldSize + sizeof (UINT32), Cert->raw.p, CertSize); + + Index++; + + // move to next + SignerInfo = SignerInfo->Next; + } + + if (CertBuf != NULL) { + // + // Update CertNumber. + // + CertBuf[0] = Index; + + *CertLength = BufferSize - OldSize - sizeof (UINT32); + *TrustedCert = calloc (*CertLength, 1); + if (*TrustedCert == NULL) { + goto _Exit; + } + + CopyMem (*TrustedCert, CertBuf + OldSize + sizeof (UINT32), *CertLength); + *CertStack = CertBuf; + *StackLength = BufferSize; + Status = TRUE; + } + +_Exit: + if (!Wrapped) { + free (WrapData); + } + + // + // Release Resources + // + if (!Status && (CertBuf != NULL)) { + free (CertBuf); + *CertStack = NULL; + } + + if (Status) { + if (Pkcs7.SignedData.Certificates.next != NULL) { + TempCrt = Pkcs7.SignedData.Certificates.next; + mbedtls_x509_crt_free (TempCrt); + } + } + + if (OldBuf != NULL) { + free (OldBuf); + } + + return Status; +} + +/** + 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; +} diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c new file mode 100644 index 0000000000..47a8230cf6 --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c @@ -0,0 +1,689 @@ +/** @file + This module verifies that Enhanced Key Usages (EKU's) are present within + a PKCS7 signature blob using MbedTLS. + + Copyright (C) Microsoft Corporation. All Rights Reserved. + Copyright (c) 2024, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include "InternalCryptLib.h" +#include +#include + +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 EkuOID[] = { 0x55, 0x1D, 0x25 }; + +/*leaf Cert basic_constraints case1: CA: false and CA object is excluded */ +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 gBasicConstraintsCase1[] = { 0x30, 0x00 }; + +/*leaf Cert basic_constraints case2: CA: false */ +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 gBasicConstraintsCase2[] = { 0x30, 0x06, 0x01, 0x01, 0xFF, 0x02, 0x01, 0x00 }; + +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 gOidBasicConstraints[] = { 0x55, 0x1D, 0x13 }; + +/** + Find first Extension data match with given OID + + @param[in] Start Pointer to the DER-encoded extensions data + @param[in] End extensions data size in bytes + @param[in ] Oid OID for match + @param[in ] OidSize OID size in bytes + @param[out] FindExtensionData output matched extension data. + @param[out] FindExtensionDataLen matched extension data size. + +**/ +STATIC +BOOLEAN +InternalX509FindExtensionData ( + UINT8 *Start, + UINT8 *End, + CONST UINT8 *Oid, + UINTN OidSize, + UINT8 **FindExtensionData, + UINTN *FindExtensionDataLen + ) +{ + UINT8 *Ptr; + UINT8 *ExtensionPtr; + UINTN ObjLen; + INT32 Ret; + BOOLEAN Status; + UINTN FindExtensionLen; + UINTN HeaderLen; + + /*If no Extension entry match Oid*/ + Status = FALSE; + Ptr = Start; + + Ret = 0; + + while (TRUE) { + // + // Extension ::= SEQUENCE { + // extnID OBJECT IDENTIFIER, + // critical BOOLEAN DEFAULT FALSE, + // extnValue OCTET STRING } + // + ExtensionPtr = Ptr; + Ret = mbedtls_asn1_get_tag ( + &Ptr, + End, + &ObjLen, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE + ); + if (Ret == 0) { + HeaderLen = (UINTN)(Ptr - ExtensionPtr); + FindExtensionLen = ObjLen; + /* Get Object Identifier*/ + Ret = mbedtls_asn1_get_tag ( + &Ptr, + End, + &ObjLen, + MBEDTLS_ASN1_OID + ); + } else { + break; + } + + if ((Ret == 0) && !CompareMem (Ptr, Oid, OidSize)) { + Ptr += ObjLen; + + Ret = mbedtls_asn1_get_tag ( + &Ptr, + End, + &ObjLen, + MBEDTLS_ASN1_BOOLEAN + ); + if (Ret == 0) { + Ptr += ObjLen; + } + + Ret = mbedtls_asn1_get_tag ( + &Ptr, + End, + &ObjLen, + MBEDTLS_ASN1_OCTET_STRING + ); + } else { + Ret = 1; + } + + if (Ret == 0) { + *FindExtensionData = Ptr; + *FindExtensionDataLen = ObjLen; + Status = TRUE; + break; + } + + /* move to next*/ + Ptr = ExtensionPtr + HeaderLen + FindExtensionLen; + Ret = 0; + } + + return Status; +} + +/** + Retrieve Extension data from one X.509 certificate. + + @param[in] Cert Pointer to the X509 certificate. + @param[in] Oid Object identifier buffer + @param[in] OidSize Object identifier buffer size + @param[out] ExtensionData Extension bytes. + @param[in, out] ExtensionDataSize Extension bytes size. + + @retval RETURN_SUCCESS The certificate Extension data retrieved successfully. + @retval RETURN_INVALID_PARAMETER If Cert is NULL. + If ExtensionDataSize is NULL. + If ExtensionData is not NULL and *ExtensionDataSize is 0. + If Certificate is invalid. + @retval RETURN_NOT_FOUND If no Extension entry match Oid. + @retval RETURN_BUFFER_TOO_SMALL If the ExtensionData is NULL. The required buffer size + is returned in the ExtensionDataSize parameter. + @retval RETURN_UNSUPPORTED The operation is not supported. +**/ +STATIC +BOOLEAN +GetExtensionData ( + CONST mbedtls_x509_crt *Cert, + CONST UINT8 *Oid, + UINTN OidSize, + UINT8 *ExtensionData, + UINTN *ExtensionDataSize + ) +{ + CONST mbedtls_x509_crt *Crt; + INT32 Ret; + BOOLEAN Status; + UINT8 *Ptr; + UINT8 *End; + UINTN ObjLen; + + Ptr = NULL; + End = NULL; + ObjLen = 0; + + if ((Cert == NULL) || (Oid == NULL) || (OidSize == 0) || + (ExtensionDataSize == NULL)) + { + return FALSE; + } + + Status = FALSE; + + Crt = Cert; + + Ptr = Crt->v3_ext.p; + End = Crt->v3_ext.p + Crt->v3_ext.len; + Ret = mbedtls_asn1_get_tag ( + &Ptr, + End, + &ObjLen, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE + ); + + if (Ret == 0) { + Status = InternalX509FindExtensionData ( + Ptr, + End, + Oid, + OidSize, + &Ptr, + &ObjLen + ); + } + + if (Status) { + if (*ExtensionDataSize < ObjLen) { + *ExtensionDataSize = ObjLen; + Status = FALSE; + goto Cleanup; + } + + if (Oid != NULL) { + if (ExtensionData == NULL) { + return FALSE; + } + + CopyMem (ExtensionData, Ptr, ObjLen); + } + + *ExtensionDataSize = ObjLen; + } else { + *ExtensionDataSize = 0; + } + +Cleanup: + return Status; +} + +/** + Determines if the specified EKU represented in ASN1 form is present + in a given certificate. + + @param[in] Cert The certificate to check. + @param[in] EKU The EKU to look for. + @param[in] EkuLen The size of EKU. + + @retval EFI_SUCCESS We successfully identified the signing type. + @retval EFI_INVALID_PARAMETER A parameter was invalid. + @retval EFI_NOT_FOUND One or more EKU's were not found in the signature. + +**/ +STATIC +EFI_STATUS +IsEkuInCertificate ( + IN CONST mbedtls_x509_crt *Cert, + IN UINT8 *EKU, + IN UINTN EkuLen + ) +{ + EFI_STATUS Status; + BOOLEAN Ret; + UINT8 *Buffer; + UINTN Index; + UINTN Len; + + if ((Cert == NULL) || (EKU == NULL)) { + Status = EFI_INVALID_PARAMETER; + return Status; + } + + Len = 0; + Buffer = NULL; + Ret = GetExtensionData ( + Cert, + (CONST UINT8 *)EkuOID, + sizeof (EkuOID), + NULL, + &Len + ); + if (Len == 0) { + Status = EFI_NOT_FOUND; + goto Exit; + } + + Buffer = AllocateZeroPool (Len); + if (Buffer == NULL) { + Status = EFI_NOT_FOUND; + goto Exit; + } + + Ret = GetExtensionData ( + Cert, + (CONST UINT8 *)EkuOID, + sizeof (EkuOID), + Buffer, + &Len + ); + + if ((Len == 0) || (!Ret)) { + Status = EFI_NOT_FOUND; + goto Exit; + } + + Status = EFI_NOT_FOUND; + /*find the spdm hardware identity OID*/ + for (Index = 0; Index <= Len - EkuLen; Index++) { + if (!CompareMem (Buffer + Index, EKU, EkuLen)) { + // check sub EKU + if (Index == Len - EkuLen) { + Status = EFI_SUCCESS; + break; + // Ensure that the OID is complete + } else if (Buffer[Index + EkuLen] == 0x06) { + Status = EFI_SUCCESS; + break; + } else { + break; + } + } + } + +Exit: + if (Buffer != NULL) { + FreePool (Buffer); + } + + return Status; +} + +/** + Get OID from txt. + + @param[in] RequiredEKUs Array of null-terminated strings listing OIDs of + required EKUs that must be present in the signature. + @param[in] RequiredEKUsSize Number of elements in the RequiredEKUs string array. + @param[in,out] CheckOid OID. + @param[out] OidLen The size of OID. + +**/ +VOID +GetOidFromTxt ( + IN CONST CHAR8 *RequiredEKUs, + IN UINTN RequiredEKUsSize, + IN OUT UINT8 *CheckOid, + OUT UINT8 *OidLen + ) +{ + UINT8 *Ptr; + UINT16 Index; + UINT32 Data; + UINT8 OidIndex; + UINTN EKUsSize; + + EKUsSize = RequiredEKUsSize; + // https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-object-identifier?redirectedfrom=MSDN + CheckOid[0] = (UINT8)((RequiredEKUs[0] - '0') * 40 + (RequiredEKUs[2] - '0')); + + EKUsSize = EKUsSize - 4; + Ptr = (UINT8 *)(RequiredEKUs + 4); + + OidIndex = 1; + + while (EKUsSize) { + Index = 0; + Data = 0; + + while ((*Ptr != '.') && (*Ptr != '\0')) { + Index++; + Ptr++; + EKUsSize--; + } + + while (Index) { + Data = 10 * Data + (*(Ptr - Index) - '0'); + Index--; + } + + if (EKUsSize != 0) { + Ptr++; + EKUsSize--; + } + + if (Data < 128) { + CheckOid[OidIndex] = (UINT8)Data; + OidIndex++; + } else { + CheckOid[OidIndex + 1] = (UINT8)(Data & 0xFF); + CheckOid[OidIndex] = (UINT8)(((((Data & 0xFF00) << 1) | 0x8000) >> 8) & 0xFF); + OidIndex = OidIndex + 2; + } + } + + *OidLen = OidIndex; +} + +/** + Verify the Cert is signer cert + + @param[in] Start Pointer to the DER-encoded certificate data Start. + @param[in] End Pointer to the DER-encoded certificate data End. + + @retval true verify pass + @retval false verify fail +**/ +STATIC +BOOLEAN +IsCertSignerCert ( + UINT8 *Start, + UINT8 *End + ) +{ + BOOLEAN Status; + UINT8 *Buffer; + UINTN Len; + mbedtls_x509_crt Cert; + UINTN ObjLen; + + mbedtls_x509_crt_init (&Cert); + + ObjLen = End - Start; + + if (mbedtls_x509_crt_parse_der (&Cert, Start, ObjLen) != 0) { + return FALSE; + } + + Len = 0; + Buffer = NULL; + Status = GetExtensionData ( + &Cert, + (CONST UINT8 *)gOidBasicConstraints, + sizeof (gOidBasicConstraints), + NULL, + &Len + ); + if (Len == 0) { + /* basic constraints is not present in Cert */ + return TRUE; + } + + Buffer = AllocateZeroPool (Len); + if (Buffer == NULL) { + return FALSE; + } + + Status = GetExtensionData ( + &Cert, + (CONST UINT8 *)gOidBasicConstraints, + sizeof (gOidBasicConstraints), + Buffer, + &Len + ); + + if (Len == 0) { + /* basic constraints is not present in Cert */ + Status = TRUE; + goto Exit; + } else if (!Status) { + Status = FALSE; + goto Exit; + } + + if ((Len == sizeof (gBasicConstraintsCase1)) && + (!CompareMem (Buffer, gBasicConstraintsCase1, sizeof (gBasicConstraintsCase1)))) + { + Status = TRUE; + goto Exit; + } + + if ((Len == sizeof (gBasicConstraintsCase2)) && + (!CompareMem (Buffer, gBasicConstraintsCase2, sizeof (gBasicConstraintsCase2)))) + { + Status = TRUE; + goto Exit; + } + + Status = FALSE; + +Exit: + mbedtls_x509_crt_free (&Cert); + + if (Buffer != NULL) { + FreePool (Buffer); + } + + return Status; +} + +/** + Determines if the specified EKUs are present in a signing certificate. + + @param[in] SignerCert The certificate to check. + @param[in] RequiredEKUs The EKUs to look for. + @param[in] RequiredEKUsSize The number of EKUs + @param[in] RequireAllPresent If TRUE, then all the specified EKUs + must be present in the certificate. + + @retval EFI_SUCCESS We successfully identified the signing type. + @retval EFI_INVALID_PARAMETER A parameter was invalid. + @retval EFI_NOT_FOUND One or more EKU's were not found in the signature. +**/ +STATIC +EFI_STATUS +CheckEKUs ( + IN CONST mbedtls_x509_crt *SignerCert, + IN CONST CHAR8 *RequiredEKUs[], + IN CONST UINT32 RequiredEKUsSize, + IN BOOLEAN RequireAllPresent + ) +{ + EFI_STATUS Status; + UINT32 NumEkusFound; + UINT32 Index; + UINT8 *EKU; + UINTN EkuLen; + UINT8 CheckOid[20]; + UINT8 OidLen; + + Status = EFI_SUCCESS; + NumEkusFound = 0; + + if ((SignerCert == NULL) || (RequiredEKUs == NULL) || (RequiredEKUsSize == 0)) { + Status = EFI_INVALID_PARAMETER; + goto Exit; + } + + for (Index = 0; Index < RequiredEKUsSize; Index++) { + // + // Finding required EKU in Cert. + // + GetOidFromTxt (RequiredEKUs[Index], strlen (RequiredEKUs[Index]), CheckOid, &OidLen); + + EKU = CheckOid; + EkuLen = OidLen; + + Status = IsEkuInCertificate (SignerCert, EKU, EkuLen); + if (Status == EFI_SUCCESS) { + NumEkusFound++; + if (!RequireAllPresent) { + // + // Found at least one, so we are done. + // + goto Exit; + } + } else { + // + // Fail to find Eku in Cert + break; + } + } + +Exit: + if (RequireAllPresent && + (NumEkusFound == RequiredEKUsSize)) + { + // + // Found all required EKUs in certificate. + // + Status = EFI_SUCCESS; + } + + return Status; +} + +/** + This function receives a PKCS#7 formatted signature blob, + looks for the EKU SEQUENCE blob, and if found then looks + for all the required EKUs. This function was created so that + the Surface team can cut down on the number of Certificate + Authorities (CA's) by checking EKU's on leaf signers for + a specific product. This prevents one product's certificate + from signing another product's firmware or unlock blobs. + + Note that this function does not validate the certificate chain. + That needs to be done before using this function. + + @param[in] Pkcs7Signature The PKCS#7 signed information content block. An array + containing the content block with both the signature, + the signer's certificate, and any necessary intermediate + certificates. + @param[in] Pkcs7SignatureSize Number of bytes in Pkcs7Signature. + @param[in] RequiredEKUs Array of null-terminated strings listing OIDs of + required EKUs that must be present in the signature. + @param[in] RequiredEKUsSize Number of elements in the RequiredEKUs string array. + @param[in] RequireAllPresent If this is TRUE, then all of the specified EKU's + must be present in the leaf signer. If it is + FALSE, then we will succeed if we find any + of the specified EKU's. + + @retval EFI_SUCCESS The required EKUs were found in the signature. + @retval EFI_INVALID_PARAMETER A parameter was invalid. + @retval EFI_NOT_FOUND One or more EKU's were not found in the signature. + +**/ +EFI_STATUS +EFIAPI +VerifyEKUsInPkcs7Signature ( + IN CONST UINT8 *Pkcs7Signature, + IN CONST UINT32 SignatureSize, + IN CONST CHAR8 *RequiredEKUs[], + IN CONST UINT32 RequiredEKUsSize, + IN BOOLEAN RequireAllPresent + ) +{ + EFI_STATUS Status; + mbedtls_x509_crt Cert; + UINT8 *Ptr; + UINT8 *End; + INT32 Len; + UINTN ObjLen; + UINT8 *OldEnd; + + // + // Check input parameter. + // + if ((RequiredEKUs == NULL) || (Pkcs7Signature == NULL)) { + Status = EFI_INVALID_PARAMETER; + return Status; + } + + mbedtls_x509_crt_init (&Cert); + + Ptr = (UINT8 *)(UINTN)Pkcs7Signature; + Len = (UINT32)SignatureSize; + End = Ptr + Len; + + // Cert + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + // tbscert + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) != 0) { + return FALSE; + } + + Ptr += ObjLen; + // signature algo + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET) != 0) { + return FALSE; + } + + Ptr += ObjLen; + // signature + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + Ptr += ObjLen; + OldEnd = Ptr; + // Cert + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) { + return FALSE; + } + + End = Ptr + ObjLen; + + // leaf Cert + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + Ptr += ObjLen; + + while ((Ptr != End) && (Ptr < End)) { + if (IsCertSignerCert (OldEnd, Ptr)) { + break; + } + + OldEnd = Ptr; + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + Ptr += ObjLen; + } + + if (Ptr != End) { + return FALSE; + } else { + Ptr = End - ObjLen; + } + + // leaf Cert + ObjLen += Ptr - OldEnd; + Ptr = OldEnd; + + if (mbedtls_x509_crt_parse_der (&Cert, Ptr, ObjLen) != 0) { + return FALSE; + } + + Status = CheckEKUs (&Cert, RequiredEKUs, RequiredEKUsSize, RequireAllPresent); + if (Status != EFI_SUCCESS) { + goto Exit; + } + +Exit: + // + // Release Resources + // + mbedtls_x509_crt_free (&Cert); + + return Status; +} diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaBasic.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaBasic.c index 8b61ae02ec..d41b064002 100644 --- a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaBasic.c +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaBasic.c @@ -33,7 +33,7 @@ RsaNew ( { VOID *RsaContext; - RsaContext = AllocateZeroPool (sizeof (mbedtls_rsa_context)); + RsaContext = calloc (sizeof (mbedtls_rsa_context), 1); if (RsaContext == NULL) { return RsaContext; } @@ -59,9 +59,7 @@ RsaFree ( ) { mbedtls_rsa_free (RsaContext); - if (RsaContext != NULL) { - FreePool (RsaContext); - } + free (RsaContext); } /** diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaExt.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaExt.c new file mode 100644 index 0000000000..5fe76f146d --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaExt.c @@ -0,0 +1,352 @@ +/** @file + RSA Asymmetric Cipher Wrapper Implementation over MbedTLS. + + This file implements following APIs which provide more capabilities for RSA: + 1) RsaGetKey + 2) RsaGenerateKey + 3) RsaCheckKey + 4) RsaPkcs1Sign + + RFC 8017 - PKCS #1: RSA Cryptography Specifications Version 2.2 + +Copyright (c) 2024, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "InternalCryptLib.h" +#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 + ) +{ + mbedtls_rsa_context *RsaKey; + INT32 Ret; + mbedtls_mpi Value; + UINTN Size; + + // + // Check input parameters. + // + if ((RsaContext == NULL) || (*BnSize > INT_MAX)) { + return FALSE; + } + + // + // Init mbedtls_mpi + // + mbedtls_mpi_init (&Value); + Size = *BnSize; + *BnSize = 0; + + RsaKey = (mbedtls_rsa_context *)RsaContext; + + switch (KeyTag) { + case RsaKeyN: + Ret = mbedtls_rsa_export (RsaKey, &Value, NULL, NULL, NULL, NULL); + break; + case RsaKeyE: + Ret = mbedtls_rsa_export (RsaKey, NULL, NULL, NULL, NULL, &Value); + break; + case RsaKeyD: + Ret = mbedtls_rsa_export (RsaKey, NULL, NULL, NULL, &Value, NULL); + break; + case RsaKeyQ: + Ret = mbedtls_rsa_export (RsaKey, NULL, NULL, &Value, NULL, NULL); + break; + case RsaKeyP: + Ret = mbedtls_rsa_export (RsaKey, NULL, &Value, NULL, NULL, NULL); + break; + case RsaKeyDp: + case RsaKeyDq: + case RsaKeyQInv: + default: + Ret = -1; + break; + } + + if (Ret != 0) { + goto End; + } + + if (mbedtls_mpi_size (&Value) == 0) { + Ret = 0; + goto End; + } + + *BnSize = Size; + + Size = mbedtls_mpi_size (&Value); + if (*BnSize < Size) { + Ret = 1; + *BnSize = Size; + goto End; + } + + if (BigNumber == NULL) { + Ret = 0; + *BnSize = Size; + goto End; + } + + if ((BigNumber != NULL) && (Ret == 0)) { + Ret = mbedtls_mpi_write_binary (&Value, BigNumber, Size); + *BnSize = Size; + } + +End: + mbedtls_mpi_free (&Value); + return Ret == 0; +} + +/** + Generates RSA key components. + + This function generates RSA key components. It takes RSA public exponent Pe 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 + ) +{ + INT32 Ret; + mbedtls_rsa_context *Rsa; + INT32 Pe; + + // + // Check input parameters. + // + if ((RsaContext == NULL) || (ModulusLength > INT_MAX) || (PublicExponentSize > INT_MAX)) { + return FALSE; + } + + Rsa = (mbedtls_rsa_context *)RsaContext; + + if (PublicExponent == NULL) { + Pe = 0x10001; + } else { + if (PublicExponentSize == 0) { + return FALSE; + } + + switch (PublicExponentSize) { + case 1: + Pe = PublicExponent[0]; + break; + case 2: + Pe = PublicExponent[0] << 8 | PublicExponent[1]; + break; + case 3: + Pe = PublicExponent[0] << 16 | PublicExponent[1] << 8 | + PublicExponent[2]; + break; + case 4: + Pe = PublicExponent[0] << 24 | PublicExponent[1] << 16 | + PublicExponent[2] << 8 | PublicExponent[3]; + break; + default: + return FALSE; + } + } + + Ret = mbedtls_rsa_gen_key ( + Rsa, + MbedtlsRand, + NULL, + (UINT32)ModulusLength, + Pe + ); + + return Ret == 0; +} + +/** + 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 + ) +{ + if (RsaContext == NULL) { + return FALSE; + } + + UINT32 Ret; + + Ret = mbedtls_rsa_complete (RsaContext); + if (Ret == 0) { + Ret = mbedtls_rsa_check_privkey (RsaContext); + } + + return Ret == 0; +} + +/** + 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, SHA-256, SHA-384 or SHA-512 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 + ) +{ + INT32 Ret; + mbedtls_md_type_t MdAlg; + + if ((RsaContext == NULL) || (MessageHash == NULL)) { + return FALSE; + } + + if (mbedtls_rsa_complete ((mbedtls_rsa_context *)RsaContext) != 0) { + return FALSE; + } + + switch (HashSize) { + #ifndef DISABLE_SHA1_DEPRECATED_INTERFACES + case SHA1_DIGEST_SIZE: + MdAlg = MBEDTLS_MD_SHA1; + break; + #endif + + case SHA256_DIGEST_SIZE: + MdAlg = MBEDTLS_MD_SHA256; + break; + + case SHA384_DIGEST_SIZE: + MdAlg = MBEDTLS_MD_SHA384; + break; + + case SHA512_DIGEST_SIZE: + MdAlg = MBEDTLS_MD_SHA512; + break; + + default: + return FALSE; + } + + if (mbedtls_rsa_get_len (RsaContext) > *SigSize) { + *SigSize = mbedtls_rsa_get_len (RsaContext); + return FALSE; + } + + if (Signature == NULL) { + return FALSE; + } + + Ret = mbedtls_rsa_set_padding (RsaContext, MBEDTLS_RSA_PKCS_V15, MdAlg); + if (Ret != 0) { + return FALSE; + } + + Ret = mbedtls_rsa_pkcs1_sign ( + RsaContext, + MbedtlsRand, + NULL, + MdAlg, + (UINT32)HashSize, + MessageHash, + Signature + ); + if (Ret != 0) { + return FALSE; + } + + *SigSize = mbedtls_rsa_get_len (RsaContext); + return TRUE; +} diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaPssSign.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaPssSign.c new file mode 100644 index 0000000000..5555f9261e --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaPssSign.c @@ -0,0 +1,140 @@ +/** @file + RSA PSS Asymmetric Cipher Wrapper Implementation over MbedTLS. + + This file implements following APIs which provide basic capabilities for RSA: + 1) RsaPssSign + +Copyright (c) 2024, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "InternalCryptLib.h" +#include +#include +#include + +/** + Carries out the RSA-SSA signature generation with EMSA-PSS encoding scheme. + + This function carries out the RSA-SSA signature generation with EMSA-PSS encoding scheme defined in + RFC 8017. + Mask generation function is the same as the message digest algorithm. + 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 Message is NULL, then return FALSE. + If MsgSize is zero or > INT_MAX, then return FALSE. + If DigestLen is NOT 32, 48 or 64, return FALSE. + If SaltLen is not equal to DigestLen, 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] Message Pointer to octet message to be signed. + @param[in] MsgSize Size of the message in bytes. + @param[in] DigestLen Length of the digest in bytes to be used for RSA signature operation. + @param[in] SaltLen Length of the salt in bytes to be used for PSS encoding. + @param[out] Signature Pointer to buffer to receive RSA PSS 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 RSASSA-PSS. + @retval FALSE Signature generation failed. + @retval FALSE SigSize is too small. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +RsaPssSign ( + IN VOID *RsaContext, + IN CONST UINT8 *Message, + IN UINTN MsgSize, + IN UINT16 DigestLen, + IN UINT16 SaltLen, + OUT UINT8 *Signature, + IN OUT UINTN *SigSize + ) +{ + INT32 Ret; + mbedtls_md_type_t MdAlg; + UINT8 HashValue[SHA512_DIGEST_SIZE]; + + if (RsaContext == NULL) { + return FALSE; + } + + if (mbedtls_rsa_complete ((mbedtls_rsa_context *)RsaContext) != 0) { + return FALSE; + } + + if ((Message == NULL) || (MsgSize == 0) || (MsgSize > INT_MAX)) { + return FALSE; + } + + if (SaltLen != DigestLen) { + return FALSE; + } + + ZeroMem (HashValue, DigestLen); + + switch (DigestLen) { + case SHA256_DIGEST_SIZE: + MdAlg = MBEDTLS_MD_SHA256; + if (mbedtls_sha256 (Message, MsgSize, HashValue, FALSE) != 0) { + return FALSE; + } + + break; + + case SHA384_DIGEST_SIZE: + MdAlg = MBEDTLS_MD_SHA384; + if (mbedtls_sha512 (Message, MsgSize, HashValue, TRUE) != 0) { + return FALSE; + } + + break; + + case SHA512_DIGEST_SIZE: + MdAlg = MBEDTLS_MD_SHA512; + if (mbedtls_sha512 (Message, MsgSize, HashValue, FALSE) != 0) { + return FALSE; + } + + break; + + default: + return FALSE; + } + + if (Signature == NULL) { + // + // If Signature is NULL, return safe SignatureSize + // + *SigSize = MBEDTLS_MPI_MAX_SIZE; + return FALSE; + } + + Ret = mbedtls_rsa_set_padding (RsaContext, MBEDTLS_RSA_PKCS_V21, MdAlg); + if (Ret != 0) { + return FALSE; + } + + Ret = mbedtls_rsa_rsassa_pss_sign ( + RsaContext, + MbedtlsRand, + NULL, + MdAlg, + (UINT32)DigestLen, + HashValue, + Signature + ); + if (Ret != 0) { + return FALSE; + } + + *SigSize = ((mbedtls_rsa_context *)RsaContext)->len; + return TRUE; +} diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptTs.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptTs.c new file mode 100644 index 0000000000..d3fa205f9c --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptTs.c @@ -0,0 +1,381 @@ +/** @file + RFC3161 Timestamp Countersignature Verification Wrapper Implementation which does + not provide real capabilities. + +Copyright (c) 2024, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "InternalCryptLib.h" +#include + +// +// OID ASN.1 Value for SPC_RFC3161_OBJID ("1.3.6.1.4.1.311.3.3.1") +// +GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 mSpcRFC3161OidValue[] = { + 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x03, 0x03, 0x01 +}; + +/** + Convert ASN.1 GeneralizedTime to EFI Time. + + @param[in] Ptr Pointer to the ASN.1 GeneralizedTime to be converted. + @param[out] EfiTime Return the corresponding EFI Time. + + @retval TRUE The time conversion succeeds. + @retval FALSE Invalid parameters. + +**/ +STATIC +BOOLEAN +ConvertAsn1TimeToEfiTime ( + IN UINT8 *Ptr, + OUT EFI_TIME *EfiTime + ) +{ + CONST CHAR8 *Str; + UINTN Index; + + if ((Ptr == NULL) || (EfiTime == NULL)) { + return FALSE; + } + + Str = (CONST CHAR8 *)Ptr; + SetMem (EfiTime, sizeof (EFI_TIME), 0); + + Index = 0; + + /* 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; +} + +/** + 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 + ) +{ + BOOLEAN Status; + UINT8 *Ptr; + UINT8 *End; + INT32 Len; + UINTN ObjLen; + UINT8 *TempPtr; + + // + // Initializations + // + if (SigningTime != NULL) { + SetMem (SigningTime, sizeof (EFI_TIME), 0); + } + + // + // Input Parameters Checking. + // + if ((AuthData == NULL) || (TsaCert == NULL)) { + return FALSE; + } + + if ((DataSize > INT_MAX) || (CertSize > INT_MAX)) { + return FALSE; + } + + Ptr = (UINT8 *)(UINTN)AuthData; + Len = (UINT32)DataSize; + End = Ptr + Len; + + // ContentInfo + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + // ContentType + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OID) != 0) { + return FALSE; + } + + Ptr += ObjLen; + // content + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) { + return FALSE; + } + + End = Ptr + ObjLen; + // signedData + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + // version + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) != 0) { + return FALSE; + } + + Ptr += ObjLen; + // digestAlgo + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET) != 0) { + return FALSE; + } + + Ptr += ObjLen; + + // encapContentInfo + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + Ptr += ObjLen; + + // cert + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) { + return FALSE; + } + + Ptr += ObjLen; + + TempPtr = Ptr; + // OPTIONAL CRLs + if (mbedtls_asn1_get_tag (&TempPtr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) == 0) { + Ptr = TempPtr + ObjLen; + } + + // signerInfo + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET) != 0) { + return FALSE; + } + + // sub parse + // signerInfo + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + End = Ptr + ObjLen; + + // version + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) != 0) { + return FALSE; + } + + Ptr += ObjLen; + + // sid + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + Ptr += ObjLen; + + // digestalgo + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + Ptr += ObjLen; + + // OPTIONAL AuthenticatedAttributes + TempPtr = Ptr; + if (mbedtls_asn1_get_tag (&TempPtr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) == 0) { + Ptr = TempPtr + ObjLen; + } + + // signaturealgo + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + Ptr += ObjLen; + + // signature + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OCTET_STRING) != 0) { + return FALSE; + } + + Ptr += ObjLen; + + // OPTIONAL UnauthenticatedAttributes + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, 0xA1) != 0) { + return FALSE; + } + + // Attribute + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + // type + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OID) != 0) { + return FALSE; + } + + if (CompareMem (Ptr, mSpcRFC3161OidValue, sizeof (mSpcRFC3161OidValue)) != 0) { + return FALSE; + } + + Ptr += ObjLen; + + // values + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET) != 0) { + return FALSE; + } + + // values + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + // signedData OID + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OID) != 0) { + return FALSE; + } + + Ptr += ObjLen; + + // [0] + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) { + return FALSE; + } + + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + // integer + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) != 0) { + return FALSE; + } + + Ptr += ObjLen; + // SET + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET) != 0) { + return FALSE; + } + + Ptr += ObjLen; + + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + // tST OID + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OID) != 0) { + return FALSE; + } + + Ptr += ObjLen; + + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) { + return FALSE; + } + + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OCTET_STRING) != 0) { + return FALSE; + } + + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + // Integer + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) != 0) { + return FALSE; + } + + Ptr += ObjLen; + // policy OID + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OID) != 0) { + return FALSE; + } + + Ptr += ObjLen; + // sequence + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return FALSE; + } + + Ptr += ObjLen; + // Integer + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) != 0) { + return FALSE; + } + + Ptr += ObjLen; + + // GeneralizedTime + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_GENERALIZED_TIME) != 0) { + return FALSE; + } + + // + // Retrieve the signing time from TS_TST_INFO structure. + // + if (SigningTime != NULL) { + SetMem (SigningTime, sizeof (EFI_TIME), 0); + Status = ConvertAsn1TimeToEfiTime (Ptr, SigningTime); + } + + return Status; +} diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptX509.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptX509.c new file mode 100644 index 0000000000..3cf44e9b95 --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptX509.c @@ -0,0 +1,1940 @@ +/** @file + X.509 Certificate Handler Wrapper Implementation over MbedTLS. + +Copyright (c) 2024, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "InternalCryptLib.h" +#include +#include +#include +#include +#include +#include + +/// +/// OID +/// +STATIC CONST UINT8 OID_commonName[] = { + 0x55, 0x04, 0x03 +}; +STATIC CONST UINT8 OID_organizationName[] = { + 0x55, 0x04, 0x0A +}; +STATIC CONST UINT8 OID_extKeyUsage[] = { + 0x55, 0x1D, 0x25 +}; +STATIC CONST UINT8 OID_BasicConstraints[] = { + 0x55, 0x1D, 0x13 +}; + +/* Profile for backward compatibility. Allows RSA 1024, unlike the default + profile. */ +STATIC mbedtls_x509_crt_profile gCompatProfile = +{ + /* Hashes from SHA-256 and above. Note that this selection + * should be aligned with ssl_preset_default_hashes in ssl_tls.c. */ + MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA256) | + MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA384) | + MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA512), + 0xFFFFFFF, /* Any PK alg */ + + /* Curves at or above 128-bit security level. Note that this selection + * should be aligned with ssl_preset_default_curves in ssl_tls.c. */ + MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_SECP256R1) | + MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_SECP384R1) | + MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_SECP521R1) | + MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_BP256R1) | + MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_BP384R1) | + MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_BP512R1) | + 0, + 1024, +}; + +/** + 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 + ) +{ + mbedtls_x509_crt *MbedTlsCert; + INT32 Ret; + + if ((Cert == NULL) || (SingleX509Cert == NULL) || (CertSize == 0)) { + return FALSE; + } + + MbedTlsCert = calloc (sizeof (mbedtls_x509_crt), 1); + if (MbedTlsCert == NULL) { + return FALSE; + } + + mbedtls_x509_crt_init (MbedTlsCert); + + *SingleX509Cert = (UINT8 *)(VOID *)MbedTlsCert; + Ret = mbedtls_x509_crt_parse_der (MbedTlsCert, Cert, CertSize); + if (Ret == 0) { + return TRUE; + } else { + mbedtls_x509_crt_free (MbedTlsCert); + free (MbedTlsCert); + return FALSE; + } +} + +/** + 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[in] Args VA_LIST marker for the variable argument list. + 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 +X509ConstructCertificateStackV ( + IN OUT UINT8 **X509Stack, + IN VA_LIST Args + ) +{ + UINT8 *Cert; + UINTN CertSize; + INT32 Index; + INT32 Ret; + mbedtls_x509_crt *Crt; + + if (X509Stack == NULL) { + return FALSE; + } + + Ret = 0; + Crt = NULL; + if (*X509Stack == NULL) { + Crt = calloc (sizeof (mbedtls_x509_crt), 1); + if (Crt == NULL) { + return FALSE; + } + + mbedtls_x509_crt_init (Crt); + *X509Stack = (UINT8 *)Crt; + } + + 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; + } + + Ret = mbedtls_x509_crt_parse_der ((mbedtls_x509_crt *)*X509Stack, Cert, CertSize); + + if (Ret != 0) { + break; + } + } + + if (Ret == 0) { + return TRUE; + } else { + if (Crt != NULL) { + mbedtls_x509_crt_free (Crt); + free (Crt); + *X509Stack = NULL; + } + + return FALSE; + } +} + +/** + 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, + ... + ) +{ + VA_LIST Args; + BOOLEAN Result; + + VA_START (Args, X509Stack); + Result = X509ConstructCertificateStackV (X509Stack, Args); + VA_END (Args); + return Result; +} + +/** + 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 + ) +{ + if (X509Cert != NULL) { + mbedtls_x509_crt_free (X509Cert); + free (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 + ) +{ + if (X509Stack == NULL) { + return; + } + + mbedtls_x509_crt_free (X509Stack); +} + +/** + Retrieve the tag and length of the tag. + + @param Ptr The position in the ASN.1 data + @param End End of data + @param Length The variable that will receive the length + @param Tag The expected tag + + @retval TRUE Get tag successful + @retval FALSe Failed to get tag or tag not match +**/ +BOOLEAN +EFIAPI +Asn1GetTag ( + IN OUT UINT8 **Ptr, + IN CONST UINT8 *End, + OUT UINTN *Length, + IN UINT32 Tag + ) +{ + if (mbedtls_asn1_get_tag (Ptr, End, Length, (INT32)Tag) == 0) { + return TRUE; + } else { + return FALSE; + } +} + +/** + 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 + ) +{ + mbedtls_x509_crt Crt; + INT32 Ret; + + if (Cert == NULL) { + return FALSE; + } + + mbedtls_x509_crt_init (&Crt); + + Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize); + + if (Ret == 0) { + if (CertSubject != NULL) { + CopyMem (CertSubject, Crt.subject_raw.p, Crt.subject_raw.len); + } + + *SubjectSize = Crt.subject_raw.len; + } + + mbedtls_x509_crt_free (&Crt); + + return Ret == 0; +} + +/** + Retrieve a string from one X.509 certificate base on the Request_NID. + + @param[in] Name mbedtls_x509_name + @param[in] Oid Oid + @param[in] OidSize Size of Oid + @param[in,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 NID Name 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 +InternalX509GetNIDName ( + IN mbedtls_x509_name *Name, + IN CHAR8 *Oid, + IN UINTN OidSize, + IN OUT CHAR8 *CommonName OPTIONAL, + IN OUT UINTN *CommonNameSize + ) +{ + CONST mbedtls_asn1_named_data *data; + + data = mbedtls_asn1_find_named_data (Name, Oid, OidSize); + if (data != NULL) { + if (*CommonNameSize <= data->val.len) { + *CommonNameSize = data->val.len + 1; + return RETURN_BUFFER_TOO_SMALL; + } + + if (CommonName != NULL) { + CopyMem (CommonName, data->val.p, data->val.len); + CommonName[data->val.len] = '\0'; + } + + *CommonNameSize = data->val.len + 1; + return RETURN_SUCCESS; + } else { + return RETURN_NOT_FOUND; + } +} + +/** + Get X509 SubjectNIDName by OID. + + @param[in] Cert certificate + @param[in] CertSize certificate size. + @param[in] Oid Oid + @param[in] OidSize Size of Oid + @param[in,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 NID Name 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 +InternalX509GetSubjectNIDName ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + IN CHAR8 *Oid, + IN UINTN OidSize, + IN OUT CHAR8 *CommonName OPTIONAL, + IN OUT UINTN *CommonNameSize + ) +{ + mbedtls_x509_crt Crt; + INT32 Ret; + mbedtls_x509_name *Name; + RETURN_STATUS ReturnStatus; + + if (Cert == NULL) { + return FALSE; + } + + ReturnStatus = RETURN_INVALID_PARAMETER; + + mbedtls_x509_crt_init (&Crt); + + Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize); + + if (Ret == 0) { + Name = &(Crt.subject); + ReturnStatus = InternalX509GetNIDName (Name, Oid, OidSize, CommonName, CommonNameSize); + } + + mbedtls_x509_crt_free (&Crt); + + return ReturnStatus; +} + +/** + Get X509 IssuerNIDName by OID. + + @param[in] Cert certificate + @param[in] CertSize certificate size. + @param[in] Oid Oid + @param[in] OidSize Size of Oid + @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 NID Name 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 +InternalX509GetIssuerNIDName ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + IN CHAR8 *Oid, + IN UINTN OidSize, + OUT CHAR8 *CommonName OPTIONAL, + IN OUT UINTN *CommonNameSize + ) +{ + mbedtls_x509_crt Crt; + INT32 Ret; + mbedtls_x509_name *Name; + RETURN_STATUS ReturnStatus; + + if (Cert == NULL) { + return FALSE; + } + + ReturnStatus = RETURN_INVALID_PARAMETER; + + mbedtls_x509_crt_init (&Crt); + + Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize); + + if (Ret == 0) { + Name = &(Crt.issuer); + ReturnStatus = InternalX509GetNIDName (Name, Oid, OidSize, CommonName, CommonNameSize); + } + + mbedtls_x509_crt_free (&Crt); + + return ReturnStatus; +} + +/** + 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. 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 InternalX509GetSubjectNIDName (Cert, CertSize, (CHAR8 *)OID_commonName, sizeof (OID_commonName), CommonName, CommonNameSize); +} + +/** + Retrieve the organization name (O) 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] NameBuffer Buffer to contain the retrieved certificate organization + name string. At most NameBufferSize 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] NameBufferSize The size in bytes of the Name buffer on input, + and the size of buffer returned Name on output. + If NameBuffer is NULL then the amount of space needed + in buffer (including the final null) is returned. + + @retval RETURN_SUCCESS The certificate Organization Name retrieved successfully. + @retval RETURN_INVALID_PARAMETER If Cert is NULL. + If NameBufferSize is NULL. + If NameBuffer is not NULL and *CommonNameSize is 0. + If Certificate is invalid. + @retval RETURN_NOT_FOUND If no Organization Name entry exists. + @retval RETURN_BUFFER_TOO_SMALL If the NameBuffer 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 +X509GetOrganizationName ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT CHAR8 *NameBuffer OPTIONAL, + IN OUT UINTN *NameBufferSize + ) +{ + return InternalX509GetSubjectNIDName (Cert, CertSize, (CHAR8 *)OID_organizationName, sizeof (OID_organizationName), NameBuffer, NameBufferSize); +} + +/** + 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 + ) +{ + mbedtls_x509_crt Crt; + mbedtls_rsa_context *Rsa; + INT32 Ret; + + mbedtls_x509_crt_init (&Crt); + + if (mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize) != 0) { + return FALSE; + } + + if (mbedtls_pk_get_type (&Crt.pk) != MBEDTLS_PK_RSA) { + mbedtls_x509_crt_free (&Crt); + return FALSE; + } + + Rsa = RsaNew (); + if (Rsa == NULL) { + mbedtls_x509_crt_free (&Crt); + return FALSE; + } + + Ret = mbedtls_rsa_copy (Rsa, mbedtls_pk_rsa (Crt.pk)); + if (Ret != 0) { + RsaFree (Rsa); + mbedtls_x509_crt_free (&Crt); + return FALSE; + } + + mbedtls_x509_crt_free (&Crt); + + *RsaContext = Rsa; + return TRUE; +} + +/** + Retrieve the EC 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] EcContext Pointer to new-generated EC DSA context which contain the retrieved + EC public key component. Use EcFree() function to free the + resource. + + If Cert is NULL, then return FALSE. + If EcContext is NULL, then return FALSE. + + @retval TRUE EC Public Key was retrieved successfully. + @retval FALSE Fail to retrieve EC public key from X509 certificate. + +**/ +BOOLEAN +EFIAPI +EcGetPublicKeyFromX509 ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT VOID **EcContext + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + 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 + ) +{ + INT32 Ret; + mbedtls_x509_crt Ca; + mbedtls_x509_crt End; + UINT32 VFlag; + mbedtls_x509_crt_profile Profile; + + if ((Cert == NULL) || (CACert == NULL)) { + return FALSE; + } + + VFlag = 0; + CopyMem (&Profile, &gCompatProfile, sizeof (mbedtls_x509_crt_profile)); + + mbedtls_x509_crt_init (&Ca); + mbedtls_x509_crt_init (&End); + + Ret = mbedtls_x509_crt_parse_der (&Ca, CACert, CACertSize); + + if (Ret == 0) { + Ret = mbedtls_x509_crt_parse_der (&End, Cert, CertSize); + } + + if (Ret == 0) { + Ret = mbedtls_x509_crt_verify_with_profile (&End, &Ca, NULL, &Profile, NULL, &VFlag, NULL, NULL); + } + + mbedtls_x509_crt_free (&Ca); + mbedtls_x509_crt_free (&End); + + return Ret == 0; +} + +/** + Verify one X509 certificate was issued by the trusted CA. + + @param[in] RootCert Trusted Root Certificate buffer + @param[in] RootCertLength Trusted Root Certificate buffer length + @param[in] CertChain One or more ASN.1 DER-encoded X.509 certificates + where the first certificate is signed by the Root + Certificate or is the Root Cerificate itself. and + subsequent cerificate is signed by the preceding + cerificate. + @param[in] CertChainLength Total length of the certificate chain, in bytes. + + @retval TRUE All cerificates was issued by the first certificate in X509Certchain. + @retval FALSE Invalid certificate or the certificate was not issued by the given + trusted CA. +**/ +BOOLEAN +EFIAPI +X509VerifyCertChain ( + IN CONST UINT8 *RootCert, + IN UINTN RootCertLength, + IN CONST UINT8 *CertChain, + IN UINTN CertChainLength + ) +{ + UINTN Asn1Len; + UINTN PrecedingCertLen; + CONST UINT8 *PrecedingCert; + UINTN CurrentCertLen; + CONST UINT8 *CurrentCert; + CONST UINT8 *TmpPtr; + UINT32 Ret; + BOOLEAN VerifyFlag; + + VerifyFlag = FALSE; + PrecedingCert = RootCert; + PrecedingCertLen = RootCertLength; + + CurrentCert = CertChain; + + // + // Get Current certificate from Certificates buffer and Verify with preciding cert + // + do { + TmpPtr = CurrentCert; + Ret = mbedtls_asn1_get_tag ((UINT8 **)&TmpPtr, CertChain + CertChainLength, &Asn1Len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (Ret != 0) { + break; + } + + CurrentCertLen = Asn1Len + (TmpPtr - CurrentCert); + + if (!X509VerifyCert (CurrentCert, CurrentCertLen, PrecedingCert, PrecedingCertLen)) { + VerifyFlag = FALSE; + break; + } else { + VerifyFlag = TRUE; + } + + // + // Save preceding certificate + // + PrecedingCert = CurrentCert; + PrecedingCertLen = CurrentCertLen; + + // + // Move current certificate to next; + // + CurrentCert = CurrentCert + CurrentCertLen; + } while (1); + + return VerifyFlag; +} + +/** + Get one X509 certificate from CertChain. + + @param[in] CertChain One or more ASN.1 DER-encoded X.509 certificates + where the first certificate is signed by the Root + Certificate or is the Root Cerificate itself. and + subsequent cerificate is signed by the preceding + cerificate. + @param[in] CertChainLength Total length of the certificate chain, in bytes. + + @param[in] CertIndex Index of certificate. + + @param[out] Cert The certificate at the index of CertChain. + @param[out] CertLength The length certificate at the index of CertChain. + + @retval TRUE Success. + @retval FALSE Failed to get certificate from certificate chain. +**/ +BOOLEAN +EFIAPI +X509GetCertFromCertChain ( + IN CONST UINT8 *CertChain, + IN UINTN CertChainLength, + IN CONST INT32 CertIndex, + OUT CONST UINT8 **Cert, + OUT UINTN *CertLength + ) +{ + UINTN Asn1Len; + INT32 CurrentIndex; + UINTN CurrentCertLen; + CONST UINT8 *CurrentCert; + CONST UINT8 *TmpPtr; + INT32 Ret; + + // + // Check input parameters. + // + if ((CertChain == NULL) || (Cert == NULL) || + (CertIndex < -1) || (CertLength == NULL)) + { + return FALSE; + } + + CurrentCert = CertChain; + CurrentIndex = -1; + + // + // Traverse the certificate chain + // + while (TRUE) { + // + // Get asn1 tag len + // + TmpPtr = CurrentCert; + Ret = mbedtls_asn1_get_tag ((UINT8 **)&TmpPtr, CertChain + CertChainLength, &Asn1Len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (Ret != 0) { + break; + } + + CurrentCertLen = Asn1Len + (TmpPtr - CurrentCert); + CurrentIndex++; + + if (CurrentIndex == CertIndex) { + *Cert = CurrentCert; + *CertLength = CurrentCertLen; + return TRUE; + } + + // + // Move to next + // + CurrentCert = CurrentCert + CurrentCertLen; + } + + // + // If CertIndex is -1, Return the last certificate + // + if ((CertIndex == -1) && (CurrentIndex >= 0)) { + *Cert = CurrentCert - CurrentCertLen; + *CertLength = CurrentCertLen; + return TRUE; + } + + return FALSE; +} + +/** + 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 + ) +{ + UINTN Length; + UINTN Ret; + UINT8 *Ptr; + CONST UINT8 *Temp; + CONST UINT8 *End; + + // + // 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. + // + + Length = 0; + + Ptr = (UINT8 *)Cert; + End = Cert + CertSize; + + Ret = mbedtls_asn1_get_tag (&Ptr, End, &Length, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (Ret != 0) { + return FALSE; + } + + Temp = Ptr; + End = Ptr + Length; + Ret = mbedtls_asn1_get_tag (&Ptr, End, &Length, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (Ret != 0) { + return FALSE; + } + + *TBSCert = (UINT8 *)Temp; + *TBSCertSize = Length + (Ptr - Temp); + + return TRUE; +} + +/** + Retrieve the version from one X.509 certificate. + + If Cert is NULL, then return FALSE. + If CertSize is 0, 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] Version Pointer to the retrieved version integer. + + @retval TRUE The certificate version retrieved successfully. + @retval FALSE If Cert is NULL or CertSize is Zero. + @retval FALSE The operation is not supported. + +**/ +BOOLEAN +EFIAPI +X509GetVersion ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT UINTN *Version + ) +{ + mbedtls_x509_crt Crt; + INT32 Ret; + BOOLEAN ReturnStatus; + + if (Cert == NULL) { + return FALSE; + } + + ReturnStatus = FALSE; + + mbedtls_x509_crt_init (&Crt); + + Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize); + + if (Ret == 0) { + *Version = Crt.version - 1; + ReturnStatus = TRUE; + } + + mbedtls_x509_crt_free (&Crt); + + return ReturnStatus; +} + +/** + Retrieve the serialNumber from one X.509 certificate. + + If Cert is NULL, then return FALSE. + If CertSize is 0, 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] SerialNumber Pointer to the retrieved certificate SerialNumber bytes. + @param[in, out] SerialNumberSize The size in bytes of the SerialNumber buffer on input, + and the size of buffer returned SerialNumber on output. + + @retval TRUE The certificate serialNumber retrieved successfully. + @retval FALSE If Cert is NULL or CertSize is Zero. + If SerialNumberSize is NULL. + If Certificate is invalid. + @retval FALSE If no SerialNumber exists. + @retval FALSE If the SerialNumber is NULL. The required buffer size + (including the final null) is returned in the + SerialNumberSize parameter. + @retval FALSE The operation is not supported. +**/ +BOOLEAN +EFIAPI +X509GetSerialNumber ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT UINT8 *SerialNumber OPTIONAL, + IN OUT UINTN *SerialNumberSize + ) +{ + mbedtls_x509_crt Crt; + INT32 Ret; + BOOLEAN ReturnStatus; + + if (Cert == NULL) { + return FALSE; + } + + ReturnStatus = FALSE; + + mbedtls_x509_crt_init (&Crt); + + Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize); + + if (Ret == 0) { + if (*SerialNumberSize <= Crt.serial.len) { + *SerialNumberSize = Crt.serial.len + 1; + ReturnStatus = FALSE; + goto Cleanup; + } + + if (SerialNumber != NULL) { + CopyMem (SerialNumber, Crt.serial.p, Crt.serial.len); + SerialNumber[Crt.serial.len] = '\0'; + } + + *SerialNumberSize = Crt.serial.len + 1; + ReturnStatus = TRUE; + } + +Cleanup: + mbedtls_x509_crt_free (&Crt); + + return ReturnStatus; +} + +/** + Retrieve the issuer bytes from one X.509 certificate. + + If Cert is NULL, then return FALSE. + If CertIssuerSize 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] CertIssuer Pointer to the retrieved certificate subject bytes. + @param[in, out] CertIssuerSize The size in bytes of the CertIssuer buffer on input, + and the size of buffer returned CertSubject on output. + + @retval TRUE The certificate issuer retrieved successfully. + @retval FALSE Invalid certificate, or the CertIssuerSize is too small for the result. + The CertIssuerSize will be updated with the required size. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +X509GetIssuerName ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT UINT8 *CertIssuer, + IN OUT UINTN *CertIssuerSize + ) +{ + mbedtls_x509_crt Crt; + INT32 Ret; + BOOLEAN Status; + + if (Cert == NULL) { + return FALSE; + } + + Status = FALSE; + + mbedtls_x509_crt_init (&Crt); + + Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize); + + if (Ret == 0) { + if (*CertIssuerSize < Crt.serial.len) { + *CertIssuerSize = Crt.serial.len; + Status = FALSE; + goto Cleanup; + } + + if (CertIssuer != NULL) { + CopyMem (CertIssuer, Crt.serial.p, Crt.serial.len); + } + + *CertIssuerSize = Crt.serial.len; + Status = TRUE; + } + +Cleanup: + mbedtls_x509_crt_free (&Crt); + + return Status; +} + +/** + Retrieve the issuer 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 issuer common + name string. 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 Issuer 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 +X509GetIssuerCommonName ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT CHAR8 *CommonName OPTIONAL, + IN OUT UINTN *CommonNameSize + ) +{ + return InternalX509GetIssuerNIDName (Cert, CertSize, (CHAR8 *)OID_commonName, sizeof (OID_commonName), CommonName, CommonNameSize); +} + +/** + Retrieve the issuer organization name (O) 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] NameBuffer Buffer to contain the retrieved certificate issuer organization + name string. At most NameBufferSize 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] NameBufferSize The size in bytes of the Name buffer on input, + and the size of buffer returned Name on output. + If NameBuffer is NULL then the amount of space needed + in buffer (including the final null) is returned. + + @retval RETURN_SUCCESS The certificate issuer Organization Name retrieved successfully. + @retval RETURN_INVALID_PARAMETER If Cert is NULL. + If NameBufferSize is NULL. + If NameBuffer is not NULL and *CommonNameSize is 0. + If Certificate is invalid. + @retval RETURN_NOT_FOUND If no Organization Name entry exists. + @retval RETURN_BUFFER_TOO_SMALL If the NameBuffer 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 +X509GetIssuerOrganizationName ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT CHAR8 *NameBuffer OPTIONAL, + IN OUT UINTN *NameBufferSize + ) +{ + return InternalX509GetIssuerNIDName (Cert, CertSize, (CHAR8 *)OID_organizationName, sizeof (OID_organizationName), NameBuffer, NameBufferSize); +} + +/** + Retrieve the Signature Algorithm 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] Oid Signature Algorithm Object identifier buffer. + @param[in,out] OidSize Signature Algorithm Object identifier buffer size + + @retval TRUE The certificate Extension data retrieved successfully. + @retval FALSE If Cert is NULL. + If OidSize is NULL. + If Oid is not NULL and *OidSize is 0. + If Certificate is invalid. + @retval FALSE If no SignatureType. + @retval FALSE If the Oid is NULL. The required buffer size + is returned in the OidSize. + @retval FALSE The operation is not supported. +**/ +BOOLEAN +EFIAPI +X509GetSignatureAlgorithm ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT UINT8 *Oid OPTIONAL, + IN OUT UINTN *OidSize + ) +{ + mbedtls_x509_crt Crt; + INT32 Ret; + BOOLEAN ReturnStatus; + + if ((Cert == NULL) || (CertSize == 0) || (OidSize == NULL)) { + return FALSE; + } + + ReturnStatus = FALSE; + + mbedtls_x509_crt_init (&Crt); + + Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize); + + if (Ret == 0) { + if (*OidSize < Crt.sig_oid.len) { + *OidSize = Crt.serial.len; + ReturnStatus = FALSE; + goto Cleanup; + } + + if (Oid != NULL) { + CopyMem (Oid, Crt.sig_oid.p, Crt.sig_oid.len); + } + + *OidSize = Crt.sig_oid.len; + ReturnStatus = TRUE; + } + +Cleanup: + mbedtls_x509_crt_free (&Crt); + + return ReturnStatus; +} + +/** + Find first Extension data match with given OID + + @param[in] Start Pointer to the DER-encoded Extensions Data + @param[in] End Extensions Data size in bytes + @param[in ] Oid OID for match + @param[in ] OidSize OID size in bytes + @param[out] FindExtensionData output matched extension data. + @param[out] FindExtensionDataLen matched extension data size. + + **/ +STATIC +RETURN_STATUS +InternalX509FindExtensionData ( + UINT8 *Start, + UINT8 *End, + CONST UINT8 *Oid, + UINTN OidSize, + UINT8 **FindExtensionData, + UINTN *FindExtensionDataLen + ) +{ + UINT8 *Ptr; + UINT8 *ExtensionPtr; + size_t ObjLen; + INT32 Ret; + RETURN_STATUS ReturnStatus; + size_t FindExtensionLen; + size_t HeaderLen; + + ReturnStatus = RETURN_INVALID_PARAMETER; + Ptr = Start; + + Ret = 0; + + while (TRUE) { + /* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING } + */ + ExtensionPtr = Ptr; + Ret = mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (Ret == 0) { + HeaderLen = (size_t)(Ptr - ExtensionPtr); + FindExtensionLen = ObjLen; + // Get Object Identifier + Ret = mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OID); + } else { + break; + } + + if ((Ret == 0) && (CompareMem (Ptr, Oid, OidSize) == 0)) { + Ptr += ObjLen; + + Ret = mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_BOOLEAN); + if (Ret == 0) { + Ptr += ObjLen; + } + + Ret = mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OCTET_STRING); + } else { + Ret = 1; + } + + if (Ret == 0) { + *FindExtensionData = Ptr; + *FindExtensionDataLen = ObjLen; + ReturnStatus = RETURN_SUCCESS; + break; + } + + // move to next + Ptr = ExtensionPtr + HeaderLen + FindExtensionLen; + Ret = 0; + } + + return ReturnStatus; +} + +/** + Retrieve Extension data 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[in] Oid Object identifier buffer + @param[in] OidSize Object identifier buffer size + @param[out] ExtensionData Extension bytes. + @param[in, out] ExtensionDataSize Extension bytes size. + + @retval TRUE The certificate Extension data retrieved successfully. + @retval FALSE If Cert is NULL. + If ExtensionDataSize is NULL. + If ExtensionData is not NULL and *ExtensionDataSize is 0. + If Certificate is invalid. + @retval FALSE If no Extension entry match Oid. + @retval FALSE If the ExtensionData is NULL. The required buffer size + is returned in the ExtensionDataSize parameter. + @retval FALSE The operation is not supported. +**/ +BOOLEAN +EFIAPI +X509GetExtensionData ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + IN CONST UINT8 *Oid, + IN UINTN OidSize, + OUT UINT8 *ExtensionData, + IN OUT UINTN *ExtensionDataSize + ) +{ + mbedtls_x509_crt Crt; + INT32 Ret; + RETURN_STATUS ReturnStatus; + BOOLEAN Status; + UINT8 *Ptr; + UINT8 *End; + size_t ObjLen; + + if ((Cert == NULL) || + (CertSize == 0) || + (Oid == NULL) || + (OidSize == 0) || + (ExtensionDataSize == NULL)) + { + return FALSE; + } + + ReturnStatus = RETURN_INVALID_PARAMETER; + Status = FALSE; + + mbedtls_x509_crt_init (&Crt); + + Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize); + + if (Ret == 0) { + Ptr = Crt.v3_ext.p; + End = Crt.v3_ext.p + Crt.v3_ext.len; + Ret = mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + } + + if (Ret == 0) { + ReturnStatus = InternalX509FindExtensionData (Ptr, End, Oid, OidSize, &Ptr, &ObjLen); + } + + if (ReturnStatus == RETURN_SUCCESS) { + if (*ExtensionDataSize < ObjLen) { + *ExtensionDataSize = ObjLen; + Status = FALSE; + goto Cleanup; + } + + if (Oid != NULL) { + CopyMem (ExtensionData, Ptr, ObjLen); + } + + *ExtensionDataSize = ObjLen; + Status = TRUE; + } + +Cleanup: + mbedtls_x509_crt_free (&Crt); + + return Status; +} + +/** + Retrieve the Validity from one X.509 certificate + + If Cert is NULL, then return FALSE. + If CertIssuerSize 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[in] From notBefore Pointer to DateTime object. + @param[in,out] FromSize notBefore DateTime object size. + @param[in] To notAfter Pointer to DateTime object. + @param[in,out] ToSize notAfter DateTime object size. + + Note: X509CompareDateTime to compare DateTime oject + x509SetDateTime to get a DateTime object from a DateTimeStr + + @retval TRUE The certificate Validity retrieved successfully. + @retval FALSE Invalid certificate, or Validity retrieve failed. + @retval FALSE This interface is not supported. +**/ +BOOLEAN +EFIAPI +X509GetValidity ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + IN UINT8 *From, + IN OUT UINTN *FromSize, + IN UINT8 *To, + IN OUT UINTN *ToSize + ) +{ + mbedtls_x509_crt Crt; + INT32 Ret; + BOOLEAN Status; + UINTN TSize; + UINTN FSize; + + if (Cert == NULL) { + return FALSE; + } + + Status = FALSE; + + mbedtls_x509_crt_init (&Crt); + + Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize); + + if (Ret == 0) { + FSize = sizeof (mbedtls_x509_time); + if (*FromSize < FSize) { + *FromSize = FSize; + goto _Exit; + } + + *FromSize = FSize; + if (From != NULL) { + CopyMem (From, &(Crt.valid_from), FSize); + } + + TSize = sizeof (mbedtls_x509_time); + if (*ToSize < TSize) { + *ToSize = TSize; + goto _Exit; + } + + *ToSize = TSize; + if (To != NULL) { + CopyMem (To, &(Crt.valid_to), sizeof (mbedtls_x509_time)); + } + + Status = TRUE; + } + +_Exit: + mbedtls_x509_crt_free (&Crt); + + return Status; +} + +/** + Retrieve the Key Usage 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] Usage Key Usage (CRYPTO_X509_KU_*) + + @retval TRUE The certificate Key Usage retrieved successfully. + @retval FALSE Invalid certificate, or Usage is NULL + @retval FALSE This interface is not supported. +**/ +BOOLEAN +EFIAPI +X509GetKeyUsage ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT UINTN *Usage + ) +{ + mbedtls_x509_crt Crt; + INT32 Ret; + BOOLEAN Status; + + if (Cert == NULL) { + return FALSE; + } + + Status = FALSE; + + mbedtls_x509_crt_init (&Crt); + + Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize); + + if (Ret == 0) { + *Usage = Crt.key_usage; + Status = TRUE; + } + + mbedtls_x509_crt_free (&Crt); + + return Status; +} + +/** + Retrieve the Extended Key Usage 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] Usage Key Usage bytes. + @param[in, out] UsageSize Key Usage buffer sizs in bytes. + + @retval TRUE The Usage bytes retrieve successfully. + @retval FALSE If Cert is NULL. + If CertSize is NULL. + If Usage is not NULL and *UsageSize is 0. + If Cert is invalid. + @retval FALSE If the Usage is NULL. The required buffer size + is returned in the UsageSize parameter. + @retval FALSE The operation is not supported. +**/ +BOOLEAN +EFIAPI +X509GetExtendedKeyUsage ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT UINT8 *Usage, + IN OUT UINTN *UsageSize + ) +{ + BOOLEAN ReturnStatus; + + if ((Cert == NULL) || (CertSize == 0) || (UsageSize == NULL)) { + return FALSE; + } + + ReturnStatus = X509GetExtensionData ((UINT8 *)Cert, CertSize, (UINT8 *)OID_extKeyUsage, sizeof (OID_extKeyUsage), Usage, UsageSize); + + return ReturnStatus; +} + +/** + Compare DateTime1 object and DateTime2 object time. + + @param[in] Before Pointer to a DateTime Ojbect + @param[in] After Pointer to a DateTime Object + + @retval 0 If DateTime1 <= DateTime2 + @retval 1 If DateTime1 > DateTime2 +**/ +STATIC +INTN +InternalX509CheckTime ( + CONST mbedtls_x509_time *Before, + CONST mbedtls_x509_time *After + ) +{ + if (Before->year > After->year) { + return (1); + } + + if ((Before->year == After->year) && + (Before->mon > After->mon)) + { + return (1); + } + + if ((Before->year == After->year) && + (Before->mon == After->mon) && + (Before->day > After->day)) + { + return (1); + } + + if ((Before->year == After->year) && + (Before->mon == After->mon) && + (Before->day == After->day) && + (Before->hour > After->hour)) + { + return (1); + } + + if ((Before->year == After->year) && + (Before->mon == After->mon) && + (Before->day == After->day) && + (Before->hour == After->hour) && + (Before->min > After->min)) + { + return (1); + } + + if ((Before->year == After->year) && + (Before->mon == After->mon) && + (Before->day == After->day) && + (Before->hour == After->hour) && + (Before->min == After->min) && + (Before->sec > After->sec)) + { + return (1); + } + + return (0); +} + +/** + change string to int. + + @param[in] PStart Pointer to a string Start + @param[in] PEnd Pointer to a string End + + @return number +**/ +STATIC +INT32 +InternalAtoI ( + CHAR8 *PStart, + CHAR8 *PEnd + ) +{ + CHAR8 *Ptr; + INT32 Knum; + + Knum = 0; + Ptr = PStart; + + while (Ptr < PEnd) { + /// + /// k = k * 2^3 + k * 2^1 = k * 8 + k * 2 = k * 10 + /// + Knum = (Knum << 3) + (Knum << 1) + (*Ptr) - '0'; + Ptr++; + } + + return Knum; +} + +/** + Format a DateTime object into DataTime Buffer + + If DateTimeStr is NULL, then return FALSE. + If DateTimeSize is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] DateTimeStr DateTime string like YYYYMMDDhhmmssZ + Ref: https://www.w3.org/TR/NOTE-datetime + Z stand for UTC time + @param[in,out] DateTime Pointer to a DateTime object. + @param[in,out] DateTimeSize DateTime object buffer size. + + @retval RETURN_SUCCESS The DateTime object create successfully. + @retval RETURN_INVALID_PARAMETER If DateTimeStr is NULL. + If DateTimeSize is NULL. + If DateTime is not NULL and *DateTimeSize is 0. + If Year Month Day Hour Minute Second combination is invalid datetime. + @retval RETURN_BUFFER_TOO_SMALL If the DateTime is NULL. The required buffer size + (including the final null) is returned in the + DateTimeSize parameter. + @retval RETURN_UNSUPPORTED The operation is not supported. +**/ +RETURN_STATUS +EFIAPI +X509SetDateTime ( + CHAR8 *DateTimeStr, + IN OUT VOID *DateTime, + IN OUT UINTN *DateTimeSize + ) +{ + mbedtls_x509_time Dt; + + INT32 Year; + INT32 Month; + INT32 Day; + INT32 Hour; + INT32 Minute; + INT32 Second; + RETURN_STATUS ReturnStatus; + CHAR8 *Ptr; + + Ptr = DateTimeStr; + + Year = InternalAtoI (Ptr, Ptr + 4); + Ptr += 4; + Month = InternalAtoI (Ptr, Ptr + 2); + Ptr += 2; + Day = InternalAtoI (Ptr, Ptr + 2); + Ptr += 2; + Hour = InternalAtoI (Ptr, Ptr + 2); + Ptr += 2; + Minute = InternalAtoI (Ptr, Ptr + 2); + Ptr += 2; + Second = InternalAtoI (Ptr, Ptr + 2); + Ptr += 2; + Dt.year = (int)Year; + Dt.mon = (int)Month; + Dt.day = (int)Day; + Dt.hour = (int)Hour; + Dt.min = (int)Minute; + Dt.sec = (int)Second; + + if (*DateTimeSize < sizeof (mbedtls_x509_time)) { + *DateTimeSize = sizeof (mbedtls_x509_time); + ReturnStatus = RETURN_BUFFER_TOO_SMALL; + goto Cleanup; + } + + if (DateTime != NULL) { + CopyMem (DateTime, &Dt, sizeof (mbedtls_x509_time)); + } + + *DateTimeSize = sizeof (mbedtls_x509_time); + ReturnStatus = RETURN_SUCCESS; +Cleanup: + return ReturnStatus; +} + +/** + Compare DateTime1 object and DateTime2 object. + + If DateTime1 is NULL, then return -2. + If DateTime2 is NULL, then return -2. + If DateTime1 == DateTime2, then return 0 + If DateTime1 > DateTime2, then return 1 + If DateTime1 < DateTime2, then return -1 + + @param[in] DateTime1 Pointer to a DateTime Ojbect + @param[in] DateTime2 Pointer to a DateTime Object + + @retval 0 If DateTime1 == DateTime2 + @retval 1 If DateTime1 > DateTime2 + @retval -1 If DateTime1 < DateTime2 +**/ +INT32 +EFIAPI +X509CompareDateTime ( + IN CONST VOID *DateTime1, + IN CONST VOID *DateTime2 + ) +{ + if ((DateTime1 == NULL) || (DateTime2 == NULL)) { + return -2; + } + + if (CompareMem (DateTime2, DateTime1, sizeof (mbedtls_x509_time)) == 0) { + return 0; + } + + if (InternalX509CheckTime ((mbedtls_x509_time *)DateTime1, (mbedtls_x509_time *)DateTime2) == 0) { + return -1; + } else { + return 1; + } +} + +/** + Retrieve the basic constraints 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] BasicConstraints basic constraints bytes. + @param[in, out] BasicConstraintsSize basic constraints buffer sizs in bytes. + + @retval TRUE The basic constraints retrieve successfully. + @retval FALSE If cert is NULL. + If cert_size is NULL. + If basic_constraints is not NULL and *basic_constraints_size is 0. + If cert is invalid. + @retval FALSE The required buffer size is small. + The return buffer size is basic_constraints_size parameter. + @retval FALSE If no Extension entry match oid. + @retval FALSE The operation is not supported. + **/ +BOOLEAN +EFIAPI +X509GetExtendedBasicConstraints ( + CONST UINT8 *Cert, + UINTN CertSize, + UINT8 *BasicConstraints, + UINTN *BasicConstraintsSize + ) +{ + BOOLEAN Status; + + if ((Cert == NULL) || (CertSize == 0) || (BasicConstraintsSize == NULL)) { + return FALSE; + } + + Status = X509GetExtensionData ( + (UINT8 *)Cert, + CertSize, + OID_BasicConstraints, + sizeof (OID_BasicConstraints), + BasicConstraints, + BasicConstraintsSize + ); + + return Status; +} + +/** + Format a DateTimeStr to DataTime object in DataTime Buffer + + If DateTimeStr is NULL, then return FALSE. + If DateTimeSize is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] DateTimeStr DateTime string like YYYYMMDDhhmmssZ + Ref: https://www.w3.org/TR/NOTE-datetime + Z stand for UTC time + @param[out] DateTime Pointer to a DateTime object. + @param[in,out] DateTimeSize DateTime object buffer size. + + @retval TRUE The DateTime object create successfully. + @retval FALSE If DateTimeStr is NULL. + If DateTimeSize is NULL. + If DateTime is not NULL and *DateTimeSize is 0. + If Year Month Day Hour Minute Second combination is invalid datetime. + @retval FALSE If the DateTime is NULL. The required buffer size + (including the final null) is returned in the + DateTimeSize parameter. + @retval FALSE The operation is not supported. +**/ +BOOLEAN +EFIAPI +X509FormatDateTime ( + IN CONST CHAR8 *DateTimeStr, + OUT VOID *DateTime, + IN OUT UINTN *DateTimeSize + ) +{ + mbedtls_x509_time *Tm; + + if (*DateTimeSize < sizeof (mbedtls_x509_time)) { + return FALSE; + } + + if (DateTime == NULL) { + return FALSE; + } + + Tm = (mbedtls_x509_time *)DateTime; + + Tm->year = (DateTimeStr[0] + '0') * 1000 + (DateTimeStr[1] + '0') * 100 + + (DateTimeStr[2] + '0') * 10 + (DateTimeStr[3] + '0') * 1; + + Tm->mon = (DateTimeStr[4] + '0') * 10 + (DateTimeStr[5] + '0') * 1; + + Tm->day = (DateTimeStr[6] + '0') * 10 + (DateTimeStr[7] + '0') * 1; + + Tm->hour = (DateTimeStr[8] + '0') * 10 + (DateTimeStr[9] + '0') * 1; + + Tm->min = (DateTimeStr[10] + '0') * 10 + (DateTimeStr[11] + '0') * 1; + + Tm->sec = (DateTimeStr[12] + '0') * 10 + (DateTimeStr[13] + '0') * 1; + + return TRUE; +} diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Rand/CryptRand.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Rand/CryptRand.c new file mode 100644 index 0000000000..e01aabc0de --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Rand/CryptRand.c @@ -0,0 +1,114 @@ +/** @file + Pseudorandom Number Generator Wrapper Implementation over MbedTLS. + +Copyright (c) 2024, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "InternalCryptLib.h" +#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 + ) +{ + return TRUE; +} + +/** + 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 + ) +{ + BOOLEAN Ret; + volatile UINT64 TempRand; + + // + // Check input parameters. + // + if ((Output == NULL) || (Size > INT_MAX)) { + return FALSE; + } + + Ret = FALSE; + + while (Size > 0) { + // Use RngLib to get random number + Ret = GetRandomNumber64 ((UINT64 *)&TempRand); + + if (!Ret) { + TempRand = 0; + return Ret; + } + + if (Size >= sizeof (TempRand)) { + *((UINT64 *)Output) = TempRand; + Output += sizeof (UINT64); + Size -= sizeof (TempRand); + } else { + CopyMem (Output, (VOID *)&TempRand, Size); + Size = 0; + } + } + + TempRand = 0; + return Ret; +} + +/** + The MbedTLS function f_rng, which MbedtlsRand implements. + + @param[in] RngState Not used, just for compatibility with mbedlts. + @param[out] Output Pointer to buffer to receive random value. + @param[in] Len Size of random bytes to generate. + + @retval 0 Pseudorandom byte stream generated successfully. + @retval Non-0 Pseudorandom number generator fails to generate due to lack of entropy. +**/ +INT32 +MbedtlsRand ( + VOID *RngState, + UINT8 *Output, + UINTN Len + ) +{ + BOOLEAN Result; + + Result = RandomBytes (Output, Len); + + return Result ? 0 : -1; +} diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Rand/CryptRandTsc.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Rand/CryptRandTsc.c new file mode 100644 index 0000000000..e01aabc0de --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Rand/CryptRandTsc.c @@ -0,0 +1,114 @@ +/** @file + Pseudorandom Number Generator Wrapper Implementation over MbedTLS. + +Copyright (c) 2024, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "InternalCryptLib.h" +#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 + ) +{ + return TRUE; +} + +/** + 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 + ) +{ + BOOLEAN Ret; + volatile UINT64 TempRand; + + // + // Check input parameters. + // + if ((Output == NULL) || (Size > INT_MAX)) { + return FALSE; + } + + Ret = FALSE; + + while (Size > 0) { + // Use RngLib to get random number + Ret = GetRandomNumber64 ((UINT64 *)&TempRand); + + if (!Ret) { + TempRand = 0; + return Ret; + } + + if (Size >= sizeof (TempRand)) { + *((UINT64 *)Output) = TempRand; + Output += sizeof (UINT64); + Size -= sizeof (TempRand); + } else { + CopyMem (Output, (VOID *)&TempRand, Size); + Size = 0; + } + } + + TempRand = 0; + return Ret; +} + +/** + The MbedTLS function f_rng, which MbedtlsRand implements. + + @param[in] RngState Not used, just for compatibility with mbedlts. + @param[out] Output Pointer to buffer to receive random value. + @param[in] Len Size of random bytes to generate. + + @retval 0 Pseudorandom byte stream generated successfully. + @retval Non-0 Pseudorandom number generator fails to generate due to lack of entropy. +**/ +INT32 +MbedtlsRand ( + VOID *RngState, + UINT8 *Output, + UINTN Len + ) +{ + BOOLEAN Result; + + Result = RandomBytes (Output, Len); + + return Result ? 0 : -1; +} diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/RuntimeCryptLib.inf b/CryptoPkg/Library/BaseCryptLibMbedTls/RuntimeCryptLib.inf index 9f17ef00bf..0179640e03 100644 --- a/CryptoPkg/Library/BaseCryptLibMbedTls/RuntimeCryptLib.inf +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/RuntimeCryptLib.inf @@ -25,6 +25,7 @@ VERSION_STRING = 1.0 LIBRARY_CLASS = BaseCryptLib|DXE_RUNTIME_DRIVER CONSTRUCTOR = RuntimeCryptLibConstructor + DEFINE BASE_CRYPT_PATH = ../BaseCryptLib # # The following information is for reference only and not required by the build tools. @@ -37,30 +38,32 @@ Hash/CryptMd5.c Hash/CryptSha1.c Hash/CryptSha256.c - Hash/CryptSm3Null.c Hash/CryptSha512.c Hash/CryptParallelHashNull.c + $(BASE_CRYPT_PATH)/Hash/CryptSm3.c Hmac/CryptHmac.c Kdf/CryptHkdf.c Cipher/CryptAes.c Cipher/CryptAeadAesGcmNull.c Pk/CryptRsaBasic.c Pk/CryptRsaExtNull.c - Pk/CryptRsaPssNull.c - Pk/CryptRsaPssSignNull.c - Bn/CryptBnNull.c - Pem/CryptPemNull.c - Pk/CryptDhNull.c - Pk/CryptEcNull.c Pk/CryptPkcs1OaepNull.c Pk/CryptPkcs5Pbkdf2Null.c Pk/CryptPkcs7SignNull.c - Pk/CryptPkcs7VerifyNull.c - Pk/CryptPkcs7VerifyEkuNull.c - Pk/CryptX509Null.c + Pk/CryptPkcs7VerifyCommon.c + Pk/CryptPkcs7VerifyRuntime.c + Pk/CryptPkcs7VerifyEkuRuntime.c + Pk/CryptDhNull.c + Pk/CryptX509.c Pk/CryptAuthenticodeNull.c Pk/CryptTsNull.c - Rand/CryptRandNull.c + Pk/CryptRsaPssNull.c + Pk/CryptRsaPssSignNull.c + Pk/CryptEcNull.c + Pem/CryptPem.c + Bn/CryptBnNull.c + Rand/CryptRand.c + SysCall/CrtWrapper.c SysCall/TimerWrapper.c SysCall/RuntimeMemAllocation.c @@ -77,6 +80,7 @@ MbedTlsLib IntrinsicLib PrintLib + RngLib # # Remove these [BuildOptions] after this library is cleaned up diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/SmmCryptLib.inf b/CryptoPkg/Library/BaseCryptLibMbedTls/SmmCryptLib.inf index 40c56d1b7d..92013bd514 100644 --- a/CryptoPkg/Library/BaseCryptLibMbedTls/SmmCryptLib.inf +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/SmmCryptLib.inf @@ -24,6 +24,7 @@ VERSION_STRING = 1.0 PI_SPECIFICATION_VERSION = 0x0001000A LIBRARY_CLASS = BaseCryptLib|DXE_SMM_DRIVER SMM_CORE MM_STANDALONE + DEFINE BASE_CRYPT_PATH = ../BaseCryptLib # # The following information is for reference only and not required by the build tools. @@ -36,30 +37,36 @@ Hash/CryptMd5.c Hash/CryptSha1.c Hash/CryptSha256.c - Hash/CryptSm3Null.c Hash/CryptSha512.c - Hash/CryptParallelHashNull.c + $(BASE_CRYPT_PATH)/Hash/CryptCShake256.c + $(BASE_CRYPT_PATH)/Hash/CryptDispatchApMm.c + $(BASE_CRYPT_PATH)/Hash/CryptParallelHash.c + $(BASE_CRYPT_PATH)/Hash/CryptSha3.c + $(BASE_CRYPT_PATH)/Hash/CryptSm3.c + $(BASE_CRYPT_PATH)/Hash/CryptXkcp.c Hmac/CryptHmac.c Kdf/CryptHkdf.c Cipher/CryptAes.c Cipher/CryptAeadAesGcmNull.c Pk/CryptRsaBasic.c Pk/CryptRsaExtNull.c - Pk/CryptRsaPss.c - Pk/CryptRsaPssSignNull.c - Bn/CryptBnNull.c - Pem/CryptPemNull.c - Pk/CryptDhNull.c - Pk/CryptEcNull.c - Pk/CryptPkcs1OaepNull.c - Pk/CryptPkcs5Pbkdf2Null.c + Pk/CryptPkcs1Oaep.c + Pk/CryptPkcs5Pbkdf2.c Pk/CryptPkcs7SignNull.c - Pk/CryptPkcs7VerifyNull.c - Pk/CryptPkcs7VerifyEkuNull.c - Pk/CryptX509Null.c + Pk/CryptPkcs7VerifyCommon.c + Pk/CryptPkcs7VerifyBase.c + Pk/CryptPkcs7VerifyEku.c + Pk/CryptDhNull.c + Pk/CryptX509.c Pk/CryptAuthenticodeNull.c Pk/CryptTsNull.c - Rand/CryptRandNull.c + Pk/CryptRsaPss.c + Pk/CryptRsaPssSignNull.c + Pk/CryptEcNull.c + Pem/CryptPem.c + Bn/CryptBnNull.c + Rand/CryptRand.c + SysCall/CrtWrapper.c SysCall/ConstantTimeClock.c @@ -75,6 +82,7 @@ IntrinsicLib PrintLib MmServicesTableLib + RngLib SynchronizationLib # diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/SysCall/ConstantTimeClock.c b/CryptoPkg/Library/BaseCryptLibMbedTls/SysCall/ConstantTimeClock.c index 2ec13ef9d0..6f5d62b93d 100644 --- a/CryptoPkg/Library/BaseCryptLibMbedTls/SysCall/ConstantTimeClock.c +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/SysCall/ConstantTimeClock.c @@ -18,27 +18,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include +#include #include -typedef int time_t; - -// -// 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 */ -}; - // // -- Time Management Routines -- // diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/SysCall/TimerWrapper.c b/CryptoPkg/Library/BaseCryptLibMbedTls/SysCall/TimerWrapper.c index b7cd4d3181..7bf6cde0b8 100644 --- a/CryptoPkg/Library/BaseCryptLibMbedTls/SysCall/TimerWrapper.c +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/SysCall/TimerWrapper.c @@ -8,29 +8,11 @@ SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include +#include #include #include #include -typedef int time_t; - -// -// 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 */ -}; - // // -- Time Management Routines -- // @@ -131,7 +113,8 @@ gmtime ( const time_t *timer ) { - struct tm *GmTime; + STATIC struct tm GmTime; + UINT16 DayNo; UINT16 DayRemainder; time_t Year; @@ -143,20 +126,15 @@ gmtime ( return NULL; } - GmTime = AllocateZeroPool (sizeof (struct tm)); - if (GmTime == NULL) { - return NULL; - } - - ZeroMem ((VOID *)GmTime, (UINTN)sizeof (struct tm)); + ZeroMem ((VOID *)&GmTime, (UINTN)sizeof (GmTime)); 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); + 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); @@ -168,8 +146,8 @@ gmtime ( } } - GmTime->tm_year = (int)(YearNo + (1970 - 1900)); - GmTime->tm_yday = (int)DayNo; + GmTime.tm_year = (int)(YearNo + (1970 - 1900)); + GmTime.tm_yday = (int)DayNo; for (MonthNo = 12; MonthNo > 1; MonthNo--) { if (DayNo >= CumulativeDays[IsLeap (Year)][MonthNo]) { @@ -178,14 +156,14 @@ gmtime ( } } - GmTime->tm_mon = (int)MonthNo - 1; - GmTime->tm_mday = (int)DayNo + 1; + GmTime.tm_mon = (int)MonthNo - 1; + GmTime.tm_mday = (int)DayNo + 1; - GmTime->tm_isdst = 0; - GmTime->tm_gmtoff = 0; - GmTime->tm_zone = NULL; + GmTime.tm_isdst = 0; + GmTime.tm_gmtoff = 0; + GmTime.tm_zone = NULL; - return GmTime; + return &GmTime; } /**_time64 function. **/ diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/TestBaseCryptLib.inf b/CryptoPkg/Library/BaseCryptLibMbedTls/TestBaseCryptLib.inf index def990b996..a14e1ab908 100644 --- a/CryptoPkg/Library/BaseCryptLibMbedTls/TestBaseCryptLib.inf +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/TestBaseCryptLib.inf @@ -18,6 +18,7 @@ MODULE_TYPE = DXE_DRIVER VERSION_STRING = 1.0 LIBRARY_CLASS = BaseCryptLib|DXE_DRIVER DXE_CORE UEFI_APPLICATION UEFI_DRIVER + DEFINE BASE_CRYPT_PATH = ../BaseCryptLib # # The following information is for reference only and not required by the build tools. @@ -27,32 +28,34 @@ [Sources] InternalCryptLib.h - Cipher/CryptAeadAesGcmNull.c - Cipher/CryptAes.c - Hash/CryptSha256.c - Hash/CryptSha512.c - Hash/CryptSm3Null.c Hash/CryptMd5.c Hash/CryptSha1.c + Hash/CryptSha256.c + Hash/CryptSha512.c + $(BASE_CRYPT_PATH)/Hash/CryptSm3.c + Hash/CryptParallelHashNull.c Hmac/CryptHmac.c Kdf/CryptHkdf.c + Cipher/CryptAes.c + Cipher/CryptAeadAesGcm.c Pk/CryptRsaBasic.c - Pk/CryptRsaExtNull.c + Pk/CryptRsaExt.c + Pk/CryptPkcs1Oaep.c + Pk/CryptPkcs5Pbkdf2.c + Pk/CryptPkcs7Sign.c + Pk/CryptPkcs7VerifyCommon.c + Pk/CryptPkcs7VerifyBase.c + Pk/CryptPkcs7VerifyEku.c + Pk/CryptDhNull.c + Pk/CryptX509.c + Pk/CryptAuthenticode.c + Pk/CryptTs.c + Pem/CryptPem.c Pk/CryptRsaPss.c - Pk/CryptRsaPssSignNull.c + Pk/CryptRsaPssSign.c Bn/CryptBnNull.c - Pem/CryptPemNull.c - Pk/CryptDhNull.c Pk/CryptEcNull.c - Pk/CryptPkcs1OaepNull.c - Pk/CryptPkcs5Pbkdf2Null.c - Pk/CryptPkcs7SignNull.c - Pk/CryptPkcs7VerifyNull.c - Pk/CryptPkcs7VerifyEkuNull.c - Pk/CryptX509Null.c - Pk/CryptAuthenticodeNull.c - Pk/CryptTsNull.c - Rand/CryptRandNull.c + Rand/CryptRand.c SysCall/CrtWrapper.c [Packages] diff --git a/CryptoPkg/Library/Include/CrtLibSupport.h b/CryptoPkg/Library/Include/CrtLibSupport.h index f36fe08f0c..155417f4a8 100644 --- a/CryptoPkg/Library/Include/CrtLibSupport.h +++ b/CryptoPkg/Library/Include/CrtLibSupport.h @@ -172,6 +172,12 @@ realloc ( size_t ); +void * +calloc ( + size_t, + size_t + ); + void free ( void * diff --git a/CryptoPkg/Library/MbedTlsLib/CrtWrapper.c b/CryptoPkg/Library/MbedTlsCrtLib/CrtWrapper.c similarity index 83% rename from CryptoPkg/Library/MbedTlsLib/CrtWrapper.c rename to CryptoPkg/Library/MbedTlsCrtLib/CrtWrapper.c index 04d2877e7d..f9e1fa8212 100644 --- a/CryptoPkg/Library/MbedTlsLib/CrtWrapper.c +++ b/CryptoPkg/Library/MbedTlsCrtLib/CrtWrapper.c @@ -18,7 +18,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent int my_snprintf ( char *str, - size_t size, + long long size, const char *format, ... ) @@ -76,6 +76,16 @@ mbedtls_calloc ( } } +/* Allocates zero-initialized memory blocks */ +void * +calloc ( + size_t num, + size_t size + ) +{ + return mbedtls_calloc (num, size); +} + /* De-allocates or frees a memory block */ void mbedtls_free ( @@ -94,3 +104,12 @@ mbedtls_free ( FreePool (PoolHdr); } } + +/* De-allocates or frees a memory block */ +void +free ( + void *ptr + ) +{ + mbedtls_free (ptr); +} diff --git a/CryptoPkg/Library/MbedTlsCrtLib/MbedTlsCrtLib.inf b/CryptoPkg/Library/MbedTlsCrtLib/MbedTlsCrtLib.inf new file mode 100644 index 0000000000..0fdabfd2b9 --- /dev/null +++ b/CryptoPkg/Library/MbedTlsCrtLib/MbedTlsCrtLib.inf @@ -0,0 +1,40 @@ +## @file +# Pre-runtime library with basic functions needed by the MbedTls. +# +# To be used by all consumers of MbedTlsLib except for DXE_RUNTIME_DRIVER kind +# which would cause a crash due to MemoryAllocationLib trying to use boot +# services after they are gone (unless some special kind of MemoryAllocationLib +# is employed). +# +# Copyright (c) 2023, Intel Corporation. All rights reserved.
+# Copyright (c) 2024, 3mdeb Sp. z o.o. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = MbedTlsCrtLib + FILE_GUID = 29A024DF-8D89-495C-8872-1A195214A980 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = MbedTlsCrtLib|SEC PEIM DXE_DRIVER DXE_SMM_DRIVER UEFI_DRIVER UEFI_APPLICATION + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 +# + +[Sources] + CrtWrapper.c + +[Packages] + CryptoPkg/CryptoPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + MemoryAllocationLib diff --git a/CryptoPkg/Library/MbedTlsCrtRuntimeLib/CrtWrapper.c b/CryptoPkg/Library/MbedTlsCrtRuntimeLib/CrtWrapper.c new file mode 100644 index 0000000000..6cbcab318b --- /dev/null +++ b/CryptoPkg/Library/MbedTlsCrtRuntimeLib/CrtWrapper.c @@ -0,0 +1,109 @@ +/** @file + C Run-Time Libraries (CRT) Wrapper Implementation for MbedTLS-based + Cryptographic Library. + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+Copyright (c) 2024, 3mdeb Sp. z o.o. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +#include +#include + +int +my_snprintf ( + char *str, + long long size, + const char *format, + ... + ) +{ + return 0; +} + +// +// 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 * +mbedtls_calloc ( + size_t num, + size_t size + ) +{ + CRYPTMEM_HEAD *PoolHdr; + UINTN NewSize; + VOID *Data; + + // + // Adjust the size by the buffer header overhead + // + NewSize = (UINTN)(size * num) + CRYPTMEM_OVERHEAD; + + Data = malloc (NewSize); + if (Data != NULL) { + ZeroMem (Data, NewSize); + + 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; + } +} + +/* Allocates zero-initialized memory blocks */ +void * +calloc ( + size_t num, + size_t size + ) +{ + return mbedtls_calloc (num, size); +} + +/* De-allocates or frees a memory block */ +void +mbedtls_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); + free (PoolHdr); + } +} diff --git a/CryptoPkg/Library/MbedTlsCrtRuntimeLib/MbedTlsCrtRuntimeLib.inf b/CryptoPkg/Library/MbedTlsCrtRuntimeLib/MbedTlsCrtRuntimeLib.inf new file mode 100644 index 0000000000..5d7c55020e --- /dev/null +++ b/CryptoPkg/Library/MbedTlsCrtRuntimeLib/MbedTlsCrtRuntimeLib.inf @@ -0,0 +1,42 @@ +## @file +# Runtime library with basic functions needed by the MbedTls. +# +# After ExitBootServices() gBS used by memory allocation libraries is no +# longer available because and EDK can no longer take any more RAM for itself. +# The only way of having dynamic memory allocation is to have a heap like in C +# backed up by a pre-allocated memory. This library redirects MbedTls to such +# a heap. +# +# Copyright (c) 2023, Intel Corporation. All rights reserved.
+# Copyright (c) 2024, 3mdeb Sp. z o.o. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = MbedTlsCrtRuntimeLib + FILE_GUID = 7F586875-08E6-4F95-A9C2-125F74993A86 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = MbedTlsCrtLib|DXE_RUNTIME_DRIVER + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 +# + +[Sources] + # Actual implementation of malloc() and free() are already available in + # BaseCryptLibMbedTls, the CrtWrapper.c basically just redirects to them. + CrtWrapper.c + +[Packages] + CryptoPkg/CryptoPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib diff --git a/CryptoPkg/Library/MbedTlsLib/MbedTlsLib.inf b/CryptoPkg/Library/MbedTlsLib/MbedTlsLib.inf index adcf770902..35e70d4256 100644 --- a/CryptoPkg/Library/MbedTlsLib/MbedTlsLib.inf +++ b/CryptoPkg/Library/MbedTlsLib/MbedTlsLib.inf @@ -13,6 +13,7 @@ MODULE_TYPE = BASE VERSION_STRING = 1.0 LIBRARY_CLASS = MbedTlsLib + DEFINE OPENSSL_PATH = ../OpensslLib/openssl # # The following information is for reference only and not required by the build tools. @@ -21,6 +22,11 @@ # [Sources] +# Openssl files list starts here + $(OPENSSL_PATH)/crypto/mem_clr.c + $(OPENSSL_PATH)/crypto/sha/keccak1600.c + $(OPENSSL_PATH)/crypto/sm3/sm3.c +# Openssl files list ends here Include/mbedtls/mbedtls_config.h mbedtls/library/aes.c mbedtls/library/asn1parse.c @@ -87,7 +93,6 @@ mbedtls/library/x509_csr.c mbedtls/library/pkcs7.c mbedtls/library/platform_util.c - CrtWrapper.c [Packages] MdePkg/MdePkg.dec @@ -97,6 +102,7 @@ BaseLib BaseMemoryLib DebugLib + MbedTlsCrtLib MemoryAllocationLib [BuildOptions] diff --git a/CryptoPkg/Library/MbedTlsLib/MbedTlsLibFull.inf b/CryptoPkg/Library/MbedTlsLib/MbedTlsLibFull.inf index 7715392a9d..95ec8d8cd2 100644 --- a/CryptoPkg/Library/MbedTlsLib/MbedTlsLibFull.inf +++ b/CryptoPkg/Library/MbedTlsLib/MbedTlsLibFull.inf @@ -13,6 +13,7 @@ MODULE_TYPE = BASE VERSION_STRING = 1.0 LIBRARY_CLASS = MbedTlsLib + DEFINE OPENSSL_PATH = ../OpensslLib/openssl # # The following information is for reference only and not required by the build tools. @@ -21,6 +22,11 @@ # [Sources] +# Openssl files list starts here + $(OPENSSL_PATH)/crypto/mem_clr.c + $(OPENSSL_PATH)/crypto/sha/keccak1600.c + $(OPENSSL_PATH)/crypto/sm3/sm3.c +# Openssl files list ends here Include/mbedtls/mbedtls_config.h mbedtls/library/aes.c mbedtls/library/asn1parse.c @@ -91,7 +97,6 @@ mbedtls/library/x509_csr.c mbedtls/library/pkcs7.c mbedtls/library/platform_util.c - CrtWrapper.c [Packages] MdePkg/MdePkg.dec @@ -101,6 +106,7 @@ BaseLib BaseMemoryLib DebugLib + MbedTlsCrtLib MemoryAllocationLib [BuildOptions] diff --git a/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf b/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf index d414988f78..60ac0e34a3 100644 --- a/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf +++ b/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf @@ -665,7 +665,7 @@ # types appropriate to the format string specified. # -Werror=unused-but-set-variable: Warn whenever a local variable is assigned to, but otherwise unused (aside from its declaration). # - GCC:*_*_IA32_CC_FLAGS = -U_WIN32 -U_WIN64 $(OPENSSL_FLAGS) $(OPENSSL_FLAGS_NOASM) -Wno-error=maybe-uninitialized -Wno-error=unused-but-set-variable + GCC:*_*_IA32_CC_FLAGS = -U_WIN32 -U_WIN64 $(OPENSSL_FLAGS) $(OPENSSL_FLAGS_NOASM) -Wno-error=maybe-uninitialized -Wno-error=unused-but-set-variable -Wno-error=format GCC:*_*_X64_CC_FLAGS = -U_WIN32 -U_WIN64 $(OPENSSL_FLAGS) $(OPENSSL_FLAGS_NOASM) -Wno-error=maybe-uninitialized -Wno-error=format -Wno-format -Wno-error=unused-but-set-variable -DNO_MSABI_VA_FUNCS GCC:*_*_ARM_CC_FLAGS = $(OPENSSL_FLAGS) -Wno-error=maybe-uninitialized -Wno-error=unused-but-set-variable GCC:*_*_AARCH64_CC_FLAGS = $(OPENSSL_FLAGS) -Wno-error=maybe-uninitialized -Wno-format -Wno-error=unused-but-set-variable -Wno-error=format diff --git a/DasharoModulePkg/DasharoBootPolicies/BootPolicies.c b/DasharoModulePkg/DasharoBootPolicies/BootPolicies.c new file mode 100644 index 0000000000..904cf92973 --- /dev/null +++ b/DasharoModulePkg/DasharoBootPolicies/BootPolicies.c @@ -0,0 +1,193 @@ +/*++ +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + SPDX-License-Identifier: BSD-2-Clause-Patent + +--*/ + +/** @file +**/ + +#include +#include +#include +#include +#include "BootPolicies.h" +#include + +#include +#include + +NETWORK_BOOT_POLICY_PROTOCOL mNetworkBootPolicy; +USB_STACK_POLICY_PROTOCOL mUsbStackPolicy; +USB_MASS_STORAGE_POLICY_PROTOCOL mUsbMassStoragePolicy; +PS2_CONTROLLER_POLICY_PROTOCOL mPs2ControllerPolicy; +SERIAL_REDIRECTION_POLICY_PROTOCOL mSerialRedirectionPolicy; + +/** + Entry point for the Boot Policies Driver. + @param ImageHandle Image handle of this driver. + @param SystemTable Global system service table. + @retval EFI_SUCCESS Initialization complete. +**/ +EFI_STATUS +EFIAPI +InitializeBootPolicies ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) + +{ + EFI_STATUS Status = EFI_SUCCESS; + BOOLEAN *EfiVar; + UINTN VarSize = sizeof(BOOLEAN); + + gBS = SystemTable->BootServices; + gRT = SystemTable->RuntimeServices; + + mNetworkBootPolicy.Revision = NETWORK_BOOT_POLICY_PROTOCOL_REVISION_01; + mNetworkBootPolicy.NetworkBootEnabled = FALSE; // disable by default + mUsbStackPolicy.Revision = USB_STACK_POLICY_PROTOCOL_REVISION_01; + mUsbStackPolicy.UsbStackEnabled = TRUE; + mUsbMassStoragePolicy.Revision = USB_MASS_STORAGE_POLICY_PROTOCOL_REVISION_01; + mUsbMassStoragePolicy.UsbMassStorageEnabled = TRUE; + mPs2ControllerPolicy.Revision = PS2_CONTROLLER_POLICY_PROTOCOL_REVISION_01; + mPs2ControllerPolicy.Ps2ControllerEnabled = TRUE; + mSerialRedirectionPolicy.Revision = PS2_CONTROLLER_POLICY_PROTOCOL_REVISION_01; + mSerialRedirectionPolicy.SerialRedirectionEnabled = FALSE; + + Status = GetVariable2 ( + DASHARO_VAR_NETWORK_BOOT, + &gDasharoSystemFeaturesGuid, + (VOID **) &EfiVar, + &VarSize + ); + + + if (Status == EFI_NOT_FOUND) + mNetworkBootPolicy.NetworkBootEnabled = FixedPcdGetBool(PcdDefaultNetworkBootEnable); + else if ((Status != EFI_NOT_FOUND) && (VarSize == sizeof(*EfiVar))) + mNetworkBootPolicy.NetworkBootEnabled = *EfiVar; + + if (mNetworkBootPolicy.NetworkBootEnabled) { + gBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gDasharoNetworkBootPolicyGuid, + &mNetworkBootPolicy, + NULL + ); + DEBUG ((EFI_D_INFO, "Boot Policy: Enabling network stack\n")); + } + + Status = GetVariable2 ( + DASHARO_VAR_USB_STACK, + &gDasharoSystemFeaturesGuid, + (VOID **) &EfiVar, + &VarSize + ); + + if ((Status == EFI_SUCCESS) && (VarSize == sizeof(*EfiVar))) + mUsbStackPolicy.UsbStackEnabled = *EfiVar; + else + mUsbStackPolicy.UsbStackEnabled = TRUE; // enable USB by default + + if (mUsbStackPolicy.UsbStackEnabled) { + gBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gDasharoUsbDriverPolicyGuid, + &mUsbStackPolicy, + NULL + ); + DEBUG ((EFI_D_INFO, "Boot Policy: Enabling USB stack\n")); + } else { + DEBUG ((EFI_D_INFO, "Boot Policy: Not enabling USB stack\n")); + } + + Status = GetVariable2 ( + DASHARO_VAR_USB_MASS_STORAGE, + &gDasharoSystemFeaturesGuid, + (VOID **) &EfiVar, + &VarSize + ); + + if ((Status == EFI_SUCCESS) && (VarSize == sizeof(*EfiVar))) + mUsbMassStoragePolicy.UsbMassStorageEnabled = *EfiVar; + else + mUsbMassStoragePolicy.UsbMassStorageEnabled = TRUE; // enable USB boot by default + + if (mUsbMassStoragePolicy.UsbMassStorageEnabled && mUsbStackPolicy.UsbStackEnabled) { + gBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gDasharoUsbMassStoragePolicyGuid, + &mUsbMassStoragePolicy, + NULL + ); + DEBUG ((EFI_D_INFO, "Boot Policy: Enabling USB Mass Storage\n")); + } else { + DEBUG ((EFI_D_INFO, "Boot Policy: Not enabling USB Mass Storage\n")); + } + + Status = GetVariable2 ( + DASHARO_VAR_PS2_CONTROLLER, + &gDasharoSystemFeaturesGuid, + (VOID **) &EfiVar, + &VarSize + ); + + if ((Status != EFI_NOT_FOUND) && (VarSize == sizeof(*EfiVar))) + mPs2ControllerPolicy.Ps2ControllerEnabled = *EfiVar; + else + mPs2ControllerPolicy.Ps2ControllerEnabled = TRUE; // enable PS2 by default + + if (mPs2ControllerPolicy.Ps2ControllerEnabled) { + gBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gDasharoPs2ControllerPolicyGuid, + &mPs2ControllerPolicy, + NULL + ); + DEBUG ((EFI_D_INFO, "Boot Policy: Enabling PS2 Controller\n")); + } + + VarSize = sizeof(BOOLEAN); + Status = GetVariable2 ( + DASHARO_VAR_SERIAL_REDIRECTION, + &gDasharoSystemFeaturesGuid, + (VOID **) &EfiVar, + &VarSize + ); + + + if (EFI_ERROR (Status)) + mSerialRedirectionPolicy.SerialRedirectionEnabled = FixedPcdGetBool(PcdSerialRedirectionDefaultState); + else if (!EFI_ERROR (Status) && (VarSize == sizeof(*EfiVar))) + mSerialRedirectionPolicy.SerialRedirectionEnabled = *EfiVar; + + /* Check if second port redirection is enabled */ + if (FixedPcdGetBool (PcdHave2ndUart)) { + VarSize = sizeof(BOOLEAN); + Status = GetVariable2 ( + DASHARO_VAR_SERIAL_REDIRECTION2, + &gDasharoSystemFeaturesGuid, + (VOID **) &EfiVar, + &VarSize + ); + + if (EFI_ERROR (Status)) + mSerialRedirectionPolicy.SerialRedirectionEnabled |= FixedPcdGetBool(PcdSerialRedirection2DefaultState); + else if (!EFI_ERROR (Status) && (VarSize == sizeof(*EfiVar))) + mSerialRedirectionPolicy.SerialRedirectionEnabled |= *EfiVar; + } + + if (mSerialRedirectionPolicy.SerialRedirectionEnabled) { + gBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gDasharoSerialRedirectionPolicyGuid, + &mSerialRedirectionPolicy, + NULL + ); + DEBUG ((EFI_D_INFO, "Boot Policy: Enabling Serial Redirection\n")); + } + + return EFI_SUCCESS; +} diff --git a/DasharoModulePkg/DasharoBootPolicies/BootPolicies.h b/DasharoModulePkg/DasharoBootPolicies/BootPolicies.h new file mode 100644 index 0000000000..0f1790f222 --- /dev/null +++ b/DasharoModulePkg/DasharoBootPolicies/BootPolicies.h @@ -0,0 +1,69 @@ +/*++ +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + SPDX-License-Identifier: BSD-2-Clause-Patent + +--*/ + +/** @file +**/ + +#ifndef _DASHARO_BOOT_POLICIES_H_ +#define _DASHARO_BOOT_POLICIES_H_ + +#define DASHARO_NETWORK_BOOT_POLICY_PROTOCOL_GUID \ + { 0xdef83d91, 0x4613, 0x474c, 0xa7, 0xad, 0xf7, 0x79, 0x10, 0x11, 0x43, 0xf2 } + +#define DASHARO_USB_DRIVER_POLICY_PROTOCOL_GUID \ + { 0x808330b5, 0xbe46, 0x4a41, 0x97, 0x79, 0x84, 0xa3, 0xd1, 0x31, 0xbb, 0xb4 } + +#define DASHARO_USB_MASS_STORAGE_POLICY_PROTOCOL_GUID \ + { 0xd7d1a290, 0x651a, 0x4c90, 0xbf, 0x09, 0x1b, 0x7c, 0x56, 0x7c, 0xd5, 0x9c } + +#define DASHARO_PS2_CONTROLLER_POLICY_PROTOCOL_GUID \ + { 0x4885b96d, 0xbdf1, 0x496d, 0xbc, 0x3d, 0x3e, 0x79, 0x57, 0x74, 0xcd, 0x40 } + +#define DASHARO_SERIAL_REDIRECTION_POLICY_PROTOCOL_GUID \ + { 0x0cd9776f, 0xd803, 0x42b4, 0x95, 0xa4, 0xa8, 0x58, 0x46, 0x46, 0x23, 0xc9 } + +#define NETWORK_BOOT_POLICY_PROTOCOL_REVISION_01 0x01 +#define USB_STACK_POLICY_PROTOCOL_REVISION_01 0x01 +#define USB_MASS_STORAGE_POLICY_PROTOCOL_REVISION_01 0x01 +#define PS2_CONTROLLER_POLICY_PROTOCOL_REVISION_01 0x01 +#define SERIAL_REDIRECTION_POLICY_PROTOCOL_REVISION_01 0x01 + +typedef struct _NETWORK_BOOT_POLICY_PROTOCOL { + UINT32 Revision; + BOOLEAN NetworkBootEnabled; +} NETWORK_BOOT_POLICY_PROTOCOL; + +typedef struct _USB_STACK_POLICY_PROTOCOL { + UINT32 Revision; + BOOLEAN UsbStackEnabled; +} USB_STACK_POLICY_PROTOCOL; + +typedef struct _USB_MASS_STORAGE_POLICY_PROTOCOL { + UINT32 Revision; + BOOLEAN UsbMassStorageEnabled; +} USB_MASS_STORAGE_POLICY_PROTOCOL; + +typedef struct _PS2_CONTROLLER_POLICY_PROTOCOL { + UINT32 Revision; + BOOLEAN Ps2ControllerEnabled; +} PS2_CONTROLLER_POLICY_PROTOCOL; + +typedef struct _SERIAL_REDIRECTION_POLICY_PROTOCOL { + UINT32 Revision; + BOOLEAN SerialRedirectionEnabled; +} SERIAL_REDIRECTION_POLICY_PROTOCOL; + +// +// Extern the GUID for protocol users. +// +extern EFI_GUID gDasharoNetworkBootPolicyGuid; +extern EFI_GUID gDasharoUsbDriverPolicyGuid; +extern EFI_GUID gDasharoUsbMassStoragePolicyGuid; +extern EFI_GUID gDasharoPs2ControllerPolicyGuid; +extern EFI_GUID gDasharoSerialRedirectionPolicyGuid; + +#endif diff --git a/DasharoModulePkg/DasharoBootPolicies/DasharoBootPolicies.inf b/DasharoModulePkg/DasharoBootPolicies/DasharoBootPolicies.inf new file mode 100644 index 0000000000..91ae66658c --- /dev/null +++ b/DasharoModulePkg/DasharoBootPolicies/DasharoBootPolicies.inf @@ -0,0 +1,56 @@ +# +# +# Copyright (c) 1999 - 2019, Intel Corporation. All rights reserved +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DasharoBootPolicies + FILE_GUID = ca90493e-1a22-4d09-9c78-3894507eb646 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = InitializeBootPolicies + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = X64 +# + +[Sources.common] + BootPolicies.c + +[Packages] + MdePkg/MdePkg.dec + DasharoModulePkg/DasharoModulePkg.dec + +[LibraryClasses] + BaseLib + DebugLib + PcdLib + UefiLib + PcdLib + UefiDriverEntryPoint + UefiRuntimeServicesTableLib + +[Guids] + gDasharoSystemFeaturesGuid ### CONSUMES + +[Protocols] + gDasharoNetworkBootPolicyGuid ### PROVIDES + gDasharoUsbDriverPolicyGuid ### PROVIDES + gDasharoUsbMassStoragePolicyGuid ### PROVIDES + gDasharoPs2ControllerPolicyGuid ### PROVIDES + gDasharoSerialRedirectionPolicyGuid ### PROVIDES + +[Pcd] + gDasharoSystemFeaturesTokenSpaceGuid.PcdDefaultNetworkBootEnable + gDasharoSystemFeaturesTokenSpaceGuid.PcdSerialRedirectionDefaultState + gDasharoSystemFeaturesTokenSpaceGuid.PcdSerialRedirection2DefaultState + gDasharoSystemFeaturesTokenSpaceGuid.PcdHave2ndUart + +[Depex] + gEfiVariableArchProtocolGuid diff --git a/DasharoModulePkg/DasharoBootPoliciesVTd/BootPolicies.c b/DasharoModulePkg/DasharoBootPoliciesVTd/BootPolicies.c new file mode 100644 index 0000000000..b039351edd --- /dev/null +++ b/DasharoModulePkg/DasharoBootPoliciesVTd/BootPolicies.c @@ -0,0 +1,72 @@ +/*++ +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + SPDX-License-Identifier: BSD-2-Clause-Patent + +--*/ + +/** @file +**/ + +#include +#include +#include +#include +#include + +#include + +/** + Entry point for the Boot Policies Driver. + @param ImageHandle Image handle of this driver. + @param SystemTable Global system service table. + @retval EFI_SUCCESS Initialization complete. +**/ +EFI_STATUS +EFIAPI +InitializeBootPolicies ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) + +{ + EFI_STATUS Status; + UINTN VarSize; + DASHARO_IOMMU_CONFIG *IommuConfig; + UINT8 PcdVal = 0; + + gBS = SystemTable->BootServices; + gRT = SystemTable->RuntimeServices; + + VarSize = sizeof(*IommuConfig); + Status = GetVariable2 ( + L"IommuConfig", + &gDasharoSystemFeaturesGuid, + (VOID **) &IommuConfig, + &VarSize + ); + + if ((Status == EFI_SUCCESS) && (VarSize == sizeof(*IommuConfig))){ + PcdVal = PcdGet8(PcdVTdPolicyPropertyMask); + if (IommuConfig->IommuEnable){ + PcdVal |= 0x01; + if (IommuConfig->IommuHandoff){ + PcdVal |= 0x02; + DEBUG ((EFI_D_INFO, "Boot Policy: IOMMU will be kept enabled on ExitBootServices\n")); + } + else{ + PcdVal &= (~0x02); + DEBUG ((EFI_D_INFO, "Boot Policy: IOMMU will be disabled on ExitBootServices\n")); + } + PcdSet8S(PcdVTdPolicyPropertyMask, PcdVal); + } else { + PcdSet8S(PcdVTdPolicyPropertyMask, PcdVal & (~0x03)); + DEBUG ((EFI_D_INFO, "Boot Policy: DMA protection disabled\n")); + } + } else { + PcdSet8S(PcdVTdPolicyPropertyMask, PcdVal & (~0x03)); + DEBUG ((EFI_D_INFO, "Boot Policy: DMA protection disabled\n")); + } + + return EFI_SUCCESS; +} diff --git a/DasharoModulePkg/DasharoBootPoliciesVTd/DasharoBootPoliciesVTd.inf b/DasharoModulePkg/DasharoBootPoliciesVTd/DasharoBootPoliciesVTd.inf new file mode 100644 index 0000000000..ad672e774e --- /dev/null +++ b/DasharoModulePkg/DasharoBootPoliciesVTd/DasharoBootPoliciesVTd.inf @@ -0,0 +1,47 @@ +# +# +# Copyright (c) 1999 - 2019, Intel Corporation. All rights reserved +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DasharoBootPoliciesVTd + FILE_GUID = ca90493f-1a22-4d09-9c78-3894507eb646 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = InitializeBootPolicies + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = X64 +# + +[Sources.common] + BootPolicies.c + +[Packages] + MdePkg/MdePkg.dec + DasharoModulePkg/DasharoModulePkg.dec + IntelSiliconPkg/IntelSiliconPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + PcdLib + UefiLib + PcdLib + UefiDriverEntryPoint + UefiRuntimeServicesTableLib + +[Guids] + gDasharoSystemFeaturesGuid ### CONSUMES + +[Pcd] + gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask + +[Depex] + gEfiVariableArchProtocolGuid diff --git a/DasharoModulePkg/DasharoModuleComponents.dsc.inc b/DasharoModulePkg/DasharoModuleComponents.dsc.inc new file mode 100644 index 0000000000..5b755b6964 --- /dev/null +++ b/DasharoModulePkg/DasharoModuleComponents.dsc.inc @@ -0,0 +1,13 @@ +## @file +# Dasharo DSC include file for [Components*] section. +# +# This file can be included to the [Components*] section(s) of a platform DSC file +# by using "!include DasharoModulePkg/DasharoModuleComponents.dsc.inc" to specify the INF files. +# +# Copyright (c) 2022, 3mdeb Sp. z o.o. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause +# +## + + DasharoModulePkg/Library/DasharoSystemFeaturesUiLib/DasharoSystemFeaturesUiLib.inf + DasharoModulePkg/UserAuthenticationDxe/UserAuthenticationDxe.inf diff --git a/DasharoModulePkg/DasharoModuleComponents.uni b/DasharoModulePkg/DasharoModuleComponents.uni new file mode 100644 index 0000000000..a7b1e80840 --- /dev/null +++ b/DasharoModulePkg/DasharoModuleComponents.uni @@ -0,0 +1,15 @@ +// /** @file +// Dasharo Module Package +// +// This Package provides cryptographic-related libraries for UEFI security modules. +// It also provides a test application to test libraries. +// +// Copyright (c) 2022, 3mdeb Sp. z o.o. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause +// +// **/ + +#string STR_PACKAGE_ABSTRACT #language en-US "Provides Dasharo-related modules" + +#string STR_PACKAGE_DESCRIPTION #language en-US "This package provides modules that are used in Dasharo firmware." diff --git a/DasharoModulePkg/DasharoModulePkg.dec b/DasharoModulePkg/DasharoModulePkg.dec new file mode 100644 index 0000000000..6d4f6d0dc2 --- /dev/null +++ b/DasharoModulePkg/DasharoModulePkg.dec @@ -0,0 +1,90 @@ +## @file +# Dasharo Module Package +# +# Provides libraries specific to Dasharo firmware. +# +# Copyright (c) 2022, 3mdeb Sp. z o.o. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause +# +## + +[Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = DasharoModulePkg + PACKAGE_GUID = 34B742F3-EB9D-4204-8C9A-E1B47966A61F + PACKAGE_VERSION = 0.1 + PACKAGE_UNI_FILE = DasharoModuleComponents.uni + +[Includes] + Include + +[LibraryClasses] + ## @libraryclass Provides a platform-specific method to return the password policy. + PlatformPasswordLib|Include/Library/PlatformPasswordLib.h + +[Guids] + gDasharoSystemFeaturesGuid = { 0xd15b327e, 0xff2d, 0x4fc1, { 0xab, 0xf6, 0xc1, 0x2b, 0xd0, 0x8c, 0x13, 0x59 }} + gDasharoSystemFeaturesTokenSpaceGuid = {0xc7d52e10, 0xadec, 0x4d49, { 0x9e, 0xc5, 0xb8, 0xcf, 0xcd, 0x4b, 0x9d, 0xb9 }} + gUserAuthFeaturePkgTokenSpaceGuid = {0xa2793a6e, 0x6af1, 0x45c4, {0x88, 0x4d, 0x3d, 0x0c, 0x7a, 0xfe, 0x91, 0xc6}} + ## Include Include/Guid/UserAuthentication.h + gUserAuthenticationGuid = { 0xee24a7f7, 0x606b, 0x4724, { 0xb3, 0xc9, 0xf5, 0xae, 0x4a, 0x3b, 0x81, 0x65}} + +[Ppis] + +[Protocols] + gDasharoNetworkBootPolicyGuid = { 0xdef83d91, 0x4613, 0x474c, { 0xa7, 0xad, 0xf7, 0x79, 0x10, 0x11, 0x43, 0xf2 }} + gDasharoUsbDriverPolicyGuid = { 0x808330b5, 0xbe46, 0x4a41, { 0x97, 0x79, 0x84, 0xa3, 0xd1, 0x31, 0xbb, 0xb4 }} + gDasharoUsbMassStoragePolicyGuid = { 0xd7d1a290, 0x651a, 0x4c90, { 0xbf, 0x09, 0x1b, 0x7c, 0x56, 0x7c, 0xd5, 0x9c }} + gDasharoPs2ControllerPolicyGuid = { 0x4885b96d, 0xbdf1, 0x496d, { 0xbc, 0x3d, 0x3e, 0x79, 0x57, 0x74, 0xcd, 0x40 }} + gDasharoSerialRedirectionPolicyGuid = { 0x0cd9776f, 0xd803, 0x42b4, { 0x95, 0xa4, 0xa8, 0x58, 0x46, 0x46, 0x23, 0xc9 }} + +[PcdsFixedAtBuild] + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowMenu|FALSE|BOOLEAN|0x00000001 + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowSecurityMenu|FALSE|BOOLEAN|0x00000002 + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowIntelMeMenu|FALSE|BOOLEAN|0x00000003 + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowUsbMenu|FALSE|BOOLEAN|0x00000004 + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowNetworkMenu|FALSE|BOOLEAN|0x00000005 + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowChipsetMenu|FALSE|BOOLEAN|0x00000006 + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowPowerMenu|FALSE|BOOLEAN|0x00000007 + gDasharoSystemFeaturesTokenSpaceGuid.PcdPowerMenuShowFanCurve|FALSE|BOOLEAN|0x00000008 + gDasharoSystemFeaturesTokenSpaceGuid.PcdDefaultNetworkBootEnable|FALSE|BOOLEAN|0x00000009 + gDasharoSystemFeaturesTokenSpaceGuid.PcdDasharoEnterprise|FALSE|BOOLEAN|0x0000000A + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowIommuOptions|FALSE|BOOLEAN|0x0000000B + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowOcWdtOptions|FALSE|BOOLEAN|0x0000000C + gDasharoSystemFeaturesTokenSpaceGuid.PcdOcWdtTimeoutDefault|500|UINT16|0x0000000D + gDasharoSystemFeaturesTokenSpaceGuid.PcdDefaultPowerFailureState|0xff|UINT8|0x0000000E + gDasharoSystemFeaturesTokenSpaceGuid.PcdPowerMenuShowSleepType|TRUE|BOOLEAN|0x0000000F + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowPciMenu|FALSE|BOOLEAN|0x00000010 + gDasharoSystemFeaturesTokenSpaceGuid.PcdPciMenuShowResizeableBars|FALSE|BOOLEAN|0x00000011 + gDasharoSystemFeaturesTokenSpaceGuid.PcdPowerMenuShowBatteryThresholds|FALSE|BOOLEAN|0x00000012 + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowMemoryMenu|FALSE|BOOLEAN|0x000000013 + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowSerialPortMenu|FALSE|BOOLEAN|0x000000014 + gDasharoSystemFeaturesTokenSpaceGuid.PcdSerialRedirectionDefaultState|FALSE|BOOLEAN|0x000000015 + gDasharoSystemFeaturesTokenSpaceGuid.PcdSecurityShowWiFiBtOption|FALSE|BOOLEAN|0x000000016 + gDasharoSystemFeaturesTokenSpaceGuid.PcdSecurityShowCameraOption|FALSE|BOOLEAN|0x000000017 + gDasharoSystemFeaturesTokenSpaceGuid.PcdIntelMeDefaultState|0|UINT8|0x000000018 + gDasharoSystemFeaturesTokenSpaceGuid.PcdIntelMeHapAvailable|TRUE|BOOLEAN|0x000000019 + gDasharoSystemFeaturesTokenSpaceGuid.PcdS3SupportExperimental|FALSE|BOOLEAN|0x000000020 + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowLockBios|FALSE|BOOLEAN|0x00000001A + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowSmmBwp|FALSE|BOOLEAN|0x00000001B + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowFum|TRUE|BOOLEAN|0x00000001C + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowPs2Option|FALSE|BOOLEAN|0x00000001D + gDasharoSystemFeaturesTokenSpaceGuid.PcdSleepTypeDefaultS3|FALSE|BOOLEAN|0x00000001E + gDasharoSystemFeaturesTokenSpaceGuid.PcdSerialRedirection2DefaultState|FALSE|BOOLEAN|0x00000001F + gDasharoSystemFeaturesTokenSpaceGuid.PcdHave2ndUart|FALSE|BOOLEAN|0x000000021 + gDasharoSystemFeaturesTokenSpaceGuid.PcdOcWdtEnableDefault|FALSE|BOOLEAN|0x000000022 + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowCpuThrottlingThreshold|FALSE|BOOLEAN|0x00000023 + gDasharoSystemFeaturesTokenSpaceGuid.PcdCpuMaxTemperature|100|UINT8|0x00000024 + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowCpuMenu|FALSE|BOOLEAN|0x000000025 + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowCpuCoreDisable|FALSE|BOOLEAN|0x000000026 + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowCpuHyperThreading|FALSE|BOOLEAN|0x000000027 + gDasharoSystemFeaturesTokenSpaceGuid.PcdCpuHyperThreadingDefault|TRUE|BOOLEAN|0x000000028 + gDasharoSystemFeaturesTokenSpaceGuid.PcdCpuThrottlingOffsetDefault|20|UINT8|0x00000029 + gDasharoSystemFeaturesTokenSpaceGuid.PcdPowerMenuShowFanCurveOffOption|FALSE|BOOLEAN|0x00000002A + +[PcdsFixedAtBuild,PcdsPatchableInModule,PcdsDynamic,PcdsDynamicEx] + ## Indicate whether the password is cleared. + # When it is configured to Dynamic or DynamicEx, it can be set through detection using + # a platform-specific method (e.g. Board Jumper set) in a actual platform in early boot phase.

+ # @Prompt The password clear status + gUserAuthFeaturePkgTokenSpaceGuid.PcdPasswordCleared|FALSE|BOOLEAN|0xF0000001 diff --git a/DasharoModulePkg/DasharoModulePkg.dsc b/DasharoModulePkg/DasharoModulePkg.dsc new file mode 100644 index 0000000000..ec8589dead --- /dev/null +++ b/DasharoModulePkg/DasharoModulePkg.dsc @@ -0,0 +1,29 @@ +## @file +# Dasharo Module Package +# +# Copyright (c) 2022, 3mdeb Sp. z o.o. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause +# +## + +[Defines] + PLATFORM_NAME = MdeModule + PLATFORM_GUID = D11BE2F6-8BD9-4099-8C73-2E09220FF8DD + PLATFORM_VERSION = 0.1 + DSC_SPECIFICATION = 0x00010005 + OUTPUT_DIRECTORY = Build/DasharoModulePkg + SUPPORTED_ARCHITECTURES = IA32|X64|EBC + BUILD_TARGETS = DEBUG|RELEASE|NOOPT + SKUID_IDENTIFIER = DEFAULT + +[LibraryClasses] + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + +[Components] + !include DasharoModulePkg/DasharoModuleComponents.dsc.inc + +[BuildOptions] + *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES -Wno-error + +[Packages] + !include DasharoModulePkg/Include/UserAuthFeature.dsc diff --git a/DasharoModulePkg/Documentation/AddNewSetting.md b/DasharoModulePkg/Documentation/AddNewSetting.md new file mode 100644 index 0000000000..07fa6ad98c --- /dev/null +++ b/DasharoModulePkg/Documentation/AddNewSetting.md @@ -0,0 +1,196 @@ +This document is meant to outline the process of adding a new Dasharo setting. +If something isn't covered, follow structure of the code used for some similar +variable. If possible, use alphabetic sorting of lists, although it's not a +requirement. + +Examples below use a new setting called `NewSetting`/`NEW_SETTING` which should +be replaced with an actual name of the setting. + +Basic variable implementation +============================= + +EFI variables are managed by a dedicated library which is used by the UI code. +It makes sense to start from here. + +Add variable name in `Include/DasharoOptions.h` +----------------------------------------------- + +Add a new `#define DASHARO_VAR_*` near the top where other settings marked with +`// Settings` are, for example: + +``` +#define DASHARO_VAR_NEW_SETTING L"NewSetting" +``` + +This is an EFI variable name. It should look roughly like the already existing +ones. The rest of the code should use the macro name after adding +`#include ` and not the string literal which can have typos. + +Add default value in `Library/DasharoVariablesLib/DasharoVariablesLib.c` +------------------------------------------------------------------------ + +Add another `if`-statement to `GetVariableDefault()` setting default variable +data, its size and additional EFI variable attributes if they are necessary. +See below if variable data is not a primitive type. + +Updating `GetVariableDefault()` enables resetting and creation (see the next +step) of the variable with the correct value. + +If the variable's data is a structure then additionally: +1. Add a new `DASHARO_*` structure at the bottom of `Include/DasharoOptions.h`. +2. Add the new structure to `VAR_DATA` in `Include/DasharoOptions.h` as well. + +Add variable creation in `Library/DasharoVariablesLib/DasharoVariablesLib.c` +---------------------------------------------------------------------------- + +By adding one more line to `mAllVariables` array there. + +Adding the setting to Dasharo System Features +============================================= + +Before a variable can become visible in the UI, the code which implements the UI +part needs to become aware of it. + +Add storage for new variable +---------------------------- + +Find `DASHARO_FEATURES_DATA` structure in +`Library/DasharoSystemFeaturesUiLib/DasharoSystemFeaturesHii.h` and add a new +field after `// Feature data` like: + +``` + BOOLEAN NewSetting; +``` + +Add initialization to constructor of `DasharoSystemFeaturesUiLib` +----------------------------------------------------------------- + +Update `DasharoSystemFeaturesUiLibConstructor()` in +`Library/DasharoSystemFeaturesUiLib/DasharoSystemFeatures.c` by adding a new +line like this: + +``` + LOAD_VAR (DASHARO_VAR_NEW_SETTING, NewSetting); +``` + +`NewSetting` here is a field of `DASHARO_FEATURES_DATA` from the above step. + +Add saving of new value +----------------------- + +`DasharoSystemFeaturesRouteConfig()` in +`Library/DasharoSystemFeaturesUiLib/DasharoSystemFeatures.c` is responsible for +writing changed values back into EFI variable storage. Add a line like this to +the function: + +``` + STORE_VAR (DASHARO_VAR_NEW_SETTING, NewSetting); +``` + +Very similar to `LOAD_VAR`. + +Some variables can even be read-only, but add this line anyway for consistency. +If no value change is detected, nothing gets written. + +Exposing the setting in Dasharo System Features UI +================================================== + +A variable might exist without being visible to the user, it might be visible +conditionally or unconditionally. The last two cases require updating UI forms +and tying them with the new code. + +Add UI strings to `Library/DasharoSystemFeaturesUiLib/DasharoSystemFeaturesStrings.uni` +--------------------------------------------------------------------------------------- + +If your variable is called `DASHARO_VAR_NEW_SETTING`, add label and help +prompt like the following: + +``` +#string STR_NEW_SETTING_PROMPT #language en-US "" +#string STR_NEW_SETTING_HELP #language en-US "" +``` + +The two IDs above (`STR_NEW_SETTING_PROMPT` and `STR_NEW_SETTING_HELP`) will be +needed on modifying a form in the next step. + +Update `Library/DasharoSystemFeaturesUiLib/DasharoSystemFeaturesVfr.vfr` UI form +-------------------------------------------------------------------------------- + +The new setting will need to go to one of the sections surrounded by `form` and +`endform`. In some cases it might be necessary to add a new section. + +Most of the settings are booleans that get represented as checkboxes in which +case the added lines would look like this: + +``` + checkbox varid = FeaturesData.NewSetting, + prompt = STRING_TOKEN(STR_NEW_SETTING_PROMPT), + help = STRING_TOKEN(STR_NEW_SETTING_HELP), + flags = RESET_REQUIRED, + endcheckbox; +``` + +Making a setting resettable +=========================== + +Not all UI elements described in VFR file can have their default specified there +as well and that value might not be permanently fixed (i.e., configured at +build-time or run-time). Handling such a situation requires writing code which +provides default value through a callback which in this case is called +`DasharoSystemFeaturesCallback()` in +`Library/DasharoSystemFeaturesUiLib/DasharoSystemFeatures.c` file. For the +callback to know which value to provide, it gets an integer value known as +question ID which is specified in VFR file as well. + +Create question ID +------------------ + +Add a new definition at the bottom of +`Library/DasharoSystemFeaturesUiLib/DasharoSystemFeaturesHii.h` like this one: + +``` +#define NEW_SETTING_QUESTION_ID 0x8010 +``` + +The integer value should be unique. + +Extend callback in `Library/DasharoSystemFeaturesUiLib/DasharoSystemFeatures.c` +------------------------------------------------------------------------------- + +Handle a new case to `switch (QuestionId)` in `DasharoSystemFeaturesCallback()` +like the following: + +``` + case NEW_SETTING_QUESTION_ID: + Value->b = DasharoGetVariableDefault (DASHARO_VAR_NEW_SETTING).Boolean; + break; +``` + +Depending on the variable type you want to change `->b` and `.Boolean` parts. + +Update UI element in VFR file +----------------------------- + +Find the element in question in +`Library/DasharoSystemFeaturesUiLib/DasharoSystemFeaturesVfr.vfr` and add two +fields to it (update flags if they already exist): + +``` + questionid = NEW_SETTING_QUESTION_ID, + flags = RESET_REQUIRED | INTERACTIVE, +``` + +`RESET_REQUIRED` flag means that resetting settings will affect this particular +one as well. + +`INTERACTIVE` flag means that the callback will be invoked for this element. +**Adding `questionid` without setting `INTERACTIVE` flag won't have any useful +effect.** + +Topics not covered +================== + +Could be added in the future: + +* Adding a new submenu. +* Controlling feature visibility via PCDs and hiding them in VFR. diff --git a/DasharoModulePkg/Include/DasharoOptions.h b/DasharoModulePkg/Include/DasharoOptions.h new file mode 100644 index 0000000000..9cd0733a7d --- /dev/null +++ b/DasharoModulePkg/Include/DasharoOptions.h @@ -0,0 +1,116 @@ +/** @file +Declarations for options of Dasharo system features + +Copyright (c) 2023, 3mdeb Sp. z o.o. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _DASHARO_OPTIONS_H_ +#define _DASHARO_OPTIONS_H_ + +// +// Names of Dasharo-specific EFI variables in DasharoSystemFeaturesGuid +// namespace. +// + +// Settings +#define DASHARO_VAR_BATTERY_CONFIG L"BatteryConfig" +#define DASHARO_VAR_BOOT_MANAGER_ENABLED L"BootManagerEnabled" +#define DASHARO_VAR_CPU_THROTTLING_OFFSET L"CpuThrottlingOffset" +#define DASHARO_VAR_ENABLE_CAMERA L"EnableCamera" +#define DASHARO_VAR_ENABLE_WIFI_BT L"EnableWifiBt" +#define DASHARO_VAR_FAN_CURVE_OPTION L"FanCurveOption" +#define DASHARO_VAR_FIRMWARE_UPDATE_MODE L"FirmwareUpdateMode" +#define DASHARO_VAR_IOMMU_CONFIG L"IommuConfig" +#define DASHARO_VAR_LOCK_BIOS L"LockBios" +#define DASHARO_VAR_MEMORY_PROFILE L"MemoryProfile" +#define DASHARO_VAR_ME_MODE L"MeMode" +#define DASHARO_VAR_NETWORK_BOOT L"NetworkBoot" +#define DASHARO_VAR_OPTION_ROM_POLICY L"OptionRomPolicy" +#define DASHARO_VAR_POWER_FAILURE_STATE L"PowerFailureState" +#define DASHARO_VAR_PS2_CONTROLLER L"Ps2Controller" +#define DASHARO_VAR_RESIZEABLE_BARS_ENABLED L"PCIeResizeableBarsEnabled" +#define DASHARO_VAR_SERIAL_REDIRECTION L"SerialRedirection" +#define DASHARO_VAR_SERIAL_REDIRECTION2 L"SerialRedirection2" +#define DASHARO_VAR_SLEEP_TYPE L"SleepType" +#define DASHARO_VAR_SMM_BWP L"SmmBwp" +#define DASHARO_VAR_USB_MASS_STORAGE L"UsbMassStorage" +#define DASHARO_VAR_USB_STACK L"UsbDriverStack" +#define DASHARO_VAR_WATCHDOG L"WatchdogConfig" +#define DASHARO_VAR_WATCHDOG_AVAILABLE L"WatchdogAvailable" +#define DASHARO_VAR_SMALL_CORE_ACTIVE_COUNT L"SmallCoreActiveCount" +#define DASHARO_VAR_CORE_ACTIVE_COUNT L"CoreActiveCount" +#define DASHARO_VAR_HYPER_THREADING L"HyperThreading" + +// Other +#define DASHARO_VAR_SMBIOS_UUID L"Type1UUID" +#define DASHARO_VAR_SMBIOS_SN L"Type2SN" + +// +// Constants for some of the above EFI variables which typically have a value of +// UINT8 type. +// + +#define DASHARO_FAN_CURVE_OPTION_SILENT 0 +#define DASHARO_FAN_CURVE_OPTION_PERFORMANCE 1 +#define DASHARO_FAN_CURVE_OPTION_OFF 2 + +#define DASHARO_ME_MODE_ENABLE 0 +#define DASHARO_ME_MODE_DISABLE_HECI 1 +#define DASHARO_ME_MODE_DISABLE_HAP 2 + +#define DASHARO_OPTION_ROM_POLICY_DISABLE_ALL 0 +#define DASHARO_OPTION_ROM_POLICY_ENABLE_ALL 1 +#define DASHARO_OPTION_ROM_POLICY_VGA_ONLY 2 + +#define DASHARO_SLEEP_TYPE_S0IX 0 +#define DASHARO_SLEEP_TYPE_S3 1 + +#define DASHARO_POWER_FAILURE_STATE_OFF 0 +#define DASHARO_POWER_FAILURE_STATE_ON 1 +#define DASHARO_POWER_FAILURE_STATE_KEEP 2 +#define DASHARO_POWER_FAILURE_STATE_HIDDEN 0xff + +// The values aren't random, they match FSP_M_CONFIG::SpdProfileSelected +#define DASHARO_MEMORY_PROFILE_JEDEC 0 +#define DASHARO_MEMORY_PROFILE_XMP1 2 +#define DASHARO_MEMORY_PROFILE_XMP2 3 +#define DASHARO_MEMORY_PROFILE_XMP3 4 + +#define DASHARO_CPU_CORES_ENABLE_ALL 0xff +// +// Structures describing format of some of the above EFI variables. Must be +// packed. +// + +#pragma pack(push,1) + +typedef struct { + BOOLEAN WatchdogEnable; + UINT16 WatchdogTimeout; +} DASHARO_WATCHDOG_CONFIG; + +typedef struct { + BOOLEAN IommuEnable; + BOOLEAN IommuHandoff; +} DASHARO_IOMMU_CONFIG; + +typedef struct { + UINT8 StartThreshold; + UINT8 StopThreshold; +} DASHARO_BATTERY_CONFIG; + +#pragma pack(pop) + +// Set of possible values of Dasharo variables. +typedef union { + BOOLEAN Boolean; + UINT8 Uint8; + + DASHARO_WATCHDOG_CONFIG Watchdog; + DASHARO_IOMMU_CONFIG Iommu; + DASHARO_BATTERY_CONFIG Battery; +} DASHARO_VAR_DATA; + +#endif diff --git a/DasharoModulePkg/Include/Guid/UserAuthentication.h b/DasharoModulePkg/Include/Guid/UserAuthentication.h new file mode 100644 index 0000000000..959916e755 --- /dev/null +++ b/DasharoModulePkg/Include/Guid/UserAuthentication.h @@ -0,0 +1,53 @@ +/** @file + GUID is for UserAuthentication SMM communication. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __USER_AUTHENTICATION_GUID_H__ +#define __USER_AUTHENTICATION_GUID_H__ + +#define PASSWORD_MIN_SIZE 9 // MIN number of chars of password, including NULL. +#define PASSWORD_MAX_SIZE 65 // MAX number of chars of password, including NULL. + +#define PASSWORD_SALT_SIZE 32 +#define PASSWORD_HASH_SIZE 32 // SHA256_DIGEST_SIZE + +#define PASSWORD_MAX_TRY_COUNT 3 +#define PASSWORD_HISTORY_CHECK_COUNT 5 + +// +// Name of the variable +// +#define USER_AUTHENTICATION_VAR_NAME L"Password" +#define USER_AUTHENTICATION_HISTORY_LAST_VAR_NAME L"PasswordLast" + +// +// Variable storage +// +typedef struct { + UINT8 PasswordHash[PASSWORD_HASH_SIZE]; + UINT8 PasswordSalt[PASSWORD_SALT_SIZE]; +} USER_PASSWORD_VAR_STRUCT; + +#define USER_AUTHENTICATION_GUID \ + { 0xf06e3ea7, 0x611c, 0x4b6b, { 0xb4, 0x10, 0xc2, 0xbf, 0x94, 0x3f, 0x38, 0xf2 } } + +extern EFI_GUID gUserAuthenticationGuid; + +typedef struct { + CHAR8 NewPassword[PASSWORD_MAX_SIZE]; + CHAR8 OldPassword[PASSWORD_MAX_SIZE]; +} PASSWORD_COMMUNICATE_SET_PASSWORD; + +typedef struct { + CHAR8 Password[PASSWORD_MAX_SIZE]; +} PASSWORD_COMMUNICATE_VERIFY_PASSWORD; + +typedef struct { + BOOLEAN NeedReVerify; +} PASSWORD_COMMUNICATE_VERIFY_POLICY; + +#endif diff --git a/DasharoModulePkg/Include/Library/DasharoVariablesLib.h b/DasharoModulePkg/Include/Library/DasharoVariablesLib.h new file mode 100644 index 0000000000..95e4940b4d --- /dev/null +++ b/DasharoModulePkg/Include/Library/DasharoVariablesLib.h @@ -0,0 +1,79 @@ +/** @file + A library for providing services related to Dasharo-specific EFI variables. + + Copyright (c) 2024, 3mdeb Sp. z o.o. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _DASHARO_VARIABLES_LIB_H_ +#define _DASHARO_VARIABLES_LIB_H_ + +#include +#include + +/** + Query a default value for a specified variable. + + @param VarName Name of the variable. + + @retval Default value which is all zeroes for an unknown variable name. +**/ +DASHARO_VAR_DATA +EFIAPI +DasharoGetVariableDefault ( + CHAR16 *VarName + ); + +/** + Query attributes of a specified variable. + + @param VarName Name of the variable. + + @retval EFI variable attributes (the value is sensible for unknown ones). +**/ +UINT32 +EFIAPI +DasharoGetVariableAttributes ( + CHAR16 *VarName + ); + +/** + Measure EFI variables specific to Dasharo. + + This function should be called before booting into an OS or a UEFI + application. + + @retval RETURN_SUCCESS Successfully measured all variables. +**/ +EFI_STATUS +EFIAPI +DasharoMeasureVariables ( + VOID + ); + +/** + Enable firmware update mode (FUM) for the duration of the next boot. + + @retval RETURN_SUCCESS FUM was successfully enabled. +**/ +EFI_STATUS +EFIAPI +DasharoEnableFUM ( + VOID + ); + +/** + Check whether capsule updates which survive a warm system reset are permitted + by current configuration. + + @retval TRUE Persistent capsules can be accepted by UpdateCapsule(). + @retval FALSE UpdateCapsule() must fail with an error for such a capsule. +**/ +BOOLEAN +EFIAPI +DasharoCapsulesCanPersistAcrossReset ( + VOID + ); + +#endif diff --git a/DasharoModulePkg/Include/Library/PlatformPasswordLib.h b/DasharoModulePkg/Include/Library/PlatformPasswordLib.h new file mode 100644 index 0000000000..ce27947f6d --- /dev/null +++ b/DasharoModulePkg/Include/Library/PlatformPasswordLib.h @@ -0,0 +1,48 @@ +/** @file + Provides a platform-specific method to return password policy. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __PLATFORM_PASSWORD_LIB_H__ +#define __PLATFORM_PASSWORD_LIB_H__ + +/** + This function is called at password driver entrypoint. + This function should be called only once, to clear the password. + + This function provides a way to reset the password, just in case + the platform owner forgets the password. + The platform should provide a secure way to make sure + only the platform owner is allowed to clear password. + + Once the password is cleared, the platform should provide a way + to set a new password. + + @retval TRUE There is a platform request to clear the password. + @retval FALSE There is no platform request to clear the password. +**/ +BOOLEAN +EFIAPI +IsPasswordCleared ( + VOID + ); + +/** + This function is called if the password driver finds that the password is not enrolled, + when the password is required to input. + + This function should return the action according to platform policy. + + @retval TRUE The caller should force the user to enroll the password. + @retval FALSE The caller may skip the password enroll. +**/ +BOOLEAN +EFIAPI +NeedEnrollPassword ( + VOID + ); + +#endif diff --git a/DasharoModulePkg/Include/PostMemory.fdf b/DasharoModulePkg/Include/PostMemory.fdf new file mode 100644 index 0000000000..b340d32c72 --- /dev/null +++ b/DasharoModulePkg/Include/PostMemory.fdf @@ -0,0 +1,10 @@ +## @file +# FDF file for post-memory modules that enable User Authentication. +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +INF UserAuthFeaturePkg/UserAuthenticationDxe/UserAuthenticationDxe.inf diff --git a/DasharoModulePkg/Include/PreMemory.fdf b/DasharoModulePkg/Include/PreMemory.fdf new file mode 100644 index 0000000000..512d1a2673 --- /dev/null +++ b/DasharoModulePkg/Include/PreMemory.fdf @@ -0,0 +1,8 @@ +## @file +# FDF file for pre-memory modules that enable User Authentication. +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## diff --git a/DasharoModulePkg/Include/UserAuthFeature.dsc b/DasharoModulePkg/Include/UserAuthFeature.dsc new file mode 100644 index 0000000000..6cf980b249 --- /dev/null +++ b/DasharoModulePkg/Include/UserAuthFeature.dsc @@ -0,0 +1,53 @@ +## @file +# This is a build description file for the User Authentication advanced feature. +# This file should be included into another package DSC file to build this feature. +# +# The DEC files are used by the utilities that parse DSC and +# INF files to generate AutoGen.c and AutoGen.h files +# for the build infrastructure. +# +# Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +################################################################################ +# +# Library Class section - list of all Library Classes needed by this feature. +# +################################################################################ + +#!include MdePkg/MdeLibs.dsc.inc + +[LibraryClasses] + PlatformPasswordLib|DasharoModulePkg/Library/PlatformPasswordLibNull/PlatformPasswordLibNull.inf + +################################################################################################### +# +# 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. +# +################################################################################################### + +# +# Feature DXE Components +# +[Components.X64] + ##################################### + # User Authentication Feature Package + ##################################### + # Add components here that should be included in the package build. + DasharoModulePkg/UserAuthenticationDxe/UserAuthenticationDxe.inf diff --git a/DasharoModulePkg/LICENSE b/DasharoModulePkg/LICENSE new file mode 100644 index 0000000000..7041a471c1 --- /dev/null +++ b/DasharoModulePkg/LICENSE @@ -0,0 +1,25 @@ +BSD 2-Clause License + +Copyright (c) 2022, Dasharo +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. diff --git a/DasharoModulePkg/Library/DasharoSystemFeaturesUiLib/CpuTopology.c b/DasharoModulePkg/Library/DasharoSystemFeaturesUiLib/CpuTopology.c new file mode 100644 index 0000000000..9e67a80f32 --- /dev/null +++ b/DasharoModulePkg/Library/DasharoSystemFeaturesUiLib/CpuTopology.c @@ -0,0 +1,186 @@ +/** @file +The CPU topology helper functions + +Copyright (c) 2024, 3mdeb Sp. z o.o. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause + +**/ + +#include "DasharoSystemFeatures.h" +#include +#include + +typedef struct { + UINT16 SA_DeviceId; + UINT8 NumPcores; + UINT8 NumEcores; +} SKU_TABLE; + +STATIC CONST SKU_TABLE CpuSkuTable[] = { + // AlderLake CPU Desktop SA Device IDs + { 0x4660, 8, 8 }, // AlderLake Desktop (8+8+GT) SA DID + { 0x4664, 8, 6 }, // AlderLake Desktop (8+6+GT) SA DID + { 0x4668, 8, 4 }, // AlderLake Desktop (8+4+GT) SA DID + { 0x466C, 8, 2 }, // AlderLake Desktop (8+2+GT) SA DID + { 0x4670, 8, 0 }, // AlderLake Desktop (8+0+GT) SA DID + { 0x4640, 6, 8 }, // AlderLake Desktop (6+8+GT) SA DID + { 0x4644, 6, 6 }, // AlderLake Desktop (6+6+GT) SA DID + { 0x4648, 6, 4 }, // AlderLake Desktop (6+4+GT) SA DID + { 0x464C, 6, 2 }, // AlderLake Desktop (6+2+GT) SA DID + { 0x4650, 6, 0 }, // AlderLake Desktop (6+0+GT) SA DID + { 0x4630, 4, 0 }, // AlderLake Desktop (4+0+GT) SA DID + { 0x4610, 2, 0 }, // AlderLake Desktop (2+0+GT) SA DID + { 0x4673, 8, 6 }, // AlderLake Desktop (8+6+GT) SA DID + { 0x4663, 8, 8 }, // AlderLake Desktop BGA (8+8+GT) SA DID + { 0x466B, 8, 4 }, // AlderLake Desktop BGA (8+4+GT) SA DID + { 0x4653, 6, 0 }, // AlderLake Desktop BGA (6+0+GT) SA DID + { 0x4633, 4, 0 }, // AlderLake Desktop BGA (4+0+GT) SA DID + { 0x4637, 8, 8 }, // AlderLake Mobile S BGA (8+8+GT) SA DID + { 0x463B, 6, 8 }, // AlderLake Mobile S BGA (6+8+GT) SA DID + { 0x4623, 4, 8 }, // AlderLake Mobile S BGA (4+8+GT) SA DID + { 0x462B, 4, 4 }, // AlderLake Mobile S BGA (4+4+GT) SA DID + { 0x4647, 6, 4 }, // AlderLake Mobile S BGA (6+4+GT) SA DID + // AlderLake CPU Mobile SA Device IDs + { 0x4641, 6, 8 }, // AlderLake P (6+8+GT) SA DID + { 0x4649, 6, 4 }, // AlderLake P (6+4+GT) SA DID + { 0x4621, 4, 8 }, // AlderLake P (4+8+GT) SA DID + { 0x4609, 2, 4 }, // AlderLake P (2+4+GT) SA DID + { 0x4601, 2, 8 }, // AlderLake P (2+8+GT) SA DID + { 0x4661, 6, 8 }, // AlderLake P (6+8+2) SA DID + { 0x4629, 4, 4 }, // AlderLake P (4+4+1) SA DID + { 0x4619, 1, 4 }, // AlderLake P (1+4+GT) SA DID + { 0x4659, 1, 8 }, // AlderLake P (1+8+GT) SA DID + { 0x4645, 6, 6 }, // AlderLake P (6+6+GT) SA DID + { 0x4602, 2, 8 }, // AlderLake M (2+8+GT) SA DID + { 0x460A, 2, 4 }, // AlderLake M (2+4+GT) SA DID + { 0x461A, 1, 4 }, // AlderLake M (1+4+GT) SA DID + { 0x4622, 1, 8 }, // AlderLake M (1+8+GT) SA DID + { 0x4617, 0, 8 }, // AlderLake N (0+8+1) SA DID + { 0x4614, 0, 2 }, // AlderLake N Celeron (0+2+0) SA DID + { 0x4618, 0, 4 }, // AlderLake N (0+4+0) SA DID + { 0x461B, 0, 4 }, // AlderLake N Pentium (0+4+0) SA DID + { 0x461C, 0, 4 }, // AlderLake N Celeron (0+4+0) SA DID + { 0x4603, 2, 8 }, // AlderLake PS (2+8+GT) SA DID + { 0x4643, 6, 8 }, // AlderLake PS (6+8+GT) SA DID + { 0x4627, 4, 8 }, // AlderLake PS (4+8+GT) SA DID + { 0x460B, 2, 4 }, // AlderLake PS (2+4+GT) SA DID + { 0x464B, 4, 4 }, // AlderLake PS (4+4+GT) SA DID + { 0x467B, 1, 4 }, // AlderLake PS (1+4+GT) SA DID + // RaptorLake CPU Desktop SA Device IDs + { 0xA700, 8, 16 }, // RaptorLake Desktop (8+16+GT) SA DID + { 0xA701, 8, 0 }, // RaptorLake Desktop (8+0+GT) SA DID + { 0xA702, 8, 16 }, // RaptorLake Desktop(BGA) (8+16+GT) SA DID + { 0xA703, 8, 8 }, // RaptorLake Desktop (8+8+GT) SA DID + { 0xA704, 6, 8 }, // RaptorLake Desktop (6+8+GT) SA DID + { 0xA705, 6, 4 }, // RaptorLake Desktop (6+4+GT) SA DID + { 0xA717, 8, 0 }, // RaptorLake Desktop(BGA) (8+0+GT) SA DID + { 0xA718, 8, 4 }, // RaptorLake Desktop(BGA) (8+4+GT) SA DID + { 0xA719, 6, 4 }, // RaptorLake Desktop(BGA) (6+4+GT) SA DID + { 0xA71A, 4, 4 }, // RaptorLake Desktop(BGA) (4+4+GT) SA DID + { 0xA728, 8, 8 }, // RaptorLake Desktop(BGA) (8+8+GT) SA DID + { 0xA729, 8, 12 }, // RaptorLake Desktop(BGA) (8+12+GT) SA DID + { 0xA72A, 6, 8 }, // RaptorLake Desktop(BGA) (6+8+GT) SA DID + { 0xA72B, 4, 0 }, // RaptorLake Desktop (4+0+GT) SA DID + { 0xA740, 8, 12 }, // RaptorLake Desktop (8+12+GT) SA DID + // RaptorLake CPU Mobile SA Device IDs + { 0xA706, 6, 8 }, // RaptorLake P (6+8+GT) SA DID + { 0xA707, 4, 8 }, // RaptorLake P (4+8+GT) SA DID + { 0xA708, 2, 8 }, // RaptorLake P (2+8+GT) SA DID + { 0xA716, 4, 4 }, // RaptorLake P (4+4+GT) SA DID + { 0xA709, 6, 8 }, // RaptorLake Px (6+8+GT) SA DID + { 0xA70A, 4, 8 }, // RaptorLake Px (4+8+GT) SA DID + { 0xA70B, 2, 8 }, // RaptorLake Px (2+8+GT) SA DID + { 0xA715, 6, 4 }, // RaptorLake P (6+4+GT) SA DID + { 0xA71B, 2, 4 }, // RaptorLake P (2+4+GT) SA DID + { 0xA71C, 1, 4 }, // RaptorLake P (1+4+GT) SA DID + { 0xA734, 6, 8 }, // RaptorLake PS (6+8+GT) SA DID + { 0xA735, 4, 8 }, // RaptorLake PS (4+8+GT) SA DID + { 0xA736, 2, 8 }, // RaptorLake PS (2+8+GT) SA DID + { 0xA737, 2, 4 }, // RaptorLake PS (2+4+GT) SA DID + { 0xA738, 6, 4 }, // RaptorLake PS (6+4+GT) SA DID + { 0xA739, 4, 4 }, // RaptorLake PS (4+4+GT) SA DID + { 0xA73A, 1, 4 } // RaptorLake PS (1+4+GT) SA DID +}; + +VOID +GetCpuInfo ( + IN OUT UINT8 *MaxBigCoreCount, + IN OUT UINT8 *MaxSmallCoreCount, + IN OUT BOOLEAN *IsHybrid, + IN OUT BOOLEAN *HyperThreadingSupported + ) +{ + UINT32 MaxCoreCount; + UINT32 Threads; + UINT32 Res; + CPUID_VERSION_INFO_EDX CpuFeaturesEdx; + CPUID_EXTENDED_TOPOLOGY_EBX CpuTopoEbx; + CPUID_EXTENDED_TOPOLOGY_ECX CpuTopoEcx; + UINT32 MaxCpuId; + UINT32 CpuTopologyIndex; + UINT32 BDF0VenIdDevId; + UINT32 Subleaf; + + AsmCpuid (0, &MaxCpuId, NULL, NULL, NULL); + + if (MaxCpuId >= CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS) { + AsmCpuidEx ( + CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS, + CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_SUB_LEAF_INFO, + NULL, NULL, NULL, &Res + ); + *IsHybrid = !!((Res >> 15) & 1); + } else { + *IsHybrid = FALSE; + } + + if (MaxCpuId >= CPUID_VERSION_INFO) { + AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &CpuFeaturesEdx.Uint32); + *HyperThreadingSupported = CpuFeaturesEdx.Bits.HTT; + } else { + *HyperThreadingSupported = FALSE; + } + + BDF0VenIdDevId = PciRead32(PCI_LIB_ADDRESS(0,0,0,0)); + + if ((BDF0VenIdDevId & 0xFFFF) == 0x8086) { + for (UINTN Idx = 0; Idx < ARRAY_SIZE(CpuSkuTable); Idx++) { + if (CpuSkuTable[Idx].SA_DeviceId == ((BDF0VenIdDevId >> 16) & 0xFFFF)) { + *MaxBigCoreCount = CpuSkuTable[Idx].NumPcores; + *MaxSmallCoreCount = CpuSkuTable[Idx].NumEcores; + *IsHybrid = TRUE; + return; + } + } + } + + if (MaxCpuId >= 0x1F) + CpuTopologyIndex = 0x1F; + else if (MaxCpuId >= CPUID_EXTENDED_TOPOLOGY) + CpuTopologyIndex = CPUID_EXTENDED_TOPOLOGY; + else { + // If we cannot probe with CPUID, then return 1. Also assume non-hybrid + // architecture, modern CPUs should support at least CPUID 0xb. That's the + // best we can do. + *MaxBigCoreCount = 1; + *MaxSmallCoreCount = 0; + *IsHybrid = FALSE; + return; + } + + Subleaf = 0; + Threads = 1; + MaxCoreCount = 1; + do { + AsmCpuidEx (CpuTopologyIndex, Subleaf++, NULL, &CpuTopoEbx.Uint32, &CpuTopoEcx.Uint32, NULL); + + if (CpuTopoEcx.Bits.LevelType == CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_SMT) + Threads = (CpuTopoEbx.Bits.LogicalProcessors == 0 ? 1 : CpuTopoEbx.Bits.LogicalProcessors); + else if (CpuTopoEcx.Bits.LevelType == CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_CORE) + MaxCoreCount = (CpuTopoEbx.Bits.LogicalProcessors == 0 ? 1 * Threads : CpuTopoEbx.Bits.LogicalProcessors); + + } while (CpuTopoEcx.Bits.LevelType != CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_INVALID); + + *MaxBigCoreCount = MaxCoreCount / Threads; + *MaxSmallCoreCount = 0; +} diff --git a/DasharoModulePkg/Library/DasharoSystemFeaturesUiLib/DasharoSystemFeatures.c b/DasharoModulePkg/Library/DasharoSystemFeaturesUiLib/DasharoSystemFeatures.c new file mode 100644 index 0000000000..c039d9b181 --- /dev/null +++ b/DasharoModulePkg/Library/DasharoSystemFeaturesUiLib/DasharoSystemFeatures.c @@ -0,0 +1,720 @@ +/** @file +The Dasharo system features reference implementation + +Copyright (c) 2022, 3mdeb Sp. z o.o. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause + +**/ + +#include "DasharoSystemFeatures.h" + +#include + +#define PCH_OC_WDT_CTL 0x54 +#define PCH_OC_WDT_CTL_EN BIT14 +#define PCH_OC_WDT_CTL_TOV_MASK 0x3FF + +#define PRIVATE_DATA(field) mDasharoSystemFeaturesPrivate.DasharoFeaturesData.field + +// Feature state +STATIC CHAR16 mVarStoreName[] = L"FeaturesData"; + +STATIC DASHARO_SYSTEM_FEATURES_PRIVATE_DATA mDasharoSystemFeaturesPrivate = { + DASHARO_SYSTEM_FEATURES_PRIVATE_DATA_SIGNATURE, + NULL, + NULL, + { + DasharoSystemFeaturesExtractConfig, + DasharoSystemFeaturesRouteConfig, + DasharoSystemFeaturesCallback + } +}; + +STATIC HII_VENDOR_DEVICE_PATH mDasharoSystemFeaturesHiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + DASHARO_SYSTEM_FEATURES_GUID + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + +/** + This function uses the ACPI SDT protocol to locate an ACPI table. + It is really only useful for finding tables that only have a single instance, + e.g. FADT, FACS, MADT, etc. It is not good for locating SSDT, etc. + Matches are determined by finding the table with ACPI table that has + a matching signature. + + @param[in] Signature - Pointer to an ASCII string containing the OEM Table ID from the ACPI table header + @param[in, out] Table - Updated with a pointer to the table + @param[in, out] Handle - AcpiSupport protocol table handle for the table found + @param[in, out] Version - The version of the table desired + + @retval EFI_SUCCESS - The function completed successfully. + @retval EFI_NOT_FOUND - Failed to locate AcpiTable. + @retval EFI_NOT_READY - Not ready to locate AcpiTable. +**/ +EFI_STATUS +EFIAPI +LocateAcpiTableBySignature ( + IN UINT32 Signature, + IN OUT EFI_ACPI_DESCRIPTION_HEADER **Table + ) +{ + EFI_STATUS Status; + INTN Index; + EFI_ACPI_TABLE_VERSION Version; + EFI_ACPI_DESCRIPTION_HEADER *OrgTable; + EFI_ACPI_SDT_PROTOCOL *SdtProtocol; + UINTN Handle; + + Status = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (VOID **)&SdtProtocol); + if (EFI_ERROR (Status)) + return Status; + + /// + /// Locate table with matching ID + /// + Version = 0; + Index = 0; + Handle = 0; + do { + Status = SdtProtocol->GetAcpiTable ( + Index, + (EFI_ACPI_SDT_HEADER **)&OrgTable, + &Version, + &Handle + ); + if (Status == EFI_NOT_FOUND) { + break; + } + ASSERT_EFI_ERROR (Status); + Index++; + } while (OrgTable->Signature != Signature); + + if (Status != EFI_NOT_FOUND) { + *Table = AllocateCopyPool (OrgTable->Length, OrgTable); + if (*Table == NULL) + return EFI_OUT_OF_RESOURCES; + } + + /// + /// If we found the table, there will be no error. + /// + return Status; +} + +/** + Install Dasharo System Features Menu driver. + + @param ImageHandle The image handle. + @param SystemTable The system table. + + @retval EFI_SUCEESS Installed Dasharo System Features. + @retval EFI_NOT_SUPPORTED Dasharo System Features not supported. + @retval Other Error. + +**/ +EFI_STATUS +EFIAPI +DasharoSystemFeaturesUiLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable +) +{ + EFI_STATUS Status; + UINTN BufferSize; + + if (!FixedPcdGetBool (PcdShowMenu)) + return EFI_SUCCESS; + + mDasharoSystemFeaturesPrivate.DriverHandle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &mDasharoSystemFeaturesPrivate.DriverHandle, + &gEfiDevicePathProtocolGuid, + &mDasharoSystemFeaturesHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mDasharoSystemFeaturesPrivate.ConfigAccess, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // Publish our HII data. + mDasharoSystemFeaturesPrivate.HiiHandle = HiiAddPackages ( + &gDasharoSystemFeaturesGuid, + mDasharoSystemFeaturesPrivate.DriverHandle, + DasharoSystemFeaturesVfrBin, + DasharoSystemFeaturesUiLibStrings, + NULL + ); + ASSERT (mDasharoSystemFeaturesPrivate.HiiHandle != NULL); + + // Set menu visibility + PRIVATE_DATA(ShowSecurityMenu) = FixedPcdGetBool (PcdShowSecurityMenu); + PRIVATE_DATA(ShowIntelMeMenu) = FixedPcdGetBool (PcdShowIntelMeMenu); + PRIVATE_DATA(ShowUsbMenu) = FixedPcdGetBool (PcdShowUsbMenu); + PRIVATE_DATA(ShowNetworkMenu) = FixedPcdGetBool (PcdShowNetworkMenu); + PRIVATE_DATA(ShowChipsetMenu) = FixedPcdGetBool (PcdShowChipsetMenu); + PRIVATE_DATA(ShowPowerMenu) = FixedPcdGetBool (PcdShowPowerMenu); + PRIVATE_DATA(ShowPciMenu) = FixedPcdGetBool (PcdShowPciMenu); + PRIVATE_DATA(ShowMemoryMenu) = FixedPcdGetBool (PcdShowMemoryMenu); + PRIVATE_DATA(ShowSerialPortMenu) = FixedPcdGetBool (PcdShowSerialPortMenu); + PRIVATE_DATA(ShowCpuMenu) = FixedPcdGetBool (PcdShowCpuMenu); + // Set feature visibility + PRIVATE_DATA(PowerMenuShowFanCurve) = FixedPcdGetBool (PcdPowerMenuShowFanCurve); + PRIVATE_DATA(PowerMenuShowSleepType) = FixedPcdGetBool (PcdPowerMenuShowSleepType); + PRIVATE_DATA(PowerMenuShowBatteryThresholds) = FixedPcdGetBool (PcdPowerMenuShowBatteryThresholds); + PRIVATE_DATA(DasharoEnterprise) = FixedPcdGetBool (PcdDasharoEnterprise); + PRIVATE_DATA(SecurityMenuShowIommu) = FixedPcdGetBool (PcdShowIommuOptions); + PRIVATE_DATA(PciMenuShowResizeableBars) = FixedPcdGetBool (PcdPciMenuShowResizeableBars); + PRIVATE_DATA(ShowSerialPortMenu) = FixedPcdGetBool (PcdShowSerialPortMenu); + PRIVATE_DATA(SecurityMenuShowWiFiBt) = FixedPcdGetBool (PcdSecurityShowWiFiBtOption); + PRIVATE_DATA(SecurityMenuShowCamera) = FixedPcdGetBool (PcdSecurityShowCameraOption); + PRIVATE_DATA(MeHapAvailable) = FixedPcdGetBool (PcdIntelMeHapAvailable); + PRIVATE_DATA(S3SupportExperimental) = FixedPcdGetBool (PcdS3SupportExperimental); + PRIVATE_DATA(ShowLockBios) = FixedPcdGetBool (PcdShowLockBios); + PRIVATE_DATA(ShowSmmBwp) = FixedPcdGetBool (PcdShowSmmBwp); + PRIVATE_DATA(ShowFum) = FixedPcdGetBool (PcdShowFum); + PRIVATE_DATA(ShowPs2Option) = FixedPcdGetBool (PcdShowPs2Option); + PRIVATE_DATA(Have2ndUart) = FixedPcdGetBool (PcdHave2ndUart); + PRIVATE_DATA(ShowCpuThrottlingThreshold) = FixedPcdGetBool (PcdShowCpuThrottlingThreshold); + PRIVATE_DATA(CpuMaxTemperature) = FixedPcdGet8 (PcdCpuMaxTemperature); + PRIVATE_DATA(ShowCpuCoreDisable) = FixedPcdGetBool(PcdShowCpuCoreDisable); + PRIVATE_DATA(ShowCpuHyperThreading) = FixedPcdGetBool(PcdShowCpuHyperThreading); + PRIVATE_DATA(WatchdogAvailable) = FixedPcdGetBool (PcdShowOcWdtOptions); + PRIVATE_DATA(ShowPowerFailureState) = FixedPcdGet8 (PcdDefaultPowerFailureState) != POWER_FAILURE_STATE_HIDDEN; + PRIVATE_DATA(HideFanCurveOff) = !FixedPcdGetBool (PcdPowerMenuShowFanCurveOffOption); + + // Ensure at least one option is visible in given menu (if enabled), otherwise hide it + if (PRIVATE_DATA(ShowSecurityMenu)) + PRIVATE_DATA(ShowSecurityMenu) = FixedPcdGetBool (PcdDasharoEnterprise) || + FixedPcdGetBool (PcdShowIommuOptions) || + FixedPcdGetBool (PcdSecurityShowWiFiBtOption) || + FixedPcdGetBool (PcdSecurityShowCameraOption) || + FixedPcdGetBool (PcdShowLockBios) || + FixedPcdGetBool (PcdShowSmmBwp) || + FixedPcdGetBool (PcdShowFum); + + if (PRIVATE_DATA(ShowChipsetMenu)) + PRIVATE_DATA(ShowChipsetMenu) = FixedPcdGetBool (PcdShowOcWdtOptions) || + FixedPcdGetBool (PcdShowPs2Option); + + if (PRIVATE_DATA(ShowPowerMenu)) + PRIVATE_DATA(ShowPowerMenu) = FixedPcdGetBool (PcdPowerMenuShowFanCurve) || + FixedPcdGetBool (PcdPowerMenuShowSleepType) || + FixedPcdGetBool (PcdPowerMenuShowBatteryThresholds) || + FixedPcdGetBool (PcdShowCpuThrottlingThreshold) || + (FixedPcdGet8 (PcdDefaultPowerFailureState) != POWER_FAILURE_STATE_HIDDEN); + + if (PRIVATE_DATA(ShowCpuMenu)) + PRIVATE_DATA(ShowCpuMenu) = FixedPcdGetBool(PcdShowCpuCoreDisable) || + FixedPcdGetBool(PcdShowCpuHyperThreading); + + GetCpuInfo(&PRIVATE_DATA(BigCoreMaxCount), + &PRIVATE_DATA(SmallCoreMaxCount), + &PRIVATE_DATA(HybridCpuArchitecture), + &PRIVATE_DATA(HyperThreadingSupported)); + + if (!PRIVATE_DATA(HybridCpuArchitecture)) + PRIVATE_DATA(CoreMaxCount) = PRIVATE_DATA(BigCoreMaxCount); + +#define LOAD_VAR(var, field) do { \ + BufferSize = sizeof (PRIVATE_DATA(field)); \ + Status = gRT->GetVariable ( \ + (var), \ + &gDasharoSystemFeaturesGuid, \ + NULL, \ + &BufferSize, \ + &PRIVATE_DATA(field) \ + ); \ + if (EFI_ERROR (Status)) \ + PRIVATE_DATA(field) = _Generic(PRIVATE_DATA(field), \ + UINT8: DasharoGetVariableDefault(var).Uint8, \ + DASHARO_WATCHDOG_CONFIG: DasharoGetVariableDefault(var).Watchdog, \ + DASHARO_IOMMU_CONFIG: DasharoGetVariableDefault(var).Iommu, \ + DASHARO_BATTERY_CONFIG: DasharoGetVariableDefault(var).Battery \ + ); \ + } while (FALSE) + + LOAD_VAR (DASHARO_VAR_BATTERY_CONFIG, BatteryConfig); + LOAD_VAR (DASHARO_VAR_BOOT_MANAGER_ENABLED, BootManagerEnabled); + LOAD_VAR (DASHARO_VAR_CPU_THROTTLING_OFFSET, CpuThrottlingOffset); + LOAD_VAR (DASHARO_VAR_ENABLE_CAMERA, EnableCamera); + LOAD_VAR (DASHARO_VAR_ENABLE_WIFI_BT, EnableWifiBt); + LOAD_VAR (DASHARO_VAR_FAN_CURVE_OPTION, FanCurveOption); + LOAD_VAR (DASHARO_VAR_IOMMU_CONFIG, IommuConfig); + LOAD_VAR (DASHARO_VAR_LOCK_BIOS, LockBios); + LOAD_VAR (DASHARO_VAR_MEMORY_PROFILE, MemoryProfile); + LOAD_VAR (DASHARO_VAR_ME_MODE, MeMode); + LOAD_VAR (DASHARO_VAR_NETWORK_BOOT, NetworkBoot); + LOAD_VAR (DASHARO_VAR_OPTION_ROM_POLICY, OptionRomExecution); + LOAD_VAR (DASHARO_VAR_POWER_FAILURE_STATE, PowerFailureState); + LOAD_VAR (DASHARO_VAR_PS2_CONTROLLER, Ps2Controller); + LOAD_VAR (DASHARO_VAR_RESIZEABLE_BARS_ENABLED, ResizeableBarsEnabled); + LOAD_VAR (DASHARO_VAR_SERIAL_REDIRECTION, SerialPortRedirection); + LOAD_VAR (DASHARO_VAR_SERIAL_REDIRECTION2, SerialPort2Redirection); + LOAD_VAR (DASHARO_VAR_SLEEP_TYPE, SleepType); + LOAD_VAR (DASHARO_VAR_SMM_BWP, SmmBwp); + LOAD_VAR (DASHARO_VAR_USB_MASS_STORAGE, UsbMassStorage); + LOAD_VAR (DASHARO_VAR_USB_STACK, UsbStack); + LOAD_VAR (DASHARO_VAR_WATCHDOG, WatchdogConfig); + LOAD_VAR (DASHARO_VAR_SMALL_CORE_ACTIVE_COUNT, SmallCoreActiveCount); + LOAD_VAR (DASHARO_VAR_CORE_ACTIVE_COUNT, BigCoreActiveCount); + LOAD_VAR (DASHARO_VAR_CORE_ACTIVE_COUNT, CoreActiveCount); + LOAD_VAR (DASHARO_VAR_HYPER_THREADING, HyperThreading); + +#undef LOAD_VAR + + PRIVATE_DATA(CpuThrottlingThreshold) = + PRIVATE_DATA(CpuMaxTemperature) - PRIVATE_DATA(CpuThrottlingOffset); + + if (PRIVATE_DATA(HybridCpuArchitecture) && + PRIVATE_DATA(SmallCoreActiveCount) == 0 && + PRIVATE_DATA(BigCoreActiveCount) == 0) { + /* + * Invalid setting, which causes a brick, enable all cores. coreboot will + * not allow to disable all cores and revert to default: enabling all + * cores. Match the behavior here, so the variables are not stuck in this + * state and showing variable state not matching the reality. + */ + PRIVATE_DATA(SmallCoreActiveCount) = DASHARO_CPU_CORES_ENABLE_ALL; + PRIVATE_DATA(BigCoreActiveCount) = DASHARO_CPU_CORES_ENABLE_ALL; + + if (FixedPcdGetBool(PcdShowCpuCoreDisable)) { + gRT->SetVariable ( + DASHARO_VAR_SMALL_CORE_ACTIVE_COUNT, + &gDasharoSystemFeaturesGuid, + DasharoGetVariableAttributes (DASHARO_VAR_SMALL_CORE_ACTIVE_COUNT), + sizeof (PRIVATE_DATA(SmallCoreActiveCount)), + &PRIVATE_DATA(SmallCoreActiveCount) + ); + gRT->SetVariable ( + DASHARO_VAR_CORE_ACTIVE_COUNT, + &gDasharoSystemFeaturesGuid, + DasharoGetVariableAttributes (DASHARO_VAR_CORE_ACTIVE_COUNT), + sizeof (PRIVATE_DATA(BigCoreActiveCount)), + &PRIVATE_DATA(BigCoreActiveCount) + ); + } + } + + return EFI_SUCCESS; +} + +/** + Unloads the application and its installed protocol. + + @param ImageHandle Handle that identifies the image to be unloaded. + @param SystemTable The system table. + + @retval EFI_SUCCESS The image has been unloaded. +**/ +EFI_STATUS +EFIAPI +DasharoSystemFeaturesUiLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable +) +{ + EFI_STATUS Status; + + Status = gBS->UninstallMultipleProtocolInterfaces ( + mDasharoSystemFeaturesPrivate.DriverHandle, + &gEfiDevicePathProtocolGuid, + &mDasharoSystemFeaturesHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mDasharoSystemFeaturesPrivate.ConfigAccess, + NULL + ); + ASSERT_EFI_ERROR (Status); + + HiiRemovePackages (mDasharoSystemFeaturesPrivate.HiiHandle); + + return EFI_SUCCESS; +} + +/** + This function allows a caller to extract the current configuration for one + or more named elements from the target driver. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Request A null-terminated Unicode string in format. + @param Progress On return, points to a character in the Request string. + Points to the string's null terminator if request was successful. + Points to the most recent '&' before the first failing name/value + pair (or the beginning of the string if the failure is in the + first name/value pair) if the request was not successful. + @param Results A null-terminated Unicode string in format which + has all values filled in for the names in the Request string. + String to be allocated by the called function. + + @retval EFI_SUCCESS The Results is filled with the requested values. + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. + @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. + +**/ +EFI_STATUS +EFIAPI +DasharoSystemFeaturesExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results + ) +{ + EFI_STATUS Status; + DASHARO_SYSTEM_FEATURES_PRIVATE_DATA *Private; + UINTN BufferSize; + EFI_STRING ConfigRequestHdr; + EFI_STRING ConfigRequest; + UINTN Size; + + if (Progress == NULL || Results == NULL) { + return EFI_INVALID_PARAMETER; + } + + *Progress = Request; + if (Request != NULL && + !HiiIsConfigHdrMatch (Request, &gDasharoSystemFeaturesGuid, mVarStoreName)) { + return EFI_NOT_FOUND; + } + + Private = DASHARO_SYSTEM_FEATURES_PRIVATE_DATA_FROM_THIS (This); + + BufferSize = sizeof (DASHARO_FEATURES_DATA); + ConfigRequest = Request; + if (Request == NULL || (StrStr (Request, L"OFFSET") == NULL)) { + // Request has no request element, construct full request string. + // Allocate and fill a buffer large enough to hold the template + // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator. + ConfigRequestHdr = HiiConstructConfigHdr ( + &gDasharoSystemFeaturesGuid, + mVarStoreName, + Private->DriverHandle + ); + Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16); + ConfigRequest = AllocateZeroPool (Size); + ASSERT (ConfigRequest != NULL); + UnicodeSPrint ( + ConfigRequest, + Size, + L"%s&OFFSET=0&WIDTH=%016LX", + ConfigRequestHdr, + (UINT64) BufferSize + ); + FreePool (ConfigRequestHdr); + } + + // Convert fields of binary structure to string representation. + Status = gHiiConfigRouting->BlockToConfig ( + gHiiConfigRouting, + ConfigRequest, + (CONST UINT8 *) &Private->DasharoFeaturesData, + BufferSize, + Results, + Progress + ); + ASSERT_EFI_ERROR (Status); + + // Free config request string if it was allocated. + if (ConfigRequest != Request) { + FreePool (ConfigRequest); + } + + if (Request != NULL && StrStr (Request, L"OFFSET") == NULL) { + *Progress = Request + StrLen (Request); + } + + return Status; +} + +/** + This function processes the results of changes in configuration. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Configuration A null-terminated Unicode string in format. + @param Progress A pointer to a string filled in with the offset of the most + recent '&' before the first failing name/value pair (or the + beginning of the string if the failure is in the first + name/value pair) or the terminating NULL if all was successful. + + @retval EFI_SUCCESS The Results is processed successfully. + @retval EFI_INVALID_PARAMETER Configuration is NULL. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. + +**/ +EFI_STATUS +EFIAPI +DasharoSystemFeaturesRouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + DASHARO_SYSTEM_FEATURES_PRIVATE_DATA *Private; + DASHARO_FEATURES_DATA DasharoFeaturesData; + DASHARO_FEATURES_DATA *PrivateData; + + if (Progress == NULL) { + return EFI_INVALID_PARAMETER; + } + + *Progress = Configuration; + if (Configuration == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (!HiiIsConfigHdrMatch (Configuration, &gDasharoSystemFeaturesGuid, mVarStoreName)) { + return EFI_NOT_FOUND; + } + + Private = DASHARO_SYSTEM_FEATURES_PRIVATE_DATA_FROM_THIS (This); + PrivateData = &Private->DasharoFeaturesData; + + // Construct data structure from configuration string. + BufferSize = sizeof (DasharoFeaturesData); + Status = gHiiConfigRouting->ConfigToBlock ( + gHiiConfigRouting, + Configuration, + (UINT8 *) &DasharoFeaturesData, + &BufferSize, + Progress + ); + ASSERT_EFI_ERROR (Status); + + if (PrivateData->HybridCpuArchitecture && FixedPcdGetBool (PcdShowCpuCoreDisable)) { + if (DasharoFeaturesData.SmallCoreActiveCount == 0 && PrivateData->BigCoreMaxCount == 0) + return EFI_INVALID_PARAMETER; + + if (DasharoFeaturesData.BigCoreActiveCount == 0 && PrivateData->SmallCoreMaxCount == 0) + return EFI_INVALID_PARAMETER; + } + + // Can use CompareMem() on structures instead of a per-field comparison as + // long as they are packed. +#define STORE_VAR_IF(var, field, cond) do { \ + if (cond) { \ + if (CompareMem (&Private->DasharoFeaturesData.field, \ + &DasharoFeaturesData.field, \ + sizeof (DasharoFeaturesData.field)) != 0) { \ + Status = gRT->SetVariable ( \ + (var), \ + &gDasharoSystemFeaturesGuid, \ + DasharoGetVariableAttributes (var), \ + sizeof (DasharoFeaturesData.field), \ + &DasharoFeaturesData.field \ + ); \ + if (EFI_ERROR (Status)) { \ + return Status; \ + } \ + } \ + } \ + } while (FALSE) + + if (FixedPcdGetBool (PcdShowSecurityMenu)) { + STORE_VAR_IF (DASHARO_VAR_BOOT_MANAGER_ENABLED, BootManagerEnabled, FixedPcdGetBool (PcdDasharoEnterprise)); + STORE_VAR_IF (DASHARO_VAR_ENABLE_CAMERA, EnableCamera, FixedPcdGetBool (PcdSecurityShowCameraOption)); + STORE_VAR_IF (DASHARO_VAR_ENABLE_WIFI_BT, EnableWifiBt, FixedPcdGetBool (PcdSecurityShowWiFiBtOption)); + STORE_VAR_IF (DASHARO_VAR_IOMMU_CONFIG, IommuConfig, FixedPcdGetBool (PcdShowIommuOptions)); + STORE_VAR_IF (DASHARO_VAR_LOCK_BIOS, LockBios, FixedPcdGetBool (PcdShowLockBios)); + STORE_VAR_IF (DASHARO_VAR_SMM_BWP, SmmBwp, FixedPcdGetBool (PcdShowSmmBwp)); + } + + STORE_VAR_IF (DASHARO_VAR_MEMORY_PROFILE, MemoryProfile, FixedPcdGetBool (PcdShowMemoryMenu)); + STORE_VAR_IF (DASHARO_VAR_ME_MODE, MeMode, FixedPcdGetBool (PcdShowIntelMeMenu)); + STORE_VAR_IF (DASHARO_VAR_NETWORK_BOOT, NetworkBoot, FixedPcdGetBool (PcdShowNetworkMenu)); + + if (FixedPcdGetBool (PcdShowPowerMenu)) { + STORE_VAR_IF (DASHARO_VAR_SLEEP_TYPE, SleepType, FixedPcdGetBool (PcdPowerMenuShowSleepType)); + STORE_VAR_IF (DASHARO_VAR_POWER_FAILURE_STATE, PowerFailureState, + FixedPcdGet8 (PcdDefaultPowerFailureState) != POWER_FAILURE_STATE_HIDDEN); + STORE_VAR_IF (DASHARO_VAR_FAN_CURVE_OPTION, FanCurveOption, FixedPcdGetBool (PcdPowerMenuShowFanCurve)); + STORE_VAR_IF (DASHARO_VAR_BATTERY_CONFIG, BatteryConfig, FixedPcdGetBool (PcdPowerMenuShowBatteryThresholds)); + STORE_VAR_IF (DASHARO_VAR_CPU_THROTTLING_OFFSET, CpuThrottlingOffset, FixedPcdGetBool (PcdShowCpuThrottlingThreshold)); + } + + if (FixedPcdGetBool (PcdShowPciMenu)) { + STORE_VAR_IF (DASHARO_VAR_OPTION_ROM_POLICY, OptionRomExecution, TRUE); + STORE_VAR_IF (DASHARO_VAR_RESIZEABLE_BARS_ENABLED, ResizeableBarsEnabled, FixedPcdGetBool (PcdPciMenuShowResizeableBars)); + } + + if (FixedPcdGetBool (PcdShowSerialPortMenu)) { + STORE_VAR_IF (DASHARO_VAR_SERIAL_REDIRECTION, SerialPortRedirection, TRUE); + STORE_VAR_IF (DASHARO_VAR_SERIAL_REDIRECTION2, SerialPort2Redirection, FixedPcdGetBool (PcdHave2ndUart)); + } + + if (FixedPcdGetBool (PcdShowUsbMenu)) { + STORE_VAR_IF (DASHARO_VAR_USB_MASS_STORAGE, UsbMassStorage, TRUE); + STORE_VAR_IF (DASHARO_VAR_USB_STACK, UsbStack, TRUE); + } + + if (FixedPcdGetBool (PcdShowChipsetMenu)) { + STORE_VAR_IF (DASHARO_VAR_WATCHDOG, WatchdogConfig, FixedPcdGetBool (PcdShowOcWdtOptions)); + STORE_VAR_IF (DASHARO_VAR_PS2_CONTROLLER, Ps2Controller, FixedPcdGetBool (PcdShowPs2Option)); + } + + if (FixedPcdGetBool (PcdShowCpuMenu)) { + STORE_VAR_IF (DASHARO_VAR_HYPER_THREADING, HyperThreading, FixedPcdGetBool (PcdShowCpuHyperThreading)); + + if (PrivateData->HybridCpuArchitecture) { + STORE_VAR_IF (DASHARO_VAR_SMALL_CORE_ACTIVE_COUNT, SmallCoreActiveCount, FixedPcdGetBool (PcdShowCpuCoreDisable)); + STORE_VAR_IF (DASHARO_VAR_CORE_ACTIVE_COUNT, BigCoreActiveCount, FixedPcdGetBool (PcdShowCpuCoreDisable)); + } else { + // CoreActiveCount used for P-cores and non-hybrid CPU architectures to match FSP + STORE_VAR_IF (DASHARO_VAR_CORE_ACTIVE_COUNT, CoreActiveCount, FixedPcdGetBool (PcdShowCpuCoreDisable)); + } + + } + +#undef STORE_VAR + + Private->DasharoFeaturesData = DasharoFeaturesData; + return EFI_SUCCESS; +} + +/** + This function is invoked if user selected a interactive opcode from Device Manager's + Formset. If user toggles bios lock, the new value is saved to EFI variable. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original exporting driver + so that it can identify the type of data to expect. + @param Type The type of value for the question. + @param Value A pointer to the data being sent to the original exporting driver. + @param ActionRequest On return, points to the action requested by the callback function. + + @retval EFI_SUCCESS The callback successfully handled the action. + @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters. + +**/ +EFI_STATUS +EFIAPI +DasharoSystemFeaturesCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) +{ + EFI_STATUS Status; + EFI_INPUT_KEY Key; + + Status = EFI_SUCCESS; + + switch (Action) { + case EFI_BROWSER_ACTION_DEFAULT_STANDARD: + case EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING: + { + if (Value == NULL) + return EFI_INVALID_PARAMETER; + + switch (QuestionId) { + case NETWORK_BOOT_QUESTION_ID: + Value->b = DasharoGetVariableDefault (DASHARO_VAR_NETWORK_BOOT).Boolean; + break; + case WATCHDOG_ENABLE_QUESTION_ID: + Value->b = DasharoGetVariableDefault (DASHARO_VAR_WATCHDOG).Watchdog.WatchdogEnable; + break; + case WATCHDOG_TIMEOUT_QUESTION_ID: + Value->u16 = DasharoGetVariableDefault (DASHARO_VAR_WATCHDOG).Watchdog.WatchdogTimeout; + break; + case POWER_FAILURE_STATE_QUESTION_ID: + Value->u8 = DasharoGetVariableDefault (DASHARO_VAR_POWER_FAILURE_STATE).Boolean; + break; + case OPTION_ROM_STATE_QUESTION_ID: + Value->u8 = DasharoGetVariableDefault (DASHARO_VAR_OPTION_ROM_POLICY).Uint8; + break; + case SERIAL_PORT_REDIR_QUESTION_ID: + Value->u8 = DasharoGetVariableDefault (DASHARO_VAR_SERIAL_REDIRECTION).Boolean; + break; + case SERIAL_PORT2_REDIR_QUESTION_ID: + Value->b = DasharoGetVariableDefault (DASHARO_VAR_SERIAL_REDIRECTION2).Boolean; + break; + case BATTERY_START_THRESHOLD_QUESTION_ID: + Value->u8 = DasharoGetVariableDefault (DASHARO_VAR_BATTERY_CONFIG).Battery.StartThreshold; + break; + case BATTERY_STOP_THRESHOLD_QUESTION_ID: + Value->u8 = DasharoGetVariableDefault (DASHARO_VAR_BATTERY_CONFIG).Battery.StopThreshold; + break; + case INTEL_ME_MODE_QUESTION_ID: + Value->u8 = DasharoGetVariableDefault (DASHARO_VAR_ME_MODE).Uint8; + break; + case SLEEP_TYPE_QUESTION_ID: + Value->u8 = DasharoGetVariableDefault (DASHARO_VAR_SLEEP_TYPE).Uint8; + break; + case HYPER_THREADING_QUESTION_ID: + Value->b = DasharoGetVariableDefault (DASHARO_VAR_HYPER_THREADING).Boolean; + break; + case CPU_THROTTLING_OFFSET_QUESTION_ID: + Value->u8 = DasharoGetVariableDefault (DASHARO_VAR_CPU_THROTTLING_OFFSET).Uint8; + break; + default: + Status = EFI_UNSUPPORTED; + break; + } + break; + } + case EFI_BROWSER_ACTION_CHANGED: + { + if (QuestionId == FIRMWARE_UPDATE_MODE_QUESTION_ID) { + if (!FixedPcdGetBool(PcdShowFum)) + return EFI_UNSUPPORTED; + + do { + CreatePopUp ( + EFI_BLACK | EFI_BACKGROUND_RED, + &Key, + L"", + L"You are about to enable Firmware Update Mode.", + L"This will turn off all flash protection mechanisms", + L"for the duration of the next boot.", + L"", + L"DTS will be started automatically through iPXE, please", + L"make sure an Ethernet cable is connected before continuing.", + L"", + L"Press ENTER to continue and reboot or ESC to cancel...", + L"", + NULL + ); + } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN)); + + if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) { + Status = DasharoEnableFUM (); + if (EFI_ERROR (Status)) { + return Status; + } + gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); + } + } else { + Status = EFI_UNSUPPORTED; + } + } + break; + default: + Status = EFI_UNSUPPORTED; + break; + } + + return Status; +} diff --git a/DasharoModulePkg/Library/DasharoSystemFeaturesUiLib/DasharoSystemFeatures.h b/DasharoModulePkg/Library/DasharoSystemFeaturesUiLib/DasharoSystemFeatures.h new file mode 100644 index 0000000000..74db4ea934 --- /dev/null +++ b/DasharoModulePkg/Library/DasharoSystemFeaturesUiLib/DasharoSystemFeatures.h @@ -0,0 +1,169 @@ +/** @file +The Dasharo system features implementation + +Copyright (c) 2022, 3mdeb Sp. z o.o. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause + +**/ + +#ifndef _DASHARO_SYSTEM_FEATURES_H_ +#define _DASHARO_SYSTEM_FEATURES_H_ + +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "DasharoSystemFeaturesHii.h" + +// +// These are the VFR compiler generated data representing our VFR data. +// +extern UINT8 DasharoSystemFeaturesVfrBin[]; + +#define DASHARO_SYSTEM_FEATURES_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('D', 'S', 'F', 'p') + +/// +/// HII specific Vendor Device Path definition. +/// +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + EFI_DEVICE_PATH_PROTOCOL End; +} HII_VENDOR_DEVICE_PATH; + +typedef struct { + UINTN Signature; + + /// + /// Device Manager HII relative handles + /// + EFI_HII_HANDLE HiiHandle; + + EFI_HANDLE DriverHandle; + + /// + /// Produced protocols + /// + EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess; + + /// + /// Configuration data + /// + DASHARO_FEATURES_DATA DasharoFeaturesData; +} DASHARO_SYSTEM_FEATURES_PRIVATE_DATA; + +#define DASHARO_SYSTEM_FEATURES_PRIVATE_DATA_FROM_THIS(a) \ + CR (a, \ + DASHARO_SYSTEM_FEATURES_PRIVATE_DATA, \ + ConfigAccess, \ + DASHARO_SYSTEM_FEATURES_PRIVATE_DATA_SIGNATURE \ + ) + +/** + This function allows a caller to extract the current configuration for one + or more named elements from the target driver. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Request A null-terminated Unicode string in format. + @param Progress On return, points to a character in the Request string. + Points to the string's null terminator if request was successful. + Points to the most recent '&' before the first failing name/value + pair (or the beginning of the string if the failure is in the + first name/value pair) if the request was not successful. + @param Results A null-terminated Unicode string in format which + has all values filled in for the names in the Request string. + String to be allocated by the called function. + + @retval EFI_SUCCESS The Results is filled with the requested values. + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. + @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. + +**/ +EFI_STATUS +EFIAPI +DasharoSystemFeaturesExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results + ); + +/** + This function processes the results of changes in configuration. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Configuration A null-terminated Unicode string in format. + @param Progress A pointer to a string filled in with the offset of the most + recent '&' before the first failing name/value pair (or the + beginning of the string if the failure is in the first + name/value pair) or the terminating NULL if all was successful. + + @retval EFI_SUCCESS The Results is processed successfully. + @retval EFI_INVALID_PARAMETER Configuration is NULL. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. + +**/ +EFI_STATUS +EFIAPI +DasharoSystemFeaturesRouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress + ); + +/** + This function is invoked if user selected a interactive opcode from Dasharo System Features' + Formset. If user set VBIOS, the new value is saved to EFI variable. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original exporting driver + so that it can identify the type of data to expect. + @param Type The type of value for the question. + @param Value A pointer to the data being sent to the original exporting driver. + @param ActionRequest On return, points to the action requested by the callback function. + + @retval EFI_SUCCESS The callback successfully handled the action. + @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters. + +**/ +EFI_STATUS +EFIAPI +DasharoSystemFeaturesCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ); + +VOID +GetCpuInfo ( + IN OUT UINT8 *MaxBigCoreCount, + IN OUT UINT8 *MaxSmallCoreCount, + IN OUT BOOLEAN *IsHybrid, + IN OUT BOOLEAN *HyperThreadingSupported + ); + +#endif diff --git a/DasharoModulePkg/Library/DasharoSystemFeaturesUiLib/DasharoSystemFeaturesHii.h b/DasharoModulePkg/Library/DasharoSystemFeaturesUiLib/DasharoSystemFeaturesHii.h new file mode 100644 index 0000000000..4c4905bd52 --- /dev/null +++ b/DasharoModulePkg/Library/DasharoSystemFeaturesUiLib/DasharoSystemFeaturesHii.h @@ -0,0 +1,156 @@ +/** @file +The Dasharo system features implementation + +Copyright (c) 2022, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause + +**/ + +#ifndef _DASHARO_SYSTEM_FEATURES_HII_H_ +#define _DASHARO_SYSTEM_FEATURES_HII_H_ + +#include + +#define DASHARO_SYSTEM_FEATURES_GUID \ + { 0xd15b327e, 0xff2d, 0x4fc1, {0xab, 0xf6, 0xc1, 0x2b, 0xd0, 0x8c, 0x13, 0x59} } + +#define DASHARO_SYSTEM_FEATURES_FORM_ID 0x1000 +#define DASHARO_SECURITY_OPTIONS_FORM_ID 0x1001 +#define DASHARO_NETWORK_OPTIONS_FORM_ID 0x1002 +#define DASHARO_USB_CONFIGURATION_FORM_ID 0x1003 +#define DASHARO_INTEL_ME_OPTIONS_FORM_ID 0x1004 +#define DASHARO_CHIPSET_CONFIGURATION_FORM_ID 0x1005 +#define DASHARO_POWER_CONFIGURATION_FORM_ID 0x1006 +#define DASHARO_PCI_CONFIGURATION_FORM_ID 0x1007 +#define DASHARO_MEMORY_CONFIGURATION_FORM_ID 0x1008 +#define DASHARO_SERIAL_PORT_CONFIGURATION_FORM_ID 0x1009 +#define DASHARO_CPU_CONFIGURATION_FORM_ID 0x100a + +#define DASHARO_FEATURES_DATA_VARSTORE_ID 0x0001 + +typedef struct { + // Feature visibility + BOOLEAN ShowSecurityMenu; + BOOLEAN ShowIntelMeMenu; + BOOLEAN ShowUsbMenu; + BOOLEAN ShowNetworkMenu; + BOOLEAN ShowChipsetMenu; + BOOLEAN ShowPowerMenu; + BOOLEAN ShowPciMenu; + BOOLEAN ShowMemoryMenu; + BOOLEAN ShowSerialPortMenu; + BOOLEAN ShowCpuMenu; + BOOLEAN ShowLockBios; + BOOLEAN ShowSmmBwp; + BOOLEAN ShowFum; + BOOLEAN ShowPs2Option; + BOOLEAN PowerMenuShowFanCurve; + BOOLEAN PowerMenuShowSleepType; + BOOLEAN PowerMenuShowBatteryThresholds; + BOOLEAN DasharoEnterprise; + BOOLEAN SecurityMenuShowIommu; + BOOLEAN PciMenuShowResizeableBars; + BOOLEAN SecurityMenuShowWiFiBt; + BOOLEAN SecurityMenuShowCamera; + BOOLEAN MeHapAvailable; + BOOLEAN S3SupportExperimental; + BOOLEAN Have2ndUart; + BOOLEAN ShowCpuThrottlingThreshold; + BOOLEAN ShowCpuCoreDisable; + BOOLEAN ShowCpuHyperThreading; + BOOLEAN ShowPowerFailureState; + BOOLEAN HideFanCurveOff; + // Feature data + BOOLEAN LockBios; + BOOLEAN SmmBwp; + BOOLEAN NetworkBoot; + BOOLEAN UsbStack; + BOOLEAN UsbMassStorage; + UINT8 MeMode; + BOOLEAN Ps2Controller; + DASHARO_WATCHDOG_CONFIG WatchdogConfig; + BOOLEAN WatchdogAvailable; + UINT8 FanCurveOption; + DASHARO_IOMMU_CONFIG IommuConfig; + BOOLEAN BootManagerEnabled; + UINT8 SleepType; + UINT8 PowerFailureState; + BOOLEAN ResizeableBarsEnabled; + UINT8 OptionRomExecution; + BOOLEAN EnableCamera; + BOOLEAN EnableWifiBt; + DASHARO_BATTERY_CONFIG BatteryConfig; + UINT8 MemoryProfile; + BOOLEAN SerialPortRedirection; + BOOLEAN SerialPort2Redirection; + UINT8 CpuThrottlingThreshold; + UINT8 CpuThrottlingOffset; + UINT8 CpuMaxTemperature; + BOOLEAN HybridCpuArchitecture; + BOOLEAN HyperThreadingSupported; + BOOLEAN HyperThreading; + UINT8 BigCoreActiveCount; + UINT8 BigCoreMaxCount; + UINT8 SmallCoreActiveCount; + UINT8 SmallCoreMaxCount; + UINT8 CoreActiveCount; + UINT8 CoreMaxCount; +} DASHARO_FEATURES_DATA; + +// +// DasharoOptions.h can be included by files unrelated to Dasharo in which case +// it's useful to indicate where they came from. +// +// HII code, however, is already specific to Dasharo and there is no need to +// have extra 8 characters here. +// + +#define FAN_CURVE_OPTION_SILENT DASHARO_FAN_CURVE_OPTION_SILENT +#define FAN_CURVE_OPTION_PERFORMANCE DASHARO_FAN_CURVE_OPTION_PERFORMANCE +#define FAN_CURVE_OPTION_OFF DASHARO_FAN_CURVE_OPTION_OFF + +#define ME_MODE_ENABLE DASHARO_ME_MODE_ENABLE +#define ME_MODE_DISABLE_HECI DASHARO_ME_MODE_DISABLE_HECI +#define ME_MODE_DISABLE_HAP DASHARO_ME_MODE_DISABLE_HAP + +#define OPTION_ROM_POLICY_DISABLE_ALL DASHARO_OPTION_ROM_POLICY_DISABLE_ALL +#define OPTION_ROM_POLICY_ENABLE_ALL DASHARO_OPTION_ROM_POLICY_ENABLE_ALL +#define OPTION_ROM_POLICY_VGA_ONLY DASHARO_OPTION_ROM_POLICY_VGA_ONLY + +#define SLEEP_TYPE_S0IX DASHARO_SLEEP_TYPE_S0IX +#define SLEEP_TYPE_S3 DASHARO_SLEEP_TYPE_S3 + +#define POWER_FAILURE_STATE_OFF DASHARO_POWER_FAILURE_STATE_OFF +#define POWER_FAILURE_STATE_ON DASHARO_POWER_FAILURE_STATE_ON +#define POWER_FAILURE_STATE_KEEP DASHARO_POWER_FAILURE_STATE_KEEP +#define POWER_FAILURE_STATE_HIDDEN DASHARO_POWER_FAILURE_STATE_HIDDEN + +#define MEMORY_PROFILE_JEDEC DASHARO_MEMORY_PROFILE_JEDEC +#define MEMORY_PROFILE_XMP1 DASHARO_MEMORY_PROFILE_XMP1 +#define MEMORY_PROFILE_XMP2 DASHARO_MEMORY_PROFILE_XMP2 +#define MEMORY_PROFILE_XMP3 DASHARO_MEMORY_PROFILE_XMP3 + +#define CPU_CORES_ENABLE_ALL DASHARO_CPU_CORES_ENABLE_ALL + +// +// Question IDs are used in VFR file to let the code in +// DasharoSystemFeaturesCallback() know what form element caused +// invocation of the callback. +// + +#define NETWORK_BOOT_QUESTION_ID 0x8000 +#define WATCHDOG_ENABLE_QUESTION_ID 0x8001 +#define WATCHDOG_TIMEOUT_QUESTION_ID 0x8002 +#define FIRMWARE_UPDATE_MODE_QUESTION_ID 0x8003 +#define POWER_FAILURE_STATE_QUESTION_ID 0x8004 +#define OPTION_ROM_STATE_QUESTION_ID 0x8005 +#define SERIAL_PORT_REDIR_QUESTION_ID 0x8006 +#define BATTERY_START_THRESHOLD_QUESTION_ID 0x8007 +#define BATTERY_STOP_THRESHOLD_QUESTION_ID 0x8008 +#define INTEL_ME_MODE_QUESTION_ID 0x8009 +#define SLEEP_TYPE_QUESTION_ID 0x800A +#define SERIAL_PORT2_REDIR_QUESTION_ID 0x800B +#define HYPER_THREADING_QUESTION_ID 0x800C +#define CPU_THROTTLING_OFFSET_QUESTION_ID 0x800D + +#endif diff --git a/DasharoModulePkg/Library/DasharoSystemFeaturesUiLib/DasharoSystemFeaturesStrings.uni b/DasharoModulePkg/Library/DasharoSystemFeaturesUiLib/DasharoSystemFeaturesStrings.uni new file mode 100644 index 0000000000..0704e2d626 --- /dev/null +++ b/DasharoModulePkg/Library/DasharoSystemFeaturesUiLib/DasharoSystemFeaturesStrings.uni @@ -0,0 +1,221 @@ +///** @file +// +// String definitions for the Dasharo System Features. +// +// Copyright (c) 2022, 3mdeb Sp. z o.o. All rights reserved.
+// SPDX-License-Identifier: BSD-2-Clause +// +//**/ + +/=# + +#langdef en-US "English" + +#string STR_EMPTY_STRING #language en-US "" +#string STR_EXIT_STRING #language en-US "Press ESC to exit." + +#string STR_EDKII_MENU_TITLE #language en-US "Dasharo System Features" +#string STR_EDKII_MENU_HELP #language en-US "This selection will take you to Dasharo System Features Manager" + +#string STR_DASHARO_SECURITY_OPTIONS_TITLE #language en-US "Dasharo Security Options" +#string STR_DASHARO_SECURITY_OPTIONS_HELP #language en-US "Security-related options" + +#string STR_DASHARO_NETWORKING_OPTIONS_TITLE #language en-US "Networking Options" +#string STR_DASHARO_NETWORKING_OPTIONS_HELP #language en-US "Network-related options" + +#string STR_DASHARO_USB_CONFIGURATION_TITLE #language en-US "USB Configuration" +#string STR_DASHARO_USB_CONFIGURATION_HELP #language en-US "USB-related options" + +#string STR_DASHARO_CHIPSET_CONFIGURATION_TITLE #language en-US "Chipset Configuration" +#string STR_DASHARO_CHIPSET_CONFIGURATION_HELP #language en-US "Chipset-related options" + +#string STR_DASHARO_POWER_CONFIGURATION_TITLE #language en-US "Power Management Options" +#string STR_DASHARO_POWER_CONFIGURATION_HELP #language en-US "Power management-related options" + +#string STR_DASHARO_PCI_CONFIGURATION_TITLE #language en-US "PCI/PCIe Configuration" +#string STR_DASHARO_PCI_CONFIGURATION_HELP #language en-US "PCI/PCIe configuration options" + +#string STR_DASHARO_MEMORY_CONFIGURATION_TITLE #language en-US "Memory Configuration" +#string STR_DASHARO_MEMORY_CONFIGURATION_HELP #language en-US "Memory-related options" + +#string STR_DASHARO_SERIAL_PORT_CONFIGURATION_TITLE #language en-US "Serial Port Configuration" +#string STR_DASHARO_SERIAL_PORT_CONFIGURATION_HELP #language en-US "Serial port options" + +#string STR_DASHARO_CPU_CONFIGURATION_TITLE #language en-US "CPU Configuration" +#string STR_DASHARO_CPU_CONFIGURATION_HELP #language en-US "CPU related configuration options" + +#string STR_FUM_PROMPT #language en-US "> Enter Firmware Update Mode" +#string STR_FUM_HELP #language en-US "Disables all firmware protections for the duration of next boot." + +#string STR_LOCK_BIOS_PROMPT #language en-US "Lock the BIOS boot medium" +#string STR_LOCK_BIOS_HELP #language en-US "Locks the recovery partition of vboot" + +#string STR_SMM_BWP_PROMPT #language en-US "Enable SMM BIOS write protection" +#string STR_SMM_BWP_HELP #language en-US "Prevents writing to the boot medium outside of SMM. Recommended to enable if using an admin password. Disable when updating firmware." + +#string STR_NETWORK_BOOT_ENABLE_PROMPT #language en-US "Enable network boot" +#string STR_NETWORK_BOOT_ENABLE_HELP #language en-US "Enables/disables the iPXE network boot and all NIC drivers" + +#string STR_USB_STACK_ENABLE_PROMPT #language en-US "Enable USB stack" +#string STR_USB_STACK_ENABLE_HELP #language en-US "Enables/disables the USB drivers. Disabling it means neither USB keyboard nor storage will work" + +#string STR_USB_MASS_STORAGE_ENABLE_PROMPT #language en-US "Enable USB Mass Storage driver" +#string STR_USB_MASS_STORAGE_ENABLE_HELP #language en-US "Enables/disables the USB Mass Storage driver. When disabled, booting from USB will not work, but USB keyboard still will" + +#string STR_DASHARO_INTEL_ME_OPTIONS_TITLE #language en-US "Intel Management Engine Options" +#string STR_DASHARO_INTEL_ME_OPTIONS_HELP #language en-US "Configuration for Intel Management Engine" + +#string STR_CAPSULE_UPDATE_MSG #language en-US "Setting 'Intel ME mode' to 'Disabled (HAP)' allows updating system firmware via a UEFI capsule." + +#string STR_ME_MODE_PROMPT #language en-US "Intel ME mode" +#string STR_ME_MODE_HELP #language en-US "Operation mode of the Intel Management Engine. The ME can be enabled, or disabled using various methods.\n\n" + "Enabled: Enable the Intel Management Engine.\n\n" + "Disabled (Soft): Disable using a HECI message.\n\n" + "Disabled (HAP): Disable using the High Assurance Platform bit in the flash descriptor.\n\n" + "Note that with ME disabled, the firmware TPM will no longer be functional." + +#string STR_ME_MODE_ENABLE #language en-US "Enabled" +#string STR_ME_MODE_DISABLE_HECI #language en-US "Disabled (Soft)" +#string STR_ME_MODE_DISABLE_HAP #language en-US "Disabled (HAP)" + +#string STR_PS2_CONTROLLER_ENABLE_PROMPT #language en-US "Enable PS2 Controller" +#string STR_PS2_CONTROLLER_ENABLE_HELP #language en-US "Enables/disables the PS/2 Controller. When enabled, PS/2 keyboards and mice will be detected in the firmware and operating system." + +#string STR_WATCHDOG_ENABLE_PROMPT #language en-US "Enable watchdog" +#string STR_WATCHDOG_ENABLE_HELP #language en-US "Enables/disables OC Watchdog Timer during POST. If the timers expires, for example due to an unexpected hang or lockup, the platform will be reset after specified timeout." + +#string STR_WATCHDOG_TIMEOUT_PROMPT #language en-US "Watchdog timeout value" +#string STR_WATCHDOG_TIMEOUT_HELP #language en-US "Sets the watchdog timer expiration value in seconds. Minimum is 300s, maximum 1024s." + +#string STR_BOOT_MENU_ENABLED_PROMPT #language en-US "Boot menu enabled" +#string STR_BOOT_MENU_ENABLED_HELP #language en-US "Enables or disables choice of one-time boot menu" + +#string STR_FAN_CURVE_PROMPT #language en-US "Fan profile" +#string STR_FAN_CURVE_HELP #language en-US "Sets the preferred fan operation mode.\n\n" + "Silent: The fan will operate at lower speeds to reduce noise.\n\n" + "Performance: The fans will work at higher speeds to reduce temperature and increase performance.\n\n" + "Fans Off: The fans will be turned off." + +#string STR_FAN_CURVE_SILENT #language en-US "Silent" +#string STR_FAN_CURVE_PERFORMANCE #language en-US "Performance" +#string STR_FAN_CURVE_OFF #language en-US "Fans Off" + +#string STR_DMA_PROTECTION_PROMPT #language en-US "Early boot DMA Protection" +#string STR_DMA_PROTECTION_HELP #language en-US "Enables IOMMU DMA protection early during POST." + +#string STR_IOMMU_HANDOFF_PROMPT #language en-US "Keep IOMMU enabled when transfer control to OS" +#string STR_IOMMU_HANDOFF_HELP #language en-US "Keeps IOMMU DMA protection enabled during ExitBootServices when control is passed to the OS.\n\n" + "If unsure or see any problems with DMA/IOMMU during OS boot, keep it disabled." + +#string STR_SLEEP_TYPE_PROMPT #language en-US "Platform sleep type" +#string STR_SLEEP_TYPE_HELP #language en-US "Select the sleep type that will be exposed to the OS.\n\n" + "Note that Suspend to Idle (S0ix) will not work if Intel ME is disabled.\n\n" + "Recommended settings:\n" + "- Windows: S0ix\n" + "- Linux: S3\n\n" + +#string STR_SLEEP_TYPE_HELP_EXPERIMENTAL #language en-US "Select the sleep type that will be exposed to the OS.\n\n" + "Note that Suspend to Idle (S0ix) will not work if Intel ME is disabled.\n\n" + "Recommended settings:\n" + "- Windows: S0ix\n" + "- Linux: S3\n\n" + "Note: S3 support is experimental on this device." + +#string STR_SLEEP_TYPE_S0IX #language en-US "Suspend to Idle (S0ix)" +#string STR_SLEEP_TYPE_S3 #language en-US "Suspend to RAM (S3)" +#string STR_SLEEP_TYPE_S3_EXPERIMENTAL #language en-US "Suspend to RAM (S3) - Experimental" + +#string STR_POWER_FAILURE_STATE_PROMPT #language en-US "Power state after power/AC loss" +#string STR_POWER_FAILURE_STATE_HELP #language en-US "Selects state the system gets into when power supply is restored after power failure.\n\n" + + "Note that the definition of power failure varies between platforms and it might take absence of power for up to 30 seconds for this option to apply.\n\n" + +#string STR_POWER_FAILURE_STATE_OFF #language en-US "Powered Off" +#string STR_POWER_FAILURE_STATE_ON #language en-US "Powered On" +#string STR_POWER_FAILURE_STATE_KEEP #language en-US "The state at the moment of power failure" + +#string STR_RESIZEABLE_BARS_PROMPT #language en-US "Enable PCIe Resizeable BARs" +#string STR_RESIZEABLE_BARS_HELP #language en-US "Enables allocation of resizeable BARs for devices that request them.\n\n" + "Enabling this option can cause conflicts with GPU virtualization.\n\n" + "Requested size might exceed maximum BAR size of the firmware in which case performance might be reduced." + +#string STR_OPTION_ROM_PROMPT #language en-US "OptionROM Execution Policy" +#string STR_OPTION_ROM_HELP #language en-US "This option allows control over which OptionROMs get loaded." + +#string STR_OPTION_ROM_DISABLE #language en-US "Disable all OptionROMs loading" +#string STR_OPTION_ROM_ENABLE #language en-US "Enable all OptionROMs loading" +#string STR_OPTION_ROM_ENABLE_VGA #language en-US "Enable OptionROM loading only on GPUs" + +#string STR_ENABLE_CAMERA_PROMPT #language en-US "Enable Camera" +#string STR_ENABLE_CAMERA_HELP #language en-US "If this option is disabled, the power to the USB webcam is disconnected completely" + +#string STR_WIFI_BT_ENABLE_PROMPT #language en-US "Enable Wi-Fi + BT radios" +#string STR_WIFI_BT_ENABLE_HELP #language en-US "When not enabled, WiFi + Bluetooth card slot is disabled." + +#string STR_BATTERY_START_THRESHOLD_PROMPT #language en-US "Battery Start Charge Threshold" +#string STR_BATTERY_START_THRESHOLD_HELP #language en-US "The battery will only start charging once the charge level drops below this value. Consider lowering the value to around 70% if the device is mostly used when connected to an AC adapter to reduce battery wear." + +#string STR_BATTERY_STOP_THRESHOLD_PROMPT #language en-US "Battery Stop Charge Threshold" +#string STR_BATTERY_STOP_THRESHOLD_HELP #language en-US "The battery will only stop charging once the charge level reaches this value. Consider lowering this value to around 80% if the device is mostly used when connected to an AC adapter to reduce battery wear." + +#string STR_BATTERY_THRESHOLD_RANGE_ERROR #language en-US "The battery stop threshold must be greater than the start threshold!" + +#string STR_MEMORY_PROFILE_PROMPT #language en-US "Memory SPD Profile" +#string STR_MEMORY_PROFILE_HELP #language en-US "This option selects memory profile applied to RAM modules.\n\n" + "Selecting an XMP profile may result in unstable memory modules and even prevent system from booting.\n\n" + "Changing this option causes memory retraining on the next boot which takes time to complete." + +#string STR_MEMORY_PROFILE_JEDEC #language en-US "JEDEC (safe non-overclocked default)" +#string STR_MEMORY_PROFILE_XMP1 #language en-US "XMP#1 (predefined extreme memory profile)" +#string STR_MEMORY_PROFILE_XMP2 #language en-US "XMP#2 (predefined extreme memory profile)" +#string STR_MEMORY_PROFILE_XMP3 #language en-US "XMP#3 (predefined extreme memory profile)" + +#string STR_SERIAL_CONSOLE_REDIRECTION_PROMPT #language en-US "Enable COM0 Serial Console Redirection" +#string STR_SERIAL_CONSOLE_REDIRECTION_HELP #language en-US "Redirect the firmware console to the serial port." + +#string STR_SERIAL_CONSOLE_REDIRECTION2_PROMPT #language en-US "Enable COM1 Serial Console Redirection" +#string STR_SERIAL_CONSOLE_REDIRECTION2_HELP #language en-US "Redirect the firmware console to the second serial port." + +#string STR_CPU_THROTTLING_THRESHOLD_PROMPT #language en-US "Current CPU Throttling Threshold Temperature" +#string STR_CPU_THROTTLING_THRESHOLD_HELP #language en-US "The temperature above which the CPU will start throttling itself." + +#string STR_CPU_THROTTLING_OFFSET_PROMPT #language en-US "CPU Throttling Temperature Offset" +#string STR_CPU_THROTTLING_OFFSET_HELP #language en-US "The temperature offset from TjMax (maximum CPU temperature) above which the CPU will start throttling itself.\n\n" + "The value is also known as TCC offset." + +#string STR_BIG_CORE_COUNT_PROMPT #language en-US "Number of active P-cores" +#string STR_BIG_CORE_COUNT_HELP #language en-US "Specify the number of Performance cores that should remain active.\n\n" + "Minimum is one, maximum is processor dependent." + +#string STR_SMALL_CORE_COUNT_PROMPT #language en-US "Number of active E-cores" +#string STR_SMALL_CORE_COUNT_HELP #language en-US "Specify the number of Efficient cores that should remain active.\n\n" + "Minimum is zero (or one if there are no Performance cores in the system), " + "maximum is processor dependent." + +#string STR_CORE_COUNT_PROMPT #language en-US "Number of active CPU cores" +#string STR_CORE_COUNT_HELP #language en-US "Specify the number of CPU cores that should remain active.\n\n" + "Minimum is one, maximum is processor dependent." + +#string STR_HYPER_THREADING_PROMPT #language en-US "Hyper-Threading" +#string STR_HYPER_THREADING_HELP #language en-US "Enable/disable CPU Hyper-Threading feature.\n\n" + "All cores supporting Hyper-Threading will have their second logical thread enabled or disabled." + +#string STR_CPU_CORES_ENABLE_ALL #language en-US "All active" + +#string STR_0 #language en-US "0" +#string STR_1 #language en-US "1" +#string STR_2 #language en-US "2" +#string STR_3 #language en-US "3" +#string STR_4 #language en-US "4" +#string STR_5 #language en-US "5" +#string STR_6 #language en-US "6" +#string STR_7 #language en-US "7" +#string STR_8 #language en-US "8" +#string STR_9 #language en-US "9" +#string STR_10 #language en-US "10" +#string STR_11 #language en-US "11" +#string STR_12 #language en-US "12" +#string STR_13 #language en-US "13" +#string STR_14 #language en-US "14" +#string STR_15 #language en-US "15" +#string STR_16 #language en-US "16" diff --git a/DasharoModulePkg/Library/DasharoSystemFeaturesUiLib/DasharoSystemFeaturesUiLib.inf b/DasharoModulePkg/Library/DasharoSystemFeaturesUiLib/DasharoSystemFeaturesUiLib.inf new file mode 100644 index 0000000000..d30a7b863e --- /dev/null +++ b/DasharoModulePkg/Library/DasharoSystemFeaturesUiLib/DasharoSystemFeaturesUiLib.inf @@ -0,0 +1,98 @@ +## @file +# Dasharo System Features Library used by UiApp +# +# Copyright (c) 2022, 3mdeb Sp. z o.o. All rights reserved.
+# SPDX-License-Identifier: GPL-2-only +# +## +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DasharoSystemFeaturesUiLib + MODULE_UNI_FILE = DasharoSystemFeaturesUiLib.uni + FILE_GUID = 12F093F3-B653-4FA3-A2D6-C76BDD33BD52 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = NULL|DXE_DRIVER UEFI_APPLICATION + CONSTRUCTOR = DasharoSystemFeaturesUiLibConstructor + DESTRUCTOR = DasharoSystemFeaturesUiLibDestructor +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + DasharoSystemFeatures.h + DasharoSystemFeaturesHii.h + DasharoSystemFeatures.c + CpuTopology.c + DasharoSystemFeaturesVfr.vfr + DasharoSystemFeaturesStrings.uni + +[Packages] + DasharoModulePkg/DasharoModulePkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + DasharoPayloadPkg/DasharoPayloadPkg.dec + +[LibraryClasses] + DevicePathLib + BaseLib + MemoryAllocationLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + BaseMemoryLib + DebugLib + IoLib + PcdLib + PciLib + PrintLib + HiiLib + UefiHiiServicesLib + DasharoVariablesLib + +[Guids] + gEfiHiiPlatformSetupFormsetGuid ## CONSUMES ## GUID (Indicate the formset class guid to be displayed) + gEfiIfrTianoGuid ## CONSUMES ## GUID (Extended IFR Guid Opcode) + gEfiIfrFrontPageGuid ## CONSUMES ## GUID (Indicate the formset in this library need to display in which page) + gDasharoSystemFeaturesGuid ## CONSUMES + +[Protocols] + gEfiHiiConfigAccessProtocolGuid ## CONSUMES + gEfiAcpiSdtProtocolGuid ## SOMETIMES_CONSUMES + +[Pcd] + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowMenu + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowSecurityMenu + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowIntelMeMenu + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowUsbMenu + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowNetworkMenu + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowChipsetMenu + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowPowerMenu + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowPciMenu + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowMemoryMenu + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowSerialPortMenu + gDasharoSystemFeaturesTokenSpaceGuid.PcdPowerMenuShowFanCurve + gDasharoSystemFeaturesTokenSpaceGuid.PcdPowerMenuShowSleepType + gDasharoSystemFeaturesTokenSpaceGuid.PcdDefaultPowerFailureState + gDasharoSystemFeaturesTokenSpaceGuid.PcdDasharoEnterprise + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowIommuOptions + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowOcWdtOptions + gDasharoSystemFeaturesTokenSpaceGuid.PcdPciMenuShowResizeableBars + gDasharoSystemFeaturesTokenSpaceGuid.PcdPowerMenuShowBatteryThresholds + gDasharoSystemFeaturesTokenSpaceGuid.PcdSerialRedirectionDefaultState + gDasharoSystemFeaturesTokenSpaceGuid.PcdSecurityShowWiFiBtOption + gDasharoSystemFeaturesTokenSpaceGuid.PcdSecurityShowCameraOption + gDasharoSystemFeaturesTokenSpaceGuid.PcdIntelMeHapAvailable + gDasharoSystemFeaturesTokenSpaceGuid.PcdS3SupportExperimental + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowLockBios + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowSmmBwp + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowFum + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowPs2Option + gDasharoSystemFeaturesTokenSpaceGuid.PcdHave2ndUart + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowCpuThrottlingThreshold + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowCpuMenu + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowCpuCoreDisable + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowCpuHyperThreading + gDasharoSystemFeaturesTokenSpaceGuid.PcdCpuMaxTemperature + gDasharoSystemFeaturesTokenSpaceGuid.PcdPowerMenuShowFanCurveOffOption diff --git a/DasharoModulePkg/Library/DasharoSystemFeaturesUiLib/DasharoSystemFeaturesUiLib.uni b/DasharoModulePkg/Library/DasharoSystemFeaturesUiLib/DasharoSystemFeaturesUiLib.uni new file mode 100644 index 0000000000..c73dec4ef1 --- /dev/null +++ b/DasharoModulePkg/Library/DasharoSystemFeaturesUiLib/DasharoSystemFeaturesUiLib.uni @@ -0,0 +1,16 @@ +// /** @file +// Dasharo System Features Library used by UiApp +// +// Copyright (c) 2022, 3mdeb Sp. z o.o. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause +// +// **/ + +#string STR_MODULE_ABSTRACT +#language en-US +"Dasharo System Features Library used by UiApp" + +#string STR_MODULE_DESCRIPTION +#language en-US +"Dasharo System Features Library used by UiApp" diff --git a/DasharoModulePkg/Library/DasharoSystemFeaturesUiLib/DasharoSystemFeaturesVfr.vfr b/DasharoModulePkg/Library/DasharoSystemFeaturesUiLib/DasharoSystemFeaturesVfr.vfr new file mode 100644 index 0000000000..340b7b3f32 --- /dev/null +++ b/DasharoModulePkg/Library/DasharoSystemFeaturesUiLib/DasharoSystemFeaturesVfr.vfr @@ -0,0 +1,654 @@ +/** @file +The Dasharo system features implementation + +Copyright (c) 2022, 3mdeb Sp. z o.o. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause + +**/ + +#include "DasharoSystemFeaturesHii.h" + +formset + guid = DASHARO_SYSTEM_FEATURES_GUID, + title = STRING_TOKEN(STR_EDKII_MENU_TITLE), + help = STRING_TOKEN(STR_EDKII_MENU_HELP), + classguid = gEfiIfrFrontPageGuid, + + varstore DASHARO_FEATURES_DATA, + varid = DASHARO_FEATURES_DATA_VARSTORE_ID, + name = FeaturesData, + guid = DASHARO_SYSTEM_FEATURES_GUID; + + form formid = DASHARO_SYSTEM_FEATURES_FORM_ID, + title = STRING_TOKEN(STR_EDKII_MENU_TITLE); + + suppressif ideqval FeaturesData.ShowSecurityMenu == 0; + goto DASHARO_SECURITY_OPTIONS_FORM_ID, + prompt = STRING_TOKEN(STR_DASHARO_SECURITY_OPTIONS_TITLE), + help = STRING_TOKEN(STR_DASHARO_SECURITY_OPTIONS_HELP); + endif; + + suppressif ideqval FeaturesData.ShowNetworkMenu == 0; + goto DASHARO_NETWORK_OPTIONS_FORM_ID, + prompt = STRING_TOKEN(STR_DASHARO_NETWORKING_OPTIONS_TITLE), + help = STRING_TOKEN(STR_DASHARO_NETWORKING_OPTIONS_HELP); + endif; + + suppressif ideqval FeaturesData.ShowUsbMenu == 0; + goto DASHARO_USB_CONFIGURATION_FORM_ID, + prompt = STRING_TOKEN(STR_DASHARO_USB_CONFIGURATION_TITLE), + help = STRING_TOKEN(STR_DASHARO_USB_CONFIGURATION_HELP); + endif; + + suppressif ideqval FeaturesData.ShowIntelMeMenu == 0; + goto DASHARO_INTEL_ME_OPTIONS_FORM_ID, + prompt = STRING_TOKEN(STR_DASHARO_INTEL_ME_OPTIONS_TITLE), + help = STRING_TOKEN(STR_DASHARO_INTEL_ME_OPTIONS_HELP); + endif; + + suppressif ideqval FeaturesData.ShowChipsetMenu == 0; + goto DASHARO_CHIPSET_CONFIGURATION_FORM_ID, + prompt = STRING_TOKEN(STR_DASHARO_CHIPSET_CONFIGURATION_TITLE), + help = STRING_TOKEN(STR_DASHARO_CHIPSET_CONFIGURATION_HELP); + endif; + + suppressif ideqval FeaturesData.ShowPowerMenu == 0; + goto DASHARO_POWER_CONFIGURATION_FORM_ID, + prompt = STRING_TOKEN(STR_DASHARO_POWER_CONFIGURATION_TITLE), + help = STRING_TOKEN(STR_DASHARO_POWER_CONFIGURATION_HELP); + endif; + + suppressif ideqval FeaturesData.ShowPciMenu == 0; + goto DASHARO_PCI_CONFIGURATION_FORM_ID, + prompt = STRING_TOKEN(STR_DASHARO_PCI_CONFIGURATION_TITLE), + help = STRING_TOKEN(STR_DASHARO_PCI_CONFIGURATION_HELP); + endif; + + suppressif ideqval FeaturesData.ShowMemoryMenu == 0; + goto DASHARO_MEMORY_CONFIGURATION_FORM_ID, + prompt = STRING_TOKEN(STR_DASHARO_MEMORY_CONFIGURATION_TITLE), + help = STRING_TOKEN(STR_DASHARO_MEMORY_CONFIGURATION_HELP); + endif; + + suppressif ideqval FeaturesData.ShowSerialPortMenu == 0; + goto DASHARO_SERIAL_PORT_CONFIGURATION_FORM_ID, + prompt = STRING_TOKEN(STR_DASHARO_SERIAL_PORT_CONFIGURATION_TITLE), + help = STRING_TOKEN(STR_DASHARO_SERIAL_PORT_CONFIGURATION_HELP); + endif; + + suppressif ideqval FeaturesData.ShowCpuMenu == 0; + goto DASHARO_CPU_CONFIGURATION_FORM_ID, + prompt = STRING_TOKEN(STR_DASHARO_CPU_CONFIGURATION_TITLE), + help = STRING_TOKEN(STR_DASHARO_CPU_CONFIGURATION_HELP); + endif; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EXIT_STRING); + endform; + + form formid = DASHARO_SECURITY_OPTIONS_FORM_ID, + title = STRING_TOKEN(STR_DASHARO_SECURITY_OPTIONS_TITLE); + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + disableif ideqval FeaturesData.ShowLockBios == 0; + checkbox varid = FeaturesData.LockBios, + prompt = STRING_TOKEN(STR_LOCK_BIOS_PROMPT), + help = STRING_TOKEN(STR_LOCK_BIOS_HELP), + flags = CHECKBOX_DEFAULT | RESET_REQUIRED, + endcheckbox; + endif; + + disableif ideqval FeaturesData.ShowSmmBwp == 0; + checkbox varid = FeaturesData.SmmBwp, + prompt = STRING_TOKEN(STR_SMM_BWP_PROMPT), + help = STRING_TOKEN(STR_SMM_BWP_HELP), + flags = RESET_REQUIRED, + endcheckbox; + endif; + + disableif ideqval FeaturesData.SecurityMenuShowIommu == 0; + checkbox name = IommuEnable, + varid = FeaturesData.IommuConfig.IommuEnable, + prompt = STRING_TOKEN(STR_DMA_PROTECTION_PROMPT), + help = STRING_TOKEN(STR_DMA_PROTECTION_HELP), + flags = RESET_REQUIRED, + endcheckbox; + + suppressif questionref(IommuEnable) == FALSE; + checkbox varid = FeaturesData.IommuConfig.IommuHandoff, + prompt = STRING_TOKEN(STR_IOMMU_HANDOFF_PROMPT), + help = STRING_TOKEN(STR_IOMMU_HANDOFF_HELP), + flags = RESET_REQUIRED, + endcheckbox; + endif; + endif; + + disableif ideqval FeaturesData.DasharoEnterprise == 0; + checkbox varid = FeaturesData.BootManagerEnabled, + prompt = STRING_TOKEN(STR_BOOT_MENU_ENABLED_PROMPT), + help = STRING_TOKEN(STR_BOOT_MENU_ENABLED_HELP), + flags = CHECKBOX_DEFAULT | RESET_REQUIRED, + endcheckbox; + endif; + + disableif ideqval FeaturesData.SecurityMenuShowWiFiBt == 0; + checkbox varid = FeaturesData.EnableWifiBt, + prompt = STRING_TOKEN(STR_WIFI_BT_ENABLE_PROMPT), + help = STRING_TOKEN(STR_WIFI_BT_ENABLE_HELP), + flags = CHECKBOX_DEFAULT | RESET_REQUIRED, + endcheckbox; + endif; + + disableif ideqval FeaturesData.SecurityMenuShowCamera == 0; + checkbox varid = FeaturesData.EnableCamera, + prompt = STRING_TOKEN(STR_ENABLE_CAMERA_PROMPT), + help = STRING_TOKEN(STR_ENABLE_CAMERA_HELP), + flags = CHECKBOX_DEFAULT | RESET_REQUIRED, + endcheckbox; + endif; + + disableif ideqval FeaturesData.ShowFum == 0; + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + text + help = STRING_TOKEN(STR_FUM_HELP), + text = STRING_TOKEN(STR_FUM_PROMPT), + flags = INTERACTIVE, + key = FIRMWARE_UPDATE_MODE_QUESTION_ID; + endif; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EXIT_STRING); + + endform; + + form formid = DASHARO_NETWORK_OPTIONS_FORM_ID, + title = STRING_TOKEN(STR_DASHARO_NETWORKING_OPTIONS_TITLE); + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + disableif ideqval FeaturesData.ShowNetworkMenu == 0; + checkbox varid = FeaturesData.NetworkBoot, + questionid = NETWORK_BOOT_QUESTION_ID, + prompt = STRING_TOKEN(STR_NETWORK_BOOT_ENABLE_PROMPT), + help = STRING_TOKEN(STR_NETWORK_BOOT_ENABLE_HELP), + flags = INTERACTIVE | RESET_REQUIRED, + endcheckbox; + endif; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EXIT_STRING); + endform; + + form formid = DASHARO_USB_CONFIGURATION_FORM_ID, + title = STRING_TOKEN(STR_DASHARO_USB_CONFIGURATION_TITLE); + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + disableif ideqval FeaturesData.ShowUsbMenu == 0; + checkbox name = UsbStack, + varid = FeaturesData.UsbStack, + prompt = STRING_TOKEN(STR_USB_STACK_ENABLE_PROMPT), + help = STRING_TOKEN(STR_USB_STACK_ENABLE_HELP), + flags = CHECKBOX_DEFAULT | RESET_REQUIRED, + endcheckbox; + + suppressif questionref(UsbStack) == FALSE; + checkbox varid = FeaturesData.UsbMassStorage, + prompt = STRING_TOKEN(STR_USB_MASS_STORAGE_ENABLE_PROMPT), + help = STRING_TOKEN(STR_USB_MASS_STORAGE_ENABLE_HELP), + flags = CHECKBOX_DEFAULT | RESET_REQUIRED, + endcheckbox; + endif; + endif; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EXIT_STRING); + endform; + + form formid = DASHARO_INTEL_ME_OPTIONS_FORM_ID, + title = STRING_TOKEN(STR_DASHARO_INTEL_ME_OPTIONS_TITLE); + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + disableif ideqval FeaturesData.ShowIntelMeMenu == 0; + disableif ideqval FeaturesData.MeHapAvailable == 0; + subtitle text = STRING_TOKEN(STR_CAPSULE_UPDATE_MSG); + endif; + oneof varid = FeaturesData.MeMode, + questionid = INTEL_ME_MODE_QUESTION_ID, + prompt = STRING_TOKEN(STR_ME_MODE_PROMPT), + help = STRING_TOKEN(STR_ME_MODE_HELP), + flags = RESET_REQUIRED | INTERACTIVE, + + option text = STRING_TOKEN(STR_ME_MODE_ENABLE), value = ME_MODE_ENABLE, flags = 0; + option text = STRING_TOKEN(STR_ME_MODE_DISABLE_HECI), value = ME_MODE_DISABLE_HECI, flags = 0; + suppressif ideqval FeaturesData.MeHapAvailable == 0; + option text = STRING_TOKEN(STR_ME_MODE_DISABLE_HAP), value = ME_MODE_DISABLE_HAP, flags = 0; + endif; + endoneof; + endif; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EXIT_STRING); + endform; + + form formid = DASHARO_CHIPSET_CONFIGURATION_FORM_ID, + title = STRING_TOKEN(STR_DASHARO_CHIPSET_CONFIGURATION_TITLE); + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + disableif ideqval FeaturesData.ShowPs2Option == 0; + checkbox varid = FeaturesData.Ps2Controller, + prompt = STRING_TOKEN(STR_PS2_CONTROLLER_ENABLE_PROMPT), + help = STRING_TOKEN(STR_PS2_CONTROLLER_ENABLE_HELP), + flags = CHECKBOX_DEFAULT | RESET_REQUIRED, + endcheckbox; + endif; + + disableif ideqval FeaturesData.WatchdogAvailable == 0; + checkbox varid = FeaturesData.WatchdogConfig.WatchdogEnable, + questionid = WATCHDOG_ENABLE_QUESTION_ID, + prompt = STRING_TOKEN(STR_WATCHDOG_ENABLE_PROMPT), + help = STRING_TOKEN(STR_WATCHDOG_ENABLE_HELP), + flags = RESET_REQUIRED | INTERACTIVE, + endcheckbox; + + suppressif ideqval FeaturesData.WatchdogConfig.WatchdogEnable == 0; + numeric varid = FeaturesData.WatchdogConfig.WatchdogTimeout, + questionid = WATCHDOG_TIMEOUT_QUESTION_ID, + prompt = STRING_TOKEN(STR_WATCHDOG_TIMEOUT_PROMPT), + help = STRING_TOKEN(STR_WATCHDOG_TIMEOUT_HELP), + flags = RESET_REQUIRED | INTERACTIVE, + minimum = 300, + maximum = 1024, + step = 0, // Stepping of 0 equates to a manual entering + // of a value, otherwise it will be adjusted by "+"/"-" + endnumeric; + endif; + endif; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EXIT_STRING); + endform; + + form formid = DASHARO_POWER_CONFIGURATION_FORM_ID, + title = STRING_TOKEN(STR_DASHARO_POWER_CONFIGURATION_TITLE); + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + disableif ideqval FeaturesData.PowerMenuShowFanCurve == 0; + oneof varid = FeaturesData.FanCurveOption, + prompt = STRING_TOKEN(STR_FAN_CURVE_PROMPT), + help = STRING_TOKEN(STR_FAN_CURVE_HELP), + flags = RESET_REQUIRED, + + option text = STRING_TOKEN(STR_FAN_CURVE_SILENT), value = FAN_CURVE_OPTION_SILENT, flags = DEFAULT; + option text = STRING_TOKEN(STR_FAN_CURVE_PERFORMANCE), value = FAN_CURVE_OPTION_PERFORMANCE, flags = 0; + suppressif ideqval FeaturesData.HideFanCurveOff == 1; + option text = STRING_TOKEN(STR_FAN_CURVE_OFF), value = FAN_CURVE_OPTION_OFF, flags = 0; + endif; + endoneof; + endif; + + disableif ideqval FeaturesData.PowerMenuShowSleepType == 0; + oneof varid = FeaturesData.SleepType, + questionid = SLEEP_TYPE_QUESTION_ID, + prompt = STRING_TOKEN(STR_SLEEP_TYPE_PROMPT), + help = STRING_TOKEN(STR_SLEEP_TYPE_HELP), + flags = RESET_REQUIRED | INTERACTIVE, + + option text = STRING_TOKEN(STR_SLEEP_TYPE_S0IX), value = SLEEP_TYPE_S0IX, flags = 0; + suppressif ideqval FeaturesData.S3SupportExperimental == 1; + option text = STRING_TOKEN(STR_SLEEP_TYPE_S3), value = SLEEP_TYPE_S3, flags = 0; + endif; + suppressif ideqval FeaturesData.S3SupportExperimental == 0; + option text = STRING_TOKEN(STR_SLEEP_TYPE_S3_EXPERIMENTAL), value = SLEEP_TYPE_S3, flags = 0; + endif; + endoneof; + endif; + + disableif ideqval FeaturesData.ShowPowerFailureState == 0; + oneof varid = FeaturesData.PowerFailureState, + questionid = POWER_FAILURE_STATE_QUESTION_ID, + prompt = STRING_TOKEN(STR_POWER_FAILURE_STATE_PROMPT), + help = STRING_TOKEN(STR_POWER_FAILURE_STATE_HELP), + flags = INTERACTIVE | RESET_REQUIRED, + + option text = STRING_TOKEN(STR_POWER_FAILURE_STATE_OFF), value = POWER_FAILURE_STATE_OFF, flags = 0; + option text = STRING_TOKEN(STR_POWER_FAILURE_STATE_ON), value = POWER_FAILURE_STATE_ON, flags = 0; + option text = STRING_TOKEN(STR_POWER_FAILURE_STATE_KEEP), value = POWER_FAILURE_STATE_KEEP, flags = 0; + endoneof; + endif; + + disableif ideqval FeaturesData.PowerMenuShowBatteryThresholds == 0; + numeric varid = FeaturesData.BatteryConfig.StartThreshold, + questionid = BATTERY_START_THRESHOLD_QUESTION_ID, + prompt = STRING_TOKEN(STR_BATTERY_START_THRESHOLD_PROMPT), + help = STRING_TOKEN(STR_BATTERY_START_THRESHOLD_HELP), + flags = RESET_REQUIRED | INTERACTIVE, + minimum = 0, + maximum = 100, + step = 1, + + nosubmitif prompt = STRING_TOKEN(STR_BATTERY_THRESHOLD_RANGE_ERROR), + ideqid FeaturesData.BatteryConfig.StartThreshold > FeaturesData.BatteryConfig.StopThreshold + endif + endnumeric; + + numeric varid = FeaturesData.BatteryConfig.StopThreshold, + questionid = BATTERY_STOP_THRESHOLD_QUESTION_ID, + prompt = STRING_TOKEN(STR_BATTERY_STOP_THRESHOLD_PROMPT), + help = STRING_TOKEN(STR_BATTERY_STOP_THRESHOLD_HELP), + flags = RESET_REQUIRED | INTERACTIVE, + minimum = 0, + maximum = 100, + step = 1, + + nosubmitif prompt = STRING_TOKEN(STR_BATTERY_THRESHOLD_RANGE_ERROR), + ideqid FeaturesData.BatteryConfig.StartThreshold > FeaturesData.BatteryConfig.StopThreshold + endif + endnumeric; + endif; + + disableif ideqval FeaturesData.ShowCpuThrottlingThreshold == 0; + numeric varid = FeaturesData.CpuThrottlingOffset, + questionid = CPU_THROTTLING_OFFSET_QUESTION_ID, + prompt = STRING_TOKEN(STR_CPU_THROTTLING_OFFSET_PROMPT), + help = STRING_TOKEN(STR_CPU_THROTTLING_OFFSET_HELP), + flags = RESET_REQUIRED | INTERACTIVE, + minimum = 0, + maximum = 63, + step = 1, + + write set(FeaturesData.CpuThrottlingThreshold, get(FeaturesData.CpuMaxTemperature) - pushthis); + + endnumeric; + + grayoutif TRUE; + numeric varid = FeaturesData.CpuThrottlingThreshold, + prompt = STRING_TOKEN(STR_CPU_THROTTLING_THRESHOLD_PROMPT), + help = STRING_TOKEN(STR_CPU_THROTTLING_THRESHOLD_HELP), + minimum = 0, + maximum = 255, + + read get(FeaturesData.CpuMaxTemperature) - get(FeaturesData.CpuThrottlingOffset); + + endnumeric; + endif; + endif; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EXIT_STRING); + endform; + + form formid = DASHARO_PCI_CONFIGURATION_FORM_ID, + title = STRING_TOKEN(STR_DASHARO_PCI_CONFIGURATION_TITLE); + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + disableif ideqval FeaturesData.ShowPciMenu == 0; + disableif ideqval FeaturesData.PciMenuShowResizeableBars == 0; + checkbox varid = FeaturesData.ResizeableBarsEnabled, + prompt = STRING_TOKEN(STR_RESIZEABLE_BARS_PROMPT), + help = STRING_TOKEN(STR_RESIZEABLE_BARS_HELP), + flags = RESET_REQUIRED, + endcheckbox; + endif; + + oneof varid = FeaturesData.OptionRomExecution, + questionid = OPTION_ROM_STATE_QUESTION_ID, + prompt = STRING_TOKEN(STR_OPTION_ROM_PROMPT), + help = STRING_TOKEN(STR_OPTION_ROM_HELP), + flags = INTERACTIVE | RESET_REQUIRED, + + option text = STRING_TOKEN(STR_OPTION_ROM_DISABLE), value = OPTION_ROM_POLICY_DISABLE_ALL, flags = 0; + option text = STRING_TOKEN(STR_OPTION_ROM_ENABLE), value = OPTION_ROM_POLICY_ENABLE_ALL, flags = 0; + option text = STRING_TOKEN(STR_OPTION_ROM_ENABLE_VGA), value = OPTION_ROM_POLICY_VGA_ONLY, flags = 0; + endoneof; + endif; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EXIT_STRING); + endform; + + form formid = DASHARO_MEMORY_CONFIGURATION_FORM_ID, + title = STRING_TOKEN(STR_DASHARO_MEMORY_CONFIGURATION_TITLE); + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + disableif ideqval FeaturesData.ShowMemoryMenu == 0; + oneof varid = FeaturesData.MemoryProfile, + prompt = STRING_TOKEN(STR_MEMORY_PROFILE_PROMPT), + help = STRING_TOKEN(STR_MEMORY_PROFILE_HELP), + flags = RESET_REQUIRED, + + option text = STRING_TOKEN(STR_MEMORY_PROFILE_JEDEC), value = MEMORY_PROFILE_JEDEC, flags = DEFAULT; + option text = STRING_TOKEN(STR_MEMORY_PROFILE_XMP1), value = MEMORY_PROFILE_XMP1, flags = 0; + option text = STRING_TOKEN(STR_MEMORY_PROFILE_XMP2), value = MEMORY_PROFILE_XMP2, flags = 0; + option text = STRING_TOKEN(STR_MEMORY_PROFILE_XMP3), value = MEMORY_PROFILE_XMP3, flags = 0; + endoneof; + endif; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EXIT_STRING); + endform; + + form formid = DASHARO_SERIAL_PORT_CONFIGURATION_FORM_ID, + title = STRING_TOKEN(STR_DASHARO_SERIAL_PORT_CONFIGURATION_TITLE); + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + suppressif ideqval FeaturesData.ShowSerialPortMenu == 0; + checkbox varid = FeaturesData.SerialPortRedirection, + questionid = SERIAL_PORT_REDIR_QUESTION_ID, + prompt = STRING_TOKEN(STR_SERIAL_CONSOLE_REDIRECTION_PROMPT), + help = STRING_TOKEN(STR_SERIAL_CONSOLE_REDIRECTION_HELP), + flags = INTERACTIVE | RESET_REQUIRED, + endcheckbox; + + disableif ideqval FeaturesData.Have2ndUart == 0; + checkbox varid = FeaturesData.SerialPort2Redirection, + questionid = SERIAL_PORT2_REDIR_QUESTION_ID, + prompt = STRING_TOKEN(STR_SERIAL_CONSOLE_REDIRECTION2_PROMPT), + help = STRING_TOKEN(STR_SERIAL_CONSOLE_REDIRECTION2_HELP), + flags = INTERACTIVE | RESET_REQUIRED, + endcheckbox; + endif; + endif; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EXIT_STRING); + endform; + + + form formid = DASHARO_CPU_CONFIGURATION_FORM_ID, + title = STRING_TOKEN(STR_DASHARO_CPU_CONFIGURATION_TITLE); + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + disableif ideqval FeaturesData.ShowCpuCoreDisable == 0; + + disableif ideqval FeaturesData.HybridCpuArchitecture == 0; + + suppressif ideqval FeaturesData.SmallCoreMaxCount == 0; + oneof varid = FeaturesData.SmallCoreActiveCount, + prompt = STRING_TOKEN(STR_SMALL_CORE_COUNT_PROMPT), + help = STRING_TOKEN(STR_SMALL_CORE_COUNT_HELP), + flags = RESET_REQUIRED, + + option text = STRING_TOKEN (STR_CPU_CORES_ENABLE_ALL), value = CPU_CORES_ENABLE_ALL, flags = DEFAULT; + suppressif ideqval FeaturesData.SmallCoreMaxCount < 16; + option text = STRING_TOKEN (STR_15), value = 15, flags = 0; + endif; + suppressif ideqval FeaturesData.SmallCoreMaxCount < 15; + option text = STRING_TOKEN (STR_14), value = 14, flags = 0; + endif; + suppressif ideqval FeaturesData.SmallCoreMaxCount < 14; + option text = STRING_TOKEN (STR_13), value = 13, flags = 0; + endif; + suppressif ideqval FeaturesData.SmallCoreMaxCount < 13; + option text = STRING_TOKEN (STR_12), value = 12, flags = 0; + endif; + suppressif ideqval FeaturesData.SmallCoreMaxCount < 12; + option text = STRING_TOKEN (STR_11), value = 11, flags = 0; + endif; + suppressif ideqval FeaturesData.SmallCoreMaxCount < 11; + option text = STRING_TOKEN (STR_10), value = 10, flags = 0; + endif; + suppressif ideqval FeaturesData.SmallCoreMaxCount < 10; + option text = STRING_TOKEN (STR_9), value = 9, flags = 0; + endif; + suppressif ideqval FeaturesData.SmallCoreMaxCount < 9; + option text = STRING_TOKEN (STR_8), value = 8, flags = 0; + endif; + suppressif ideqval FeaturesData.SmallCoreMaxCount < 8; + option text = STRING_TOKEN (STR_7), value = 7, flags = 0; + endif; + suppressif ideqval FeaturesData.SmallCoreMaxCount < 7; + option text = STRING_TOKEN (STR_6), value = 6, flags = 0; + endif; + suppressif ideqval FeaturesData.SmallCoreMaxCount < 6; + option text = STRING_TOKEN (STR_5), value = 5, flags = 0; + endif; + suppressif ideqval FeaturesData.SmallCoreMaxCount < 5; + option text = STRING_TOKEN (STR_4), value = 4, flags = 0; + endif; + suppressif ideqval FeaturesData.SmallCoreMaxCount < 4; + option text = STRING_TOKEN (STR_3), value = 3, flags = 0; + endif; + suppressif ideqval FeaturesData.SmallCoreMaxCount < 3; + option text = STRING_TOKEN (STR_2), value = 2, flags = 0; + endif; + suppressif ideqval FeaturesData.SmallCoreMaxCount < 2; + option text = STRING_TOKEN (STR_1), value = 1, flags = 0; + endif; + suppressif ideqval FeaturesData.BigCoreMaxCount == 0; + option text = STRING_TOKEN (STR_0), value = 0, flags = 0; + endif; + endoneof; + endif; + + suppressif ideqval FeaturesData.BigCoreMaxCount == 0; + oneof varid = FeaturesData.BigCoreActiveCount, + prompt = STRING_TOKEN(STR_BIG_CORE_COUNT_PROMPT), + help = STRING_TOKEN(STR_BIG_CORE_COUNT_HELP), + flags = RESET_REQUIRED, + + option text = STRING_TOKEN (STR_CPU_CORES_ENABLE_ALL), value = CPU_CORES_ENABLE_ALL, flags = DEFAULT; + suppressif ideqval FeaturesData.BigCoreMaxCount < 8; + option text = STRING_TOKEN (STR_7), value = 7, flags = 0; + endif; + suppressif ideqval FeaturesData.BigCoreMaxCount < 7; + option text = STRING_TOKEN (STR_6), value = 6, flags = 0; + endif; + suppressif ideqval FeaturesData.BigCoreMaxCount < 6; + option text = STRING_TOKEN (STR_5), value = 5, flags = 0; + endif; + suppressif ideqval FeaturesData.BigCoreMaxCount < 5; + option text = STRING_TOKEN (STR_4), value = 4, flags = 0; + endif; + suppressif ideqval FeaturesData.BigCoreMaxCount < 4; + option text = STRING_TOKEN (STR_3), value = 3, flags = 0; + endif; + suppressif ideqval FeaturesData.BigCoreMaxCount < 3; + option text = STRING_TOKEN (STR_2), value = 2, flags = 0; + endif; + suppressif ideqval FeaturesData.BigCoreMaxCount < 2; + option text = STRING_TOKEN (STR_1), value = 1, flags = 0; + endif; + endoneof; + endif; // suppressif FeaturesData.BigCoreMaxCount == 0 + + endif; // disableif HybridCpuArchitecture == 0 + + disableif ideqval FeaturesData.HybridCpuArchitecture == 1; + + suppressif ideqval FeaturesData.CoreMaxCount == 1; + oneof varid = FeaturesData.CoreActiveCount, + prompt = STRING_TOKEN(STR_CORE_COUNT_PROMPT), + help = STRING_TOKEN(STR_CORE_COUNT_HELP), + flags = RESET_REQUIRED, + + option text = STRING_TOKEN (STR_CPU_CORES_ENABLE_ALL), value = CPU_CORES_ENABLE_ALL, flags = DEFAULT; + suppressif ideqval FeaturesData.CoreMaxCount < 16; + option text = STRING_TOKEN (STR_15), value = 15, flags = 0; + endif; + suppressif ideqval FeaturesData.CoreMaxCount < 15; + option text = STRING_TOKEN (STR_14), value = 14, flags = 0; + endif; + suppressif ideqval FeaturesData.CoreMaxCount < 14; + option text = STRING_TOKEN (STR_13), value = 13, flags = 0; + endif; + suppressif ideqval FeaturesData.CoreMaxCount < 13; + option text = STRING_TOKEN (STR_12), value = 12, flags = 0; + endif; + suppressif ideqval FeaturesData.CoreMaxCount < 12; + option text = STRING_TOKEN (STR_11), value = 11, flags = 0; + endif; + suppressif ideqval FeaturesData.CoreMaxCount < 11; + option text = STRING_TOKEN (STR_10), value = 10, flags = 0; + endif; + suppressif ideqval FeaturesData.CoreMaxCount < 10; + option text = STRING_TOKEN (STR_9), value = 9, flags = 0; + endif; + suppressif ideqval FeaturesData.CoreMaxCount < 9; + option text = STRING_TOKEN (STR_8), value = 8, flags = 0; + endif; + suppressif ideqval FeaturesData.CoreMaxCount < 8; + option text = STRING_TOKEN (STR_7), value = 7, flags = 0; + endif; + suppressif ideqval FeaturesData.CoreMaxCount < 7; + option text = STRING_TOKEN (STR_6), value = 6, flags = 0; + endif; + suppressif ideqval FeaturesData.CoreMaxCount < 6; + option text = STRING_TOKEN (STR_5), value = 5, flags = 0; + endif; + suppressif ideqval FeaturesData.CoreMaxCount < 5; + option text = STRING_TOKEN (STR_4), value = 4, flags = 0; + endif; + suppressif ideqval FeaturesData.CoreMaxCount < 4; + option text = STRING_TOKEN (STR_3), value = 3, flags = 0; + endif; + suppressif ideqval FeaturesData.CoreMaxCount < 3; + option text = STRING_TOKEN (STR_2), value = 2, flags = 0; + endif; + suppressif ideqval FeaturesData.CoreMaxCount < 2; + option text = STRING_TOKEN (STR_1), value = 1, flags = 0; + endif; + endoneof; + endif; // suppressif FeaturesData.CoreMaxCount == 1; + + endif; // disableif HybridCpuArchitecture == 1 + + endif; // disableif ShowCpuCoreDisable == 0 + + disableif ideqval FeaturesData.ShowCpuHyperThreading == 0; + suppressif ideqval FeaturesData.HyperThreadingSupported == 0; + checkbox varid = FeaturesData.HyperThreading, + questionid = HYPER_THREADING_QUESTION_ID, + prompt = STRING_TOKEN(STR_HYPER_THREADING_PROMPT), + help = STRING_TOKEN(STR_HYPER_THREADING_HELP), + flags = INTERACTIVE | RESET_REQUIRED, + endcheckbox; + endif; + endif; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EXIT_STRING); + endform; // CPU configuration form + +endformset; diff --git a/DasharoModulePkg/Library/DasharoVariablesLib/DasharoVariablesLib.c b/DasharoModulePkg/Library/DasharoVariablesLib/DasharoVariablesLib.c new file mode 100644 index 0000000000..679eb72f72 --- /dev/null +++ b/DasharoModulePkg/Library/DasharoVariablesLib/DasharoVariablesLib.c @@ -0,0 +1,599 @@ +/** @file + A library for providing services related to Dasharo-specific EFI variables. + + Copyright (c) 2024, 3mdeb Sp. z o.o. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Library/DasharoVariablesLib.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// PCR number for Dasharo variables. +#define DASHARO_VAR_PCR 1 + +// Event type for Dasharo variables. +#define EV_DASHARO_VAR 0x00DA0000 + +// Description of a single variable. +typedef struct { + // Default value. + DASHARO_VAR_DATA Data; // Value for the variable. + UINTN Size; // Number of bytes of Data actually used. + + UINT32 Attributes; // EFI variable attributes for this variable. +} VAR_INFO; + +typedef struct { + CHAR16 *Name; + BOOLEAN Condition; +} AUTO_VARIABLE; + +// List of Dasharo EFI variables in gDasharoSystemFeaturesGuid namespace that +// are created if missing. Each variable should have a FixedAtBuild PCD which +// controls the visibility/activity of the variable in the project and must be +// used to determine whether the variable should be created or not. + +STATIC CONST AUTO_VARIABLE mAutoCreatedVariables[] = { + { DASHARO_VAR_BATTERY_CONFIG, FixedPcdGetBool (PcdShowPowerMenu) && FixedPcdGetBool (PcdPowerMenuShowBatteryThresholds) }, + { DASHARO_VAR_BOOT_MANAGER_ENABLED, FixedPcdGetBool (PcdShowSecurityMenu) && FixedPcdGetBool (PcdDasharoEnterprise) }, + { DASHARO_VAR_CPU_THROTTLING_OFFSET, FixedPcdGetBool (PcdShowPowerMenu) && FixedPcdGetBool (PcdShowCpuThrottlingThreshold) }, + { DASHARO_VAR_ENABLE_CAMERA, FixedPcdGetBool (PcdShowSecurityMenu) && FixedPcdGetBool (PcdSecurityShowCameraOption) }, + { DASHARO_VAR_ENABLE_WIFI_BT, FixedPcdGetBool (PcdShowSecurityMenu) && FixedPcdGetBool (PcdSecurityShowWiFiBtOption) }, + { DASHARO_VAR_FAN_CURVE_OPTION, FixedPcdGetBool (PcdShowPowerMenu) && FixedPcdGetBool (PcdPowerMenuShowFanCurve) }, + { DASHARO_VAR_IOMMU_CONFIG, FixedPcdGetBool (PcdShowSecurityMenu) && FixedPcdGetBool (PcdShowIommuOptions) }, + { DASHARO_VAR_LOCK_BIOS, FixedPcdGetBool (PcdShowSecurityMenu) && FixedPcdGetBool (PcdShowLockBios) }, + { DASHARO_VAR_MEMORY_PROFILE, FixedPcdGetBool (PcdShowMemoryMenu) }, + { DASHARO_VAR_ME_MODE, FixedPcdGetBool (PcdShowIntelMeMenu) }, + { DASHARO_VAR_NETWORK_BOOT, FixedPcdGetBool (PcdShowNetworkMenu) }, + { DASHARO_VAR_OPTION_ROM_POLICY, FixedPcdGetBool (PcdShowPciMenu) }, + { DASHARO_VAR_POWER_FAILURE_STATE, FixedPcdGetBool (PcdShowPowerMenu) && (FixedPcdGet8 (PcdDefaultPowerFailureState) != DASHARO_POWER_FAILURE_STATE_HIDDEN) }, + { DASHARO_VAR_PS2_CONTROLLER, FixedPcdGetBool (PcdShowChipsetMenu) && FixedPcdGetBool (PcdShowPs2Option) }, + { DASHARO_VAR_RESIZEABLE_BARS_ENABLED, FixedPcdGetBool (PcdShowPciMenu) && FixedPcdGetBool (PcdPciMenuShowResizeableBars) }, + { DASHARO_VAR_SERIAL_REDIRECTION, FixedPcdGetBool (PcdShowSerialPortMenu) }, + { DASHARO_VAR_SERIAL_REDIRECTION2, FixedPcdGetBool (PcdShowSerialPortMenu) && FixedPcdGetBool (PcdHave2ndUart) }, + { DASHARO_VAR_SLEEP_TYPE, FixedPcdGetBool (PcdShowPowerMenu) && FixedPcdGetBool (PcdPowerMenuShowSleepType) }, + { DASHARO_VAR_SMM_BWP, FixedPcdGetBool (PcdShowSecurityMenu) && FixedPcdGetBool (PcdShowSmmBwp) }, + { DASHARO_VAR_USB_MASS_STORAGE, FixedPcdGetBool (PcdShowUsbMenu) }, + { DASHARO_VAR_USB_STACK, FixedPcdGetBool (PcdShowUsbMenu) }, + { DASHARO_VAR_WATCHDOG, FixedPcdGetBool (PcdShowChipsetMenu) && FixedPcdGetBool (PcdShowOcWdtOptions) }, + { DASHARO_VAR_SMALL_CORE_ACTIVE_COUNT, FixedPcdGetBool (PcdShowCpuMenu) && FixedPcdGetBool (PcdShowCpuCoreDisable) }, + { DASHARO_VAR_CORE_ACTIVE_COUNT, FixedPcdGetBool (PcdShowCpuMenu) && FixedPcdGetBool (PcdShowCpuCoreDisable) }, + { DASHARO_VAR_HYPER_THREADING, FixedPcdGetBool (PcdShowCpuMenu) && FixedPcdGetBool (PcdShowCpuHyperThreading) }, +}; + +/** + Produce a default value for a specified variable. + + @param VarName Name of the variable. + + @retval Default value and its length which is zero for unknown variable name. +**/ +STATIC +VAR_INFO +GetVariableInfo ( + CHAR16 *VarName + ) +{ + VAR_INFO Value; + DASHARO_VAR_DATA Data; + UINTN Size; + UINT32 ExtraAttrs; + + SetMem (&Data, sizeof (Data), 0); + Size = 0; + ExtraAttrs = 0; + + if (StrCmp (VarName, DASHARO_VAR_BATTERY_CONFIG) == 0) { + Data.Battery.StartThreshold = 95; + Data.Battery.StopThreshold = 98; + Size = sizeof (Data.Battery); + } else if (StrCmp (VarName, DASHARO_VAR_BOOT_MANAGER_ENABLED) == 0) { + Data.Boolean = TRUE; + Size = sizeof (Data.Boolean); + } else if (StrCmp (VarName, DASHARO_VAR_CPU_THROTTLING_OFFSET) == 0) { + Data.Uint8 = FixedPcdGet8 (PcdCpuThrottlingOffsetDefault); + Size = sizeof (Data.Uint8); + } else if (StrCmp (VarName, DASHARO_VAR_ENABLE_CAMERA) == 0) { + Data.Boolean = TRUE; + Size = sizeof (Data.Boolean); + } else if (StrCmp (VarName, DASHARO_VAR_ENABLE_WIFI_BT) == 0) { + Data.Boolean = TRUE; + Size = sizeof (Data.Boolean); + } else if (StrCmp (VarName, DASHARO_VAR_FAN_CURVE_OPTION) == 0) { + Data.Uint8 = DASHARO_FAN_CURVE_OPTION_SILENT; + Size = sizeof (Data.Uint8); + } else if (StrCmp (VarName, DASHARO_VAR_IOMMU_CONFIG) == 0) { + Data.Iommu.IommuEnable = FALSE; + Data.Iommu.IommuHandoff = FALSE; + Size = sizeof (Data.Iommu); + } else if (StrCmp (VarName, DASHARO_VAR_LOCK_BIOS) == 0) { + Data.Boolean = TRUE; + Size = sizeof (Data.Boolean); + } else if (StrCmp (VarName, DASHARO_VAR_MEMORY_PROFILE) == 0) { + Data.Uint8 = DASHARO_MEMORY_PROFILE_JEDEC; + Size = sizeof (Data.Uint8); + } else if (StrCmp (VarName, DASHARO_VAR_ME_MODE) == 0) { + Data.Uint8 = FixedPcdGet8 (PcdIntelMeDefaultState); + Size = sizeof (Data.Uint8); + } else if (StrCmp (VarName, DASHARO_VAR_NETWORK_BOOT) == 0) { + Data.Boolean = FixedPcdGetBool (PcdDefaultNetworkBootEnable); + Size = sizeof (Data.Boolean); + } else if (StrCmp (VarName, DASHARO_VAR_OPTION_ROM_POLICY) == 0) { + Data.Uint8 = FixedPcdGetBool (PcdLoadOptionRoms) + ? DASHARO_OPTION_ROM_POLICY_ENABLE_ALL + : DASHARO_OPTION_ROM_POLICY_DISABLE_ALL; + Size = sizeof (Data.Uint8); + } else if (StrCmp (VarName, DASHARO_VAR_POWER_FAILURE_STATE) == 0) { + Data.Uint8 = FixedPcdGet8 (PcdDefaultPowerFailureState); + Size = sizeof (Data.Uint8); + } else if (StrCmp (VarName, DASHARO_VAR_PS2_CONTROLLER) == 0) { + Data.Boolean = TRUE; + Size = sizeof (Data.Boolean); + } else if (StrCmp (VarName, DASHARO_VAR_RESIZEABLE_BARS_ENABLED) == 0) { + Data.Boolean = FALSE; + Size = sizeof (Data.Boolean); + } else if (StrCmp (VarName, DASHARO_VAR_SERIAL_REDIRECTION) == 0) { + Data.Boolean = FixedPcdGetBool (PcdSerialRedirectionDefaultState); + Size = sizeof (Data.Boolean); + ExtraAttrs = EFI_VARIABLE_RUNTIME_ACCESS; + } else if (StrCmp (VarName, DASHARO_VAR_SERIAL_REDIRECTION2) == 0) { + Data.Boolean = FixedPcdGetBool (PcdHave2ndUart) ? FixedPcdGetBool (PcdSerialRedirection2DefaultState) : FALSE; + Size = sizeof (Data.Boolean); + ExtraAttrs = EFI_VARIABLE_RUNTIME_ACCESS; + } else if (StrCmp (VarName, DASHARO_VAR_SLEEP_TYPE) == 0) { + Data.Uint8 = FixedPcdGetBool (PcdSleepTypeDefaultS3) ? DASHARO_SLEEP_TYPE_S3 : DASHARO_SLEEP_TYPE_S0IX; + Size = sizeof (Data.Uint8); + } else if (StrCmp (VarName, DASHARO_VAR_SMM_BWP) == 0) { + Data.Boolean = FALSE; + Size = sizeof (Data.Boolean); + } else if (StrCmp (VarName, DASHARO_VAR_USB_MASS_STORAGE) == 0) { + Data.Boolean = TRUE; + Size = sizeof (Data.Boolean); + } else if (StrCmp (VarName, DASHARO_VAR_USB_STACK) == 0) { + Data.Boolean = TRUE; + Size = sizeof (Data.Boolean); + } else if (StrCmp (VarName, DASHARO_VAR_WATCHDOG) == 0) { + Data.Watchdog.WatchdogEnable = FixedPcdGetBool (PcdOcWdtEnableDefault); + Data.Watchdog.WatchdogTimeout = FixedPcdGet16 (PcdOcWdtTimeoutDefault); + Size = sizeof (Data.Watchdog); + } else if (StrCmp (VarName, DASHARO_VAR_WATCHDOG_AVAILABLE) == 0) { + Data.Boolean = FixedPcdGetBool (PcdShowOcWdtOptions); + Size = sizeof (Data.Boolean); + } else if (StrCmp (VarName, DASHARO_VAR_SMALL_CORE_ACTIVE_COUNT) == 0) { + Data.Uint8 = DASHARO_CPU_CORES_ENABLE_ALL; + Size = sizeof (Data.Uint8); + } else if (StrCmp (VarName, DASHARO_VAR_CORE_ACTIVE_COUNT) == 0) { + Data.Uint8 = DASHARO_CPU_CORES_ENABLE_ALL; + Size = sizeof (Data.Uint8); + } else if (StrCmp (VarName, DASHARO_VAR_HYPER_THREADING) == 0) { + Data.Boolean = FixedPcdGetBool (PcdCpuHyperThreadingDefault); + Size = sizeof (Data.Boolean); + } else { + DEBUG ((EFI_D_ERROR, "%a(): Unknown variable: %s.\n", __FUNCTION__, VarName)); + ASSERT ((0 && "No default value set for a variable.")); + } + + Value.Data = Data; + Value.Size = Size; + Value.Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE | ExtraAttrs; + + return Value; +} + +DASHARO_VAR_DATA +EFIAPI +DasharoGetVariableDefault ( + CHAR16 *VarName + ) +{ + VAR_INFO VarInfo; + + VarInfo = GetVariableInfo (VarName); + if (VarInfo.Size == 0) { + DEBUG ((EFI_D_VERBOSE, "%a(): Failed to look up default for %s.\n", __FUNCTION__, VarName)); + } + + return VarInfo.Data; +} + +UINT32 +EFIAPI +DasharoGetVariableAttributes ( + CHAR16 *VarName + ) +{ + VAR_INFO VarInfo; + + VarInfo = GetVariableInfo (VarName); + if (VarInfo.Size == 0) { + DEBUG ((EFI_D_VERBOSE, "%a(): Failed to look up attributes of %s.\n", __FUNCTION__, VarName)); + } + + return VarInfo.Attributes; +} + +/** + Reset a single Dasharo EFI variable to its default value. + + @param VarName Name of the variable to reset. + + @retval RETURN_SUCCESS Successfully measured all variables. +**/ +STATIC +EFI_STATUS +ResetVariable ( + CHAR16 *VarName + ) +{ + EFI_STATUS Status; + VAR_INFO VarInfo; + + VarInfo = GetVariableInfo (VarName); + if (VarInfo.Size == 0) + return EFI_NOT_FOUND; + + Status = gRT->SetVariable ( + VarName, + &gDasharoSystemFeaturesGuid, + VarInfo.Attributes, + VarInfo.Size, + &VarInfo.Data + ); + + return Status; +} + +/** + Check whether a specified variable exists and create it if it doesn't. + + The variable is created with a default value. + + @param VarName Name of the variable to initialize. +**/ +STATIC +VOID +InitVariable ( + CHAR16 *VarName + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + + BufferSize = 0; + Status = gRT->GetVariable ( + VarName, + &gDasharoSystemFeaturesGuid, + NULL, + &BufferSize, + NULL + ); + + if (Status == EFI_NOT_FOUND) { + Status = ResetVariable (VarName); + ASSERT_EFI_ERROR (Status); + } +} + +/** + Measure a single variable into DASHARO_VAR_PCR with EV_DASHARO_VAR event type. + + @param VarName Name of the variable. + @param Vendor Namespace of the variable. + + @retval EFI_SUCCESS If the variable was read and measured without errors. + @retval EFI_OUT_OF_RESOURCES On memory allocation failure. +**/ +STATIC +EFI_STATUS +MeasureVariable ( + CHAR16 *VarName, + EFI_GUID *Vendor + ) +{ + EFI_STATUS Status; + UINTN PrefixSize; + VOID *VarData; + UINTN VarSize; + CHAR8 *EventData; + + DEBUG ((EFI_D_VERBOSE, "%a(): %g:%s.\r\n", __FUNCTION__, Vendor, VarName)); + + PrefixSize = StrLen (VarName) + 1; + + Status = GetVariable2 (VarName, Vendor, &VarData, &VarSize); + ASSERT_EFI_ERROR (Status); + + EventData = AllocatePool (PrefixSize + VarSize); + if (EventData == NULL) { + FreePool (VarData); + return EFI_OUT_OF_RESOURCES; + } + + UnicodeStrToAsciiStrS (VarName, EventData, PrefixSize); + CopyMem (EventData + PrefixSize, VarData, VarSize); + + Status = TpmMeasureAndLogData ( + DASHARO_VAR_PCR, + EV_DASHARO_VAR, + EventData, + PrefixSize + VarSize, + VarData, + VarSize + ); + + FreePool (EventData); + FreePool (VarData); + + return Status; +} + +/** + A comparison function for sorting an array of variable names. + + @param Buffer1 Pointer to pointer of the first variable name. + @param Buffer2 Pointer to pointer of the second variable name. + + @retval <0 The first variable name is less than the second one. + @retval =0 The names are equal. + @retval >0 The first variable name is greater than the second one. +**/ +STATIC +INTN +EFIAPI +CompareVariableNames ( + IN CONST VOID *Buffer1, + IN CONST VOID *Buffer2 + ) +{ + return StrCmp (*(CONST CHAR16 **) Buffer1, *(CONST CHAR16 **) Buffer2); +} + +/** + Measures single all existing variables with the specified GUID. + + @param Vendor Namespace of the variable. + + @retval EFI_SUCCESS If the variable was read and measured without errors. +**/ +STATIC +EFI_STATUS +MeasureVariables ( + EFI_GUID *Vendor + ) +{ + EFI_STATUS Status; + CHAR16 *Name; + CHAR16 *NewBuf; + UINTN MaxNameSize; + UINTN NameSize; + EFI_GUID Guid; + CHAR16 **Names; + UINTN NameCount; + CHAR16 SortBuf; + UINTN MaxNameCount; + UINTN Index; + + MaxNameSize = 32 * sizeof (CHAR16); + Name = AllocateZeroPool (MaxNameSize); + if (Name == NULL) + return EFI_OUT_OF_RESOURCES; + + MaxNameCount = 32; + NameCount = 0; + Names = AllocatePool (MaxNameCount * sizeof (*Names)); + if (Names == NULL) { + FreePool(Name); + return EFI_OUT_OF_RESOURCES; + } + + while (TRUE) { + NameSize = MaxNameSize; + Status = gRT->GetNextVariableName (&NameSize, Name, &Guid); + if (Status == EFI_BUFFER_TOO_SMALL) { + NewBuf = AllocatePool (NameSize); + if (NewBuf == NULL) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + + StrnCpyS (NewBuf, NameSize / sizeof (CHAR16), Name, MaxNameSize / sizeof (CHAR16)); + FreePool (Name); + + Name = NewBuf; + MaxNameSize = NameSize; + + Status = gRT->GetNextVariableName (&NameSize, Name, &Guid); + } + + if (Status == EFI_NOT_FOUND) { + Status = EFI_SUCCESS; + break; + } + + if (EFI_ERROR (Status)) + break; + + if (!CompareGuid (&Guid, Vendor)) + continue; + + if (NameCount == MaxNameCount - 1) { + Names = ReallocatePool ( + MaxNameCount * sizeof (*Names), + 2 * MaxNameCount * sizeof (*Names), + Names + ); + if (Names == NULL) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + + MaxNameCount *= 2; + } + + Names[NameCount] = AllocateCopyPool (NameSize, Name); + if (Names[NameCount] == NULL) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + + NameCount++; + } + + if (Status == EFI_SUCCESS) { + // + // Achieve predictable ordering of variables by sorting them by name within + // a particular vendor. + // + QuickSort ( + Names, + NameCount, + sizeof (*Names), + CompareVariableNames, + &SortBuf + ); + + for (Index = 0; Index < NameCount; Index++) { + Status = MeasureVariable (Names[Index], Vendor); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_WARN, "%a(): Failed to measure variable: %g:%s.\n", + __FUNCTION__, Vendor, Name)); + } + } + } + + for (Index = 0; Index < NameCount; Index++) + FreePool (Names[Index]); + + FreePool (Name); + FreePool (Names); + return Status; +} + +EFI_STATUS +EFIAPI +DasharoMeasureVariables ( + VOID + ) +{ + EFI_STATUS Status; + + Status = MeasureVariables (&gDasharoSystemFeaturesGuid); + if (Status == EFI_SUCCESS) + Status = MeasureVariables (&gApuConfigurationFormsetGuid); + + return Status; +} + +/** + Enable firmware update mode (FUM) for the next boot. + + @retval RETURN_SUCCESS FUM was successfully enabled. +**/ +EFI_STATUS +EFIAPI +DasharoEnableFUM ( + VOID + ) +{ + EFI_STATUS Status; + BOOLEAN Enable; + + Enable = TRUE; + Status = gRT->SetVariable ( + DASHARO_VAR_FIRMWARE_UPDATE_MODE, + &gDasharoSystemFeaturesGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + sizeof (Enable), + &Enable + ); + + return Status; +} + +/** + Check whether capsule updates which survive a warm system reset are permitted + by current configuration. + + @retval TRUE Persistent capsules can be accepted by UpdateCapsule(). + @retval FALSE UpdateCapsule() must fail with an error for such a capsule. +**/ +BOOLEAN +EFIAPI +DasharoCapsulesCanPersistAcrossReset ( + VOID + ) +{ + EFI_STATUS Status; + UINT8 MeMode; + UINTN VarSize; + + // + // Assuming there is no ME if the corresponding menu is not enabled. + // + if (!FixedPcdGetBool (PcdShowIntelMeMenu)) { + return TRUE; + } + + // + // Guard against variable's value obviously lying about the state. + // + if (!FixedPcdGetBool (PcdIntelMeHapAvailable)) { + return FALSE; + } + + MeMode = DASHARO_ME_MODE_ENABLE; + VarSize = sizeof (MeMode); + + Status = gRT->GetVariable ( + DASHARO_VAR_ME_MODE, + &gDasharoSystemFeaturesGuid, + NULL, + &VarSize, + &MeMode + ); + ASSERT_EFI_ERROR (Status); + + // + // HAP-disabled ME doesn't do anything, including writing to system flash, + // which is what we need for a firmware update that relies on a warm reset. + // coreboot assumes that HECI/soft-disabled state of ME isn't as good as + // HMRFPO and switches to HMRFPO doing a global reset which loses in-RAM + // capsules. + // + // Checking variable's value should be enough, if somebody manually set it to + // an invalid value, the update there will be a reboot without a capsule + // update. A more reliable solution would be to pass this information from + // coreboot. + // + return MeMode == DASHARO_ME_MODE_DISABLE_HAP; +} + +EFI_STATUS +EFIAPI +DasharoVariablesLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + UINTN Idx; + + // Create Dasharo-specific variables that are missing by initializing + // them with default values. + for (Idx = 0; Idx < ARRAY_SIZE (mAutoCreatedVariables); Idx++) { + if (mAutoCreatedVariables[Idx].Condition) + InitVariable (mAutoCreatedVariables[Idx].Name); + } + + return EFI_SUCCESS; +} diff --git a/DasharoModulePkg/Library/DasharoVariablesLib/DasharoVariablesLib.inf b/DasharoModulePkg/Library/DasharoVariablesLib/DasharoVariablesLib.inf new file mode 100644 index 0000000000..0baba7aade --- /dev/null +++ b/DasharoModulePkg/Library/DasharoVariablesLib/DasharoVariablesLib.inf @@ -0,0 +1,86 @@ +# +# A library for providing services related to Dasharo-specific EFI variables. +# +# Copyright (c) 2024, 3mdeb Sp. z o.o. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = DasharoVariablesLib + MODULE_UNI_FILE = DasharoVariablesLib.uni + FILE_GUID = F7C51973-0F61-4955-87D2-710FD578D161 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = DasharoVariablesLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION + CONSTRUCTOR = DasharoVariablesLibConstructor + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + DasharoVariablesLib.c + +[Packages] + DasharoModulePkg/DasharoModulePkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + DasharoPayloadPkg/DasharoPayloadPkg.dec + +[LibraryClasses] + DebugLib + TpmMeasurementLib + PcdLib + UefiLib + +[Guids] + gDasharoSystemFeaturesGuid ### CONSUMES + gApuConfigurationFormsetGuid ### SOMETIMES CONSUMES + +[Pcd] + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowMenu + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowSecurityMenu + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowIntelMeMenu + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowUsbMenu + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowNetworkMenu + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowChipsetMenu + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowPowerMenu + gDasharoSystemFeaturesTokenSpaceGuid.PcdPowerMenuShowFanCurve + gDasharoSystemFeaturesTokenSpaceGuid.PcdDefaultNetworkBootEnable + gDasharoSystemFeaturesTokenSpaceGuid.PcdDasharoEnterprise + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowIommuOptions + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowOcWdtOptions + gDasharoSystemFeaturesTokenSpaceGuid.PcdOcWdtTimeoutDefault + gDasharoSystemFeaturesTokenSpaceGuid.PcdDefaultPowerFailureState + gDasharoSystemFeaturesTokenSpaceGuid.PcdPowerMenuShowSleepType + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowPciMenu + gDasharoSystemFeaturesTokenSpaceGuid.PcdPciMenuShowResizeableBars + gDasharoSystemFeaturesTokenSpaceGuid.PcdPowerMenuShowBatteryThresholds + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowMemoryMenu + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowSerialPortMenu + gDasharoSystemFeaturesTokenSpaceGuid.PcdSerialRedirectionDefaultState + gDasharoSystemFeaturesTokenSpaceGuid.PcdSecurityShowWiFiBtOption + gDasharoSystemFeaturesTokenSpaceGuid.PcdSecurityShowCameraOption + gDasharoSystemFeaturesTokenSpaceGuid.PcdIntelMeDefaultState + gDasharoSystemFeaturesTokenSpaceGuid.PcdIntelMeHapAvailable + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowLockBios + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowSmmBwp + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowPs2Option + gDasharoSystemFeaturesTokenSpaceGuid.PcdSleepTypeDefaultS3 + gDasharoSystemFeaturesTokenSpaceGuid.PcdSerialRedirection2DefaultState + gDasharoSystemFeaturesTokenSpaceGuid.PcdHave2ndUart + gDasharoSystemFeaturesTokenSpaceGuid.PcdOcWdtEnableDefault + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowCpuThrottlingThreshold + gDasharoSystemFeaturesTokenSpaceGuid.PcdCpuMaxTemperature + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowCpuMenu + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowCpuCoreDisable + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowCpuHyperThreading + gDasharoSystemFeaturesTokenSpaceGuid.PcdCpuHyperThreadingDefault + gDasharoSystemFeaturesTokenSpaceGuid.PcdCpuThrottlingOffsetDefault + + gDasharoPayloadPkgTokenSpaceGuid.PcdLoadOptionRoms diff --git a/DasharoModulePkg/Library/DasharoVariablesLib/DasharoVariablesLib.uni b/DasharoModulePkg/Library/DasharoVariablesLib/DasharoVariablesLib.uni new file mode 100644 index 0000000000..838e60e2b1 --- /dev/null +++ b/DasharoModulePkg/Library/DasharoVariablesLib/DasharoVariablesLib.uni @@ -0,0 +1,13 @@ +// /** @file +// A library for providing services related to Dasharo-specific EFI variables. +// +// Copyright (c) 2024, 3mdeb Sp. z o.o. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "DasharoVariablesLib library provides services related to Dasharo-specific EFI variables." + +#string STR_MODULE_DESCRIPTION #language en-US "DasharoVariablesLib library exposes list of Dasharo-specific variables and a few functions related to handling them." diff --git a/DasharoModulePkg/Library/PlatformPasswordLibNull/PlatformPasswordLibNull.c b/DasharoModulePkg/Library/PlatformPasswordLibNull/PlatformPasswordLibNull.c new file mode 100644 index 0000000000..23c293976d --- /dev/null +++ b/DasharoModulePkg/Library/PlatformPasswordLibNull/PlatformPasswordLibNull.c @@ -0,0 +1,77 @@ +/** @file + NULL PlatformPasswordLib instance does NOT really detect whether the password is cleared + but returns the PCD value directly. This instance can be used to verify security + related features during platform enabling and development. It should be replaced + by a platform-specific method(e.g. Button pressed) in a real platform for product. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +BOOLEAN mPasswordCleared = FALSE; + +/** + This function is called at password driver entrypoint. + This function should be called only once, to clear the password. + + This function provides a way to reset the password, just in case + the platform owner forgets the password. + The platform should provide a secure way to make sure + only the platform owner is allowed to clear password. + + Once the password is cleared, the platform should provide a way + to set a new password. + + @retval TRUE There is a platform request to clear the password. + @retval FALSE There is no platform request to clear the password. +**/ +BOOLEAN +EFIAPI +IsPasswordCleared ( + VOID + ) +{ + return mPasswordCleared; +} + +/** + This function is called if the password driver finds that the password is not enrolled, + when the password is required to input. + + This function should return the action according to platform policy. + + @retval TRUE The caller should force the user to enroll the password. + @retval FALSE The caller may skip the password enroll. +**/ +BOOLEAN +EFIAPI +NeedEnrollPassword ( + VOID + ) +{ + return FALSE; +} + + +/** + Save password clear state from a PCD to mPasswordCleared. + + @param ImageHandle ImageHandle of the loaded driver. + @param SystemTable Pointer to the EFI System Table. + + @retval EFI_SUCCESS PcdPasswordCleared is got successfully. + +**/ +EFI_STATUS +EFIAPI +PlatformPasswordLibNullConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + + mPasswordCleared = PcdGetBool(PcdPasswordCleared); + + return EFI_SUCCESS; +} diff --git a/DasharoModulePkg/Library/PlatformPasswordLibNull/PlatformPasswordLibNull.inf b/DasharoModulePkg/Library/PlatformPasswordLibNull/PlatformPasswordLibNull.inf new file mode 100644 index 0000000000..0e6bfe2e5e --- /dev/null +++ b/DasharoModulePkg/Library/PlatformPasswordLibNull/PlatformPasswordLibNull.inf @@ -0,0 +1,38 @@ +## @file +# NULL platform password library instance that returns the password clear state based upon PCD. +# +# NULL PlatformPasswordLib instance does NOT really detect whether the password is cleared +# but returns the PCD value directly. This instance can be used to verify security +# related features during platform enabling and development. It should be replaced +# by a platform-specific method(e.g. Button pressed) in a real platform for product. +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = PlatformPasswordLibNull + MODULE_UNI_FILE = PlatformPasswordLibNull.uni + FILE_GUID = 27417BCA-0CCD-4089-9711-AD069A33C555 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = PlatformPasswordLib|DXE_RUNTIME_DRIVER DXE_DRIVER UEFI_APPLICATION + CONSTRUCTOR = PlatformPasswordLibNullConstructor + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + PlatformPasswordLibNull.c + +[Packages] + MdePkg/MdePkg.dec + DasharoModulePkg/DasharoModulePkg.dec + +[Pcd] + gUserAuthFeaturePkgTokenSpaceGuid.PcdPasswordCleared ## CONSUMES diff --git a/DasharoModulePkg/Library/PlatformPasswordLibNull/PlatformPasswordLibNull.uni b/DasharoModulePkg/Library/PlatformPasswordLibNull/PlatformPasswordLibNull.uni new file mode 100644 index 0000000000..a6b218306a --- /dev/null +++ b/DasharoModulePkg/Library/PlatformPasswordLibNull/PlatformPasswordLibNull.uni @@ -0,0 +1,18 @@ +// /** @file +// NULL platform password library instance that returns the password clear state based upon PCD. +// +// NULL PlatformPasswordLib instance does NOT really detect whether the password is cleared +// but returns the PCD value directly. This instance can be used to verify security +// related features during platform enabling and development. It should be replaced +// by a platform-specific method(e.g. Button pressed) in a real platform for product. +// +// Copyright (c) 2019, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "NULL platform password library instance that returns the password clear state based upon PCD." + +#string STR_MODULE_DESCRIPTION #language en-US "NULL PlatformPasswordLib instance does NOT really detect whether the password is cleared but returns the PCD value directly. This instance can be used to verify security related features during platform enabling and development. It should be replaced by a platform-specific method(e.g. Button pressed) in a real platform for product." diff --git a/DasharoModulePkg/README.md b/DasharoModulePkg/README.md new file mode 100644 index 0000000000..6ca6fe1533 --- /dev/null +++ b/DasharoModulePkg/README.md @@ -0,0 +1,2 @@ +# DasharoModulePkg +EDK2 modules for Dasharo systems diff --git a/DasharoModulePkg/UserAuthenticationDxe/KeyService.c b/DasharoModulePkg/UserAuthenticationDxe/KeyService.c new file mode 100644 index 0000000000..8b06e58ca5 --- /dev/null +++ b/DasharoModulePkg/UserAuthenticationDxe/KeyService.c @@ -0,0 +1,133 @@ +/** @file + Password key service. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include "KeyService.h" + +/** + Compares the contents of two buffers with slow algorithm + + 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 -1 The SourceBuffer is not identical to DestinationBuffer. + +**/ +INTN +EFIAPI +KeyLibSlowCompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + UINT8 Delta; + UINTN Index; + UINT8 *Destination; + UINT8 *Source; + + Destination = (UINT8 *)DestinationBuffer; + Source = (UINT8 *)SourceBuffer; + Delta = 0; + for (Index = 0; Index < Length; Index++) { + Delta |= Destination[Index] ^ Source[Index]; + } + if (Delta == 0) { + return 0; + } else { + return -1; + } +} + +/** + Generate Salt value. + + @param[in, out] SaltValue Points to the salt buffer + @param[in] SaltSize Size of the salt buffer + + @retval TRUE Salt is generated. + @retval FALSE Salt is not generated. +**/ +BOOLEAN +EFIAPI +KeyLibGenerateSalt ( + IN OUT UINT8 *SaltValue, + IN UINTN SaltSize + ) +{ + if (SaltValue == NULL) { + return FALSE; + } + RandomSeed(NULL, 0); + RandomBytes(SaltValue, SaltSize); + return TRUE; +} + +/** + Hash the password with PBKDF2. + + @param[in] HashType Hash type + @param[in] Key Points to the key buffer + @param[in] KeySize Key buffer size + @param[in] SaltValue Points to the salt buffer + @param[in] SaltSize Size of the salt buffer + @param[out] KeyHash Points to the hashed result + @param[in] KeyHashSize Size of the hash buffer + + @retval TRUE Hash the data successfully. + @retval FALSE Failed to hash the data. + +**/ +BOOLEAN +EFIAPI +KeyLibGeneratePBKDF2Hash ( + IN UINT32 HashType, + IN VOID *Key, + IN UINTN KeySize, + IN UINT8 *SaltValue, + IN UINTN SaltSize, + OUT UINT8 *KeyHash, + IN UINTN KeyHashSize + ) +{ + BOOLEAN Result; + + if (HashType != HASH_TYPE_SHA256) { + return FALSE; + } + if (KeyHashSize != SHA256_DIGEST_SIZE) { + return FALSE; + } + + Result = Pkcs5HashPassword ( + KeySize, + Key, + SaltSize, + SaltValue, + DEFAULT_PBKDF2_ITERATION_COUNT, + SHA256_DIGEST_SIZE, + KeyHashSize, + KeyHash + ); + return Result; +} diff --git a/DasharoModulePkg/UserAuthenticationDxe/KeyService.h b/DasharoModulePkg/UserAuthenticationDxe/KeyService.h new file mode 100644 index 0000000000..f030f36f1c --- /dev/null +++ b/DasharoModulePkg/UserAuthenticationDxe/KeyService.h @@ -0,0 +1,87 @@ +/** @file + Header file for key service. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __KEY_LIB_H__ +#define __KEY_LIB_H__ + +/** + Compares the contents of two buffers with slow algorithm + + 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 -1 The SourceBuffer is not identical to DestinationBuffer. + +**/ +INTN +EFIAPI +KeyLibSlowCompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ); + +/** + Generate Salt value. + + @param[in, out] SaltValue Points to the salt buffer + @param[in] SaltSize Size of the salt buffer + + @retval TRUE Salt is generated. + @retval FALSE Salt is not generated. +**/ +BOOLEAN +EFIAPI +KeyLibGenerateSalt( + IN OUT UINT8 *SaltValue, + IN UINTN SaltSize + ); + +#define HASH_TYPE_SHA256 0x000B +#define DEFAULT_PBKDF2_ITERATION_COUNT 1000 + +/** + Hash the password with PBKDF2. + + @param[in] HashType Hash type + @param[in] Key Points to the key buffer + @param[in] KeySize Key buffer size + @param[in] SaltValue Points to the salt buffer + @param[in] SaltSize Size of the salt buffer + @param[out] KeyHash Points to the hashed result + @param[in] KeyHashSize Size of the hash buffer + + @retval TRUE Hash the data successfully. + @retval FALSE Failed to hash the data. + +**/ +BOOLEAN +EFIAPI +KeyLibGeneratePBKDF2Hash ( + IN UINT32 HashType, + IN VOID *Key, + IN UINTN KeySize, + IN UINT8 *SaltValue, + IN UINTN SaltSize, + OUT UINT8 *KeyHash, + IN UINTN KeyHashSize + ); + +#endif diff --git a/DasharoModulePkg/UserAuthenticationDxe/UserAuthenticationDxe.c b/DasharoModulePkg/UserAuthenticationDxe/UserAuthenticationDxe.c new file mode 100644 index 0000000000..7ac2f8b3e3 --- /dev/null +++ b/DasharoModulePkg/UserAuthenticationDxe/UserAuthenticationDxe.c @@ -0,0 +1,772 @@ +/** @file + This Driver mainly provides Setup Form to change password and + does user authentication before entering Setup. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "UserAuthenticationDxe.h" + +EFI_EVENT mExitBootServicesEvent = NULL; +EFI_RSC_HANDLER_PROTOCOL *mRscHandlerProtocol = NULL; +USER_AUTHENTICATION_PRIVATE_DATA *mUserAuthenticationData = NULL; + +EFI_GUID mUserAuthenticationVendorGuid = USER_AUTHENTICATION_FORMSET_GUID; +HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + USER_AUTHENTICATION_FORMSET_GUID + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + +/** + Get a user input string. + + @param[in] PopUpString A popup string to inform user. + @param[in, out] UserInput The user input string + @param[in] UserInputMaxLen The max unicode count of the UserInput without NULL terminator. +**/ +EFI_STATUS +GetUserInput ( + IN CHAR16 *PopUpString, + IN OUT CHAR16 *UserInput, + IN UINTN UserInputMaxLen + ) +{ + EFI_INPUT_KEY InputKey; + UINTN InputLength; + CHAR16 *Mask; + + UserInput[0] = 0; + Mask = AllocateZeroPool ((UserInputMaxLen + 1) * sizeof(CHAR16)); + if (Mask == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + InputLength = 0; + + while (TRUE) { + if (InputLength < UserInputMaxLen) { + Mask[InputLength] = L'_'; + } + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &InputKey, + PopUpString, + L"--------------------------------", + Mask, + NULL + ); + if (InputKey.ScanCode == SCAN_NULL) { + // + // Check whether finish inputing password. + // + if (InputKey.UnicodeChar == CHAR_CARRIAGE_RETURN && InputLength > 0) { + // + // Add the null terminator. + // + UserInput[InputLength] = 0; + break; + } else if ((InputKey.UnicodeChar == CHAR_NULL) || + (InputKey.UnicodeChar == CHAR_LINEFEED) || + (InputKey.UnicodeChar == CHAR_CARRIAGE_RETURN) + ) { + continue; + } else { + // + // delete last key entered + // + if (InputKey.UnicodeChar == CHAR_BACKSPACE) { + if (InputLength > 0) { + UserInput[InputLength] = 0; + Mask[InputLength] = 0; + InputLength--; + } + } else { + if (InputLength == UserInputMaxLen) { + Mask[InputLength] = 0; + continue; + } + // + // add Next key entry + // + UserInput[InputLength] = InputKey.UnicodeChar; + Mask[InputLength] = L'*'; + InputLength++; + } + } + } + } + FreePool (Mask); + return EFI_SUCCESS; +} + +/** + Display a message box to end user. + + @param[in] DisplayString The string in message box. +**/ +VOID +MessageBox ( + IN CHAR16 *DisplayString + ) +{ + EFI_INPUT_KEY Key; + + do { + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"", + DisplayString, + L"Press ENTER to continue ...", + L"", + NULL + ); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); +} + +/** + Force system reset. +**/ +VOID +ForceSystemReset ( + VOID + ) +{ + MessageBox (L"Password retry count reach, reset system!"); + gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); + CpuDeadLoop(); +} + +/** + Display message for set password. + + @param[in] ReturnStatus The return status for set password. +**/ +VOID +PrintSetPasswordStatus ( + IN EFI_STATUS ReturnStatus + ) +{ + CHAR16 *DisplayString; + CHAR16 *DisplayString2; + + EFI_INPUT_KEY Key; + + if (ReturnStatus == EFI_UNSUPPORTED) { + DisplayString = L"New password is not strong enough!"; + DisplayString2 = L"Password must be at least 8 chars"; + + do { + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"", + DisplayString, + DisplayString2, + L"Press ENTER to continue ...", + L"", + NULL + ); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + } else { + if (ReturnStatus == EFI_SUCCESS) { + DisplayString = L"New password is updated successfully!"; + } else if (ReturnStatus == EFI_ALREADY_STARTED) { + DisplayString = L"New password is found in the history passwords!"; + } else { + DisplayString = L"New password update fails!"; + } + + do { + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"", + DisplayString, + L"Press ENTER to continue ...", + L"", + NULL + ); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + } +} + +/** + Require user input password. + + @retval TRUE User input correct password successfully. + @retval FALSE The password is not set. +**/ +BOOLEAN +RequireUserPassword ( + VOID + ) +{ + EFI_STATUS Status; + CHAR16 UserInputPw[PASSWORD_MAX_SIZE]; + CHAR16 *PopUpString; + PASSWORD_COMMUNICATE_VERIFY_POLICY VerifyPolicy; + + Status = EFI_SUCCESS; + ZeroMem(UserInputPw, sizeof(UserInputPw)); + + if (!IsPasswordInstalled ()) { + return FALSE; + } + + Status = GetPasswordVerificationPolicy (&VerifyPolicy); + if (!EFI_ERROR (Status)) { + if (WasPasswordVerified() && (!VerifyPolicy.NeedReVerify)) { + DEBUG ((DEBUG_INFO, "Password was verified and Re-verify is not needed\n")); + return TRUE; + } + } + + PopUpString = L"Please input admin password"; + + while (TRUE) { + gST->ConOut->ClearScreen(gST->ConOut); + GetUserInput (PopUpString, UserInputPw, PASSWORD_MAX_SIZE - 1); + + Status = VerifyPassword (UserInputPw, StrSize(UserInputPw)); + if (!EFI_ERROR(Status)) { + break; + } + if (Status == EFI_ACCESS_DENIED) { + // + // Password retry count reach. + // + ForceSystemReset (); + } + MessageBox (L"Incorrect password!"); + } + + ZeroMem(UserInputPw, sizeof(UserInputPw)); + + gST->ConOut->ClearScreen(gST->ConOut); + + return TRUE; +} + +/** + Set user password. + +**/ +VOID +SetUserPassword ( + VOID + ) +{ + EFI_STATUS Status; + CHAR16 UserInputPw[PASSWORD_MAX_SIZE]; + CHAR16 TmpPassword[PASSWORD_MAX_SIZE]; + CHAR16 *PopUpString; + CHAR16 *PopUpString2; + + ZeroMem(UserInputPw, sizeof(UserInputPw)); + ZeroMem(TmpPassword, sizeof(TmpPassword)); + + PopUpString = L"Please set admin password"; + + while (TRUE) { + gST->ConOut->ClearScreen(gST->ConOut); + GetUserInput (PopUpString, UserInputPw, PASSWORD_MAX_SIZE - 1); + + PopUpString2 = L"Please confirm your new password"; + gST->ConOut->ClearScreen(gST->ConOut); + GetUserInput (PopUpString2, TmpPassword, PASSWORD_MAX_SIZE - 1); + if (StrCmp (TmpPassword, UserInputPw) != 0) { + MessageBox (L"Password are not the same!"); + continue; + } + + Status = SetPassword (UserInputPw, StrSize(UserInputPw), NULL, 0); + PrintSetPasswordStatus (Status); + if (!EFI_ERROR(Status)) { + break; + } + } + + ZeroMem(UserInputPw, sizeof(UserInputPw)); + ZeroMem(TmpPassword, sizeof(TmpPassword)); + + gST->ConOut->ClearScreen(gST->ConOut); +} + +/** + Check password before entering into setup. + + @param CodeType Indicates the type of status code being reported. Type EFI_STATUS_CODE_TYPE is defined in "Related Definitions" below. + + @param Value Describes the current status of a hardware or software entity. + This included information about the class and subclass that is used to classify the entity + as well as an operation. For progress codes, the operation is the current activity. + For error codes, it is the exception. For debug codes, it is not defined at this time. + Type EFI_STATUS_CODE_VALUE is defined in "Related Definitions" below. + Specific values are discussed in the Intel? Platform Innovation Framework for EFI Status Code Specification. + + @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. + Type EFI_GUID is defined in InstallProtocolInterface() in the UEFI 2.0 Specification. + + + @param Data This optional parameter may be used to pass additional data + + @retval EFI_SUCCESS Status code is what we expected. + @retval EFI_UNSUPPORTED Status code not supported. + +**/ +EFI_STATUS +EFIAPI +CheckForPassword ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId, OPTIONAL + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ) +{ + BOOLEAN PasswordSet; + + if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) && + (Value == (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_USER_SETUP))) { + // + // Check whether enter setup page. + // + PasswordSet = RequireUserPassword (); + if (PasswordSet) { + DEBUG ((DEBUG_INFO, "Welcome Admin!\n")); + } else { + DEBUG ((DEBUG_INFO, "Admin password is not set!\n")); + if (NeedEnrollPassword()) { + SetUserPassword (); + } + } + + return EFI_SUCCESS; + } else{ + return EFI_UNSUPPORTED; + } +} + +/** + This function allows a caller to extract the current configuration for one + or more named elements from the target driver. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Request A null-terminated Unicode string in + format. + @param Progress On return, points to a character in the Request + string. Points to the string's null terminator if + request was successful. Points to the most recent + '&' before the first failing name/value pair (or + the beginning of the string if the failure is in + the first name/value pair) if the request was not + successful. + @param Results A null-terminated Unicode string in + format which has all values filled + in for the names in the Request string. String to + be allocated by the called function. + + @retval EFI_SUCCESS The Results is filled with the requested values. + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. + @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this + driver. + +**/ +EFI_STATUS +EFIAPI +ExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results + ) +{ + if (Progress == NULL || Results == NULL) { + return EFI_INVALID_PARAMETER; + } + *Progress = Request; + return EFI_NOT_FOUND; +} + + +/** + This function processes the results of changes in configuration. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Configuration A null-terminated Unicode string in + format. + @param Progress A pointer to a string filled in with the offset of + the most recent '&' before the first failing + name/value pair (or the beginning of the string if + the failure is in the first name/value pair) or + the terminating NULL if all was successful. + + @retval EFI_SUCCESS The Results is processed successfully. + @retval EFI_INVALID_PARAMETER Configuration is NULL. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this + driver. + +**/ +EFI_STATUS +EFIAPI +RouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress + ) +{ + if (Configuration == NULL || Progress == NULL) { + return EFI_INVALID_PARAMETER; + } + + *Progress = Configuration; + + return EFI_NOT_FOUND; +} + +/** + HII update Admin Password status. + +**/ +VOID +HiiUpdateAdminPasswordStatus ( + VOID + ) +{ + if (IsPasswordInstalled ()) { + HiiSetString ( + mUserAuthenticationData->HiiHandle, + STRING_TOKEN (STR_ADMIN_PASSWORD_STS_CONTENT), + L"Installed", + NULL + ); + } else { + HiiSetString ( + mUserAuthenticationData->HiiHandle, + STRING_TOKEN (STR_ADMIN_PASSWORD_STS_CONTENT), + L"Not Installed", + NULL + ); + } +} + +/** + This function processes the results of changes in configuration. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original + exporting driver so that it can identify the type + of data to expect. + @param Type The type of value for the question. + @param Value A pointer to the data being sent to the original + exporting driver. + @param ActionRequest On return, points to the action requested by the + callback function. + + @retval EFI_SUCCESS The callback successfully handled the action. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the + variable and its data. + @retval EFI_DEVICE_ERROR The variable could not be saved. + @retval EFI_UNSUPPORTED The specified Action is not supported by the + callback. + +**/ +EFI_STATUS +EFIAPI +UserAuthenticationCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) +{ + EFI_STATUS Status; + CHAR16 *UserInputPassword; + + Status = EFI_SUCCESS; + + if (((Value == NULL) && (Action != EFI_BROWSER_ACTION_FORM_OPEN) && (Action != EFI_BROWSER_ACTION_FORM_CLOSE)) || + (ActionRequest == NULL)) { + return EFI_INVALID_PARAMETER; + } + + switch (Action) { + case EFI_BROWSER_ACTION_FORM_OPEN: + { + switch (QuestionId) { + case ADMIN_PASSWORD_KEY_ID: + HiiUpdateAdminPasswordStatus (); + default: + break; + } + } + break; + case EFI_BROWSER_ACTION_CHANGING: + { + switch (QuestionId) { + case ADMIN_PASSWORD_KEY_ID: + if ((Type == EFI_IFR_TYPE_STRING) && (Value->string == 0) && + (mUserAuthenticationData->PasswordState == BROWSER_STATE_SET_PASSWORD)) { + mUserAuthenticationData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD; + ZeroMem (mUserAuthenticationData->OldPassword, sizeof(mUserAuthenticationData->OldPassword)); + return EFI_INVALID_PARAMETER; + } + // + // The Callback is responsible for validating old password input by user, + // If Callback return EFI_SUCCESS, it indicates validation pass. + // + switch (mUserAuthenticationData->PasswordState) { + case BROWSER_STATE_VALIDATE_PASSWORD: + UserInputPassword = HiiGetString (mUserAuthenticationData->HiiHandle, Value->string, NULL); + if ((StrLen (UserInputPassword) >= PASSWORD_MAX_SIZE)) { + Status = EFI_NOT_READY; + break; + } + if (UserInputPassword[0] == 0) { + // + // Setup will use a NULL password to check whether the old password is set, + // If the validation is successful, means there is no old password, return + // success to set the new password. Or need to return EFI_NOT_READY to + // let user input the old password. + // + Status = VerifyPassword (UserInputPassword, StrSize (UserInputPassword)); + if (Status == EFI_SUCCESS) { + mUserAuthenticationData->PasswordState = BROWSER_STATE_SET_PASSWORD; + } else { + Status = EFI_NOT_READY; + } + break; + } + Status = VerifyPassword (UserInputPassword, StrSize (UserInputPassword)); + if (Status == EFI_SUCCESS) { + mUserAuthenticationData->PasswordState = BROWSER_STATE_SET_PASSWORD; + StrCpyS ( + mUserAuthenticationData->OldPassword, + sizeof(mUserAuthenticationData->OldPassword)/sizeof(CHAR16), + UserInputPassword + ); + } else { + // + // Old password mismatch, return EFI_NOT_READY to prompt for error message. + // + if (Status == EFI_ACCESS_DENIED) { + // + // Password retry count reach. + // + ForceSystemReset (); + } + Status = EFI_NOT_READY; + } + break; + + case BROWSER_STATE_SET_PASSWORD: + UserInputPassword = HiiGetString (mUserAuthenticationData->HiiHandle, Value->string, NULL); + if ((StrLen (UserInputPassword) >= PASSWORD_MAX_SIZE)) { + Status = EFI_NOT_READY; + break; + } + Status = SetPassword (UserInputPassword, StrSize (UserInputPassword), mUserAuthenticationData->OldPassword, StrSize(mUserAuthenticationData->OldPassword)); + PrintSetPasswordStatus (Status); + ZeroMem (mUserAuthenticationData->OldPassword, sizeof(mUserAuthenticationData->OldPassword)); + mUserAuthenticationData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD; + HiiUpdateAdminPasswordStatus (); + break; + + default: + break; + } + default: + break; + } + } + break; + default: + break; + } + return Status; +} + +/** + Unregister status code callback functions. + + @param Event Event whose notification function is being invoked. + @param Context Pointer to the notification function's context, which is + always zero in current implementation. + +**/ +VOID +EFIAPI +UnregisterBootTimeHandlers ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + mRscHandlerProtocol->Unregister (CheckForPassword); +} + +/** + User Authentication entry point. + + @param ImageHandle The image handle. + @param SystemTable The system table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @return other Contain some other errors. + +**/ +EFI_STATUS +EFIAPI +UserAuthenticationEntry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE DriverHandle; + EFI_HII_HANDLE HiiHandle; + + DriverHandle = NULL; + + mUserAuthenticationData = AllocateZeroPool (sizeof (USER_AUTHENTICATION_PRIVATE_DATA)); + if (mUserAuthenticationData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + mUserAuthenticationData->ConfigAccess.ExtractConfig = ExtractConfig; + mUserAuthenticationData->ConfigAccess.RouteConfig = RouteConfig; + mUserAuthenticationData->ConfigAccess.Callback = UserAuthenticationCallback; + mUserAuthenticationData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD; + + // + // Install Config Access protocol to driver handle. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mUserAuthenticationData->ConfigAccess, + NULL + ); + ASSERT_EFI_ERROR (Status); + mUserAuthenticationData->DriverHandle = DriverHandle; + + // + // Add HII data to database. + // + HiiHandle = HiiAddPackages ( + &mUserAuthenticationVendorGuid, + DriverHandle, + UserAuthenticationDxeStrings, + UserAuthenticationDxeVfrBin, + NULL + ); + if (HiiHandle == NULL) { + return EFI_OUT_OF_RESOURCES; + } + mUserAuthenticationData->HiiHandle = HiiHandle; + + // + // Locate report status code protocol. + // + Status = gBS->LocateProtocol ( + &gEfiRscHandlerProtocolGuid, + NULL, + (VOID **) &mRscHandlerProtocol + ); + ASSERT_EFI_ERROR (Status); + + // + //Register the callback function for ReportStatusCode() notification. + // + mRscHandlerProtocol->Register (CheckForPassword, TPL_HIGH_LEVEL); + + // + // Unregister boot time report status code listener at ExitBootService Event. + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + UnregisterBootTimeHandlers, + NULL, + &gEfiEventExitBootServicesGuid, + &mExitBootServicesEvent + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + +/** + Unloads the application and its installed protocol. + + @param[in] ImageHandle Handle that identifies the image to be unloaded. + + @retval EFI_SUCCESS The image has been unloaded. +**/ +EFI_STATUS +EFIAPI +UserAuthenticationUnload ( + IN EFI_HANDLE ImageHandle + ) +{ + ASSERT (mUserAuthenticationData != NULL); + + // + // Uninstall Config Access Protocol. + // + if (mUserAuthenticationData->DriverHandle != NULL) { + gBS->UninstallMultipleProtocolInterfaces ( + mUserAuthenticationData->DriverHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mUserAuthenticationData->ConfigAccess, + NULL + ); + mUserAuthenticationData->DriverHandle = NULL; + } + + // + // Remove Hii Data. + // + if (mUserAuthenticationData->HiiHandle != NULL) { + HiiRemovePackages (mUserAuthenticationData->HiiHandle); + } + + FreePool (mUserAuthenticationData); + mUserAuthenticationData = NULL; + + return EFI_SUCCESS; +} diff --git a/DasharoModulePkg/UserAuthenticationDxe/UserAuthenticationDxe.h b/DasharoModulePkg/UserAuthenticationDxe/UserAuthenticationDxe.h new file mode 100644 index 0000000000..86694ad15c --- /dev/null +++ b/DasharoModulePkg/UserAuthenticationDxe/UserAuthenticationDxe.h @@ -0,0 +1,136 @@ +/** @file + Header file for UserAuthenticationDxe. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _USER_AUTHENTICATION_DXE_H_ +#define _USER_AUTHENTICATION_DXE_H_ + + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "UserAuthenticationDxeFormset.h" +#include "KeyService.h" + +extern UINT8 UserAuthenticationDxeVfrBin[]; +extern UINT8 UserAuthenticationDxeStrings[]; + +typedef struct { + EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess; + EFI_HANDLE DriverHandle; + EFI_HII_HANDLE HiiHandle; + UINT8 PasswordState; + CHAR16 OldPassword[PASSWORD_MAX_SIZE]; +} USER_AUTHENTICATION_PRIVATE_DATA; + +#pragma pack(1) +/// +/// HII specific Vendor Device Path definition. +/// +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + EFI_DEVICE_PATH_PROTOCOL End; +} HII_VENDOR_DEVICE_PATH; +#pragma pack() + +/** + Validate if the password is correct. + + @param[in] Password The user input password. + @param[in] PasswordSize The size of Password in byte. + + @retval EFI_SUCCESS The password is correct. + @retval EFI_SECURITY_VIOLATION The password is incorrect. + @retval EFI_INVALID_PARAMETER The password or size is invalid. + @retval EFI_OUT_OF_RESOURCES Insufficient resources to verify the password. + @retval EFI_ACCESS_DENIED Password retry count reach. +**/ +EFI_STATUS +VerifyPassword ( + IN CHAR16 *Password, + IN UINTN PasswordSize + ); + +/** + Set a new password. + + @param[in] NewPassword The user input new password. + NULL means clear password. + @param[in] NewPasswordSize The size of NewPassword in byte. + @param[in] OldPassword The user input old password. + NULL means no old password. + @param[in] OldPasswordSize The size of OldPassword in byte. + + @retval EFI_SUCCESS The NewPassword is set successfully. + @retval EFI_SECURITY_VIOLATION The OldPassword is incorrect. + @retval EFI_INVALID_PARAMETER The password or size is invalid. + @retval EFI_OUT_OF_RESOURCES Insufficient resources to set the password. + @retval EFI_ACCESS_DENIED Password retry count reach. + @retval EFI_UNSUPPORTED NewPassword is not strong enough. + @retval EFI_ALREADY_STARTED NewPassword is in history. +**/ +EFI_STATUS +SetPassword ( + IN CHAR16 *NewPassword, OPTIONAL + IN UINTN NewPasswordSize, + IN CHAR16 *OldPassword, OPTIONAL + IN UINTN OldPasswordSize + ); + +/** + Return if the password is set. + + @retval TRUE The password is set. + @retval FALSE The password is not set. +**/ +BOOLEAN +IsPasswordInstalled ( + VOID + ); + +/** + Get password verification policy. + + @param[out] VerifyPolicy Verification policy. + + @retval EFI_SUCCESS Get verification policy successfully. + @retval EFI_OUT_OF_RESOURCES Insufficient resources to get verification policy. +**/ +EFI_STATUS +GetPasswordVerificationPolicy ( + OUT PASSWORD_COMMUNICATE_VERIFY_POLICY *VerifyPolicy + ); + +/** + Return if the password was verified. + + @retval TRUE The password was verified. + @retval FALSE The password was not verified. +**/ +BOOLEAN +WasPasswordVerified ( + VOID + ); + +#endif diff --git a/DasharoModulePkg/UserAuthenticationDxe/UserAuthenticationDxe.inf b/DasharoModulePkg/UserAuthenticationDxe/UserAuthenticationDxe.inf new file mode 100644 index 0000000000..bc8f97538e --- /dev/null +++ b/DasharoModulePkg/UserAuthenticationDxe/UserAuthenticationDxe.inf @@ -0,0 +1,64 @@ +## @file +# User Authentication Dxe Driver. +# +# This Driver mainly provides Setup Form to change password and +# does user authentication before entering Setup. +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UserAuthenticationDxe + FILE_GUID = 0683FB88-664C-4BA6-9ED4-1C0916EE43A4 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 2.0 + ENTRY_POINT = UserAuthenticationEntry + UNLOAD_IMAGE = UserAuthenticationUnload + +[Sources] + UserAuthenticationDxe.c + UserAuthenticationDxe.h + UserAuthenticationDxePassword.c + UserAuthenticationDxeFormset.h + UserAuthenticationDxeVfr.vfr + UserAuthenticationDxeStrings.uni + KeyService.c + KeyService.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + CryptoPkg/CryptoPkg.dec + DasharoModulePkg/DasharoModulePkg.dec + +[LibraryClasses] + BaseLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiRuntimeServicesTableLib + BaseMemoryLib + DebugLib + UefiLib + BaseCryptLib + HiiLib + DevicePathLib + MemoryAllocationLib + PlatformPasswordLib + PrintLib + +[Guids] + gUserAuthenticationGuid ## CONSUMES ## GUID + gEfiEventExitBootServicesGuid ## CONSUMES ## Event + gEfiIfrFrontPageGuid ## CONSUMES ## GUID (Indicate the formset in this library need to display in which page) + +[Protocols] + gEfiRscHandlerProtocolGuid ## CONSUMES + gEfiDevicePathProtocolGuid ## PRODUCES + gEfiHiiConfigAccessProtocolGuid ## PRODUCES + +[Depex] + gEfiSimpleTextOutProtocolGuid AND + gEfiVariableArchProtocolGuid AND + gEfiVariableWriteArchProtocolGuid diff --git a/DasharoModulePkg/UserAuthenticationDxe/UserAuthenticationDxeFormset.h b/DasharoModulePkg/UserAuthenticationDxe/UserAuthenticationDxeFormset.h new file mode 100644 index 0000000000..a88996cfac --- /dev/null +++ b/DasharoModulePkg/UserAuthenticationDxe/UserAuthenticationDxeFormset.h @@ -0,0 +1,23 @@ +/** @file + Header file for UserAuthentication formset. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _USER_AUTHENTICATION_DXE_FORMSET_H_ +#define _USER_AUTHENTICATION_DXE_FORMSET_H_ + +// +// Vendor GUID of the formset +// +#define USER_AUTHENTICATION_FORMSET_GUID \ + { 0x760e3022, 0xf149, 0x4560, {0x9c, 0x6f, 0x33, 0xaa, 0x7d, 0x48, 0x75, 0xfa} } + +#define ADMIN_PASSWORD_KEY_ID 0x2001 + +#define MAX_PASSWORD_LEN 64 +#define MIN_PASSWORD_LEN 0 + +#endif diff --git a/DasharoModulePkg/UserAuthenticationDxe/UserAuthenticationDxePassword.c b/DasharoModulePkg/UserAuthenticationDxe/UserAuthenticationDxePassword.c new file mode 100644 index 0000000000..ed13e39fc9 --- /dev/null +++ b/DasharoModulePkg/UserAuthenticationDxe/UserAuthenticationDxePassword.c @@ -0,0 +1,600 @@ +/** @file + UserAuthentication DXE password wrapper. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "UserAuthenticationDxe.h" + +UINTN mAdminPasswordTryCount = 0; + +BOOLEAN mNeedReVerify = TRUE; +BOOLEAN mPasswordVerified = FALSE; + +/** + Verify if the password is correct. + + @param[in] Password The user input password. + @param[in] PasswordSize The size of Password in byte. + @param[in] UserPasswordVarStruct The storage of password in variable. + + @retval EFI_SUCCESS The password is correct. + @retval EFI_SECURITY_VIOLATION The password is incorrect. +**/ +EFI_STATUS +CheckPassword ( + IN CHAR8 *Password, + IN UINTN PasswordSize, + IN USER_PASSWORD_VAR_STRUCT *UserPasswordVarStruct + ) +{ + BOOLEAN HashOk; + UINT8 HashData[PASSWORD_HASH_SIZE]; + + HashOk = KeyLibGeneratePBKDF2Hash ( + HASH_TYPE_SHA256, + (UINT8 *)Password, + PasswordSize, + UserPasswordVarStruct->PasswordSalt, + sizeof(UserPasswordVarStruct->PasswordSalt), + HashData, + sizeof(HashData) + ); + if (!HashOk) { + return EFI_DEVICE_ERROR; + } + if (KeyLibSlowCompareMem (UserPasswordVarStruct->PasswordHash, HashData, PASSWORD_HASH_SIZE) == 0) { + return EFI_SUCCESS; + } else { + return EFI_SECURITY_VIOLATION; + } +} + +/** + Get hash data of password from non-volatile variable region. + + @param[in] UserGuid The user GUID of the password variable. + @param[in] Index The index of the password. + 0 means current password. + Non-0 means the password history. + @param[out] UserPasswordVarStruct The storage of password in variable. + + @retval EFI_SUCCESS The password hash is returned successfully. + @retval EFI_NOT_FOUND The password hash is not found. +**/ +EFI_STATUS +GetPasswordHashFromVariable ( + IN EFI_GUID *UserGuid, + IN UINTN Index, + OUT USER_PASSWORD_VAR_STRUCT *UserPasswordVarStruct + ) +{ + UINTN DataSize; + CHAR16 PasswordName[sizeof(USER_AUTHENTICATION_VAR_NAME)/sizeof(CHAR16) + 5]; + + if (Index != 0) { + UnicodeSPrint (PasswordName, sizeof (PasswordName), L"%s%04x", USER_AUTHENTICATION_VAR_NAME, Index); + } else { + UnicodeSPrint (PasswordName, sizeof (PasswordName), L"%s", USER_AUTHENTICATION_VAR_NAME); + } + + DataSize = sizeof(*UserPasswordVarStruct); + return gRT->GetVariable ( + PasswordName, + UserGuid, + NULL, + &DataSize, + UserPasswordVarStruct + ); +} + +/** + Save password hash data to non-volatile variable region. + + @param[in] UserGuid The user GUID of the password variable. + @param[in] UserPasswordVarStruct The storage of password in variable. + + @retval EFI_SUCCESS The password hash is saved successfully. + @retval EFI_OUT_OF_RESOURCES Insufficient resources to save the password hash. +**/ +EFI_STATUS +SavePasswordHashToVariable ( + IN EFI_GUID *UserGuid, + IN USER_PASSWORD_VAR_STRUCT *UserPasswordVarStruct + ) +{ + EFI_STATUS Status; + + if (UserPasswordVarStruct == NULL) { + Status = gRT->SetVariable ( + USER_AUTHENTICATION_VAR_NAME, + UserGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, + 0, + NULL + ); + } else { + Status = gRT->SetVariable ( + USER_AUTHENTICATION_VAR_NAME, + UserGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, + sizeof(*UserPasswordVarStruct), + UserPasswordVarStruct + ); + } + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SavePasswordHashToVariable fails with %r\n", Status)); + } + + return Status; +} + +/** + Save old password hash data to non-volatile variable region as history. + + The number of password history variable is limited. + If all the password history variables are used, the new password history + will override the oldest one. + + @param[in] UserGuid The user GUID of the password variable. + @param[in] UserPasswordVarStruct The storage of password in variable. + + @retval EFI_SUCCESS The password hash is saved successfully. + @retval EFI_OUT_OF_RESOURCES Insufficient resources to save the password hash. +**/ +EFI_STATUS +SaveOldPasswordToHistory ( + IN EFI_GUID *UserGuid, + IN USER_PASSWORD_VAR_STRUCT *UserPasswordVarStruct + ) +{ + EFI_STATUS Status; + UINTN DataSize; + UINT32 LastIndex; + CHAR16 PasswordName[sizeof(USER_AUTHENTICATION_VAR_NAME)/sizeof(CHAR16) + 5]; + + DEBUG ((DEBUG_INFO, "SaveOldPasswordToHistory\n")); + + DataSize = sizeof(LastIndex); + Status = gRT->GetVariable ( + USER_AUTHENTICATION_HISTORY_LAST_VAR_NAME, + UserGuid, + NULL, + &DataSize, + &LastIndex + ); + if (EFI_ERROR(Status)) { + LastIndex = 0; + } + if (LastIndex >= PASSWORD_HISTORY_CHECK_COUNT) { + LastIndex = 0; + } + + LastIndex ++; + UnicodeSPrint (PasswordName, sizeof (PasswordName), L"%s%04x", USER_AUTHENTICATION_VAR_NAME, LastIndex); + + + Status = gRT->SetVariable ( + PasswordName, + UserGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, + sizeof(*UserPasswordVarStruct), + UserPasswordVarStruct + ); + DEBUG ((DEBUG_INFO, " -- to %s, %r\n", PasswordName, Status)); + if (!EFI_ERROR(Status)) { + Status = gRT->SetVariable ( + USER_AUTHENTICATION_HISTORY_LAST_VAR_NAME, + UserGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, + sizeof(LastIndex), + &LastIndex + ); + DEBUG ((DEBUG_INFO, " LastIndex - 0x%04x, %r\n", LastIndex, Status)); + } + + return Status; +} + +/** + Calculate password hash data and save it to non-volatile variable region. + + @param[in] UserGuid The user GUID of the password variable. + @param[in] Password The user input password. + NULL means delete the password variable. + @param[in] PasswordSize The size of Password in byte. + + @retval EFI_SUCCESS The password hash is calculated and saved. + @retval EFI_OUT_OF_RESOURCES Insufficient resources to save the password hash. +**/ +EFI_STATUS +SavePasswordToVariable ( + IN EFI_GUID *UserGuid, + IN CHAR8 *Password, OPTIONAL + IN UINTN PasswordSize + ) +{ + EFI_STATUS Status; + USER_PASSWORD_VAR_STRUCT UserPasswordVarStruct; + BOOLEAN HashOk; + + // + // If password is NULL, it means we want to clean password field saved in variable region. + // + if (Password != NULL) { + KeyLibGenerateSalt (UserPasswordVarStruct.PasswordSalt, sizeof(UserPasswordVarStruct.PasswordSalt)); + HashOk = KeyLibGeneratePBKDF2Hash ( + HASH_TYPE_SHA256, + (UINT8 *)Password, + PasswordSize, + UserPasswordVarStruct.PasswordSalt, + sizeof(UserPasswordVarStruct.PasswordSalt), + UserPasswordVarStruct.PasswordHash, + sizeof(UserPasswordVarStruct.PasswordHash) + ); + if (!HashOk) { + return EFI_DEVICE_ERROR; + } + Status = SavePasswordHashToVariable (UserGuid, &UserPasswordVarStruct); + // + // Save Password data to history variable + // + if (!EFI_ERROR(Status)) { + SaveOldPasswordToHistory (UserGuid, &UserPasswordVarStruct); + } + } else { + Status = SavePasswordHashToVariable (UserGuid, NULL); + } + + return Status; +} + +/** + Verify the password. + If the password variable does not exist, it passes the verification. + If the password variable exists, it does verification based upon password variable. + + @param[in] UserGuid The user GUID of the password variable. + @param[in] Password The user input password. + @param[in] PasswordSize The size of Password in byte. + + @retval TRUE The verification passes. + @retval FALSE The verification fails. +**/ +BOOLEAN +IsPasswordVerified ( + IN EFI_GUID *UserGuid, + IN CHAR8 *Password, + IN UINTN PasswordSize + ) +{ + USER_PASSWORD_VAR_STRUCT UserPasswordVarStruct; + EFI_STATUS Status; + UINTN *PasswordTryCount; + + PasswordTryCount = &mAdminPasswordTryCount; + + Status = GetPasswordHashFromVariable (UserGuid, 0, &UserPasswordVarStruct); + if (EFI_ERROR(Status)) { + return TRUE; + } + + // + // Old password exists + // + Status = CheckPassword (Password, PasswordSize, &UserPasswordVarStruct); + if (EFI_ERROR(Status)) { + if (Password[0] != 0) { + *PasswordTryCount = *PasswordTryCount + 1; + } + return FALSE; + } + + return TRUE; +} + +/** + Return if the password is set. + + @param[in] UserGuid The user GUID of the password variable. + + @retval TRUE The password is set. + @retval FALSE The password is not set. +**/ +BOOLEAN +IsPasswordSet ( + IN EFI_GUID *UserGuid + ) +{ + USER_PASSWORD_VAR_STRUCT UserPasswordVarStruct; + EFI_STATUS Status; + + Status = GetPasswordHashFromVariable(UserGuid, 0, &UserPasswordVarStruct); + if (EFI_ERROR(Status)) { + return FALSE; + } + return TRUE; +} + +/** + Return if the password is strong. + Criteria: + 1) length >= PASSWORD_MIN_SIZE + + @param[in] Password The user input password. + @param[in] PasswordSize The size of Password in byte. + + @retval TRUE The password is strong. + @retval FALSE The password is weak. +**/ +BOOLEAN +IsPasswordStrong ( + IN CHAR8 *Password, + IN UINTN PasswordSize + ) +{ + if (PasswordSize < PASSWORD_MIN_SIZE) { + return FALSE; + } + + return TRUE; +} + +/** + Return if the password is set before in PASSWORD_HISTORY_CHECK_COUNT. + + @param[in] UserGuid The user GUID of the password variable. + @param[in] Password The user input password. + @param[in] PasswordSize The size of Password in byte. + + @retval TRUE The password is set before. + @retval FALSE The password is not set before. +**/ +BOOLEAN +IsPasswordInHistory ( + IN EFI_GUID *UserGuid, + IN CHAR8 *Password, + IN UINTN PasswordSize + ) +{ + EFI_STATUS Status; + USER_PASSWORD_VAR_STRUCT UserPasswordVarStruct; + UINTN Index; + + for (Index = 1; Index <= PASSWORD_HISTORY_CHECK_COUNT; Index++) { + Status = GetPasswordHashFromVariable (UserGuid, Index, &UserPasswordVarStruct); + if (!EFI_ERROR(Status)) { + Status = CheckPassword (Password, PasswordSize, &UserPasswordVarStruct); + if (!EFI_ERROR(Status)) { + return TRUE; + } + } + } + + return FALSE; +} + +/** + Validate if the password is correct. + + @param[in] Password The user input password. + @param[in] PasswordSize The size of Password in byte. + + @retval EFI_SUCCESS The password is correct. + @retval EFI_SECURITY_VIOLATION The password is incorrect. + @retval EFI_INVALID_PARAMETER The password or size is invalid. + @retval EFI_ACCESS_DENIED Password retry count reach. +**/ +EFI_STATUS +VerifyPassword ( + IN CHAR16 *Password, + IN UINTN PasswordSize + ) +{ + EFI_STATUS Status; + UINTN *PasswordTryCount; + UINTN PasswordLen; + EFI_GUID *UserGuid; + CHAR8 AsciiPassword[PASSWORD_MAX_SIZE]; + + Status = UnicodeStrToAsciiStrS (Password, AsciiPassword, sizeof(AsciiPassword)); + if (EFI_ERROR(Status)) { + goto EXIT; + } + + PasswordLen = 0; + PasswordTryCount = &mAdminPasswordTryCount; + UserGuid = &gUserAuthenticationGuid; + + if (*PasswordTryCount >= PASSWORD_MAX_TRY_COUNT) { + DEBUG ((DEBUG_ERROR, "PasswordHandler: VERIFY_PASSWORD try count reach!\n")); + PasswordTryCount = NULL; + Status = EFI_ACCESS_DENIED; + goto EXIT; + } + + PasswordLen = AsciiStrnLenS(AsciiPassword, sizeof(AsciiPassword)); + if (PasswordLen == sizeof(AsciiPassword)) { + DEBUG ((DEBUG_ERROR, "PasswordHandler: Password invalid!\n")); + Status = EFI_INVALID_PARAMETER; + goto EXIT; + } + if (!IsPasswordVerified (UserGuid, AsciiPassword, PasswordLen + 1)) { + DEBUG ((DEBUG_ERROR, "PasswordHandler: PasswordVerify - FAIL\n")); + if (*PasswordTryCount >= PASSWORD_MAX_TRY_COUNT) { + DEBUG ((DEBUG_ERROR, "PasswordHandler: VERIFY_PASSWORD try count reach!\n")); + Status = EFI_ACCESS_DENIED; + } else { + Status = EFI_SECURITY_VIOLATION; + } + goto EXIT; + } + mPasswordVerified = TRUE; + Status = EFI_SUCCESS; + +EXIT: + if (PasswordTryCount != NULL) { + if (Status == EFI_SUCCESS) { + *PasswordTryCount = 0; + } + } + + return Status; +} + +/** + Set a new password. + + @param[in] NewPassword The user input new password. + NULL means clear password. + @param[in] NewPasswordSize The size of NewPassword in byte. + @param[in] OldPassword The user input old password. + NULL means no old password. + @param[in] OldPasswordSize The size of OldPassword in byte. + + @retval EFI_SUCCESS The NewPassword is set successfully. + @retval EFI_SECURITY_VIOLATION The OldPassword is incorrect. + @retval EFI_INVALID_PARAMETER The password or size is invalid. + @retval EFI_ACCESS_DENIED Password retry count reach. + @retval EFI_UNSUPPORTED NewPassword is not strong enough. + @retval EFI_ALREADY_STARTED NewPassword is in history. +**/ +EFI_STATUS +SetPassword ( + IN CHAR16 *NewPassword, OPTIONAL + IN UINTN NewPasswordSize, + IN CHAR16 *OldPassword, OPTIONAL + IN UINTN OldPasswordSize + ) +{ + EFI_STATUS Status; + UINTN *PasswordTryCount; + UINTN PasswordLen; + EFI_GUID *UserGuid; + CHAR8 AsciiNewPassword[PASSWORD_MAX_SIZE]; + CHAR8 AsciiOldPassword[PASSWORD_MAX_SIZE]; + + Status = UnicodeStrToAsciiStrS (NewPassword, AsciiNewPassword, sizeof(AsciiNewPassword)); + if (EFI_ERROR(Status)) { + goto EXIT; + } + Status = UnicodeStrToAsciiStrS (OldPassword, AsciiOldPassword, sizeof(AsciiOldPassword)); + if (EFI_ERROR(Status)) { + goto EXIT; + } + + PasswordLen = 0; + PasswordTryCount = &mAdminPasswordTryCount; + UserGuid = &gUserAuthenticationGuid; + + if (NewPasswordSize > sizeof(AsciiNewPassword) * sizeof(CHAR16)) { + return EFI_INVALID_PARAMETER; + } + if (OldPasswordSize > sizeof(AsciiOldPassword) * sizeof(CHAR16)) { + return EFI_INVALID_PARAMETER; + } + + if (*PasswordTryCount >= PASSWORD_MAX_TRY_COUNT) { + DEBUG ((DEBUG_ERROR, "PasswordHandler: SET_PASSWORD try count reach!\n")); + PasswordTryCount = NULL; + Status = EFI_ACCESS_DENIED; + goto EXIT; + } + + PasswordLen = AsciiStrnLenS(AsciiOldPassword, sizeof(AsciiOldPassword)); + if (PasswordLen == sizeof(AsciiOldPassword)) { + DEBUG ((DEBUG_ERROR, "PasswordHandler: OldPassword invalid!\n")); + Status = EFI_INVALID_PARAMETER; + goto EXIT; + } + + if (!IsPasswordVerified (UserGuid, AsciiOldPassword, PasswordLen + 1)) { + DEBUG ((DEBUG_ERROR, "PasswordHandler: PasswordVerify - FAIL\n")); + if (*PasswordTryCount >= PASSWORD_MAX_TRY_COUNT) { + DEBUG ((DEBUG_ERROR, "PasswordHandler: SET_PASSWORD try count reach!\n")); + Status = EFI_ACCESS_DENIED; + } else { + Status = EFI_SECURITY_VIOLATION; + } + goto EXIT; + } + + PasswordLen = AsciiStrnLenS(AsciiNewPassword, sizeof(AsciiNewPassword)); + if (PasswordLen == sizeof(AsciiNewPassword)) { + DEBUG ((DEBUG_ERROR, "PasswordHandler: NewPassword invalid!\n")); + Status = EFI_INVALID_PARAMETER; + goto EXIT; + } + if (PasswordLen != 0 && !IsPasswordStrong (AsciiNewPassword, PasswordLen + 1)) { + DEBUG ((DEBUG_ERROR, "PasswordHandler: NewPassword too weak!\n")); + Status = EFI_UNSUPPORTED; + goto EXIT; + } + if (PasswordLen != 0 && IsPasswordInHistory (UserGuid, AsciiNewPassword, PasswordLen + 1)) { + DEBUG ((DEBUG_ERROR, "PasswordHandler: NewPassword in history!\n")); + Status = EFI_ALREADY_STARTED; + goto EXIT; + } + + if (PasswordLen == 0) { + Status = SavePasswordToVariable (UserGuid, NULL, 0); + } else { + Status = SavePasswordToVariable (UserGuid, AsciiNewPassword, PasswordLen + 1); + } + +EXIT: + if (PasswordTryCount != NULL) { + if (Status == EFI_SUCCESS) { + *PasswordTryCount = 0; + } + } + + return Status; +} + +/** + Return if the password is set. + + @retval TRUE The password is set. + @retval FALSE The password is not set. +**/ +BOOLEAN +IsPasswordInstalled ( + VOID + ) +{ + return IsPasswordSet(&gUserAuthenticationGuid); +} + +/** + Get password verification policy. + + @param[out] VerifyPolicy Verification policy. + + @retval EFI_SUCCESS Get verification policy successfully. +**/ +EFI_STATUS +GetPasswordVerificationPolicy ( + OUT PASSWORD_COMMUNICATE_VERIFY_POLICY *VerifyPolicy + ) +{ + VerifyPolicy->NeedReVerify = mNeedReVerify; + + return EFI_SUCCESS; +} + +/** + Return if the password was verified. + + @retval TRUE The password was verified. + @retval FALSE The password was not verified. +**/ +BOOLEAN +WasPasswordVerified ( + VOID + ) +{ + return mPasswordVerified; +} diff --git a/DasharoModulePkg/UserAuthenticationDxe/UserAuthenticationDxeStrings.uni b/DasharoModulePkg/UserAuthenticationDxe/UserAuthenticationDxeStrings.uni new file mode 100644 index 0000000000..3d32ec10e6 --- /dev/null +++ b/DasharoModulePkg/UserAuthenticationDxe/UserAuthenticationDxeStrings.uni @@ -0,0 +1,29 @@ +/** @file +// String definitions for User Authentication formset. +// +// Copyright (c) 2019, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +**/ + +#langdef en-US "English" +#langdef fr-FR "Francais" + + +#string STR_FORM_SET_TITLE #language en-US "User Password Management" + #language fr-FR "User Password Management" +#string STR_FORM_SET_TITLE_HELP #language en-US "This selection will take you to the password management menu" + #language fr-FR "This selection will take you to the password management menu" +#string STR_FORM_TITLE #language en-US "Password Management" + #language fr-FR "Password Management" +#string STR_ADMIN_PASSWORD_PROMPT #language en-US "Change Admin Password" + #language fr-FR "Change Admin Password" +#string STR_ADMIN_PASSWORD_HELP #language en-US "Input old admin password if it was set, then you can change the password to a new one. After the change action, you may need input the new password when you enter UI. The new password must be between 8 and 32 chars. Input an empty password can clean old admin password, then no need input password to enter UI." + #language fr-FR "Input old admin password if it was set, then you can change the password to a new one. After the change action, you may need input the new password when you enter UI. The new password must be between 8 and 32 chars. Input an empty password can clean old admin password, then no need input password to enter UI." +#string STR_ADMIN_PASSWORD_STS_HELP #language en-US "Current Admin Password status: Installed or Not Installed." + #language fr-FR "Current Admin Password status: Installed or Not Installed." +#string STR_ADMIN_PASSWORD_STS_PROMPT #language en-US "Admin Password Status" + #language fr-FR "Admin Password Status" +#string STR_ADMIN_PASSWORD_STS_CONTENT #language en-US "" + #language fr-FR "" diff --git a/DasharoModulePkg/UserAuthenticationDxe/UserAuthenticationDxeVfr.vfr b/DasharoModulePkg/UserAuthenticationDxe/UserAuthenticationDxeVfr.vfr new file mode 100644 index 0000000000..df8b7edb4c --- /dev/null +++ b/DasharoModulePkg/UserAuthenticationDxe/UserAuthenticationDxeVfr.vfr @@ -0,0 +1,39 @@ +///** @file +// UserAuthentication formset. +// +// Copyright (c) 2019, Intel Corporation. All rights reserved.
+// SPDX-License-Identifier: BSD-2-Clause-Patent +// +//**/ + +#include +#include "UserAuthenticationDxeFormset.h" + +formset + guid = USER_AUTHENTICATION_FORMSET_GUID, + title = STRING_TOKEN(STR_FORM_SET_TITLE), + help = STRING_TOKEN(STR_FORM_SET_TITLE_HELP), + classguid = gEfiIfrFrontPageGuid, + + form formid = 1, + title = STRING_TOKEN(STR_FORM_TITLE); + + grayoutif TRUE; + text + help = STRING_TOKEN(STR_ADMIN_PASSWORD_STS_HELP), + text = STRING_TOKEN(STR_ADMIN_PASSWORD_STS_PROMPT), + text = STRING_TOKEN(STR_ADMIN_PASSWORD_STS_CONTENT); + endif; + + password + prompt = STRING_TOKEN(STR_ADMIN_PASSWORD_PROMPT), + help = STRING_TOKEN(STR_ADMIN_PASSWORD_HELP), + flags = INTERACTIVE, + key = ADMIN_PASSWORD_KEY_ID, + minsize = MIN_PASSWORD_LEN, + maxsize = MAX_PASSWORD_LEN, + endpassword; + + endform; + +endformset; diff --git a/DasharoPayloadPkg/AcpiPlatformDxe/AcpiPlatform.c b/DasharoPayloadPkg/AcpiPlatformDxe/AcpiPlatform.c new file mode 100644 index 0000000000..2f794343a3 --- /dev/null +++ b/DasharoPayloadPkg/AcpiPlatformDxe/AcpiPlatform.c @@ -0,0 +1,541 @@ +/** @file + Sample ACPI Platform Driver + + Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +EFI_ACPI_TABLE_PROTOCOL *mAcpiProtocol; +EFI_ACPI_SDT_PROTOCOL *mSdtProtocol; +EFI_EVENT mEfiExitBootServicesEvent; + +EFI_STATUS +EFIAPI +InstallTablesFromXsdt ( + IN EFI_ACPI_DESCRIPTION_HEADER *Xsdt, + IN UINTN *TableHandle + ) +{ + EFI_STATUS Status; + EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE *FadtTable; + EFI_ACPI_6_3_FIRMWARE_ACPI_CONTROL_STRUCTURE *FacsTable; + EFI_ACPI_DESCRIPTION_HEADER *DsdtTable; + VOID *CurrentTableEntry; + UINTN CurrentTablePointer; + EFI_ACPI_DESCRIPTION_HEADER *CurrentTable; + UINTN Index; + UINTN NumberOfTableEntries; + + Status = EFI_SUCCESS; + // + // Retrieve the addresses of XSDT and + // calculate the number of its table entries. + // + NumberOfTableEntries = (Xsdt->Length - + sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / + sizeof (UINT64); + // + // Install ACPI tables found in XSDT. + // + for (Index = 0; Index < NumberOfTableEntries; Index++) { + // + // Get the table entry from XSDT + // + CurrentTableEntry = (VOID *) ((UINT8 *) Xsdt + + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + + Index * sizeof (UINT64)); + CurrentTablePointer = (UINTN) *(UINT64 *) CurrentTableEntry; + CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTablePointer; + + // + // Get the FACS and DSDT table address from the table FADT + // + if (!AsciiStrnCmp ((CHAR8 *) &CurrentTable->Signature, "FACP", 4)) { + FadtTable = (EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE *) + (UINTN) CurrentTablePointer; + DsdtTable = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) FadtTable->XDsdt; + + FacsTable = (EFI_ACPI_6_3_FIRMWARE_ACPI_CONTROL_STRUCTURE *) (UINTN) FadtTable->XFirmwareCtrl; + if (FacsTable == NULL) + FacsTable = (EFI_ACPI_6_3_FIRMWARE_ACPI_CONTROL_STRUCTURE *) (UINTN) FadtTable->FirmwareCtrl; + + if (!AsciiStrnCmp ((CHAR8 *) &DsdtTable->Signature, "DSDT", 4)) { + // + // Install DSDT table. + // + Status = mAcpiProtocol->InstallAcpiTable ( + mAcpiProtocol, + DsdtTable, + DsdtTable->Length, + TableHandle + ); + ASSERT_EFI_ERROR (Status); + } else { + DEBUG((DEBUG_ERROR, "DSDT not found\n")); + ASSERT_EFI_ERROR (Status); + } + + if (!AsciiStrnCmp ((CHAR8 *) &FacsTable->Signature, "FACS", 4)) { + // + // Install the FACS tables + // + Status = mAcpiProtocol->InstallAcpiTable ( + mAcpiProtocol, + FacsTable, + FacsTable->Length, + TableHandle + ); + ASSERT_EFI_ERROR (Status); + } else { + DEBUG((DEBUG_ERROR, "FACS not found\n")); + ASSERT_EFI_ERROR (Status); + } + } + + // + // Install the XSDT tables + // + Status = mAcpiProtocol->InstallAcpiTable ( + mAcpiProtocol, + CurrentTable, + CurrentTable->Length, + TableHandle + ); + + if (EFI_ERROR (Status)) { + return Status; + } + } + + return Status; +} + + +EFI_STATUS +EFIAPI +InstallTablesFromRsdt ( + IN EFI_ACPI_DESCRIPTION_HEADER *Rsdt, + IN UINTN *TableHandle + ) +{ + EFI_STATUS Status; + EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE *FadtTable; + EFI_ACPI_6_3_FIRMWARE_ACPI_CONTROL_STRUCTURE *FacsTable; + EFI_ACPI_DESCRIPTION_HEADER *DsdtTable; + VOID *CurrentTableEntry; + UINTN CurrentTablePointer; + EFI_ACPI_DESCRIPTION_HEADER *CurrentTable; + UINTN Index; + UINTN NumberOfTableEntries; + + Status = EFI_SUCCESS; + // + // Retrieve the addresses of RSDT and + // calculate the number of its table entries. + // + NumberOfTableEntries = (Rsdt->Length - + sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / + sizeof (UINT32); + // + // Install ACPI tables found in RSDT. + // + for (Index = 0; Index < NumberOfTableEntries; Index++) { + // + // Get the table entry from RSDT + // + CurrentTableEntry = (VOID *) ((UINT8 *) Rsdt + + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + + Index * sizeof (UINT32)); + CurrentTablePointer = (UINTN) *(UINT32 *) CurrentTableEntry; + CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTablePointer; + + // + // Get the FACS and DSDT table address from the table FADT + // + if (!AsciiStrnCmp ((CHAR8 *) &CurrentTable->Signature, "FACP", 4)) { + FadtTable = (EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE *) + (UINTN) CurrentTablePointer; + DsdtTable = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) FadtTable->Dsdt; + FacsTable = (EFI_ACPI_6_3_FIRMWARE_ACPI_CONTROL_STRUCTURE *) (UINTN) FadtTable->FirmwareCtrl; + + if (!AsciiStrnCmp ((CHAR8 *) &DsdtTable->Signature, "DSDT", 4)) { + // + // Install DSDT table. + // + Status = mAcpiProtocol->InstallAcpiTable ( + mAcpiProtocol, + DsdtTable, + DsdtTable->Length, + TableHandle + ); + ASSERT_EFI_ERROR (Status); + } else { + DEBUG((DEBUG_ERROR, "DSDT not found\n")); + ASSERT_EFI_ERROR (Status); + } + + if (!AsciiStrnCmp ((CHAR8 *) &FacsTable->Signature, "FACS", 4)) { + // + // Install the FACS tables + // + Status = mAcpiProtocol->InstallAcpiTable ( + mAcpiProtocol, + FacsTable, + FacsTable->Length, + TableHandle + ); + ASSERT_EFI_ERROR (Status); + } else { + DEBUG((DEBUG_ERROR, "FACS not found\n")); + ASSERT_EFI_ERROR (Status); + } + } + // + // Install the RSDT tables + // + Status = mAcpiProtocol->InstallAcpiTable ( + mAcpiProtocol, + CurrentTable, + CurrentTable->Length, + TableHandle + ); + + if (EFI_ERROR (Status)) { + return Status; + } + } + + return Status; +} + +/** + This function uses the ACPI SDT protocol to locate an ACPI table. + It is really only useful for finding tables that only have a single instance, + e.g. FADT, FACS, MADT, etc. It is not good for locating SSDT, etc. + Matches are determined by finding the table with ACPI table that has + a matching signature. + + @param[in] Signature - Pointer to an ASCII string containing the OEM Table ID from the ACPI table header + @param[in, out] Table - Updated with a pointer to the table + @param[in, out] Handle - AcpiSupport protocol table handle for the table found + @param[in, out] Version - The version of the table desired + + @retval EFI_SUCCESS - The function completed successfully. + @retval EFI_NOT_FOUND - Failed to locate AcpiTable. + @retval EFI_NOT_READY - Not ready to locate AcpiTable. +**/ +EFI_STATUS +EFIAPI +LocateAcpiTableBySignature ( + IN UINT32 Signature, + IN OUT EFI_ACPI_DESCRIPTION_HEADER **Table, + IN OUT UINTN *Handle + ) +{ + EFI_STATUS Status; + INTN Index; + EFI_ACPI_TABLE_VERSION Version; + EFI_ACPI_DESCRIPTION_HEADER *OrgTable; + + /// + /// Locate table with matching ID + /// + Version = 0; + Index = 0; + do { + Status = mSdtProtocol->GetAcpiTable (Index, (EFI_ACPI_SDT_HEADER **)&OrgTable, &Version, Handle); + if (Status == EFI_NOT_FOUND) { + break; + } + ASSERT_EFI_ERROR (Status); + Index++; + } while (OrgTable->Signature != Signature); + + if (Status != EFI_NOT_FOUND) { + *Table = AllocateCopyPool (OrgTable->Length, OrgTable); + ASSERT (*Table); + } + + /// + /// If we found the table, there will be no error. + /// + return Status; +} + + +/** + This function calculates RCR based on PCI Device ID and Vendor ID from the devices + available on the platform. + It also includes other instances of BIOS change to calculate CRC and provides as + HWSignature filed in FADT table. +**/ +VOID +IsHardwareChange ( + VOID + ) +{ + EFI_STATUS Status; + UINTN Index; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT32 CRC; + UINT32 *HWChange; + UINTN HWChangeSize; + UINT32 PciId; + UINTN Handle; + EFI_ACPI_6_3_FIRMWARE_ACPI_CONTROL_STRUCTURE *FacsPtr; + EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE *pFADT; + + HandleCount = 0; + HandleBuffer = NULL; + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return; // PciIO protocol not installed yet! + } + + // + // Allocate memory for HWChange and add additional entrie for + // pFADT->XDsdt + // + HWChangeSize = HandleCount + 1; + HWChange = AllocateZeroPool (sizeof(UINT32) * HWChangeSize); + ASSERT(HWChange != NULL); + + if (HWChange == NULL) return; + + // + // add HWChange inputs: PCI devices + // + for (Index = 0; HandleCount > 0; HandleCount--) { + PciId = 0; + Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID **) &PciIo); + if (!EFI_ERROR (Status)) { + Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, 1, &PciId); + if (EFI_ERROR (Status)) { + continue; + } + HWChange[Index++] = PciId; + } + } + + // + // Locate FACP Table + // + Handle = 0; + Status = LocateAcpiTableBySignature ( + EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE, + (EFI_ACPI_DESCRIPTION_HEADER **) &pFADT, + &Handle + ); + if (EFI_ERROR (Status) || (pFADT == NULL)) { + return; //Table not found or out of memory resource for pFADT table + } + + // + // add HWChange inputs: others + // + HWChange[Index++] = (UINT32)pFADT->XDsdt; + + // + // Calculate CRC value with HWChange data. + // + Status = gBS->CalculateCrc32(HWChange, HWChangeSize, &CRC); + DEBUG ((DEBUG_INFO, "CRC = %x and Status = %r\n", CRC, Status)); + + // + // Set HardwareSignature value based on CRC value. + // + FacsPtr = (EFI_ACPI_6_3_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)pFADT->FirmwareCtrl; + FacsPtr->HardwareSignature = CRC; + FreePool (HWChange); +} + +VOID +EFIAPI +AcpiEndOfDxeEvent ( + EFI_EVENT Event, + VOID *ParentImageHandle + ) +{ + if (Event != NULL) { + gBS->CloseEvent (Event); + } + + // + // Calculate Hardware Signature value based on current platform configurations + // + IsHardwareChange (); +} + +/** On exiting boot services we must make sure the new RSDP is in the legacy + segment where coreboot expects it. +**/ +STATIC +VOID +EFIAPI +AcpiExitBootServicesEventNotify ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + UINTN Ptr; + EFI_STATUS Status; + EFI_ACPI_6_3_ROOT_SYSTEM_DESCRIPTION_POINTER *cbRsdp; + EFI_ACPI_6_3_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp; + + cbRsdp = NULL; + Rsdp = NULL; + + /* Find coreboot RSDP. */ + for (Ptr = 0xe0000; Ptr < 0xfffff; Ptr += 16) { + if (!AsciiStrnCmp ((CHAR8 *)Ptr, "RSD PTR ", 8)) { + cbRsdp = (EFI_ACPI_6_3_ROOT_SYSTEM_DESCRIPTION_POINTER *)Ptr; + break; + } + } + + if (cbRsdp == NULL) { + DEBUG ((EFI_D_ERROR, "No coreboot RSDP found, wake up from S3 not possible.\n")); + return; + } + + Status = EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, (VOID **) &Rsdp); + if (EFI_ERROR (Status) || (Rsdp == NULL)) { + DEBUG ((EFI_D_ERROR, "No RSDP found, wake up from S3 not possible.\n")); + return; + } + + CopyMem((VOID *)cbRsdp, (CONST VOID *)Rsdp, sizeof(*Rsdp)); + DEBUG ((EFI_D_INFO, "coreboot RSDP updated\n")); +} + +/** + Entrypoint of Acpi Platform driver. + + @param ImageHandle + @param SystemTable + + @return EFI_SUCCESS + @return EFI_LOAD_ERROR + @return EFI_OUT_OF_RESOURCES + +**/ +EFI_STATUS +EFIAPI +AcpiPlatformEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HOB_GUID_TYPE *GuidHob; + EFI_ACPI_6_3_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp; + SYSTEM_TABLE_INFO *SystemTableInfo; + UINTN TableHandle; + EFI_EVENT EndOfDxeEvent; + + TableHandle = 0; + + // + // Find the AcpiTable protocol + // + Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID**)&mAcpiProtocol); + ASSERT_EFI_ERROR (Status); + + Status = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (VOID **)&mSdtProtocol); + ASSERT_EFI_ERROR (Status); + + // + // Find the system table information guid hob + // + GuidHob = GetFirstGuidHob (&gUefiSystemTableInfoGuid); + ASSERT (GuidHob != NULL); + SystemTableInfo = (SYSTEM_TABLE_INFO *)GET_GUID_HOB_DATA (GuidHob); + + // + // Set pointers to ACPI tables + // + if (SystemTableInfo->AcpiTableBase != 0 && SystemTableInfo->AcpiTableSize != 0) { + ASSERT_EFI_ERROR (Status); + } + + Rsdp = (EFI_ACPI_6_3_ROOT_SYSTEM_DESCRIPTION_POINTER *) SystemTableInfo->AcpiTableBase; + // + // If XSDT table is found, just install its tables. + // + if (Rsdp->XsdtAddress) { + Status = InstallTablesFromXsdt ((EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Rsdp->XsdtAddress, + &TableHandle); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "Failed to install ACPI tables from XSDT\n")); + return Status; + } + } else { + DEBUG((DEBUG_ERROR, "XSDT not found, trying RSDT\n")); + if (Rsdp->RsdtAddress) { + Status = InstallTablesFromRsdt ((EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Rsdp->RsdtAddress, + &TableHandle); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "Failed to install ACPI tables from RSDT\n")); + return Status; + } + } else { + DEBUG((DEBUG_ERROR, "RSDT not found. Failed to install ACPI tables\n")); + ASSERT_EFI_ERROR (Status); + } + } + + // + // Create an End of DXE event. + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + AcpiEndOfDxeEvent, + NULL, + &gEfiEndOfDxeEventGroupGuid, + &EndOfDxeEvent + ); + ASSERT_EFI_ERROR (Status); + + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + AcpiExitBootServicesEventNotify, + NULL, + &gEfiEventExitBootServicesGuid, + &mEfiExitBootServicesEvent + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + diff --git a/DasharoPayloadPkg/AcpiPlatformDxe/AcpiPlatform.uni b/DasharoPayloadPkg/AcpiPlatformDxe/AcpiPlatform.uni new file mode 100644 index 0000000000..4b8d33dbcc --- /dev/null +++ b/DasharoPayloadPkg/AcpiPlatformDxe/AcpiPlatform.uni @@ -0,0 +1,16 @@ +// /** @file +// Sample ACPI Platform Driver +// +// Sample ACPI Platform Driver +// +// Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Sample ACPI Platform Driver" + +#string STR_MODULE_DESCRIPTION #language en-US "Sample ACPI Platform Driver" + diff --git a/DasharoPayloadPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf b/DasharoPayloadPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf new file mode 100644 index 0000000000..f84efc0819 --- /dev/null +++ b/DasharoPayloadPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf @@ -0,0 +1,58 @@ +## @file +# Sample ACPI Platform Driver +# +# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = AcpiPlatform + MODULE_UNI_FILE = AcpiPlatform.uni + FILE_GUID = cb933912-df8f-4305-b1f9-7b44fa11395c + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = AcpiPlatformEntryPoint + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + AcpiPlatform.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + DasharoPayloadPkg/DasharoPayloadPkg.dec + +[LibraryClasses] + UefiLib + PcdLib + DebugLib + HobLib + BaseMemoryLib + UefiBootServicesTableLib + UefiDriverEntryPoint + +[Protocols] + gEfiAcpiTableProtocolGuid ## CONSUMES + gEfiAcpiSdtProtocolGuid ## CONSUMES + gEfiPciIoProtocolGuid ## CONSUMES + +[Guids] + gUefiSystemTableInfoGuid ## CONSUMES + gEfiEndOfDxeEventGroupGuid ## CONSUMES + gEfiEventExitBootServicesGuid ## CONSUMES + gEfiAcpiTableGuid ## CONSUMES + +[Depex] + gEfiAcpiTableProtocolGuid AND + gEfiAcpiSdtProtocolGuid AND + gEfiPciRootBridgeIoProtocolGuid + +[UserExtensions.TianoCore."ExtraFiles"] + AcpiPlatformExtra.uni diff --git a/DasharoPayloadPkg/AcpiPlatformDxe/AcpiPlatformExtra.uni b/DasharoPayloadPkg/AcpiPlatformDxe/AcpiPlatformExtra.uni new file mode 100644 index 0000000000..7e7728ef9b --- /dev/null +++ b/DasharoPayloadPkg/AcpiPlatformDxe/AcpiPlatformExtra.uni @@ -0,0 +1,14 @@ +// /** @file +// AcpiPlatform Localized Strings and Content +// +// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + +#string STR_PROPERTIES_MODULE_NAME +#language en-US +"ACPI Platform Sample DXE Driver" + + diff --git a/DasharoPayloadPkg/ApuConfigurationUi/ApuConfigurationUi.c b/DasharoPayloadPkg/ApuConfigurationUi/ApuConfigurationUi.c new file mode 100644 index 0000000000..d7386e8364 --- /dev/null +++ b/DasharoPayloadPkg/ApuConfigurationUi/ApuConfigurationUi.c @@ -0,0 +1,176 @@ +/** @file + Dasharo APU Configuration UI for Setup Front Page. + + Copyright (c) 2024, 3mdeb All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/// +/// HII specific Vendor Device Path definition. +/// +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + EFI_DEVICE_PATH_PROTOCOL End; +} HII_VENDOR_DEVICE_PATH; + +extern UINT8 ApuConfigurationUiVfrBin[]; +extern UINT8 ApuConfigurationUiStrings[]; + +EFI_HANDLE mApuConfigDriverHandle = NULL; +EFI_HII_HANDLE mApuConfigHiiHandle = NULL; + +APU_CONFIGURATION_VARSTORE_DATA mDefaultApuConfig = { + .CorePerfBoost = TRUE, + .WatchdogEnable = FALSE, + .WatchdogTimeout = 60, + .PciePwrMgmt = FALSE, +}; + +HII_VENDOR_DEVICE_PATH mApuConfigVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + APU_CONFIGURATION_FORMSET_GUID + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + + +/** + + Initialize Boot Maintenance Menu library. + + @param ImageHandle The image handle. + @param SystemTable The system table. + + @retval EFI_SUCCESS Install Boot manager menu success. + @retval Other Return error status.gBPDisplayLibGuid + +**/ +EFI_STATUS +EFIAPI +ApuConfigurationUiEntry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINTN Size; + APU_CONFIGURATION_VARSTORE_DATA ApuConfig; + + Size = sizeof (ApuConfig); + Status = gRT->GetVariable ( + APU_CONFIGURATION_VAR, + &gApuConfigurationFormsetGuid, + NULL, + &Size, + &ApuConfig + ); + // + // Ensure the variable exists before changing the form + // + if (EFI_ERROR (Status)) { + Status = gRT->SetVariable ( + APU_CONFIGURATION_VAR, + &gApuConfigurationFormsetGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, + sizeof (mDefaultApuConfig), + &mDefaultApuConfig + ); + ASSERT_EFI_ERROR (Status); + } + + + Status = gBS->InstallMultipleProtocolInterfaces ( + &mApuConfigDriverHandle, + &gEfiDevicePathProtocolGuid, + &mApuConfigVendorDevicePath, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Publish our HII data + // + mApuConfigHiiHandle = HiiAddPackages ( + &gApuConfigurationFormsetGuid, + mApuConfigDriverHandle, + ApuConfigurationUiVfrBin, + ApuConfigurationUiStrings, + NULL + ); + + if (mApuConfigHiiHandle == NULL) { + gBS->UninstallProtocolInterface ( + mApuConfigDriverHandle, + &gEfiDevicePathProtocolGuid, + &mApuConfigVendorDevicePath + ); + + return EFI_OUT_OF_RESOURCES; + } + + return Status; +} + +/** + Destructor of Boot Maintenance menu library. + + @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 +ApuConfigurationUiUnload ( + IN EFI_HANDLE ImageHandle + ) +{ + + if (mApuConfigDriverHandle != NULL) { + gBS->UninstallProtocolInterface ( + mApuConfigDriverHandle, + &gEfiDevicePathProtocolGuid, + &mApuConfigVendorDevicePath + ); + mApuConfigDriverHandle = NULL; + } + + if (mApuConfigHiiHandle != NULL) { + HiiRemovePackages (mApuConfigHiiHandle); + mApuConfigHiiHandle = NULL; + } + + return EFI_SUCCESS; +} diff --git a/DasharoPayloadPkg/ApuConfigurationUi/ApuConfigurationUi.inf b/DasharoPayloadPkg/ApuConfigurationUi/ApuConfigurationUi.inf new file mode 100644 index 0000000000..29d59f1274 --- /dev/null +++ b/DasharoPayloadPkg/ApuConfigurationUi/ApuConfigurationUi.inf @@ -0,0 +1,55 @@ +## @file +# Driver for DXE phase to publish Dasharo APU Configuration form +# +# Copyright (c) 2024, 3mdeb All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ApuConfigurationUi + MODULE_UNI_FILE = ApuConfigurationUi.uni + FILE_GUID = D21C607C-B034-4727-AA91-7B156907CDEA + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 2.0 + ENTRY_POINT = ApuConfigurationUiEntry + UNLOAD_IMAGE = ApuConfigurationUiUnload +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 AARCH64 +# + +[Sources] + ApuConfigurationUi.c + ApuConfigurationUiStrings.uni + ApuConfigurationUiVfr.Vfr + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + DasharoPayloadPkg/DasharoPayloadPkg.dec + +[LibraryClasses] + DevicePathLib + BaseLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + UefiDriverEntryPoint + DebugLib + HiiLib + UefiLib + BaseMemoryLib + +[Guids] + gApuConfigurationFormsetGuid + gEfiIfrFrontPageGuid + +[Protocols] + gEfiDevicePathProtocolGuid ## PRODUCES + +[Depex] + gEfiHiiDatabaseProtocolGuid AND + gEfiVariableArchProtocolGuid AND + gEfiVariableWriteArchProtocolGuid diff --git a/DasharoPayloadPkg/ApuConfigurationUi/ApuConfigurationUi.uni b/DasharoPayloadPkg/ApuConfigurationUi/ApuConfigurationUi.uni new file mode 100644 index 0000000000..5106e3f9ed --- /dev/null +++ b/DasharoPayloadPkg/ApuConfigurationUi/ApuConfigurationUi.uni @@ -0,0 +1,17 @@ +// /** @file +// Dasharo APU Configuration UI module. +// +// Copyright (c) 2024, 3mdeb All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT +#language en-US "Dasharo APU Configuration UI module." + +#string STR_MODULE_DESCRIPTION +#language en-US "Dasharo APU Configuration UI module." + + diff --git a/DasharoPayloadPkg/ApuConfigurationUi/ApuConfigurationUiStrings.uni b/DasharoPayloadPkg/ApuConfigurationUi/ApuConfigurationUiStrings.uni new file mode 100644 index 0000000000..e209c6500d --- /dev/null +++ b/DasharoPayloadPkg/ApuConfigurationUi/ApuConfigurationUiStrings.uni @@ -0,0 +1,36 @@ +// *++ +// +// Copyright (c) 2024, 3mdeb All rights reserved.
+// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// Module Name: +// +// ApuConfigurationUiStrings.uni +// +// Abstract: +// +// String definitions for Dasharo APU Configuration UI. +// +// --*/ + +/=# + +#langdef en-US "English" + +#string STR_FORM_APU_CONFIG_TITLE #language en-US "Dasharo APU Configuration" + +#string STR_CPB_PROMPT #language en-US "Core Performance Boost" +#string STR_CPB_HELP #language en-US "Enables/disables AMD Core Performance Boost. When enabled, two additional boosted P-states will be available.\n\n" + "The performance of a single core can be raised from 1000MHz up to 1400Mhz if other cores are inactive.\n\n" + + "Disable the feature if you notice system instability." + +#string STR_WATCHDOG_ENABLE_PROMPT #language en-US "Enable watchdog" +#string STR_WATCHDOG_ENABLE_HELP #language en-US "Enables/disables FCH Watchdog Timer during POST.\n\n" + "If the timers expires, for example due to an unexpected hang or lockup, the platform will be reset after specified timeout." + +#string STR_WATCHDOG_TIMEOUT_PROMPT #language en-US "Watchdog timeout value" +#string STR_WATCHDOG_TIMEOUT_HELP #language en-US "Sets the watchdog timer expiration value in seconds. Minimum is 60s, maximum 65535s." + +#string STR_PCIE_PWR_MGMT_PROMPT #language en-US "Enable PCI Express power management features" +#string STR_PCIE_PWR_MGMT_HELP #language en-US "When enabled the Clock Power Management, ASPM L0s and L1 features will be enabled on PCI Express ports." diff --git a/DasharoPayloadPkg/ApuConfigurationUi/ApuConfigurationUiVfr.Vfr b/DasharoPayloadPkg/ApuConfigurationUi/ApuConfigurationUiVfr.Vfr new file mode 100644 index 0000000000..f0a36b59ac --- /dev/null +++ b/DasharoPayloadPkg/ApuConfigurationUi/ApuConfigurationUiVfr.Vfr @@ -0,0 +1,59 @@ +///** @file +// +// Formset for Dasharo APU Configuration UI +// +// Copyright (c) 2024, 3mdeb All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +//**/ + +#include +#include + +formset + guid = APU_CONFIGURATION_FORMSET_GUID, + title = STRING_TOKEN(STR_FORM_APU_CONFIG_TITLE), + help = STRING_TOKEN(STR_FORM_APU_CONFIG_TITLE), + classguid = gEfiIfrFrontPageGuid, + + efivarstore APU_CONFIGURATION_VARSTORE_DATA, + attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, + name = ApuConfig, + guid = APU_CONFIGURATION_FORMSET_GUID; + + form formid = 0x0001, + title = STRING_TOKEN(STR_FORM_APU_CONFIG_TITLE); + + checkbox varid = ApuConfig.CorePerfBoost, + prompt = STRING_TOKEN(STR_CPB_PROMPT), + help = STRING_TOKEN(STR_CPB_HELP), + flags = CHECKBOX_DEFAULT | RESET_REQUIRED, + endcheckbox; + + checkbox varid = ApuConfig.WatchdogEnable, + prompt = STRING_TOKEN(STR_WATCHDOG_ENABLE_PROMPT), + help = STRING_TOKEN(STR_WATCHDOG_ENABLE_HELP), + flags = RESET_REQUIRED, + endcheckbox; + + suppressif ideqval ApuConfig.WatchdogEnable == 0; + numeric varid = ApuConfig.WatchdogTimeout, + prompt = STRING_TOKEN(STR_WATCHDOG_TIMEOUT_PROMPT), + help = STRING_TOKEN(STR_WATCHDOG_TIMEOUT_HELP), + flags = NUMERIC_SIZE_2 | DISPLAY_UINT_DEC | RESET_REQUIRED, + minimum = 60, + maximum = 65535, + step = 0, + default = 60, + endnumeric; + endif; + + checkbox varid = ApuConfig.PciePwrMgmt, + prompt = STRING_TOKEN(STR_PCIE_PWR_MGMT_PROMPT), + help = STRING_TOKEN(STR_PCIE_PWR_MGMT_HELP), + flags = RESET_REQUIRED, + endcheckbox; + + endform; +endformset; diff --git a/DasharoPayloadPkg/BlSupportDxe/BlSupportDxe.c b/DasharoPayloadPkg/BlSupportDxe/BlSupportDxe.c new file mode 100644 index 0000000000..e2ae2c66b1 --- /dev/null +++ b/DasharoPayloadPkg/BlSupportDxe/BlSupportDxe.c @@ -0,0 +1,303 @@ +/** @file + This driver will report some MMIO/IO resources to dxe core, extract smbios and acpi + tables from bootloader. + + Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include "BlSupportDxe.h" + +/** + Reserve MMIO/IO resource in GCD + + @param IsMMIO Flag of whether it is mmio resource or io resource. + @param GcdType Type of the space. + @param BaseAddress Base address of the space. + @param Length Length of the space. + @param Alignment Align with 2^Alignment + @param ImageHandle Handle for the image of this driver. + + @retval EFI_SUCCESS Reserve successful +**/ +EFI_STATUS +ReserveResourceInGcd ( + IN BOOLEAN IsMMIO, + IN UINTN GcdType, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINTN Alignment, + IN EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor; + + Status = gDS->GetMemorySpaceDescriptor ((EFI_PHYSICAL_ADDRESS)BaseAddress, &GcdDescriptor); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "Failed to look up memory space: 0x%lx 0x%lx\n", + BaseAddress, + Length + )); + return EFI_ACCESS_DENIED; + } + + if (GcdDescriptor.GcdMemoryType != EfiGcdMemoryTypeNonExistent) { + DEBUG (( + DEBUG_ERROR, + "Skipping to add memory space: 0x%lx 0x%lx, already exists\n", + BaseAddress, + Length + )); + return EFI_SUCCESS; + } + + if (IsMMIO) { + Status = gDS->AddMemorySpace ( + GcdType, + BaseAddress, + Length, + EFI_MEMORY_UC + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "Failed to add memory space :0x%lx 0x%lx\n", + BaseAddress, + Length + )); + } + ASSERT_EFI_ERROR (Status); + Status = gDS->AllocateMemorySpace ( + EfiGcdAllocateAddress, + GcdType, + Alignment, + Length, + &BaseAddress, + ImageHandle, + NULL + ); + ASSERT_EFI_ERROR (Status); + } else { + Status = gDS->AddIoSpace ( + GcdType, + BaseAddress, + Length + ); + ASSERT_EFI_ERROR (Status); + Status = gDS->AllocateIoSpace ( + EfiGcdAllocateAddress, + GcdType, + Alignment, + Length, + &BaseAddress, + ImageHandle, + NULL + ); + ASSERT_EFI_ERROR (Status); + } + return Status; +} + +EFI_STATUS +EFIAPI +BlDxeInstallSMBIOStables( + IN UINT64 SmbiosTableBase, + IN UINT32 SmbiosTableSize +) +{ + EFI_STATUS Status; + SMBIOS_TABLE_ENTRY_POINT *SmbiosTable; + SMBIOS_TABLE_3_0_ENTRY_POINT *Smbios30Table; + SMBIOS_STRUCTURE_POINTER Smbios; + SMBIOS_STRUCTURE_POINTER SmbiosEnd; + CHAR8 *String; + EFI_SMBIOS_HANDLE SmbiosHandle; + EFI_SMBIOS_PROTOCOL *SmbiosProto; + + // + // Locate Smbios protocol. + // + Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **)&SmbiosProto); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Failed to locate gEfiSmbiosProtocolGuid\n", + __FUNCTION__ + )); + return Status; + } + + Smbios30Table = (SMBIOS_TABLE_3_0_ENTRY_POINT *)(UINTN)(SmbiosTableBase); + SmbiosTable = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)(SmbiosTableBase); + + if (CompareMem (Smbios30Table->AnchorString, "_SM3_", 5) == 0) { + Smbios.Hdr = (SMBIOS_STRUCTURE *) (UINTN) Smbios30Table->TableAddress; + SmbiosEnd.Raw = (UINT8 *) (UINTN) (Smbios30Table->TableAddress + Smbios30Table->TableMaximumSize); + if (Smbios30Table->TableMaximumSize > SmbiosTableSize) { + DEBUG((EFI_D_INFO, "%a: SMBIOS table size greater than reported by bootloader\n", + __FUNCTION__)); + } + } else if (CompareMem (SmbiosTable->AnchorString, "_SM_", 4) == 0) { + Smbios.Hdr = (SMBIOS_STRUCTURE *) (UINTN) SmbiosTable->TableAddress; + SmbiosEnd.Raw = (UINT8 *) ((UINTN) SmbiosTable->TableAddress + SmbiosTable->TableLength); + + if (SmbiosTable->TableLength > SmbiosTableSize) { + DEBUG((EFI_D_INFO, "%a: SMBIOS table size greater than reported by bootloader\n", + __FUNCTION__ + )); + } + } else { + DEBUG ((DEBUG_ERROR, "%a: No valid SMBIOS table found\n", + __FUNCTION__ + )); + return EFI_NOT_FOUND; + } + + do { + // Check for end marker + if (Smbios.Hdr->Type == 127) { + break; + } + + // Install the table + SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; + Status = SmbiosProto->Add ( + SmbiosProto, + gImageHandle, + &SmbiosHandle, + Smbios.Hdr + ); + ASSERT_EFI_ERROR (Status); + + // + // Go to the next SMBIOS structure. Each SMBIOS structure may include 2 parts: + // 1. Formatted section; 2. Unformatted string section. So, 2 steps are needed + // to skip one SMBIOS structure. + // + + // + // Step 1: Skip over formatted section. + // + String = (CHAR8 *) (Smbios.Raw + Smbios.Hdr->Length); + + // + // Step 2: Skip over unformatted string section. + // + do { + // + // Each string is terminated with a NULL(00h) BYTE and the sets of strings + // is terminated with an additional NULL(00h) BYTE. + // + for ( ; *String != 0; String++) { + } + + if (*(UINT8*)++String == 0) { + // + // Pointer to the next SMBIOS structure. + // + Smbios.Raw = (UINT8 *)++String; + break; + } + } while (TRUE); + } while (Smbios.Raw < SmbiosEnd.Raw); + + return EFI_SUCCESS; +} + +/** + Main entry for the bootloader support DXE module. + + @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 +BlDxeEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HOB_GUID_TYPE *GuidHob; + SYSTEM_TABLE_INFO *SystemTableInfo; + EFI_PEI_GRAPHICS_INFO_HOB *GfxInfo; + EFI_GUID FwGuid; + UINT32 FwVersion; + UINT32 FwLsv; + UINT32 FwSize; + EFI_SYSTEM_RESOURCE_TABLE *Esrt; + EFI_SYSTEM_RESOURCE_ENTRY *Esre; + + Status = EFI_SUCCESS; + // + // Report MMIO/IO Resources + // + Status = ReserveResourceInGcd (TRUE, EfiGcdMemoryTypeMemoryMappedIo, 0xFEC00000, SIZE_4KB, 0, ImageHandle); // IOAPIC + ASSERT_EFI_ERROR (Status); + + Status = ReserveResourceInGcd (TRUE, EfiGcdMemoryTypeMemoryMappedIo, 0xFED00000, SIZE_1KB, 0, ImageHandle); // HPET + ASSERT_EFI_ERROR (Status); + + // + // Find the system table information guid hob + // + GuidHob = GetFirstGuidHob (&gUefiSystemTableInfoGuid); + ASSERT (GuidHob != NULL); + SystemTableInfo = (SYSTEM_TABLE_INFO *)GET_GUID_HOB_DATA (GuidHob); + + // + // Install Smbios Table + // + if (SystemTableInfo->SmbiosTableBase != 0 && SystemTableInfo->SmbiosTableSize != 0) { + DEBUG ((DEBUG_ERROR, "Install Smbios Table at 0x%lx, length 0x%x\n", SystemTableInfo->SmbiosTableBase, SystemTableInfo->SmbiosTableSize)); + + if (BlDxeInstallSMBIOStables(SystemTableInfo->SmbiosTableBase, + SystemTableInfo->SmbiosTableSize) != EFI_SUCCESS) { + Status = gBS->InstallConfigurationTable (&gEfiSmbiosTableGuid, (VOID *)(UINTN)SystemTableInfo->SmbiosTableBase); + ASSERT_EFI_ERROR (Status); + } + } + + // + // Find the frame buffer information and update PCDs + // + GuidHob = GetFirstGuidHob (&gEfiGraphicsInfoHobGuid); + if (GuidHob != NULL) { + GfxInfo = (EFI_PEI_GRAPHICS_INFO_HOB *)GET_GUID_HOB_DATA (GuidHob); + Status = PcdSet32S (PcdVideoHorizontalResolution, GfxInfo->GraphicsMode.HorizontalResolution); + ASSERT_EFI_ERROR (Status); + Status = PcdSet32S (PcdVideoVerticalResolution, GfxInfo->GraphicsMode.VerticalResolution); + ASSERT_EFI_ERROR (Status); + Status = PcdSet32S (PcdSetupVideoHorizontalResolution, GfxInfo->GraphicsMode.HorizontalResolution); + ASSERT_EFI_ERROR (Status); + Status = PcdSet32S (PcdSetupVideoVerticalResolution, GfxInfo->GraphicsMode.VerticalResolution); + ASSERT_EFI_ERROR (Status); + } + + Status = ParseFwInfo (&FwGuid, &FwVersion, &FwLsv, &FwSize); + if (!EFI_ERROR (Status)) { + Esrt = AllocateZeroPool (sizeof (EFI_SYSTEM_RESOURCE_TABLE) + sizeof (EFI_SYSTEM_RESOURCE_ENTRY)); + ASSERT (Esrt != NULL); + + Esrt->FwResourceVersion = EFI_SYSTEM_RESOURCE_TABLE_FIRMWARE_RESOURCE_VERSION; + Esrt->FwResourceCount = 1; + Esrt->FwResourceCountMax = 1; + + Esre = (EFI_SYSTEM_RESOURCE_ENTRY *)&Esrt[1]; + CopyMem (&Esre->FwClass, &FwGuid, sizeof (EFI_GUID)); + Esre->FwType = ESRT_FW_TYPE_SYSTEMFIRMWARE; + Esre->FwVersion = FwVersion; + Esre->LowestSupportedFwVersion = FwLsv; + + Status = gBS->InstallConfigurationTable (&gEfiSystemResourceTableGuid, Esrt); + ASSERT_EFI_ERROR (Status); + } + + return EFI_SUCCESS; +} + diff --git a/DasharoPayloadPkg/BlSupportDxe/BlSupportDxe.h b/DasharoPayloadPkg/BlSupportDxe/BlSupportDxe.h new file mode 100644 index 0000000000..3325519925 --- /dev/null +++ b/DasharoPayloadPkg/BlSupportDxe/BlSupportDxe.h @@ -0,0 +1,38 @@ +/** @file + The header file of bootloader support DXE. + +Copyright (c) 2014, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#ifndef __DXE_BOOTLOADER_SUPPORT_H__ +#define __DXE_BOOTLOADER_SUPPORT_H__ + +#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/DasharoPayloadPkg/BlSupportDxe/BlSupportDxe.inf b/DasharoPayloadPkg/BlSupportDxe/BlSupportDxe.inf new file mode 100644 index 0000000000..ea9e749d74 --- /dev/null +++ b/DasharoPayloadPkg/BlSupportDxe/BlSupportDxe.inf @@ -0,0 +1,64 @@ +## @file +# Bootloader Support DXE Module +# +# Report some MMIO/IO resources to dxe core, extract smbios and acpi tables +# +# Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BlSupportDxe + FILE_GUID = C68DAA4E-7AB5-41e8-A91D-5954421053F3 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = BlDxeEntryPoint + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + BlSupportDxe.c + BlSupportDxe.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + DasharoPayloadPkg/DasharoPayloadPkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + UefiBootServicesTableLib + DxeServicesTableLib + DebugLib + BaseMemoryLib + UefiLib + HobLib + BlParseLib + MemoryAllocationLib + +[Guids] + gEfiAcpiTableGuid + gEfiSmbiosTableGuid + gUefiSystemTableInfoGuid + gUefiAcpiBoardInfoGuid + gEfiGraphicsInfoHobGuid + gEfiSystemResourceTableGuid + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution + +[Protocols] + gEfiSmbiosProtocolGuid + +[Depex] + gEfiSmbiosProtocolGuid diff --git a/DasharoPayloadPkg/BlSupportPei/BlSupportPei.c b/DasharoPayloadPkg/BlSupportPei/BlSupportPei.c new file mode 100644 index 0000000000..383a76314e --- /dev/null +++ b/DasharoPayloadPkg/BlSupportPei/BlSupportPei.c @@ -0,0 +1,768 @@ +/** @file + This PEIM will parse bootloader information and report resource information into pei core. + This file contains the main entrypoint of the PEIM. + +Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include "BlSupportPei.h" + +#define PEI_MEM_SIZE SIZE_64MB + +#define LEGACY_8259_MASK_REGISTER_MASTER 0x21 +#define LEGACY_8259_MASK_REGISTER_SLAVE 0xA1 + +EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = { + { EfiACPIReclaimMemory, FixedPcdGet32 (PcdMemoryTypeEfiACPIReclaimMemory) }, + { EfiACPIMemoryNVS, FixedPcdGet32 (PcdMemoryTypeEfiACPIMemoryNVS) }, + { EfiReservedMemoryType, FixedPcdGet32 (PcdMemoryTypeEfiReservedMemoryType) }, + { EfiRuntimeServicesData, FixedPcdGet32 (PcdMemoryTypeEfiRuntimeServicesData) }, + { EfiRuntimeServicesCode, FixedPcdGet32 (PcdMemoryTypeEfiRuntimeServicesCode) }, + { EfiMaxMemoryType, 0 } +}; + +EFI_PEI_PPI_DESCRIPTOR mPpiBootMode[] = { + { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gEfiPeiMasterBootModePpiGuid, + NULL + } +}; + +EFI_PEI_GRAPHICS_DEVICE_INFO_HOB mDefaultGraphicsDeviceInfo = { + MAX_UINT16, MAX_UINT16, MAX_UINT16, MAX_UINT16, MAX_UINT8, MAX_UINT8 +}; + +/** + Create memory mapped io resource hob. + + @param MmioBase Base address of the memory mapped io range + @param MmioSize Length of the memory mapped io range + +**/ +VOID +BuildMemoryMappedIoRangeHob ( + EFI_PHYSICAL_ADDRESS MmioBase, + UINT64 MmioSize + ) +{ + BuildResourceDescriptorHob ( + EFI_RESOURCE_MEMORY_MAPPED_IO, + (EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_TESTED), + MmioBase, + MmioSize + ); + + BuildMemoryAllocationHob ( + MmioBase, + MmioSize, + EfiMemoryMappedIO + ); +} + +/** + Check the integrity of firmware volume header + + @param[in] FwVolHeader A pointer to a firmware volume header + + @retval TRUE The firmware volume is consistent + @retval FALSE The firmware volume has corrupted. + +**/ +STATIC +BOOLEAN +IsFvHeaderValid ( + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader + ) +{ + UINT16 Checksum; + + // Skip nv storage fv + if (CompareMem (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem2Guid, sizeof(EFI_GUID)) != 0 ) { + return FALSE; + } + + if ( (FwVolHeader->Revision != EFI_FVH_REVISION) || + (FwVolHeader->Signature != EFI_FVH_SIGNATURE) || + (FwVolHeader->FvLength == ((UINTN) -1)) || + ((FwVolHeader->HeaderLength & 0x01 ) !=0) ) { + return FALSE; + } + + Checksum = CalculateCheckSum16 ((UINT16 *) FwVolHeader, FwVolHeader->HeaderLength); + if (Checksum != 0) { + DEBUG (( DEBUG_ERROR, + "ERROR - Invalid Firmware Volume Header Checksum, change 0x%04x to 0x%04x\r\n", + FwVolHeader->Checksum, + (UINT16)( Checksum + FwVolHeader->Checksum ))); + return TRUE; //FALSE; Need update UEFI build tool when patching entrypoin @start of fd. + } + + return TRUE; +} + +/** + Install FvInfo PPI and create fv hobs for remained fvs + +**/ +VOID +PeiReportRemainedFvs ( + VOID + ) +{ + UINT8* TempPtr; + UINT8* EndPtr; + + TempPtr = (UINT8* )(UINTN) PcdGet32 (PcdPayloadFdMemBase); + EndPtr = (UINT8* )(UINTN) (PcdGet32 (PcdPayloadFdMemBase) + PcdGet32 (PcdPayloadFdMemSize)); + + for (;TempPtr < EndPtr;) { + if (IsFvHeaderValid ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)) { + if (TempPtr != (UINT8* )(UINTN) PcdGet32 (PcdPayloadFdMemBase)) { + // Skip the PEI FV + DEBUG((DEBUG_INFO, "Found one valid fv : 0x%lx.\n", TempPtr, ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength)); + + PeiServicesInstallFvInfoPpi ( + NULL, + (VOID *) (UINTN) TempPtr, + (UINT32) (UINTN) ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength, + NULL, + NULL + ); + BuildFvHob ((EFI_PHYSICAL_ADDRESS)(UINTN) TempPtr, ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength); + } + } + TempPtr += ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength; + } +} + + +/** + Find the board related info from ACPI table + + @param AcpiTableBase ACPI table start address in memory + @param AcpiBoardInfo Pointer to the acpi board info strucutre + + @retval RETURN_SUCCESS Successfully find out all the required information. + @retval RETURN_NOT_FOUND Failed to find the required info. + +**/ +RETURN_STATUS +ParseAcpiInfo ( + IN UINT64 AcpiTableBase, + OUT ACPI_BOARD_INFO *AcpiBoardInfo + ) +{ + EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp; + EFI_ACPI_DESCRIPTION_HEADER *Rsdt; + UINT32 *Entry32; + UINTN Entry32Num; + EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt; + EFI_ACPI_DESCRIPTION_HEADER *Xsdt; + UINT64 *Entry64; + UINTN Entry64Num; + UINTN Idx; + UINT32 *Signature; + EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER *MmCfgHdr; + EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *MmCfgBase; + + Rsdp = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)(UINTN)AcpiTableBase; + DEBUG ((DEBUG_INFO, "Rsdp at 0x%p\n", Rsdp)); + DEBUG ((DEBUG_INFO, "Rsdt at 0x%x, Xsdt at 0x%lx\n", Rsdp->RsdtAddress, Rsdp->XsdtAddress)); + + // + // Search Rsdt First + // + Fadt = NULL; + MmCfgHdr = NULL; + Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)(Rsdp->RsdtAddress); + if (Rsdt != NULL) { + Entry32 = (UINT32 *)(Rsdt + 1); + Entry32Num = (Rsdt->Length - sizeof(EFI_ACPI_DESCRIPTION_HEADER)) >> 2; + for (Idx = 0; Idx < Entry32Num; Idx++) { + Signature = (UINT32 *)(UINTN)Entry32[Idx]; + if (*Signature == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) { + Fadt = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)Signature; + DEBUG ((DEBUG_INFO, "Found Fadt in Rsdt\n")); + } + + if (*Signature == EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE) { + MmCfgHdr = (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER *)Signature; + DEBUG ((DEBUG_INFO, "Found MM config address in Rsdt\n")); + } + + if ((Fadt != NULL) && (MmCfgHdr != NULL)) { + goto Done; + } + } + } + + // + // Search Xsdt Second + // + Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)(Rsdp->XsdtAddress); + if (Xsdt != NULL) { + Entry64 = (UINT64 *)(Xsdt + 1); + Entry64Num = (Xsdt->Length - sizeof(EFI_ACPI_DESCRIPTION_HEADER)) >> 3; + for (Idx = 0; Idx < Entry64Num; Idx++) { + Signature = (UINT32 *)(UINTN)Entry64[Idx]; + if (*Signature == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) { + Fadt = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)Signature; + DEBUG ((DEBUG_INFO, "Found Fadt in Xsdt\n")); + } + + if (*Signature == EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE) { + MmCfgHdr = (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER *)Signature; + DEBUG ((DEBUG_INFO, "Found MM config address in Xsdt\n")); + } + + if ((Fadt != NULL) && (MmCfgHdr != NULL)) { + goto Done; + } + } + } + + if (Fadt == NULL) { + return RETURN_NOT_FOUND; + } + +Done: + + AcpiBoardInfo->PmCtrlRegBase = Fadt->Pm1aCntBlk; + AcpiBoardInfo->PmTimerRegBase = Fadt->PmTmrBlk; + AcpiBoardInfo->ResetRegAddress = Fadt->ResetReg.Address; + AcpiBoardInfo->ResetValue = Fadt->ResetValue; + AcpiBoardInfo->PmEvtBase = Fadt->Pm1aEvtBlk; + AcpiBoardInfo->PmGpeEnBase = Fadt->Gpe0Blk + Fadt->Gpe0BlkLen / 2; + + if (MmCfgHdr != NULL) { + MmCfgBase = (EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *)((UINT8*) MmCfgHdr + sizeof (*MmCfgHdr)); + AcpiBoardInfo->PcieBaseAddress = MmCfgBase->BaseAddress; + AcpiBoardInfo->PcieBaseSize = (MmCfgBase->EndBusNumber + 1 - MmCfgBase->StartBusNumber) * 4096 * 32 * 8; + } else { + AcpiBoardInfo->PcieBaseAddress = 0; + AcpiBoardInfo->PcieBaseSize = 0; + } + DEBUG ((DEBUG_INFO, "PmCtrl Reg 0x%lx\n", AcpiBoardInfo->PmCtrlRegBase)); + DEBUG ((DEBUG_INFO, "PmTimer Reg 0x%lx\n", AcpiBoardInfo->PmTimerRegBase)); + DEBUG ((DEBUG_INFO, "Reset Reg 0x%lx\n", AcpiBoardInfo->ResetRegAddress)); + DEBUG ((DEBUG_INFO, "Reset Value 0x%x\n", AcpiBoardInfo->ResetValue)); + DEBUG ((DEBUG_INFO, "PmEvt Reg 0x%lx\n", AcpiBoardInfo->PmEvtBase)); + DEBUG ((DEBUG_INFO, "PmGpeEn Reg 0x%lx\n", AcpiBoardInfo->PmGpeEnBase)); + DEBUG ((DEBUG_INFO, "PcieBaseAddr 0x%lx\n", AcpiBoardInfo->PcieBaseAddress)); + DEBUG ((DEBUG_INFO, "PcieBaseSize 0x%lx\n", AcpiBoardInfo->PcieBaseSize)); + + // + // Verify values for proper operation + // + ASSERT(Fadt->Pm1aCntBlk != 0); + ASSERT(Fadt->PmTmrBlk != 0); + ASSERT(Fadt->ResetReg.Address != 0); + ASSERT(Fadt->Pm1aEvtBlk != 0); + ASSERT(Fadt->Gpe0Blk != 0); + + DEBUG_CODE_BEGIN (); + BOOLEAN SciEnabled; + + // + // Check the consistency of SCI enabling + // + + // + // Get SCI_EN value + // + if (Fadt->Pm1CntLen == 4) { + SciEnabled = (IoRead32 (Fadt->Pm1aCntBlk) & BIT0)? TRUE : FALSE; + } else { + // + // if (Pm1CntLen == 2), use 16 bit IO read; + // if (Pm1CntLen != 2 && Pm1CntLen != 4), use 16 bit IO read as a fallback + // + SciEnabled = (IoRead16 (Fadt->Pm1aCntBlk) & BIT0)? TRUE : FALSE; + } + + if (!(Fadt->Flags & EFI_ACPI_5_0_HW_REDUCED_ACPI) && + (Fadt->SmiCmd == 0) && + !SciEnabled) { + // + // The ACPI enabling status is inconsistent: SCI is not enabled but ACPI + // table does not provide a means to enable it through FADT->SmiCmd + // + DEBUG ((DEBUG_ERROR, "ERROR: The ACPI enabling status is inconsistent: SCI is not" + " enabled but the ACPI table does not provide a means to enable it through FADT->SmiCmd." + " This may cause issues in OS.\n")); + } + DEBUG_CODE_END (); + + return RETURN_SUCCESS; +} + +EFI_STATUS +MemInfoCallback ( + IN MEMROY_MAP_ENTRY *MemoryMapEntry, + IN VOID *Params + ) +{ + EFI_PHYSICAL_ADDRESS *UsableLowMemTop; + UINTN Attribute; + EFI_PHYSICAL_ADDRESS Base; + EFI_RESOURCE_TYPE Type; + UINT64 Size; + UINT8 Flag; + + Attribute = EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_TESTED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE; + + UsableLowMemTop = (EFI_PHYSICAL_ADDRESS *)Params; + Type = MemoryMapEntry->Type; + Base = MemoryMapEntry->Base; + Size = MemoryMapEntry->Size; + Flag = MemoryMapEntry->Flag; + + if ((Base < BASE_1MB) && ((Base + Size) > BASE_1MB)) { + Size -= (BASE_1MB - Base); + Base = BASE_1MB; + } + + if (Base >= BASE_1MB) { + if (!(Flag & EFI_RESOURCE_ATTRIBUTE_PRESENT)) { + BuildResourceDescriptorHob ( + Type, + 0, + (EFI_PHYSICAL_ADDRESS)Base, + Size + ); + } else if (Type == EFI_RESOURCE_SYSTEM_MEMORY) { + if (Base < BASE_4GB) { + // + // Skip regions smaller than PEI_MEM_SIZE, the highest non-reserved + // region may be too small. + // + if (Size >= PEI_MEM_SIZE) { + *UsableLowMemTop = Base + Size; + } + } else { + Attribute &= ~EFI_RESOURCE_ATTRIBUTE_TESTED; + } + BuildResourceDescriptorHob ( + EFI_RESOURCE_SYSTEM_MEMORY, + Attribute, + (EFI_PHYSICAL_ADDRESS)Base, + Size + ); + } else if (Type == EFI_RESOURCE_MEMORY_RESERVED) { + BuildResourceDescriptorHob ( + EFI_RESOURCE_MEMORY_RESERVED, + Attribute, + (EFI_PHYSICAL_ADDRESS)Base, + Size + ); + BuildMemoryAllocationHob ( + (EFI_PHYSICAL_ADDRESS)Base, + Size, + EfiACPIReclaimMemory + ); + } else if (Type == EFI_RESOURCE_MEMORY_MAPPED_IO) { + BuildMemoryMappedIoRangeHob((EFI_PHYSICAL_ADDRESS)Base, Size); + } else if (Type == EFI_RESOURCE_FIRMWARE_DEVICE) { + BuildResourceDescriptorHob ( + EFI_RESOURCE_FIRMWARE_DEVICE, + (EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_TESTED), + (EFI_PHYSICAL_ADDRESS)Base, + Size + ); + BuildMemoryAllocationHob ( + (EFI_PHYSICAL_ADDRESS)Base, + Size, + EfiACPIMemoryNVS + ); + } + } + + return EFI_SUCCESS; +} + +/** + Check the integrity of firmware volume header. + + @retval EFI_SUCCESS - The firmware volume is consistent + @retval EFI_NOT_FOUND - The firmware volume has been corrupted. + +**/ +EFI_STATUS +ValidateFvHeader ( + SMMSTORE_INFO *SmmStoreInfo + ) +{ + UINT16 Checksum; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + VARIABLE_STORE_HEADER *VariableStoreHeader; + UINTN VariableStoreLength; + UINTN FvLength; + UINT32 NvStorageSize; + UINT32 NvVariableSize; + UINT32 FtwWorkingSize; + UINT32 FtwSpareSize; + + + NvStorageSize = SmmStoreInfo->NumBlocks * SmmStoreInfo->BlockSize; + FtwSpareSize = (SmmStoreInfo->NumBlocks / 2) * SmmStoreInfo->BlockSize; + FtwWorkingSize = SmmStoreInfo->BlockSize; + NvVariableSize = NvStorageSize - FtwSpareSize - FtwWorkingSize; + + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)SmmStoreInfo->MmioAddress; + if (!FwVolHeader) { + return EFI_OUT_OF_RESOURCES; + } + + + FvLength = FtwSpareSize + FtwWorkingSize + NvVariableSize; + + // + // Verify the header revision, header signature, length + // Length of FvBlock cannot be 2**64-1 + // HeaderLength cannot be an odd number + // + if ( (FwVolHeader->Revision != EFI_FVH_REVISION) + || (FwVolHeader->Signature != EFI_FVH_SIGNATURE) + || (FwVolHeader->FvLength != FvLength) + ) + { + DEBUG (( + DEBUG_INFO, + "%a: No Firmware Volume header present\n", + __FUNCTION__ + )); + return EFI_NOT_FOUND; + } + + // Check the Firmware Volume Guid + if ( CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid) == FALSE ) { + DEBUG (( + DEBUG_INFO, + "%a: Firmware Volume Guid non-compatible\n", + __FUNCTION__ + )); + return EFI_NOT_FOUND; + } + + // Verify the header checksum + Checksum = CalculateSum16 ((UINT16 *)FwVolHeader, FwVolHeader->HeaderLength); + if (Checksum != 0) { + DEBUG (( + DEBUG_INFO, + "%a: FV checksum is invalid (Checksum:0x%X)\n", + __FUNCTION__, + Checksum + )); + return EFI_NOT_FOUND; + } + + VariableStoreHeader = (VARIABLE_STORE_HEADER *)(UINTN)(SmmStoreInfo->MmioAddress + FwVolHeader->HeaderLength); + + // Check the Variable Store Guid + if (!CompareGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid) && + !CompareGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid)) + { + DEBUG (( + DEBUG_INFO, + "%a: Variable Store Guid non-compatible\n", + __FUNCTION__ + )); + return EFI_NOT_FOUND; + } + + VariableStoreLength = NvVariableSize - FwVolHeader->HeaderLength; + if (VariableStoreHeader->Size != VariableStoreLength) { + DEBUG (( + DEBUG_INFO, + "%a: Variable Store Length does not match\n", + __FUNCTION__ + )); + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + +/** + This is the entrypoint of PEIM + + @param FileHandle Handle of the file being invoked. + @param PeiServices Describes the list of possible PEI Services. + + @retval EFI_SUCCESS if it completed successfully. +**/ +EFI_STATUS +EFIAPI +BlPeiEntryPoint ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS UsableLowMemTop = 0; + EFI_PHYSICAL_ADDRESS PeiMemBase = 0; + UINT32 RegEax; + UINT8 PhysicalAddressBits; + SYSTEM_TABLE_INFO SysTableInfo; + SYSTEM_TABLE_INFO *NewSysTableInfo; + ACPI_BOARD_INFO AcpiBoardInfo; + ACPI_BOARD_INFO *NewAcpiBoardInfo; + SMMSTORE_INFO SMMSTOREInfo; + SMMSTORE_INFO *NewSMMSTOREInfo; + TCG_PHYSICAL_PRESENCE_INFO PhysicalPresenceInfo; + TCG_PHYSICAL_PRESENCE_INFO *NewPhysicalPresenceInfo; + EFI_PEI_GRAPHICS_INFO_HOB GfxInfo; + EFI_PEI_GRAPHICS_INFO_HOB *NewGfxInfo; + EFI_PEI_GRAPHICS_DEVICE_INFO_HOB GfxDeviceInfo; + EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *NewGfxDeviceInfo; + FIRMWARE_SEC_PERFORMANCE Performance; + + // Report lower 640KB of RAM. + // Mark memory as reserved to keep coreboot header in place. + // + BuildResourceDescriptorHob ( + EFI_RESOURCE_MEMORY_RESERVED, + ( + EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_TESTED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE + ), + (EFI_PHYSICAL_ADDRESS)(0), + (UINT64)(0x1000) + ); + + BuildResourceDescriptorHob ( + EFI_RESOURCE_SYSTEM_MEMORY, + ( + EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE + ), + (EFI_PHYSICAL_ADDRESS)(0x1000), + (UINT64)(0x9F000) + ); + + BuildResourceDescriptorHob ( + EFI_RESOURCE_MEMORY_RESERVED, + ( + EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_TESTED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE + ), + (EFI_PHYSICAL_ADDRESS)(0xA0000), + (UINT64)(0x60000) + ); + + + // + // Parse memory info + // + Status = ParseMemoryInfo (MemInfoCallback, &UsableLowMemTop); + if (EFI_ERROR(Status)) { + return Status; + } + + // + // Install memory + // + ASSERT (UsableLowMemTop >= BASE_1MB + PEI_MEM_SIZE); + PeiMemBase = (UsableLowMemTop - PEI_MEM_SIZE) & (~(BASE_64KB - 1)); + DEBUG ((DEBUG_INFO, "UsableLowMemTop 0x%lx\n", UsableLowMemTop)); + DEBUG ((DEBUG_INFO, "PeiMemBase: 0x%lx.\n", PeiMemBase)); + DEBUG ((DEBUG_INFO, "PeiMemSize: 0x%lx.\n", PEI_MEM_SIZE)); + Status = PeiServicesInstallPeiMemory (PeiMemBase, PEI_MEM_SIZE); + ASSERT_EFI_ERROR (Status); + + // + // Create Memory Type Information HOB + // + BuildGuidDataHob ( + &gEfiMemoryTypeInformationGuid, + mDefaultMemoryTypeInformation, + sizeof(mDefaultMemoryTypeInformation) + ); + + // + // Create Fv hob + // + PeiReportRemainedFvs (); + + BuildMemoryAllocationHob ( + PcdGet32 (PcdPayloadFdMemBase), + PcdGet32 (PcdPayloadFdMemSize), + EfiBootServicesData + ); + + // + // Build CPU memory space and IO space hob + // + AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); + if (RegEax >= 0x80000008) { + AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL); + PhysicalAddressBits = (UINT8) RegEax; + } else { + PhysicalAddressBits = 36; + } + + // + // Create a CPU hand-off information + // + BuildCpuHob (PhysicalAddressBits, 16); + + // + // Report Local APIC range + // + BuildMemoryMappedIoRangeHob (0xFEC80000, SIZE_512KB); + + // + // Boot mode + // + Status = PeiServicesSetBootMode (BOOT_WITH_FULL_CONFIGURATION); + ASSERT_EFI_ERROR (Status); + + Status = PeiServicesInstallPpi (mPpiBootMode); + ASSERT_EFI_ERROR (Status); + + // + // Create guid hob for frame buffer information + // + Status = ParseGfxInfo (&GfxInfo); + if (!EFI_ERROR (Status)) { + NewGfxInfo = BuildGuidHob (&gEfiGraphicsInfoHobGuid, sizeof (GfxInfo)); + ASSERT (NewGfxInfo != NULL); + CopyMem (NewGfxInfo, &GfxInfo, sizeof (GfxInfo)); + DEBUG ((DEBUG_INFO, "Created graphics info hob\n")); + } + + + Status = ParseGfxDeviceInfo (&GfxDeviceInfo); + if (!EFI_ERROR (Status)) { + NewGfxDeviceInfo = BuildGuidHob (&gEfiGraphicsDeviceInfoHobGuid, sizeof (GfxDeviceInfo)); + ASSERT (NewGfxDeviceInfo != NULL); + CopyMem (NewGfxDeviceInfo, &GfxDeviceInfo, sizeof (GfxDeviceInfo)); + DEBUG ((DEBUG_INFO, "Created graphics device info hob\n")); + } + + // + // Create guid hob for SMMSTORE + // + Status = ParseSMMSTOREInfo (&SMMSTOREInfo); + if (!EFI_ERROR (Status)) { + NewSMMSTOREInfo = BuildGuidHob (&gEfiSmmStoreInfoHobGuid, sizeof (SMMSTOREInfo)); + ASSERT (NewSMMSTOREInfo != NULL); + CopyMem (NewSMMSTOREInfo, &SMMSTOREInfo, sizeof (SMMSTOREInfo)); + DEBUG ((DEBUG_INFO, "Created SMMSTORE info hob\n")); + + Status = ValidateFvHeader (&SMMSTOREInfo); + if (EFI_ERROR (Status)) { + Status = PeiServicesSetBootMode (BOOT_WITH_DEFAULT_SETTINGS); + DEBUG ((DEBUG_INFO, "BootMode: Boot with default settings\n")); + ASSERT_EFI_ERROR (Status); + } else { + Status = PeiServicesSetBootMode (BOOT_ASSUMING_NO_CONFIGURATION_CHANGES); + DEBUG ((DEBUG_INFO, "BootMode: Boot boot assuming no configuration changes\n")); + ASSERT_EFI_ERROR (Status); + } + } + + // + // Create guid hob for Tcg Physical Presence Interface + // + Status = ParseTPMPPIInfo (&PhysicalPresenceInfo); + if (!EFI_ERROR (Status)) { + NewPhysicalPresenceInfo = BuildGuidHob (&gEfiTcgPhysicalPresenceInfoHobGuid, sizeof (TCG_PHYSICAL_PRESENCE_INFO)); + ASSERT (NewPhysicalPresenceInfo != NULL); + CopyMem (NewPhysicalPresenceInfo, &PhysicalPresenceInfo, sizeof (TCG_PHYSICAL_PRESENCE_INFO)); + DEBUG ((DEBUG_INFO, "Created Tcg Physical Presence info hob\n")); + } + + // + // Create guid hob for system tables like acpi table and smbios table + // + Status = ParseSystemTable(&SysTableInfo); + ASSERT_EFI_ERROR (Status); + if (!EFI_ERROR (Status)) { + NewSysTableInfo = BuildGuidHob (&gUefiSystemTableInfoGuid, sizeof (SYSTEM_TABLE_INFO)); + ASSERT (NewSysTableInfo != NULL); + CopyMem (NewSysTableInfo, &SysTableInfo, sizeof (SYSTEM_TABLE_INFO)); + DEBUG ((DEBUG_INFO, "Detected Acpi Table at 0x%lx, length 0x%x\n", SysTableInfo.AcpiTableBase, SysTableInfo.AcpiTableSize)); + DEBUG ((DEBUG_INFO, "Detected Smbios Table at 0x%lx, length 0x%x\n", SysTableInfo.SmbiosTableBase, SysTableInfo.SmbiosTableSize)); + } + + // + // Create guid hob for acpi board information + // + Status = ParseAcpiInfo (SysTableInfo.AcpiTableBase, &AcpiBoardInfo); + ASSERT_EFI_ERROR (Status); + if (!EFI_ERROR (Status)) { + NewAcpiBoardInfo = BuildGuidHob (&gUefiAcpiBoardInfoGuid, sizeof (ACPI_BOARD_INFO)); + ASSERT (NewAcpiBoardInfo != NULL); + CopyMem (NewAcpiBoardInfo, &AcpiBoardInfo, sizeof (ACPI_BOARD_INFO)); + DEBUG ((DEBUG_INFO, "Create acpi board info guid hob\n")); + } + + // Build SEC Performance Data Hob + Status = ParseTimestampTable(&Performance); + if (!EFI_ERROR (Status)) { + BuildGuidDataHob (&gEfiFirmwarePerformanceGuid, &Performance, sizeof (Performance)); + } else { + DEBUG ((DEBUG_ERROR, "Error when parsing timestamp info, Status = %r\n", Status)); + } + + // + // Parse platform specific information. + // + Status = ParsePlatformInfo (); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Error when parsing platform info, Status = %r\n", Status)); + return Status; + } + + // + // Import update capsules, if there are any. + // + Status = ParseCapsules (BuildCvHob); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Error when importing update capsules, Status = %r\n", Status)); + return Status; + } + + if (GetFirstHob (EFI_HOB_TYPE_UEFI_CAPSULE) != NULL) { + Status = PeiServicesSetBootMode (BOOT_ON_FLASH_UPDATE); + ASSERT_EFI_ERROR (Status); + } + + // + // Mask off all legacy 8259 interrupt sources + // + IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF); + IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0xFF); + + return EFI_SUCCESS; +} + diff --git a/DasharoPayloadPkg/BlSupportPei/BlSupportPei.h b/DasharoPayloadPkg/BlSupportPei/BlSupportPei.h new file mode 100644 index 0000000000..17007320c5 --- /dev/null +++ b/DasharoPayloadPkg/BlSupportPei/BlSupportPei.h @@ -0,0 +1,40 @@ +/** @file + The header file of bootloader support PEIM. + +Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#ifndef __PEI_BOOTLOADER_SUPPORT_H__ +#define __PEI_BOOTLOADER_SUPPORT_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 + +#endif diff --git a/DasharoPayloadPkg/BlSupportPei/BlSupportPei.inf b/DasharoPayloadPkg/BlSupportPei/BlSupportPei.inf new file mode 100644 index 0000000000..08a14e0040 --- /dev/null +++ b/DasharoPayloadPkg/BlSupportPei/BlSupportPei.inf @@ -0,0 +1,81 @@ +## @file +# Bootloader Support PEI Module +# +# Parses bootloader information and report resource information into pei core. It will install +# the memory as required. +# +# Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BlSupportPeim + FILE_GUID = 352C6AF8-315B-4bd6-B04F-31D4ED1EBE57 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + ENTRY_POINT = BlPeiEntryPoint + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + BlSupportPei.c + BlSupportPei.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + IntelFsp2Pkg/IntelFsp2Pkg.dec + IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dec + DasharoPayloadPkg/DasharoPayloadPkg.dec + UefiCpuPkg/UefiCpuPkg.dec + +[LibraryClasses] + PeimEntryPoint + PeiServicesLib + BaseLib + BaseMemoryLib + DebugLib + HobLib + PcdLib + BlParseLib + MtrrLib + IoLib + PlatformSupportLib + +[Guids] + gEfiMemoryTypeInformationGuid + gEfiFirmwareFileSystem2Guid + gUefiSystemTableInfoGuid + gEfiGraphicsInfoHobGuid + gEfiGraphicsDeviceInfoHobGuid + gUefiAcpiBoardInfoGuid + gEfiSmmStoreInfoHobGuid + gEfiTcgPhysicalPresenceInfoHobGuid + gEfiFirmwarePerformanceGuid + gEfiSystemNvDataFvGuid + gEfiVariableGuid + gEfiAuthenticatedVariableGuid + gEdkiiNvVarStoreFormattedGuid + +[Ppis] + gEfiPeiMasterBootModePpiGuid + +[Pcd] + gDasharoPayloadPkgTokenSpaceGuid.PcdPayloadFdMemBase + gDasharoPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize + gDasharoPayloadPkgTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory + gDasharoPayloadPkgTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS + gDasharoPayloadPkgTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType + gDasharoPayloadPkgTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData + gDasharoPayloadPkgTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode + +[Depex] + TRUE diff --git a/DasharoPayloadPkg/BuildAndIntegrationInstructions.txt b/DasharoPayloadPkg/BuildAndIntegrationInstructions.txt new file mode 100644 index 0000000000..b06c699d54 --- /dev/null +++ b/DasharoPayloadPkg/BuildAndIntegrationInstructions.txt @@ -0,0 +1,82 @@ +================================================================================ +Build And Integration Instructions +2019 March 27th +================================================================================ + +================================================================================ +DISCLAIMER +================================================================================ +This release note as well as the software described in it is furnished under license +and may only be used or copied in accordance with the terms of the license. The +information in this manual is furnished for informational use only, is subject to +change without notice, and should not be construed as a commitment by Intel Corporation. +Intel Corporation assumes no responsibility or liability for any errors or inaccuracies +that may appear in this document or any software that may be provided in association +with this document. +Except as permitted by such license, no part of this document may be reproduced, +stored in a retrieval system, or transmitted in any form or by any means without +the express written consent of Intel Corporation. + +================================================================================ + INDEX +================================================================================ +A. INTRODUCTION +B. HOW TO BUILD +C. HOW TO INTEGRATE INTO COREBOOT +D. HOW TO INTEGRATE INTO SLIM BOOTLOADER + +================================================================================ +A. INTRODUCTION +================================================================================ +This document provides instructions on how to build UEFI Payload and how to +integrate it into coreboot or Slim Bootloader firmware. + +================================================================================ +B. HOW TO BUILD +================================================================================ +1. Run the below two commands in windows command prompt window: + edksetup.bat + + For debug ia32 build: + build -a IA32 -p DasharoPayloadPkg\DasharoPayloadPkgIa32.dsc -b DEBUG -t -D BOOTLOADER= + + For release ia32 build: + build -a IA32 -p DasharoPayloadPkg\DasharoPayloadPkgIa32.dsc -b RELEASE -t -D BOOTLOADER= + + For debug X64 build: + build -a IA32 -a X64 -p DasharoPayloadPkg\DasharoPayloadPkgIa32X64.dsc -b DEBUG -t -D BOOTLOADER= + + For release X64 build: + build -a IA32 -a X64 -p DasharoPayloadPkg\DasharoPayloadPkgIa32X64.dsc -b RELEASE -t -D BOOTLOADER= + + is the EDK II build environment on your host. Currently it was tested + with VS2015x86 toolchain. + could be "SBL" for Slim Bootloader and "COREBOOT" for coreboot. + + Refer to https://github.com/tianocore/tianocore.github.io/wiki/UDK2018-How-to-Build for + details about EDK II build steps. + +2. If build is successfully, the payload image (UEFIPAYLOAD.fd) will be generated inside the + folder of Build\DasharoPayloadPkg. + +================================================================================ +C. HOW TO INTEGRATE INTO COREBOOT +================================================================================ +1. Copy the payload image (UEFIPAYLOAD.fd) into the top-level directory of Coreboot source tree. +2. Run "make menuconfig" in linux console to start Coreboot configuration surface. +3. In the Payload section, + 1) Choose "An ELF executable payload" for the option of "Add a payload". + 2) Type the path of payload image for the option of "Payload path and filename". + 3) Select the option of "Use LZMA compression for payloads". +4. If the graphics console is required in UEFI payload, enable framebuffer initialization in coreboot. + This could be done by enabling native graphics or using VGA BIOS option rom. +5. Build the coreboot firmware image. + +================================================================================ +D. HOW TO INTEGRATE INTO SLIM BOOTLOADER +================================================================================ +Please refer https://slimbootloader.github.io/how-tos/integrate-multiple-payloads.html for below steps. +1. Copy the payload image (UEFIPAYLOAD.fd) into Slim Bootloader source at PayloadPkg\PayloadBins\UefiPld.fd +2. Update config data to make UEFI payload as default payload if required. +3. Build Slim Bootloader with UEFI payload: + BuildLoader.py build -p "OsLoader.efi:LLDR:Lz4;UefiPld.fd:UEFI:Lzma" diff --git a/DasharoPayloadPkg/CapsuleRootKey.inc b/DasharoPayloadPkg/CapsuleRootKey.inc new file mode 100644 index 0000000000..69f7341d6d --- /dev/null +++ b/DasharoPayloadPkg/CapsuleRootKey.inc @@ -0,0 +1 @@ + gFmpDevicePkgTokenSpaceGuid.PcdFmpDevicePkcs7CertBufferXdr|{0x00, 0x00, 0x03, 0xF0, 0x30, 0x82, 0x03, 0xEC, 0x30, 0x82, 0x02, 0xD4, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xC0, 0x91, 0xC5, 0xE2, 0xB7, 0x66, 0xC0, 0xF8, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x02, 0x53, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x02, 0x53, 0x48, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x09, 0x54, 0x69, 0x61, 0x6E, 0x6F, 0x43, 0x6F, 0x72, 0x65, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x05, 0x45, 0x44, 0x4B, 0x49, 0x49, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x08, 0x54, 0x65, 0x73, 0x74, 0x52, 0x6F, 0x6F, 0x74, 0x31, 0x22, 0x30, 0x20, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x13, 0x65, 0x64, 0x6B, 0x69, 0x69, 0x40, 0x74, 0x69, 0x61, 0x6E, 0x6F, 0x63, 0x6F, 0x72, 0x65, 0x2E, 0x6F, 0x72, 0x67, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x37, 0x30, 0x34, 0x31, 0x30, 0x30, 0x38, 0x32, 0x37, 0x34, 0x30, 0x5A, 0x17, 0x0D, 0x31, 0x37, 0x30, 0x35, 0x31, 0x30, 0x30, 0x38, 0x32, 0x37, 0x34, 0x30, 0x5A, 0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x02, 0x53, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x02, 0x53, 0x48, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x09, 0x54, 0x69, 0x61, 0x6E, 0x6F, 0x43, 0x6F, 0x72, 0x65, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x05, 0x45, 0x44, 0x4B, 0x49, 0x49, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x08, 0x54, 0x65, 0x73, 0x74, 0x52, 0x6F, 0x6F, 0x74, 0x31, 0x22, 0x30, 0x20, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x13, 0x65, 0x64, 0x6B, 0x69, 0x69, 0x40, 0x74, 0x69, 0x61, 0x6E, 0x6F, 0x63, 0x6F, 0x72, 0x65, 0x2E, 0x6F, 0x72, 0x67, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xB9, 0x29, 0x29, 0x6C, 0x60, 0x0C, 0xD7, 0x23, 0xF6, 0x7D, 0xEE, 0xF0, 0x62, 0xFF, 0xD9, 0xC9, 0xAA, 0x55, 0x8C, 0x81, 0x95, 0x56, 0x3F, 0xB7, 0x56, 0x53, 0xB0, 0xC2, 0x82, 0x12, 0xC5, 0x3B, 0x75, 0x23, 0xB9, 0x4D, 0xD6, 0xC4, 0x55, 0x73, 0xF3, 0xAA, 0x95, 0xA8, 0x1B, 0xF3, 0x93, 0x7E, 0x9E, 0x40, 0xE4, 0x1D, 0x22, 0x9C, 0x93, 0x07, 0x0B, 0xD7, 0xAA, 0x5B, 0xD7, 0xE4, 0x1A, 0x21, 0x84, 0xD7, 0x63, 0x59, 0x03, 0x50, 0x1F, 0xF5, 0x14, 0x55, 0x93, 0x91, 0x9B, 0xF5, 0x52, 0xB0, 0xBF, 0x0E, 0x5C, 0x68, 0x3B, 0x59, 0x52, 0x98, 0x96, 0x56, 0xE1, 0xAB, 0xC4, 0x43, 0xBB, 0x05, 0x57, 0x78, 0x45, 0x01, 0x9F, 0x58, 0x15, 0x53, 0x0E, 0x11, 0x94, 0x2F, 0x0E, 0xF1, 0xA6, 0x19, 0xA2, 0x6E, 0x86, 0x39, 0x2B, 0x33, 0x8D, 0xC7, 0xC5, 0xEB, 0xEE, 0x1E, 0x33, 0xD3, 0x32, 0x94, 0xC1, 0x59, 0xC4, 0x0C, 0x97, 0x0B, 0x12, 0x48, 0x5F, 0x33, 0xF6, 0x60, 0x74, 0x7D, 0x57, 0xC2, 0x13, 0x2D, 0x7D, 0xA9, 0x87, 0xA3, 0x35, 0xEA, 0x91, 0x83, 0x3F, 0x67, 0x7A, 0x92, 0x1F, 0x01, 0x53, 0x9F, 0x62, 0x5F, 0x99, 0x12, 0xFD, 0x73, 0x1B, 0x2D, 0x9E, 0x2B, 0x6C, 0x34, 0x49, 0xAF, 0x4F, 0x07, 0x8F, 0xC0, 0xE9, 0x6B, 0x9E, 0x5F, 0x79, 0x35, 0xDA, 0x2A, 0x5C, 0x88, 0xEE, 0xF6, 0x48, 0x61, 0xDA, 0x96, 0xE3, 0x48, 0x46, 0xA0, 0x94, 0x1C, 0x9D, 0xF6, 0x5C, 0x87, 0x0E, 0xEF, 0x74, 0x09, 0x91, 0x0D, 0x3D, 0x5A, 0xE7, 0xC5, 0x4C, 0x8A, 0x7A, 0xAC, 0xA1, 0x85, 0xB6, 0x67, 0x44, 0x17, 0x55, 0x52, 0x3A, 0xE8, 0x11, 0x4D, 0x58, 0xA2, 0x93, 0x00, 0x62, 0xEA, 0x7B, 0x80, 0xED, 0xCF, 0xBD, 0xDF, 0x75, 0x80, 0x4B, 0xB9, 0x65, 0x63, 0xAD, 0x0B, 0x4D, 0x74, 0xFA, 0x59, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x63, 0x30, 0x61, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x16, 0xAA, 0xD6, 0x8E, 0x1B, 0x2D, 0x43, 0xF3, 0x2D, 0xB0, 0x24, 0xAD, 0x36, 0x65, 0x3F, 0xB2, 0xFA, 0xB1, 0x2C, 0xED, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x16, 0xAA, 0xD6, 0x8E, 0x1B, 0x2D, 0x43, 0xF3, 0x2D, 0xB0, 0x24, 0xAD, 0x36, 0x65, 0x3F, 0xB2, 0xFA, 0xB1, 0x2C, 0xED, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x95, 0xDE, 0xDF, 0xA4, 0x14, 0xDB, 0x92, 0x22, 0x78, 0x1A, 0xBD, 0x31, 0x9D, 0x1E, 0xD7, 0x2F, 0x0A, 0x10, 0x11, 0x5D, 0x74, 0x61, 0xE8, 0x30, 0xC4, 0xF3, 0x15, 0xE9, 0x30, 0x54, 0xF4, 0xBB, 0x0C, 0x04, 0x78, 0x13, 0x5D, 0x2C, 0xDD, 0x8C, 0x92, 0x90, 0xD1, 0x9C, 0xD0, 0xD0, 0x18, 0xA3, 0xA3, 0xFC, 0x8C, 0x28, 0x5A, 0xD4, 0x91, 0x4D, 0x08, 0xC3, 0xF6, 0x1A, 0xC8, 0xDD, 0xA6, 0x08, 0x58, 0xE2, 0x15, 0x95, 0xFB, 0x2D, 0x2D, 0x8A, 0xB1, 0x30, 0x80, 0xBD, 0x9A, 0xB6, 0xE1, 0x2C, 0x20, 0x3E, 0xDD, 0xC4, 0xC7, 0x55, 0x65, 0xCF, 0x28, 0x17, 0xF4, 0xEE, 0xDA, 0xBE, 0x77, 0x70, 0xD5, 0x52, 0xD6, 0x15, 0x7A, 0xFB, 0xAD, 0xAF, 0xFD, 0xD5, 0x45, 0x90, 0x5A, 0xE6, 0x31, 0x42, 0xD7, 0x84, 0xB3, 0x49, 0x56, 0x6A, 0xD3, 0x47, 0xF3, 0xBF, 0x68, 0x60, 0x8B, 0x0F, 0xE2, 0xAF, 0xF4, 0xE3, 0xEC, 0x12, 0xB9, 0xE2, 0x3A, 0x16, 0x11, 0x4E, 0x4D, 0x73, 0x79, 0xAF, 0x47, 0x85, 0x4C, 0x76, 0x26, 0x9E, 0x8B, 0x32, 0xC0, 0x8E, 0xC2, 0xDC, 0x27, 0xA6, 0xEF, 0xAC, 0x93, 0x9E, 0xA1, 0x5E, 0xCF, 0x34, 0x45, 0xE0, 0x2A, 0xC7, 0x9D, 0x4D, 0xD7, 0xD7, 0x37, 0x72, 0x97, 0xF8, 0x58, 0xF9, 0xB6, 0x35, 0x48, 0xF1, 0xD1, 0x0A, 0x72, 0x7F, 0xFD, 0x4D, 0x7C, 0xE9, 0xCC, 0xD8, 0x48, 0x1B, 0x49, 0x52, 0x53, 0xDE, 0x51, 0x01, 0x53, 0x35, 0xBC, 0x90, 0xCD, 0x8C, 0x8A, 0xCC, 0x43, 0x20, 0xA7, 0x45, 0xFF, 0x2B, 0x55, 0xB0, 0x8B, 0x2D, 0xFF, 0x55, 0x15, 0x4B, 0x84, 0xD0, 0xC3, 0xD3, 0x90, 0x9C, 0x94, 0x4B, 0x55, 0xD5, 0x62, 0xEA, 0x22, 0xAB, 0x62, 0x68, 0xDD, 0x53, 0xC6, 0xDC, 0xA5, 0xDD, 0x9A, 0x2D, 0x8E, 0x79, 0x7C, 0x2E, 0x9C, 0xE4, 0x66, 0x80, 0x8C, 0x1D} \ No newline at end of file diff --git a/DasharoPayloadPkg/CapsuleSplashDxe/CapsuleSplashDxe.c b/DasharoPayloadPkg/CapsuleSplashDxe/CapsuleSplashDxe.c new file mode 100644 index 0000000000..fb7d1a6fd8 --- /dev/null +++ b/DasharoPayloadPkg/CapsuleSplashDxe/CapsuleSplashDxe.c @@ -0,0 +1,343 @@ +/** @file + Driver for displaying capsule update progress consistently. + + Position and size of progress bar produced by DisplayUpdateProgressLibGraphics + depends on the size of boot logo. As the logo can be customized by users, a + dummy logo with determinable dimensions, depending on the size of current GOP + mode, is created to make progress bar appear always in the same place. + +Copyright (c) 2024, 3mdeb Sp. z o.o. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + + +**/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +/** + scalable-font2 memory management assumes existence of realloc() as defined by + C standard. The closest edk2 has to offer seems to be ReallocatePool(), but + it requires the caller to pass the old size as an argument. Instead of adding + bookkeeping code, just turn off dynamic memory allocation completely by + defining SSFN_MAXLINES. This has some serious limitations, but should be + enough to print few simple lines. It also makes context size significantly + bigger, so move it to .bss to reduce stack usage. + + https://gitlab.com/bztsrc/scalable-font2/blob/master/docs/API.md#configuring-memory-management +**/ + +#define SSFN_MAXLINES 4096 +#define SSFN_IMPLEMENTATION +#include "SSFN/ssfn.h" +#include "SSFN/VeraB.h" + +ssfn_t mCtx; +ssfn_buf_t mFBuf; + +/** + Dimensions used by DisplayUpdateProgressLibGraphics: + + +-----------------------------------------------------------------+ + | | + | | + | +-------------------------------------+ | + | | | | + | | | | + | | | | + | | LOGO | | + | | | | + | | | | + | | | | + | | | | + | +-------------------------------------+ | + | ^ | + | | padding - 20% * logo height | + | v | + | +-------------------------------------+ | + | | Progress bar - 10% * logo height | | + | +-------------------------------------+ | + | | + | | + +-----------------------------------------------------------------+ + + Progress bar has the same width as logo, rounded up to represent 100 equally + wide ticks. Note that all progress bar dimensions are relative to the logo, + and not screen dimensions. In addition, DisplayUpdateProgressLibGraphics + ignores all black and red (and everything in between) pixels of the logo when + doing the calculations. + + This driver creates all-white logo with width equal to 75% of screen width, + and height - 60% of screen height. The logo is aligned to top of screen and + centered horizontally. + + This results in progress bar that: + - has width of 75% of screen width (potentially rounded up by up to 99px) + - has height of 6% (10% of 60% logo) of screen height + - is centered horizontally + - is located 22% (100% - 60% - (20% + 10%) * 60%) of screen height from the + bottom. + +**/ + +#define WIDTH_PERCENT 75 +#define HEIGHT_PERCENT 60 + +EFI_STATUS +SetDummyLogo ( + IN EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *ModeInfo +) +{ + EFI_STATUS Status; + EDKII_BOOT_LOGO2_PROTOCOL *BootLogo2; + UINTN Height, Width, OffsetX; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer; + UINTN BufferSize; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL White = {0xFF, 0xFF, 0xFF, 0}; + + // + // Try to open BootLogo2 protocol. DisplayUpdateProgressLibGraphics doesn't + // use the original BootLogo. + // + Status = gBS->LocateProtocol (&gEdkiiBootLogo2ProtocolGuid, NULL, (VOID **)&BootLogo2); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + // + // Calculate dummy logo dimensions from GOP mode size. + // + Height = ModeInfo->VerticalResolution * HEIGHT_PERCENT / 100; + Width = ModeInfo->HorizontalResolution * WIDTH_PERCENT / 100; + OffsetX = ((ModeInfo->HorizontalResolution * (100 - WIDTH_PERCENT)) / 2) / 100; + + // + // Ensure the Height * Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) does + // not overflow UINTN + // + Status = SafeUintnMult ( + Width, + Height, + &BufferSize + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Status = SafeUintnMult ( + BufferSize, + sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), + &BufferSize + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + // + // Allocate buffer for dummy logo and make it white. + // + BltBuffer = AllocatePool (BufferSize); + if (BltBuffer == NULL) { + return EFI_UNSUPPORTED; + } + + for (UINTN i = 0; i < BufferSize / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL); i++) { + BltBuffer[i] = White; + } + + // + // Set the new logo in BootLogo2 protocol. Note that this doesn't display it. + // + Status = BootLogo2->SetBootLogo (BootLogo2, BltBuffer, OffsetX, 0, Width, Height); + + FreePool (BltBuffer); + + return Status; +} + +// Note: this is horizontal baseline (aka ascender), not line height. +#define FONT_SIZE_PERCENT 5 +#define FONT_SIZE(Mode) ( \ + (Mode->VerticalResolution * FONT_SIZE_PERCENT / 100) < SSFN_SIZE_MAX ? \ + (Mode->VerticalResolution * FONT_SIZE_PERCENT / 100) : SSFN_SIZE_MAX \ + ) + +EFI_STATUS +InitSsfn ( + EFI_PHYSICAL_ADDRESS FrameBufferBase, + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info +) +{ + int Status; + + // + // Context must be zeroed, done by having it in .bss. + // + + // + // Load the font. + // + Status = ssfn_load(&mCtx, VeraB); + if (Status != SSFN_OK) { + DEBUG ((DEBUG_ERROR, "ssfn_load failed with %a!\n", ssfn_error(Status))); + return EFI_UNSUPPORTED; + } + + // + // Select the face. + // + Status = ssfn_select(&mCtx, SSFN_FAMILY_ANY, NULL, SSFN_STYLE_BOLD, FONT_SIZE(Info)); + if (Status != SSFN_OK) { + DEBUG ((DEBUG_ERROR, "ssfn_select failed with %a!\n", ssfn_error(Status))); + return EFI_UNSUPPORTED; + } + + // + // Initialize fields of frame buffer context that won't change. + // + mFBuf.ptr = (uint8_t *)FrameBufferBase; + mFBuf.w = Info->HorizontalResolution; + mFBuf.h = Info->VerticalResolution; + mFBuf.p = Info->PixelsPerScanLine * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL); + mFBuf.fg = 0xFFFFFFFF; // This uses alpha channel for anti-aliasing + mFBuf.bg = 0; + + return EFI_SUCCESS; +} + +EFI_STATUS +RenderTextCenteredAt ( + const char *str, + UINTN x, + UINTN y +) +{ + int w, h, left, top; + int Status; + + // + // Get the size of rendered text. + // + Status = ssfn_bbox(&mCtx, str, &w, &h, &left, &top); + if (Status != SSFN_OK) { + DEBUG ((DEBUG_ERROR, "ssfn_bbox failed with %a!\n", ssfn_error(Status))); + return EFI_UNSUPPORTED; + } + + // + // Calculate and bound leftmost baseline coordinates of text. + // + w /= 2; + h /= 2; + mFBuf.x = x > w ? x - w : 0; + mFBuf.y = y > h ? y - h : 0; + + // + // Add baseline to get the final coordinates. + // + mFBuf.x += left; + mFBuf.y += top; + + // + // Render the text. The function takes care to not write outside of buffer. + // It returns number of bytes consumed to render one glyph (UTF-8). Special + // characters like \n are not handled. + // + while((Status = ssfn_render(&mCtx, &mFBuf, str)) > 0) + str += Status; + + if (Status < 0) { + DEBUG ((DEBUG_ERROR, "ssfn_render failed with %a!\n", ssfn_error(Status))); + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +/** + The Entry Point for CapsuleSplash driver. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS This is the only returned value, even in case of + errors. Reasoning is that this driver gives only + informational output, and failure to do so shouldn't + abort the update process. +**/ +EFI_STATUS +EFIAPI +CapsuleSplashEntry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *ModeInfo; + + // + // Find GOP and ensure that pixel size is 32b. + // + Status = gBS->HandleProtocol (gST->ConsoleOutHandle, + &gEfiGraphicsOutputProtocolGuid, + (VOID **)&GraphicsOutput); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Couldn't find GOP\n")); + return EFI_SUCCESS; + } + + ModeInfo = GraphicsOutput->Mode->Info; + if (ModeInfo->PixelFormat != PixelRedGreenBlueReserved8BitPerColor && + ModeInfo->PixelFormat != PixelBlueGreenRedReserved8BitPerColor) { + DEBUG ((DEBUG_ERROR, "Wrong pixel format\n")); + return EFI_SUCCESS; + } + + // + // Set dummy logo for consistent progress bar + // + Status = SetDummyLogo (ModeInfo); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Couldn't set dummy logo\n")); + return EFI_SUCCESS; + } + + // + // Initialize font renderer. + // + Status = InitSsfn (GraphicsOutput->Mode->FrameBufferBase, ModeInfo); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Couldn't init font renderer\n")); + return EFI_SUCCESS; + } + + // + // Clear the background. We don't know what logo was shown there, if any. + // + ZeroMem ((VOID *)GraphicsOutput->Mode->FrameBufferBase, + GraphicsOutput->Mode->FrameBufferSize); + + // + // Print some warnings. Ignore the result, we still want to try printing even + // if one of the earlier lines fails. + // + Status = RenderTextCenteredAt("Firmware update in progress", + ModeInfo->HorizontalResolution / 2, + ModeInfo->VerticalResolution * 37 / 100); + + Status = RenderTextCenteredAt("Don't turn off your platform!", + ModeInfo->HorizontalResolution / 2, + ModeInfo->VerticalResolution * 88 / 100); + + return EFI_SUCCESS; +} diff --git a/DasharoPayloadPkg/CapsuleSplashDxe/CapsuleSplashDxe.inf b/DasharoPayloadPkg/CapsuleSplashDxe/CapsuleSplashDxe.inf new file mode 100644 index 0000000000..c9f5570624 --- /dev/null +++ b/DasharoPayloadPkg/CapsuleSplashDxe/CapsuleSplashDxe.inf @@ -0,0 +1,46 @@ +## @file +# This driver produces GraphicsOutput protocol based on the GraphicsInfo HOB information. +# +# Copyright (c) 2016, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = CapsuleSplashDxe + FILE_GUID = 6E65E801-5425-4E81-930C-40525C3BA3E5 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = CapsuleSplashEntry + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.common] + CapsuleSplashDxe.c + SSFN/ssfn.h + SSFN/VeraB.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + MemoryAllocationLib + SafeIntLib + UefiLib + UefiBootServicesTableLib + UefiDriverEntryPoint + +[Protocols] + gEfiGraphicsOutputProtocolGuid ## CONSUMES + gEdkiiBootLogo2ProtocolGuid ## CONSUMES + +[Depex] + gEfiGraphicsOutputProtocolGuid AND gEdkiiBootLogo2ProtocolGuid diff --git a/DasharoPayloadPkg/CapsuleSplashDxe/SSFN/README b/DasharoPayloadPkg/CapsuleSplashDxe/SSFN/README new file mode 100644 index 0000000000..a5824caf25 --- /dev/null +++ b/DasharoPayloadPkg/CapsuleSplashDxe/SSFN/README @@ -0,0 +1,5 @@ +Files in this directory were obtained from https://gitlab.com/bztsrc/scalable-font2, +revision 26dc7c5c97c4a005ff2bdf76870168d244135e78. Their license is MIT. + +VeraB.h was created by extracting VeraB.sfn and running 'xxd -i', with resulting +array made constant. diff --git a/DasharoPayloadPkg/CapsuleSplashDxe/SSFN/VeraB.h b/DasharoPayloadPkg/CapsuleSplashDxe/SSFN/VeraB.h new file mode 100644 index 0000000000..223b18938c --- /dev/null +++ b/DasharoPayloadPkg/CapsuleSplashDxe/SSFN/VeraB.h @@ -0,0 +1,1458 @@ +const unsigned char VeraB[] = { + 0x53, 0x46, 0x4e, 0x32, 0x33, 0x44, 0x00, 0x00, 0x11, 0x00, 0xff, 0xd7, + 0xab, 0xcb, 0xa9, 0x00, 0x0b, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x8e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x69, 0x74, 0x73, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x20, 0x56, 0x65, 0x72, 0x61, 0x20, 0x53, + 0x61, 0x6e, 0x73, 0x20, 0x42, 0x6f, 0x6c, 0x64, 0x00, 0x42, 0x69, 0x74, + 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x20, 0x56, 0x65, 0x72, 0x61, 0x20, + 0x53, 0x61, 0x6e, 0x73, 0x00, 0x42, 0x6f, 0x6c, 0x64, 0x00, 0x52, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x31, 0x2e, 0x31, 0x30, 0x00, 0x42, + 0x69, 0x74, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x20, 0x49, 0x6e, 0x63, + 0x2e, 0x00, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, + 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x33, 0x20, 0x62, 0x79, 0x20, + 0x42, 0x69, 0x74, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2c, 0x20, 0x49, + 0x6e, 0x63, 0x2e, 0x20, 0x41, 0x6c, 0x6c, 0x20, 0x52, 0x69, 0x67, 0x68, + 0x74, 0x73, 0x20, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x2e, + 0x00, 0x04, 0x54, 0x01, 0x00, 0x00, 0x15, 0x00, 0x15, 0x17, 0x00, 0x17, + 0x00, 0x00, 0x04, 0x54, 0x01, 0x00, 0x00, 0x15, 0x00, 0x15, 0x16, 0x00, + 0x16, 0x00, 0x00, 0x08, 0xa8, 0x6a, 0x01, 0x15, 0x00, 0x05, 0x03, 0x0b, + 0x00, 0x00, 0x0d, 0x00, 0x06, 0x05, 0x17, 0x00, 0x13, 0x10, 0x1a, 0x09, + 0x1a, 0x1f, 0x14, 0x19, 0x1a, 0x25, 0x03, 0x25, 0x0d, 0x25, 0x00, 0x15, + 0x00, 0x03, 0x54, 0x00, 0x36, 0x25, 0x36, 0x12, 0x00, 0x00, 0x36, 0x08, + 0xa8, 0xaa, 0x02, 0x15, 0x00, 0x05, 0x08, 0x0b, 0x00, 0x00, 0x1e, 0x00, + 0x0f, 0x05, 0x34, 0x00, 0x2c, 0x15, 0x3c, 0x0b, 0x3c, 0x26, 0x34, 0x20, + 0x3c, 0x2b, 0x1e, 0x2b, 0x2c, 0x26, 0x08, 0x2b, 0x0f, 0x15, 0x00, 0x20, + 0x00, 0x14, 0x54, 0xaa, 0x5a, 0xaa, 0xa9, 0x02, 0x66, 0x2d, 0x66, 0x67, + 0x45, 0x67, 0x45, 0x58, 0x37, 0x65, 0x3f, 0x61, 0x23, 0x6a, 0x2f, 0x6a, + 0x0a, 0x60, 0x14, 0x6a, 0x00, 0x49, 0x00, 0x57, 0x0c, 0x2f, 0x00, 0x37, + 0x32, 0x26, 0x18, 0x26, 0x45, 0x26, 0x45, 0x24, 0x3f, 0x19, 0x45, 0x1c, + 0x2d, 0x15, 0x39, 0x15, 0x19, 0x17, 0x22, 0x15, 0x09, 0x1d, 0x10, 0x19, + 0x09, 0x05, 0x1e, 0x01, 0x13, 0x02, 0x32, 0x00, 0x28, 0x00, 0x5a, 0x0b, + 0x4e, 0x00, 0x66, 0x2d, 0x66, 0x15, 0xc0, 0x00, 0x5c, 0x00, 0x00, 0xeb, + 0x00, 0x00, 0x87, 0x03, 0x04, 0x54, 0x01, 0x00, 0x00, 0x20, 0x00, 0x20, + 0x23, 0x00, 0x23, 0x00, 0x00, 0x04, 0x54, 0x01, 0x00, 0x00, 0x73, 0x00, + 0x73, 0x15, 0x00, 0x15, 0x00, 0x00, 0x08, 0x54, 0x55, 0x01, 0x61, 0x6d, + 0x2b, 0x6d, 0x23, 0x86, 0x00, 0x86, 0x32, 0x00, 0x5b, 0x00, 0x8d, 0x86, + 0x6a, 0x86, 0x61, 0x6d, 0x08, 0xa8, 0xaa, 0x02, 0x45, 0x00, 0x78, 0x13, + 0x65, 0x00, 0x8a, 0x46, 0x8a, 0x25, 0x78, 0x79, 0x8a, 0x66, 0x45, 0x8c, + 0x65, 0x8c, 0x12, 0x79, 0x25, 0x8c, 0x00, 0x46, 0x00, 0x66, 0x12, 0x13, + 0x00, 0x25, 0x45, 0x00, 0x25, 0x00, 0x08, 0xa8, 0xaa, 0x02, 0x21, 0x00, + 0x09, 0x0c, 0x11, 0x00, 0x00, 0x2d, 0x00, 0x18, 0x09, 0x4e, 0x00, 0x42, + 0x21, 0x59, 0x11, 0x59, 0x3a, 0x4e, 0x31, 0x59, 0x42, 0x2d, 0x42, 0x42, + 0x3a, 0x0c, 0x42, 0x18, 0x21, 0x00, 0x31, 0x00, 0x08, 0xa8, 0xaa, 0x02, + 0x37, 0x00, 0x60, 0x0e, 0x51, 0x00, 0x6f, 0x35, 0x6f, 0x1c, 0x60, 0x5c, + 0x6f, 0x4d, 0x37, 0x6a, 0x51, 0x6a, 0x0f, 0x5c, 0x1d, 0x6a, 0x00, 0x35, + 0x00, 0x4d, 0x0f, 0x0e, 0x00, 0x1c, 0x37, 0x00, 0x1d, 0x00, 0xc0, 0x00, + 0x37, 0x00, 0x00, 0xeb, 0x00, 0x00, 0xf9, 0x01, 0xc0, 0x00, 0x24, 0x00, + 0x00, 0xea, 0x00, 0x00, 0xe6, 0x02, 0x04, 0x54, 0x01, 0x14, 0x8c, 0x00, + 0x8c, 0x54, 0x00, 0x68, 0x00, 0x14, 0x8c, 0x04, 0x54, 0x01, 0x00, 0x00, + 0x23, 0x00, 0x23, 0x86, 0x00, 0x86, 0x00, 0x00, 0x04, 0x54, 0x01, 0x19, + 0x00, 0x33, 0x21, 0x21, 0x21, 0x00, 0x00, 0x19, 0x00, 0x04, 0x54, 0x01, + 0x00, 0x00, 0x20, 0x00, 0x20, 0x65, 0x00, 0x65, 0x00, 0x00, 0x05, 0xa8, + 0x06, 0x2a, 0x15, 0x25, 0x06, 0x2a, 0x0b, 0x17, 0x00, 0x1f, 0x00, 0x07, + 0x06, 0x0d, 0x00, 0x00, 0x15, 0x02, 0x0b, 0x2a, 0x15, 0x07, 0x54, 0x55, + 0x14, 0x00, 0x30, 0x00, 0x44, 0x18, 0x34, 0x18, 0x22, 0x09, 0x10, 0x18, + 0x00, 0x18, 0x14, 0x00, 0x0c, 0x54, 0x55, 0x55, 0x01, 0x00, 0x00, 0x5d, + 0x00, 0x5d, 0x1a, 0x23, 0x1a, 0x23, 0x33, 0x5a, 0x33, 0x5a, 0x4d, 0x23, + 0x4d, 0x23, 0x6c, 0x5f, 0x6c, 0x5f, 0x86, 0x00, 0x86, 0x00, 0x00, 0x0e, + 0x94, 0x6a, 0xa5, 0x1a, 0x00, 0x00, 0x23, 0x00, 0x23, 0x50, 0x28, 0x68, + 0x23, 0x61, 0x3a, 0x6f, 0x2d, 0x6f, 0x4c, 0x68, 0x46, 0x6f, 0x51, 0x50, + 0x51, 0x61, 0x51, 0x00, 0x74, 0x00, 0x74, 0x50, 0x65, 0x7b, 0x74, 0x6d, + 0x3a, 0x89, 0x57, 0x89, 0x0e, 0x7b, 0x1d, 0x89, 0x00, 0x50, 0x00, 0x6d, + 0x00, 0x00, 0x0f, 0x94, 0x6a, 0xaa, 0xaa, 0x6c, 0x34, 0x6c, 0x3d, 0x21, + 0x3d, 0x29, 0x4e, 0x22, 0x49, 0x3d, 0x54, 0x30, 0x54, 0x51, 0x51, 0x47, + 0x54, 0x67, 0x48, 0x5c, 0x4e, 0x67, 0x61, 0x50, 0x67, 0x5c, 0x65, 0x3a, + 0x6a, 0x45, 0x6a, 0x0f, 0x5c, 0x1e, 0x6a, 0x00, 0x35, 0x00, 0x4e, 0x0f, + 0x0e, 0x00, 0x1c, 0x38, 0x00, 0x1e, 0x00, 0x5e, 0x0e, 0x50, 0x00, 0x6c, + 0x34, 0x6c, 0x1c, 0x14, 0x54, 0xaa, 0xaa, 0x55, 0xa9, 0x02, 0x00, 0x3e, + 0x00, 0x00, 0x20, 0x00, 0x20, 0x0a, 0x20, 0x1f, 0x20, 0x12, 0x20, 0x2f, + 0x20, 0x2b, 0x21, 0x41, 0x20, 0x3b, 0x23, 0x49, 0x21, 0x46, 0x28, 0x4d, + 0x25, 0x4c, 0x2f, 0x4f, 0x2b, 0x4f, 0x3f, 0x47, 0x3a, 0x4f, 0x45, 0x32, + 0x45, 0x40, 0x45, 0x00, 0x65, 0x00, 0x65, 0x65, 0x45, 0x65, 0x45, 0x56, + 0x36, 0x63, 0x3e, 0x5f, 0x24, 0x68, 0x2d, 0x68, 0x09, 0x5d, 0x12, 0x68, + 0x00, 0x3e, 0x00, 0x52, 0xc0, 0x00, 0x24, 0x00, 0x00, 0xc9, 0x00, 0x00, + 0x3f, 0x03, 0x04, 0x54, 0x01, 0x12, 0x00, 0x2b, 0x00, 0x12, 0x18, 0x00, + 0x18, 0x12, 0x00, 0x07, 0x54, 0x55, 0x17, 0x00, 0x2d, 0x00, 0x44, 0x21, + 0x34, 0x21, 0x22, 0x0d, 0x10, 0x21, 0x00, 0x21, 0x17, 0x00, 0x07, 0x54, + 0x55, 0x17, 0x21, 0x00, 0x00, 0x10, 0x00, 0x22, 0x14, 0x34, 0x00, 0x44, + 0x00, 0x2d, 0x21, 0x17, 0x21, 0x12, 0xa8, 0xaa, 0xa6, 0xaa, 0x1a, 0x72, + 0x82, 0x5e, 0x89, 0x69, 0x87, 0x49, 0x8c, 0x54, 0x8c, 0x14, 0x79, 0x27, + 0x8c, 0x00, 0x46, 0x00, 0x66, 0x14, 0x13, 0x00, 0x26, 0x49, 0x00, 0x27, + 0x00, 0x5e, 0x03, 0x54, 0x00, 0x72, 0x0a, 0x69, 0x05, 0x72, 0x26, 0x5f, + 0x1c, 0x69, 0x1f, 0x4c, 0x19, 0x56, 0x19, 0x2e, 0x25, 0x39, 0x19, 0x24, + 0x46, 0x24, 0x31, 0x2e, 0x67, 0x24, 0x5b, 0x4c, 0x72, 0x39, 0x72, 0x5f, + 0x6f, 0x56, 0x72, 0x72, 0x66, 0x69, 0x6c, 0x72, 0x82, 0x12, 0xa4, 0xaa, + 0x9a, 0xaa, 0x2a, 0x59, 0x05, 0x59, 0x20, 0x4c, 0x19, 0x52, 0x1b, 0x3e, + 0x17, 0x45, 0x17, 0x29, 0x1f, 0x31, 0x17, 0x22, 0x35, 0x22, 0x27, 0x29, + 0x4b, 0x22, 0x43, 0x3e, 0x53, 0x31, 0x53, 0x4c, 0x50, 0x46, 0x53, 0x59, + 0x4a, 0x53, 0x4e, 0x59, 0x64, 0x4a, 0x68, 0x51, 0x67, 0x3a, 0x6a, 0x42, + 0x6a, 0x0f, 0x5c, 0x1f, 0x6a, 0x00, 0x35, 0x00, 0x4e, 0x0f, 0x0e, 0x00, + 0x1c, 0x3a, 0x00, 0x1f, 0x00, 0x4a, 0x01, 0x42, 0x00, 0x59, 0x05, 0x51, + 0x03, 0xc0, 0x00, 0x36, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x2f, 0x03, 0x04, + 0x54, 0x01, 0x15, 0x00, 0x15, 0x32, 0x00, 0x32, 0x00, 0x00, 0x15, 0x00, + 0x04, 0x54, 0x01, 0x00, 0x00, 0x20, 0x00, 0x20, 0x1a, 0x00, 0x1a, 0x00, + 0x00, 0x04, 0x54, 0x01, 0x19, 0x00, 0x33, 0x00, 0x12, 0x21, 0x00, 0x21, + 0x19, 0x00, 0x04, 0x54, 0x01, 0x1a, 0x00, 0x33, 0x00, 0x12, 0x21, 0x00, + 0x21, 0x1a, 0x00, 0x07, 0x54, 0x55, 0x2c, 0x00, 0x2c, 0x16, 0x12, 0x2a, + 0x2c, 0x3e, 0x2c, 0x54, 0x00, 0x32, 0x00, 0x22, 0x2c, 0x00, 0x07, 0x54, + 0x55, 0x00, 0x00, 0x2c, 0x22, 0x2c, 0x32, 0x00, 0x54, 0x00, 0x3e, 0x1a, + 0x2a, 0x00, 0x16, 0x00, 0x00, 0x09, 0x54, 0x55, 0x05, 0x00, 0x00, 0x26, + 0x00, 0x44, 0x30, 0x63, 0x00, 0x89, 0x00, 0x56, 0x4d, 0x56, 0x86, 0x33, + 0x86, 0x33, 0x4d, 0x00, 0x00, 0x0b, 0x54, 0x55, 0x55, 0x02, 0x3d, 0x14, + 0x3d, 0x14, 0x0e, 0x00, 0x13, 0x00, 0x04, 0x15, 0x00, 0x29, 0x00, 0x29, + 0x3d, 0x3b, 0x3d, 0x3b, 0x4b, 0x02, 0x4b, 0x02, 0x3d, 0x0e, 0x54, 0xa5, + 0x95, 0x16, 0x00, 0x00, 0x20, 0x00, 0x3b, 0x45, 0x52, 0x00, 0x72, 0x00, + 0x48, 0x6e, 0x39, 0x86, 0x42, 0x7f, 0x23, 0x8d, 0x31, 0x8d, 0x10, 0x8d, + 0x10, 0x78, 0x1a, 0x78, 0x26, 0x75, 0x22, 0x78, 0x2c, 0x6c, 0x2a, 0x72, + 0x2d, 0x69, 0x00, 0x00, 0x1c, 0xa4, 0xaa, 0xa9, 0x6a, 0xaa, 0x9a, 0xaa, + 0x02, 0x61, 0x07, 0x61, 0x23, 0x4c, 0x1c, 0x56, 0x1e, 0x38, 0x19, 0x41, + 0x19, 0x25, 0x1d, 0x2b, 0x19, 0x1f, 0x27, 0x1f, 0x20, 0x23, 0x30, 0x1f, + 0x2d, 0x32, 0x35, 0x27, 0x33, 0x41, 0x38, 0x60, 0x46, 0x57, 0x3c, 0x6a, + 0x60, 0x6a, 0x4f, 0x5d, 0x81, 0x6a, 0x76, 0x35, 0x8c, 0x50, 0x8c, 0x1b, + 0x89, 0x28, 0x8c, 0x01, 0x82, 0x0e, 0x87, 0x01, 0x65, 0x1a, 0x6f, 0x0e, + 0x6c, 0x31, 0x72, 0x26, 0x72, 0x43, 0x6f, 0x3d, 0x72, 0x49, 0x64, 0x49, + 0x6b, 0x44, 0x5a, 0x49, 0x5e, 0x34, 0x54, 0x40, 0x57, 0x27, 0x51, 0x09, + 0x43, 0x13, 0x4d, 0x00, 0x2a, 0x00, 0x3a, 0x0d, 0x0b, 0x00, 0x16, 0x32, + 0x00, 0x1a, 0x00, 0x49, 0x02, 0x3d, 0x00, 0x61, 0x07, 0x55, 0x04, 0x1c, + 0xa4, 0xaa, 0xa9, 0x6a, 0xaa, 0x9a, 0xaa, 0x02, 0x55, 0x05, 0x55, 0x1e, + 0x41, 0x17, 0x4a, 0x1a, 0x2e, 0x15, 0x37, 0x15, 0x21, 0x18, 0x25, 0x15, + 0x1c, 0x1f, 0x1c, 0x1a, 0x20, 0x24, 0x1c, 0x22, 0x2c, 0x28, 0x23, 0x27, + 0x32, 0x28, 0x53, 0x33, 0x4a, 0x2b, 0x5b, 0x49, 0x5b, 0x3a, 0x4f, 0x61, + 0x5b, 0x59, 0x2c, 0x6a, 0x44, 0x6a, 0x17, 0x68, 0x22, 0x6a, 0x02, 0x63, + 0x0d, 0x66, 0x02, 0x4b, 0x15, 0x52, 0x0b, 0x4f, 0x2a, 0x54, 0x1f, 0x54, + 0x38, 0x52, 0x33, 0x54, 0x3d, 0x4a, 0x3d, 0x4f, 0x39, 0x43, 0x3d, 0x45, + 0x2c, 0x40, 0x36, 0x41, 0x27, 0x3f, 0x09, 0x35, 0x11, 0x3d, 0x00, 0x1f, + 0x00, 0x2e, 0x0b, 0x08, 0x00, 0x0f, 0x2d, 0x00, 0x16, 0x00, 0x3f, 0x01, + 0x35, 0x00, 0x55, 0x05, 0x49, 0x02, 0xc0, 0x00, 0x24, 0x00, 0x00, 0xfd, + 0x00, 0x00, 0xa5, 0x00, 0xc0, 0x01, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, + 0x9f, 0x03, 0xe3, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x91, 0x03, 0x04, 0x54, + 0x01, 0x00, 0x00, 0x20, 0x00, 0x20, 0x20, 0x00, 0x20, 0x00, 0x00, 0x04, + 0x54, 0x01, 0x00, 0x00, 0x38, 0x00, 0x38, 0x1a, 0x00, 0x1a, 0x00, 0x00, + 0x04, 0x54, 0x01, 0x14, 0x00, 0x14, 0x44, 0x00, 0x44, 0x00, 0x00, 0x14, + 0x00, 0x04, 0x54, 0x01, 0x00, 0x00, 0x20, 0x00, 0x20, 0x22, 0x00, 0x22, + 0x00, 0x00, 0x04, 0x54, 0x01, 0x19, 0x00, 0x2b, 0x18, 0x19, 0x18, 0x00, + 0x00, 0x19, 0x00, 0x04, 0x54, 0x01, 0x19, 0x00, 0x32, 0x00, 0x11, 0x21, + 0x00, 0x21, 0x19, 0x00, 0x04, 0x54, 0x01, 0x00, 0x00, 0x1b, 0x00, 0x1b, + 0x1c, 0x00, 0x1c, 0x00, 0x00, 0x06, 0x54, 0x15, 0x09, 0x00, 0x29, 0x00, + 0x29, 0x1c, 0x13, 0x3d, 0x00, 0x3d, 0x09, 0x1c, 0x09, 0x00, 0x06, 0x54, + 0x15, 0x1f, 0x39, 0x00, 0x39, 0x00, 0x1f, 0x14, 0x00, 0x28, 0x00, 0x1f, + 0x1f, 0x1f, 0x39, 0x06, 0x54, 0x15, 0x09, 0x00, 0x28, 0x00, 0x28, 0x19, + 0x13, 0x39, 0x00, 0x39, 0x09, 0x19, 0x09, 0x00, 0x06, 0x54, 0x15, 0x09, + 0x00, 0x28, 0x00, 0x28, 0x1a, 0x13, 0x39, 0x00, 0x39, 0x09, 0x1a, 0x09, + 0x00, 0x07, 0x54, 0x55, 0x17, 0x00, 0x2c, 0x00, 0x43, 0x21, 0x33, 0x21, + 0x21, 0x0d, 0x10, 0x21, 0x00, 0x21, 0x17, 0x00, 0x07, 0x54, 0x55, 0x14, + 0x18, 0x00, 0x00, 0x10, 0x00, 0x22, 0x0f, 0x34, 0x00, 0x44, 0x00, 0x30, + 0x18, 0x14, 0x18, 0x08, 0xa8, 0xaa, 0x02, 0x24, 0x00, 0x3e, 0x0a, 0x35, + 0x00, 0x48, 0x25, 0x48, 0x14, 0x3e, 0x40, 0x48, 0x36, 0x24, 0x49, 0x35, + 0x49, 0x0a, 0x40, 0x13, 0x49, 0x00, 0x25, 0x00, 0x36, 0x0a, 0x0a, 0x00, + 0x14, 0x24, 0x00, 0x13, 0x00, 0x08, 0xa8, 0xaa, 0x02, 0x0e, 0x00, 0x04, + 0x06, 0x07, 0x00, 0x00, 0x16, 0x00, 0x0c, 0x04, 0x26, 0x00, 0x20, 0x0e, + 0x2b, 0x07, 0x2b, 0x18, 0x26, 0x14, 0x2b, 0x1b, 0x16, 0x1b, 0x20, 0x18, + 0x06, 0x1b, 0x0c, 0x0e, 0x00, 0x14, 0x00, 0x08, 0xa8, 0xaa, 0x02, 0x24, + 0x00, 0x3e, 0x0a, 0x34, 0x00, 0x48, 0x25, 0x48, 0x14, 0x3e, 0x40, 0x48, + 0x36, 0x24, 0x4a, 0x34, 0x4a, 0x09, 0x40, 0x13, 0x4a, 0x00, 0x25, 0x00, + 0x36, 0x09, 0x0a, 0x00, 0x14, 0x24, 0x00, 0x13, 0x00, 0x08, 0xa8, 0xaa, + 0x02, 0x0e, 0x00, 0x04, 0x05, 0x07, 0x00, 0x00, 0x15, 0x00, 0x0b, 0x04, + 0x25, 0x00, 0x1f, 0x0e, 0x2a, 0x07, 0x2a, 0x18, 0x25, 0x14, 0x2a, 0x1b, + 0x15, 0x1b, 0x1f, 0x18, 0x05, 0x1b, 0x0b, 0x0e, 0x00, 0x14, 0x00, 0x08, + 0xa8, 0xaa, 0x02, 0x15, 0x3b, 0x25, 0x34, 0x20, 0x3b, 0x2b, 0x1e, 0x2b, + 0x2c, 0x25, 0x08, 0x2b, 0x0f, 0x15, 0x00, 0x20, 0x00, 0x06, 0x08, 0x0b, + 0x00, 0x00, 0x1e, 0x00, 0x0f, 0x06, 0x34, 0x00, 0x2c, 0x15, 0x3b, 0x0b, + 0x3b, 0x08, 0xa8, 0xaa, 0x02, 0x15, 0x00, 0x06, 0x08, 0x0c, 0x00, 0x00, + 0x1c, 0x00, 0x0f, 0x06, 0x31, 0x00, 0x2a, 0x15, 0x39, 0x0b, 0x39, 0x25, + 0x31, 0x20, 0x39, 0x2b, 0x1c, 0x2b, 0x2a, 0x25, 0x08, 0x2b, 0x0f, 0x15, + 0x00, 0x20, 0x00, 0x08, 0xa8, 0xaa, 0x02, 0x16, 0x00, 0x06, 0x08, 0x0b, + 0x00, 0x00, 0x1e, 0x00, 0x0f, 0x06, 0x34, 0x00, 0x2c, 0x16, 0x3b, 0x0b, + 0x3b, 0x25, 0x34, 0x20, 0x3b, 0x2b, 0x1e, 0x2b, 0x2c, 0x25, 0x08, 0x2b, + 0x0f, 0x16, 0x00, 0x20, 0x00, 0x0a, 0x54, 0x55, 0x15, 0x00, 0x00, 0x27, + 0x00, 0x57, 0x5c, 0x57, 0x00, 0x78, 0x00, 0x78, 0x86, 0x52, 0x86, 0x21, + 0x2a, 0x21, 0x86, 0x00, 0x86, 0x00, 0x00, 0x0a, 0x54, 0x55, 0x15, 0x02, + 0x00, 0x73, 0x00, 0x73, 0x15, 0x2b, 0x6c, 0x75, 0x6c, 0x75, 0x86, 0x00, + 0x86, 0x00, 0x71, 0x48, 0x1a, 0x02, 0x1a, 0x02, 0x00, 0x0a, 0x54, 0x55, + 0x15, 0x02, 0x00, 0x5a, 0x00, 0x5a, 0x17, 0x25, 0x4e, 0x5a, 0x4e, 0x5a, + 0x65, 0x00, 0x65, 0x00, 0x4e, 0x35, 0x17, 0x02, 0x17, 0x02, 0x00, 0x0e, + 0xa8, 0x6a, 0xaa, 0x1a, 0x1f, 0x00, 0x26, 0x0a, 0x24, 0x06, 0x29, 0x13, + 0x29, 0x0f, 0x23, 0x20, 0x29, 0x1c, 0x12, 0x24, 0x1e, 0x24, 0x0a, 0x23, + 0x0e, 0x24, 0x00, 0x22, 0x05, 0x23, 0x00, 0x14, 0x08, 0x16, 0x05, 0x15, + 0x0f, 0x17, 0x0c, 0x17, 0x17, 0x15, 0x14, 0x17, 0x1a, 0x0f, 0x1a, 0x13, + 0x18, 0x09, 0x1a, 0x0d, 0x12, 0x00, 0x16, 0x05, 0x1f, 0x00, 0x10, 0xa8, + 0xaa, 0xaa, 0xaa, 0x02, 0x43, 0x00, 0x5c, 0x05, 0x50, 0x00, 0x72, 0x14, + 0x68, 0x0a, 0x80, 0x2a, 0x7c, 0x1e, 0x85, 0x43, 0x85, 0x35, 0x80, 0x5d, + 0x85, 0x51, 0x72, 0x72, 0x7c, 0x68, 0x5c, 0x81, 0x68, 0x7c, 0x43, 0x86, + 0x50, 0x86, 0x29, 0x81, 0x35, 0x86, 0x14, 0x72, 0x1d, 0x7c, 0x05, 0x5d, + 0x0a, 0x68, 0x00, 0x43, 0x00, 0x51, 0x05, 0x2a, 0x00, 0x35, 0x14, 0x14, + 0x0a, 0x1e, 0x29, 0x05, 0x1d, 0x0a, 0x43, 0x00, 0x35, 0x00, 0x10, 0xa8, + 0xaa, 0xaa, 0xaa, 0x02, 0x35, 0x00, 0x20, 0x04, 0x2a, 0x00, 0x0f, 0x10, + 0x17, 0x08, 0x03, 0x21, 0x07, 0x18, 0x00, 0x35, 0x00, 0x2a, 0x03, 0x4a, + 0x00, 0x40, 0x0f, 0x5b, 0x07, 0x53, 0x20, 0x66, 0x17, 0x62, 0x35, 0x6a, + 0x2a, 0x6a, 0x49, 0x66, 0x40, 0x6a, 0x5a, 0x5b, 0x52, 0x62, 0x66, 0x4a, + 0x62, 0x53, 0x6a, 0x35, 0x6a, 0x40, 0x66, 0x21, 0x6a, 0x2a, 0x5a, 0x10, + 0x62, 0x18, 0x49, 0x04, 0x52, 0x08, 0x35, 0x00, 0x40, 0x00, 0x13, 0x54, + 0xa9, 0x6a, 0x55, 0xaa, 0x65, 0x2a, 0x65, 0x67, 0x45, 0x67, 0x45, 0x5d, + 0x45, 0x38, 0x44, 0x26, 0x45, 0x2b, 0x42, 0x1f, 0x44, 0x21, 0x3d, 0x1a, + 0x40, 0x1c, 0x36, 0x18, 0x3a, 0x18, 0x26, 0x20, 0x2c, 0x18, 0x20, 0x35, + 0x20, 0x28, 0x20, 0x67, 0x00, 0x67, 0x00, 0x02, 0x20, 0x02, 0x20, 0x11, + 0x30, 0x04, 0x27, 0x08, 0x42, 0x00, 0x38, 0x00, 0x5c, 0x0a, 0x53, 0x00, + 0x65, 0x2a, 0x65, 0x15, 0x15, 0xa8, 0xaa, 0x56, 0xaa, 0xa9, 0x06, 0x4c, + 0x56, 0x3d, 0x63, 0x45, 0x5f, 0x2b, 0x67, 0x35, 0x67, 0x0c, 0x58, 0x18, + 0x67, 0x00, 0x33, 0x00, 0x4a, 0x0c, 0x0e, 0x00, 0x1d, 0x2b, 0x00, 0x18, + 0x00, 0x3d, 0x04, 0x35, 0x00, 0x4c, 0x11, 0x45, 0x08, 0x4c, 0x02, 0x6c, + 0x02, 0x6c, 0x5d, 0x5d, 0x82, 0x6c, 0x75, 0x30, 0x8f, 0x4d, 0x8f, 0x1e, + 0x8d, 0x27, 0x8f, 0x0c, 0x89, 0x15, 0x8c, 0x0c, 0x70, 0x1d, 0x77, 0x15, + 0x75, 0x2d, 0x79, 0x25, 0x79, 0x44, 0x72, 0x3d, 0x79, 0x4c, 0x5d, 0x4c, + 0x6c, 0x4c, 0x56, 0x16, 0xa8, 0xaa, 0xa6, 0xaa, 0x5a, 0x15, 0x80, 0x7f, + 0x66, 0x88, 0x73, 0x85, 0x49, 0x8c, 0x58, 0x8c, 0x14, 0x79, 0x27, 0x8c, + 0x00, 0x46, 0x00, 0x66, 0x14, 0x13, 0x00, 0x25, 0x4b, 0x00, 0x28, 0x00, + 0x64, 0x03, 0x58, 0x00, 0x7b, 0x0a, 0x71, 0x05, 0x7b, 0x26, 0x65, 0x1c, + 0x70, 0x20, 0x4f, 0x19, 0x5a, 0x19, 0x2f, 0x25, 0x3a, 0x19, 0x24, 0x46, + 0x24, 0x30, 0x2f, 0x67, 0x24, 0x5b, 0x4d, 0x72, 0x39, 0x72, 0x57, 0x72, + 0x53, 0x72, 0x60, 0x70, 0x5c, 0x71, 0x60, 0x56, 0x4a, 0x56, 0x4a, 0x3e, + 0x80, 0x3e, 0x80, 0x7f, 0x19, 0xa4, 0x5a, 0xaa, 0x9a, 0x6a, 0xaa, 0x0a, + 0x1f, 0x14, 0x1a, 0x10, 0x19, 0x10, 0x1a, 0x10, 0x13, 0x0d, 0x15, 0x0d, + 0x0e, 0x10, 0x10, 0x0d, 0x0c, 0x17, 0x0c, 0x13, 0x0c, 0x18, 0x00, 0x18, + 0x00, 0x17, 0x00, 0x17, 0x00, 0x15, 0x00, 0x16, 0x05, 0x06, 0x00, 0x0c, + 0x11, 0x00, 0x09, 0x00, 0x18, 0x01, 0x15, 0x00, 0x1f, 0x04, 0x1b, 0x02, + 0x24, 0x08, 0x28, 0x0a, 0x26, 0x09, 0x2b, 0x0b, 0x29, 0x0b, 0x30, 0x08, + 0x2e, 0x0b, 0x32, 0x00, 0x32, 0x05, 0x3e, 0x00, 0x3e, 0x01, 0x3e, 0x01, + 0x3e, 0x03, 0x3e, 0x02, 0x39, 0x12, 0x3e, 0x0c, 0x2d, 0x18, 0x34, 0x18, + 0x26, 0x17, 0x29, 0x18, 0x1f, 0x14, 0x23, 0x16, 0xc0, 0x00, 0x3c, 0x00, + 0x00, 0xea, 0x00, 0x00, 0x5e, 0x03, 0xc0, 0x00, 0x37, 0x00, 0x00, 0xea, + 0x00, 0x00, 0x6c, 0x03, 0xc0, 0x00, 0x37, 0x00, 0x00, 0xea, 0x00, 0x00, + 0x4f, 0x03, 0x03, 0x54, 0x26, 0x00, 0x00, 0x38, 0x26, 0x38, 0x26, 0x00, + 0x03, 0x54, 0x15, 0x00, 0x00, 0x1d, 0x15, 0x1d, 0x15, 0x00, 0x03, 0x54, + 0x16, 0x00, 0x00, 0x1d, 0x16, 0x1d, 0x16, 0x00, 0x03, 0x54, 0x1d, 0x00, + 0x00, 0x4d, 0x3b, 0x4d, 0x1d, 0x00, 0x04, 0x54, 0x01, 0x1e, 0x00, 0x06, + 0x00, 0x00, 0x18, 0x17, 0x18, 0x1e, 0x00, 0x04, 0x54, 0x01, 0x2f, 0x00, + 0x43, 0x00, 0x14, 0x97, 0x00, 0x97, 0x2f, 0x00, 0x04, 0x54, 0x01, 0x2f, + 0x97, 0x00, 0x00, 0x14, 0x00, 0x43, 0x97, 0x2f, 0x97, 0x04, 0x54, 0x01, + 0x5c, 0x00, 0x5c, 0x11, 0x00, 0x11, 0x00, 0x00, 0x5c, 0x00, 0x04, 0x54, + 0x01, 0x00, 0x00, 0x20, 0x00, 0x20, 0x8c, 0x00, 0x8c, 0x00, 0x00, 0x04, + 0x54, 0x01, 0x14, 0x00, 0x14, 0xb8, 0x00, 0xb8, 0x00, 0x00, 0x14, 0x00, + 0x04, 0x54, 0x01, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x20, 0x20, 0x00, + 0x20, 0x04, 0x54, 0x01, 0x00, 0x00, 0x49, 0x00, 0x49, 0x12, 0x00, 0x12, + 0x00, 0x00, 0x04, 0x54, 0x01, 0x00, 0x00, 0x39, 0x00, 0x39, 0x11, 0x00, + 0x11, 0x00, 0x00, 0x04, 0x54, 0x01, 0x00, 0x00, 0x4a, 0x00, 0x4a, 0x12, + 0x00, 0x12, 0x00, 0x00, 0x04, 0x54, 0x01, 0x14, 0x8c, 0x00, 0x8c, 0x53, + 0x00, 0x68, 0x00, 0x14, 0x8c, 0x04, 0x54, 0x01, 0x21, 0x20, 0x00, 0x20, + 0x00, 0x00, 0x21, 0x00, 0x21, 0x20, 0x04, 0x54, 0x01, 0x1a, 0x00, 0x2b, + 0x18, 0x1a, 0x18, 0x00, 0x00, 0x1a, 0x00, 0x04, 0x54, 0x01, 0x17, 0x00, + 0x00, 0x37, 0x22, 0x37, 0x22, 0x00, 0x17, 0x00, 0x04, 0x54, 0x01, 0x1a, + 0x00, 0x2c, 0x18, 0x1a, 0x18, 0x00, 0x00, 0x1a, 0x00, 0x04, 0x54, 0x01, + 0x19, 0x00, 0x2b, 0x18, 0x1a, 0x18, 0x00, 0x00, 0x19, 0x00, 0x04, 0x54, + 0x01, 0x00, 0x00, 0x22, 0x00, 0x22, 0x86, 0x00, 0x86, 0x00, 0x00, 0x04, + 0x54, 0x01, 0x11, 0x00, 0x2b, 0x00, 0x11, 0x18, 0x00, 0x18, 0x11, 0x00, + 0x04, 0x54, 0x01, 0x12, 0x00, 0x2c, 0x00, 0x12, 0x18, 0x00, 0x18, 0x12, + 0x00, 0x04, 0x54, 0x01, 0x1a, 0x00, 0x33, 0x21, 0x21, 0x21, 0x00, 0x00, + 0x1a, 0x00, 0x04, 0x54, 0x01, 0x00, 0x00, 0x21, 0x00, 0x21, 0x65, 0x00, + 0x65, 0x00, 0x00, 0x04, 0x54, 0x01, 0x00, 0x00, 0x16, 0x00, 0x16, 0x17, + 0x00, 0x17, 0x00, 0x00, 0x04, 0x54, 0x01, 0x12, 0x00, 0x2b, 0x00, 0x11, + 0x18, 0x00, 0x18, 0x12, 0x00, 0x04, 0x54, 0x01, 0x00, 0x00, 0x18, 0x00, + 0x18, 0x16, 0x00, 0x16, 0x00, 0x00, 0x04, 0x54, 0x01, 0x00, 0x00, 0x16, + 0x00, 0x16, 0x16, 0x00, 0x16, 0x00, 0x00, 0x04, 0x54, 0x01, 0x00, 0x00, + 0x19, 0x00, 0x19, 0x17, 0x00, 0x17, 0x00, 0x00, 0x04, 0x54, 0x01, 0x11, + 0x00, 0x25, 0x00, 0x0f, 0x21, 0x00, 0x21, 0x11, 0x00, 0x04, 0x54, 0x01, + 0x13, 0x00, 0x28, 0x00, 0x0f, 0x21, 0x00, 0x21, 0x13, 0x00, 0x04, 0x54, + 0x01, 0x00, 0x00, 0x5c, 0x00, 0x5c, 0x17, 0x00, 0x17, 0x00, 0x00, 0x04, + 0x54, 0x01, 0x00, 0x00, 0xb8, 0x00, 0xb8, 0x17, 0x00, 0x17, 0x00, 0x00, + 0x04, 0x54, 0x01, 0x00, 0x00, 0x21, 0x00, 0x21, 0x23, 0x00, 0x23, 0x00, + 0x00, 0x04, 0x54, 0x01, 0x33, 0x00, 0x4e, 0x00, 0x80, 0x85, 0x00, 0x85, + 0x33, 0x00, 0x04, 0x54, 0x01, 0x73, 0x00, 0x73, 0x15, 0x00, 0x15, 0x00, + 0x00, 0x73, 0x00, 0x04, 0x54, 0x01, 0x2d, 0x00, 0x5a, 0x60, 0x2d, 0xc0, + 0x00, 0x60, 0x2d, 0x00, 0x04, 0x54, 0x01, 0x23, 0x00, 0x00, 0x4a, 0x23, + 0x94, 0x46, 0x4a, 0x23, 0x00, 0x05, 0xa4, 0x0a, 0x0e, 0x18, 0x0e, 0x00, + 0x03, 0x04, 0x07, 0x01, 0x00, 0x0c, 0x00, 0x07, 0x03, 0x14, 0x00, 0x11, + 0x0e, 0x18, 0x07, 0x17, 0x05, 0xa4, 0x0a, 0x00, 0x00, 0x00, 0x19, 0x0c, + 0x16, 0x08, 0x19, 0x10, 0x0d, 0x10, 0x13, 0x0c, 0x04, 0x10, 0x07, 0x00, + 0x00, 0x09, 0x01, 0x05, 0xa8, 0x06, 0x0d, 0x00, 0x03, 0x0a, 0x06, 0x04, + 0x00, 0x1b, 0x00, 0x11, 0x03, 0x2b, 0x00, 0x24, 0x0d, 0x36, 0x06, 0x32, + 0x0d, 0x00, 0x05, 0xa8, 0x06, 0x29, 0x15, 0x24, 0x06, 0x29, 0x0b, 0x16, + 0x00, 0x1e, 0x00, 0x07, 0x06, 0x0c, 0x00, 0x00, 0x15, 0x01, 0x0b, 0x29, + 0x15, 0x05, 0xa8, 0x06, 0x2a, 0x15, 0x24, 0x06, 0x2a, 0x0b, 0x16, 0x00, + 0x1f, 0x00, 0x07, 0x06, 0x0d, 0x00, 0x00, 0x15, 0x01, 0x0b, 0x2a, 0x15, + 0x06, 0x54, 0x15, 0x00, 0x00, 0x20, 0x00, 0x20, 0x33, 0x1c, 0x59, 0x05, + 0x59, 0x00, 0x33, 0x00, 0x00, 0x06, 0x54, 0x15, 0x00, 0x00, 0x23, 0x00, + 0x23, 0x6c, 0x5f, 0x6c, 0x5f, 0x86, 0x00, 0x86, 0x00, 0x00, 0x06, 0x54, + 0x15, 0x00, 0x59, 0x00, 0x25, 0x05, 0x00, 0x1c, 0x00, 0x20, 0x25, 0x20, + 0x59, 0x00, 0x59, 0x06, 0x54, 0x15, 0x00, 0x00, 0x73, 0x00, 0x73, 0x38, + 0x5e, 0x38, 0x5e, 0x16, 0x00, 0x16, 0x00, 0x00, 0x06, 0x54, 0x15, 0x1f, + 0x39, 0x00, 0x39, 0x00, 0x20, 0x15, 0x00, 0x28, 0x00, 0x1f, 0x20, 0x1f, + 0x39, 0x06, 0x54, 0x15, 0x0a, 0x00, 0x28, 0x00, 0x28, 0x19, 0x14, 0x39, + 0x00, 0x39, 0x0a, 0x19, 0x0a, 0x00, 0x06, 0x54, 0x15, 0x0a, 0x00, 0x28, + 0x00, 0x28, 0x1a, 0x14, 0x39, 0x00, 0x39, 0x0a, 0x1a, 0x0a, 0x00, 0x07, + 0xa8, 0x6a, 0x0c, 0x00, 0x03, 0x0a, 0x06, 0x04, 0x00, 0x15, 0x00, 0x0f, + 0x08, 0x27, 0x00, 0x20, 0x1a, 0x2e, 0x0f, 0x2e, 0x25, 0x2d, 0x20, 0x2e, + 0x2f, 0x27, 0x2b, 0x2b, 0x0c, 0x00, 0x07, 0x54, 0x55, 0x00, 0x00, 0x65, + 0x00, 0x65, 0x13, 0x31, 0x86, 0x0f, 0x86, 0x41, 0x19, 0x00, 0x19, 0x00, + 0x00, 0x07, 0x54, 0x55, 0x73, 0x16, 0x1d, 0x34, 0x73, 0x52, 0x73, 0x68, + 0x00, 0x3f, 0x00, 0x2a, 0x73, 0x00, 0x73, 0x16, 0x07, 0x54, 0x55, 0x00, + 0x16, 0x00, 0x00, 0x73, 0x2a, 0x73, 0x3f, 0x00, 0x68, 0x00, 0x52, 0x57, + 0x34, 0x00, 0x16, 0x07, 0xa8, 0x56, 0x13, 0x1d, 0x1f, 0x19, 0x1b, 0x1d, + 0x23, 0x0e, 0x23, 0x15, 0x1f, 0x04, 0x23, 0x08, 0x13, 0x00, 0x1b, 0x00, + 0x00, 0x00, 0x00, 0x1d, 0x13, 0x1d, 0x07, 0xa8, 0x56, 0x14, 0x23, 0x24, + 0x1f, 0x1e, 0x23, 0x29, 0x12, 0x29, 0x1b, 0x24, 0x05, 0x29, 0x09, 0x14, + 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x23, 0x14, 0x23, 0x07, 0x94, 0x6a, + 0x00, 0x00, 0x00, 0x52, 0x0c, 0x52, 0x2c, 0x47, 0x21, 0x52, 0x38, 0x29, + 0x38, 0x3d, 0x2c, 0x0a, 0x38, 0x15, 0x0c, 0x00, 0x21, 0x00, 0x00, 0x00, + 0x07, 0x94, 0x6a, 0x00, 0x00, 0x00, 0x25, 0x13, 0x25, 0x22, 0x20, 0x1d, + 0x25, 0x28, 0x12, 0x28, 0x1b, 0x22, 0x05, 0x28, 0x09, 0x13, 0x00, 0x1d, + 0x00, 0x00, 0x00, 0x07, 0xa8, 0x56, 0x0e, 0x22, 0x1e, 0x1e, 0x19, 0x22, + 0x23, 0x11, 0x23, 0x1a, 0x1e, 0x04, 0x23, 0x08, 0x0e, 0x00, 0x19, 0x00, + 0x00, 0x00, 0x00, 0x22, 0x0e, 0x22, 0x07, 0x54, 0x55, 0x00, 0x00, 0x23, + 0x00, 0x46, 0x63, 0x6a, 0x00, 0x8d, 0x00, 0x5b, 0x86, 0x32, 0x86, 0x00, + 0x00, 0x07, 0x54, 0x55, 0x46, 0x00, 0x75, 0x32, 0x5f, 0x32, 0x3b, 0x17, + 0x16, 0x32, 0x00, 0x32, 0x2f, 0x00, 0x46, 0x00, 0x07, 0x54, 0x55, 0x00, + 0x00, 0x20, 0x00, 0x39, 0x46, 0x52, 0x00, 0x73, 0x00, 0x4b, 0x65, 0x28, + 0x65, 0x00, 0x00, 0x07, 0x54, 0xaa, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, + 0x04, 0x12, 0x0e, 0x10, 0x0b, 0x12, 0x12, 0x09, 0x12, 0x0e, 0x0e, 0x02, + 0x12, 0x04, 0x04, 0x00, 0x0b, 0x00, 0x07, 0xa8, 0x6a, 0x39, 0x0b, 0x2e, + 0x03, 0x34, 0x05, 0x21, 0x00, 0x29, 0x00, 0x09, 0x0c, 0x11, 0x00, 0x00, + 0x2d, 0x00, 0x18, 0x01, 0x38, 0x00, 0x33, 0x02, 0x41, 0x01, 0x3d, 0x39, + 0x0b, 0x07, 0xa8, 0x6a, 0x00, 0x37, 0x0b, 0x3f, 0x05, 0x3c, 0x18, 0x41, + 0x11, 0x41, 0x31, 0x36, 0x28, 0x41, 0x3a, 0x15, 0x3a, 0x2a, 0x39, 0x0a, + 0x3a, 0x0f, 0x37, 0x00, 0x38, 0x04, 0x00, 0x37, 0x07, 0x94, 0x6a, 0x00, + 0x00, 0x00, 0x26, 0x13, 0x26, 0x22, 0x21, 0x1d, 0x26, 0x28, 0x13, 0x28, + 0x1c, 0x22, 0x05, 0x28, 0x0a, 0x13, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x07, + 0xa8, 0x6a, 0x24, 0x05, 0x1e, 0x01, 0x21, 0x02, 0x16, 0x00, 0x1b, 0x00, + 0x06, 0x08, 0x0c, 0x00, 0x00, 0x1e, 0x00, 0x0f, 0x01, 0x24, 0x00, 0x21, + 0x02, 0x2a, 0x01, 0x27, 0x24, 0x05, 0x07, 0xa8, 0x6a, 0x00, 0x25, 0x06, + 0x29, 0x03, 0x28, 0x0e, 0x2b, 0x0a, 0x2b, 0x1e, 0x23, 0x19, 0x2b, 0x24, + 0x0d, 0x24, 0x1b, 0x24, 0x06, 0x24, 0x09, 0x23, 0x00, 0x23, 0x03, 0x00, + 0x25, 0x07, 0xa4, 0x5a, 0x3d, 0x00, 0x33, 0x00, 0x0d, 0x0a, 0x1a, 0x00, + 0x00, 0x29, 0x00, 0x14, 0x0d, 0x48, 0x00, 0x3d, 0x33, 0x52, 0x1a, 0x52, + 0x3d, 0x52, 0x3d, 0x00, 0x07, 0x54, 0x55, 0x15, 0x18, 0x00, 0x00, 0x10, + 0x00, 0x22, 0x0f, 0x34, 0x00, 0x44, 0x00, 0x30, 0x18, 0x15, 0x18, 0x07, + 0x54, 0x55, 0x73, 0x16, 0x23, 0x28, 0x73, 0x3b, 0x73, 0x51, 0x00, 0x33, + 0x00, 0x1e, 0x73, 0x00, 0x73, 0x16, 0x07, 0x54, 0x55, 0x00, 0x16, 0x00, + 0x00, 0x73, 0x1e, 0x73, 0x33, 0x00, 0x51, 0x00, 0x3b, 0x51, 0x28, 0x00, + 0x16, 0x08, 0xa8, 0xaa, 0x02, 0x6f, 0x46, 0x60, 0x79, 0x6f, 0x67, 0x37, + 0x8c, 0x52, 0x8c, 0x0e, 0x79, 0x1d, 0x8c, 0x00, 0x46, 0x00, 0x67, 0x0e, + 0x12, 0x00, 0x24, 0x37, 0x00, 0x1d, 0x00, 0x60, 0x12, 0x52, 0x00, 0x6f, + 0x46, 0x6f, 0x24, 0x08, 0xa8, 0xaa, 0x02, 0x29, 0x2e, 0x24, 0x0a, 0x29, + 0x14, 0x14, 0x00, 0x1f, 0x00, 0x04, 0x0a, 0x09, 0x00, 0x00, 0x2e, 0x00, + 0x14, 0x04, 0x52, 0x00, 0x47, 0x14, 0x5c, 0x09, 0x5c, 0x24, 0x52, 0x1f, + 0x5c, 0x29, 0x2e, 0x29, 0x47, 0x08, 0xa8, 0xaa, 0x02, 0x12, 0x00, 0x05, + 0x06, 0x09, 0x00, 0x00, 0x17, 0x00, 0x0b, 0x05, 0x29, 0x00, 0x23, 0x12, + 0x2f, 0x09, 0x2f, 0x20, 0x29, 0x1b, 0x2f, 0x24, 0x17, 0x24, 0x23, 0x20, + 0x06, 0x24, 0x0b, 0x12, 0x00, 0x1b, 0x00, 0x08, 0xa8, 0xaa, 0x02, 0x00, + 0x11, 0x04, 0x1d, 0x00, 0x19, 0x11, 0x21, 0x09, 0x21, 0x1d, 0x1d, 0x19, + 0x21, 0x22, 0x11, 0x22, 0x19, 0x1d, 0x04, 0x22, 0x09, 0x11, 0x00, 0x19, + 0x00, 0x04, 0x04, 0x09, 0x00, 0x00, 0x11, 0x00, 0x09, 0x08, 0xa8, 0xaa, + 0x02, 0x14, 0x00, 0x05, 0x05, 0x0a, 0x00, 0x00, 0x14, 0x00, 0x0a, 0x05, + 0x24, 0x00, 0x1e, 0x14, 0x29, 0x0a, 0x29, 0x23, 0x24, 0x1d, 0x29, 0x28, + 0x14, 0x28, 0x1e, 0x23, 0x05, 0x28, 0x0a, 0x14, 0x00, 0x1d, 0x00, 0x08, + 0xa8, 0xaa, 0x02, 0x13, 0x2f, 0x20, 0x29, 0x1c, 0x2f, 0x25, 0x18, 0x25, + 0x24, 0x20, 0x06, 0x25, 0x0c, 0x13, 0x00, 0x1c, 0x00, 0x05, 0x06, 0x0a, + 0x00, 0x00, 0x18, 0x00, 0x0c, 0x05, 0x29, 0x00, 0x24, 0x13, 0x2f, 0x0a, + 0x2f, 0x08, 0xa8, 0xaa, 0x02, 0x00, 0x17, 0x04, 0x29, 0x00, 0x23, 0x11, + 0x2f, 0x09, 0x2f, 0x1e, 0x29, 0x19, 0x2f, 0x23, 0x17, 0x23, 0x22, 0x1e, + 0x06, 0x23, 0x0d, 0x11, 0x00, 0x19, 0x00, 0x04, 0x06, 0x09, 0x00, 0x00, + 0x17, 0x00, 0x0d, 0x08, 0xa8, 0xaa, 0x02, 0x21, 0x00, 0x09, 0x0c, 0x11, + 0x00, 0x00, 0x2d, 0x00, 0x18, 0x08, 0x4e, 0x00, 0x43, 0x21, 0x59, 0x11, + 0x59, 0x3a, 0x4e, 0x31, 0x59, 0x42, 0x2d, 0x42, 0x42, 0x3a, 0x0c, 0x42, + 0x18, 0x21, 0x00, 0x31, 0x00, 0x08, 0x54, 0x55, 0x01, 0x00, 0x00, 0x7c, + 0x00, 0x7c, 0x1a, 0x4f, 0x1a, 0x4f, 0x86, 0x2d, 0x86, 0x2d, 0x1a, 0x00, + 0x1a, 0x00, 0x00, 0x08, 0x54, 0x55, 0x01, 0x00, 0x00, 0x38, 0x00, 0x38, + 0x14, 0x1f, 0x14, 0x1f, 0x90, 0x38, 0x90, 0x38, 0xa4, 0x00, 0xa4, 0x00, + 0x00, 0x08, 0x54, 0x55, 0x01, 0x38, 0xa4, 0x00, 0xa4, 0x00, 0x90, 0x19, + 0x90, 0x19, 0x14, 0x00, 0x14, 0x00, 0x00, 0x38, 0x00, 0x38, 0xa4, 0x08, + 0xa8, 0xaa, 0x02, 0x16, 0x3b, 0x25, 0x34, 0x20, 0x3b, 0x2b, 0x1e, 0x2b, + 0x2c, 0x25, 0x08, 0x2b, 0x0f, 0x16, 0x00, 0x20, 0x00, 0x06, 0x08, 0x0b, + 0x00, 0x00, 0x1e, 0x00, 0x0f, 0x06, 0x34, 0x00, 0x2c, 0x16, 0x3b, 0x0b, + 0x3b, 0x08, 0xa8, 0xaa, 0x02, 0x15, 0x00, 0x06, 0x08, 0x0b, 0x00, 0x00, + 0x1e, 0x00, 0x0f, 0x06, 0x34, 0x00, 0x2c, 0x15, 0x3b, 0x0b, 0x3b, 0x25, + 0x34, 0x20, 0x3b, 0x2b, 0x1e, 0x2b, 0x2c, 0x25, 0x08, 0x2b, 0x0f, 0x15, + 0x00, 0x20, 0x00, 0x08, 0xa8, 0xaa, 0x02, 0x14, 0x27, 0x22, 0x21, 0x1c, + 0x27, 0x28, 0x13, 0x28, 0x1c, 0x22, 0x05, 0x28, 0x0b, 0x14, 0x00, 0x1c, + 0x00, 0x06, 0x05, 0x0c, 0x00, 0x00, 0x13, 0x00, 0x0b, 0x06, 0x21, 0x00, + 0x1c, 0x14, 0x27, 0x0c, 0x27, 0x08, 0xa8, 0xaa, 0x02, 0x0c, 0x00, 0x03, + 0x06, 0x06, 0x02, 0x00, 0x0e, 0x00, 0x09, 0x05, 0x18, 0x00, 0x14, 0x1b, + 0x23, 0x0b, 0x1d, 0x24, 0x1d, 0x21, 0x21, 0x27, 0x15, 0x27, 0x19, 0x21, + 0x0a, 0x27, 0x0f, 0x0c, 0x00, 0x1b, 0x05, 0x08, 0xa8, 0x6a, 0x01, 0x16, + 0x00, 0x05, 0x02, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x04, 0x03, 0x11, 0x00, + 0x0f, 0x0b, 0x14, 0x06, 0x14, 0x19, 0x0f, 0x13, 0x14, 0x1e, 0x02, 0x1e, + 0x0a, 0x1e, 0x00, 0x16, 0x00, 0x08, 0xa8, 0xaa, 0x02, 0x0f, 0x00, 0x04, + 0x04, 0x09, 0x00, 0x00, 0x0f, 0x00, 0x09, 0x04, 0x1a, 0x00, 0x16, 0x0f, + 0x1e, 0x08, 0x1e, 0x1a, 0x1a, 0x16, 0x1e, 0x1e, 0x0f, 0x1e, 0x15, 0x1a, + 0x04, 0x1e, 0x09, 0x0f, 0x00, 0x15, 0x00, 0x08, 0xa8, 0xaa, 0x02, 0x29, + 0x00, 0x48, 0x0a, 0x3d, 0x00, 0x53, 0x25, 0x53, 0x14, 0x48, 0x40, 0x53, + 0x36, 0x29, 0x4a, 0x3d, 0x4a, 0x0b, 0x40, 0x16, 0x4a, 0x00, 0x25, 0x00, + 0x36, 0x0b, 0x0a, 0x00, 0x14, 0x29, 0x00, 0x16, 0x00, 0x08, 0xa8, 0xaa, + 0x02, 0x0f, 0x00, 0x04, 0x05, 0x08, 0x00, 0x00, 0x15, 0x00, 0x0b, 0x04, + 0x25, 0x00, 0x20, 0x0f, 0x2b, 0x08, 0x2b, 0x1b, 0x25, 0x17, 0x2b, 0x1f, + 0x15, 0x1f, 0x20, 0x1b, 0x05, 0x1f, 0x0b, 0x0f, 0x00, 0x17, 0x00, 0x08, + 0xa8, 0xaa, 0x02, 0x00, 0x0c, 0x03, 0x14, 0x00, 0x10, 0x0b, 0x17, 0x07, + 0x17, 0x14, 0x14, 0x10, 0x17, 0x17, 0x0c, 0x17, 0x10, 0x14, 0x03, 0x17, + 0x07, 0x0b, 0x00, 0x10, 0x00, 0x03, 0x03, 0x07, 0x00, 0x00, 0x0c, 0x00, + 0x07, 0x08, 0xa8, 0xaa, 0x02, 0x00, 0x1a, 0x08, 0x08, 0x00, 0x0f, 0x1a, + 0x00, 0x0f, 0x00, 0x2c, 0x08, 0x24, 0x00, 0x33, 0x1a, 0x33, 0x0f, 0x2c, + 0x2c, 0x33, 0x25, 0x1a, 0x34, 0x24, 0x34, 0x08, 0x2c, 0x0f, 0x34, 0x00, + 0x1a, 0x00, 0x25, 0x08, 0xa8, 0xaa, 0x02, 0x00, 0x0c, 0x03, 0x14, 0x00, + 0x11, 0x0c, 0x18, 0x07, 0x18, 0x14, 0x14, 0x11, 0x18, 0x18, 0x0c, 0x18, + 0x11, 0x14, 0x04, 0x18, 0x07, 0x0c, 0x00, 0x11, 0x00, 0x03, 0x04, 0x07, + 0x00, 0x00, 0x0c, 0x00, 0x07, 0x08, 0xa8, 0xaa, 0x02, 0x00, 0x1a, 0x07, + 0x08, 0x00, 0x0f, 0x1a, 0x00, 0x0f, 0x00, 0x2c, 0x08, 0x24, 0x00, 0x33, + 0x1a, 0x33, 0x0f, 0x2c, 0x2c, 0x33, 0x25, 0x1a, 0x34, 0x24, 0x34, 0x07, + 0x2c, 0x0f, 0x34, 0x00, 0x1a, 0x00, 0x25, 0x08, 0xa8, 0xaa, 0x02, 0x00, + 0x0c, 0x03, 0x14, 0x00, 0x11, 0x0c, 0x18, 0x07, 0x18, 0x14, 0x14, 0x11, + 0x18, 0x17, 0x0c, 0x17, 0x11, 0x14, 0x04, 0x17, 0x07, 0x0c, 0x00, 0x10, + 0x00, 0x03, 0x04, 0x07, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x08, 0xa8, 0xaa, + 0x02, 0x24, 0x00, 0x3e, 0x0a, 0x35, 0x00, 0x47, 0x25, 0x47, 0x14, 0x3e, + 0x40, 0x47, 0x36, 0x24, 0x4a, 0x35, 0x4a, 0x0a, 0x40, 0x13, 0x4a, 0x00, + 0x25, 0x00, 0x36, 0x0a, 0x0a, 0x00, 0x14, 0x24, 0x00, 0x13, 0x00, 0x08, + 0xa8, 0xaa, 0x02, 0x0d, 0x00, 0x03, 0x05, 0x07, 0x00, 0x00, 0x15, 0x00, + 0x0b, 0x03, 0x25, 0x00, 0x1f, 0x0d, 0x2a, 0x07, 0x2a, 0x17, 0x25, 0x14, + 0x2a, 0x1a, 0x15, 0x1a, 0x1f, 0x17, 0x05, 0x1a, 0x0b, 0x0d, 0x00, 0x14, + 0x00, 0x08, 0x54, 0x55, 0x01, 0x2f, 0x00, 0x2f, 0x0d, 0x1f, 0x0d, 0x1f, + 0x34, 0x0f, 0x34, 0x0f, 0x0d, 0x00, 0x0d, 0x00, 0x00, 0x2f, 0x00, 0x08, + 0xa8, 0xaa, 0x02, 0x20, 0x15, 0x1d, 0x05, 0x20, 0x0b, 0x14, 0x00, 0x1a, + 0x00, 0x05, 0x0c, 0x0b, 0x00, 0x00, 0x2b, 0x00, 0x18, 0x03, 0x3b, 0x00, + 0x36, 0x0c, 0x40, 0x06, 0x40, 0x1b, 0x34, 0x15, 0x40, 0x20, 0x15, 0x20, + 0x28, 0x08, 0x54, 0x55, 0x01, 0x00, 0x00, 0x76, 0x00, 0x76, 0xa8, 0x57, + 0xa8, 0x57, 0x1a, 0x1f, 0x1a, 0x1f, 0xa8, 0x00, 0xa8, 0x00, 0x00, 0x08, + 0xa8, 0xaa, 0x02, 0x27, 0x0c, 0x1e, 0x03, 0x23, 0x06, 0x12, 0x00, 0x19, + 0x00, 0x05, 0x04, 0x0a, 0x00, 0x00, 0x10, 0x00, 0x09, 0x04, 0x1b, 0x00, + 0x17, 0x10, 0x20, 0x09, 0x20, 0x1c, 0x1b, 0x16, 0x20, 0x27, 0x0c, 0x21, + 0x16, 0x08, 0xa8, 0xaa, 0x02, 0x00, 0x14, 0x0a, 0x1e, 0x04, 0x1b, 0x15, + 0x21, 0x0f, 0x21, 0x23, 0x1c, 0x1e, 0x21, 0x28, 0x10, 0x28, 0x18, 0x23, + 0x05, 0x28, 0x0a, 0x18, 0x00, 0x1e, 0x00, 0x0c, 0x05, 0x11, 0x00, 0x00, + 0x14, 0x06, 0x0a, 0x09, 0xa4, 0x5a, 0x05, 0x00, 0x00, 0x39, 0x00, 0x61, + 0x0b, 0x53, 0x00, 0x6f, 0x2b, 0x6f, 0x16, 0x61, 0x4c, 0x6f, 0x41, 0x39, + 0x57, 0x53, 0x57, 0x23, 0x57, 0x23, 0x86, 0x00, 0x86, 0x00, 0x00, 0x0a, + 0xa4, 0x9a, 0x2a, 0x36, 0xa4, 0x1b, 0xa4, 0x07, 0x7a, 0x0d, 0x8e, 0x00, + 0x52, 0x00, 0x66, 0x07, 0x2a, 0x00, 0x3f, 0x1b, 0x00, 0x0d, 0x16, 0x36, + 0x00, 0x24, 0x2a, 0x2a, 0x16, 0x1f, 0x52, 0x1f, 0x3e, 0x24, 0x7a, 0x1f, + 0x66, 0x36, 0xa4, 0x2a, 0x8f, 0x0a, 0xa8, 0xa6, 0x1a, 0x00, 0xa4, 0x11, + 0x7a, 0x0c, 0x8f, 0x17, 0x52, 0x17, 0x66, 0x11, 0x2a, 0x17, 0x3e, 0x00, + 0x00, 0x0c, 0x16, 0x1b, 0x00, 0x2f, 0x2a, 0x28, 0x16, 0x36, 0x52, 0x36, + 0x3f, 0x2f, 0x7a, 0x36, 0x66, 0x1b, 0xa4, 0x28, 0x8e, 0x00, 0xa4, 0x0a, + 0x54, 0x55, 0x15, 0x00, 0x00, 0x5d, 0x00, 0x5d, 0x1a, 0x23, 0x1a, 0x23, + 0x33, 0x5a, 0x33, 0x5a, 0x4d, 0x23, 0x4d, 0x23, 0x86, 0x00, 0x86, 0x00, + 0x00, 0x0a, 0x94, 0x56, 0x1a, 0x1b, 0x00, 0x3e, 0x00, 0x3e, 0x79, 0x30, + 0x9e, 0x3e, 0x92, 0x07, 0xab, 0x23, 0xab, 0x00, 0xab, 0x00, 0x91, 0x05, + 0x91, 0x16, 0x8b, 0x10, 0x91, 0x1b, 0x79, 0x1b, 0x85, 0x1b, 0x00, 0x0a, + 0x94, 0x56, 0x1a, 0x16, 0x00, 0x36, 0x00, 0x36, 0x63, 0x2c, 0x82, 0x36, + 0x77, 0x10, 0x8d, 0x22, 0x8d, 0x00, 0x8d, 0x00, 0x78, 0x06, 0x78, 0x12, + 0x73, 0x0f, 0x78, 0x16, 0x63, 0x16, 0x6f, 0x16, 0x00, 0x0a, 0xa8, 0xaa, + 0x2a, 0x29, 0x05, 0x1f, 0x02, 0x24, 0x03, 0x15, 0x00, 0x1a, 0x00, 0x05, + 0x06, 0x0b, 0x00, 0x00, 0x17, 0x00, 0x0c, 0x05, 0x2c, 0x00, 0x24, 0x15, + 0x34, 0x0b, 0x34, 0x26, 0x2c, 0x20, 0x34, 0x2b, 0x16, 0x2b, 0x24, 0x2b, + 0x0d, 0x2b, 0x12, 0x29, 0x05, 0x2a, 0x09, 0x0a, 0xa4, 0x9a, 0x2a, 0x00, + 0x00, 0x0d, 0x00, 0x13, 0x08, 0x0f, 0x06, 0x1e, 0x0b, 0x17, 0x0b, 0x29, + 0x08, 0x25, 0x0b, 0x30, 0x00, 0x2e, 0x06, 0x3d, 0x00, 0x33, 0x12, 0x3b, + 0x0c, 0x1e, 0x18, 0x2c, 0x18, 0x09, 0x12, 0x11, 0x18, 0x00, 0x00, 0x02, + 0x0c, 0x0a, 0xa4, 0x9a, 0x2a, 0x00, 0x00, 0x0d, 0x00, 0x13, 0x09, 0x0e, + 0x06, 0x1f, 0x0c, 0x17, 0x0c, 0x2b, 0x09, 0x26, 0x0c, 0x30, 0x00, 0x2f, + 0x06, 0x3d, 0x00, 0x34, 0x13, 0x3c, 0x0c, 0x1f, 0x1a, 0x2d, 0x1a, 0x09, + 0x13, 0x11, 0x1a, 0x00, 0x00, 0x01, 0x0c, 0x0a, 0xa4, 0x9a, 0x2a, 0x00, + 0x00, 0x0d, 0x00, 0x12, 0x09, 0x0e, 0x06, 0x1e, 0x0c, 0x17, 0x0c, 0x2a, + 0x09, 0x26, 0x0c, 0x30, 0x00, 0x2f, 0x06, 0x3c, 0x00, 0x34, 0x13, 0x3c, + 0x0c, 0x1e, 0x1a, 0x2c, 0x1a, 0x08, 0x13, 0x10, 0x1a, 0x00, 0x00, 0x01, + 0x0c, 0x0b, 0x54, 0x55, 0x55, 0x01, 0x6e, 0x1f, 0x6e, 0x1f, 0x17, 0x00, + 0x1e, 0x00, 0x06, 0x1f, 0x00, 0x40, 0x00, 0x40, 0x6e, 0x5f, 0x6e, 0x5f, + 0x86, 0x01, 0x86, 0x01, 0x6e, 0x0b, 0x54, 0x55, 0x55, 0x36, 0x00, 0x5c, + 0x00, 0x5c, 0x54, 0x6f, 0x54, 0x6f, 0x6d, 0x5c, 0x6d, 0x5c, 0x86, 0x3c, + 0x86, 0x3c, 0x6d, 0x00, 0x6d, 0x00, 0x50, 0x36, 0x00, 0x0b, 0xa8, 0x56, + 0xaa, 0x57, 0x3e, 0x68, 0x4a, 0x62, 0x41, 0x6f, 0x5f, 0x6f, 0x53, 0x61, + 0x7c, 0x6f, 0x73, 0x39, 0x86, 0x54, 0x86, 0x00, 0x86, 0x00, 0x00, 0x34, + 0x00, 0x5c, 0x08, 0x50, 0x00, 0x69, 0x23, 0x69, 0x11, 0x64, 0x34, 0x69, + 0x2d, 0x57, 0x3e, 0x60, 0x3b, 0x0b, 0xa4, 0xaa, 0x5a, 0x00, 0x00, 0x25, + 0x00, 0x52, 0x04, 0x43, 0x00, 0x6c, 0x13, 0x61, 0x08, 0x7a, 0x28, 0x75, + 0x1c, 0x7e, 0x43, 0x7e, 0x34, 0x7a, 0x5e, 0x7e, 0x52, 0x6c, 0x73, 0x75, + 0x6a, 0x52, 0x82, 0x61, 0x7d, 0x25, 0x86, 0x43, 0x86, 0x00, 0x86, 0x00, + 0x00, 0x0b, 0x54, 0x55, 0x55, 0x00, 0x00, 0x23, 0x00, 0x23, 0x31, 0x55, + 0x00, 0x7d, 0x00, 0x3c, 0x3f, 0x83, 0x86, 0x58, 0x86, 0x23, 0x51, 0x23, + 0x86, 0x00, 0x86, 0x00, 0x00, 0x0b, 0x54, 0x55, 0x55, 0x00, 0x00, 0x20, + 0x00, 0x20, 0x4c, 0x45, 0x27, 0x6b, 0x27, 0x39, 0x55, 0x6f, 0x8c, 0x47, + 0x8c, 0x20, 0x62, 0x20, 0x8c, 0x00, 0x8c, 0x00, 0x00, 0x0b, 0x54, 0x55, + 0x55, 0x22, 0x00, 0x38, 0x00, 0x38, 0x2e, 0x44, 0x2e, 0x44, 0x3c, 0x38, + 0x3c, 0x38, 0x4b, 0x23, 0x4b, 0x23, 0x3c, 0x00, 0x3c, 0x00, 0x2d, 0x22, + 0x00, 0x0b, 0x54, 0x55, 0x55, 0x21, 0x00, 0x38, 0x00, 0x38, 0x2e, 0x44, + 0x2e, 0x44, 0x3c, 0x38, 0x3c, 0x38, 0x4b, 0x23, 0x4b, 0x23, 0x3c, 0x00, + 0x3c, 0x00, 0x2d, 0x21, 0x00, 0x0b, 0x54, 0x95, 0x6a, 0x00, 0x00, 0x00, + 0x1d, 0x15, 0x1d, 0x15, 0x34, 0x00, 0x34, 0x00, 0x52, 0x0d, 0x52, 0x2d, + 0x47, 0x22, 0x52, 0x38, 0x29, 0x38, 0x3d, 0x2d, 0x0a, 0x38, 0x15, 0x0d, + 0x00, 0x22, 0x00, 0x00, 0x00, 0x0b, 0x54, 0x95, 0x6a, 0x23, 0x6f, 0x23, + 0x86, 0x00, 0x86, 0x00, 0x00, 0x23, 0x00, 0x23, 0x17, 0x39, 0x17, 0x61, + 0x22, 0x53, 0x17, 0x6f, 0x43, 0x6f, 0x2e, 0x61, 0x63, 0x6f, 0x58, 0x39, + 0x6f, 0x53, 0x6f, 0x23, 0x6f, 0x0b, 0x54, 0x55, 0x55, 0x61, 0x00, 0x74, + 0x00, 0x74, 0x0d, 0x6c, 0x0d, 0x37, 0x9e, 0x2c, 0x9e, 0x10, 0x52, 0x03, + 0x56, 0x00, 0x4b, 0x20, 0x3f, 0x34, 0x79, 0x61, 0x00, 0x0c, 0x54, 0x55, + 0x55, 0x01, 0x44, 0x00, 0x44, 0x30, 0x73, 0x30, 0x73, 0x45, 0x44, 0x45, + 0x44, 0x74, 0x2f, 0x74, 0x2f, 0x45, 0x00, 0x45, 0x00, 0x30, 0x2f, 0x30, + 0x2f, 0x00, 0x44, 0x00, 0x0c, 0x54, 0x55, 0x55, 0x01, 0x00, 0x00, 0x23, + 0x00, 0x23, 0x33, 0x56, 0x33, 0x56, 0x00, 0x78, 0x00, 0x78, 0x86, 0x56, + 0x86, 0x56, 0x4d, 0x23, 0x4d, 0x23, 0x86, 0x00, 0x86, 0x00, 0x00, 0x0c, + 0xa4, 0xaa, 0x5a, 0x01, 0x49, 0x8b, 0x46, 0x8b, 0x12, 0x79, 0x25, 0x8b, + 0x00, 0x46, 0x00, 0x67, 0x12, 0x13, 0x00, 0x25, 0x45, 0x00, 0x25, 0x00, + 0x78, 0x13, 0x66, 0x00, 0x8a, 0x46, 0x8a, 0x25, 0x80, 0x6d, 0x8a, 0x5d, + 0x65, 0x86, 0x77, 0x7d, 0x80, 0xa4, 0x5f, 0xa4, 0x49, 0x8b, 0x0c, 0x54, + 0x55, 0x55, 0x01, 0x58, 0x41, 0x87, 0x86, 0x63, 0x86, 0x43, 0x58, 0x24, + 0x86, 0x00, 0x86, 0x2f, 0x41, 0x02, 0x00, 0x26, 0x00, 0x43, 0x2b, 0x61, + 0x00, 0x85, 0x00, 0x58, 0x41, 0x0c, 0x54, 0x55, 0x55, 0x01, 0x26, 0x31, + 0x02, 0x00, 0x24, 0x00, 0x38, 0x1e, 0x4d, 0x00, 0x6f, 0x00, 0x4b, 0x31, + 0x71, 0x65, 0x4f, 0x65, 0x38, 0x45, 0x22, 0x65, 0x00, 0x65, 0x26, 0x31, + 0x0c, 0xa8, 0xaa, 0xaa, 0x02, 0x1e, 0x00, 0x29, 0x02, 0x24, 0x00, 0x33, + 0x09, 0x2f, 0x05, 0x3a, 0x13, 0x37, 0x0d, 0x3c, 0x1e, 0x3c, 0x18, 0x3a, + 0x2a, 0x3c, 0x24, 0x33, 0x33, 0x37, 0x2f, 0x2a, 0x3a, 0x2f, 0x37, 0x1e, + 0x3c, 0x24, 0x3c, 0x09, 0x33, 0x11, 0x3c, 0x00, 0x1e, 0x00, 0x2b, 0x09, + 0x09, 0x00, 0x11, 0x1e, 0x00, 0x11, 0x00, 0x0c, 0x54, 0x55, 0x55, 0x01, + 0x44, 0x00, 0x44, 0x20, 0x73, 0x20, 0x73, 0x36, 0x44, 0x36, 0x44, 0x55, + 0x2f, 0x55, 0x2f, 0x36, 0x00, 0x36, 0x00, 0x20, 0x2f, 0x20, 0x2f, 0x00, + 0x44, 0x00, 0x0c, 0x54, 0x55, 0xa9, 0x02, 0x2b, 0x00, 0x59, 0x00, 0x59, + 0x98, 0x48, 0x98, 0x48, 0x0d, 0x37, 0x0d, 0x37, 0x98, 0x26, 0x98, 0x26, + 0x4c, 0x0a, 0x40, 0x14, 0x49, 0x00, 0x26, 0x00, 0x36, 0x0c, 0x0a, 0x00, + 0x15, 0x2b, 0x00, 0x17, 0x00, 0x0c, 0x54, 0x55, 0x55, 0x01, 0x6c, 0x0f, + 0x45, 0x36, 0x6c, 0x5d, 0x5d, 0x6c, 0x36, 0x45, 0x0f, 0x6c, 0x00, 0x5d, + 0x27, 0x36, 0x00, 0x0f, 0x0f, 0x00, 0x36, 0x27, 0x5d, 0x00, 0x6c, 0x0f, + 0x0c, 0x54, 0x55, 0x55, 0x01, 0x15, 0x00, 0x36, 0x00, 0x36, 0x2d, 0x41, + 0x25, 0x4b, 0x33, 0x36, 0x42, 0x36, 0x8c, 0x15, 0x8c, 0x15, 0x52, 0x0a, + 0x5a, 0x00, 0x4c, 0x15, 0x3e, 0x15, 0x00, 0x0c, 0x54, 0x55, 0x55, 0x01, + 0x1a, 0x00, 0x38, 0x00, 0x38, 0x22, 0x52, 0x22, 0x52, 0x37, 0x38, 0x37, + 0x38, 0x98, 0x1a, 0x98, 0x1a, 0x37, 0x00, 0x37, 0x00, 0x22, 0x1a, 0x22, + 0x1a, 0x00, 0x0c, 0x54, 0x55, 0x55, 0x01, 0x02, 0x00, 0x78, 0x00, 0x78, + 0x18, 0x29, 0x18, 0x61, 0x52, 0x29, 0x90, 0x7d, 0x90, 0x7d, 0xa8, 0x00, + 0xa8, 0x00, 0x99, 0x3f, 0x53, 0x02, 0x15, 0x02, 0x00, 0x0d, 0x54, 0x55, + 0x55, 0x05, 0x00, 0x00, 0x2c, 0x00, 0x4b, 0x48, 0x69, 0x00, 0x95, 0x00, + 0x95, 0x86, 0x75, 0x86, 0x75, 0x24, 0x56, 0x6c, 0x40, 0x6c, 0x21, 0x24, + 0x21, 0x86, 0x00, 0x86, 0x00, 0x00, 0x0d, 0x54, 0x55, 0x55, 0x05, 0x00, + 0x00, 0x21, 0x00, 0x38, 0x61, 0x4f, 0x00, 0x71, 0x00, 0x88, 0x61, 0x9f, + 0x00, 0xc0, 0x00, 0xa0, 0x86, 0x78, 0x86, 0x60, 0x20, 0x48, 0x86, 0x20, + 0x86, 0x00, 0x00, 0x0d, 0xa8, 0xaa, 0x56, 0x05, 0x20, 0x36, 0x2f, 0x29, + 0x27, 0x2d, 0x42, 0x25, 0x37, 0x25, 0x60, 0x34, 0x54, 0x25, 0x6c, 0x5a, + 0x6c, 0x42, 0x60, 0x80, 0x6c, 0x71, 0x42, 0x8f, 0x54, 0x8f, 0x2f, 0x8a, + 0x37, 0x8f, 0x20, 0x7d, 0x27, 0x86, 0x20, 0x8c, 0x00, 0x8c, 0x00, 0x00, + 0x20, 0x00, 0x20, 0x36, 0x0d, 0x54, 0xa5, 0xaa, 0x0a, 0x4c, 0x36, 0x4c, + 0x00, 0x6c, 0x00, 0x6c, 0x8c, 0x4c, 0x8c, 0x4c, 0x7d, 0x3d, 0x8a, 0x45, + 0x86, 0x2b, 0x8f, 0x35, 0x8f, 0x0c, 0x80, 0x18, 0x8f, 0x00, 0x5a, 0x00, + 0x71, 0x0c, 0x34, 0x00, 0x42, 0x2b, 0x25, 0x18, 0x25, 0x3d, 0x29, 0x35, + 0x25, 0x4c, 0x36, 0x45, 0x2d, 0x0d, 0x54, 0xa5, 0xaa, 0x0a, 0x20, 0x58, + 0x20, 0x8d, 0x00, 0x8d, 0x00, 0x02, 0x20, 0x02, 0x20, 0x11, 0x2f, 0x04, + 0x27, 0x08, 0x42, 0x00, 0x37, 0x00, 0x60, 0x0f, 0x54, 0x00, 0x6c, 0x35, + 0x6c, 0x1d, 0x60, 0x5b, 0x6c, 0x4c, 0x42, 0x6a, 0x54, 0x6a, 0x2f, 0x65, + 0x37, 0x6a, 0x20, 0x58, 0x27, 0x61, 0x0d, 0xa8, 0xaa, 0x56, 0x05, 0x4c, + 0x58, 0x3d, 0x65, 0x45, 0x61, 0x2b, 0x6a, 0x35, 0x6a, 0x0c, 0x5b, 0x18, + 0x6a, 0x00, 0x35, 0x00, 0x4c, 0x0c, 0x0f, 0x00, 0x1d, 0x2b, 0x00, 0x18, + 0x00, 0x3d, 0x04, 0x35, 0x00, 0x4c, 0x11, 0x45, 0x08, 0x4c, 0x02, 0x6c, + 0x02, 0x6c, 0x8d, 0x4c, 0x8d, 0x4c, 0x58, 0x0d, 0x54, 0x55, 0x55, 0x05, + 0x00, 0x00, 0x1f, 0x00, 0x30, 0x46, 0x41, 0x00, 0x5c, 0x00, 0x6d, 0x45, + 0x7e, 0x00, 0x9d, 0x00, 0x83, 0x65, 0x60, 0x65, 0x4f, 0x20, 0x3e, 0x65, + 0x1b, 0x65, 0x00, 0x00, 0x0d, 0x54, 0xa5, 0xaa, 0x0a, 0x20, 0x7d, 0x20, + 0xb2, 0x00, 0xb2, 0x00, 0x00, 0x20, 0x00, 0x20, 0x36, 0x2f, 0x29, 0x27, + 0x2d, 0x42, 0x25, 0x37, 0x25, 0x60, 0x34, 0x54, 0x25, 0x6c, 0x5a, 0x6c, + 0x42, 0x60, 0x80, 0x6c, 0x71, 0x42, 0x8f, 0x54, 0x8f, 0x2f, 0x8a, 0x37, + 0x8f, 0x20, 0x7d, 0x27, 0x86, 0x0d, 0x54, 0x55, 0x55, 0x05, 0x14, 0x00, + 0x1f, 0x14, 0x2a, 0x00, 0x3e, 0x00, 0x3e, 0x34, 0x2f, 0x34, 0x2f, 0x0c, + 0x22, 0x23, 0x1c, 0x23, 0x0f, 0x0c, 0x0f, 0x34, 0x00, 0x34, 0x00, 0x00, + 0x14, 0x00, 0x0e, 0xa8, 0x56, 0xa5, 0x1a, 0x4b, 0x1e, 0x42, 0x1b, 0x47, + 0x1c, 0x3a, 0x1a, 0x3e, 0x1a, 0x27, 0x22, 0x2e, 0x1a, 0x20, 0x39, 0x20, + 0x2a, 0x20, 0x67, 0x00, 0x67, 0x00, 0x02, 0x20, 0x02, 0x20, 0x13, 0x2e, + 0x04, 0x26, 0x09, 0x42, 0x00, 0x36, 0x00, 0x45, 0x00, 0x43, 0x00, 0x4b, + 0x01, 0x47, 0x00, 0x4b, 0x1e, 0x0e, 0xa8, 0x6a, 0xaa, 0x1a, 0x1f, 0x00, + 0x26, 0x0a, 0x24, 0x06, 0x29, 0x13, 0x29, 0x0f, 0x23, 0x20, 0x29, 0x1c, + 0x12, 0x24, 0x1e, 0x24, 0x09, 0x23, 0x0e, 0x24, 0x00, 0x22, 0x05, 0x23, + 0x00, 0x14, 0x08, 0x16, 0x04, 0x15, 0x0f, 0x17, 0x0c, 0x17, 0x17, 0x15, + 0x14, 0x17, 0x1a, 0x0f, 0x1a, 0x13, 0x18, 0x09, 0x1a, 0x0d, 0x12, 0x00, + 0x16, 0x05, 0x1f, 0x00, 0x0e, 0xa8, 0x6a, 0xaa, 0x1a, 0x1e, 0x00, 0x26, + 0x0a, 0x24, 0x06, 0x28, 0x13, 0x28, 0x0f, 0x23, 0x20, 0x28, 0x1c, 0x12, + 0x24, 0x1d, 0x24, 0x09, 0x23, 0x0e, 0x24, 0x00, 0x22, 0x05, 0x23, 0x00, + 0x14, 0x08, 0x16, 0x04, 0x15, 0x0f, 0x17, 0x0c, 0x17, 0x17, 0x15, 0x14, + 0x17, 0x1a, 0x0f, 0x1a, 0x13, 0x18, 0x09, 0x1a, 0x0d, 0x12, 0x00, 0x16, + 0x05, 0x1e, 0x00, 0x0e, 0x54, 0x55, 0x55, 0x15, 0x1a, 0x00, 0x3d, 0x00, + 0x3d, 0x25, 0x54, 0x14, 0x60, 0x26, 0x3d, 0x3e, 0x3d, 0x6c, 0x7a, 0x6c, + 0x7a, 0x86, 0x1a, 0x86, 0x1a, 0x57, 0x0d, 0x60, 0x00, 0x4f, 0x1a, 0x3e, + 0x1a, 0x00, 0x0e, 0xa8, 0x6a, 0xaa, 0x1a, 0x1e, 0x00, 0x26, 0x0a, 0x24, + 0x06, 0x29, 0x13, 0x29, 0x0f, 0x23, 0x20, 0x29, 0x1c, 0x12, 0x24, 0x1e, + 0x24, 0x09, 0x23, 0x0e, 0x24, 0x00, 0x22, 0x05, 0x23, 0x00, 0x14, 0x08, + 0x16, 0x04, 0x15, 0x0f, 0x17, 0x0c, 0x17, 0x17, 0x15, 0x14, 0x17, 0x1a, + 0x0f, 0x1a, 0x13, 0x18, 0x09, 0x1a, 0x0d, 0x12, 0x00, 0x16, 0x05, 0x1e, + 0x00, 0x0e, 0xa4, 0xaa, 0xa9, 0x2a, 0x0a, 0x00, 0x17, 0x00, 0x10, 0x09, + 0x12, 0x06, 0x0f, 0x0f, 0x0f, 0x0d, 0x11, 0x15, 0x0f, 0x12, 0x18, 0x17, + 0x14, 0x17, 0x1f, 0x16, 0x1c, 0x17, 0x26, 0x14, 0x23, 0x15, 0x26, 0x22, + 0x1d, 0x23, 0x22, 0x23, 0x15, 0x24, 0x19, 0x24, 0x05, 0x20, 0x0b, 0x24, + 0x00, 0x14, 0x00, 0x1c, 0x02, 0x0a, 0x00, 0x0f, 0x0a, 0x00, 0x05, 0x05, + 0x0f, 0x54, 0x55, 0xaa, 0xaa, 0x5c, 0x27, 0x8d, 0xab, 0x6a, 0xab, 0x61, + 0x92, 0x2b, 0x92, 0x23, 0xab, 0x00, 0xab, 0x31, 0x27, 0x2e, 0x21, 0x2f, + 0x24, 0x2d, 0x1a, 0x2d, 0x1d, 0x34, 0x08, 0x2d, 0x0f, 0x46, 0x00, 0x3c, + 0x00, 0x58, 0x08, 0x51, 0x00, 0x60, 0x1a, 0x60, 0x0f, 0x5f, 0x21, 0x60, + 0x1e, 0x5c, 0x27, 0x5e, 0x25, 0x0f, 0xa4, 0xaa, 0x5a, 0x55, 0x10, 0x00, + 0x34, 0x00, 0x62, 0x04, 0x53, 0x00, 0x7b, 0x13, 0x71, 0x08, 0x89, 0x28, + 0x85, 0x1c, 0x8e, 0x43, 0x8e, 0x34, 0x89, 0x5e, 0x8e, 0x52, 0x7b, 0x73, + 0x85, 0x6a, 0x61, 0x82, 0x70, 0x7d, 0x34, 0x86, 0x52, 0x86, 0x10, 0x86, + 0x10, 0x4e, 0x00, 0x4e, 0x00, 0x37, 0x10, 0x37, 0x10, 0x00, 0x10, 0xa8, + 0xaa, 0xaa, 0xaa, 0x02, 0x1c, 0x41, 0x09, 0x36, 0x0f, 0x3e, 0x03, 0x23, + 0x03, 0x2e, 0x10, 0x09, 0x03, 0x12, 0x35, 0x00, 0x1c, 0x00, 0x5a, 0x09, + 0x4d, 0x00, 0x67, 0x23, 0x67, 0x12, 0x60, 0x36, 0x67, 0x2e, 0x4e, 0x41, + 0x5a, 0x3e, 0x62, 0x4e, 0x5c, 0x45, 0x69, 0x63, 0x69, 0x56, 0x5c, 0x81, + 0x69, 0x77, 0x35, 0x8c, 0x4f, 0x8c, 0x0d, 0x81, 0x1b, 0x8c, 0x00, 0x63, + 0x00, 0x77, 0x07, 0x4e, 0x00, 0x56, 0x1c, 0x41, 0x0e, 0x45, 0x10, 0x54, + 0xa9, 0x6a, 0xa5, 0x01, 0x23, 0x53, 0x23, 0x86, 0x00, 0x86, 0x00, 0x00, + 0x35, 0x00, 0x5c, 0x09, 0x4f, 0x00, 0x68, 0x25, 0x68, 0x11, 0x62, 0x3b, + 0x68, 0x32, 0x4e, 0x47, 0x5b, 0x43, 0x5b, 0x4f, 0x55, 0x49, 0x66, 0x60, + 0x61, 0x54, 0x79, 0x86, 0x54, 0x86, 0x44, 0x65, 0x3a, 0x57, 0x3f, 0x5b, + 0x2c, 0x53, 0x35, 0x53, 0x23, 0x53, 0x10, 0xa8, 0x6a, 0xa5, 0x55, 0x01, + 0x1a, 0x00, 0x31, 0x06, 0x2a, 0x00, 0x39, 0x16, 0x39, 0x0b, 0x35, 0x23, + 0x39, 0x1e, 0x27, 0x29, 0x30, 0x28, 0x2e, 0x2f, 0x2b, 0x2b, 0x34, 0x38, + 0x31, 0x32, 0x3e, 0x4c, 0x29, 0x4c, 0x20, 0x38, 0x1a, 0x2e, 0x1c, 0x31, + 0x14, 0x2c, 0x17, 0x2c, 0x13, 0x2c, 0x13, 0x4c, 0x00, 0x4c, 0x00, 0x00, + 0x1a, 0x00, 0x10, 0x54, 0x55, 0x55, 0x55, 0x01, 0x38, 0x00, 0xb8, 0x00, + 0xb8, 0x1a, 0x7e, 0x1a, 0x7e, 0x33, 0xb5, 0x33, 0xb5, 0x4d, 0x7e, 0x4d, + 0x7e, 0x6c, 0xba, 0x6c, 0xba, 0x86, 0x5b, 0x86, 0x5b, 0x66, 0x2f, 0x66, + 0x21, 0x86, 0x00, 0x86, 0x38, 0x00, 0x10, 0x54, 0x55, 0x95, 0xa6, 0x01, + 0x7d, 0x00, 0x79, 0x14, 0x6a, 0x14, 0x5c, 0x62, 0x42, 0x62, 0x50, 0x14, + 0x3a, 0x14, 0x2d, 0x62, 0x13, 0x62, 0x20, 0x14, 0x1e, 0x14, 0x17, 0x17, + 0x19, 0x14, 0x13, 0x20, 0x14, 0x19, 0x00, 0x20, 0x0b, 0x07, 0x03, 0x0e, + 0x27, 0x00, 0x14, 0x00, 0x7d, 0x00, 0x10, 0xa8, 0xaa, 0xaa, 0xaa, 0x02, + 0x00, 0x20, 0x02, 0x14, 0x00, 0x1a, 0x09, 0x0a, 0x05, 0x0e, 0x14, 0x03, + 0x0e, 0x05, 0x20, 0x00, 0x1a, 0x00, 0x2d, 0x03, 0x27, 0x00, 0x37, 0x0a, + 0x33, 0x05, 0x3e, 0x14, 0x3c, 0x0e, 0x41, 0x20, 0x41, 0x1a, 0x3e, 0x2d, + 0x41, 0x27, 0x37, 0x37, 0x3c, 0x33, 0x2d, 0x3e, 0x33, 0x3c, 0x20, 0x41, + 0x27, 0x41, 0x14, 0x3e, 0x1a, 0x41, 0x09, 0x37, 0x0e, 0x3c, 0x02, 0x2d, + 0x05, 0x33, 0x00, 0x20, 0x00, 0x27, 0x10, 0xa8, 0xaa, 0xaa, 0xaa, 0x02, + 0x3b, 0x35, 0x2e, 0x47, 0x35, 0x41, 0x1e, 0x4c, 0x27, 0x4c, 0x09, 0x41, + 0x12, 0x4c, 0x00, 0x26, 0x00, 0x36, 0x08, 0x0b, 0x00, 0x15, 0x1c, 0x00, + 0x10, 0x00, 0x2b, 0x05, 0x24, 0x00, 0x3b, 0x17, 0x32, 0x0a, 0x49, 0x06, + 0x41, 0x0b, 0x58, 0x00, 0x50, 0x00, 0x6e, 0x0b, 0x65, 0x00, 0x77, 0x26, + 0x77, 0x16, 0x6f, 0x42, 0x77, 0x37, 0x5a, 0x4c, 0x67, 0x4c, 0x4b, 0x47, + 0x52, 0x4c, 0x3b, 0x35, 0x45, 0x42, 0x11, 0xa4, 0xaa, 0xaa, 0xaa, 0x0a, + 0x62, 0x06, 0x62, 0x1f, 0x52, 0x19, 0x59, 0x1b, 0x43, 0x17, 0x4a, 0x17, + 0x2b, 0x20, 0x34, 0x17, 0x21, 0x39, 0x22, 0x28, 0x2e, 0x33, 0x27, 0x35, + 0x3d, 0x30, 0x35, 0x30, 0x5e, 0x3c, 0x52, 0x30, 0x6b, 0x5c, 0x6b, 0x48, + 0x5d, 0x7f, 0x6b, 0x72, 0x37, 0x8c, 0x4f, 0x8c, 0x0e, 0x7a, 0x1d, 0x8c, + 0x00, 0x48, 0x00, 0x68, 0x11, 0x13, 0x00, 0x26, 0x3f, 0x00, 0x22, 0x00, + 0x51, 0x02, 0x48, 0x00, 0x62, 0x06, 0x59, 0x03, 0x11, 0xa4, 0xaa, 0xaa, + 0xaa, 0x0a, 0x09, 0x86, 0x09, 0x6d, 0x19, 0x73, 0x11, 0x71, 0x28, 0x75, + 0x20, 0x75, 0x40, 0x6c, 0x37, 0x75, 0x4a, 0x53, 0x48, 0x64, 0x3d, 0x5a, + 0x44, 0x57, 0x2e, 0x5c, 0x36, 0x5c, 0x0d, 0x50, 0x19, 0x5c, 0x00, 0x30, + 0x00, 0x44, 0x0e, 0x0d, 0x00, 0x1b, 0x34, 0x00, 0x1c, 0x00, 0x5c, 0x12, + 0x4e, 0x00, 0x6b, 0x44, 0x6b, 0x24, 0x5a, 0x79, 0x6b, 0x66, 0x2c, 0x8c, + 0x49, 0x8c, 0x1a, 0x8a, 0x22, 0x8c, 0x09, 0x86, 0x11, 0x89, 0x12, 0x54, + 0x55, 0x55, 0x55, 0x15, 0x59, 0x1c, 0x3b, 0x2b, 0x59, 0x3b, 0x52, 0x47, + 0x34, 0x37, 0x34, 0x56, 0x25, 0x56, 0x25, 0x37, 0x07, 0x47, 0x00, 0x3b, + 0x1e, 0x2b, 0x00, 0x1c, 0x07, 0x0f, 0x25, 0x1f, 0x25, 0x00, 0x34, 0x00, + 0x34, 0x1f, 0x52, 0x0f, 0x59, 0x1c, 0x12, 0x94, 0x56, 0x55, 0x55, 0x1a, + 0x4e, 0x00, 0x4e, 0x15, 0x3c, 0x15, 0x33, 0x18, 0x36, 0x15, 0x30, 0x20, + 0x30, 0x1a, 0x30, 0x27, 0x4c, 0x27, 0x4c, 0x3e, 0x30, 0x3e, 0x30, 0x8c, + 0x10, 0x8c, 0x10, 0x3e, 0x00, 0x3e, 0x00, 0x27, 0x10, 0x27, 0x10, 0x20, + 0x19, 0x08, 0x10, 0x10, 0x36, 0x00, 0x22, 0x00, 0x4e, 0x00, 0x12, 0x54, + 0xa5, 0x95, 0x56, 0x15, 0x30, 0x00, 0x30, 0x1c, 0x51, 0x1c, 0x51, 0x33, + 0x30, 0x33, 0x30, 0x5e, 0x33, 0x67, 0x30, 0x65, 0x3e, 0x6a, 0x36, 0x6a, + 0x4f, 0x6a, 0x4f, 0x81, 0x33, 0x81, 0x18, 0x79, 0x20, 0x81, 0x10, 0x5e, + 0x10, 0x71, 0x10, 0x33, 0x00, 0x33, 0x00, 0x1c, 0x10, 0x1c, 0x10, 0x00, + 0x30, 0x00, 0x12, 0xa4, 0xaa, 0x9a, 0xaa, 0x2a, 0x73, 0x00, 0x73, 0x15, + 0x62, 0x20, 0x6a, 0x1d, 0x51, 0x23, 0x5a, 0x23, 0x3b, 0x1e, 0x47, 0x23, + 0x39, 0x1d, 0x39, 0x1d, 0x37, 0x1c, 0x38, 0x1d, 0x20, 0x17, 0x29, 0x17, + 0x11, 0x1a, 0x18, 0x17, 0x00, 0x25, 0x09, 0x1d, 0x00, 0x0f, 0x12, 0x05, + 0x0a, 0x08, 0x22, 0x02, 0x1a, 0x02, 0x39, 0x07, 0x2c, 0x02, 0x3b, 0x08, + 0x3a, 0x07, 0x3d, 0x08, 0x3b, 0x08, 0x53, 0x0e, 0x4b, 0x0e, 0x62, 0x0b, + 0x5b, 0x0e, 0x73, 0x00, 0x6a, 0x07, 0x12, 0xa4, 0xaa, 0x9a, 0xaa, 0x2a, + 0x41, 0x04, 0x41, 0x17, 0x36, 0x12, 0x3b, 0x14, 0x2c, 0x11, 0x31, 0x11, + 0x1c, 0x16, 0x22, 0x11, 0x17, 0x26, 0x17, 0x1c, 0x1c, 0x36, 0x17, 0x31, + 0x2c, 0x3c, 0x22, 0x3c, 0x37, 0x3a, 0x32, 0x3c, 0x41, 0x36, 0x3c, 0x39, + 0x41, 0x49, 0x35, 0x4c, 0x3b, 0x4b, 0x29, 0x4d, 0x2f, 0x4d, 0x0b, 0x42, + 0x16, 0x4d, 0x00, 0x26, 0x00, 0x38, 0x0b, 0x0a, 0x00, 0x15, 0x29, 0x00, + 0x16, 0x00, 0x35, 0x01, 0x30, 0x00, 0x41, 0x04, 0x3b, 0x02, 0x12, 0xa8, + 0x6a, 0xa5, 0xaa, 0x15, 0x12, 0x77, 0x08, 0x63, 0x0c, 0x6e, 0x05, 0x4a, + 0x05, 0x58, 0x17, 0x17, 0x05, 0x29, 0x4a, 0x04, 0x2a, 0x04, 0x63, 0x08, + 0x58, 0x04, 0x77, 0x12, 0x6e, 0x0b, 0x89, 0x00, 0x94, 0x0a, 0x81, 0x1c, + 0x8c, 0x31, 0x88, 0x25, 0x8f, 0x4a, 0x8f, 0x3c, 0x7d, 0x7d, 0x8f, 0x6a, + 0x4a, 0x90, 0x6b, 0x90, 0x31, 0x8c, 0x3c, 0x90, 0x1c, 0x81, 0x25, 0x88, + 0x0a, 0x94, 0x00, 0x89, 0x12, 0x77, 0x12, 0xa8, 0x6a, 0xa5, 0xaa, 0x15, + 0x0d, 0x5f, 0x04, 0x4f, 0x07, 0x58, 0x01, 0x3b, 0x01, 0x46, 0x10, 0x14, + 0x01, 0x22, 0x38, 0x06, 0x1e, 0x06, 0x4a, 0x08, 0x42, 0x06, 0x59, 0x0e, + 0x52, 0x0a, 0x66, 0x00, 0x70, 0x09, 0x63, 0x16, 0x6c, 0x26, 0x69, 0x1d, + 0x70, 0x3b, 0x70, 0x2f, 0x61, 0x62, 0x70, 0x53, 0x38, 0x70, 0x52, 0x70, + 0x26, 0x6d, 0x2f, 0x70, 0x17, 0x67, 0x1e, 0x6b, 0x0a, 0x75, 0x00, 0x6d, + 0x0d, 0x5f, 0x12, 0xa4, 0xaa, 0x9a, 0xaa, 0x2a, 0x73, 0x00, 0x73, 0x16, + 0x62, 0x20, 0x6a, 0x1d, 0x51, 0x23, 0x5a, 0x23, 0x3b, 0x1e, 0x47, 0x23, + 0x39, 0x1d, 0x39, 0x1d, 0x37, 0x1c, 0x38, 0x1d, 0x20, 0x17, 0x29, 0x17, + 0x11, 0x1a, 0x18, 0x17, 0x00, 0x25, 0x09, 0x1e, 0x00, 0x0f, 0x11, 0x05, + 0x09, 0x08, 0x22, 0x02, 0x1a, 0x02, 0x39, 0x07, 0x2c, 0x02, 0x3b, 0x08, + 0x3a, 0x08, 0x3d, 0x09, 0x3b, 0x08, 0x53, 0x0e, 0x4b, 0x0e, 0x62, 0x0b, + 0x5b, 0x0e, 0x73, 0x00, 0x6a, 0x07, 0x12, 0xa4, 0xaa, 0x9a, 0xaa, 0x2a, + 0x73, 0x00, 0x73, 0x16, 0x62, 0x21, 0x6a, 0x1d, 0x51, 0x24, 0x5a, 0x24, + 0x3b, 0x1e, 0x47, 0x24, 0x38, 0x1e, 0x39, 0x1e, 0x37, 0x1d, 0x38, 0x1d, + 0x20, 0x17, 0x29, 0x17, 0x11, 0x1b, 0x18, 0x17, 0x00, 0x26, 0x09, 0x1e, + 0x00, 0x10, 0x12, 0x06, 0x0a, 0x09, 0x22, 0x02, 0x1a, 0x02, 0x39, 0x08, + 0x2c, 0x02, 0x3b, 0x08, 0x3a, 0x08, 0x3d, 0x09, 0x3b, 0x09, 0x53, 0x0f, + 0x4b, 0x0f, 0x62, 0x0b, 0x5b, 0x0f, 0x73, 0x00, 0x6a, 0x08, 0x13, 0x54, + 0xa5, 0xaa, 0xa9, 0x6a, 0x26, 0x6f, 0x62, 0x6f, 0x62, 0x89, 0x00, 0x89, + 0x00, 0x6f, 0x31, 0x44, 0x3b, 0x39, 0x38, 0x3e, 0x3e, 0x2d, 0x3e, 0x33, + 0x37, 0x1e, 0x3e, 0x23, 0x27, 0x18, 0x31, 0x18, 0x15, 0x1b, 0x1f, 0x18, + 0x00, 0x26, 0x0b, 0x1f, 0x00, 0x08, 0x17, 0x02, 0x0c, 0x04, 0x2e, 0x00, + 0x23, 0x00, 0x53, 0x0b, 0x46, 0x00, 0x61, 0x28, 0x61, 0x15, 0x5b, 0x3d, + 0x61, 0x33, 0x43, 0x56, 0x55, 0x46, 0x26, 0x6f, 0x13, 0x54, 0xa9, 0x6a, + 0x55, 0xaa, 0x65, 0x4f, 0x65, 0x8c, 0x45, 0x8c, 0x45, 0x82, 0x45, 0x5d, + 0x44, 0x4b, 0x45, 0x50, 0x42, 0x44, 0x44, 0x46, 0x3d, 0x3f, 0x40, 0x41, + 0x36, 0x3d, 0x3a, 0x3d, 0x26, 0x45, 0x2c, 0x3d, 0x20, 0x5a, 0x20, 0x4d, + 0x20, 0x8c, 0x00, 0x8c, 0x00, 0x00, 0x20, 0x00, 0x20, 0x36, 0x30, 0x29, + 0x27, 0x2d, 0x42, 0x25, 0x38, 0x25, 0x5c, 0x2f, 0x53, 0x25, 0x65, 0x4f, + 0x65, 0x3a, 0x13, 0x54, 0xa5, 0xaa, 0xa9, 0x6a, 0x1b, 0x3e, 0x3d, 0x3e, + 0x3d, 0x4d, 0x00, 0x4d, 0x00, 0x3f, 0x1c, 0x27, 0x24, 0x1f, 0x22, 0x22, + 0x26, 0x18, 0x26, 0x1b, 0x23, 0x10, 0x26, 0x13, 0x1a, 0x0e, 0x20, 0x0e, + 0x0e, 0x10, 0x15, 0x0e, 0x01, 0x16, 0x08, 0x12, 0x01, 0x05, 0x10, 0x02, + 0x08, 0x03, 0x1e, 0x00, 0x17, 0x00, 0x34, 0x06, 0x2c, 0x00, 0x3c, 0x16, + 0x3c, 0x0c, 0x39, 0x22, 0x3c, 0x1c, 0x2d, 0x2f, 0x36, 0x27, 0x1b, 0x3e, + 0x13, 0x54, 0xa5, 0xaa, 0xa9, 0x6a, 0x1b, 0x3e, 0x3d, 0x3e, 0x3d, 0x4d, + 0x00, 0x4d, 0x00, 0x3f, 0x1c, 0x27, 0x24, 0x1f, 0x22, 0x22, 0x27, 0x18, + 0x27, 0x1b, 0x23, 0x10, 0x27, 0x13, 0x1a, 0x0e, 0x20, 0x0e, 0x0f, 0x10, + 0x15, 0x0e, 0x01, 0x16, 0x08, 0x12, 0x01, 0x05, 0x10, 0x01, 0x09, 0x03, + 0x1e, 0x00, 0x17, 0x00, 0x34, 0x06, 0x2c, 0x00, 0x3c, 0x16, 0x3c, 0x0c, + 0x39, 0x22, 0x3c, 0x1c, 0x2d, 0x2f, 0x36, 0x27, 0x1b, 0x3e, 0x13, 0x54, + 0x55, 0x55, 0xaa, 0xaa, 0x59, 0x00, 0xbe, 0x00, 0xbe, 0x1a, 0x84, 0x1a, + 0x84, 0x33, 0xbb, 0x33, 0xbb, 0x4d, 0x84, 0x4d, 0x84, 0x6c, 0xc0, 0x6c, + 0xc0, 0x86, 0x59, 0x86, 0x56, 0x86, 0x58, 0x86, 0x52, 0x86, 0x53, 0x86, + 0x15, 0x75, 0x2b, 0x86, 0x00, 0x43, 0x00, 0x63, 0x15, 0x11, 0x00, 0x22, + 0x52, 0x00, 0x2b, 0x00, 0x56, 0x00, 0x53, 0x00, 0x59, 0x00, 0x58, 0x00, + 0x14, 0x54, 0xaa, 0x5a, 0xaa, 0xa9, 0x02, 0x4c, 0x20, 0x4c, 0x48, 0x36, + 0x48, 0x36, 0x3d, 0x2b, 0x47, 0x31, 0x44, 0x1c, 0x4a, 0x24, 0x4a, 0x07, + 0x44, 0x0f, 0x4a, 0x00, 0x34, 0x00, 0x3e, 0x09, 0x21, 0x00, 0x27, 0x27, + 0x1b, 0x13, 0x1b, 0x34, 0x1b, 0x34, 0x1a, 0x2f, 0x12, 0x34, 0x14, 0x24, + 0x0f, 0x2c, 0x0f, 0x15, 0x11, 0x1c, 0x0f, 0x06, 0x15, 0x0d, 0x12, 0x06, + 0x05, 0x16, 0x02, 0x0e, 0x03, 0x24, 0x00, 0x1d, 0x00, 0x42, 0x08, 0x38, + 0x00, 0x4c, 0x20, 0x4c, 0x10, 0x14, 0x54, 0x55, 0x55, 0x55, 0x55, 0x01, + 0x1a, 0x00, 0x38, 0x00, 0x38, 0x22, 0x52, 0x22, 0x52, 0x37, 0x38, 0x37, + 0x38, 0x60, 0x52, 0x60, 0x52, 0x75, 0x38, 0x75, 0x38, 0x98, 0x1a, 0x98, + 0x1a, 0x75, 0x00, 0x75, 0x00, 0x60, 0x1a, 0x60, 0x1a, 0x37, 0x00, 0x37, + 0x00, 0x22, 0x1a, 0x22, 0x1a, 0x00, 0x14, 0xa8, 0xaa, 0xaa, 0xaa, 0xaa, + 0x02, 0x40, 0x3d, 0x42, 0x2b, 0x41, 0x33, 0x43, 0x1d, 0x43, 0x23, 0x41, + 0x10, 0x43, 0x16, 0x3b, 0x0b, 0x3e, 0x0b, 0x2f, 0x13, 0x37, 0x0b, 0x1f, + 0x1b, 0x26, 0x1b, 0x17, 0x18, 0x1a, 0x1b, 0x15, 0x11, 0x15, 0x15, 0x1d, + 0x06, 0x15, 0x0b, 0x31, 0x00, 0x25, 0x00, 0x4e, 0x0f, 0x44, 0x00, 0x5a, + 0x37, 0x5a, 0x1d, 0x4b, 0x69, 0x5a, 0x56, 0x25, 0x7d, 0x3c, 0x7d, 0x0b, + 0x73, 0x15, 0x7d, 0x00, 0x58, 0x00, 0x68, 0x0b, 0x3a, 0x00, 0x46, 0x26, + 0x2e, 0x15, 0x2e, 0x35, 0x31, 0x2f, 0x2e, 0x40, 0x3d, 0x3b, 0x35, 0x14, + 0x54, 0x55, 0x55, 0x55, 0x55, 0x01, 0x00, 0x1b, 0x47, 0x1b, 0x5e, 0x00, + 0x6b, 0x0b, 0x5e, 0x1b, 0x73, 0x1b, 0x73, 0x30, 0x4e, 0x30, 0x3e, 0x44, + 0x73, 0x44, 0x73, 0x59, 0x2c, 0x59, 0x16, 0x75, 0x08, 0x69, 0x15, 0x59, + 0x00, 0x59, 0x00, 0x44, 0x26, 0x44, 0x36, 0x30, 0x00, 0x30, 0x00, 0x1b, + 0x14, 0x94, 0x56, 0x55, 0x55, 0xa5, 0x01, 0x4e, 0x00, 0x4e, 0x15, 0x3c, + 0x15, 0x33, 0x18, 0x35, 0x15, 0x30, 0x20, 0x30, 0x1a, 0x30, 0x27, 0x75, + 0x27, 0x75, 0x8c, 0x55, 0x8c, 0x55, 0x3e, 0x30, 0x3e, 0x30, 0x8c, 0x10, + 0x8c, 0x10, 0x3e, 0x00, 0x3e, 0x00, 0x27, 0x10, 0x27, 0x10, 0x20, 0x19, + 0x08, 0x10, 0x10, 0x35, 0x00, 0x22, 0x00, 0x4e, 0x00, 0x14, 0x54, 0xa5, + 0x55, 0x55, 0x95, 0x02, 0x36, 0x00, 0x76, 0x00, 0x76, 0x8c, 0x55, 0x8c, + 0x55, 0x15, 0x3c, 0x15, 0x33, 0x18, 0x36, 0x15, 0x30, 0x20, 0x30, 0x1a, + 0x30, 0x27, 0x49, 0x27, 0x49, 0x3e, 0x30, 0x3e, 0x30, 0x8c, 0x10, 0x8c, + 0x10, 0x3e, 0x00, 0x3e, 0x00, 0x27, 0x10, 0x27, 0x10, 0x20, 0x19, 0x08, + 0x10, 0x10, 0x36, 0x00, 0x22, 0x00, 0x15, 0xa8, 0xaa, 0x6a, 0x55, 0x55, + 0x05, 0x5b, 0x29, 0x6a, 0x41, 0x65, 0x35, 0x6f, 0x5a, 0x6f, 0x4c, 0x60, + 0x81, 0x6f, 0x72, 0x37, 0x8f, 0x51, 0x8f, 0x0f, 0x81, 0x1d, 0x8f, 0x00, + 0x5a, 0x00, 0x72, 0x0d, 0x39, 0x00, 0x45, 0x33, 0x2d, 0x1b, 0x2d, 0x3a, + 0x2e, 0x37, 0x2d, 0x41, 0x2f, 0x3e, 0x2e, 0x30, 0x1c, 0x0f, 0x27, 0x0b, + 0x1b, 0x27, 0x12, 0x16, 0x00, 0x36, 0x00, 0x40, 0x0a, 0x61, 0x00, 0x65, + 0x0c, 0x48, 0x14, 0x5b, 0x29, 0x15, 0x54, 0x55, 0x55, 0xa5, 0xaa, 0x0a, + 0x4c, 0x36, 0x4c, 0x1d, 0x2e, 0x1d, 0x2e, 0x0a, 0x4c, 0x0a, 0x4c, 0x00, + 0x6c, 0x00, 0x6c, 0x0a, 0x7a, 0x0a, 0x7a, 0x1d, 0x6c, 0x1d, 0x6c, 0x8c, + 0x4c, 0x8c, 0x4c, 0x7d, 0x3d, 0x8a, 0x45, 0x86, 0x2b, 0x8f, 0x35, 0x8f, + 0x0c, 0x80, 0x18, 0x8f, 0x00, 0x5a, 0x00, 0x71, 0x0c, 0x34, 0x00, 0x42, + 0x2b, 0x25, 0x18, 0x25, 0x3d, 0x29, 0x35, 0x25, 0x4c, 0x36, 0x45, 0x2d, + 0x16, 0x54, 0xa9, 0xaa, 0xa6, 0xaa, 0x1a, 0x05, 0x00, 0x5b, 0x00, 0x5b, + 0x19, 0x21, 0x19, 0x21, 0x2e, 0x29, 0x2c, 0x25, 0x2d, 0x31, 0x2c, 0x2d, + 0x2c, 0x57, 0x38, 0x4a, 0x2c, 0x65, 0x5a, 0x65, 0x44, 0x56, 0x7c, 0x65, + 0x70, 0x2d, 0x89, 0x47, 0x89, 0x16, 0x86, 0x21, 0x89, 0x00, 0x80, 0x0b, + 0x84, 0x00, 0x64, 0x15, 0x6e, 0x0b, 0x6b, 0x27, 0x71, 0x1f, 0x71, 0x3b, + 0x6b, 0x34, 0x71, 0x42, 0x5a, 0x42, 0x65, 0x3b, 0x49, 0x42, 0x50, 0x27, + 0x43, 0x34, 0x43, 0x17, 0x45, 0x20, 0x43, 0x05, 0x4b, 0x0f, 0x47, 0x05, + 0x00, 0x16, 0x94, 0xa6, 0xaa, 0xa9, 0x6a, 0x1a, 0x33, 0x5c, 0x13, 0x5c, + 0x13, 0x57, 0x16, 0x4a, 0x13, 0x50, 0x22, 0x3c, 0x19, 0x44, 0x28, 0x36, + 0x2f, 0x2e, 0x2d, 0x32, 0x32, 0x25, 0x32, 0x29, 0x2d, 0x1c, 0x32, 0x1f, + 0x21, 0x18, 0x29, 0x18, 0x12, 0x1b, 0x1a, 0x18, 0x00, 0x24, 0x09, 0x1e, + 0x00, 0x08, 0x14, 0x02, 0x0b, 0x04, 0x25, 0x00, 0x1d, 0x00, 0x47, 0x09, + 0x3b, 0x00, 0x52, 0x23, 0x52, 0x12, 0x4f, 0x33, 0x52, 0x2c, 0x43, 0x42, + 0x4b, 0x3a, 0x3d, 0x47, 0x35, 0x50, 0x37, 0x4d, 0x33, 0x58, 0x33, 0x54, + 0x33, 0x5c, 0x16, 0x94, 0xa6, 0xaa, 0xa9, 0x6a, 0x1a, 0x1f, 0x00, 0x40, + 0x00, 0x40, 0x05, 0x3d, 0x12, 0x40, 0x0c, 0x30, 0x20, 0x3a, 0x17, 0x2a, + 0x25, 0x23, 0x2e, 0x25, 0x2a, 0x20, 0x36, 0x20, 0x32, 0x25, 0x40, 0x20, + 0x3d, 0x31, 0x44, 0x29, 0x44, 0x41, 0x41, 0x38, 0x44, 0x52, 0x38, 0x49, + 0x3e, 0x52, 0x54, 0x3e, 0x5a, 0x47, 0x58, 0x2d, 0x5c, 0x35, 0x5c, 0x0c, + 0x53, 0x17, 0x5c, 0x00, 0x39, 0x00, 0x4a, 0x04, 0x29, 0x00, 0x30, 0x0f, + 0x1a, 0x07, 0x22, 0x15, 0x15, 0x1d, 0x0c, 0x1b, 0x0f, 0x1f, 0x04, 0x1f, + 0x08, 0x1f, 0x00, 0x16, 0xa4, 0x5a, 0xaa, 0xa9, 0x96, 0x2a, 0x1f, 0x14, + 0x1a, 0x11, 0x19, 0x10, 0x1a, 0x11, 0x13, 0x0e, 0x15, 0x0e, 0x0e, 0x10, + 0x0f, 0x0e, 0x0c, 0x19, 0x0c, 0x13, 0x0c, 0x19, 0x00, 0x19, 0x04, 0x06, + 0x00, 0x0d, 0x11, 0x00, 0x09, 0x00, 0x18, 0x01, 0x14, 0x00, 0x1f, 0x05, + 0x1b, 0x02, 0x24, 0x09, 0x28, 0x0b, 0x26, 0x0a, 0x2b, 0x0b, 0x29, 0x0b, + 0x30, 0x09, 0x2e, 0x0b, 0x32, 0x01, 0x32, 0x06, 0x32, 0x00, 0x3e, 0x00, + 0x39, 0x13, 0x3e, 0x0c, 0x2d, 0x19, 0x35, 0x19, 0x26, 0x18, 0x29, 0x19, + 0x1f, 0x14, 0x23, 0x17, 0x16, 0xa4, 0x5a, 0xaa, 0xa9, 0x96, 0x2a, 0x20, + 0x14, 0x1b, 0x11, 0x1a, 0x10, 0x1a, 0x11, 0x13, 0x0e, 0x15, 0x0e, 0x0e, + 0x10, 0x10, 0x0e, 0x0d, 0x19, 0x0d, 0x13, 0x0d, 0x19, 0x00, 0x19, 0x05, + 0x06, 0x00, 0x0d, 0x12, 0x00, 0x09, 0x00, 0x18, 0x01, 0x15, 0x00, 0x1f, + 0x05, 0x1b, 0x02, 0x25, 0x09, 0x28, 0x0b, 0x27, 0x0a, 0x2b, 0x0b, 0x2a, + 0x0b, 0x30, 0x09, 0x2f, 0x0b, 0x32, 0x01, 0x32, 0x06, 0x32, 0x00, 0x3f, + 0x00, 0x3a, 0x13, 0x3f, 0x0c, 0x2d, 0x19, 0x35, 0x19, 0x27, 0x18, 0x2a, + 0x19, 0x20, 0x14, 0x24, 0x17, 0x16, 0xa4, 0x5a, 0xaa, 0xa9, 0x96, 0x2a, + 0x20, 0x14, 0x1b, 0x11, 0x1a, 0x10, 0x1a, 0x11, 0x13, 0x0e, 0x16, 0x0e, + 0x0e, 0x10, 0x10, 0x0e, 0x0d, 0x19, 0x0d, 0x13, 0x0d, 0x19, 0x00, 0x19, + 0x05, 0x06, 0x00, 0x0d, 0x12, 0x00, 0x09, 0x00, 0x18, 0x01, 0x15, 0x00, + 0x1f, 0x05, 0x1c, 0x02, 0x25, 0x09, 0x28, 0x0b, 0x27, 0x0a, 0x2b, 0x0b, + 0x2a, 0x0b, 0x30, 0x09, 0x2f, 0x0b, 0x32, 0x01, 0x32, 0x06, 0x32, 0x00, + 0x3f, 0x00, 0x3a, 0x13, 0x3f, 0x0c, 0x2d, 0x19, 0x35, 0x19, 0x27, 0x18, + 0x2a, 0x19, 0x20, 0x14, 0x24, 0x17, 0x16, 0xa4, 0x5a, 0xaa, 0xa9, 0x96, + 0x2a, 0x1f, 0x14, 0x1b, 0x11, 0x1a, 0x10, 0x1a, 0x11, 0x13, 0x0e, 0x15, + 0x0e, 0x0e, 0x10, 0x10, 0x0e, 0x0c, 0x19, 0x0c, 0x13, 0x0c, 0x19, 0x00, + 0x19, 0x05, 0x06, 0x00, 0x0d, 0x12, 0x00, 0x09, 0x00, 0x18, 0x01, 0x15, + 0x00, 0x1f, 0x05, 0x1b, 0x02, 0x25, 0x09, 0x28, 0x0b, 0x27, 0x0a, 0x2b, + 0x0b, 0x2a, 0x0b, 0x30, 0x09, 0x2e, 0x0b, 0x32, 0x01, 0x32, 0x06, 0x32, + 0x00, 0x3f, 0x00, 0x3a, 0x13, 0x3f, 0x0c, 0x2d, 0x19, 0x35, 0x19, 0x27, + 0x18, 0x2a, 0x19, 0x1f, 0x14, 0x24, 0x17, 0x17, 0xa4, 0xa5, 0x69, 0x95, + 0x6a, 0xa5, 0x59, 0x1f, 0x59, 0x3a, 0x4c, 0x33, 0x52, 0x35, 0x3f, 0x31, + 0x45, 0x31, 0x3e, 0x31, 0x3e, 0x6c, 0x4d, 0x6a, 0x46, 0x6c, 0x59, 0x64, + 0x54, 0x68, 0x59, 0x7e, 0x4b, 0x82, 0x51, 0x81, 0x3f, 0x84, 0x44, 0x84, + 0x3e, 0x84, 0x3e, 0x9d, 0x2f, 0x9d, 0x2f, 0x83, 0x0c, 0x72, 0x18, 0x80, + 0x00, 0x4d, 0x00, 0x64, 0x0c, 0x2a, 0x00, 0x37, 0x2f, 0x1a, 0x18, 0x1d, + 0x2f, 0x00, 0x3e, 0x00, 0x3e, 0x1a, 0x4b, 0x1c, 0x45, 0x1a, 0x59, 0x1f, + 0x52, 0x1d, 0x17, 0x94, 0x6a, 0xaa, 0xaa, 0xaa, 0xaa, 0xb9, 0x34, 0xb9, + 0x3d, 0x6d, 0x3d, 0x76, 0x4e, 0x6f, 0x49, 0x89, 0x54, 0x7d, 0x54, 0x9e, + 0x51, 0x93, 0x54, 0xb4, 0x48, 0xa9, 0x4e, 0xb4, 0x61, 0x9d, 0x67, 0xa9, + 0x65, 0x86, 0x6a, 0x92, 0x6a, 0x6e, 0x66, 0x77, 0x6a, 0x5e, 0x5a, 0x64, + 0x62, 0x4d, 0x66, 0x56, 0x62, 0x37, 0x6a, 0x43, 0x6a, 0x0f, 0x5c, 0x1d, + 0x6a, 0x00, 0x35, 0x00, 0x4d, 0x0f, 0x0e, 0x00, 0x1c, 0x37, 0x00, 0x1d, + 0x00, 0x4d, 0x03, 0x44, 0x00, 0x5d, 0x0f, 0x56, 0x07, 0x6e, 0x03, 0x65, + 0x07, 0x83, 0x00, 0x77, 0x00, 0xaa, 0x0e, 0x9c, 0x00, 0xb9, 0x34, 0xb9, + 0x1c, 0x18, 0xa4, 0x5a, 0x55, 0x55, 0x55, 0xa9, 0x02, 0x65, 0x05, 0x65, + 0x1f, 0x58, 0x1a, 0x5e, 0x1b, 0x4a, 0x18, 0x51, 0x18, 0x3a, 0x1e, 0x3f, + 0x18, 0x35, 0x2f, 0x35, 0x23, 0x35, 0x3e, 0x57, 0x3e, 0x57, 0x54, 0x35, + 0x54, 0x35, 0x71, 0x66, 0x71, 0x66, 0x89, 0x00, 0x89, 0x00, 0x71, 0x14, + 0x71, 0x14, 0x54, 0x03, 0x54, 0x03, 0x3e, 0x14, 0x3e, 0x14, 0x2f, 0x20, + 0x0b, 0x14, 0x17, 0x44, 0x00, 0x2b, 0x00, 0x54, 0x02, 0x4c, 0x00, 0x65, + 0x05, 0x5d, 0x03, 0x18, 0x54, 0xa9, 0xaa, 0x56, 0xa9, 0xaa, 0x02, 0x69, + 0x71, 0x84, 0x71, 0x84, 0x88, 0x4d, 0x88, 0x4d, 0x6e, 0x5e, 0x5a, 0x58, + 0x66, 0x64, 0x40, 0x64, 0x4e, 0x5b, 0x23, 0x64, 0x2d, 0x42, 0x18, 0x52, + 0x18, 0x29, 0x23, 0x32, 0x18, 0x20, 0x40, 0x20, 0x2d, 0x25, 0x5a, 0x20, + 0x4e, 0x37, 0x6e, 0x2b, 0x66, 0x37, 0x88, 0x00, 0x88, 0x00, 0x71, 0x1a, + 0x71, 0x09, 0x5a, 0x0f, 0x66, 0x04, 0x3e, 0x04, 0x4d, 0x15, 0x11, 0x04, + 0x22, 0x42, 0x00, 0x26, 0x00, 0x6f, 0x11, 0x5e, 0x00, 0x80, 0x3e, 0x80, + 0x22, 0x7a, 0x5a, 0x80, 0x4d, 0x69, 0x71, 0x75, 0x66, 0x19, 0x54, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x05, 0x78, 0x61, 0x4f, 0x61, 0x4f, 0x86, 0x2d, + 0x86, 0x2d, 0x61, 0x04, 0x61, 0x04, 0x4f, 0x2d, 0x4f, 0x2d, 0x49, 0x28, + 0x41, 0x04, 0x41, 0x04, 0x30, 0x1e, 0x30, 0x00, 0x00, 0x24, 0x00, 0x3e, + 0x29, 0x58, 0x00, 0x7c, 0x00, 0x5e, 0x30, 0x78, 0x30, 0x78, 0x41, 0x53, + 0x41, 0x4f, 0x49, 0x4f, 0x4f, 0x78, 0x4f, 0x78, 0x61, 0x19, 0x54, 0xaa, + 0x95, 0x6a, 0xaa, 0xaa, 0x05, 0x00, 0x8b, 0x00, 0x00, 0x20, 0x00, 0x20, + 0x3b, 0x25, 0x4a, 0x20, 0x45, 0x33, 0x4f, 0x29, 0x4f, 0x40, 0x4a, 0x3c, + 0x4f, 0x45, 0x3b, 0x45, 0x45, 0x45, 0x00, 0x65, 0x00, 0x65, 0x44, 0x67, + 0x4c, 0x65, 0x4a, 0x6c, 0x4f, 0x68, 0x4f, 0x6f, 0x4f, 0x6d, 0x4f, 0x72, + 0x4d, 0x70, 0x4e, 0x72, 0x63, 0x69, 0x67, 0x6d, 0x66, 0x61, 0x68, 0x65, + 0x68, 0x54, 0x64, 0x59, 0x68, 0x4c, 0x59, 0x4f, 0x61, 0x41, 0x64, 0x47, + 0x60, 0x33, 0x68, 0x3b, 0x68, 0x28, 0x65, 0x2d, 0x68, 0x20, 0x5f, 0x23, + 0x63, 0x20, 0x8b, 0x00, 0x8b, 0x19, 0xa4, 0x5a, 0xaa, 0x9a, 0x6a, 0xaa, + 0x0a, 0x1f, 0x14, 0x1a, 0x10, 0x19, 0x10, 0x1a, 0x10, 0x13, 0x0d, 0x15, + 0x0d, 0x0e, 0x10, 0x10, 0x0d, 0x0c, 0x17, 0x0c, 0x13, 0x0c, 0x18, 0x00, + 0x18, 0x00, 0x17, 0x00, 0x17, 0x00, 0x15, 0x00, 0x16, 0x05, 0x06, 0x00, + 0x0c, 0x11, 0x00, 0x0a, 0x00, 0x18, 0x01, 0x15, 0x00, 0x1f, 0x04, 0x1b, + 0x02, 0x24, 0x08, 0x28, 0x0a, 0x26, 0x09, 0x2b, 0x0b, 0x2a, 0x0b, 0x30, + 0x08, 0x2e, 0x0b, 0x32, 0x00, 0x32, 0x05, 0x3e, 0x00, 0x3e, 0x01, 0x3e, + 0x01, 0x3e, 0x03, 0x3e, 0x02, 0x39, 0x12, 0x3e, 0x0c, 0x2d, 0x18, 0x35, + 0x18, 0x26, 0x17, 0x29, 0x18, 0x1f, 0x14, 0x23, 0x16, 0x1c, 0x54, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x01, 0x45, 0x00, 0x3d, 0x22, 0x55, 0x22, + 0x5d, 0x00, 0x71, 0x00, 0x68, 0x22, 0x81, 0x22, 0x81, 0x36, 0x64, 0x36, + 0x5d, 0x4e, 0x77, 0x4e, 0x77, 0x61, 0x59, 0x61, 0x50, 0x84, 0x3c, 0x84, + 0x45, 0x61, 0x2d, 0x61, 0x25, 0x84, 0x10, 0x84, 0x19, 0x61, 0x00, 0x61, + 0x00, 0x4e, 0x1d, 0x4e, 0x24, 0x36, 0x0a, 0x36, 0x0a, 0x22, 0x29, 0x22, + 0x31, 0x00, 0x45, 0x00, 0x1c, 0x94, 0xa6, 0xa5, 0x5a, 0x69, 0x5a, 0xaa, + 0x01, 0x39, 0xa7, 0x2b, 0xa7, 0x2a, 0x8c, 0x15, 0x89, 0x1f, 0x8b, 0x00, + 0x84, 0x0a, 0x87, 0x00, 0x6c, 0x15, 0x74, 0x0b, 0x71, 0x2b, 0x77, 0x20, + 0x77, 0x2b, 0x5b, 0x28, 0x5b, 0x09, 0x4f, 0x12, 0x57, 0x00, 0x38, 0x00, + 0x47, 0x0b, 0x1f, 0x00, 0x28, 0x2a, 0x15, 0x16, 0x16, 0x2b, 0x00, 0x39, + 0x00, 0x39, 0x14, 0x4b, 0x17, 0x42, 0x15, 0x5d, 0x1b, 0x54, 0x18, 0x5d, + 0x31, 0x4b, 0x2c, 0x54, 0x2e, 0x39, 0x29, 0x42, 0x29, 0x39, 0x43, 0x3c, + 0x43, 0x5c, 0x4f, 0x53, 0x47, 0x65, 0x68, 0x65, 0x58, 0x5a, 0x82, 0x65, + 0x79, 0x39, 0x8c, 0x4f, 0x8a, 0x39, 0xa7, 0x1c, 0xa4, 0x69, 0xa5, 0xaa, + 0xaa, 0x9a, 0xaa, 0x02, 0x3d, 0x30, 0x62, 0x58, 0x69, 0x4a, 0x66, 0x52, + 0x6c, 0x38, 0x6b, 0x42, 0x88, 0x38, 0x81, 0x56, 0x86, 0x49, 0x73, 0x6c, + 0x7c, 0x62, 0x8e, 0x89, 0x68, 0x89, 0x5f, 0x7f, 0x4b, 0x88, 0x55, 0x85, + 0x35, 0x8c, 0x41, 0x8c, 0x0f, 0x7f, 0x1d, 0x8c, 0x00, 0x5f, 0x00, 0x73, + 0x06, 0x48, 0x00, 0x52, 0x1b, 0x34, 0x0d, 0x3e, 0x16, 0x2b, 0x18, 0x2f, + 0x14, 0x21, 0x14, 0x26, 0x1f, 0x09, 0x14, 0x12, 0x3e, 0x00, 0x2b, 0x00, + 0x4f, 0x02, 0x46, 0x00, 0x61, 0x05, 0x58, 0x03, 0x61, 0x1e, 0x51, 0x18, + 0x59, 0x1a, 0x43, 0x16, 0x4a, 0x16, 0x38, 0x19, 0x3c, 0x16, 0x34, 0x20, + 0x34, 0x1b, 0x36, 0x27, 0x34, 0x23, 0x3d, 0x30, 0x38, 0x2b, 0x1c, 0x54, + 0xaa, 0x95, 0x6a, 0xa5, 0x5a, 0xa9, 0x02, 0x20, 0x56, 0x0e, 0x68, 0x00, + 0x5b, 0x13, 0x48, 0x0f, 0x3f, 0x10, 0x44, 0x0e, 0x34, 0x0e, 0x3a, 0x0f, + 0x2a, 0x0e, 0x2f, 0x13, 0x21, 0x10, 0x25, 0x00, 0x0e, 0x0e, 0x01, 0x21, + 0x13, 0x2a, 0x0f, 0x25, 0x10, 0x34, 0x0e, 0x2f, 0x0e, 0x3e, 0x0f, 0x39, + 0x0e, 0x48, 0x13, 0x43, 0x10, 0x5a, 0x00, 0x68, 0x0e, 0x55, 0x21, 0x59, + 0x2a, 0x58, 0x26, 0x5b, 0x34, 0x5b, 0x2f, 0x59, 0x3f, 0x5b, 0x3a, 0x55, + 0x48, 0x58, 0x43, 0x68, 0x5a, 0x5a, 0x68, 0x47, 0x55, 0x3e, 0x5a, 0x43, + 0x58, 0x34, 0x5b, 0x3a, 0x5b, 0x2a, 0x5a, 0x2f, 0x5b, 0x20, 0x56, 0x25, + 0x58, 0x1c, 0xa4, 0x5a, 0x95, 0x6a, 0xaa, 0x55, 0xa9, 0x02, 0x77, 0x04, + 0x77, 0x1a, 0x70, 0x17, 0x73, 0x18, 0x68, 0x15, 0x6c, 0x15, 0x5b, 0x1b, + 0x60, 0x15, 0x55, 0x2c, 0x57, 0x20, 0x52, 0x3b, 0x6b, 0x3b, 0x6b, 0x51, + 0x4d, 0x51, 0x41, 0x8d, 0x33, 0xa9, 0x3e, 0xa0, 0x18, 0xb2, 0x29, 0xb2, + 0x0c, 0xb1, 0x12, 0xb2, 0x00, 0xaf, 0x06, 0xb0, 0x00, 0x98, 0x08, 0x9c, + 0x04, 0x9a, 0x0f, 0x9d, 0x0c, 0x9d, 0x1c, 0x98, 0x17, 0x9d, 0x23, 0x86, + 0x20, 0x92, 0x2d, 0x51, 0x18, 0x51, 0x18, 0x3b, 0x32, 0x3b, 0x36, 0x25, + 0x44, 0x09, 0x3a, 0x12, 0x60, 0x00, 0x4e, 0x00, 0x6b, 0x01, 0x66, 0x00, + 0x77, 0x04, 0x71, 0x02, 0x1c, 0xa8, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0x02, 0x1c, 0xa2, 0x27, 0x66, 0x25, 0xa2, 0x27, 0x58, 0x27, 0x5d, 0x33, + 0x15, 0x29, 0x29, 0x52, 0x00, 0x3d, 0x00, 0x61, 0x05, 0x5c, 0x00, 0x67, + 0x11, 0x67, 0x0a, 0x64, 0x1a, 0x67, 0x17, 0x5a, 0x1e, 0x60, 0x1e, 0x51, + 0x1b, 0x54, 0x1e, 0x4e, 0x10, 0x4e, 0x17, 0x4e, 0x0c, 0x4e, 0x0d, 0x4c, + 0x0b, 0x4d, 0x0b, 0x40, 0x47, 0x42, 0x0b, 0x40, 0x4f, 0x40, 0x4c, 0x3d, + 0x7a, 0x3f, 0x6d, 0x38, 0x90, 0x3c, 0x87, 0x2a, 0xa6, 0x33, 0x9f, 0x15, + 0xad, 0x21, 0xad, 0x06, 0xa9, 0x0c, 0xad, 0x00, 0x9c, 0x00, 0xa4, 0x04, + 0x93, 0x00, 0x96, 0x0e, 0x8f, 0x08, 0x8f, 0x16, 0x93, 0x13, 0x8f, 0x19, + 0x9c, 0x19, 0x96, 0x19, 0x9e, 0x19, 0x9d, 0x19, 0x9e, 0x19, 0x9e, 0x1a, + 0xa1, 0x19, 0xa1, 0x1c, 0xa2, 0x1a, 0xa2, 0x1d, 0xa8, 0x6a, 0xaa, 0x5a, + 0xa9, 0x6a, 0xaa, 0x0a, 0x49, 0x41, 0x5e, 0x4d, 0x57, 0x44, 0x65, 0x63, + 0x65, 0x55, 0x56, 0x81, 0x65, 0x77, 0x29, 0x8c, 0x47, 0x8c, 0x15, 0x8a, + 0x1f, 0x8c, 0x00, 0x85, 0x0a, 0x88, 0x00, 0x6a, 0x13, 0x72, 0x0a, 0x6f, + 0x26, 0x74, 0x1d, 0x74, 0x3b, 0x6f, 0x34, 0x74, 0x43, 0x62, 0x43, 0x6a, + 0x3b, 0x54, 0x43, 0x58, 0x25, 0x4f, 0x34, 0x4f, 0x17, 0x4f, 0x17, 0x39, + 0x26, 0x39, 0x39, 0x35, 0x33, 0x39, 0x3f, 0x28, 0x3f, 0x30, 0x39, 0x1c, + 0x3f, 0x20, 0x28, 0x18, 0x33, 0x18, 0x17, 0x1a, 0x1f, 0x18, 0x06, 0x1f, + 0x0e, 0x1c, 0x06, 0x06, 0x1a, 0x02, 0x10, 0x03, 0x2e, 0x00, 0x24, 0x00, + 0x55, 0x09, 0x48, 0x00, 0x62, 0x23, 0x62, 0x11, 0x5c, 0x36, 0x62, 0x2e, + 0x49, 0x41, 0x56, 0x3d, 0x1d, 0xa8, 0x56, 0xaa, 0x5a, 0xa9, 0x56, 0xa5, + 0x0a, 0x5e, 0x13, 0x6c, 0x05, 0x64, 0x0a, 0x7f, 0x00, 0x74, 0x00, 0x99, + 0x0a, 0x90, 0x00, 0xa2, 0x2a, 0xa2, 0x15, 0xa2, 0x67, 0x82, 0x67, 0x82, + 0x32, 0x82, 0x30, 0x82, 0x31, 0x82, 0x2c, 0x82, 0x2f, 0x7f, 0x1d, 0x82, + 0x22, 0x75, 0x18, 0x7c, 0x18, 0x66, 0x20, 0x6b, 0x18, 0x61, 0x35, 0x61, + 0x27, 0x61, 0x67, 0x41, 0x67, 0x41, 0x32, 0x3e, 0x1d, 0x41, 0x22, 0x34, + 0x18, 0x3b, 0x18, 0x25, 0x20, 0x2a, 0x18, 0x20, 0x35, 0x20, 0x27, 0x20, + 0x67, 0x00, 0x67, 0x00, 0x02, 0x20, 0x02, 0x20, 0x11, 0x2e, 0x04, 0x26, + 0x08, 0x3f, 0x00, 0x36, 0x00, 0x51, 0x05, 0x49, 0x00, 0x5e, 0x13, 0x59, + 0x0a, 0x1d, 0x94, 0xa6, 0x95, 0xa6, 0x95, 0xa6, 0x9a, 0x06, 0x55, 0x96, + 0x55, 0xaa, 0x42, 0xaa, 0x25, 0xa2, 0x2e, 0xaa, 0x1c, 0x89, 0x1c, 0x9a, + 0x1c, 0x78, 0x17, 0x65, 0x1c, 0x6a, 0x05, 0x60, 0x12, 0x60, 0x00, 0x60, + 0x00, 0x4b, 0x05, 0x4b, 0x17, 0x46, 0x12, 0x4b, 0x1c, 0x34, 0x1c, 0x41, + 0x1c, 0x21, 0x25, 0x08, 0x1c, 0x10, 0x42, 0x00, 0x2e, 0x00, 0x55, 0x00, + 0x55, 0x14, 0x4f, 0x14, 0x3e, 0x18, 0x42, 0x14, 0x3b, 0x29, 0x3b, 0x1c, + 0x3b, 0x38, 0x36, 0x4c, 0x3b, 0x46, 0x29, 0x55, 0x32, 0x53, 0x36, 0x5e, + 0x33, 0x57, 0x3b, 0x72, 0x3b, 0x64, 0x3b, 0x81, 0x3e, 0x92, 0x3b, 0x8e, + 0x4f, 0x96, 0x42, 0x96, 0x55, 0x96, 0x1d, 0xa4, 0xa9, 0xa6, 0x95, 0xa6, + 0x95, 0xa6, 0x05, 0x00, 0x96, 0x06, 0x96, 0x17, 0x92, 0x13, 0x96, 0x1b, + 0x81, 0x1b, 0x8e, 0x1b, 0x72, 0x1f, 0x5e, 0x1b, 0x64, 0x2d, 0x55, 0x23, + 0x57, 0x1f, 0x4c, 0x23, 0x53, 0x1b, 0x38, 0x1b, 0x46, 0x1b, 0x29, 0x17, + 0x18, 0x1b, 0x1c, 0x06, 0x14, 0x13, 0x14, 0x00, 0x14, 0x00, 0x00, 0x14, + 0x00, 0x30, 0x08, 0x27, 0x00, 0x39, 0x21, 0x39, 0x10, 0x39, 0x34, 0x3e, + 0x46, 0x39, 0x41, 0x50, 0x4b, 0x43, 0x4b, 0x55, 0x4b, 0x55, 0x60, 0x50, + 0x60, 0x3e, 0x65, 0x43, 0x60, 0x39, 0x78, 0x39, 0x6a, 0x39, 0x89, 0x30, + 0xa2, 0x39, 0x9a, 0x14, 0xaa, 0x27, 0xaa, 0x00, 0xaa, 0x00, 0x96, 0x1d, + 0xa8, 0x6a, 0xaa, 0x5a, 0xa9, 0x6a, 0xaa, 0x0a, 0x2d, 0x24, 0x3a, 0x2b, + 0x35, 0x26, 0x3f, 0x37, 0x3f, 0x30, 0x36, 0x48, 0x3f, 0x43, 0x1b, 0x4e, + 0x2d, 0x4e, 0x0d, 0x4d, 0x13, 0x4e, 0x00, 0x4a, 0x06, 0x4c, 0x00, 0x3b, + 0x0c, 0x3f, 0x06, 0x3e, 0x17, 0x41, 0x11, 0x41, 0x24, 0x3e, 0x1f, 0x41, + 0x29, 0x36, 0x29, 0x3b, 0x24, 0x2e, 0x29, 0x30, 0x15, 0x2b, 0x1f, 0x2b, + 0x0e, 0x2b, 0x0e, 0x1e, 0x16, 0x1e, 0x23, 0x1c, 0x1f, 0x1e, 0x27, 0x16, + 0x27, 0x1a, 0x23, 0x10, 0x27, 0x12, 0x18, 0x0e, 0x20, 0x0e, 0x0e, 0x0f, + 0x14, 0x0e, 0x02, 0x12, 0x09, 0x10, 0x02, 0x03, 0x0f, 0x01, 0x08, 0x02, + 0x1e, 0x00, 0x16, 0x00, 0x35, 0x05, 0x2d, 0x00, 0x3d, 0x14, 0x3d, 0x0a, + 0x39, 0x1e, 0x3d, 0x1a, 0x2d, 0x24, 0x35, 0x23, 0x1d, 0xa8, 0x6a, 0xaa, + 0x5a, 0xa9, 0x6a, 0xaa, 0x0a, 0x2d, 0x24, 0x3a, 0x2b, 0x35, 0x26, 0x3f, + 0x37, 0x3f, 0x30, 0x36, 0x48, 0x3f, 0x43, 0x1b, 0x4e, 0x2d, 0x4e, 0x0d, + 0x4d, 0x13, 0x4e, 0x00, 0x4a, 0x06, 0x4c, 0x00, 0x3b, 0x0c, 0x3f, 0x06, + 0x3e, 0x17, 0x41, 0x11, 0x41, 0x24, 0x3e, 0x1f, 0x41, 0x29, 0x36, 0x29, + 0x3b, 0x24, 0x2e, 0x29, 0x30, 0x15, 0x2b, 0x1f, 0x2b, 0x0e, 0x2b, 0x0e, + 0x1e, 0x16, 0x1e, 0x23, 0x1c, 0x1f, 0x1e, 0x27, 0x16, 0x27, 0x1a, 0x23, + 0x10, 0x27, 0x12, 0x19, 0x0e, 0x20, 0x0e, 0x0e, 0x0f, 0x14, 0x0e, 0x02, + 0x12, 0x09, 0x10, 0x02, 0x03, 0x0f, 0x01, 0x08, 0x02, 0x1e, 0x00, 0x16, + 0x00, 0x35, 0x05, 0x2d, 0x00, 0x3d, 0x14, 0x3d, 0x0a, 0x39, 0x1e, 0x3d, + 0x1a, 0x2d, 0x24, 0x35, 0x23, 0x20, 0xa8, 0xaa, 0x96, 0x6a, 0xaa, 0xaa, + 0x5a, 0xaa, 0x01, 0x09, 0x05, 0x1d, 0x01, 0x14, 0x02, 0x30, 0x00, 0x28, + 0x00, 0x47, 0x03, 0x3e, 0x00, 0x58, 0x0e, 0x51, 0x07, 0x68, 0x03, 0x5f, + 0x07, 0x7c, 0x00, 0x71, 0x00, 0xa2, 0x0e, 0x94, 0x00, 0xb0, 0x34, 0xb0, + 0x1c, 0xb0, 0x3d, 0x65, 0x3d, 0x6d, 0x4e, 0x66, 0x49, 0x81, 0x54, 0x74, + 0x54, 0x96, 0x51, 0x8b, 0x54, 0xab, 0x48, 0xa0, 0x4e, 0xab, 0x61, 0x95, + 0x67, 0xa0, 0x65, 0x7e, 0x6a, 0x89, 0x6a, 0x62, 0x65, 0x6e, 0x6a, 0x4f, + 0x57, 0x56, 0x60, 0x3c, 0x65, 0x46, 0x61, 0x26, 0x6a, 0x32, 0x6a, 0x0a, + 0x61, 0x14, 0x6a, 0x00, 0x49, 0x00, 0x58, 0x0c, 0x2f, 0x00, 0x37, 0x32, + 0x26, 0x18, 0x26, 0x45, 0x26, 0x45, 0x24, 0x3f, 0x19, 0x45, 0x1c, 0x2d, + 0x15, 0x39, 0x15, 0x19, 0x17, 0x22, 0x15, 0x09, 0x1d, 0x10, 0x19, 0x09, + 0x05, 0x22, 0xa4, 0xaa, 0xaa, 0xaa, 0x9a, 0xaa, 0xaa, 0xaa, 0x2a, 0x4e, + 0x05, 0x4e, 0x1a, 0x3e, 0x15, 0x45, 0x16, 0x32, 0x13, 0x37, 0x13, 0x28, + 0x15, 0x2b, 0x13, 0x25, 0x1c, 0x25, 0x17, 0x35, 0x29, 0x25, 0x22, 0x39, + 0x2a, 0x38, 0x2a, 0x53, 0x3a, 0x4c, 0x32, 0x5a, 0x4d, 0x5a, 0x42, 0x55, + 0x5f, 0x5a, 0x57, 0x45, 0x6a, 0x50, 0x66, 0x50, 0x73, 0x4c, 0x6e, 0x53, + 0x7e, 0x53, 0x78, 0x48, 0x93, 0x53, 0x8b, 0x2a, 0x9a, 0x3d, 0x9a, 0x1a, + 0x99, 0x23, 0x9a, 0x09, 0x95, 0x12, 0x98, 0x09, 0x80, 0x1c, 0x86, 0x13, + 0x84, 0x29, 0x87, 0x24, 0x87, 0x32, 0x85, 0x2f, 0x87, 0x36, 0x7f, 0x36, + 0x83, 0x26, 0x72, 0x36, 0x79, 0x21, 0x70, 0x22, 0x71, 0x07, 0x61, 0x0e, + 0x69, 0x00, 0x4d, 0x00, 0x59, 0x05, 0x3d, 0x00, 0x44, 0x14, 0x31, 0x0a, + 0x36, 0x0a, 0x28, 0x0d, 0x2c, 0x08, 0x1c, 0x08, 0x23, 0x12, 0x08, 0x08, + 0x0f, 0x2e, 0x00, 0x1c, 0x00, 0x3e, 0x02, 0x36, 0x00, 0x4e, 0x05, 0x46, + 0x03, 0x23, 0xa8, 0xa6, 0x9a, 0xaa, 0xa6, 0xaa, 0xa9, 0xaa, 0x56, 0x00, + 0x28, 0x0c, 0x0a, 0x00, 0x14, 0x31, 0x00, 0x18, 0x00, 0x54, 0x0a, 0x48, + 0x00, 0x60, 0x28, 0x60, 0x14, 0x60, 0x2e, 0x4c, 0x33, 0x53, 0x2f, 0x46, + 0x3d, 0x46, 0x36, 0x48, 0x43, 0x46, 0x40, 0x53, 0x4a, 0x4a, 0x45, 0x59, + 0x4d, 0x68, 0x5b, 0x63, 0x53, 0x6d, 0x6d, 0x6d, 0x62, 0x63, 0x86, 0x6d, + 0x7e, 0x44, 0x8f, 0x58, 0x8f, 0x38, 0x8d, 0x3e, 0x8f, 0x2b, 0x8a, 0x31, + 0x8c, 0x2b, 0x74, 0x35, 0x78, 0x30, 0x77, 0x3f, 0x79, 0x3a, 0x79, 0x49, + 0x76, 0x45, 0x79, 0x4d, 0x6e, 0x4d, 0x73, 0x4b, 0x66, 0x4d, 0x69, 0x40, + 0x5e, 0x48, 0x63, 0x39, 0x5b, 0x2e, 0x50, 0x31, 0x56, 0x2a, 0x42, 0x2a, + 0x4a, 0x30, 0x31, 0x2a, 0x38, 0x43, 0x25, 0x36, 0x29, 0x3f, 0x19, 0x43, + 0x1d, 0x32, 0x15, 0x3b, 0x15, 0x25, 0x1a, 0x29, 0x15, 0x20, 0x29, 0x20, + 0x1f, 0x20, 0x8c, 0x00, 0x8c, 0x00, 0x28, 0x26, 0xa8, 0x56, 0xaa, 0x95, + 0x6a, 0xaa, 0x95, 0x6a, 0xa5, 0x1a, 0x77, 0x82, 0x65, 0x89, 0x6f, 0x87, + 0x52, 0x8c, 0x5c, 0x8c, 0x2a, 0x80, 0x3b, 0x8c, 0x14, 0x5e, 0x1a, 0x74, + 0x00, 0x5e, 0x08, 0x4d, 0x11, 0x4d, 0x11, 0x4a, 0x11, 0x4b, 0x11, 0x46, + 0x11, 0x48, 0x11, 0x42, 0x11, 0x43, 0x11, 0x3f, 0x11, 0x40, 0x00, 0x3f, + 0x08, 0x2e, 0x14, 0x2e, 0x2a, 0x0c, 0x1a, 0x17, 0x52, 0x00, 0x3b, 0x00, + 0x65, 0x03, 0x5c, 0x00, 0x77, 0x0a, 0x6f, 0x05, 0x77, 0x26, 0x68, 0x1c, + 0x70, 0x1f, 0x57, 0x18, 0x5f, 0x18, 0x43, 0x1d, 0x4b, 0x18, 0x37, 0x2e, + 0x3b, 0x23, 0x67, 0x2e, 0x60, 0x3f, 0x33, 0x3f, 0x33, 0x42, 0x33, 0x41, + 0x33, 0x47, 0x33, 0x44, 0x33, 0x4a, 0x33, 0x48, 0x33, 0x4d, 0x33, 0x4b, + 0x5a, 0x4d, 0x52, 0x5e, 0x37, 0x5e, 0x43, 0x6e, 0x3c, 0x69, 0x57, 0x74, + 0x4b, 0x74, 0x68, 0x70, 0x5f, 0x74, 0x77, 0x66, 0x70, 0x6d, 0x77, 0x82, + 0x2e, 0xa8, 0xaa, 0x56, 0xaa, 0xaa, 0xaa, 0xaa, 0xa9, 0xaa, 0xaa, 0xaa, + 0x16, 0x63, 0x6d, 0x5b, 0x77, 0x61, 0x73, 0x4d, 0x7a, 0x55, 0x7a, 0x34, + 0x6f, 0x3d, 0x7a, 0x2a, 0x52, 0x2a, 0x64, 0x34, 0x34, 0x2a, 0x40, 0x4d, + 0x29, 0x3d, 0x29, 0x5b, 0x2d, 0x55, 0x29, 0x63, 0x37, 0x61, 0x30, 0x63, + 0x2b, 0x76, 0x2b, 0x76, 0x69, 0x88, 0x5f, 0x81, 0x68, 0x8e, 0x47, 0x8e, + 0x56, 0x8c, 0x37, 0x8e, 0x3e, 0x84, 0x28, 0x89, 0x2f, 0x6e, 0x17, 0x7b, + 0x1d, 0x53, 0x11, 0x61, 0x11, 0x3f, 0x14, 0x48, 0x11, 0x2d, 0x1c, 0x35, + 0x17, 0x18, 0x33, 0x20, 0x25, 0x11, 0x51, 0x11, 0x41, 0x16, 0x6a, 0x11, + 0x5f, 0x24, 0x7f, 0x1a, 0x76, 0x38, 0x8c, 0x2d, 0x88, 0x51, 0x91, 0x44, + 0x91, 0x68, 0x8d, 0x5c, 0x91, 0x7b, 0x81, 0x73, 0x89, 0x85, 0x90, 0x6c, + 0x9d, 0x79, 0x99, 0x51, 0xa2, 0x5f, 0xa2, 0x32, 0x9c, 0x41, 0xa2, 0x18, + 0x8b, 0x23, 0x96, 0x06, 0x71, 0x0c, 0x80, 0x00, 0x51, 0x00, 0x62, 0x06, + 0x32, 0x00, 0x41, 0x18, 0x18, 0x0c, 0x23, 0x32, 0x07, 0x23, 0x0d, 0x51, + 0x00, 0x41, 0x00, 0x76, 0x08, 0x65, 0x00, 0x91, 0x1e, 0x86, 0x10, 0x9b, + 0x31, 0x98, 0x27, 0x9f, 0x47, 0x9f, 0x3c, 0x90, 0x6d, 0x9f, 0x5f, 0x67, + 0x7a, 0x82, 0x7a, 0x63, 0x7a, 0x63, 0x6d, 0xc0, 0x00, 0x39, 0x00, 0x00, + 0xea, 0x00, 0x00, 0x7a, 0x03, 0xc0, 0x00, 0x24, 0x00, 0x00, 0xeb, 0x00, + 0x00, 0x57, 0x00, 0xc0, 0x00, 0x26, 0x00, 0x00, 0xfd, 0x00, 0x00, 0xf3, + 0x00, 0xc0, 0x00, 0x32, 0x00, 0x00, 0xeb, 0x00, 0x00, 0x24, 0x02, 0xc0, + 0x00, 0x24, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x88, 0x01, 0xc0, 0x00, 0x37, + 0x00, 0x00, 0xeb, 0x00, 0x00, 0x1b, 0x03, 0xc0, 0x00, 0x24, 0x00, 0x00, + 0xfe, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x24, 0x00, 0x00, 0xd2, 0x00, + 0x00, 0x40, 0x01, 0xc0, 0x00, 0x24, 0x00, 0x00, 0xc9, 0x00, 0x00, 0xc5, + 0x01, 0xc0, 0x00, 0x26, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x7a, 0x02, 0xc0, + 0x00, 0xb5, 0x00, 0x00, 0xb7, 0x00, 0x00, 0x97, 0x03, 0xc0, 0x00, 0x48, + 0x00, 0x00, 0xb1, 0x00, 0x00, 0x05, 0x03, 0xc0, 0x00, 0xb5, 0x00, 0x00, + 0xb7, 0x00, 0x00, 0x9b, 0x03, 0xc0, 0x00, 0x24, 0x00, 0x00, 0xea, 0x00, + 0x00, 0xc6, 0x02, 0xc0, 0x00, 0x24, 0x00, 0x00, 0xea, 0x00, 0x00, 0xa2, + 0x02, 0xc0, 0x00, 0x32, 0x00, 0x00, 0xeb, 0x00, 0x00, 0x4f, 0x02, 0x9f, + 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x02, 0x21, 0xac, 0x3b, 0x00, + 0x00, 0x25, 0xa8, 0x0c, 0x00, 0x00, 0x8b, 0xf2, 0x05, 0x00, 0x00, 0x02, + 0x3e, 0x58, 0x4f, 0x00, 0x00, 0x25, 0x37, 0x04, 0x00, 0x28, 0x25, 0x37, + 0x04, 0x00, 0x00, 0x02, 0x82, 0xac, 0x8e, 0x00, 0x00, 0x27, 0xa5, 0x27, + 0x00, 0x32, 0x5d, 0x6e, 0x0a, 0x00, 0x00, 0x04, 0x66, 0xc7, 0x72, 0x00, + 0x01, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x1f, 0xe8, 0x27, 0x00, 0x1d, 0x48, + 0x35, 0x0c, 0x00, 0x39, 0x7d, 0x4c, 0x0c, 0x00, 0x00, 0x06, 0xae, 0xaf, + 0xb3, 0x00, 0x01, 0x00, 0x6b, 0x2f, 0x00, 0x00, 0x22, 0xb7, 0x06, 0x00, + 0x22, 0x22, 0x22, 0x02, 0x00, 0x16, 0x31, 0xdd, 0x06, 0x00, 0x65, 0x64, + 0x03, 0x07, 0x00, 0x7b, 0x74, 0x29, 0x07, 0x00, 0x00, 0x03, 0x8f, 0xaf, + 0x96, 0x00, 0x01, 0x00, 0x2d, 0x04, 0x00, 0x00, 0x22, 0x4b, 0x28, 0x00, + 0x1f, 0x68, 0x1f, 0x0d, 0x00, 0x00, 0x02, 0x16, 0x58, 0x27, 0x00, 0x01, + 0x00, 0x28, 0x0a, 0x00, 0x00, 0x25, 0x37, 0x04, 0x00, 0x00, 0x01, 0x37, + 0xc4, 0x45, 0x00, 0x00, 0x1f, 0xa3, 0x13, 0x00, 0x00, 0x02, 0x37, 0xc4, + 0x46, 0x00, 0x01, 0x00, 0x75, 0x2f, 0x00, 0x00, 0x1f, 0xcd, 0x13, 0x00, + 0x00, 0x02, 0x5a, 0x79, 0x5d, 0x00, 0x01, 0x00, 0x32, 0x0a, 0x00, 0x00, + 0x22, 0x62, 0x1d, 0x00, 0x00, 0x01, 0x74, 0xac, 0x87, 0x00, 0x00, 0x37, + 0x65, 0x16, 0x00, 0x00, 0x01, 0x2a, 0xc6, 0x3d, 0x00, 0x00, 0x88, 0x4d, + 0x06, 0x00, 0x00, 0x01, 0x39, 0x84, 0x43, 0x00, 0x00, 0x69, 0xff, 0x05, + 0x00, 0x00, 0x02, 0x21, 0xac, 0x34, 0x00, 0x01, 0x00, 0x7f, 0x2f, 0x00, + 0x00, 0x88, 0x6c, 0x01, 0x00, 0x00, 0x02, 0x44, 0xbd, 0x44, 0x00, 0x01, + 0x00, 0x89, 0x2f, 0x00, 0x00, 0x25, 0x7b, 0x0a, 0x00, 0x00, 0x02, 0x70, + 0xaf, 0x78, 0x00, 0x00, 0x22, 0x3d, 0x0f, 0x00, 0x23, 0x3a, 0x63, 0x0f, + 0x00, 0x00, 0x01, 0x60, 0xac, 0x6c, 0x00, 0x00, 0x25, 0x01, 0x15, 0x00, + 0x00, 0x02, 0x63, 0xac, 0x72, 0x00, 0x01, 0x00, 0x18, 0x02, 0x00, 0x00, + 0x22, 0xae, 0x1f, 0x00, 0x00, 0x02, 0x66, 0xaf, 0x74, 0x00, 0x01, 0x00, + 0x93, 0x2f, 0x00, 0x00, 0x22, 0xfb, 0x29, 0x00, 0x00, 0x02, 0x70, 0xac, + 0x78, 0x00, 0x00, 0x25, 0x1d, 0x15, 0x00, 0x16, 0x41, 0x46, 0x0a, 0x00, + 0x00, 0x02, 0x66, 0xaf, 0x73, 0x00, 0x01, 0x00, 0x9d, 0x2f, 0x00, 0x00, + 0x25, 0x04, 0x23, 0x00, 0x00, 0x03, 0x6c, 0xaf, 0x75, 0x00, 0x01, 0x00, + 0xe0, 0x05, 0x00, 0x00, 0x22, 0xce, 0x1c, 0x00, 0x25, 0x69, 0x89, 0x0f, + 0x00, 0x00, 0x02, 0x66, 0xac, 0x74, 0x00, 0x01, 0x00, 0xa7, 0x2f, 0x00, + 0x00, 0x25, 0x3e, 0x0d, 0x00, 0x00, 0x04, 0x6a, 0xaf, 0x75, 0x00, 0x01, + 0x00, 0x58, 0x03, 0x00, 0x00, 0x22, 0x2e, 0x1b, 0x00, 0x24, 0x38, 0xaf, + 0x0f, 0x00, 0x21, 0x6f, 0xd5, 0x0f, 0x00, 0x00, 0x03, 0x6c, 0xaf, 0x77, + 0x00, 0x01, 0x00, 0xb1, 0x2f, 0x00, 0x00, 0x22, 0x18, 0x1d, 0x00, 0x21, + 0x38, 0xfb, 0x0f, 0x00, 0x00, 0x03, 0x21, 0xac, 0x36, 0x00, 0x01, 0x00, + 0xbb, 0x2f, 0x00, 0x00, 0x46, 0x6c, 0x01, 0x00, 0x00, 0x88, 0x6c, 0x01, + 0x00, 0x00, 0x03, 0x2a, 0xc6, 0x3f, 0x00, 0x01, 0x00, 0xc5, 0x2f, 0x00, + 0x09, 0x46, 0x6c, 0x01, 0x00, 0x00, 0x88, 0x4d, 0x06, 0x00, 0x00, 0x02, + 0x74, 0xa6, 0x87, 0x00, 0x01, 0x00, 0xd6, 0x05, 0x00, 0x00, 0x3d, 0x51, + 0x0d, 0x00, 0x00, 0x02, 0x74, 0x91, 0x87, 0x00, 0x00, 0x52, 0x79, 0x01, + 0x00, 0x00, 0x7b, 0x79, 0x01, 0x00, 0x00, 0x01, 0x74, 0xa6, 0x87, 0x00, + 0x00, 0x3d, 0x64, 0x0d, 0x00, 0x00, 0x02, 0x53, 0xac, 0x5f, 0x00, 0x00, + 0x22, 0x59, 0x23, 0x00, 0x13, 0x8b, 0xf2, 0x05, 0x00, 0x00, 0x02, 0xa0, + 0xcc, 0xad, 0x00, 0x00, 0x29, 0xb0, 0x2e, 0x00, 0x3f, 0x63, 0x21, 0x10, + 0x00, 0x00, 0x02, 0x8e, 0xac, 0x8e, 0x00, 0x00, 0x25, 0x86, 0x01, 0x00, + 0x34, 0x44, 0xe5, 0x00, 0x00, 0x00, 0x03, 0x70, 0xac, 0x7c, 0x00, 0x00, + 0x25, 0x39, 0x15, 0x00, 0x23, 0x3c, 0x77, 0x0d, 0x00, 0x23, 0x70, 0x92, + 0x0d, 0x00, 0x00, 0x01, 0x73, 0xaf, 0x7f, 0x00, 0x00, 0x22, 0x95, 0x03, + 0x00, 0x00, 0x03, 0x7f, 0xac, 0x89, 0x00, 0x01, 0x00, 0x62, 0x01, 0x00, + 0x00, 0x25, 0x65, 0x15, 0x00, 0x23, 0x3f, 0xad, 0x0d, 0x00, 0x00, 0x01, + 0x60, 0xac, 0x6d, 0x00, 0x00, 0x25, 0x80, 0x02, 0x00, 0x00, 0x01, 0x5e, + 0xac, 0x6d, 0x00, 0x00, 0x25, 0xf7, 0x13, 0x00, 0x00, 0x01, 0x81, 0xaf, + 0x8f, 0x00, 0x00, 0x22, 0x6f, 0x09, 0x00, 0x00, 0x01, 0x79, 0xac, 0x8a, + 0x00, 0x00, 0x25, 0x84, 0x16, 0x00, 0x00, 0x02, 0x24, 0xac, 0x34, 0x00, + 0x01, 0x00, 0xcf, 0x2f, 0x00, 0x00, 0x25, 0x2f, 0x02, 0x00, 0x0b, 0x01, + 0x3f, 0xd1, 0x4f, 0x00, 0x00, 0x25, 0x11, 0x14, 0x00, 0x00, 0x01, 0x84, + 0xac, 0x7e, 0x00, 0x00, 0x25, 0x91, 0x15, 0x00, 0x00, 0x01, 0x60, 0xac, + 0x65, 0x00, 0x00, 0x25, 0xb9, 0x0c, 0x00, 0x00, 0x01, 0x96, 0xac, 0xa7, + 0x00, 0x00, 0x25, 0x09, 0x18, 0x00, 0x00, 0x02, 0x79, 0xac, 0x8a, 0x00, + 0x01, 0x00, 0xd9, 0x2f, 0x00, 0x00, 0x25, 0xc1, 0x07, 0x00, 0x00, 0x02, + 0x8b, 0xaf, 0x94, 0x00, 0x00, 0x22, 0x9c, 0x01, 0x00, 0x24, 0x3b, 0xc2, + 0x01, 0x00, 0x00, 0x02, 0x70, 0xac, 0x77, 0x00, 0x00, 0x25, 0x83, 0x13, + 0x00, 0x23, 0x3e, 0xc8, 0x0d, 0x00, 0x00, 0x02, 0x8b, 0xc7, 0x94, 0x00, + 0x00, 0x22, 0xa3, 0x16, 0x00, 0x24, 0x3b, 0x47, 0x10, 0x00, 0x00, 0x02, + 0x7a, 0xac, 0x7d, 0x00, 0x00, 0x25, 0x76, 0x1b, 0x00, 0x23, 0x3e, 0xe3, + 0x0d, 0x00, 0x00, 0x01, 0x6b, 0xaf, 0x78, 0x00, 0x00, 0x22, 0xf0, 0x04, + 0x00, 0x00, 0x01, 0x7d, 0xac, 0x7d, 0x00, 0x00, 0x25, 0x6d, 0x10, 0x00, + 0x00, 0x02, 0x75, 0xaf, 0x85, 0x00, 0x01, 0x00, 0xe3, 0x2f, 0x00, 0x00, + 0x25, 0x9f, 0x02, 0x00, 0x00, 0x01, 0x8e, 0xac, 0x8e, 0x00, 0x00, 0x25, + 0xfe, 0x0d, 0x00, 0x00, 0x01, 0xc1, 0xac, 0xc6, 0x00, 0x00, 0x25, 0x2a, + 0x18, 0x00, 0x00, 0x01, 0x88, 0xac, 0x8b, 0x00, 0x00, 0x25, 0xd2, 0x16, + 0x00, 0x02, 0x01, 0x8a, 0xac, 0x88, 0x00, 0x00, 0x25, 0x91, 0x04, 0x00, + 0x00, 0x01, 0x76, 0xac, 0x7e, 0x00, 0x00, 0x25, 0xdb, 0x07, 0x00, 0x00, + 0x01, 0x39, 0xc4, 0x45, 0x00, 0x00, 0x1f, 0x83, 0x10, 0x00, 0x00, 0x01, + 0x44, 0xbd, 0x44, 0x00, 0x00, 0x25, 0x88, 0x0a, 0x00, 0x00, 0x01, 0x39, + 0xc4, 0x48, 0x00, 0x00, 0x1f, 0x99, 0x10, 0x00, 0x00, 0x01, 0x76, 0x58, + 0x88, 0x00, 0x00, 0x25, 0x11, 0x0e, 0x00, 0x00, 0x01, 0x5d, 0xd7, 0x5d, + 0x00, 0x00, 0xc5, 0x95, 0x0a, 0x00, 0x00, 0x01, 0x34, 0x3a, 0x54, 0x00, + 0x00, 0x18, 0x3c, 0x02, 0x00, 0x00, 0x02, 0x67, 0xaf, 0x75, 0x00, 0x00, + 0x44, 0x15, 0x01, 0x00, 0x20, 0x7e, 0xc3, 0x00, 0x00, 0x00, 0x03, 0x6d, + 0xaf, 0x75, 0x00, 0x01, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x1f, 0x4b, 0x18, + 0x00, 0x20, 0x5b, 0xaf, 0x10, 0x00, 0x00, 0x01, 0x5a, 0xaf, 0x66, 0x00, + 0x00, 0x44, 0xe1, 0x03, 0x00, 0x00, 0x03, 0x6d, 0xaf, 0x7c, 0x00, 0x01, + 0x00, 0x2d, 0x04, 0x00, 0x00, 0x1f, 0x7c, 0x18, 0x00, 0x21, 0x5b, 0x4f, + 0x07, 0x00, 0x00, 0x02, 0x6d, 0xaf, 0x76, 0x00, 0x00, 0x44, 0xd2, 0x02, + 0x00, 0x21, 0x59, 0x56, 0x02, 0x00, 0x00, 0x01, 0x4f, 0xac, 0x4d, 0x00, + 0x00, 0x1f, 0x8e, 0x1d, 0x00, 0x00, 0x03, 0x6d, 0xd4, 0x7c, 0x00, 0x01, + 0x00, 0x18, 0x02, 0x00, 0x00, 0x44, 0x1c, 0x09, 0x00, 0x21, 0x5b, 0x75, + 0x07, 0x00, 0x00, 0x02, 0x66, 0xac, 0x74, 0x00, 0x01, 0x00, 0x58, 0x03, + 0x00, 0x00, 0x1f, 0xf4, 0x1f, 0x00, 0x00, 0x03, 0x21, 0xac, 0x30, 0x00, + 0x01, 0x00, 0x62, 0x01, 0x00, 0x00, 0x1f, 0x44, 0x04, 0x00, 0x00, 0x46, + 0x49, 0x02, 0x00, 0x07, 0x03, 0x37, 0xd4, 0x46, 0x00, 0x01, 0x00, 0x62, + 0x01, 0x00, 0x16, 0x1f, 0x44, 0x04, 0x00, 0x00, 0x46, 0x33, 0x14, 0x00, + 0x00, 0x02, 0x70, 0xac, 0x6c, 0x00, 0x01, 0x00, 0x62, 0x01, 0x00, 0x00, + 0x1f, 0xad, 0x15, 0x00, 0x00, 0x02, 0x21, 0xac, 0x30, 0x00, 0x01, 0x00, + 0x62, 0x01, 0x00, 0x00, 0x1f, 0xa2, 0x0a, 0x00, 0x00, 0x02, 0xa3, 0xac, + 0xb1, 0x00, 0x01, 0x00, 0x62, 0x01, 0x00, 0x00, 0x44, 0x70, 0x2a, 0x00, + 0x00, 0x02, 0x66, 0xac, 0x74, 0x00, 0x01, 0x00, 0x62, 0x01, 0x00, 0x00, + 0x44, 0xda, 0x08, 0x00, 0x00, 0x02, 0x70, 0xaf, 0x77, 0x00, 0x00, 0x44, + 0xe8, 0x01, 0x00, 0x22, 0x5b, 0xef, 0x00, 0x00, 0x00, 0x02, 0x6d, 0xd2, + 0x75, 0x00, 0x00, 0x44, 0xad, 0x18, 0x00, 0x20, 0x5b, 0x9b, 0x07, 0x00, + 0x00, 0x02, 0x6d, 0xd2, 0x7c, 0x00, 0x00, 0x44, 0xde, 0x18, 0x00, 0x21, + 0x5b, 0xd5, 0x10, 0x00, 0x00, 0x01, 0x4c, 0xac, 0x4c, 0x00, 0x00, 0x44, + 0x82, 0x19, 0x00, 0x00, 0x01, 0x5c, 0xaf, 0x65, 0x00, 0x00, 0x44, 0x63, + 0x05, 0x00, 0x00, 0x01, 0x52, 0xac, 0x56, 0x00, 0x00, 0x2a, 0xc2, 0x1d, + 0x00, 0x00, 0x01, 0x66, 0xaf, 0x75, 0x00, 0x00, 0x46, 0x0f, 0x03, 0x00, + 0x00, 0x01, 0x74, 0xac, 0x76, 0x00, 0x00, 0x46, 0x24, 0x0e, 0x00, 0x00, + 0x01, 0x9e, 0xac, 0xa4, 0x00, 0x00, 0x46, 0x0f, 0x19, 0x00, 0x00, 0x01, + 0x72, 0xac, 0x75, 0x00, 0x00, 0x46, 0xf1, 0x16, 0x00, 0x00, 0x01, 0x73, + 0xd4, 0x76, 0x00, 0x00, 0x46, 0xc5, 0x04, 0x00, 0x00, 0x01, 0x5b, 0xac, + 0x63, 0x00, 0x00, 0x46, 0xf5, 0x07, 0x00, 0x00, 0x01, 0x56, 0xca, 0x6d, + 0x00, 0x00, 0x1f, 0xd9, 0x2a, 0x00, 0x00, 0x01, 0x15, 0xd7, 0x2c, 0x00, + 0x00, 0x1e, 0xaf, 0x0a, 0x00, 0x00, 0x01, 0x56, 0xca, 0x6d, 0x00, 0x00, + 0x1f, 0x3e, 0x2b, 0x00, 0x00, 0x01, 0x74, 0x85, 0x87, 0x00, 0x00, 0x5f, + 0xf6, 0x1d, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x02, + 0x21, 0xac, 0x3b, 0x00, 0x00, 0x25, 0xbc, 0x0a, 0x00, 0x00, 0x52, 0xca, + 0x0c, 0x00, 0x00, 0x02, 0x5a, 0xc8, 0x71, 0x00, 0x00, 0x2a, 0x57, 0x25, + 0x00, 0x22, 0x5e, 0x63, 0x0c, 0x00, 0x00, 0x01, 0x67, 0xac, 0x75, 0x00, + 0x00, 0x22, 0x05, 0x26, 0x00, 0x00, 0x02, 0x69, 0xa6, 0x6f, 0x00, 0x00, + 0x3d, 0xba, 0x28, 0x00, 0x20, 0x5e, 0xfb, 0x10, 0x00, 0x00, 0x01, 0x7d, + 0xac, 0x7e, 0x00, 0x00, 0x25, 0xa9, 0x26, 0x00, 0x00, 0x02, 0x15, 0xcb, + 0x2c, 0x00, 0x00, 0x2a, 0x0c, 0x06, 0x00, 0x00, 0x86, 0x0c, 0x06, 0x00, + 0x00, 0x02, 0x5b, 0xbd, 0x5b, 0x00, 0x00, 0x22, 0x0d, 0x2d, 0x00, 0x1a, + 0x5e, 0x21, 0x11, 0x00, 0x00, 0x02, 0x3a, 0x34, 0x4b, 0x00, 0x00, 0x1c, + 0xa9, 0x00, 0x00, 0x24, 0x1c, 0xa9, 0x00, 0x00, 0x00, 0x03, 0x86, 0xac, + 0x9f, 0x00, 0x00, 0x25, 0x4a, 0x08, 0x00, 0x0e, 0x33, 0x92, 0x08, 0x00, + 0x1d, 0x42, 0x42, 0x1e, 0x00, 0x00, 0x03, 0x4d, 0x8a, 0x5a, 0x00, 0x00, + 0x22, 0x00, 0x21, 0x00, 0x16, 0x4a, 0x47, 0x11, 0x00, 0x02, 0x77, 0xc9, + 0x0a, 0x00, 0x00, 0x02, 0x58, 0xa0, 0x69, 0x00, 0x00, 0x4b, 0x6b, 0x04, + 0x00, 0x2b, 0x4b, 0x6b, 0x04, 0x00, 0x00, 0x01, 0x74, 0x92, 0x87, 0x00, + 0x00, 0x59, 0xdb, 0x0c, 0x00, 0x00, 0x02, 0x39, 0x84, 0x43, 0x00, 0x01, + 0x00, 0x0e, 0x02, 0x00, 0x00, 0x69, 0xff, 0x05, 0x00, 0x00, 0x05, 0x86, + 0xac, 0x9f, 0x00, 0x01, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x25, 0x4a, 0x08, + 0x00, 0x0e, 0x33, 0x92, 0x08, 0x00, 0x27, 0x41, 0xae, 0x1b, 0x00, 0x3a, + 0x4e, 0x37, 0x0e, 0x00, 0x00, 0x02, 0x3a, 0x31, 0x4b, 0x00, 0x01, 0x00, + 0x18, 0x02, 0x00, 0x00, 0x1f, 0xd6, 0x0a, 0x00, 0x00, 0x02, 0x3d, 0x5e, + 0x4d, 0x00, 0x00, 0x21, 0x10, 0x17, 0x00, 0x0f, 0x30, 0x69, 0x11, 0x00, + 0x00, 0x02, 0x74, 0xac, 0x87, 0x00, 0x00, 0x37, 0x47, 0x17, 0x00, 0x00, + 0x96, 0x79, 0x01, 0x00, 0x00, 0x01, 0x3e, 0x70, 0x47, 0x00, 0x00, 0x22, + 0x36, 0x20, 0x00, 0x00, 0x01, 0x40, 0x71, 0x49, 0x00, 0x00, 0x22, 0xa3, + 0x2b, 0x00, 0x00, 0x02, 0x34, 0x3a, 0x3c, 0x00, 0x01, 0x00, 0xed, 0x2f, + 0x00, 0x00, 0x18, 0x51, 0x04, 0x00, 0x00, 0x01, 0x73, 0xd2, 0x78, 0x00, + 0x00, 0x46, 0xe5, 0x26, 0x00, 0x00, 0x02, 0x5a, 0xbe, 0x6a, 0x00, 0x01, + 0x00, 0xf7, 0x2f, 0x00, 0x00, 0x25, 0x66, 0x17, 0x00, 0x00, 0x01, 0x21, + 0x7d, 0x34, 0x00, 0x00, 0x5a, 0x19, 0x06, 0x00, 0x00, 0x01, 0x2a, 0xd0, + 0x45, 0x00, 0x00, 0xab, 0xb5, 0x19, 0x00, 0x00, 0x01, 0x3c, 0x70, 0x46, + 0x00, 0x00, 0x24, 0xa9, 0x04, 0x00, 0x00, 0x03, 0x54, 0x8a, 0x5e, 0x00, + 0x00, 0x22, 0x8f, 0x11, 0x00, 0x1a, 0x32, 0xb5, 0x11, 0x00, 0x04, 0x77, + 0xe3, 0x0a, 0x00, 0x00, 0x03, 0x58, 0xa0, 0x66, 0x00, 0x01, 0x00, 0xd6, + 0x05, 0x00, 0x00, 0x4b, 0x7e, 0x04, 0x00, 0x2b, 0x4b, 0x7e, 0x04, 0x00, + 0x00, 0x04, 0xa8, 0xaf, 0xb6, 0x00, 0x25, 0x22, 0x22, 0x02, 0x00, 0x00, + 0x24, 0xa9, 0x04, 0x00, 0x63, 0x60, 0xc9, 0x15, 0x00, 0x71, 0x71, 0x50, + 0x0a, 0x00, 0x00, 0x03, 0xae, 0xaf, 0xb6, 0x00, 0x25, 0x22, 0x22, 0x02, + 0x00, 0x00, 0x24, 0xa9, 0x04, 0x00, 0x70, 0x5e, 0x7c, 0x20, 0x00, 0x00, + 0x04, 0xa8, 0xaf, 0xb6, 0x00, 0x00, 0x22, 0x18, 0x2c, 0x00, 0x25, 0x22, + 0xf0, 0x0a, 0x00, 0x63, 0x60, 0xe5, 0x15, 0x00, 0x70, 0x71, 0x5a, 0x0a, + 0x00, 0x00, 0x02, 0x53, 0xaf, 0x5f, 0x00, 0x1f, 0x25, 0xfd, 0x0a, 0x00, + 0x00, 0x52, 0xae, 0x23, 0x00, 0x00, 0x03, 0x8e, 0xac, 0x8e, 0x00, 0x26, + 0x00, 0x0a, 0x0b, 0x00, 0x00, 0x25, 0x86, 0x01, 0x00, 0x34, 0x44, 0xe5, + 0x00, 0x00, 0x00, 0x03, 0x8e, 0xac, 0x8e, 0x00, 0x37, 0x00, 0x62, 0x03, + 0x00, 0x00, 0x25, 0x86, 0x01, 0x00, 0x34, 0x44, 0xe5, 0x00, 0x00, 0x00, + 0x03, 0x8e, 0xac, 0x8e, 0x00, 0x22, 0x00, 0x6d, 0x02, 0x00, 0x00, 0x25, + 0x86, 0x01, 0x00, 0x34, 0x44, 0xe5, 0x00, 0x00, 0x00, 0x03, 0x8e, 0xac, + 0x8e, 0x00, 0x25, 0x00, 0x41, 0x27, 0x00, 0x00, 0x25, 0x86, 0x01, 0x00, + 0x34, 0x44, 0xe5, 0x00, 0x00, 0x00, 0x05, 0x8e, 0xac, 0x8e, 0x00, 0x01, + 0x00, 0x3c, 0x0a, 0x00, 0x28, 0x00, 0xb6, 0x00, 0x00, 0x4b, 0x00, 0xb6, + 0x00, 0x00, 0x00, 0x25, 0x86, 0x01, 0x00, 0x34, 0x44, 0xe5, 0x00, 0x00, + 0x00, 0x04, 0x8e, 0xac, 0x8e, 0x00, 0x01, 0x00, 0x3c, 0x0a, 0x00, 0x00, + 0x00, 0xc4, 0x1a, 0x00, 0x3b, 0x0e, 0xdb, 0x11, 0x00, 0x34, 0x44, 0xe5, + 0x00, 0x00, 0x00, 0x02, 0xbb, 0xac, 0xc8, 0x00, 0x00, 0x25, 0xe6, 0x1b, + 0x00, 0x39, 0x3c, 0x17, 0x0b, 0x00, 0x00, 0x03, 0x73, 0xd0, 0x7f, 0x00, + 0x01, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x22, 0x95, 0x03, 0x00, 0x30, 0xab, + 0xf0, 0x19, 0x00, 0x00, 0x02, 0x60, 0xac, 0x6d, 0x00, 0x0f, 0x00, 0x24, + 0x0b, 0x00, 0x00, 0x25, 0x80, 0x02, 0x00, 0x00, 0x03, 0x60, 0xac, 0x6d, + 0x00, 0x01, 0x00, 0x0e, 0x02, 0x00, 0x20, 0x00, 0x62, 0x03, 0x00, 0x00, + 0x25, 0x80, 0x02, 0x00, 0x00, 0x02, 0x60, 0xac, 0x6d, 0x00, 0x0b, 0x00, + 0x6d, 0x02, 0x00, 0x00, 0x25, 0x80, 0x02, 0x00, 0x00, 0x03, 0x60, 0xac, + 0x6d, 0x00, 0x11, 0x00, 0xb6, 0x00, 0x00, 0x35, 0x00, 0xb6, 0x00, 0x00, + 0x00, 0x25, 0x80, 0x02, 0x00, 0x00, 0x02, 0x33, 0xac, 0x43, 0x00, 0x00, + 0x00, 0x31, 0x0b, 0x00, 0x0f, 0x25, 0x2f, 0x02, 0x00, 0x00, 0x02, 0x2e, + 0xac, 0x34, 0x00, 0x02, 0x00, 0x62, 0x03, 0x00, 0x00, 0x25, 0x2f, 0x02, + 0x00, 0x02, 0x02, 0x45, 0xac, 0x47, 0x00, 0x00, 0x00, 0x6d, 0x02, 0x00, + 0x13, 0x25, 0x3e, 0x0b, 0x00, 0x00, 0x03, 0x3a, 0xac, 0x41, 0x00, 0x00, + 0x00, 0xb6, 0x00, 0x00, 0x24, 0x00, 0xb6, 0x00, 0x00, 0x0d, 0x25, 0x2f, + 0x02, 0x00, 0x00, 0x03, 0x8f, 0xac, 0x98, 0x00, 0x01, 0x00, 0x18, 0x02, + 0x00, 0x00, 0x25, 0xf9, 0x1a, 0x00, 0x32, 0x3f, 0x01, 0x16, 0x00, 0x00, + 0x03, 0x79, 0xac, 0x8a, 0x00, 0x01, 0x00, 0x18, 0x02, 0x00, 0x1a, 0x00, + 0xc4, 0x09, 0x00, 0x00, 0x25, 0xc1, 0x07, 0x00, 0x00, 0x04, 0x8b, 0xaf, + 0x94, 0x00, 0x01, 0x00, 0x18, 0x02, 0x00, 0x25, 0x00, 0x26, 0x06, 0x00, + 0x00, 0x22, 0x9c, 0x01, 0x00, 0x24, 0x3b, 0xc2, 0x01, 0x00, 0x00, 0x04, + 0x8b, 0xaf, 0x94, 0x00, 0x01, 0x00, 0x58, 0x03, 0x00, 0x36, 0x00, 0x4b, + 0x0b, 0x00, 0x00, 0x22, 0x9c, 0x01, 0x00, 0x24, 0x3b, 0xc2, 0x01, 0x00, + 0x00, 0x04, 0x8b, 0xaf, 0x94, 0x00, 0x01, 0x00, 0x58, 0x03, 0x00, 0x21, + 0x00, 0x6d, 0x02, 0x00, 0x00, 0x22, 0x9c, 0x01, 0x00, 0x24, 0x3b, 0xc2, + 0x01, 0x00, 0x00, 0x04, 0x8b, 0xaf, 0x94, 0x00, 0x01, 0x00, 0x58, 0x03, + 0x00, 0x24, 0x00, 0xc4, 0x09, 0x00, 0x00, 0x22, 0x9c, 0x01, 0x00, 0x24, + 0x3b, 0xc2, 0x01, 0x00, 0x00, 0x04, 0x8b, 0xaf, 0x94, 0x00, 0x27, 0x00, + 0xb6, 0x00, 0x00, 0x4a, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x22, 0x9c, 0x01, + 0x00, 0x24, 0x3b, 0xc2, 0x01, 0x00, 0x00, 0x01, 0x6d, 0xa8, 0x84, 0x00, + 0x00, 0x3b, 0x8d, 0x17, 0x00, 0x00, 0x03, 0x95, 0xb3, 0x99, 0x00, 0x00, + 0x1e, 0x8e, 0x1e, 0x00, 0x29, 0x3b, 0x52, 0x0e, 0x00, 0x32, 0x53, 0x71, + 0x0e, 0x00, 0x00, 0x02, 0x75, 0xaf, 0x85, 0x00, 0x1a, 0x00, 0x26, 0x06, + 0x00, 0x00, 0x25, 0x9f, 0x02, 0x00, 0x00, 0x02, 0x75, 0xaf, 0x85, 0x00, + 0x2a, 0x00, 0x58, 0x0b, 0x00, 0x00, 0x25, 0x9f, 0x02, 0x00, 0x00, 0x02, + 0x75, 0xaf, 0x85, 0x00, 0x16, 0x00, 0x6d, 0x02, 0x00, 0x00, 0x25, 0x9f, + 0x02, 0x00, 0x00, 0x03, 0x75, 0xaf, 0x85, 0x00, 0x1b, 0x00, 0xb6, 0x00, + 0x00, 0x3f, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x25, 0x9f, 0x02, 0x00, 0x02, + 0x02, 0x8a, 0xac, 0x88, 0x00, 0x35, 0x00, 0x62, 0x03, 0x00, 0x00, 0x25, + 0x91, 0x04, 0x00, 0x00, 0x02, 0x70, 0xac, 0x78, 0x00, 0x00, 0x25, 0x25, + 0x16, 0x00, 0x23, 0x55, 0x90, 0x0e, 0x00, 0x00, 0x01, 0x6e, 0xaf, 0x76, + 0x00, 0x00, 0x1f, 0x9d, 0x2d, 0x00, 0x00, 0x03, 0x67, 0xaf, 0x75, 0x00, + 0x11, 0x18, 0x65, 0x0b, 0x00, 0x00, 0x44, 0x15, 0x01, 0x00, 0x20, 0x7e, + 0xc3, 0x00, 0x00, 0x00, 0x04, 0x67, 0xaf, 0x75, 0x00, 0x01, 0x00, 0x01, + 0x30, 0x00, 0x2a, 0x18, 0x33, 0x06, 0x00, 0x00, 0x44, 0x15, 0x01, 0x00, + 0x20, 0x7e, 0xc3, 0x00, 0x00, 0x00, 0x03, 0x67, 0xaf, 0x75, 0x00, 0x15, + 0x18, 0x6f, 0x03, 0x00, 0x00, 0x44, 0x15, 0x01, 0x00, 0x20, 0x7e, 0xc3, + 0x00, 0x00, 0x00, 0x04, 0x67, 0xaf, 0x75, 0x00, 0x01, 0x00, 0xe0, 0x05, + 0x00, 0x18, 0x1c, 0x03, 0x24, 0x00, 0x00, 0x44, 0x15, 0x01, 0x00, 0x20, + 0x7e, 0xc3, 0x00, 0x00, 0x00, 0x04, 0x67, 0xaf, 0x75, 0x00, 0x1b, 0x1c, + 0xa9, 0x00, 0x00, 0x3e, 0x1c, 0xa9, 0x00, 0x00, 0x00, 0x44, 0x15, 0x01, + 0x00, 0x20, 0x7e, 0xc3, 0x00, 0x00, 0x00, 0x04, 0x67, 0xaf, 0x75, 0x00, + 0x1d, 0x07, 0x01, 0x12, 0x00, 0x2b, 0x15, 0x27, 0x12, 0x00, 0x00, 0x44, + 0x15, 0x01, 0x00, 0x20, 0x7e, 0xc3, 0x00, 0x00, 0x00, 0x03, 0xb1, 0xaf, + 0xba, 0x00, 0x00, 0x44, 0x8d, 0x2c, 0x00, 0x66, 0x59, 0x7a, 0x0c, 0x00, + 0x20, 0x7e, 0xc3, 0x00, 0x00, 0x00, 0x02, 0x5a, 0xd0, 0x66, 0x00, 0x00, + 0x44, 0xe1, 0x03, 0x00, 0x20, 0xab, 0x0f, 0x08, 0x00, 0x00, 0x04, 0x6d, + 0xaf, 0x76, 0x00, 0x01, 0x00, 0x28, 0x0a, 0x00, 0x14, 0x18, 0x3c, 0x02, + 0x00, 0x00, 0x44, 0xd2, 0x02, 0x00, 0x21, 0x59, 0x56, 0x02, 0x00, 0x00, + 0x03, 0x6d, 0xaf, 0x76, 0x00, 0x2c, 0x18, 0x5e, 0x04, 0x00, 0x00, 0x44, + 0xd2, 0x02, 0x00, 0x21, 0x59, 0x56, 0x02, 0x00, 0x00, 0x04, 0x6d, 0xaf, + 0x76, 0x00, 0x01, 0x00, 0xd6, 0x05, 0x00, 0x18, 0x18, 0x6f, 0x03, 0x00, + 0x00, 0x44, 0xd2, 0x02, 0x00, 0x21, 0x59, 0x56, 0x02, 0x00, 0x00, 0x04, + 0x6d, 0xaf, 0x76, 0x00, 0x1d, 0x1c, 0xa9, 0x00, 0x00, 0x41, 0x1c, 0xa9, + 0x00, 0x00, 0x00, 0x44, 0xd2, 0x02, 0x00, 0x21, 0x59, 0x56, 0x02, 0x00, + 0x04, 0x02, 0x35, 0xac, 0x44, 0x00, 0x00, 0x18, 0x3c, 0x02, 0x00, 0x13, + 0x46, 0x72, 0x0b, 0x00, 0x00, 0x02, 0x39, 0xac, 0x30, 0x00, 0x05, 0x18, + 0x51, 0x04, 0x00, 0x00, 0x46, 0x49, 0x02, 0x00, 0x01, 0x02, 0x45, 0xac, + 0x40, 0x00, 0x00, 0x18, 0x6f, 0x03, 0x00, 0x10, 0x46, 0x49, 0x02, 0x00, + 0x00, 0x03, 0x3a, 0xac, 0x3a, 0x00, 0x00, 0x1c, 0xa9, 0x00, 0x00, 0x24, + 0x1c, 0xa9, 0x00, 0x00, 0x0a, 0x46, 0x49, 0x02, 0x00, 0x00, 0x02, 0x70, + 0xaf, 0x77, 0x00, 0x00, 0x1f, 0x7a, 0x22, 0x00, 0x22, 0x63, 0x55, 0x14, + 0x00, 0x00, 0x02, 0x66, 0xac, 0x74, 0x00, 0x15, 0x1c, 0x58, 0x24, 0x00, + 0x00, 0x44, 0xda, 0x08, 0x00, 0x00, 0x03, 0x70, 0xaf, 0x77, 0x00, 0x14, + 0x18, 0x3c, 0x02, 0x00, 0x00, 0x44, 0xe8, 0x01, 0x00, 0x22, 0x5b, 0xef, + 0x00, 0x00, 0x00, 0x03, 0x70, 0xaf, 0x77, 0x00, 0x2c, 0x18, 0x5e, 0x04, + 0x00, 0x00, 0x44, 0xe8, 0x01, 0x00, 0x22, 0x5b, 0xef, 0x00, 0x00, 0x00, + 0x03, 0x70, 0xaf, 0x77, 0x00, 0x18, 0x18, 0x91, 0x06, 0x00, 0x00, 0x44, + 0xe8, 0x01, 0x00, 0x22, 0x5b, 0xef, 0x00, 0x00, 0x00, 0x03, 0x70, 0xaf, + 0x77, 0x00, 0x1a, 0x1c, 0xad, 0x24, 0x00, 0x00, 0x44, 0xe8, 0x01, 0x00, + 0x22, 0x5b, 0xef, 0x00, 0x00, 0x00, 0x05, 0x70, 0xaf, 0x77, 0x00, 0x01, + 0x00, 0x32, 0x0a, 0x00, 0x1d, 0x1c, 0xa9, 0x00, 0x00, 0x41, 0x1c, 0xa9, + 0x00, 0x00, 0x00, 0x44, 0xe8, 0x01, 0x00, 0x22, 0x5b, 0xef, 0x00, 0x00, + 0x00, 0x03, 0x74, 0xa4, 0x87, 0x00, 0x2c, 0x3f, 0x40, 0x06, 0x00, 0x00, + 0x67, 0x79, 0x01, 0x00, 0x2c, 0x87, 0x40, 0x06, 0x00, 0x00, 0x03, 0x71, + 0xb4, 0x78, 0x00, 0x00, 0x3e, 0xd2, 0x1e, 0x00, 0x22, 0x5b, 0xab, 0x0e, + 0x00, 0x2a, 0x6c, 0xca, 0x0e, 0x00, 0x00, 0x03, 0x66, 0xaf, 0x75, 0x00, + 0x01, 0x00, 0xe0, 0x05, 0x00, 0x10, 0x18, 0x3c, 0x02, 0x00, 0x00, 0x46, + 0x0f, 0x03, 0x00, 0x00, 0x02, 0x66, 0xaf, 0x75, 0x00, 0x28, 0x18, 0x5e, + 0x04, 0x00, 0x00, 0x46, 0x0f, 0x03, 0x00, 0x00, 0x03, 0x66, 0xaf, 0x75, + 0x00, 0x01, 0x00, 0x2d, 0x04, 0x00, 0x14, 0x18, 0x91, 0x06, 0x00, 0x00, + 0x46, 0x0f, 0x03, 0x00, 0x00, 0x03, 0x66, 0xaf, 0x75, 0x00, 0x19, 0x1c, + 0xa9, 0x00, 0x00, 0x3d, 0x1c, 0xa9, 0x00, 0x00, 0x00, 0x46, 0x0f, 0x03, + 0x00, 0x00, 0x03, 0x73, 0xd4, 0x76, 0x00, 0x01, 0x00, 0x2d, 0x04, 0x00, + 0x2d, 0x18, 0x33, 0x06, 0x00, 0x00, 0x46, 0xc5, 0x04, 0x00, 0x00, 0x02, + 0x6d, 0xd2, 0x75, 0x00, 0x00, 0x1f, 0x30, 0x19, 0x00, 0x20, 0x5b, 0x9b, + 0x07, 0x00, 0x00, 0x03, 0x73, 0xd4, 0x76, 0x00, 0x1d, 0x1c, 0x7f, 0x0b, + 0x00, 0x41, 0x1c, 0xa9, 0x00, 0x00, 0x00, 0x46, 0xc5, 0x04, 0x00, 0x85, + 0x00, 0x02, 0x73, 0xaf, 0x7f, 0x00, 0x38, 0x00, 0x8c, 0x0b, 0x00, 0x00, + 0x22, 0x95, 0x03, 0x00, 0x00, 0x02, 0x60, 0xaf, 0x66, 0x00, 0x2c, 0x18, + 0x51, 0x04, 0x00, 0x00, 0x44, 0xe1, 0x03, 0x00, 0x83, 0x00, 0x02, 0x73, + 0xaf, 0x7f, 0x00, 0x23, 0x00, 0xa4, 0x06, 0x00, 0x00, 0x22, 0x95, 0x03, + 0x00, 0x00, 0x02, 0x5c, 0xaf, 0x66, 0x00, 0x17, 0x18, 0x82, 0x03, 0x00, + 0x00, 0x44, 0xe1, 0x03, 0x00, 0x82, 0x00, 0x02, 0x7b, 0xaf, 0x7c, 0x00, + 0x00, 0x1f, 0xc1, 0x22, 0x00, 0x21, 0x5b, 0x4f, 0x07, 0x00, 0x8b, 0x00, + 0x02, 0x81, 0xaf, 0x8f, 0x00, 0x22, 0x00, 0x83, 0x14, 0x00, 0x00, 0x22, + 0x6f, 0x09, 0x00, 0x00, 0x03, 0x6d, 0xd4, 0x7c, 0x00, 0x1b, 0x1b, 0xad, + 0x14, 0x00, 0x00, 0x44, 0x1c, 0x09, 0x00, 0x21, 0x5b, 0x75, 0x07, 0x00, + 0x8f, 0x00, 0x02, 0x24, 0xac, 0x34, 0x00, 0x03, 0x00, 0x99, 0x0b, 0x00, + 0x00, 0x25, 0x2f, 0x02, 0x00, 0x00, 0x01, 0x21, 0xac, 0x30, 0x00, 0x00, + 0x46, 0x49, 0x02, 0x00, 0x8e, 0x09, 0x01, 0x7b, 0xac, 0x7f, 0x00, 0x00, + 0x25, 0x2b, 0x1a, 0x00, 0x04, 0x01, 0x4c, 0xac, 0x48, 0x00, 0x00, 0x1f, + 0xac, 0x17, 0x00, 0x8e, 0x00, 0x02, 0xc1, 0xac, 0xce, 0x00, 0x00, 0x25, + 0xc2, 0x20, 0x00, 0x24, 0x3f, 0xe9, 0x0e, 0x00, 0x00, 0x03, 0xba, 0xaf, + 0xc2, 0x00, 0x00, 0x44, 0xa6, 0x25, 0x00, 0x6e, 0x59, 0x91, 0x0c, 0x00, + 0x22, 0x5b, 0xef, 0x00, 0x00, 0x89, 0x00, 0x02, 0x6b, 0xd0, 0x78, 0x00, + 0x00, 0x22, 0xf0, 0x04, 0x00, 0x1e, 0xab, 0x0f, 0x08, 0x00, 0x00, 0x02, + 0x5c, 0xd0, 0x65, 0x00, 0x00, 0x44, 0x63, 0x05, 0x00, 0x17, 0xab, 0x4e, + 0x1a, 0x00, 0x00, 0x02, 0x6b, 0xaf, 0x78, 0x00, 0x11, 0x00, 0xa4, 0x06, + 0x00, 0x00, 0x22, 0xf0, 0x04, 0x00, 0x00, 0x02, 0x5c, 0xaf, 0x65, 0x00, + 0x0b, 0x18, 0x82, 0x03, 0x00, 0x00, 0x44, 0x63, 0x05, 0x00, 0x95, 0x02, + 0x03, 0x8a, 0xac, 0x88, 0x00, 0x26, 0x00, 0xb6, 0x00, 0x00, 0x49, 0x00, + 0xa6, 0x0b, 0x00, 0x00, 0x25, 0x91, 0x04, 0x00, 0x83, 0x00, 0x02, 0x76, + 0xac, 0x7e, 0x00, 0x16, 0x00, 0x04, 0x0f, 0x00, 0x00, 0x25, 0xdb, 0x07, + 0x00, 0x00, 0x02, 0x5b, 0xac, 0x63, 0x00, 0x0b, 0x18, 0x82, 0x03, 0x00, + 0x00, 0x46, 0xf5, 0x07, 0x00, 0x92, 0x00, 0x01, 0x78, 0xd2, 0x80, 0x00, + 0x00, 0x1f, 0x1d, 0x29, 0x00, 0xc1, 0x32, 0x00, 0x01, 0x45, 0x3a, 0x51, + 0x00, 0x00, 0x18, 0x6f, 0x03, 0x00, 0x00, 0x01, 0x45, 0x3a, 0x51, 0x00, + 0x00, 0x18, 0x82, 0x03, 0x00, 0x8f, 0x00, 0x01, 0x3d, 0x36, 0x4d, 0x00, + 0x00, 0x1b, 0xd7, 0x14, 0x00, 0x00, 0x01, 0x1a, 0x34, 0x3b, 0x00, 0x00, + 0x1c, 0xb3, 0x0b, 0x00, 0x00, 0x02, 0x34, 0x3c, 0x48, 0x00, 0x00, 0x07, + 0x4d, 0x12, 0x00, 0x0e, 0x15, 0x73, 0x12, 0x00, 0x00, 0x01, 0x27, 0xd0, + 0x3e, 0x00, 0x00, 0xab, 0x89, 0x1a, 0x00, 0x00, 0x01, 0x40, 0x36, 0x4e, + 0x00, 0x00, 0x1c, 0x02, 0x25, 0x00, 0x00, 0x02, 0x48, 0x3a, 0x4b, 0x00, + 0x00, 0x18, 0xc0, 0x0b, 0x00, 0x1f, 0x18, 0xcd, 0x0b, 0x00, 0xc0, 0xca, + 0x00, 0x01, 0x85, 0xac, 0x89, 0x00, 0x00, 0x23, 0x4f, 0x26, 0x00, 0x95, + 0x04, 0x01, 0x7e, 0xac, 0x7a, 0x00, 0x00, 0x49, 0x0e, 0x1c, 0x00, 0xdc, + 0x51, 0x00, 0x01, 0x5d, 0x85, 0x5d, 0x00, 0x00, 0x6d, 0xda, 0x0b, 0x00, + 0x00, 0x01, 0xb9, 0x85, 0xb9, 0x00, 0x00, 0x6d, 0xe7, 0x0b, 0x00, 0x82, + 0x00, 0x01, 0x29, 0x5f, 0x34, 0x00, 0x00, 0x25, 0x5e, 0x06, 0x00, 0x00, + 0x01, 0x29, 0x5f, 0x3b, 0x00, 0x00, 0x25, 0x6f, 0x06, 0x00, 0x00, 0x01, + 0x29, 0xc2, 0x39, 0x00, 0x00, 0x88, 0x80, 0x06, 0x00, 0x80, 0x00, 0x02, + 0x56, 0x5f, 0x67, 0x00, 0x00, 0x25, 0x5e, 0x06, 0x00, 0x2d, 0x25, 0xec, + 0x0c, 0x00, 0x00, 0x02, 0x56, 0x5f, 0x69, 0x00, 0x00, 0x25, 0x6f, 0x06, + 0x00, 0x2d, 0x25, 0xfd, 0x0c, 0x00, 0x00, 0x02, 0x56, 0xc2, 0x6c, 0x00, + 0x00, 0x88, 0x80, 0x06, 0x00, 0x2d, 0x88, 0x0e, 0x0d, 0x00, 0x80, 0x00, + 0x01, 0x53, 0xbe, 0x58, 0x00, 0x00, 0x25, 0xcb, 0x17, 0x00, 0x00, 0x01, + 0x53, 0xbe, 0x58, 0x00, 0x00, 0x25, 0x4d, 0x21, 0x00, 0x00, 0x01, 0x42, + 0x88, 0x5c, 0x00, 0x00, 0x46, 0x3e, 0x1c, 0x00, 0x82, 0x00, 0x03, 0x9c, + 0xac, 0xaa, 0x00, 0x00, 0x88, 0x6c, 0x01, 0x00, 0x3d, 0x88, 0xf4, 0x0b, + 0x00, 0x7b, 0x88, 0x6c, 0x01, 0x00, 0x88, 0x00, 0x07, 0xff, 0xaf, 0x04, + 0x00, 0x00, 0x22, 0xb7, 0x06, 0x00, 0x22, 0x22, 0x22, 0x02, 0x00, 0x16, + 0x31, 0xdd, 0x06, 0x00, 0x65, 0x64, 0x03, 0x07, 0x00, 0xb7, 0x64, 0x99, + 0x12, 0x00, 0x7b, 0x74, 0x29, 0x07, 0x00, 0xce, 0x74, 0xbf, 0x12, 0x00, + 0x87, 0x00, 0x01, 0x2d, 0xa0, 0x3e, 0x00, 0x00, 0x4b, 0x6b, 0x04, 0x00, + 0x00, 0x01, 0x2d, 0xa0, 0x3b, 0x00, 0x00, 0x4b, 0x7e, 0x04, 0x00, 0xc0, + 0x70, 0x04, 0x01, 0x78, 0xaf, 0x84, 0x00, 0x00, 0x22, 0x27, 0x2e, 0x00, + 0xc0, 0x74, 0x00, 0x02, 0x78, 0x5a, 0x9e, 0x00, 0x00, 0x25, 0xe5, 0x12, + 0x00, 0x39, 0x25, 0x61, 0x19, 0x00, 0xc0, 0xde, 0x00, 0x02, 0x5b, 0xae, + 0x5f, 0x00, 0x00, 0x30, 0x7e, 0x21, 0x00, 0x19, 0x66, 0xfb, 0x12, 0x00, + 0x82, 0x00, 0x02, 0x81, 0xac, 0x81, 0x00, 0x00, 0x26, 0x01, 0x0c, 0x00, + 0x23, 0x47, 0x64, 0x0a, 0x00, 0x87, 0x00, 0x01, 0x77, 0xcf, 0x84, 0x00, + 0x00, 0x26, 0x21, 0x13, 0x00, 0x80, 0x00, 0x01, 0x7e, 0xcf, 0x81, 0x00, + 0x00, 0x26, 0xea, 0x17, 0x00, 0x00, 0x01, 0x74, 0x7d, 0x87, 0x00, 0x00, + 0x67, 0x79, 0x01, 0x00, 0x81, 0x25, 0x01, 0x69, 0xaf, 0x44, 0x00, 0x00, + 0x22, 0x22, 0x02, 0x00, 0x82, 0x00, 0x01, 0x21, 0x7d, 0x34, 0x00, 0x00, + 0x5a, 0x19, 0x06, 0x00, 0x00, 0x01, 0x75, 0xb0, 0x75, 0x00, 0x00, 0x11, + 0x49, 0x16, 0x00, 0x82, 0x00, 0x03, 0x78, 0x9b, 0x88, 0x00, 0x00, 0x4e, + 0x86, 0x1c, 0x00, 0x0b, 0x64, 0x37, 0x13, 0x00, 0x44, 0x64, 0x5d, 0x13, + 0x00, 0x8b, 0x00, 0x01, 0x68, 0xcd, 0x6c, 0x00, 0x00, 0x1f, 0x80, 0x29, + 0x00, 0x9b, 0x00, 0x02, 0x74, 0x98, 0x87, 0x00, 0x00, 0x4c, 0x16, 0x1f, + 0x00, 0x00, 0x71, 0x62, 0x1f, 0x00, 0x96, 0x00, 0x01, 0x74, 0xad, 0x87, + 0x00, 0x00, 0x37, 0xd7, 0x21, 0x00, 0x82, 0x00, 0x02, 0x74, 0xac, 0x87, + 0x00, 0x00, 0x40, 0x17, 0x0f, 0x00, 0x00, 0x96, 0x0e, 0x0c, 0x00, 0x00, + 0x02, 0x74, 0xac, 0x87, 0x00, 0x00, 0x40, 0x2a, 0x0f, 0x00, 0x00, 0x96, + 0x79, 0x01, 0x00, 0xc3, 0x63, 0x00, 0x02, 0x5b, 0xd7, 0x5b, 0x00, 0x00, + 0x16, 0x1b, 0x0c, 0x00, 0x0a, 0x2c, 0x28, 0x0c, 0x00, 0xfe, 0xff, 0xfe, + 0xff, 0xfe, 0xff, 0xd8, 0x35, 0x00, 0x02, 0x76, 0xac, 0x85, 0x00, 0x00, + 0x1f, 0x08, 0x22, 0x00, 0x55, 0x1f, 0x44, 0x04, 0x00, 0x00, 0x01, 0x77, + 0xac, 0x86, 0x00, 0x00, 0x1f, 0x41, 0x22, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xc4, 0xfd, 0x00, 0xf3, 0x91, 0x00, 0x00, 0x05, 0x8b, 0x00, 0x04, 0xea, + 0x00, 0xe9, 0x00, 0xe9, 0x88, 0x00, 0x00, 0xe9, 0x81, 0x00, 0x07, 0xed, + 0xe9, 0x00, 0xed, 0x00, 0xed, 0x00, 0xec, 0x84, 0x00, 0x00, 0xf3, 0x85, + 0x00, 0x85, 0xea, 0x84, 0xe9, 0x84, 0x00, 0x84, 0xe9, 0x00, 0xed, 0xa0, + 0x00, 0x01, 0xf0, 0xf3, 0x8a, 0x00, 0x81, 0xf3, 0x81, 0x00, 0x00, 0xf3, + 0x87, 0x00, 0x00, 0xec, 0x88, 0x00, 0x81, 0xea, 0x03, 0x00, 0xf3, 0x00, + 0xf3, 0x99, 0x00, 0x00, 0xe9, 0x85, 0x00, 0x00, 0xec, 0x8d, 0x00, 0x04, + 0xe9, 0x00, 0xe9, 0x00, 0xe9, 0x00, 0xec, 0x9e, 0x00, 0x00, 0xf7, 0x82, + 0x00, 0x00, 0xfa, 0x88, 0x00, 0x00, 0xfa, 0x81, 0x00, 0x00, 0xf6, 0x81, + 0x00, 0x00, 0xf8, 0x82, 0x00, 0x00, 0xf7, 0x84, 0x00, 0x00, 0xec, 0x85, + 0x00, 0x85, 0xf7, 0x00, 0x00, 0x83, 0xfa, 0x84, 0x00, 0x84, 0xfa, 0x00, + 0xf8, 0xa0, 0x00, 0x01, 0xf7, 0xfa, 0x8a, 0x00, 0x81, 0xec, 0x81, 0x00, + 0x00, 0xfa, 0x84, 0x00, 0x00, 0x04, 0x81, 0x00, 0x00, 0xf7, 0x88, 0x00, + 0x81, 0xe3, 0x03, 0x00, 0xec, 0x00, 0xec, 0xa0, 0x00, 0x00, 0xf7, 0x02, + 0xf0, 0x00, 0xfb, 0x8a, 0x00, 0x00, 0xfb, 0x90, 0x00, 0x00, 0xf1, 0x82, + 0x00, 0x00, 0xf1, 0x88, 0x00, 0x00, 0xf1, 0x84, 0x00, 0x00, 0xf4, 0x88, + 0x00, 0x02, 0xf0, 0x00, 0xfb, 0x81, 0x00, 0x01, 0xfb, 0x00, 0x85, 0xf1, + 0x00, 0x00, 0x83, 0xf1, 0x84, 0x00, 0x84, 0xf1, 0x00, 0xf4, 0xa0, 0x00, + 0x81, 0xf1, 0x8a, 0x00, 0x81, 0xf0, 0x02, 0xfb, 0xf9, 0xf1, 0x91, 0x00, + 0x05, 0xe0, 0xe6, 0x00, 0xf0, 0x00, 0xf0, 0x85, 0x00, 0x82, 0xfb, 0xa7, + 0x00, 0x02, 0xfb, 0x00, 0xfb, 0x00, 0xf9, 0x8a, 0x00, 0x00, 0xf9, 0x84, + 0x00, 0x00, 0xfe, 0x8e, 0x00, 0x00, 0xfe, 0x88, 0x00, 0x00, 0xfe, 0x84, + 0x00, 0x00, 0xfe, 0x82, 0x00, 0x00, 0xf6, 0x86, 0x00, 0x00, 0xf9, 0x81, + 0x00, 0x01, 0xf9, 0xfe, 0x86, 0x00, 0x83, 0xfe, 0x84, 0x00, 0x85, 0xfe, + 0xa1, 0x00, 0x00, 0xfe, 0x8c, 0x00, 0x02, 0xf9, 0xf8, 0xfe, 0x87, 0x00, + 0x00, 0xf6, 0x88, 0x00, 0x81, 0x04, 0x89, 0x00, 0x82, 0xf9, 0x82, 0xfe, + 0x94, 0x00, 0x00, 0xf6, 0x8e, 0x00, 0x02, 0xf9, 0x00, 0xf9, 0x00, 0xf5, + 0x8c, 0x00, 0x00, 0xfe, 0x90, 0x00, 0x00, 0xf7, 0x82, 0x00, 0x00, 0xf7, + 0x82, 0x00, 0x00, 0xfe, 0x84, 0x00, 0x00, 0xf7, 0x84, 0x00, 0x00, 0xfb, + 0x88, 0x00, 0x00, 0xf5, 0x83, 0x00, 0x01, 0xfe, 0x00, 0x85, 0xf7, 0x00, + 0x00, 0x83, 0xf7, 0x84, 0x00, 0x84, 0xf7, 0x00, 0xfb, 0xa0, 0x00, 0x81, + 0xf7, 0x8a, 0x00, 0x81, 0xf5, 0x81, 0xfe, 0x00, 0xf7, 0x91, 0x00, 0x05, + 0xed, 0xf1, 0x00, 0xf5, 0x00, 0xf5, 0x85, 0x00, 0x82, 0xfe, 0x00, 0xf1, + 0x9e, 0x00, 0x00, 0xfd, 0x90, 0x00, 0x00, 0xfe, 0x84, 0x00, 0x00, 0x04, + 0x84, 0x00, 0x00, 0xf1, 0x85, 0x00, 0x85, 0xfd, 0xb0, 0x00, 0x00, 0xfd, + 0x8b, 0x00, 0x81, 0xf1, 0x85, 0x00, 0x02, 0x04, 0x00, 0x06, 0x81, 0x00, + 0x00, 0x04, 0x88, 0x00, 0x81, 0xdc, 0x03, 0x00, 0xf1, 0x00, 0xf1, 0x99, + 0x00, 0x00, 0xfe, 0x85, 0x00, 0x00, 0x04, 0x8d, 0x00, 0x00, 0xfe, 0x00, + 0xf9, 0x9e, 0x00, 0x00, 0xfb, 0x82, 0x00, 0x00, 0xfb, 0x88, 0x00, 0x00, + 0xfb, 0x81, 0x00, 0x00, 0xfe, 0x8b, 0x00, 0x00, 0xf9, 0x85, 0x00, 0x85, + 0xfb, 0x00, 0x00, 0x83, 0xfb, 0x84, 0x00, 0x84, 0xfb, 0xa1, 0x00, 0x81, + 0xfb, 0x8a, 0x00, 0x81, 0xf9, 0x81, 0x00, 0x00, 0xfb, 0x94, 0x00, 0x02, + 0xf9, 0x00, 0xf9, 0x05, 0xf3, 0xfc, 0xf5, 0xf9, 0x00, 0xf0, 0x9b, 0x00, + 0x00, 0xfb, 0x81, 0x00, 0x00, 0xfb, 0x8a, 0x00, 0x00, 0xfc, 0xcb, 0x00, + 0x02, 0xf1, 0x00, 0xf1, 0x81, 0x00, 0x01, 0xfb, 0xf0, 0x87, 0x00, 0x81, + 0x0b, 0x8c, 0x00, 0x82, 0xfc, 0x93, 0x00, 0x01, 0xf0, 0xfb, 0x00, 0xfb, + 0x83, 0x00, 0x05, 0xe3, 0xfb, 0xe8, 0xf3, 0x00, 0xe5, 0x9e, 0x00, 0x00, + 0xf5, 0x89, 0x00, 0x81, 0xfb, 0xc5, 0x00, 0x81, 0xfb, 0x83, 0x00, 0x02, + 0xd5, 0x00, 0xd7, 0x81, 0x00, 0x01, 0xf5, 0xe5, 0x93, 0x00, 0x85, 0xfb, + 0x93, 0x00, 0x01, 0xe5, 0xf5, 0x00, 0xfb, 0x83, 0x00, 0x05, 0xe3, 0xfb, + 0xe8, 0xf3, 0x00, 0xe5, 0x9e, 0x00, 0x00, 0xf5, 0x89, 0x00, 0x81, 0xfb, + 0xc5, 0x00, 0x81, 0xfb, 0x83, 0x00, 0x02, 0xe0, 0x00, 0xe3, 0x81, 0x00, + 0x01, 0xf5, 0xe5, 0x93, 0x00, 0x85, 0xfb, 0x93, 0x00, 0x01, 0xe5, 0xf5, + 0x00, 0xfb, 0x8a, 0x00, 0x00, 0xfb, 0x94, 0x00, 0x00, 0xfd, 0x9a, 0x00, + 0x00, 0xfb, 0x81, 0x00, 0x00, 0xfb, 0x87, 0x00, 0x83, 0xfd, 0xba, 0x00, + 0x81, 0xfb, 0x92, 0x00, 0x81, 0x04, 0x89, 0x00, 0x82, 0xfb, 0xa7, 0x00, + 0x02, 0xfb, 0x00, 0xfb, 0x00, 0xec, 0x87, 0x00, 0x00, 0xf9, 0x8a, 0x00, + 0x00, 0x04, 0x81, 0x00, 0x00, 0x07, 0xa4, 0x00, 0x00, 0xec, 0xc9, 0x00, + 0x81, 0xec, 0x8b, 0x00, 0x00, 0x07, 0x8a, 0x00, 0x02, 0xec, 0x00, 0xec, + 0x9f, 0x00, 0x00, 0x07, 0x00, 0xea, 0x87, 0x00, 0x00, 0xf9, 0x8d, 0x00, + 0x00, 0x04, 0xa4, 0x00, 0x00, 0xea, 0xc9, 0x00, 0x81, 0xea, 0x8b, 0x00, + 0x00, 0x04, 0x8a, 0x00, 0x02, 0xea, 0x00, 0xea, 0x9f, 0x00, 0x00, 0x04, + 0x00, 0xfd, 0x93, 0x00, 0x01, 0xfd, 0x00, 0x81, 0xfb, 0xa4, 0x00, 0x00, + 0xfd, 0xc9, 0x00, 0x81, 0xfd, 0x8b, 0x00, 0x00, 0xfb, 0x8a, 0x00, 0x02, + 0xfd, 0x00, 0xfd, 0x9f, 0x00, 0x00, 0xfb, 0x00, 0xfd, 0x88, 0x00, 0x00, + 0xfd, 0x9c, 0x00, 0x83, 0xfd, 0x84, 0x00, 0x84, 0xfd, 0xa2, 0x00, 0x00, + 0xfd, 0x8e, 0x00, 0x00, 0xfd, 0x00, 0xf9, 0x83, 0x00, 0x00, 0xf7, 0x9e, + 0x00, 0x00, 0xf9, 0xdc, 0x00, 0x01, 0xf9, 0xf7, 0xad, 0x00, 0x01, 0xf7, + 0xf9, 0x00, 0x04, 0xfd, 0x00, 0x02, 0x07, 0x00, 0x07, 0xaa, 0x00, 0x00, + 0x04, 0x94, 0x00, 0x00, 0x04, 0x00, 0xfc, 0xbc, 0x00, 0x00, 0xfc, 0xc9, + 0x00, 0x81, 0xfc, 0x97, 0x00, 0x02, 0xfc, 0x00, 0xfc, 0x05, 0xdc, 0x00, + 0xe8, 0xee, 0x00, 0xe1, 0xfd, 0x00, 0x00, 0xe1, 0xad, 0x00, 0x00, 0xe1, + 0x00, 0xf4, 0xfd, 0x00, 0x00, 0xf4, 0x87, 0x00, 0x81, 0xfe, 0xa3, 0x00, + 0x00, 0xf4, 0x00, 0xfe, 0x83, 0x00, 0x00, 0xfd, 0xfd, 0x00, 0x00, 0xfd, + 0xad, 0x00, 0x00, 0xfd, 0x03, 0xfa, 0xf7, 0x00, 0xf7, 0xfd, 0x00, 0x00, + 0xf7, 0xad, 0x00, 0x00, 0xf7, 0x00, 0xfc, 0xdc, 0x00, 0x00, 0xfc, 0xaf, + 0x00, 0x00, 0xfc, 0x00, 0xf9, 0x94, 0x00, 0x00, 0xf9, 0x02, 0x08, 0x00, + 0x0d, 0x02, 0x04, 0x00, 0x08, 0x00, 0xf9, 0x32, 0x4e, 0x46, 0x53 +}; +const unsigned int VeraB_len = 17459; diff --git a/DasharoPayloadPkg/CapsuleSplashDxe/SSFN/ssfn.h b/DasharoPayloadPkg/CapsuleSplashDxe/SSFN/ssfn.h new file mode 100644 index 0000000000..85a816ec76 --- /dev/null +++ b/DasharoPayloadPkg/CapsuleSplashDxe/SSFN/ssfn.h @@ -0,0 +1,1598 @@ +/* + * ssfn.h + * https://gitlab.com/bztsrc/scalable-font2 + * + * Copyright (C) 2020 - 2022 bzt + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * @brief Scalable Screen Font renderers + * + */ + +#ifndef _SSFN_H_ +#define _SSFN_H_ + +#define SSFN_VERSION 0x0200 + +#ifdef __cplusplus +extern "C" { +# ifndef __THROW +# define __THROW throw() +# endif +#else +# ifndef __THROW +# define __THROW +# endif +#endif +/* if stdint.h was not included before us */ +#ifndef _STDINT_H +typedef unsigned char uint8_t; +typedef unsigned short int uint16_t; +typedef short int int16_t; +typedef unsigned int uint32_t; +#ifndef _UINT64_T +typedef unsigned long int uint64_t; +#endif +#endif + +/***** file format *****/ + +/* magic bytes */ +#define SSFN_MAGIC "SFN2" +#define SSFN_COLLECTION "SFNC" +#define SSFN_ENDMAGIC "2NFS" + +/* ligatures area */ +#define SSFN_LIG_FIRST 0xF000 +#define SSFN_LIG_LAST 0xF8FF + +/* font family group in font type byte */ +#define SSFN_TYPE_FAMILY(x) ((x)&15) +#define SSFN_FAMILY_SERIF 0 +#define SSFN_FAMILY_SANS 1 +#define SSFN_FAMILY_DECOR 2 +#define SSFN_FAMILY_MONOSPACE 3 +#define SSFN_FAMILY_HAND 4 + +/* font style flags in font type byte */ +#define SSFN_TYPE_STYLE(x) (((x)>>4)&15) +#define SSFN_STYLE_REGULAR 0 +#define SSFN_STYLE_BOLD 1 +#define SSFN_STYLE_ITALIC 2 +#define SSFN_STYLE_USRDEF1 4 /* user defined variant 1 */ +#define SSFN_STYLE_USRDEF2 8 /* user defined variant 2 */ + +/* contour commands */ +#define SSFN_CONTOUR_MOVE 0 +#define SSFN_CONTOUR_LINE 1 +#define SSFN_CONTOUR_QUAD 2 +#define SSFN_CONTOUR_CUBIC 3 + +/* glyph fragments, kerning groups and hinting grid info */ +#define SSFN_FRAG_CONTOUR 0 +#define SSFN_FRAG_BITMAP 1 +#define SSFN_FRAG_PIXMAP 2 +#define SSFN_FRAG_KERNING 3 +#define SSFN_FRAG_HINTING 4 + +/* main SSFN header, 32 bytes */ +#ifndef _MSC_VER +#define _pack __attribute__((packed)) +#else +#define _pack +#pragma pack(push) +#pragma pack(1) +#endif +typedef struct { + uint8_t magic[4]; /* SSFN magic bytes */ + uint32_t size; /* total size in bytes */ + uint8_t type; /* font family and style */ + uint8_t features; /* format features and revision */ + uint8_t width; /* overall width of the font */ + uint8_t height; /* overall height of the font */ + uint8_t baseline; /* horizontal baseline in grid pixels */ + uint8_t underline; /* position of under line in grid pixels */ + uint16_t fragments_offs; /* offset of fragments table */ + uint32_t characters_offs; /* characters table offset */ + uint32_t ligature_offs; /* ligatures table offset */ + uint32_t kerning_offs; /* kerning table offset */ + uint32_t cmap_offs; /* color map offset */ +} _pack ssfn_font_t; +#ifdef _MSC_VER +#pragma pack(pop) +#endif + +/***** renderer API *****/ +#define SSFN_FAMILY_ANY 0xff /* select the first loaded font */ +#define SSFN_FAMILY_BYNAME 0xfe /* select font by its unique name */ + +/* additional styles not stored in fonts */ +#define SSFN_STYLE_UNDERLINE 16 /* under line glyph */ +#define SSFN_STYLE_STHROUGH 32 /* strike through glyph */ +#define SSFN_STYLE_NOAA 64 /* no anti-aliasing */ +#define SSFN_STYLE_NOKERN 128 /* no kerning */ +#define SSFN_STYLE_NODEFGLYPH 256 /* don't draw default glyph */ +#define SSFN_STYLE_NOCACHE 512 /* don't cache rasterized glyph */ +#define SSFN_STYLE_NOHINTING 1024 /* no auto hinting grid (not used as of now) */ +#define SSFN_STYLE_RTL 2048 /* render right-to-left */ +#define SSFN_STYLE_ABS_SIZE 4096 /* scale absoulte height */ +#define SSFN_STYLE_NOSMOOTH 8192 /* no edge-smoothing for bitmaps */ + +/* error codes */ +#define SSFN_OK 0 /* success */ +#define SSFN_ERR_ALLOC -1 /* allocation error */ +#define SSFN_ERR_BADFILE -2 /* bad SSFN file format */ +#define SSFN_ERR_NOFACE -3 /* no font face selected */ +#define SSFN_ERR_INVINP -4 /* invalid input */ +#define SSFN_ERR_BADSTYLE -5 /* bad style */ +#define SSFN_ERR_BADSIZE -6 /* bad size */ +#define SSFN_ERR_NOGLYPH -7 /* glyph (or kerning info) not found */ + +#define SSFN_SIZE_MAX 192 /* biggest size we can render */ +#define SSFN_ITALIC_DIV 4 /* italic angle divisor, glyph top side pushed width / this pixels */ +#define SSFN_PREC 4 /* precision in bits */ + +/* destination frame buffer context */ +typedef struct { + uint8_t *ptr; /* pointer to the buffer */ + int w; /* width (positive: ARGB, negative: ABGR pixels) */ + int h; /* height */ + uint16_t p; /* pitch, bytes per line */ + int x; /* cursor x */ + int y; /* cursor y */ + uint32_t fg; /* foreground color */ + uint32_t bg; /* background color */ +} ssfn_buf_t; + +/* cached bitmap struct */ +#define SSFN_DATA_MAX 65536 +typedef struct { + uint16_t p; /* data buffer pitch, bytes per line */ + uint8_t h; /* data buffer height */ + uint8_t o; /* overlap of glyph, scaled to size */ + uint8_t x; /* advance x, scaled to size */ + uint8_t y; /* advance y, scaled to size */ + uint8_t a; /* ascender, scaled to size */ + uint8_t d; /* descender, scaled to size */ + uint8_t data[SSFN_DATA_MAX]; /* data buffer */ +} ssfn_glyph_t; + +/* character metrics */ +typedef struct { + uint8_t t; /* type and overlap */ + uint8_t n; /* number of fragments */ + uint8_t w; /* width */ + uint8_t h; /* height */ + uint8_t x; /* advance x */ + uint8_t y; /* advance y */ +} ssfn_chr_t; + +#ifdef SSFN_PROFILING +#include +#include +#endif + +/* renderer context */ +typedef struct { +#ifdef SSFN_MAXLINES + const ssfn_font_t *fnt[5][16]; /* static font registry */ +#else + const ssfn_font_t **fnt[5]; /* dynamic font registry */ +#endif + const ssfn_font_t *s; /* explicitly selected font */ + const ssfn_font_t *f; /* font selected by best match */ + ssfn_glyph_t ga; /* glyph sketch area */ + ssfn_glyph_t *g; /* current glyph pointer */ +#ifdef SSFN_MAXLINES + uint16_t p[SSFN_MAXLINES*2]; +#else + ssfn_glyph_t ***c[17]; /* glyph cache */ + uint16_t *p; + char **bufs; /* allocated extra buffers */ +#endif + ssfn_chr_t *rc; /* pointer to current character */ + int numbuf, lenbuf, np, ap, ox, oy, ax; + int mx, my, lx, ly; /* move to coordinates, last coordinates */ + int len[5]; /* number of fonts in registry */ + int family; /* required family */ + int style; /* required style */ + int size; /* required size */ + int line; /* calculate line height */ +#ifdef SSFN_PROFILING + uint64_t lookup, raster, blit, kern;/* profiling accumulators */ +#endif +} ssfn_t; + +/***** API function protoypes *****/ + +uint32_t ssfn_utf8(char **str); /* decode UTF-8 sequence */ + +/* normal renderer */ +int ssfn_load(ssfn_t *ctx, const void *data); /* add an SSFN to context */ +int ssfn_select(ssfn_t *ctx, int family, const char *name, int style, int size); /* select font to use */ +int ssfn_render(ssfn_t *ctx, ssfn_buf_t *dst, const char *str); /* render a glyph to a pixel buffer */ +int ssfn_bbox(ssfn_t *ctx, const char *str, int *w, int *h, int *left, int *top); /* get bounding box */ +ssfn_buf_t *ssfn_text(ssfn_t *ctx, const char *str, unsigned int fg); /* renders text to a newly allocated buffer */ +int ssfn_mem(ssfn_t *ctx); /* return how much memory is used */ +void ssfn_free(ssfn_t *ctx); /* free context */ +#define ssfn_error(err) (err<0&&err>=-7?ssfn_errstr[-err]:"Unknown error") /* return string for error code */ +extern const char *ssfn_errstr[]; + +/* simple renderer */ +extern ssfn_font_t *ssfn_src; /* font buffer */ +extern ssfn_buf_t ssfn_dst; /* destination frame buffer */ +int ssfn_putc(uint32_t unicode); /* render console bitmap font */ + +/***** renderer implementations *****/ + +/*** these go for both renderers ***/ +#if (defined(SSFN_IMPLEMENTATION) || defined(SSFN_CONSOLEBITMAP_PALETTE) || \ + defined(SSFN_CONSOLEBITMAP_HICOLOR) || defined(SSFN_CONSOLEBITMAP_TRUECOLOR)) && !defined(SSFN_COMMON) +#define SSFN_COMMON + +/** + * Error code strings + */ +const char *ssfn_errstr[] = { "", + "Memory allocation error", + "Bad file format", + "No font face found", + "Invalid input value", + "Invalid style", + "Invalid size", + "Glyph not found" +}; + +/** + * Decode an UTF-8 multibyte, advance string pointer and return UNICODE. Watch out, no input checks + * + * @param **s pointer to an UTF-8 string pointer + * @return unicode, and *s moved to next multibyte sequence + */ +uint32_t ssfn_utf8(char **s) +{ + uint32_t c = **s; + + if((**s & 128) != 0) { + if(!(**s & 32)) { c = ((**s & 0x1F)<<6)|(*(*s+1) & 0x3F); *s += 1; } else + if(!(**s & 16)) { c = ((**s & 0xF)<<12)|((*(*s+1) & 0x3F)<<6)|(*(*s+2) & 0x3F); *s += 2; } else + if(!(**s & 8)) { c = ((**s & 0x7)<<18)|((*(*s+1) & 0x3F)<<12)|((*(*s+2) & 0x3F)<<6)|(*(*s+3) & 0x3F); *s += 3; } + else c = 0; + } + (*s)++; + return c; +} +#endif + +#ifdef SSFN_IMPLEMENTATION +/*** normal renderer (ca. 28k, fully featured with error checking) ***/ + +# ifndef NULL +# define NULL (void*)0 +# endif +# ifndef size_t + typedef __SIZE_TYPE__ size_t; +# endif +# ifndef inline +# define inline __inline__ +# endif + +#ifndef _STRING_H_ +extern int memcmp (const void *__s1, const void *__s2, size_t __n) __THROW; +extern void *memset (void *__s, int __c, size_t __n) __THROW; +#endif + +/* Clang does not have built-ins */ +# ifndef SSFN_memcmp +# ifdef __builtin_memcmp +# define SSFN_memcmp __builtin_memcmp +# else +# ifndef SSFN_MAXLINES +# define SSFN_memcmp memcmp +# else +static int SSFN_memcmp(const void *__s1, const void *__s2, size_t __n) +{ unsigned char *a = (unsigned char *)__s1, *b = (unsigned char *)__s2; + if(__n > 0) { while(__n-- > 0) { if(*a != *b) { return *a - *b; } a++; b++; } } return 0; } +# endif +# endif +# endif + +# ifndef SSFN_memset +# ifdef __builtin_memset +# define SSFN_memset __builtin_memset +# else +# ifndef SSFN_MAXLINES +# define SSFN_memset memset +# else +static void *SSFN_memset(void *__s, int __c, size_t __n) +{ unsigned char *a = __s; if(__n > 0) { while(__n-- > 0) *a++ = __c; } return __s; } +# endif +# endif +# endif + +# ifndef SSFN_MAXLINES + +# ifndef SSFN_realloc +# ifdef __builtin_realloc +# define SSFN_realloc __builtin_realloc +# else +# define SSFN_realloc realloc + extern void *realloc (void *__ptr, size_t __size) __THROW; +# endif +# endif + +# ifndef SSFN_free +# ifdef __builtin_free +# define SSFN_free __builtin_free +# else +# define SSFN_free free + extern void free (void *p) __THROW; +# endif +# endif + +# endif /* if !SSFN_MAXLINES */ + +/*** Private functions ***/ + +/* parse character table */ +static uint8_t *_ssfn_c(const ssfn_font_t *font, const char *str, int *len, uint32_t *unicode) +{ + uint32_t i, j, u = -1U; + uint16_t *l; + uint8_t *ptr, *s; + + *len = 0; *unicode = 0; + if(!font || !font->characters_offs || !str || !*str) return NULL; + + if(font->ligature_offs) { + for(l = (uint16_t*)((uint8_t*)font + font->ligature_offs), i = 0; l[i] && u == -1U; i++) { + for(ptr = (uint8_t*)font + l[i], s = (uint8_t*)str; *ptr && *ptr == *s; ptr++, s++); + if(!*ptr) { u = SSFN_LIG_FIRST + i; break; } + } + } + if(u == -1U) { + /* inline ssfn_utf8 to workaround -O2 bug in gcc 11.1 */ + s = (uint8_t*)str; u = *s; + if((*s & 128) != 0) { + if(!(*s & 32)) { u = ((*s & 0x1F)<<6)|(*(s+1) & 0x3F); s++; } else + if(!(*s & 16)) { u = ((*s & 0xF)<<12)|((*(s+1) & 0x3F)<<6)|(*(s+2) & 0x3F); s += 2; } else + if(!(*s & 8)) { u = ((*s & 0x7)<<18)|((*(s+1) & 0x3F)<<12)|((*(s+2) & 0x3F)<<6)|(*(s+3) & 0x3F); s += 3; } + else u = 0; + } + s++; + } + *len = (int)(s - (uint8_t*)str); + *unicode = u; + for(ptr = (uint8_t*)font + font->characters_offs, i = 0; i < 0x110000; i++) { + if(ptr[0] == 0xFF) { i += 65535; ptr++; } + else if((ptr[0] & 0xC0) == 0xC0) { j = (((ptr[0] & 0x3F) << 8) | ptr[1]); i += j; ptr += 2; } + else if((ptr[0] & 0xC0) == 0x80) { j = (ptr[0] & 0x3F); i += j; ptr++; } + else { + if(i == u) return ptr; + ptr += 6 + ptr[1] * (ptr[0] & 0x40 ? 6 : 5); + } + } + return NULL; +} + +/* add a line to contour */ +static void _ssfn_l(ssfn_t *ctx, int p, int h, int x, int y) +{ + if(x < 0 || y < 0 || x >= p || y >= h || ( + ((ctx->lx + (1 << (SSFN_PREC-1))) >> SSFN_PREC) == ((x + (1 << (SSFN_PREC-1))) >> SSFN_PREC) && + ((ctx->ly + (1 << (SSFN_PREC-1))) >> SSFN_PREC) == ((y + (1 << (SSFN_PREC-1))) >> SSFN_PREC))) return; +#ifdef SSFN_MAXLINES + if(ctx->np >= SSFN_MAXLINES*2-2) return; +#else + if(ctx->ap <= ctx->np) { + ctx->ap = ctx->np + 512; + ctx->p = (uint16_t*)SSFN_realloc(ctx->p, ctx->ap * sizeof(uint16_t)); + if(!ctx->p) { ctx->ap = ctx->np = 0; return; } + } +#endif + if(!ctx->np) { + ctx->p[0] = ctx->mx; + ctx->p[1] = ctx->my; + ctx->np += 2; + } + ctx->p[ctx->np+0] = x; + ctx->p[ctx->np+1] = y; + ctx->np += 2; + ctx->lx = x; ctx->ly = y; +} + +/* add a Bezier curve to contour */ +static void _ssfn_b(ssfn_t *ctx, int p,int h, int x0,int y0, int x1,int y1, int x2,int y2, int x3,int y3, int l) +{ + int m0x, m0y, m1x, m1y, m2x, m2y, m3x, m3y, m4x, m4y,m5x, m5y; + if(l<4 && (x0!=x3 || y0!=y3)) { + m0x = ((x1-x0)/2) + x0; m0y = ((y1-y0)/2) + y0; + m1x = ((x2-x1)/2) + x1; m1y = ((y2-y1)/2) + y1; + m2x = ((x3-x2)/2) + x2; m2y = ((y3-y2)/2) + y2; + m3x = ((m1x-m0x)/2) + m0x; m3y = ((m1y-m0y)/2) + m0y; + m4x = ((m2x-m1x)/2) + m1x; m4y = ((m2y-m1y)/2) + m1y; + m5x = ((m4x-m3x)/2) + m3x; m5y = ((m4y-m3y)/2) + m3y; + _ssfn_b(ctx, p,h, x0,y0, m0x,m0y, m3x,m3y, m5x,m5y, l+1); + _ssfn_b(ctx, p,h, m5x,m5y, m4x,m4y, m2x,m2y, x3,y3, l+1); + } + if(l) _ssfn_l(ctx, p,h, x3, y3); +} + +#ifndef SSFN_MAXLINES +static void _ssfn_fc(ssfn_t *ctx) +{ + int i, j, k; + if(!ctx) return; + for(k = 0; k <= 16; k++) + if(ctx->c[k]) { + for(j = 0; j < 256; j++) + if(ctx->c[k][j]) { + for(i = 0; i < 256; i++) + if(ctx->c[k][j][i]) SSFN_free(ctx->c[k][j][i]); + SSFN_free(ctx->c[k][j]); + } + SSFN_free(ctx->c[k]); + ctx->c[k] = NULL; + } +} + +/* + * gzip deflate uncompressor from stb_image.h with minor modifications to reduce dependency + * stb_image - v2.23 - public domain image loader - http://nothings.org/stb_image.h + */ +#define SSFN__ZFAST_BITS 9 +#define SSFN__ZFAST_MASK ((1 << SSFN__ZFAST_BITS) - 1) + +typedef struct +{ + uint16_t fast[1 << SSFN__ZFAST_BITS]; + uint16_t firstcode[16]; + int maxcode[17]; + uint16_t firstsymbol[16]; + unsigned char size[288]; + uint16_t value[288]; +} _ssfn__zhuffman; + +inline static int _ssfn__bitreverse16(int n) +{ + n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); + n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); + n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); + n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); + return n; +} + +inline static int _ssfn__bit_reverse(int v, int bits) +{ + return _ssfn__bitreverse16(v) >> (16-bits); +} + +static int _ssfn__zbuild_huffman(_ssfn__zhuffman *z, unsigned char *sizelist, int num) +{ + int i,k=0; + int code, next_code[16], sizes[17]; + + SSFN_memset(sizes, 0, sizeof(sizes)); + SSFN_memset(z->fast, 0, sizeof(z->fast)); + for (i=0; i < num; ++i) + ++sizes[sizelist[i]]; + sizes[0] = 0; + for (i=1; i < 16; ++i) + if (sizes[i] > (1 << i)) + return 0; + code = 0; + for (i=1; i < 16; ++i) { + next_code[i] = code; + z->firstcode[i] = (uint16_t) code; + z->firstsymbol[i] = (uint16_t) k; + code = (code + sizes[i]); + if (sizes[i]) + if (code-1 >= (1 << i)) return 0; + z->maxcode[i] = code << (16-i); + code <<= 1; + k += sizes[i]; + } + z->maxcode[16] = 0x10000; + for (i=0; i < num; ++i) { + int s = sizelist[i]; + if (s) { + int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; + uint16_t fastv = (uint16_t) ((s << 9) | i); + z->size [c] = (unsigned char) s; + z->value[c] = (uint16_t) i; + if (s <= SSFN__ZFAST_BITS) { + int j = _ssfn__bit_reverse(next_code[s],s); + while (j < (1 << SSFN__ZFAST_BITS)) { + z->fast[j] = fastv; + j += (1 << s); + } + } + ++next_code[s]; + } + } + return 1; +} + +typedef struct +{ + unsigned char *zbuffer; + int num_bits; + uint32_t code_buffer; + + char *zout; + char *zout_start; + char *zout_end; + + _ssfn__zhuffman z_length, z_distance; +} _ssfn__zbuf; + +inline static unsigned char _ssfn__zget8(_ssfn__zbuf *z) +{ + return *z->zbuffer++; +} + +static void _ssfn__fill_bits(_ssfn__zbuf *z) +{ + do { + z->code_buffer |= (unsigned int) _ssfn__zget8(z) << z->num_bits; + z->num_bits += 8; + } while (z->num_bits <= 24); +} + +inline static unsigned int _ssfn__zreceive(_ssfn__zbuf *z, int n) +{ + unsigned int k; + if (z->num_bits < n) _ssfn__fill_bits(z); + k = z->code_buffer & ((1 << n) - 1); + z->code_buffer >>= n; + z->num_bits -= n; + return k; +} + +static int _ssfn__zhuffman_decode_slowpath(_ssfn__zbuf *a, _ssfn__zhuffman *z) +{ + int b,s,k; + k = _ssfn__bit_reverse(a->code_buffer, 16); + for (s=SSFN__ZFAST_BITS+1; ; ++s) + if (k < z->maxcode[s]) + break; + if (s == 16) return -1; + b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; + a->code_buffer >>= s; + a->num_bits -= s; + return z->value[b]; +} + +inline static int _ssfn__zhuffman_decode(_ssfn__zbuf *a, _ssfn__zhuffman *z) +{ + int b,s; + if (a->num_bits < 16) _ssfn__fill_bits(a); + b = z->fast[a->code_buffer & SSFN__ZFAST_MASK]; + if (b) { + s = b >> 9; + a->code_buffer >>= s; + a->num_bits -= s; + return b & 511; + } + return _ssfn__zhuffman_decode_slowpath(a, z); +} + +static int _ssfn__zexpand(_ssfn__zbuf *z, char *zout) +{ + char *q; + unsigned int cur, limit; +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wuse-after-free" +#endif + z->zout = zout; cur = (unsigned int) (z->zout - z->zout_start); limit = (unsigned int) (z->zout_end - z->zout_start); + if(limit == 8) { if(z->zout_start[0] != 'S' || z->zout_start[1] != 'F' || z->zout_start[2] != 'N') return 0; limit = *((uint32_t*)&z->zout_start[4]); } else return 0; + q = (char *) SSFN_realloc(z->zout_start, limit); + if (q == NULL) return 0; + z->zout_start = q; z->zout = q + cur; z->zout_end = q + limit; +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + return 1; +} + +static int _ssfn__zlength_base[31]={3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0}; +static int _ssfn__zlength_extra[31]={0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0}; +static int _ssfn__zdist_base[32]={1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; +static int _ssfn__zdist_extra[32]={0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +static int _ssfn__parse_huffman_block(_ssfn__zbuf *a) +{ + char *zout = a->zout; + for(;;) { + int z = _ssfn__zhuffman_decode(a, &a->z_length); + if (z < 256) { + if (z < 0) return 0; + if (zout >= a->zout_end) { if (!_ssfn__zexpand(a, zout)) return 0; zout = a->zout; } + *zout++ = (char) z; + } else { + unsigned char *p; + int len,dist; + if (z == 256) { a->zout = zout; return 1; } + z -= 257; + len = _ssfn__zlength_base[z]; + if (_ssfn__zlength_extra[z]) len += _ssfn__zreceive(a, _ssfn__zlength_extra[z]); + z = _ssfn__zhuffman_decode(a, &a->z_distance); + if (z < 0) return 0; + dist = _ssfn__zdist_base[z]; + if (_ssfn__zdist_extra[z]) dist += _ssfn__zreceive(a, _ssfn__zdist_extra[z]); + if (zout - a->zout_start < dist) return 0; + if (zout + len > a->zout_end) { + if (!_ssfn__zexpand(a, zout)) return 0; + zout = a->zout; + } + p = (unsigned char *) (zout - dist); + if (dist == 1) {unsigned char v = *p;if (len) { do *zout++ = v; while (--len); } + } else { if (len) { do *zout++ = *p++; while (--len); } } + } + } +} + +static int _ssfn__compute_huffman_codes(_ssfn__zbuf *a) +{ + static unsigned char length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + _ssfn__zhuffman z_codelength; + unsigned char lencodes[286+32+137]; + unsigned char codelength_sizes[19]; + int i,n; + + int hlit = _ssfn__zreceive(a,5) + 257; + int hdist = _ssfn__zreceive(a,5) + 1; + int hclen = _ssfn__zreceive(a,4) + 4; + int ntot = hlit + hdist; + + SSFN_memset(codelength_sizes, 0, sizeof(codelength_sizes)); + for (i=0; i < hclen; ++i) { + int s = _ssfn__zreceive(a,3); + codelength_sizes[length_dezigzag[i]] = (unsigned char) s; + } + if (!_ssfn__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; + + n = 0; + while (n < ntot) { + int c = _ssfn__zhuffman_decode(a, &z_codelength); + if (c < 0 || c >= 19) return 0; + if (c < 16) + lencodes[n++] = (unsigned char) c; + else { + unsigned char fill = 0; + if (c == 16) { + c = _ssfn__zreceive(a,2)+3; + if (n == 0) return 0; + fill = lencodes[n-1]; + } else + if (c == 17) c = _ssfn__zreceive(a,3)+3; + else { c = _ssfn__zreceive(a,7)+11; } + if (ntot - n < c) return 0; + SSFN_memset(lencodes+n, fill, c); + n += c; + } + } + if (n != ntot) return 0; + if (!_ssfn__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; + if (!_ssfn__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; + return 1; +} + +inline static int _ssfn__parse_uncompressed_block(_ssfn__zbuf *a) +{ + unsigned char header[4]; + int len,nlen,k; + if (a->num_bits & 7) + _ssfn__zreceive(a, a->num_bits & 7); + k = 0; + while (a->num_bits > 0) { + header[k++] = (unsigned char) (a->code_buffer & 255); + a->code_buffer >>= 8; + a->num_bits -= 8; + } + while (k < 4) + header[k++] = _ssfn__zget8(a); + len = header[1] * 256 + header[0]; + nlen = header[3] * 256 + header[2]; + if (nlen != (len ^ 0xffff)) return 0; + if (a->zout + len > a->zout_end) + if (!_ssfn__zexpand(a, a->zout)) return 0; + for(k = 0; k < len; k++) + a->zout[k] = a->zbuffer[k]; + a->zbuffer += len; + a->zout += len; + return 1; +} + +static unsigned char _ssfn__zdefault_length[288], _ssfn__zdefault_distance[32]; +static void _ssfn__init_zdefaults(void) +{ + int i; + for (i=0; i <= 143; ++i) _ssfn__zdefault_length[i] = 8; + for ( ; i <= 255; ++i) _ssfn__zdefault_length[i] = 9; + for ( ; i <= 279; ++i) _ssfn__zdefault_length[i] = 7; + for ( ; i <= 287; ++i) _ssfn__zdefault_length[i] = 8; + + for (i=0; i <= 31; ++i) _ssfn__zdefault_distance[i] = 5; +} + +static int _ssfn__parse_zlib(_ssfn__zbuf *a) +{ + int fin, type; + a->num_bits = 0; + a->code_buffer = 0; + do { + fin = _ssfn__zreceive(a,1); + type = _ssfn__zreceive(a,2); + if (type == 0) { if (!_ssfn__parse_uncompressed_block(a)) return 0; } + else if (type == 3) { return 0; } + else { + if (type == 1) { + if (!_ssfn__zbuild_huffman(&a->z_length , _ssfn__zdefault_length , 288)) return 0; + if (!_ssfn__zbuild_huffman(&a->z_distance, _ssfn__zdefault_distance, 32)) return 0; + } else { + if (!_ssfn__compute_huffman_codes(a)) return 0; + } + if (!_ssfn__parse_huffman_block(a)) return 0; + } + } while (!fin); + return 1; +} + +char *_ssfn_zlib_decode(const char *buffer) +{ + _ssfn__zbuf a; + char *p = (char *) SSFN_realloc(NULL, 8); + if (p == NULL) return NULL; + a.zbuffer = (unsigned char *) buffer; + a.zout_start = p; a.zout = p; a.zout_end = p + 8; + _ssfn__init_zdefaults(); + if (_ssfn__parse_zlib(&a)) { return a.zout_start; } else { SSFN_free(a.zout_start); return NULL; } +} +#endif /* if !SSFN_MAXLINES */ + +/*** Public API implementation ***/ + +/** + * Load a font or font collection into renderer context + * + * @param ctx rendering context + * @param font SSFN font or font collection in memory + * @return error code + */ +int ssfn_load(ssfn_t *ctx, const void *data) +{ + const ssfn_font_t *font = (const ssfn_font_t *)data; + ssfn_font_t *fnt, *end; + int family; +#ifndef SSFN_MAXLINES + uint8_t c, r, *ptr = (uint8_t *)font; +#endif + if(!ctx || !font) + return SSFN_ERR_INVINP; + if(((uint8_t *)font)[0] == 0x1f && ((uint8_t *)font)[1] == 0x8b) { +#ifdef SSFN_MAXLINES + return SSFN_ERR_BADFILE; +#else + ptr += 2; + if(*ptr++ != 8) return SSFN_ERR_BADFILE; + c = *ptr++; ptr += 6; + if(c & 4) { r = *ptr++; r += (*ptr++ << 8); ptr += r; } + if(c & 8) { while(*ptr++ != 0); } + if(c & 16) { while(*ptr++ != 0); } + font = (ssfn_font_t*)_ssfn_zlib_decode((const char*)ptr); + if(!font) return SSFN_ERR_BADFILE; + ctx->bufs = (char**)SSFN_realloc(ctx->bufs, (ctx->numbuf + 1) * sizeof(char*)); + if(!ctx->bufs) { ctx->numbuf = 0; return SSFN_ERR_ALLOC; } + ctx->bufs[ctx->numbuf++] = (char*)font; + ctx->lenbuf += font->size; +#endif + } + if(!SSFN_memcmp(font->magic, SSFN_COLLECTION, 4)) { + end = (ssfn_font_t*)((uint8_t*)font + font->size); + for(fnt = (ssfn_font_t*)((uint8_t*)font + 8); fnt < end && !ssfn_load(ctx, (const void *)fnt); + fnt = (ssfn_font_t*)((uint8_t*)fnt + fnt->size)); + } else { + family = SSFN_TYPE_FAMILY(font->type); + if(SSFN_memcmp(font->magic, SSFN_MAGIC, 4) || SSFN_memcmp((uint8_t*)font + font->size - 4, SSFN_ENDMAGIC, 4) || + family > SSFN_FAMILY_HAND || font->fragments_offs >= font->size || font->characters_offs >= font->size || + font->ligature_offs >= font->size || font->kerning_offs >= font->size || font->cmap_offs >= font->size || + font->fragments_offs >= font->characters_offs) { + return SSFN_ERR_BADFILE; + } else { + ctx->len[family]++; +#ifdef SSFN_MAXLINES + if(ctx->len[family] > 15) return SSFN_ERR_ALLOC; +#else + ctx->fnt[family] = (const ssfn_font_t**)SSFN_realloc(ctx->fnt[family], ctx->len[family]*sizeof(void*)); + if(!ctx->fnt[family]) { + ctx->len[family] = 0; + return SSFN_ERR_ALLOC; + } else +#endif + ctx->fnt[family][ctx->len[family]-1] = font; + } +#ifndef SSFN_MAXLINES + _ssfn_fc(ctx); +#endif + } + return SSFN_OK; +} + +/** + * Free renderer context + * + * @param ctx rendering context + */ +void ssfn_free(ssfn_t *ctx) +{ +#ifndef SSFN_MAXLINES + int i; +#endif + if(!ctx) return; +#ifndef SSFN_MAXLINES + _ssfn_fc(ctx); + if(ctx->bufs) { + for(i = 0; i < ctx->numbuf; i++) + if(ctx->bufs[i]) SSFN_free(ctx->bufs[i]); + SSFN_free(ctx->bufs); + } + for(i = 0; i < 5; i++) + if(ctx->fnt[i]) SSFN_free(ctx->fnt[i]); + if(ctx->p) SSFN_free(ctx->p); +#endif + SSFN_memset(ctx, 0, sizeof(ssfn_t)); +} + +/** + * Returns how much memory a context consumes + * + * @param ctx rendering context + * @return total memory used by that context in bytes + */ +int ssfn_mem(ssfn_t *ctx) +{ +#ifdef SSFN_MAXLINES + return ctx ? sizeof(ssfn_t) : 0; +#else + int i, j, k, ret = sizeof(ssfn_t); + + if(!ctx) return 0; + for(i = 0; i < 5; i++) ret += ctx->len[i] * sizeof(ssfn_font_t*); + ret += ctx->lenbuf; + for(k = 0; k <= 16; k++) { + if(ctx->c[k]) { + for(j = 0; j < 256; j++) + if(ctx->c[k][j]) { + for(i = 0; i < 256; i++) + if(ctx->c[k][j][i]) ret += 8 + ctx->c[k][j][i]->p * ctx->c[k][j][i]->h; + ret += 256 * sizeof(void*); + } + ret += 256 * sizeof(void*); + } + } + if(ctx->p) ret += ctx->ap * sizeof(uint16_t); + return ret; +#endif +} + +/** + * Set up rendering parameters + * + * @param ctx rendering context + * @param family one of SSFN_FAMILY_* + * @param name NULL or UTF-8 string if family is SSFN_FAMILY_BYNAME + * @param style OR'd values of SSFN_STYLE_* + * @param size how big glyph it should render, 8 - 192 + * @return error code + */ +int ssfn_select(ssfn_t *ctx, int family, const char *name, int style, int size) +{ + int i, j, l; + + if(!ctx) return SSFN_ERR_INVINP; +#ifndef SSFN_MAXLINES + _ssfn_fc(ctx); +#endif + if((style & ~0x5FFF)) return SSFN_ERR_BADSTYLE; + if(size < 8 || size > SSFN_SIZE_MAX) return SSFN_ERR_BADSIZE; + + if(family == SSFN_FAMILY_BYNAME) { + if(!name || !name[0]) return SSFN_ERR_INVINP; + for(l=0; name[l]; l++); + for(i=0; i < 5; i++) { + for(j=0; j < ctx->len[i]; j++) { + if(!SSFN_memcmp(name, (uint8_t*)&ctx->fnt[i][j]->magic + sizeof(ssfn_font_t), l)) { + ctx->s = ctx->fnt[i][j]; + goto familyfound; + } + } + } + return SSFN_ERR_NOFACE; + } else { + if(family != SSFN_FAMILY_ANY && (family > SSFN_FAMILY_HAND || !ctx->len[family])) return SSFN_ERR_NOFACE; + ctx->s = NULL; + } +familyfound: + ctx->f = NULL; + ctx->family = family; + ctx->style = style; + ctx->size = size; + ctx->line = 0; + return SSFN_OK; +} + +/** + * Render a glyph to a pixel buffer + * + * @param ctx rendering context + * @param dst destination buffer + * @param str pointer to an UTF-8 string + * @return number of bytes parsed in str (zero means end of string) or error code + */ + +int ssfn_render(ssfn_t *ctx, ssfn_buf_t *dst, const char *str) +{ + ssfn_font_t **fl; + uint8_t *ptr = NULL, *frg, *end, *tmp, color, ci = 0, cb = 0, cs, dec[65536]; + uint16_t r[640]; + uint32_t unicode, P, O, *Op, *Ol, sR, sG, sB, sA, bA; + int ret = 0, i, j, k, l, p, m, n, o, s, x, y, w, h, H, a, A, b, B, nr, uix, uax; + int ox, oy, y0, y1, Y0, Y1, x0, x1, X0, X1, X2, xs, ys, yp, pc, fB, fG, fR, fA, bB, bG, bR, dB, dG, dR, dA; +#ifdef SSFN_PROFILING + struct timeval tv0, tv1, tvd; + gettimeofday(&tv0, NULL); +#endif +#define PUTPIXEL O = *Ol;bR = (O >> (16 - cs)) & 0xFF; bG = (O >> 8) & 0xFF; bB = (O >> cs) & 0xFF; bA = (O >> 24) & 0xFF;\ + bB += ((fB - bB) * fA) >> 8; bG += ((fG - bG) * fA) >> 8; bR += ((fR - bR) * fA) >> 8; bA += ((fA - bA) * fA) >> 8;\ + *Ol = (bA << 24) | (bR << (16 - cs)) | (bG << 8) | (bB << cs); + + if(!ctx || !str) return SSFN_ERR_INVINP; + if(!*str) return 0; + if(*str == '\r') { dst->x = 0; return 1; } + if(*str == '\n') { dst->x = 0; dst->y += ctx->line ? ctx->line : ctx->size; return 1; } + + if(ctx->s) { + ctx->f = ctx->s; + ptr = _ssfn_c(ctx->f, str, &ret, &unicode); + } else { + /* find best match */ + p = ctx->family; + ctx->f = NULL; +again: if(p >= SSFN_FAMILY_BYNAME) { n = 0; m = 4; } else n = m = p; + for(; n <= m; n++) { + fl = (ssfn_font_t **)ctx->fnt[n]; + if(ctx->style & 3) { + /* check if we have a specific ctx->f for the requested style and size */ + for(i=0;ilen[n];i++) + if(((fl[i]->type>>4) & 3) == (ctx->style & 3) && fl[i]->height == ctx->size && + (ptr = _ssfn_c(fl[i], str, &ret, &unicode))) { ctx->f = fl[i]; break; } + /* if not, check if we have the requested size (for bitmap fonts) */ + if(!ptr) + for(i=0;ilen[n];i++) + if(fl[i]->height == ctx->size && (ptr = _ssfn_c(fl[i], str, &ret, &unicode))) { ctx->f = fl[i]; break; } + /* if neither size+style nor size matched, look for style match */ + if(!ptr) + for(i=0;ilen[n];i++) + if(((fl[i]->type>>4) & 3) == (ctx->style & 3) && (ptr = _ssfn_c(fl[i], str, &ret, &unicode))) + { ctx->f = fl[i]; break; } + /* if bold italic was requested, check if we have at least bold or italic */ + if(!ptr && (ctx->style & 3) == 3) + for(i=0;ilen[n];i++) + if(((fl[i]->type>>4) & 3) && (ptr = _ssfn_c(fl[i], str, &ret, &unicode))) { ctx->f = fl[i]; break; } + } + /* last resort, get the first ctx->f which has a glyph for this multibyte, no matter style */ + if(!ptr) { + for(i=0;ilen[n];i++) + if((ptr = _ssfn_c(fl[i], str, &ret, &unicode))) { ctx->f = fl[i]; break; } + } + } + /* if glyph still not found, try any family group */ + if(!ptr && p != SSFN_FAMILY_ANY) { p = SSFN_FAMILY_ANY; goto again; } + } + if(!ptr) { + if(ctx->style & SSFN_STYLE_NODEFGLYPH) return SSFN_ERR_NOGLYPH; + else { + unicode = 0; + if(ctx->family >= SSFN_FAMILY_BYNAME) { n = 0; m = 4; } else n = m = ctx->family; + for(; n <= m && !ptr; n++) + if(ctx->len[n] && ctx->fnt[n][0] && !(*((uint8_t*)ctx->fnt[n][0] + ctx->fnt[n][0]->characters_offs) & 0x80)) + { ctx->f = ctx->fnt[n][0]; ptr = (uint8_t*)ctx->f + ctx->f->characters_offs; } + } + if(!ptr) return SSFN_ERR_NOGLYPH; + } + if(!ctx->f || !ctx->f->height || !ctx->size) return SSFN_ERR_NOFACE; + if((unicode >> 16) > 0x10) return SSFN_ERR_INVINP; + ctx->rc = (ssfn_chr_t*)ptr; ptr += sizeof(ssfn_chr_t); + H = (ctx->style & SSFN_STYLE_ABS_SIZE) || SSFN_TYPE_FAMILY(ctx->f->type) == SSFN_FAMILY_MONOSPACE || !ctx->f->baseline ? + ctx->size : ctx->size * ctx->f->height / ctx->f->baseline; + +#ifdef SSFN_PROFILING + gettimeofday(&tv1, NULL); tvd.tv_sec = tv1.tv_sec - tv0.tv_sec; tvd.tv_usec = tv1.tv_usec - tv0.tv_usec; + if(tvd.tv_usec < 0) { tvd.tv_sec--; tvd.tv_usec += 1000000L; } + ctx->lookup += tvd.tv_sec * 1000000L + tvd.tv_usec; + memcpy(&tv0, &tv1, sizeof(struct timeval)); +#endif + /* render glyph into cache */ +#ifndef SSFN_MAXLINES + if(!(ctx->style & SSFN_STYLE_NOCACHE) && ctx->c[unicode >> 16] && ctx->c[unicode >> 16][(unicode >> 8) & 0xFF] && + ctx->c[unicode >> 16][(unicode >> 8) & 0xFF][unicode & 0xFF]) { + ctx->g = ctx->c[unicode >> 16][(unicode >> 8) & 0xFF][unicode & 0xFF]; + } else +#endif + { + h = ctx->style & SSFN_STYLE_NOAA ? H : (ctx->size > ctx->f->height ? (ctx->size + 4) & ~3 : ctx->f->height); + ci = (ctx->style & SSFN_STYLE_ITALIC) && !(SSFN_TYPE_STYLE(ctx->f->type) & SSFN_STYLE_ITALIC); + cb = (ctx->style & SSFN_STYLE_BOLD) && !(SSFN_TYPE_STYLE(ctx->f->type) & SSFN_STYLE_BOLD) ? (ctx->f->height+64)>>6 : 0; + w = (ctx->rc->w * h + ctx->f->height - 1) / ctx->f->height; + if(w > SSFN_SIZE_MAX) { h = h * SSFN_SIZE_MAX / w; w = SSFN_SIZE_MAX; } + p = w + (ci ? h / SSFN_ITALIC_DIV : 0) + cb; + /* failsafe, should never happen */ + if(p * h >= SSFN_DATA_MAX) return SSFN_ERR_BADSIZE; +#ifndef SSFN_MAXLINES + if(!(ctx->style & SSFN_STYLE_NOCACHE)) { + if(!ctx->c[unicode >> 16]) { + ctx->c[unicode >> 16] = (ssfn_glyph_t***)SSFN_realloc(NULL, 256 * sizeof(void*)); + if(!ctx->c[unicode >> 16]) return SSFN_ERR_ALLOC; + SSFN_memset(ctx->c[unicode >> 16], 0, 256 * sizeof(void*)); + } + if(!ctx->c[unicode >> 16][(unicode >> 8) & 0xFF]) { + ctx->c[unicode >> 16][(unicode >> 8) & 0xFF] = (ssfn_glyph_t**)SSFN_realloc(NULL, 256 * sizeof(void*)); + if(!ctx->c[unicode >> 16][(unicode >> 8) & 0xFF]) return SSFN_ERR_ALLOC; + SSFN_memset(ctx->c[unicode >> 16][(unicode >> 8) & 0xFF], 0, 256 * sizeof(void*)); + } + ctx->g = ctx->c[unicode >> 16][(unicode >> 8) & 0xFF][unicode & 0xFF] = (ssfn_glyph_t*)SSFN_realloc(NULL, p * h + 8); + if(!ctx->c[unicode >> 16][(unicode >> 8) & 0xFF][unicode & 0xFF]) return SSFN_ERR_ALLOC; + } else +#endif + ctx->g = &ctx->ga; + x = (ctx->rc->x > 0 && ci ? (ctx->f->height - ctx->f->baseline) * h / SSFN_ITALIC_DIV / ctx->f->height : 0); + ctx->g->p = p; + ctx->g->h = h; + ctx->g->x = (ctx->rc->x + x > 255 ? 255 : ctx->rc->x + x); + ctx->g->y = ctx->rc->y; + ctx->g->o = (ctx->rc->t & 0x3F) + x; + SSFN_memset(&ctx->g->data, 0xFF, p * h); + color = 0xFE; ctx->g->a = ctx->g->d = 0; + for(n = 0; n < ctx->rc->n; n++) { + if(ptr[0] == 255 && ptr[1] == 255) { color = ptr[2]; ptr += ctx->rc->t & 0x40 ? 6 : 5; continue; } + x = ((ptr[0] + cb) << SSFN_PREC) * h / ctx->f->height; y = (ptr[1] << SSFN_PREC) * h / ctx->f->height; + if(ctx->rc->t & 0x40) { m = (ptr[5] << 24) | (ptr[4] << 16) | (ptr[3] << 8) | ptr[2]; ptr += 6; } + else { m = (ptr[4] << 16) | (ptr[3] << 8) | ptr[2]; ptr += 5; } + frg = (uint8_t*)ctx->f + m; + if(!(frg[0] & 0x80)) { + /* contour */ + j = (frg[0] & 0x3F); + if(frg[0] & 0x40) { j <<= 8; j |= frg[1]; frg++; } + j++; frg++; tmp = frg; frg += (j+3)/4; ctx->np = 0; + for(i = 0; i < j; i++) { + k = (frg[0] << SSFN_PREC) * h / ctx->f->height + x; m = (frg[1] << SSFN_PREC) * h / ctx->f->height + y; + switch((tmp[i >> 2] >> ((i & 3) << 1)) & 3) { + case SSFN_CONTOUR_MOVE: ctx->mx = ctx->lx = k; ctx->my = ctx->ly = m; frg += 2; break; + case SSFN_CONTOUR_LINE: _ssfn_l(ctx, p << SSFN_PREC, h << SSFN_PREC, k, m); frg += 2; break; + case SSFN_CONTOUR_QUAD: + a = (frg[2] << SSFN_PREC) * h / ctx->f->height + x; A = (frg[3] << SSFN_PREC) * h / ctx->f->height + y; + _ssfn_b(ctx, p << SSFN_PREC,h << SSFN_PREC, ctx->lx,ctx->ly, ((a-ctx->lx)/2)+ctx->lx, + ((A-ctx->ly)/2)+ctx->ly, ((k-a)/2)+a,((A-m)/2)+m, k,m, 0); + frg += 4; + break; + case SSFN_CONTOUR_CUBIC: + a = (frg[2] << SSFN_PREC) * h / ctx->f->height + x; A = (frg[3] << SSFN_PREC) * h / ctx->f->height + y; + b = (frg[4] << SSFN_PREC) * h / ctx->f->height + x; B = (frg[5] << SSFN_PREC) * h / ctx->f->height + y; + _ssfn_b(ctx, p << SSFN_PREC,h << SSFN_PREC, ctx->lx,ctx->ly, a,A, b,B, k,m, 0); + frg += 6; + break; + } + } + /* close path */ + if(ctx->mx != ctx->lx || ctx->my != ctx->ly) { ctx->p[ctx->np+0] = ctx->mx; ctx->p[ctx->np+1] = ctx->my; ctx->np += 2; } + /* add rasterized vector layers to cached glyph */ + if(ctx->np > 4) { + for(b = A = B = o = 0; b < h; b++, B += p) { + a = b << SSFN_PREC; + for(nr = 0, i = 0; i < ctx->np - 3; i += 2) { + if( (ctx->p[i+1] < a && ctx->p[i+3] >= a) || + (ctx->p[i+3] < a && ctx->p[i+1] >= a)) { + if((ctx->p[i+1] >> SSFN_PREC) == (ctx->p[i+3] >> SSFN_PREC)) + x = (((int)ctx->p[i]+(int)ctx->p[i+2])>>1); + else + x = ((int)ctx->p[i]) + ((a - (int)ctx->p[i+1])* + ((int)ctx->p[i+2] - (int)ctx->p[i])/ + ((int)ctx->p[i+3] - (int)ctx->p[i+1])); + x >>= SSFN_PREC; + if(ci) x += (h - b) / SSFN_ITALIC_DIV; + if(cb && !o) { + if(ctx->g->data[B + x] != color) { o = -cb; A = cb; } + else { o = cb; A = -cb; } + } + for(k = 0; k < nr && x > r[k]; k++); + for(l = nr; l > k; l--) r[l] = r[l-1]; + r[k] = x; + nr++; + } + } + if(nr > 1 && nr & 1) { r[nr - 2] = r[nr - 1]; nr--; } + if(nr) { + if(ctx->g->d < y + b) ctx->g->d = y + b; + for(i = 0; i < nr - 1; i += 2) { + l = r[i] + o; m = r[i + 1] + A; + if(l < 0) l = 0; + if(m > p) m = p; + if(i > 0 && l < r[i - 1] + A) l = r[i - 1] + A; + for(; l < m; l++) + ctx->g->data[B + l] = ctx->g->data[B + l] == color ? 0xFF : color; + } + } + } + } + } else if((frg[0] & 0x60) == 0x00) { + /* bitmap */ + B = ((frg[0] & 0x1F) + 1) << 3; A = frg[1] + 1; x >>= SSFN_PREC; y >>= SSFN_PREC; + b = B * h / ctx->f->height; a = A * h / ctx->f->height; + if(ctx->g->d < y + a) ctx->g->d = y + a; + frg += 2; + for(j = 0; j < a; j++) { + k = j * A / a; + l = (y + j) * p + x + (ci ? (h - y - j) / SSFN_ITALIC_DIV : 0); + for(i = 0; i < b; i++) { + m = i * B / b; + if(frg[(k * B + m) >> 3] & (1 << (m & 7))) { + for(o = 0; o <= cb; o++) + ctx->g->data[l + i + o] = color; + } + } + } + if(!(ctx->style & (SSFN_STYLE_NOAA|SSFN_STYLE_NOSMOOTH))) { + m = color == 0xFD ? 0xFC : 0xFD; o = y * p + p + x; + for(k = h; k > ctx->f->height + 4; k -= 2*ctx->f->height) { + for(j = 1, l = o; j < a - 1; j++, l += p) + for(i = 1; i < b - 1; i++) { + if(ctx->g->data[l + i] == 0xFF && (ctx->g->data[l + i - p] == color || + ctx->g->data[l + i + p] == color) && (ctx->g->data[l + i - 1] == color || + ctx->g->data[l + i + 1] == color)) ctx->g->data[l + i] = m; + } + for(j = 1, l = o; j < a - 1; j++, l += p) + for(i = 1; i < b - 1; i++) { + if(ctx->g->data[l + i] == m) ctx->g->data[l + i] = color; + } + } + } + } else if((frg[0] & 0x60) == 0x20) { + /* pixmap */ + k = (((frg[0] & 0x1F) << 8) | frg[1]) + 1; B = frg[2] + 1; A = frg[3] + 1; x >>= SSFN_PREC; y >>= SSFN_PREC; + b = B * h / ctx->f->height; a = A * h / ctx->f->height; + if(ctx->g->d < y + a) ctx->g->d = y + a; + frg += 4; end = frg + k; i = 0; + while(frg < end) { + l = ((*frg++) & 0x7F) + 1; + if(frg[-1] & 0x80) { + while(l--) dec[i++] = *frg; + frg++; + } else while(l--) dec[i++] = *frg++; + } + for(j = 0; j < a; j++) { + k = j * A / a * B; + l = (y + j) * p + x + (ci ? (h - y - j) / SSFN_ITALIC_DIV : 0); + for(i = 0; i < b; i++) { + m = dec[k + i * B / b]; + if(m != 0xFF) ctx->g->data[l + i] = m; + } + } + } + color = 0xFE; + } + ctx->g->a = ctx->f->baseline; + if(ctx->g->d > ctx->g->a + 1) ctx->g->d -= ctx->g->a + 1; else ctx->g->d = 0; +#ifdef SSFN_DEBUGGLYPH + printf("\nU+%06X size %d p %d h %d base %d under %d overlap %d ascender %d descender %d advance x %d advance y %d cb %d\n", + unicode, ctx->size,p,h,ctx->f->baseline,ctx->f->underline,ctx->g->o,ctx->g->a,ctx->g->d,ctx->g->x,ctx->g->y,cb); + for(j = 0; j < h; j++) { printf("%3d: ", j); for(i = 0; i < p; i++) { if(ctx->g->data[j*p+i] == 0xFF) printf(j == ctx->g->a ? "_" : "."); else printf("%x", ctx->g->data[j*p+i] & 0xF); } printf("\n"); } +#endif +#ifdef SSFN_PROFILING + gettimeofday(&tv1, NULL); tvd.tv_sec = tv1.tv_sec - tv0.tv_sec; tvd.tv_usec = tv1.tv_usec - tv0.tv_usec; + if(tvd.tv_usec < 0) { tvd.tv_sec--; tvd.tv_usec += 1000000L; } + ctx->raster += tvd.tv_sec * 1000000L + tvd.tv_usec; + memcpy(&tv0, &tv1, sizeof(struct timeval)); +#endif + } + if(dst) { + /* blit glyph from cache into buffer */ + h = H; + if(h > ctx->line) ctx->line = h; + w = ctx->g->p * h / ctx->g->h; + s = ((ctx->g->x - ctx->g->o) * h + ctx->f->height - 1) / ctx->f->height; + n = ctx->size > 16 ? 2 : 1; + if(w < n) w = n; + if(s < n) s = n; + if(ctx->g->x) { + ctx->ox = ox = ((ctx->g->o * h + ctx->f->height - 1) / ctx->f->height) + (ctx->style & SSFN_STYLE_RTL ? w : 0); + ctx->oy = oy = (ctx->g->a * h + ctx->f->height - 1) / ctx->f->height; + } else { ctx->ox = ox = w / 2; ctx->oy = oy = 0; } + if(dst->ptr) { + j = dst->w < 0 ? -dst->w : dst->w; + cs = dst->w < 0 ? 16 : 0; + cb = (h + 64) >> 6; uix = w > s ? w : s; uax = 0; + n = (ctx->f->underline * h + ctx->f->height - 1) / ctx->f->height; +#ifdef SSFN_DEBUGGLYPH + printf("Scaling to w %d h %d (glyph %d %d, cache %d %d, font %d)\n", + w,h,ctx->rc->w,ctx->rc->h,ctx->g->p,ctx->g->h,ctx->f->height); +#endif + fR = (dst->fg >> 16) & 0xFF; fG = (dst->fg >> 8) & 0xFF; fB = (dst->fg >> 0) & 0xFF; fA = (dst->fg >> 24) & 0xFF; + bR = (dst->bg >> 16) & 0xFF; bG = (dst->bg >> 8) & 0xFF; bB = (dst->bg >> 0) & 0xFF; O = 0xFF000000; + Op = (uint32_t*)(dst->ptr + dst->p * (dst->y - oy) + ((dst->x - ox) << 2)); + for (y = 0; y < h && dst->y + y - oy < dst->h; y++, Op += dst->p >> 2) { + if(dst->y + y - oy < 0) continue; + y0 = (y << 8) * ctx->g->h / h; Y0 = y0 >> 8; y1 = ((y + 1) << 8) * ctx->g->h / h; Y1 = y1 >> 8; Ol = Op; + for (x = 0; x < w && dst->x + x - ox < j; x++, Ol++) { + if(dst->x + x - ox < 0) continue; + m = 0; sR = sG = sB = sA = bA = 0; + if(!dst->bg) { + /* real linear frame buffers should be accessed only as uint32_t on 32 bit boundary */ + O = *Ol; + bA = (O >> 24) & 0xFF; + bR = (O >> (16 - cs)) & 0xFF; + bG = (O >> 8) & 0xFF; + bB = (O >> cs) & 0xFF; + } + x0 = (x << 8) * ctx->g->p / w; X0 = x0 >> 8; x1 = ((x + 1) << 8) * ctx->g->p / w; X1 = x1 >> 8; + for(ys = y0; ys < y1; ys += 256) { + if(ys >> 8 == Y0) { yp = 256 - (ys & 0xFF); ys &= ~0xFF; if(yp > y1 - y0) yp = y1 - y0; } + else if(ys >> 8 == Y1) yp = y1 & 0xFF; else yp = 256; + X2 = (ys >> 8) * ctx->g->p; + for(xs = x0; xs < x1; xs += 256) { + if (xs >> 8 == X0) { + k = 256 - (xs & 0xFF); xs &= ~0xFF; if(k > x1 - x0) k = x1 - x0; pc = k == 256 ? yp : (k * yp)>>8; + } else + if (xs >> 8 == X1) { k = x1 & 0xFF; pc = k == 256 ? yp : (k * yp) >> 8; } + else pc = yp; + m += pc; + k = ctx->g->data[X2 + (xs >> 8)]; + if(k == 0xFF) { + sB += bB * pc; sG += bG * pc; sR += bR * pc; sA += 255; + } else { + if(k == 0xFE || !ctx->f->cmap_offs) { + dB = fB; dG = fG; dR = fR; dA = fA; + } else { + P = *((uint32_t*)((uint8_t*)ctx->f + ctx->f->cmap_offs + (k << 2))); + dR = (P >> 16) & 0xFF; dG = (P >> 8) & 0xFF; dB = (P >> 0) & 0xFF; dA = (P >> 24) & 0xFF; + } + if(dA == 255) { + sB += dB * pc; sG += dG * pc; sR += dR * pc; sA += dA * pc; + } else { + sB += (dB * dA + bB * (255 - dA)) * pc / 255; sG += (dG * dA + bG * (255 - dA)) * pc / 255; + sR += (dR * dA + bR * (255 - dA)) * pc / 255; sA += dA * pc; + } + } + } + } + if(m) { sR /= m; sG /= m; sB /= m; sA /= m; } else { sR >>= 8; sG >>= 8; sB >>= 8; sA >>= 8; } + if(ctx->style & SSFN_STYLE_NOAA) sA = sA > 127 ? 255 : 0; + if(sA > 15) { + *Ol = ((sA > 255 ? 255 : (sA > bA ? sA : bA)) << 24) | + ((sR > 255 ? 255 : sR) << (16 - cs)) | ((sG > 255 ? 255 : sG) << 8) | ((sB > 255 ? 255 : sB) << cs); + if(y == n) { if(uix > x) { uix = x; } if(uax < x) { uax = x; } } + } + } + } + if(ctx->style & SSFN_STYLE_UNDERLINE) { + uix -= cb + 1; uax += cb + 2; + if(uax < uix) uax = uix + 1; + k = (w > s ? w : s); + Op = (uint32_t*)(dst->ptr + dst->p * (dst->y - oy + n) + ((dst->x - ox - 1) << 2)); + for (y = n; y < n + cb && dst->y + y - oy < dst->h; y++, Op += dst->p >> 2) { + if(dst->y + y - oy < 0) continue; + for (Ol = Op, x = 0; x <= k && dst->x + x - ox < j; x++, Ol++) { + if(dst->x + x - ox < 0 || (x > uix && x < uax)) continue; + PUTPIXEL; + } + } + } + if(ctx->style & SSFN_STYLE_STHROUGH) { + n = (h >> 1); k = (w > s ? w : s) + 1; + Op = (uint32_t*)(dst->ptr + dst->p * (dst->y - oy + n) + ((dst->x - ox - 1) << 2)); + for (y = n; y < n + cb && dst->y + y - oy < dst->h; y++, Op += dst->p >> 2) { + if(dst->y + y - oy < 0) continue; + for (Ol = Op, x = 0; x <= k && dst->x + x - ox < j; x++, Ol++) { + if(dst->x + x - ox < 0) continue; + PUTPIXEL; + } + } + } +#ifdef SSFN_PROFILING + gettimeofday(&tv1, NULL); tvd.tv_sec = tv1.tv_sec - tv0.tv_sec;tvd.tv_usec = tv1.tv_usec - tv0.tv_usec; + if(tvd.tv_usec < 0) { tvd.tv_sec--; tvd.tv_usec += 1000000L; } + ctx->blit += tvd.tv_sec * 1000000L + tvd.tv_usec; + memcpy(&tv0, &tv1, sizeof(struct timeval)); +#endif + } + /* add advance and kerning */ + ctx->ax = (ctx->style & SSFN_STYLE_RTL ? -s : s); + dst->x += ctx->ax; + dst->y += (ctx->g->y * h + ctx->f->height - 1) / ctx->f->height; + ptr = (uint8_t*)str + ret; + if(!(ctx->style & SSFN_STYLE_NOKERN) && ctx->f->kerning_offs && _ssfn_c(ctx->f, (const char*)ptr, &i, &P) && P > 32) { + ptr = (uint8_t*)ctx->rc + sizeof(ssfn_chr_t); + /* check all kerning fragments, because we might have both vertical and horizontal kerning offsets */ + for(n = 0; n < ctx->rc->n; n++) { + if(ptr[0] == 255 && ptr[1] == 255) { ptr += ctx->rc->t & 0x40 ? 6 : 5; continue; } + x = ptr[0]; + if(ctx->rc->t & 0x40) { m = (ptr[5] << 24) | (ptr[4] << 16) | (ptr[3] << 8) | ptr[2]; ptr += 6; } + else { m = (ptr[4] << 16) | (ptr[3] << 8) | ptr[2]; ptr += 5; } + frg = (uint8_t*)ctx->f + m; + if((frg[0] & 0xE0) == 0xC0) { + k = (((frg[0] & 0x1F) << 8) | frg[1]) + 1; frg += 2; + while(k--) { + m = ((frg[2] & 0xF) << 16) | (frg[1] << 8) | frg[0]; + if(P >= (uint32_t)m && P <= (uint32_t)(((frg[5] & 0xF) << 16) | (frg[4] << 8) | frg[3])) { + P -= m; + m = ctx->f->kerning_offs + ((((frg[2] >> 4) & 0xF) << 24) | (((frg[5] >> 4) & 0xF) << 16) | + (frg[7] << 8) | frg[6]); + tmp = (uint8_t*)ctx->f + m; + while(tmp < (uint8_t*)ctx->f + ctx->f->size - 4) { + if((tmp[0] & 0x7F) < P) { + P -= (tmp[0] & 0x7F) + 1; + tmp += 2 + (tmp[0] & 0x80 ? 0 : tmp[0] & 0x7F); + } else { + y = (int)((signed char)tmp[1 + ((tmp[0] & 0x80) ? 0 : P)]) * h / ctx->f->height; + if(x) dst->x += y; else dst->y += y; + break; + } + } + break; + } + frg += 8; + } + } + } +#ifdef SSFN_PROFILING + gettimeofday(&tv1, NULL); tvd.tv_sec = tv1.tv_sec - tv0.tv_sec; tvd.tv_usec = tv1.tv_usec - tv0.tv_usec; + if(tvd.tv_usec < 0) { tvd.tv_sec--; tvd.tv_usec += 1000000L; } + ctx->kern += tvd.tv_sec * 1000000L + tvd.tv_usec; +#endif + } + } + return ret; +} + +/** + * Get the bounding box for a string + + * @param ctx rendering context + * @param str string to measure + * @param w returned width + * @param h returned height + * @param left returned left margin + * @param top returned ascender + * @return error code + */ +int ssfn_bbox(ssfn_t *ctx, const char *str, int *w, int *h, int *left, int *top) +{ + ssfn_buf_t buf; + int ret, f = 1, l = 0, t = 0; + + if(!ctx || !str) return SSFN_ERR_INVINP; + if(w) {*w = 0;} if(h) {*h = 0;} if(top) {*top = 0;} if(left) {*left = 0;} + if(!*str) return SSFN_OK; + SSFN_memset(&buf, 0, sizeof(ssfn_buf_t)); ctx->line = 0; + while((ret = ssfn_render(ctx, &buf, str))) { + if(ret < 0 || !ctx->g) return ret; + if(f) { f = 0; l = ctx->ox; buf.x += l; } + if(ctx->g->x) { + if(ctx->oy > t) t = ctx->oy; + } else { + if(buf.w < ctx->g->p) buf.w = ctx->g->p; + buf.h += ctx->g->y ? ctx->g->y : ctx->g->h; + } + str += ret; + } + if((ctx->style & SSFN_STYLE_ITALIC) && !(SSFN_TYPE_STYLE(ctx->f->type) & SSFN_STYLE_ITALIC)) + buf.x += ctx->size / SSFN_ITALIC_DIV - l; + if(ctx->g->x) { if(w) {*w = buf.x;} if(h) {*h = ctx->line;} if(left) {*left = l;} if(top) {*top = t;} } + else { if(w) {*w = buf.w;} if(h) {*h = buf.y;} if(top) {*top = 0;} if(left) {*left = 0;} } + return SSFN_OK; +} + +/** + * Render text to a newly allocated pixel buffer + * + * @param ctx rendering context + * @param str string to measure + * @return a newly allocated pixel buffer or NULL + */ +ssfn_buf_t *ssfn_text(ssfn_t *ctx, const char *str, unsigned int fg) +{ +#ifndef SSFN_MAXLINES + ssfn_buf_t *buf; + int ret; + + if(!ctx || !str) return NULL; + buf = (ssfn_buf_t*)SSFN_realloc(NULL, sizeof(ssfn_buf_t)); + if(!buf) return NULL; + SSFN_memset(buf, 0, sizeof(ssfn_buf_t)); + buf->fg = fg; + if(!*str || ssfn_bbox(ctx, str, (int*)&buf->w, (int*)&buf->h, (int*)&buf->x, (int*)&buf->y) != SSFN_OK) + return buf; + buf->p = buf->w * sizeof(uint32_t); + buf->ptr = (uint8_t*)SSFN_realloc(NULL, buf->p * buf->h); + SSFN_memset(buf->ptr, 0, buf->p * buf->h); + while((ret = ssfn_render(ctx, buf, str)) > 0) + str += ret; + if(ret != SSFN_OK) { SSFN_free(buf->ptr); SSFN_free(buf); return NULL; } + return buf; +#else + (void)ctx; + (void)str; + (void)fg; + return NULL; +#endif +} + +#endif /* SSFN_IMPLEMENTATION */ + +#if defined(SSFN_CONSOLEBITMAP_PALETTE) || defined(SSFN_CONSOLEBITMAP_HICOLOR) || defined(SSFN_CONSOLEBITMAP_TRUECOLOR) +/*** special console bitmap font renderer (ca. 1.5k, no dependencies, no memory allocation and no error checking) ***/ + +/** + * public variables to configure + */ +ssfn_font_t *ssfn_src; /* font buffer with an inflated bitmap font */ +ssfn_buf_t ssfn_dst; /* destination frame buffer */ + +/** + * Minimal OS kernel console renderer + * + * @param unicode character + * @return error code + */ +int ssfn_putc(uint32_t unicode) +{ +# ifdef SSFN_CONSOLEBITMAP_PALETTE +# define SSFN_PIXEL uint8_t +# else +# ifdef SSFN_CONSOLEBITMAP_HICOLOR +# define SSFN_PIXEL uint16_t +# else +# define SSFN_PIXEL uint32_t +# endif +# endif + register SSFN_PIXEL *o, *p; + register uint8_t *ptr, *chr = NULL, *frg; + register int i, j, k, l, m, y = 0, w, s = ssfn_dst.p / sizeof(SSFN_PIXEL); + + if(!ssfn_src || ssfn_src->magic[0] != 'S' || ssfn_src->magic[1] != 'F' || ssfn_src->magic[2] != 'N' || + ssfn_src->magic[3] != '2' || !ssfn_dst.ptr || !ssfn_dst.p) return SSFN_ERR_INVINP; + w = ssfn_dst.w < 0 ? -ssfn_dst.w : ssfn_dst.w; + for(ptr = (uint8_t*)ssfn_src + ssfn_src->characters_offs, i = 0; i < 0x110000; i++) { + if(ptr[0] == 0xFF) { i += 65535; ptr++; } + else if((ptr[0] & 0xC0) == 0xC0) { j = (((ptr[0] & 0x3F) << 8) | ptr[1]); i += j; ptr += 2; } + else if((ptr[0] & 0xC0) == 0x80) { j = (ptr[0] & 0x3F); i += j; ptr++; } + else { if((uint32_t)i == unicode) { chr = ptr; break; } ptr += 6 + ptr[1] * (ptr[0] & 0x40 ? 6 : 5); } + } +#ifdef SSFN_CONSOLEBITMAP_CONTROL + i = ssfn_src->height; j = ssfn_dst.h - i - (ssfn_dst.h % i); + if(chr && w) { + if(unicode == '\t') ssfn_dst.x -= ssfn_dst.x % chr[4]; + if(ssfn_dst.x + chr[4] > w) { ssfn_dst.x = 0; ssfn_dst.y += i; } + } + if(unicode == '\n') ssfn_dst.y += i; + if(j > 0 && ssfn_dst.y > j) { + ssfn_dst.y = j; + for(k = 0; k < j; k++) + for(l = 0; l < ssfn_dst.p; l++) ssfn_dst.ptr[k * ssfn_dst.p + l] = ssfn_dst.ptr[(k + i) * ssfn_dst.p + l]; + } + if(unicode == '\r' || unicode == '\n') { ssfn_dst.x = 0; return SSFN_OK; } +#endif + if(!chr) return SSFN_ERR_NOGLYPH; + ptr = chr + 6; o = (SSFN_PIXEL*)(ssfn_dst.ptr + ssfn_dst.y * ssfn_dst.p + ssfn_dst.x * sizeof(SSFN_PIXEL)); + for(i = 0; i < chr[1]; i++, ptr += chr[0] & 0x40 ? 6 : 5) { + if(ptr[0] == 255 && ptr[1] == 255) continue; + frg = (uint8_t*)ssfn_src + (chr[0] & 0x40 ? ((ptr[5] << 24) | (ptr[4] << 16) | (ptr[3] << 8) | ptr[2]) : + ((ptr[4] << 16) | (ptr[3] << 8) | ptr[2])); + if((frg[0] & 0xE0) != 0x80) continue; + if(ssfn_dst.bg) { + for(; y < ptr[1] && (!ssfn_dst.h || ssfn_dst.y + y < ssfn_dst.h); y++, o += s) { + for(p = o, j = 0; j < chr[2] && (!w || ssfn_dst.x + j < w); j++, p++) + *p = ssfn_dst.bg; + } + } else { o += (int)(ptr[1] - y) * s; y = ptr[1]; } + k = ((frg[0] & 0x1F) + 1) << 3; j = frg[1] + 1; frg += 2; + for(m = 1; j && (!ssfn_dst.h || ssfn_dst.y + y < ssfn_dst.h); j--, y++, o += s) + for(p = o, l = 0; l < k; l++, p++, m <<= 1) { + if(m > 0x80) { frg++; m = 1; } + if(ssfn_dst.x + l >= 0 && (!w || ssfn_dst.x + l < w)) { + if(*frg & m) *p = ssfn_dst.fg; else + if(ssfn_dst.bg) *p = ssfn_dst.bg; + } + } + } + if(ssfn_dst.bg) + for(; y < chr[3] && (!ssfn_dst.h || ssfn_dst.y + y < ssfn_dst.h); y++, o += s) { + for(p = o, j = 0; j < chr[2] && (!w || ssfn_dst.x + j < w); j++, p++) + *p = ssfn_dst.bg; + } + ssfn_dst.x += chr[4]; ssfn_dst.y += chr[5]; + return SSFN_OK; +} + +#endif /* SSFN_CONSOLEBITMAP */ + +#ifdef __cplusplus +} +/*** SSFN C++ Wrapper Class ***/ +#include + +namespace SSFN { +#ifndef SSFN_IMPLEMENTATION + class Font { + public: + Font(); + ~Font(); + + public: + int Load(const std::string &data); + int Load(const void *data, int len); + int Select(int family, const std::string &name, int style, int size); + int Select(int family, const char *name, int style, int size); + int Render(ssfn_buf_t *dst, const std::string &str); + int Render(ssfn_buf_t *dst, const char *str); + int BBox(const std::string &str, int *w, int *h, int *left, int *top); + int BBox(const char *str, int *w, int *h, int *left, int *top); + ssfn_buf_t *Text(const std::string &str, unsigned int fg); + ssfn_buf_t *Text(const char *str, unsigned int fg); + int LineHeight(); + int Mem(); + const std::string ErrorStr(int err); + }; +#else + class Font { + private: + ssfn_t ctx; + + public: + Font() { SSFN_memset(&this->ctx, 0, sizeof(ssfn_t)); } + ~Font() { ssfn_free(&this->ctx); } + + public: + int Load(const std::string &data) { return ssfn_load(&this->ctx,reinterpret_cast(data.data())); } + int Load(const void *data) { return ssfn_load(&this->ctx, data); } + int Select(int family, const std::string &name, int style, int size) + { return ssfn_select(&this->ctx, family, (char*)name.data(), style, size); } + int Select(int family, char *name, int style, int size) { return ssfn_select(&this->ctx,family,name,style,size); } + int Render(ssfn_buf_t *dst, const std::string &str) { return ssfn_render(&this->ctx,dst,(const char *)str.data()); } + int Render(ssfn_buf_t *dst, const char *str) { return ssfn_render(&this->ctx, dst, str); } + int BBox(const std::string &str, int *w, int *h, int *left, int *top) + { return ssfn_bbox(&this->ctx, (const char *)str.data(), w, h, left, top); } + int BBox(const char *str, int *w, int *h, int *left, int *top) { return ssfn_bbox(&this->ctx,str,w,h,left,top); } + ssfn_buf_t *Text(const std::string &str, unsigned int fg) + { return ssfn_text(&this->ctx,(const char*)str.data(), fg); } + ssfn_buf_t *Text(const char *str, unsigned int fg) { return ssfn_text(&this->ctx, str, fg); } + int LineHeight() { return this->ctx.line ? this->ctx.line : this->ctx.size; } + int Mem() { return ssfn_mem(&this->ctx); } + const std::string ErrorStr(int err) { return std::string(ssfn_error(err)); } + }; +#endif +} +#endif +/* */ +/* */ +#endif /* _SSFN_H_ */ diff --git a/DasharoPayloadPkg/DasharoPayloadPkg.dec b/DasharoPayloadPkg/DasharoPayloadPkg.dec new file mode 100644 index 0000000000..9fa3c919d7 --- /dev/null +++ b/DasharoPayloadPkg/DasharoPayloadPkg.dec @@ -0,0 +1,103 @@ +## @file +# UEFI Payload Package +# +# Provides drivers and definitions to create uefi payload for bootloaders. +# +# Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = DasharoPayloadPkg + PACKAGE_GUID = E0FC9D50-415E-4946-B686-9A130D5859E7 + PACKAGE_VERSION = 0.1 + +[Includes] + Include + + +[Guids] + # + ## Defines the token space for the UEFI Payload Package PCDs. + # + gDasharoPayloadPkgTokenSpaceGuid = {0x66d719f9, 0xfa16, 0x4729, {0xa9, 0xb5, 0x23, 0xad, 0xd4, 0xc6, 0x8e, 0x93}} + + # + # Gop Temp + # + gBmpImageGuid = { 0x878AC2CC, 0x5343, 0x46F2, { 0xB5, 0x63, 0x51, 0xF8, 0x9D, 0xAF, 0x56, 0xBA } } + + gUefiSystemTableInfoGuid = {0x16c8a6d0, 0xfe8a, 0x4082, {0xa2, 0x8, 0xcf, 0x89, 0xc4, 0x29, 0x4, 0x33}} + gUefiAcpiBoardInfoGuid = {0xad3d31b, 0xb3d8, 0x4506, {0xae, 0x71, 0x2e, 0xf1, 0x10, 0x6, 0xd9, 0xf}} + gUefiSerialPortInfoGuid = { 0x6c6872fe, 0x56a9, 0x4403, { 0xbb, 0x98, 0x95, 0x8d, 0x62, 0xde, 0x87, 0xf1 } } + gLoaderMemoryMapInfoGuid = { 0xa1ff7424, 0x7a1a, 0x478e, { 0xa9, 0xe4, 0x92, 0xf3, 0x57, 0xd1, 0x28, 0x32 } } + gEfiSmmStoreInfoHobGuid = { 0xf585ca19, 0x881b, 0x44fb, { 0x3f, 0x3d, 0x81, 0x89, 0x7c, 0x57, 0xbb, 0x01 } } + gEfiTcgPhysicalPresenceInfoHobGuid = { 0xf367be59, 0x5891, 0x40eb, { 0x21, 0x44, 0xed, 0x2e, 0xac, 0x57, 0xfd, 0x14 }} + + ## GUID used for ApuConfigurationUi FormSet guid and related variables. + gApuConfigurationFormsetGuid = {0x6f4e051b, 0x1c10, 0x422a, {0x98, 0xcf, 0x96, 0x2e, 0x78, 0x36, 0x5c, 0x74} } + +[Ppis] + gEfiPayLoadHobBasePpiGuid = { 0xdbe23aa1, 0xa342, 0x4b97, {0x85, 0xb6, 0xb2, 0x26, 0xf1, 0x61, 0x73, 0x89} } + +[Protocols] + # + # Gop Temp + # + gPlatformGOPPolicyGuid = { 0xec2e931b, 0x3281, 0x48a5, { 0x81, 0x07, 0xdf, 0x8a, 0x8b, 0xed, 0x3c, 0x5d } } + +################################################################################ +# +# PCD Declarations section - list of all PCDs Declared by this Package +# Only this package should be providing the +# declaration, other packages should not. +# +################################################################################ +[PcdsFixedAtBuild, PcdsPatchableInModule] +## Indicates the base address of the payload binary in memory +gDasharoPayloadPkgTokenSpaceGuid.PcdPayloadFdMemBase|0|UINT32|0x10000001 +## Provides the size of the payload binary in memory +gDasharoPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize|0|UINT32|0x10000002 +## Payload stack top +gDasharoPayloadPkgTokenSpaceGuid.PcdPayloadStackTop|0x90000|UINT32|0x10000004 + +## FFS filename to find the shell application. +gDasharoPayloadPkgTokenSpaceGuid.PcdShellFile|{ 0x83, 0xA5, 0x04, 0x7C, 0x3E, 0x9E, 0x1c, 0x4f, 0xAD, 0x65, 0xE0, 0x52, 0x68, 0xD0, 0xB4, 0xD1 }|VOID*|0x10000005 + +### FFS filename to find the ipxe application. +gDasharoPayloadPkgTokenSpaceGuid.PcdiPXEFile|{ 0xC7, 0x53, 0x86, 0xb6, 0xA1, 0xEE, 0x35, 0x44, 0xA1, 0x99, 0xA4, 0x4F, 0x59, 0xE4, 0x47, 0x6C }|VOID*|0x10000006 +gDasharoPayloadPkgTokenSpaceGuid.PcdiPXEOptionName|L"iPXE"|VOID*|0x10000007 + + +## Used to help reduce fragmentation in the EFI memory map +gDasharoPayloadPkgTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory|0x08|UINT32|0x10000012 +gDasharoPayloadPkgTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS|0x04|UINT32|0x10000013 +gDasharoPayloadPkgTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType|0x04|UINT32|0x00000014 +gDasharoPayloadPkgTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData|0xC0|UINT32|0x00000015 +gDasharoPayloadPkgTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode|0x80|UINT32|0x00000016 +## Used to block PCI OptionROM loading +gDasharoPayloadPkgTokenSpaceGuid.PcdLoadOptionRoms|TRUE|BOOLEAN|0x10000017 +## Used to skip PS/2 keyboard detection. +# Useful for laptops where the PS/2 keyboard is always connected. +# If set to TRUE, Boot Manager will unconditionally add PS keyboard to ConIn. +gDasharoPayloadPkgTokenSpaceGuid.PcdSkipPs2Detect|FALSE|BOOLEAN|0x10000018 + +[PcdsFixedAtBuild] +## Specifies the initial value for Register_A in RTC. +# @Prompt Initial value for Register_A in RTC. +gPcAtChipsetPkgTokenSpaceGuid.PcdInitialValueRtcRegisterA|0x26|UINT8|0x00000006 + +## Specifies the initial value for Register_B in RTC. +# @Prompt Initial value for Register_B in RTC. +gPcAtChipsetPkgTokenSpaceGuid.PcdInitialValueRtcRegisterB|0x02|UINT8|0x00000002 + +## Specifies the scan code of the key to enter boot menu +gDasharoPayloadPkgTokenSpaceGuid.PcdBootMenuKey|0x0016|UINT16|0x00000007 + +## Specifies the scan code of the key to enter boot menu +gDasharoPayloadPkgTokenSpaceGuid.PcdSetupMenuKey|0x0017|UINT16|0x00000008 + +gDasharoPayloadPkgTokenSpaceGuid.PcdPrintSolStrings|FALSE|BOOLEAN|0x0000000A +gDasharoPayloadPkgTokenSpaceGuid.PcdSerialOnSuperIo|FALSE|BOOLEAN|0x0000000B diff --git a/DasharoPayloadPkg/DasharoPayloadPkg.dsc b/DasharoPayloadPkg/DasharoPayloadPkg.dsc new file mode 100644 index 0000000000..cfbbf37a09 --- /dev/null +++ b/DasharoPayloadPkg/DasharoPayloadPkg.dsc @@ -0,0 +1,1051 @@ +## @file +# Bootloader Payload Package +# +# Provides drivers and definitions to create uefi payload for bootloaders. +# +# Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + PLATFORM_NAME = DasharoPayloadPkg + PLATFORM_GUID = 9EE9C760-A126-41E6-8D35-42FFF29C8DC8 + PLATFORM_VERSION = 0.1 + DSC_SPECIFICATION = 0x00010005 + SUPPORTED_ARCHITECTURES = IA32|X64 + BUILD_TARGETS = DEBUG|RELEASE|NOOPT + SKUID_IDENTIFIER = DEFAULT + OUTPUT_DIRECTORY = Build/DasharoPayloadPkgX64 + FLASH_DEFINITION = DasharoPayloadPkg/DasharoPayloadPkg.fdf + + DEFINE SOURCE_DEBUG_ENABLE = FALSE + DEFINE PS2_KEYBOARD_ENABLE = FALSE + + # + # SBL: UEFI payload for Slim Bootloader + # COREBOOT: UEFI payload for coreboot + # + DEFINE BOOTLOADER = SBL + + # + # CPU options + # + DEFINE MAX_LOGICAL_PROCESSORS = 64 + + # + # Serial port set up + # + DEFINE BAUD_RATE = 115200 + DEFINE SERIAL_CLOCK_RATE = 1843200 + DEFINE SERIAL_LINE_CONTROL = 3 # 8-bits, no parity + DEFINE SERIAL_HARDWARE_FLOW_CONTROL = FALSE + DEFINE SERIAL_DETECT_CABLE = FALSE + DEFINE SERIAL_FIFO_CONTROL = 7 # Enable FIFO + DEFINE SERIAL_EXTENDED_TX_FIFO_SIZE = 16 + DEFINE UART_DEFAULT_BAUD_RATE = $(BAUD_RATE) + DEFINE UART_DEFAULT_DATA_BITS = 8 + DEFINE UART_DEFAULT_PARITY = 1 + DEFINE UART_DEFAULT_STOP_BITS = 1 + DEFINE DEFAULT_TERMINAL_TYPE = 4 + + DEFINE UART_ON_SUPERIO = FALSE + + DEFINE BOOT_MENU_KEY = 0x0016 + DEFINE SETUP_MENU_KEY = 0x0017 + + DEFINE PLATFORM_BOOT_TIMEOUT = 5 + + # + # typedef struct { + # UINT16 VendorId; ///< Vendor ID to match the PCI device. The value 0xFFFF terminates the list of entries. + # UINT16 DeviceId; ///< Device ID to match the PCI device + # UINT32 ClockRate; ///< UART clock rate. Set to 0 for default clock rate of 1843200 Hz + # UINT64 Offset; ///< The byte offset into to the BAR + # UINT8 BarIndex; ///< Which BAR to get the UART base address + # UINT8 RegisterStride; ///< UART register stride in bytes. Set to 0 for default register stride of 1 byte. + # UINT16 ReceiveFifoDepth; ///< UART receive FIFO depth in bytes. Set to 0 for a default FIFO depth of 16 bytes. + # UINT16 TransmitFifoDepth; ///< UART transmit FIFO depth in bytes. Set to 0 for a default FIFO depth of 16 bytes. + # UINT8 Reserved[2]; + # } PCI_SERIAL_PARAMETER; + # + # Vendor FFFF Device 0000 Prog Interface 1, BAR #0, Offset 0, Stride = 1, Clock 1843200 (0x1c2000) + # + # [Vendor] [Device] [----ClockRate---] [------------Offset-----------] [Bar] [Stride] [RxFifo] [TxFifo] [Rsvd] [Vendor] + DEFINE PCI_SERIAL_PARAMETERS = {0xff,0xff, 0x00,0x00, 0x0,0x20,0x1c,0x00, 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x00, 0x01, 0x0,0x0, 0x0,0x0, 0x0,0x0, 0xff,0xff} + + # + # Shell options: [BUILD_SHELL, MIN_BIN, NONE, UEFI_BIN] + # + DEFINE SHELL_TYPE = BUILD_SHELL + + # For recent X86 CPU, 0x15 CPUID instruction will return Time Stamp Counter Frequence. + # This is how BaseCpuTimerLib works, and a recommended way to get Frequence, so set the default value as TRUE. + # Note: for emulation platform such as QEMU, this may not work and should set it as FALSE + DEFINE CPU_TIMER_LIB_ENABLE = TRUE + + # + # Security options: + # + DEFINE SECURE_BOOT_ENABLE = FALSE + DEFINE SECURE_BOOT_DEFAULT_ENABLE = TRUE + DEFINE TPM_ENABLE = TRUE + DEFINE SATA_PASSWORD_ENABLE = FALSE + DEFINE OPAL_PASSWORD_ENABLE = FALSE + DEFINE LOAD_OPTION_ROMS = TRUE + DEFINE DASHARO_SYSTEM_FEATURES_ENABLE = FALSE + DEFINE SETUP_PASSWORD_ENABLE = FALSE + DEFINE USE_CBMEM_FOR_CONSOLE = FALSE + DEFINE SYSTEM76_EC_LOGGING = FALSE + DEFINE ABOVE_4G_MEMORY = TRUE + DEFINE IOMMU_ENABLE = FALSE + DEFINE SD_MMC_TIMEOUT = 1000000 + DEFINE BATTERY_CHECK = FALSE + DEFINE PERFORMANCE_MEASUREMENT_ENABLE = FALSE + DEFINE RAM_DISK_ENABLE = FALSE + DEFINE APU_CONFIG_ENABLE = FALSE + DEFINE USE_PLATFORM_GOP = FALSE + DEFINE USE_LAPTOP_LID_LIB = FALSE + DEFINE USE_UEFIVAR_BACKED_TPM_PPI = FALSE + DEFINE CAPSULE_SUPPORT = FALSE + DEFINE CAPSULE_MAIN_FW_GUID = + + # + # Network definition + # + DEFINE NETWORK_PXE_BOOT = FALSE + DEFINE NETWORK_ENABLE = FALSE + DEFINE NETWORK_TLS_ENABLE = FALSE + DEFINE NETWORK_IP6_ENABLE = FALSE + DEFINE NETWORK_IP4_ENABLE = TRUE + DEFINE NETWORK_LAN_ROM = FALSE + +!if $(NETWORK_PXE_BOOT) == TRUE + DEFINE NETWORK_SNP_ENABLE = TRUE + DEFINE NETWORK_HTTP_BOOT_ENABLE = FALSE + DEFINE NETWORK_ISCSI_ENABLE = FALSE +!else + DEFINE NETWORK_SNP_ENABLE = FALSE + DEFINE NETWORK_HTTP_BOOT_ENABLE = TRUE + DEFINE NETWORK_ALLOW_HTTP_CONNECTIONS = TRUE + DEFINE NETWORK_ISCSI_ENABLE = TRUE +!endif + + +!include NetworkPkg/NetworkDefines.dsc.inc + # + # IPXE support + # + DEFINE NETWORK_IPXE = FALSE + +[BuildOptions] + *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES -Wno-stringop-overflow +!if $(USE_CBMEM_FOR_CONSOLE) == FALSE + GCC:RELEASE_*_*_CC_FLAGS = -DMDEPKG_NDEBUG + INTEL:RELEASE_*_*_CC_FLAGS = /D MDEPKG_NDEBUG + MSFT:RELEASE_*_*_CC_FLAGS = /D MDEPKG_NDEBUG +!endif + + +################################################################################ +# +# SKU Identification section - list of all SKU IDs supported by this Platform. +# +################################################################################ +[SkuIds] + 0|DEFAULT + +################################################################################ +# +# Library Class section - list of all Library Classes needed by this Platform. +# +################################################################################ +[LibraryClasses] + # + # Entry point + # + PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf + PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf + DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf + UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf + UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf + + # + # Basic + # + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf + BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf + SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf + PciLib|DasharoPayloadPkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf + PciExpressLib|DasharoPayloadPkg/Library/BasePciExpressLib/BasePciExpressLib.inf + PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf + PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf + SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf + RngLib|DasharoPayloadPkg/Library/BaseRngLib/BaseRngLib.inf + + # + # UEFI & PI + # + UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf + HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf + PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf + PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf + SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf + + # + # Generic Modules + # + UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf + UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf + OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf + SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf + UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf + BootLogoLib|MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf + BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf + CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf + FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf + + # + # Capsule Updates + # +!if $(CAPSULE_SUPPORT) == TRUE + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf + # At the moment there are no update checks to do, so null-library suffices + CapsuleUpdatePolicyLib|FmpDevicePkg/Library/CapsuleUpdatePolicyLibNull/CapsuleUpdatePolicyLibNull.inf + DisplayUpdateProgressLib|MdeModulePkg/Library/DisplayUpdateProgressLibGraphics/DisplayUpdateProgressLibGraphics.inf + FmpAuthenticationLib|SecurityPkg/Library/FmpAuthenticationLibPkcs7/FmpAuthenticationLibPkcs7.inf + FmpDependencyCheckLib|FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.inf + # No need to save/restore FMP dependencies until they are utilized + FmpDependencyDeviceLib|FmpDevicePkg/Library/FmpDependencyDeviceLibNull/FmpDependencyDeviceLibNull.inf + FmpDependencyLib|FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.inf + FmpDeviceLib|DasharoPayloadPkg/Library/FmpDeviceSmmLib/FmpDeviceSmmLib.inf + FmpPayloadHeaderLib|FmpDevicePkg/Library/FmpPayloadHeaderLibV1/FmpPayloadHeaderLibV1.inf +!else + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf +!endif + + # + # CPU + # + MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf + LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf + MicrocodeLib|UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.inf + CpuPageTableLib|UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf + CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf + BaseCpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf + + # + # Platform + # +!if $(CPU_TIMER_LIB_ENABLE) == TRUE + TimerLib|UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf +!else + TimerLib|DasharoPayloadPkg/Library/AcpiTimerLib/AcpiTimerLib.inf +!endif + ResetSystemLib|DasharoPayloadPkg/Library/ResetSystemLib/ResetSystemLib.inf +!if (($(USE_CBMEM_FOR_CONSOLE) == TRUE) && ($(TARGET) == RELEASE)) + SerialPortLib|UefiPayloadPkg/Library/CbSerialPortLib/CbSerialPortLib.inf + PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf +!elseif $(SYSTEM76_EC_LOGGING) == TRUE + SerialPortLib|DasharoPayloadPkg/Library/System76EcLib/System76EcLib.inf + PlatformHookLib|DasharoPayloadPkg/Library/System76EcLib/System76EcLib.inf +!else + SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf + PlatformHookLib|DasharoPayloadPkg/Library/PlatformHookLib/PlatformHookLib.inf +!endif + PlatformBootManagerLib|DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf + IoApicLib|PcAtChipsetPkg/Library/BaseIoApicLib/BaseIoApicLib.inf + + # + # Misc + # + DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf +!if $(SOURCE_DEBUG_ENABLE) == TRUE + PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf + DebugCommunicationLib|SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.inf +!else + PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf + DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf +!endif + PlatformSupportLib|DasharoPayloadPkg/Library/PlatformSupportLibNull/PlatformSupportLibNull.inf +!if $(BOOTLOADER) == "COREBOOT" + BlParseLib|DasharoPayloadPkg/Library/CbParseLib/CbParseLib.inf +!else + BlParseLib|DasharoPayloadPkg/Library/SblParseLib/SblParseLib.inf +!endif + FmapLib|DasharoPayloadPkg/Library/FmapLib/FmapLib.inf + CbfsLib|DasharoPayloadPkg/Library/CbfsLib/CbfsLib.inf + EfiVarsLib|DasharoPayloadPkg/Library/EfiVarsLib/EfiVarsLib.inf + + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf + FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf + TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf + VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf + RegisterFilterLib|MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf + VariableFlashInfoLib|MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseVariableFlashInfoLib.inf + VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf + VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf + + DasharoVariablesLib|DasharoModulePkg/Library/DasharoVariablesLib/DasharoVariablesLib.inf + + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf + +!if $(OPAL_PASSWORD_ENABLE) == TRUE + TcgStorageCoreLib|SecurityPkg/Library/TcgStorageCoreLib/TcgStorageCoreLib.inf + TcgStorageOpalLib|SecurityPkg/Library/TcgStorageOpalLib/TcgStorageOpalLib.inf +!endif + S3BootScriptLib|MdePkg/Library/BaseS3BootScriptLibNull/BaseS3BootScriptLibNull.inf + +# +# Network +# +!include NetworkPkg/NetworkLibs.dsc.inc + + MbedTlsLib|CryptoPkg/Library/MbedTlsLib/MbedTlsLib.inf + MbedTlsCrtLib|CryptoPkg/Library/MbedTlsCrtLib/MbedTlsCrtLib.inf +!if $(NETWORK_TLS_ENABLE) == TRUE + TlsLib|CryptoPkg/Library/TlsLib/TlsLib.inf +!endif + +!if $(SECURE_BOOT_ENABLE) == TRUE + PlatformSecureLib|OvmfPkg/Library/PlatformSecureLib/PlatformSecureLib.inf + AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf + SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf + SecureBootVariableProvisionLib|SecurityPkg/Library/SecureBootVariableProvisionLib/SecureBootVariableProvisionLib.inf + PlatformPKProtectionLib|SecurityPkg/Library/PlatformPKProtectionLibVarPolicy/PlatformPKProtectionLibVarPolicy.inf +!else + AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf +!endif + + # + # SMMSTORE + # +!if $(BOOTLOADER) == "COREBOOT" + SmmStoreLib|DasharoPayloadPkg/Library/SmmStoreLib/SmmStoreLib.inf +!endif + +!if $(TPM_ENABLE) == TRUE + Tpm12CommandLib|SecurityPkg/Library/Tpm12CommandLib/Tpm12CommandLib.inf + Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf + +!if $(USE_UEFIVAR_BACKED_TPM_PPI) == TRUE + Tcg2PhysicalPresenceLib|SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.inf +!else + Tcg2PhysicalPresenceLib|OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf + Tcg2PhysicalPresencePlatformLib|DasharoPayloadPkg/Library/Tcg2PhysicalPresencePlatformLibUefipayload/DxeTcg2PhysicalPresencePlatformLib.inf +!endif + Tcg2PpVendorLib|SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.inf + TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf +!else + TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf + Tcg2PhysicalPresenceLib|OvmfPkg/Library/Tcg2PhysicalPresenceLibNull/DxeTcg2PhysicalPresenceLib.inf +!endif + +!if $(USE_PLATFORM_GOP) == TRUE +!if $(USE_LAPTOP_LID_LIB) == TRUE + LaptopLidLib|DasharoPayloadPkg/Library/LaptopLidLib/LaptopLidLib.inf +!else + LaptopLidLib|DasharoPayloadPkg/Library/LaptopLidLib/LaptopLidLibNull.inf +!endif +!endif + +[LibraryClasses.IA32.SEC] + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf + MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf + DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf + ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf + PerformanceLib|MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.inf + +[LibraryClasses.IA32.PEI_CORE, LibraryClasses.IA32.PEIM] + PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf + HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf + PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf + MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf + ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf + PerformanceLib|MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.inf +!if $(SOURCE_DEBUG_ENABLE) + DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf +!endif + +[LibraryClasses.common.PEIM] +!if $(TPM_ENABLE) == TRUE + BaseCryptLib|CryptoPkg/Library/BaseCryptLibMbedTls/PeiCryptLib.inf + Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12DeviceLibDTpm.inf + Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.inf + Tcg2PhysicalPresenceLib|SecurityPkg/Library/PeiTcg2PhysicalPresenceLib/PeiTcg2PhysicalPresenceLib.inf +!endif + PerformanceLib|MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.inf + +[LibraryClasses.common.DXE_CORE] + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf + MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf + ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf + PerformanceLib|MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf +!if $(SOURCE_DEBUG_ENABLE) + DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf +!endif + CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLibMbedTls/BaseCryptLib.inf + +[LibraryClasses.common.DXE_DRIVER] + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf + PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf +!if $(SOURCE_DEBUG_ENABLE) + DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf +!endif + CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf + MpInitLib|UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLibMbedTls/BaseCryptLib.inf +!if $(TPM_ENABLE) == TRUE + Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.inf + Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.inf +!endif +!if $(BATTERY_CHECK) + LaptopBatteryLib|DasharoPayloadPkg/Library/LaptopBatteryLib/LaptopBatteryLib.inf +!else + LaptopBatteryLib|DasharoPayloadPkg/Library/LaptopBatteryLib/LaptopBatteryLibNull.inf +!endif + +[LibraryClasses.common.DXE_RUNTIME_DRIVER] + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/RuntimeDxeReportStatusCodeLib.inf + VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLibMbedTls/RuntimeCryptLib.inf + DebugLib|MdeModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf + PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf + MbedTlsCrtLib|CryptoPkg/Library/MbedTlsCrtRuntimeLib/MbedTlsCrtRuntimeLib.inf +!if $(CAPSULE_SUPPORT) == TRUE + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf +!endif + +[LibraryClasses.common.UEFI_DRIVER,LibraryClasses.common.UEFI_APPLICATION] + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLibMbedTls/BaseCryptLib.inf + DebugLib|MdeModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf + +################################################################################ +# +# Pcd Section - list of all EDK II PCD Entries defined by this Platform. +# +################################################################################ +[PcdsFeatureFlag] + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutUgaSupport|FALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics|TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwarePerformanceDataTableS3Support|FALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdInstallAcpiSdtProtocol|TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdPs2KbdExtendedVerification|TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdSupportUpdateCapsuleReset|$(CAPSULE_SUPPORT) + +[PcdsFixedAtBuild] + # UEFI spec: Minimal value is 0x8000! + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x8000 + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x8800 + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize|0x8000 + gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x10000 + gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress|0x0 + gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable|TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile|{ 0x21, 0xaa, 0x2c, 0x46, 0x14, 0x76, 0x03, 0x45, 0x83, 0x6e, 0x8a, 0xb6, 0xf4, 0x66, 0x23, 0x31 } + gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|8000 + # 4K displays may need bigger buffers for the option strings in forms + gEfiMdePkgTokenSpaceGuid.PcdMaximumUnicodeStringLength|2000000 + gDasharoPayloadPkgTokenSpaceGuid.PcdBootMenuKey|$(BOOT_MENU_KEY) + gDasharoPayloadPkgTokenSpaceGuid.PcdSetupMenuKey|$(SETUP_MENU_KEY) + gDasharoPayloadPkgTokenSpaceGuid.PcdLoadOptionRoms|$(LOAD_OPTION_ROMS) + + gEfiMdeModulePkgTokenSpaceGuid.PcdSdMmcGenericTimeoutValue|$(SD_MMC_TIMEOUT) + gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleFmpSupport|$(CAPSULE_SUPPORT) + + gDasharoPayloadPkgTokenSpaceGuid.PcdSerialOnSuperIo|$(UART_ON_SUPERIO) + + gUefiCpuPkgTokenSpaceGuid.PcdFirstTimeWakeUpAPsBySipi|FALSE + + # Disable MTRR programming as coreboot has already done it + gUefiCpuPkgTokenSpaceGuid.PcdCpuDisableMtrrProgramming|TRUE + +!if $(SECURE_BOOT_DEFAULT_ENABLE) == TRUE + gEfiSecurityPkgTokenSpaceGuid.PcdSecureBootDefaultEnable|1 +!else + gEfiSecurityPkgTokenSpaceGuid.PcdSecureBootDefaultEnable|0 +!endif + +!if $(SOURCE_DEBUG_ENABLE) + gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdDebugLoadImageMethod|0x2 +!endif + +!if $(PERFORMANCE_MEASUREMENT_ENABLE) + gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask|0x1 +!endif + +!if $(DASHARO_SYSTEM_FEATURES_ENABLE) == TRUE + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowMenu|TRUE + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowIommuOptions|$(IOMMU_ENABLE) + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowSerialPortMenu|$(SERIAL_TERMINAL) + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowPs2Option|$(PS2_KEYBOARD_ENABLE) +!endif + +[PcdsPatchableInModule.common] +!if ($(TARGET) == DEBUG || $(USE_CBMEM_FOR_CONSOLE) == TRUE) + gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|TRUE +!else + gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE +!endif + gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|FALSE + + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x7 + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F +!if $(USE_CBMEM_FOR_CONSOLE) == FALSE + !if $(SOURCE_DEBUG_ENABLE) + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17 + !else + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F + !endif +!else + !if $(TARGET) == DEBUG + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x07 + !else + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x03 + !endif +!endif + + # + # Network Pcds + # +!include NetworkPkg/NetworkPcds.dsc.inc + + # + # The following parameters are set by Library/PlatformHookLib + # + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseMmio|FALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase|0x3f8 + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialBaudRate|$(BAUD_RATE) + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterStride|1 + + # + # Enable these parameters to be set on the command line + # + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialClockRate|$(SERIAL_CLOCK_RATE) + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialLineControl|$(SERIAL_LINE_CONTROL) + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseHardwareFlowControl|$(SERIAL_HARDWARE_FLOW_CONTROL) + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialDetectCable|$(SERIAL_DETECT_CABLE) + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialFifoControl|$(SERIAL_FIFO_CONTROL) + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialExtendedTxFifoSize|$(SERIAL_EXTENDED_TX_FIFO_SIZE) + + gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration|TRUE + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate|$(UART_DEFAULT_BAUD_RATE) + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits|$(UART_DEFAULT_DATA_BITS) + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity|$(UART_DEFAULT_PARITY) + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits|$(UART_DEFAULT_STOP_BITS) + gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType|$(DEFAULT_TERMINAL_TYPE) + gEfiMdeModulePkgTokenSpaceGuid.PcdPciSerialParameters|$(PCI_SERIAL_PARAMETERS) + + gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber|$(MAX_LOGICAL_PROCESSORS) + +!if $(PS2_KEYBOARD_ENABLE) == TRUE + gDasharoPayloadPkgTokenSpaceGuid.PcdSkipPs2Detect|FALSE +!else + gDasharoPayloadPkgTokenSpaceGuid.PcdSkipPs2Detect|TRUE +!endif + + +################################################################################ +# +# Pcd Dynamic Section - list of all EDK II PCD Entries defined by this Platform +# +################################################################################ + +[PcdsDynamicDefault] + gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved|0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase|0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|0 + gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|$(PLATFORM_BOOT_TIMEOUT) + gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvModeEnable|FALSE + + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize |0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize|0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize |0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase |0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64|0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64|0 + + gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE + + ## This PCD defines the video horizontal resolution. + # This PCD could be set to 0 then video resolution could be at highest resolution. + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution|0 + ## This PCD defines the video vertical resolution. + # This PCD could be set to 0 then video resolution could be at highest resolution. + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution|0 + + ## The PCD is used to specify the video horizontal resolution of text setup. + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution|0 + ## The PCD is used to specify the video vertical resolution of text setup. + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution|0 + + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow|31 + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn|100 + + gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid|{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + + # No need to initialize TPM again, coreboot already did that + gEfiSecurityPkgTokenSpaceGuid.PcdTpm2InitializationPolicy|0 + gEfiSecurityPkgTokenSpaceGuid.PcdTpm2SelfTestPolicy|0 + gEfiSecurityPkgTokenSpaceGuid.PcdTpmInitializationPolicy|0 +!if $(USE_EDK2_PLATFORMS) == TRUE + gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask|1 +!endif + +[PcdsDynamicHii] +!if $(TPM_ENABLE) == TRUE + gEfiSecurityPkgTokenSpaceGuid.PcdTcgPhysicalPresenceInterfaceVer|L"TCG2_VERSION"|gTcg2ConfigFormSetGuid|0x0|"1.3"|NV,BS + gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableRev|L"TCG2_VERSION"|gTcg2ConfigFormSetGuid|0x8|4|NV,BS +!endif + +################################################################################ +# +# Components Section - list of all EDK II Modules needed by this Platform. +# +################################################################################ +[Components.IA32] + # + # SEC Core + # + DasharoPayloadPkg/SecCore/SecCore.inf + + # + # PEI Core + # + MdeModulePkg/Core/Pei/PeiMain.inf + + # + # PEIM + # + MdeModulePkg/Universal/PCD/Pei/Pcd.inf { + + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + } + MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf + MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf + MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.inf + + DasharoPayloadPkg/BlSupportPei/BlSupportPei.inf + MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf + +!if $(TPM_ENABLE) == TRUE + DasharoPayloadPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf + SecurityPkg/Tcg/TcgPei/TcgPei.inf + SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf { + + HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.inf + NULL|SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.inf + NULL|SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf + NULL|SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.inf + NULL|SecurityPkg/Library/HashInstanceLibSha512/HashInstanceLibSha512.inf + NULL|SecurityPkg/Library/HashInstanceLibSm3/HashInstanceLibSm3.inf + } +!if $(OPAL_PASSWORD_ENABLE) == TRUE + SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf +!endif +!endif + +!if $(SATA_PASSWORD_ENABLE) == TRUE + SecurityPkg/HddPassword/HddPasswordPei.inf +!endif + +[LibraryClasses.common.DXE_CORE,LibraryClasses.common.DXE_DRIVER,LibraryClasses.common.UEFI_APPLICATION] + DebugLib|MdeModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf + +[Components.X64] + # + # DXE Core + # + MdeModulePkg/Core/Dxe/DxeMain.inf { + + NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf + } + + # + # Components that produce the architectural protocols + # + MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf { + +!if $(SECURE_BOOT_ENABLE) == TRUE + NULL|SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf +!endif +!if $(TPM_ENABLE) == TRUE + NULL|SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf + NULL|SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf +!endif + } + +!if $(SECURE_BOOT_ENABLE) == TRUE + SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf + SecurityPkg/EnrollFromDefaultKeysApp/EnrollFromDefaultKeysApp.inf + SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.inf +!endif + +!if $(SETUP_PASSWORD_ENABLE) == TRUE + DasharoModulePkg/UserAuthenticationDxe/UserAuthenticationDxe.inf { + + PlatformPasswordLib|DasharoModulePkg/Library/PlatformPasswordLibNull/PlatformPasswordLibNull.inf + } +!endif + +!if $(APU_CONFIG_ENABLE) == TRUE + DasharoPayloadPkg/ApuConfigurationUi/ApuConfigurationUi.inf +!endif + + UefiCpuPkg/CpuDxe/CpuDxe.inf + MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.inf + MdeModulePkg/Universal/BdsDxe/BdsDxe.inf + MdeModulePkg/Logo/LogoDxe.inf + MdeModulePkg/Application/UiApp/UiApp.inf { + + NULL|MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf + NULL|DasharoModulePkg/Library/DasharoSystemFeaturesUiLib/DasharoSystemFeaturesUiLib.inf + NULL|MdeModulePkg/Library/BootManagerUiLib/BootManagerUiLib.inf + NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerUiLib.inf + } + MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuApp.inf +!if $(CAPSULE_SUPPORT) == TRUE + FmpDevicePkg/FmpDxe/FmpDxe.inf { + + # FmpDxe interprets its FILE_GUID as firmware GUID. This allows including + # multiple FmpDxe instances along each other targeting different + # components. + FILE_GUID = $(CAPSULE_MAIN_FW_GUID) + + gFmpDevicePkgTokenSpaceGuid.PcdFmpDeviceImageIdName|L"System Firmware" + # Public certificate used for validation of UEFI capsules + # + # See BaseTools/Source/Python/Pkcs7Sign/Readme.md for more details on such + # PCDs and include files. + !include DasharoPayloadPkg/CapsuleRootKey.inc + } + MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf + MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf + DasharoPayloadPkg/CapsuleSplashDxe/CapsuleSplashDxe.inf +!endif +!if $(RAM_DISK_ENABLE) == TRUE + MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.inf +!endif + PcAtChipsetPkg/HpetTimerDxe/HpetTimerDxe.inf + MdeModulePkg/Universal/Metronome/Metronome.inf + MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf + MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf + MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf + MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf + MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf + PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf +!if $(BOOTLOADER) == "COREBOOT" + DasharoPayloadPkg/SmmStoreFvb/SmmStoreFvbRuntimeDxe.inf +!endif + MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf + MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf { + + NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf + NULL|EmbeddedPkg/Library/NvVarStoreFormattedLib/NvVarStoreFormattedLib.inf + } + + # + # Following are the DXE drivers + # + MdeModulePkg/Universal/PCD/Dxe/Pcd.inf { + + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + } + + MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf + MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf + UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf + MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf + MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf + MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf + MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf + MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf + DasharoPayloadPkg/BlSupportDxe/BlSupportDxe.inf + CrScreenshotDxe/CrScreenshotDxe.inf + + # + # SMBIOS Support + # + MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf + MdeModulePkg/Universal/SmbiosMeasurementDxe/SmbiosMeasurementDxe.inf + + # + # ACPI Support + # + MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf + DasharoPayloadPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf + MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.inf + + # + # PCI Support + # + MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf + MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf { + + PciHostBridgeLib|DasharoPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf + } + + # + # SCSI/ATA/IDE/DISK Support + # + MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf + MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf + MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf + FatPkg/EnhancedFatDxe/Fat.inf + MdeModulePkg/Bus/Pci/SataControllerDxe/SataControllerDxe.inf + MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf + MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf + MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf + MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf + MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf + + # + # SD/eMMC Support + # + MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf + MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.inf + MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf + + # + # Usb Support + # + MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf + MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf + MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf + MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf + MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf + MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouseDxe.inf + MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf + MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointerDxe.inf + + # + # ISA Support + # +!if $(UART_ON_SUPERIO) == TRUE && $(SYSTEM76_EC_LOGGING) == FALSE + MdeModulePkg/Bus/Pci/PciSioSerialDxe/PciSioSerialDxe.inf +!else + MdeModulePkg/Universal/SerialDxe/SerialDxe.inf { + + !if $(SYSTEM76_EC_LOGGING) == TRUE + SerialPortLib|DasharoPayloadPkg/Library/System76EcLib/System76EcLib.inf + PlatformHookLib|DasharoPayloadPkg/Library/System76EcLib/System76EcLib.inf + !else + SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf + PlatformHookLib|DasharoPayloadPkg/Library/PlatformHookLib/PlatformHookLib.inf + !endif + } +!endif + + OvmfPkg/SioBusDxe/SioBusDxe.inf +!if $(PS2_KEYBOARD_ENABLE) == TRUE + MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf + MdeModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf +!endif + + # + # Console Support + # + MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf + MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf + MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf + MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf + DasharoPayloadPkg/PciPlatformDxe/PciPlatformDxe.inf + +!if $(USE_PLATFORM_GOP) == TRUE + DasharoPayloadPkg/PlatformGopPolicy/PlatformGopPolicy.inf +!else + DasharoPayloadPkg/GraphicsOutputDxe/GraphicsOutputDxe.inf +!endif + + + # + # Network Support + # +!include NetworkPkg/NetworkComponents.dsc.inc + +!if $(NETWORK_TLS_ENABLE) == TRUE + NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf { + + NULL|OvmfPkg/Library/TlsAuthConfigLib/TlsAuthConfigLib.inf + } +!endif + + DasharoModulePkg/DasharoBootPolicies/DasharoBootPolicies.inf + +!if $(USE_EDK2_PLATFORMS) == TRUE + DasharoModulePkg/DasharoBootPoliciesVTd/DasharoBootPoliciesVTd.inf +!endif + + # + # Random Number Generator + # + SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf + + # + # Hash2 + # + SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.inf { + + BaseCryptLib|CryptoPkg/Library/BaseCryptLibMbedTls/BaseCryptLib.inf + } + + # + # PKCS7 Verification + # + SecurityPkg/Pkcs7Verify/Pkcs7VerifyDxe/Pkcs7VerifyDxe.inf + +!if $(TPM_ENABLE) == TRUE + SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf { + + Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterDxe.inf + NULL|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.inf + HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf + NULL|SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.inf + NULL|SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf + NULL|SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.inf + NULL|SecurityPkg/Library/HashInstanceLibSha512/HashInstanceLibSha512.inf + NULL|SecurityPkg/Library/HashInstanceLibSm3/HashInstanceLibSm3.inf + } + SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf + SecurityPkg/Tcg/TcgDxe/TcgDxe.inf { + + Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12DeviceLibDTpm.inf + } + SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDxe.inf{ + + Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12DeviceLibDTpm.inf + } +!if $(OPAL_PASSWORD_ENABLE) == TRUE + SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf { + + Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterDxe.inf + } +!endif +!endif + +!if $(SATA_PASSWORD_ENABLE) == TRUE + SecurityPkg/HddPassword/HddPasswordDxe.inf +!endif + +!if $(IOMMU_ENABLE) == TRUE + IntelSiliconPkg/Feature/VTd/IntelVTdDxe/IntelVTdDxe.inf +!endif + +!if $(PERFORMANCE_MEASUREMENT_ENABLE) + MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.inf +!endif + + #------------------------------ + # Build the shell + #------------------------------ + +!if $(SHELL_TYPE) == BUILD_SHELL + + # + # Shell Lib + # +[LibraryClasses] + BcfgCommandLib|ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf + ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf + +[Components.X64] + ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf { + + ## This flag is used to control initialization of the shell library + # This should be FALSE for compiling the dynamic command. + gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE + } + ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.inf { + + ## This flag is used to control initialization of the shell library + # This should be FALSE for compiling the dynamic command. + gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE + } + ShellPkg/Application/Shell/Shell.inf { + + ## This flag is used to control initialization of the shell library + # This should be FALSE for compiling the shell application itself only. + gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE + + #------------------------------ + # Basic commands + #------------------------------ + + + NULL|ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf + NULL|ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf + NULL|ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf + NULL|ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf + NULL|ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf + NULL|ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf + NULL|ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf + + #------------------------------ + # Networking commands + #------------------------------ + + + NULL|ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf + + #------------------------------ + # Support libraries + #------------------------------ + + + DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + HandleParsingLib|ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf + OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf + ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf + SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf + } + +!endif diff --git a/DasharoPayloadPkg/DasharoPayloadPkg.fdf b/DasharoPayloadPkg/DasharoPayloadPkg.fdf new file mode 100644 index 0000000000..2907ad406c --- /dev/null +++ b/DasharoPayloadPkg/DasharoPayloadPkg.fdf @@ -0,0 +1,508 @@ +## @file +# Bootloader Payload Package +# +# Provides drivers and definitions to create uefi payload for bootloaders. +# +# Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +################################################################################ +[FD.UefiPayload] +BaseAddress = 0x800000|gDasharoPayloadPkgTokenSpaceGuid.PcdPayloadFdMemBase +Size = 0xE00000|gDasharoPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize +ErasePolarity = 1 +BlockSize = 0x1000 +NumBlocks = 0xE00 + +0x00000000|0x060000 +FV = PEIFV + +0x00060000|0xDA0000 +FV = DXEFV + +################################################################################ +[FV.PEIFV] +BlockSize = 0x1000 +FvAlignment = 16 +ERASE_POLARITY = 1 +MEMORY_MAPPED = TRUE +STICKY_WRITE = TRUE +LOCK_CAP = TRUE +LOCK_STATUS = TRUE +WRITE_DISABLED_CAP = TRUE +WRITE_ENABLED_CAP = TRUE +WRITE_STATUS = TRUE +WRITE_LOCK_CAP = TRUE +WRITE_LOCK_STATUS = TRUE +READ_DISABLED_CAP = TRUE +READ_ENABLED_CAP = TRUE +READ_STATUS = TRUE +READ_LOCK_CAP = TRUE +READ_LOCK_STATUS = TRUE + +INF DasharoPayloadPkg/SecCore/SecCore.inf + +INF MdeModulePkg/Core/Pei/PeiMain.inf +INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf +INF DasharoPayloadPkg/BlSupportPei/BlSupportPei.inf +INF MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf +INF MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf +INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf +INF MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.inf + +!if $(TPM_ENABLE) == TRUE +INF DasharoPayloadPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf +INF SecurityPkg/Tcg/TcgPei/TcgPei.inf +INF SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf +!if $(OPAL_PASSWORD_ENABLE) == TRUE +INF SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf +!endif +!endif + +!if $(SATA_PASSWORD_ENABLE) == TRUE +INF SecurityPkg/HddPassword/HddPasswordPei.inf +!endif +################################################################################ + +[FV.DXEFV] +BlockSize = 0x1000 +FvForceRebase = FALSE +FvAlignment = 16 +ERASE_POLARITY = 1 +MEMORY_MAPPED = TRUE +STICKY_WRITE = TRUE +LOCK_CAP = TRUE +LOCK_STATUS = TRUE +WRITE_DISABLED_CAP = TRUE +WRITE_ENABLED_CAP = TRUE +WRITE_STATUS = TRUE +WRITE_LOCK_CAP = TRUE +WRITE_LOCK_STATUS = TRUE +READ_DISABLED_CAP = TRUE +READ_ENABLED_CAP = TRUE +READ_STATUS = TRUE +READ_LOCK_CAP = TRUE +READ_LOCK_STATUS = TRUE + +APRIORI DXE { + INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf + INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf + INF MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf + INF MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf +} + +# +# DXE Phase modules +# +INF MdeModulePkg/Core/Dxe/DxeMain.inf +INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf +INF MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf +INF MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf +!if $(PERFORMANCE_MEASUREMENT_ENABLE) +INF MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.inf +!endif + +INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf +INF UefiCpuPkg/CpuDxe/CpuDxe.inf +INF MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.inf +INF MdeModulePkg/Universal/BdsDxe/BdsDxe.inf +INF MdeModulePkg/Application/UiApp/UiApp.inf +INF MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuApp.inf +!if $(RAM_DISK_ENABLE) == TRUE +INF MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.inf +!endif +INF PcAtChipsetPkg/HpetTimerDxe/HpetTimerDxe.inf +INF MdeModulePkg/Universal/Metronome/Metronome.inf +INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf +INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf +INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf +INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf +INF MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf +INF PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf + +!if $(BOOTLOADER) == "COREBOOT" + # Initialize VariableStore and update PCDs before VariableRuntimeDxe + INF DasharoPayloadPkg/SmmStoreFvb/SmmStoreFvbRuntimeDxe.inf +!endif +INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf +INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf + +INF UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf +INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf +INF MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf +INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf +INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf +INF MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf +INF DasharoPayloadPkg/BlSupportDxe/BlSupportDxe.inf + +INF MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf +INF MdeModulePkg/Logo/LogoDxe.inf +INF MdeModulePkg/Universal/SmbiosMeasurementDxe/SmbiosMeasurementDxe.inf + +# +# ACPI Support +# +INF MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf +INF DasharoPayloadPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf +INF MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.inf + +# +# PCI Support +# +INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf +INF MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf + +# +# ISA Support +# +!if $(UART_ON_SUPERIO) == TRUE && $(SYSTEM76_EC_LOGGING) == FALSE +INF MdeModulePkg/Bus/Pci/PciSioSerialDxe/PciSioSerialDxe.inf +!else +INF MdeModulePkg/Universal/SerialDxe/SerialDxe.inf +!endif +INF OvmfPkg/SioBusDxe/SioBusDxe.inf +!if $(PS2_KEYBOARD_ENABLE) == TRUE +INF MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf +INF MdeModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf +!endif + +# +# Console Support +# +INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf +INF MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf +INF MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf +INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf +INF DasharoPayloadPkg/PciPlatformDxe/PciPlatformDxe.inf + +!if $(USE_PLATFORM_GOP) == TRUE +!if "X64" in $(ARCH) +INF DasharoPayloadPkg/PlatformGopPolicy/PlatformGopPolicy.inf +!endif +FILE DRIVER = FF0C8745-3270-4439-B74F-3E45F8C77064 { + SECTION DXE_DEPEX_EXP = {gPlatformGOPPolicyGuid} + SECTION PE32 = DasharoPayloadPkg/IntelGopDriver.efi + SECTION UI = "IntelGopDriver" +} + +FILE FREEFORM = 878AC2CC-5343-46F2-B563-51F89DAF56BA { + SECTION RAW = DasharoPayloadPkg/vbt.bin + SECTION UI = "IntelGopVbt" +} +!else + INF DasharoPayloadPkg/GraphicsOutputDxe/GraphicsOutputDxe.inf +!endif + + + +# +# SCSI/ATA/IDE/DISK Support +# +INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf +INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf +INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf +INF MdeModulePkg/Bus/Pci/SataControllerDxe/SataControllerDxe.inf +INF MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf +INF MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf +INF MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf +INF MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf +INF MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf + +INF FatPkg/EnhancedFatDxe/Fat.inf + +# +# Filesystem drivers +# +!if $(ARCH) == IA32 +INF RuleOverride=BINARY USE = IA32 FSDrivers/exfat.inf +INF RuleOverride=BINARY USE = IA32 FSDrivers/ext2.inf +INF RuleOverride=BINARY USE = IA32 FSDrivers/ntfs.inf +INF RuleOverride=BINARY USE = IA32 FSDrivers/ext4.inf +!else +INF RuleOverride=BINARY USE = X64 FSDrivers/exfat.inf +INF RuleOverride=BINARY USE = X64 FSDrivers/ext2.inf +INF RuleOverride=BINARY USE = X64 FSDrivers/ntfs.inf +INF RuleOverride=BINARY USE = X64 FSDrivers/ext4.inf +!endif + +# +# SD/eMMC Support +# +INF MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf +INF MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.inf +INF MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf + +# +# Usb Support +# +INF MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf +INF MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf +INF MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf +INF MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf +INF MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf +INF MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouseDxe.inf +INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf +INF MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointerDxe.inf + +# +# Hash2 +# +INF SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.inf + +# +# PKCS7 Verification +# +INF SecurityPkg/Pkcs7Verify/Pkcs7VerifyDxe/Pkcs7VerifyDxe.inf + +# +# Security +# +!if $(SECURE_BOOT_ENABLE) == TRUE + INF SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf + INF SecurityPkg/EnrollFromDefaultKeysApp/EnrollFromDefaultKeysApp.inf + INF SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.inf + + # gDefaultKEKFileGuid + FILE FREEFORM = 6F64916E-9F7A-4C35-B952-CD041EFB05A3 { + SECTION RAW = DasharoPayloadPkg/SecureBootDefaultKeys/MicCorKEKCA2011_2011-06-24.crt + SECTION RAW = DasharoPayloadPkg/SecureBootDefaultKeys/microsoft_corporation_kek_2k_ca_2023.crt + SECTION UI = "DefaultKekCert" + } + + # gDefaultPKFileGuid + FILE FREEFORM = 85254EA7-4759-4FC4-82D4-5EED5FB0A4A0 { + SECTION RAW = DasharoPayloadPkg/SecureBootDefaultKeys/pk.crt + SECTION UI = "DefaultPkCert" + } + + # gDefaultdbFileGuid + FILE FREEFORM = C491D352-7623-4843-ACCC-2791A7574421 { + SECTION RAW = DasharoPayloadPkg/SecureBootDefaultKeys/MicWinProPCA2011_2011-10-19.crt + SECTION RAW = DasharoPayloadPkg/SecureBootDefaultKeys/MicCorUEFCA2011_2011-06-27.crt + SECTION RAW = DasharoPayloadPkg/SecureBootDefaultKeys/windows_uefi_ca_2023.crt + SECTION RAW = DasharoPayloadPkg/SecureBootDefaultKeys/microsoft_uefi_ca_2023.crt + SECTION UI = "DefaultDbCert" + } + + # gDefaultdbxFileGuid + FILE FREEFORM = 5740766A-718E-4DC0-9935-C36F7D3F884F { + SECTION RAW = DasharoPayloadPkg/SecureBootDefaultKeys/DBXUpdate.bin + SECTION UI = "DefaultDbxCert" + } +!endif + +# +# Network Support +# +!include NetworkPkg/Network.fdf.inc + +# +# Network modules (only available on X64) +# +!if $(NETWORK_LAN_ROM) == TRUE +# +# Build system must place the LanRom.efi before building the UEFI Payload. + +# Typically will be done per platform needs by coreboot. +# + FILE DRIVER = DEB917C0-C56A-4860-A05B-BF2F22EBB717 { + SECTION DXE_DEPEX_EXP = {gDasharoNetworkBootPolicyGuid} + SECTION PE32 = DasharoPayloadPkg/NetworkDrivers/LanRom.efi + } +!endif + +# +# iPXE support +# +!if $(NETWORK_IPXE) == TRUE + # + # coreboot build system should put the ipxe.efi file here before EDK2 build + # + FILE FREEFORM = B68653C7-EEA1-4435-A199-A44F59E4476C { + SECTION PE32 = DasharoPayloadPkg/NetworkDrivers/ipxe.efi + } +!endif + +INF DasharoModulePkg/DasharoBootPolicies/DasharoBootPolicies.inf + +!if $(USE_EDK2_PLATFORMS) == TRUE +INF DasharoModulePkg/DasharoBootPoliciesVTd/DasharoBootPoliciesVTd.inf +!endif + +# +# Random Number Generator +# +INF SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf + +# +# Security +# +!if $(TPM_ENABLE) == TRUE +INF SecurityPkg/Tcg/TcgDxe/TcgDxe.inf +INF SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf +INF SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDxe.inf +INF SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf +!if $(OPAL_PASSWORD_ENABLE) == TRUE +INF SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf +!endif +!endif + +!if $(SATA_PASSWORD_ENABLE) == TRUE +INF SecurityPkg/HddPassword/HddPasswordDxe.inf +!endif + +!if $(SETUP_PASSWORD_ENABLE) == TRUE +INF DasharoModulePkg/UserAuthenticationDxe/UserAuthenticationDxe.inf +!endif + +!if $(IOMMU_ENABLE) == TRUE +INF IntelSiliconPkg/Feature/VTd/IntelVTdDxe/IntelVTdDxe.inf +!endif + +!if $(APU_CONFIG_ENABLE) == TRUE +INF DasharoPayloadPkg/ApuConfigurationUi/ApuConfigurationUi.inf +!endif + +# +# Shell +# +!if $(SHELL_TYPE) == BUILD_SHELL +INF ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf +INF ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.inf +INF ShellPkg/Application/Shell/Shell.inf +!endif + +!if $(SHELL_TYPE) == MIN_BIN +!if $(ARCH) == IA32 +INF RuleOverride = BINARY USE = IA32 ShellBinPkg/MinUefiShell/MinUefiShell.inf +!else +INF RuleOverride = BINARY USE = X64 ShellBinPkg/MinUefiShell/MinUefiShell.inf +!endif +!endif + +!if $(SHELL_TYPE) == UEFI_BIN +!if $(ARCH) == IA32 +INF RuleOverride = BINARY USE = IA32 ShellBinPkg/UefiShell/UefiShell.inf +!else +INF RuleOverride = BINARY USE = X64 ShellBinPkg/UefiShell/UefiShell.inf +!endif +!endif + +INF CrScreenshotDxe/CrScreenshotDxe.inf + +!if $(CAPSULE_SUPPORT) == TRUE +INF MdeModulePkg/Universal/EsrtDxe/EsrtDxe.inf +!endif + +################################################################################ +# +# Rules are use with the [FV] section's module INF type to define +# how an FFS file is created for a given INF file. The following Rule are the default +# rules for the different module type. User can add the customized rules to define the +# content of the FFS file. +# +################################################################################ + +[Rule.Common.SEC] + FILE SEC = $(NAMED_GUID) { + PE32 PE32 Align=32 $(INF_OUTPUT)/$(MODULE_NAME).efi + } + +[Rule.Common.PEI_CORE] + FILE PEI_CORE = $(NAMED_GUID) { + PE32 PE32 Align=Auto $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING ="$(MODULE_NAME)" Optional + VERSION STRING ="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.PEIM] + FILE PEIM = $(NAMED_GUID) { + PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 Align=Auto $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.DXE_CORE] + FILE DXE_CORE = $(NAMED_GUID) { + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.DXE_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.DXE_RUNTIME_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.UEFI_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.UEFI_DRIVER.BINARY] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.UEFI_APPLICATION] + FILE APPLICATION = $(NAMED_GUID) { + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.UEFI_APPLICATION.BINARY] + FILE APPLICATION = $(NAMED_GUID) { + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.USER_DEFINED.ACPITABLE] + FILE FREEFORM = $(NAMED_GUID) { + RAW ACPI |.acpi + RAW ASL |.aml + } + +[Rule.Common.USER_DEFINED.CSM] + FILE FREEFORM = $(NAMED_GUID) { + RAW BIN |.bin + } + +[Rule.Common.SEC.RESET_VECTOR] + FILE RAW = $(NAMED_GUID) { + RAW RAW |.raw + } + +[RULE.COMMON.USER_DEFINED] + FILE FREEFORM = $(NAMED_GUID) { + RAW BIN |.crt + RAW BIN |.bin + } + +[RULE.COMMON.USER_DEFINED.BINARY] + FILE FREEFORM = $(NAMED_GUID) { + RAW BIN |.crt + RAW BIN |.bin + UI STRING="$(MODULE_NAME)" Optional + } diff --git a/DasharoPayloadPkg/GraphicsOutputDxe/ComponentName.c b/DasharoPayloadPkg/GraphicsOutputDxe/ComponentName.c new file mode 100644 index 0000000000..7b7f5683a5 --- /dev/null +++ b/DasharoPayloadPkg/GraphicsOutputDxe/ComponentName.c @@ -0,0 +1,184 @@ +/** @file + UEFI Component Name(2) protocol implementation for the generic GOP driver. + +Copyright (c) 2016, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + + +**/ + +#include +#include + +extern EFI_COMPONENT_NAME_PROTOCOL mGraphicsOutputComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL mGraphicsOutputComponentName2; + +// +// Driver name table for GraphicsOutput module. +// It is shared by the implementation of ComponentName & ComponentName2 Protocol. +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mGraphicsOutputDriverNameTable[] = { + { + "eng;en", + L"Generic Graphics Output Driver" + }, + { + NULL, + NULL + } +}; + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +GraphicsOutputComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mGraphicsOutputDriverNameTable, + DriverName, + (BOOLEAN) (This == &mGraphicsOutputComponentName) + ); +} + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by a driver. + + This function retrieves the user readable name of the controller specified by + ControllerHandle and ChildHandle in the form of a Unicode string. If the + driver specified by This has a user readable name in the language specified by + Language, then a pointer to the controller name is returned in ControllerName, + and EFI_SUCCESS is returned. If the driver specified by This is not currently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This does not + support the language specified by Language, then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param ControllerHandle[in] The handle of a controller that the driver + specified by This is managing. This handle + specifies the controller whose name is to be + returned. + + @param ChildHandle[in] The handle of the child controller to retrieve + the name of. This is an optional parameter that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus drivers + that wish to retrieve the name of the bus + controller. It will not be NULL for a bus + driver that wishes to retrieve the name of a + child controller. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified in + RFC 4646 or ISO 639-2 language code format. + + @param ControllerName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle and + ChildHandle in the language specified by + Language from the point of view of the driver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable name in + the language specified by Language for the + driver specified by This was returned in + DriverName. + + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +GraphicsOutputComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + return EFI_UNSUPPORTED; +} + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL mGraphicsOutputComponentName = { + GraphicsOutputComponentNameGetDriverName, + GraphicsOutputComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL mGraphicsOutputComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) GraphicsOutputComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) GraphicsOutputComponentNameGetControllerName, + "en" +}; diff --git a/DasharoPayloadPkg/GraphicsOutputDxe/GraphicsOutput.c b/DasharoPayloadPkg/GraphicsOutputDxe/GraphicsOutput.c new file mode 100644 index 0000000000..86ca2f1e33 --- /dev/null +++ b/DasharoPayloadPkg/GraphicsOutputDxe/GraphicsOutput.c @@ -0,0 +1,740 @@ +/** @file + Implementation for a generic GOP driver. + +Copyright (c) 2016, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + + +**/ + +#include "GraphicsOutput.h" +CONST ACPI_ADR_DEVICE_PATH mGraphicsOutputAdrNode = { + { + ACPI_DEVICE_PATH, + ACPI_ADR_DP, + { sizeof (ACPI_ADR_DEVICE_PATH), 0 }, + }, + ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0) +}; + +EFI_PEI_GRAPHICS_DEVICE_INFO_HOB mDefaultGraphicsDeviceInfo = { + MAX_UINT16, MAX_UINT16, MAX_UINT16, MAX_UINT16, MAX_UINT8, MAX_UINT8 +}; + +// +// The driver should only start on one graphics controller. +// So a global flag is used to remember that the driver is already started. +// +BOOLEAN mDriverStarted = FALSE; + +/** + 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. + +**/ +EFI_STATUS +EFIAPI +GraphicsOutputQueryMode ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber, + OUT UINTN *SizeOfInfo, + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info + ) +{ + if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) { + return EFI_INVALID_PARAMETER; + } + + *SizeOfInfo = This->Mode->SizeOfInfo; + *Info = AllocateCopyPool (*SizeOfInfo, This->Mode->Info); + return EFI_SUCCESS; +} + +/** + Set the video device into the specified mode and clears the visible portions of + the output display to black. + + @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance. + @param ModeNumber Abstraction that defines the current video mode. + + @retval EFI_SUCCESS The graphics mode specified by ModeNumber was selected. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + @retval EFI_UNSUPPORTED ModeNumber is not supported by this device. + +**/ +EFI_STATUS +EFIAPI +GraphicsOutputSetMode ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber +) +{ + RETURN_STATUS Status; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black; + GRAPHICS_OUTPUT_PRIVATE_DATA *Private; + + if (ModeNumber >= This->Mode->MaxMode) { + return EFI_UNSUPPORTED; + } + + Private = GRAPHICS_OUTPUT_PRIVATE_FROM_THIS (This); + + Black.Blue = 0; + Black.Green = 0; + Black.Red = 0; + Black.Reserved = 0; + + Status = FrameBufferBlt ( + Private->FrameBufferBltLibConfigure, + &Black, + EfiBltVideoFill, + 0, 0, + 0, 0, + This->Mode->Info->HorizontalResolution, + This->Mode->Info->VerticalResolution, + 0 + ); + return RETURN_ERROR (Status) ? EFI_DEVICE_ERROR : EFI_SUCCESS; +} + +/** + 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. + +**/ +EFI_STATUS +EFIAPI +GraphicsOutputBlt ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL + IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta OPTIONAL + ) +{ + RETURN_STATUS Status; + EFI_TPL Tpl; + GRAPHICS_OUTPUT_PRIVATE_DATA *Private; + + Private = GRAPHICS_OUTPUT_PRIVATE_FROM_THIS (This); + // + // We have to raise to TPL_NOTIFY, so we make an atomic write to the frame buffer. + // We would not want a timer based event (Cursor, ...) to come in while we are + // doing this operation. + // + Tpl = gBS->RaiseTPL (TPL_NOTIFY); + Status = FrameBufferBlt ( + Private->FrameBufferBltLibConfigure, + BltBuffer, + BltOperation, + SourceX, SourceY, + DestinationX, DestinationY, Width, Height, + Delta + ); + gBS->RestoreTPL (Tpl); + + return RETURN_ERROR (Status) ? EFI_INVALID_PARAMETER : EFI_SUCCESS; +} + +CONST GRAPHICS_OUTPUT_PRIVATE_DATA mGraphicsOutputInstanceTemplate = { + GRAPHICS_OUTPUT_PRIVATE_DATA_SIGNATURE, // Signature + NULL, // GraphicsOutputHandle + { + GraphicsOutputQueryMode, + GraphicsOutputSetMode, + GraphicsOutputBlt, + NULL // Mode + }, + { + 1, // MaxMode + 0, // Mode + NULL, // Info + sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION), // SizeOfInfo + 0, // FrameBufferBase + 0 // FrameBufferSize + }, + NULL, // DevicePath + NULL, // PciIo + 0, // PciAttributes + NULL, // FrameBufferBltLibConfigure + 0 // FrameBufferBltLibConfigureSize +}; + +/** + Test whether the Controller can be managed by the driver. + + @param This Driver Binding protocol instance pointer. + @param Controller The PCI controller. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS The driver can manage the video device. + @retval other The driver cannot manage the video device. +**/ +EFI_STATUS +EFIAPI +GraphicsOutputDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + // + // Since there is only one GraphicsInfo HOB, the driver only manages one video device. + // + if (mDriverStarted) { + return EFI_ALREADY_STARTED; + } + + // + // Test the PCI I/O Protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + Status = EFI_SUCCESS; + } + if (EFI_ERROR (Status)) { + return Status; + } + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + // + // Test the DevicePath protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + Status = EFI_SUCCESS; + } + if (EFI_ERROR (Status)) { + return Status; + } + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + if ((RemainingDevicePath == NULL) || + IsDevicePathEnd (RemainingDevicePath) || + CompareMem (RemainingDevicePath, &mGraphicsOutputAdrNode, sizeof (mGraphicsOutputAdrNode)) == 0) { + return EFI_SUCCESS; + } else { + return EFI_INVALID_PARAMETER; + } +} + +/** + Start the video controller. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle The PCI controller. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS The driver starts to manage the video device. + @retval other The driver cannot manage the video device. +**/ +EFI_STATUS +EFIAPI +GraphicsOutputDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + RETURN_STATUS ReturnStatus; + GRAPHICS_OUTPUT_PRIVATE_DATA *Private; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_DEVICE_PATH *PciDevicePath; + PCI_TYPE00 Pci; + UINT8 Index; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Resources; + VOID *HobStart; + EFI_PEI_GRAPHICS_INFO_HOB *GraphicsInfo; + EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *DeviceInfo; + EFI_PHYSICAL_ADDRESS FrameBufferBase; + + FrameBufferBase = 0; + + HobStart = GetFirstGuidHob (&gEfiGraphicsInfoHobGuid); + ASSERT ((HobStart != NULL) && (GET_GUID_HOB_DATA_SIZE (HobStart) == sizeof (EFI_PEI_GRAPHICS_INFO_HOB))); + GraphicsInfo = (EFI_PEI_GRAPHICS_INFO_HOB *) (GET_GUID_HOB_DATA (HobStart)); + + HobStart = GetFirstGuidHob (&gEfiGraphicsDeviceInfoHobGuid); + if ((HobStart == NULL) || (GET_GUID_HOB_DATA_SIZE (HobStart) < sizeof (*DeviceInfo))) { + // + // Use default device infomation when the device info HOB doesn't exist + // + DeviceInfo = &mDefaultGraphicsDeviceInfo; + DEBUG ((DEBUG_INFO, "[%a]: GraphicsDeviceInfo HOB doesn't exist!\n", gEfiCallerBaseName)); + } else { + DeviceInfo = (EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *) (GET_GUID_HOB_DATA (HobStart)); + DEBUG ((DEBUG_INFO, "[%a]: GraphicsDeviceInfo HOB:\n" + " VendorId = %04x, DeviceId = %04x,\n" + " RevisionId = %02x, BarIndex = %x,\n" + " SubsystemVendorId = %04x, SubsystemId = %04x\n", + gEfiCallerBaseName, + DeviceInfo->VendorId, DeviceInfo->DeviceId, + DeviceInfo->RevisionId, DeviceInfo->BarIndex, + DeviceInfo->SubsystemVendorId, DeviceInfo->SubsystemId)); + } + + // + // Open the PCI I/O Protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + Status = EFI_SUCCESS; + } + ASSERT_EFI_ERROR (Status); + + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &PciDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + Status = EFI_SUCCESS; + } + ASSERT_EFI_ERROR (Status); + + // + // Read the PCI Class Code from the PCI Device + // + Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0, sizeof (Pci), &Pci); + if (!EFI_ERROR (Status)) { + if (!IS_PCI_DISPLAY (&Pci) || ( + ((DeviceInfo->VendorId != MAX_UINT16) && (DeviceInfo->VendorId != Pci.Hdr.VendorId)) || + ((DeviceInfo->DeviceId != MAX_UINT16) && (DeviceInfo->DeviceId != Pci.Hdr.DeviceId)) || + ((DeviceInfo->RevisionId != MAX_UINT8) && (DeviceInfo->RevisionId != Pci.Hdr.RevisionID)) || + ((DeviceInfo->SubsystemVendorId != MAX_UINT16) && (DeviceInfo->SubsystemVendorId != Pci.Device.SubsystemVendorID)) || + ((DeviceInfo->SubsystemId != MAX_UINT16) && (DeviceInfo->SubsystemId != Pci.Device.SubsystemID)) + ) + ) { + // + // It's not a video device, or device infomation doesn't match. + // + Status = EFI_UNSUPPORTED; + } else { + // + // If it's a video device and device information matches, use the BarIndex + // from device information, or any BAR if BarIndex is not specified + // whose size >= the frame buffer size from GraphicsInfo HOB. + // Store the new frame buffer base. + // + for (Index = 0; Index < MAX_PCI_BAR; Index++) { + if ((DeviceInfo->BarIndex != MAX_UINT8) && (DeviceInfo->BarIndex != Index)) { + continue; + } + Status = PciIo->GetBarAttributes (PciIo, Index, NULL, (VOID**) &Resources); + if (!EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "[%a]: BAR[%d]: Base = %lx, Length = %lx\n", + gEfiCallerBaseName, Index, Resources->AddrRangeMin, Resources->AddrLen)); + if ((Resources->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) && + (Resources->Len == (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3)) && + (Resources->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) && + (Resources->AddrLen >= GraphicsInfo->FrameBufferSize) + ) { + if (FrameBufferBase == 0) { + FrameBufferBase = Resources->AddrRangeMin; + } + if (DeviceInfo->BarIndex == MAX_UINT8) { + if (Resources->AddrRangeMin <= GraphicsInfo->FrameBufferBase + && Resources->AddrRangeMin + Resources->AddrLen >= GraphicsInfo->FrameBufferBase + GraphicsInfo->FrameBufferSize ) { + FrameBufferBase = GraphicsInfo->FrameBufferBase; + break; + } + } else { + break; + } + } + } + } + if (Index == MAX_PCI_BAR) { + Status = EFI_UNSUPPORTED; + } else { + DEBUG ((DEBUG_INFO, "[%a]: ... matched!\n", gEfiCallerBaseName)); + } + } + } + + if (EFI_ERROR (Status)) { + goto CloseProtocols; + } + + if ((RemainingDevicePath != NULL) && IsDevicePathEnd (RemainingDevicePath)) { + return EFI_SUCCESS; + } + + Private = AllocateCopyPool (sizeof (mGraphicsOutputInstanceTemplate), &mGraphicsOutputInstanceTemplate); + if (Private == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto CloseProtocols; + } + + Private->GraphicsOutputMode.FrameBufferBase = FrameBufferBase; + Private->GraphicsOutputMode.FrameBufferSize = GraphicsInfo->FrameBufferSize; + Private->GraphicsOutputMode.Info = &GraphicsInfo->GraphicsMode; + + // + // Fix up Mode pointer in GraphicsOutput + // + Private->GraphicsOutput.Mode = &Private->GraphicsOutputMode; + + // + // Set attributes + // + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationGet, + 0, + &Private->PciAttributes + ); + if (!EFI_ERROR (Status)) { + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + EFI_PCI_DEVICE_ENABLE, + NULL + ); + } + + if (EFI_ERROR (Status)) { + goto FreeMemory; + } + + // + // Create the FrameBufferBltLib configuration. + // + ReturnStatus = FrameBufferBltConfigure ( + (VOID *) (UINTN) Private->GraphicsOutput.Mode->FrameBufferBase, + Private->GraphicsOutput.Mode->Info, + Private->FrameBufferBltLibConfigure, + &Private->FrameBufferBltLibConfigureSize + ); + if (ReturnStatus == RETURN_BUFFER_TOO_SMALL) { + Private->FrameBufferBltLibConfigure = AllocatePool (Private->FrameBufferBltLibConfigureSize); + if (Private->FrameBufferBltLibConfigure != NULL) { + ReturnStatus = FrameBufferBltConfigure ( + (VOID *) (UINTN) Private->GraphicsOutput.Mode->FrameBufferBase, + Private->GraphicsOutput.Mode->Info, + Private->FrameBufferBltLibConfigure, + &Private->FrameBufferBltLibConfigureSize + ); + } + } + if (RETURN_ERROR (ReturnStatus)) { + Status = EFI_OUT_OF_RESOURCES; + goto RestorePciAttributes; + } + + Private->DevicePath = AppendDevicePathNode (PciDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &mGraphicsOutputAdrNode); + if (Private->DevicePath == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto RestorePciAttributes; + } + + Status = gBS->InstallMultipleProtocolInterfaces ( + &Private->GraphicsOutputHandle, + &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput, + &gEfiDevicePathProtocolGuid, Private->DevicePath, + NULL + ); + + if (!EFI_ERROR (Status)) { + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &Private->PciIo, + This->DriverBindingHandle, + Private->GraphicsOutputHandle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + if (!EFI_ERROR (Status)) { + mDriverStarted = TRUE; + } else { + gBS->UninstallMultipleProtocolInterfaces ( + Private->GraphicsOutputHandle, + &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput, + &gEfiDevicePathProtocolGuid, Private->DevicePath, + NULL + ); + } + } + +RestorePciAttributes: + if (EFI_ERROR (Status)) { + // + // Restore original PCI attributes + // + PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationSet, + Private->PciAttributes, + NULL + ); + } + +FreeMemory: + if (EFI_ERROR (Status)) { + if (Private != NULL) { + if (Private->DevicePath != NULL) { + FreePool (Private->DevicePath); + } + if (Private->FrameBufferBltLibConfigure != NULL) { + FreePool (Private->FrameBufferBltLibConfigure); + } + FreePool (Private); + } + } + +CloseProtocols: + if (EFI_ERROR (Status)) { + // + // Close the PCI I/O Protocol + // + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + // + // Close the PCI I/O Protocol + // + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } + return Status; +} + +/** + Stop the video controller. + + @param This Driver Binding protocol instance pointer. + @param Controller The PCI controller. + @param NumberOfChildren The number of child device handles in ChildHandleBuffer. + @param ChildHandleBuffer An array of child handles to be freed. May be NULL + if NumberOfChildren is 0. + + @retval EFI_SUCCESS The device was stopped. + @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. +**/ +EFI_STATUS +EFIAPI +GraphicsOutputDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop; + GRAPHICS_OUTPUT_PRIVATE_DATA *Private; + + if (NumberOfChildren == 0) { + + // + // Close the PCI I/O Protocol + // + Status = gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + ASSERT_EFI_ERROR (Status); + + Status = gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + ASSERT_EFI_ERROR (Status); + return EFI_SUCCESS; + } + + ASSERT (NumberOfChildren == 1); + Status = gBS->OpenProtocol ( + ChildHandleBuffer[0], + &gEfiGraphicsOutputProtocolGuid, + (VOID **) &Gop, + This->DriverBindingHandle, + ChildHandleBuffer[0], + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Private = GRAPHICS_OUTPUT_PRIVATE_FROM_THIS (Gop); + + Status = gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Private->GraphicsOutputHandle + ); + ASSERT_EFI_ERROR (Status); + // + // Remove the GOP protocol interface from the system + // + Status = gBS->UninstallMultipleProtocolInterfaces ( + Private->GraphicsOutputHandle, + &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput, + &gEfiDevicePathProtocolGuid, Private->DevicePath, + NULL + ); + if (!EFI_ERROR (Status)) { + // + // Restore original PCI attributes + // + Status = Private->PciIo->Attributes ( + Private->PciIo, + EfiPciIoAttributeOperationSet, + Private->PciAttributes, + NULL + ); + ASSERT_EFI_ERROR (Status); + + FreePool (Private->DevicePath); + FreePool (Private->FrameBufferBltLibConfigure); + mDriverStarted = FALSE; + } else { + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &Private->PciIo, + This->DriverBindingHandle, + Private->GraphicsOutputHandle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + ASSERT_EFI_ERROR (Status); + } + return Status; +} + +EFI_DRIVER_BINDING_PROTOCOL mGraphicsOutputDriverBinding = { + GraphicsOutputDriverBindingSupported, + GraphicsOutputDriverBindingStart, + GraphicsOutputDriverBindingStop, + 0x10, + NULL, + NULL +}; + +/** + The Entry Point for GraphicsOutput driver. + + It installs DriverBinding, ComponentName and ComponentName2 protocol if there is + GraphicsInfo HOB passed from Graphics PEIM. + + @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 +InitializeGraphicsOutput ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + VOID *HobStart; + + HobStart = GetFirstGuidHob (&gEfiGraphicsInfoHobGuid); + + if ((HobStart == NULL) || (GET_GUID_HOB_DATA_SIZE (HobStart) < sizeof (EFI_PEI_GRAPHICS_INFO_HOB))) { + return EFI_NOT_FOUND; + } + + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &mGraphicsOutputDriverBinding, + ImageHandle, + &mGraphicsOutputComponentName, + &mGraphicsOutputComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/DasharoPayloadPkg/GraphicsOutputDxe/GraphicsOutput.h b/DasharoPayloadPkg/GraphicsOutputDxe/GraphicsOutput.h new file mode 100644 index 0000000000..a40768b1ee --- /dev/null +++ b/DasharoPayloadPkg/GraphicsOutputDxe/GraphicsOutput.h @@ -0,0 +1,53 @@ +/** @file + Header file for a generic GOP driver. + +Copyright (c) 2016, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + + +**/ +#ifndef _GRAPHICS_OUTPUT_DXE_H_ +#define _GRAPHICS_OUTPUT_DXE_H_ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_PCI_BAR 6 + +typedef struct { + UINT32 Signature; + EFI_HANDLE GraphicsOutputHandle; + EFI_GRAPHICS_OUTPUT_PROTOCOL GraphicsOutput; + EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE GraphicsOutputMode; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT64 PciAttributes; + FRAME_BUFFER_CONFIGURE *FrameBufferBltLibConfigure; + UINTN FrameBufferBltLibConfigureSize; +} GRAPHICS_OUTPUT_PRIVATE_DATA; + +#define GRAPHICS_OUTPUT_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('g', 'g', 'o', 'p') +#define GRAPHICS_OUTPUT_PRIVATE_FROM_THIS(a) \ + CR(a, GRAPHICS_OUTPUT_PRIVATE_DATA, GraphicsOutput, GRAPHICS_OUTPUT_PRIVATE_DATA_SIGNATURE) + +extern EFI_COMPONENT_NAME_PROTOCOL mGraphicsOutputComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL mGraphicsOutputComponentName2; +#endif diff --git a/DasharoPayloadPkg/GraphicsOutputDxe/GraphicsOutputDxe.inf b/DasharoPayloadPkg/GraphicsOutputDxe/GraphicsOutputDxe.inf new file mode 100644 index 0000000000..af21095a66 --- /dev/null +++ b/DasharoPayloadPkg/GraphicsOutputDxe/GraphicsOutputDxe.inf @@ -0,0 +1,53 @@ +## @file +# This driver produces GraphicsOutput protocol based on the GraphicsInfo HOB information. +# +# Copyright (c) 2016, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = GraphicsOutputDxe + FILE_GUID = 0B04B2ED-861C-42cd-A22F-C3AAFACCB896 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = InitializeGraphicsOutput + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.common] + GraphicsOutput.h + GraphicsOutput.c + ComponentName.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + UefiBootServicesTableLib + DxeServicesTableLib + DebugLib + MemoryAllocationLib + BaseMemoryLib + DevicePathLib + FrameBufferBltLib + UefiLib + HobLib + +[Guids] + gEfiGraphicsInfoHobGuid ## CONSUMES ## HOB + gEfiGraphicsDeviceInfoHobGuid ## CONSUMES ## HOB + +[Protocols] + gEfiGraphicsOutputProtocolGuid ## BY_START + gEfiDevicePathProtocolGuid ## BY_START + gEfiPciIoProtocolGuid ## TO_START diff --git a/DasharoPayloadPkg/Include/Coreboot.h b/DasharoPayloadPkg/Include/Coreboot.h new file mode 100644 index 0000000000..526656e918 --- /dev/null +++ b/DasharoPayloadPkg/Include/Coreboot.h @@ -0,0 +1,786 @@ +/** @file + Coreboot PEI module include file. + + Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + + Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+ SPDX-License-Identifier: BSD-3-Clause +**/ + +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * + * 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 author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (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 _COREBOOT_PEI_H_INCLUDED_ +#define _COREBOOT_PEI_H_INCLUDED_ + +#if defined(_MSC_VER) +#pragma warning( disable : 4200 ) +#endif + +#define DYN_CBMEM_ALIGN_SIZE (4096) + +#define IMD_ENTRY_MAGIC (~0xC0389481) +#define CBMEM_ENTRY_MAGIC (~0xC0389479) + +struct cbmem_entry { + UINT32 magic; + UINT32 start; + UINT32 size; + UINT32 id; +}; + +struct cbmem_root { + UINT32 max_entries; + UINT32 num_entries; + UINT32 locked; + UINT32 size; + struct cbmem_entry entries[0]; +}; + +struct imd_entry { + UINT32 magic; + UINT32 start_offset; + UINT32 size; + UINT32 id; +}; + +struct imd_root { + UINT32 max_entries; + UINT32 num_entries; + UINT32 flags; + UINT32 entry_align; + UINT32 max_offset; + struct imd_entry entries[0]; +}; + +struct cbuint64 { + UINT32 lo; + UINT32 hi; +}; + +#define CB_HEADER_SIGNATURE 0x4F49424C + +struct cb_header { + UINT32 signature; + UINT32 header_bytes; + UINT32 header_checksum; + UINT32 table_bytes; + UINT32 table_checksum; + UINT32 table_entries; +}; + +struct cb_record { + UINT32 tag; + UINT32 size; +}; + +#define CB_TAG_UNUSED 0x0000 +#define CB_TAG_MEMORY 0x0001 + +struct cb_memory_range { + struct cbuint64 start; + struct cbuint64 size; + UINT32 type; +}; + +#define CB_MEM_RAM 1 +#define CB_MEM_RESERVED 2 +#define CB_MEM_ACPI 3 +#define CB_MEM_NVS 4 +#define CB_MEM_UNUSABLE 5 +#define CB_MEM_VENDOR_RSVD 6 +#define CB_MEM_TABLE 16 + +struct cb_memory { + UINT32 tag; + UINT32 size; + struct cb_memory_range map[0]; +}; + +#define CB_TAG_MAINBOARD 0x0003 + +struct cb_mainboard { + UINT32 tag; + UINT32 size; + UINT8 vendor_idx; + UINT8 part_number_idx; + UINT8 strings[0]; +}; +#define CB_TAG_VERSION 0x0004 +#define CB_TAG_EXTRA_VERSION 0x0005 +#define CB_TAG_BUILD 0x0006 +#define CB_TAG_COMPILE_TIME 0x0007 +#define CB_TAG_COMPILE_BY 0x0008 +#define CB_TAG_COMPILE_HOST 0x0009 +#define CB_TAG_COMPILE_DOMAIN 0x000a +#define CB_TAG_COMPILER 0x000b +#define CB_TAG_LINKER 0x000c +#define CB_TAG_ASSEMBLER 0x000d + +struct cb_string { + UINT32 tag; + UINT32 size; + UINT8 string[0]; +}; + +#define CB_TAG_SERIAL 0x000f + +struct cb_serial { + UINT32 tag; + UINT32 size; +#define CB_SERIAL_TYPE_IO_MAPPED 1 +#define CB_SERIAL_TYPE_MEMORY_MAPPED 2 + UINT32 type; + UINT32 baseaddr; + UINT32 baud; + UINT32 regwidth; + + // Crystal or input frequency to the chip containing the UART. + // Provide the board specific details to allow the payload to + // initialize the chip containing the UART and make independent + // decisions as to which dividers to select and their values + // to eventually arrive at the desired console baud-rate. + UINT32 input_hertz; + + // UART PCI address: bus, device, function + // 1 << 31 - Valid bit, PCI UART in use + // Bus << 20 + // Device << 15 + // Function << 12 + UINT32 uart_pci_addr; +}; + +#define CB_TAG_CONSOLE 0x00010 + +struct cb_console { + UINT32 tag; + UINT32 size; + UINT16 type; +}; + +#define CB_TAG_CONSOLE_SERIAL8250 0 +#define CB_TAG_CONSOLE_VGA 1 // OBSOLETE +#define CB_TAG_CONSOLE_BTEXT 2 // OBSOLETE +#define CB_TAG_CONSOLE_LOGBUF 3 +#define CB_TAG_CONSOLE_SROM 4 // OBSOLETE +#define CB_TAG_CONSOLE_EHCI 5 + +#define CB_TAG_FORWARD 0x00011 + +struct cb_forward { + UINT32 tag; + UINT32 size; + UINT64 forward; +}; + +struct cb_cbmem_ref { + UINT32 tag; + // Field contains size of this struct == 0x0010 + UINT32 size; + UINT64 cbmem_addr; +}; + +#define CB_TAG_FRAMEBUFFER 0x0012 +struct cb_framebuffer { + UINT32 tag; + UINT32 size; + + UINT64 physical_address; + UINT32 x_resolution; + UINT32 y_resolution; + UINT32 bytes_per_line; + UINT8 bits_per_pixel; + UINT8 red_mask_pos; + UINT8 red_mask_size; + UINT8 green_mask_pos; + UINT8 green_mask_size; + UINT8 blue_mask_pos; + UINT8 blue_mask_size; + UINT8 reserved_mask_pos; + UINT8 reserved_mask_size; +}; + +#define CB_TAG_VDAT 0x0015 +struct cb_vdat { + UINT32 tag; + UINT32 size; /* size of the entire entry */ + UINT64 vdat_addr; + UINT32 vdat_size; +}; + +#define CB_TAG_TIMESTAMPS 0x0016 +#define CB_TAG_CBMEM_CONSOLE 0x0017 +struct cbmem_console { + UINT32 size; + UINT32 cursor; + UINT8 body[0]; +} __attribute__ ((packed)); + +#define CB_TAG_MRC_CACHE 0x0018 +struct cb_cbmem_tab { + UINT32 tag; + UINT32 size; + UINT64 cbmem_tab; +}; + +#define CB_TAG_SMMSTOREV2 0x0039 +struct cb_smmstorev2 { + UINT32 tag; + UINT32 size; + UINT32 num_blocks; /* Number of writeable blocks in SMM */ + UINT32 block_size; /* Size of a block in byte. Default: 64 KiB */ + UINT32 mmap_addr; /* MMIO address of the store for read only access */ + UINT32 com_buffer; /* Physical address of the communication buffer */ + UINT32 com_buffer_size; /* Size of the communication buffer in byte */ + UINT8 apm_cmd; /* The command byte to write to the APM I/O port */ + UINT8 unused[3]; /* Set to zero */ +}; + +#define CB_TAG_VBOOT_WORKBUF 0x0034 + +struct cb_cbmem_entry { + UINT32 tag; + UINT32 size; + + UINT64 address; + UINT32 entry_size; + UINT32 id; +}; + +/* Recovery reason codes */ +enum vb2_nv_recovery { + /**********************************************************************/ + /**** Uncategorized errors ********************************************/ + + /* Recovery not requested. */ + VB2_RECOVERY_NOT_REQUESTED = 0x00, + + /* + * Recovery requested from legacy utility. (Prior to the NV storage + * spec, recovery mode was a single bitfield; this value is reserved so + * that scripts which wrote 1 to the recovery field are distinguishable + * from scripts whch use the recovery reasons listed here. + */ + VB2_RECOVERY_LEGACY = 0x01, + + /* User manually requested recovery via recovery button */ + VB2_RECOVERY_RO_MANUAL = 0x02, + + + + /**********************************************************************/ + /**** Firmware verification (RO) errors (and some EC stuff???) ********/ + + /* Unspecified RW verification error (when none of 0x10-0x1f fit) */ + VB2_RECOVERY_RO_INVALID_RW = 0x03, + + /* S3 resume failed (deprecated) */ + VB2_RECOVERY_DEPRECATED_RO_S3_RESUME = 0x04, + + /* TPM error in read-only firmware (deprecated, see 0x54+) */ + VB2_RECOVERY_DEPRECATED_RO_TPM_ERROR = 0x05, + + /* Shared data error in read-only firmware */ + VB2_RECOVERY_RO_SHARED_DATA = 0x06, + + /* Test error from S3Resume() (deprecated) */ + VB2_RECOVERY_DEPRECATED_RO_TEST_S3 = 0x07, + + /* Test error from LoadFirmwareSetup() (deprecated) */ + VB2_RECOVERY_DEPRECATED_RO_TEST_LFS = 0x08, + + /* Test error from LoadFirmware() (deprecated) */ + VB2_RECOVERY_DEPRECATED_RO_TEST_LF = 0x09, + + /* + * RW firmware failed signature check (neither RW firmware slot was + * valid). Recovery reason is VB2_RECOVERY_DEPRECATED_RW_NOT_DONE + + * the check value for the slot which came closest to validating; see + * VBSD_LF_CHECK_* in vboot_struct.h (deprecated). + */ + VB2_RECOVERY_DEPRECATED_RW_NOT_DONE = 0x10, + + /* Latest tried RW firmware developer flag mismatch */ + VB2_RECOVERY_DEPRECATED_RW_DEV_FLAG_MISMATCH = 0x11, + + /* Latest tried RW firmware recovery flag mismatch */ + VB2_RECOVERY_DEPRECATED_RW_REC_FLAG_MISMATCH = 0x12, + + /* Latest tried RW firmware keyblock verification failed */ + VB2_RECOVERY_FW_KEYBLOCK = 0x13, + + /* Latest tried RW firmware key version too old */ + VB2_RECOVERY_FW_KEY_ROLLBACK = 0x14, + + /* Latest tried RW firmware unable to parse data key */ + VB2_RECOVERY_DEPRECATED_RW_DATA_KEY_PARSE = 0x15, + + /* Latest tried RW firmware preamble verification failed */ + VB2_RECOVERY_FW_PREAMBLE = 0x16, + + /* Latest tried RW firmware version too old */ + VB2_RECOVERY_FW_ROLLBACK = 0x17, + + /* Latest tried RW firmware header valid */ + VB2_RECOVERY_DEPRECATED_FW_HEADER_VALID = 0x18, + + /* Latest tried RW firmware unable to get firmware body */ + VB2_RECOVERY_DEPRECATED_FW_GET_FW_BODY = 0x19, + + /* Latest tried RW firmware hash wrong size */ + VB2_RECOVERY_DEPRECATED_FW_HASH_WRONG_SIZE = 0x1a, + + /* Latest tried RW firmware body verification failed */ + VB2_RECOVERY_FW_BODY = 0x1b, + + /* Latest tried RW firmware valid */ + VB2_RECOVERY_DEPRECATED_FW_VALID = 0x1c, + + /* Latest tried RW firmware RO normal path not supported */ + VB2_RECOVERY_DEPRECATED_FW_NO_RO_NORMAL = 0x1d, + + /* + * Firmware boot failure outside of verified boot (RAM init, missing + * SSD, etc.). + */ + VB2_RECOVERY_RO_FIRMWARE = 0x20, + + /* + * Recovery mode TPM initialization requires a system reboot. The + * system was already in recovery mode for some other reason when this + * happened. + */ + VB2_RECOVERY_RO_TPM_REBOOT = 0x21, + + /* EC software sync - other error */ + VB2_RECOVERY_EC_SOFTWARE_SYNC = 0x22, + + /* EC software sync - unable to determine active EC image */ + VB2_RECOVERY_EC_UNKNOWN_IMAGE = 0x23, + + /* EC software sync - error obtaining EC image hash (deprecated) */ + VB2_RECOVERY_DEPRECATED_EC_HASH = 0x24, + + /* EC software sync - error obtaining expected EC image (deprecated) */ + VB2_RECOVERY_DEPRECATED_EC_EXPECTED_IMAGE = 0x25, + + /* EC software sync - error updating EC */ + VB2_RECOVERY_EC_UPDATE = 0x26, + + /* EC software sync - unable to jump to EC-RW */ + VB2_RECOVERY_EC_JUMP_RW = 0x27, + + /* EC software sync - unable to protect / unprotect EC-RW */ + VB2_RECOVERY_EC_PROTECT = 0x28, + + /* EC software sync - error obtaining expected EC hash */ + VB2_RECOVERY_EC_EXPECTED_HASH = 0x29, + + /* EC software sync - expected EC image doesn't match hash (deprc.) */ + VB2_RECOVERY_DEPRECATED_EC_HASH_MISMATCH = 0x2a, + + /* Firmware secure data initialization error */ + VB2_RECOVERY_SECDATA_FIRMWARE_INIT = 0x2b, + + /* GBB header is bad */ + VB2_RECOVERY_GBB_HEADER = 0x2c, + + /* Unable to clear TPM owner */ + VB2_RECOVERY_TPM_CLEAR_OWNER = 0x2d, + + /* Error determining/updating virtual dev switch */ + VB2_RECOVERY_DEV_SWITCH = 0x2e, + + /* Error determining firmware slot */ + VB2_RECOVERY_FW_SLOT = 0x2f, + + /* Error updating auxiliary firmware */ + VB2_RECOVERY_AUXFW_UPDATE = 0x30, + + /* + * Intel CSE Lite SKU firmware failure; see subcodes defined in coreboot for specific + * reason. + */ + VB2_RECOVERY_INTEL_CSE_LITE_SKU = 0x31, + + /* Unspecified/unknown error in read-only firmware */ + VB2_RECOVERY_RO_UNSPECIFIED = 0x3f, + + + + /**********************************************************************/ + /**** Kernel verification (RW) errors *********************************/ + + /* + * User manually requested recovery by pressing a key at developer + * warning screen (deprecated) + */ + VB2_RECOVERY_DEPRECATED_RW_DEV_SCREEN = 0x41, + + /* No OS kernel detected (deprecated, now 0x5b) */ + VB2_RECOVERY_DEPRECATED_RW_NO_OS = 0x42, + + /* OS kernel failed signature check. Since the kernel corrupts itself + (DMVERROR) on a verity failure, may also indicate corrupt rootfs. */ + VB2_RECOVERY_RW_INVALID_OS = 0x43, + + /* TPM error in rewritable firmware (deprecated, see 0x54+) */ + VB2_RECOVERY_DEPRECATED_RW_TPM_ERROR = 0x44, + + /* RW firmware in dev mode, but dev switch is off (deprecated) */ + VB2_RECOVERY_DEPRECATED_RW_DEV_MISMATCH = 0x45, + + /* Shared data error in rewritable firmware */ + VB2_RECOVERY_RW_SHARED_DATA = 0x46, + + /* Test error from LoadKernel() (deprecated) */ + VB2_RECOVERY_DEPRECATED_RW_TEST_LK = 0x47, + + /* No bootable disk found (deprecated, see 0x5a) */ + VB2_RECOVERY_DEPRECATED_RW_NO_DISK = 0x48, + + /* Rebooting did not correct TPM_E_FAIL or TPM_E_FAILEDSELFTEST */ + VB2_RECOVERY_TPM_E_FAIL = 0x49, + + /* TPM setup error in read-only firmware */ + VB2_RECOVERY_RO_TPM_S_ERROR = 0x50, + + /* TPM write error in read-only firmware */ + VB2_RECOVERY_RO_TPM_W_ERROR = 0x51, + + /* TPM lock error in read-only firmware */ + VB2_RECOVERY_RO_TPM_L_ERROR = 0x52, + + /* TPM update error in read-only firmware */ + VB2_RECOVERY_RO_TPM_U_ERROR = 0x53, + + /* TPM read error in rewritable firmware */ + VB2_RECOVERY_RW_TPM_R_ERROR = 0x54, + + /* TPM write error in rewritable firmware */ + VB2_RECOVERY_RW_TPM_W_ERROR = 0x55, + + /* TPM lock error in rewritable firmware */ + VB2_RECOVERY_RW_TPM_L_ERROR = 0x56, + + /* EC software sync unable to get EC image hash */ + VB2_RECOVERY_EC_HASH_FAILED = 0x57, + + /* EC software sync invalid image hash size */ + VB2_RECOVERY_EC_HASH_SIZE = 0x58, + + /* Unspecified error while trying to load kernel */ + VB2_RECOVERY_LK_UNSPECIFIED = 0x59, + + /* No bootable storage device in system */ + VB2_RECOVERY_RW_NO_DISK = 0x5a, + + /* No bootable kernel found on disk */ + VB2_RECOVERY_RW_NO_KERNEL = 0x5b, + + /* BCB related error in RW firmware (deprecated) */ + VB2_RECOVERY_DEPRECATED_RW_BCB_ERROR = 0x5c, + + /* Kernel secure data initialization error */ + VB2_RECOVERY_SECDATA_KERNEL_INIT = 0x5d, + + /* Fastboot mode requested in firmware (deprecated) */ + VB2_RECOVERY_DEPRECATED_FW_FASTBOOT = 0x5e, + + /* Recovery hash space lock error in RO firmware */ + VB2_RECOVERY_RO_TPM_REC_HASH_L_ERROR = 0x5f, + + /* Failed to disable the TPM [prior to running untrusted code] */ + VB2_RECOVERY_TPM_DISABLE_FAILED = 0x60, + + /* Verification of altfw payload failed (deprecated) */ + VB2_RECOVERY_ALTFW_HASH_MISMATCH = 0x61, + + /* FWMP secure data initialization error */ + VB2_RECOVERY_SECDATA_FWMP_INIT = 0x62, + + /* Failed to get boot mode from TPM/Cr50 */ + VB2_RECOVERY_CR50_BOOT_MODE = 0x63, + + /* Attempt to escape from NO_BOOT mode was detected */ + VB2_RECOVERY_ESCAPE_NO_BOOT = 0x64, + + /* Unspecified/unknown error in rewritable firmware */ + VB2_RECOVERY_RW_UNSPECIFIED = 0x7f, + + + + /**********************************************************************/ + /**** OS level (kernel) errors (deprecated) ***************************/ + + /* + * Note: we want to avoid having the kernel touch vboot NVRAM directly + * in the future, so this whole range is essentially deprecated until + * further notice. + */ + + /* DM-verity error (deprecated) */ + VB2_RECOVERY_DEPRECATED_KE_DM_VERITY = 0x81, + + /* Unspecified/unknown error in kernel (deprecated) */ + VB2_RECOVERY_DEPRECATED_KE_UNSPECIFIED = 0xbf, + + + + /**********************************************************************/ + /**** OS level (userspace) errors *************************************/ + + /* Recovery mode test from user-mode */ + VB2_RECOVERY_US_TEST = 0xc1, + + /* Recovery requested by user-mode via BCB (deprecated) */ + VB2_RECOVERY_DEPRECATED_BCB_USER_MODE = 0xc2, + + /* Fastboot mode requested by user-mode (deprecated) */ + VB2_RECOVERY_DEPRECATED_US_FASTBOOT = 0xc3, + + /* User requested recovery for training memory and rebooting. */ + VB2_RECOVERY_TRAIN_AND_REBOOT = 0xc4, + + /* Unspecified/unknown error in user-mode */ + VB2_RECOVERY_US_UNSPECIFIED = 0xff, +}; + +/* MAX_SIZE should not be changed without bumping up DATA_VERSION_MAJOR. */ +#define VB2_CONTEXT_MAX_SIZE 384 + +/* Current version of vb2_shared_data struct */ +#define VB2_SHARED_DATA_VERSION_MAJOR 3 + +#define VB2_SHARED_DATA_MAGIC 0x44533256 + +struct cb_vboot_workbuf_v2 { + /* Magic number for struct (VB2_SHARED_DATA_MAGIC) */ + UINT32 magic; + + /* Version of this structure */ + UINT16 struct_version_major; + UINT16 struct_version_minor; + + /* Public fields are stored in the context object */ + UINT8 ctx[VB2_CONTEXT_MAX_SIZE]; + + /* Work buffer length in bytes. */ + UINT32 workbuf_size; + + /* + * Amount of work buffer used so far. Verified boot sub-calls use + * this to know where the unused work area starts. + */ + UINT32 workbuf_used; + + /* Flags; see enum vb2_shared_data_flags */ + UINT32 flags; + + /* + * Reason we are in recovery mode this boot (enum vb2_nv_recovery), or + * 0 if we aren't. + */ + UINT32 recovery_reason; + + /* Firmware slot used last boot (0=A, 1=B) */ + UINT32 last_fw_slot; + + /* Result of last boot (enum vb2_fw_result) */ + UINT32 last_fw_result; + + /* Firmware slot used this boot */ + UINT32 fw_slot; + + /* + * Version for this slot (top 16 bits = key, lower 16 bits = firmware). + */ + UINT32 fw_version; + + /* Version from secdata_firmware (must be <= fw_version to boot). */ + UINT32 fw_version_secdata; + + /* + * Status flags for this boot; see enum vb2_shared_data_status. Status + * is "what we've done"; flags above are "decisions we've made". + */ + UINT32 status; + + /* Offset from start of this struct to GBB header */ + UINT32 gbb_offset; + + /********************************************************************** + * Data from kernel verification stage. + */ + + /* + * Version for the current kernel (top 16 bits = key, lower 16 bits = + * kernel preamble). + */ + UINT32 kernel_version; + + /* Version from secdata_kernel (must be <= kernel_version to boot) */ + UINT32 kernel_version_secdata; + + /********************************************************************** + * Temporary variables used during firmware verification. These don't + * really need to persist through to the OS, but there's nowhere else + * we can put them. + */ + + /* Offset of preamble from start of vblock */ + UINT32 vblock_preamble_offset; + + /* + * Offset and size of packed data key in work buffer. Size is 0 if + * data key is not stored in the work buffer. + */ + UINT32 data_key_offset; + UINT32 data_key_size; + + /* + * Offset and size of firmware preamble in work buffer. Size is 0 if + * preamble is not stored in the work buffer. + */ + UINT32 preamble_offset; + UINT32 preamble_size; + + /* + * Offset and size of hash context in work buffer. Size is 0 if + * hash context is not stored in the work buffer. + */ + UINT32 hash_offset; + UINT32 hash_size; + + /* + * Current tag we're hashing + * + * For new structs, this is the offset of the vb2_signature struct + * in the work buffer. + */ + UINT32 hash_tag; + + /* Amount of data we still expect to hash */ + UINT32 hash_remaining_size; + + /********************************************************************** + * Temporary variables used during kernel verification. These don't + * really need to persist through to the OS, but there's nowhere else + * we can put them. + */ + + /* + * Formerly a pointer to vboot1 shared data header ("VBSD"). Caller + * may now export a copy of VBSD via vb2api_export_vbsd(). + */ + UINTN reserved0; + + /* + * Offset and size of packed kernel key in work buffer. Size is 0 if + * subkey is not stored in the work buffer. Note that kernel key may + * be inside the firmware preamble. + */ + UINT32 kernel_key_offset; + UINT32 kernel_key_size; +} __attribute__((packed)); + +#define CB_TAG_LOGO 0x00a0 + +struct cb_bootlogo_header { + UINT64 size; +} __attribute__((packed)); + +/* Helpful macros */ + +#define MEM_RANGE_COUNT(_rec) \ + (((_rec)->size - sizeof(*(_rec))) / sizeof((_rec)->map[0])) + +#define MEM_RANGE_PTR(_rec, _idx) \ + (void *)(((UINT8 *) (_rec)) + sizeof(*(_rec)) \ + + (sizeof((_rec)->map[0]) * (_idx))) + +#define CB_TAG_TPM_PPI_HANDOFF 0x003a + +enum lb_tmp_ppi_tpm_version { + LB_TPM_VERSION_UNSPEC = 0, + LB_TPM_VERSION_TPM_VERSION_1_2, + LB_TPM_VERSION_TPM_VERSION_2, +}; + +/* + * Handoff buffer for TPM Physical Presence Interface. + * * ppi_address Pointer to PPI buffer shared with ACPI + * The layout of the buffer matches the QEMU virtual memory device + * that is generated by QEMU. + * See files 'hw/i386/acpi-build.c' and 'include/hw/acpi/tpm.h' + * for details. + * * tpm_version TPM version: 1 for TPM1.2, 2 for TPM2.0 + * * ppi_version BCD encoded version of TPM PPI interface + */ +struct cb_tpm_physical_presence { + UINT32 tag; + UINT32 size; + UINT32 ppi_address; /* Address of ACPI PPI communication buffer */ + UINT8 tpm_version; /* 1: TPM1.2, 2: TPM2.0 */ + UINT8 ppi_version; /* BCD encoded */ +}; + +#define CB_TAG_CAPSULE 0x0046 + +struct cb_range { + UINT32 tag; + UINT32 size; + UINT64 range_start; + UINT32 range_size; +} __attribute__((packed)); + +#define CB_TAG_FW_INFO 0x0045 + +/* + * Machine-friendly version of a system firmware component. A component is + * identified by a GUID. coreboot is an obvious main component but there could + * be others (like EC) which should get their own instances of the tag. + * + * The main consumer of this information is UEFI firmware but something else + * could reuse it too. + * + * Larger number in a version field corresponds to a more recent version. + */ +struct lb_efi_fw_info { + UINT32 tag; + UINT32 size; + UINT8 guid[16]; /* Called "firmware class" in UEFI */ + UINT32 version; /* Current version */ + UINT32 lowest_supported_version; /* Lowest allowed version */ + UINT32 fw_size; /* Size of firmware in bytes */ +} __attribute__ ((packed)); + +#endif // _COREBOOT_PEI_H_INCLUDED_ diff --git a/DasharoPayloadPkg/Include/Guid/AcpiBoardInfoGuid.h b/DasharoPayloadPkg/Include/Guid/AcpiBoardInfoGuid.h new file mode 100644 index 0000000000..043b748ae4 --- /dev/null +++ b/DasharoPayloadPkg/Include/Guid/AcpiBoardInfoGuid.h @@ -0,0 +1,30 @@ +/** @file + This file defines the hob structure for board related information from acpi table + + Copyright (c) 2014, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __ACPI_BOARD_INFO_GUID_H__ +#define __ACPI_BOARD_INFO_GUID_H__ + +/// +/// Board information GUID +/// +extern EFI_GUID gUefiAcpiBoardInfoGuid; + +typedef struct { + UINT8 Revision; + UINT8 Reserved0[2]; + UINT8 ResetValue; + UINT64 PmEvtBase; + UINT64 PmGpeEnBase; + UINT64 PmCtrlRegBase; + UINT64 PmTimerRegBase; + UINT64 ResetRegAddress; + UINT64 PcieBaseAddress; + UINT64 PcieBaseSize; +} ACPI_BOARD_INFO; + +#endif diff --git a/DasharoPayloadPkg/Include/Guid/ApuConfigurationGuid.h b/DasharoPayloadPkg/Include/Guid/ApuConfigurationGuid.h new file mode 100644 index 0000000000..2bd0366a66 --- /dev/null +++ b/DasharoPayloadPkg/Include/Guid/ApuConfigurationGuid.h @@ -0,0 +1,26 @@ +/** @file + Definition for structure & defines exported by APU Configuration UI + + Copyright (c) 2024, 3mdeb All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef APU_CONFIGURATION_UI_H_ +#define APU_CONFIGURATION_UI_H_ + +#define APU_CONFIGURATION_FORMSET_GUID {0x6f4e051b, 0x1c10, 0x422a, { 0x98, 0xcf, 0x96, 0x2e, 0x78, 0x36, 0x5c, 0x74 } } + +#define APU_CONFIGURATION_VAR L"ApuConfig" + +#pragma pack(push,1) +typedef struct { + BOOLEAN CorePerfBoost; + BOOLEAN WatchdogEnable; + UINT16 WatchdogTimeout; + BOOLEAN PciePwrMgmt; +} APU_CONFIGURATION_VARSTORE_DATA; +#pragma pack(pop) + +#endif diff --git a/DasharoPayloadPkg/Include/Guid/MemoryMapInfoGuid.h b/DasharoPayloadPkg/Include/Guid/MemoryMapInfoGuid.h new file mode 100644 index 0000000000..99187e8037 --- /dev/null +++ b/DasharoPayloadPkg/Include/Guid/MemoryMapInfoGuid.h @@ -0,0 +1,36 @@ +/** @file + This file defines the hob structure for memory map information. + + Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __MEMORY_MAP_INFO_GUID_H__ +#define __MEMORY_MAP_INFO_GUID_H__ + +#include + +/// +/// Memory Map Information GUID +/// +extern EFI_GUID gLoaderMemoryMapInfoGuid; + +#pragma pack(1) +typedef struct { + UINT64 Base; + UINT64 Size; + UINT8 Type; + UINT8 Flag; + UINT8 Reserved[6]; +} MEMROY_MAP_ENTRY; + +typedef struct { + UINT8 Revision; + UINT8 Reserved0[3]; + UINT32 Count; + MEMROY_MAP_ENTRY Entry[0]; +} MEMROY_MAP_INFO; +#pragma pack() + +#endif diff --git a/DasharoPayloadPkg/Include/Guid/SerialPortInfoGuid.h b/DasharoPayloadPkg/Include/Guid/SerialPortInfoGuid.h new file mode 100644 index 0000000000..a15d5b8671 --- /dev/null +++ b/DasharoPayloadPkg/Include/Guid/SerialPortInfoGuid.h @@ -0,0 +1,31 @@ +/** @file + This file defines the hob structure for serial port. + + Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __SERIAL_PORT_INFO_GUID_H__ +#define __SERIAL_PORT_INFO_GUID_H__ + +/// +/// Serial Port Information GUID +/// +extern EFI_GUID gUefiSerialPortInfoGuid; + +#define PLD_SERIAL_TYPE_IO_MAPPED 1 +#define PLD_SERIAL_TYPE_MEMORY_MAPPED 2 + +typedef struct { + UINT8 Revision; + UINT8 Reserved0[3]; + UINT32 Type; + UINT32 BaseAddr; + UINT32 Baud; + UINT32 RegWidth; + UINT32 InputHertz; + UINT32 UartPciAddr; +} SERIAL_PORT_INFO; + +#endif diff --git a/DasharoPayloadPkg/Include/Guid/SmmStoreInfoGuid.h b/DasharoPayloadPkg/Include/Guid/SmmStoreInfoGuid.h new file mode 100644 index 0000000000..d5dcb8218f --- /dev/null +++ b/DasharoPayloadPkg/Include/Guid/SmmStoreInfoGuid.h @@ -0,0 +1,27 @@ +/** @file + This file defines the hob structure for coreboot's SmmStore. + + Copyright (c) 2022, 9elements GmbH
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef SMMSTORE_GUID_H_ +#define SMMSTORE_GUID_H_ + +/// +/// System Table Information GUID +/// +extern EFI_GUID gEfiSmmStoreInfoHobGuid; + +typedef struct { + UINT64 ComBuffer; + UINT32 ComBufferSize; + UINT32 NumBlocks; + UINT32 BlockSize; + UINT64 MmioAddress; + UINT8 ApmCmd; + UINT8 Reserved0[3]; +} SMMSTORE_INFO; + +#endif // SMMSTORE_GUID_H_ diff --git a/DasharoPayloadPkg/Include/Guid/SystemTableInfoGuid.h b/DasharoPayloadPkg/Include/Guid/SystemTableInfoGuid.h new file mode 100644 index 0000000000..2446820285 --- /dev/null +++ b/DasharoPayloadPkg/Include/Guid/SystemTableInfoGuid.h @@ -0,0 +1,26 @@ +/** @file + This file defines the hob structure for system tables like ACPI, SMBIOS tables. + + Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __SYSTEM_TABLE_INFO_GUID_H__ +#define __SYSTEM_TABLE_INFO_GUID_H__ + +/// +/// System Table Information GUID +/// +extern EFI_GUID gUefiSystemTableInfoGuid; + +typedef struct { + UINT8 Revision; + UINT8 Reserved0[3]; + UINT64 AcpiTableBase; + UINT32 AcpiTableSize; + UINT64 SmbiosTableBase; + UINT32 SmbiosTableSize; +} SYSTEM_TABLE_INFO; + +#endif diff --git a/DasharoPayloadPkg/Include/Guid/TcgPhysicalPresenceGuid.h b/DasharoPayloadPkg/Include/Guid/TcgPhysicalPresenceGuid.h new file mode 100644 index 0000000000..1f8ca6e3ab --- /dev/null +++ b/DasharoPayloadPkg/Include/Guid/TcgPhysicalPresenceGuid.h @@ -0,0 +1,30 @@ +/** @file + This file defines the hob structure for Tcg Physical Presence Interface. + + Copyright (c) 2020, 9elements Agency GmbH
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __TCG_PHYSICAL_PRESENCE_GUID_H__ +#define __TCG_PHYSICAL_PRESENCE_GUID_H__ + +/// +/// TCG Physical Presence Information GUID +/// +extern EFI_GUID gEfiTcgPhysicalPresenceInfoHobGuid; + +typedef struct { + UINT32 PpiAddress; + UINT8 TpmVersion; + UINT8 PpiVersion; +} TCG_PHYSICAL_PRESENCE_INFO; + +#define UEFIPAYLOAD_TPM_VERSION_UNSPEC 0 +#define UEFIPAYLOAD_TPM_VERSION_1_2 1 +#define UEFIPAYLOAD_TPM_VERSION_2 2 + +#define UEFIPAYLOAD_TPM_PPI_VERSION_NONE 0 +#define UEFIPAYLOAD_TPM_PPI_VERSION_1_30 1 + +#endif diff --git a/DasharoPayloadPkg/Include/Library/BlParseLib.h b/DasharoPayloadPkg/Include/Library/BlParseLib.h new file mode 100644 index 0000000000..75718f2b5e --- /dev/null +++ b/DasharoPayloadPkg/Include/Library/BlParseLib.h @@ -0,0 +1,250 @@ +/** @file + This library will parse the coreboot table in memory and extract those required + information. + + Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef __BOOTLOADER_PARSE_LIB__ +#define __BOOTLOADER_PARSE_LIB__ + +#define GET_BOOTLOADER_PARAMETER() (*(UINT32 *)(UINTN)(PcdGet32(PcdPayloadStackTop) - sizeof(UINT32))) +#define SET_BOOTLOADER_PARAMETER(Value) GET_BOOTLOADER_PARAMETER()=Value + +typedef RETURN_STATUS \ + (*BL_MEM_INFO_CALLBACK) (MEMROY_MAP_ENTRY *MemoryMapEntry, VOID *Param); + +typedef VOID \ + (*BL_CAPSULE_CALLBACK) (EFI_PHYSICAL_ADDRESS BaseAddress, UINT64 Length); + +/** + This function retrieves the parameter base address from boot loader. + + This function will get bootloader specific parameter address for UEFI payload. + e.g. HobList pointer for Slim Bootloader, and coreboot table header for Coreboot. + + @retval NULL Failed to find the GUID HOB. + @retval others GUIDed HOB data pointer. + +**/ +VOID * +EFIAPI +GetParameterBase ( + VOID + ); + +/** + Acquire the memory map information. + + @param MemInfoCallback The callback routine + @param Params Pointer to the callback routine parameter + + @retval RETURN_SUCCESS Successfully find out the memory information. + @retval RETURN_NOT_FOUND Failed to find the memory information. + +**/ +RETURN_STATUS +EFIAPI +ParseMemoryInfo ( + IN BL_MEM_INFO_CALLBACK MemInfoCallback, + IN VOID *Params + ); + +/** + Acquire acpi table and smbios table from slim bootloader + + @param SystemTableInfo Pointer to the system table info + + @retval RETURN_SUCCESS Successfully find out the tables. + @retval RETURN_NOT_FOUND Failed to find the tables. + +**/ +RETURN_STATUS +EFIAPI +ParseSystemTable ( + OUT SYSTEM_TABLE_INFO *SystemTableInfo + ); + + +/** + Find the serial port information + + @param SERIAL_PORT_INFO Pointer to serial port info structure + + @retval RETURN_SUCCESS Successfully find the serial port information. + @retval RETURN_NOT_FOUND Failed to find the serial port information . + +**/ +RETURN_STATUS +EFIAPI +ParseSerialInfo ( + OUT SERIAL_PORT_INFO *SerialPortInfo + ); + + +/** + Find the video frame buffer information + + @param GfxInfo Pointer to the EFI_PEI_GRAPHICS_INFO_HOB structure + + @retval RETURN_SUCCESS Successfully find the video frame buffer information. + @retval RETURN_NOT_FOUND Failed to find the video frame buffer information . + +**/ +RETURN_STATUS +EFIAPI +ParseGfxInfo ( + OUT EFI_PEI_GRAPHICS_INFO_HOB *GfxInfo + ); + +/** + Find the video frame buffer device information + + @param GfxDeviceInfo Pointer to the EFI_PEI_GRAPHICS_DEVICE_INFO_HOB structure + + @retval RETURN_SUCCESS Successfully find the video frame buffer information. + @retval RETURN_NOT_FOUND Failed to find the video frame buffer information . + +**/ +RETURN_STATUS +EFIAPI +ParseGfxDeviceInfo ( + OUT EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *GfxDeviceInfo + ); + +/** + Find the video frame buffer device information + + @param SMMSTOREInfo Pointer to the SMMSTORE_INFO structure + + @retval RETURN_SUCCESS Successfully find the SMM store buffer information. + @retval RETURN_NOT_FOUND Failed to find the SMM store buffer information . + +**/ +RETURN_STATUS +EFIAPI +ParseSMMSTOREInfo ( + OUT SMMSTORE_INFO *SMMSTOREInfo + ); + +/** + Find the Tcg Physical Presence store information + + @param PPIInfo Pointer to the TCG_PHYSICAL_PRESENCE_INFO structure + + @retval RETURN_SUCCESS Successfully find the SMM store buffer information. + @retval RETURN_NOT_FOUND Failed to find the SMM store buffer information . + +**/ +RETURN_STATUS +EFIAPI +ParseTPMPPIInfo ( + OUT TCG_PHYSICAL_PRESENCE_INFO *PPIInfo + ); + +/** + Acquire Vboot recovery information from coreboot + + @param RecoveryCode Recovery reason code, zero if not in recovery mode. + @param RecoveryReason Why are we in recovery boot as a string. + + @retval RETURN_SUCCESS Successfully found VBoot data. + @retval RETURN_NOT_FOUND Failed to find VBoot data. + +**/ +RETURN_STATUS +EFIAPI +ParseVBootWorkbuf ( + OUT UINT8 *RecoveryCode, + OUT CONST CHAR8 **RecoveryReason + ); + +/** + Parse the coreboot timestamps + + @retval RETURN_SUCCESS Successfully find the timestamps information. + @retval RETURN_NOT_FOUND Failed to find the tiemstamps information . +**/ +RETURN_STATUS +EFIAPI +ParseTimestampTable ( + OUT FIRMWARE_SEC_PERFORMANCE *Performance + ); + +/** + Parse update capsules passed in by coreboot + + @param CapsuleCallback The callback routine invoked for each capsule. + + @retval RETURN_SUCCESS Successfully parsed capsules. + @retval RETURN_NOT_FOUND coreboot table is missing. +**/ +RETURN_STATUS +EFIAPI +ParseCapsules ( + IN BL_CAPSULE_CALLBACK CapsuleCallback + ); + +/** + Acquire boot logo from coreboot + + @param BmpAddress Pointer to the bitmap file + @param BmpSize Size of the image + + @retval RETURN_SUCCESS Successfully find the boot logo. + @retval RETURN_NOT_FOUND Failed to find the boot logo. +**/ +RETURN_STATUS +EFIAPI +ParseBootLogo ( + OUT UINT64 *BmpAddress, + OUT UINT32 *BmpSize + ); + +/** + Parse firmware information passed in by coreboot + + @param Guid Kind of the firmware. + @param Version Current version. + @param Lsv Lowest supported version. + @param Size Firmware size in bytes. + + @retval RETURN_INVALID_PARAMETER At least one of the parameters is NULL. + @retval RETURN_SUCCESS Successfully parsed capsules. + @retval RETURN_NOT_FOUND coreboot table is missing. +**/ +RETURN_STATUS +EFIAPI +ParseFwInfo ( + OUT EFI_GUID *Guid, + OUT UINT32 *Version, + OUT UINT32 *Lsv, + OUT UINT32 *Size + ); + +/** + Parse information in a string form identified by a number + + @param Id String identifier. + + @retval NULL The requested information wasn't found. + @retval Otherwise A pointer to a static string. +**/ +CONST CHAR8 * +EFIAPI +ParseInfoString ( + IN UINTN Id + ); + +#endif diff --git a/DasharoPayloadPkg/Include/Library/CbfsLib.h b/DasharoPayloadPkg/Include/Library/CbfsLib.h new file mode 100644 index 0000000000..beb7ea557c --- /dev/null +++ b/DasharoPayloadPkg/Include/Library/CbfsLib.h @@ -0,0 +1,6 @@ +#ifndef __CBFS_LIB__ +#define __CBFS_LIB__ + +#include + +#endif diff --git a/DasharoPayloadPkg/Include/Library/EfiVarsLib.h b/DasharoPayloadPkg/Include/Library/EfiVarsLib.h new file mode 100644 index 0000000000..24c4eba025 --- /dev/null +++ b/DasharoPayloadPkg/Include/Library/EfiVarsLib.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: BSD-2-Clause-Patent */ + +#ifndef __EFI_VARS_LIB__ +#define __EFI_VARS_LIB__ + +#include +#include +#include +#include + +typedef struct { + UINT8 *Start; + UINTN Length; +} MemRange; + +typedef struct EfiVar { + UINT32 Attrs; + EFI_GUID Guid; + CHAR16 *Name; + UINTN NameSize; // in bytes + UINT8 *Data; + UINTN DataSize; // in bytes + struct EfiVar *Next; +} EfiVar; + +typedef struct { + MemRange Fv; + MemRange Store; + EfiVar *Vars; +} EfiVars; + +BOOLEAN +EFIAPI +EfiVarsInit ( + IN OUT MemRange Fv, + OUT EfiVars *Storage + ); + +BOOLEAN +EFIAPI +EfiVarsWrite ( + IN EfiVars *Storage + ); + +EfiVar * +EFIAPI +EfiVarsCreateVar ( + IN EfiVars *Storage + ); + +VOID +EFIAPI +EfiVarsFree ( + IN EfiVars *Storage + ); + +#endif diff --git a/DasharoPayloadPkg/Include/Library/FmapLib.h b/DasharoPayloadPkg/Include/Library/FmapLib.h new file mode 100644 index 0000000000..86fb95bd2a --- /dev/null +++ b/DasharoPayloadPkg/Include/Library/FmapLib.h @@ -0,0 +1,88 @@ +/** @file + coreboot flash map data parsing library. + +Copyright (c) 2024, coreboot project
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/* SPDX-License-Identifier: BSD-3-Clause or GPL-2.0-only */ + +#ifndef FLASHMAP_LIB_FMAP_H__ +#define FLASHMAP_LIB_FMAP_H__ + +#define FMAP_SIGNATURE "__FMAP__" +#define FMAP_VER_MAJOR 1 /* this header's FMAP minor version */ +#define FMAP_VER_MINOR 1 /* this header's FMAP minor version */ +#define FMAP_STRLEN 32 /* maximum length for strings (including * + * null-terminator) */ + +/* Mapping of volatile and static regions in firmware binary */ +typedef struct { + UINT32 offset; /* offset relative to base */ + UINT32 size; /* size in bytes */ + UINT8 name[FMAP_STRLEN]; /* descriptive name */ + UINT16 flags; /* flags for this area */ +} __attribute__((packed)) FmapArea; + +typedef struct { + UINT8 signature[8]; /* "__FMAP__" (0x5F5F464D41505F5F) */ + UINT8 ver_major; /* major version */ + UINT8 ver_minor; /* minor version */ + UINT64 base; /* address of the firmware binary */ + UINT32 size; /* size of firmware binary in bytes */ + UINT8 name[FMAP_STRLEN]; /* name of this firmware binary */ + UINT16 nareas; /* number of areas described by fmap_areas[] below */ + FmapArea areas[]; +} __attribute__((packed)) Fmap; + +/* + * FmapFind - find FMAP signature in a binary Image + * + * @Image: binary Image + * @Len: length of binary Image + * + * This function does no error checking. The caller is responsible for + * verifying that the contents are sane. + * + * returns offset of FMAP signature to indicate success + * returns <0 to indicate failure + */ +INTN +EFIAPI +FmapFind ( + CONST UINT8 *Image, + UINTN Len + ); + +/* + * fmap_size - returns size of fmap data structure (including areas) + * + * @Map: fmap + * + * returns size of fmap structure if successful + * returns <0 to indicate failure + */ +INTN +EFIAPI +FmapSize ( + IN CONST Fmap *Map + ); + +/* + * FmapFindArea - find an fmap_area entry (by name) and return pointer to it + * + * @Map: fmap structure to parse + * @Name: name of area to find + * + * returns a pointer to the entry in the fmap structure if successful + * returns NULL to indicate failure or if no matching area entry is found + */ +CONST FmapArea * +EFIAPI +FmapFindArea ( + IN CONST Fmap *Map, + IN CONST CHAR8 *Name +); + +#endif /* FLASHMAP_LIB_FMAP_H__*/ diff --git a/DasharoPayloadPkg/Include/Library/LaptopBatteryLib.h b/DasharoPayloadPkg/Include/Library/LaptopBatteryLib.h new file mode 100644 index 0000000000..1b4f6b799c --- /dev/null +++ b/DasharoPayloadPkg/Include/Library/LaptopBatteryLib.h @@ -0,0 +1,68 @@ +/** @file + Library that query laptop EC for AC state and battery capacity. + +Copyright (c) 2023, 3mdeb. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +#ifndef __LAPTOP_BATTERY_LIB__ +#define __LAPTOP_BATTERY_LIB__ + +/** + This function retrieves the AC adapter connection state from EC. + + @param AcState Pointer to the AC state + + @retval RETURN_SUCCESS Successfully probed the AC connection state. + @retval RETURN_UNSUPPORTED Function is unsupported. + @retval RETURN_TIMEOUT EC cpommunication timeout. + @retval RETURN_INVALID_PARAMETER NULL pointer passed as parameter + +**/ +RETURN_STATUS +EFIAPI +LaptopGetAcState ( + BOOLEAN *AcState + ); + +/** + This function retrieves the battery connection state from EC. + + @param AcState Pointer to the AC state + + @retval RETURN_SUCCESS Successfully probed the battery connection state. + @retval RETURN_UNSUPPORTED Function is unsupported. + @retval RETURN_TIMEOUT EC cpommunication timeout. + @retval RETURN_INVALID_PARAMETER NULL pointer passed as parameter + +**/ +RETURN_STATUS +EFIAPI +LaptopGetBatState ( + BOOLEAN *BatState + ); + +/** + This function retrieves the current battery capacity from EC. + + @param BatteryCapacity Pointer to the battery capacity in percent + + @retval RETURN_SUCCESS Successfully probed the battery capacity. + @retval RETURN_UNSUPPORTED Function is unsupported. + @retval RETURN_TIMEOUT EC cpommunication timeout. + @retval RETURN_INVALID_PARAMETER NULL pointer passed as parameter + +**/ +RETURN_STATUS +EFIAPI +LaptopGetBatteryCapacity ( + UINT32 *BatteryCapacity + ); + +#endif diff --git a/DasharoPayloadPkg/Include/Library/LaptopLidLib.h b/DasharoPayloadPkg/Include/Library/LaptopLidLib.h new file mode 100644 index 0000000000..ace3a6ee14 --- /dev/null +++ b/DasharoPayloadPkg/Include/Library/LaptopLidLib.h @@ -0,0 +1,44 @@ +/** @file + Library that query laptop EC for lid state. + +Copyright (c) 2023, 3mdeb. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +#ifndef __LAPTOP_LID_LIB__ +#define __LAPTOP_LID_LIB__ + +#pragma pack(1) + +typedef enum { + LidClosed, + LidOpen, + LidStatusMax +} LID_STATUS; + +#pragma pack() + +/** + This function retrieves the lid state from EC. + + @param LidState Pointer to the lid state + + @retval RETURN_SUCCESS Successfully probed the lid state. + @retval RETURN_UNSUPPORTED Function is unsupported. + @retval RETURN_TIMEOUT EC communication timeout. + @retval RETURN_INVALID_PARAMETER NULL pointer passed as parameter + +**/ +EFI_STATUS +EFIAPI +LaptopGetLidState ( + LID_STATUS *LidState + ); + +#endif diff --git a/DasharoPayloadPkg/Include/Library/PlatformSupportLib.h b/DasharoPayloadPkg/Include/Library/PlatformSupportLib.h new file mode 100644 index 0000000000..d9f0b83075 --- /dev/null +++ b/DasharoPayloadPkg/Include/Library/PlatformSupportLib.h @@ -0,0 +1,28 @@ +/** @file + Bootloader Platform Support library. Platform can provide an implementation of this + library class to provide hooks that may be required for some type of + platform features. + +Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __BOOTLOADER_PLATFORM_SUPPORT_LIB__ +#define __BOOTLOADER_PLATFORM_SUPPORT_LIB__ + +/** + Parse platform specific information from bootloader + + @retval RETURN_SUCCESS The platform specific coreboot support succeeded. + @retval RETURN_DEVICE_ERROR The platform specific coreboot support could not be completed. + +**/ +EFI_STATUS +EFIAPI +ParsePlatformInfo ( + VOID + ); + +#endif // __BOOTLOADER_PLATFORM_SUPPORT_LIB__ + diff --git a/DasharoPayloadPkg/Include/Library/SmmStoreLib.h b/DasharoPayloadPkg/Include/Library/SmmStoreLib.h new file mode 100644 index 0000000000..3148612423 --- /dev/null +++ b/DasharoPayloadPkg/Include/Library/SmmStoreLib.h @@ -0,0 +1,196 @@ +/** @file SmmStoreLib.h + + Copyright (c) 2022, 9elements GmbH
+ Copyright (c) 2024, 3mdeb Sp. z o.o.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef SMM_STORE_LIB_H_ +#define SMM_STORE_LIB_H_ + +#include +#include +#include + +#define SMMSTORE_COMBUF_SIZE 16 + +/** + Get the SmmStore block size + + @param BlockSize The pointer to store the block size in. + +**/ +EFI_STATUS +SmmStoreLibGetBlockSize ( + OUT UINTN *BlockSize + ); + +/** + Get the SmmStore number of blocks + + @param NumBlocks The pointer to store the number of blocks in. + +**/ +EFI_STATUS +SmmStoreLibGetNumBlocks ( + OUT UINTN *NumBlocks + ); + +/** + Get the SmmStore MMIO address + + @param MmioAddress The pointer to store the address in. + +**/ +EFI_STATUS +SmmStoreLibGetMmioAddress ( + OUT EFI_PHYSICAL_ADDRESS *MmioAddress + ); + +/** + Read from SmmStore + + @param[in] Lba The starting logical block index to read from. + @param[in] Offset Offset into the block at which to begin reading. + @param[in] NumBytes On input, indicates the requested read size. On + output, indicates the actual number of bytes read + @param[in] Buffer Pointer to the buffer to read into. + +**/ +EFI_STATUS +SmmStoreLibRead ( + IN EFI_LBA Lba, + IN UINTN Offset, + IN UINTN *NumBytes, + IN UINT8 *Buffer + ); + +/** + Read from an arbitrary flash location. The whole flash is represented as a + sequence of blocks. + + @param[in] Lba The starting logical block index to read from. + @param[in] Offset Offset into the block at which to begin reading. + @param[in] NumBytes On input, indicates the requested read size. On + output, indicates the actual number of bytes read + @param[in] Buffer Pointer to the buffer to read into. + +**/ +EFI_STATUS +SmmStoreLibReadAnyBlock ( + IN EFI_LBA Lba, + IN UINTN Offset, + IN UINTN *NumBytes, + IN UINT8 *Buffer + ); + +/** + Write to SmmStore + + @param[in] Lba The starting logical block index to write to. + @param[in] Offset Offset into the block at which to begin writing. + @param[in] NumBytes On input, indicates the requested write size. On + output, indicates the actual number of bytes written + @param[in] Buffer Pointer to the data to write. + +**/ +EFI_STATUS +SmmStoreLibWrite ( + IN EFI_LBA Lba, + IN UINTN Offset, + IN UINTN *NumBytes, + IN UINT8 *Buffer + ); + +/** + Write to an arbitrary flash location. The whole flash is represented as a + sequence of blocks. + + @param[in] Lba The starting logical block index to write to. + @param[in] Offset Offset into the block at which to begin writing. + @param[in] NumBytes On input, indicates the requested write size. On + output, indicates the actual number of bytes written + @param[in] Buffer Pointer to the data to write. + +**/ +EFI_STATUS +SmmStoreLibWriteAnyBlock ( + IN EFI_LBA Lba, + IN UINTN Offset, + IN UINTN *NumBytes, + IN UINT8 *Buffer + ); + +/** + Erase a block using the SmmStore + + @param Lba The logical block index to erase. + +**/ +EFI_STATUS +SmmStoreLibEraseBlock ( + IN EFI_LBA Lba + ); + +/** + Erase an arbitrary block of the flash. The whole flash is represented as a + sequence of blocks. + + @param Lba The logical block index to erase. + +**/ +EFI_STATUS +SmmStoreLibEraseAnyBlock ( + IN EFI_LBA Lba + ); + +/** + Function to update a pointer on virtual address change. Matches the signature + and operation of EfiConvertPointer. + +**/ +typedef EFI_STATUS EFIAPI (*ConvertPointerFunc) ( + IN UINTN DebugDisposition, + IN OUT VOID **Address + ); + +/** + Initializes SmmStore support + + @retval EFI_WRITE_PROTECTED The SmmStore is not present. + @retval EFI_UNSUPPORTED The SmmStoreInfo HOB wasn't found. + @retval EFI_SUCCESS The SmmStore is supported. + +**/ +EFI_STATUS +SmmStoreLibInitialize ( + VOID + ); + +/** + Fixup internal data so that EFI can be called in virtual mode. + Converts any pointers in lib to virtual mode. This function is meant to + be invoked on gEfiEventVirtualAddressChangeGuid event when the library is + used at run-time. + + @param[in] ConvertPointer Function to switch virtual address space. + +**/ +VOID +EFIAPI +SmmStoreLibVirtualAddressChange ( + IN ConvertPointerFunc ConvertPointer + ); + +/** + Denitializes SmmStore support +**/ +VOID +EFIAPI +SmmStoreLibDeinitialize ( + VOID + ); + +#endif /* SMM_STORE_LIB_H_ */ diff --git a/DasharoPayloadPkg/Library/AcpiTimerLib/AcpiTimerLib.c b/DasharoPayloadPkg/Library/AcpiTimerLib/AcpiTimerLib.c new file mode 100644 index 0000000000..5e3b427db0 --- /dev/null +++ b/DasharoPayloadPkg/Library/AcpiTimerLib/AcpiTimerLib.c @@ -0,0 +1,286 @@ +/** @file + ACPI Timer implements one instance of Timer Library. + + Copyright (c) 2014, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#define ACPI_TIMER_COUNT_SIZE BIT24 + +UINTN mPmTimerReg = 0; + +/** + The constructor function enables ACPI IO space. + + If ACPI I/O space not enabled, this function will enable it. + It will always return RETURN_SUCCESS. + + @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS. + +**/ +RETURN_STATUS +EFIAPI +AcpiTimerLibConstructor ( + VOID + ) +{ + EFI_HOB_GUID_TYPE *GuidHob; + ACPI_BOARD_INFO *pAcpiBoardInfo; + + if (GetHobList () == NULL) { + // When this library is used by PEI_CORE and HOBs are created by one of + // PEIMs (e.g., BlSupportPei) doing nothing is the best we can do. An + // alternative is to crash in GetFirstGuidHob () because it assumes there + // is at least on HOB. + // + // This function will get called later by InternalAcpiGetTimerTick () until + // a successful initialization which practically means several times and + // a non-working timer doesn't cause an infinite loop at that point. + return EFI_SUCCESS; + } + + // + // Find the acpi board information guid hob + // + GuidHob = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid); + ASSERT (GuidHob != NULL); + + pAcpiBoardInfo = (ACPI_BOARD_INFO *)GET_GUID_HOB_DATA (GuidHob); + + mPmTimerReg = (UINTN)pAcpiBoardInfo->PmTimerRegBase; + + return EFI_SUCCESS; +} + +/** + Internal function to read the current tick counter of ACPI. + + Internal function to read the current tick counter of ACPI. + + @return The tick counter read. + +**/ +UINT32 +InternalAcpiGetTimerTick ( + VOID + ) +{ + if (mPmTimerReg == 0) { + AcpiTimerLibConstructor (); + if (mPmTimerReg == 0) { + // Must be too early, avoid IoRead32 () call below. + return 0; + } + } + return IoRead32 (mPmTimerReg); +} + +/** + Stalls the CPU for at least the given number of ticks. + + Stalls the CPU for at least the given number of ticks. It's invoked by + MicroSecondDelay() and NanoSecondDelay(). + + @param Delay A period of time to delay in ticks. + +**/ +VOID +InternalAcpiDelay ( + IN UINT32 Delay + ) +{ + UINT32 Ticks; + UINT32 Times; + + Times = Delay >> 22; + Delay &= BIT22 - 1; + do { + // + // The target timer count is calculated here + // + Ticks = InternalAcpiGetTimerTick () + Delay; + Delay = BIT22; + // + // Wait until time out + // Delay >= 2^23 could not be handled by this function + // Timer wrap-arounds are handled correctly by this function + // + while (((Ticks - InternalAcpiGetTimerTick ()) & BIT23) == 0) { + CpuPause (); + } + } while (Times-- > 0); +} + +/** + Stalls the CPU for at least the given number of microseconds. + + Stalls the CPU for the number of microseconds specified by MicroSeconds. + + @param MicroSeconds The minimum number of microseconds to delay. + + @return MicroSeconds + +**/ +UINTN +EFIAPI +MicroSecondDelay ( + IN UINTN MicroSeconds + ) +{ + InternalAcpiDelay ( + (UINT32)DivU64x32 ( + MultU64x32 ( + MicroSeconds, + ACPI_TIMER_FREQUENCY + ), + 1000000u + ) + ); + return MicroSeconds; +} + +/** + Stalls the CPU for at least the given number of nanoseconds. + + Stalls the CPU for the number of nanoseconds specified by NanoSeconds. + + @param NanoSeconds The minimum number of nanoseconds to delay. + + @return NanoSeconds + +**/ +UINTN +EFIAPI +NanoSecondDelay ( + IN UINTN NanoSeconds + ) +{ + InternalAcpiDelay ( + (UINT32)DivU64x32 ( + MultU64x32 ( + NanoSeconds, + ACPI_TIMER_FREQUENCY + ), + 1000000000u + ) + ); + return NanoSeconds; +} + +/** + Retrieves the current value of a 64-bit free running performance counter. + + Retrieves the current value of a 64-bit free running performance counter. The + counter can either count up by 1 or count down by 1. If the physical + performance counter counts by a larger increment, then the counter values + must be translated. The properties of the counter can be retrieved from + GetPerformanceCounterProperties(). + + @return The current value of the free running performance counter. + +**/ +UINT64 +EFIAPI +GetPerformanceCounter ( + VOID + ) +{ + return (UINT64)InternalAcpiGetTimerTick (); +} + +/** + Retrieves the 64-bit frequency in Hz and the range of performance counter + values. + + If StartValue is not NULL, then the value that the performance counter starts + with immediately after is it rolls over is returned in StartValue. If + EndValue is not NULL, then the value that the performance counter end with + immediately before it rolls over is returned in EndValue. The 64-bit + frequency of the performance counter in Hz is always returned. If StartValue + is less than EndValue, then the performance counter counts up. If StartValue + is greater than EndValue, then the performance counter counts down. For + example, a 64-bit free running counter that counts up would have a StartValue + of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter + that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0. + + @param StartValue The value the performance counter starts with when it + rolls over. + @param EndValue The value that the performance counter ends with before + it rolls over. + + @return The frequency in Hz. + +**/ +UINT64 +EFIAPI +GetPerformanceCounterProperties ( + OUT UINT64 *StartValue, OPTIONAL + OUT UINT64 *EndValue OPTIONAL + ) +{ + if (StartValue != NULL) { + *StartValue = 0; + } + + if (EndValue != NULL) { + *EndValue = ACPI_TIMER_COUNT_SIZE - 1; + } + + return ACPI_TIMER_FREQUENCY; +} + +/** + Converts elapsed ticks of performance counter to time in nanoseconds. + + This function converts the elapsed ticks of running performance counter to + time value in unit of nanoseconds. + + @param Ticks The number of elapsed ticks of running performance counter. + + @return The elapsed time in nanoseconds. + +**/ +UINT64 +EFIAPI +GetTimeInNanoSecond ( + IN UINT64 Ticks + ) +{ + UINT64 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/DasharoPayloadPkg/Library/AcpiTimerLib/AcpiTimerLib.inf b/DasharoPayloadPkg/Library/AcpiTimerLib/AcpiTimerLib.inf new file mode 100644 index 0000000000..758dbbeca0 --- /dev/null +++ b/DasharoPayloadPkg/Library/AcpiTimerLib/AcpiTimerLib.inf @@ -0,0 +1,40 @@ +## @file +# ACPI Timer Library Instance. +# +# Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = AcpiTimerLib + FILE_GUID = A41BF616-EF77-4658-9992-D813071C34CF + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = TimerLib + + CONSTRUCTOR = AcpiTimerLibConstructor + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + AcpiTimerLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + DasharoPayloadPkg/DasharoPayloadPkg.dec + +[LibraryClasses] + BaseLib + IoLib + HobLib + DebugLib + +[Guids] + gUefiAcpiBoardInfoGuid diff --git a/DasharoPayloadPkg/Library/BasePciExpressLib/BasePciExpressLib.inf b/DasharoPayloadPkg/Library/BasePciExpressLib/BasePciExpressLib.inf new file mode 100644 index 0000000000..07cc8a2c7c --- /dev/null +++ b/DasharoPayloadPkg/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.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BasePciExpressLib + MODULE_UNI_FILE = BasePciExpressLib.uni + FILE_GUID = 287e50f4-a188-4699-b907-3e4080ca5688 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PciExpressLib + CONSTRUCTOR = PciExpressLibInitialize + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + PciExpressLib.c + +[Packages] + MdePkg/MdePkg.dec + DasharoPayloadPkg/DasharoPayloadPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + HobLib + IoLib + +[Guids] + gUefiAcpiBoardInfoGuid + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress ## CONSUMES + diff --git a/DasharoPayloadPkg/Library/BasePciExpressLib/BasePciExpressLib.uni b/DasharoPayloadPkg/Library/BasePciExpressLib/BasePciExpressLib.uni new file mode 100644 index 0000000000..98010ef2f9 --- /dev/null +++ b/DasharoPayloadPkg/Library/BasePciExpressLib/BasePciExpressLib.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of PCI Express Library using the 256 MB PCI Express MMIO window. +// +// PCI Express Library that uses the 256 MB PCI Express MMIO window to perform +// PCI Configuration cycles. Layers on top of an I/O Library instance. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of PCI Express Library using the 256 MB PCI Express MMIO window" + +#string STR_MODULE_DESCRIPTION #language en-US "PCI Express Library that uses the 256 MB PCI Express MMIO window to perform PCI Configuration cycles. Layers on top of an I/O Library instance." + diff --git a/DasharoPayloadPkg/Library/BasePciExpressLib/PciExpressLib.c b/DasharoPayloadPkg/Library/BasePciExpressLib/PciExpressLib.c new file mode 100644 index 0000000000..f3b4582d3c --- /dev/null +++ b/DasharoPayloadPkg/Library/BasePciExpressLib/PciExpressLib.c @@ -0,0 +1,1455 @@ +/** @file + Functions in this library instance make use of MMIO functions in IoLib to + access memory mapped PCI configuration space. + + All assertions for I/O operations are handled in MMIO functions in the IoLib + Library. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +STATIC ACPI_BOARD_INFO mBoardInfo; +/** + Assert the validity of a PCI address. + If Address > 0x0FFFFFFF, then ASSERT(). + + Return 0xff on transaction outside of the MMCONF space. + + @param A The address to validate. + +**/ +#define ASSERT_INVALID_PCI_ADDRESS(A) \ + ASSERT (((A) & ~0xfffffff) == 0); \ + if ((A) >= mBoardInfo.PcieBaseSize) { \ + return ~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; +} + +/** + Performs platform specific initialization required for the CPU to access + the MMCONF space. This function does not initialize the MMCONF itself. + + @retval RETURN_SUCCESS The platform specific initialization succeeded. + @retval RETURN_DEVICE_ERROR The platform specific initialization could not be completed. + +**/ +RETURN_STATUS +EFIAPI +PciExpressLibInitialize ( + VOID + ) +{ + EFI_HOB_GUID_TYPE *GuidHob; + + // + // Find the acpi board information guid hob + // + GuidHob = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid); + ASSERT (GuidHob != NULL); + if (GuidHob == NULL) { + return EFI_UNSUPPORTED; + } + + CopyMem (&mBoardInfo, GET_GUID_HOB_DATA (GuidHob), sizeof(mBoardInfo)); + return EFI_SUCCESS; +} + +/** + 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) mBoardInfo.PcieBaseAddress; +} + +/** + 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/DasharoPayloadPkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf b/DasharoPayloadPkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf new file mode 100644 index 0000000000..03b719d4bd --- /dev/null +++ b/DasharoPayloadPkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf @@ -0,0 +1,42 @@ +## @file +# Instance of PCI Library based on PCI Express Library. +# +# PCI Library that uses the 256 MB PCI Express MMIO window to perform PCI +# Configuration cycles. Layers on one PCI Express Library instance. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BasePciLibPciExpress + MODULE_UNI_FILE = BasePciLibPciExpress.uni + FILE_GUID = 8987081e-daeb-44a9-8bef-a195b22d9417 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PciLib + CONSTRUCTOR = PciLibInitialize + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + PciLib.c + +[Packages] + MdePkg/MdePkg.dec + DasharoPayloadPkg/DasharoPayloadPkg.dec + +[Guids] + gUefiAcpiBoardInfoGuid + +[LibraryClasses] + PciExpressLib + PciCf8Lib + BaseLib + HobLib diff --git a/DasharoPayloadPkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.uni b/DasharoPayloadPkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.uni new file mode 100644 index 0000000000..ccc456356c --- /dev/null +++ b/DasharoPayloadPkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of PCI Library based on PCI Express Library. +// +// PCI Library that uses the 256 MB PCI Express MMIO window to perform PCI +// Configuration cycles. Layers on one PCI Express Library instance. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of PCI Library based on PCI Express Library" + +#string STR_MODULE_DESCRIPTION #language en-US "PCI Library that uses the 256 MB PCI Express MMIO window to perform PCI Configuration cycles. Layers on an PCI Express Library instance." + diff --git a/DasharoPayloadPkg/Library/BasePciLibPciExpress/PciLib.c b/DasharoPayloadPkg/Library/BasePciLibPciExpress/PciLib.c new file mode 100644 index 0000000000..fba5914462 --- /dev/null +++ b/DasharoPayloadPkg/Library/BasePciLibPciExpress/PciLib.c @@ -0,0 +1,1302 @@ +/** @file + PCI Library functions that use the 256 MB PCI Express MMIO window to perform PCI + Configuration cycles. Layers on PCI Express Library. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +STATIC BOOLEAN mMMCONFEnabled; + +/** + 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); +} + +/** + Performs platform specific initialization required for the CPU to access + the MMCONF space. This function does not initialize the MMCONF itself. + + @retval RETURN_SUCCESS The platform specific initialization succeeded. + @retval RETURN_DEVICE_ERROR The platform specific initialization could not be completed. + +**/ +RETURN_STATUS +EFIAPI +PciLibInitialize ( + VOID + ) +{ + EFI_HOB_GUID_TYPE *GuidHob; + ACPI_BOARD_INFO *AcpiBoardInfoPtr; + + // + // Find the acpi board information guid hob + // + GuidHob = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid); + if (GuidHob == NULL) { + return EFI_SUCCESS; + } + AcpiBoardInfoPtr = (ACPI_BOARD_INFO *)GET_GUID_HOB_DATA (GuidHob); + + mMMCONFEnabled = AcpiBoardInfoPtr->PcieBaseAddress != 0 && + AcpiBoardInfoPtr->PcieBaseSize != 0; + return EFI_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 +PciRead8 ( + IN UINTN Address + ) +{ + if (mMMCONFEnabled) { + return PciExpressRead8 (Address); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressWrite8 (Address, Value); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressOr8 (Address, OrData); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressAnd8 (Address, AndData); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressAndThenOr8 (Address, AndData, OrData); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressBitFieldRead8 (Address, StartBit, EndBit); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressBitFieldWrite8 (Address, StartBit, EndBit, Value); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressBitFieldOr8 (Address, StartBit, EndBit, OrData); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressBitFieldAnd8 (Address, StartBit, EndBit, AndData); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressBitFieldAndThenOr8 (Address, StartBit, EndBit, AndData, OrData); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressRead16 (Address); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressWrite16 (Address, Value); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressOr16 (Address, OrData); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressAnd16 (Address, AndData); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressAndThenOr16 (Address, AndData, OrData); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressBitFieldRead16 (Address, StartBit, EndBit); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressBitFieldWrite16 (Address, StartBit, EndBit, Value); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressBitFieldOr16 (Address, StartBit, EndBit, OrData); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressBitFieldAnd16 (Address, StartBit, EndBit, AndData); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressBitFieldAndThenOr16 (Address, StartBit, EndBit, AndData, OrData); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressRead32 (Address); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressWrite32 (Address, Value); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressOr32 (Address, OrData); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressAnd32 (Address, AndData); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressAndThenOr32 (Address, AndData, OrData); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressBitFieldRead32 (Address, StartBit, EndBit); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressBitFieldWrite32 (Address, StartBit, EndBit, Value); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressBitFieldOr32 (Address, StartBit, EndBit, OrData); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressBitFieldAnd32 (Address, StartBit, EndBit, AndData); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressBitFieldAndThenOr32 (Address, StartBit, EndBit, AndData, OrData); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressReadBuffer (StartAddress, Size, Buffer); + } else { + 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 + ) +{ + if (mMMCONFEnabled) { + return PciExpressWriteBuffer (StartAddress, Size, Buffer); + } else { + return PciCf8WriteBuffer (StartAddress, Size, Buffer); + } +} diff --git a/DasharoPayloadPkg/Library/BaseRngLib/BaseRng.c b/DasharoPayloadPkg/Library/BaseRngLib/BaseRng.c new file mode 100644 index 0000000000..2aa3495be0 --- /dev/null +++ b/DasharoPayloadPkg/Library/BaseRngLib/BaseRng.c @@ -0,0 +1,192 @@ +/** @file + Random number generator services that uses RdRand instruction access + to provide high-quality random numbers. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +STATIC BOOLEAN mHasRdRand; + +// +// 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); + + mHasRdRand = ((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); + + if (mHasRdRand) { + // + // 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); + + if (mHasRdRand) { + // + // 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); + + if (mHasRdRand) { + // + // 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/DasharoPayloadPkg/Library/BaseRngLib/BaseRngLib.inf b/DasharoPayloadPkg/Library/BaseRngLib/BaseRngLib.inf new file mode 100644 index 0000000000..67a91ccfff --- /dev/null +++ b/DasharoPayloadPkg/Library/BaseRngLib/BaseRngLib.inf @@ -0,0 +1,32 @@ +## @file +# Instance of RNG (Random Number Generator) Library. +# +# Copyright (c) 2020 9elements Agency GmbH.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseRngLib + MODULE_UNI_FILE = BaseRngLib.uni + FILE_GUID = 05C48431-DE18-4550-931A-3350E8551498 + 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/DasharoPayloadPkg/Library/BaseRngLib/BaseRngLib.uni b/DasharoPayloadPkg/Library/BaseRngLib/BaseRngLib.uni new file mode 100644 index 0000000000..f3ed954c52 --- /dev/null +++ b/DasharoPayloadPkg/Library/BaseRngLib/BaseRngLib.uni @@ -0,0 +1,17 @@ +// /** @file +// Instance of RNG (Random Number Generator) Library. +// +// BaseRng Library that uses CPU RdRand instruction access to provide +// high-quality random numbers. +// +// Copyright (c) 2015, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Instance of RNG Library" + +#string STR_MODULE_DESCRIPTION #language en-US "BaseRng Library that uses CPU RdRand instruction access to provide high-quality random numbers" + diff --git a/DasharoPayloadPkg/Library/CbParseLib/CbParseLib.c b/DasharoPayloadPkg/Library/CbParseLib/CbParseLib.c new file mode 100644 index 0000000000..8331252b10 --- /dev/null +++ b/DasharoPayloadPkg/Library/CbParseLib/CbParseLib.c @@ -0,0 +1,1089 @@ +/** @file + This library will parse the coreboot table in memory and extract those required + information. + + Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + + Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+ SPDX-License-Identifier: BSD-3-Clause +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/** + Convert a packed value from cbuint64 to a UINT64 value. + + @param val The pointer to packed data. + + @return the UNIT64 value after conversion. + +**/ +UINT64 +cb_unpack64 ( + IN struct cbuint64 val + ) +{ + return LShiftU64 (val.hi, 32) | val.lo; +} + + +/** + Returns the sum of all elements in a buffer of 16-bit values. During + calculation, the carry bits are also been added. + + @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 included during additions. + +**/ +UINT16 +CbCheckSum16 ( + IN UINT16 *Buffer, + IN UINTN Length + ) +{ + UINT32 Sum; + UINT32 TmpValue; + UINTN Idx; + UINT8 *TmpPtr; + + Sum = 0; + TmpPtr = (UINT8 *)Buffer; + for(Idx = 0; Idx < Length; Idx++) { + TmpValue = TmpPtr[Idx]; + if (Idx % 2 == 1) { + TmpValue <<= 8; + } + + Sum += TmpValue; + + // Wrap + if (Sum >= 0x10000) { + Sum = (Sum + (Sum >> 16)) & 0xFFFF; + } + } + + return (UINT16)((~Sum) & 0xFFFF); +} + + +/** + Check the coreboot table if it is valid. + + @param Header Pointer to coreboot table + + @retval TRUE The coreboot table is valid. + @retval Others The coreboot table is not valid. + +**/ +BOOLEAN +IsValidCbTable ( + IN struct cb_header *Header + ) +{ + UINT16 CheckSum; + + if ((Header == NULL) || (Header->table_bytes == 0)) { + return FALSE; + } + + if (Header->signature != CB_HEADER_SIGNATURE) { + return FALSE; + } + + // + // Check the checksum of the coreboot table header + // + CheckSum = CbCheckSum16 ((UINT16 *)Header, sizeof (*Header)); + if (CheckSum != 0) { + DEBUG ((DEBUG_ERROR, "Invalid coreboot table header checksum\n")); + return FALSE; + } + + CheckSum = CbCheckSum16 ((UINT16 *)((UINT8 *)Header + sizeof (*Header)), Header->table_bytes); + if (CheckSum != Header->table_checksum) { + DEBUG ((DEBUG_ERROR, "Incorrect checksum of all the coreboot table entries\n")); + return FALSE; + } + + return TRUE; +} + + +/** + This function retrieves the parameter base address from boot loader. + + This function will get bootloader specific parameter address for UEFI payload. + e.g. HobList pointer for Slim Bootloader, and coreboot table header for Coreboot. + + @retval NULL Failed to find the GUID HOB. + @retval others GUIDed HOB data pointer. + +**/ +VOID * +EFIAPI +GetParameterBase ( + VOID + ) +{ + struct cb_header *Header; + struct cb_record *Record; + UINT8 *TmpPtr; + UINT8 *CbTablePtr; + UINTN Idx; + + // + // coreboot could pass coreboot table to UEFI payload + // + Header = (struct cb_header *)(UINTN)GET_BOOTLOADER_PARAMETER (); + if (IsValidCbTable (Header)) { + return Header; + } + + // + // Find simplified coreboot table in memory range 0 ~ 4KB. + // Some GCC version does not allow directly access to NULL pointer, + // so start the search from 0x10 instead. + // + for (Idx = 16; Idx < 4096; Idx += 16) { + Header = (struct cb_header *)Idx; + if (Header->signature == CB_HEADER_SIGNATURE) { + break; + } + } + + if (Idx >= 4096) { + return NULL; + } + + // + // Check the coreboot header + // + if (!IsValidCbTable (Header)) { + return NULL; + } + + // + // Find full coreboot table in high memory + // + CbTablePtr = NULL; + TmpPtr = (UINT8 *)Header + Header->header_bytes; + for (Idx = 0; Idx < Header->table_entries; Idx++) { + Record = (struct cb_record *)TmpPtr; + if (Record->tag == CB_TAG_FORWARD) { + CbTablePtr = (VOID *)(UINTN)((struct cb_forward *)(UINTN)Record)->forward; + break; + } + TmpPtr += Record->size; + } + + // + // Check the coreboot header in high memory + // + if (!IsValidCbTable ((struct cb_header *)CbTablePtr)) { + return NULL; + } + + SET_BOOTLOADER_PARAMETER ((UINT32)(UINTN)CbTablePtr); + + return CbTablePtr; +} + + +/** + Find coreboot record with given Tag. + + @param Tag The tag id to be found + + @retval NULL The Tag is not found. + @retval Others The pointer to the record found. + +**/ +VOID * +FindCbTag ( + IN UINT32 Tag + ) +{ + struct cb_header *Header; + struct cb_record *Record; + UINT8 *TmpPtr; + UINT8 *TagPtr; + UINTN Idx; + + Header = (struct cb_header *) GetParameterBase (); + + TagPtr = NULL; + TmpPtr = (UINT8 *)Header + Header->header_bytes; + for (Idx = 0; Idx < Header->table_entries; Idx++) { + Record = (struct cb_record *)TmpPtr; + if (Record->tag == Tag) { + TagPtr = TmpPtr; + break; + } + TmpPtr += Record->size; + } + + return TagPtr; +} + + +/** + Find the given table with TableId from the given coreboot memory Root. + + @param Root The coreboot memory table to be searched in + @param TableId Table id to be found + @param MemTable To save the base address of the memory table found + @param MemTableSize To save the size of memory table found + + @retval RETURN_SUCCESS Successfully find out the memory table. + @retval RETURN_INVALID_PARAMETER Invalid input parameters. + @retval RETURN_NOT_FOUND Failed to find the memory table. + +**/ +RETURN_STATUS +FindCbMemTable ( + IN struct cbmem_root *Root, + IN UINT32 TableId, + OUT VOID **MemTable, + OUT UINT32 *MemTableSize + ) +{ + UINTN Idx; + BOOLEAN IsImdEntry; + struct cbmem_entry *Entries; + + if ((Root == NULL) || (MemTable == NULL)) { + return RETURN_INVALID_PARAMETER; + } + // + // Check if the entry is CBMEM or IMD + // and handle them separately + // + Entries = Root->entries; + if (Entries[0].magic == CBMEM_ENTRY_MAGIC) { + IsImdEntry = FALSE; + } else { + Entries = (struct cbmem_entry *)((struct imd_root *)Root)->entries; + if (Entries[0].magic == IMD_ENTRY_MAGIC) { + IsImdEntry = TRUE; + } else { + return RETURN_NOT_FOUND; + } + } + + for (Idx = 0; Idx < Root->num_entries; Idx++) { + if (Entries[Idx].id == TableId) { + if (IsImdEntry) { + *MemTable = (VOID *) ((UINTN)Entries[Idx].start + (UINTN)Root); + } else { + *MemTable = (VOID *) (UINTN)Entries[Idx].start; + } + if (MemTableSize != NULL) { + *MemTableSize = Entries[Idx].size; + } + + DEBUG ((DEBUG_INFO, "Find CbMemTable Id 0x%x, base %p, size 0x%x\n", + TableId, *MemTable, Entries[Idx].size)); + return RETURN_SUCCESS; + } + } + + return RETURN_NOT_FOUND; +} + +/** + Acquire the coreboot memory table with the given table id + + @param TableId Table id to be searched + @param MemTable Pointer to the base address of the memory table + @param MemTableSize Pointer to the size of the memory table + + @retval RETURN_SUCCESS Successfully find out the memory table. + @retval RETURN_INVALID_PARAMETER Invalid input parameters. + @retval RETURN_NOT_FOUND Failed to find the memory table. + +**/ +RETURN_STATUS +ParseCbMemTable ( + IN UINT32 TableId, + OUT VOID **MemTable, + OUT UINT32 *MemTableSize + ) +{ + EFI_STATUS Status; + struct cb_memory *rec; + struct cb_memory_range *Range; + UINT64 Start; + UINT64 Size; + UINTN Index; + struct cbmem_root *CbMemRoot; + + if (MemTable == NULL) { + return RETURN_INVALID_PARAMETER; + } + + *MemTable = NULL; + Status = RETURN_NOT_FOUND; + + // + // Get the coreboot memory table + // + rec = (struct cb_memory *)FindCbTag (CB_TAG_MEMORY); + if (rec == NULL) { + return Status; + } + + for (Index = 0; Index < MEM_RANGE_COUNT(rec); Index++) { + Range = MEM_RANGE_PTR(rec, Index); + Start = cb_unpack64(Range->start); + Size = cb_unpack64(Range->size); + + if ((Range->type == CB_MEM_TABLE) && (Start > 0x1000)) { + CbMemRoot = (struct cbmem_root *)(UINTN)(Start + Size - DYN_CBMEM_ALIGN_SIZE); + Status = FindCbMemTable (CbMemRoot, TableId, MemTable, MemTableSize); + if (!EFI_ERROR (Status)) { + break; + } + } + } + + return Status; +} + + + +/** + Acquire the memory information from the coreboot table in memory. + + @param MemInfoCallback The callback routine + @param Params Pointer to the callback routine parameter + + @retval RETURN_SUCCESS Successfully find out the memory information. + @retval RETURN_NOT_FOUND Failed to find the memory information. + +**/ +RETURN_STATUS +EFIAPI +ParseMemoryInfo ( + IN BL_MEM_INFO_CALLBACK MemInfoCallback, + IN VOID *Params + ) +{ + struct cb_memory *rec; + struct cb_memory_range *Range; + UINTN Index; + MEMROY_MAP_ENTRY MemoryMap; + UINT32 Tolud; + + Tolud = PciRead32(PCI_LIB_ADDRESS(0,0,0,0xbc)) & 0xFFF00000; + + // + // Get the coreboot memory table + // + rec = (struct cb_memory *)FindCbTag (CB_TAG_MEMORY); + if (rec == NULL) { + return RETURN_NOT_FOUND; + } + + for (Index = 0; Index < MEM_RANGE_COUNT(rec); Index++) { + Range = MEM_RANGE_PTR(rec, Index); + MemoryMap.Base = cb_unpack64(Range->start); + MemoryMap.Size = cb_unpack64(Range->size); + MemoryMap.Type = (UINT8)Range->type; + + switch (Range->type) { + case CB_MEM_RAM: + MemoryMap.Type = EFI_RESOURCE_SYSTEM_MEMORY; + MemoryMap.Flag = EFI_RESOURCE_ATTRIBUTE_PRESENT; + break; + /* Only MMIO is marked reserved */ + case CB_MEM_RESERVED: + /* + * Reserved memory Below TOLUD can't be MMIO except legacy VGA which + * is reported elsewhere as reserved. + */ + if (MemoryMap.Base < Tolud) { + MemoryMap.Type = EFI_RESOURCE_MEMORY_RESERVED; + MemoryMap.Flag = EFI_RESOURCE_ATTRIBUTE_PRESENT; + } else { + MemoryMap.Type = EFI_RESOURCE_MEMORY_MAPPED_IO; + MemoryMap.Flag = EFI_RESOURCE_ATTRIBUTE_PRESENT; + } + break; + case CB_MEM_UNUSABLE: + MemoryMap.Type = EFI_RESOURCE_MEMORY_RESERVED; + MemoryMap.Flag = 0; + break; + case CB_MEM_VENDOR_RSVD: + MemoryMap.Type = EFI_RESOURCE_FIRMWARE_DEVICE; + MemoryMap.Flag = EFI_RESOURCE_ATTRIBUTE_PRESENT; + break; + /* ACPI/SMBIOS/CBMEM has it's own tag */ + case CB_MEM_ACPI: + case CB_MEM_TABLE: + MemoryMap.Type = EFI_RESOURCE_MEMORY_RESERVED; + MemoryMap.Flag = EFI_RESOURCE_ATTRIBUTE_PRESENT; + break; + default: + continue; + } + + DEBUG ((DEBUG_INFO, "%d. %016lx - %016lx [%02x]\n", + Index, MemoryMap.Base, MemoryMap.Base + MemoryMap.Size - 1, MemoryMap.Type)); + + MemInfoCallback (&MemoryMap, Params); + } + + return RETURN_SUCCESS; +} + + +/** + Acquire acpi table and smbios table from coreboot + + @param SystemTableInfo Pointer to the system table info + + @retval RETURN_SUCCESS Successfully find out the tables. + @retval RETURN_NOT_FOUND Failed to find the tables. + +**/ +RETURN_STATUS +EFIAPI +ParseSystemTable ( + OUT SYSTEM_TABLE_INFO *SystemTableInfo + ) +{ + EFI_STATUS Status; + VOID *MemTable; + UINT32 MemTableSize; + + Status = ParseCbMemTable (SIGNATURE_32 ('T', 'B', 'M', 'S'), &MemTable, &MemTableSize); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + SystemTableInfo->SmbiosTableBase = (UINT64) (UINTN)MemTable; + SystemTableInfo->SmbiosTableSize = MemTableSize; + + Status = ParseCbMemTable (SIGNATURE_32 ('I', 'P', 'C', 'A'), &MemTable, &MemTableSize); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + SystemTableInfo->AcpiTableBase = (UINT64) (UINTN)MemTable; + SystemTableInfo->AcpiTableSize = MemTableSize; + + return Status; +} + + +/** + Find the serial port information + + @param SERIAL_PORT_INFO Pointer to serial port info structure + + @retval RETURN_SUCCESS Successfully find the serial port information. + @retval RETURN_NOT_FOUND Failed to find the serial port information . + +**/ +RETURN_STATUS +EFIAPI +ParseSerialInfo ( + OUT SERIAL_PORT_INFO *SerialPortInfo + ) +{ + struct cb_serial *CbSerial; + + CbSerial = FindCbTag (CB_TAG_SERIAL); + if (CbSerial == NULL) { + return RETURN_NOT_FOUND; + } + + SerialPortInfo->BaseAddr = CbSerial->baseaddr; + SerialPortInfo->RegWidth = CbSerial->regwidth; + SerialPortInfo->Type = CbSerial->type; + SerialPortInfo->Baud = CbSerial->baud; + SerialPortInfo->InputHertz = CbSerial->input_hertz; + SerialPortInfo->UartPciAddr = CbSerial->uart_pci_addr; + + return RETURN_SUCCESS; +} + +/** + Find the video frame buffer information + + @param GfxInfo Pointer to the EFI_PEI_GRAPHICS_INFO_HOB structure + + @retval RETURN_SUCCESS Successfully find the video frame buffer information. + @retval RETURN_NOT_FOUND Failed to find the video frame buffer information . + +**/ +RETURN_STATUS +EFIAPI +ParseGfxInfo ( + OUT EFI_PEI_GRAPHICS_INFO_HOB *GfxInfo + ) +{ + struct cb_framebuffer *CbFbRec; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *GfxMode; + + if (GfxInfo == NULL) { + return RETURN_INVALID_PARAMETER; + } + + CbFbRec = FindCbTag (CB_TAG_FRAMEBUFFER); + if (CbFbRec == NULL) { + return RETURN_NOT_FOUND; + } + + DEBUG ((DEBUG_INFO, "Found coreboot video frame buffer information\n")); + DEBUG ((DEBUG_INFO, "physical_address: 0x%lx\n", CbFbRec->physical_address)); + DEBUG ((DEBUG_INFO, "x_resolution: 0x%x\n", CbFbRec->x_resolution)); + DEBUG ((DEBUG_INFO, "y_resolution: 0x%x\n", CbFbRec->y_resolution)); + DEBUG ((DEBUG_INFO, "bits_per_pixel: 0x%x\n", CbFbRec->bits_per_pixel)); + DEBUG ((DEBUG_INFO, "bytes_per_line: 0x%x\n", CbFbRec->bytes_per_line)); + + DEBUG ((DEBUG_INFO, "red_mask_size: 0x%x\n", CbFbRec->red_mask_size)); + DEBUG ((DEBUG_INFO, "red_mask_pos: 0x%x\n", CbFbRec->red_mask_pos)); + DEBUG ((DEBUG_INFO, "green_mask_size: 0x%x\n", CbFbRec->green_mask_size)); + DEBUG ((DEBUG_INFO, "green_mask_pos: 0x%x\n", CbFbRec->green_mask_pos)); + DEBUG ((DEBUG_INFO, "blue_mask_size: 0x%x\n", CbFbRec->blue_mask_size)); + DEBUG ((DEBUG_INFO, "blue_mask_pos: 0x%x\n", CbFbRec->blue_mask_pos)); + DEBUG ((DEBUG_INFO, "reserved_mask_size: 0x%x\n", CbFbRec->reserved_mask_size)); + DEBUG ((DEBUG_INFO, "reserved_mask_pos: 0x%x\n", CbFbRec->reserved_mask_pos)); + + GfxMode = &GfxInfo->GraphicsMode; + GfxMode->Version = 0; + GfxMode->HorizontalResolution = CbFbRec->x_resolution; + GfxMode->VerticalResolution = CbFbRec->y_resolution; + GfxMode->PixelsPerScanLine = (CbFbRec->bytes_per_line << 3) / CbFbRec->bits_per_pixel; + if ((CbFbRec->red_mask_pos == 0) && (CbFbRec->green_mask_pos == 8) && (CbFbRec->blue_mask_pos == 16)) { + GfxMode->PixelFormat = PixelRedGreenBlueReserved8BitPerColor; + } else if ((CbFbRec->blue_mask_pos == 0) && (CbFbRec->green_mask_pos == 8) && (CbFbRec->red_mask_pos == 16)) { + GfxMode->PixelFormat = PixelBlueGreenRedReserved8BitPerColor; + } + GfxMode->PixelInformation.RedMask = ((1 << CbFbRec->red_mask_size) - 1) << CbFbRec->red_mask_pos; + GfxMode->PixelInformation.GreenMask = ((1 << CbFbRec->green_mask_size) - 1) << CbFbRec->green_mask_pos; + GfxMode->PixelInformation.BlueMask = ((1 << CbFbRec->blue_mask_size) - 1) << CbFbRec->blue_mask_pos; + GfxMode->PixelInformation.ReservedMask = ((1 << CbFbRec->reserved_mask_size) - 1) << CbFbRec->reserved_mask_pos; + + GfxInfo->FrameBufferBase = CbFbRec->physical_address; + GfxInfo->FrameBufferSize = CbFbRec->bytes_per_line * CbFbRec->y_resolution; + + return RETURN_SUCCESS; +} + +/** + Find the video frame buffer device information + + @param GfxDeviceInfo Pointer to the EFI_PEI_GRAPHICS_DEVICE_INFO_HOB structure + + @retval RETURN_SUCCESS Successfully find the video frame buffer information. + @retval RETURN_NOT_FOUND Failed to find the video frame buffer information. + +**/ +RETURN_STATUS +EFIAPI +ParseGfxDeviceInfo ( + OUT EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *GfxDeviceInfo + ) +{ + return RETURN_NOT_FOUND; +} + +/** + Find the SMM store information + + @param SMMSTOREInfo Pointer to the SMMSTORE_INFO structure + + @retval RETURN_SUCCESS Successfully find the SMM store buffer information. + @retval RETURN_NOT_FOUND Failed to find the SMM store buffer information . + +**/ +RETURN_STATUS +EFIAPI +ParseSMMSTOREInfo ( + OUT SMMSTORE_INFO *SMMSTOREInfo + ) +{ + struct cb_smmstorev2 *CbSSRec; + + if (SMMSTOREInfo == NULL) { + return RETURN_INVALID_PARAMETER; + } + + CbSSRec = FindCbTag (CB_TAG_SMMSTOREV2); + if (CbSSRec == NULL) { + return RETURN_NOT_FOUND; + } + + DEBUG ((DEBUG_INFO, "Found SMM Store information\n")); + DEBUG ((DEBUG_INFO, "block size: 0x%x\n", CbSSRec->block_size)); + DEBUG ((DEBUG_INFO, "number of blocks: 0x%x\n", CbSSRec->num_blocks)); + DEBUG ((DEBUG_INFO, "communication buffer: 0x%x\n", CbSSRec->com_buffer)); + DEBUG ((DEBUG_INFO, "communication buffer size: 0x%x\n", CbSSRec->com_buffer_size)); + DEBUG ((DEBUG_INFO, "MMIO address of store: 0x%x\n", CbSSRec->mmap_addr)); + + SMMSTOREInfo->ComBuffer = CbSSRec->com_buffer; + SMMSTOREInfo->ComBufferSize = CbSSRec->com_buffer_size; + SMMSTOREInfo->BlockSize = CbSSRec->block_size; + SMMSTOREInfo->NumBlocks = CbSSRec->num_blocks; + SMMSTOREInfo->MmioAddress = CbSSRec->mmap_addr; + SMMSTOREInfo->ApmCmd = CbSSRec->apm_cmd; + + return RETURN_SUCCESS; +} + +/** + Find the Tcg Physical Presence store information + + @param PPIInfo Pointer to the TCG_PHYSICAL_PRESENCE_INFO structure + + @retval RETURN_SUCCESS Successfully find the SMM store buffer information. + @retval RETURN_NOT_FOUND Failed to find the SMM store buffer information . + +**/ +RETURN_STATUS +EFIAPI +ParseTPMPPIInfo ( + OUT TCG_PHYSICAL_PRESENCE_INFO *PPIInfo + ) +{ + struct cb_tpm_physical_presence *CbTPPRec; + UINT8 VersionMajor; + UINT8 VersionMinor; + + if (PPIInfo == NULL) { + return RETURN_INVALID_PARAMETER; + } + + CbTPPRec = FindCbTag (CB_TAG_TPM_PPI_HANDOFF); + if (CbTPPRec == NULL) { + return RETURN_NOT_FOUND; + } + + VersionMajor = CbTPPRec->ppi_version >> 4; + VersionMinor = CbTPPRec->ppi_version & 0xF; + + DEBUG ((DEBUG_INFO, "Found Tcg Physical Presence information\n")); + DEBUG ((DEBUG_INFO, "PpiAddress: 0x%x\n", CbTPPRec->ppi_address)); + DEBUG ((DEBUG_INFO, "TpmVersion: 0x%x\n", CbTPPRec->tpm_version)); + DEBUG ((DEBUG_INFO, "PpiVersion: %x.%x\n", VersionMajor, VersionMinor)); + + PPIInfo->PpiAddress = CbTPPRec->ppi_address; + if (CbTPPRec->tpm_version == LB_TPM_VERSION_TPM_VERSION_1_2) { + PPIInfo->TpmVersion = UEFIPAYLOAD_TPM_VERSION_1_2; + } else if (CbTPPRec->tpm_version == LB_TPM_VERSION_TPM_VERSION_2) { + PPIInfo->TpmVersion = UEFIPAYLOAD_TPM_VERSION_2; + } + if (VersionMajor == 1 && VersionMinor >= 3) { + PPIInfo->PpiVersion = UEFIPAYLOAD_TPM_PPI_VERSION_1_30; + } + + return RETURN_SUCCESS; +} + +STATIC +CONST CHAR8 * +GetRecoveryReasonString( + IN UINT8 code + ) +{ + switch ((enum vb2_nv_recovery)code) { + case VB2_RECOVERY_NOT_REQUESTED: /* 0x00 */ + return "recovery not requested"; + case VB2_RECOVERY_LEGACY: /* 0x01 */ + return "recovery requested from legacy utility"; + case VB2_RECOVERY_RO_MANUAL: /* 0x02 */ + return "recovery button pressed"; + case VB2_RECOVERY_RO_INVALID_RW: /* 0x03 */ + return "RW firmware failed signature check"; + case VB2_RECOVERY_DEPRECATED_RO_S3_RESUME: /* 0x04 */ + return "S3 resume failed"; + case VB2_RECOVERY_DEPRECATED_RO_TPM_ERROR: /* 0x05 */ + return "TPM error in read-only firmware"; + case VB2_RECOVERY_RO_SHARED_DATA: /* 0x06 */ + return "shared data error in read-only firmware"; + case VB2_RECOVERY_DEPRECATED_RO_TEST_S3: /* 0x07 */ + return "test error from S3Resume()"; + case VB2_RECOVERY_DEPRECATED_RO_TEST_LFS: /* 0x08 */ + return "test error from LoadFirmwareSetup()"; + case VB2_RECOVERY_DEPRECATED_RO_TEST_LF: /* 0x09 */ + return "test error from LoadFirmware()"; + case VB2_RECOVERY_DEPRECATED_RW_NOT_DONE: /* 0x10 */ + return "RW firmware check not done"; + case VB2_RECOVERY_DEPRECATED_RW_DEV_FLAG_MISMATCH: /* 0x11 */ + return "RW firmware developer flag mismatch"; + case VB2_RECOVERY_DEPRECATED_RW_REC_FLAG_MISMATCH: /* 0x12 */ + return "RW firmware recovery flag mismatch"; + case VB2_RECOVERY_FW_KEYBLOCK: /* 0x13 */ + return "RW firmware unable to verify keyblock"; + case VB2_RECOVERY_FW_KEY_ROLLBACK: /* 0x14 */ + return "RW firmware key version rollback detected"; + case VB2_RECOVERY_DEPRECATED_RW_DATA_KEY_PARSE: /* 0x15 */ + return "RW firmware unable to parse data key"; + case VB2_RECOVERY_FW_PREAMBLE: /* 0x16 */ + return "RW firmware unable to verify preamble"; + case VB2_RECOVERY_FW_ROLLBACK: /* 0x17 */ + return "RW firmware version rollback detected"; + case VB2_RECOVERY_DEPRECATED_FW_HEADER_VALID: /* 0x18 */ + return "RW firmware header is valid"; + case VB2_RECOVERY_DEPRECATED_FW_GET_FW_BODY: /* 0x19 */ + return "RW firmware unable to get firmware body"; + case VB2_RECOVERY_DEPRECATED_FW_HASH_WRONG_SIZE: /* 0x1a */ + return "RW firmware hash is wrong size"; + case VB2_RECOVERY_FW_BODY: /* 0x1b */ + return "RW firmware unable to verify firmware body"; + case VB2_RECOVERY_DEPRECATED_FW_VALID: /* 0x1c */ + return "RW firmware is valid"; + case VB2_RECOVERY_DEPRECATED_FW_NO_RO_NORMAL: /* 0x1d */ + return "RW firmware read-only normal path is not supported"; + case VB2_RECOVERY_RO_FIRMWARE: /* 0x20 */ + return "firmware problem outside of verified boot"; + case VB2_RECOVERY_RO_TPM_REBOOT: /* 0x21 */ + return "TPM requires a system reboot (should be transient)"; + case VB2_RECOVERY_EC_SOFTWARE_SYNC: /* 0x22 */ + return "EC software sync error"; + case VB2_RECOVERY_EC_UNKNOWN_IMAGE: /* 0x23 */ + return "EC software sync unable to determine active EC image"; + case VB2_RECOVERY_DEPRECATED_EC_HASH: /* 0x24 */ + return "EC software sync error obtaining EC image hash"; + case VB2_RECOVERY_DEPRECATED_EC_EXPECTED_IMAGE: /* 0x25 */ + return "EC software sync error obtaining expected EC image from BIOS"; + case VB2_RECOVERY_EC_UPDATE: /* 0x26 */ + return "EC software sync error updating EC"; + case VB2_RECOVERY_EC_JUMP_RW: /* 0x27 */ + return "EC software sync unable to jump to EC-RW"; + case VB2_RECOVERY_EC_PROTECT: /* 0x28 */ + return "EC software sync protection error"; + case VB2_RECOVERY_EC_EXPECTED_HASH: /* 0x29 */ + return "EC software sync error obtaining expected EC hash from BIOS"; + case VB2_RECOVERY_DEPRECATED_EC_HASH_MISMATCH: /* 0x2a */ + return "EC software sync error comparing expected EC hash and image"; + case VB2_RECOVERY_SECDATA_FIRMWARE_INIT: /* 0x2b */ + return "firmware secure NVRAM (TPM) initialization error"; + case VB2_RECOVERY_GBB_HEADER: /* 0x2c */ + return "error parsing GBB header"; + case VB2_RECOVERY_TPM_CLEAR_OWNER: /* 0x2d */ + return "error trying to clear TPM owner"; + case VB2_RECOVERY_DEV_SWITCH: /* 0x2e */ + return "error reading or updating developer switch"; + case VB2_RECOVERY_FW_SLOT: /* 0x2f */ + return "error selecting RW firmware slot"; + case VB2_RECOVERY_AUXFW_UPDATE: /* 0x30 */ + return "error updating auxiliary firmware"; + case VB2_RECOVERY_INTEL_CSE_LITE_SKU: /* 0x31 */ + return "Intel CSE Lite SKU firmware failure"; + case VB2_RECOVERY_RO_UNSPECIFIED: /* 0x3f */ + return "unspecified/unknown error in RO firmware"; + case VB2_RECOVERY_DEPRECATED_RW_DEV_SCREEN: /* 0x41 */ + return "user requested recovery from dev-mode warning screen"; + case VB2_RECOVERY_DEPRECATED_RW_NO_OS: /* 0x42 */ + return "no OS kernel detected (or kernel rollback attempt?)"; + case VB2_RECOVERY_RW_INVALID_OS: /* 0x43 */ + return "OS kernel or rootfs failed signature check"; + case VB2_RECOVERY_DEPRECATED_RW_TPM_ERROR: /* 0x44 */ + return "TPM error in rewritable firmware"; + case VB2_RECOVERY_DEPRECATED_RW_DEV_MISMATCH: /* 0x45 */ + return "RW firmware in dev mode, but dev switch is off"; + case VB2_RECOVERY_RW_SHARED_DATA: /* 0x46 */ + return "shared data error in rewritable firmware"; + case VB2_RECOVERY_DEPRECATED_RW_TEST_LK: /* 0x47 */ + return "test error from LoadKernel()"; + case VB2_RECOVERY_DEPRECATED_RW_NO_DISK: /* 0x48 */ + return "no bootable storage device in system"; + case VB2_RECOVERY_TPM_E_FAIL: /* 0x49 */ + return "TPM error that was not fixed by reboot"; + case VB2_RECOVERY_RO_TPM_S_ERROR: /* 0x50 */ + return "TPM setup error in read-only firmware"; + case VB2_RECOVERY_RO_TPM_W_ERROR: /* 0x51 */ + return "TPM write error in read-only firmware"; + case VB2_RECOVERY_RO_TPM_L_ERROR: /* 0x52 */ + return "TPM lock error in read-only firmware"; + case VB2_RECOVERY_RO_TPM_U_ERROR: /* 0x53 */ + return "TPM update error in read-only firmware"; + case VB2_RECOVERY_RW_TPM_R_ERROR: /* 0x54 */ + return "TPM read error in rewritable firmware"; + case VB2_RECOVERY_RW_TPM_W_ERROR: /* 0x55 */ + return "TPM write error in rewritable firmware"; + case VB2_RECOVERY_RW_TPM_L_ERROR: /* 0x56 */ + return "TPM lock error in rewritable firmware"; + case VB2_RECOVERY_EC_HASH_FAILED: /* 0x57 */ + return "EC software sync unable to get EC image hash"; + case VB2_RECOVERY_EC_HASH_SIZE: /* 0x58 */ + return "EC software sync invalid image hash size"; + case VB2_RECOVERY_LK_UNSPECIFIED: /* 0x59 */ + return "unspecified error while trying to load kernel"; + case VB2_RECOVERY_RW_NO_DISK: /* 0x5a */ + return "no bootable storage device in system"; + case VB2_RECOVERY_RW_NO_KERNEL: /* 0x5b */ + return "no bootable kernel found on disk"; + case VB2_RECOVERY_DEPRECATED_RW_BCB_ERROR: /* 0x5c */ + return "BCB partition error on disk"; + case VB2_RECOVERY_SECDATA_KERNEL_INIT: /* 0x5d */ + return "kernel secure NVRAM (TPM) initialization error"; + case VB2_RECOVERY_DEPRECATED_FW_FASTBOOT: /* 0x5e */ + return "fastboot-mode requested in firmware"; + case VB2_RECOVERY_RO_TPM_REC_HASH_L_ERROR: /* 0x5f */ + return "recovery hash space lock error in RO firmware"; + case VB2_RECOVERY_TPM_DISABLE_FAILED: /* 0x60 */ + return "failed to disable TPM before running untrusted code"; + case VB2_RECOVERY_ALTFW_HASH_MISMATCH: /* 0x61 */ + return "verification of alternate bootloader payload failed"; + case VB2_RECOVERY_SECDATA_FWMP_INIT: /* 0x62 */ + return "FWMP secure NVRAM (TPM) initialization error"; + case VB2_RECOVERY_CR50_BOOT_MODE: /* 0x63 */ + return "failed to get boot mode from Cr50"; + case VB2_RECOVERY_ESCAPE_NO_BOOT: /* 0x64 */ + return "attempt to escape from NO_BOOT mode was detected"; + case VB2_RECOVERY_RW_UNSPECIFIED: /* 0x7f */ + return "unspecified/unknown error in RW firmware"; + case VB2_RECOVERY_DEPRECATED_KE_DM_VERITY: /* 0x81 */ + return "DM-verity error"; + case VB2_RECOVERY_DEPRECATED_KE_UNSPECIFIED: /* 0xbf */ + return "unspecified/unknown error in kernel"; + case VB2_RECOVERY_US_TEST: /* 0xc1 */ + return "recovery mode test from user-mode"; + case VB2_RECOVERY_DEPRECATED_BCB_USER_MODE: /* 0xc2 */ + return "user-mode requested recovery via BCB"; + case VB2_RECOVERY_DEPRECATED_US_FASTBOOT: /* 0xc3 */ + return "user-mode requested fastboot mode"; + case VB2_RECOVERY_TRAIN_AND_REBOOT: /* 0xc4 */ + return "user-mode requested DRAM train and reboot"; + case VB2_RECOVERY_US_UNSPECIFIED: /* 0xff */ + return "unspecified/unknown error in user-mode"; + } + return "unknown error code"; +} + +/** + Acquire Vboot recovery information from coreboot + + @param RecoveryCode Recovery reason code, zero if not in recovery mode. + @param RecoveryReason Why are we in recovery boot as a string. + + @retval RETURN_SUCCESS Successfully found VBoot data. + @retval RETURN_NOT_FOUND Failed to find VBoot data. + +**/ +RETURN_STATUS +EFIAPI +ParseVBootWorkbuf ( + OUT UINT8 *RecoveryCode, + OUT CONST CHAR8 **RecoveryReason + ) +{ + struct cb_cbmem_entry *CbmemEntry; + struct cb_vboot_workbuf_v2 *Workbuf; + + if (RecoveryCode == NULL || RecoveryReason == NULL) { + return RETURN_INVALID_PARAMETER; + } + + CbmemEntry = FindCbTag (CB_TAG_VBOOT_WORKBUF); + if (CbmemEntry == NULL) { + DEBUG ((DEBUG_INFO, "Did not find VBootWorkbuf tag\n")); + return RETURN_NOT_FOUND; + } + + Workbuf = (struct cb_vboot_workbuf_v2 *)(UINTN)CbmemEntry->address; + if (Workbuf->magic != VB2_SHARED_DATA_MAGIC) { + DEBUG ((DEBUG_INFO, "VBootWorkbuf tag data is wrong\n")); + return RETURN_NOT_FOUND; + } + + if (Workbuf->struct_version_major != VB2_SHARED_DATA_VERSION_MAJOR) { + DEBUG ((DEBUG_INFO, "VBootWorkbuf tag data is of wrong major version\n")); + return RETURN_NOT_FOUND; + } + + *RecoveryCode = Workbuf->recovery_reason; + *RecoveryReason = GetRecoveryReasonString(Workbuf->recovery_reason); + + return RETURN_SUCCESS; +} + +PACKED struct timestamp_entry { + UINT32 entry_id; + UINT64 entry_stamp; +}; + +PACKED struct timestamp_table { + UINT64 base_time; + UINT16 max_entries; + UINT16 tick_freq_mhz; + UINT32 num_entries; + struct timestamp_entry entries[0]; /* Variable number of entries */ +}; + + +/** + Parse the coreboot timestamps + + @retval RETURN_SUCCESS Successfully find the timestamps information. + @retval RETURN_NOT_FOUND Failed to find the tiemstamps information . + +**/ +RETURN_STATUS +EFIAPI +ParseTimestampTable ( + OUT FIRMWARE_SEC_PERFORMANCE *Performance + ) +{ + struct timestamp_table *CbTsRec; + + if (Performance == NULL) { + return RETURN_INVALID_PARAMETER; + } + + CbTsRec = FindCbTag (CB_TAG_TIMESTAMPS); + if (CbTsRec == NULL) { + return RETURN_NOT_FOUND; + } + + /* ResetEnd must be reported in nanoseconds, not ticks */ + Performance->ResetEnd = DivU64x32(CbTsRec->base_time, CbTsRec->tick_freq_mhz); + return RETURN_SUCCESS; +} + +/** + Parse update capsules passed in by coreboot + + @param CapsuleCallback The callback routine invoked for each capsule. + + @retval RETURN_SUCCESS Successfully parsed capsules. + @retval RETURN_NOT_FOUND coreboot table is missing. +**/ +RETURN_STATUS +EFIAPI +ParseCapsules ( + IN BL_CAPSULE_CALLBACK CapsuleCallback + ) +{ + struct cb_header *Header; + struct cb_range *Range; + UINT8 *TmpPtr; + UINTN Idx; + + Header = GetParameterBase (); + if (Header == NULL) { + return RETURN_NOT_FOUND; + } + + TmpPtr = (UINT8 *)Header + Header->header_bytes; + for (Idx = 0; Idx < Header->table_entries; Idx++) { + Range = (struct cb_range *)TmpPtr; + if (Range->tag == CB_TAG_CAPSULE) { + CapsuleCallback (Range->range_start, Range->range_size); + } + TmpPtr += Range->size; + } + + return RETURN_SUCCESS; +} + +/** + Acquire boot logo from coreboot + + @param BmpAddress Pointer to the bitmap file + @param BmpSize Size of the image + + @retval RETURN_SUCCESS Successfully find the boot logo. + @retval RETURN_NOT_FOUND Failed to find the boot logo. +**/ +RETURN_STATUS +EFIAPI +ParseBootLogo ( + OUT UINT64 *BmpAddress, + OUT UINT32 *BmpSize + ) +{ + struct cb_cbmem_ref *CbLogo; + struct cb_bootlogo_header *CbLogoHeader; + + CbLogo = FindCbTag (CB_TAG_LOGO); + if (CbLogo == NULL) { + DEBUG ((DEBUG_INFO, "Did not find BootLogo tag\n")); + return RETURN_NOT_FOUND; + } + + CbLogoHeader = (struct cb_bootlogo_header*)(UINTN) CbLogo->cbmem_addr; + + *BmpAddress = CbLogo->cbmem_addr + sizeof(*CbLogoHeader); + *BmpSize = CbLogoHeader->size; + + return RETURN_SUCCESS; +} + +/** + Parse firmware information passed in by coreboot + + @param Guid Kind of the firmware. + @param Version Current version. + @param Lsv Lowest supported version. + @param Size Firmware size in bytes. + + @retval RETURN_INVALID_PARAMETER At least one of the parameters is NULL. + @retval RETURN_SUCCESS Successfully parsed capsules. + @retval RETURN_NOT_FOUND coreboot table is missing. +**/ +RETURN_STATUS +EFIAPI +ParseFwInfo ( + OUT EFI_GUID *Guid, + OUT UINT32 *Version, + OUT UINT32 *Lsv, + OUT UINT32 *Size + ) +{ + struct lb_efi_fw_info *FwInfo; + + if (Guid == NULL || Version == NULL || Lsv == NULL || Size == NULL) { + return RETURN_INVALID_PARAMETER; + } + + FwInfo = FindCbTag (CB_TAG_FW_INFO); + if (FwInfo == NULL) { + return RETURN_NOT_FOUND; + } + + CopyMem (Guid, &FwInfo->guid, sizeof (*Guid)); + *Version = FwInfo->version; + *Lsv = FwInfo->lowest_supported_version; + *Size = FwInfo->fw_size; + return RETURN_SUCCESS; +} + +/** + Parse information in a string form identified by a number + + @param Id String identifier. + + @retval NULL The requested information wasn't found. + @retval Otherwise A pointer to a static string. +**/ +CONST CHAR8 * +EFIAPI +ParseInfoString ( + IN UINTN Id + ) +{ + struct cb_string *CbString; + + CbString = FindCbTag (Id); + if (CbString == NULL) { + return NULL; + } + + return (CONST CHAR8 *)CbString->string; +} diff --git a/DasharoPayloadPkg/Library/CbParseLib/CbParseLib.inf b/DasharoPayloadPkg/Library/CbParseLib/CbParseLib.inf new file mode 100644 index 0000000000..544c9423a6 --- /dev/null +++ b/DasharoPayloadPkg/Library/CbParseLib/CbParseLib.inf @@ -0,0 +1,41 @@ +## @file +# Coreboot Table Parse Library. +# +# Copyright (c) 2014, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = CbParseLib + FILE_GUID = 49EDFC9E-5945-4386-9C0B-C9B60CD45BB1 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = BlParseLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + CbParseLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + DasharoPayloadPkg/DasharoPayloadPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + IoLib + DebugLib + PcdLib + PciLib + +[Pcd] + gDasharoPayloadPkgTokenSpaceGuid.PcdPayloadStackTop + diff --git a/DasharoPayloadPkg/Library/CbfsLib/CbfsLib.inf b/DasharoPayloadPkg/Library/CbfsLib/CbfsLib.inf new file mode 100644 index 0000000000..c810b60e28 --- /dev/null +++ b/DasharoPayloadPkg/Library/CbfsLib/CbfsLib.inf @@ -0,0 +1,34 @@ +## @file +# coreboot file-system management library. +# +# Copyright (c) 2024, 3mdeb Sp. z o.o. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = CbfsLib + FILE_GUID = B531AC59-411A-4359-B60E-610E28DADF70 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = CbfsLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + cbfs_image.c + common.c + xdr.c + +[Packages] + DasharoPayloadPkg/DasharoPayloadPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib diff --git a/DasharoPayloadPkg/Library/CbfsLib/adapt.h b/DasharoPayloadPkg/Library/CbfsLib/adapt.h new file mode 100644 index 0000000000..e325999771 --- /dev/null +++ b/DasharoPayloadPkg/Library/CbfsLib/adapt.h @@ -0,0 +1,39 @@ +#ifndef ADAPT_H__ +#define ADAPT_H__ + +#include +#include +#include +#include + +typedef UINTN size_t; +typedef INTN ptrdiff_t; +typedef UINT8 uint8_t; +typedef UINT16 uint16_t; +typedef UINT32 uint32_t; +typedef UINT64 uint64_t; +typedef INT8 int8_t; +typedef INT16 int16_t; +typedef INT32 int32_t; +typedef INT64 int64_t; +typedef BOOLEAN bool; + +#define assert(x) ASSERT (x) +#define memcmp(a, b, l) CompareMem ((a), (b), (l)) +#define memcpy(a, b, l) CopyMem ((a), (b), (l)) +#define memmove(a, b, l) CopyMem ((a), (b), (l)) +#define memset(b, v, l) SetMem ((b), (l), (v)) +#define strcpy(d, s) AsciiStrCpyS ((d), AsciiStrSize (s), (s)) +#define strlen(s) AsciiStrLen (s) +#define strcasecmp(s, t) AsciiStriCmp ((s), (t)) +#define malloc(s) AllocatePool (s) +#define free(p) FreePool (p) + +#define false FALSE +#define true TRUE + +#define ERROR(...) DEBUG ((DEBUG_ERROR, __VA_ARGS__)) +#define INFO(...) DEBUG ((DEBUG_INFO, __VA_ARGS__)) +#define WARN(...) DEBUG ((DEBUG_WARN, __VA_ARGS__)) + +#endif /* ADAPT_H__ */ diff --git a/DasharoPayloadPkg/Library/CbfsLib/cbfs.h b/DasharoPayloadPkg/Library/CbfsLib/cbfs.h new file mode 100644 index 0000000000..7dd286fa11 --- /dev/null +++ b/DasharoPayloadPkg/Library/CbfsLib/cbfs.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __CBFS_H +#define __CBFS_H + +#include "cbfs_serialized.h" + +/* To make CBFS more friendly to ROM, fill -1 (0xFF) instead of zero. */ +#define CBFS_CONTENT_DEFAULT_VALUE (-1) + +#define CBFS_SUBHEADER(_p) ( (void *) ((((uint8_t *) (_p)) + ntohl((_p)->offset))) ) + +#endif diff --git a/DasharoPayloadPkg/Library/CbfsLib/cbfs_image.c b/DasharoPayloadPkg/Library/CbfsLib/cbfs_image.c new file mode 100644 index 0000000000..406fdc8b8d --- /dev/null +++ b/DasharoPayloadPkg/Library/CbfsLib/cbfs_image.c @@ -0,0 +1,511 @@ +/* CBFS Image Manipulation */ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include "common.h" +#include "cbfs_image.h" + +/* Even though the file-adding functions---cbfs_add_entry() and + * cbfs_add_entry_at()---perform their sizing checks against the beginning of + * the subsequent section rather than a stable recorded value such as an empty + * file header's len field, it's possible to prove two interesting properties + * about their behavior: + * - Placing a new file within an empty entry located below an existing file + * entry will never leave an aligned flash address containing neither the + * beginning of a file header nor part of a file. + * - Placing a new file in an empty entry at the very end of the image such + * that it fits, but leaves no room for a final header, is guaranteed not to + * change the total amount of space for entries, even if that new file is + * later removed from the CBFS. + * These properties are somewhat nonobvious from the implementation, so the + * reader is encouraged to blame this comment and examine the full proofs + * in the commit message before making significant changes that would risk + * removing said guarantees. + */ + +/* CBFS image */ + +size_t cbfs_calculate_file_header_size(const char *name) +{ + return (sizeof(struct cbfs_file) + + align_up(strlen(name) + 1, CBFS_ATTRIBUTE_ALIGN)); +} + +/* Only call on legacy CBFSes possessing a master header. */ +static int cbfs_fix_legacy_size(struct cbfs_image *image, char *hdr_loc) +{ + assert(image); + assert(cbfs_is_legacy_cbfs(image)); + // A bug in old cbfstool may produce extra few bytes (by alignment) and + // cause cbfstool to overwrite things after free space -- which is + // usually CBFS header on x86. We need to workaround that. + // Except when we run across a file that contains the actual header, + // in which case this image is a safe, new-style + // `cbfstool add-master-header` based image. + + struct cbfs_file *entry, *first = NULL, *last = NULL; + for (first = entry = cbfs_find_first_entry(image); + entry && cbfs_is_valid_entry(image, entry); + entry = cbfs_find_next_entry(image, entry)) { + /* Is the header guarded by a CBFS file entry? Then exit */ + if (((char *)entry) + ntohl(entry->offset) == hdr_loc) { + return 0; + } + last = entry; + } + if ((char *)first < (char *)hdr_loc && + (char *)entry > (char *)hdr_loc) { + WARN("CBFS image was created with old cbfstool with size bug. " + "Fixing size in last entry...\n"); + last->len = htonl(ntohl(last->len) - image->header.align); + } + return 0; +} + +void cbfs_get_header(struct cbfs_header *header, void *src) +{ + struct buffer outheader; + + outheader.data = src; /* We're not modifying the data */ + outheader.size = 0; + + header->magic = xdr_be.get32(&outheader); + header->version = xdr_be.get32(&outheader); + header->romsize = xdr_be.get32(&outheader); + header->bootblocksize = xdr_be.get32(&outheader); + header->align = xdr_be.get32(&outheader); + header->offset = xdr_be.get32(&outheader); + header->architecture = xdr_be.get32(&outheader); +} + +int cbfs_image_from_buffer(struct cbfs_image *out, struct buffer *in, + uint32_t offset) +{ + assert(out); + assert(in); + assert(in->data); + + buffer_clone(&out->buffer, in); + out->has_header = false; + + if (cbfs_is_valid_cbfs(out)) { + return 0; + } + + void *header_loc = cbfs_find_header(in->data, in->size, offset); + if (header_loc) { + cbfs_get_header(&out->header, header_loc); + out->has_header = true; + cbfs_fix_legacy_size(out, header_loc); + return 0; + } else if (offset != HEADER_OFFSET_UNKNOWN) { + ERROR("The -H switch is only valid on legacy images having CBFS master headers.\n"); + } + ERROR("Selected image region is not a valid CBFS.\n"); + return 1; +} + +/* Tries to add an entry with its data (CBFS_SUBHEADER) at given offset. */ +static int cbfs_add_entry_at(struct cbfs_image *image, + struct cbfs_file *entry, + const void *data, + uint32_t content_offset, + const struct cbfs_file *header, + const size_t len_align) +{ + struct cbfs_file *next = cbfs_find_next_entry(image, entry); + uint32_t addr = cbfs_get_entry_addr(image, entry), + addr_next = cbfs_get_entry_addr(image, next); + uint32_t min_entry_size = cbfs_calculate_file_header_size(""); + uint32_t len, header_offset; + uint32_t align = image->has_header ? image->header.align : + CBFS_ALIGNMENT; + uint32_t header_size = ntohl(header->offset); + + header_offset = content_offset - header_size; + if (header_offset % align) + header_offset -= header_offset % align; + if (header_offset < addr) { + ERROR("No space to hold cbfs_file header."); + return -1; + } + + // Process buffer BEFORE content_offset. + if (header_offset - addr > min_entry_size) { + len = header_offset - addr - min_entry_size; + if (cbfs_create_empty_entry(entry, CBFS_TYPE_NULL, len, "")) + return -1; + entry = cbfs_find_next_entry(image, entry); + addr = cbfs_get_entry_addr(image, entry); + } + + len = content_offset - addr - header_size; + memcpy(entry, header, header_size); + if (len != 0) { + /* + * The header moved backwards a bit to accommodate cbfs_file + * alignment requirements, so patch up ->offset to still point + * to file data. Move attributes forward so the end of the + * attribute list still matches the end of the metadata. + */ + uint32_t offset = ntohl(entry->offset); + uint32_t attrs = ntohl(entry->attributes_offset); + if (attrs == 0) { + memset((uint8_t *)entry + offset, 0, len); + } else { + uint8_t *p = (uint8_t *)entry + attrs; + memmove(p + len, p, offset - attrs); + memset(p, 0, len); + attrs += len; + entry->attributes_offset = htonl(attrs); + } + offset += len; + entry->offset = htonl(offset); + } + + // Ready to fill data into entry. + assert((char*)CBFS_SUBHEADER(entry) - image->buffer.data == + (ptrdiff_t)content_offset); + memcpy(CBFS_SUBHEADER(entry), data, ntohl(entry->len)); + + // Align the length to a multiple of len_align + if (len_align && + ((ntohl(entry->offset) + ntohl(entry->len)) % len_align)) { + size_t off = (ntohl(entry->offset) + ntohl(entry->len)) % len_align; + entry->len = htonl(ntohl(entry->len) + len_align - off); + } + + // Process buffer AFTER entry. + entry = cbfs_find_next_entry(image, entry); + addr = cbfs_get_entry_addr(image, entry); + if (addr == addr_next) + return 0; + + assert(addr < addr_next); + if (addr_next - addr < min_entry_size) { + /* No need to increase the size of the just + * stored file to extend to next file. Alignment + * of next file takes care of this. + */ + return 0; + } + + len = addr_next - addr - min_entry_size; + /* keep space for master header pointer */ + if ((uint8_t *)entry + min_entry_size + len > + (uint8_t *)buffer_get(&image->buffer) + + buffer_size(&image->buffer) - sizeof(int32_t)) { + len -= sizeof(int32_t); + } + if (cbfs_create_empty_entry(entry, CBFS_TYPE_NULL, len, "")) + return -1; + return 0; +} + +int cbfs_add_entry(struct cbfs_image *image, struct buffer *buffer, + uint32_t content_offset, + struct cbfs_file *header, + const size_t len_align) +{ + assert(image); + assert(buffer); + assert(buffer->data); + assert(!IS_HOST_SPACE_ADDRESS(content_offset)); + + const char *name = header->filename; + + /* This is so special rows in cbfstool print -k -v output stay unambiguous. */ + if (name[0] == '[') { + ERROR("CBFS file name `%s` must not start with `[`\n", name); + return -1; + } + + uint32_t entry_type; + uint32_t addr, addr_next; + uint32_t entry_size; + uint32_t max_null_entry_size = 0; + struct cbfs_file *entry, *next; + uint32_t need_size; + uint32_t header_size = ntohl(header->offset); + + need_size = header_size + buffer->size; + + // Merge empty entries. + cbfs_legacy_walk(image, cbfs_merge_empty_entry, NULL); + + for (entry = cbfs_find_first_entry(image); + entry && cbfs_is_valid_entry(image, entry); + entry = cbfs_find_next_entry(image, entry)) { + + entry_type = ntohl(entry->type); + if (entry_type != CBFS_TYPE_NULL) + continue; + + addr = cbfs_get_entry_addr(image, entry); + next = cbfs_find_next_entry(image, entry); + addr_next = cbfs_get_entry_addr(image, next); + entry_size = addr_next - addr; + max_null_entry_size = MAX(max_null_entry_size, entry_size); + + /* Will the file fit? Don't yet worry if we have space for a new + * "empty" entry. We take care of that later. + */ + if (addr + need_size > addr_next) + continue; + + // Test for complicated cases + if (content_offset > 0) { + if (addr_next < content_offset) { + continue; + } else if (addr > content_offset) { + break; + } else if (addr + header_size > content_offset) { + ERROR("Not enough space for header.\n"); + break; + } else if (content_offset + buffer->size > addr_next) { + ERROR("Not enough space for content.\n"); + break; + } + } + + // TODO there are more few tricky cases that we may + // want to fit by altering offset. + + if (content_offset == 0) { + // we tested every condition earlier under which + // placing the file there might fail + content_offset = addr + header_size; + } + + if (cbfs_add_entry_at(image, entry, buffer->data, + content_offset, header, len_align) == 0) { + return 0; + } + break; + } + + ERROR("Could not add %s [header %d + content %zd bytes (%zd KB)] @0x%x; " + "Largest empty slot: %d bytes\n", + buffer->name, header_size, buffer->size, buffer->size / 1024, content_offset, + max_null_entry_size); + return -1; +} + +struct cbfs_file *cbfs_get_entry(struct cbfs_image *image, const char *name) +{ + struct cbfs_file *entry; + for (entry = cbfs_find_first_entry(image); + entry && cbfs_is_valid_entry(image, entry); + entry = cbfs_find_next_entry(image, entry)) { + if (strcasecmp(entry->filename, name) == 0) { + return entry; + } + } + return NULL; +} + +int cbfs_remove_entry(struct cbfs_image *image, const char *name) +{ + struct cbfs_file *entry; + entry = cbfs_get_entry(image, name); + if (!entry) { + ERROR("CBFS file %s not found.\n", name); + return -1; + } + entry->type = htonl(CBFS_TYPE_DELETED); + cbfs_legacy_walk(image, cbfs_merge_empty_entry, NULL); + return 0; +} + +int cbfs_merge_empty_entry(struct cbfs_image *image, struct cbfs_file *entry, + unused void *arg) +{ + struct cbfs_file *next; + uint32_t next_addr = 0; + + /* We don't return here even if this entry is already empty because we + want to merge the empty entries following after it. */ + + /* Loop until non-empty entry is found, starting from the current entry. + After the loop, next_addr points to the next non-empty entry. */ + next = entry; + while (ntohl(next->type) == CBFS_TYPE_DELETED || + ntohl(next->type) == CBFS_TYPE_NULL) { + next = cbfs_find_next_entry(image, next); + if (!next) + break; + next_addr = cbfs_get_entry_addr(image, next); + if (!cbfs_is_valid_entry(image, next)) + /* 'next' could be the end of cbfs */ + break; + } + + if (!next_addr) + /* Nothing to empty */ + return 0; + + /* We can return here if we find only a single empty entry. + For simplicity, we just proceed (and make it empty again). */ + + /* We're creating one empty entry for combined empty spaces */ + uint32_t addr = cbfs_get_entry_addr(image, entry); + size_t len = next_addr - addr - cbfs_calculate_file_header_size(""); + return cbfs_create_empty_entry(entry, CBFS_TYPE_NULL, len, ""); +} + +int cbfs_legacy_walk(struct cbfs_image *image, cbfs_entry_callback callback, + void *arg) +{ + int count = 0; + struct cbfs_file *entry; + for (entry = cbfs_find_first_entry(image); + entry && cbfs_is_valid_entry(image, entry); + entry = cbfs_find_next_entry(image, entry)) { + count ++; + if (callback(image, entry, arg) != 0) + break; + } + return count; +} + +static int cbfs_header_valid(struct cbfs_header *header) +{ + if ((ntohl(header->magic) == CBFS_HEADER_MAGIC) && + ((ntohl(header->version) == CBFS_HEADER_VERSION1) || + (ntohl(header->version) == CBFS_HEADER_VERSION2)) && + (ntohl(header->offset) < ntohl(header->romsize))) + return 1; + return 0; +} + +struct cbfs_header *cbfs_find_header(char *data, size_t size, + uint32_t forced_offset) +{ + size_t offset; + int found = 0; + int32_t rel_offset; + struct cbfs_header *header, *result = NULL; + + if (forced_offset < (size - sizeof(struct cbfs_header))) { + /* Check if the forced header is valid. */ + header = (struct cbfs_header *)(data + forced_offset); + if (cbfs_header_valid(header)) + return header; + return NULL; + } + + // Try finding relative offset of master header at end of file first. + rel_offset = *(int32_t *)(data + size - sizeof(int32_t)); + offset = size + rel_offset; + + if (offset >= size - sizeof(*header) || + !cbfs_header_valid((struct cbfs_header *)(data + offset))) { + // Some use cases append non-CBFS data to the end of the ROM. + offset = 0; + } + + for (; offset + sizeof(*header) < size; offset++) { + header = (struct cbfs_header *)(data + offset); + if (!cbfs_header_valid(header)) + continue; + if (!found++) + result = header; + } + if (found > 1) + // Top-aligned images usually have a working relative offset + // field, so this is more likely to happen on bottom-aligned + // ones (where the first header is the "outermost" one) + WARN("Multiple (%d) CBFS headers found, using the first one.\n", + found); + return result; +} + + +struct cbfs_file *cbfs_find_first_entry(struct cbfs_image *image) +{ + assert(image); + if (image->has_header) + /* header.offset is relative to start of flash, not + * start of region, so use it with the full image. + */ + return (struct cbfs_file *) + (buffer_get_original_backing(&image->buffer) + + image->header.offset); + else + return (struct cbfs_file *)buffer_get(&image->buffer); +} + +struct cbfs_file *cbfs_find_next_entry(struct cbfs_image *image, + struct cbfs_file *entry) +{ + uint32_t addr = cbfs_get_entry_addr(image, entry); + int align = image->has_header ? image->header.align : CBFS_ALIGNMENT; + assert(entry && cbfs_is_valid_entry(image, entry)); + addr += ntohl(entry->offset) + ntohl(entry->len); + addr = align_up(addr, align); + return (struct cbfs_file *)(image->buffer.data + addr); +} + +uint32_t cbfs_get_entry_addr(struct cbfs_image *image, struct cbfs_file *entry) +{ + assert(image && image->buffer.data && entry); + return (int32_t)((char *)entry - image->buffer.data); +} + +int cbfs_is_valid_cbfs(struct cbfs_image *image) +{ + return buffer_check_magic(&image->buffer, CBFS_FILE_MAGIC, + strlen(CBFS_FILE_MAGIC)); +} + +int cbfs_is_legacy_cbfs(struct cbfs_image *image) +{ + return image->has_header; +} + +int cbfs_is_valid_entry(struct cbfs_image *image, struct cbfs_file *entry) +{ + uint32_t offset = cbfs_get_entry_addr(image, entry); + + if (offset >= image->buffer.size) + return 0; + + struct buffer entry_data; + buffer_clone(&entry_data, &image->buffer); + buffer_seek(&entry_data, offset); + return buffer_check_magic(&entry_data, CBFS_FILE_MAGIC, + strlen(CBFS_FILE_MAGIC)); +} + +struct cbfs_file *cbfs_create_file_header(int type, + size_t len, const char *name) +{ + size_t header_size = cbfs_calculate_file_header_size(name); + if (header_size > CBFS_METADATA_MAX_SIZE) { + ERROR("'%s' name too long to fit in CBFS header\n", name); + return NULL; + } + + struct cbfs_file *entry = malloc(CBFS_METADATA_MAX_SIZE); + memset(entry, CBFS_CONTENT_DEFAULT_VALUE, CBFS_METADATA_MAX_SIZE); + memcpy(entry->magic, CBFS_FILE_MAGIC, sizeof(entry->magic)); + entry->type = htonl(type); + entry->len = htonl(len); + entry->attributes_offset = 0; + entry->offset = htonl(header_size); + memset(entry->filename, 0, ntohl(entry->offset) - sizeof(*entry)); + strcpy(entry->filename, name); + return entry; +} + +int cbfs_create_empty_entry(struct cbfs_file *entry, int type, + size_t len, const char *name) +{ + struct cbfs_file *tmp = cbfs_create_file_header(type, len, name); + if (!tmp) + return -1; + + memcpy(entry, tmp, ntohl(tmp->offset)); + free(tmp); + memset(CBFS_SUBHEADER(entry), CBFS_CONTENT_DEFAULT_VALUE, len); + return 0; +} diff --git a/DasharoPayloadPkg/Library/CbfsLib/cbfs_image.h b/DasharoPayloadPkg/Library/CbfsLib/cbfs_image.h new file mode 100644 index 0000000000..669f8518db --- /dev/null +++ b/DasharoPayloadPkg/Library/CbfsLib/cbfs_image.h @@ -0,0 +1,108 @@ +/* CBFS Image Manipulation */ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __CBFS_IMAGE_H +#define __CBFS_IMAGE_H + +#include "common.h" +#include "cbfs.h" + +#define HEADER_OFFSET_UNKNOWN (~0u) + +/* CBFS image processing */ + +struct cbfs_image { + struct buffer buffer; + /* An image has a header iff it's a legacy CBFS. */ + bool has_header; + /* Only meaningful if has_header is selected. */ + struct cbfs_header header; +}; + +/* Or deserialize into host-native format */ +void cbfs_get_header(struct cbfs_header *header, void *src); + +/* Constructs a cbfs_image from a buffer. The resulting image contains a shallow + * copy of the buffer; releasing either one is the legal way to clean up after + * both of them at once. Always produces a cbfs_image, but... + * Returns 0 if it contains a valid CBFS, non-zero if it's unrecognized data. */ +int cbfs_image_from_buffer(struct cbfs_image *out, struct buffer *in, + uint32_t offset); + +/* Returns a pointer to entry by name, or NULL if name is not found. */ +struct cbfs_file *cbfs_get_entry(struct cbfs_image *image, const char *name); + +/* Adds an entry to CBFS image by given name and type. If content_offset is + * non-zero, try to align "content" (CBFS_SUBHEADER(p)) at content_offset. + * Never pass this function a top-aligned address: convert it to an offset. + * Returns 0 on success, otherwise non-zero. */ +int cbfs_add_entry(struct cbfs_image *image, struct buffer *buffer, + uint32_t content_offset, struct cbfs_file *header, + const size_t len_align); + +/* Removes an entry from CBFS image. Returns 0 on success, otherwise non-zero. */ +int cbfs_remove_entry(struct cbfs_image *image, const char *name); + +/* Create a new cbfs file header structure to work with. + Returns newly allocated memory that the caller needs to free after use. */ +struct cbfs_file *cbfs_create_file_header(int type, size_t len, + const char *name); + +/* Initializes a new empty (type = NULL) entry with size and name in CBFS image. + * Returns 0 on success, otherwise (ex, not found) non-zero. */ +int cbfs_create_empty_entry(struct cbfs_file *entry, int type, + size_t len, const char *name); + +/* Callback function used by cbfs_legacy_walk. + * Returns 0 on success, or non-zero to stop further iteration. */ +typedef int (*cbfs_entry_callback)(struct cbfs_image *image, + struct cbfs_file *file, + void *arg); + +/* Iterates through all entries in CBFS image, and invoke with callback. + * Stops if callback returns non-zero values. Unlike the commonlib cbfs_walk(), + * this can deal with different alignments in legacy CBFS (with master header). + * Returns number of entries invoked. */ +int cbfs_legacy_walk(struct cbfs_image *image, cbfs_entry_callback callback, + void *arg); + +/* Primitive CBFS utilities */ + +/* Returns a pointer to the only valid CBFS header in give buffer, otherwise + * NULL (including when multiple headers were found). If there is a X86 ROM + * style signature (pointer at 0xfffffffc) found in ROM, it will be selected as + * the only header.*/ +struct cbfs_header *cbfs_find_header(char *data, size_t size, + uint32_t forced_offset); + +/* Returns the first cbfs_file entry in CBFS image by CBFS header (no matter if + * the entry has valid content or not), otherwise NULL. */ +struct cbfs_file *cbfs_find_first_entry(struct cbfs_image *image); + +/* Returns next cbfs_file entry (no matter if its content is valid or not), or + * NULL on failure. */ +struct cbfs_file *cbfs_find_next_entry(struct cbfs_image *image, + struct cbfs_file *entry); + +/* Returns ROM address (offset) of entry. + * This is different from entry->offset (pointer to content). */ +uint32_t cbfs_get_entry_addr(struct cbfs_image *image, struct cbfs_file *entry); + +/* Returns 1 if valid new-format CBFS (without a master header), otherwise 0. */ +int cbfs_is_valid_cbfs(struct cbfs_image *image); + +/* Returns 1 if valid legacy CBFS (with a master header), otherwise 0. */ +int cbfs_is_legacy_cbfs(struct cbfs_image *image); + +/* Returns 1 if entry has valid data (by checking magic number), otherwise 0. */ +int cbfs_is_valid_entry(struct cbfs_image *image, struct cbfs_file *entry); + +/* Merge empty entries starting from given entry. + * Returns 0 on success, otherwise non-zero. */ +int cbfs_merge_empty_entry(struct cbfs_image *image, struct cbfs_file *entry, + void *arg); + +/* Returns the size of a cbfs file header with no extensions */ +size_t cbfs_calculate_file_header_size(const char *name); + +#endif diff --git a/DasharoPayloadPkg/Library/CbfsLib/cbfs_serialized.h b/DasharoPayloadPkg/Library/CbfsLib/cbfs_serialized.h new file mode 100644 index 0000000000..132b2381fe --- /dev/null +++ b/DasharoPayloadPkg/Library/CbfsLib/cbfs_serialized.h @@ -0,0 +1,210 @@ +/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only */ + +#ifndef _CBFS_SERIALIZED_H_ +#define _CBFS_SERIALIZED_H_ + +#include "adapt.h" + +#ifdef __packed +#undef __packed +#endif + +#define __packed __attribute__((packed)) + +enum cbfs_compression { + CBFS_COMPRESS_NONE = 0, + CBFS_COMPRESS_LZMA = 1, + CBFS_COMPRESS_LZ4 = 2, +}; + +enum cbfs_type { + /* QUERY is an alias for DELETED that can be passed to CBFS APIs to + inquire about the type of a file, rather than constrain it. */ + CBFS_TYPE_QUERY = 0, + CBFS_TYPE_DELETED = 0x00000000, + CBFS_TYPE_NULL = 0xffffffff, + CBFS_TYPE_BOOTBLOCK = 0x01, + CBFS_TYPE_CBFSHEADER = 0x02, + CBFS_TYPE_LEGACY_STAGE = 0x10, + CBFS_TYPE_STAGE = 0x11, + CBFS_TYPE_SELF = 0x20, + CBFS_TYPE_FIT_PAYLOAD = 0x21, + CBFS_TYPE_OPTIONROM = 0x30, + CBFS_TYPE_BOOTSPLASH = 0x40, + CBFS_TYPE_RAW = 0x50, + CBFS_TYPE_VSA = 0x51, + CBFS_TYPE_MBI = 0x52, + CBFS_TYPE_MICROCODE = 0x53, + CBFS_TYPE_INTEL_FIT = 0x54, + CBFS_TYPE_FSP = 0x60, + CBFS_TYPE_MRC = 0x61, + CBFS_TYPE_MMA = 0x62, + CBFS_TYPE_EFI = 0x63, + CBFS_TYPE_STRUCT = 0x70, + CBFS_TYPE_AMDFW = 0x80, + CBFS_TYPE_CMOS_DEFAULT = 0xaa, + CBFS_TYPE_SPD = 0xab, + CBFS_TYPE_MRC_CACHE = 0xac, + CBFS_TYPE_CMOS_LAYOUT = 0x01aa, +}; + +#define CBFS_HEADER_MAGIC 0x4F524243 /* BE: 'ORBC' */ +#define CBFS_HEADER_VERSION1 0x31313131 /* BE: '1111' */ +#define CBFS_HEADER_VERSION2 0x31313132 /* BE: '1112' */ +#define CBFS_HEADER_VERSION CBFS_HEADER_VERSION2 + +/* this is the master cbfs header - it must be located somewhere available + * to bootblock (to load romstage). The last 4 bytes in the image contain its + * relative offset from the end of the image (as a 32-bit signed integer). */ + +struct cbfs_header { + uint32_t magic; + uint32_t version; + uint32_t romsize; + uint32_t bootblocksize; + uint32_t align; /* fixed to 64 bytes */ + uint32_t offset; + uint32_t architecture; + uint32_t pad[1]; +} __packed; + +/* this used to be flexible, but wasn't ever set to something different. */ +#define CBFS_ALIGNMENT 64 + +/* "Unknown" refers to CBFS headers version 1, + * before the architecture was defined (i.e., x86 only). + */ +enum cbfs_architecture { + CBFS_ARCHITECTURE_UNKNOWN = 0xFFFFFFFF, + CBFS_ARCHITECTURE_X86 = 0x00000001, + CBFS_ARCHITECTURE_ARM = 0x00000010, + CBFS_ARCHITECTURE_AARCH64 = 0x0000aa64, + CBFS_ARCHITECTURE_MIPS = 0x00000100, /* deprecated */ + CBFS_ARCHITECTURE_RISCV = 0xc001d0de, + CBFS_ARCHITECTURE_PPC64 = 0x407570ff, +}; + +/** This is a component header - every entry in the CBFS + will have this header. + + This is how the component is arranged in the ROM: + + -------------- <- 0 + component header + -------------- <- sizeof(struct component) + component name + -------------- <- offset + data + ... + -------------- <- offset + len +*/ + +#define CBFS_FILE_MAGIC "LARCHIVE" +#define CBFS_METADATA_MAX_SIZE 256 + +struct cbfs_file { + char magic[8]; + uint32_t len; + uint32_t type; + uint32_t attributes_offset; + uint32_t offset; + char filename[]; +} __packed; + +#if defined __GNUC__ && (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 +_Static_assert(sizeof(struct cbfs_file) == 24, "cbfs_file size mismatch"); +#endif + +/* The common fields of extended cbfs file attributes. + Attributes are expected to start with tag/len, then append their + specific fields. */ +struct cbfs_file_attribute { + uint32_t tag; + /* len covers the whole structure, incl. tag and len */ + uint32_t len; + uint8_t data[]; +} __packed; + +/* All attribute sizes must be divisible by this! */ +#define CBFS_ATTRIBUTE_ALIGN 4 + +/* Depending on how the header was initialized, it may be backed with 0x00 or + * 0xff. Support both. */ +enum cbfs_file_attr_tag { + CBFS_FILE_ATTR_TAG_UNUSED = 0, + CBFS_FILE_ATTR_TAG_UNUSED2 = 0xffffffff, + CBFS_FILE_ATTR_TAG_COMPRESSION = 0x42435a4c, /* BE: 'BCZL' */ + CBFS_FILE_ATTR_TAG_HASH = 0x68736148, /* BE: 'hsaH' */ + CBFS_FILE_ATTR_TAG_POSITION = 0x42435350, /* BE: 'BCSP' */ + CBFS_FILE_ATTR_TAG_ALIGNMENT = 0x42434c41, /* BE: 'BCLA' */ + CBFS_FILE_ATTR_TAG_IBB = 0x32494242, /* BE: '2IBB' */ + CBFS_FILE_ATTR_TAG_PADDING = 0x47444150, /* BE: 'GNDP' */ + CBFS_FILE_ATTR_TAG_STAGEHEADER = 0x53746748, /* BE: 'StgH' */ +}; + +struct cbfs_file_attr_compression { + uint32_t tag; + uint32_t len; + /* whole file compression format. 0 if no compression. */ + uint32_t compression; + uint32_t decompressed_size; +} __packed; + +struct cbfs_file_attr_position { + uint32_t tag; + uint32_t len; + uint32_t position; +} __packed; + +struct cbfs_file_attr_align { + uint32_t tag; + uint32_t len; + uint32_t alignment; +} __packed; + +struct cbfs_file_attr_stageheader { + uint32_t tag; + uint32_t len; + uint64_t loadaddr; /* Memory address to load the code to. */ + uint32_t entry_offset; /* Offset of entry point from loadaddr. */ + uint32_t memlen; /* Total length (including BSS) in memory. */ +} __packed; + + +/*** Component sub-headers ***/ + +/* Following are component sub-headers for the "standard" + component types */ + +/** this is the sub-header for payload components. Payloads + are loaded by coreboot at the end of the boot process */ + +struct cbfs_payload_segment { + uint32_t type; + uint32_t compression; + uint32_t offset; + uint64_t load_addr; + uint32_t len; + uint32_t mem_len; +} __packed; + +struct cbfs_payload { + struct cbfs_payload_segment segments; +}; + +enum cbfs_payload_segment_type { + PAYLOAD_SEGMENT_CODE = 0x434F4445, /* BE: 'CODE' */ + PAYLOAD_SEGMENT_DATA = 0x44415441, /* BE: 'DATA' */ + PAYLOAD_SEGMENT_BSS = 0x42535320, /* BE: 'BSS ' */ + PAYLOAD_SEGMENT_ENTRY = 0x454E5452, /* BE: 'ENTR' */ + + /* PARAMS for PAYLOAD_INFO feature. Broken since 2012, removed 2024. */ + PAYLOAD_SEGMENT_DEPRECATED_PARAMS = 0x50415241, /* BE: 'PARA' */ +}; + +struct cbfs_optionrom { + uint32_t compression; + uint32_t len; +} __packed; + +#endif /* _CBFS_SERIALIZED_H_ */ diff --git a/DasharoPayloadPkg/Library/CbfsLib/common.c b/DasharoPayloadPkg/Library/CbfsLib/common.c new file mode 100644 index 0000000000..2d3ed12d16 --- /dev/null +++ b/DasharoPayloadPkg/Library/CbfsLib/common.c @@ -0,0 +1,16 @@ +/* common utility functions for cbfstool */ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include "common.h" +#include "cbfs.h" + +/* Small, OS/libc independent runtime check for endianness */ +int is_big_endian(void) +{ + static const uint32_t inttest = 0x12345678; + const uint8_t inttest_lsb = *(const uint8_t *)&inttest; + if (inttest_lsb == 0x12) { + return 1; + } + return 0; +} diff --git a/DasharoPayloadPkg/Library/CbfsLib/common.h b/DasharoPayloadPkg/Library/CbfsLib/common.h new file mode 100644 index 0000000000..de02288ed8 --- /dev/null +++ b/DasharoPayloadPkg/Library/CbfsLib/common.h @@ -0,0 +1,142 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __CBFSTOOL_COMMON_H +#define __CBFSTOOL_COMMON_H + +#include "adapt.h" + +#include "cbfs_serialized.h" +#include "swab.h" + +/* + * There are two address spaces that this tool deals with - SPI flash address space and host + * address space. This macros checks if the address is greater than 2GiB under the assumption + * that the low MMIO lives in the top half of the 4G address space of the host. + */ +#define IS_HOST_SPACE_ADDRESS(addr) ((uint32_t)(addr) > 0x80000000) + +// #define ERROR(...) do { fprintf(stderr, __VA_ARGS__); } while(0) +// #define INFO(...) do { fprintf(stderr, __VA_ARGS__); } while(0) +// #define WARN(...) do { fprintf(stderr, __VA_ARGS__); } while(0) +// #define DEBUG(...) do { fprintf(stderr, __VA_ARGS__); } while(0) +#define LOG(...) do { fprintf(stderr, __VA_ARGS__); } while(0) + +#define unused __attribute__((unused)) + +static inline uint32_t align_up(uint32_t value, uint32_t align) +{ + if (value % align) + value += align - (value % align); + return value; +} + +/* Buffer and file I/O */ +struct buffer { + char *name; + char *data; + size_t offset; + size_t size; +}; + +static inline void *buffer_get(const struct buffer *b) +{ + return b->data; +} + +static inline size_t buffer_size(const struct buffer *b) +{ + return b->size; +} + +static inline size_t buffer_offset(const struct buffer *b) +{ + return b->offset; +} + +/* + * Shrink a buffer toward the beginning of its previous space. + * Afterward, buffer_delete() remains the means of cleaning it up. */ +static inline void buffer_set_size(struct buffer *b, size_t size) +{ + b->size = size; +} + +/* Initialize a buffer with the given constraints. */ +static inline void buffer_init(struct buffer *b, char *name, void *data, + size_t size) +{ + b->name = name; + b->data = data; + b->size = size; + b->offset = 0; +} + +/* Splice a buffer into another buffer. Note that it's up to the caller to + * bounds check the offset and size. The resulting buffer is backed by the same + * storage as the original, so although it is valid to buffer_delete() either + * one of them, doing so releases both simultaneously. */ +static inline void buffer_splice(struct buffer *dest, const struct buffer *src, + size_t offset, size_t size) +{ + dest->name = src->name; + dest->data = src->data + offset; + dest->offset = src->offset + offset; + dest->size = size; +} + +/* + * Shallow copy a buffer. To clean up the resources, buffer_delete() + * either one, but not both. */ +static inline void buffer_clone(struct buffer *dest, const struct buffer *src) +{ + buffer_splice(dest, src, 0, src->size); +} + +/* + * Shrink a buffer toward the end of its previous space. + * Afterward, buffer_delete() remains the means of cleaning it up. */ +static inline void buffer_seek(struct buffer *b, size_t size) +{ + b->offset += size; + b->size -= size; + b->data += size; +} + +/* Returns whether the buffer begins with the specified magic bytes. */ +static inline bool buffer_check_magic(const struct buffer *b, const char *magic, + size_t magic_len) +{ + assert(magic); + return b && b->size >= magic_len && + memcmp(b->data, magic, magic_len) == 0; +} + +/* Returns the start of the underlying buffer, with the offset undone */ +static inline void *buffer_get_original_backing(const struct buffer *b) +{ + if (!b) + return NULL; + return buffer_get(b) - buffer_offset(b); +} + +/* Loads a file into memory buffer. Returns 0 on success, otherwise non-zero. */ +int buffer_from_file(struct buffer *buffer, const char *filename); + +/* Destroys a memory buffer. */ +void buffer_delete(struct buffer *buffer); + +/* xdr.c */ +struct xdr { + uint8_t (*get8)(struct buffer *input); + uint16_t (*get16)(struct buffer *input); + uint32_t (*get32)(struct buffer *input); + uint64_t (*get64)(struct buffer *input); + void (*put8)(struct buffer *input, uint8_t val); + void (*put16)(struct buffer *input, uint16_t val); + void (*put32)(struct buffer *input, uint32_t val); + void (*put64)(struct buffer *input, uint64_t val); +}; + +extern struct xdr xdr_be; + +#endif diff --git a/DasharoPayloadPkg/Library/CbfsLib/swab.h b/DasharoPayloadPkg/Library/CbfsLib/swab.h new file mode 100644 index 0000000000..a45a7673d9 --- /dev/null +++ b/DasharoPayloadPkg/Library/CbfsLib/swab.h @@ -0,0 +1,56 @@ +#ifndef _SWAB_H +#define _SWAB_H + +/* + * linux/byteorder/swab.h + * Byte-swapping, independently from CPU endianness + * swabXX[ps]?(foo) + * + * Francois-Rene Rideau 19971205 + * separated swab functions from cpu_to_XX, + * to clean up support for bizarre-endian architectures. + * + * See asm-i386/byteorder.h and suches for examples of how to provide + * architecture-dependent optimized versions + * + */ + +#if !defined(__APPLE__) && !defined(__NetBSD__) +#define ntohl(x) (is_big_endian() ? (uint32_t)(x) : swab32(x)) +#define htonl(x) (is_big_endian() ? (uint32_t)(x) : swab32(x)) +#else +#include +#endif +#define ntohll(x) (is_big_endian() ? (uint64_t)(x) : swab64(x)) +#define htonll(x) (is_big_endian() ? (uint64_t)(x) : swab64(x)) + +/* casts are necessary for constants, because we never know how for sure + * how U/UL/ULL map to __u16, __u32, __u64. At least not in a portable way. + */ +#define swab16(x) \ + ((unsigned short)( \ + (((unsigned short)(x) & (unsigned short)0x00ffU) << 8) | \ + (((unsigned short)(x) & (unsigned short)0xff00U) >> 8) )) + +#define swab32(x) \ + ((unsigned int)( \ + (((unsigned int)(x) & (unsigned int)0x000000ffUL) << 24) | \ + (((unsigned int)(x) & (unsigned int)0x0000ff00UL) << 8) | \ + (((unsigned int)(x) & (unsigned int)0x00ff0000UL) >> 8) | \ + (((unsigned int)(x) & (unsigned int)0xff000000UL) >> 24) )) + +#define swab64(x) \ + ((uint64_t)( \ + (((uint64_t)(x) & (uint64_t)0x00000000000000ffULL) << 56) | \ + (((uint64_t)(x) & (uint64_t)0x000000000000ff00ULL) << 40) | \ + (((uint64_t)(x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \ + (((uint64_t)(x) & (uint64_t)0x00000000ff000000ULL) << 8) | \ + (((uint64_t)(x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \ + (((uint64_t)(x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \ + (((uint64_t)(x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \ + (((uint64_t)(x) & (uint64_t)0xff00000000000000ULL) >> 56) )) + +/* common.c */ +int is_big_endian(void); + +#endif /* _SWAB_H */ diff --git a/DasharoPayloadPkg/Library/CbfsLib/xdr.c b/DasharoPayloadPkg/Library/CbfsLib/xdr.c new file mode 100644 index 0000000000..ff12afa6f1 --- /dev/null +++ b/DasharoPayloadPkg/Library/CbfsLib/xdr.c @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include "common.h" + +/* The assumption in all this code is that we're given a pointer to enough data. + * Hence, we do not check for underflow. + */ +static uint8_t get8(struct buffer *input) +{ + uint8_t ret = *input->data++; + input->size--; + return ret; +} + +static uint16_t get16be(struct buffer *input) +{ + uint16_t ret; + ret = get8(input) << 8; + ret |= get8(input); + return ret; +} + +static uint32_t get32be(struct buffer *input) +{ + uint32_t ret; + ret = get16be(input) << 16; + ret |= get16be(input); + return ret; +} + +static uint64_t get64be(struct buffer *input) +{ + uint64_t ret; + ret = get32be(input); + ret <<= 32; + ret |= get32be(input); + return ret; +} + +static void put8(struct buffer *input, uint8_t val) +{ + input->data[input->size] = val; + input->size++; +} + +static void put16be(struct buffer *input, uint16_t val) +{ + put8(input, val >> 8); + put8(input, val); +} + +static void put32be(struct buffer *input, uint32_t val) +{ + put16be(input, val >> 16); + put16be(input, val); +} + +static void put64be(struct buffer *input, uint64_t val) +{ + put32be(input, val >> 32); + put32be(input, val); +} + +struct xdr xdr_be = { + get8, get16be, get32be, get64be, + put8, put16be, put32be, put64be +}; diff --git a/DasharoPayloadPkg/Library/EfiVarsLib/EfiVarsLib.c b/DasharoPayloadPkg/Library/EfiVarsLib/EfiVarsLib.c new file mode 100644 index 0000000000..91dd0f2484 --- /dev/null +++ b/DasharoPayloadPkg/Library/EfiVarsLib/EfiVarsLib.c @@ -0,0 +1,246 @@ +/* SPDX-License-Identifier: BSD-2-Clause-Patent */ + +#include + +#include +#include +#include +#include +#include + +// Firmware volume is what's stored in SMMSTORE region of CBFS. It wraps +// variable store. +// +// Variable store is part of firmware volume. This unit doesn't deal with its +// header only with data that follows. + +STATIC +UINT16 +CalcChecksum ( + CONST UINT16 *Hdr, + UINTN Size + ) +{ + UINT16 Checksum; + UINTN Idx; + + ASSERT (Size % 2 == 0 && "Header can't have odd length."); + + Checksum = 0; + for (Idx = 0; Idx < Size / 2; ++Idx) + Checksum += Hdr[Idx]; + + return Checksum; +} + +STATIC +BOOLEAN +InitFv ( + IN OUT MemRange Fv + ) +{ + EFI_STATUS Status; + UINTN BlockSize; + UINTN VolHdrLen; + EFI_FIRMWARE_VOLUME_HEADER *VolHdr; + VARIABLE_STORE_HEADER *VarStoreHdr; + + Status = SmmStoreLibGetBlockSize (&BlockSize); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a(): SmmStoreLibGetBlockSize() failed with: %r\n", + __FUNCTION__, + Status + )); + return FALSE; + } + + if (Fv.Length % BlockSize != 0) { + DEBUG (( + DEBUG_ERROR, + "%a(): firmware Volume size is not a multiple of 64KiB\n", + __FUNCTION__ + )); + return FALSE; + } + + SetMem (Fv.Start, Fv.Length, 0xff); + + VolHdrLen = sizeof (*VolHdr) + sizeof (EFI_FV_BLOCK_MAP_ENTRY); + + VolHdr = (EFI_FIRMWARE_VOLUME_HEADER *) Fv.Start; + SetMem (VolHdr, sizeof (*VolHdr), 0x00); + + VolHdr->FileSystemGuid = gEfiSystemNvDataFvGuid; + VolHdr->FvLength = Fv.Length; + VolHdr->Signature = EFI_FVH_SIGNATURE; + VolHdr->Attributes = EFI_FVB2_READ_ENABLED_CAP + | EFI_FVB2_READ_STATUS + | EFI_FVB2_WRITE_ENABLED_CAP + | EFI_FVB2_WRITE_STATUS + | EFI_FVB2_STICKY_WRITE + | EFI_FVB2_MEMORY_MAPPED + | EFI_FVB2_ERASE_POLARITY; + VolHdr->HeaderLength = VolHdrLen; + VolHdr->Revision = EFI_FVH_REVISION; + + VolHdr->BlockMap[0].NumBlocks = Fv.Length / BlockSize; + VolHdr->BlockMap[0].Length = BlockSize; + VolHdr->BlockMap[1].NumBlocks = 0; + VolHdr->BlockMap[1].Length = 0; + + VolHdr->Checksum = ~CalcChecksum ((CONST UINT16 *) VolHdr, VolHdrLen) + 1; + + VarStoreHdr = (VARIABLE_STORE_HEADER *) (Fv.Start + VolHdrLen); + SetMem (VarStoreHdr, sizeof (*VarStoreHdr), 0x00); + + // Authentication-related fields will be filled with 0xff. + VarStoreHdr->Signature = gEfiAuthenticatedVariableGuid; + // Actual size of the storage is block size, the rest is + // Fault Tolerant Write (FTW) space and the FTW spare space. + VarStoreHdr->Size = BlockSize - VolHdrLen; + VarStoreHdr->Format = VARIABLE_STORE_FORMATTED; + VarStoreHdr->State = VARIABLE_STORE_HEALTHY; + + return TRUE; +} + +BOOLEAN +EFIAPI +EfiVarsInit ( + IN OUT MemRange Fv, + OUT EfiVars *Storage + ) +{ + CONST EFI_FIRMWARE_VOLUME_HEADER *VolHdr; + CONST VARIABLE_STORE_HEADER *VarStoreHdr; + UINT8 *VolData; + UINTN VolDataSize; + + if (!InitFv (Fv)) { + DEBUG (( + DEBUG_ERROR, + "%a(): failed to create variable store", + __FUNCTION__ + )); + return FALSE; + } + + VolHdr = (CONST EFI_FIRMWARE_VOLUME_HEADER *) Fv.Start; + VolData = Fv.Start + VolHdr->HeaderLength; + VolDataSize = Fv.Length - VolHdr->HeaderLength; + VarStoreHdr = (CONST VARIABLE_STORE_HEADER *) VolData; + + Storage->Fv = Fv; + Storage->Store.Start = VolData + sizeof (*VarStoreHdr); + Storage->Store.Length = VolDataSize - sizeof (*VarStoreHdr); + Storage->Vars = NULL; + + return TRUE; +} + +STATIC +VOID +StoreVar ( + IN CONST EfiVar *Var, + OUT UINT8 *Data + ) +{ + AUTHENTICATED_VARIABLE_HEADER hdr; + SetMem (&hdr, sizeof (hdr), 0xff); + + hdr.StartId = VARIABLE_DATA; + hdr.State = VAR_ADDED; + hdr.Reserved = 0; + hdr.Attributes = Var->Attrs; + hdr.VendorGuid = Var->Guid; + hdr.NameSize = Var->NameSize; + hdr.DataSize = Var->DataSize; + + CopyMem (Data, &hdr, sizeof (hdr)); + Data += sizeof (hdr); + + CopyMem (Data, Var->Name, Var->NameSize); + CopyMem (Data + Var->NameSize, Var->Data, Var->DataSize); +} + +BOOLEAN +EFIAPI +EfiVarsWrite ( + IN EfiVars *Storage + ) +{ + MemRange VarStore; + UINT8 *OutData; + EfiVar *Var; + UINTN VarSize; + + VarStore = Storage->Store; + OutData = VarStore.Start; + + for (Var = Storage->Vars; Var != NULL; Var = Var->Next) { + VarSize = + sizeof (AUTHENTICATED_VARIABLE_HEADER) + Var->NameSize + Var->DataSize; + if (OutData + VarSize > VarStore.Start + VarStore.Length) { + DEBUG (( + DEBUG_ERROR, + "%a(): not enough space to serialize Variable Store (have 0x%x).\n", + __FUNCTION__, + VarStore.Length + )); + return FALSE; + } + + StoreVar (Var, OutData); + OutData += HEADER_ALIGN (VarSize); + } + + // The rest is "uninitialized". + SetMem (OutData, VarStore.Length - (OutData - VarStore.Start), 0xff); + + return TRUE; +} + +EfiVar * +EFIAPI +EfiVarsCreateVar ( + IN EfiVars *Storage + ) +{ + EfiVar *NewVar; + EfiVar *Var; + + NewVar = AllocateZeroPool (sizeof (*NewVar)); + if (NewVar == NULL) + return NULL; + + Var = Storage->Vars; + if (Var == NULL) { + Storage->Vars = NewVar; + } else { + while (Var->Next != NULL) + Var = Var->Next; + Var->Next = NewVar; + } + + return NewVar; +} + +VOID +EFIAPI +EfiVarsFree ( + IN EfiVars *Storage + ) +{ + EfiVar *Next; + EfiVar *Var; + + for (Var = Storage->Vars; Var != NULL; Var = Next) { + Next = Var->Next; + + FreePool (Var->Name); + FreePool (Var->Data); + FreePool (Var); + } +} diff --git a/DasharoPayloadPkg/Library/EfiVarsLib/EfiVarsLib.inf b/DasharoPayloadPkg/Library/EfiVarsLib/EfiVarsLib.inf new file mode 100644 index 0000000000..cfe5c05dcd --- /dev/null +++ b/DasharoPayloadPkg/Library/EfiVarsLib/EfiVarsLib.inf @@ -0,0 +1,41 @@ +## @file +# Simple EFI variables driver as a library. +# +# The functionality is limited to store initialization and addition of +# variables. +# +# Copyright (c) 2024, 3mdeb Sp. z o.o. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = EfiVarsLib + FILE_GUID = 48B9E949-AA19-4193-A216-878772E61A25 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = EfiVarsLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + EfiVarsLib.c + +[Packages] + DasharoPayloadPkg/DasharoPayloadPkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + SmmStoreLib + +[Guids] + gEfiAuthenticatedVariableGuid + gEfiSystemNvDataFvGuid diff --git a/DasharoPayloadPkg/Library/FmapLib/FmapLib.c b/DasharoPayloadPkg/Library/FmapLib/FmapLib.c new file mode 100644 index 0000000000..ffa18e39ed --- /dev/null +++ b/DasharoPayloadPkg/Library/FmapLib/FmapLib.c @@ -0,0 +1,197 @@ +/** @file + coreboot flash map data parsing library. + +Copyright (c) 2024, coreboot project
+SPDX-License-Identifier: BSD-3-Clause or GPL-2.0-only + +**/ + +#include + +#include +#include + +/* No-op on x86, but still useful to have. */ +#define le32toh(x) (x) +#define le16toh(x) (x) + +STATIC +BOOLEAN +IsPrint ( + IN CHAR8 Chr + ) +{ + return (Chr > 32 && Chr < 126); +} + +/* Make a best-effort assessment if the given fmap is real */ +STATIC +UINTN +IsValidFmap ( + IN CONST Fmap *Map + ) +{ + UINTN Idx; + + if (CompareMem (Map, FMAP_SIGNATURE, AsciiStrLen (FMAP_SIGNATURE)) != 0) + return 0; + /* strings containing the magic tend to fail here */ + if (Map->ver_major != FMAP_VER_MAJOR) + return 0; + /* a basic consistency check: flash should be larger than fmap */ + if (le32toh (Map->size) < + sizeof (*Map) + le16toh (Map->nareas) * sizeof (FmapArea)) + return 0; + + /* fmap-alikes along binary data tend to fail on having a valid, + * null-terminated string in the name field.*/ + Idx = 0; + while (Idx < FMAP_STRLEN) { + if (Map->name[Idx] == 0) + break; + if (!IsPrint (Map->name[Idx])) + return 0; + if (Idx == FMAP_STRLEN - 1) { + /* name is specified to be null terminated single-word string + * without spaces. We did not break in the 0 test, we know it + * is a printable spaceless string but we're seeing FMAP_STRLEN + * symbols, which is one too many. + */ + return 0; + } + Idx++; + } + return 1; + +} + +/* returns size of fmap data structure if successful, <0 to indicate error */ +INTN +EFIAPI +FmapSize ( + IN CONST Fmap *Map + ) +{ + if (!Map) + return -1; + + return sizeof (*Map) + (le16toh (Map->nareas) * sizeof (FmapArea)); +} + +/* brute force linear search */ +STATIC +INTN +FmapLsearch ( + IN CONST UINT8 *Image, + IN UINTN Len + ) +{ + INTN Offset; + BOOLEAN FmapFound; + + FmapFound = FALSE; + + for (Offset = 0; Offset < Len - sizeof (Fmap); Offset++) { + if (IsValidFmap ((CONST Fmap *) &Image[Offset])) { + FmapFound = 1; + break; + } + } + + if (!FmapFound) + return -1; + + if (Offset + FmapSize ((CONST Fmap *) &Image[Offset]) > Len) + return -1; + + return Offset; +} + +/* if Image length is a power of 2, use binary search */ +STATIC +INTN +FmapBsearch ( + IN CONST UINT8 *Image, + IN UINTN Len + ) +{ + INTN Offset; + UINTN Stride; + BOOLEAN FmapFound; + + FmapFound = FALSE; + + /* + * For efficient operation, we start with the largest Stride possible + * and then decrease the Stride on each iteration. Also, check for a + * remainder when modding the Offset with the previous Stride. This + * makes it so that each Offset is only checked once. + */ + for (Stride = Len / 2; Stride >= 16; Stride /= 2) { + if (FmapFound) + break; + + for (Offset = 0; Offset < Len - sizeof (Fmap); Offset += Stride) { + if ((Offset % (Stride * 2) == 0) && (Offset != 0)) + continue; + if (IsValidFmap ((CONST Fmap *) &Image[Offset])) { + FmapFound = 1; + break; + } + } + } + + if (!FmapFound) + return -1; + + if (Offset + FmapSize ((CONST Fmap *) &Image[Offset]) > Len) + return -1; + + return Offset; +} + +STATIC +BOOLEAN +IsPowerOf2 ( + UINTN Number +) +{ + return Number != 0 && (Number & (Number - 1)) == 0; +} + +INTN +EFIAPI +FmapFind ( + CONST UINT8 *Image, + UINTN Len + ) +{ + if ((Image == NULL) || (Len == 0)) + return -1; + + if (IsPowerOf2 (Len)) + return FmapBsearch (Image, Len); + + return FmapLsearch (Image, Len); +} + +CONST FmapArea * +EFIAPI +FmapFindArea ( + IN CONST Fmap *Map, + IN CONST CHAR8 *Name +) +{ + UINTN Idx; + + if (!Map || !Name) + return NULL; + + for (Idx = 0; Idx < le16toh (Map->nareas); Idx++) { + if (AsciiStrCmp ((CONST CHAR8 *) Map->areas[Idx].name, Name) == 0) { + return &Map->areas[Idx]; + } + } + + return NULL; +} diff --git a/DasharoPayloadPkg/Library/FmapLib/FmapLib.inf b/DasharoPayloadPkg/Library/FmapLib/FmapLib.inf new file mode 100644 index 0000000000..40ce8c8ff3 --- /dev/null +++ b/DasharoPayloadPkg/Library/FmapLib/FmapLib.inf @@ -0,0 +1,32 @@ +## @file +# coreboot flash map data parsing library. +# +# Copyright (c) 2024, 3mdeb Sp. z o.o. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = FmapLib + FILE_GUID = 757DD2FD-A779-4F4C-BE43-A584649F838A + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = FmapLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + FmapLib.c + +[Packages] + DasharoPayloadPkg/DasharoPayloadPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib diff --git a/DasharoPayloadPkg/Library/FmpDeviceSmmLib/Flashing.c b/DasharoPayloadPkg/Library/FmpDeviceSmmLib/Flashing.c new file mode 100644 index 0000000000..592ac17a80 --- /dev/null +++ b/DasharoPayloadPkg/Library/FmpDeviceSmmLib/Flashing.c @@ -0,0 +1,695 @@ +#include "Flashing.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef enum { + REGION_MIGRATED, + REGION_NOT_IN_SRC, + REGION_NOT_IN_DST, + REGION_AT_DIFFERENT_OFFSET, + REGION_OF_DIFFERENT_SIZE, +} RegionMigrationStatus; + +typedef struct { + CONST UINT8 *Current; + UINT8 *Updated; + CONST Fmap *CurrentFmap; + CONST Fmap *UpdatedFmap; + UINTN FwSize; +} MigrationData; + +STATIC +BOOLEAN +GetFmap ( + IN CONST UINT8 *Image, + IN UINTN Size, + OUT CONST Fmap **Map + ) +{ + INTN FmapOffset; + CONST FmapArea *FmapRegion; + + FmapOffset = FmapFind (Image, Size); + if (FmapOffset < 0) { + DEBUG ((DEBUG_ERROR, "%a(): failed to find FMAP\n", __FUNCTION__)); + *Map = NULL; + return FALSE; + } + + *Map = (CONST Fmap *) (Image + FmapOffset); + + if ((*Map)->size > Size) { + DEBUG ((DEBUG_ERROR, "%a(): FMAP is larger than firmware\n", __FUNCTION__)); + return FALSE; + } + + FmapRegion = FmapFindArea (*Map, "FMAP"); + if (FmapRegion == NULL) { + DEBUG ((DEBUG_ERROR, "%a(): FMAP doesn't describe itself\n", __FUNCTION__)); + return FALSE; + } + + if (FmapRegion->offset != FmapOffset) { + DEBUG (( + DEBUG_ERROR, + "%a(): wrong FMAP offset (expected: 0x%x, actual: 0x%x)\n", + __FUNCTION__, + FmapRegion->offset, + FmapOffset + )); + return FALSE; + } + + return TRUE; +} + +/** + Read current firmware in full and return as newly allocated pool memory. + + @return NULL On error. +**/ +VOID * +EFIAPI +ReadCurrentFirmware ( + VOID + ) +{ + EFI_STATUS Status; + UINT8 *Image; + UINTN FwSize; + UINTN Block; + UINTN BlockSize; + UINTN NumBytes; + + Status = SmmStoreLibGetBlockSize (&BlockSize); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a(): SmmStoreLibGetBlockSize() failed with: %r\n", + __FUNCTION__, + Status + )); + return NULL; + } + + Status = FmpDeviceGetSize (&FwSize); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a(): FmpDeviceGetSize() failed with: %r\n", + __FUNCTION__, + Status + )); + return NULL; + } + + Image = AllocatePool (FwSize); + if (Image == NULL) { + DEBUG (( + DEBUG_ERROR, + "%a(): failed to allocate current image buffer\n", + __FUNCTION__ + )); + return NULL; + } + + for (Block = 0; Block < FwSize / BlockSize; Block++) { + NumBytes = BlockSize; + Status = SmmStoreLibReadAnyBlock ( + Block, + 0, + &NumBytes, + Image + Block * BlockSize + ); + if (EFI_ERROR (Status) || NumBytes != BlockSize) { + DEBUG (( + DEBUG_ERROR, + "%a(): read %d out of %d bytes of flash at 0x%x (%r)\n", + __FUNCTION__, + NumBytes, + BlockSize, + Block * BlockSize, + Status + )); + FreePool (Image); + return NULL; + } + } + + return Image; +} + +/** + Migrates a flash map region from current firmware to a new one. + + @param[in] RegionName Name of the region to migrate. + @param[in] Data New image which gets patched. + @param[in] OffsetSensitive Whether mismatched offset is a fatal error. + + @return RegionMigrationStatus Status which might not be considered an error + depending on the region. +**/ +STATIC +RegionMigrationStatus +MigrateRegion ( + IN CONST CHAR8 *RegionName, + IN CONST MigrationData *Data, + IN BOOLEAN OffsetSensitive + ) +{ + CONST FmapArea *CurrentRegion; + CONST FmapArea *UpdatedRegion; + + CurrentRegion = FmapFindArea (Data->CurrentFmap, RegionName); + if (CurrentRegion == NULL) { + DEBUG (( + DEBUG_WARN, + "%a(): failed to find %a region in current firmware\n", + __FUNCTION__, + RegionName + )); + return REGION_NOT_IN_SRC; + } + + UpdatedRegion = FmapFindArea (Data->UpdatedFmap, RegionName); + if (UpdatedRegion == NULL) { + DEBUG (( + DEBUG_WARN, + "%a(): failed to find %a region in new firmware\n", + __FUNCTION__, + RegionName + )); + return REGION_NOT_IN_DST; + } + + if (OffsetSensitive && CurrentRegion->offset != UpdatedRegion->offset) { + DEBUG (( + DEBUG_WARN, + "%a(): %a regions' offsets don't match (current: 0x%x, updated: 0x%x)\n", + __FUNCTION__, + RegionName, + CurrentRegion->offset, + UpdatedRegion->offset + )); + return REGION_AT_DIFFERENT_OFFSET; + } + + if (CurrentRegion->size != UpdatedRegion->size) { + DEBUG (( + DEBUG_WARN, + "%a(): %a regions don't match in size (current: 0x%x, updated: 0x%x)\n", + __FUNCTION__, + RegionName, + CurrentRegion->size, + UpdatedRegion->size + )); + return REGION_OF_DIFFERENT_SIZE; + } + + CopyMem ( + Data->Updated + UpdatedRegion->offset, + Data->Current + CurrentRegion->offset, + UpdatedRegion->size + ); + + return REGION_MIGRATED; +} + +STATIC +EFI_STATUS +CopyVariable ( + IN OUT EfiVars *Storage, + IN CHAR16 *VarName, + IN CONST EFI_GUID *Vendor + ) +{ + EFI_STATUS Status; + VOID *VarData; + UINTN NameSize; + UINTN VarSize; + EfiVar *Var; + UINT32 Attrs; + + NameSize = StrSize (VarName); + + VarName = AllocateCopyPool (NameSize, VarName); + if (VarName == NULL) { + DEBUG (( + DEBUG_ERROR, + "%a(): failed to clone EFI variable name: %g-%s\n", + __FUNCTION__, + Vendor, + VarName + )); + return EFI_OUT_OF_RESOURCES; + } + + Status = GetVariable3 (VarName, Vendor, &VarData, &VarSize, &Attrs); + if (EFI_ERROR (Status)) { + FreePool (VarName); + return Status; + } + + if (!(Attrs & EFI_VARIABLE_NON_VOLATILE)) { + FreePool (VarName); + FreePool (VarData); + return EFI_SUCCESS; + } + + Var = EfiVarsCreateVar (Storage); + if (Var == NULL) { + DEBUG (( + DEBUG_ERROR, + "%a(): failed to allocate EFI variable structure for %g-%s\n", + __FUNCTION__, + Vendor, + VarName + )); + FreePool (VarName); + FreePool (VarData); + return EFI_OUT_OF_RESOURCES; + } + + Var->Name = VarName; + Var->NameSize = NameSize; + Var->Data = VarData; + Var->DataSize = VarSize; + Var->Guid = *Vendor; + Var->Attrs = Attrs; + + return Status; +} + +STATIC +EFI_STATUS +CopyVariables ( + IN OUT EfiVars *Storage + ) +{ + EFI_STATUS Status; + CHAR16 *Name; + CHAR16 *NewBuf; + UINTN MaxNameSize; + UINTN NameSize; + EFI_GUID Guid; + + MaxNameSize = 32 * sizeof (CHAR16); + Name = AllocateZeroPool (MaxNameSize); + if (Name == NULL) + return EFI_OUT_OF_RESOURCES; + + while (TRUE) { + NameSize = MaxNameSize; + Status = gRT->GetNextVariableName (&NameSize, Name, &Guid); + if (Status == EFI_BUFFER_TOO_SMALL) { + NewBuf = AllocatePool (NameSize); + if (NewBuf == NULL) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + + StrnCpyS ( + NewBuf, + NameSize / sizeof (CHAR16), + Name, + MaxNameSize / sizeof (CHAR16) + ); + FreePool (Name); + + Name = NewBuf; + MaxNameSize = NameSize; + + Status = gRT->GetNextVariableName (&NameSize, Name, &Guid); + } + + if (Status == EFI_NOT_FOUND) { + Status = EFI_SUCCESS; + break; + } + + if (EFI_ERROR (Status)) + break; + + CopyVariable (Storage, Name, &Guid); + } + + FreePool (Name); + return Status; +} + +STATIC +BOOLEAN +MigrateVariables ( + IN CONST MigrationData *Data + ) +{ + EFI_STATUS Status; + CONST FmapArea *UpdatedRegion; + MemRange Fv; + EfiVars Storage; + + UpdatedRegion = FmapFindArea (Data->UpdatedFmap, "SMMSTORE"); + if (UpdatedRegion == NULL) { + DEBUG (( + DEBUG_WARN, + "%a(): failed to find SMMSTORE in updated firmware\n", + __FUNCTION__ + )); + return TRUE; + } + + Fv.Start = Data->Updated + UpdatedRegion->offset; + Fv.Length = UpdatedRegion->size; + + if (!EfiVarsInit (Fv, &Storage)) { + DEBUG (( + DEBUG_WARN, + "%a(): failed to open SMMSTORE in updated firmware\n", + __FUNCTION__ + )); + return TRUE; + } + + Status = CopyVariables (&Storage); + if (EFI_ERROR (Status)) { + EfiVarsFree (&Storage); + DEBUG (( + DEBUG_ERROR, + "%a(): failed to copy EFI variables to updated firmware: %r\n", + __FUNCTION__, + Status + )); + return TRUE; + } + + if (!EfiVarsWrite (&Storage)) { + DEBUG (( + DEBUG_ERROR, + "%a(): failed to write SMMSTORE to updated firmware\n", + __FUNCTION__ + )); + EfiVarsFree (&Storage); + return FALSE; + } + + EfiVarsFree (&Storage); + return TRUE; +} + +STATIC +BOOLEAN +MigrateRomhole ( + IN CONST MigrationData *Data + ) +{ + RegionMigrationStatus Status; + + Status = MigrateRegion ("ROMHOLE", Data, TRUE); + + return Status == REGION_MIGRATED + || Status == REGION_NOT_IN_SRC + || Status == REGION_NOT_IN_DST; +} + +STATIC +BOOLEAN +MigrateBootLogo ( + IN CONST MigrationData *Data + ) +{ + RegionMigrationStatus Status; + + Status = MigrateRegion ("BOOTSPLASH", Data, FALSE); + + return Status == REGION_MIGRATED + || Status == REGION_NOT_IN_SRC + || Status == REGION_NOT_IN_DST; +} + +STATIC +BOOLEAN +MigrateFile ( + CONST CHAR8 *Name, + struct cbfs_image *CurrentCbfs, + struct cbfs_image *UpdatedCbfs + ) +{ + struct buffer Buf; + struct cbfs_file *Entry; + struct cbfs_file *Header; + + Entry = cbfs_get_entry (CurrentCbfs, Name); + if (Entry == NULL) { + DEBUG (( + DEBUG_WARN, + "%a(): failed to find %a in current CBFS\n", + __FUNCTION__, + Name + )); + return FALSE; + } + + buffer_init ( + &Buf, + Entry->filename, + CBFS_SUBHEADER (Entry), + ntohl (Entry->len) + ); + + Header = cbfs_create_file_header (ntohl (Entry->type), Buf.size, Name); + if (Header == NULL) { + DEBUG (( + DEBUG_ERROR, + "%a(): failed to allocate header for %a file\n", + __FUNCTION__, + Name + )); + return FALSE; + } + + // + // An unlikely situation, but won't hurt to handle it. + // + if (cbfs_get_entry (UpdatedCbfs, Name) != NULL) { + DEBUG (( + DEBUG_INFO, + "%a(): found %a in updated CBFS\n", + __FUNCTION__, + Name + )); + if (cbfs_remove_entry (UpdatedCbfs, Name) != 0) { + DEBUG (( + DEBUG_ERROR, + "%a(): failed to remove %a from updated CBFS\n", + __FUNCTION__, + Name + )); + return FALSE; + } + } + + if (cbfs_add_entry (UpdatedCbfs, &Buf, 0, Header, 0) != 0) { + DEBUG (( + DEBUG_ERROR, + "%a(): failed to add %a to updated CBFS\n", + __FUNCTION__, + Name + )); + FreePool (Header); + return FALSE; + } + + FreePool (Header); + return TRUE; +} + +STATIC +BOOLEAN +GetCbfs ( + IN CONST UINT8 *Image, + IN CONST Fmap *Fmap, + OUT struct cbfs_image *Cbfs + ) +{ + struct buffer Buf; + CONST FmapArea *CbRegion; + + CbRegion = FmapFindArea (Fmap, "COREBOOT"); + if (CbRegion == NULL) { + DEBUG (( + DEBUG_ERROR, + "%a(): failed to find COREBOOT region\n", + __FUNCTION__ + )); + return FALSE; + } + + buffer_init (&Buf, NULL, (UINT8 *) Image + CbRegion->offset, CbRegion->size); + if (cbfs_image_from_buffer (Cbfs, &Buf, ~0U) != 0) { + DEBUG ((DEBUG_ERROR, "%a(): failed to load CBFS\n", __FUNCTION__)); + return FALSE; + } + + return TRUE; +} + +/** + Migrates data from current firmware to new image before it's written. + + @param[in] Data Description of old and new firmware images. + + @return TRUE On successful migration of data that was found. + @return FALSE On error. +**/ +STATIC +BOOLEAN +MigrateSmbiosData ( + IN CONST MigrationData *Data + ) +{ + struct cbfs_image CurrentCbfs; + struct cbfs_image UpdatedCbfs; + + if (!GetCbfs (Data->Current, Data->CurrentFmap, &CurrentCbfs)) { + DEBUG ((DEBUG_ERROR, "%a(): failed to load current CBFS\n", __FUNCTION__)); + return FALSE; + } + + if (!GetCbfs (Data->Updated, Data->UpdatedFmap, &UpdatedCbfs)) { + DEBUG ((DEBUG_ERROR, "%a(): failed to load updated CBFS\n", __FUNCTION__)); + return FALSE; + } + + // + // Not considering these errors fatal. + // + if (!MigrateFile ("serial_number", &CurrentCbfs, &UpdatedCbfs)) { + DEBUG (( + DEBUG_WARN, + "%a(): failed to migrate 'serial_number' CBFS file\n", + __FUNCTION__ + )); + } + if (!MigrateFile ("system_uuid", &CurrentCbfs, &UpdatedCbfs)) { + DEBUG (( + DEBUG_WARN, + "%a(): failed to migrate 'system_uuid' CBFS file\n", + __FUNCTION__ + )); + } + + // + // TODO: if CONFIG_CBFS_VERIFICATION is on, need to update CBFS hash here + // (file can have hashes too, but they seem optional) + // + + return TRUE; +} + +/** + Migrates data from current firmware to new image before it's written. + + @param[in] Current Current image used as a source of data. + @param[in] New New image which gets patched. + + @return NULL On error. +**/ +VOID * +EFIAPI +MergeFirmwareImages ( + IN CONST VOID *Current, + IN CONST VOID *New + ) +{ + EFI_STATUS Status; + MigrationData Data; + + Data.Current = Current; + + // + // The assumption is that current firmware image contains all the interesting + // data, i.e. if there was anything that needed to be flushed, it was flushed + // before the snapshot was taken. + // + + Status = FmpDeviceGetSize (&Data.FwSize); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a(): FmpDeviceGetSize() failed with: %r\n", + __FUNCTION__, + Status + )); + return NULL; + } + + Data.Updated = AllocateCopyPool (Data.FwSize, New); + if (Data.Updated == NULL) { + DEBUG (( + DEBUG_ERROR, + "%a(): failed to allocate merged image buffer\n", + __FUNCTION__ + )); + return NULL; + } + + if (!GetFmap (Data.Current, Data.FwSize, &Data.CurrentFmap)) { + DEBUG (( + DEBUG_ERROR, + "%a(): failed to parse current firmware\n", + __FUNCTION__ + )); + goto Fail; + } + + if (!GetFmap (Data.Updated, Data.FwSize, &Data.UpdatedFmap)) { + DEBUG (( + DEBUG_WARN, + "%a(): failed to parse updated firmware\n", + __FUNCTION__ + )); + if (Data.UpdatedFmap == NULL) { + // + // Not a hard error. It's conceivable that for a capsule to be used to + // flash non-coreboot firmware. + // + return Data.Updated; + } + goto Fail; + } + + if (!MigrateVariables (&Data)) { + DEBUG ((DEBUG_ERROR, "%a(): MigrateVariables() failed\n", __FUNCTION__)); + goto Fail; + } + + if (!MigrateRomhole (&Data)) { + DEBUG ((DEBUG_ERROR, "%a(): MigrateRomhole () failed\n", __FUNCTION__)); + goto Fail; + } + + if (!MigrateBootLogo (&Data)) { + DEBUG ((DEBUG_ERROR, "%a(): MigrateBootLogo () failed\n", __FUNCTION__)); + goto Fail; + } + + if (!MigrateSmbiosData (&Data)) { + DEBUG ((DEBUG_ERROR, "%a(): MigrateSmbiosData () failed\n", __FUNCTION__)); + goto Fail; + } + + return Data.Updated; + +Fail: + FreePool (Data.Updated); + return NULL; +} diff --git a/DasharoPayloadPkg/Library/FmpDeviceSmmLib/Flashing.h b/DasharoPayloadPkg/Library/FmpDeviceSmmLib/Flashing.h new file mode 100644 index 0000000000..d383e1472a --- /dev/null +++ b/DasharoPayloadPkg/Library/FmpDeviceSmmLib/Flashing.h @@ -0,0 +1,30 @@ +#ifndef FLASHING_H__ +#define FLASHING_H__ + +/** + Read current firmware in full and return as newly allocated pool memory. + + @return NULL On error. +**/ +VOID * +EFIAPI +ReadCurrentFirmware ( + VOID + ); + +/** + Migrates data from current firmware to new image before it's written. + + @param[in] Current Current image used as a source of data. + @param[in] New New image which gets patched. + + @return NULL On error. +**/ +VOID * +EFIAPI +MergeFirmwareImages ( + IN CONST VOID *Current, + IN CONST VOID *New + ); + +#endif // FLASHING_H__ diff --git a/DasharoPayloadPkg/Library/FmpDeviceSmmLib/FmpDeviceSmmLib.c b/DasharoPayloadPkg/Library/FmpDeviceSmmLib/FmpDeviceSmmLib.c new file mode 100644 index 0000000000..51c07e8e7e --- /dev/null +++ b/DasharoPayloadPkg/Library/FmpDeviceSmmLib/FmpDeviceSmmLib.c @@ -0,0 +1,1109 @@ +/** @file + Provides firmware device specific services to support updates of a firmware + image stored in a firmware device. + + Copyright (c) Microsoft Corporation.
+ Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.
+ Copyright (c) 2024, 3mdeb Sp. z o.o. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Flashing.h" + +typedef struct { + EFI_GUID FwGuid; + UINT32 FwVersion; + UINT32 FwLsv; + UINT32 FwSize; +} FwInfo; + +/** + This function requests firmware information on the first call, caches it and + returns on all calls afterwards. + + @param[out] Info Place to store a pointer to firmware information. + + @retval EFI_SUCCESS Info points to firmware information. + @retval EFI_INVALID_PARAMETER Info is NULL. +**/ +STATIC +EFI_STATUS +GetFwInfo ( + OUT FwInfo **Info + ) +{ + STATIC FwInfo Storage; + STATIC BOOLEAN Initialized; + + EFI_STATUS Status; + + if (Info == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (!Initialized) { + Status = ParseFwInfo (&Storage.FwGuid, &Storage.FwVersion, &Storage.FwLsv, &Storage.FwSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a(): ParseFwInfo() failed with: %r\n", __FUNCTION__, Status)); + return Status; + } + + Initialized = TRUE; + } + + *Info = &Storage; + return EFI_SUCCESS; +} + +/** + Provide a function to install the Firmware Management Protocol instance onto a + device handle when the device is managed by a driver that follows the UEFI + Driver Model. If the device is not managed by a driver that follows the UEFI + Driver Model, then EFI_UNSUPPORTED is returned. + + @param[in] FmpInstaller Function that installs the Firmware Management + Protocol. + + @retval EFI_SUCCESS The device is managed by a driver that follows the + UEFI Driver Model. FmpInstaller must be called on + each Driver Binding Start(). + @retval EFI_UNSUPPORTED The device is not managed by a driver that follows + the UEFI Driver Model. + @retval other The Firmware Management Protocol for this firmware + device is not installed. The firmware device is + still locked using FmpDeviceLock(). +**/ +EFI_STATUS +EFIAPI +RegisterFmpInstaller ( + IN FMP_DEVICE_LIB_REGISTER_FMP_INSTALLER Function + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Provide a function to uninstall the Firmware Management Protocol instance from a + device handle when the device is managed by a driver that follows the UEFI + Driver Model. If the device is not managed by a driver that follows the UEFI + Driver Model, then EFI_UNSUPPORTED is returned. + + @param[in] FmpUninstaller Function that installs the Firmware Management + Protocol. + + @retval EFI_SUCCESS The device is managed by a driver that follows the + UEFI Driver Model. FmpUninstaller must be called on + each Driver Binding Stop(). + @retval EFI_UNSUPPORTED The device is not managed by a driver that follows + the UEFI Driver Model. + @retval other The Firmware Management Protocol for this firmware + device is not installed. The firmware device is + still locked using FmpDeviceLock(). +**/ +EFI_STATUS +EFIAPI +RegisterFmpUninstaller ( + IN FMP_DEVICE_LIB_REGISTER_FMP_UNINSTALLER Function + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Set the device context for the FmpDeviceLib services when the device is + managed by a driver that follows the UEFI Driver Model. If the device is not + managed by a driver that follows the UEFI Driver Model, then EFI_UNSUPPORTED + is returned. Once a device context is set, the FmpDeviceLib services + operate on the currently set device context. + + @param[in] Handle Device handle for the FmpDeviceLib services. + If Handle is NULL, then Context is freed. + @param[in, out] Context Device context for the FmpDeviceLib services. + If Context is NULL, then a new context is allocated + for Handle and the current device context is set and + returned in Context. If Context is not NULL, then + the current device context is set. + + @retval EFI_SUCCESS The device is managed by a driver that follows the + UEFI Driver Model. + @retval EFI_UNSUPPORTED The device is not managed by a driver that follows + the UEFI Driver Model. + @retval other The Firmware Management Protocol for this firmware + device is not installed. The firmware device is + still locked using FmpDeviceLock(). +**/ +EFI_STATUS +EFIAPI +FmpDeviceSetContext ( + IN EFI_HANDLE Handle, + IN OUT VOID **Context + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Returns the size, in bytes, of the firmware image currently stored in the + firmware device. This function is used to by the GetImage() and + GetImageInfo() services of the Firmware Management Protocol. If the image + size can not be determined from the firmware device, then 0 must be returned. + + @param[out] Size Pointer to the size, in bytes, of the firmware image + currently stored in the firmware device. + + @retval EFI_SUCCESS The size of the firmware image currently + stored in the firmware device was returned. + @retval EFI_INVALID_PARAMETER Size is NULL. + @retval EFI_UNSUPPORTED The firmware device does not support reporting + the size of the currently stored firmware image. + @retval EFI_DEVICE_ERROR An error occurred attempting to determine the + size of the firmware image currently stored in + in the firmware device. +**/ +EFI_STATUS +EFIAPI +FmpDeviceGetSize ( + OUT UINTN *Size + ) +{ + EFI_STATUS Status; + FwInfo *FwInfo; + + if (Size == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = GetFwInfo (&FwInfo); + if (!EFI_ERROR (Status)) { + *Size = FwInfo->FwSize; + } + return Status; +} + +/** + Returns the GUID value used to fill in the ImageTypeId field of the + EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo() + service of the Firmware Management Protocol. If EFI_UNSUPPORTED is returned, + then the ImageTypeId field is set to gEfiCallerIdGuid. If EFI_SUCCESS is + returned, then ImageTypeId is set to the Guid returned from this function. + + @param[out] Guid Double pointer to a GUID value that is updated to point to + to a GUID value. The GUID value is not allocated and must + not be modified or freed by the caller. + + @retval EFI_SUCCESS EFI_FIRMWARE_IMAGE_DESCRIPTOR ImageTypeId GUID is set + to the returned Guid value. + @retval EFI_UNSUPPORTED EFI_FIRMWARE_IMAGE_DESCRIPTOR ImageTypeId GUID is set + to gEfiCallerIdGuid. +**/ +EFI_STATUS +EFIAPI +FmpDeviceGetImageTypeIdGuidPtr ( + OUT EFI_GUID **Guid + ) +{ + EFI_STATUS Status; + FwInfo *FwInfo; + + if (Guid == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = GetFwInfo (&FwInfo); + if (!EFI_ERROR (Status)) { + *Guid = &FwInfo->FwGuid; + } + return Status; +} + +/** + Returns values used to fill in the AttributesSupported and AttributesSettings + fields of the EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the + GetImageInfo() service of the Firmware Management Protocol. The following + bit values from the Firmware Management Protocol may be combined: + IMAGE_ATTRIBUTE_IMAGE_UPDATABLE + IMAGE_ATTRIBUTE_RESET_REQUIRED + IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED + IMAGE_ATTRIBUTE_IN_USE + IMAGE_ATTRIBUTE_UEFI_IMAGE + + @param[out] Supported Attributes supported by this firmware device. + @param[out] Setting Attributes settings for this firmware device. + + @retval EFI_SUCCESS The attributes supported by the firmware + device were returned. + @retval EFI_INVALID_PARAMETER Supported is NULL. + @retval EFI_INVALID_PARAMETER Setting is NULL. +**/ +EFI_STATUS +EFIAPI +FmpDeviceGetAttributes ( + OUT UINT64 *Supported, + OUT UINT64 *Setting + ) +{ + if (Supported == NULL || Setting == NULL) { + return EFI_INVALID_PARAMETER; + } + + *Supported = IMAGE_ATTRIBUTE_IMAGE_UPDATABLE + | IMAGE_ATTRIBUTE_RESET_REQUIRED + | IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED + | IMAGE_ATTRIBUTE_IN_USE; + *Setting = *Supported; + return EFI_SUCCESS; +} + +/** + Returns the value used to fill in the LowestSupportedVersion field of the + EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo() + service of the Firmware Management Protocol. If EFI_SUCCESS is returned, then + the firmware device supports a method to report the LowestSupportedVersion + value from the currently stored firmware image. If the value can not be + reported for the firmware image currently stored in the firmware device, then + EFI_UNSUPPORTED must be returned. EFI_DEVICE_ERROR is returned if an error + occurs attempting to retrieve the LowestSupportedVersion value for the + currently stored firmware image. + + @note It is recommended that all firmware devices support a method to report + the LowestSupportedVersion value from the currently stored firmware + image. + + @param[out] LowestSupportedVersion LowestSupportedVersion value retrieved + from the currently stored firmware image. + + @retval EFI_SUCCESS The lowest supported version of currently stored + firmware image was returned in LowestSupportedVersion. + @retval EFI_UNSUPPORTED The firmware device does not support a method to + report the lowest supported version of the currently + stored firmware image. + @retval EFI_DEVICE_ERROR An error occurred attempting to retrieve the lowest + supported version of the currently stored firmware + image. +**/ +EFI_STATUS +EFIAPI +FmpDeviceGetLowestSupportedVersion ( + OUT UINT32 *LowestSupportedVersion + ) +{ + EFI_STATUS Status; + FwInfo *FwInfo; + + if (LowestSupportedVersion == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = GetFwInfo (&FwInfo); + if (!EFI_ERROR (Status)) { + *LowestSupportedVersion = FwInfo->FwLsv; + } + return Status; +} + +/** + Returns the Null-terminated Unicode string that is used to fill in the + VersionName field of the EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is + returned by the GetImageInfo() service of the Firmware Management Protocol. + The returned string must be allocated using EFI_BOOT_SERVICES.AllocatePool(). + + @note It is recommended that all firmware devices support a method to report + the VersionName string from the currently stored firmware image. + + @param[out] VersionString The version string retrieved from the currently + stored firmware image. + + @retval EFI_SUCCESS The version string of currently stored + firmware image was returned in Version. + @retval EFI_INVALID_PARAMETER VersionString is NULL. + @retval EFI_UNSUPPORTED The firmware device does not support a method + to report the version string of the currently + stored firmware image. + @retval EFI_DEVICE_ERROR An error occurred attempting to retrieve the + version string of the currently stored + firmware image. + @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate the + buffer for the version string of the currently + stored firmware image. +**/ +EFI_STATUS +EFIAPI +FmpDeviceGetVersionString ( + OUT CHAR16 **VersionString + ) +{ + CONST CHAR8 *CbVersion; + CONST CHAR8 *CbExtraVersion; + UINTN Size; + + if (VersionString == NULL) { + return EFI_INVALID_PARAMETER; + } + + CbVersion = ParseInfoString (CB_TAG_VERSION); + CbExtraVersion = ParseInfoString (CB_TAG_EXTRA_VERSION); + + if (CbVersion == NULL) { + CbVersion = ""; + } + + if (CbExtraVersion == NULL) { + CbExtraVersion = ""; + } + + Size = (AsciiStrLen (CbVersion) + AsciiStrLen (CbExtraVersion) + 1) * sizeof (CHAR16); + *VersionString = AllocatePool (Size); + if (*VersionString == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + UnicodeSPrint (*VersionString, Size, L"%a%a", CbVersion, CbExtraVersion); + + return EFI_SUCCESS; +} + +/** + Returns the value used to fill in the Version field of the + EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo() + service of the Firmware Management Protocol. If EFI_SUCCESS is returned, then + the firmware device supports a method to report the Version value from the + currently stored firmware image. If the value can not be reported for the + firmware image currently stored in the firmware device, then EFI_UNSUPPORTED + must be returned. EFI_DEVICE_ERROR is returned if an error occurs attempting + to retrieve the LowestSupportedVersion value for the currently stored firmware + image. + + @note It is recommended that all firmware devices support a method to report + the Version value from the currently stored firmware image. + + @param[out] Version The version value retrieved from the currently stored + firmware image. + + @retval EFI_SUCCESS The version of currently stored firmware image was + returned in Version. + @retval EFI_UNSUPPORTED The firmware device does not support a method to + report the version of the currently stored firmware + image. + @retval EFI_DEVICE_ERROR An error occurred attempting to retrieve the version + of the currently stored firmware image. +**/ +EFI_STATUS +EFIAPI +FmpDeviceGetVersion ( + OUT UINT32 *Version + ) +{ + EFI_STATUS Status; + FwInfo *FwInfo; + + if (Version == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = GetFwInfo (&FwInfo); + if (!EFI_ERROR (Status)) { + *Version = FwInfo->FwVersion; + } + return Status; +} + +/** + Returns the value used to fill in the HardwareInstance field of the + EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo() + service of the Firmware Management Protocol. If EFI_SUCCESS is returned, then + the firmware device supports a method to report the HardwareInstance value. + If the value can not be reported for the firmware device, then EFI_UNSUPPORTED + must be returned. EFI_DEVICE_ERROR is returned if an error occurs attempting + to retrieve the HardwareInstance value for the firmware device. + + @param[out] HardwareInstance The hardware instance value for the firmware + device. + + @retval EFI_SUCCESS The hardware instance for the current firmware + device is returned in HardwareInstance. + @retval EFI_UNSUPPORTED The firmware device does not support a method to + report the hardware instance value. + @retval EFI_DEVICE_ERROR An error occurred attempting to retrieve the hardware + instance value. +**/ +EFI_STATUS +EFIAPI +FmpDeviceGetHardwareInstance ( + OUT UINT64 *HardwareInstance + ) +{ + if (HardwareInstance == NULL) { + return EFI_INVALID_PARAMETER; + } + + *HardwareInstance = 0; + return EFI_SUCCESS; +} + +/** + Returns a copy of the firmware image currently stored in the firmware device. + + @note It is recommended that all firmware devices support a method to retrieve + a copy currently stored firmware image. This can be used to support + features such as recovery and rollback. + + @param[out] Image Pointer to a caller allocated buffer where the + currently stored firmware image is copied to. + @param[in, out] ImageSize Pointer the size, in bytes, of the Image buffer. + On return, points to the size, in bytes, of firmware + image currently stored in the firmware device. + + @retval EFI_SUCCESS Image contains a copy of the firmware image + currently stored in the firmware device, and + ImageSize contains the size, in bytes, of the + firmware image currently stored in the + firmware device. + @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small + to hold the firmware image currently stored in + the firmware device. The buffer size required + is returned in ImageSize. + @retval EFI_INVALID_PARAMETER The Image is NULL. + @retval EFI_INVALID_PARAMETER The ImageSize is NULL. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_DEVICE_ERROR An error occurred attempting to retrieve the + firmware image currently stored in the firmware + device. +**/ +EFI_STATUS +EFIAPI +FmpDeviceGetImage ( + OUT VOID *Image, + IN OUT UINTN *ImageSize + ) +{ + // + // This seems useful only if FMP device is part of the running firmware. + // + return EFI_UNSUPPORTED; +} + +/** + Checks if a new firmware image is valid for the firmware device. This + function allows firmware update operation to validate the firmware image + before FmpDeviceSetImage() is called. + + @param[in] Image Points to a new firmware image. + @param[in] ImageSize Size, in bytes, of a new firmware image. + @param[out] ImageUpdatable Indicates if a new firmware image is valid for + a firmware update to the firmware device. The + following values from the Firmware Management + Protocol are supported: + IMAGE_UPDATABLE_VALID + IMAGE_UPDATABLE_INVALID + IMAGE_UPDATABLE_INVALID_TYPE + IMAGE_UPDATABLE_INVALID_OLD + IMAGE_UPDATABLE_VALID_WITH_VENDOR_CODE + + @retval EFI_SUCCESS The image was successfully checked. Additional + status information is returned in + ImageUpdatable. + @retval EFI_INVALID_PARAMETER Image is NULL. + @retval EFI_INVALID_PARAMETER ImageUpdatable is NULL. +**/ +EFI_STATUS +EFIAPI +FmpDeviceCheckImage ( + IN CONST VOID *Image, + IN UINTN ImageSize, + OUT UINT32 *ImageUpdatable + ) +{ + UINT32 LastAttemptStatus; + + return FmpDeviceCheckImageWithStatus (Image, ImageSize, ImageUpdatable, &LastAttemptStatus); +} + +/** + Checks if a new firmware image is valid for the firmware device. This + function allows firmware update operation to validate the firmware image + before FmpDeviceSetImage() is called. + + @param[in] Image Points to a new firmware image. + @param[in] ImageSize Size, in bytes, of a new firmware image. + @param[out] ImageUpdatable Indicates if a new firmware image is valid for + a firmware update to the firmware device. The + following values from the Firmware Management + Protocol are supported: + IMAGE_UPDATABLE_VALID + IMAGE_UPDATABLE_INVALID + IMAGE_UPDATABLE_INVALID_TYPE + IMAGE_UPDATABLE_INVALID_OLD + IMAGE_UPDATABLE_VALID_WITH_VENDOR_CODE + @param[out] LastAttemptStatus A pointer to a UINT32 that holds the last attempt + status to report back to the ESRT table in case + of error. + + The return status code must fall in the range of + LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE to + LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE. + + If the value falls outside this range, it will be converted + to LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL. + + @retval EFI_SUCCESS The image was successfully checked. Additional + status information is returned in + ImageUpdatable. + @retval EFI_INVALID_PARAMETER Image is NULL. + @retval EFI_INVALID_PARAMETER ImageUpdatable is NULL. +**/ +EFI_STATUS +EFIAPI +FmpDeviceCheckImageWithStatus ( + IN CONST VOID *Image, + IN UINTN ImageSize, + OUT UINT32 *ImageUpdatable, + OUT UINT32 *LastAttemptStatus + ) +{ + EFI_STATUS Status; + UINTN FwSize; + UINTN BlockSize; + + if (Image == NULL || ImageUpdatable == NULL) { + return EFI_INVALID_PARAMETER; + } + + *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL; + *ImageUpdatable = IMAGE_UPDATABLE_INVALID; + + Status = FmpDeviceGetSize (&FwSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a(): FmpDeviceGetSize() failed with: %r\n", + __FUNCTION__, Status)); + return Status; + } + + if (ImageSize != FwSize) { + DEBUG ((DEBUG_ERROR, "%a(): image size (0x%x) doesn't match firmware size (0x%x)\n", + __FUNCTION__, ImageSize, FwSize)); + return EFI_ABORTED; + } + + Status = SmmStoreLibGetBlockSize (&BlockSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a(): SmmStoreLibGetBlockSize() failed with: %r\n", + __FUNCTION__, Status)); + return Status; + } + + if (FwSize % BlockSize != 0) { + DEBUG ((DEBUG_ERROR, "%a(): firmware size (0x%x) is not a multiple of block size (0x%x)\n", + __FUNCTION__, FwSize, BlockSize)); + return EFI_ABORTED; + } + + *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS; + *ImageUpdatable = IMAGE_UPDATABLE_VALID; + return EFI_SUCCESS; +} + +/** + Updates a firmware device with a 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 that the image is a supported image for this firmware device. + Return EFI_ABORTED if the image is not supported. Additional details + on why the image is not a supported image may be returned in AbortReason. + - Validate the data from VendorCode if is not NULL. Firmware image + validation must be performed before VendorCode data validation. + VendorCode data is ignored or considered invalid if image validation + fails. Return EFI_ABORTED if the VendorCode 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] Image Points to the new firmware image. + @param[in] ImageSize Size, in bytes, of the new firmware image. + @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 to report the progress of + updating the firmware device with the new + firmware image. + @param[in] CapsuleFwVersion The version of the new firmware image from the + update capsule that provided the new firmware + image. + @param[out] AbortReason A pointer to a pointer to a Null-terminated + Unicode string providing more details on an + aborted operation. The buffer is allocated by + this function with + EFI_BOOT_SERVICES.AllocatePool(). It is the + caller's responsibility to free this buffer with + EFI_BOOT_SERVICES.FreePool(). + + @retval EFI_SUCCESS The firmware device was successfully updated + with the new firmware image. + @retval EFI_ABORTED The operation is aborted. Additional details + are provided in AbortReason. + @retval EFI_INVALID_PARAMETER The Image was NULL. + @retval EFI_UNSUPPORTED The operation is not supported. +**/ +EFI_STATUS +EFIAPI +FmpDeviceSetImage ( + IN CONST VOID *Image, + IN UINTN ImageSize, + IN CONST VOID *VendorCode OPTIONAL, + IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress OPTIONAL, + IN UINT32 CapsuleFwVersion, + OUT CHAR16 **AbortReason + ) +{ + UINT32 LastAttemptStatus; + + return FmpDeviceSetImageWithStatus ( + Image, + ImageSize, + VendorCode, + Progress, + CapsuleFwVersion, + AbortReason, + &LastAttemptStatus + ); +} + +/** + Advances progress of the operation by a single step, converts the steps to + percents and invokes a callback if there is one. + + @param[in] Callback External callback for progress reporting + or NULL if there is none. + @param[in] TotalSteps Total number of flashing steps. + @param[in] By How many steps to advance. + @param[in, out] Step Current step number. + @param[in, out] ShouldReportProgress A flag indicating whether progress needs + to be reported. +**/ +STATIC +VOID +IncrementProgress ( + IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Callback OPTIONAL, + IN UINTN TotalSteps, + IN UINTN By, + IN OUT UINTN *Step, + IN OUT BOOLEAN *ShouldReportProgress + ) +{ + EFI_STATUS Status; + UINTN Progress; + + if (!*ShouldReportProgress) { + return; + } + + if (Callback == NULL) { + *ShouldReportProgress = FALSE; + return; + } + + *Step += By; + Progress = (*Step * 100) / TotalSteps; + + // + // Value of 0 means "progress reporting is not supported", so avoid using it. + // + if (Progress == 0) { + Progress = 1; + } + + Status = Callback (Progress); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "%a(): progress callback failed with: %r\n", + __FUNCTION__, Status)); + *ShouldReportProgress = FALSE; + } +} + +/** + This code finds variable in storage blocks (Volatile or Non-Volatile). + + @param[in] VariableName Name of Variable to be found. + @param[in] VendorGuid Variable vendor GUID. + @param[out] Attributes Attribute value of the variable found. + @param[in, out] DataSize Size of Data found. If size is less than the + data, this value contains the required size. + @param[out] Data Data pointer. + + @return EFI_INVALID_PARAMETER Invalid parameter. + @return EFI_SUCCESS Find the specified variable. + @return EFI_NOT_FOUND Not found. + @return EFI_BUFFER_TO_SMALL DataSize is too small for the result. +**/ +STATIC +EFI_STATUS +EFIAPI +GetVariableHook ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, + OUT VOID *Data + ) +{ + DEBUG ((DEBUG_INFO, "%a(): %g:%S\n", + __FUNCTION__, VendorGuid, VariableName)); + return EFI_NOT_AVAILABLE_YET; +} + +/** + This code Finds the Next available variable. + + @param[in, out] VariableNameSize Size of the variable name. + @param[in, out] VariableName Pointer to variable name. + @param[in, out] VendorGuid Variable Vendor Guid. + + @return EFI_INVALID_PARAMETER Invalid parameter. + @return EFI_SUCCESS Find the specified variable. + @return EFI_NOT_FOUND Not found. + @return EFI_BUFFER_TO_SMALL DataSize is too small for the result. +**/ +STATIC +EFI_STATUS +EFIAPI +GetNextVariableNameHook ( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VendorGuid + ) +{ + DEBUG ((DEBUG_INFO, "%a(): %g:%S\n", + __FUNCTION__, VendorGuid, VariableName)); + return EFI_NOT_AVAILABLE_YET; +} + +/** + This code sets variable in storage blocks (Volatile or Non-Volatile). + + @param[in] VariableName Name of Variable to be found. + @param[in] VendorGuid Variable vendor GUID. + @param[in] Attributes Attribute value of the variable found + @param[in] DataSize Size of Data found. If size is less than the + data, this value contains the required size. + @param[in] Data Data pointer. + + @return EFI_INVALID_PARAMETER Invalid parameter. + @return EFI_SUCCESS Set successfully. + @return EFI_OUT_OF_RESOURCES Resource not enough to set variable. + @return EFI_NOT_FOUND Not found. + @return EFI_WRITE_PROTECTED Variable is read-only. +**/ +STATIC +EFI_STATUS +EFIAPI +SetVariableHook ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data + ) +{ + DEBUG ((DEBUG_INFO, "%a(): %g:%S, 0x%x bytes, 0x%x\n", + __FUNCTION__, VendorGuid, VariableName, DataSize, Attributes)); + return EFI_NOT_AVAILABLE_YET; +} + +/** + This code 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 Pointer to the maximum size of the storage space available + for the EFI variables associated with the attributes specified. + @param[out] RemainingVariableStorageSize Pointer to the remaining size of the storage space available + for EFI variables associated with the attributes specified. + @param[out] MaximumVariableSize Pointer to the maximum size of an individual EFI variables + associated with the attributes specified. + + @return EFI_SUCCESS Query successfully. +**/ +STATIC +EFI_STATUS +EFIAPI +QueryVariableInfoHook ( + IN UINT32 Attributes, + OUT UINT64 *MaximumVariableStorageSize, + OUT UINT64 *RemainingVariableStorageSize, + OUT UINT64 *MaximumVariableSize + ) +{ + DEBUG ((DEBUG_INFO, "%a(): 0x%x\n", __FUNCTION__, Attributes)); + return EFI_NOT_AVAILABLE_YET; +} + +/** + Updates a firmware device with a 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 that the image is a supported image for this firmware device. + Return EFI_ABORTED if the image is not supported. Additional details + on why the image is not a supported image may be returned in AbortReason. + - Validate the data from VendorCode if is not NULL. Firmware image + validation must be performed before VendorCode data validation. + VendorCode data is ignored or considered invalid if image validation + fails. Return EFI_ABORTED if the VendorCode 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] Image Points to the new firmware image. + @param[in] ImageSize Size, in bytes, of the new firmware image. + @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 to report the progress of + updating the firmware device with the new + firmware image. + @param[in] CapsuleFwVersion The version of the new firmware image from the + update capsule that provided the new firmware + image. + @param[out] AbortReason A pointer to a pointer to a Null-terminated + Unicode string providing more details on an + aborted operation. The buffer is allocated by + this function with + EFI_BOOT_SERVICES.AllocatePool(). It is the + caller's responsibility to free this buffer with + EFI_BOOT_SERVICES.FreePool(). + @param[out] LastAttemptStatus A pointer to a UINT32 that holds the last attempt + status to report back to the ESRT table in case + of error. This value will only be checked when this + function returns an error. + + The return status code must fall in the range of + LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE to + LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE. + + If the value falls outside this range, it will be converted + to LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL. + + @retval EFI_SUCCESS The firmware device was successfully updated + with the new firmware image. + @retval EFI_ABORTED The operation is aborted. Additional details + are provided in AbortReason. + @retval EFI_INVALID_PARAMETER The Image was NULL. + @retval EFI_UNSUPPORTED The operation is not supported. +**/ +EFI_STATUS +EFIAPI +FmpDeviceSetImageWithStatus ( + IN CONST VOID *Image, + IN UINTN ImageSize, + IN CONST VOID *VendorCode OPTIONAL, + IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress OPTIONAL, + IN UINT32 CapsuleFwVersion, + OUT CHAR16 **AbortReason, + OUT UINT32 *LastAttemptStatus + ) +{ + EFI_STATUS Status; + UINTN BlockSize; + UINTN BlockCount; + UINTN Block; + UINTN NumBytes; + UINTN TotalSteps; + UINTN ReadSteps; + UINTN Step; + BOOLEAN ShouldReportProgress; + UINT8 *CurrentImage; + UINT8 *UpdatedImage; + UINTN Offset; + + *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL; + + // + // FmpDeviceCheckImageWithStatus() has already validated the image, so not + // repeating the checks. However, could move the checks here to be able to + // report abort reason which can't be done in FmpDeviceCheckImageWithStatus(). + // + + Status = SmmStoreLibGetBlockSize (&BlockSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a(): SmmStoreLibGetBlockSize() failed with: %r\n", + __FUNCTION__, Status)); + return Status; + } + + BlockCount = ImageSize / BlockSize; + DEBUG ((DEBUG_INFO, "%a(): 0x%x blocks of 0x%x bytes\n", + __FUNCTION__, BlockCount, BlockSize)); + + ShouldReportProgress = TRUE; + TotalSteps = BlockCount * 2; // Erase and write of each block. + Step = 0; + + // Allocate 5% of progress for reading the flash. + ReadSteps = (TotalSteps * 5) / 100; + TotalSteps += ReadSteps; + + CurrentImage = ReadCurrentFirmware (); + if (CurrentImage == NULL) { + DEBUG (( + DEBUG_ERROR, + "%a(): failed to read current firmware\n", + __FUNCTION__ + )); + return EFI_OUT_OF_RESOURCES; + } + + IncrementProgress (Progress, TotalSteps, ReadSteps, &Step, &ShouldReportProgress); + + UpdatedImage = MergeFirmwareImages (CurrentImage, Image); + if (UpdatedImage == NULL) { + FreePool (CurrentImage); + DEBUG (( + DEBUG_ERROR, + "%a(): failed to migrate data into new firmware image\n", + __FUNCTION__ + )); + return EFI_ABORTED; + } + + Offset = 0; + for (Block = 0; Block < BlockCount; Block++, Offset += BlockSize) { + // + // Save the flash and time by only writing a block if new contents differs + // from the old one. + // + if (CompareMem (CurrentImage + Offset, UpdatedImage + Offset, BlockSize) == 0) { + // Erase and write steps. + IncrementProgress (Progress, TotalSteps, 2, &Step, &ShouldReportProgress); + continue; + } + + Status = SmmStoreLibEraseAnyBlock (Block); + if (EFI_ERROR (Status)) + goto IoError; + + IncrementProgress (Progress, TotalSteps, 1, &Step, &ShouldReportProgress); + + NumBytes = BlockSize; + Status = SmmStoreLibWriteAnyBlock (Block, 0, &NumBytes, UpdatedImage + Offset); + if (EFI_ERROR (Status) || NumBytes != BlockSize) + goto IoError; + + IncrementProgress (Progress, TotalSteps, 1, &Step, &ShouldReportProgress); + } + + FreePool (CurrentImage); + FreePool (UpdatedImage); + + *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS; + + // + // After the firmware on system flash was successfully updated working with + // variable store on the flash isn't safe. Switch to the use of stubs which + // do nothing. + // + // New firmware will not report result of flashing in any way unless some + // kind of communication mechanism is implemented for this purpose. + // + // If there was an error, it's unclear whether these stubs would be of any + // help, so they are employed only on successful flashing. + // + + gRT->GetVariable = GetVariableHook; + gRT->GetNextVariableName = GetNextVariableNameHook; + gRT->SetVariable = SetVariableHook; + gRT->QueryVariableInfo = QueryVariableInfoHook; + + gRT->Hdr.CRC32 = 0; + gBS->CalculateCrc32 ( + (UINT8 *) &gRT->Hdr, + gRT->Hdr.HeaderSize, + &gRT->Hdr.CRC32 + ); + + return EFI_SUCCESS; + +IoError: + // + // Would be nice to warn the user about potential brick state or maybe attempt + // a recovery. Doesn't seem that the calling code will do any of it. + // + FreePool (CurrentImage); + FreePool (UpdatedImage); + DEBUG ((DEBUG_ERROR, "%a(): flashing has failed at block 0x%x/0x%x: %r\n", + __FUNCTION__, Block, BlockCount, EFI_DEVICE_ERROR)); + return EFI_DEVICE_ERROR; +} + +/** + Lock the firmware device that contains a firmware image. Once a firmware + device is locked, any attempts to modify the firmware image contents in the + firmware device must fail. + + @note It is recommended that all firmware devices support a lock method to + prevent modifications to a stored firmware image. + + @note A firmware device lock mechanism is typically only cleared by a full + system reset (not just sleep state/low power mode). + + @retval EFI_SUCCESS The firmware device was locked. + @retval EFI_UNSUPPORTED The firmware device does not support locking +**/ +EFI_STATUS +EFIAPI +FmpDeviceLock ( + VOID + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Constructor that performs required initialization. + + @param ImageHandle The image handle of the process. + @param SystemTable The EFI System Table pointer. + + @retval EFI_SUCCESS Initialization was successful. +**/ +EFI_STATUS +EFIAPI +FmpDeviceSmmLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + SmmStoreLibInitialize (); + return EFI_SUCCESS; +} diff --git a/DasharoPayloadPkg/Library/FmpDeviceSmmLib/FmpDeviceSmmLib.inf b/DasharoPayloadPkg/Library/FmpDeviceSmmLib/FmpDeviceSmmLib.inf new file mode 100644 index 0000000000..bd2dc9d0b7 --- /dev/null +++ b/DasharoPayloadPkg/Library/FmpDeviceSmmLib/FmpDeviceSmmLib.inf @@ -0,0 +1,49 @@ +## @file +# Provides firmware device specific services to support updates of a firmware +# image stored in a firmware device. +# +# Copyright (c) 2016, Microsoft Corporation. All rights reserved.
+# Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.
+# Copyright (c) 2024, 3mdeb Sp. z o.o. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = FmpDeviceSmmLib + MODULE_UNI_FILE = FmpDeviceSmmLib.uni + FILE_GUID = 979CF0F8-7214-4D12-89CE-F32112ED71C6 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = FmpDeviceLib|DXE_DRIVER UEFI_DRIVER + CONSTRUCTOR = FmpDeviceSmmLibConstructor + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 +# + +[Sources] + Flashing.c + FmpDeviceSmmLib.c + +[LibraryClasses] + BaseMemoryLib + BlParseLib + CbfsLib + DebugLib + EfiVarsLib + FmapLib + MemoryAllocationLib + PrintLib + SmmStoreLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + +[Packages] + DasharoPayloadPkg/DasharoPayloadPkg.dec + FmpDevicePkg/FmpDevicePkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec diff --git a/DasharoPayloadPkg/Library/FmpDeviceSmmLib/FmpDeviceSmmLib.uni b/DasharoPayloadPkg/Library/FmpDeviceSmmLib/FmpDeviceSmmLib.uni new file mode 100644 index 0000000000..37efb8c9ec --- /dev/null +++ b/DasharoPayloadPkg/Library/FmpDeviceSmmLib/FmpDeviceSmmLib.uni @@ -0,0 +1,13 @@ +// /** @file +// Provides firmware device specific services to support updates of a firmware +// image stored in a firmware device. +// +// Copyright (c) 2018, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + +#string STR_MODULE_ABSTRACT #language en-US "Provides firmware device specific services to support updates of a firmware image stored in a firmware device." + +#string STR_MODULE_DESCRIPTION #language en-US "Provides firmware device specific services to support updates of a firmware image stored in a firmware device." diff --git a/DasharoPayloadPkg/Library/LaptopBatteryLib/LaptopBatteryLib.c b/DasharoPayloadPkg/Library/LaptopBatteryLib/LaptopBatteryLib.c new file mode 100644 index 0000000000..7beafde4a0 --- /dev/null +++ b/DasharoPayloadPkg/Library/LaptopBatteryLib/LaptopBatteryLib.c @@ -0,0 +1,308 @@ +/** @file + Library that query laptop EC for AC state and battery capacity. + +Copyright (c) 2023, 3mdeb. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#define EC_POLL_DELAY_US 10 +#define EC_SEND_TIMEOUT_US 20000 // 20ms +#define EC_RECV_TIMEOUT_US 320000 // 320ms + +#define EC_SC 0x66 +#define EC_DATA 0x62 + +#define EC_CMD (1 << 3) +#define EC_IBF (1 << 1) +#define EC_OBF (1 << 0) + +#define RD_EC 0x80 + +#define CHARGER_STATE_REG 0x10 +#define AC_STATE (1 << 0) +#define BAT_STATE (1 << 2) +#define BAT_FULL_CAP_REG 0x1a +#define BAT_REMAIN_CAP_REG 0x2e + +RETURN_STATUS +EcScWait ( + UINTN TimeoutUs, + UINT8 Mask, + UINT8 State + ) +{ + while (TimeoutUs > 0 && (IoRead8(EC_SC) & Mask) != State) { + MicroSecondDelay(EC_POLL_DELAY_US); + TimeoutUs -= EC_POLL_DELAY_US; + } + + return TimeoutUs > 0 ? RETURN_SUCCESS : RETURN_TIMEOUT; +} + +RETURN_STATUS +EcReadySend ( + UINTN TimeoutUs + ) +{ + return EcScWait(TimeoutUs, EC_IBF, 0); +} + +RETURN_STATUS +EcReadyRecv ( + UINTN TimeoutUs + ) +{ + return EcScWait(TimeoutUs, EC_OBF, EC_OBF); +} + +RETURN_STATUS +EcRecvDataTimeout ( + UINT8 *Data, + UINTN TimeoutUs + ) +{ + EFI_STATUS Status; + + if (!Data) + return RETURN_INVALID_PARAMETER; + + Status = EcReadyRecv(TimeoutUs); + + if (Status != RETURN_SUCCESS) + return Status; + + *Data = IoRead8(EC_DATA); + + return RETURN_SUCCESS; +} + +RETURN_STATUS +EcSendDataTimeout ( + UINT8 Data, + UINTN TimeoutUs + ) +{ + EFI_STATUS Status; + + Status = EcReadySend(TimeoutUs); + + if (Status != RETURN_SUCCESS) + return Status; + + IoWrite8(EC_DATA, Data); + + return RETURN_SUCCESS; +} + +RETURN_STATUS +EcSendCmdTimeout ( + UINT8 Cmd, + UINTN TimeoutUs + ) +{ + EFI_STATUS Status; + + if (!Cmd) + return RETURN_INVALID_PARAMETER; + + Status = EcReadySend(TimeoutUs); + + if (Status != RETURN_SUCCESS) + return Status; + + IoWrite8(EC_SC, Cmd); + + return RETURN_SUCCESS; +} + +RETURN_STATUS +EcSendCmd ( + UINT8 Cmd + ) +{ + return EcSendCmdTimeout(Cmd, EC_SEND_TIMEOUT_US); +} + +RETURN_STATUS +EcSendData ( + UINT8 Data + ) +{ + return EcSendDataTimeout(Data, EC_SEND_TIMEOUT_US); +} + +RETURN_STATUS +EcRecvData ( + UINT8 *Data + ) +{ + return EcRecvDataTimeout(Data, EC_RECV_TIMEOUT_US); +} + +RETURN_STATUS +EcReadReg ( + UINT8 Reg, + UINT8 *Data + ) +{ + EFI_STATUS Status; + + Status = EcSendCmd(RD_EC); + + if (Status != RETURN_SUCCESS) { + DEBUG ((DEBUG_ERROR, "Failed to send read EC command for reg %02x: %r\n", Reg, Status)); + return Status; + } + + Status = EcSendData(Reg); + + if (Status != RETURN_SUCCESS) { + DEBUG ((DEBUG_ERROR, "Failed to send read EC address %02x: %r\n", Reg, Status)); + return Status; + } + + return EcRecvData(Data); +} + +RETURN_STATUS +EcReadReg32 ( + UINT8 Reg, + UINT32 *Data32 + ) +{ + RETURN_STATUS Status; + UINT8 Data8[4]; + UINTN Index; + + if (!Data32) + return RETURN_INVALID_PARAMETER; + + *Data32 = 0; + + for (Index = 0; Index < 4; Index++) { + Status = EcReadReg(Reg + Index, &Data8[Index]); + + if (Status != RETURN_SUCCESS) + return Status; + + *Data32 |= (UINT32)Data8[Index] << (8 * Index); + } + + return RETURN_SUCCESS; +} + +/** + This function retrieves the AC adapter connection state from EC. + + @param AcState Pointer to the AC state + + @retval RETURN_SUCCESS Successfully probed the battery capacity. + @retval RETURN_UNSUPPORTED Function is unsupported. + @retval RETURN_TIMEOUT EC cpommunication timeout. + @retval RETURN_INVALID_PARAMETER NULL pointer passed as parameter + +**/ +RETURN_STATUS +EFIAPI +LaptopGetAcState ( + BOOLEAN *AcState + ) +{ + EFI_STATUS Status; + UINT8 ChargerState; + + Status = EcReadReg(CHARGER_STATE_REG, &ChargerState); + + if (Status != RETURN_SUCCESS) { + DEBUG ((DEBUG_ERROR, "Failed to read AC adapter state: %r\n", Status)); + return Status; + } + + *AcState = (ChargerState & AC_STATE) ? TRUE : FALSE; + + DEBUG ((DEBUG_INFO, "AC adapter %aconnected\n", *AcState ? "" : "dis")); + + return RETURN_SUCCESS; +} + +/** + This function retrieves the battery connection state from EC. + + @param AcState Pointer to the AC state + + @retval RETURN_SUCCESS Successfully probed the battery connection state. + @retval RETURN_UNSUPPORTED Function is unsupported. + @retval RETURN_TIMEOUT EC cpommunication timeout. + @retval RETURN_INVALID_PARAMETER NULL pointer passed as parameter + +**/ +RETURN_STATUS +EFIAPI +LaptopGetBatState ( + BOOLEAN *BatState + ) +{ + EFI_STATUS Status; + UINT8 ChargerState; + + Status = EcReadReg(CHARGER_STATE_REG, &ChargerState); + + if (Status != RETURN_SUCCESS) { + DEBUG ((DEBUG_ERROR, "Failed to read battery connection state: %r\n", Status)); + return Status; + } + + *BatState = (ChargerState & BAT_STATE) ? TRUE : FALSE; + + DEBUG ((DEBUG_INFO, "Battery %aconnected\n", *BatState ? "" : "dis")); + + return RETURN_SUCCESS; +} + +/** + This function retrieves the current battery capacity from EC. + + @param BatteryCapacity Pointer to the battery capacity in percent + + @retval RETURN_SUCCESS Successfully probed the battery capacity. + @retval RETURN_UNSUPPORTED Function is unsupported. + @retval RETURN_TIMEOUT EC cpommunication timeout. + @retval RETURN_INVALID_PARAMETER NULL pointer passed as parameter + +**/ +RETURN_STATUS +EFIAPI +LaptopGetBatteryCapacity ( + UINT32 *BatteryCapacity + ) +{ + EFI_STATUS Status; + UINT32 LastFullChargeCap; + UINT32 RemainingCap; + + Status = EcReadReg32(BAT_FULL_CAP_REG, &LastFullChargeCap); + + if (Status != RETURN_SUCCESS) { + DEBUG ((DEBUG_ERROR, "Failed to read battery last full charge capacity: %r\n", Status)); + return Status; + } + + Status = EcReadReg32(BAT_REMAIN_CAP_REG, &RemainingCap); + + if (Status != RETURN_SUCCESS) { + DEBUG ((DEBUG_ERROR, "Failed to read battery remaining capacity: %r\n", Status)); + return Status; + } + + *BatteryCapacity = RemainingCap * 100 / LastFullChargeCap; + + if (*BatteryCapacity > 100) + DEBUG ((DEBUG_WARN, "Battery capacity over 100%%: %d%%\n", *BatteryCapacity)); + else + DEBUG ((DEBUG_INFO, "Battery capacity: %d%%\n", *BatteryCapacity)); + + return RETURN_SUCCESS; +} diff --git a/DasharoPayloadPkg/Library/LaptopBatteryLib/LaptopBatteryLib.inf b/DasharoPayloadPkg/Library/LaptopBatteryLib/LaptopBatteryLib.inf new file mode 100644 index 0000000000..cd6a6ae619 --- /dev/null +++ b/DasharoPayloadPkg/Library/LaptopBatteryLib/LaptopBatteryLib.inf @@ -0,0 +1,33 @@ +## @file +# Include all platform specific features which can be customized by IBV/OEM. +# +# Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = LaptopBatteryLib + FILE_GUID = 5D0D7B0F-E2BB-499A-B658-18B93068BC22 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = LaptopBatteryLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + LaptopBatteryLib.c + +[Packages] + MdePkg/MdePkg.dec + DasharoPayloadPkg/DasharoPayloadPkg.dec + +[LibraryClasses] + IoLib + TimerLib + DebugLib diff --git a/DasharoPayloadPkg/Library/LaptopBatteryLib/LaptopBatteryLibNull.c b/DasharoPayloadPkg/Library/LaptopBatteryLib/LaptopBatteryLibNull.c new file mode 100644 index 0000000000..268bdbbd56 --- /dev/null +++ b/DasharoPayloadPkg/Library/LaptopBatteryLib/LaptopBatteryLibNull.c @@ -0,0 +1,69 @@ +/** @file + Library that query laptop EC for AC state and battery capacity. + +Copyright (c) 2023, 3mdeb. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +/** + This function retrieves the AC adapter connection state from EC. + + @param AcState Pointer to the AC state + + @retval RETURN_SUCCESS Successfully probed the battery capacity. + @retval RETURN_UNSUPPORTED Function is unsupported. + @retval RETURN_TIMEOUT EC cpommunication timeout. + @retval RETURN_INVALID_PARAMETER NULL pointer passed as parameter + +**/ +RETURN_STATUS +EFIAPI +LaptopGetAcState ( + BOOLEAN *AcState + ) +{ + return RETURN_UNSUPPORTED; +} + +/** + This function retrieves the battery connection state from EC. + + @param AcState Pointer to the AC state + + @retval RETURN_SUCCESS Successfully probed the battery connection state. + @retval RETURN_UNSUPPORTED Function is unsupported. + @retval RETURN_TIMEOUT EC cpommunication timeout. + @retval RETURN_INVALID_PARAMETER NULL pointer passed as parameter + +**/ +RETURN_STATUS +EFIAPI +LaptopGetBatState ( + BOOLEAN *BatState + ) +{ + return RETURN_UNSUPPORTED; +} + +/** + This function retrieves the current battery capacity from EC. + + @param BatteryCapacity Pointer to the battery capacity in percent + + @retval RETURN_SUCCESS Successfully probed the battery capacity. + @retval RETURN_UNSUPPORTED Function is unsupported. + @retval RETURN_TIMEOUT EC cpommunication timeout. + @retval RETURN_INVALID_PARAMETER NULL pointer passed as parameter + +**/ +RETURN_STATUS +EFIAPI +LaptopGetBatteryCapacity ( + UINT32 *BatteryCapacity + ) +{ + return RETURN_UNSUPPORTED; +} diff --git a/DasharoPayloadPkg/Library/LaptopBatteryLib/LaptopBatteryLibNull.inf b/DasharoPayloadPkg/Library/LaptopBatteryLib/LaptopBatteryLibNull.inf new file mode 100644 index 0000000000..fbe651994d --- /dev/null +++ b/DasharoPayloadPkg/Library/LaptopBatteryLib/LaptopBatteryLibNull.inf @@ -0,0 +1,28 @@ +## @file +# Include all platform specific features which can be customized by IBV/OEM. +# +# Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = LaptopBatteryLib + FILE_GUID = 5D0D7B0F-E2BB-499A-B658-18B93068BC22 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = LaptopBatteryLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + LaptopBatteryLibNull.c + +[Packages] + MdePkg/MdePkg.dec + DasharoPayloadPkg/DasharoPayloadPkg.dec diff --git a/DasharoPayloadPkg/Library/LaptopLidLib/LaptopLidLib.c b/DasharoPayloadPkg/Library/LaptopLidLib/LaptopLidLib.c new file mode 100644 index 0000000000..7e08f93f47 --- /dev/null +++ b/DasharoPayloadPkg/Library/LaptopLidLib/LaptopLidLib.c @@ -0,0 +1,228 @@ +/** @file + Library that query laptop EC for lid state. + +Copyright (c) 2024, 3mdeb. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#define EC_POLL_DELAY_US 10 +#define EC_SEND_TIMEOUT_US 20000 // 20ms +#define EC_RECV_TIMEOUT_US 320000 // 320ms + +#define EC_SC 0x66 +#define EC_DATA 0x62 + +#define EC_CMD (1 << 3) +#define EC_IBF (1 << 1) +#define EC_OBF (1 << 0) + +#define RD_EC 0x80 + +#define LID_STATE_REG 0x3 +#define LID_STATE (1 << 0) + + +RETURN_STATUS +EcScWait ( + UINTN TimeoutUs, + UINT8 Mask, + UINT8 State + ) +{ + while (TimeoutUs > 0 && (IoRead8(EC_SC) & Mask) != State) { + MicroSecondDelay(EC_POLL_DELAY_US); + TimeoutUs -= EC_POLL_DELAY_US; + } + + return TimeoutUs > 0 ? RETURN_SUCCESS : RETURN_TIMEOUT; +} + +RETURN_STATUS +EcReadySend ( + UINTN TimeoutUs + ) +{ + return EcScWait(TimeoutUs, EC_IBF, 0); +} + +RETURN_STATUS +EcReadyRecv ( + UINTN TimeoutUs + ) +{ + return EcScWait(TimeoutUs, EC_OBF, EC_OBF); +} + +RETURN_STATUS +EcRecvDataTimeout ( + UINT8 *Data, + UINTN TimeoutUs + ) +{ + EFI_STATUS Status; + + if (!Data) + return RETURN_INVALID_PARAMETER; + + Status = EcReadyRecv(TimeoutUs); + + if (Status != RETURN_SUCCESS) + return Status; + + *Data = IoRead8(EC_DATA); + + return RETURN_SUCCESS; +} + +RETURN_STATUS +EcSendDataTimeout ( + UINT8 Data, + UINTN TimeoutUs + ) +{ + EFI_STATUS Status; + + Status = EcReadySend(TimeoutUs); + + if (Status != RETURN_SUCCESS) + return Status; + + IoWrite8(EC_DATA, Data); + + return RETURN_SUCCESS; +} + +RETURN_STATUS +EcSendCmdTimeout ( + UINT8 Cmd, + UINTN TimeoutUs + ) +{ + EFI_STATUS Status; + + if (!Cmd) + return RETURN_INVALID_PARAMETER; + + Status = EcReadySend(TimeoutUs); + + if (Status != RETURN_SUCCESS) + return Status; + + IoWrite8(EC_SC, Cmd); + + return RETURN_SUCCESS; +} + +RETURN_STATUS +EcSendCmd ( + UINT8 Cmd + ) +{ + return EcSendCmdTimeout(Cmd, EC_SEND_TIMEOUT_US); +} + +RETURN_STATUS +EcSendData ( + UINT8 Data + ) +{ + return EcSendDataTimeout(Data, EC_SEND_TIMEOUT_US); +} + +RETURN_STATUS +EcRecvData ( + UINT8 *Data + ) +{ + return EcRecvDataTimeout(Data, EC_RECV_TIMEOUT_US); +} + +RETURN_STATUS +EcReadReg ( + UINT8 Reg, + UINT8 *Data + ) +{ + EFI_STATUS Status; + + Status = EcSendCmd(RD_EC); + + if (Status != RETURN_SUCCESS) { + DEBUG ((DEBUG_ERROR, "Failed to send read EC command for reg %02x: %r\n", Reg, Status)); + return Status; + } + + Status = EcSendData(Reg); + + if (Status != RETURN_SUCCESS) { + DEBUG ((DEBUG_ERROR, "Failed to send read EC address %02x: %r\n", Reg, Status)); + return Status; + } + + return EcRecvData(Data); +} + +RETURN_STATUS +EcReadReg32 ( + UINT8 Reg, + UINT32 *Data32 + ) +{ + RETURN_STATUS Status; + UINT8 Data8[4]; + UINTN Index; + + if (!Data32) + return RETURN_INVALID_PARAMETER; + + *Data32 = 0; + + for (Index = 0; Index < 4; Index++) { + Status = EcReadReg(Reg + Index, &Data8[Index]); + + if (Status != RETURN_SUCCESS) + return Status; + + *Data32 |= (UINT32)Data8[Index] << (8 * Index); + } + + return RETURN_SUCCESS; +} + +/** + This function retrieves the lid state from EC. + + @param LidState Pointer to the lid state + + @retval RETURN_SUCCESS Successfully probed the lid state. + @retval RETURN_UNSUPPORTED Function is unsupported. + @retval RETURN_TIMEOUT EC communication timeout. + @retval RETURN_INVALID_PARAMETER NULL pointer passed as parameter + +**/ +EFI_STATUS +EFIAPI +LaptopGetLidState ( + LID_STATUS *LidState + ) +{ + EFI_STATUS Status; + UINT8 Reg; + + Status = EcReadReg(LID_STATE_REG, &Reg); + + if (Status != RETURN_SUCCESS) { + DEBUG ((DEBUG_ERROR, "Failed to read lid state: %r\n", Status)); + return Status; + } + + *LidState = (Reg & LID_STATE) ? LidOpen : LidClosed; + + DEBUG ((DEBUG_INFO, "Lid %a\n", *LidState ? "open" : "closed")); + + return RETURN_SUCCESS; +} + diff --git a/DasharoPayloadPkg/Library/LaptopLidLib/LaptopLidLib.inf b/DasharoPayloadPkg/Library/LaptopLidLib/LaptopLidLib.inf new file mode 100644 index 0000000000..2162428005 --- /dev/null +++ b/DasharoPayloadPkg/Library/LaptopLidLib/LaptopLidLib.inf @@ -0,0 +1,33 @@ +## @file +# Library that query laptop EC for lid state. +# +# Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = LaptopLidLib + FILE_GUID = F0E7259F-8EAE-4CED-82E8-F0971660A644 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = LaptopLidLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + LaptopLidLib.c + +[Packages] + MdePkg/MdePkg.dec + DasharoPayloadPkg/DasharoPayloadPkg.dec + +[LibraryClasses] + IoLib + TimerLib + DebugLib diff --git a/DasharoPayloadPkg/Library/LaptopLidLib/LaptopLidLibNull.c b/DasharoPayloadPkg/Library/LaptopLidLib/LaptopLidLibNull.c new file mode 100644 index 0000000000..2be773605d --- /dev/null +++ b/DasharoPayloadPkg/Library/LaptopLidLib/LaptopLidLibNull.c @@ -0,0 +1,30 @@ +/** @file + Library that query laptop EC for lid state. + +Copyright (c) 2024, 3mdeb. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +/** + This function retrieves the lid state from EC. + + @param LidState Pointer to the lid state + + @retval RETURN_SUCCESS Successfully probed the lid state. + @retval RETURN_UNSUPPORTED Function is unsupported. + @retval RETURN_TIMEOUT EC communication timeout. + @retval RETURN_INVALID_PARAMETER NULL pointer passed as parameter + +**/ +EFI_STATUS +EFIAPI +LaptopGetLidState ( + LID_STATUS *LidState + ) +{ + *LidState = LidOpen; + return EFI_SUCCESS; +} diff --git a/DasharoPayloadPkg/Library/LaptopLidLib/LaptopLidLibNull.inf b/DasharoPayloadPkg/Library/LaptopLidLib/LaptopLidLibNull.inf new file mode 100644 index 0000000000..da267d4141 --- /dev/null +++ b/DasharoPayloadPkg/Library/LaptopLidLib/LaptopLidLibNull.inf @@ -0,0 +1,28 @@ +## @file +# Include all platform specific features which can be customized by IBV/OEM. +# +# Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = LaptopLidLib + FILE_GUID = F0E7259F-8EAE-4CED-82E8-F0971660A644 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = LaptopLidLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + LaptopLidLibNull.c + +[Packages] + MdePkg/MdePkg.dec + DasharoPayloadPkg/DasharoPayloadPkg.dec diff --git a/DasharoPayloadPkg/Library/PciHostBridgeLib/PciHostBridge.h b/DasharoPayloadPkg/Library/PciHostBridgeLib/PciHostBridge.h new file mode 100644 index 0000000000..c2961b3bee --- /dev/null +++ b/DasharoPayloadPkg/Library/PciHostBridgeLib/PciHostBridge.h @@ -0,0 +1,80 @@ +/** @file + Header file of PciHostBridgeLib. + + Copyright (C) 2016, Red Hat, Inc. + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _PCI_HOST_BRIDGE_H +#define _PCI_HOST_BRIDGE_H + +typedef struct { + ACPI_HID_DEVICE_PATH AcpiDevicePath; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} CB_PCI_ROOT_BRIDGE_DEVICE_PATH; + +PCI_ROOT_BRIDGE * +ScanForRootBridges ( + UINTN *NumberOfRootBridges +); + +/** + Initialize a PCI_ROOT_BRIDGE structure. + + @param[in] Supports Supported attributes. + + @param[in] Attributes Initial attributes. + + @param[in] AllocAttributes Allocation attributes. + + @param[in] RootBusNumber The bus number to store in RootBus. + + @param[in] MaxSubBusNumber The inclusive maximum bus number that can be + assigned to any subordinate bus found behind any + PCI bridge hanging off this root bus. + + The caller is responsible for ensuring that + RootBusNumber <= MaxSubBusNumber. If + RootBusNumber equals MaxSubBusNumber, then the + root bus has no room for subordinate buses. + + @param[in] Io IO aperture. + + @param[in] Mem MMIO aperture. + + @param[in] MemAbove4G MMIO aperture above 4G. + + @param[in] PMem Prefetchable MMIO aperture. + + @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G. + + @param[out] RootBus The PCI_ROOT_BRIDGE structure (allocated by the + caller) that should be filled in by this + function. + + @retval EFI_SUCCESS Initialization successful. A device path + consisting of an ACPI device path node, with + UID = RootBusNumber, has been allocated and + linked into RootBus. + + @retval EFI_OUT_OF_RESOURCES Memory allocation failed. +**/ +EFI_STATUS +InitRootBridge ( + IN UINT64 Supports, + IN UINT64 Attributes, + IN UINT64 AllocAttributes, + IN UINT8 RootBusNumber, + IN UINT8 MaxSubBusNumber, + IN PCI_ROOT_BRIDGE_APERTURE *Io, + IN PCI_ROOT_BRIDGE_APERTURE *Mem, + IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G, + IN PCI_ROOT_BRIDGE_APERTURE *PMem, + IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G, + OUT PCI_ROOT_BRIDGE *RootBus +); + +#endif diff --git a/DasharoPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c b/DasharoPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c new file mode 100644 index 0000000000..a6538aeafa --- /dev/null +++ b/DasharoPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c @@ -0,0 +1,249 @@ +/** @file + Library instance of PciHostBridgeLib library class for coreboot. + + Copyright (C) 2016, Red Hat, Inc. + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "PciHostBridge.h" + +STATIC +CONST +CB_PCI_ROOT_BRIDGE_DEVICE_PATH mRootBridgeDevicePathTemplate = { + { + { + ACPI_DEVICE_PATH, + ACPI_DP, + { + (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), + (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8) + } + }, + EISA_PNP_ID(0x0A03), // HID + 0 // UID + }, + + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } +}; + + +/** + Initialize a PCI_ROOT_BRIDGE structure. + + @param[in] Supports Supported attributes. + + @param[in] Attributes Initial attributes. + + @param[in] AllocAttributes Allocation attributes. + + @param[in] RootBusNumber The bus number to store in RootBus. + + @param[in] MaxSubBusNumber The inclusive maximum bus number that can be + assigned to any subordinate bus found behind any + PCI bridge hanging off this root bus. + + The caller is responsible for ensuring that + RootBusNumber <= MaxSubBusNumber. If + RootBusNumber equals MaxSubBusNumber, then the + root bus has no room for subordinate buses. + + @param[in] Io IO aperture. + + @param[in] Mem MMIO aperture. + + @param[in] MemAbove4G MMIO aperture above 4G. + + @param[in] PMem Prefetchable MMIO aperture. + + @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G. + + @param[out] RootBus The PCI_ROOT_BRIDGE structure (allocated by the + caller) that should be filled in by this + function. + + @retval EFI_SUCCESS Initialization successful. A device path + consisting of an ACPI device path node, with + UID = RootBusNumber, has been allocated and + linked into RootBus. + + @retval EFI_OUT_OF_RESOURCES Memory allocation failed. +**/ +EFI_STATUS +InitRootBridge ( + IN UINT64 Supports, + IN UINT64 Attributes, + IN UINT64 AllocAttributes, + IN UINT8 RootBusNumber, + IN UINT8 MaxSubBusNumber, + IN PCI_ROOT_BRIDGE_APERTURE *Io, + IN PCI_ROOT_BRIDGE_APERTURE *Mem, + IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G, + IN PCI_ROOT_BRIDGE_APERTURE *PMem, + IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G, + OUT PCI_ROOT_BRIDGE *RootBus +) +{ + CB_PCI_ROOT_BRIDGE_DEVICE_PATH *DevicePath; + + // + // Be safe if other fields are added to PCI_ROOT_BRIDGE later. + // + ZeroMem (RootBus, sizeof *RootBus); + + RootBus->Segment = 0; + + RootBus->Supports = Supports; + RootBus->Attributes = Attributes; + + RootBus->DmaAbove4G = FALSE; + + RootBus->AllocationAttributes = AllocAttributes; + RootBus->Bus.Base = RootBusNumber; + RootBus->Bus.Limit = MaxSubBusNumber; + CopyMem (&RootBus->Io, Io, sizeof (*Io)); + CopyMem (&RootBus->Mem, Mem, sizeof (*Mem)); + CopyMem (&RootBus->MemAbove4G, MemAbove4G, sizeof (*MemAbove4G)); + CopyMem (&RootBus->PMem, PMem, sizeof (*PMem)); + CopyMem (&RootBus->PMemAbove4G, PMemAbove4G, sizeof (*PMemAbove4G)); + + // + // Handle overlaps between Mem and PMem, Mem takes precedence + // + if (!(RootBus->Mem.Limit < RootBus->PMem.Base || + RootBus->Mem.Base > RootBus->PMem.Limit) + ) { + DEBUG ((DEBUG_INFO, "%a: PMem overlaps with Mem, trimming PMem\n", + __FUNCTION__)); + if (RootBus->Mem.Base <= RootBus->PMem.Base) { + RootBus->PMem.Base = RootBus->Mem.Limit + 1; + } else { + RootBus->PMem.Limit = RootBus->Mem.Base - 1; + } + } + if (!(RootBus->MemAbove4G.Limit < RootBus->PMemAbove4G.Base || + RootBus->MemAbove4G.Base > RootBus->PMemAbove4G.Limit) + ) { + DEBUG ((DEBUG_INFO, + "%a: PMemAbove4G overlaps with MemAbove4G, trimming PMemAbove4G\n", + __FUNCTION__)); + if (RootBus->MemAbove4G.Base <= RootBus->PMemAbove4G.Base) { + RootBus->PMemAbove4G.Base = RootBus->MemAbove4G.Limit + 1; + } else { + RootBus->PMemAbove4G.Limit = RootBus->MemAbove4G.Base - 1; + } + } + + RootBus->NoExtendedConfigSpace = FALSE; + + DevicePath = AllocateCopyPool (sizeof (mRootBridgeDevicePathTemplate), + &mRootBridgeDevicePathTemplate); + if (DevicePath == NULL) { + DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES)); + return EFI_OUT_OF_RESOURCES; + } + DevicePath->AcpiDevicePath.UID = RootBusNumber; + RootBus->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath; + + DEBUG ((DEBUG_INFO, + "%a: populated root bus %d, with room for %d subordinate bus(es)\n", + __FUNCTION__, RootBusNumber, MaxSubBusNumber - RootBusNumber)); + return EFI_SUCCESS; +} + + +/** + Return all the root bridge instances in an array. + + @param Count Return the count of root bridge instances. + + @return All the root bridge instances in an array. + The array should be passed into PciHostBridgeFreeRootBridges() + when it's not used. +**/ +PCI_ROOT_BRIDGE * +EFIAPI +PciHostBridgeGetRootBridges ( + UINTN *Count +) +{ + return ScanForRootBridges (Count); +} + + +/** + Free the root bridge instances array returned from + PciHostBridgeGetRootBridges(). + + @param The root bridge instances array. + @param The count of the array. +**/ +VOID +EFIAPI +PciHostBridgeFreeRootBridges ( + PCI_ROOT_BRIDGE *Bridges, + UINTN Count +) +{ + if (Bridges == NULL && Count == 0) { + return; + } + ASSERT (Bridges != NULL && Count > 0); + + do { + --Count; + FreePool (Bridges[Count].DevicePath); + } while (Count > 0); + + FreePool (Bridges); +} + + +/** + Inform the platform that the resource conflict happens. + + @param HostBridgeHandle Handle of the Host Bridge. + @param Configuration Pointer to PCI I/O and PCI memory resource + descriptors. The Configuration contains the resources + for all the root bridges. The resource for each root + bridge is terminated with END descriptor and an + additional END is appended indicating the end of the + entire resources. The resource descriptor field + values follow the description in + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL + .SubmitResources(). +**/ +VOID +EFIAPI +PciHostBridgeResourceConflict ( + EFI_HANDLE HostBridgeHandle, + VOID *Configuration +) +{ + // + // coreboot UEFI Payload does not do PCI enumeration and should not call this + // library interface. + // + ASSERT (FALSE); +} diff --git a/DasharoPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf b/DasharoPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf new file mode 100644 index 0000000000..1682493406 --- /dev/null +++ b/DasharoPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf @@ -0,0 +1,42 @@ +## @file +# Library instance of PciHostBridgeLib library class for coreboot. +# +# Copyright (C) 2016, Red Hat, Inc. +# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PciHostBridgeLib + FILE_GUID = 62EE5269-CFFD-43a3-BE3F-622FC79F467E + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PciHostBridgeLib + +# +# The following information is for reference only and not required by the build +# tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + PciHostBridge.h + PciHostBridgeLib.c + PciHostBridgeSupport.c + +[Packages] + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + DevicePathLib + MemoryAllocationLib + PciLib + DxeServicesTableLib diff --git a/DasharoPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeSupport.c b/DasharoPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeSupport.c new file mode 100644 index 0000000000..0e0520fe92 --- /dev/null +++ b/DasharoPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeSupport.c @@ -0,0 +1,570 @@ +/** @file + Scan the entire PCI bus for root bridges to support coreboot UEFI payload. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "PciHostBridge.h" + +/** + Probe a bar is existed or not. + + @param[in] Address PCI address for the BAR. + @param[out] OriginalValue The original bar value returned. + @param[out] Value The probed bar value returned. +**/ +STATIC +VOID +PcatPciRootBridgeBarExisted ( + IN UINTN Address, + OUT UINT32 *OriginalValue, + OUT UINT32 *Value +) +{ + // + // Preserve the original value + // + *OriginalValue = PciRead32 (Address); + + // + // Disable timer interrupt while the BAR is probed + // + DisableInterrupts (); + + PciWrite32 (Address, 0xFFFFFFFF); + *Value = PciRead32 (Address); + PciWrite32 (Address, *OriginalValue); + + // + // Enable interrupt + // + EnableInterrupts (); +} + +STATIC +EFI_STATUS +PcatPciRootBridgeWarnAboutBrokenFW ( + IN UINT64 Start, + IN UINT64 Limit +) +{ + EFI_STATUS Status; + UINTN Index; + UINT64 IntersectionBase; + UINT64 IntersectionEnd; + UINTN NumberOfDescriptors; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Map; + + Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &Map); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "%a: %a: GetMemorySpaceMap(): %r\n", + gEfiCallerBaseName, __FUNCTION__, Status)); + return Status; + } + + for (Index = 0; Index < NumberOfDescriptors; Index++) { + if (Map[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) { + // + // Ignore non existent entries + // + continue; + } + + IntersectionBase = MAX (Start, Map[Index].BaseAddress); + IntersectionEnd = MIN (Limit, Map[Index].BaseAddress + Map[Index].Length); + if (IntersectionBase >= IntersectionEnd) { + // + // The descriptor and the aperture don't overlap. + // + continue; + } + + if (Map[Index].GcdMemoryType == EfiGcdMemoryTypeReserved) { + DEBUG ((EFI_D_ERROR, "%a: PCI aperature overlaps reserved memory region\n", + __FUNCTION__)); + DEBUG ((EFI_D_ERROR, "%a: Please consider fixing EDK2 or your firmware\n", + __FUNCTION__)); + return EFI_ACCESS_DENIED; + } + } + return EFI_SUCCESS; +} + +/** + Parse PCI bar and collect the assigned PCI resource information. + + @param[in] Command Supported attributes. + + @param[in] Bus PCI bus number. + + @param[in] Device PCI device number. + + @param[in] Function PCI function number. + + @param[in] BarOffsetBase PCI bar start offset. + + @param[in] BarOffsetEnd PCI bar end offset. + + @param[in] Io IO aperture. + + @param[in] Mem MMIO aperture. + + @param[in] MemAbove4G MMIO aperture above 4G. +**/ +STATIC +VOID +PcatPciRootBridgeParseBars ( + IN UINT16 Command, + IN UINTN Bus, + IN UINTN Device, + IN UINTN Function, + IN UINTN BarOffsetBase, + IN UINTN BarOffsetEnd, + IN PCI_ROOT_BRIDGE_APERTURE *Io, + IN PCI_ROOT_BRIDGE_APERTURE *Mem, + IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G + +) +{ + UINT32 OriginalValue; + UINT32 Value; + UINT32 OriginalUpperValue; + UINT32 UpperValue; + UINT64 Mask; + UINTN Offset; + UINTN LowBit; + UINT64 Base; + UINT64 Length; + UINT64 Limit; + PCI_ROOT_BRIDGE_APERTURE *MemAperture; + UINT64 NewBase; + UINT64 NewLength; + EFI_STATUS Status; + + for (Offset = BarOffsetBase; Offset < BarOffsetEnd; Offset += sizeof (UINT32)) { + PcatPciRootBridgeBarExisted ( + PCI_LIB_ADDRESS (Bus, Device, Function, Offset), + &OriginalValue, &Value + ); + if (Value == 0) { + continue; + } + if ((Value & BIT0) == BIT0) { + // + // IO Bar + // + if (Command & EFI_PCI_COMMAND_IO_SPACE) { + Mask = 0xfffffffc; + Base = OriginalValue & Mask; + Length = ((~(Value & Mask)) & Mask) + 0x04; + if (!(Value & 0xFFFF0000)) { + Length &= 0x0000FFFF; + } + Limit = Base + Length - 1; + + if ((Base > 0) && (Base < Limit)) { + if (Io->Base > Base) { + Io->Base = Base; + } + if (Io->Limit < Limit) { + Io->Limit = Limit; + } + } + } + } else { + // + // Mem Bar + // + if (Command & EFI_PCI_COMMAND_MEMORY_SPACE) { + + Mask = 0xfffffff0; + Base = OriginalValue & Mask; + Length = Value & Mask; + + if ((Value & (BIT1 | BIT2)) == 0) { + // + // 32bit + // + Length = ((~Length) + 1) & 0xffffffff; + + MemAperture = Mem; + } else { + // + // 64bit + // + Offset += 4; + PcatPciRootBridgeBarExisted ( + PCI_LIB_ADDRESS (Bus, Device, Function, Offset), + &OriginalUpperValue, + &UpperValue + ); + + Base = Base | LShiftU64 ((UINT64) OriginalUpperValue, 32); + Length = Length | LShiftU64 ((UINT64) UpperValue, 32); + if (Length != 0) { + LowBit = LowBitSet64 (Length); + Length = LShiftU64 (1ULL, LowBit); + } + + if (Base < BASE_4GB) { + MemAperture = Mem; + } else { + MemAperture = MemAbove4G; + } + } + + Limit = Base + Length - 1; + if ((Base > 0) && (Base < Limit)) { + NewBase = MemAperture->Base; + if (MemAperture->Base > Base) { + NewBase = Base; + } + NewLength = MemAperture->Base; + if (MemAperture->Limit < Limit) { + NewLength = Base; + } + + // + // In case the BAR is placed on "the other side" of the MMCONF window + // this would cause the aperature to cover the MMCONF window, which + // isn't supported by EDK2. + // + Status = PcatPciRootBridgeWarnAboutBrokenFW(NewBase, NewLength); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "%a: Not adding PCI %x:%x.%x BAR@%d %x:%x to aperature\n", + __FUNCTION__, + Bus, + Device, + Function, + Offset, + Base, + Limit)); + continue; + } + + if (MemAperture->Base > Base) { + MemAperture->Base = Base; + } + if (MemAperture->Limit < Limit) { + MemAperture->Limit = Limit; + } + } + } + } + } +} + +STATIC PCI_ROOT_BRIDGE_APERTURE mNonExistAperture = { MAX_UINT64, 0 }; + +/** + Scan for all root bridges in platform. + + @param[out] NumberOfRootBridges Number of root bridges detected + + @retval Pointer to the allocated PCI_ROOT_BRIDGE structure array. +**/ +PCI_ROOT_BRIDGE * +ScanForRootBridges ( + OUT UINTN *NumberOfRootBridges +) +{ + UINTN PrimaryBus; + UINTN SubBus; + UINT8 Device; + UINT8 Function; + UINTN NumberOfDevices; + UINTN Address; + PCI_TYPE01 Pci; + UINT64 Attributes; + UINT64 Base; + UINT64 Limit; + UINT64 Value; + PCI_ROOT_BRIDGE_APERTURE Io, Mem, MemAbove4G, *MemAperture; + PCI_ROOT_BRIDGE *RootBridges; + UINTN BarOffsetEnd; + + + *NumberOfRootBridges = 0; + RootBridges = NULL; + + // + // After scanning all the PCI devices on the PCI root bridge's primary bus, + // update the Primary Bus Number for the next PCI root bridge to be this PCI + // root bridge's subordinate bus number + 1. + // + for (PrimaryBus = 0; PrimaryBus <= PCI_MAX_BUS; PrimaryBus = SubBus + 1) { + SubBus = PrimaryBus; + Attributes = 0; + + ZeroMem (&Io, sizeof (Io)); + ZeroMem (&Mem, sizeof (Mem)); + ZeroMem (&MemAbove4G, sizeof (MemAbove4G)); + Io.Base = Mem.Base = MemAbove4G.Base = MAX_UINT64; + // + // Scan all the PCI devices on the primary bus of the PCI root bridge + // + for (Device = 0, NumberOfDevices = 0; Device <= PCI_MAX_DEVICE; Device++) { + + for (Function = 0; Function <= PCI_MAX_FUNC; Function++) { + + // + // Compute the PCI configuration address of the PCI device to probe + // + Address = PCI_LIB_ADDRESS (PrimaryBus, Device, Function, 0); + + // + // Read the Vendor ID from the PCI Configuration Header + // + if (PciRead16 (Address) == MAX_UINT16) { + if (Function == 0) { + // + // If the PCI Configuration Read fails, or a PCI device does not + // exist, then skip this entire PCI device + // + break; + } else { + // + // If PCI function != 0, VendorId == 0xFFFF, we continue to search + // PCI function. + // + continue; + } + } + + // + // Read the entire PCI Configuration Header + // + PciReadBuffer (Address, sizeof (Pci), &Pci); + + // + // Increment the number of PCI device found on the primary bus of the + // PCI root bridge + // + NumberOfDevices++; + + // + // Look for devices with the VGA Palette Snoop enabled in the COMMAND + // register of the PCI Config Header + // + if ((Pci.Hdr.Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) != 0) { + Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO; + Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16; + } + + BarOffsetEnd = 0; + + // + // PCI-PCI Bridge + // + if (IS_PCI_BRIDGE (&Pci)) { + // + // Get the Bus range that the PPB is decoding + // + if (Pci.Bridge.SubordinateBus > SubBus) { + // + // If the subordinate bus number of the PCI-PCI bridge is greater + // than the PCI root bridge's current subordinate bus number, + // then update the PCI root bridge's subordinate bus number + // + SubBus = Pci.Bridge.SubordinateBus; + } + + // + // Get the I/O range that the PPB is decoding + // + Value = Pci.Bridge.IoBase & 0x0f; + Base = ((UINT32) Pci.Bridge.IoBase & 0xf0) << 8; + Limit = (((UINT32) Pci.Bridge.IoLimit & 0xf0) << 8) | 0x0fff; + if (Value == BIT0) { + Base |= ((UINT32) Pci.Bridge.IoBaseUpper16 << 16); + Limit |= ((UINT32) Pci.Bridge.IoLimitUpper16 << 16); + } + if ((Base > 0) && (Base < Limit)) { + if (Io.Base > Base) { + Io.Base = Base; + } + if (Io.Limit < Limit) { + Io.Limit = Limit; + } + } + + // + // Get the Memory range that the PPB is decoding + // + Base = ((UINT32) Pci.Bridge.MemoryBase & 0xfff0) << 16; + Limit = (((UINT32) Pci.Bridge.MemoryLimit & 0xfff0) << 16) | 0xfffff; + if ((Base > 0) && (Base < Limit)) { + if (Mem.Base > Base) { + Mem.Base = Base; + } + if (Mem.Limit < Limit) { + Mem.Limit = Limit; + } + } + + // + // Get the Prefetchable Memory range that the PPB is decoding + // + Value = Pci.Bridge.PrefetchableMemoryBase & 0x0f; + Base = ((UINT32) Pci.Bridge.PrefetchableMemoryBase & 0xfff0) << 16; + Limit = (((UINT32) Pci.Bridge.PrefetchableMemoryLimit & 0xfff0) + << 16) | 0xfffff; + if (Value == BIT0) { + Base |= LShiftU64 (Pci.Bridge.PrefetchableBaseUpper32, 32); + Limit |= LShiftU64 (Pci.Bridge.PrefetchableLimitUpper32, 32); + } + if ((Base > 0) && (Base < Limit)) { + if (Base < BASE_4GB) { + MemAperture = &Mem; + } else { + MemAperture = &MemAbove4G; + } + + if (MemAperture->Base > Base) { + MemAperture->Base = Base; + } + if (MemAperture->Limit < Limit) { + MemAperture->Limit = Limit; + } + } + + // + // Look at the PPB Configuration for legacy decoding attributes + // + if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) + == EFI_PCI_BRIDGE_CONTROL_ISA) { + Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO; + Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO_16; + Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO; + } + if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) + == EFI_PCI_BRIDGE_CONTROL_VGA) { + Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO; + Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY; + Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO; + if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA_16) + != 0) { + Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16; + Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO_16; + } + } + + BarOffsetEnd = OFFSET_OF (PCI_TYPE01, Bridge.Bar[2]); + } else { + // + // Parse the BARs of the PCI device to get what I/O Ranges, Memory + // Ranges, and Prefetchable Memory Ranges the device is decoding + // + if ((Pci.Hdr.HeaderType & HEADER_LAYOUT_CODE) == HEADER_TYPE_DEVICE) { + BarOffsetEnd = OFFSET_OF (PCI_TYPE00, Device.Bar[6]); + } + } + + PcatPciRootBridgeParseBars ( + Pci.Hdr.Command, + PrimaryBus, + Device, + Function, + OFFSET_OF (PCI_TYPE00, Device.Bar), + BarOffsetEnd, + &Io, + &Mem, &MemAbove4G + ); + + // + // See if the PCI device is an IDE controller + // + if (IS_CLASS2 (&Pci, PCI_CLASS_MASS_STORAGE, + PCI_CLASS_MASS_STORAGE_IDE)) { + if (Pci.Hdr.ClassCode[0] & 0x80) { + Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO; + Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO; + } + if (Pci.Hdr.ClassCode[0] & 0x01) { + Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO; + } + if (Pci.Hdr.ClassCode[0] & 0x04) { + Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO; + } + } + + // + // See if the PCI device is a legacy VGA controller or + // a standard VGA controller + // + if (IS_CLASS2 (&Pci, PCI_CLASS_OLD, PCI_CLASS_OLD_VGA) || + IS_CLASS2 (&Pci, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_VGA) + ) { + Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO; + Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16; + Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY; + Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO; + Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO_16; + } + + // + // See if the PCI Device is a PCI - ISA or PCI - EISA + // or ISA_POSITIVE_DECODE Bridge device + // + if (Pci.Hdr.ClassCode[2] == PCI_CLASS_BRIDGE) { + if (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA || + Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_EISA || + Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA_PDECODE) { + Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO; + Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO_16; + Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO; + } + } + + // + // If this device is not a multi function device, then skip the rest + // of this PCI device + // + if (Function == 0 && !IS_PCI_MULTI_FUNC (&Pci)) { + break; + } + } + } + + // + // If at least one PCI device was found on the primary bus of this PCI + // root bridge, then the PCI root bridge exists. + // + if (NumberOfDevices > 0) { + RootBridges = ReallocatePool ( + (*NumberOfRootBridges) * sizeof (PCI_ROOT_BRIDGE), + (*NumberOfRootBridges + 1) * sizeof (PCI_ROOT_BRIDGE), + RootBridges + ); + ASSERT (RootBridges != NULL); + + InitRootBridge ( + Attributes, Attributes, 0, + (UINT8) PrimaryBus, (UINT8) SubBus, + &Io, &Mem, &MemAbove4G, + &mNonExistAperture, &mNonExistAperture, + &RootBridges[*NumberOfRootBridges] + ); + RootBridges[*NumberOfRootBridges].ResourceAssigned = TRUE; + // + // Increment the index for the next PCI Root Bridge + // + (*NumberOfRootBridges)++; + } + } + + return RootBridges; +} diff --git a/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c b/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c new file mode 100644 index 0000000000..926a8bf57d --- /dev/null +++ b/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c @@ -0,0 +1,1794 @@ +/** @file + This file include all platform action which can be customized + by IBV/OEM. + +Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PlatformBootManager.h" +#include "PlatformConsole.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +EFI_GUID mBootMenuFile = { + 0xEEC25BDC, 0x67F2, 0x4D95, { 0xB1, 0xD5, 0xF8, 0x1B, 0x20, 0x39, 0xD1, 0x1D } +}; + +VOID +InstallReadyToLock ( + VOID + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + EFI_SMM_ACCESS2_PROTOCOL *SmmAccess; + + DEBUG((DEBUG_INFO,"InstallReadyToLock entering......\n")); + // + // Inform the SMM infrastructure that we're entering BDS and may run 3rd party code hereafter + // Since PI1.2.1, we need signal EndOfDxe as ExitPmAuth + // + EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid); + DEBUG((DEBUG_INFO,"All EndOfDxe callbacks have returned successfully\n")); + + // + // Install DxeSmmReadyToLock protocol in order to lock SMM + // + Status = gBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **) &SmmAccess); + if (!EFI_ERROR (Status)) { + Handle = NULL; + Status = gBS->InstallProtocolInterface ( + &Handle, + &gEfiDxeSmmReadyToLockProtocolGuid, + EFI_NATIVE_INTERFACE, + NULL + ); + ASSERT_EFI_ERROR (Status); + } + + DEBUG((DEBUG_INFO,"InstallReadyToLock end\n")); + return; +} + +/** + Return the index of the load option in the load option array. + + The function consider two load options are equal when the + OptionType, Attributes, Description, FilePath and OptionalData are equal. + + @param Key Pointer to the load option to be found. + @param Array Pointer to the array of load options to be found. + @param Count Number of entries in the Array. + + @retval -1 Key wasn't found in the Array. + @retval 0 ~ Count-1 The index of the Key in the Array. +**/ +INTN +PlatformFindLoadOption ( + IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key, + IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array, + IN UINTN Count +) +{ + UINTN Index; + + for (Index = 0; Index < Count; Index++) { + if ((Key->OptionType == Array[Index].OptionType) && + (Key->Attributes == Array[Index].Attributes) && + (StrCmp (Key->Description, Array[Index].Description) == 0) && + (CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSize (Key->FilePath)) == 0) && + (Key->OptionalDataSize == Array[Index].OptionalDataSize) && + (CompareMem (Key->OptionalData, Array[Index].OptionalData, Key->OptionalDataSize) == 0)) { + return (INTN) Index; + } + } + + return -1; +} + +VOID +PlatformRegisterFvBootOption ( + EFI_GUID *FileGuid, + CHAR16 *Description, + UINT32 Attributes, + BOOLEAN BootNow + ) +{ + EFI_STATUS Status; + INTN OptionIndex; + EFI_BOOT_MANAGER_LOAD_OPTION NewOption; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; + UINTN BootOptionCount; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + Status = gBS->HandleProtocol ( + gImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &LoadedImage + ); + ASSERT_EFI_ERROR (Status); + + EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid); + DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle); + ASSERT (DevicePath != NULL); + DevicePath = AppendDevicePathNode ( + DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &FileNode + ); + ASSERT (DevicePath != NULL); + + Status = EfiBootManagerInitializeLoadOption ( + &NewOption, + LoadOptionNumberUnassigned, + LoadOptionTypeBoot, + Attributes, + Description, + DevicePath, + NULL, + 0 + ); + ASSERT_EFI_ERROR (Status); + FreePool (DevicePath); + + if (BootNow) + EfiBootManagerBoot (&NewOption); + + BootOptions = EfiBootManagerGetLoadOptions ( + &BootOptionCount, LoadOptionTypeBoot + ); + + OptionIndex = EfiBootManagerFindLoadOption ( + &NewOption, BootOptions, BootOptionCount + ); + + if (OptionIndex == -1) { + Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN); + ASSERT_EFI_ERROR (Status); + } + + EfiBootManagerFreeLoadOption (&NewOption); + EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); +} + +VOID +PlatformUnregisterFvBootOption ( + EFI_GUID *FileGuid, + CHAR16 *Description, + UINT32 Attributes + ) +{ + EFI_STATUS Status; + INTN OptionIndex; + EFI_BOOT_MANAGER_LOAD_OPTION NewOption; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; + UINTN BootOptionCount; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + Status = gBS->HandleProtocol ( + gImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &LoadedImage + ); + ASSERT_EFI_ERROR (Status); + + EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid); + DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle); + ASSERT (DevicePath != NULL); + DevicePath = AppendDevicePathNode ( + DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &FileNode + ); + ASSERT (DevicePath != NULL); + + Status = EfiBootManagerInitializeLoadOption ( + &NewOption, + LoadOptionNumberUnassigned, + LoadOptionTypeBoot, + Attributes, + Description, + DevicePath, + NULL, + 0 + ); + ASSERT_EFI_ERROR (Status); + FreePool (DevicePath); + + BootOptions = EfiBootManagerGetLoadOptions ( + &BootOptionCount, LoadOptionTypeBoot + ); + + OptionIndex = EfiBootManagerFindLoadOption ( + &NewOption, BootOptions, BootOptionCount + ); + + if (OptionIndex >= 0 && OptionIndex < BootOptionCount) { + Status = EfiBootManagerDeleteLoadOptionVariable (BootOptions[OptionIndex].OptionNumber, + BootOptions[OptionIndex].OptionType); + ASSERT_EFI_ERROR (Status); + } + EfiBootManagerFreeLoadOption (&NewOption); + EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); +} + +EFI_DEVICE_PATH * +FvFilePath ( + EFI_GUID *FileGuid + ) +{ + + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode; + + EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid); + + Status = gBS->HandleProtocol ( + gImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &LoadedImage + ); + ASSERT_EFI_ERROR (Status); + return AppendDevicePathNode ( + DevicePathFromHandle (LoadedImage->DeviceHandle), + (EFI_DEVICE_PATH_PROTOCOL *) &FileNode + ); +} + +/** + Create one boot option for BootManagerMenuApp. + + @retval OptionNumber Return the option number info. + +**/ +UINTN +RegisterBootManagerMenuAppBootOption ( + VOID + ) +{ + EFI_STATUS Status; + EFI_BOOT_MANAGER_LOAD_OPTION NewOption; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN OptionNumber; + + DevicePath = FvFilePath (&mBootMenuFile); + // Use LOAD_OPTION_HIDDEN to not display Boot Manager Menu App in + // "One Time Boot" menu. + Status = EfiBootManagerInitializeLoadOption ( + &NewOption, + LoadOptionNumberUnassigned, + LoadOptionTypeBoot, + LOAD_OPTION_CATEGORY_APP | LOAD_OPTION_HIDDEN, + L"UEFI BootManagerMenuApp", + DevicePath, + NULL, + 0 + ); + ASSERT_EFI_ERROR (Status); + FreePool (DevicePath); + + DEBUG((EFI_D_INFO, "Registering Boot Manager app option\n")); + Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN); + ASSERT_EFI_ERROR (Status); + + OptionNumber = NewOption.OptionNumber; + + EfiBootManagerFreeLoadOption (&NewOption); + + return OptionNumber; +} + +/** + Delete one boot option for BootManagerMenuApp. + + @retval OptionNumber Return the option number info. + +**/ +EFI_STATUS +UnregisterBootManagerMenuAppBootOption ( + VOID + ) +{ + EFI_STATUS Status; + EFI_BOOT_MANAGER_LOAD_OPTION NewOption; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN BootOptionCount; + INTN OptionIndex; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; + + DevicePath = FvFilePath (&mBootMenuFile); + // Use LOAD_OPTION_HIDDEN to not display Boot Manager Menu App in + // "One Time Boot" menu. + Status = EfiBootManagerInitializeLoadOption ( + &NewOption, + LoadOptionNumberUnassigned, + LoadOptionTypeBoot, + LOAD_OPTION_CATEGORY_APP | LOAD_OPTION_HIDDEN, + L"UEFI BootManagerMenuApp", + DevicePath, + NULL, + 0 + ); + ASSERT_EFI_ERROR (Status); + FreePool (DevicePath); + + DEBUG((EFI_D_INFO, "Unregistering Boot Manager app option\n")); + BootOptions = EfiBootManagerGetLoadOptions ( + &BootOptionCount, LoadOptionTypeBoot + ); + + OptionIndex = EfiBootManagerFindLoadOption ( + &NewOption, BootOptions, BootOptionCount + ); + + if (OptionIndex >= 0 && OptionIndex < BootOptionCount) { + Status = EfiBootManagerDeleteLoadOptionVariable (BootOptions[OptionIndex].OptionNumber, + BootOptions[OptionIndex].OptionType); + } + + return Status; +} + +/** + Check if it's a Device Path pointing to BootManagerMenuApp. + + @param DevicePath Input device path. + + @retval TRUE The device path is BootManagerMenuApp File Device Path. + @retval FALSE The device path is NOT BootManagerMenuApp File Device Path. +**/ +BOOLEAN +IsBootManagerMenuAppFilePath ( + EFI_DEVICE_PATH_PROTOCOL *DevicePath +) +{ + EFI_HANDLE FvHandle; + VOID *NameGuid; + EFI_STATUS Status; + + Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &DevicePath, &FvHandle); + if (!EFI_ERROR (Status)) { + NameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) DevicePath); + if (NameGuid != NULL) { + return CompareGuid (NameGuid, &mBootMenuFile); + } + } + + return FALSE; +} + +/** + Return the boot option number to the BootManagerMenuApp. + + If not found it in the current boot option, create a new one. + + @retval OptionNumber Return the boot option number to the BootManagerMenuApp. + +**/ +UINTN +GetBootManagerMenuAppOption ( + VOID + ) +{ + UINTN BootOptionCount; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; + UINTN Index; + UINTN OptionNumber; + + OptionNumber = 0; + + BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot); + + for (Index = 0; Index < BootOptionCount; Index++) { + if (IsBootManagerMenuAppFilePath (BootOptions[Index].FilePath)) { + OptionNumber = BootOptions[Index].OptionNumber; + break; + } + } + + EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); + + if (Index >= BootOptionCount) { + // + // If not found the BootManagerMenuApp, create it. + // + DEBUG((EFI_D_INFO, "Creating Boot Manager option\n")); + OptionNumber = (UINT16) RegisterBootManagerMenuAppBootOption (); + } else { + DEBUG((EFI_D_INFO, "Boot Manager option number %d\n", OptionNumber)); + } + + return OptionNumber; +} + + +/** + Check if the handle satisfies a particular condition. + + @param[in] Handle The handle to check. + @param[in] ReportText A caller-allocated string passed in for reporting + purposes. It must never be NULL. + + @retval TRUE The condition is satisfied. + @retval FALSE Otherwise. This includes the case when the condition could not + be fully evaluated due to an error. +**/ +typedef +BOOLEAN +(EFIAPI *FILTER_FUNCTION) ( + IN EFI_HANDLE Handle, + IN CONST CHAR16 *ReportText + ); + + +/** + Process a handle. + + @param[in] Handle The handle to process. + @param[in] ReportText A caller-allocated string passed in for reporting + purposes. It must never be NULL. +**/ +typedef +VOID +(EFIAPI *CALLBACK_FUNCTION) ( + IN EFI_HANDLE Handle, + IN CONST CHAR16 *ReportText + ); + +/** + Locate all handles that carry the specified protocol, filter them with a + callback function, and pass each handle that passes the filter to another + callback. + + @param[in] ProtocolGuid The protocol to look for. + + @param[in] Filter The filter function to pass each handle to. If this + parameter is NULL, then all handles are processed. + + @param[in] Process The callback function to pass each handle to that + clears the filter. +**/ +STATIC +VOID +FilterAndProcess ( + IN EFI_GUID *ProtocolGuid, + IN FILTER_FUNCTION Filter OPTIONAL, + IN CALLBACK_FUNCTION Process + ) +{ + EFI_STATUS Status; + EFI_HANDLE *Handles; + UINTN NoHandles; + UINTN Idx; + + Status = gBS->LocateHandleBuffer (ByProtocol, ProtocolGuid, + NULL /* SearchKey */, &NoHandles, &Handles); + if (EFI_ERROR (Status)) { + // + // This is not an error, just an informative condition. + // + DEBUG ((EFI_D_VERBOSE, "%a: %g: %r\n", __FUNCTION__, ProtocolGuid, + Status)); + return; + } + + ASSERT (NoHandles > 0); + for (Idx = 0; Idx < NoHandles; ++Idx) { + CHAR16 *DevicePathText; + STATIC CHAR16 Fallback[] = L""; + + // + // The ConvertDevicePathToText() function handles NULL input transparently. + // + DevicePathText = ConvertDevicePathToText ( + DevicePathFromHandle (Handles[Idx]), + FALSE, // DisplayOnly + FALSE // AllowShortcuts + ); + if (DevicePathText == NULL) { + DevicePathText = Fallback; + } + + if (Filter == NULL || Filter (Handles[Idx], DevicePathText)) { + Process (Handles[Idx], DevicePathText); + } + + if (DevicePathText != Fallback) { + FreePool (DevicePathText); + } + } + gBS->FreePool (Handles); +} + + +/** + This FILTER_FUNCTION checks if a handle corresponds to a PCI display device. +**/ +STATIC +BOOLEAN +EFIAPI +IsPciDisplay ( + IN EFI_HANDLE Handle, + IN CONST CHAR16 *ReportText + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE00 Pci; + + Status = gBS->HandleProtocol (Handle, &gEfiPciIoProtocolGuid, + (VOID**)&PciIo); + if (EFI_ERROR (Status)) { + // + // This is not an error worth reporting. + // + return FALSE; + } + + Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0 /* Offset */, + sizeof Pci / sizeof (UINT32), &Pci); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "%a: %s: %r\n", __FUNCTION__, ReportText, Status)); + return FALSE; + } + + return IS_PCI_DISPLAY (&Pci); +} + + +/** + This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking + the matching driver to produce all first-level child handles. +**/ +STATIC +VOID +EFIAPI +Connect ( + IN EFI_HANDLE Handle, + IN CONST CHAR16 *ReportText + ) +{ + EFI_STATUS Status; + + Status = gBS->ConnectController ( + Handle, // ControllerHandle + NULL, // DriverImageHandle + NULL, // RemainingDevicePath -- produce all children + FALSE // Recursive + ); + DEBUG ((EFI_ERROR (Status) ? EFI_D_ERROR : EFI_D_VERBOSE, "%a: %s: %r\n", + __FUNCTION__, ReportText, Status)); +} + + +/** + This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the + handle, and adds it to ConOut and ErrOut. +**/ +STATIC +VOID +EFIAPI +AddOutput ( + IN EFI_HANDLE Handle, + IN CONST CHAR16 *ReportText + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + DevicePath = DevicePathFromHandle (Handle); + if (DevicePath == NULL) { + DEBUG ((EFI_D_ERROR, "%a: %s: handle %p: device path not found\n", + __FUNCTION__, ReportText, Handle)); + return; + } + + Status = EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "%a: %s: adding to ConOut: %r\n", __FUNCTION__, + ReportText, Status)); + return; + } + + Status = EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "%a: %s: adding to ErrOut: %r\n", __FUNCTION__, + ReportText, Status)); + return; + } + + DEBUG ((EFI_D_VERBOSE, "%a: %s: added to ConOut and ErrOut\n", __FUNCTION__, + ReportText)); +} + + +/** + Do the platform specific action before the console is connected. + + Such as: + Update console variable; + Register new Driver#### or Boot####; + Signal ReadyToLock event. +**/ +VOID +EFIAPI +PlatformBootManagerBeforeConsole ( + VOID +) +{ + EFI_INPUT_KEY Esc; + EFI_INPUT_KEY F12; + EFI_BOOT_MANAGER_LOAD_OPTION BootOption; + UINTN OptionNumber; + + // For Boot Menu Enabled functionality + EFI_STATUS Status; + BOOLEAN BootMenuEnable; + UINTN VarSize; + + // + // Map ESC to Boot Manager Menu + // + Esc.ScanCode = FixedPcdGet16(PcdSetupMenuKey); + Esc.UnicodeChar = CHAR_NULL; + EfiBootManagerGetBootManagerMenu (&BootOption); + EfiBootManagerAddKeyOptionVariable (NULL, (UINT16) BootOption.OptionNumber, 0, &Esc, NULL); + + // + // Map F12 to Boot Device List menu + // + F12.ScanCode = FixedPcdGet16(PcdBootMenuKey); + F12.UnicodeChar = CHAR_NULL; + + VarSize = sizeof (BootMenuEnable); + Status = gRT->GetVariable ( + DASHARO_VAR_BOOT_MANAGER_ENABLED, + &gDasharoSystemFeaturesGuid, + NULL, + &VarSize, + &BootMenuEnable + ); + + DEBUG((EFI_D_ERROR, "Boot Manager option: %r, Size: %x, Enabled: %d\n", + Status, VarSize, BootMenuEnable)); + + if (EFI_ERROR(Status) || VarSize != sizeof(BootMenuEnable) || BootMenuEnable) { + DEBUG((EFI_D_INFO, "Registering Boot Manager key option\n")); + OptionNumber = GetBootManagerMenuAppOption (); + EfiBootManagerAddKeyOptionVariable (NULL, (UINT16)OptionNumber, 0, &F12, NULL); + } else { + DEBUG((EFI_D_INFO, "Unregistering Boot Manager key option\n")); + EfiBootManagerDeleteKeyOptionVariable(NULL, 0, &F12, NULL); + UnregisterBootManagerMenuAppBootOption (); + } + + // + // Process system firmware update capsules and possibly device update + // capsules that don't contain embedded drivers if those devices are already + // available. + // + if (GetBootModeHob() == BOOT_ON_FLASH_UPDATE) { + // TODO: when enabling capsule support for laptops, add a battery check here + Status = ProcessCapsules (); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "%a(): ProcessCapsule() failed with: %r\n", __FUNCTION__, Status)); + } + } + + // + // Install ready to lock. + // This needs to be done before option rom dispatched. + // + InstallReadyToLock (); + + // + // Dispatch deferred images after EndOfDxe event and ReadyToLock installation. + // + EfiBootManagerDispatchDeferredImages (); + + // + // Locate the PCI root bridges and make the PCI bus driver connect each, + // non-recursively. This will produce a number of child handles with PciIo on + // them. + // + FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid, NULL, Connect); + + // + // PCI initialization from above should be sufficient for the discovery and + // processing of consoles. + // + PlatformConsoleInit (); + + // + // Find all display class PCI devices (using the handles from the previous + // step), and connect them non-recursively. This should produce a number of + // child handles with GOPs on them. + // + FilterAndProcess (&gEfiPciIoProtocolGuid, IsPciDisplay, Connect); + + // + // Now add the device path of all handles with GOP on them to ConOut and + // ErrOut. + // + FilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput); +} + +CHAR16* +GetKeyStringFromScanCode ( + UINT16 ScanCode, + CHAR16* Default +) +{ + switch (ScanCode) { + case SCAN_UP: return L"UP"; + case SCAN_DOWN: return L"DOWN"; + case SCAN_RIGHT: return L"RIGHT"; + case SCAN_LEFT: return L"LEFT"; + case SCAN_HOME: return L"HOME"; + case SCAN_END: return L"END"; + case SCAN_INSERT: return L"INS"; + case SCAN_DELETE: return L"DEL"; + case SCAN_F1: return L"F1"; + case SCAN_F2: return L"F2"; + case SCAN_F3: return L"F3"; + case SCAN_F4: return L"F4"; + case SCAN_F5: return L"F5"; + case SCAN_F6: return L"F6"; + case SCAN_F7: return L"F7"; + case SCAN_F8: return L"F8"; + case SCAN_F9: return L"F9"; + case SCAN_F10: return L"F10"; + case SCAN_F11: return L"F11"; + case SCAN_F12: return L"F12"; + case SCAN_ESC: return L"ESC"; + default: return Default; + } +} + +STATIC +VOID +DrainInput ( + VOID +) +{ + EFI_INPUT_KEY Key; + + // + // Drain any queued keys. + // + while (!EFI_ERROR (gST->ConIn->ReadKeyStroke (gST->ConIn, &Key))) { + // + // just throw away Key + // + } +} + +STATIC +VOID +WarnIfRecoveryBoot ( + VOID +) +{ + EFI_STATUS Status; + EFI_EVENT TimerEvent; + EFI_EVENT Events[2]; + UINTN Index; + EFI_INPUT_KEY Key; + RETURN_STATUS RetStatus; + UINT8 RecoveryCode; + CONST CHAR8 *RecoveryReason; + CHAR16 RecoveryCodeLine[81]; + CHAR16 RecoveryMsgLine[81]; + CHAR16 DelayLine[81]; + BOOLEAN CursorVisible; + UINTN CurrentAttribute; + UINTN SecondsLeft; + + RetStatus = ParseVBootWorkbuf (&RecoveryCode, &RecoveryReason); + + if (RetStatus != RETURN_SUCCESS || RecoveryCode == 0) { + return; + } + + Status = gBS->CreateEvent ( + EVT_TIMER, + TPL_CALLBACK, + NULL, + NULL, + &TimerEvent + ); + ASSERT_EFI_ERROR (Status); + + UnicodeSPrint ( + RecoveryCodeLine, + sizeof (RecoveryCodeLine), + L"Recovery reason code: 0x%02x", + RecoveryCode + ); + UnicodeSPrint ( + RecoveryMsgLine, + sizeof (RecoveryMsgLine), + L"Recovery reason: %a", + RecoveryReason + ); + + CurrentAttribute = gST->ConOut->Mode->Attribute; + CursorVisible = gST->ConOut->Mode->CursorVisible; + + gST->ConOut->EnableCursor (gST->ConOut, FALSE); + + DrainInput (); + gBS->SetTimer (TimerEvent, TimerPeriodic, 1 * 1000 * 1000 * 10); + + Events[0] = gST->ConIn->WaitForKey; + Events[1] = TimerEvent; + + SecondsLeft = 30; + while (SecondsLeft > 0) { + UnicodeSPrint ( + DelayLine, + sizeof (DelayLine), + L"(The boot process will continue automatically in %d second%a.)", + SecondsLeft, + SecondsLeft == 1 ? "" : "s" + ); + + switch (RecoveryCode) { + case VB2_RECOVERY_EC_SOFTWARE_SYNC: + CreateMultiStringPopUp ( + 78, + 10, + L"!!! WARNING !!!", + L"", + L"Embedded Controller firmware update failed. Try rebooting the device", + L"with an AC adapter connected.", + L"", + L"If the message persists, contact support or see docs.dasharo.com for", + L"more information.", + L"", + L"Press ENTER key to continue.", + DelayLine + ); + break; + default: + CreateMultiStringPopUp ( + 78, + 12, + L"!!! WARNING !!!", + L"", + L"This message is displayed because the platform has booted from the recovery", + L"firmware partition. If you have just updated firmware, it is likely that", + L"the signature verification process failed. Please verify again that the", + L"firmware was downloaded from the proper source and try updating again.", + L"", + RecoveryCodeLine, + RecoveryMsgLine, + L"", + L"Press ENTER key to continue.", + DelayLine + ); + break; + } + + Status = gBS->WaitForEvent (2, Events, &Index); + ASSERT_EFI_ERROR (Status); + + if (Index == 0) { + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + ASSERT_EFI_ERROR (Status); + + if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) { + break; + } + } else { + SecondsLeft--; + } + } + + Status = gBS->CloseEvent (TimerEvent); + ASSERT_EFI_ERROR (Status); + + gST->ConOut->EnableCursor (gST->ConOut, CursorVisible); + gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute); + + gST->ConOut->ClearScreen (gST->ConOut); + DrainInput (); +} + +STATIC +VOID +WarnIfBatteryLow ( + VOID +) +{ + EFI_STATUS Status; + EFI_EVENT TimerEvent; + EFI_EVENT Events[2]; + UINTN Index; + EFI_INPUT_KEY Key; + RETURN_STATUS RetStatus; + UINT32 BatteryCapacity; + BOOLEAN AcConnected; + BOOLEAN BatteryConnected; + BOOLEAN BatteryTooLow; + CHAR16 BatteryCapLine[81]; + CHAR16 DelayLine[81]; + BOOLEAN CursorVisible; + BOOLEAN EcReadDataFailure; + UINTN CurrentAttribute; + UINTN SecondsLeft; + EFI_TPL OriginalTPL; + + BatteryTooLow = FALSE; + EcReadDataFailure = FALSE; + + OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL); + RetStatus = LaptopGetAcState(&AcConnected); + + if (RetStatus == RETURN_UNSUPPORTED) { + gBS->RestoreTPL (OriginalTPL); + return; + } + + if (RetStatus != RETURN_SUCCESS) + EcReadDataFailure = TRUE; + + RetStatus = LaptopGetBatState(&BatteryConnected); + if (RetStatus != RETURN_SUCCESS) + EcReadDataFailure = TRUE; + + /* We only need the baterry capacity if AC not connected */ + if (!EcReadDataFailure && !AcConnected && BatteryConnected) { + RetStatus = LaptopGetBatteryCapacity(&BatteryCapacity); + if (RetStatus != RETURN_SUCCESS) + EcReadDataFailure = TRUE; + } + + gBS->RestoreTPL (OriginalTPL); + + /* Check if there is a need to display a warning */ + if (!EcReadDataFailure && BatteryConnected) { + if(AcConnected) + return; + if(!AcConnected && BatteryCapacity >= 5) + return; + } + + if (!EcReadDataFailure && !AcConnected && + BatteryConnected && BatteryCapacity < 5) + BatteryTooLow = TRUE; + + Status = gBS->CreateEvent ( + EVT_TIMER, + TPL_CALLBACK, + NULL, + NULL, + &TimerEvent + ); + ASSERT_EFI_ERROR (Status); + + CurrentAttribute = gST->ConOut->Mode->Attribute; + CursorVisible = gST->ConOut->Mode->CursorVisible; + + gST->ConOut->EnableCursor (gST->ConOut, FALSE); + + DrainInput (); + gBS->SetTimer (TimerEvent, TimerPeriodic, 1 * 1000 * 1000 * 10); + + Events[0] = gST->ConIn->WaitForKey; + Events[1] = TimerEvent; + + SecondsLeft = 10; + while (SecondsLeft > 0) { + if (BatteryTooLow) { + UnicodeSPrint ( + BatteryCapLine, + sizeof (BatteryCapLine), + L"Current battery capacity: %d%%", + BatteryCapacity + ); + + UnicodeSPrint ( + DelayLine, + sizeof (DelayLine), + L"(The laptop will shut down automatically in %d second%a.)", + SecondsLeft, + SecondsLeft == 1 ? "" : "s" + ); + + CreateMultiStringPopUp ( + 78, + 11, + L"!!! WARNING !!!", + L"", + L"The laptop's current battery is critically low (< 5%).", + L"To protect your disk data from corruption due to abrupt shut down,", + L"the laptop will power off now. Please plug the AC adapter and power", + L"the laptop on again to boot.", + L"", + BatteryCapLine, + L"", + L"Press ENTER key to shut down immediately.", + DelayLine + ); + } else if (!EcReadDataFailure && AcConnected && !BatteryConnected) { + UnicodeSPrint ( + DelayLine, + sizeof (DelayLine), + L"(The boot process will continue automatically in %d second%a.)", + SecondsLeft, + SecondsLeft == 1 ? "" : "s" + ); + + CreateMultiStringPopUp ( + 78, + 7, + L"!!! WARNING !!!", + L"", + L"The laptop's battery is not detected!", + L"Please check the battery connection or contact the manufacturer.", + L"", + L"Press ENTER key to continue.", + DelayLine + ); + } else if (EcReadDataFailure) { + UnicodeSPrint ( + DelayLine, + sizeof (DelayLine), + L"(The boot process will continue automatically in %d second%a.)", + SecondsLeft, + SecondsLeft == 1 ? "" : "s" + ); + + CreateMultiStringPopUp ( + 78, + 7, + L"!!! ERROR !!!", + L"", + L"Could not retrieve information about AC and battery state!", + L"Please contact the manufacturer.", + L"", + L"Press ENTER key to continue.", + DelayLine + ); + } + + Status = gBS->WaitForEvent (2, Events, &Index); + ASSERT_EFI_ERROR (Status); + + if (Index == 0) { + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + ASSERT_EFI_ERROR (Status); + + if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) { + break; + } + } else { + SecondsLeft--; + } + } + + Status = gBS->CloseEvent (TimerEvent); + ASSERT_EFI_ERROR (Status); + + if (BatteryTooLow) + gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL); + + gST->ConOut->EnableCursor (gST->ConOut, CursorVisible); + gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute); + + gST->ConOut->ClearScreen (gST->ConOut); + DrainInput (); +} + +STATIC +BOOLEAN +WarnIfFirmwareUpdateMode ( + VOID +) +{ + EFI_STATUS Status; + EFI_EVENT TimerEvent; + EFI_EVENT Events[2]; + UINTN Index; + EFI_INPUT_KEY Key; + EFI_TIME Time; + CHAR16 RandomDigit; + CHAR16 DelayLine[81]; + CHAR16 PressKeyLine[81]; + BOOLEAN CursorVisible; + UINTN CurrentAttribute; + UINTN SecondsLeft; + UINTN VarSize; + BOOLEAN FUMEnabled; + + VarSize = sizeof (FUMEnabled); + + Status = gRT->GetVariable ( + DASHARO_VAR_FIRMWARE_UPDATE_MODE, + &gDasharoSystemFeaturesGuid, + NULL, + &VarSize, + &FUMEnabled + ); + + if (EFI_ERROR(Status) || VarSize != sizeof(FUMEnabled) || !FUMEnabled) { + return FALSE; + } + + // + // Remove variable to disable FUM on next boot + // + Status = gRT->SetVariable ( + DASHARO_VAR_FIRMWARE_UPDATE_MODE, + &gDasharoSystemFeaturesGuid, + 0, + 0, + NULL + ); + + // + // Create volatile runtime variable so applications can detect FUM + // + Status = gRT->SetVariable ( + DASHARO_VAR_FIRMWARE_UPDATE_MODE, + &gDasharoSystemFeaturesGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + VarSize, + &FUMEnabled + ); + + Status = gBS->CreateEvent ( + EVT_TIMER, + TPL_CALLBACK, + NULL, + NULL, + &TimerEvent + ); + ASSERT_EFI_ERROR (Status); + + Status = gRT->GetTime (&Time, NULL); + // + // Don't check status, even if the call failed we still have "random" data + // from stack where Time is located. It is better than nothing, and we don't + // need more. + // + RandomDigit = L'0' + (Time.Second % 10); + + UnicodeSPrint ( + PressKeyLine, + sizeof (PressKeyLine), + L"Press %c to continue.", + RandomDigit + ); + + CurrentAttribute = gST->ConOut->Mode->Attribute; + CursorVisible = gST->ConOut->Mode->CursorVisible; + + gST->ConOut->EnableCursor (gST->ConOut, FALSE); + + DrainInput (); + gBS->SetTimer (TimerEvent, TimerPeriodic, 1 * 1000 * 1000 * 10); + + Events[0] = gST->ConIn->WaitForKey; + Events[1] = TimerEvent; + + SecondsLeft = 30; + while (SecondsLeft > 0) { + UnicodeSPrint ( + DelayLine, + sizeof (DelayLine), + L"automatically in %d second%a.)", + SecondsLeft, + SecondsLeft == 1 ? "" : "s" + ); + + CreateMultiStringPopUp ( + 78, + 11, + L"!!! WARNING !!!", + L"", + L"This message is displayed because the platform has booted in Firmware", + L"Update Mode. All firmware write protections are disabled in this mode.", + L"If you intend to update the firmware, press the key listed below to", + L"proceed; otherwise, press any other key or wait for the timeout.", + L"", + PressKeyLine, + L"", + L"(The platform will automatically reboot and disable Firmware Update Mode", + DelayLine + ); + + Status = gBS->WaitForEvent (2, Events, &Index); + ASSERT_EFI_ERROR (Status); + + if (Index == 0) { + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + ASSERT_EFI_ERROR (Status); + + if (Key.UnicodeChar == RandomDigit) { + break; + } else { + gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); + } + } else { + SecondsLeft--; + } + } + + if (SecondsLeft == 0) { + gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); + } + + Status = gBS->CloseEvent (TimerEvent); + ASSERT_EFI_ERROR (Status); + + gST->ConOut->EnableCursor (gST->ConOut, CursorVisible); + gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute); + + gST->ConOut->ClearScreen (gST->ConOut); + DrainInput (); + return TRUE; +} +/** + + Acquire the string associated with the Index from smbios structure and return it. + The caller is responsible for free the string buffer. + + @param OptionalStrStart The start position to search the string + @param Index The index of the string to extract + @param String The string that is extracted + + @retval EFI_SUCCESS The function returns EFI_SUCCESS always. + +**/ +EFI_STATUS +GetOptionalStringByIndex ( + IN CHAR8 *OptionalStrStart, + IN UINT8 Index, + OUT CHAR16 **String + ) +{ + UINTN StrSize; + + if (Index == 0) { + *String = AllocateZeroPool (sizeof (CHAR16)); + return EFI_SUCCESS; + } + + StrSize = 0; + do { + Index--; + OptionalStrStart += StrSize; + StrSize = AsciiStrSize (OptionalStrStart); + } while (OptionalStrStart[StrSize] != 0 && Index != 0); + + if ((Index != 0) || (StrSize == 1)) { + // + // Meet the end of strings set but Index is non-zero, or + // Find an empty string + // + *String = NULL; + return EFI_NOT_FOUND; + } else { + *String = AllocatePool (StrSize * sizeof (CHAR16)); + AsciiStrToUnicodeStrS (OptionalStrStart, *String, StrSize); + } + + return EFI_SUCCESS; +} + +STATIC +VOID +PrintSolStrings ( + VOID +) +{ + UINT8 StrIndex; + CHAR16 *FirmwareVersionString; + CHAR16 *EcVersionString; + CHAR16 *EcVariantString; + EFI_STATUS Status; + EFI_SMBIOS_HANDLE SmbiosHandle; + EFI_SMBIOS_PROTOCOL *Smbios; + SMBIOS_TABLE_TYPE0 *Type0Record; + SMBIOS_TABLE_TYPE11 *Type11Record; + EFI_SMBIOS_TABLE_HEADER *Record; + BOOLEAN GotType0; + BOOLEAN GotType11; + UINTN CurrentAttribute; + + GotType0 = FALSE; + GotType11 = FALSE; + + Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **) &Smbios); + + if (EFI_ERROR(Status)) + return; + + SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; + Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL); + while (!EFI_ERROR(Status)) { + if (Record->Type == SMBIOS_TYPE_BIOS_INFORMATION) { + Type0Record = (SMBIOS_TABLE_TYPE0 *) Record; + StrIndex = Type0Record->BiosVersion; + Status = GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type0Record + Type0Record->Hdr.Length), StrIndex, &FirmwareVersionString); + + if (!EFI_ERROR(Status) && (*FirmwareVersionString != 0x0000)) { + Print (L"Firmware version: %s\n", FirmwareVersionString); + } else { + Print (L"Firmware version: "); + CurrentAttribute = gST->ConOut->Mode->Attribute; + gST->ConOut->SetAttribute (gST->ConOut, EFI_RED | EFI_BRIGHT | EFI_BACKGROUND_BLACK); + Print (L"UNKNOWN\n"); + gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute); + } + GotType0 = TRUE; + } + + if (Record->Type == SMBIOS_TYPE_OEM_STRINGS) { + Type11Record = (SMBIOS_TABLE_TYPE11 *) Record; + if (Type11Record->StringCount < 2) { + DEBUG((EFI_D_ERROR, "Missing some EC strings\n")); + Print (L"EC firmware version: "); + CurrentAttribute = gST->ConOut->Mode->Attribute; + gST->ConOut->SetAttribute (gST->ConOut, EFI_RED | EFI_BRIGHT | EFI_BACKGROUND_BLACK); + Print (L"UNKNOWN\n"); + Print (L"Unable to detect EC firmware version!\n"); + Print (L"Please update your EC firmware per docs.dasharo.com instructions!\n"); + gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute); + } else { + // First string should be the EC variant + Status = GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type11Record + Type11Record->Hdr.Length), 1, &EcVariantString); + // If string is not found or not open EC, print error straight away + if (EFI_ERROR(Status) || StrStr(EcVariantString, L"EC: unknown")) { + DEBUG((EFI_D_ERROR, "Missing EC variant string or EC variant reported as unknown\n")); + Print (L"EC firmware version: "); + CurrentAttribute = gST->ConOut->Mode->Attribute; + gST->ConOut->SetAttribute (gST->ConOut, EFI_RED | EFI_BRIGHT | EFI_BACKGROUND_BLACK); + Print (L"UNKNOWN\n"); + Print (L"Unable to detect EC firmware version!\n"); + Print (L"Please update your EC firmware per docs.dasharo.com instructions!\n"); + gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute); + } else { + // Second string should be the EC firmware version. + // Print it without any error if found, because it has to be open EC now + Status = GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type11Record + Type11Record->Hdr.Length), 2, &EcVersionString); + if (EFI_ERROR(Status) || StrStr(EcVersionString, L"EC firmware version: unknown")) { + DEBUG((EFI_D_ERROR, "Missing EC version string or EC version reported as unknown\n")); + CurrentAttribute = gST->ConOut->Mode->Attribute; + gST->ConOut->SetAttribute (gST->ConOut, EFI_RED | EFI_BRIGHT | EFI_BACKGROUND_BLACK); + Print (L"UNKNOWN\n"); + Print (L"Unable to detect EC firmware version!\n"); + Print (L"Please update your EC firmware per docs.dasharo.com instructions!\n"); + gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute); + } else { + Print (L"%s\n", EcVersionString); + if (StrStr(EcVariantString, L"EC: proprietary")) { + CurrentAttribute = gST->ConOut->Mode->Attribute; + gST->ConOut->SetAttribute (gST->ConOut, EFI_RED | EFI_BRIGHT | EFI_BACKGROUND_BLACK); + Print (L"Proprietary EC firmware detected!\n"); + Print (L"Please update your EC firmware per docs.dasharo.com instructions!\n"); + gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute); + } + } + } + } + } + + if (GotType0 && GotType11) + break; + + Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL); + } +} + +STATIC +VOID +SaveSmBiosFieldToEfiVar ( + IN VOID *FieldValue, + IN UINTN FieldSize, + IN CHAR16* VarName +) +{ + VOID *CurrentValue; + EFI_STATUS Status; + UINTN CurrentSize; + BOOLEAN NeedUpdate; + + NeedUpdate = FALSE; + CurrentSize = FieldSize; + CurrentValue = AllocatePool (FieldSize); + + if (!CurrentValue) + return; + + Status = gRT->GetVariable ( + VarName, + &gDasharoSystemFeaturesGuid, + NULL, + &CurrentSize, + CurrentValue + ); + + if (EFI_ERROR (Status)) { + NeedUpdate = TRUE; + } else { + if (CurrentSize != FieldSize) + NeedUpdate = TRUE; + else if (CompareMem (CurrentValue, FieldValue, FieldSize) != 0) + NeedUpdate = TRUE; + } + + if (NeedUpdate) { + DEBUG ((EFI_D_INFO, "%s variable needs update\n", VarName)); + Status = gRT->SetVariable ( + VarName, + &gDasharoSystemFeaturesGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, + FieldSize, + FieldValue + ); + } + + FreePool(CurrentValue); +} + +STATIC +VOID +SaveSMBIOSFields ( + VOID +) +{ + UINT8 StrIndex; + EFI_STATUS Status; + EFI_SMBIOS_HANDLE SmbiosHandle; + EFI_SMBIOS_PROTOCOL *Smbios; + SMBIOS_TABLE_TYPE1 *Type1Record; + SMBIOS_TABLE_TYPE2 *Type2Record; + EFI_SMBIOS_TABLE_HEADER *Record; + BOOLEAN GotType1; + BOOLEAN GotType2; + CHAR8 *OptionalStrStart; + UINTN StrSize; + + GotType1 = FALSE; + GotType2 = FALSE; + + Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **) &Smbios); + + if (EFI_ERROR(Status)) + return; + + + SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; + Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL); + while (!EFI_ERROR(Status)) { + if (Record->Type == SMBIOS_TYPE_SYSTEM_INFORMATION) { + Type1Record = (SMBIOS_TABLE_TYPE1 *) Record; + SaveSmBiosFieldToEfiVar((VOID *)&Type1Record->Uuid, sizeof(Type1Record->Uuid), DASHARO_VAR_SMBIOS_UUID); + GotType1 = TRUE; + } + + if (Record->Type == SMBIOS_TYPE_BASEBOARD_INFORMATION) { + Type2Record = (SMBIOS_TABLE_TYPE2 *) Record; + StrIndex = Type2Record->SerialNumber; + OptionalStrStart = (CHAR8*)((UINT8*)Type2Record + Type2Record->Hdr.Length); + StrSize = 0; + do { + StrIndex--; + OptionalStrStart += StrSize; + StrSize = AsciiStrSize (OptionalStrStart); + } while (OptionalStrStart[StrSize] != 0 && StrIndex != 0); + + if ((StrIndex != 0) || (StrSize == 1)) + DEBUG((EFI_D_INFO, "SMBIOS Type2 Serial Number missing\n")); + else + SaveSmBiosFieldToEfiVar((VOID *)OptionalStrStart, StrSize, DASHARO_VAR_SMBIOS_SN); + + GotType2 = TRUE; + } + + if (GotType1 && GotType2) + break; + + Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL); + } +} + +/** + Refresh the logo on ReadyToBoot event. It will clear the screen from strings + + and progress bar when timeout is reached or continue key is pressed. + + @param Event Event pointer. + @param Context Context pass to this function. +**/ +VOID +EFIAPI +RefreshLogo ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + gBS->CloseEvent (Event); + gST->ConOut->ClearScreen (gST->ConOut); + BootLogoEnableLogo (); +} + +/** + Do the platform specific action after the console is connected. + + Such as: + Dynamically switch output mode; + Signal console ready platform customized event; + Run diagnostics like memory testing; + Connect certain devices; + Dispatch additional option roms. +**/ +VOID +EFIAPI +PlatformBootManagerAfterConsole ( + VOID +) +{ + EFI_STATUS Status; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL White; + CHAR16 *BootMenuKey; + CHAR16 *SetupMenuKey; + BOOLEAN NetBootEnabled; + BOOLEAN FUMEnabled; + BOOLEAN BootMenuEnable; + UINTN VarSize; + EFI_EVENT Event; + EFI_INPUT_KEY Enter; + + Black.Blue = Black.Green = Black.Red = Black.Reserved = 0; + White.Blue = White.Green = White.Red = White.Reserved = 0xFF; + + gST->ConOut->EnableCursor (gST->ConOut, FALSE); + gST->ConOut->ClearScreen (gST->ConOut); + + WarnIfBatteryLow (); + WarnIfRecoveryBoot (); + FUMEnabled = PcdGetBool (PcdShowFum) && WarnIfFirmwareUpdateMode (); + + + BootLogoEnableLogo (); + + // + // Register ENTER as CONTINUE key + // + Enter.ScanCode = SCAN_NULL; + Enter.UnicodeChar = CHAR_CARRIAGE_RETURN; + EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL); + + // FIXME: USB devices are not being detected unless we wait a bit. + gBS->Stall (100 * 1000); + + EfiBootManagerConnectAll (); + EfiBootManagerRefreshAllBootOption (); + + // + // Process device update capsules there weren't processed along with system + // firmware capsules on first call to ProcessCapsules() in + // PlatformBootManagerBeforeConsole(). + // + if (GetBootModeHob() == BOOT_ON_FLASH_UPDATE) { + // TODO: when enabling capsule support for laptops, add a battery check here + Status = ProcessCapsules (); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "%a(): ProcessCapsule() failed with: %r\n", __FUNCTION__, Status)); + } + + // + // Reset the system to disable SMI handler in order to exclude the + // possibility of it being used outside of the firmware + // + // In practice, this will rarely execute because even the first + // ProcessCapsules() invocation might do a reset if all capsules were + // processed and at least one of them needed a reset. This is just to catch + // a case when this doesn't happen which is possible on error. + // + gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); + } + + // + // Process TPM PPI request + // + Tcg2PhysicalPresenceLibProcessRequest (NULL); + + SaveSMBIOSFields(); + + VarSize = sizeof (NetBootEnabled); + Status = gRT->GetVariable ( + DASHARO_VAR_NETWORK_BOOT, + &gDasharoSystemFeaturesGuid, + NULL, + &VarSize, + &NetBootEnabled + ); + + // + // Register iPXE + // + if (FUMEnabled) { + DEBUG((DEBUG_INFO, "Registering iPXE boot option for FUM\n")); + PlatformRegisterFvBootOption (PcdGetPtr (PcdiPXEFile), + (CHAR16 *) PcdGetPtr(PcdiPXEOptionName), + LOAD_OPTION_ACTIVE, + TRUE); + } else if ((Status != EFI_NOT_FOUND) && (VarSize == sizeof(NetBootEnabled))) { + if (NetBootEnabled) { + DEBUG((DEBUG_INFO, "Registering iPXE boot option by variable\n")); + PlatformRegisterFvBootOption (PcdGetPtr (PcdiPXEFile), + (CHAR16 *) PcdGetPtr(PcdiPXEOptionName), + LOAD_OPTION_ACTIVE, + FALSE); + } else { + DEBUG((DEBUG_INFO, "Unregistering iPXE boot option by variable\n")); + PlatformUnregisterFvBootOption (PcdGetPtr (PcdiPXEFile), + (CHAR16 *) PcdGetPtr(PcdiPXEOptionName), + LOAD_OPTION_ACTIVE); + } + } else if ((Status == EFI_NOT_FOUND) && FixedPcdGetBool(PcdDefaultNetworkBootEnable)) { + DEBUG((DEBUG_INFO, "Registering iPXE boot option by policy\n")); + PlatformRegisterFvBootOption (PcdGetPtr (PcdiPXEFile), + (CHAR16 *) PcdGetPtr(PcdiPXEOptionName), + LOAD_OPTION_ACTIVE, + FALSE); + } else { + DEBUG((DEBUG_INFO, "Unregistering iPXE boot option\n")); + PlatformUnregisterFvBootOption (PcdGetPtr (PcdiPXEFile), + (CHAR16 *) PcdGetPtr(PcdiPXEOptionName), + LOAD_OPTION_ACTIVE); + } + // + // Register UEFI Shell + // + DEBUG((DEBUG_INFO, "Registering UEFI Shell boot option\n")); + PlatformRegisterFvBootOption (PcdGetPtr (PcdShellFile), + L"UEFI Shell", + LOAD_OPTION_ACTIVE, + FALSE); + + BootMenuKey = GetKeyStringFromScanCode (FixedPcdGet16(PcdBootMenuKey), L"F12"); + SetupMenuKey = GetKeyStringFromScanCode (FixedPcdGet16(PcdSetupMenuKey), L"ESC"); + + VarSize = sizeof (BootMenuEnable); + Status = gRT->GetVariable ( + DASHARO_VAR_BOOT_MANAGER_ENABLED, + &gDasharoSystemFeaturesGuid, + NULL, + &VarSize, + &BootMenuEnable + ); + + if (PcdGetBool (PcdPrintSolStrings)) + PrintSolStrings(); + + Print (L"%-5s to enter Setup\n", SetupMenuKey); + + if (EFI_ERROR(Status) || VarSize != sizeof(BootMenuEnable) || BootMenuEnable) + Print (L"%-5s to enter Boot Manager Menu\n", BootMenuKey); + + Print (L"ENTER to boot directly\n"); + + EfiCreateEventReadyToBootEx ( + TPL_CALLBACK, + RefreshLogo, + NULL, + &Event + ); +} + +/** + This function is called each second during the boot manager waits the timeout. + + @param TimeoutRemain The remaining timeout. +**/ +VOID +EFIAPI +PlatformBootManagerWaitCallback ( + UINT16 TimeoutRemain +) +{ + EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White; + UINT16 Timeout; + UINTN DataSize; + EFI_STATUS Status; + + DEBUG ((EFI_D_INFO, "[Bds]BdsWait ...Zzzzzzzzzzzz...\n")); + + DataSize = sizeof(Timeout); + Status = gRT->GetVariable( + EFI_TIME_OUT_VARIABLE_NAME, + &gEfiGlobalVariableGuid, + NULL, + &DataSize, + &Timeout + ); + if (EFI_ERROR (Status)) { + Timeout = PcdGet16 (PcdPlatformBootTimeOut); + } + + Black.Raw = 0x00000000; + White.Raw = 0x00FFFFFF; + + BootLogoUpdateProgress ( + White.Pixel, + Black.Pixel, + L"", + White.Pixel, + (Timeout - TimeoutRemain) * 100 / Timeout, + 0 + ); +} + +/** + The function is called when no boot option could be launched, + including platform recovery options and options pointing to applications + built into firmware volumes. + + If this function returns, BDS attempts to enter an infinite loop. +**/ +VOID +EFIAPI +PlatformBootManagerUnableToBoot ( + VOID + ) +{ + EFI_STATUS Status; + EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu; + UINTN Index; + + // + // BootManagerMenu doesn't contain the correct information when return status + // is EFI_NOT_FOUND. + // + Status = EfiBootManagerGetBootManagerMenu (&BootManagerMenu); + if (EFI_ERROR (Status)) { + return; + } + // + // Normally BdsDxe does not print anything to the system console, but this is + // a last resort -- the end-user will likely not see any DEBUG messages + // logged in this situation. + // + // AsciiPrint() will NULL-check gST->ConOut internally. We check gST->ConIn + // here to see if it makes sense to request and wait for a keypress. + // + if (gST->ConOut != NULL && gST->ConIn != NULL) { + gST->ConOut->ClearScreen (gST->ConOut); + AsciiPrint ( + "%a: No bootable option or device was found.\n" + "%a: Press any key to enter the Boot Manager Menu.\n", + gEfiCallerBaseName, + gEfiCallerBaseName + ); + Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index); + ASSERT_EFI_ERROR (Status); + ASSERT (Index == 0); + + DrainInput (); + } + + for (;;) { + EfiBootManagerBoot (&BootManagerMenu); + } +} + diff --git a/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.h b/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.h new file mode 100644 index 0000000000..a886ee75a9 --- /dev/null +++ b/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.h @@ -0,0 +1,138 @@ +/**@file + Head file for BDS Platform specific code + +Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef _PLATFORM_BOOT_MANAGER_H +#define _PLATFORM_BOOT_MANAGER_H + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN ConnectType; +} PLATFORM_CONSOLE_CONNECT_ENTRY; + +extern PLATFORM_CONSOLE_CONNECT_ENTRY gPlatformConsole[]; + +#define gEndEntire \ + { \ + END_DEVICE_PATH_TYPE,\ + END_ENTIRE_DEVICE_PATH_SUBTYPE,\ + { END_DEVICE_PATH_LENGTH, 0 },\ + } + +#define CONSOLE_OUT BIT0 +#define CONSOLE_IN BIT1 +#define STD_ERROR BIT2 + +#define CLASS_HID 3 +#define SUBCLASS_BOOT 1 +#define PROTOCOL_KEYBOARD 1 + +typedef struct { + USB_CLASS_DEVICE_PATH UsbClass; + EFI_DEVICE_PATH_PROTOCOL End; +} USB_CLASS_FORMAT_DEVICE_PATH; + +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + UINT32 Instance; +} WIN_NT_VENDOR_DEVICE_PATH_NODE; + +// +// Below is the platform console device path +// +typedef struct { + VENDOR_DEVICE_PATH NtBus; + WIN_NT_VENDOR_DEVICE_PATH_NODE SerialDevice; + UART_DEVICE_PATH Uart; + VENDOR_DEVICE_PATH TerminalType; + EFI_DEVICE_PATH_PROTOCOL End; +} NT_ISA_SERIAL_DEVICE_PATH; + +typedef struct { + VENDOR_DEVICE_PATH NtBus; + WIN_NT_VENDOR_DEVICE_PATH_NODE NtGopDevice; + EFI_DEVICE_PATH_PROTOCOL End; +} NT_PLATFORM_GOP_DEVICE_PATH; + +extern USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath; + +/** + Use SystemTable Conout to stop video based Simple Text Out consoles from going + to the video device. Put up LogoFile on every video device that is a console. + + @param[in] LogoFile File name of logo to display on the center of the screen. + + @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed. + @retval EFI_UNSUPPORTED Logo not found + +**/ +EFI_STATUS +PlatformBootManagerEnableQuietBoot ( + IN EFI_GUID *LogoFile +); + +/** + Use SystemTable Conout to turn on video based Simple Text Out consoles. The + Simple Text Out screens will now be synced up with all non video output devices + + @retval EFI_SUCCESS UGA devices are back in text mode and synced up. + +**/ +EFI_STATUS +PlatformBootManagerDisableQuietBoot ( + VOID +); + +/** + Show progress bar with title above it. It only works in Graphics mode. + + @param TitleForeground Foreground color for Title. + @param TitleBackground Background color for Title. + @param Title Title above progress bar. + @param ProgressColor Progress bar color. + @param Progress Progress (0-100) + @param PreviousValue The previous value of the progress. + + @retval EFI_STATUS Success update the progress bar + +**/ +EFI_STATUS +PlatformBootManagerShowProgress ( + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground, + IN CHAR16 *Title, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor, + IN UINTN Progress, + IN UINTN PreviousValue +); + +#endif // _PLATFORM_BOOT_MANAGER_H diff --git a/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf b/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf new file mode 100644 index 0000000000..7386861dd0 --- /dev/null +++ b/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf @@ -0,0 +1,113 @@ +## @file +# Include all platform action which can be customized by IBV/OEM. +# +# Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PlatformBootManagerLib + FILE_GUID = F0D9063A-DADB-4185-85E2-D7ACDA93F7A6 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = PlatformBootManagerLib|DXE_DRIVER + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + PlatformData.c + PlatformConsole.c + PlatformConsole.h + PlatformBootManager.c + PlatformBootManager.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + DasharoPayloadPkg/DasharoPayloadPkg.dec + DasharoModulePkg/DasharoModulePkg.dec + SecurityPkg/SecurityPkg.dec + +[LibraryClasses] + BaseLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + UefiLib + UefiBootManagerLib + BootLogoLib + PcdLib + DxeServicesLib + MemoryAllocationLib + DevicePathLib + HiiLib + IoLib + PrintLib + TimerLib + PlatformHookLib + Tcg2PhysicalPresenceLib + CustomizedDisplayLib + LaptopBatteryLib + BlParseLib + CapsuleLib + HobLib + +[Guids] + gEfiEndOfDxeEventGroupGuid + gEfiGlobalVariableGuid + gEfiPcAnsiGuid + gEfiVT100Guid + gEfiVT100PlusGuid + gEfiVTUTF8Guid + gEfiTtyTermGuid + gEdkiiLinuxTermGuid + gEdkiiXtermR6Guid + gEdkiiVT400Guid + gEdkiiSCOTermGuid + gEfiPcAnsiGuid + gDasharoSystemFeaturesGuid + +[Protocols] + gEfiGenericMemTestProtocolGuid ## CONSUMES + gEfiGraphicsOutputProtocolGuid ## CONSUMES + gEfiUgaDrawProtocolGuid ## CONSUMES + gEfiBootLogoProtocolGuid ## CONSUMES + gEfiDxeSmmReadyToLockProtocolGuid + gEfiSmmAccess2ProtocolGuid + gEfiPciRootBridgeIoProtocolGuid ## CONSUMES + gEfiDevicePathProtocolGuid ## CONSUMES + gEfiSmbiosProtocolGuid ## CONSUMES + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut + gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn + gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand + gDasharoPayloadPkgTokenSpaceGuid.PcdShellFile + gDasharoPayloadPkgTokenSpaceGuid.PcdiPXEFile + gDasharoPayloadPkgTokenSpaceGuid.PcdiPXEOptionName + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits + gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType + gDasharoPayloadPkgTokenSpaceGuid.PcdBootMenuKey + gDasharoPayloadPkgTokenSpaceGuid.PcdSetupMenuKey + gEfiMdeModulePkgTokenSpaceGuid.PcdFastPS2Detection + gEfiMdeModulePkgTokenSpaceGuid.PcdDetectPs2KbOnCmdAck + gDasharoPayloadPkgTokenSpaceGuid.PcdSkipPs2Detect + gDasharoSystemFeaturesTokenSpaceGuid.PcdDefaultNetworkBootEnable + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowPs2Option + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowFum + gDasharoPayloadPkgTokenSpaceGuid.PcdPrintSolStrings + gDasharoPayloadPkgTokenSpaceGuid.PcdSerialOnSuperIo + gDasharoSystemFeaturesTokenSpaceGuid.PcdSerialRedirectionDefaultState + gDasharoSystemFeaturesTokenSpaceGuid.PcdSerialRedirection2DefaultState + gDasharoSystemFeaturesTokenSpaceGuid.PcdHave2ndUart diff --git a/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformConsole.c b/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformConsole.c new file mode 100644 index 0000000000..cd30dd9c3f --- /dev/null +++ b/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformConsole.c @@ -0,0 +1,730 @@ +/** @file +This file include all platform action which can be customized by IBV/OEM. + +Copyright (c) 2016, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PlatformBootManager.h" +#include "PlatformConsole.h" +#include +#include +#include +#include + +#define PCI_DEVICE_PATH_NODE(Func, Dev) \ + { \ + { \ + HARDWARE_DEVICE_PATH, \ + HW_PCI_DP, \ + { \ + (UINT8) (sizeof (PCI_DEVICE_PATH)), \ + (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8) \ + } \ + }, \ + (Func), \ + (Dev) \ + } + +#define PNPID_DEVICE_PATH_NODE(PnpId) \ + { \ + { \ + ACPI_DEVICE_PATH, \ + ACPI_DP, \ + { \ + (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \ + (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \ + }, \ + }, \ + EISA_PNP_ID((PnpId)), \ + 0 \ + } + +#define gUartVendor \ + { \ + { \ + HARDWARE_DEVICE_PATH, \ + HW_VENDOR_DP, \ + { \ + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), \ + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) \ + } \ + }, \ + EDKII_SERIAL_PORT_LIB_VENDOR_GUID \ + } + +#define gUart \ + { \ + { \ + MESSAGING_DEVICE_PATH, \ + MSG_UART_DP, \ + { \ + (UINT8) (sizeof (UART_DEVICE_PATH)), \ + (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8) \ + } \ + }, \ + 0, \ + 115200, \ + 8, \ + 1, \ + 1 \ + } + +#define gPcAnsiTerminal \ + { \ + { \ + MESSAGING_DEVICE_PATH, \ + MSG_VENDOR_DP, \ + { \ + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), \ + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) \ + } \ + }, \ + DEVICE_PATH_MESSAGING_PC_ANSI \ + } + +#define gPciRootBridge \ + PNPID_DEVICE_PATH_NODE(0x0A03) + +#define gPnp16550ComPort \ + PNPID_DEVICE_PATH_NODE(0x0501) + +#define gPnpPs2Keyboard \ + PNPID_DEVICE_PATH_NODE(0x0303) + +#define KEYBOARD_8042_DATA_REGISTER 0x60 +#define KEYBOARD_8042_STATUS_REGISTER 0x64 + +#define KBC_INPBUF_VIA60_KBECHO 0xEE +#define KEYBOARD_CMDECHO_ACK 0xFA +#define KEYBOARD_CMD_RESEND 0xFE + +#define KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA BIT0 +#define KEYBOARD_STATUS_REGISTER_HAS_INPUT_DATA BIT1 +#define KEYBOARD_STATUS_REGISTER_RECEIVE_TIMEOUT BIT6 + +#define KEYBOARD_TIMEOUT 65536 // 0.07s +#define KEYBOARD_WAITFORVALUE_TIMEOUT 1000000 // 1s + +typedef enum _TYPE_OF_TERMINAL { + TerminalTypePcAnsi = 0, + TerminalTypeVt100, + TerminalTypeVt100Plus, + TerminalTypeVtUtf8, + TerminalTypeTtyTerm, + TerminalTypeLinux, + TerminalTypeXtermR6, + TerminalTypeVt400, + TerminalTypeSCO +} TYPE_OF_TERMINAL; + +ACPI_HID_DEVICE_PATH gPnpPs2KeyboardDeviceNode = gPnpPs2Keyboard; +ACPI_HID_DEVICE_PATH gPnp16550ComPortDeviceNode = gPnp16550ComPort; +UART_DEVICE_PATH gUartDeviceNode = gUart; +VENDOR_DEVICE_PATH gTerminalTypeDeviceNode = gPcAnsiTerminal; +VENDOR_DEVICE_PATH gUartDeviceVendorNode = gUartVendor; + +BOOLEAN mDetectDisplayOnly; +/** + Check if PS2 keyboard is connected, by sending ECHO command. + @param none + @retval TRUE connected + @retvar FALSE unconnected +**/ +BOOLEAN +DetectPs2Keyboard ( + VOID + ) +{ + UINT32 TimeOut; + UINT32 RegEmptied; + UINT8 Data; + UINT8 Status; + UINT32 SumTimeOut; + UINT32 GotIt; + + TimeOut = 0; + RegEmptied = 0; + + if (PcdGetBool (PcdSkipPs2Detect)) + return TRUE; + + // + // Wait for input buffer empty + // + for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) { + if ((IoRead8 (KEYBOARD_8042_STATUS_REGISTER) & KEYBOARD_STATUS_REGISTER_HAS_INPUT_DATA) == 0) { + RegEmptied = 1; + break; + } + MicroSecondDelay (30); + } + + if (RegEmptied == 0) { + DEBUG ((EFI_D_INFO, "PS2 reg not emptied\n")); + return FALSE; + } + + // + // Write it + // + IoWrite8 (KEYBOARD_8042_DATA_REGISTER, KBC_INPBUF_VIA60_KBECHO); + + // + // wait for 1s + // + GotIt = 0; + TimeOut = 0; + SumTimeOut = 0; + Data = 0; + Status = 0; + + // + // Read from 8042 (multiple times if needed) + // until the expected value appears + // use SumTimeOut to control the iteration + // + while (1) { + + // + // Perform a read + // + for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) { + Status = IoRead8 (KEYBOARD_8042_STATUS_REGISTER); + Data = IoRead8 (KEYBOARD_8042_DATA_REGISTER); + MicroSecondDelay (30); + } + + SumTimeOut += TimeOut; + + if (PcdGetBool (PcdDetectPs2KbOnCmdAck)) { + if(Data == KEYBOARD_CMDECHO_ACK) { + GotIt = 1; + break; + } + } + + // If keyboard not connected, the timeout will occur + if (Status & KEYBOARD_STATUS_REGISTER_RECEIVE_TIMEOUT || Data == KEYBOARD_CMD_RESEND) { + DEBUG ((EFI_D_INFO, "PS/2 receive timeout, keyboard not connected\n")); + GotIt = 0; + break; + } + + if (SumTimeOut >= KEYBOARD_WAITFORVALUE_TIMEOUT || PcdGetBool (PcdFastPS2Detection)) { + // Some PS/2 controllers may not respond to echo command. + // Assume keyboard connected if no timeout has been detected + DEBUG ((EFI_D_INFO, "PS/2 detect timeout\n")); + if (Data == KBC_INPBUF_VIA60_KBECHO) { + GotIt = 1; + break; + } + break; + } + } + + // + // Check results + // + if (GotIt == 1) { + return TRUE; + } else { + return FALSE; + } +} + +STATIC +VOID +RegisterUartConsole ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *UartNode, + IN UINT32 UartNumber +) +{ + EFI_STATUS Status; + BOOLEAN UartEnabled; + UINTN VarSize; + CHAR16 *DevPathStr; + + VarSize = sizeof (UartEnabled); + Status = gRT->GetVariable ( + UartNumber == 1 ? DASHARO_VAR_SERIAL_REDIRECTION2 : DASHARO_VAR_SERIAL_REDIRECTION, + &gDasharoSystemFeaturesGuid, + NULL, + &VarSize, + &UartEnabled + ); + + if (EFI_ERROR (Status)) { + if (UartNumber == 1) + UartEnabled = PcdGetBool (PcdHave2ndUart) ? PcdGetBool (PcdSerialRedirection2DefaultState) : FALSE; + else + UartEnabled = PcdGetBool (PcdSerialRedirectionDefaultState); + } + + if (PcdGetBool (PcdSerialOnSuperIo)) + DevicePath = AppendDevicePathNode ((EFI_DEVICE_PATH_PROTOCOL *)DevicePath, UartNode); + else + DevicePath = AppendDevicePathNode ((EFI_DEVICE_PATH_PROTOCOL *)NULL, UartNode); + + DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode); + DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode); + + // + // Print Device Path + // + DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE); + if (DevPathStr != NULL) { + DEBUG(( + EFI_D_INFO, + "%segistering UART Console: COM%d DevPath: %s\n", + UartEnabled ? L"R" : L"Unr", + UartNumber + 1, + DevPathStr + )); + FreePool(DevPathStr); + } + + if (UartEnabled) { + EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL); + EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL); + EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL); + } else { + EfiBootManagerUpdateConsoleVariable (ConOut, NULL, DevicePath); + EfiBootManagerUpdateConsoleVariable (ConIn, NULL, DevicePath); + EfiBootManagerUpdateConsoleVariable (ErrOut, NULL, DevicePath); + } +} + +/** + Add IsaKeyboard to ConIn; add IsaSerial to ConOut, ConIn, ErrOut. + + @param[in] DeviceHandle Handle of the LPC Bridge device. + + @retval EFI_SUCCESS Console devices on the LPC bridge have been added to + ConOut, ConIn, and ErrOut. + + @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing + from DeviceHandle. +**/ +EFI_STATUS +PrepareLpcBridgeDevicePath ( + IN EFI_HANDLE DeviceHandle +) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + EFI_GUID TerminalTypeGuid; + BOOLEAN Ps2Enabled; + UINTN VarSize; + + DevicePath = NULL; + Status = gBS->HandleProtocol ( + DeviceHandle, + &gEfiDevicePathProtocolGuid, + (VOID*)&DevicePath + ); + if (EFI_ERROR (Status)) { + return Status; + } + + TempDevicePath = DevicePath; + + /* Don't bother with adding PS/2 keyboard if PS/2 not enabled in the project */ + if (PcdGetBool (PcdShowPs2Option)) { + DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode); + + VarSize = sizeof (Ps2Enabled); + Status = gRT->GetVariable ( + DASHARO_VAR_PS2_CONTROLLER, + &gDasharoSystemFeaturesGuid, + NULL, + &VarSize, + &Ps2Enabled + ); + + if ((Status == EFI_SUCCESS) && (VarSize == sizeof(Ps2Enabled))) { + if (Ps2Enabled) { + DEBUG ((DEBUG_INFO, "PS/2 controller enabled\n")); + if (DetectPs2Keyboard()) { + // + // Register Keyboard + // + DEBUG ((DEBUG_INFO, "PS/2 keyboard connected\n")); + EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL); + } else { + // Remove PS/2 Keyboard from ConIn + DEBUG ((DEBUG_INFO, "PS/2 keyboard not connected\n")); + EfiBootManagerUpdateConsoleVariable (ConIn, NULL, DevicePath); + } + } else { + DEBUG ((DEBUG_INFO, "PS/2 controller disabled\n")); + // Remove PS/2 Keyboard from ConIn + EfiBootManagerUpdateConsoleVariable (ConIn, NULL, DevicePath); + } + } else { + DEBUG ((DEBUG_INFO, "PS/2 controller variable status %r\n", Status)); + if (DetectPs2Keyboard()) { + // + // Register Keyboard + // + DEBUG ((DEBUG_INFO, "PS/2 keyboard connected\n")); + EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL); + } + } + } // PcdShowPs2Option + + switch (PcdGet8 (PcdDefaultTerminalType)) { + case TerminalTypePcAnsi: TerminalTypeGuid = gEfiPcAnsiGuid; break; + case TerminalTypeVt100: TerminalTypeGuid = gEfiVT100Guid; break; + case TerminalTypeVt100Plus: TerminalTypeGuid = gEfiVT100PlusGuid; break; + case TerminalTypeVtUtf8: TerminalTypeGuid = gEfiVTUTF8Guid; break; + case TerminalTypeTtyTerm: TerminalTypeGuid = gEfiTtyTermGuid; break; + case TerminalTypeLinux: TerminalTypeGuid = gEdkiiLinuxTermGuid; break; + case TerminalTypeXtermR6: TerminalTypeGuid = gEdkiiXtermR6Guid; break; + case TerminalTypeVt400: TerminalTypeGuid = gEdkiiVT400Guid; break; + case TerminalTypeSCO: TerminalTypeGuid = gEdkiiSCOTermGuid; break; + default: TerminalTypeGuid = gEfiPcAnsiGuid; break; + } + + CopyGuid (&gTerminalTypeDeviceNode.Guid, &TerminalTypeGuid); + + if (!PcdGetBool (PcdSerialOnSuperIo)) { + // + // Register COM1 + // + DevicePath = TempDevicePath; + + RegisterUartConsole(DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceVendorNode, 0); + } else { + // + // Register COM1 + // + DevicePath = TempDevicePath; + + gPnp16550ComPortDeviceNode.UID = 0; + RegisterUartConsole(DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode, 0); + + // + // Register COM2 + // + DevicePath = TempDevicePath; + gPnp16550ComPortDeviceNode.UID = 1; + + RegisterUartConsole(DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode, 1); + + } + + return EFI_SUCCESS; +} + +/** + Add PCI Serial to ConOut, ConIn, ErrOut. + + @param[in] DeviceHandle - Handle of PciIo protocol. + + @retval EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut. + @retval EFI_STATUS - No PCI Serial device is added. + +**/ +EFI_STATUS +PreparePciSerialDevicePath ( + IN EFI_HANDLE DeviceHandle +) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + BOOLEAN PciSerialEnabled; + UINTN VarSize; + CHAR16 *DevPathStr; + + DevicePath = NULL; + Status = gBS->HandleProtocol ( + DeviceHandle, + &gEfiDevicePathProtocolGuid, + (VOID*)&DevicePath + ); + if (EFI_ERROR (Status)) { + return Status; + } + + VarSize = sizeof (PciSerialEnabled); + Status = gRT->GetVariable ( + DASHARO_VAR_SERIAL_REDIRECTION, + &gDasharoSystemFeaturesGuid, + NULL, + &VarSize, + &PciSerialEnabled + ); + + if (EFI_ERROR (Status)) + PciSerialEnabled = PcdGetBool (PcdSerialRedirectionDefaultState); + + DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode); + DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode); + // + // Print Device Path + // + DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE); + if (DevPathStr != NULL) { + DEBUG(( + EFI_D_INFO, + "%segistering PCI Serial Console, DevPath: %s\n", + PciSerialEnabled ? L"R" : L"Unr", + DevPathStr + )); + FreePool(DevPathStr); + } + + if (PciSerialEnabled) { + EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL); + EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL); + EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL); + } else { + EfiBootManagerUpdateConsoleVariable (ConOut, NULL, DevicePath); + EfiBootManagerUpdateConsoleVariable (ConIn, NULL, DevicePath); + EfiBootManagerUpdateConsoleVariable (ErrOut, NULL, DevicePath); + } + + return EFI_SUCCESS; +} + + +/** + For every PCI instance execute a callback function. + + @param[in] Id - The protocol GUID for callback + @param[in] CallBackFunction - The callback function + @param[in] Context - The context of the callback + + @retval EFI_STATUS - Callback function failed. + +**/ +EFI_STATUS +EFIAPI +VisitAllInstancesOfProtocol ( + IN EFI_GUID *Id, + IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction, + IN VOID *Context +) +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + VOID *Instance; + + // + // Start to check all the PciIo to find all possible device + // + HandleCount = 0; + HandleBuffer = NULL; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + Id, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance); + if (EFI_ERROR (Status)) { + continue; + } + + Status = (*CallBackFunction) ( + HandleBuffer[Index], + Instance, + Context + ); + } + + gBS->FreePool (HandleBuffer); + + return EFI_SUCCESS; +} + + +/** + For every PCI instance execute a callback function. + + @param[in] Handle - The PCI device handle + @param[in] Instance - The instance of the PciIo protocol + @param[in] Context - The context of the callback + + @retval EFI_STATUS - Callback function failed. + +**/ +EFI_STATUS +EFIAPI +VisitingAPciInstance ( + IN EFI_HANDLE Handle, + IN VOID *Instance, + IN VOID *Context +) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE00 Pci; + + PciIo = (EFI_PCI_IO_PROTOCOL*) Instance; + + // + // Check for all PCI device + // + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (Pci) / sizeof (UINT32), + &Pci + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) ( + Handle, + PciIo, + &Pci + ); + +} + + +/** + For every PCI instance execute a callback function. + + @param[in] CallBackFunction - Callback function pointer + + @retval EFI_STATUS - Callback function failed. + +**/ +EFI_STATUS +EFIAPI +VisitAllPciInstances ( + IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction +) +{ + return VisitAllInstancesOfProtocol ( + &gEfiPciIoProtocolGuid, + VisitingAPciInstance, + (VOID*)(UINTN) CallBackFunction + ); +} + + +/** + Do platform specific PCI Device check and add them to + ConOut, ConIn, ErrOut. + + @param[in] Handle - Handle of PCI device instance + @param[in] PciIo - PCI IO protocol instance + @param[in] Pci - PCI Header register block + + @retval EFI_SUCCESS - PCI Device check and Console variable update successfully. + @retval EFI_STATUS - PCI Device check or Console variable update fail. + +**/ +EFI_STATUS +EFIAPI +DetectAndPreparePlatformPciDevicePath ( + IN EFI_HANDLE Handle, + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN PCI_TYPE00 *Pci +) +{ + EFI_STATUS Status; + + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + EFI_PCI_DEVICE_ENABLE, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Here we decide whether it is LPC Bridge + // + if ((IS_PCI_LPC (Pci)) || + ((IS_PCI_ISA_PDECODE (Pci)) && (Pci->Hdr.VendorId == 0x8086))) { + // + // Add IsaKeyboard to ConIn, + // add IsaSerial to ConOut, ConIn, ErrOut + // + DEBUG ((DEBUG_INFO, "Found LPC Bridge device\n")); + PrepareLpcBridgeDevicePath (Handle); + return EFI_SUCCESS; + } + // + // Here we decide which Serial device to enable in PCI bus + // + if (IS_PCI_16550SERIAL (Pci) && !PcdGetBool (PcdSerialOnSuperIo)) { + // + // Add them to ConOut, ConIn, ErrOut. + // + DEBUG ((DEBUG_INFO, "Found PCI 16550 SERIAL device\n")); + PreparePciSerialDevicePath (Handle); + return EFI_SUCCESS; + } + + return Status; +} + + +/** + Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut + + @param[in] DetectDisplayOnly - Only detect display device if it's TRUE. + + @retval EFI_SUCCESS - PCI Device check and Console variable update successfully. + @retval EFI_STATUS - PCI Device check or Console variable update fail. + +**/ +EFI_STATUS +DetectAndPreparePlatformPciDevicePaths ( + BOOLEAN DetectDisplayOnly + ) +{ + mDetectDisplayOnly = DetectDisplayOnly; + + EfiBootManagerUpdateConsoleVariable ( + ConIn, + (EFI_DEVICE_PATH_PROTOCOL *) &gUsbClassKeyboardDevicePath, + NULL + ); + + return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath); +} + + + +/** + Platform console init. Include the platform firmware vendor, revision + and so crc check. + +**/ +VOID +EFIAPI +PlatformConsoleInit ( + VOID +) +{ + gUartDeviceNode.BaudRate = PcdGet64 (PcdUartDefaultBaudRate); + gUartDeviceNode.DataBits = PcdGet8 (PcdUartDefaultDataBits); + gUartDeviceNode.Parity = PcdGet8 (PcdUartDefaultParity); + gUartDeviceNode.StopBits = PcdGet8 (PcdUartDefaultStopBits); + + // + // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut + // + DetectAndPreparePlatformPciDevicePaths (FALSE); + +} diff --git a/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformConsole.h b/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformConsole.h new file mode 100644 index 0000000000..68855ccfa5 --- /dev/null +++ b/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformConsole.h @@ -0,0 +1,72 @@ +/** @file +Head file for BDS Platform specific code + +Copyright (c) 2016, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef _PLATFORM_CONSOLE_H +#define _PLATFORM_CONSOLE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IS_PCI_ISA_PDECODE(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA_PDECODE, 0) +#define IS_PCI_16550SERIAL(_p) IS_CLASS3 (_p, PCI_CLASS_SCC, PCI_SUBCLASS_SERIAL, PCI_IF_16550) + +// +// Type definitions +// + +// +// Platform Root Bridge +// +typedef struct { + ACPI_HID_DEVICE_PATH PciRootBridge; + EFI_DEVICE_PATH_PROTOCOL End; +} PLATFORM_ROOT_BRIDGE_DEVICE_PATH; + +typedef +EFI_STATUS +(EFIAPI *PROTOCOL_INSTANCE_CALLBACK)( + IN EFI_HANDLE Handle, + IN VOID *Instance, + IN VOID *Context +); + +/** + @param[in] Handle - Handle of PCI device instance + @param[in] PciIo - PCI IO protocol instance + @param[in] Pci - PCI Header register block +**/ +typedef +EFI_STATUS +(EFIAPI *VISIT_PCI_INSTANCE_CALLBACK)( + IN EFI_HANDLE Handle, + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN PCI_TYPE00 *Pci +); + +/** + Platform console init. Include the platform firmware vendor, revision + and so crc check. + +**/ +VOID +EFIAPI +PlatformConsoleInit ( + VOID +); + +#endif diff --git a/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformData.c b/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformData.c new file mode 100644 index 0000000000..d17e660e0f --- /dev/null +++ b/DasharoPayloadPkg/Library/PlatformBootManagerLib/PlatformData.c @@ -0,0 +1,39 @@ +/**@file + Defined the platform specific device path which will be filled to + ConIn/ConOut variables. + +Copyright (c) 2016, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "PlatformBootManager.h" + +/// +/// Predefined platform default console device path +/// +GLOBAL_REMOVE_IF_UNREFERENCED PLATFORM_CONSOLE_CONNECT_ENTRY gPlatformConsole[] = { + { + NULL, + 0 + } +}; + + +GLOBAL_REMOVE_IF_UNREFERENCED USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath = { + { + { + MESSAGING_DEVICE_PATH, + MSG_USB_CLASS_DP, + { + (UINT8) (sizeof (USB_CLASS_DEVICE_PATH)), + (UINT8) ((sizeof (USB_CLASS_DEVICE_PATH)) >> 8) + } + }, + 0xffff, // VendorId + 0xffff, // ProductId + CLASS_HID, // DeviceClass + SUBCLASS_BOOT, // DeviceSubClass + PROTOCOL_KEYBOARD // DeviceProtocol + }, + gEndEntire +}; diff --git a/DasharoPayloadPkg/Library/PlatformHookLib/PlatformHookLib.c b/DasharoPayloadPkg/Library/PlatformHookLib/PlatformHookLib.c new file mode 100644 index 0000000000..72a17dc8a7 --- /dev/null +++ b/DasharoPayloadPkg/Library/PlatformHookLib/PlatformHookLib.c @@ -0,0 +1,98 @@ +/** @file + Platform Hook Library instance for UART device. + + Copyright (c) 2015, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include + +typedef struct { + UINT16 VendorId; ///< Vendor ID to match the PCI device. The value 0xFFFF terminates the list of entries. + UINT16 DeviceId; ///< Device ID to match the PCI device + UINT32 ClockRate; ///< UART clock rate. Set to 0 for default clock rate of 1843200 Hz + UINT64 Offset; ///< The byte offset into to the BAR + UINT8 BarIndex; ///< Which BAR to get the UART base address + UINT8 RegisterStride; ///< UART register stride in bytes. Set to 0 for default register stride of 1 byte. + UINT16 ReceiveFifoDepth; ///< UART receive FIFO depth in bytes. Set to 0 for a default FIFO depth of 16 bytes. + UINT16 TransmitFifoDepth; ///< UART transmit FIFO depth in bytes. Set to 0 for a default FIFO depth of 16 bytes. + UINT8 Reserved[2]; +} PCI_SERIAL_PARAMETER; + +/** + Performs platform specific initialization required for the CPU to access + the hardware associated with a SerialPortLib instance. This function does + not initialize the serial port hardware itself. Instead, it initializes + hardware devices that are required for the CPU to access the serial port + hardware. This function may be called more than once. + + @retval RETURN_SUCCESS The platform specific initialization succeeded. + @retval RETURN_DEVICE_ERROR The platform specific initialization could not be completed. + +**/ +RETURN_STATUS +EFIAPI +PlatformHookSerialPortInitialize ( + VOID + ) +{ + RETURN_STATUS Status; + UINT32 DeviceVendor; + PCI_SERIAL_PARAMETER *SerialParam; + SERIAL_PORT_INFO SerialPortInfo; + + Status = ParseSerialInfo (&SerialPortInfo); + if (RETURN_ERROR (Status)) { + return Status; + } + + if (SerialPortInfo.Type == PLD_SERIAL_TYPE_MEMORY_MAPPED) { + Status = PcdSetBoolS (PcdSerialUseMmio, TRUE); + } else { //IO + Status = PcdSetBoolS (PcdSerialUseMmio, FALSE); + } + if (RETURN_ERROR (Status)) { + return Status; + } + Status = PcdSet64S (PcdSerialRegisterBase, SerialPortInfo.BaseAddr); + if (RETURN_ERROR (Status)) { + return Status; + } + + Status = PcdSet32S (PcdSerialRegisterStride, SerialPortInfo.RegWidth); + if (RETURN_ERROR (Status)) { + return Status; + } + + Status = PcdSet32S (PcdSerialBaudRate, SerialPortInfo.Baud); + if (RETURN_ERROR (Status)) { + return Status; + } + + Status = PcdSet64S (PcdUartDefaultBaudRate, SerialPortInfo.Baud); + if (RETURN_ERROR (Status)) { + return Status; + } + + Status = PcdSet32S (PcdSerialClockRate, SerialPortInfo.InputHertz); + if (RETURN_ERROR (Status)) { + return Status; + } + + if (SerialPortInfo.UartPciAddr >= 0x80000000) { + DeviceVendor = PciRead32 (SerialPortInfo.UartPciAddr & 0x0ffff000); + SerialParam = PcdGetPtr(PcdPciSerialParameters); + SerialParam->VendorId = (UINT16)DeviceVendor; + SerialParam->DeviceId = DeviceVendor >> 16; + SerialParam->ClockRate = SerialPortInfo.InputHertz; + SerialParam->RegisterStride = (UINT8)SerialPortInfo.RegWidth; + } + + return RETURN_SUCCESS; +} diff --git a/DasharoPayloadPkg/Library/PlatformHookLib/PlatformHookLib.inf b/DasharoPayloadPkg/Library/PlatformHookLib/PlatformHookLib.inf new file mode 100644 index 0000000000..0025130714 --- /dev/null +++ b/DasharoPayloadPkg/Library/PlatformHookLib/PlatformHookLib.inf @@ -0,0 +1,39 @@ +## @file +# Platform Hook Library instance for UART device. +# +# Copyright (c) 2015, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PlatformHookLib + FILE_GUID = 40A2CBC6-CFB8-447b-A90E-198E88FD345E + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PlatformHookLib + CONSTRUCTOR = PlatformHookSerialPortInitialize + +[Sources] + PlatformHookLib.c + +[LibraryClasses] + BlParseLib + PcdLib + PciLib + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + DasharoPayloadPkg/DasharoPayloadPkg.dec + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseMmio ## PRODUCES + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase ## PRODUCES + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialBaudRate ## PRODUCES + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterStride ## PRODUCES + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialClockRate ## PRODUCES + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate ## PRODUCES + gEfiMdeModulePkgTokenSpaceGuid.PcdPciSerialParameters ## PRODUCES diff --git a/DasharoPayloadPkg/Library/PlatformSupportLibNull/PlatformSupportLibNull.c b/DasharoPayloadPkg/Library/PlatformSupportLibNull/PlatformSupportLibNull.c new file mode 100644 index 0000000000..a1b129814e --- /dev/null +++ b/DasharoPayloadPkg/Library/PlatformSupportLibNull/PlatformSupportLibNull.c @@ -0,0 +1,29 @@ +/** @file + Include all platform specific features which can be customized by IBV/OEM. + +Copyright (c) 2016, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +/** + Parse platform specific information from coreboot. + + @retval RETURN_SUCCESS The platform specific coreboot support succeeded. + @retval RETURN_DEVICE_ERROR The platform specific coreboot support could not be completed. + +**/ +EFI_STATUS +EFIAPI +ParsePlatformInfo ( + VOID + ) +{ + return EFI_SUCCESS; +} + diff --git a/DasharoPayloadPkg/Library/PlatformSupportLibNull/PlatformSupportLibNull.inf b/DasharoPayloadPkg/Library/PlatformSupportLibNull/PlatformSupportLibNull.inf new file mode 100644 index 0000000000..1fe2429829 --- /dev/null +++ b/DasharoPayloadPkg/Library/PlatformSupportLibNull/PlatformSupportLibNull.inf @@ -0,0 +1,28 @@ +## @file +# Include all platform specific features which can be customized by IBV/OEM. +# +# Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PlatformSupportLib + FILE_GUID = B42AA265-00CA-4d4b-AC14-DBD5268E1BC7 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PlatformSupportLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + PlatformSupportLibNull.c + +[Packages] + MdePkg/MdePkg.dec + DasharoPayloadPkg/DasharoPayloadPkg.dec diff --git a/DasharoPayloadPkg/Library/ResetSystemLib/ResetSystemLib.c b/DasharoPayloadPkg/Library/ResetSystemLib/ResetSystemLib.c new file mode 100644 index 0000000000..2e4b7fe592 --- /dev/null +++ b/DasharoPayloadPkg/Library/ResetSystemLib/ResetSystemLib.c @@ -0,0 +1,153 @@ +/** @file + Reset System Library functions for bootloader + + Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include + +ACPI_BOARD_INFO mAcpiBoardInfo; + +/** + The constructor function to initialize mAcpiBoardInfo. + + @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS. + +**/ +RETURN_STATUS +EFIAPI +ResetSystemLibConstructor ( + VOID + ) +{ + EFI_HOB_GUID_TYPE *GuidHob; + ACPI_BOARD_INFO *AcpiBoardInfoPtr; + + // + // Find the acpi board information guid hob + // + GuidHob = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid); + ASSERT (GuidHob != NULL); + + AcpiBoardInfoPtr = (ACPI_BOARD_INFO *)GET_GUID_HOB_DATA (GuidHob); + CopyMem (&mAcpiBoardInfo, AcpiBoardInfoPtr, sizeof (ACPI_BOARD_INFO)); + + return EFI_SUCCESS; +} + + +VOID +AcpiPmControl ( + UINTN SuspendType + ) +{ + UINTN PmCtrlReg; + + ASSERT (SuspendType <= 7); + + PmCtrlReg = (UINTN)mAcpiBoardInfo.PmCtrlRegBase; + IoAndThenOr16 (PmCtrlReg, (UINT16) ~0x3c00, (UINT16) (SuspendType << 10)); + IoOr16 (PmCtrlReg, BIT13); + CpuDeadLoop (); +} + +/** + Calling this function causes a system-wide reset. This sets + all circuitry within the system to its initial state. This type of reset + is asynchronous to system operation and operates without regard to + cycle boundaries. + + System reset should not return, if it returns, it means the system does + not support cold reset. +**/ +VOID +EFIAPI +ResetCold ( + VOID + ) +{ + IoWrite8 ((UINTN)mAcpiBoardInfo.ResetRegAddress, mAcpiBoardInfo.ResetValue); + CpuDeadLoop (); +} + +/** + Calling this function causes a system-wide initialization. The processors + are set to their initial state, and pending cycles are not corrupted. + + System reset should not return, if it returns, it means the system does + not support warm reset. +**/ +VOID +EFIAPI +ResetWarm ( + VOID + ) +{ + IoWrite8 ((UINTN)mAcpiBoardInfo.ResetRegAddress, mAcpiBoardInfo.ResetValue); + CpuDeadLoop (); +} + +/** + Calling this function causes the system to enter a power state equivalent + to the ACPI G2/S5 or G3 states. + + System shutdown should not return, if it returns, it means the system does + not support shut down reset. +**/ +VOID +EFIAPI +ResetShutdown ( + VOID + ) +{ + UINTN PmCtrlReg; + + // + // GPE0_EN should be disabled to avoid any GPI waking up the system from S5 + // + IoWrite16 ((UINTN)mAcpiBoardInfo.PmGpeEnBase, 0); + + // + // Clear Power Button Status + // + IoWrite16((UINTN) mAcpiBoardInfo.PmEvtBase, BIT8); + + // + // Transform system into S5 sleep state + // + PmCtrlReg = (UINTN)mAcpiBoardInfo.PmCtrlRegBase; + IoAndThenOr16 (PmCtrlReg, (UINT16) ~0x3c00, (UINT16) (7 << 10)); + IoOr16 (PmCtrlReg, BIT13); + CpuDeadLoop (); + + ASSERT (FALSE); +} + +/** + This function causes a systemwide 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. + + @param[in] DataSize The size, in bytes, of ResetData. + @param[in] ResetData The data buffer starts with a Null-terminated string, + followed by the EFI_GUID. +**/ +VOID +EFIAPI +ResetPlatformSpecific ( + IN UINTN DataSize, + IN VOID *ResetData + ) +{ + ResetCold (); +} diff --git a/DasharoPayloadPkg/Library/ResetSystemLib/ResetSystemLib.inf b/DasharoPayloadPkg/Library/ResetSystemLib/ResetSystemLib.inf new file mode 100644 index 0000000000..cc4b0bc81d --- /dev/null +++ b/DasharoPayloadPkg/Library/ResetSystemLib/ResetSystemLib.inf @@ -0,0 +1,40 @@ +## @file +# Library instance for ResetSystem library class for bootloader +# +# Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ResetSystemLib + FILE_GUID = C5CD4EEE-527F-47df-9C92-B41414AF7479 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = ResetSystemLib + + CONSTRUCTOR = ResetSystemLibConstructor +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + ResetSystemLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + DasharoPayloadPkg/DasharoPayloadPkg.dec + +[LibraryClasses] + DebugLib + IoLib + HobLib + BaseMemoryLib + +[Guids] + gUefiAcpiBoardInfoGuid + diff --git a/DasharoPayloadPkg/Library/SblParseLib/SblParseLib.c b/DasharoPayloadPkg/Library/SblParseLib/SblParseLib.c new file mode 100644 index 0000000000..6f6d6ed3a5 --- /dev/null +++ b/DasharoPayloadPkg/Library/SblParseLib/SblParseLib.c @@ -0,0 +1,275 @@ +/** @file + This library will parse the Slim Bootloader to get required information. + + Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/** + This function retrieves the parameter base address from boot loader. + + This function will get bootloader specific parameter address for UEFI payload. + e.g. HobList pointer for Slim Bootloader, and coreboot table header for Coreboot. + + @retval NULL Failed to find the GUID HOB. + @retval others GUIDed HOB data pointer. + +**/ +VOID * +EFIAPI +GetParameterBase ( + VOID + ) +{ + EFI_HOB_HANDOFF_INFO_TABLE *HandoffTable; + + HandoffTable = (EFI_HOB_HANDOFF_INFO_TABLE *)(UINTN) GET_BOOTLOADER_PARAMETER (); + if ((HandoffTable->Header.HobType == EFI_HOB_TYPE_HANDOFF) && + (HandoffTable->Header.HobLength == sizeof (EFI_HOB_HANDOFF_INFO_TABLE)) && + (HandoffTable->Header.Reserved == 0)) { + return (VOID *)HandoffTable; + } + + return NULL; +} + + +/** + This function retrieves a GUIDed HOB data from Slim Bootloader. + + This function will search SBL HOB list to find the first GUIDed HOB that + its GUID matches Guid. + + @param[in] Guid A pointer to HOB GUID to search. + + @retval NULL Failed to find the GUID HOB. + @retval others GUIDed HOB data pointer. + +**/ +VOID * +GetGuidHobDataFromSbl ( + IN EFI_GUID *Guid + ) +{ + UINT8 *GuidHob; + CONST VOID *HobList; + + HobList = GetParameterBase (); + ASSERT (HobList != NULL); + GuidHob = GetNextGuidHob (Guid, HobList); + if (GuidHob != NULL) { + return GET_GUID_HOB_DATA (GuidHob); + } + + return NULL; +} + +/** + Acquire the memory map information. + + @param MemInfoCallback The callback routine + @param Params Pointer to the callback routine parameter + + @retval RETURN_SUCCESS Successfully find out the memory information. + @retval RETURN_NOT_FOUND Failed to find the memory information. + +**/ +RETURN_STATUS +EFIAPI +ParseMemoryInfo ( + IN BL_MEM_INFO_CALLBACK MemInfoCallback, + IN VOID *Params + ) +{ + MEMROY_MAP_INFO *MemoryMapInfo; + MEMROY_MAP_ENTRY MemoryMap; + UINTN Idx; + + MemoryMapInfo = (MEMROY_MAP_INFO *) GetGuidHobDataFromSbl (&gLoaderMemoryMapInfoGuid); + if (MemoryMapInfo == NULL) { + ASSERT (FALSE); + return RETURN_NOT_FOUND; + } + + for (Idx = 0; Idx < MemoryMapInfo->Count; Idx++) { + MemoryMap.Base = MemoryMapInfo->Entry[Idx].Base; + MemoryMap.Size = MemoryMapInfo->Entry[Idx].Size; + + switch (MemoryMapInfo->Entry[Idx].Type) { + case 1: + MemoryMap.Type = EFI_RESOURCE_SYSTEM_MEMORY; + MemoryMap.Flag = EFI_RESOURCE_ATTRIBUTE_PRESENT; + break; + case 2: + MemoryMap.Type = EFI_RESOURCE_MEMORY_RESERVED; + MemoryMap.Flag = EFI_RESOURCE_ATTRIBUTE_PRESENT; + break; + default: + continue; + } + + MemInfoCallback (&MemoryMap, Params); + } + + return RETURN_SUCCESS; +} + +/** + Acquire acpi table and smbios table from slim bootloader + + @param SystemTableInfo Pointer to the system table info + + @retval RETURN_SUCCESS Successfully find out the tables. + @retval RETURN_NOT_FOUND Failed to find the tables. + +**/ +RETURN_STATUS +EFIAPI +ParseSystemTable ( + OUT SYSTEM_TABLE_INFO *SystemTableInfo + ) +{ + SYSTEM_TABLE_INFO *TableInfo; + + TableInfo = (SYSTEM_TABLE_INFO *)GetGuidHobDataFromSbl (&gUefiSystemTableInfoGuid); + if (TableInfo == NULL) { + ASSERT (FALSE); + return RETURN_NOT_FOUND; + } + + CopyMem (SystemTableInfo, TableInfo, sizeof (SYSTEM_TABLE_INFO)); + + return RETURN_SUCCESS; +} + + +/** + Find the serial port information + + @param SERIAL_PORT_INFO Pointer to serial port info structure + + @retval RETURN_SUCCESS Successfully find the serial port information. + @retval RETURN_NOT_FOUND Failed to find the serial port information . + +**/ +RETURN_STATUS +EFIAPI +ParseSerialInfo ( + OUT SERIAL_PORT_INFO *SerialPortInfo + ) +{ + SERIAL_PORT_INFO *BlSerialInfo; + + BlSerialInfo = (SERIAL_PORT_INFO *) GetGuidHobDataFromSbl (&gUefiSerialPortInfoGuid); + if (BlSerialInfo == NULL) { + ASSERT (FALSE); + return RETURN_NOT_FOUND; + } + + CopyMem (SerialPortInfo, BlSerialInfo, sizeof (SERIAL_PORT_INFO)); + + return RETURN_SUCCESS; +} + + +/** + Find the video frame buffer information + + @param GfxInfo Pointer to the EFI_PEI_GRAPHICS_INFO_HOB structure + + @retval RETURN_SUCCESS Successfully find the video frame buffer information. + @retval RETURN_NOT_FOUND Failed to find the video frame buffer information . + +**/ +RETURN_STATUS +EFIAPI +ParseGfxInfo ( + OUT EFI_PEI_GRAPHICS_INFO_HOB *GfxInfo + ) +{ + EFI_PEI_GRAPHICS_INFO_HOB *BlGfxInfo; + + BlGfxInfo = (EFI_PEI_GRAPHICS_INFO_HOB *) GetGuidHobDataFromSbl (&gEfiGraphicsInfoHobGuid); + if (BlGfxInfo == NULL) { + return RETURN_NOT_FOUND; + } + + CopyMem (GfxInfo, BlGfxInfo, sizeof (EFI_PEI_GRAPHICS_INFO_HOB)); + + return RETURN_SUCCESS; +} + +/** + Find the video frame buffer device information + + @param GfxDeviceInfo Pointer to the EFI_PEI_GRAPHICS_DEVICE_INFO_HOB structure + + @retval RETURN_SUCCESS Successfully find the video frame buffer information. + @retval RETURN_NOT_FOUND Failed to find the video frame buffer information. + +**/ +RETURN_STATUS +EFIAPI +ParseGfxDeviceInfo ( + OUT EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *GfxDeviceInfo + ) +{ + EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *BlGfxDeviceInfo; + + BlGfxDeviceInfo = (EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *) GetGuidHobDataFromSbl (&gEfiGraphicsDeviceInfoHobGuid); + if (BlGfxDeviceInfo == NULL) { + return RETURN_NOT_FOUND; + } + + CopyMem (GfxDeviceInfo, BlGfxDeviceInfo, sizeof (EFI_PEI_GRAPHICS_DEVICE_INFO_HOB)); + + return RETURN_SUCCESS; +} + +/** + Find the video frame buffer device information + + @param SMMSTOREInfo Pointer to the SMMSTORE_INFO structure + + @retval RETURN_SUCCESS Successfully find the SMM store buffer information. + @retval RETURN_NOT_FOUND Failed to find the SMM store buffer information . + +**/ +RETURN_STATUS +EFIAPI +ParseSMMSTOREInfo ( + OUT SMMSTORE_INFO *SMMSTOREInfo + ) +{ + return RETURN_NOT_FOUND; +} + +/** + Find the Tcg Physical Presence store information + + @param PPIInfo Pointer to the TCG_PHYSICAL_PRESENCE_INFO structure + + @retval RETURN_SUCCESS Successfully find the SMM store buffer information. + @retval RETURN_NOT_FOUND Failed to find the SMM store buffer information . + +**/ +RETURN_STATUS +EFIAPI +ParseTPMPPIInfo ( + OUT TCG_PHYSICAL_PRESENCE_INFO *PPIInfo + ) +{ + return RETURN_NOT_FOUND; +} diff --git a/DasharoPayloadPkg/Library/SblParseLib/SblParseLib.inf b/DasharoPayloadPkg/Library/SblParseLib/SblParseLib.inf new file mode 100644 index 0000000000..f68a4371bc --- /dev/null +++ b/DasharoPayloadPkg/Library/SblParseLib/SblParseLib.inf @@ -0,0 +1,46 @@ +## @file +# Slim Bootloader parse library. +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SblParseLib + FILE_GUID = DE6FB32C-52CF-4A17-A84C-B323653CB5E0 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = BlParseLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + SblParseLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + DasharoPayloadPkg/DasharoPayloadPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + PcdLib + HobLib + +[Guids] + gUefiSystemTableInfoGuid + gUefiSerialPortInfoGuid + gLoaderMemoryMapInfoGuid + gEfiGraphicsInfoHobGuid + gEfiGraphicsDeviceInfoHobGuid + +[Pcd] + gDasharoPayloadPkgTokenSpaceGuid.PcdPayloadStackTop diff --git a/DasharoPayloadPkg/Library/SmmStoreLib/SmmStore.c b/DasharoPayloadPkg/Library/SmmStoreLib/SmmStore.c new file mode 100644 index 0000000000..b53168a959 --- /dev/null +++ b/DasharoPayloadPkg/Library/SmmStoreLib/SmmStore.c @@ -0,0 +1,580 @@ +/** @file SmmStore.c + + Copyright (c) 2022, 9elements GmbH
+ Copyright (c) 2024, 3mdeb Sp. z o.o.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "SmmStore.h" + +/* + * A memory buffer to place arguments in. + */ +STATIC SMM_STORE_COM_BUF *mArgComBuf; +STATIC EFI_PHYSICAL_ADDRESS mArgComBufPhys; + +/* + * Metadata provided by the first stage bootloader. + */ +STATIC SMMSTORE_INFO *mSmmStoreInfo; + +/** + Calls into SMM to use the SMMSTOREv2 implementation for persistent storage. + + @param Cmd The command to write into the APM port. This allows to enter the + Smi special command handler. + @param SubCmd The subcommand to execute in the Smi handler. + @param Arg Optional argument to pass to the Smi handler. Typically a pointer + in 'flat' memory mode, which points to read only memory. + + @retval EFI_NO_RESPONSE The SmmStore is not present or didn't response. + @retval EFI_UNSUPPORTED The request isn't suppored. + @retval EFI_DEVICE_ERROR An error occured while executing the request. + @retval EFI_SUCCESS The operation was executed successfully. +**/ +STATIC +EFI_STATUS +CallSmm ( + UINT8 Cmd, + UINT8 SubCmd, + UINTN Arg + ) +{ + CONST UINTN Rax = ((SubCmd << 8) | Cmd); + CONST UINTN Rbx = Arg; + UINTN Result; + + Result = TriggerSmi (Rax, Rbx, 5); + if (Result == Rax) { + return EFI_NO_RESPONSE; + } else if (Result == SMMSTORE_RET_SUCCESS) { + return EFI_SUCCESS; + } else if (Result == SMMSTORE_RET_UNSUPPORTED) { + return EFI_UNSUPPORTED; + } + + return EFI_DEVICE_ERROR; +} + +/** + Get the SmmStore block size + + @param BlockSize The pointer to store the block size in. + +**/ +EFI_STATUS +SmmStoreLibGetBlockSize ( + OUT UINTN *BlockSize + ) +{ + if (mSmmStoreInfo == NULL) { + return EFI_NO_MEDIA; + } + + if (BlockSize == NULL) { + return EFI_INVALID_PARAMETER; + } + + *BlockSize = mSmmStoreInfo->BlockSize; + + return EFI_SUCCESS; +} + +/** + Get the SmmStore number of blocks + + @param NumBlocks The pointer to store the number of blocks in. + +**/ +EFI_STATUS +SmmStoreLibGetNumBlocks ( + OUT UINTN *NumBlocks + ) +{ + if (mSmmStoreInfo == NULL) { + return EFI_NO_MEDIA; + } + + if (NumBlocks == NULL) { + return EFI_INVALID_PARAMETER; + } + + *NumBlocks = mSmmStoreInfo->NumBlocks; + + return EFI_SUCCESS; +} + +/** + Get the SmmStore MMIO address + + @param MmioAddress The pointer to store the address in. + +**/ +EFI_STATUS +SmmStoreLibGetMmioAddress ( + OUT EFI_PHYSICAL_ADDRESS *MmioAddress + ) +{ + if (mSmmStoreInfo == NULL) { + return EFI_NO_MEDIA; + } + + if (MmioAddress == NULL) { + return EFI_INVALID_PARAMETER; + } + + *MmioAddress = mSmmStoreInfo->MmioAddress; + + return EFI_SUCCESS; +} + +/** + Read a flash block. The whole flash is represented as a + sequence of blocks. + + @param[in] Lba The starting logical block index to read from. + @param[in] Offset Offset into the block at which to begin reading. + @param[in] NumBytes On input, indicates the requested read size. On + output, indicates the actual number of bytes read + @param[in] Buffer Pointer to the buffer to read into. + @param[in] ReadCmd Read command to use. + + @note Validation of mSmmStoreInfo and Lba must be done by the calling code. + +**/ +STATIC +EFI_STATUS +ReadBlock ( + IN EFI_LBA Lba, + IN UINTN Offset, + IN UINTN *NumBytes, + IN UINT8 *Buffer, + IN UINT8 ReadCmd + ) +{ + EFI_STATUS Status; + + if (((*NumBytes + Offset) > mSmmStoreInfo->BlockSize) || + ((*NumBytes + Offset) > mSmmStoreInfo->ComBufferSize)) + { + return EFI_INVALID_PARAMETER; + } + + mArgComBuf->Read.BufSize = *NumBytes; + mArgComBuf->Read.BufOffset = Offset; + mArgComBuf->Read.BlockId = Lba; + + Status = CallSmm (mSmmStoreInfo->ApmCmd, ReadCmd, mArgComBufPhys); + if (EFI_ERROR (Status)) { + return Status; + } + + CopyMem (Buffer, (VOID *)(UINTN)(mSmmStoreInfo->ComBuffer + Offset), *NumBytes); + + return EFI_SUCCESS; +} + +/** + Read from SmmStore + + @param[in] Lba The starting logical block index to read from. + @param[in] Offset Offset into the block at which to begin reading. + @param[in] NumBytes On input, indicates the requested read size. On + output, indicates the actual number of bytes read + @param[in] Buffer Pointer to the buffer to read into. + +**/ +EFI_STATUS +SmmStoreLibRead ( + IN EFI_LBA Lba, + IN UINTN Offset, + IN UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ + if (mSmmStoreInfo == NULL) { + return EFI_NO_MEDIA; + } + + if (Lba >= mSmmStoreInfo->NumBlocks) { + return EFI_INVALID_PARAMETER; + } + + return ReadBlock (Lba, Offset, NumBytes, Buffer, SMMSTORE_CMD_RAW_READ); +} + +/** + Read from an arbitrary flash location. The whole flash is represented as a + sequence of blocks. + + @param[in] Lba The starting logical block index to read from. + @param[in] Offset Offset into the block at which to begin reading. + @param[in] NumBytes On input, indicates the requested read size. On + output, indicates the actual number of bytes read + @param[in] Buffer Pointer to the buffer to read into. + +**/ +EFI_STATUS +SmmStoreLibReadAnyBlock ( + IN EFI_LBA Lba, + IN UINTN Offset, + IN UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ + if (mSmmStoreInfo == NULL) { + return EFI_NO_MEDIA; + } + + return ReadBlock (Lba, Offset, NumBytes, Buffer, SMMSTORE_CMD_USE_FULL_FLASH | SMMSTORE_CMD_RAW_READ); +} + +/** + Write a flash block. The whole flash is represented as a + sequence of blocks. + + @param[in] Lba The starting logical block index to write to. + @param[in] Offset Offset into the block at which to begin writing. + @param[in] NumBytes On input, indicates the requested write size. On + output, indicates the actual number of bytes written + @param[in] Buffer Pointer to the data to write. + @param[in] WriteCmd Write command to use. + + @note Validation of mSmmStoreInfo and Lba must be done by the calling code. + +**/ +STATIC +EFI_STATUS +WriteBlock ( + IN EFI_LBA Lba, + IN UINTN Offset, + IN UINTN *NumBytes, + IN UINT8 *Buffer, + IN UINT8 WriteCmd + ) +{ + if (((*NumBytes + Offset) > mSmmStoreInfo->BlockSize) || + ((*NumBytes + Offset) > mSmmStoreInfo->ComBufferSize)) + { + return EFI_INVALID_PARAMETER; + } + + mArgComBuf->Write.BufSize = *NumBytes; + mArgComBuf->Write.BufOffset = Offset; + mArgComBuf->Write.BlockId = Lba; + + CopyMem ((VOID *)(UINTN)(mSmmStoreInfo->ComBuffer + Offset), Buffer, *NumBytes); + + return CallSmm (mSmmStoreInfo->ApmCmd, WriteCmd, mArgComBufPhys); +} + +/** + Write to SmmStore + + @param[in] Lba The starting logical block index to write to. + @param[in] Offset Offset into the block at which to begin writing. + @param[in] NumBytes On input, indicates the requested write size. On + output, indicates the actual number of bytes written + @param[in] Buffer Pointer to the data to write. + +**/ +EFI_STATUS +SmmStoreLibWrite ( + IN EFI_LBA Lba, + IN UINTN Offset, + IN UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ + if (mSmmStoreInfo == NULL) { + return EFI_NO_MEDIA; + } + + if (Lba >= mSmmStoreInfo->NumBlocks) { + return EFI_INVALID_PARAMETER; + } + + return WriteBlock (Lba, Offset, NumBytes, Buffer, SMMSTORE_CMD_RAW_WRITE); +} + +/** + Write to an arbitrary flash location. The whole flash is represented as a + sequence of blocks. + + @param[in] Lba The starting logical block index to write to. + @param[in] Offset Offset into the block at which to begin writing. + @param[in] NumBytes On input, indicates the requested write size. On + output, indicates the actual number of bytes written + @param[in] Buffer Pointer to the data to write. + +**/ +EFI_STATUS +SmmStoreLibWriteAnyBlock ( + IN EFI_LBA Lba, + IN UINTN Offset, + IN UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ + if (mSmmStoreInfo == NULL) { + return EFI_NO_MEDIA; + } + + return WriteBlock (Lba, Offset, NumBytes, Buffer, SMMSTORE_CMD_USE_FULL_FLASH | SMMSTORE_CMD_RAW_WRITE); +} + +/** + Erase a SmmStore block + + @param Lba The logical block index to erase. + +**/ +EFI_STATUS +SmmStoreLibEraseBlock ( + IN EFI_LBA Lba + ) +{ + if (mSmmStoreInfo == NULL) { + return EFI_NO_MEDIA; + } + + if (Lba >= mSmmStoreInfo->NumBlocks) { + return EFI_INVALID_PARAMETER; + } + + mArgComBuf->Clear.BlockId = Lba; + + return CallSmm (mSmmStoreInfo->ApmCmd, SMMSTORE_CMD_RAW_CLEAR, mArgComBufPhys); +} + +/** + Erase an arbitrary block of the flash. The whole flash is represented as a + sequence of blocks. + + @param Lba The logical block index to erase. + +**/ +EFI_STATUS +SmmStoreLibEraseAnyBlock ( + IN EFI_LBA Lba + ) +{ + if (mSmmStoreInfo == NULL) { + return EFI_NO_MEDIA; + } + + mArgComBuf->Clear.BlockId = Lba; + + return CallSmm (mSmmStoreInfo->ApmCmd, + SMMSTORE_CMD_USE_FULL_FLASH | SMMSTORE_CMD_RAW_CLEAR, + mArgComBufPhys); +} + +/** + Fixup internal data so that EFI can be called in virtual mode. + Converts any pointers in lib to virtual mode. This function is meant to + be invoked on gEfiEventVirtualAddressChangeGuid event when the library is + used at run-time. + + @param[in] ConvertPointer Function to switch virtual address space. + +**/ +VOID +EFIAPI +SmmStoreLibVirtualAddressChange ( + IN ConvertPointerFunc ConvertPointer + ) +{ + ConvertPointer (0x0, (VOID **)&mArgComBuf); + if (mSmmStoreInfo != NULL) { + ConvertPointer (0x0, (VOID **)&mSmmStoreInfo->ComBuffer); + ConvertPointer (0x0, (VOID **)&mSmmStoreInfo); + } + + return; +} + +/** + Initializes SmmStore support + + @retval EFI_WRITE_PROTECTED The SmmStore is not present. + @retval EFI_OUT_OF_RESOURCES Run out of memory. + @retval EFI_SUCCESS The SmmStore is supported. + +**/ +EFI_STATUS +SmmStoreLibInitialize ( + VOID + ) +{ + EFI_STATUS Status; + VOID *GuidHob; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor; + + // + // Find the SmmStore information guid hob + // + GuidHob = GetFirstGuidHob (&gEfiSmmStoreInfoHobGuid); + if (GuidHob == NULL) { + DEBUG ((DEBUG_WARN, "SmmStore not supported! Skipping driver init.\n")); + return EFI_UNSUPPORTED; + } + + // + // Place SmmStore information hob in a runtime buffer + // + mSmmStoreInfo = AllocateRuntimePool (GET_GUID_HOB_DATA_SIZE (GuidHob)); + if (mSmmStoreInfo == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CopyMem (mSmmStoreInfo, GET_GUID_HOB_DATA (GuidHob), GET_GUID_HOB_DATA_SIZE (GuidHob)); + + // + // Validate input + // + if ((mSmmStoreInfo->MmioAddress == 0) || + (mSmmStoreInfo->ComBuffer == 0) || + (mSmmStoreInfo->BlockSize == 0) || + (mSmmStoreInfo->NumBlocks == 0)) + { + DEBUG ((DEBUG_ERROR, "%a: Invalid data in SmmStore Info hob\n", __FUNCTION__)); + FreePool (mSmmStoreInfo); + mSmmStoreInfo = NULL; + return EFI_WRITE_PROTECTED; + } + + // + // Allocate Communication Buffer for arguments to pass to SMM. + // The argument com buffer is only read by SMM, but never written. + // The FVB data send/retrieved will be placed in a separate bootloader + // pre-allocated memory region, the ComBuffer. + // + if (mSmmStoreInfo->ComBuffer < BASE_4GB) { + // + // Assume that SMM handler is running in 32-bit mode when ComBuffer is + // is placed below BASE_4GB. + // + mArgComBufPhys = BASE_4GB - 1; + } else { + mArgComBufPhys = BASE_8EB - 1; + } + + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiRuntimeServicesData, + EFI_SIZE_TO_PAGES (sizeof (SMM_STORE_COM_BUF)), + &mArgComBufPhys + ); + + if (EFI_ERROR (Status)) { + FreePool (mSmmStoreInfo); + mSmmStoreInfo = NULL; + return EFI_OUT_OF_RESOURCES; + } + + mArgComBuf = (VOID *)mArgComBufPhys; + + // + // Finally mark the SMM communication buffer provided by CB or SBL as runtime memory + // + Status = gDS->GetMemorySpaceDescriptor (mSmmStoreInfo->ComBuffer, &GcdDescriptor); + if (EFI_ERROR (Status) || (GcdDescriptor.GcdMemoryType != EfiGcdMemoryTypeReserved)) { + DEBUG ( + ( + DEBUG_INFO, + "%a: No memory space descriptor for com buffer found\n", + __FUNCTION__ + ) + ); + + // + // Add a new entry if not covered by existing mapping + // + Status = gDS->AddMemorySpace ( + EfiGcdMemoryTypeReserved, + mSmmStoreInfo->ComBuffer, + mSmmStoreInfo->ComBufferSize, + EFI_MEMORY_WB | EFI_MEMORY_RUNTIME + ); + ASSERT_EFI_ERROR (Status); + } + + // + // Mark as runtime service + // + Status = gDS->SetMemorySpaceAttributes ( + mSmmStoreInfo->ComBuffer, + mSmmStoreInfo->ComBufferSize, + EFI_MEMORY_RUNTIME + ); + ASSERT_EFI_ERROR (Status); + + // + // Mark the memory mapped store as MMIO memory + // + Status = gDS->GetMemorySpaceDescriptor (mSmmStoreInfo->MmioAddress, &GcdDescriptor); + if (EFI_ERROR (Status) || (GcdDescriptor.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo)) { + DEBUG ( + ( + DEBUG_INFO, + "%a: No memory space descriptor for MMIO memory found\n", + __FUNCTION__ + ) + ); + + // + // Add a new entry if not covered by existing mapping + // + Status = gDS->AddMemorySpace ( + EfiGcdMemoryTypeMemoryMappedIo, + mSmmStoreInfo->MmioAddress, + mSmmStoreInfo->NumBlocks * mSmmStoreInfo->BlockSize, + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME + ); + ASSERT_EFI_ERROR (Status); + } + + // + // Mark as runtime service + // + Status = gDS->SetMemorySpaceAttributes ( + mSmmStoreInfo->MmioAddress, + mSmmStoreInfo->NumBlocks * mSmmStoreInfo->BlockSize, + EFI_MEMORY_RUNTIME + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + +/** + Denitializes SmmStore support by freeing allocated memory. +**/ +VOID +EFIAPI +SmmStoreLibDeinitialize ( + VOID + ) +{ + if (mArgComBuf != NULL) { + gBS->FreePages (mArgComBufPhys, EFI_SIZE_TO_PAGES (sizeof (SMM_STORE_COM_BUF))); + mArgComBuf = NULL; + } + + if (mSmmStoreInfo != NULL) { + FreePool (mSmmStoreInfo); + mSmmStoreInfo = NULL; + } +} diff --git a/DasharoPayloadPkg/Library/SmmStoreLib/SmmStore.h b/DasharoPayloadPkg/Library/SmmStoreLib/SmmStore.h new file mode 100644 index 0000000000..fc178f56eb --- /dev/null +++ b/DasharoPayloadPkg/Library/SmmStoreLib/SmmStore.h @@ -0,0 +1,85 @@ +/** @file SmmStore.h + + Copyright (c) 2022, 9elements GmbH
+ Copyright (c) 2024, 3mdeb Sp. z o.o.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef COREBOOT_SMMSTORE_H_ +#define COREBOOT_SMMSTORE_H_ + +#define SMMSTORE_RET_SUCCESS 0 +#define SMMSTORE_RET_FAILURE 1 +#define SMMSTORE_RET_UNSUPPORTED 2 + +/* Version 2 only */ +#define SMMSTORE_CMD_INIT 4 +#define SMMSTORE_CMD_RAW_READ 5 +#define SMMSTORE_CMD_RAW_WRITE 6 +#define SMMSTORE_CMD_RAW_CLEAR 7 + +/* Used by capsule updates as a standalone command or modifier to v2 commands */ +#define SMMSTORE_CMD_USE_FULL_FLASH 0x80 + +/* + * This allows the payload to store raw data in the flash regions. + * This can be used by a FaultTolerantWrite implementation, that uses at least + * two regions in an A/B update scheme. + */ + +#pragma pack(1) + +/* + * Reads a chunk of raw data with size BufSize from the block specified by + * block_id starting at BufOffset. + * The read data is placed in buf. + * + * block_id must be less than num_blocks + * BufOffset + BufSize must be less than block_size + */ +typedef struct { + UINT32 BufSize; + UINT32 BufOffset; + UINT32 BlockId; +} SMM_STORE_PARAMS_WRITE; + +/* + * Writes a chunk of raw data with size BufSize to the block specified by + * block_id starting at BufOffset. + * + * block_id must be less than num_blocks + * BufOffset + BufSize must be less than block_size + */ +typedef struct { + UINT32 BufSize; + UINT32 BufOffset; + UINT32 BlockId; +} SMM_STORE_PARAMS_READ; + +/* + * Erases the specified block. + * + * block_id must be less than num_blocks + */ +typedef struct { + UINT32 BlockId; +} SMM_STORE_PARAMS_CLEAR; + +typedef union { + SMM_STORE_PARAMS_WRITE Write; + SMM_STORE_PARAMS_READ Read; + SMM_STORE_PARAMS_CLEAR Clear; +} SMM_STORE_COM_BUF; +#pragma pack(0) + +UINTN +EFIAPI +TriggerSmi ( + IN UINTN Cmd, + IN UINTN Arg, + IN UINTN Retry + ); + +#endif // COREBOOT_SMMSTORE_H_ diff --git a/DasharoPayloadPkg/Library/SmmStoreLib/SmmStoreLib.inf b/DasharoPayloadPkg/Library/SmmStoreLib/SmmStoreLib.inf new file mode 100644 index 0000000000..2a58b08a08 --- /dev/null +++ b/DasharoPayloadPkg/Library/SmmStoreLib/SmmStoreLib.inf @@ -0,0 +1,40 @@ +## @file +# SmmStore library for coreboot +# +# Copyright (c) 2022 9elements GmbH.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmmStoreLib + FILE_GUID = 40A2CBC6-CFB8-447b-A90E-298E88FD345E + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = SmmStoreLib + +[Sources] + SmmStore.c + SmmStore.h + +[Sources.X64] + X64/SmmStore.nasm + +[LibraryClasses] + BaseMemoryLib + DebugLib + DxeServicesTableLib + HobLib + MemoryAllocationLib + UefiBootServicesTableLib + +[Guids] + gEfiSmmStoreInfoHobGuid ## CONSUMES + gEfiEventVirtualAddressChangeGuid ## CONSUMES + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + DasharoPayloadPkg/DasharoPayloadPkg.dec diff --git a/DasharoPayloadPkg/Library/SmmStoreLib/X64/SmmStore.nasm b/DasharoPayloadPkg/Library/SmmStoreLib/X64/SmmStore.nasm new file mode 100644 index 0000000000..1a8b5b64c8 --- /dev/null +++ b/DasharoPayloadPkg/Library/SmmStoreLib/X64/SmmStore.nasm @@ -0,0 +1,48 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2022, 9elements GmbH. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------- + +%include "Nasm.inc" + +DEFAULT REL +SECTION .text + +;UINTN +;EFIAPI +;TriggerSmi ( +; UINTN Cmd, +; UINTN Arg, +; UINTN Retry +; ) + +global ASM_PFX(TriggerSmi) +ASM_PFX(TriggerSmi): + push rbx + mov rax, rcx ; Smi handler expect Cmd in RAX + mov rbx, rdx ; Smi handler expect Argument in RBX +@Trigger: + out 0b2h, al ; write to APM port to trigger SMI + +; There might ba a delay between writing the Smi trigger register and +; entering SMM, in which case the Smi handler will do nothing as only +; synchronous Smis are handled. In addition when there's no Smi handler +; or the SmmStore feature isn't compiled in, no register will be modified. + +; As there's no livesign from SMM, just wait a bit for the handler to fire, +; and then try again. + + cmp rax, rcx ; Check if rax was modified by SMM + jne @Return ; SMM modified rax, return now + push rcx ; save rcx to stack + mov rcx, 10000 + rep pause ; add a small delay + pop rcx ; restore rcx + cmp r8, 0 + je @Return + dec r8 + jmp @Trigger +@Return: + pop rbx + ret diff --git a/DasharoPayloadPkg/Library/System76EcLib/System76EcLib.c b/DasharoPayloadPkg/Library/System76EcLib/System76EcLib.c new file mode 100644 index 0000000000..9bb7a90606 --- /dev/null +++ b/DasharoPayloadPkg/Library/System76EcLib/System76EcLib.c @@ -0,0 +1,144 @@ +/** @file + System76 EC logging + + Copyright (c) 2020 System76, Inc. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +// From coreboot/src/drivers/system76_ec/system76_ec.c { +#define SYSTEM76_EC_BASE 0x0E00 + +static inline UINT8 system76_ec_read(UINT8 addr) { + return IoRead8(SYSTEM76_EC_BASE + (UINT16)addr); +} + +static inline void system76_ec_write(UINT8 addr, UINT8 data) { + IoWrite8(SYSTEM76_EC_BASE + (UINT16)addr, data); +} + +void system76_ec_init(void) { + // Clear entire command region + for (int i = 0; i < 256; i++) { + system76_ec_write((UINT8)i, 0); + } +} + +void system76_ec_flush(void) { + // Send command + system76_ec_write(0, 4); + + // Wait for command completion + while (system76_ec_read(0) != 0) {} + + // Clear length + system76_ec_write(3, 0); +} + +void system76_ec_print(UINT8 byte) { + // Read length + UINT8 len = system76_ec_read(3); + // Write data at offset + system76_ec_write(len + 4, byte); + // Update length + system76_ec_write(3, len + 1); + + // If we hit the end of the buffer, or were given a newline, flush + if (byte == '\n' || len >= 128) { + system76_ec_flush(); + } +} +// } From coreboot/src/drivers/system76_ec/system76_ec.c + +// Implement SerialPortLib { +#include + +RETURN_STATUS +EFIAPI +SerialPortInitialize ( + VOID + ) +{ + system76_ec_init(); + return RETURN_SUCCESS; +} + +UINTN +EFIAPI +SerialPortWrite ( + IN UINT8 *Buffer, + IN UINTN NumberOfBytes + ) +{ + if (Buffer == NULL) { + return 0; + } + + if (NumberOfBytes == 0) { + system76_ec_flush(); + return 0; + } + + for(UINTN i = 0; i < NumberOfBytes; i++) { + system76_ec_print(Buffer[i]); + } + + return NumberOfBytes; +} + +BOOLEAN +EFIAPI +SerialPortPoll ( + VOID + ) +{ + return FALSE; +} + +RETURN_STATUS +EFIAPI +SerialPortGetControl ( + OUT UINT32 *Control + ) +{ + return RETURN_UNSUPPORTED; +} + +RETURN_STATUS +EFIAPI +SerialPortSetControl ( + IN UINT32 Control + ) +{ + return RETURN_UNSUPPORTED; +} + +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; +} +// } Implement SerialPortLib + +// Implement PlatformHookLib { +#include + +RETURN_STATUS +EFIAPI +PlatformHookSerialPortInitialize ( + VOID + ) +{ + return RETURN_SUCCESS; +} +// } Implement PlatformHookLib diff --git a/DasharoPayloadPkg/Library/System76EcLib/System76EcLib.inf b/DasharoPayloadPkg/Library/System76EcLib/System76EcLib.inf new file mode 100644 index 0000000000..69f0e17831 --- /dev/null +++ b/DasharoPayloadPkg/Library/System76EcLib/System76EcLib.inf @@ -0,0 +1,28 @@ +## @file +# System76 EC logging. +# +# Copyright (c) 2020, System76, Inc. +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = System76EcLib + MODULE_UNI_FILE = System76EcLib.uni + FILE_GUID = 76ECF0DD-148B-4E48-8589-FC998823F8C2 + MODULE_TYPE = BASE + VERSION_STRING = 0.1 + LIBRARY_CLASS = System76EcLib + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + DasharoPayloadPkg/DasharoPayloadPkg.dec + +[LibraryClasses] + IoLib + +[Sources] + System76EcLib.c + +[Pcd] diff --git a/DasharoPayloadPkg/Library/System76EcLib/System76EcLib.uni b/DasharoPayloadPkg/Library/System76EcLib/System76EcLib.uni new file mode 100644 index 0000000000..f0db62f232 --- /dev/null +++ b/DasharoPayloadPkg/Library/System76EcLib/System76EcLib.uni @@ -0,0 +1,13 @@ +// /** @file +// System76 EC logging. +// +// Copyright (c) 2020, System76, Inc. +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "System76 EC logging" + +#string STR_MODULE_DESCRIPTION #language en-US "System76 EC logging." + diff --git a/DasharoPayloadPkg/Library/Tcg2PhysicalPresencePlatformLibUefipayload/DxeTcg2PhysicalPresencePlatformLib.c b/DasharoPayloadPkg/Library/Tcg2PhysicalPresencePlatformLibUefipayload/DxeTcg2PhysicalPresencePlatformLib.c new file mode 100644 index 0000000000..a35d73c165 --- /dev/null +++ b/DasharoPayloadPkg/Library/Tcg2PhysicalPresencePlatformLibUefipayload/DxeTcg2PhysicalPresencePlatformLib.c @@ -0,0 +1,80 @@ +/** @file + Returns the platform specific configuration for the QEMU PPI. + + Caution: This module requires additional review when modified. + This driver will have external input - variable. + This external input must be validated carefully to avoid security issue. + +Copyright (C) 2018, Red Hat, Inc. +Copyright (c) 2018, IBM Corporation. All rights reserved.
+Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include + +#include +#include +#include +#include + +#include + +/** + Reads QEMU PPI config from TcgPhysicalPresenceInfoHobGuid. + + @param[out] The Config structure to read to. + @param[out] The PPIinMMIO is True when the PPI is in MMIO memory space + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_PROTOCOL_ERROR Invalid HOB entry. +**/ +EFI_STATUS +TpmPPIPlatformReadConfig ( + OUT QEMU_FWCFG_TPM_CONFIG *Config, + OUT BOOLEAN *PPIinMMIO + ) +{ + EFI_HOB_GUID_TYPE *GuidHob; + TCG_PHYSICAL_PRESENCE_INFO *pPPInfo; + + // + // Find the TPM Physical Presence HOB + // + GuidHob = GetFirstGuidHob (&gEfiTcgPhysicalPresenceInfoHobGuid); + + if (GuidHob == NULL) { + return EFI_NOT_FOUND; + } + + pPPInfo = (TCG_PHYSICAL_PRESENCE_INFO *)GET_GUID_HOB_DATA (GuidHob); + + if (pPPInfo->PpiAddress == 0 || pPPInfo->PpiAddress == ~0) { + return EFI_NOT_FOUND; + } else { + Config->PpiAddress = pPPInfo->PpiAddress; + } + + if (pPPInfo->TpmVersion == UEFIPAYLOAD_TPM_VERSION_1_2) { + Config->TpmVersion = QEMU_TPM_VERSION_1_2; + } else if (pPPInfo->TpmVersion == UEFIPAYLOAD_TPM_VERSION_2) { + Config->TpmVersion = QEMU_TPM_VERSION_2; + } else { + return EFI_UNSUPPORTED; + } + + if (pPPInfo->PpiVersion == UEFIPAYLOAD_TPM_PPI_VERSION_NONE) { + Config->PpiVersion = QEMU_TPM_PPI_VERSION_NONE; + } else if (pPPInfo->PpiVersion == UEFIPAYLOAD_TPM_PPI_VERSION_1_30) { + Config->PpiVersion = QEMU_TPM_PPI_VERSION_1_30; + } else { + return EFI_UNSUPPORTED; + } + + *PPIinMMIO = FALSE; + + return EFI_SUCCESS; +} diff --git a/DasharoPayloadPkg/Library/Tcg2PhysicalPresencePlatformLibUefipayload/DxeTcg2PhysicalPresencePlatformLib.inf b/DasharoPayloadPkg/Library/Tcg2PhysicalPresencePlatformLibUefipayload/DxeTcg2PhysicalPresencePlatformLib.inf new file mode 100644 index 0000000000..7c6cff56a3 --- /dev/null +++ b/DasharoPayloadPkg/Library/Tcg2PhysicalPresencePlatformLibUefipayload/DxeTcg2PhysicalPresencePlatformLib.inf @@ -0,0 +1,44 @@ +## @file +# Returns the platform specific configuration for the QEMU PPI. +# +# Caution: This module requires additional review when modified. +# This driver will have external input - variable. +# This external input must be validated carefully to avoid security issue. +# +# Copyright (C) 2018, Red Hat, Inc. +# Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Tcg2PhysicalPresencePlatformLibUefipayload + FILE_GUID = F5967F4F-B53F-4669-91A5-A3DA0F30AF22 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = Tcg2PhysicalPresencePlatformLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + OvmfPkg/OvmfPkg.dec + DasharoPayloadPkg/DasharoPayloadPkg.dec + +[Sources] + DxeTcg2PhysicalPresencePlatformLib.c + +[LibraryClasses] + BlParseLib + HobLib + DebugLib + DxeServicesTableLib + +[Guids] + gEfiTcgPhysicalPresenceInfoHobGuid diff --git a/DasharoPayloadPkg/PciPlatformDxe/PciPlatformDxe.c b/DasharoPayloadPkg/PciPlatformDxe/PciPlatformDxe.c new file mode 100644 index 0000000000..afb869649a --- /dev/null +++ b/DasharoPayloadPkg/PciPlatformDxe/PciPlatformDxe.c @@ -0,0 +1,490 @@ +/** @file + Implementation for a generic GOP driver. + +Copyright (c) 2016, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + + +**/ + +#include "PciPlatformDxe.h" +#include +#include +#include +#include + +// +// The driver should only start on one graphics controller. +// So a global flag is used to remember that the driver is already started. +// +EFI_HANDLE mDriverHandle = NULL; + +EFI_STATUS +EFIAPI +PciPlatformNotify( + 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 + ) +{ + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +PciPlatformPrepController( + 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 + ) +{ + return EFI_UNSUPPORTED; +} + +STATIC +BOOLEAN +IsVgaDevice ( + IN EFI_HANDLE PciHandle + ) +{ + EFI_STATUS Status; + BOOLEAN LoadOptionRom; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE00 PciConfHeader; + + LoadOptionRom = FALSE; + + Status = gBS->HandleProtocol ( + PciHandle, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + if (EFI_ERROR (Status)) { + return FALSE; + } + + // + // Read the PCI Configuration Header from the PCI Device + // + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (PciConfHeader) / sizeof (UINT32), + &PciConfHeader + ); + if (!EFI_ERROR (Status)) { + LoadOptionRom = IS_PCI_DISPLAY (&PciConfHeader); + } + + return LoadOptionRom; +} + +STATIC +BOOLEAN +ShouldLoadOptionRom ( + IN EFI_HANDLE PciHandle + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + UINT8 OptionRomPolicy; + + BufferSize = sizeof (OptionRomPolicy); + Status = gRT->GetVariable ( + DASHARO_VAR_OPTION_ROM_POLICY, + &gDasharoSystemFeaturesGuid, + NULL, + &BufferSize, + &OptionRomPolicy + ); + if (EFI_ERROR (Status)) { + // Fallback to PCD. + return PcdGetBool (PcdLoadOptionRoms); + } + + switch (OptionRomPolicy) { + case DASHARO_OPTION_ROM_POLICY_ENABLE_ALL: + return TRUE; + case DASHARO_OPTION_ROM_POLICY_DISABLE_ALL: + return FALSE; + case DASHARO_OPTION_ROM_POLICY_VGA_ONLY: + return IsVgaDevice (PciHandle); + } + + DEBUG ((EFI_D_WARN, "Warning: Unhandled Option ROM Policy value: %d\n", OptionRomPolicy)); + return FALSE; +} + +EFI_STATUS +EFIAPI +PciGetPciRom ( + IN CONST EFI_PCI_PLATFORM_PROTOCOL *This, + IN EFI_HANDLE PciHandle, + OUT VOID **RomImage, + OUT UINTN *RomSize + ) +{ + EFI_STATUS Status; + IN EFI_PCI_IO_PROTOCOL *PciIo; + UINTN PciSegment; + UINTN PciBus; + UINTN PciDevice; + UINTN PciFunction; + UINTN RomBarIndex; + UINT32 Buffer; + UINT32 AllOnes; + PCI_IO_DEVICE *PciIoDevice; + UINT8 Indicator; + UINT16 OffsetPcir; + UINT32 RomBarOffset; + UINT32 RomBar; + BOOLEAN FirstCheck; + PCI_EXPANSION_ROM_HEADER *RomHeader; + PCI_DATA_STRUCTURE *RomPcir; + UINT64 RomImageSize; + UINT32 LegacyImageLength; + UINT8 *RomInMemory; + UINT8 CodeType; + + if (!RomImage || !RomSize) { + return EFI_INVALID_PARAMETER; + } + + *RomImage = NULL; + *RomSize = 0; + + if (!ShouldLoadOptionRom (PciHandle)) { + return EFI_NOT_FOUND; + } + + Status = gBS->HandleProtocol ( + PciHandle, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_INFO, "%a: Failed to open gEfiPciIoProtocolGuid\n", __FUNCTION__)); + + return EFI_UNSUPPORTED; + } + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo); + + // + // Get the location of the PCI device + // + PciIo->GetLocation ( + PciIo, + &PciSegment, + &PciBus, + &PciDevice, + &PciFunction + ); + + DEBUG ((EFI_D_INFO, "%a: Searching Option ROM on device:\n", __FUNCTION__)); + DEBUG ((EFI_D_INFO, " PciSegment - %02x\n", PciSegment)); + DEBUG ((EFI_D_INFO, " PciBus - %02x\n", PciBus)); + DEBUG ((EFI_D_INFO, " PciDevice - %02x\n", PciDevice)); + DEBUG ((EFI_D_INFO, " PciFunction - %02x\n", PciFunction)); + + // + // 0x30 + // + RomBarIndex = PCI_EXPANSION_ROM_BASE; + + if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) { + // + // If is ppb, 0x38 + // + RomBarIndex = PCI_BRIDGE_ROMBAR; + } + // + // Backup BAR + // + + Status = PciIo->Pci.Read ( + PciIo, + EfiPciWidthUint32, + RomBarIndex, + 1, + &Buffer + ); + if (EFI_ERROR (Status)) { + goto CloseAndReturn; + return Status; + } + + // + // The bit0 is 0 to prevent the enabling of the Rom address decoder + // + AllOnes = 0xfffffffe; + + Status = PciIo->Pci.Write ( + PciIo, + EfiPciWidthUint32, + RomBarIndex, + 1, + &AllOnes + ); + if (EFI_ERROR (Status)) { + goto CloseAndReturn; + } + + // + // Read back + // + Status = PciIo->Pci.Read( + PciIo, + EfiPciWidthUint32, + RomBarIndex, + 1, + &AllOnes + ); + if (EFI_ERROR (Status)) { + goto CloseAndReturn; + } + + // + // Bits [1, 10] are reserved + // + AllOnes &= 0xFFFFF800; + if ((AllOnes == 0) || (AllOnes == 0xFFFFF800)) { + DEBUG ((EFI_D_INFO, "%a: No Option ROM found\n", __FUNCTION__)); + return EFI_NOT_FOUND; + } + + *RomSize = (~AllOnes) + 1; + + DEBUG ((EFI_D_INFO, "%a: Option ROM with size %d\n", __FUNCTION__, *RomSize)); + + // + // Restore BAR and enable it + // + Buffer |= 1; + Status = PciIo->Pci.Write ( + PciIo, + EfiPciWidthUint32, + RomBarIndex, + 1, + &Buffer + ); + if (EFI_ERROR (Status)) { + goto CloseAndReturn; + } + + // + // Allocate memory for Rom header and PCIR + // + RomHeader = AllocatePool (sizeof (PCI_EXPANSION_ROM_HEADER)); + if (RomHeader == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto CloseAndReturn; + } + + RomPcir = AllocatePool (sizeof (PCI_DATA_STRUCTURE)); + if (RomPcir == NULL) { + FreePool (RomHeader); + Status = EFI_OUT_OF_RESOURCES; + goto CloseAndReturn; + } + + RomBar = (UINT32) Buffer &~1; + + RomBarOffset = RomBar; + FirstCheck = TRUE; + LegacyImageLength = 0; + RomImageSize = 0; + + do { + PciIoDevice->PciRootBridgeIo->Mem.Read ( + PciIoDevice->PciRootBridgeIo, + EfiPciWidthUint8, + RomBarOffset, + sizeof (PCI_EXPANSION_ROM_HEADER), + (UINT8 *) RomHeader + ); + + DEBUG ((EFI_D_INFO, "%a: RomHeader->Signature %x\n", __FUNCTION__, RomHeader->Signature)); + + if (RomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) { + RomBarOffset = RomBarOffset + 512; + if (FirstCheck) { + break; + } else { + RomImageSize = RomImageSize + 512; + continue; + } + } + + FirstCheck = FALSE; + OffsetPcir = RomHeader->PcirOffset; + // + // 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 (OffsetPcir == 0 || + (OffsetPcir & 3) != 0 || + RomImageSize + OffsetPcir + sizeof (PCI_DATA_STRUCTURE) > *RomSize) { + break; + } + + PciIoDevice->PciRootBridgeIo->Mem.Read ( + PciIoDevice->PciRootBridgeIo, + EfiPciWidthUint8, + RomBarOffset + OffsetPcir, + sizeof (PCI_DATA_STRUCTURE), + (UINT8 *) RomPcir + ); + DEBUG ((EFI_D_INFO, "%a: RomPcir->Signature %x\n", __FUNCTION__, RomPcir->Signature)); + + // + // If a valid signature is not present in the PCI Data Structure, no further images can be located. + // + if (RomPcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) { + break; + } + if (RomImageSize + RomPcir->ImageLength * 512 > *RomSize) { + break; + } + if (RomPcir->CodeType == PCI_CODE_TYPE_PCAT_IMAGE) { + CodeType = PCI_CODE_TYPE_PCAT_IMAGE; + LegacyImageLength = ((UINT32)((EFI_LEGACY_EXPANSION_ROM_HEADER *)RomHeader)->Size512) * 512; + } + Indicator = RomPcir->Indicator; + RomImageSize = RomImageSize + RomPcir->ImageLength * 512; + RomBarOffset = RomBarOffset + RomPcir->ImageLength * 512; + } while (((Indicator & 0x80) == 0x00) && ((RomBarOffset - RomBar) < *RomSize)); + + // + // Some Legacy Cards do not report the correct ImageLength so used the maximum + // of the legacy length and the PCIR Image Length + // + if (CodeType == PCI_CODE_TYPE_PCAT_IMAGE) { + RomImageSize = MAX (RomImageSize, LegacyImageLength); + } + + if (RomImageSize > 0) { + Status = EFI_SUCCESS; + RomInMemory = (UINT8 *) AllocatePool ((UINT32) RomImageSize); + if (RomInMemory == NULL) { + PciIo->Pci.Write ( + PciIo, + EfiPciWidthUint32, + RomBarIndex, + 1, + &RomBar + ); + FreePool (RomHeader); + FreePool (RomPcir); + Status = EFI_OUT_OF_RESOURCES; + goto CloseAndReturn; + } + // + DEBUG ((EFI_D_INFO, "%a: Found Option ROM at %p, length 0x%x\n", __FUNCTION__, + RomBar, RomImageSize)); + // Copy Rom image into memory + // + PciIoDevice->PciRootBridgeIo->Mem.Read ( + PciIoDevice->PciRootBridgeIo, + EfiPciWidthUint8, + RomBar, + (UINT32) RomImageSize, + RomInMemory + ); + } else { + FreePool (RomHeader); + FreePool (RomPcir); + Status = EFI_NOT_FOUND; + goto CloseAndReturn; + } + + PciIo->Pci.Write ( + PciIo, + EfiPciWidthUint32, + RomBarIndex, + 1, + &RomBar + ); + + PciIoDevice->EmbeddedRom = TRUE; + PciIoDevice->PciIo.RomSize = RomImageSize; + PciIoDevice->PciIo.RomImage = RomInMemory; + + // + // Free allocated memory + // + FreePool (RomHeader); + FreePool (RomPcir); + + *RomImage = RomInMemory; + *RomSize = RomImageSize; + + Status = EFI_SUCCESS; + +CloseAndReturn: + // + // Close the I/O Abstraction(s) used to perform the supported test + // + gBS->CloseProtocol ( + PciHandle, + &gEfiPciIoProtocolGuid, + PciIo, + PciHandle + ); + + return Status; +} + +EFI_STATUS +EFIAPI +PciGetPlatformPolicy ( + IN CONST EFI_PCI_PLATFORM_PROTOCOL *This, + OUT EFI_PCI_PLATFORM_POLICY *PciPolicy + ) +{ + if (PciPolicy == NULL) + return EFI_INVALID_PARAMETER; + + *PciPolicy = 0; + + return EFI_SUCCESS; +} + +EFI_PCI_PLATFORM_PROTOCOL mPciPlatformProtocol = { + PciPlatformNotify, + PciPlatformPrepController, + PciGetPlatformPolicy, + PciGetPciRom, +}; + +/** + The Entry Point for Option ROM driver. + + It installs DriverBinding. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +InstallPciPlatformProtocol ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->InstallProtocolInterface ( + &mDriverHandle, + &gEfiPciPlatformProtocolGuid, + EFI_NATIVE_INTERFACE, + &mPciPlatformProtocol + ); + + return Status; +} diff --git a/DasharoPayloadPkg/PciPlatformDxe/PciPlatformDxe.h b/DasharoPayloadPkg/PciPlatformDxe/PciPlatformDxe.h new file mode 100644 index 0000000000..c40518c703 --- /dev/null +++ b/DasharoPayloadPkg/PciPlatformDxe/PciPlatformDxe.h @@ -0,0 +1,19 @@ +/** @file + Header file for a PCI platform driver. + +Copyright (c) 2016, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + + +**/ +#ifndef _PCI_PLATFORM_DXE_H_ +#define _PCI_PLATFORM_DXE_H_ +#include + +#include +#include +#include +#include +#include + +#endif diff --git a/DasharoPayloadPkg/PciPlatformDxe/PciPlatformDxe.inf b/DasharoPayloadPkg/PciPlatformDxe/PciPlatformDxe.inf new file mode 100644 index 0000000000..739de0ce00 --- /dev/null +++ b/DasharoPayloadPkg/PciPlatformDxe/PciPlatformDxe.inf @@ -0,0 +1,56 @@ +## @file +# This driver produces gEfiPciPlatform protocol to load PCI Option ROMs +# +# Copyright (c) 2020, 9elements Agency GmbH +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PciPlatformDxe + FILE_GUID = 86D58F7B-6E7C-401F-BDD4-E32E6D582AAD + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = InstallPciPlatformProtocol + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.common] + PciPlatformDxe.h + PciPlatformDxe.c + +[Packages] + DasharoModulePkg/DasharoModulePkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + DasharoPayloadPkg/DasharoPayloadPkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + DxeServicesTableLib + DebugLib + MemoryAllocationLib + BaseMemoryLib + DevicePathLib + UefiLib + HobLib + PcdLib + +[Guids] + gDasharoSystemFeaturesGuid + +[Protocols] + gEfiPciPlatformProtocolGuid ## PRODUCES + gEfiPciIoProtocolGuid ## COMSUMES + +[Pcd] + gDasharoPayloadPkgTokenSpaceGuid.PcdLoadOptionRoms diff --git a/DasharoPayloadPkg/PlatformGopPolicy/PlatformGopPolicy.c b/DasharoPayloadPkg/PlatformGopPolicy/PlatformGopPolicy.c new file mode 100644 index 0000000000..1205a3843c --- /dev/null +++ b/DasharoPayloadPkg/PlatformGopPolicy/PlatformGopPolicy.c @@ -0,0 +1,180 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + + SPDX-License-Identifier: BSD-2-Clause-Patent + + + + +--*/ + +/** @file +**/ + +#include +#include +#include +#include +#include "PlatformGopPolicy.h" + +#include +#include + +PLATFORM_GOP_POLICY_PROTOCOL mPlatformGOPPolicy; + +// +// Function implementations +// + +/** + The function will execute with as the platform policy, and gives + the Platform Lid Status. IBV/OEM can customize this code for their specific + policy action. + + @param CurrentLidStatus Gives the current LID Status + + @retval EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +GetPlatformLidStatus ( + OUT LID_STATUS *CurrentLidStatus +) +{ + EFI_STATUS Status; + + Status = LaptopGetLidState (CurrentLidStatus); + + if (EFI_ERROR (Status)) + *CurrentLidStatus = LidOpen; + + return EFI_SUCCESS; +} + +/** + The function will execute and gives the Video Bios Table Size and Address. + + @param VbtAddress Gives the Physical Address of Video BIOS Table + + @param VbtSize Gives the Size of Video BIOS Table + + @retval EFI_STATUS. + +**/ + +EFI_STATUS +EFIAPI +GetVbtData ( + OUT EFI_PHYSICAL_ADDRESS *VbtAddress, + OUT UINT32 *VbtSize +) +{ + EFI_STATUS Status; + UINTN FvProtocolCount; + EFI_HANDLE *FvHandles; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; + UINTN Index; + UINT32 AuthenticationStatus; + + UINT8 *Buffer; + UINTN VbtBufferSize; + + Buffer = 0; + FvHandles = NULL; + + if (VbtAddress == NULL || VbtSize == NULL){ + return EFI_INVALID_PARAMETER; + } + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolume2ProtocolGuid, + NULL, + &FvProtocolCount, + &FvHandles + ); + + if (!EFI_ERROR (Status)) { + for (Index = 0; Index < FvProtocolCount; Index++) { + Status = gBS->HandleProtocol ( + FvHandles[Index], + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **) &Fv + ); + VbtBufferSize = 0; + Status = Fv->ReadSection ( + Fv, + &gBmpImageGuid, + EFI_SECTION_RAW, + 0, + (void **)&Buffer, + &VbtBufferSize, + &AuthenticationStatus + ); + + if (!EFI_ERROR (Status)) { + *VbtAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer; + *VbtSize = (UINT32)VbtBufferSize; + Status = EFI_SUCCESS; + break; + } + } + } else { + Status = EFI_NOT_FOUND; + } + + if (FvHandles != NULL) { + gBS->FreePool (FvHandles); + FvHandles = NULL; + } + + return Status; +} + +/** + Entry point for the Platform GOP Policy Driver. + + @param ImageHandle Image handle of this driver. + @param SystemTable Global system service table. + + @retval EFI_SUCCESS Initialization complete. + @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver. + +**/ + +EFI_STATUS +EFIAPI +PlatformGOPPolicyEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) + +{ + EFI_STATUS Status = EFI_SUCCESS; + + gBS = SystemTable->BootServices; + + gBS->SetMem ( + &mPlatformGOPPolicy, + sizeof (PLATFORM_GOP_POLICY_PROTOCOL), + 0 + ); + + mPlatformGOPPolicy.Revision = PLATFORM_GOP_POLICY_PROTOCOL_REVISION_01; + mPlatformGOPPolicy.GetPlatformLidStatus = GetPlatformLidStatus; + mPlatformGOPPolicy.GetVbtData = GetVbtData; + + // + // Install protocol to allow access to this Policy. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gPlatformGOPPolicyGuid, + &mPlatformGOPPolicy, + NULL + ); + + return Status; +} diff --git a/DasharoPayloadPkg/PlatformGopPolicy/PlatformGopPolicy.h b/DasharoPayloadPkg/PlatformGopPolicy/PlatformGopPolicy.h new file mode 100644 index 0000000000..251d6701e8 --- /dev/null +++ b/DasharoPayloadPkg/PlatformGopPolicy/PlatformGopPolicy.h @@ -0,0 +1,64 @@ +/*++ + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved + + + SPDX-License-Identifier: BSD-2-Clause-Patent + + + + +--*/ + +/** @file +**/ + +#ifndef _PLATFORM_GOP_POLICY_PROTOCOL_H_ +#define _PLATFORM_GOP_POLICY_PROTOCOL_H_ + +#define EFI_PLATFORM_GOP_POLICY_PROTOCOL_GUID \ + { 0xec2e931b, 0x3281, 0x48a5, 0x81, 0x7, 0xdf, 0x8a, 0x8b, 0xed, 0x3c, 0x5d } + +#define EFI_BMP_IMAGE_GUID \ + { 0x878AC2CC, 0x5343, 0x46F2, 0xB5, 0x63, 0x51, 0xF8, 0x9D, 0xAF, 0x56, 0xBA } + +#define PLATFORM_GOP_POLICY_PROTOCOL_REVISION_01 0x01 +#define PLATFORM_GOP_POLICY_PROTOCOL_REVISION_02 x0222 + +#pragma pack(1) + +typedef enum { + Docked, + UnDocked, + DockStatusMax +} DOCK_STATUS; + +typedef +EFI_STATUS +(EFIAPI *GET_PLATFORM_LID_STATUS) ( + OUT LID_STATUS *CurrentLidStatus +); + +typedef +EFI_STATUS +(EFIAPI *GET_VBT_DATA) ( + OUT EFI_PHYSICAL_ADDRESS *VbtAddress, + OUT UINT32 *VbtSize +); + +#pragma pack() + +typedef struct _PLATFORM_GOP_POLICY_PROTOCOL { + UINT32 Revision; + GET_PLATFORM_LID_STATUS GetPlatformLidStatus; + GET_VBT_DATA GetVbtData; +} PLATFORM_GOP_POLICY_PROTOCOL; + +// +// Extern the GUID for protocol users. +// +extern EFI_GUID gPlatformGOPPolicyGuid; + +extern EFI_GUID gBmpImageGuid; + +#endif diff --git a/DasharoPayloadPkg/PlatformGopPolicy/PlatformGopPolicy.inf b/DasharoPayloadPkg/PlatformGopPolicy/PlatformGopPolicy.inf new file mode 100644 index 0000000000..c424f23753 --- /dev/null +++ b/DasharoPayloadPkg/PlatformGopPolicy/PlatformGopPolicy.inf @@ -0,0 +1,45 @@ +# +# +# Copyright (c) 1999 - 2019, Intel Corporation. All rights reserved +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PlatformGOPPolicy + FILE_GUID = 9737D7CA-D869-45e5-A5EF-75D9438688DE + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = PlatformGOPPolicyEntryPoint + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = X64 +# + +[Sources.common] + PlatformGopPolicy.c + +[Packages] + MdePkg/MdePkg.dec + DasharoPayloadPkg/DasharoPayloadPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + UefiDriverEntryPoint + UefiRuntimeServicesTableLib + LaptopLidLib + +[Guids] + gBmpImageGuid + +[Protocols] + gEfiFirmwareVolume2ProtocolGuid + gPlatformGOPPolicyGuid + +[Depex] + gEfiVariableArchProtocolGuid diff --git a/DasharoPayloadPkg/SecCore/FindPeiCore.c b/DasharoPayloadPkg/SecCore/FindPeiCore.c new file mode 100644 index 0000000000..f67d1afb96 --- /dev/null +++ b/DasharoPayloadPkg/SecCore/FindPeiCore.c @@ -0,0 +1,193 @@ +/** @file + Locate the entry point for the PEI Core + +Copyright (c) 2013, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +#include "SecMain.h" + +/** + Find core image base. + + @param BootFirmwareVolumePtr Point to the boot firmware volume. + @param SecCoreImageBase The base address of the SEC core image. + @param PeiCoreImageBase The base address of the PEI core image. + +**/ +EFI_STATUS +EFIAPI +FindImageBase ( + IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr, + OUT EFI_PHYSICAL_ADDRESS *SecCoreImageBase, + OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase + ) +{ + EFI_PHYSICAL_ADDRESS CurrentAddress; + EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume; + EFI_FFS_FILE_HEADER *File; + UINT32 Size; + EFI_PHYSICAL_ADDRESS EndOfFile; + EFI_COMMON_SECTION_HEADER *Section; + EFI_PHYSICAL_ADDRESS EndOfSection; + + *SecCoreImageBase = 0; + *PeiCoreImageBase = 0; + + CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) BootFirmwareVolumePtr; + EndOfFirmwareVolume = CurrentAddress + BootFirmwareVolumePtr->FvLength; + + // + // Loop through the FFS files in the Boot Firmware Volume + // + for (EndOfFile = CurrentAddress + BootFirmwareVolumePtr->HeaderLength; ; ) { + + CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL; + if (CurrentAddress > EndOfFirmwareVolume) { + return EFI_NOT_FOUND; + } + + File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress; + if (IS_FFS_FILE2 (File)) { + Size = FFS_FILE2_SIZE (File); + if (Size <= 0x00FFFFFF) { + return EFI_NOT_FOUND; + } + } else { + Size = FFS_FILE_SIZE (File); + if (Size < sizeof (EFI_FFS_FILE_HEADER)) { + return EFI_NOT_FOUND; + } + } + + EndOfFile = CurrentAddress + Size; + if (EndOfFile > EndOfFirmwareVolume) { + return EFI_NOT_FOUND; + } + + // + // Look for SEC Core / PEI Core files + // + if (File->Type != EFI_FV_FILETYPE_SECURITY_CORE && + File->Type != EFI_FV_FILETYPE_PEI_CORE) { + continue; + } + + // + // Loop through the FFS file sections within the FFS file + // + if (IS_FFS_FILE2 (File)) { + EndOfSection = (EFI_PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) File + sizeof (EFI_FFS_FILE_HEADER2)); + } else { + EndOfSection = (EFI_PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) File + sizeof (EFI_FFS_FILE_HEADER)); + } + for (;;) { + CurrentAddress = (EndOfSection + 3) & 0xfffffffffffffffcULL; + Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress; + + if (IS_SECTION2 (Section)) { + Size = SECTION2_SIZE (Section); + if (Size <= 0x00FFFFFF) { + return EFI_NOT_FOUND; + } + } else { + Size = SECTION_SIZE (Section); + if (Size < sizeof (EFI_COMMON_SECTION_HEADER)) { + return EFI_NOT_FOUND; + } + } + + EndOfSection = CurrentAddress + Size; + if (EndOfSection > EndOfFile) { + return EFI_NOT_FOUND; + } + + // + // Look for executable sections + // + if (Section->Type == EFI_SECTION_PE32 || Section->Type == EFI_SECTION_TE) { + if (File->Type == EFI_FV_FILETYPE_SECURITY_CORE) { + if (IS_SECTION2 (Section)) { + *SecCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER2)); + } else { + *SecCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER)); + } + } else { + if (IS_SECTION2 (Section)) { + *PeiCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER2)); + } else { + *PeiCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER)); + } + } + break; + } + } + + // + // Both SEC Core and PEI Core images found + // + if (*SecCoreImageBase != 0 && *PeiCoreImageBase != 0) { + return EFI_SUCCESS; + } + } +} + +/** + Find and return Pei Core entry point. + + It also find SEC and PEI Core file debug information. It will report them if + remote debug is enabled. + + @param BootFirmwareVolumePtr Point to the boot firmware volume. + @param PeiCoreEntryPoint The entry point of the PEI core. + +**/ +VOID +EFIAPI +FindAndReportEntryPoints ( + IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr, + OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS SecCoreImageBase; + EFI_PHYSICAL_ADDRESS PeiCoreImageBase; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + + // + // Find SEC Core and PEI Core image base + // + Status = FindImageBase (BootFirmwareVolumePtr, &SecCoreImageBase, &PeiCoreImageBase); + ASSERT_EFI_ERROR (Status); + + ZeroMem ((VOID *) &ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT)); + // + // Report SEC Core debug information when remote debug is enabled + // + ImageContext.ImageAddress = SecCoreImageBase; + ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress); + PeCoffLoaderRelocateImageExtraAction (&ImageContext); + + // + // Report PEI Core debug information when remote debug is enabled + // + ImageContext.ImageAddress = PeiCoreImageBase; + ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress); + PeCoffLoaderRelocateImageExtraAction (&ImageContext); + + // + // Find PEI Core entry point + // + Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, (VOID**) PeiCoreEntryPoint); + if (EFI_ERROR (Status)) { + *PeiCoreEntryPoint = 0; + } + + return; +} + diff --git a/DasharoPayloadPkg/SecCore/Ia32/SecEntry.nasm b/DasharoPayloadPkg/SecCore/Ia32/SecEntry.nasm new file mode 100644 index 0000000000..877fc61ef0 --- /dev/null +++ b/DasharoPayloadPkg/SecCore/Ia32/SecEntry.nasm @@ -0,0 +1,78 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Abstract: +; +; Entry point for the coreboot UEFI payload. +; +;------------------------------------------------------------------------------ + +SECTION .text + +; C Functions +extern ASM_PFX(SecStartup) + +; Pcds +extern ASM_PFX(PcdGet32 (PcdPayloadFdMemBase)) +extern ASM_PFX(PcdGet32 (PcdPayloadStackTop)) + +; +; SecCore Entry Point +; +; Processor is in flat protected mode +; +; @param[in] EAX Initial value of the EAX register (BIST: Built-in Self Test) +; @param[in] DI 'BP': boot-strap processor, or 'AP': application processor +; @param[in] EBP Pointer to the start of the Boot Firmware Volume +; +; @return None This routine does not return +; +global ASM_PFX(_ModuleEntryPoint) +ASM_PFX(_ModuleEntryPoint): + ; + ; Disable all the interrupts + ; + cli + + ; + ; Save the Payload HOB base address before switching the stack + ; + mov eax, [esp + 4] + + ; + ; Construct the temporary memory at 0x80000, length 0x10000 + ; + mov esp, DWORD [ASM_PFX(PcdGet32 (PcdPayloadStackTop))] + + ; + ; Push the Payload HOB base address onto new stack + ; + push eax + + ; + ; Pass BFV into the PEI Core + ; + push DWORD [ASM_PFX(PcdGet32 (PcdPayloadFdMemBase))] + + ; + ; Pass stack base into the PEI Core + ; + push BASE_512KB + + ; + ; Pass stack size into the PEI Core + ; + push SIZE_64KB + + ; + ; Pass Control into the PEI Core + ; + call ASM_PFX(SecStartup) + + ; + ; Should never return + ; + jmp $ + diff --git a/DasharoPayloadPkg/SecCore/Ia32/Stack.nasm b/DasharoPayloadPkg/SecCore/Ia32/Stack.nasm new file mode 100644 index 0000000000..55fd2243c8 --- /dev/null +++ b/DasharoPayloadPkg/SecCore/Ia32/Stack.nasm @@ -0,0 +1,72 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Abstract: +; +; Switch the stack from temporary memory to permanent memory. +; +;------------------------------------------------------------------------------ + +SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; SecSwitchStack ( +; UINT32 TemporaryMemoryBase, +; UINT32 PermenentMemoryBase +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(SecSwitchStack) +ASM_PFX(SecSwitchStack): + ; + ; Save three register: eax, ebx, ecx + ; + push eax + push ebx + push ecx + push edx + + ; + ; !!CAUTION!! this function address's is pushed into stack after + ; migration of whole temporary memory, so need save it to permanent + ; memory at first! + ; + + mov ebx, [esp + 20] ; Save the first parameter + mov ecx, [esp + 24] ; Save the second parameter + + ; + ; Save this function's return address into permanent memory at first. + ; Then, Fixup the esp point to permanent memory + ; + mov eax, esp + sub eax, ebx + add eax, ecx + mov edx, [esp] ; copy pushed register's value to permanent memory + mov [eax], edx + mov edx, [esp + 4] + mov [eax + 4], edx + mov edx, [esp + 8] + mov [eax + 8], edx + mov edx, [esp + 12] + mov [eax + 12], edx + mov edx, [esp + 16] ; Update return address into permanent memory + mov [eax + 16], edx + mov esp, eax ; From now, esp is pointed to permanent memory + + ; + ; Fixup the ebp point to permanent memory + ; + mov eax, ebp + sub eax, ebx + add eax, ecx + mov ebp, eax ; From now, ebp is pointed to permanent memory + + pop edx + pop ecx + pop ebx + pop eax + ret diff --git a/DasharoPayloadPkg/SecCore/SecCore.inf b/DasharoPayloadPkg/SecCore/SecCore.inf new file mode 100644 index 0000000000..d8197a300d --- /dev/null +++ b/DasharoPayloadPkg/SecCore/SecCore.inf @@ -0,0 +1,58 @@ +## @file +# This is the first module taking control from the coreboot. +# +# Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SecCore + FILE_GUID = BA7BE337-6CFB-4dbb-B26C-21EC2FC16073 + MODULE_TYPE = SEC + VERSION_STRING = 1.0 + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + SecMain.c + SecMain.h + FindPeiCore.c + +[Sources.IA32] + Ia32/Stack.nasm + Ia32/SecEntry.nasm + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiCpuPkg/UefiCpuPkg.dec + DasharoPayloadPkg/DasharoPayloadPkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + BaseLib + PcdLib + DebugAgentLib + BaseCpuLib + PeCoffGetEntryPointLib + PeCoffExtraActionLib + +[Ppis] + gEfiSecPlatformInformationPpiGuid # PPI ALWAYS_PRODUCED + gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED + gEfiPayLoadHobBasePpiGuid # PPI ALWAYS_PRODUCED + +[Pcd] + gDasharoPayloadPkgTokenSpaceGuid.PcdPayloadFdMemBase + gDasharoPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize + gDasharoPayloadPkgTokenSpaceGuid.PcdPayloadStackTop diff --git a/DasharoPayloadPkg/SecCore/SecMain.c b/DasharoPayloadPkg/SecCore/SecMain.c new file mode 100644 index 0000000000..c0ca0e7d40 --- /dev/null +++ b/DasharoPayloadPkg/SecCore/SecMain.c @@ -0,0 +1,288 @@ +/** @file + C functions in SEC + +Copyright (c) 2013, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include "SecMain.h" + +EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI gSecTemporaryRamSupportPpi = { + SecTemporaryRamSupport +}; + +EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformationPpi[] = { + { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiTemporaryRamSupportPpiGuid, + &gSecTemporaryRamSupportPpi + } +}; + +// +// These are IDT entries pointing to 10:FFFFFFE4h. +// +UINT64 mIdtEntryTemplate = 0xffff8e000010ffe4ULL; + +/** + Caller provided function to be invoked at the end of InitializeDebugAgent(). + + Entry point to the C language phase of SEC. After the SEC assembly + code has initialized some temporary memory and set up the stack, + the control is transferred to this function. + + @param[in] Context The first input parameter of InitializeDebugAgent(). + +**/ +VOID +EFIAPI +SecStartupPhase2( + IN VOID *Context + ); + + +/** + + Entry point to the C language phase of SEC. After the SEC assembly + code has initialized some temporary memory and set up the stack, + the control is transferred to this function. + + + @param SizeOfRam Size of the temporary memory available for use. + @param TempRamBase Base address of temporary ram + @param BootFirmwareVolume Base address of the Boot Firmware Volume. + @param BootloaderParameter A parameter from bootloader, e.g. HobList from SlimBootloader + +**/ +VOID +EFIAPI +SecStartup ( + IN UINT32 SizeOfRam, + IN UINT32 TempRamBase, + IN VOID *BootFirmwareVolume, + IN UINT32 BootloaderParameter + ) +{ + EFI_SEC_PEI_HAND_OFF SecCoreData; + IA32_DESCRIPTOR IdtDescriptor; + SEC_IDT_TABLE IdtTableInStack; + UINT32 Index; + UINT32 PeiStackSize; + + PeiStackSize = (SizeOfRam >> 1); + + ASSERT (PeiStackSize < SizeOfRam); + + // + // Process all libraries constructor function linked to SecCore. + // + ProcessLibraryConstructorList (); + + // + // Initialize floating point operating environment + // to be compliant with UEFI spec. + // + InitializeFloatingPointUnits (); + + + // |-------------------|----> + // |Idt Table | + // |-------------------| + // |PeiService Pointer | PeiStackSize + // |-------------------| + // | | + // | Stack | + // |-------------------|----> + // | | + // | | + // | Heap | PeiTemporaryRamSize + // | | + // | | + // |-------------------|----> TempRamBase + + IdtTableInStack.PeiService = 0; + for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) { + CopyMem ((VOID*)&IdtTableInStack.IdtTable[Index], (VOID*)&mIdtEntryTemplate, sizeof (UINT64)); + } + + IdtDescriptor.Base = (UINTN) &IdtTableInStack.IdtTable; + IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1); + + AsmWriteIdtr (&IdtDescriptor); + + // + // Update the base address and length of Pei temporary memory + // + SecCoreData.DataSize = (UINT16) sizeof (EFI_SEC_PEI_HAND_OFF); + SecCoreData.BootFirmwareVolumeBase = BootFirmwareVolume; + SecCoreData.BootFirmwareVolumeSize = (UINTN)(0x100000000ULL - (UINTN) BootFirmwareVolume); + SecCoreData.TemporaryRamBase = (VOID*)(UINTN) TempRamBase; + SecCoreData.TemporaryRamSize = SizeOfRam; + SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase; + SecCoreData.PeiTemporaryRamSize = SizeOfRam - PeiStackSize; + SecCoreData.StackBase = (VOID*)(UINTN)(TempRamBase + SecCoreData.PeiTemporaryRamSize); + SecCoreData.StackSize = PeiStackSize; + + // + // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready. + // + InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2); + +} + +/** + Caller provided function to be invoked at the end of InitializeDebugAgent(). + + Entry point to the C language phase of SEC. After the SEC assembly + code has initialized some temporary memory and set up the stack, + the control is transferred to this function. + + @param[in] Context The first input parameter of InitializeDebugAgent(). + +**/ +VOID +EFIAPI +SecStartupPhase2( + IN VOID *Context + ) +{ + EFI_SEC_PEI_HAND_OFF *SecCoreData; + EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint; + + SecCoreData = (EFI_SEC_PEI_HAND_OFF *) Context; + // + // Find Pei Core entry point. It will report SEC and Pei Core debug information if remote debug + // is enabled. + // + FindAndReportEntryPoints ((EFI_FIRMWARE_VOLUME_HEADER *) SecCoreData->BootFirmwareVolumeBase, &PeiCoreEntryPoint); + if (PeiCoreEntryPoint == NULL) + { + CpuDeadLoop (); + } + + // + // Transfer the control to the PEI core + // + ASSERT (PeiCoreEntryPoint != NULL); + (*PeiCoreEntryPoint) (SecCoreData, (EFI_PEI_PPI_DESCRIPTOR *)&mPeiSecPlatformInformationPpi); + + // + // Should not come here. + // + return ; +} + +/** + This service of the TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into + permanent memory. + + @param PeiServices Pointer to the PEI Services Table. + @param TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the + Temporary RAM contents. + @param PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the + Temporary RAM contents. + @param CopySize Amount of memory to migrate from temporary to permanent memory. + + @retval EFI_SUCCESS The data was successfully returned. + @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when + TemporaryMemoryBase > PermanentMemoryBase. + +**/ +EFI_STATUS +EFIAPI +SecTemporaryRamSupport ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase, + IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase, + IN UINTN CopySize + ) +{ + IA32_DESCRIPTOR IdtDescriptor; + VOID* OldHeap; + VOID* NewHeap; + VOID* OldStack; + VOID* NewStack; + DEBUG_AGENT_CONTEXT_POSTMEM_SEC DebugAgentContext; + BOOLEAN OldStatus; + UINTN PeiStackSize; + + PeiStackSize = (CopySize >> 1); + + ASSERT (PeiStackSize < CopySize); + + // + // |-------------------|----> + // | Stack | PeiStackSize + // |-------------------|----> + // | Heap | PeiTemporaryRamSize + // |-------------------|----> TempRamBase + // + // |-------------------|----> + // | Heap | PeiTemporaryRamSize + // |-------------------|----> + // | Stack | PeiStackSize + // |-------------------|----> PermanentMemoryBase + // + + OldHeap = (VOID*)(UINTN)TemporaryMemoryBase; + NewHeap = (VOID*)((UINTN)PermanentMemoryBase + PeiStackSize); + + OldStack = (VOID*)((UINTN)TemporaryMemoryBase + CopySize - PeiStackSize); + NewStack = (VOID*)(UINTN)PermanentMemoryBase; + + DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap; + DebugAgentContext.StackMigrateOffset = (UINTN)NewStack - (UINTN)OldStack; + + OldStatus = SaveAndSetDebugTimerInterrupt (FALSE); + // + // Initialize Debug Agent to support source level debug in PEI phase after memory ready. + // It will build HOB and fix up the pointer in IDT table. + // + InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *) &DebugAgentContext, NULL); + + // + // Migrate Heap + // + CopyMem (NewHeap, OldHeap, CopySize - PeiStackSize); + + // + // Migrate Stack + // + CopyMem (NewStack, OldStack, PeiStackSize); + + + // + // We need *not* fix the return address because currently, + // The PeiCore is executed in flash. + // + + // + // Rebase IDT table in permanent memory + // + AsmReadIdtr (&IdtDescriptor); + IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack; + + AsmWriteIdtr (&IdtDescriptor); + + + // + // Program MTRR + // + + // + // SecSwitchStack function must be invoked after the memory migration + // immediately, also we need fixup the stack change caused by new call into + // permanent memory. + // + SecSwitchStack ( + (UINT32) (UINTN) OldStack, + (UINT32) (UINTN) NewStack + ); + + SaveAndSetDebugTimerInterrupt (OldStatus); + + return EFI_SUCCESS; +} + diff --git a/DasharoPayloadPkg/SecCore/SecMain.h b/DasharoPayloadPkg/SecCore/SecMain.h new file mode 100644 index 0000000000..42e4c8517e --- /dev/null +++ b/DasharoPayloadPkg/SecCore/SecMain.h @@ -0,0 +1,131 @@ +/** @file + Master header file for SecCore. + +Copyright (c) 2013, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _SEC_CORE_H_ +#define _SEC_CORE_H_ + + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +#define SEC_IDT_ENTRY_COUNT 34 + +typedef struct _SEC_IDT_TABLE { + // + // Reserved 8 bytes preceding IDT to store EFI_PEI_SERVICES**, since IDT base + // address should be 8-byte alignment. + // Note: For IA32, only the 4 bytes immediately preceding IDT is used to store + // EFI_PEI_SERVICES** + // + UINT64 PeiService; + UINT64 IdtTable[SEC_IDT_ENTRY_COUNT]; +} SEC_IDT_TABLE; + +/** + Switch the stack in the temporary memory to the one in the permanent memory. + + This function must be invoked after the memory migration immediately. The relative + position of the stack in the temporary and permanent memory is same. + + @param TemporaryMemoryBase Base address of the temporary memory. + @param PermenentMemoryBase Base address of the permanent memory. +**/ +VOID +EFIAPI +SecSwitchStack ( + UINT32 TemporaryMemoryBase, + UINT32 PermenentMemoryBase + ); + +/** + This service of the TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into + permanent memory. + + @param PeiServices Pointer to the PEI Services Table. + @param TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the + Temporary RAM contents. + @param PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the + Temporary RAM contents. + @param CopySize Amount of memory to migrate from temporary to permanent memory. + + @retval EFI_SUCCESS The data was successfully returned. + @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when + TemporaryMemoryBase > PermanentMemoryBase. + +**/ +EFI_STATUS +EFIAPI +SecTemporaryRamSupport ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase, + IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase, + IN UINTN CopySize + ); + +/** + Entry point to the C language phase of SEC. After the SEC assembly + code has initialized some temporary memory and set up the stack, + the control is transferred to this function. + + @param SizeOfRam Size of the temporary memory available for use. + @param TempRamBase Base address of temporary ram + @param BootFirmwareVolume Base address of the Boot Firmware Volume. + @param BootloaderParameter A parameter from bootloader, e.g. HobList from SlimBootloader + +**/ +VOID +EFIAPI +SecStartup ( + IN UINT32 SizeOfRam, + IN UINT32 TempRamBase, + IN VOID *BootFirmwareVolume, + IN UINT32 BootloaderParameter + ); + +/** + Find and return Pei Core entry point. + + It also find SEC and PEI Core file debug information. It will report them if + remote debug is enabled. + + @param BootFirmwareVolumePtr Point to the boot firmware volume. + @param PeiCoreEntryPoint Point to the PEI core entry point. + +**/ +VOID +EFIAPI +FindAndReportEntryPoints ( + IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr, + OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint + ); + +/** + Autogenerated function that calls the library constructors for all of the module's + dependent libraries. This function must be called by the SEC Core once a stack has + been established. + +**/ +VOID +EFIAPI +ProcessLibraryConstructorList ( + VOID + ); + +#endif diff --git a/DasharoPayloadPkg/SecureBootDefaultKeys/DBXUpdate.bin b/DasharoPayloadPkg/SecureBootDefaultKeys/DBXUpdate.bin new file mode 100644 index 0000000000..27be253ff6 Binary files /dev/null and b/DasharoPayloadPkg/SecureBootDefaultKeys/DBXUpdate.bin differ diff --git a/DasharoPayloadPkg/SecureBootDefaultKeys/MicCorKEKCA2011_2011-06-24.crt b/DasharoPayloadPkg/SecureBootDefaultKeys/MicCorKEKCA2011_2011-06-24.crt new file mode 100644 index 0000000000..2787083e0c Binary files /dev/null and b/DasharoPayloadPkg/SecureBootDefaultKeys/MicCorKEKCA2011_2011-06-24.crt differ diff --git a/DasharoPayloadPkg/SecureBootDefaultKeys/MicCorUEFCA2011_2011-06-27.crt b/DasharoPayloadPkg/SecureBootDefaultKeys/MicCorUEFCA2011_2011-06-27.crt new file mode 100644 index 0000000000..9aa6ac6c79 Binary files /dev/null and b/DasharoPayloadPkg/SecureBootDefaultKeys/MicCorUEFCA2011_2011-06-27.crt differ diff --git a/DasharoPayloadPkg/SecureBootDefaultKeys/MicWinProPCA2011_2011-10-19.crt b/DasharoPayloadPkg/SecureBootDefaultKeys/MicWinProPCA2011_2011-10-19.crt new file mode 100644 index 0000000000..a6d001c219 Binary files /dev/null and b/DasharoPayloadPkg/SecureBootDefaultKeys/MicWinProPCA2011_2011-10-19.crt differ diff --git a/DasharoPayloadPkg/SecureBootDefaultKeys/README b/DasharoPayloadPkg/SecureBootDefaultKeys/README new file mode 100644 index 0000000000..d39e547f53 --- /dev/null +++ b/DasharoPayloadPkg/SecureBootDefaultKeys/README @@ -0,0 +1,9 @@ +# PK certificate generation + +* Do not save private key for re-usage. +* Generate a RSA 2048 x509 certificate +* Exponent should be 65537 +* Microsoft certificates can be found here: https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/windows-secure-boot-key-creation-and-management-guidance +* Date of downloading Microsoft certificates and DBX: 16-11-2023 + +openssl req -outform DER -newkey rsa:2048 -keyout /dev/null -passout file:<(head -c 40 /dev/urandom) -x509 -days 1825 -out pk.crt -subj "/C=PL/ST=Pomerania/L=Gdansk/O=3mdeb Sp. z o.o./CN=Dasharo PK/emailAddress=contact@dasharo.com" diff --git a/DasharoPayloadPkg/SecureBootDefaultKeys/microsoft_corporation_kek_2k_ca_2023.crt b/DasharoPayloadPkg/SecureBootDefaultKeys/microsoft_corporation_kek_2k_ca_2023.crt new file mode 100644 index 0000000000..e6ffb4f975 Binary files /dev/null and b/DasharoPayloadPkg/SecureBootDefaultKeys/microsoft_corporation_kek_2k_ca_2023.crt differ diff --git a/DasharoPayloadPkg/SecureBootDefaultKeys/microsoft_uefi_ca_2023.crt b/DasharoPayloadPkg/SecureBootDefaultKeys/microsoft_uefi_ca_2023.crt new file mode 100644 index 0000000000..39a91b3173 Binary files /dev/null and b/DasharoPayloadPkg/SecureBootDefaultKeys/microsoft_uefi_ca_2023.crt differ diff --git a/DasharoPayloadPkg/SecureBootDefaultKeys/pk.crt b/DasharoPayloadPkg/SecureBootDefaultKeys/pk.crt new file mode 100644 index 0000000000..e0e0156c99 Binary files /dev/null and b/DasharoPayloadPkg/SecureBootDefaultKeys/pk.crt differ diff --git a/DasharoPayloadPkg/SecureBootDefaultKeys/windows_uefi_ca_2023.crt b/DasharoPayloadPkg/SecureBootDefaultKeys/windows_uefi_ca_2023.crt new file mode 100644 index 0000000000..4c5430b283 Binary files /dev/null and b/DasharoPayloadPkg/SecureBootDefaultKeys/windows_uefi_ca_2023.crt differ diff --git a/DasharoPayloadPkg/SecureBootEnrollDefaultKeys/SecureBootSetup.c b/DasharoPayloadPkg/SecureBootEnrollDefaultKeys/SecureBootSetup.c new file mode 100644 index 0000000000..a246e1cd3f --- /dev/null +++ b/DasharoPayloadPkg/SecureBootEnrollDefaultKeys/SecureBootSetup.c @@ -0,0 +1,645 @@ +/** @file + Enroll default PK, KEK, DB and DBX + + 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 which accompanies this + distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license. + + THE 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 EFI_MICROSOFT_KEK_CERT_GUID \ + { 0xA23665E3, 0xACA6, 0x4F6D, {0x80, 0xCC, 0x34, 0x1E, 0x7D, 0x7B, 0x8C, 0xC6} } + +#define EFI_SECUREBOOT_PK_CERT_GUID \ + { 0xF8104268, 0xA364, 0x45F5, {0x8E, 0x00, 0xAB, 0xA3, 0xFD, 0xEA, 0x12, 0xBE} } + +#define EFI_MICROSOFT_DB1_CERT_GUID \ + { 0x26A517B0, 0xE3FD, 0x46C2, {0x89, 0x32, 0xE9, 0x26, 0xBF, 0x98, 0x94, 0x1F} } + +#define EFI_MICROSOFT_DB2_CERT_GUID \ + { 0x91D2E32B, 0x0134, 0x4306, {0xBA, 0x90, 0x54, 0xED, 0xCB, 0xF3, 0x49, 0xCA} } + +#define EFI_MICROSOFT_DBX_GUID \ + { 0x74BB6E72, 0x2A56, 0x4D0E, {0xA5, 0xB3, 0x5D, 0x39, 0xFC, 0x2E, 0xE3, 0x46} } + +#define EFI_MICROSOFT_OWNER_GUID \ + { 0x77FA9ABD, 0x0359, 0x4D32, {0xBD, 0x60, 0x28, 0xF4, 0xE7, 0x8F, 0x78, 0x4B} } + +EFI_GUID gEfiSecureBootDb1CertGuid = EFI_MICROSOFT_DB1_CERT_GUID; +EFI_GUID gEfiSecureBootDb2CertGuid = EFI_MICROSOFT_DB2_CERT_GUID; +EFI_GUID gEfiSecureBootDbxCrlGuid = EFI_MICROSOFT_DBX_GUID; +EFI_GUID gEfiSecureBootKekCertGuid = EFI_MICROSOFT_KEK_CERT_GUID; +EFI_GUID gEfiSecureBootPkCertGuid = EFI_SECUREBOOT_PK_CERT_GUID; +EFI_GUID gEfiMicrosoftOwnerGuid = EFI_MICROSOFT_OWNER_GUID; + +// +// The most important thing about the variable payload is that it is a list of +// lists, where the element size of any given *inner* list is constant. +// +// Since X509 certificates vary in size, each of our *inner* lists will contain +// one element only (one X.509 certificate). This is explicitly mentioned in +// the UEFI specification, in "28.4.1 Signature Database", in a Note. +// +// The list structure looks as follows: +// +// struct EFI_VARIABLE_AUTHENTICATION_2 { | +// struct EFI_TIME { | +// UINT16 Year; | +// UINT8 Month; | +// UINT8 Day; | +// UINT8 Hour; | +// UINT8 Minute; | +// UINT8 Second; | +// UINT8 Pad1; | +// UINT32 Nanosecond; | +// INT16 TimeZone; | +// UINT8 Daylight; | +// UINT8 Pad2; | +// } TimeStamp; | +// | +// struct WIN_CERTIFICATE_UEFI_GUID { | | +// struct WIN_CERTIFICATE { | | +// UINT32 dwLength; ----------------------------------------+ | +// UINT16 wRevision; | | +// UINT16 wCertificateType; | | +// } Hdr; | +- DataSize +// | | +// EFI_GUID CertType; | | +// UINT8 CertData[1] = { <--- "struct hack" | | +// struct EFI_SIGNATURE_LIST { | | | +// EFI_GUID SignatureType; | | | +// UINT32 SignatureListSize; -------------------------+ | | +// UINT32 SignatureHeaderSize; | | | +// UINT32 SignatureSize; ---------------------------+ | | | +// UINT8 SignatureHeader[SignatureHeaderSize]; | | | | +// v | | | +// struct EFI_SIGNATURE_DATA { | | | | +// EFI_GUID SignatureOwner; | | | | +// UINT8 SignatureData[1] = { <--- "struct hack" | | | | +// X.509 payload | | | | +// } | | | | +// } Signatures[]; | | | +// } SigLists[]; | | +// }; | | +// } AuthInfo; | | +// }; | +// +// Given that the "struct hack" invokes undefined behavior (which is why C99 +// introduced the flexible array member), and because subtracting those pesky +// sizes of 1 is annoying, and because the format is fully specified in the +// UEFI specification, we'll introduce two matching convenience structures that +// are customized for our X.509 purposes. +// + +#pragma pack(1) +typedef struct { + EFI_TIME TimeStamp; + + // + // dwLength covers data below + // + UINT32 dwLength; + UINT16 wRevision; + UINT16 wCertificateType; + EFI_GUID CertType; +} SINGLE_HEADER; + +typedef struct { + // + // SignatureListSize covers data below + // + EFI_GUID SignatureType; + UINT32 SignatureListSize; + UINT32 SignatureHeaderSize; // constant 0 + UINT32 SignatureSize; + + // + // SignatureSize covers data below + // + EFI_GUID SignatureOwner; + + // + // X.509 certificate follows + // +} REPEATING_HEADER; +#pragma pack() + +/** + Enroll a set of certificates in a global variable, overwriting it. + + The variable will be rewritten with NV+BS+RT+AT attributes. + + @param[in] VariableName The name of the variable to overwrite. + + @param[in] VendorGuid The namespace (ie. vendor GUID) of the variable to + overwrite. + + @param[in] CertType The GUID determining the type of all the + certificates in the set that is passed in. For + example, gEfiCertX509Guid stands for DER-encoded + X.509 certificates, while gEfiCertSha256Guid stands + for SHA256 image hashes. + + @param[in] ... A list of + + IN CONST UINT8 *Cert, + IN UINTN CertSize, + IN CONST EFI_GUID *OwnerGuid + + triplets. If the first component of a triplet is + NULL, then the other two components are not + accessed, and processing is terminated. The list of + certificates is enrolled in the variable specified, + overwriting it. The OwnerGuid component identifies + the agent installing the certificate. + + @retval EFI_INVALID_PARAMETER The triplet list is empty (ie. the first Cert + value is NULL), or one of the CertSize values + is 0, or one of the CertSize values would + overflow the accumulated UINT32 data size. + + @retval EFI_OUT_OF_RESOURCES Out of memory while formatting variable + payload. + + @retval EFI_SUCCESS Enrollment successful; the variable has been + overwritten (or created). + + @return Error codes from gRT->GetTime() and + gRT->SetVariable(). + **/ +STATIC +EFI_STATUS +EFIAPI +EnrollListOfCerts ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN EFI_GUID *CertType, + ... + ) +{ + UINTN DataSize; + SINGLE_HEADER *SingleHeader; + REPEATING_HEADER *RepeatingHeader; + VA_LIST Marker; + CONST UINT8 *Cert; + EFI_STATUS Status; + UINT8 *Data; + UINT8 *Position; + + Status = EFI_SUCCESS; + + // + // compute total size first, for UINT32 range check, and allocation + // + DataSize = sizeof *SingleHeader; + VA_START (Marker, CertType); + for (Cert = VA_ARG (Marker, CONST UINT8 *); + Cert != NULL; + Cert = VA_ARG (Marker, CONST UINT8 *)) { + UINTN CertSize; + + CertSize = VA_ARG (Marker, UINTN); + (VOID)VA_ARG (Marker, CONST EFI_GUID *); + + if (CertSize == 0 || + CertSize > MAX_UINT32 - sizeof *RepeatingHeader || + DataSize > MAX_UINT32 - sizeof *RepeatingHeader - CertSize) { + Status = EFI_INVALID_PARAMETER; + break; + } + DataSize += sizeof *RepeatingHeader + CertSize; + } + VA_END (Marker); + + if (DataSize == sizeof *SingleHeader) { + Status = EFI_INVALID_PARAMETER; + } + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SecureBootSetup: Invalid certificate parameters\n")); + goto Out; + } + + Data = AllocatePool (DataSize); + if (Data == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Out; + } + + Position = Data; + + SingleHeader = (SINGLE_HEADER *)Position; + Status = gRT->GetTime (&SingleHeader->TimeStamp, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_INFO, "SecureBootSetup: GetTime failed\n")); + // Fill in dummy values + SingleHeader->TimeStamp.Year = 2018; + SingleHeader->TimeStamp.Month = 1; + SingleHeader->TimeStamp.Day = 1; + SingleHeader->TimeStamp.Hour = 0; + SingleHeader->TimeStamp.Minute = 0; + SingleHeader->TimeStamp.Second = 0; + Status = EFI_SUCCESS; + } + SingleHeader->TimeStamp.Pad1 = 0; + SingleHeader->TimeStamp.Nanosecond = 0; + SingleHeader->TimeStamp.TimeZone = 0; + SingleHeader->TimeStamp.Daylight = 0; + SingleHeader->TimeStamp.Pad2 = 0; + + // + // This looks like a bug in edk2. According to the UEFI specification, + // dwLength is "The length of the entire certificate, including the length of + // the header, in bytes". That shouldn't stop right after CertType -- it + // should include everything below it. + // + SingleHeader->dwLength = sizeof *SingleHeader - sizeof SingleHeader->TimeStamp; + SingleHeader->wRevision = 0x0200; + SingleHeader->wCertificateType = WIN_CERT_TYPE_EFI_GUID; + CopyGuid (&SingleHeader->CertType, &gEfiCertPkcs7Guid); + Position += sizeof *SingleHeader; + + VA_START (Marker, CertType); + for (Cert = VA_ARG (Marker, CONST UINT8 *); + Cert != NULL; + Cert = VA_ARG (Marker, CONST UINT8 *)) { + UINTN CertSize; + CONST EFI_GUID *OwnerGuid; + + CertSize = VA_ARG (Marker, UINTN); + OwnerGuid = VA_ARG (Marker, CONST EFI_GUID *); + + RepeatingHeader = (REPEATING_HEADER *)Position; + CopyGuid (&RepeatingHeader->SignatureType, CertType); + RepeatingHeader->SignatureListSize = + (UINT32)(sizeof *RepeatingHeader + CertSize); + RepeatingHeader->SignatureHeaderSize = 0; + RepeatingHeader->SignatureSize = + (UINT32)(sizeof RepeatingHeader->SignatureOwner + CertSize); + CopyGuid (&RepeatingHeader->SignatureOwner, OwnerGuid); + Position += sizeof *RepeatingHeader; + + CopyMem (Position, Cert, CertSize); + Position += CertSize; + } + VA_END (Marker); + + ASSERT (Data + DataSize == Position); + + Status = gRT->SetVariable (VariableName, VendorGuid, + (EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_RUNTIME_ACCESS | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS), + DataSize, Data); + + FreePool (Data); + +Out: + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SecureBootSetup: %a(\"%s\", %g): %r\n", __FUNCTION__, VariableName, + VendorGuid, Status)); + } + return Status; +} + + +STATIC +EFI_STATUS +EFIAPI +GetExact ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT VOID *Data, + IN UINTN DataSize, + IN BOOLEAN AllowMissing + ) +{ + UINTN Size; + EFI_STATUS Status; + + Size = DataSize; + Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &Size, Data); + if (EFI_ERROR (Status)) { + if (Status == EFI_NOT_FOUND && AllowMissing) { + ZeroMem (Data, DataSize); + return EFI_SUCCESS; + } + + DEBUG ((EFI_D_ERROR, "SecureBootSetup: GetVariable(\"%s\", %g): %r\n", VariableName, + VendorGuid, Status)); + return Status; + } + + if (Size != DataSize) { + DEBUG ((EFI_D_INFO, "SecureBootSetup: GetVariable(\"%s\", %g): expected size 0x%Lx, " + "got 0x%Lx\n", VariableName, VendorGuid, (UINT64)DataSize, (UINT64)Size)); + return EFI_PROTOCOL_ERROR; + } + + return EFI_SUCCESS; +} + +typedef struct { + UINT8 SetupMode; + UINT8 SecureBoot; + UINT8 SecureBootEnable; + UINT8 CustomMode; + UINT8 VendorKeys; +} SETTINGS; + +STATIC +EFI_STATUS +EFIAPI +GetSettings ( + OUT SETTINGS *Settings, + BOOLEAN AllowMissing + ) +{ + EFI_STATUS Status; + + ZeroMem (Settings, sizeof(SETTINGS)); + + Status = GetExact (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, + &Settings->SetupMode, sizeof Settings->SetupMode, AllowMissing); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = GetExact (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, + &Settings->SecureBoot, sizeof Settings->SecureBoot, AllowMissing); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = GetExact (EFI_SECURE_BOOT_ENABLE_NAME, + &gEfiSecureBootEnableDisableGuid, &Settings->SecureBootEnable, + sizeof Settings->SecureBootEnable, AllowMissing); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = GetExact (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, + &Settings->CustomMode, sizeof Settings->CustomMode, AllowMissing); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = GetExact (EFI_VENDOR_KEYS_VARIABLE_NAME, &gEfiGlobalVariableGuid, + &Settings->VendorKeys, sizeof Settings->VendorKeys, AllowMissing); + return Status; +} + +STATIC +VOID +EFIAPI +PrintSettings ( + IN CONST SETTINGS *Settings + ) +{ + DEBUG ((EFI_D_INFO, "SecureBootSetup: SetupMode=%d SecureBoot=%d SecureBootEnable=%d " + "CustomMode=%d VendorKeys=%d\n", Settings->SetupMode, Settings->SecureBoot, + Settings->SecureBootEnable, Settings->CustomMode, Settings->VendorKeys)); +} + +/** + Install SecureBoot certificates once the VariableDriver is running. + + @param[in] Event Event whose notification function is being invoked + @param[in] Context Pointer to the notification function's context +**/ +VOID +EFIAPI +InstallSecureBootHook ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + VOID *Protocol; + SETTINGS Settings; + + UINT8 *MicrosoftPCA = 0; + UINTN MicrosoftPCASize; + UINT8 *MicrosoftUefiCA = 0; + UINTN MicrosoftUefiCASize; + UINT8 *MicrosoftKEK = 0; + UINTN MicrosoftKEKSize; + UINT8 *SecureBootPk = 0; + UINTN SecureBootPkSize; + UINT8 *MicrosoftDbx = 0; + UINTN MicrosoftDbxSize; + + Status = gBS->LocateProtocol (&gEfiVariableWriteArchProtocolGuid, NULL, (VOID **)&Protocol); + if (EFI_ERROR (Status)) { + return; + } + + Status = GetSettings (&Settings, TRUE); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SecureBootSetup: Failed to get current settings\n")); + return; + } + + if (Settings.SetupMode != SETUP_MODE) { + DEBUG ((EFI_D_ERROR, "SecureBootSetup: already in User Mode\n")); + return; + } + PrintSettings (&Settings); + + if (Settings.CustomMode != CUSTOM_SECURE_BOOT_MODE) { + Settings.CustomMode = CUSTOM_SECURE_BOOT_MODE; + Status = gRT->SetVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, + (EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS), + sizeof Settings.CustomMode, &Settings.CustomMode); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SecureBootSetup: SetVariable(\"%s\", %g): %r\n", EFI_CUSTOM_MODE_NAME, + &gEfiCustomModeEnableGuid, Status)); + ASSERT_EFI_ERROR (Status); + } + } + + Status = GetSectionFromAnyFv(&gEfiSecureBootDb1CertGuid, EFI_SECTION_RAW, 0, (void **)&MicrosoftPCA, &MicrosoftPCASize); + ASSERT_EFI_ERROR (Status); + + Status = GetSectionFromAnyFv(&gEfiSecureBootDb2CertGuid, EFI_SECTION_RAW, 0, (void **)&MicrosoftUefiCA, &MicrosoftUefiCASize); + ASSERT_EFI_ERROR (Status); + + Status = GetSectionFromAnyFv(&gEfiSecureBootKekCertGuid, EFI_SECTION_RAW, 0, (void **)&MicrosoftKEK, &MicrosoftKEKSize); + ASSERT_EFI_ERROR (Status); + + Status = GetSectionFromAnyFv(&gEfiSecureBootPkCertGuid, EFI_SECTION_RAW, 0, (void **)&SecureBootPk, &SecureBootPkSize); + ASSERT_EFI_ERROR (Status); + + Status = GetSectionFromAnyFv(&gEfiSecureBootDbxCrlGuid, EFI_SECTION_RAW, 0, (void **)&MicrosoftDbx, &MicrosoftDbxSize); + ASSERT_EFI_ERROR (Status); + + Status = gRT->SetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, + (EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS), + MicrosoftDbxSize, MicrosoftDbx); + ASSERT_EFI_ERROR (Status); + + Status = EnrollListOfCerts ( + EFI_IMAGE_SECURITY_DATABASE, + &gEfiImageSecurityDatabaseGuid, + &gEfiCertX509Guid, + MicrosoftPCA, MicrosoftPCASize, &gEfiMicrosoftOwnerGuid, + MicrosoftUefiCA, MicrosoftUefiCASize, &gEfiMicrosoftOwnerGuid, + NULL); + ASSERT_EFI_ERROR (Status); + + Status = EnrollListOfCerts ( + EFI_KEY_EXCHANGE_KEY_NAME, + &gEfiGlobalVariableGuid, + &gEfiCertX509Guid, + SecureBootPk, SecureBootPkSize, &gEfiCallerIdGuid, + MicrosoftKEK, MicrosoftKEKSize, &gEfiMicrosoftOwnerGuid, + NULL); + ASSERT_EFI_ERROR (Status); + + Status = EnrollListOfCerts ( + EFI_PLATFORM_KEY_NAME, + &gEfiGlobalVariableGuid, + &gEfiCertX509Guid, + SecureBootPk, SecureBootPkSize, &gEfiGlobalVariableGuid, + NULL); + ASSERT_EFI_ERROR (Status); + + FreePool (MicrosoftPCA); + FreePool (MicrosoftUefiCA); + FreePool (MicrosoftKEK); + FreePool (SecureBootPk); + FreePool (MicrosoftDbx); + + Settings.CustomMode = STANDARD_SECURE_BOOT_MODE; + Status = gRT->SetVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof Settings.CustomMode, &Settings.CustomMode); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SecureBootSetup: SetVariable(\"%s\", %g): %r\n", EFI_CUSTOM_MODE_NAME, + &gEfiCustomModeEnableGuid, Status)); + ASSERT_EFI_ERROR (Status); + } + + // FIXME: Optionally force SecureBoot to ON. The AuthService will do this if authenticated variables + // are supported, which aren't as the SMM handler isn't able to verify them. + + Settings.SecureBootEnable = PcdGetBool (PcdSecureBootDefaultEnable) ? SECURE_BOOT_ENABLE : SECURE_BOOT_DISABLE; + Status = gRT->SetVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof Settings.SecureBootEnable, &Settings.SecureBootEnable); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SecureBootSetup: SetVariable(\"%s\", %g): %r\n", EFI_SECURE_BOOT_ENABLE_NAME, + &gEfiSecureBootEnableDisableGuid, Status)); + ASSERT_EFI_ERROR (Status); + } + + Settings.SecureBoot = PcdGetBool (PcdSecureBootDefaultEnable) ? SECURE_BOOT_ENABLE : SECURE_BOOT_DISABLE; + Status = gRT->SetVariable (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof Settings.SecureBoot, &Settings.SecureBoot); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SecureBootSetup: SetVariable(\"%s\", %g): %r\n", EFI_SECURE_BOOT_MODE_NAME, + &gEfiGlobalVariableGuid, Status)); + ASSERT_EFI_ERROR (Status); + } + + Status = GetSettings (&Settings, FALSE); + ASSERT_EFI_ERROR (Status); + + // + // Final sanity check: + // + // [SetupMode] + // (read-only, standardized by UEFI) + // / \_ + // 0 1, default + // / \_ + // PK enrolled no PK enrolled yet, + // (this is called "User Mode") PK enrollment possible + // | + // | + // [SecureBootEnable] + // (read-write, edk2-specific, boot service only) + // / \_ + // 0 1, default + // / \_ + // [SecureBoot]=0 [SecureBoot]=1 + // (read-only, standardized by UEFI) (read-only, standardized by UEFI) + // images are not verified images are verified, platform is + // operating in Secure Boot mode + // | + // | + // [CustomMode] + // (read-write, edk2-specific, boot service only) + // / \_ + // 0, default 1 + // / \_ + // PK, KEK, db, dbx PK, KEK, db, dbx + // updates are verified updates are not verified + // + + PrintSettings (&Settings); + + if (Settings.SetupMode != 0 || Settings.SecureBoot != 1 || + Settings.SecureBootEnable != 1 || Settings.CustomMode != 0 || + Settings.VendorKeys != 0) { + DEBUG ((EFI_D_ERROR, "SecureBootSetup: disabled\n")); + return; + } + + DEBUG ((EFI_D_INFO, "SecureBootSetup: SecureBoot enabled\n")); +} + +EFI_STATUS +EFIAPI +DriverEntry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + VOID *TcgProtocol; + VOID *Registration; + + Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **) &TcgProtocol); + if (!EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SecureBootSetup: Started too late." + "TPM is already running!\n")); + return EFI_DEVICE_ERROR; + } + + // + // Create event callback, because we need access variable on SecureBootPolicyVariable + // We should use VariableWriteArch instead of VariableArch, because Variable driver + // may update SecureBoot value based on last setting. + // + EfiCreateProtocolNotifyEvent ( + &gEfiVariableWriteArchProtocolGuid, + TPL_CALLBACK, + InstallSecureBootHook, + NULL, + &Registration); + + return EFI_SUCCESS; +} diff --git a/DasharoPayloadPkg/SmmStoreFvb/SmmStoreFvbRuntime.c b/DasharoPayloadPkg/SmmStoreFvb/SmmStoreFvbRuntime.c new file mode 100644 index 0000000000..881a4be02d --- /dev/null +++ b/DasharoPayloadPkg/SmmStoreFvb/SmmStoreFvbRuntime.c @@ -0,0 +1,284 @@ +/** @file SmmStoreFvbRuntime.c + + Copyright (c) 2022, 9elements GmbH
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "SmmStoreFvbRuntime.h" + +STATIC EFI_EVENT mSmmStoreVirtualAddrChangeEvent; + +// +// Global variable declarations +// +SMMSTORE_INSTANCE *mSmmStoreInstance; + +SMMSTORE_INSTANCE mSmmStoreInstanceTemplate = { + SMMSTORE_SIGNATURE, // Signature + NULL, // Handle ... NEED TO BE FILLED + { + FvbGetAttributes, // GetAttributes + FvbSetAttributes, // SetAttributes + FvbGetPhysicalAddress, // GetPhysicalAddress + FvbGetBlockSize, // GetBlockSize + FvbRead, // Read + FvbWrite, // Write + FvbEraseBlocks, // EraseBlocks + NULL, // ParentHandle + }, // FvbProtoccol + 0, // BlockSize ... NEED TO BE FILLED + 0, // LastBlock ... NEED TO BE FILLED + 0, // MmioAddress ... NEED TO BE FILLED + { + { + { + HARDWARE_DEVICE_PATH, + HW_MEMMAP_DP, + { + (UINT8)(sizeof (MEMMAP_DEVICE_PATH)), + (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8) + } + }, + EfiMemoryMappedIO, + (EFI_PHYSICAL_ADDRESS)0, // NEED TO BE FILLED + (EFI_PHYSICAL_ADDRESS)0, // NEED TO BE FILLED + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } + } // DevicePath +}; + +/** + Initialize the SmmStore instance. + + + @param[in] FvBase The physical MMIO base address of the FV containing + the variable store. + + @param[in] NumberofBlocks Number of blocks within the FV. + @param[in] BlockSize The size in bytes of one block within the FV. + @param[in, out] Instance The SmmStore instace to initialize + +**/ +STATIC +EFI_STATUS +SmmStoreInitInstance ( + IN EFI_PHYSICAL_ADDRESS FvBase, + IN UINTN NumberofBlocks, + IN UINTN BlockSize, + IN OUT SMMSTORE_INSTANCE *Instance + ) +{ + EFI_STATUS Status; + FV_MEMMAP_DEVICE_PATH *FvDevicePath; + + ASSERT (Instance != NULL); + + Instance->BlockSize = BlockSize; + Instance->LastBlock = NumberofBlocks - 1; + Instance->MmioAddress = FvBase; + + FvDevicePath = &Instance->DevicePath; + FvDevicePath->MemMapDevPath.StartingAddress = FvBase; + FvDevicePath->MemMapDevPath.EndingAddress = FvBase + BlockSize * NumberofBlocks - 1; + + Status = FvbInitialize (Instance); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->InstallMultipleProtocolInterfaces ( + &Instance->Handle, + &gEfiDevicePathProtocolGuid, + &Instance->DevicePath, + &gEfiFirmwareVolumeBlockProtocolGuid, + &Instance->FvbProtocol, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + DEBUG ((DEBUG_INFO, "%a: Created a new instance\n", __FUNCTION__)); + + return Status; +} + +/** + 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 Event Context +**/ +STATIC +VOID +EFIAPI +SmmStoreVirtualNotifyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + SmmStoreLibVirtualAddressChange (EfiConvertPointer); + + // Convert Fvb + EfiConvertPointer (0x0, (VOID **)&mSmmStoreInstance->FvbProtocol.EraseBlocks); + EfiConvertPointer (0x0, (VOID **)&mSmmStoreInstance->FvbProtocol.GetAttributes); + EfiConvertPointer (0x0, (VOID **)&mSmmStoreInstance->FvbProtocol.GetBlockSize); + EfiConvertPointer (0x0, (VOID **)&mSmmStoreInstance->FvbProtocol.GetPhysicalAddress); + EfiConvertPointer (0x0, (VOID **)&mSmmStoreInstance->FvbProtocol.Read); + EfiConvertPointer (0x0, (VOID **)&mSmmStoreInstance->FvbProtocol.SetAttributes); + EfiConvertPointer (0x0, (VOID **)&mSmmStoreInstance->FvbProtocol.Write); + EfiConvertPointer (0x0, (VOID **)&mSmmStoreInstance->MmioAddress); + EfiConvertPointer (0x0, (VOID **)&mSmmStoreInstance); + + return; +} + +/** + The user Entry Point for module SmmStoreFvbRuntimeDxe. The user code starts with this function. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +SmmStoreInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS MmioAddress; + UINTN BlockSize; + UINTN BlockCount; + UINT32 NvStorageBase; + UINT32 NvStorageSize; + UINT32 NvVariableSize; + UINT32 FtwWorkingSize; + UINT32 FtwSpareSize; + + Status = SmmStoreLibInitialize (); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Failed to initialize SmmStoreLib\n", __FUNCTION__)); + return Status; + } + + Status = SmmStoreLibGetMmioAddress (&MmioAddress); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Failed to get SmmStore MMIO address\n", __FUNCTION__)); + SmmStoreLibDeinitialize (); + return Status; + } + + Status = SmmStoreLibGetNumBlocks (&BlockCount); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Failed to get SmmStore No. blocks\n", __FUNCTION__)); + SmmStoreLibDeinitialize (); + return Status; + } + + Status = SmmStoreLibGetBlockSize (&BlockSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Failed to get SmmStore block size\n", __FUNCTION__)); + SmmStoreLibDeinitialize (); + return Status; + } + + NvStorageSize = BlockCount * BlockSize; + NvStorageBase = MmioAddress; + + FtwSpareSize = (BlockCount / 2) * BlockSize; + FtwWorkingSize = BlockSize; + NvVariableSize = NvStorageSize - FtwSpareSize - FtwWorkingSize; + DEBUG ((DEBUG_INFO, "NvStorageBase:0x%x, NvStorageSize:0x%x\n", NvStorageBase, NvStorageSize)); + + if (NvVariableSize >= 0x80000000) { + SmmStoreLibDeinitialize (); + return EFI_INVALID_PARAMETER; + } + + Status = PcdSet32S (PcdFlashNvStorageVariableSize, NvVariableSize); + ASSERT_EFI_ERROR (Status); + Status = PcdSet32S (PcdFlashNvStorageVariableBase, NvStorageBase); + ASSERT_EFI_ERROR (Status); + Status = PcdSet64S (PcdFlashNvStorageVariableBase64, NvStorageBase); + ASSERT_EFI_ERROR (Status); + + Status = PcdSet32S (PcdFlashNvStorageFtwWorkingSize, FtwWorkingSize); + ASSERT_EFI_ERROR (Status); + Status = PcdSet32S (PcdFlashNvStorageFtwWorkingBase, NvStorageBase + NvVariableSize); + ASSERT_EFI_ERROR (Status); + Status = PcdSet64S (PcdFlashNvStorageFtwWorkingBase64, NvStorageBase + NvVariableSize); + ASSERT_EFI_ERROR (Status); + + Status = PcdSet32S (PcdFlashNvStorageFtwSpareSize, FtwSpareSize); + ASSERT_EFI_ERROR (Status); + Status = PcdSet32S (PcdFlashNvStorageFtwSpareBase, NvStorageBase + NvVariableSize + FtwWorkingSize); + ASSERT_EFI_ERROR (Status); + Status = PcdSet64S (PcdFlashNvStorageFtwSpareBase64, NvStorageBase + NvVariableSize + FtwWorkingSize); + ASSERT_EFI_ERROR (Status); + + mSmmStoreInstance = AllocateRuntimeCopyPool (sizeof (SMMSTORE_INSTANCE), &mSmmStoreInstanceTemplate); + if (mSmmStoreInstance == NULL) { + SmmStoreLibDeinitialize (); + DEBUG ((DEBUG_ERROR, "%a: Out of resources\n", __FUNCTION__)); + return EFI_OUT_OF_RESOURCES; + } + + Status = SmmStoreInitInstance ( + MmioAddress, + BlockCount, + BlockSize, + mSmmStoreInstance + ); + if (EFI_ERROR (Status)) { + DEBUG ( + ( + DEBUG_ERROR, + "%a: Fail to create instance for SmmStore\n", + __FUNCTION__ + ) + ); + FreePool (mSmmStoreInstance); + SmmStoreLibDeinitialize (); + return Status; + } + + // + // Register for the virtual address change event + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + SmmStoreVirtualNotifyEvent, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &mSmmStoreVirtualAddrChangeEvent + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/DasharoPayloadPkg/SmmStoreFvb/SmmStoreFvbRuntime.h b/DasharoPayloadPkg/SmmStoreFvb/SmmStoreFvbRuntime.h new file mode 100644 index 0000000000..8015d12d13 --- /dev/null +++ b/DasharoPayloadPkg/SmmStoreFvb/SmmStoreFvbRuntime.h @@ -0,0 +1,111 @@ +/** @file SmmStoreFvbRuntime.h + + Copyright (c) 2022, 9elements GmbH
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef SMM_STORE_DXE_H_ +#define SMM_STORE_DXE_H_ + +#include +#include + +#include + +#include + +#include +#include +#include +#include + +#define SMMSTORE_SIGNATURE SIGNATURE_32('S', 'M', 'M', 'S') +#define INSTANCE_FROM_FVB_THIS(a) CR(a, SMMSTORE_INSTANCE, FvbProtocol, SMMSTORE_SIGNATURE) + +typedef struct _SMMSTORE_INSTANCE SMMSTORE_INSTANCE; + +typedef struct { + MEMMAP_DEVICE_PATH MemMapDevPath; + EFI_DEVICE_PATH_PROTOCOL EndDevPath; +} FV_MEMMAP_DEVICE_PATH; + +struct _SMMSTORE_INSTANCE { + UINT32 Signature; + EFI_HANDLE Handle; + EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol; + UINTN BlockSize; + UINTN LastBlock; + EFI_PHYSICAL_ADDRESS MmioAddress; + FV_MEMMAP_DEVICE_PATH DevicePath; +}; + +// +// SmmStoreFvbRuntimeDxe.c +// + +EFI_STATUS +EFIAPI +FvbInitialize ( + IN SMMSTORE_INSTANCE *Instance + ); + +EFI_STATUS +EFIAPI +FvbGetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ); + +EFI_STATUS +EFIAPI +FvbSetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ); + +EFI_STATUS +EFIAPI +FvbGetPhysicalAddress ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ); + +EFI_STATUS +EFIAPI +FvbGetBlockSize ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumberOfBlocks + ); + +EFI_STATUS +EFIAPI +FvbRead ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN OUT UINT8 *Buffer + ); + +EFI_STATUS +EFIAPI +FvbWrite ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ); + +EFI_STATUS +EFIAPI +FvbEraseBlocks ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + ... + ); + +#endif // SMM_STORE_DXE_H_ diff --git a/DasharoPayloadPkg/SmmStoreFvb/SmmStoreFvbRuntimeDxe.c b/DasharoPayloadPkg/SmmStoreFvb/SmmStoreFvbRuntimeDxe.c new file mode 100644 index 0000000000..0b9654a2a6 --- /dev/null +++ b/DasharoPayloadPkg/SmmStoreFvb/SmmStoreFvbRuntimeDxe.c @@ -0,0 +1,840 @@ +/** @file SmmStoreFvbRuntimeDxe.c + + Copyright (c) 2022, 9elements GmbH
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "SmmStoreFvbRuntime.h" + +/// +/// 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. +/// + +/** + Initialises the FV Header and Variable Store Header + to support variable operations. + + @param[in] Instance - Pointer to SmmStore instance + +**/ +EFI_STATUS +InitializeFvAndVariableStoreHeaders ( + IN SMMSTORE_INSTANCE *Instance + ) +{ + EFI_STATUS Status; + VOID *Headers; + UINTN HeadersLength; + EFI_FIRMWARE_VOLUME_HEADER *FirmwareVolumeHeader; + VARIABLE_STORE_HEADER *VariableStoreHeader; + UINT32 NvStorageFtwSpareSize; + UINT32 NvStorageFtwWorkingSize; + UINT32 NvStorageVariableSize; + UINT64 NvStorageFtwSpareBase; + UINT64 NvStorageFtwWorkingBase; + UINT64 NvStorageVariableBase; + + HeadersLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY) + sizeof (VARIABLE_STORE_HEADER); + Headers = AllocateZeroPool (HeadersLength); + + NvStorageFtwWorkingSize = PcdGet32 (PcdFlashNvStorageFtwWorkingSize); + NvStorageFtwSpareSize = PcdGet32 (PcdFlashNvStorageFtwSpareSize); + NvStorageVariableSize = PcdGet32 (PcdFlashNvStorageVariableSize); + + NvStorageFtwSpareBase = (PcdGet64 (PcdFlashNvStorageFtwSpareBase64) != 0) ? + PcdGet64 (PcdFlashNvStorageFtwSpareBase64) : PcdGet32 (PcdFlashNvStorageFtwSpareBase); + NvStorageFtwWorkingBase = (PcdGet64 (PcdFlashNvStorageFtwWorkingBase64) != 0) ? + PcdGet64 (PcdFlashNvStorageFtwWorkingBase64) : PcdGet32 (PcdFlashNvStorageFtwWorkingBase); + NvStorageVariableBase = (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0) ? + PcdGet64 (PcdFlashNvStorageVariableBase64) : PcdGet32 (PcdFlashNvStorageVariableBase); + + // FirmwareVolumeHeader->FvLength is declared to have the Variable area AND the FTW working area AND the FTW Spare contiguous. + if ((NvStorageVariableBase + NvStorageVariableSize) != NvStorageFtwWorkingBase) { + DEBUG (( + DEBUG_ERROR, + "%a: NvStorageFtwWorkingBase is not contiguous with NvStorageVariableBase region\n", + __FUNCTION__ + )); + return EFI_INVALID_PARAMETER; + } + + if ((NvStorageFtwWorkingBase + NvStorageFtwWorkingSize) != NvStorageFtwSpareBase) { + DEBUG (( + DEBUG_ERROR, + "%a: NvStorageFtwSpareBase is not contiguous with NvStorageFtwWorkingBase region\n", + __FUNCTION__ + )); + return EFI_INVALID_PARAMETER; + } + + // Check if the size of the area is at least one block size + if ((NvStorageVariableSize <= 0) || (NvStorageVariableSize / Instance->BlockSize <= 0)) { + DEBUG (( + DEBUG_ERROR, + "%a: NvStorageVariableSize is 0x%x, should be atleast one block size\n", + __FUNCTION__, + NvStorageVariableSize + )); + return EFI_INVALID_PARAMETER; + } + + if ((NvStorageFtwWorkingSize <= 0) || (NvStorageFtwWorkingSize / Instance->BlockSize <= 0)) { + DEBUG (( + DEBUG_ERROR, + "%a: NvStorageFtwWorkingSize is 0x%x, should be atleast one block size\n", + __FUNCTION__, + NvStorageFtwWorkingSize + )); + return EFI_INVALID_PARAMETER; + } + + if ((NvStorageFtwSpareSize <= 0) || (NvStorageFtwSpareSize / Instance->BlockSize <= 0)) { + DEBUG (( + DEBUG_ERROR, + "%a: NvStorageFtwSpareSize is 0x%x, should be atleast one block size\n", + __FUNCTION__, + NvStorageFtwSpareSize + )); + return EFI_INVALID_PARAMETER; + } + + // + // EFI_FIRMWARE_VOLUME_HEADER + // + FirmwareVolumeHeader = (EFI_FIRMWARE_VOLUME_HEADER *)Headers; + CopyGuid (&FirmwareVolumeHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid); + FirmwareVolumeHeader->FvLength = + PcdGet32 (PcdFlashNvStorageVariableSize) + + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) + + PcdGet32 (PcdFlashNvStorageFtwSpareSize); + FirmwareVolumeHeader->Signature = EFI_FVH_SIGNATURE; + FirmwareVolumeHeader->Attributes = (EFI_FVB_ATTRIBUTES_2)( + EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled + EFI_FVB2_READ_STATUS | // Reads are currently enabled + EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY + EFI_FVB2_MEMORY_MAPPED | // It is memory mapped + EFI_FVB2_ERASE_POLARITY | // After erasure all bits take this value (i.e. '1') + EFI_FVB2_WRITE_STATUS | // Writes are currently enabled + EFI_FVB2_WRITE_ENABLED_CAP // Writes may be enabled + ); + FirmwareVolumeHeader->HeaderLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY); + FirmwareVolumeHeader->Revision = EFI_FVH_REVISION; + FirmwareVolumeHeader->BlockMap[0].NumBlocks = Instance->LastBlock + 1; + FirmwareVolumeHeader->BlockMap[0].Length = Instance->BlockSize; + FirmwareVolumeHeader->BlockMap[1].NumBlocks = 0; + FirmwareVolumeHeader->BlockMap[1].Length = 0; + FirmwareVolumeHeader->Checksum = CalculateCheckSum16 ((UINT16 *)FirmwareVolumeHeader, FirmwareVolumeHeader->HeaderLength); + + // + // VARIABLE_STORE_HEADER + // + VariableStoreHeader = (VARIABLE_STORE_HEADER *)((UINTN)Headers + FirmwareVolumeHeader->HeaderLength); + CopyGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid); + VariableStoreHeader->Size = PcdGet32 (PcdFlashNvStorageVariableSize) - FirmwareVolumeHeader->HeaderLength; + VariableStoreHeader->Format = VARIABLE_STORE_FORMATTED; + VariableStoreHeader->State = VARIABLE_STORE_HEALTHY; + + // Install the combined super-header in the NorFlash + Status = FvbWrite (&Instance->FvbProtocol, 0, 0, &HeadersLength, Headers); + + FreePool (Headers); + return Status; +} + +/** + Check the integrity of firmware volume header. + + @retval EFI_SUCCESS - The firmware volume is consistent + @retval EFI_NOT_FOUND - The firmware volume has been corrupted. + +**/ +EFI_STATUS +ValidateFvHeader ( + VOID + ) +{ + UINT16 Checksum; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + VARIABLE_STORE_HEADER *VariableStoreHeader; + UINTN VariableStoreLength; + UINTN FvLength; + EFI_STATUS TempStatus; + UINTN BufferSize; + UINTN BufferSizeReqested; + + BufferSizeReqested = sizeof (EFI_FIRMWARE_VOLUME_HEADER); + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)AllocatePool (BufferSizeReqested); + if (!FwVolHeader) { + return EFI_OUT_OF_RESOURCES; + } + + BufferSize = BufferSizeReqested; + TempStatus = SmmStoreLibRead (0, 0, &BufferSize, (UINT8 *)FwVolHeader); + if (EFI_ERROR (TempStatus) || (BufferSizeReqested != BufferSize)) { + FreePool (FwVolHeader); + return EFI_DEVICE_ERROR; + } + + FvLength = PcdGet32 (PcdFlashNvStorageVariableSize) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) + + PcdGet32 (PcdFlashNvStorageFtwSpareSize); + + // + // Verify the header revision, header signature, length + // Length of FvBlock cannot be 2**64-1 + // HeaderLength cannot be an odd number + // + if ( (FwVolHeader->Revision != EFI_FVH_REVISION) + || (FwVolHeader->Signature != EFI_FVH_SIGNATURE) + || (FwVolHeader->FvLength != FvLength) + ) + { + DEBUG (( + DEBUG_INFO, + "%a: No Firmware Volume header present\n", + __FUNCTION__ + )); + FreePool (FwVolHeader); + return EFI_NOT_FOUND; + } + + // Check the Firmware Volume Guid + if ( CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid) == FALSE ) { + DEBUG (( + DEBUG_INFO, + "%a: Firmware Volume Guid non-compatible\n", + __FUNCTION__ + )); + FreePool (FwVolHeader); + return EFI_NOT_FOUND; + } + + BufferSizeReqested = FwVolHeader->HeaderLength; + FreePool (FwVolHeader); + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)AllocatePool (BufferSizeReqested); + if (!FwVolHeader) { + return EFI_OUT_OF_RESOURCES; + } + + BufferSize = BufferSizeReqested; + TempStatus = SmmStoreLibRead (0, 0, &BufferSize, (UINT8 *)FwVolHeader); + if (EFI_ERROR (TempStatus) || (BufferSizeReqested != BufferSize)) { + FreePool (FwVolHeader); + return EFI_DEVICE_ERROR; + } + + // Verify the header checksum + Checksum = CalculateSum16 ((UINT16 *)FwVolHeader, FwVolHeader->HeaderLength); + if (Checksum != 0) { + DEBUG (( + DEBUG_INFO, + "%a: FV checksum is invalid (Checksum:0x%X)\n", + __FUNCTION__, + Checksum + )); + FreePool (FwVolHeader); + return EFI_NOT_FOUND; + } + + BufferSizeReqested = sizeof (VARIABLE_STORE_HEADER); + VariableStoreHeader = (VARIABLE_STORE_HEADER *)AllocatePool (BufferSizeReqested); + if (!VariableStoreHeader) { + return EFI_OUT_OF_RESOURCES; + } + + BufferSize = BufferSizeReqested; + TempStatus = SmmStoreLibRead (0, FwVolHeader->HeaderLength, &BufferSize, (UINT8 *)VariableStoreHeader); + if (EFI_ERROR (TempStatus) || (BufferSizeReqested != BufferSize)) { + FreePool (VariableStoreHeader); + FreePool (FwVolHeader); + return EFI_DEVICE_ERROR; + } + + // Check the Variable Store Guid + if (!CompareGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid) && + !CompareGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid)) + { + DEBUG (( + DEBUG_INFO, + "%a: Variable Store Guid non-compatible\n", + __FUNCTION__ + )); + FreePool (FwVolHeader); + FreePool (VariableStoreHeader); + return EFI_NOT_FOUND; + } + + VariableStoreLength = PcdGet32 (PcdFlashNvStorageVariableSize) - FwVolHeader->HeaderLength; + if (VariableStoreHeader->Size != VariableStoreLength) { + DEBUG (( + DEBUG_INFO, + "%a: Variable Store Length does not match\n", + __FUNCTION__ + )); + FreePool (FwVolHeader); + FreePool (VariableStoreHeader); + return EFI_NOT_FOUND; + } + + FreePool (FwVolHeader); + FreePool (VariableStoreHeader); + + return EFI_SUCCESS; +} + +/** + 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. + + **/ +EFI_STATUS +EFIAPI +FvbGetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +{ + EFI_FVB_ATTRIBUTES_2 FlashFvbAttributes; + + FlashFvbAttributes = (EFI_FVB_ATTRIBUTES_2)( + EFI_FVB2_READ_STATUS | // Reads are currently enabled + EFI_FVB2_WRITE_STATUS | // Writes are enabled + EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY + EFI_FVB2_MEMORY_MAPPED | // It is memory mapped + EFI_FVB2_ERASE_POLARITY // After erasure all bits take this value (i.e. '1') + ); + + *Attributes = FlashFvbAttributes; + + DEBUG ((DEBUG_BLKIO, "FvbGetAttributes(0x%X)\n", *Attributes)); + + return EFI_SUCCESS; +} + +/** + 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. + + **/ +EFI_STATUS +EFIAPI +FvbSetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +{ + DEBUG ((DEBUG_ERROR, "FvbSetAttributes(0x%X) is not supported\n", *Attributes)); + return EFI_UNSUPPORTED; +} + +/** + 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_NOT_SUPPORTED The firmware volume is not memory mapped. + + **/ +EFI_STATUS +EFIAPI +FvbGetPhysicalAddress ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ) +{ + SMMSTORE_INSTANCE *Instance; + + Instance = INSTANCE_FROM_FVB_THIS (This); + + ASSERT (Address != NULL); + *Address = Instance->MmioAddress; + + return EFI_SUCCESS; +} + +/** + 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. + + **/ +EFI_STATUS +EFIAPI +FvbGetBlockSize ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumberOfBlocks + ) +{ + EFI_STATUS Status; + SMMSTORE_INSTANCE *Instance; + + Instance = INSTANCE_FROM_FVB_THIS (This); + + DEBUG ((DEBUG_BLKIO, "FvbGetBlockSize(Lba=%ld, BlockSize=0x%x, LastBlock=%ld)\n", Lba, Instance->BlockSize, Instance->LastBlock)); + + if (Lba > Instance->LastBlock) { + DEBUG ((DEBUG_ERROR, "FvbGetBlockSize: ERROR - Parameter LBA %ld is beyond the last Lba (%ld).\n", Lba, Instance->LastBlock)); + Status = EFI_INVALID_PARAMETER; + } else { + *BlockSize = (UINTN)Instance->BlockSize; + *NumberOfBlocks = (UINTN)(Instance->LastBlock - Lba + 1); + + DEBUG ((DEBUG_BLKIO, "FvbGetBlockSize: *BlockSize=0x%x, *NumberOfBlocks=0x%x.\n", *BlockSize, *NumberOfBlocks)); + + Status = EFI_SUCCESS; + } + + return Status; +} + +/** + 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. + + **/ +EFI_STATUS +EFIAPI +FvbRead ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN OUT UINT8 *Buffer + ) +{ + UINTN BlockSize; + SMMSTORE_INSTANCE *Instance; + + Instance = INSTANCE_FROM_FVB_THIS (This); + + DEBUG ((DEBUG_BLKIO, "FvbRead(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Lba, Offset, *NumBytes, Buffer)); + + // Cache the block size to avoid de-referencing pointers all the time + BlockSize = Instance->BlockSize; + + // The read must not span block boundaries. + // We need to check each variable individually because adding two large values together overflows. + if ((Offset >= BlockSize) || + (*NumBytes > BlockSize) || + ((Offset + *NumBytes) > BlockSize)) + { + DEBUG ((DEBUG_ERROR, "FvbRead: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize)); + return EFI_BAD_BUFFER_SIZE; + } + + // We must have some bytes to read + if (*NumBytes == 0) { + return EFI_BAD_BUFFER_SIZE; + } + + return SmmStoreLibRead (Lba, Offset, NumBytes, 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. + + + **/ +EFI_STATUS +EFIAPI +FvbWrite ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ + UINTN BlockSize; + SMMSTORE_INSTANCE *Instance; + + Instance = INSTANCE_FROM_FVB_THIS (This); + + DEBUG ((DEBUG_BLKIO, "FvbWrite(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Lba, Offset, *NumBytes, Buffer)); + + // Cache the block size to avoid de-referencing pointers all the time + BlockSize = Instance->BlockSize; + + // The read must not span block boundaries. + // We need to check each variable individually because adding two large values together overflows. + if ((Offset >= BlockSize) || + (*NumBytes > BlockSize) || + ((Offset + *NumBytes) > BlockSize)) + { + DEBUG ((DEBUG_ERROR, "FvbRead: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize)); + return EFI_BAD_BUFFER_SIZE; + } + + // We must have some bytes to read + if (*NumBytes == 0) { + return EFI_BAD_BUFFER_SIZE; + } + + return SmmStoreLibWrite (Lba, Offset, NumBytes, Buffer); +} + +/** + Erases and initialises 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. + + **/ +EFI_STATUS +EFIAPI +FvbEraseBlocks ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + ... + ) +{ + EFI_STATUS Status; + VA_LIST Args; + EFI_LBA StartingLba; // Lba from which we start erasing + UINTN NumOfLba; // Number of Lba blocks to erase + SMMSTORE_INSTANCE *Instance; + + Instance = INSTANCE_FROM_FVB_THIS (This); + + Status = EFI_SUCCESS; + + // Before erasing, check the entire list of parameters to ensure all specified blocks are valid + + VA_START (Args, This); + do { + // Get the Lba from which we start erasing + StartingLba = VA_ARG (Args, EFI_LBA); + + // Have we reached the end of the list? + if (StartingLba == EFI_LBA_LIST_TERMINATOR) { + // Exit the while loop + break; + } + + // How many Lba blocks are we requested to erase? + NumOfLba = VA_ARG (Args, UINTN); + + // All blocks must be within range + DEBUG (( + DEBUG_BLKIO, + "FvbEraseBlocks: Check if: ( StartingLba=%ld + NumOfLba=%Lu - 1 ) > LastBlock=%ld.\n", + StartingLba, + (UINT64)NumOfLba, + Instance->LastBlock + )); + if ((NumOfLba == 0) || ((StartingLba + NumOfLba - 1) > Instance->LastBlock)) { + VA_END (Args); + DEBUG ((DEBUG_ERROR, "FvbEraseBlocks: ERROR - Lba range goes past the last Lba.\n")); + Status = EFI_INVALID_PARAMETER; + goto EXIT; + } + } while (TRUE); + + VA_END (Args); + + // + // To get here, all must be ok, so start erasing + // + VA_START (Args, This); + do { + // Get the Lba from which we start erasing + StartingLba = VA_ARG (Args, EFI_LBA); + + // Have we reached the end of the list? + if (StartingLba == EFI_LBA_LIST_TERMINATOR) { + // Exit the while loop + break; + } + + // How many Lba blocks are we requested to erase? + NumOfLba = VA_ARG (Args, UINTN); + + // Go through each one and erase it + while (NumOfLba > 0) { + // Erase it + DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks: Erasing Lba=%ld\n", StartingLba)); + Status = SmmStoreLibEraseBlock (StartingLba); + if (EFI_ERROR (Status)) { + VA_END (Args); + Status = EFI_DEVICE_ERROR; + goto EXIT; + } + + // Move to the next Lba + StartingLba++; + NumOfLba--; + } + } while (TRUE); + + VA_END (Args); + +EXIT: + return Status; +} + +/** + Initialized the Firmware Volume if necessary and installs the + gEdkiiNvVarStoreFormattedGuid protocol. + + @param Instance Pointer to SmmStore instance + + **/ +EFI_STATUS +EFIAPI +FvbInitialize ( + IN SMMSTORE_INSTANCE *Instance + ) +{ + EFI_STATUS Status; + UINT32 FvbNumLba; + EFI_BOOT_MODE BootMode; + + ASSERT ((Instance != NULL)); + + BootMode = GetBootModeHob (); + if (BootMode == BOOT_WITH_DEFAULT_SETTINGS) { + Status = EFI_INVALID_PARAMETER; + } else { + // Determine if there is a valid header at the beginning of the NorFlash + Status = ValidateFvHeader (); + } + + // Install the Default FVB header if required + if (EFI_ERROR (Status)) { + // There is no valid header, so time to install one. + DEBUG ((DEBUG_INFO, "%a: The FVB Header is not valid.\n", __FUNCTION__)); + DEBUG (( + DEBUG_INFO, + "%a: Installing a correct one for this volume.\n", + __FUNCTION__ + )); + + // Erase all the NorFlash that is reserved for variable storage + FvbNumLba = (PcdGet32 (PcdFlashNvStorageVariableSize) + + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) + + PcdGet32 (PcdFlashNvStorageFtwSpareSize)) / Instance->BlockSize; + + Status = FvbEraseBlocks (&Instance->FvbProtocol, (EFI_LBA)0, FvbNumLba, EFI_LBA_LIST_TERMINATOR); + if (EFI_ERROR (Status)) { + return Status; + } + + // Install all appropriate headers + Status = InitializeFvAndVariableStoreHeaders (Instance); + if (EFI_ERROR (Status)) { + return Status; + } + } else { + DEBUG ((DEBUG_INFO, "%a: FVB header is valid\n", __FUNCTION__)); + } + + // + // The driver implementing the variable read service can now be dispatched; + // the varstore headers are in place. + // + Status = gBS->InstallProtocolInterface ( + &gImageHandle, + &gEdkiiNvVarStoreFormattedGuid, + EFI_NATIVE_INTERFACE, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/DasharoPayloadPkg/SmmStoreFvb/SmmStoreFvbRuntimeDxe.inf b/DasharoPayloadPkg/SmmStoreFvb/SmmStoreFvbRuntimeDxe.inf new file mode 100644 index 0000000000..75e004d097 --- /dev/null +++ b/DasharoPayloadPkg/SmmStoreFvb/SmmStoreFvbRuntimeDxe.inf @@ -0,0 +1,63 @@ +## @file +# This is the component description file for SmmStore module. +# +# Copyright (c) 2022, 9elements GmbH.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmmStoreFvbRuntimeDxe + FILE_GUID = A0402FCA-6B25-4CEA-B7DD-C08F99714B29 + MODULE_TYPE = DXE_RUNTIME_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = SmmStoreInitialize + +[Sources.common] + SmmStoreFvbRuntimeDxe.c + SmmStoreFvbRuntime.h + SmmStoreFvbRuntime.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + DasharoPayloadPkg/DasharoPayloadPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + HobLib + SmmStoreLib + UefiLib + UefiDriverEntryPoint + UefiBootServicesTableLib + UefiRuntimeLib + DxeServicesTableLib + +[Guids] + gEfiSystemNvDataFvGuid + gEfiVariableGuid ## PRODUCES ## PROTOCOL + gEfiAuthenticatedVariableGuid + gEfiEventVirtualAddressChangeGuid + gEdkiiNvVarStoreFormattedGuid ## PRODUCES ## PROTOCOL + +[Protocols] + gEfiDevicePathProtocolGuid ## BY_START + gEfiFirmwareVolumeBlockProtocolGuid ## BY_START + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 + +[Depex] + TRUE diff --git a/DasharoPayloadPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf b/DasharoPayloadPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf new file mode 100644 index 0000000000..16205e20df --- /dev/null +++ b/DasharoPayloadPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf @@ -0,0 +1,54 @@ +## @file +# Set TPM device type +# +# In SecurityPkg, this module initializes the TPM device type based on a UEFI +# variable and/or hardware detection. In OvmfPkg, the module only performs TPM2 +# hardware detection. +# +# Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
+# Copyright (C) 2018, Red Hat, Inc. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Tcg2ConfigPei + FILE_GUID = BF7F2B0C-9F2F-4889-AB5C-12460022BE87 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + ENTRY_POINT = Tcg2ConfigPeimEntryPoint + +[Sources] + Tcg2ConfigPeim.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + DasharoPayloadPkg/DasharoPayloadPkg.dec + SecurityPkg/SecurityPkg.dec + +[LibraryClasses] + PeimEntryPoint + DebugLib + PeiServicesLib + Tpm12CommandLib + Tpm12DeviceLib + Tpm2DeviceLib + +[Guids] + gEfiTpmDeviceSelectedGuid ## PRODUCES ## GUID # Used as a PPI GUID + gEfiTpmDeviceInstanceTpm20DtpmGuid ## SOMETIMES_CONSUMES + gEfiTpmDeviceInstanceTpm12Guid ## SOMETIMES_CONSUMES + +[Ppis] + gPeiTpmInitializationDonePpiGuid ## SOMETIMES_PRODUCES + +[Pcd] + gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid ## PRODUCES + +[Depex.IA32, Depex.X64] + TRUE + +[Depex.ARM, Depex.AARCH64] + gOvmfTpmDiscoveredPpiGuid diff --git a/DasharoPayloadPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c b/DasharoPayloadPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c new file mode 100644 index 0000000000..53acf45c84 --- /dev/null +++ b/DasharoPayloadPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c @@ -0,0 +1,104 @@ +/** @file + Set TPM device type + + In SecurityPkg, this module initializes the TPM device type based on a UEFI + variable and/or hardware detection. In OvmfPkg, the module only performs TPM2 + hardware detection. + + Copyright (c) 2015, Intel Corporation. All rights reserved.
+ Copyright (C) 2018, Red Hat, Inc. + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +STATIC CONST EFI_PEI_PPI_DESCRIPTOR mTpmSelectedPpi = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiTpmDeviceSelectedGuid, + NULL +}; + +STATIC CONST EFI_PEI_PPI_DESCRIPTOR mTpmInitializationDonePpiList = { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gPeiTpmInitializationDonePpiGuid, + NULL +}; + +static +EFI_STATUS +TestTpm12 ( + ) +{ + TPM_STCLEAR_FLAGS VolatileFlags; + + return Tpm12GetCapabilityFlagVolatile (&VolatileFlags); +} + +/** + The entry point for Tcg2 configuration driver. + + @param FileHandle Handle of the file being invoked. + @param PeiServices Describes the list of possible PEI Services. +**/ +EFI_STATUS +EFIAPI +Tcg2ConfigPeimEntryPoint ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + UINTN Size; + EFI_STATUS Status; + + Status = Tpm12RequestUseTpm (); + if (!EFI_ERROR (Status) && !EFI_ERROR (TestTpm12 ())) { + DEBUG ((DEBUG_INFO, "%a: TPM1.2 detected\n", __FUNCTION__)); + Size = sizeof (gEfiTpmDeviceInstanceTpm12Guid); + Status = PcdSetPtrS ( + PcdTpmInstanceGuid, + &Size, + &gEfiTpmDeviceInstanceTpm12Guid + ); + ASSERT_EFI_ERROR (Status); + } else { + Status = Tpm2RequestUseTpm (); + if (!EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "%a: TPM2 detected\n", __FUNCTION__)); + Size = sizeof (gEfiTpmDeviceInstanceTpm20DtpmGuid); + Status = PcdSetPtrS ( + PcdTpmInstanceGuid, + &Size, + &gEfiTpmDeviceInstanceTpm20DtpmGuid + ); + ASSERT_EFI_ERROR (Status); + } else { + DEBUG ((DEBUG_INFO, "%a: no TPM detected\n", __FUNCTION__)); + // + // If no TPM2 was detected, we still need to install + // TpmInitializationDonePpi. Namely, Tcg2Pei will exit early upon seeing + // the default (all-bits-zero) contents of PcdTpmInstanceGuid, thus we have + // to install the PPI in its place, in order to unblock any dependent + // PEIMs. + // + Status = PeiServicesInstallPpi (&mTpmInitializationDonePpiList); + ASSERT_EFI_ERROR (Status); + } + } + + // + // Selection done + // + Status = PeiServicesInstallPpi (&mTpmSelectedPpi); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/FSDrivers/IA32/LICENSE.txt b/FSDrivers/IA32/LICENSE.txt new file mode 100644 index 0000000000..cdeae2b89e --- /dev/null +++ b/FSDrivers/IA32/LICENSE.txt @@ -0,0 +1,47 @@ +Licensing for the filesystem drivers is complex. Three different licenses +apply to various parts of the code: + +* Christoph Pfisterer's original file system wrapper (FSW) code is covered + by a BSD-style license. Many of the source files with names that take the + form fsw_*.[ch] are so licensed, but this is NOT generally true of + filesystem-specific files (e.g., fsw_ext2.c or fsw_btrfs.c). + +* Certain filesystem drivers are licensed under the GPLv2, either because + they borrow code from the Linux kernel or because a developer (typically + Oracle) applied the GPLv2 license to them. This is true of the ext2fs, + ext4fs, ReiserFS, HFS+, and ISO-9660 drivers. + +* At least one filesystem driver (Btrfs) uses code taken from GRUB, and so + uses the GPLv3 (or later) license. + +Note that the GPLv2 and GPLv3 are, ironically, not compatible licenses. +Thus, code from GPLv2 and GPLv3 projects should not be mixed. The BSD +license used by Pfisterer's original code is compatible with both versions +of the GPL, so the fact that both GPLv2 and GPLv3 drivers is built upon it +is OK. If you intend to contribute to this project's drivers or use the +code yourself, please keep this fact in mind. + +The below was written by Christoph Pfisterer with respect to his original +code: + + File System Wrapper License +============================= + +The various parts of the File System Wrapper source code come from +different sources and may carry different licenses. Here's a quick +account of the situation: + + * The core code was written from scratch and is covered by a + BSD-style license. + + * The EFI host driver was written from scratch, possibly using code + from the TianoCore project and Intel's EFI Application Toolkit. It + is covered by a BSD-style license. + + * The ext2 and reiserfs file system drivers use definitions from the + Linux kernel source. The actual code was written from scratch, + using multiple sources for reference. These drivers are covered by + the GNU GPL. + +For more details, see each file's boilerplate comment. The full text +of the GNU GPL is in the file LICENSE_GPL.txt. diff --git a/FSDrivers/IA32/LICENSE_GPL.txt b/FSDrivers/IA32/LICENSE_GPL.txt new file mode 100644 index 0000000000..d60c31a97a --- /dev/null +++ b/FSDrivers/IA32/LICENSE_GPL.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/FSDrivers/IA32/exfat_ia32.efi b/FSDrivers/IA32/exfat_ia32.efi new file mode 100644 index 0000000000..d293a24ccd Binary files /dev/null and b/FSDrivers/IA32/exfat_ia32.efi differ diff --git a/FSDrivers/IA32/ext2_ia32.efi b/FSDrivers/IA32/ext2_ia32.efi new file mode 100644 index 0000000000..b512afe828 Binary files /dev/null and b/FSDrivers/IA32/ext2_ia32.efi differ diff --git a/FSDrivers/IA32/ext4_ia32.efi b/FSDrivers/IA32/ext4_ia32.efi new file mode 100644 index 0000000000..445b89c916 Binary files /dev/null and b/FSDrivers/IA32/ext4_ia32.efi differ diff --git a/FSDrivers/IA32/ntfs_ia32.efi b/FSDrivers/IA32/ntfs_ia32.efi new file mode 100644 index 0000000000..edea0d6eb2 Binary files /dev/null and b/FSDrivers/IA32/ntfs_ia32.efi differ diff --git a/FSDrivers/X64/LICENSE.txt b/FSDrivers/X64/LICENSE.txt new file mode 100644 index 0000000000..cdeae2b89e --- /dev/null +++ b/FSDrivers/X64/LICENSE.txt @@ -0,0 +1,47 @@ +Licensing for the filesystem drivers is complex. Three different licenses +apply to various parts of the code: + +* Christoph Pfisterer's original file system wrapper (FSW) code is covered + by a BSD-style license. Many of the source files with names that take the + form fsw_*.[ch] are so licensed, but this is NOT generally true of + filesystem-specific files (e.g., fsw_ext2.c or fsw_btrfs.c). + +* Certain filesystem drivers are licensed under the GPLv2, either because + they borrow code from the Linux kernel or because a developer (typically + Oracle) applied the GPLv2 license to them. This is true of the ext2fs, + ext4fs, ReiserFS, HFS+, and ISO-9660 drivers. + +* At least one filesystem driver (Btrfs) uses code taken from GRUB, and so + uses the GPLv3 (or later) license. + +Note that the GPLv2 and GPLv3 are, ironically, not compatible licenses. +Thus, code from GPLv2 and GPLv3 projects should not be mixed. The BSD +license used by Pfisterer's original code is compatible with both versions +of the GPL, so the fact that both GPLv2 and GPLv3 drivers is built upon it +is OK. If you intend to contribute to this project's drivers or use the +code yourself, please keep this fact in mind. + +The below was written by Christoph Pfisterer with respect to his original +code: + + File System Wrapper License +============================= + +The various parts of the File System Wrapper source code come from +different sources and may carry different licenses. Here's a quick +account of the situation: + + * The core code was written from scratch and is covered by a + BSD-style license. + + * The EFI host driver was written from scratch, possibly using code + from the TianoCore project and Intel's EFI Application Toolkit. It + is covered by a BSD-style license. + + * The ext2 and reiserfs file system drivers use definitions from the + Linux kernel source. The actual code was written from scratch, + using multiple sources for reference. These drivers are covered by + the GNU GPL. + +For more details, see each file's boilerplate comment. The full text +of the GNU GPL is in the file LICENSE_GPL.txt. diff --git a/FSDrivers/X64/LICENSE_GPL.txt b/FSDrivers/X64/LICENSE_GPL.txt new file mode 100644 index 0000000000..d60c31a97a --- /dev/null +++ b/FSDrivers/X64/LICENSE_GPL.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/FSDrivers/X64/exfat_ia32.efi b/FSDrivers/X64/exfat_ia32.efi new file mode 100644 index 0000000000..d293a24ccd Binary files /dev/null and b/FSDrivers/X64/exfat_ia32.efi differ diff --git a/FSDrivers/X64/exfat_x64.efi b/FSDrivers/X64/exfat_x64.efi new file mode 100644 index 0000000000..5e1f8a8010 Binary files /dev/null and b/FSDrivers/X64/exfat_x64.efi differ diff --git a/FSDrivers/X64/ext2_x64.efi b/FSDrivers/X64/ext2_x64.efi new file mode 100644 index 0000000000..1da0928d38 Binary files /dev/null and b/FSDrivers/X64/ext2_x64.efi differ diff --git a/FSDrivers/X64/ext4_x64.efi b/FSDrivers/X64/ext4_x64.efi new file mode 100644 index 0000000000..bcb65fc0ff Binary files /dev/null and b/FSDrivers/X64/ext4_x64.efi differ diff --git a/FSDrivers/X64/ntfs_x64.efi b/FSDrivers/X64/ntfs_x64.efi new file mode 100644 index 0000000000..5aaa97aca0 Binary files /dev/null and b/FSDrivers/X64/ntfs_x64.efi differ diff --git a/FSDrivers/exfat.inf b/FSDrivers/exfat.inf new file mode 100644 index 0000000000..caf940cfda --- /dev/null +++ b/FSDrivers/exfat.inf @@ -0,0 +1,27 @@ +# ReadOnly exFAT filesystem driver +# From https://efi.akeo.ie/ v1.5 +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = exfat + FILE_GUID = CB683001-379F-48C7-B7B6-707D29454BF5 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +VALID_ARCHITECTURES = X64 IA32 + +[Binaries.X64] + PE32|X64/exfat_x64.efi|* + +[Binaries.IA32] + PE32|IA32/exfat_ia32.efi|* + + diff --git a/FSDrivers/ext2.inf b/FSDrivers/ext2.inf new file mode 100644 index 0000000000..67a985e385 --- /dev/null +++ b/FSDrivers/ext2.inf @@ -0,0 +1,25 @@ +# EXT2 filesystem driver. See */LICENSE.txt for details. +# https://www.rodsbooks.com/refind/ v0.12 + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ext2 + FILE_GUID = 8EC49C43-D1C4-4E6C-98BF-232CA5D89A1B + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +VALID_ARCHITECTURES = X64 IA32 + +[Binaries.X64] + PE32|X64/ext2_x64.efi|* + +[Binaries.IA32] + PE32|IA32/ext2_ia32.efi|* + diff --git a/FSDrivers/ext4.inf b/FSDrivers/ext4.inf new file mode 100644 index 0000000000..c9d0807251 --- /dev/null +++ b/FSDrivers/ext4.inf @@ -0,0 +1,25 @@ +# EXT4 filesystem driver. See */LICENSE.txt for details. +# https://www.rodsbooks.com/refind/ v0.12 + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ext4 + FILE_GUID = 9d380387-a15a-4053-ae19-ff3495b6d0d5 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +VALID_ARCHITECTURES = X64 IA32 + +[Binaries.X64] + PE32|X64/ext4_x64.efi|* + +[Binaries.IA32] + PE32|IA32/ext4_ia32.efi|* + diff --git a/FSDrivers/ntfs.inf b/FSDrivers/ntfs.inf new file mode 100644 index 0000000000..804f655cd7 --- /dev/null +++ b/FSDrivers/ntfs.inf @@ -0,0 +1,27 @@ +# ReadOnly NTFS filesystem driver +# From https://efi.akeo.ie/ v1.5 +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ntfs + FILE_GUID = 2282efd0-678b-4753-8d06-200d5940285d + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +VALID_ARCHITECTURES = X64 IA32 + +[Binaries.X64] + PE32|X64/ntfs_x64.efi|* + +[Binaries.IA32] + PE32|IA32/ntfs_ia32.efi|* + + diff --git a/FUNDING.yml b/FUNDING.yml new file mode 100644 index 0000000000..4e77cf822a --- /dev/null +++ b/FUNDING.yml @@ -0,0 +1,2 @@ + +open_collective: 3mdeb_com diff --git a/MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenu.c b/MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenu.c index ef19319614..4e9e126e69 100644 --- a/MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenu.c +++ b/MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenu.c @@ -517,7 +517,8 @@ BootMenuSelectItem ( } for (Index = 0; Index < ItemCountPerScreen; Index++) { - PrintStringAt (PrintCol, PrintRow + Index, String); + PrintStringAt (PrintCol, PrintRow, L" "); + PrintStringAt (PrintCol + 2, PrintRow + Index, String); } FreePool (String); @@ -526,7 +527,8 @@ BootMenuSelectItem ( // for (Index = 0; Index < ItemCountPerScreen; Index++, PrintRow++) { String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[Index + FirstItem], NULL); - PrintStringAt (PrintCol, PrintRow, String); + PrintStringAt (PrintCol, PrintRow, L" "); + PrintStringAt (PrintCol + 2, PrintRow, String); FreePool (String); } @@ -543,18 +545,21 @@ BootMenuSelectItem ( String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[BootMenuData->SelectItem], NULL); PrintCol = StartCol + 1; PrintRow = StartRow + 3 + BootMenuData->SelectItem - FirstItem; - PrintStringAt (PrintCol, PrintRow, String); + PrintStringAt (PrintCol, PrintRow, L" "); + PrintStringAt (PrintCol + 2, PrintRow, String); FreePool (String); } // // Print want to select item // - gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLACK); + FirstItem = BootMenuData->ScrollBarControl.FirstItem; + gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT | EFI_BACKGROUND_BLUE); String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[WantSelectItem], NULL); PrintCol = StartCol + 1; PrintRow = StartRow + TITLE_TOKEN_COUNT + 2 + WantSelectItem - FirstItem; - PrintStringAt (PrintCol, PrintRow, String); + PrintStringAt (PrintCol, PrintRow, L"→"); + PrintStringAt (PrintCol + 2, PrintRow, String); FreePool (String); gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute); @@ -688,7 +693,8 @@ DrawBootPopupMenu ( PrintRow = StartRow + TITLE_TOKEN_COUNT + 2; for (Index = 0; Index < ItemCountPerScreen; Index++, PrintRow++) { String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[Index], NULL); - PrintStringAt (PrintCol, PrintRow, String); + PrintStringAt (PrintCol, PrintRow, L" "); + PrintStringAt (PrintCol + 2, PrintRow, String); FreePool (String); } diff --git a/MdeModulePkg/Application/UiApp/FrontPage.c b/MdeModulePkg/Application/UiApp/FrontPage.c index 0e784fb327..f2015ea742 100644 --- a/MdeModulePkg/Application/UiApp/FrontPage.c +++ b/MdeModulePkg/Application/UiApp/FrontPage.c @@ -425,24 +425,37 @@ ConvertProcessorToString ( } /** - Convert Memory Size to a string. + Convert Memory Info to a string. @param MemorySize The size of the memory to process + @param MemorySpeed The speed of the memory to process @param String The string that is created **/ VOID -ConvertMemorySizeToString ( +ConvertMemoryInfoToString ( IN UINT32 MemorySize, + IN UINT16 MemorySpeed, OUT CHAR16 **String ) { CHAR16 *StringBuffer; + CHAR16 SpeedBuffer[8]; - StringBuffer = AllocateZeroPool (0x24); + StringBuffer = AllocateZeroPool (0x34); ASSERT (StringBuffer != NULL); - UnicodeValueToStringS (StringBuffer, 0x24, LEFT_JUSTIFY, MemorySize, 10); - StrCatS (StringBuffer, 0x24 / sizeof (CHAR16), L" MB RAM"); + UnicodeValueToStringS (StringBuffer, 0x34, LEFT_JUSTIFY, MemorySize, 10); + StrCatS (StringBuffer, 0x34 / sizeof (CHAR16), L" MB RAM"); + + // + // Some FSPs don't report speed in the memory HOB properly. + // + if (MemorySpeed != 0) { + UnicodeValueToStringS (SpeedBuffer, 8 * sizeof (CHAR16), LEFT_JUSTIFY, MemorySpeed, 10); + StrCatS (StringBuffer, 0x34 / sizeof (CHAR16), L" @ "); + StrCatS (StringBuffer, 0x34 / sizeof (CHAR16), SpeedBuffer); + StrCatS (StringBuffer, 0x34 / sizeof (CHAR16), L" MHz"); + } *String = (CHAR16 *)StringBuffer; @@ -515,12 +528,19 @@ UpdateFrontPageBannerStrings ( SMBIOS_TABLE_TYPE0 *Type0Record; SMBIOS_TABLE_TYPE1 *Type1Record; SMBIOS_TABLE_TYPE4 *Type4Record; + SMBIOS_TABLE_TYPE17 *Type17Record; SMBIOS_TABLE_TYPE19 *Type19Record; EFI_SMBIOS_TABLE_HEADER *Record; + UINT16 MemorySize; + UINT32 ExtendedMemorySize; UINT64 InstalledMemory; + UINT16 MemorySpeed; BOOLEAN FoundCpu; + MemorySize = 0xFFFF; // means "unknown" in Type 17 table of SMBIOS + ExtendedMemorySize = 0; InstalledMemory = 0; + MemorySpeed = 0; FoundCpu = 0; // @@ -633,6 +653,16 @@ UpdateFrontPageBannerStrings ( } } + if ( Record->Type == SMBIOS_TYPE_MEMORY_DEVICE ) { + Type17Record = (SMBIOS_TABLE_TYPE17 *) Record; + if (Type17Record->ConfiguredMemoryClockSpeed > MemorySpeed) { + MemorySpeed = Type17Record->ConfiguredMemoryClockSpeed; + } + + MemorySize = Type17Record->Size; + ExtendedMemorySize = Type17Record->ExtendedSize; + } + if ( Record->Type == SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS ) { Type19Record = (SMBIOS_TABLE_TYPE19 *)Record; if (Type19Record->StartingAddress != 0xFFFFFFFF ) { @@ -653,10 +683,23 @@ UpdateFrontPageBannerStrings ( Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL); } + if ( InstalledMemory == 0 && MemorySize != 0xFFFF ) { + if ( MemorySize == 0x7FFF ) { + // There is more than (32GiB - 1MiB) of memory. The size is given in Mebibytes. + InstalledMemory = ExtendedMemorySize; + } else if ( MemorySize & 0x8000 ) { + // The size is given in Kibibytes. + InstalledMemory = RShiftU64 (MemorySize & ~0x8000U, 10); + } else { + // The size is given in Mebibytes. + InstalledMemory = MemorySize; + } + } + // - // Now update the total installed RAM size + // Now update the total installed RAM size and its speed // - ConvertMemorySizeToString ((UINT32)InstalledMemory, &NewString); + ConvertMemoryInfoToString ((UINT32)InstalledMemory, MemorySpeed, &NewString); UiCustomizeFrontPageBanner (3, FALSE, &NewString); HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_MEMORY_SIZE), NewString, NULL); FreePool (NewString); diff --git a/MdeModulePkg/Application/UiApp/FrontPageCustomizedUiSupport.c b/MdeModulePkg/Application/UiApp/FrontPageCustomizedUiSupport.c index 8bc7883bb7..c460feb2c7 100644 --- a/MdeModulePkg/Application/UiApp/FrontPageCustomizedUiSupport.c +++ b/MdeModulePkg/Application/UiApp/FrontPageCustomizedUiSupport.c @@ -11,6 +11,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include +#include #include #include @@ -182,6 +183,8 @@ UiSupportLibCallbackHandler ( OUT EFI_STATUS *Status ) { + EDKII_FORM_BROWSER_EXTENSION_PROTOCOL *FormBrowserEx; + if ((QuestionId != FRONT_PAGE_KEY_CONTINUE) && (QuestionId != FRONT_PAGE_KEY_RESET) && (QuestionId != FRONT_PAGE_KEY_LANGUAGE)) @@ -231,6 +234,10 @@ UiSupportLibCallbackHandler ( // // Reset // + *Status = gBS->LocateProtocol (&gEdkiiFormBrowserExProtocolGuid, NULL, (VOID **) &FormBrowserEx); + if (!EFI_ERROR (Status)) + FormBrowserEx->SaveReminder(); + gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); *Status = EFI_UNSUPPORTED; diff --git a/MdeModulePkg/Application/UiApp/UiApp.inf b/MdeModulePkg/Application/UiApp/UiApp.inf index 3b9e048851..0e89a2c04f 100644 --- a/MdeModulePkg/Application/UiApp/UiApp.inf +++ b/MdeModulePkg/Application/UiApp/UiApp.inf @@ -62,6 +62,7 @@ [Protocols] gEfiSmbiosProtocolGuid ## CONSUMES gEfiHiiConfigAccessProtocolGuid ## CONSUMES + gEdkiiFormBrowserExProtocolGuid ## CONSUMES [FeaturePcd] diff --git a/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.h b/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.h index ca1dd9b2c2..3abec59b99 100644 --- a/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.h +++ b/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.h @@ -151,8 +151,10 @@ InstallPs2KeyboardDriver ( #define KEYBOARD_8042_STATUS_REGISTER 0x64 #define KEYBOARD_8042_COMMAND_REGISTER 0x64 -#define KEYBOARD_KBEN 0xF4 -#define KEYBOARD_CMDECHO_ACK 0xFA +#define KBC_INPBUF_VIA60_KBECHO 0xEE +#define KEYBOARD_KBEN 0xF4 +#define KEYBOARD_CMDECHO_ACK 0xFA +#define KEYBOARD_CMD_RESEND 0xFE #define KEYBOARD_MAX_TRY 256 // 256 #define KEYBOARD_TIMEOUT 65536 // 0.07s diff --git a/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf b/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf index d551c53fa4..4d026a2dec 100644 --- a/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf +++ b/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf @@ -37,6 +37,7 @@ [Packages] MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec + DasharoModulePkg/DasharoModulePkg.dec [LibraryClasses] MemoryAllocationLib @@ -64,6 +65,7 @@ [Pcd] gEfiMdeModulePkgTokenSpaceGuid.PcdFastPS2Detection ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdDetectPs2KbOnCmdAck ## SOMETIMES_CONSUMES # # [Event] @@ -76,3 +78,6 @@ [UserExtensions.TianoCore."ExtraFiles"] Ps2KeyboardDxeExtra.uni + +[Depex] + gDasharoPs2ControllerPolicyGuid diff --git a/MdeModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf b/MdeModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf index 7e801ecd1f..c236329ba7 100644 --- a/MdeModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf +++ b/MdeModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf @@ -36,6 +36,7 @@ [Packages] MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec + DasharoModulePkg/DasharoModulePkg.dec [LibraryClasses] ReportStatusCodeLib @@ -68,3 +69,6 @@ [UserExtensions.TianoCore."ExtraFiles"] Ps2MouseDxeExtra.uni + +[Depex] + gDasharoPs2ControllerPolicyGuid diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf b/MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf index ffce075c23..e92c358f54 100644 --- a/MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf +++ b/MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf @@ -54,6 +54,7 @@ [Packages] MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec + DasharoModulePkg/DasharoModulePkg.dec [FeaturePcd] gEfiMdeModulePkgTokenSpaceGuid.PcdTurnOffUsbLegacySupport ## CONSUMES @@ -82,3 +83,7 @@ [UserExtensions.TianoCore."ExtraFiles"] EhciDxeExtra.uni + +[Depex] + gDasharoUsbDriverPolicyGuid + \ No newline at end of file diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c index 6594b8eae8..56519a4dd0 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c @@ -2582,15 +2582,12 @@ PciEnumeratorLight ( ); if (!EFI_ERROR (Status)) { - // - // Remove those PCI devices which are rejected when full enumeration - // - RemoveRejectedPciDevices (RootBridgeDev->Handle, RootBridgeDev); - - // - // Process option rom light - // - ProcessOptionRomLight (RootBridgeDev); + if (!PcdGetBool (PcdPciDisableBusEnumeration)) { + // + // Process option rom light + // + ProcessOptionRomLight (RootBridgeDev); + } // // Determine attributes for all devices under this root bridge @@ -2705,109 +2702,6 @@ StartManagingRootBridge ( return EFI_SUCCESS; } -/** - This routine can be used to check whether a PCI device should be rejected when light enumeration. - - @param PciIoDevice Pci device instance. - - @retval TRUE This device should be rejected. - @retval FALSE This device shouldn't be rejected. - -**/ -BOOLEAN -IsPciDeviceRejected ( - IN PCI_IO_DEVICE *PciIoDevice - ) -{ - EFI_STATUS Status; - UINT32 TestValue; - UINT32 OldValue; - UINT32 Mask; - UINT8 BarOffset; - - // - // PPB should be skip! - // - if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) { - return FALSE; - } - - if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) { - // - // Only test base registers for P2C - // - for (BarOffset = 0x1C; BarOffset <= 0x38; BarOffset += 2 * sizeof (UINT32)) { - Mask = (BarOffset < 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC; - Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue); - if (EFI_ERROR (Status)) { - continue; - } - - TestValue = TestValue & Mask; - if ((TestValue != 0) && (TestValue == (OldValue & Mask))) { - // - // The bar isn't programed, so it should be rejected - // - return TRUE; - } - } - - return FALSE; - } - - for (BarOffset = 0x14; BarOffset <= 0x24; BarOffset += sizeof (UINT32)) { - // - // Test PCI devices - // - Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue); - if (EFI_ERROR (Status)) { - continue; - } - - if ((TestValue & 0x01) != 0) { - // - // IO Bar - // - Mask = 0xFFFFFFFC; - TestValue = TestValue & Mask; - if ((TestValue != 0) && (TestValue == (OldValue & Mask))) { - return TRUE; - } - } else { - // - // Mem Bar - // - Mask = 0xFFFFFFF0; - TestValue = TestValue & Mask; - - if ((TestValue & 0x07) == 0x04) { - // - // Mem64 or PMem64 - // - BarOffset += sizeof (UINT32); - if ((TestValue != 0) && (TestValue == (OldValue & Mask))) { - // - // Test its high 32-Bit BAR - // - Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue); - if (TestValue == OldValue) { - return TRUE; - } - } - } else { - // - // Mem32 or PMem32 - // - if ((TestValue != 0) && (TestValue == (OldValue & Mask))) { - return TRUE; - } - } - } - } - - return FALSE; -} - /** Reset all bus number from specific bridge. diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h index 7daa6e020d..9baa5924cb 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h @@ -429,20 +429,6 @@ StartManagingRootBridge ( IN PCI_IO_DEVICE *RootBridgeDev ); -/** - This routine can be used to check whether a PCI device should be rejected when light enumeration. - - @param PciIoDevice Pci device instance. - - @retval TRUE This device should be rejected. - @retval FALSE This device shouldn't be rejected. - -**/ -BOOLEAN -IsPciDeviceRejected ( - IN PCI_IO_DEVICE *PciIoDevice - ); - /** Reset all bus number from specific bridge. diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c index 84fc0161a1..49f0667f75 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c @@ -139,65 +139,6 @@ GetBackPcCardBar ( } } -/** - Remove rejected pci device from specific root bridge - handle. - - @param RootBridgeHandle Specific parent root bridge handle. - @param Bridge Bridge device instance. - -**/ -VOID -RemoveRejectedPciDevices ( - IN EFI_HANDLE RootBridgeHandle, - IN PCI_IO_DEVICE *Bridge - ) -{ - PCI_IO_DEVICE *Temp; - LIST_ENTRY *CurrentLink; - LIST_ENTRY *LastLink; - - if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) { - return; - } - - CurrentLink = Bridge->ChildList.ForwardLink; - - while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) { - Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); - - if (IS_PCI_BRIDGE (&Temp->Pci)) { - // - // Remove rejected devices recusively - // - RemoveRejectedPciDevices (RootBridgeHandle, Temp); - } else { - // - // Skip rejection for all PPBs, while detect rejection for others - // - if (IsPciDeviceRejected (Temp)) { - // - // For P2C, remove all devices on it - // - if (!IsListEmpty (&Temp->ChildList)) { - RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp); - } - - // - // Finally remove itself - // - LastLink = CurrentLink->BackLink; - RemoveEntryList (CurrentLink); - FreePciDevice (Temp); - - CurrentLink = LastLink; - } - } - - CurrentLink = CurrentLink->ForwardLink; - } -} - /** Dump the resourc map of the bridge device. diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h index 5d2551148b..8235f86127 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h @@ -39,20 +39,6 @@ GetBackPcCardBar ( IN PCI_IO_DEVICE *PciIoDevice ); -/** - Remove rejected pci device from specific root bridge - handle. - - @param RootBridgeHandle Specific parent root bridge handle. - @param Bridge Bridge device instance. - -**/ -VOID -RemoveRejectedPciDevices ( - IN EFI_HANDLE RootBridgeHandle, - IN PCI_IO_DEVICE *Bridge - ); - /** Submits the I/O and memory resource requirements for the specified PCI Host Bridge. diff --git a/MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf b/MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf index a5da1a9120..491dbd5bc0 100644 --- a/MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf +++ b/MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf @@ -50,6 +50,7 @@ [Packages] MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec + DasharoModulePkg/DasharoModulePkg.dec [FeaturePcd] gEfiMdeModulePkgTokenSpaceGuid.PcdTurnOffUsbLegacySupport ## CONSUMES @@ -78,3 +79,6 @@ [UserExtensions.TianoCore."ExtraFiles"] UhciDxeExtra.uni + +[Depex] + gDasharoUsbDriverPolicyGuid diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h index 4401675872..f9068aa871 100644 --- a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h +++ b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h @@ -54,9 +54,9 @@ typedef struct _USB_DEV_CONTEXT USB_DEV_CONTEXT; #define XHC_1_MILLISECOND (1000) // // XHC generic timeout experience values. -// The unit is millisecond, setting it as 10s. +// The unit is millisecond, setting it as 2s. // -#define XHC_GENERIC_TIMEOUT (10 * 1000) +#define XHC_GENERIC_TIMEOUT (2 * 1000) // // XHC reset timeout experience values. // The unit is millisecond, setting it as 1s. diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf b/MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf index 18ef87916a..d085d79d9f 100644 --- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf +++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf @@ -45,6 +45,7 @@ [Packages] MdePkg/MdePkg.dec + DasharoModulePkg/DasharoModulePkg.dec [LibraryClasses] MemoryAllocationLib @@ -70,3 +71,6 @@ [UserExtensions.TianoCore."ExtraFiles"] XhciDxeExtra.uni + +[Depex] + gDasharoUsbDriverPolicyGuid diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf index dd85894346..21045ec8de 100644 --- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf +++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf @@ -43,7 +43,7 @@ [Packages] MdePkg/MdePkg.dec - + DasharoModulePkg/DasharoModulePkg.dec [LibraryClasses] MemoryAllocationLib @@ -71,3 +71,6 @@ [UserExtensions.TianoCore."ExtraFiles"] UsbBusDxeExtra.uni + +[Depex] + gDasharoUsbDriverPolicyGuid diff --git a/MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf b/MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf index e981a0afc2..76352b57e6 100644 --- a/MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf +++ b/MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf @@ -48,6 +48,7 @@ [Packages] MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec + DasharoModulePkg/DasharoModulePkg.dec [LibraryClasses] MemoryAllocationLib @@ -91,3 +92,6 @@ [UserExtensions.TianoCore."ExtraFiles"] UsbKbDxeExtra.uni + +[Depex] + gDasharoUsbDriverPolicyGuid diff --git a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf index 54039389fb..4fb31f5b96 100644 --- a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf +++ b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf @@ -55,6 +55,7 @@ [Packages] MdePkg/MdePkg.dec + DasharoModulePkg/DasharoModulePkg.dec [LibraryClasses] BaseLib @@ -79,3 +80,6 @@ [UserExtensions.TianoCore."ExtraFiles"] UsbMassStorageDxeExtra.uni + +[Depex] + gDasharoUsbDriverPolicyGuid AND gDasharoUsbMassStoragePolicyGuid \ No newline at end of file diff --git a/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointerDxe.inf b/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointerDxe.inf index 00e061f56a..83392e8165 100644 --- a/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointerDxe.inf +++ b/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointerDxe.inf @@ -43,6 +43,7 @@ [Packages] MdePkg/MdePkg.dec + DasharoModulePkg/DasharoModulePkg.dec [LibraryClasses] MemoryAllocationLib @@ -64,3 +65,6 @@ [UserExtensions.TianoCore."ExtraFiles"] UsbMouseAbsolutePointerDxeExtra.uni + +[Depex] + gDasharoUsbDriverPolicyGuid diff --git a/MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouseDxe.inf b/MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouseDxe.inf index 5221a41316..f000316817 100644 --- a/MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouseDxe.inf +++ b/MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouseDxe.inf @@ -43,6 +43,7 @@ [Packages] MdePkg/MdePkg.dec + DasharoModulePkg/DasharoModulePkg.dec [LibraryClasses] MemoryAllocationLib @@ -64,3 +65,6 @@ [UserExtensions.TianoCore."ExtraFiles"] UsbMouseDxeExtra.uni + +[Depex] + gDasharoUsbDriverPolicyGuid diff --git a/MdeModulePkg/Include/Library/CustomizedDisplayLib.h b/MdeModulePkg/Include/Library/CustomizedDisplayLib.h index 0607dd1a61..1441bf6c10 100644 --- a/MdeModulePkg/Include/Library/CustomizedDisplayLib.h +++ b/MdeModulePkg/Include/Library/CustomizedDisplayLib.h @@ -348,4 +348,43 @@ GetSubTitleTextColor ( VOID ); +/** + 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. + + If String is NULL, then ASSERT (). + + @param String The input string to be counted. + + @return Storage space for the input string. + +**/ +UINTN +EFIAPI +GetStringWidth ( + IN CHAR16 *String + ); + +/** + Draw a pop up windows based on the dimension, number of lines and + strings specified. + + @param RequestedWidth The width of the pop-up. + @param NumberOfLines The number of lines. + @param ... A series of text strings that displayed in the pop-up. + +**/ +VOID +EFIAPI +CreateMultiStringPopUp ( + IN UINTN RequestedWidth, + IN UINTN NumberOfLines, + ... + ); + #endif diff --git a/MdeModulePkg/Library/BootLogoLib/BootLogoLib.c b/MdeModulePkg/Library/BootLogoLib/BootLogoLib.c index 478ec2d40e..e142b67838 100644 --- a/MdeModulePkg/Library/BootLogoLib/BootLogoLib.c +++ b/MdeModulePkg/Library/BootLogoLib/BootLogoLib.c @@ -176,7 +176,7 @@ BootLogoEnableLogo ( break; case EdkiiPlatformLogoDisplayAttributeCenter: DestX = (SizeOfX - Image.Width) / 2; - DestY = (SizeOfY - Image.Height) / 2; + DestY = (SizeOfY * 382) / 1000 - Image.Height / 2; break; case EdkiiPlatformLogoDisplayAttributeCenterRight: DestX = SizeOfX - Image.Width; @@ -522,7 +522,7 @@ BootLogoUpdateProgress ( 0, PosX, PosY, - BlockWidth - 1, + BlockWidth, BlockHeight, (BlockWidth) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) ); @@ -535,7 +535,7 @@ BootLogoUpdateProgress ( 0, PosX, PosY, - BlockWidth - 1, + BlockWidth, BlockHeight, (BlockWidth) * sizeof (EFI_UGA_PIXEL) ); @@ -544,6 +544,37 @@ BootLogoUpdateProgress ( } } + /* Draw any reminder pixels at the right end of the screen when progress is 100% */ + if (Progress == 100) { + if (GraphicsOutput != NULL) { + Status = GraphicsOutput->Blt ( + GraphicsOutput, + &ProgressColor, + EfiBltVideoFill, + 0, + 0, + PosX, + PosY, + SizeOfX - PosX, + BlockHeight, + (SizeOfX - PosX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + ); + } else if (FeaturePcdGet (PcdUgaConsumeSupport)) { + Status = UgaDraw->Blt ( + UgaDraw, + (EFI_UGA_PIXEL *)&ProgressColor, + EfiUgaVideoFill, + 0, + 0, + PosX, + PosY, + SizeOfX - PosX, + BlockHeight, + (SizeOfX - PosX) * sizeof (EFI_UGA_PIXEL) + ); + } + } + PrintXY ( (SizeOfX - StrLen (Title) * EFI_GLYPH_WIDTH) / 2, PosY - EFI_GLYPH_HEIGHT - 1, diff --git a/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenance.c b/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenance.c index 19751642a3..0a8a3c3000 100644 --- a/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenance.c +++ b/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenance.c @@ -882,8 +882,8 @@ BootMaintRouteConfig ( } if (CompareMem (&NewBmmData->BootTimeOut, &OldBmmData->BootTimeOut, sizeof (NewBmmData->BootTimeOut)) != 0) { - Status = gRT->SetVariable ( - L"Timeout", + Status = gRT->SetVariable( + EFI_TIME_OUT_VARIABLE_NAME, &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, sizeof (UINT16), @@ -1109,7 +1109,9 @@ BootMaintCallback ( UINTN Index; EFI_DEVICE_PATH_PROTOCOL *File; - if ((Action != EFI_BROWSER_ACTION_CHANGING) && (Action != EFI_BROWSER_ACTION_CHANGED) && (Action != EFI_BROWSER_ACTION_FORM_OPEN)) { + if ((Action != EFI_BROWSER_ACTION_CHANGING) && (Action != EFI_BROWSER_ACTION_CHANGED) && + (Action != EFI_BROWSER_ACTION_FORM_OPEN) && (Action != EFI_BROWSER_ACTION_DEFAULT_STANDARD) && + (Action != EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING)) { // // Do nothing for other UEFI Action. Only do call back when data is changed or the form is open. // @@ -1145,6 +1147,18 @@ BootMaintCallback ( OldFakeNVMap = &Private->BmmOldFakeNVData; HiiGetBrowserData (&mBootMaintGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *)CurrentFakeNVMap); + if (Action == EFI_BROWSER_ACTION_DEFAULT_STANDARD || Action == EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING) { + if (Value == NULL) + return EFI_INVALID_PARAMETER; + + if (QuestionId == FORM_TIME_OUT_ID) { + CurrentFakeNVMap->BootTimeOut = PcdGet16 (PcdPlatformBootTimeOut); + Value->u16 = PcdGet16 (PcdPlatformBootTimeOut); + } else { + return EFI_UNSUPPORTED; + } + } + if (Action == EFI_BROWSER_ACTION_CHANGING) { if (Value == NULL) { return EFI_INVALID_PARAMETER; @@ -1503,6 +1517,9 @@ InitializeBmmConfig ( BM_MENU_ENTRY *NewMenuEntry; BM_LOAD_CONTEXT *NewLoadContext; UINT16 Index; + EFI_STATUS Status; + UINTN DataSize; + UINT16 BootTimeout = 0xFFFF; ASSERT (CallbackData != NULL); @@ -1520,7 +1537,20 @@ InitializeBmmConfig ( } } - CallbackData->BmmFakeNvData.BootTimeOut = PcdGet16 (PcdPlatformBootTimeOut); + DataSize = sizeof(BootTimeout); + Status = gRT->GetVariable( + EFI_TIME_OUT_VARIABLE_NAME, + &gEfiGlobalVariableGuid, + NULL, + &DataSize, + &BootTimeout + ); + if (!EFI_ERROR (Status)) { + DEBUG ((EFI_D_INFO, "%a: Timeout from variable: %d\n", __FUNCTION__, BootTimeout)); + CallbackData->BmmFakeNvData.BootTimeOut = BootTimeout; + } else { + CallbackData->BmmFakeNvData.BootTimeOut = PcdGet16 (PcdPlatformBootTimeOut); + } // // Initialize data which located in Boot Options Menu diff --git a/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManager.h b/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManager.h index 2e9a70dccb..b776effba9 100644 --- a/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManager.h +++ b/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManager.h @@ -161,7 +161,7 @@ typedef enum _TYPE_OF_TERMINAL { #define COM1_DATA_RATE_VAR_OFFSET VAR_OFFSET (COM1DataRate) #define COM1_STOP_BITS_VAR_OFFSET VAR_OFFSET (COM1StopBits) #define COM1_PARITY_VAR_OFFSET VAR_OFFSET (COM1Parity) -#define COM1_TERMINAL_VAR_OFFSET VAR_OFFSET (COM2TerminalType) +#define COM1_TERMINAL_VAR_OFFSET VAR_OFFSET (COM1TerminalType) #define COM2_BAUD_RATE_VAR_OFFSET VAR_OFFSET (COM2BaudRate) #define COM2_DATA_RATE_VAR_OFFSET VAR_OFFSET (COM2DataRate) #define COM2_STOP_BITS_VAR_OFFSET VAR_OFFSET (COM2StopBits) diff --git a/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManager.vfr b/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManager.vfr index 69fb606324..93dbf34573 100644 --- a/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManager.vfr +++ b/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManager.vfr @@ -40,6 +40,17 @@ formset // label LABEL_FORM_MAIN_END; + numeric varid = BmmData.BootTimeOut, + questionid = FORM_TIME_OUT_ID, + prompt = STRING_TOKEN(STR_NUM_AUTO_BOOT), + help = STRING_TOKEN(STR_HLP_AUTO_BOOT), + flags = RESET_REQUIRED | INTERACTIVE | NUMERIC_SIZE_2 | DISPLAY_UINT_DEC, + key = FORM_TIME_OUT_ID, + minimum = 0, + maximum = 65535, + step = 0, + endnumeric; + endform; form formid = FORM_BOOT_SETUP_ID, diff --git a/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerCustomizedUi.c b/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerCustomizedUi.c index d79212e75c..a98d867ba2 100644 --- a/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerCustomizedUi.c +++ b/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerCustomizedUi.c @@ -58,7 +58,7 @@ UiCustomizeBMMPage ( // // Create "Time Out" menu. // - BmmCreateTimeOutMenu (HiiHandle, StartOpCodeHandle); + // BmmCreateTimeOutMenu (HiiHandle, StartOpCodeHandle); } /** diff --git a/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerCustomizedUiSupport.c b/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerCustomizedUiSupport.c index e16936041a..48c424c941 100644 --- a/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerCustomizedUiSupport.c +++ b/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerCustomizedUiSupport.c @@ -120,6 +120,18 @@ BmmCreateTimeOutMenu ( IN VOID *StartOpCodeHandle ) { + VOID *DefaultOpCodeHandle; + + DefaultOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (DefaultOpCodeHandle != NULL); + + HiiCreateDefaultOpCode ( + DefaultOpCodeHandle, + EFI_HII_DEFAULT_CLASS_STANDARD, + EFI_IFR_TYPE_NUM_SIZE_16, + PcdGet16 (PcdPlatformBootTimeOut) + ); + HiiCreateNumericOpCode ( StartOpCodeHandle, (EFI_QUESTION_ID)FORM_TIME_OUT_ID, @@ -132,8 +144,10 @@ BmmCreateTimeOutMenu ( 0, 65535, 0, - NULL + DefaultOpCodeHandle ); + + HiiFreeOpCodeHandle (DefaultOpCodeHandle); } /** diff --git a/MdeModulePkg/Library/BootManagerUiLib/BootManager.c b/MdeModulePkg/Library/BootManagerUiLib/BootManager.c index b7526796d6..5ceb54164d 100644 --- a/MdeModulePkg/Library/BootManagerUiLib/BootManager.c +++ b/MdeModulePkg/Library/BootManagerUiLib/BootManager.c @@ -493,8 +493,10 @@ UpdateBootManager ( BOOLEAN IsLegacyOption; BOOLEAN NeedEndOp; UINTN MaxLen; + UINTN OptionCount; DeviceType = (UINT16)-1; + OptionCount = 0; // // for better user experience @@ -535,8 +537,9 @@ UpdateBootManager ( EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; EndLabel->Number = LABEL_BOOT_OPTION_END; - mKeyInput = 0; - NeedEndOp = FALSE; + + mKeyInput = 0; + NeedEndOp = FALSE; for (Index = 0; Index < BootOptionCount; Index++) { // // At this stage we are creating a menu entry, thus the Keys are reproduceable @@ -550,6 +553,8 @@ UpdateBootManager ( continue; } + OptionCount++; + // // Group the legacy boot option in the sub title created dynamically // @@ -605,6 +610,10 @@ UpdateBootManager ( ); } + if (OptionCount == 0) { + HiiCreateSubTitleOpCode (StartOpCodeHandle, STRING_TOKEN (STR_NO_BOOTABLE_MEDIA), 0, 0, 0); + } + if (NeedEndOp) { HiiCreateEndOpCode (StartOpCodeHandle); } @@ -797,7 +806,7 @@ BootManagerCallback ( { EFI_BOOT_MANAGER_LOAD_OPTION *BootOption; UINTN BootOptionCount; - EFI_INPUT_KEY Key; + //EFI_INPUT_KEY Key; if (Action == EFI_BROWSER_ACTION_FORM_OPEN) { // @@ -842,13 +851,13 @@ BootManagerCallback ( EfiBootManagerBoot (&BootOption[QuestionId - 1]); BmSetConsoleMode (TRUE); - if (EFI_ERROR (BootOption[QuestionId - 1].Status)) { - gST->ConOut->OutputString ( - gST->ConOut, - HiiGetString (gBootManagerPrivate.HiiHandle, STRING_TOKEN (STR_ANY_KEY_CONTINUE), NULL) - ); - gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); - } + //if (EFI_ERROR (BootOption[QuestionId - 1].Status)) { + // gST->ConOut->OutputString ( + // gST->ConOut, + // HiiGetString (gBootManagerPrivate.HiiHandle, STRING_TOKEN (STR_ANY_KEY_CONTINUE), NULL) + // ); + // gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + //} EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount); diff --git a/MdeModulePkg/Library/BootManagerUiLib/BootManager.h b/MdeModulePkg/Library/BootManagerUiLib/BootManager.h index 0076a9dfce..4405a663a5 100644 --- a/MdeModulePkg/Library/BootManagerUiLib/BootManager.h +++ b/MdeModulePkg/Library/BootManagerUiLib/BootManager.h @@ -46,7 +46,7 @@ typedef struct { 0x847bc3fe, 0xb974, 0x446d, {0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b} \ } -#define BOOT_MANAGER_FORM_ID 0x1000 +#define BOOT_MANAGER_FORM_ID 0x1030 #define LABEL_BOOT_OPTION 0x00 #define LABEL_BOOT_OPTION_END 0x01 diff --git a/MdeModulePkg/Library/BootManagerUiLib/BootManagerStrings.uni b/MdeModulePkg/Library/BootManagerUiLib/BootManagerStrings.uni index 2fcb9a29c5..c280fd9f87 100644 --- a/MdeModulePkg/Library/BootManagerUiLib/BootManagerStrings.uni +++ b/MdeModulePkg/Library/BootManagerUiLib/BootManagerStrings.uni @@ -17,20 +17,9 @@ /=# #langdef en-US "English" -#langdef fr-FR "Français" -#string STR_BM_BANNER #language en-US "Boot Manager" - #language fr-FR "Boot Manager" -#string STR_BOOT_MANAGER_HELP #language en-US "This selection will take you to the Boot Manager" - #language fr-FR "This selection will take you to the Boot Manager" -#string STR_HELP_FOOTER #language en-US "Use the <↑> and <↓> keys to choose a boot option, the key to select a boot option, and the key to exit the Boot Manager Menu." - #language fr-FR "<↑> pour <↓> changer l'option, choisir une option, pour sortir" -#string STR_AND #language en-US " and " - #language fr-FR " et " -#string STR_BOOT_OPTION_BANNER #language en-US "Boot Manager Menu" - #language fr-FR "le Menu d'Option de Botte" +#string STR_BM_BANNER #language en-US "One Time Boot" +#string STR_BOOT_MANAGER_HELP #language en-US "Boot an entry one time" #string STR_ANY_KEY_CONTINUE #language en-US "Press any key to continue..." - #language fr-FR "Appuie n'importe quelle pour continuer..." -#string STR_LAST_STRING #language en-US "" - #language fr-FR "" - +#string STR_NO_BOOTABLE_MEDIA #language en-US "No bootable media found" +#string STR_EMPTY_STRING #language en-US "" diff --git a/MdeModulePkg/Library/BootManagerUiLib/BootManagerVfr.Vfr b/MdeModulePkg/Library/BootManagerUiLib/BootManagerVfr.Vfr index 4049fe6774..c49b6f50b1 100644 --- a/MdeModulePkg/Library/BootManagerUiLib/BootManagerVfr.Vfr +++ b/MdeModulePkg/Library/BootManagerUiLib/BootManagerVfr.Vfr @@ -8,7 +8,7 @@ //**/ #define FORMSET_GUID { 0x847bc3fe, 0xb974, 0x446d, 0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b } -#define BOOT_MANAGER_FORM_ID 0x1000 +#define BOOT_MANAGER_FORM_ID 0x1030 #define LABEL_BOOT_OPTION 0x00 #define LABEL_BOOT_OPTION_END 0x01 @@ -20,22 +20,18 @@ formset classguid = gEfiIfrFrontPageGuid, form formid = BOOT_MANAGER_FORM_ID, - title = STRING_TOKEN(STR_BM_BANNER); - - subtitle text = STRING_TOKEN(STR_LAST_STRING); - subtitle text = STRING_TOKEN(STR_BOOT_OPTION_BANNER); - subtitle text = STRING_TOKEN(STR_LAST_STRING); + title = STRING_TOKEN(STR_BM_BANNER); // //Add this invisable text in order to indicate enter Boot Manager form. // suppressif TRUE; - text - help = STRING_TOKEN(STR_LAST_STRING ), - text = STRING_TOKEN(STR_LAST_STRING ), - flags = INTERACTIVE, - key = 0x1212; - endif; + text + help = STRING_TOKEN(STR_EMPTY_STRING), + text = STRING_TOKEN(STR_EMPTY_STRING), + flags = INTERACTIVE, + key = 0x1212; + endif; // // This is where we will dynamically add choices for the Boot Manager @@ -43,9 +39,6 @@ formset label LABEL_BOOT_OPTION; label LABEL_BOOT_OPTION_END; - subtitle text = STRING_TOKEN(STR_LAST_STRING); - subtitle text = STRING_TOKEN(STR_HELP_FOOTER); - endform; endformset; diff --git a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.c b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.c index b3da13d0a3..8c984b5025 100644 --- a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.c +++ b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.c @@ -134,6 +134,7 @@ RefreshKeyHelp ( UINTN ThdCol; UINTN RightColumnOfHelp; UINTN TopRowOfHelp; + UINTN MiddleRowOfHelp; UINTN BottomRowOfHelp; UINTN StartColumnOfHelp; EFI_IFR_NUMERIC *NumericOp; @@ -167,6 +168,7 @@ RefreshKeyHelp ( StartColumnOfHelp = gScreenDimensions.LeftColumn + 2; RightColumnOfHelp = gScreenDimensions.RightColumn - 1; TopRowOfHelp = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight + 1; + MiddleRowOfHelp = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight + 2; BottomRowOfHelp = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 2; ColumnWidth1 = SecCol - StartColumnOfHelp; @@ -179,22 +181,28 @@ RefreshKeyHelp ( // // Clean the space at gScreenDimensions.LeftColumn + 1. // - PrintStringAtWithWidth (StartColumnOfHelp - 1, BottomRowOfHelp, gLibEmptyString, 1); PrintStringAtWithWidth (StartColumnOfHelp - 1, TopRowOfHelp, gLibEmptyString, 1); + PrintStringAtWithWidth (StartColumnOfHelp - 1, MiddleRowOfHelp, gLibEmptyString, 1); + PrintStringAtWithWidth (StartColumnOfHelp - 1, BottomRowOfHelp, gLibEmptyString, 1); + + // + // Always print screenshot helptext + // + PrintStringAtWithWidth (StartColumnOfHelp, BottomRowOfHelp, gScreenshotString, ColumnWidth1); if (Statement == NULL) { // // Print Key for Form without showable statement. // PrintHotKeyHelpString (FormData, TRUE); - PrintStringAtWithWidth (StartColumnOfHelp, BottomRowOfHelp, gLibEmptyString, ColumnWidth1); - PrintStringAtWithWidth (SecCol, BottomRowOfHelp, gLibEmptyString, ColumnWidth2); + PrintStringAtWithWidth (StartColumnOfHelp, MiddleRowOfHelp, gLibEmptyString, ColumnWidth1); + PrintStringAtWithWidth (SecCol, MiddleRowOfHelp, gLibEmptyString, ColumnWidth2); PrintStringAtWithWidth (StartColumnOfHelp, TopRowOfHelp, gLibEmptyString, ColumnWidth1); if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) { ColumnStr3 = gEscapeString; } - PrintStringAtWithWidth (ThdCol, BottomRowOfHelp, ColumnStr3, ColumnWidth3); + PrintStringAtWithWidth (ThdCol, MiddleRowOfHelp, ColumnStr3, ColumnWidth3); return; } @@ -227,7 +235,7 @@ RefreshKeyHelp ( ColumnStr3 = gEscapeString; } - PrintStringAtWithWidth (ThdCol, BottomRowOfHelp, ColumnStr3, ColumnWidth3); + PrintStringAtWithWidth (ThdCol, MiddleRowOfHelp, ColumnStr3, ColumnWidth3); if ((Statement->OpCode->OpCode == EFI_IFR_DATE_OP) || (Statement->OpCode->OpCode == EFI_IFR_TIME_OP)) @@ -235,7 +243,7 @@ RefreshKeyHelp ( PrintAt ( ColumnWidth1, StartColumnOfHelp, - BottomRowOfHelp, + MiddleRowOfHelp, L"%c%c%c%c%s", ARROW_UP, ARROW_DOWN, @@ -243,20 +251,20 @@ RefreshKeyHelp ( ARROW_LEFT, gMoveHighlight ); - PrintStringAtWithWidth (SecCol, BottomRowOfHelp, gEnterString, ColumnWidth2); + PrintStringAtWithWidth (SecCol, MiddleRowOfHelp, gEnterString, ColumnWidth2); PrintStringAtWithWidth (StartColumnOfHelp, TopRowOfHelp, gAdjustNumber, ColumnWidth1); } else { - PrintAt (ColumnWidth1, StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight); + PrintAt (ColumnWidth1, StartColumnOfHelp, MiddleRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight); if ((Statement->OpCode->OpCode == EFI_IFR_NUMERIC_OP) && (NumericOp != NULL) && (LibGetFieldFromNum (Statement->OpCode) != 0)) { ColumnStr1 = gAdjustNumber; } PrintStringAtWithWidth (StartColumnOfHelp, TopRowOfHelp, ColumnStr1, ColumnWidth1); - PrintStringAtWithWidth (SecCol, BottomRowOfHelp, gEnterString, ColumnWidth2); + PrintStringAtWithWidth (SecCol, MiddleRowOfHelp, gEnterString, ColumnWidth2); } } else { PrintHotKeyHelpString (FormData, FALSE); - PrintStringAtWithWidth (SecCol, BottomRowOfHelp, gEnterCommitString, ColumnWidth2); + PrintStringAtWithWidth (SecCol, MiddleRowOfHelp, gEnterCommitString, ColumnWidth2); // // If it is a selected numeric with manual input, display different message @@ -266,9 +274,9 @@ RefreshKeyHelp ( (Statement->OpCode->OpCode == EFI_IFR_TIME_OP)) { ColumnStr2 = HexDisplay ? gHexNumericInput : gDecNumericInput; - PrintStringAtWithWidth (StartColumnOfHelp, BottomRowOfHelp, gLibEmptyString, ColumnWidth1); + PrintStringAtWithWidth (StartColumnOfHelp, MiddleRowOfHelp, gLibEmptyString, ColumnWidth1); } else { - PrintAt (ColumnWidth1, StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight); + PrintAt (ColumnWidth1, StartColumnOfHelp, MiddleRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight); } if (Statement->OpCode->OpCode == EFI_IFR_ORDERED_LIST_OP) { @@ -280,7 +288,7 @@ RefreshKeyHelp ( PrintStringAtWithWidth (ThdCol, TopRowOfHelp, ColumnStr3, ColumnWidth3); PrintStringAtWithWidth (SecCol, TopRowOfHelp, ColumnStr2, ColumnWidth2); - PrintStringAtWithWidth (ThdCol, BottomRowOfHelp, gEnterEscapeString, ColumnWidth3); + PrintStringAtWithWidth (ThdCol, MiddleRowOfHelp, gEnterEscapeString, ColumnWidth3); } break; @@ -292,10 +300,10 @@ RefreshKeyHelp ( ColumnStr3 = gEscapeString; } - PrintStringAtWithWidth (ThdCol, BottomRowOfHelp, ColumnStr3, ColumnWidth3); + PrintStringAtWithWidth (ThdCol, MiddleRowOfHelp, ColumnStr3, ColumnWidth3); - PrintAt (ColumnWidth1, StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight); - PrintStringAtWithWidth (SecCol, BottomRowOfHelp, gToggleCheckBox, ColumnWidth2); + PrintAt (ColumnWidth1, StartColumnOfHelp, MiddleRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight); + PrintStringAtWithWidth (SecCol, MiddleRowOfHelp, gToggleCheckBox, ColumnWidth2); PrintStringAtWithWidth (StartColumnOfHelp, TopRowOfHelp, gLibEmptyString, ColumnWidth1); break; @@ -313,14 +321,14 @@ RefreshKeyHelp ( ColumnStr3 = gEscapeString; } - PrintStringAtWithWidth (ThdCol, BottomRowOfHelp, ColumnStr3, ColumnWidth3); + PrintStringAtWithWidth (ThdCol, MiddleRowOfHelp, ColumnStr3, ColumnWidth3); - PrintAt (ColumnWidth1, StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight); + PrintAt (ColumnWidth1, StartColumnOfHelp, MiddleRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight); if ((Statement->OpCode->OpCode != EFI_IFR_TEXT_OP) && (Statement->OpCode->OpCode != EFI_IFR_SUBTITLE_OP)) { ColumnStr2 = gEnterString; } - PrintStringAtWithWidth (SecCol, BottomRowOfHelp, ColumnStr2, ColumnWidth2); + PrintStringAtWithWidth (SecCol, MiddleRowOfHelp, ColumnStr2, ColumnWidth2); PrintStringAtWithWidth (StartColumnOfHelp, TopRowOfHelp, ColumnStr1, ColumnWidth1); } else { PrintHotKeyHelpString (FormData, FALSE); @@ -330,9 +338,9 @@ RefreshKeyHelp ( } PrintStringAtWithWidth (StartColumnOfHelp, TopRowOfHelp, ColumnStr1, ColumnWidth1); - PrintStringAtWithWidth (StartColumnOfHelp, BottomRowOfHelp, ColumnStr1, ColumnWidth1); - PrintStringAtWithWidth (SecCol, BottomRowOfHelp, ColumnStr2, ColumnWidth2); - PrintStringAtWithWidth (ThdCol, BottomRowOfHelp, ColumnStr3, ColumnWidth3); + PrintStringAtWithWidth (StartColumnOfHelp, MiddleRowOfHelp, ColumnStr1, ColumnWidth1); + PrintStringAtWithWidth (SecCol, MiddleRowOfHelp, ColumnStr2, ColumnWidth2); + PrintStringAtWithWidth (ThdCol, MiddleRowOfHelp, ColumnStr3, ColumnWidth3); } break; @@ -410,6 +418,26 @@ UpdateStatusBar ( } } +// +// If screen dimension info is not ready, get it from console. +// +STATIC +VOID +FillScreenDimentions ( + IN OUT EFI_SCREEN_DESCRIPTOR *ScreenDimensions + ) +{ + if (ScreenDimensions->RightColumn == 0 || ScreenDimensions->BottomRow == 0) { + ZeroMem (ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); + gST->ConOut->QueryMode ( + gST->ConOut, + gST->ConOut->Mode->Mode, + &ScreenDimensions->RightColumn, + &ScreenDimensions->BottomRow + ); + } +} + /** Create popup window. It will replace CreateDialog(). @@ -444,18 +472,7 @@ CreateDialog ( UINTN CurrentAttribute; BOOLEAN CursorVisible; - // - // If screen dimension info is not ready, get it from console. - // - if ((gScreenDimensions.RightColumn == 0) || (gScreenDimensions.BottomRow == 0)) { - ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); - gST->ConOut->QueryMode ( - gST->ConOut, - gST->ConOut->Mode->Mode, - &gScreenDimensions.RightColumn, - &gScreenDimensions.BottomRow - ); - } + FillScreenDimentions (&gScreenDimensions); DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn; DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow; @@ -924,6 +941,114 @@ ClearDisplayPage ( gLibIsFirstForm = TRUE; } +/** + 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. + + If String is NULL, then ASSERT (). + + @param String The input string to be counted. + + @return Storage space for the input string. + +**/ +UINTN +EFIAPI +GetStringWidth ( + IN CHAR16 *String + ) +{ + UINTN Index; + UINTN Count; + UINTN IncrementValue; + + ASSERT (String != NULL); + 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 + ) + { + } + + // + // We hit the null-terminator, we now have a count + // + if (String[Index] == 0) { + break; + } + + // + // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed + // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2) + // + if (String[Index] == NARROW_CHAR) { + // + // Skip to the next character + // + Index++; + IncrementValue = 1; + } else { + // + // Skip to the next character + // + Index++; + IncrementValue = 2; + } + } while (String[Index] != 0); + + // + // Increment by one to include the null-terminator in the size + // + Count++; + + return Count * sizeof (CHAR16); +} + +/** + Draw a pop up windows based on the dimension, number of lines and + strings specified. + + @param RequestedWidth The width of the pop-up. + @param NumberOfLines The number of lines. + @param ... A series of text strings that displayed in the pop-up. + +**/ +VOID +EFIAPI +CreateMultiStringPopUp ( + IN UINTN RequestedWidth, + IN UINTN NumberOfLines, + ... + ) +{ + VA_LIST Marker; + + FillScreenDimentions (&gScreenDimensions); + + VA_START (Marker, NumberOfLines); + + CreateSharedPopUp (RequestedWidth, NumberOfLines, Marker); + + VA_END (Marker); +} + /** Constructor of Customized Display Library Instance. diff --git a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.uni b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.uni index 3f2efa5626..abc03fc2c1 100644 --- a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.uni +++ b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.uni @@ -43,8 +43,8 @@ #language fr-FR "Bascule la Case de pointage" #string NV_UPDATE_MESSAGE #language en-US "Configuration changed" #language fr-FR "Configuration changed" -#string INPUT_ERROR_MESSAGE #language en-US "!!" - #language fr-FR "!!" +#string INPUT_ERROR_MESSAGE #language en-US "Invalid input value!!" + #language fr-FR "Invalid input value!!" #string EMPTY_STRING #language en-US "" #language fr-FR "" #string ARE_YOU_SURE_YES #language en-US "Y" @@ -55,3 +55,4 @@ #language fr-FR "Enregistrer les modifications et quitter?" #string ARE_YOU_SURE #language en-US "Press 'Y' to save and exit, 'N' to discard and exit, 'ESC' to cancel." #language fr-FR "Pressez 'Y' pour sauvegarder et quitter, 'N' de se défaire et de sortie" +#string SCREENSHOT_STRING #language en-US "LCtrl+LAlt+F12=Save screenshot" diff --git a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c index 58130d9383..9eeea21792 100644 --- a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c +++ b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c @@ -25,6 +25,7 @@ CHAR16 *gMoveHighlight; CHAR16 *gDecNumericInput; CHAR16 *gHexNumericInput; CHAR16 *gToggleCheckBox; +CHAR16 *gScreenshotString; CHAR16 *gLibEmptyString; CHAR16 *gAreYouSure; CHAR16 *gYesResponse; @@ -582,7 +583,7 @@ PrintHotKeyHelpString ( CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); ColumnWidth = (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3; - BottomRowOfHotKeyHelp = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 3; + BottomRowOfHotKeyHelp = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 4; ColumnStr = gLibEmptyString; // @@ -722,6 +723,7 @@ InitializeLibStrings ( gDecNumericInput = LibGetToken (STRING_TOKEN (DEC_NUMERIC_INPUT), mCDLStringPackHandle); gHexNumericInput = LibGetToken (STRING_TOKEN (HEX_NUMERIC_INPUT), mCDLStringPackHandle); gToggleCheckBox = LibGetToken (STRING_TOKEN (TOGGLE_CHECK_BOX), mCDLStringPackHandle); + gScreenshotString = LibGetToken (STRING_TOKEN (SCREENSHOT_STRING), mCDLStringPackHandle); gAreYouSure = LibGetToken (STRING_TOKEN (ARE_YOU_SURE), mCDLStringPackHandle); gYesResponse = LibGetToken (STRING_TOKEN (ARE_YOU_SURE_YES), mCDLStringPackHandle); @@ -762,6 +764,7 @@ FreeLibStrings ( FreePool (gDecNumericInput); FreePool (gHexNumericInput); FreePool (gToggleCheckBox); + FreePool (gScreenshotString); FreePool (gAreYouSure); FreePool (gYesResponse); @@ -985,3 +988,108 @@ PrintAt ( VA_END (Args); return LengthOfPrinted; } + +/** + Draw a pop up windows based on the dimension, number of lines and + strings specified. + + @param RequestedWidth The width of the pop-up. + @param NumberOfLines The number of lines. + @param Marker The variable argument list for the list of string to be printed. + +**/ +VOID +CreateSharedPopUp ( + IN UINTN RequestedWidth, + IN UINTN NumberOfLines, + IN VA_LIST Marker + ) +{ + UINTN Index; + UINTN Count; + CHAR16 Character; + UINTN Start; + UINTN End; + UINTN Top; + UINTN Bottom; + CHAR16 *String; + UINTN DimensionsWidth; + UINTN DimensionsHeight; + + DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn; + DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow; + + gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ()); + + if ((RequestedWidth + 2) > DimensionsWidth) { + RequestedWidth = DimensionsWidth - 2; + } + + // + // Subtract the PopUp width from total Columns, allow for one space extra on + // each end plus a border. + // + Start = (DimensionsWidth - RequestedWidth - 2) / 2 + gScreenDimensions.LeftColumn + 1; + End = Start + RequestedWidth + 1; + + Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1; + Bottom = Top + NumberOfLines + 2; + + Character = BOXDRAW_DOWN_RIGHT; + PrintCharAt (Start, Top, Character); + Character = BOXDRAW_HORIZONTAL; + for (Index = Start; Index + 2 < End; Index++) { + PrintCharAt ((UINTN)-1, (UINTN)-1, Character); + } + + Character = BOXDRAW_DOWN_LEFT; + PrintCharAt ((UINTN)-1, (UINTN)-1, Character); + Character = BOXDRAW_VERTICAL; + + Count = 0; + for (Index = Top; Index + 2 < Bottom; Index++, Count++) { + String = VA_ARG (Marker, CHAR16 *); + + // + // This will clear the background of the line - we never know who might have been + // here before us. This differs from the next clear in that it used the non-reverse + // video for normal printing. + // + if (GetStringWidth (String) / 2 > 1) { + ClearLines (Start, End, Index + 1, Index + 1, GetPopupColor ()); + } + + // + // Passing in a space results in the assumption that this is where typing will occur + // + if (String[0] == L' ') { + ClearLines (Start + 1, End - 1, Index + 1, Index + 1, GetPopupInverseColor ()); + } + + // + // Passing in a NULL results in a blank space + // + if (String[0] == CHAR_NULL) { + ClearLines (Start, End, Index + 1, Index + 1, GetPopupColor ()); + } + + PrintStringAt ( + ((DimensionsWidth - GetStringWidth (String) / 2) / 2) + gScreenDimensions.LeftColumn + 1, + Index + 1, + String + ); + gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ()); + PrintCharAt (Start, Index + 1, Character); + PrintCharAt (End - 1, Index + 1, Character); + } + + Character = BOXDRAW_UP_RIGHT; + PrintCharAt (Start, Bottom - 1, Character); + Character = BOXDRAW_HORIZONTAL; + for (Index = Start; Index + 2 < End; Index++) { + PrintCharAt ((UINTN)-1, (UINTN)-1, Character); + } + + Character = BOXDRAW_UP_LEFT; + PrintCharAt ((UINTN)-1, (UINTN)-1, Character); +} diff --git a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.h b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.h index 01213cb059..8b2e0e4e38 100644 --- a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.h +++ b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.h @@ -50,7 +50,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #define FRONT_PAGE_HEADER_HEIGHT 6 #define NONE_FRONT_PAGE_HEADER_HEIGHT 3 -#define FOOTER_HEIGHT 4 +#define FOOTER_HEIGHT 5 #define STATUS_BAR_HEIGHT 1 // @@ -95,6 +95,7 @@ extern CHAR16 *gMoveHighlight; extern CHAR16 *gDecNumericInput; extern CHAR16 *gHexNumericInput; extern CHAR16 *gToggleCheckBox; +extern CHAR16 *gScreenshotString; extern CHAR16 *gLibEmptyString; extern CHAR16 *gAreYouSure; extern CHAR16 *gYesResponse; @@ -284,4 +285,20 @@ ProcessExternedOpcode ( IN FORM_DISPLAY_ENGINE_FORM *FormData ); +/** + Draw a pop up windows based on the dimension, number of lines and + strings specified. + + @param RequestedWidth The width of the pop-up. + @param NumberOfLines The number of lines. + @param Marker The variable argument list for the list of string to be printed. + +**/ +VOID +CreateSharedPopUp ( + IN UINTN RequestedWidth, + IN UINTN NumberOfLines, + IN VA_LIST Marker + ); + #endif diff --git a/MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/ReportStatusCodeLib.c b/MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/ReportStatusCodeLib.c index 8fd20ff239..daa4a34218 100644 --- a/MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/ReportStatusCodeLib.c +++ b/MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/ReportStatusCodeLib.c @@ -231,6 +231,15 @@ InternalReportStatusCode ( return EFI_UNSUPPORTED; } + // + // Prevent debugging at runtime by not doing anything after boot services + // are exited. This is done to avoid accesses to cbmem CONSOLE buffer which + // is neither marked as runtime code nor data. + // + if (mHaveExitedBootServices) { + return EFI_UNSUPPORTED; + } + // // A Report Status Code Protocol is present in system, so pass in all the parameters to the service. // diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c index 7a97f7cdcc..61cb0e19ab 100644 --- a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c +++ b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c @@ -1853,6 +1853,9 @@ EfiBootManagerBoot ( UINTN FileSize; EFI_BOOT_LOGO_PROTOCOL *BootLogo; EFI_EVENT LegacyBootEvent; + EFI_INPUT_KEY Key; + UINTN Index; + UINT8 *SecureBoot; if (BootOption == NULL) { return; @@ -1993,6 +1996,46 @@ EfiBootManagerBoot ( // BmReportLoadFailure (EFI_SW_DXE_BS_EC_BOOT_OPTION_LOAD_ERROR, Status); BootOption->Status = Status; + + if (gST->ConOut != NULL) { + gST->ConOut->ClearScreen (gST->ConOut); + + // + // When UEFI Secure Boot is enabled, unsigned modules won't load. + // + SecureBoot = NULL; + GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME, (VOID**)&SecureBoot, NULL); + if ((SecureBoot != NULL) && (*SecureBoot == SECURE_BOOT_MODE_ENABLE)) { + AsciiPrint ("Secure Boot is enabled.\n"); + } else { + AsciiPrint ("Secure Boot is disabled.\n"); + } + + if ((BootOption->Status == EFI_ACCESS_DENIED) && + (SecureBoot != NULL) && + (*SecureBoot == SECURE_BOOT_MODE_ENABLE)) { + AsciiPrint ( + "The image signature is invalid or missing!\n" + "Sign the image with a valid key or disable Secure Boot\n"); + } + + if (SecureBoot != NULL) { + FreePool (SecureBoot); + } + + AsciiPrint ( + "Booting '%s' failed due to '%r'.\n" + "Press any key to continue...\n", + BootOption->Description, BootOption->Status); + + } + if (gST->ConIn != NULL) { + Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index); + ASSERT_EFI_ERROR (Status); + ASSERT (Index == 0); + while (!EFI_ERROR (gST->ConIn->ReadKeyStroke (gST->ConIn, &Key))) {} + } + return; } } @@ -2168,6 +2211,715 @@ BmMatchPartitionDevicePathNode ( return FALSE; } +/** + Get the headers (dos, image, optional header) from an image + + @param Device SimpleFileSystem device handle + @param FileName File name for the image + @param DosHeader Pointer to dos header + @param Hdr The buffer in which to return the PE32, PE32+, or TE header. + + @retval EFI_SUCCESS Successfully get the machine type. + @retval EFI_NOT_FOUND The file is not found. + @retval EFI_LOAD_ERROR File is not a valid image file. + +**/ +STATIC +EFI_STATUS +EFIAPI +BdsLibGetImageHeader ( + IN EFI_HANDLE Device, + IN CHAR16 *FileName, + OUT EFI_IMAGE_DOS_HEADER *DosHeader, + OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume; + EFI_FILE_HANDLE Root; + EFI_FILE_HANDLE ThisFile; + UINTN BufferSize; + UINT64 FileSize; + EFI_FILE_INFO *Info; + + Root = NULL; + ThisFile = NULL; + // + // Handle the file system interface to the device + // + Status = gBS->HandleProtocol ( + Device, + &gEfiSimpleFileSystemProtocolGuid, + (VOID *) &Volume + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + Status = Volume->OpenVolume ( + Volume, + &Root + ); + if (EFI_ERROR (Status)) { + Root = NULL; + goto Done; + } + ASSERT (Root != NULL); + Status = Root->Open (Root, &ThisFile, FileName, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR (Status)) { + goto Done; + } + ASSERT (ThisFile != NULL); + + // + // Get file size + // + BufferSize = SIZE_OF_EFI_FILE_INFO + 200; + do { + Info = NULL; + Status = gBS->AllocatePool (EfiBootServicesData, BufferSize, (VOID **) &Info); + if (EFI_ERROR (Status)) { + goto Done; + } + Status = ThisFile->GetInfo ( + ThisFile, + &gEfiFileInfoGuid, + &BufferSize, + Info + ); + if (!EFI_ERROR (Status)) { + break; + } + if (Status != EFI_BUFFER_TOO_SMALL) { + FreePool (Info); + goto Done; + } + FreePool (Info); + } while (TRUE); + + FileSize = Info->FileSize; + FreePool (Info); + + // + // Read dos header + // + BufferSize = sizeof (EFI_IMAGE_DOS_HEADER); + Status = ThisFile->Read (ThisFile, &BufferSize, DosHeader); + if (EFI_ERROR (Status) || + BufferSize < sizeof (EFI_IMAGE_DOS_HEADER) || + FileSize <= DosHeader->e_lfanew || + DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) { + Status = EFI_LOAD_ERROR; + goto Done; + } + + // + // Move to PE signature + // + Status = ThisFile->SetPosition (ThisFile, DosHeader->e_lfanew); + if (EFI_ERROR (Status)) { + Status = EFI_LOAD_ERROR; + goto Done; + } + + // + // Read and check PE signature + // + BufferSize = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION); + Status = ThisFile->Read (ThisFile, &BufferSize, Hdr.Pe32); + if (EFI_ERROR (Status) || + BufferSize < sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION) || + Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) { + Status = EFI_LOAD_ERROR; + goto Done; + } + + // + // Check PE32 or PE32+ magic + // + if (Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC && + Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + Status = EFI_LOAD_ERROR; + goto Done; + } + + Done: + if (ThisFile != NULL) { + ThisFile->Close (ThisFile); + } + if (Root != NULL) { + Root->Close (Root); + } + return Status; +} + +/** + Return the bootable media handle. + First, check the device is connected + Second, check whether the device path point to a device which support SimpleFileSystemProtocol, + Third, detect the the default boot file in the Media, and return the removable Media handle. + + @param DevicePath Device Path to a bootable device + + @return The bootable media handle. If the media on the DevicePath is not bootable, NULL will return. + +**/ +EFI_HANDLE +EFIAPI +BdsLibGetBootableHandle ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_STATUS Status; + EFI_TPL OldTpl; + EFI_DEVICE_PATH_PROTOCOL *UpdatedDevicePath; + EFI_DEVICE_PATH_PROTOCOL *DupDevicePath; + EFI_HANDLE Handle; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + VOID *Buffer; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + UINTN Size; + UINTN TempSize; + EFI_HANDLE ReturnHandle; + EFI_HANDLE *SimpleFileSystemHandles; + + UINTN NumberSimpleFileSystemHandles; + UINTN Index; + EFI_IMAGE_DOS_HEADER DosHeader; + EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData; + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; + + UpdatedDevicePath = DevicePath; + + // + // Enter to critical section to protect the acquired BlockIo instance + // from getting released due to the USB mass storage hotplug event + // + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + // + // Check whether the device is connected + // + Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &UpdatedDevicePath, &Handle); + if (EFI_ERROR (Status)) { + // + // Skip the case that the boot option point to a simple file protocol which does not consume block Io protocol, + // + Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &UpdatedDevicePath, &Handle); + if (EFI_ERROR (Status)) { + // + // Fail to find the proper BlockIo and simple file protocol, maybe because device not present, we need to connect it firstly + // + UpdatedDevicePath = DevicePath; + Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &UpdatedDevicePath, &Handle); + gBS->ConnectController (Handle, NULL, NULL, TRUE); + } + } else { + // + // For removable device boot option, its contained device path only point to the removable device handle, + // should make sure all its children handles (its child partion or media handles) are created and connected. + // + gBS->ConnectController (Handle, NULL, NULL, TRUE); + // + // Get BlockIo protocol and check removable attribute + // + Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo); + ASSERT_EFI_ERROR (Status); + + // + // Issue a dummy read to the device to check for media change. + // When the removable media is changed, any Block IO read/write will + // cause the BlockIo protocol be reinstalled and EFI_MEDIA_CHANGED is + // returned. After the Block IO protocol is reinstalled, subsequent + // Block IO read/write will success. + // + Buffer = AllocatePool (BlockIo->Media->BlockSize); + if (Buffer != NULL) { + BlockIo->ReadBlocks ( + BlockIo, + BlockIo->Media->MediaId, + 0, + BlockIo->Media->BlockSize, + Buffer + ); + FreePool(Buffer); + } + } + + // + // Detect the the default boot file from removable Media + // + + // + // If fail to get bootable handle specified by a USB boot option, the BDS should try to find other bootable device in the same USB bus + // Try to locate the USB node device path first, if fail then use its previous PCI node to search + // + DupDevicePath = DuplicateDevicePath (DevicePath); + ASSERT (DupDevicePath != NULL); + + UpdatedDevicePath = DupDevicePath; + Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &UpdatedDevicePath, &Handle); + // + // if the resulting device path point to a usb node, and the usb node is a dummy node, should only let device path only point to the previous Pci node + // Acpi()/Pci()/Usb() --> Acpi()/Pci() + // + if ((DevicePathType (UpdatedDevicePath) == MESSAGING_DEVICE_PATH) && + (DevicePathSubType (UpdatedDevicePath) == MSG_USB_DP)) { + // + // Remove the usb node, let the device path only point to PCI node + // + SetDevicePathEndNode (UpdatedDevicePath); + UpdatedDevicePath = DupDevicePath; + } else { + UpdatedDevicePath = DevicePath; + } + + // + // Get the device path size of boot option + // + Size = GetDevicePathSize(UpdatedDevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL); // minus the end node + ReturnHandle = NULL; + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSimpleFileSystemProtocolGuid, + NULL, + &NumberSimpleFileSystemHandles, + &SimpleFileSystemHandles + ); + for (Index = 0; Index < NumberSimpleFileSystemHandles; Index++) { + // + // Get the device path size of SimpleFileSystem handle + // + TempDevicePath = DevicePathFromHandle (SimpleFileSystemHandles[Index]); + TempSize = GetDevicePathSize (TempDevicePath)- sizeof (EFI_DEVICE_PATH_PROTOCOL); // minus the end node + // + // Check whether the device path of boot option is part of the SimpleFileSystem handle's device path + // + if (Size <= TempSize && CompareMem (TempDevicePath, UpdatedDevicePath, Size)==0) { + // + // Load the default boot file \EFI\BOOT\boot{machinename}.EFI from removable Media + // machinename is ia32, ia64, x64, ... + // + Hdr.Union = &HdrData; + Status = BdsLibGetImageHeader ( + SimpleFileSystemHandles[Index], + EFI_REMOVABLE_MEDIA_FILE_NAME, + &DosHeader, + Hdr + ); + if (!EFI_ERROR (Status) && + EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Hdr.Pe32->FileHeader.Machine) && + Hdr.Pe32->OptionalHeader.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) { + ReturnHandle = SimpleFileSystemHandles[Index]; + break; + } + } + } + + FreePool(DupDevicePath); + + if (SimpleFileSystemHandles != NULL) { + FreePool(SimpleFileSystemHandles); + } + + gBS->RestoreTPL (OldTpl); + + return ReturnHandle; +} + +typedef struct { + CHAR16* FileName; + CHAR16* BootOptionFmt; +} PRE_INSTALLED_BOOT_OPT; + +STATIC CONST PRE_INSTALLED_BOOT_OPT PreInstalledBootOpts[] = { + { L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi", L"Windows Boot Manager (on %s)" }, + { L"\\EFI\\Suse\\elilo.efi", L"Suse Boot Manager (on %s)" }, + { L"\\EFI\\Redhat\\elilo.efi", L"RedHat Boot Manager (on %s)" }, +}; + +STATIC CONST PRE_INSTALLED_BOOT_OPT PreInstalledBootOptsShim[] = { + { L"\\EFI\\ubuntu\\shimx64.efi", L"Ubuntu (on %s)" }, + { L"\\EFI\\redhat\\shimx64.efi", L"RedHat (on %s)" }, + { L"\\EFI\\fedora\\shimx64.efi", L"Fedora (on %s)" }, + { L"\\EFI\\centos\\shimx64.efi", L"CentOS (on %s)" }, + { L"\\EFI\\opensuse\\shimx64.efi", L"OpenSuse (on %s)" }, + { L"\\EFI\\debian\\shimx64.efi", L"Debian (on %s)" }, + { L"\\EFI\\qubes\\shimx64.efi", L"Qubes OS (on %s)" }, +}; + +STATIC CONST PRE_INSTALLED_BOOT_OPT PreInstalledBootOptsGrub[] = { + { L"\\EFI\\ubuntu\\grubx64.efi", L"Ubuntu (on %s)" }, + { L"\\EFI\\redhat\\grubx64.efi", L"RedHat (on %s)" }, + { L"\\EFI\\fedora\\grubx64.efi", L"Fedora (on %s)" }, + { L"\\EFI\\centos\\grubx64.efi", L"CentOS (on %s)" }, + { L"\\EFI\\opensuse\\grubx64.efi", L"OpenSuse (on %s)" }, + { L"\\EFI\\debian\\grubx64.efi", L"Debian (on %s)" }, + { L"\\EFI\\qubes\\grubx64.efi", L"Qubes OS (on %s)" }, +}; + +STATIC CONST PRE_INSTALLED_BOOT_OPT DtsBootOpt = { + L"\\EFI\\DTS\\grubx64.efi", L"Dasharo Tools Suite (on %s)" +}; + +EFI_HANDLE +GetDiskHandleByFsHandle ( + EFI_HANDLE FsHandle +) +{ + UINTN HandleCount; + EFI_HANDLE *Handles; + EFI_HANDLE DiskHandle; + UINTN Index; + EFI_DEVICE_PATH_PROTOCOL *DiskDevicePath; + EFI_DEVICE_PATH_PROTOCOL *FileSystemDevicePath; + EFI_DEVICE_PATH_PROTOCOL *TempFileSystemDevicePath; + BOOLEAN FoundMatch; + + FoundMatch = FALSE; + FileSystemDevicePath = DevicePathFromHandle (FsHandle); + + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &HandleCount, + &Handles + ); + for (Index = 0; Index < HandleCount; Index++) { + + DiskDevicePath = DevicePathFromHandle (Handles[Index]); + TempFileSystemDevicePath = FileSystemDevicePath; + + while (!IsDevicePathEnd (DiskDevicePath) && !IsDevicePathEnd (TempFileSystemDevicePath)) { + + if (!CompareMem(TempFileSystemDevicePath, DiskDevicePath, DevicePathNodeLength(TempFileSystemDevicePath))) { + if ((DevicePathType (DiskDevicePath) == MEDIA_DEVICE_PATH) && + (DevicePathSubType (DiskDevicePath) == MEDIA_HARDDRIVE_DP)) { + // If DiskDevicePath has HardDrive DP, it is not the one we look for + break; + } + // Continue search + TempFileSystemDevicePath = NextDevicePathNode (TempFileSystemDevicePath); + DiskDevicePath = NextDevicePathNode (DiskDevicePath); + + // If we reached the end, check for a match, because the loop will not check it on next iteration + if (IsDevicePathEnd (DiskDevicePath)) { + if ((DevicePathType (TempFileSystemDevicePath) == MEDIA_DEVICE_PATH) && + (DevicePathSubType (TempFileSystemDevicePath) == MEDIA_HARDDRIVE_DP)) { + FoundMatch = TRUE; + DiskHandle = Handles[Index]; + } + } + } else { + // If we found first uncommon node and it is HardDrive DP, then we have a match + if ((DevicePathType (TempFileSystemDevicePath) == MEDIA_DEVICE_PATH) && + (DevicePathSubType (TempFileSystemDevicePath) == MEDIA_HARDDRIVE_DP)) { + FoundMatch = TRUE; + DiskHandle = Handles[Index]; + } + break; + } + } + + if (FoundMatch) { + if (HandleCount != 0) + FreePool (Handles); + + return DiskHandle; + } + + } + + if (HandleCount != 0) + FreePool (Handles); + + // No match, return the FS handle. Description will not be the one we would like to be though. + return FsHandle; +} + +VOID +StrStripTrailingSpaces ( + CHAR16 *String +) +{ + UINTN Idx; + + for (Idx = StrLen(String) - 1; Idx > 0; Idx--) { + if(String[Idx] == 0x0020) + String[Idx] = 0; + else + break; + } +} + +EFI_BOOT_MANAGER_LOAD_OPTION * +CreatePreInstalledBootOption ( + IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions, + IN OUT UINTN *BootOptionCount, + IN EFI_HANDLE Handle, + IN CONST PRE_INSTALLED_BOOT_OPT *BootOpt +) +{ + EFI_STATUS Status; + UINTN OptNameSize; + CHAR16 *Description; + CHAR16 *FullOptionName; + CHAR16 *DevPathStr; + EFI_DEVICE_PATH_PROTOCOL *OptDevicePath; + + Description = BmGetBootDescription (GetDiskHandleByFsHandle(Handle)); + BootOptions = ReallocatePool ( + sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount), + sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCount + 1), + BootOptions + ); + ASSERT (BootOptions != NULL); + + if (Description != NULL && StrLen(Description) != 0) { + // Some descriptions have a space character at the end, strip it + StrStripTrailingSpaces(Description); + OptNameSize = StrLen(BootOpt->BootOptionFmt) + StrLen(Description); + } else { + OptNameSize = StrLen(BootOpt->BootOptionFmt) + StrLen(L"Unknown"); + } + + FullOptionName = AllocatePool(OptNameSize * sizeof(CHAR16)); + ASSERT (FullOptionName != NULL); + + UnicodeSPrint( + FullOptionName, + OptNameSize * sizeof(CHAR16), + BootOpt->BootOptionFmt, + Description ? Description : L"Unknown"); + + OptDevicePath = FileDevicePath (Handle, BootOpt->FileName); + ASSERT (OptDevicePath != NULL); + + DevPathStr = ConvertDevicePathToText(OptDevicePath, FALSE, FALSE); + + DEBUG ((EFI_D_INFO, "%a: Creating boot option:\n %s (%s)\n", __FUNCTION__, + FullOptionName, DevPathStr ? DevPathStr : L"")); + + if (DevPathStr) + FreePool(DevPathStr); + + Status = EfiBootManagerInitializeLoadOption ( + &BootOptions[(*BootOptionCount)++], + LoadOptionNumberUnassigned, + LoadOptionTypeBoot, + LOAD_OPTION_ACTIVE, + FullOptionName, + OptDevicePath, + NULL, + 0 + ); + ASSERT_EFI_ERROR (Status); + FreePool (FullOptionName); + FreePool (OptDevicePath); + + if (Description != NULL) + FreePool (Description); + + return BootOptions; +} + +/** + Check if the SimpleFileSystem handle is an EFI system Partition. + + @param FsHandle The handle with SimpleFileSystem. + + @retval TRUE FsHandle is an ESP. + @retval FALSE FsHandle is not a an ESP. + +**/ +BOOLEAN +IsEfiSysPartition ( + IN EFI_HANDLE FsHandle + ) +{ + EFI_STATUS Status; + EFI_PARTITION_INFO_PROTOCOL *PartitionInfo; + + // + // PartitionInfo protocol should be present if the SimpleFS protocol is present. + // + Status = gBS->HandleProtocol ( + FsHandle, + &gEfiPartitionInfoProtocolGuid, + (VOID**)&PartitionInfo + ); + + if (!EFI_ERROR (Status)) + return (PartitionInfo->System == 1); + + return FALSE; +} + +EFI_BOOT_MANAGER_LOAD_OPTION * +CheckIfFilesExistAndCreateBootOptions ( + IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions, + IN OUT UINTN *BootOptionCount, + IN EFI_HANDLE Handle, + IN CONST PRE_INSTALLED_BOOT_OPT *BootOptsArray, + IN CONST UINTN BootOptsCount, + IN CONST PRE_INSTALLED_BOOT_OPT *BootOptsArray2 OPTIONAL, + IN CONST UINTN BootOptsCount2 OPTIONAL +) +{ + EFI_STATUS Status; + UINTN OsIdx; + EFI_IMAGE_DOS_HEADER DosHeader; + EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData; + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; + + if (BootOptsArray2 != NULL) + ASSERT (BootOptsCount == BootOptsCount2); + + for (OsIdx = 0; OsIdx < BootOptsCount; OsIdx++) { + + Hdr.Union = &HdrData; + Status = BdsLibGetImageHeader ( + Handle, + BootOptsArray[OsIdx].FileName, + &DosHeader, + Hdr + ); + if (!EFI_ERROR (Status) && + EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Hdr.Pe32->FileHeader.Machine) && + Hdr.Pe32->OptionalHeader.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) { + BootOptions = CreatePreInstalledBootOption( + BootOptions, + BootOptionCount, + Handle, + &BootOptsArray[OsIdx] + ); + } else { + if (BootOptsArray2 == NULL) + continue; + + /* Shimx64.efi not found or any other error, try grubx64.efi */ + Hdr.Union = &HdrData; + Status = BdsLibGetImageHeader ( + Handle, + BootOptsArray2[OsIdx].FileName, + &DosHeader, + Hdr + ); + if (!EFI_ERROR (Status) && + EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Hdr.Pe32->FileHeader.Machine) && + Hdr.Pe32->OptionalHeader.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) { + BootOptions = CreatePreInstalledBootOption( + BootOptions, + BootOptionCount, + Handle, + &BootOptsArray2[OsIdx] + ); + } + } + + } // for OsIdx + + return BootOptions; +} + +EFI_BOOT_MANAGER_LOAD_OPTION * +BmEnumeratePreInstalledBootOptions ( + IN OUT UINTN *BootOptionCount + ) +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *Handles; + EFI_BLOCK_IO_PROTOCOL *BlkIo; + UINTN Index; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; + CHAR16 *DevPathStr; + + ASSERT (BootOptionCount != NULL); + + BootOptions = NULL; + DEBUG ((EFI_D_INFO, "%a\n", __FUNCTION__)); + // + // Parse gEfiPartTypeSystemPartGuid handles + // + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSimpleFileSystemProtocolGuid, + NULL, + &HandleCount, + &Handles + ); + for (Index = 0; Index < HandleCount; Index++) { + + DevPathStr = ConvertDevicePathToText(DevicePathFromHandle (Handles[Index]), FALSE, FALSE); + + DEBUG ((EFI_D_INFO, "%a: Processing file system:\n %s\n", __FUNCTION__, + DevPathStr ? DevPathStr : L"")); + + if (DevPathStr) + FreePool(DevPathStr); + + /* Skip non-ESP */ + if (!IsEfiSysPartition(Handles[Index])) { + DEBUG ((EFI_D_INFO, "%a: Skipping, not an ESP\n", __FUNCTION__)); + continue; + } + + // + // Skip the removable media, except if DTS. + // + BootOptions = CheckIfFilesExistAndCreateBootOptions ( + BootOptions, + BootOptionCount, + Handles[Index], + &DtsBootOpt, + 1, + NULL, + 0 + ); + + Status = gBS->HandleProtocol ( + Handles[Index], + &gEfiBlockIoProtocolGuid, + (VOID **) &BlkIo + ); + if (!EFI_ERROR (Status) && BlkIo->Media->RemovableMedia) { + DEBUG ((EFI_D_INFO, "%a: Skipping, media removable\n", __FUNCTION__)); + continue; + } + + // Custom boot managers first + BootOptions = CheckIfFilesExistAndCreateBootOptions ( + BootOptions, + BootOptionCount, + Handles[Index], + PreInstalledBootOpts, + ARRAY_SIZE (PreInstalledBootOpts), + NULL, + 0 + ); + + // Linux installations with shim and GRUB or GRUB only + BootOptions = CheckIfFilesExistAndCreateBootOptions ( + BootOptions, + BootOptionCount, + Handles[Index], + PreInstalledBootOptsShim, + ARRAY_SIZE (PreInstalledBootOptsShim), + PreInstalledBootOptsGrub, + ARRAY_SIZE (PreInstalledBootOptsGrub) + ); + + } // for Handles + + if (HandleCount != 0) { + FreePool (Handles); + } + + return BootOptions; +} + /** Emuerate all possible bootable medias in the following order: 1. Removable BlockIo - The boot option only points to the removable media @@ -2198,11 +2950,16 @@ BmEnumerateBootOptions ( UINTN Removable; UINTN Index; CHAR16 *Description; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; ASSERT (BootOptionCount != NULL); *BootOptionCount = 0; - BootOptions = NULL; + + if (PcdGetBool (PcdCreatePreInstalledBootOptions)) + BootOptions = BmEnumeratePreInstalledBootOptions(BootOptionCount); + else + BootOptions = NULL; // // Parse removable block io followed by fixed block io @@ -2233,6 +2990,12 @@ BmEnumerateBootOptions ( continue; } + // Skip devices that do not have an EFI volume + DevicePath = DevicePathFromHandle (Handles[Index]); + if (BdsLibGetBootableHandle (DevicePath) == NULL) { + continue; + } + // // Skip the fixed block io then the removable block io // @@ -2562,7 +3325,7 @@ BmRegisterBootManagerMenu ( LoadOptionNumberUnassigned, LoadOptionTypeBoot, LOAD_OPTION_CATEGORY_APP | LOAD_OPTION_ACTIVE | LOAD_OPTION_HIDDEN, - (Description != NULL) ? Description : L"Boot Manager Menu", + L"Setup", DevicePath, NULL, 0 diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmBootDescription.c b/MdeModulePkg/Library/UefiBootManagerLib/BmBootDescription.c index 030b2ee3ec..403a3768ce 100644 --- a/MdeModulePkg/Library/UefiBootManagerLib/BmBootDescription.c +++ b/MdeModulePkg/Library/UefiBootManagerLib/BmBootDescription.c @@ -15,7 +15,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #define PRODUCT_IDENTIFICATION_LENGTH 16 CONST UINT16 mBmUsbLangId = 0x0409; // English -CHAR16 mBmUefiPrefix[] = L"UEFI "; +//CHAR16 mBmUefiPrefix[] = L"UEFI "; LIST_ENTRY mPlatformBootDescriptionHandlers = INITIALIZE_LIST_HEAD_VARIABLE (mPlatformBootDescriptionHandlers); @@ -182,16 +182,16 @@ BmGetDescriptionFromDiskInfo ( } Length = Index; - Description[Length++] = L' '; + //Description[Length++] = L' '; - for (Index = 0; Index + 1 < SerialNumberLength; Index += 2) { - Description[Length + Index] = (CHAR16)IdentifyData.SerialNo[Index + 1]; - Description[Length + Index + 1] = (CHAR16)IdentifyData.SerialNo[Index]; - } + //for (Index = 0; Index + 1 < SerialNumberLength; Index += 2) { + // Description[Length + Index] = (CHAR16)IdentifyData.SerialNo[Index + 1]; + // Description[Length + Index + 1] = (CHAR16)IdentifyData.SerialNo[Index]; + //} - Length += Index; + //Length += Index; Description[Length++] = L'\0'; - ASSERT (Length == ModelNameLength + SerialNumberLength + 2); + //ASSERT (Length == ModelNameLength + SerialNumberLength + 2); BmEliminateExtraSpaces (Description); } @@ -316,15 +316,16 @@ BmGetUsbDescription ( Product = &NullChar; } - Status = UsbIo->UsbGetStringDescriptor ( - UsbIo, - mBmUsbLangId, - DevDesc.StrSerialNumber, - &SerialNumber - ); - if (EFI_ERROR (Status)) { - SerialNumber = &NullChar; - } + //Status = UsbIo->UsbGetStringDescriptor ( + // UsbIo, + // mBmUsbLangId, + // DevDesc.StrSerialNumber, + // &SerialNumber + // ); + //if (EFI_ERROR (Status)) { + // SerialNumber = &NullChar; + //} + SerialNumber = &NullChar; if ((Manufacturer == &NullChar) && (Product == &NullChar) && @@ -655,19 +656,19 @@ BmGetNvmeDescription ( *(Char++) = (CHAR16)ControllerData.Mn[Index]; } - *(Char++) = L' '; - for (Index = 0; Index < ARRAY_SIZE (ControllerData.Sn); Index++) { - *(Char++) = (CHAR16)ControllerData.Sn[Index]; - } - - *(Char++) = L' '; - UnicodeValueToStringS ( - Char, - sizeof (CHAR16) * (MAXIMUM_VALUE_CHARACTERS + 1), - 0, - DevicePath.NvmeNamespace->NamespaceId, - 0 - ); + //*(Char++) = L' '; + //for (Index = 0; Index < ARRAY_SIZE (ControllerData.Sn); Index++) { + // *(Char++) = (CHAR16)ControllerData.Sn[Index]; + //} + + //*(Char++) = L' '; + //UnicodeValueToStringS ( + // Char, + // sizeof (CHAR16) * (MAXIMUM_VALUE_CHARACTERS + 1), + // 0, + // DevicePath.NvmeNamespace->NamespaceId, + // 0 + // ); BmEliminateExtraSpaces (Description); } @@ -817,10 +818,12 @@ BmGetBootDescription ( // Avoid description confusion between UEFI & Legacy boot option by adding "UEFI " prefix // ONLY for core provided boot description handler. // - Temp = AllocatePool (StrSize (DefaultDescription) + sizeof (mBmUefiPrefix)); + //Temp = AllocatePool (StrSize (DefaultDescription) + sizeof (mBmUefiPrefix)); + Temp = AllocatePool (StrSize (DefaultDescription)); ASSERT (Temp != NULL); - StrCpyS (Temp, (StrSize (DefaultDescription) + sizeof (mBmUefiPrefix)) / sizeof (CHAR16), mBmUefiPrefix); - StrCatS (Temp, (StrSize (DefaultDescription) + sizeof (mBmUefiPrefix)) / sizeof (CHAR16), DefaultDescription); + //StrCpyS (Temp, (StrSize (DefaultDescription) + sizeof (mBmUefiPrefix)) / sizeof (CHAR16), mBmUefiPrefix); + //StrCatS (Temp, (StrSize (DefaultDescription) + sizeof (mBmUefiPrefix)) / sizeof (CHAR16), DefaultDescription); + StrCpyS (Temp, StrSize (DefaultDescription) / sizeof (CHAR16), DefaultDescription); FreePool (DefaultDescription); DefaultDescription = Temp; break; diff --git a/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h b/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h index b7dfe2a7e0..33d1534815 100644 --- a/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h +++ b/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h @@ -42,7 +42,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include +#include #include #include #include diff --git a/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf b/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf index 2fc0a80a4e..2655d5c5e4 100644 --- a/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf +++ b/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf @@ -86,6 +86,7 @@ gEfiDiskInfoScsiInterfaceGuid ## SOMETIMES_CONSUMES ## GUID gEfiDiskInfoSdMmcInterfaceGuid ## SOMETIMES_CONSUMES ## GUID gEfiDiskInfoUfsInterfaceGuid ## SOMETIMES_CONSUMES ## GUID + gEfiPartTypeSystemPartGuid ## CONSUMES ## GUID [Protocols] gEfiPciRootBridgeIoProtocolGuid ## CONSUMES @@ -111,6 +112,7 @@ gEfiRamDiskProtocolGuid ## SOMETIMES_CONSUMES gEfiDeferredImageLoadProtocolGuid ## SOMETIMES_CONSUMES gEdkiiPlatformBootManagerProtocolGuid ## SOMETIMES_CONSUMES + gEfiPartitionInfoProtocolGuid ## SOMETIMES_CONSUMES [Pcd] gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange ## SOMETIMES_CONSUMES @@ -120,3 +122,4 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdDriverHealthConfigureForm ## SOMETIMES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdMaxRepairCount ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdCreatePreInstalledBootOptions ## CONSUMES diff --git a/MdeModulePkg/Logo/Logo.c b/MdeModulePkg/Logo/Logo.c index 8ab874d2da..4be9b3c4c9 100644 --- a/MdeModulePkg/Logo/Logo.c +++ b/MdeModulePkg/Logo/Logo.c @@ -13,6 +13,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include +#include typedef struct { EFI_IMAGE_ID ImageId; @@ -56,7 +58,12 @@ GetImage ( OUT INTN *OffsetY ) { - UINT32 Current; + UINT32 Current; + UINTN GopBltSize; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt; + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS BmpAddr; + UINT32 BmpSize; if ((Instance == NULL) || (Image == NULL) || (Attribute == NULL) || (OffsetX == NULL) || (OffsetY == NULL)) @@ -70,6 +77,33 @@ GetImage ( } (*Instance)++; + + Status = ParseBootLogo (&BmpAddr, &BmpSize); + if (!EFI_ERROR (Status)) { + // Logo from CBMEM + *Attribute = EdkiiPlatformLogoDisplayAttributeCenter; + *OffsetX = 0; + *OffsetY = 0; + GopBltSize = 0; + Blt = NULL; + + Status = TranslateBmpToGopBlt ( + (void*) BmpAddr, + BmpSize, + &Blt, + &GopBltSize, + (UINTN*) &(Image->Height), + (UINTN*) &(Image->Width)); + + if (!EFI_ERROR (Status)) { + Image->Bitmap = Blt; + return Status; + } + + DEBUG ((DEBUG_ERROR, "Failed to translate logo image: %r\n", Status)); + } + + // No or bad logo in CBMEM, fallback to builtin *Attribute = mLogos[Current].Attribute; *OffsetX = mLogos[Current].OffsetX; *OffsetY = mLogos[Current].OffsetY; diff --git a/MdeModulePkg/Logo/LogoDxe.inf b/MdeModulePkg/Logo/LogoDxe.inf index 41215d25d8..cd8ac8e2dc 100644 --- a/MdeModulePkg/Logo/LogoDxe.inf +++ b/MdeModulePkg/Logo/LogoDxe.inf @@ -34,6 +34,7 @@ Logo.idf [Packages] + DasharoPayloadPkg/DasharoPayloadPkg.dec MdeModulePkg/MdeModulePkg.dec MdePkg/MdePkg.dec @@ -41,6 +42,8 @@ UefiBootServicesTableLib UefiDriverEntryPoint DebugLib + BlParseLib + BmpSupportLib [Protocols] gEfiHiiDatabaseProtocolGuid ## CONSUMES diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec index a2cd83345f..f69068683c 100644 --- a/MdeModulePkg/MdeModulePkg.dec +++ b/MdeModulePkg/MdeModulePkg.dec @@ -1598,6 +1598,14 @@ # @Prompt Maximum Number of PEI Reset Filters, Reset Notifications or Reset Handlers. gEfiMdeModulePkgTokenSpaceGuid.PcdMaximumPeiResetNotifies|0x10|UINT32|0x0000010A + ## Whether to report support of FMP capsules in OsIndicationSupport.

+ # This PCD indicates if support of FMP capsules should be advertised.
+ # TRUE - support of FMP capsules is advertised.
+ # FALSE - support of FMP capsules is not advertised.
+ # If platform does not use this feature, this PCD should be set to FALSE.

+ # @Prompt Enable advertising support of FMP capsules. + gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleFmpSupport|FALSE|BOOLEAN|0x00000028 + ## Capsule On Disk is to deliver capsules via files on Mass Storage device.

# This PCD indicates if the Capsule On Disk is supported.
# TRUE - Capsule On Disk is supported.
@@ -1678,6 +1686,8 @@ # @Prompt Boot Discovery Policy gEfiMdeModulePkgTokenSpaceGuid.PcdBootDiscoveryPolicy|2|UINT32|0x4000000f + gEfiMdeModulePkgTokenSpaceGuid.PcdDetectPs2KbOnCmdAck|TRUE|BOOLEAN|0x40000010 + [PcdsFixedAtBuild.AARCH64, PcdsPatchableInModule.AARCH64] gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiExposedTableVersions|0x20|UINT32|0x0001004c @@ -2167,6 +2177,13 @@ # @Prompt The value is use for Usb Network rate limiting supported. gEfiMdeModulePkgTokenSpaceGuid.PcdUsbNetworkRateLimitingFactor|100|UINT32|0x10000028 + ## Controls whether to scan ESP partitions to detect pre-installed OSes and create boot options + # from it. + # TRUE - Create boot options for pre-installed OSes.
+ # FALSE - Do not create boot options for pre-installed OSes. + # @Prompt Create boot options for pre-installed OSes. + gEfiMdeModulePkgTokenSpaceGuid.PcdCreatePreInstalledBootOptions|FALSE|BOOLEAN|0x0001007a + [PcdsPatchableInModule] ## Specify memory size with page number for PEI code when # Loading Module at Fixed Address feature is enabled. diff --git a/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c b/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c index e09bc9b704..83b81002c2 100644 --- a/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c +++ b/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c @@ -705,16 +705,13 @@ AddTableToList ( // if ((UINT64)(UINTN)AcpiTableInstance->Facs3 < BASE_4GB) { AcpiTableInstance->Fadt3->FirmwareCtrl = (UINT32)(UINTN)AcpiTableInstance->Facs3; - ZeroMem (&AcpiTableInstance->Fadt3->XFirmwareCtrl, sizeof (UINT64)); - } else { - Buffer64 = (UINT64)(UINTN)AcpiTableInstance->Facs3; - CopyMem ( - &AcpiTableInstance->Fadt3->XFirmwareCtrl, - &Buffer64, - sizeof (UINT64) - ); - AcpiTableInstance->Fadt3->FirmwareCtrl = 0; } + Buffer64 = (UINT64) (UINTN) AcpiTableInstance->Facs3; + CopyMem ( + &AcpiTableInstance->Fadt3->XFirmwareCtrl, + &Buffer64, + sizeof (UINT64) + ); if ((UINT64)(UINTN)AcpiTableInstance->Dsdt3 < BASE_4GB) { AcpiTableInstance->Fadt3->Dsdt = (UINT32)(UINTN)AcpiTableInstance->Dsdt3; @@ -863,16 +860,13 @@ AddTableToList ( // if ((UINT64)(UINTN)AcpiTableInstance->Facs3 < BASE_4GB) { AcpiTableInstance->Fadt3->FirmwareCtrl = (UINT32)(UINTN)AcpiTableInstance->Facs3; - ZeroMem (&AcpiTableInstance->Fadt3->XFirmwareCtrl, sizeof (UINT64)); - } else { - Buffer64 = (UINT64)(UINTN)AcpiTableInstance->Facs3; - CopyMem ( - &AcpiTableInstance->Fadt3->XFirmwareCtrl, - &Buffer64, - sizeof (UINT64) - ); - AcpiTableInstance->Fadt3->FirmwareCtrl = 0; } + Buffer64 = (UINT64) (UINTN) AcpiTableInstance->Facs3; + CopyMem ( + &AcpiTableInstance->Fadt3->XFirmwareCtrl, + &Buffer64, + sizeof (UINT64) + ); // // Checksum FADT table diff --git a/MdeModulePkg/Universal/BdsDxe/BdsDxe.inf b/MdeModulePkg/Universal/BdsDxe/BdsDxe.inf index 5bac635def..95d2607b8d 100644 --- a/MdeModulePkg/Universal/BdsDxe/BdsDxe.inf +++ b/MdeModulePkg/Universal/BdsDxe/BdsDxe.inf @@ -97,6 +97,7 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable ## SOMETIMES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdTestKeyUsed ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleOnDiskSupport ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleFmpSupport ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdPlatformRecoverySupport ## CONSUMES [Depex] diff --git a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c index 72de8d3211..5b0d8c681e 100644 --- a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c +++ b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c @@ -318,10 +318,25 @@ BdsWait ( { EFI_STATUS Status; UINT16 TimeoutRemain; + UINT16 BootTimeout; + UINTN DataSize; DEBUG ((DEBUG_INFO, "[Bds]BdsWait ...Zzzzzzzzzzzz...\n")); - TimeoutRemain = PcdGet16 (PcdPlatformBootTimeOut); + DataSize = sizeof(BootTimeout); + Status = gRT->GetVariable( + EFI_TIME_OUT_VARIABLE_NAME, + &gEfiGlobalVariableGuid, + NULL, + &DataSize, + &BootTimeout + ); + if (EFI_ERROR (Status)) { + BootTimeout = PcdGet16 (PcdPlatformBootTimeOut); + } + + TimeoutRemain = BootTimeout; + while (TimeoutRemain != 0) { DEBUG ((DEBUG_INFO, "[Bds]BdsWait(%d)..Zzzz...\n", (UINTN)TimeoutRemain)); PlatformBootManagerWaitCallback (TimeoutRemain); @@ -354,7 +369,7 @@ BdsWait ( // Note that the (TimeoutRemain == 0) condition excludes // PcdPlatformBootTimeOut=0xFFFF, and that's deliberate. // - if ((PcdGet16 (PcdPlatformBootTimeOut) != 0) && (TimeoutRemain == 0)) { + if ((BootTimeout != 0) && (TimeoutRemain == 0)) { PlatformBootManagerWaitCallback (0); } @@ -580,6 +595,10 @@ BdsFormalizeOSIndicationVariable ( OsIndicationSupport |= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED; } + if (PcdGetBool (PcdCapsuleFmpSupport)) { + OsIndicationSupport |= EFI_OS_INDICATIONS_FMP_CAPSULE_SUPPORTED; + } + Status = gRT->SetVariable ( EFI_OS_INDICATIONS_SUPPORT_VARIABLE_NAME, &gEfiGlobalVariableGuid, @@ -696,6 +715,7 @@ BdsEntry ( HotkeyTriggered = NULL; Status = EFI_SUCCESS; BootSuccess = FALSE; + BootTimeOut = 0xFFFF; // // Insert the performance probe @@ -746,22 +766,29 @@ BdsEntry ( InitializeHwErrRecSupport (); - // - // Initialize L"Timeout" EFI global variable. - // - BootTimeOut = PcdGet16 (PcdPlatformBootTimeOut); - if (BootTimeOut != 0xFFFF) { - // - // If time out value equal 0xFFFF, no need set to 0xFFFF to variable area because UEFI specification - // define same behavior between no value or 0xFFFF value for L"Timeout". - // - BdsDxeSetVariableAndReportStatusCodeOnError ( - EFI_TIME_OUT_VARIABLE_NAME, - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - sizeof (UINT16), - &BootTimeOut - ); + DataSize = sizeof(BootTimeOut); + Status = gRT->GetVariable( + EFI_TIME_OUT_VARIABLE_NAME, + &gEfiGlobalVariableGuid, + NULL, + &DataSize, + &BootTimeOut + ); + if (EFI_ERROR (Status)) { + BootTimeOut = PcdGet16 (PcdPlatformBootTimeOut); + if (BootTimeOut != 0xFFFF) { + // + // If time out value equal 0xFFFF, no need set to 0xFFFF to variable area because UEFI specification + // define same behavior between no value or 0xFFFF value for L"Timeout". + // + BdsDxeSetVariableAndReportStatusCodeOnError ( + EFI_TIME_OUT_VARIABLE_NAME, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + sizeof (UINT16), + &BootTimeOut + ); + } } // diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleReset.c b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleReset.c index f3cb6d5f8b..1636021573 100644 --- a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleReset.c +++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleReset.c @@ -24,5 +24,9 @@ IsPersistAcrossResetCapsuleSupported ( VOID ) { + if (!DasharoCapsulesCanPersistAcrossReset()) { + return FALSE; + } + return FeaturePcdGet (PcdSupportUpdateCapsuleReset); } diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf index 601eada170..d3763e5c2f 100644 --- a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf +++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf @@ -51,6 +51,7 @@ [Packages] MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec + DasharoModulePkg/DasharoModulePkg.dec [LibraryClasses] UefiBootServicesTableLib @@ -64,6 +65,7 @@ PrintLib BaseMemoryLib CacheMaintenanceLib + DasharoVariablesLib [LibraryClasses.X64] UefiLib diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c index f8047c23e1..05ba90a52f 100644 --- a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c +++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c @@ -183,6 +183,16 @@ UpdateCapsule ( return EFI_UNSUPPORTED; } + if (NeedReset) { + // + // Request going into update mode after reboot to have full access to flash. + // + Status = DasharoEnableFUM (); + if (EFI_ERROR (Status)) { + return Status; + } + } + CapsuleCacheWriteBack (ScatterGatherList); // diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.h b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.h index c671626f2f..8e33bf5524 100644 --- a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.h +++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.h @@ -30,6 +30,7 @@ #include #include #include +#include /** Create the variable to save the base address of page table and stack diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c index e2d779c783..adb14a7568 100644 --- a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c +++ b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c @@ -113,8 +113,8 @@ TERMINAL_DEV mTerminalDevTemplate = { TERMINAL_CONSOLE_MODE_DATA mTerminalConsoleModeData[] = { { 80, 25 }, - { 80, 50 }, - { 100, 31 }, +// { 80, 50 }, +// { 100, 31 }, // // New modes can be added here. // diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf index b2a8aeba85..fe7fce636f 100644 --- a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf +++ b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf @@ -42,6 +42,7 @@ [Packages] MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec + DasharoModulePkg/DasharoModulePkg.dec [LibraryClasses] DevicePathLib @@ -96,3 +97,6 @@ [UserExtensions.TianoCore."ExtraFiles"] TerminalDxeExtra.uni + +[Depex] + gDasharoSerialRedirectionPolicyGuid diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c index a7b7dc743a..46b9897ae3 100644 --- a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c +++ b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c @@ -810,85 +810,6 @@ ConvertStatementToMenu ( } } -/** - 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. - - If String is NULL, then ASSERT (). - - @param String The input string to be counted. - - @return Storage space for the input string. - -**/ -UINTN -GetStringWidth ( - IN CHAR16 *String - ) -{ - UINTN Index; - UINTN Count; - UINTN IncrementValue; - - ASSERT (String != NULL); - 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 - ) - { - } - - // - // We hit the null-terminator, we now have a count - // - if (String[Index] == 0) { - break; - } - - // - // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed - // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2) - // - if (String[Index] == NARROW_CHAR) { - // - // Skip to the next character - // - Index++; - IncrementValue = 1; - } else { - // - // Skip to the next character - // - Index++; - IncrementValue = 2; - } - } while (String[Index] != 0); - - // - // Increment by one to include the null-terminator in the size - // - Count++; - - return Count * sizeof (CHAR16); -} - /** Base on the input option string to update the skip value for a menu option. diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h index 6e2670428e..e8771ef353 100644 --- a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h +++ b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h @@ -422,23 +422,6 @@ CompareHiiValue ( IN EFI_HII_HANDLE HiiHandle OPTIONAL ); -/** - Draw a pop up windows based on the dimension, number of lines and - strings specified. - - @param RequestedWidth The width of the pop-up. - @param NumberOfLines The number of lines. - @param ... A series of text strings that displayed in the pop-up. - -**/ -VOID -EFIAPI -CreateMultiStringPopUp ( - IN UINTN RequestedWidth, - IN UINTN NumberOfLines, - ... - ); - /** Will copy LineWidth amount of a string in the OutputString buffer and return the number of CHAR16 characters that were copied into the OutputString buffer. @@ -482,27 +465,6 @@ GetToken ( IN EFI_HII_HANDLE HiiHandle ); -/** - 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. - - If String is NULL, then ASSERT (). - - @param String The input string to be counted. - - @return Storage space for the input string. - -**/ -UINTN -GetStringWidth ( - IN CHAR16 *String - ); - /** This routine reads a numeric value from the user input. @@ -535,22 +497,6 @@ ReadString ( IN OUT CHAR16 *StringPtr ); -/** - Draw a pop up windows based on the dimension, number of lines and - strings specified. - - @param RequestedWidth The width of the pop-up. - @param NumberOfLines The number of lines. - @param Marker The variable argument list for the list of string to be printed. - -**/ -VOID -CreateSharedPopUp ( - IN UINTN RequestedWidth, - IN UINTN NumberOfLines, - IN VA_LIST Marker - ); - /** Wait for a key to be pressed by user. diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c b/MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c index f70feeb55f..783672468d 100644 --- a/MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c +++ b/MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c @@ -760,6 +760,10 @@ GetNumericInput ( switch (Key.UnicodeChar) { case '+': case '-': + if (ManualInput && ((NumericOp->Flags & EFI_IFR_DISPLAY) == EFI_IFR_DISPLAY_UINT_DEC)) { + UpdateStatusBar(INPUT_ERROR, TRUE); + break; + } if (ManualInput && IntInput) { // // In Manual input mode, check whether input the negative flag. diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c b/MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c index 0d4cfa4cf0..415a8ffbe8 100644 --- a/MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c +++ b/MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c @@ -570,137 +570,6 @@ PrintFormattedNumber ( return EFI_SUCCESS; } -/** - Draw a pop up windows based on the dimension, number of lines and - strings specified. - - @param RequestedWidth The width of the pop-up. - @param NumberOfLines The number of lines. - @param Marker The variable argument list for the list of string to be printed. - -**/ -VOID -CreateSharedPopUp ( - IN UINTN RequestedWidth, - IN UINTN NumberOfLines, - IN VA_LIST Marker - ) -{ - UINTN Index; - UINTN Count; - CHAR16 Character; - UINTN Start; - UINTN End; - UINTN Top; - UINTN Bottom; - CHAR16 *String; - UINTN DimensionsWidth; - UINTN DimensionsHeight; - - DimensionsWidth = gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn; - DimensionsHeight = gStatementDimensions.BottomRow - gStatementDimensions.TopRow; - - gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ()); - - if ((RequestedWidth + 2) > DimensionsWidth) { - RequestedWidth = DimensionsWidth - 2; - } - - // - // Subtract the PopUp width from total Columns, allow for one space extra on - // each end plus a border. - // - Start = (DimensionsWidth - RequestedWidth - 2) / 2 + gStatementDimensions.LeftColumn + 1; - End = Start + RequestedWidth + 1; - - Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + gStatementDimensions.TopRow - 1; - Bottom = Top + NumberOfLines + 2; - - Character = BOXDRAW_DOWN_RIGHT; - PrintCharAt (Start, Top, Character); - Character = BOXDRAW_HORIZONTAL; - for (Index = Start; Index + 2 < End; Index++) { - PrintCharAt ((UINTN)-1, (UINTN)-1, Character); - } - - Character = BOXDRAW_DOWN_LEFT; - PrintCharAt ((UINTN)-1, (UINTN)-1, Character); - Character = BOXDRAW_VERTICAL; - - Count = 0; - for (Index = Top; Index + 2 < Bottom; Index++, Count++) { - String = VA_ARG (Marker, CHAR16 *); - - // - // This will clear the background of the line - we never know who might have been - // here before us. This differs from the next clear in that it used the non-reverse - // video for normal printing. - // - if (GetStringWidth (String) / 2 > 1) { - ClearLines (Start, End, Index + 1, Index + 1, GetPopupColor ()); - } - - // - // Passing in a space results in the assumption that this is where typing will occur - // - if (String[0] == L' ') { - ClearLines (Start + 1, End - 1, Index + 1, Index + 1, GetPopupInverseColor ()); - } - - // - // Passing in a NULL results in a blank space - // - if (String[0] == CHAR_NULL) { - ClearLines (Start, End, Index + 1, Index + 1, GetPopupColor ()); - } - - PrintStringAt ( - ((DimensionsWidth - GetStringWidth (String) / 2) / 2) + gStatementDimensions.LeftColumn + 1, - Index + 1, - String - ); - gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ()); - PrintCharAt (Start, Index + 1, Character); - PrintCharAt (End - 1, Index + 1, Character); - } - - Character = BOXDRAW_UP_RIGHT; - PrintCharAt (Start, Bottom - 1, Character); - Character = BOXDRAW_HORIZONTAL; - for (Index = Start; Index + 2 < End; Index++) { - PrintCharAt ((UINTN)-1, (UINTN)-1, Character); - } - - Character = BOXDRAW_UP_LEFT; - PrintCharAt ((UINTN)-1, (UINTN)-1, Character); -} - -/** - Draw a pop up windows based on the dimension, number of lines and - strings specified. - - @param RequestedWidth The width of the pop-up. - @param NumberOfLines The number of lines. - @param ... A series of text strings that displayed in the pop-up. - -**/ -VOID -EFIAPI -CreateMultiStringPopUp ( - IN UINTN RequestedWidth, - IN UINTN NumberOfLines, - ... - ) -{ - VA_LIST Marker; - - VA_START (Marker, NumberOfLines); - - CreateSharedPopUp (RequestedWidth, NumberOfLines, Marker); - - VA_END (Marker); -} - /** Process nothing. diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c index 2f7b11b1aa..0dcfa0a7dc 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c +++ b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c @@ -53,7 +53,7 @@ BOOLEAN gResetRequiredSystemLevel = FALSE; BOOLEAN gExitRequired; BOOLEAN gFlagReconnect; BOOLEAN gCallbackReconnect; -BROWSER_SETTING_SCOPE gBrowserSettingScope = FormSetLevel; +BROWSER_SETTING_SCOPE gBrowserSettingScope = SystemLevel; BOOLEAN mBrowserScopeFirstSet = TRUE; EXIT_HANDLER ExitHandlerFunction = NULL; FORM_BROWSER_FORMSET *mSystemLevelFormSet; diff --git a/MdePkg/Include/Uefi/UefiSpec.h b/MdePkg/Include/Uefi/UefiSpec.h index 7fcdeab93e..0945cb93e8 100644 --- a/MdePkg/Include/Uefi/UefiSpec.h +++ b/MdePkg/Include/Uefi/UefiSpec.h @@ -1852,7 +1852,7 @@ EFI_STATUS #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_SYSTEM_TABLE_REVISION EFI_2_80_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') diff --git a/MdePkg/Library/DxeHstiLib/HstiDxe.c b/MdePkg/Library/DxeHstiLib/HstiDxe.c index d895599cd4..e5aae13931 100644 --- a/MdePkg/Library/DxeHstiLib/HstiDxe.c +++ b/MdePkg/Library/DxeHstiLib/HstiDxe.c @@ -105,7 +105,7 @@ InternalHstiFindAip ( &InformationBlock, &InformationBlockSize ); - if (EFI_ERROR (Status)) { + if (EFI_ERROR (Status) || InformationBlockSize == 0) { continue; } diff --git a/MdePkg/Library/PeiHobLib/HobLib.c b/MdePkg/Library/PeiHobLib/HobLib.c index 4fecd19660..5f25e76aa5 100644 --- a/MdePkg/Library/PeiHobLib/HobLib.c +++ b/MdePkg/Library/PeiHobLib/HobLib.c @@ -42,7 +42,11 @@ GetHobList ( Status = PeiServicesGetHobList (&HobList); ASSERT_EFI_ERROR (Status); + // Workaround for when AcpiTimerLibConstructor() is invoked before loading + // BlSupportPei. +#if 0 ASSERT (HobList != NULL); +#endif return HobList; } diff --git a/MdePkg/Library/UefiLib/UefiLibPrint.c b/MdePkg/Library/UefiLib/UefiLibPrint.c index 39edeb7283..ab7bc25632 100644 --- a/MdePkg/Library/UefiLib/UefiLibPrint.c +++ b/MdePkg/Library/UefiLib/UefiLibPrint.c @@ -545,8 +545,9 @@ InternalPrintGraphic ( } else { PrintNum = 0; } - - FreePool (RowInfoArray); + if (RowInfoArray != NULL) { + FreePool (RowInfoArray); + } FreePool (Blt); return PrintNum; diff --git a/NetworkPkg/Library/DxeNetLib/DxeNetLib.c b/NetworkPkg/Library/DxeNetLib/DxeNetLib.c index fd4a9e15a8..3b93d6c9e8 100644 --- a/NetworkPkg/Library/DxeNetLib/DxeNetLib.c +++ b/NetworkPkg/Library/DxeNetLib/DxeNetLib.c @@ -2641,6 +2641,13 @@ NetLibDetectMediaWaitTimeout ( &DataSize ); if (!EFI_ERROR (Status)) { + if (DataSize == 0) { + if (MediaInfo != NULL) { + FreePool (MediaInfo); + } + return EFI_NOT_FOUND; + } + *MediaState = MediaInfo->MediaState; FreePool (MediaInfo); if ((*MediaState != EFI_NOT_READY) || (Timeout < MEDIA_STATE_DETECT_TIME_INTERVAL)) { @@ -2704,6 +2711,12 @@ NetLibDetectMediaWaitTimeout ( &DataSize ); if (!EFI_ERROR (Status)) { + if (DataSize == 0) { + if (MediaInfo != NULL) { + FreePool (MediaInfo); + } + return EFI_NOT_FOUND; + } *MediaState = MediaInfo->MediaState; FreePool (MediaInfo); } else { diff --git a/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrImpl.c b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrImpl.c index 4c5460b65c..b6140605b4 100644 --- a/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrImpl.c +++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrImpl.c @@ -830,8 +830,12 @@ WifiMgrGetLinkState ( gBS->RestoreTPL (OldTpl); - CopyMem (LinkState, UndiState, sizeof (EFI_ADAPTER_INFO_MEDIA_STATE)); - FreePool (UndiState); + if (DataSize != 0) { + CopyMem (LinkState, UndiState, sizeof (EFI_ADAPTER_INFO_MEDIA_STATE)); + FreePool (UndiState); + } else { + return EFI_NOT_FOUND; + } return EFI_SUCCESS; } diff --git a/OvmfPkg/Include/Dsc/OvmfTpmComponentsDxe.dsc.inc b/OvmfPkg/Include/Dsc/OvmfTpmComponentsDxe.dsc.inc index 75ae09571e..e8743b08b8 100644 --- a/OvmfPkg/Include/Dsc/OvmfTpmComponentsDxe.dsc.inc +++ b/OvmfPkg/Include/Dsc/OvmfTpmComponentsDxe.dsc.inc @@ -15,6 +15,10 @@ NULL|SecurityPkg/Library/HashInstanceLibSm3/HashInstanceLibSm3.inf } SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf + SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDxe.inf { + + Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12DeviceLibDTpm.inf + } !if $(TPM1_ENABLE) == TRUE SecurityPkg/Tcg/TcgDxe/TcgDxe.inf { @@ -25,4 +29,10 @@ TpmPlatformHierarchyLib|SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLib/PeiDxeTpmPlatformHierarchyLib.inf } +!if $(OPAL_PASSWORD_ENABLE) == TRUE + SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf { + + Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterDxe.inf + } +!endif !endif diff --git a/OvmfPkg/Include/Dsc/OvmfTpmComponentsPei.dsc.inc b/OvmfPkg/Include/Dsc/OvmfTpmComponentsPei.dsc.inc index fa486eed82..3383528036 100644 --- a/OvmfPkg/Include/Dsc/OvmfTpmComponentsPei.dsc.inc +++ b/OvmfPkg/Include/Dsc/OvmfTpmComponentsPei.dsc.inc @@ -23,4 +23,7 @@ TpmPlatformHierarchyLib|SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLib/PeiDxeTpmPlatformHierarchyLib.inf } +!if $(OPAL_PASSWORD_ENABLE) == TRUE + SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf +!endif !endif diff --git a/OvmfPkg/Include/Dsc/OvmfTpmDefines.dsc.inc b/OvmfPkg/Include/Dsc/OvmfTpmDefines.dsc.inc index a65564d8d9..fcafe5b992 100644 --- a/OvmfPkg/Include/Dsc/OvmfTpmDefines.dsc.inc +++ b/OvmfPkg/Include/Dsc/OvmfTpmDefines.dsc.inc @@ -2,7 +2,7 @@ # SPDX-License-Identifier: BSD-2-Clause-Patent ## - DEFINE TPM2_ENABLE = FALSE + DEFINE TPM2_ENABLE = TRUE # has no effect unless TPM2_ENABLE == TRUE DEFINE TPM1_ENABLE = TRUE diff --git a/OvmfPkg/Include/Dsc/OvmfTpmLibs.dsc.inc b/OvmfPkg/Include/Dsc/OvmfTpmLibs.dsc.inc index b97244695b..0353508877 100644 --- a/OvmfPkg/Include/Dsc/OvmfTpmLibs.dsc.inc +++ b/OvmfPkg/Include/Dsc/OvmfTpmLibs.dsc.inc @@ -9,6 +9,7 @@ !endif Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf Tcg2PhysicalPresenceLib|OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf + Tcg2PhysicalPresencePlatformLib|OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.inf Tcg2PpVendorLib|SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.inf !else Tcg2PhysicalPresenceLib|OvmfPkg/Library/Tcg2PhysicalPresenceLibNull/DxeTcg2PhysicalPresenceLib.inf @@ -26,7 +27,7 @@ [LibraryClasses.common.PEIM] !if $(TPM2_ENABLE) == TRUE - BaseCryptLib|CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLibMbedTls/PeiCryptLib.inf !if $(TPM1_ENABLE) == TRUE Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12DeviceLibDTpm.inf !endif diff --git a/OvmfPkg/Include/Fdf/OvmfTpmDxe.fdf.inc b/OvmfPkg/Include/Fdf/OvmfTpmDxe.fdf.inc index 7fc2bf8590..6ae6606f0b 100644 --- a/OvmfPkg/Include/Fdf/OvmfTpmDxe.fdf.inc +++ b/OvmfPkg/Include/Fdf/OvmfTpmDxe.fdf.inc @@ -7,6 +7,10 @@ INF SecurityPkg/Tcg/TcgDxe/TcgDxe.inf !endif INF SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf +INF SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDxe.inf INF SecurityPkg/Tcg/Tcg2PlatformDxe/Tcg2PlatformDxe.inf INF SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf +!if $(OPAL_PASSWORD_ENABLE) == TRUE +INF SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf +!endif !endif diff --git a/OvmfPkg/Include/Fdf/OvmfTpmPei.fdf.inc b/OvmfPkg/Include/Fdf/OvmfTpmPei.fdf.inc index 9f8b9bdd5b..c9993e3005 100644 --- a/OvmfPkg/Include/Fdf/OvmfTpmPei.fdf.inc +++ b/OvmfPkg/Include/Fdf/OvmfTpmPei.fdf.inc @@ -12,4 +12,7 @@ INF OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf !endif INF SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf INF SecurityPkg/Tcg/Tcg2PlatformPei/Tcg2PlatformPei.inf +!if $(OPAL_PASSWORD_ENABLE) == TRUE +INF SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.inf +!endif !endif diff --git a/OvmfPkg/Include/Library/Tcg2PhysicalPresencePlatformLib.h b/OvmfPkg/Include/Library/Tcg2PhysicalPresencePlatformLib.h new file mode 100644 index 0000000000..76bfd2a87f --- /dev/null +++ b/OvmfPkg/Include/Library/Tcg2PhysicalPresencePlatformLib.h @@ -0,0 +1,29 @@ +/** @file + Returns the platform specific Physical Presence configuration. + + Copyright (C) 2020 9elements GmbH + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef __TCG2_PHYSICAL_PRESENCE_PLATFORM_LIB_H__ +#define __TCG2_PHYSICAL_PRESENCE_PLATFORM_LIB_H__ + +#include + +/** + Reads the platform specific Physical Presence configuration. + + @param[out] The Config structure to read to. + @param[out] The PPIinMMIO is True when the PPI is in MMIO memory space + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_PROTOCOL_ERROR Invalid fw_cfg entry size. +**/ +EFI_STATUS +TpmPPIPlatformReadConfig ( + OUT QEMU_FWCFG_TPM_CONFIG *Config, + OUT BOOLEAN *PPIinMMIO + ); + +#endif diff --git a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c index d9f61757cf..e8aa3af1ad 100644 --- a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c +++ b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c @@ -14,6 +14,12 @@ #include #include #include +#include +#include + +EFI_GUID mBootMenuFile = { + 0xEEC25BDC, 0x67F2, 0x4D95, { 0xB1, 0xD5, 0xF8, 0x1B, 0x20, 0x39, 0xD1, 0x1D } +}; // // Global data @@ -82,11 +88,154 @@ InstallDevicePathCallback ( VOID ); +EFI_DEVICE_PATH * +FvFilePath ( + EFI_GUID *FileGuid + ) +{ + + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode; + + EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid); + + Status = gBS->HandleProtocol ( + gImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &LoadedImage + ); + ASSERT_EFI_ERROR (Status); + return AppendDevicePathNode ( + DevicePathFromHandle (LoadedImage->DeviceHandle), + (EFI_DEVICE_PATH_PROTOCOL *) &FileNode + ); +} + +/** + Create one boot option for BootManagerMenuApp. + + @param FileGuid Input file guid for the BootManagerMenuApp. + @param Description Description of the BootManagerMenuApp boot option. + @param Position Position of the new load option to put in the ****Order variable. + @param IsBootCategory Whether this is a boot category. + + + @retval OptionNumber Return the option number info. + +**/ +UINTN +RegisterBootManagerMenuAppBootOption ( + EFI_GUID *FileGuid, + CHAR16 *Description, + UINTN Position, + BOOLEAN IsBootCategory + ) +{ + EFI_STATUS Status; + EFI_BOOT_MANAGER_LOAD_OPTION NewOption; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN OptionNumber; + + DevicePath = FvFilePath (FileGuid); + Status = EfiBootManagerInitializeLoadOption ( + &NewOption, + LoadOptionNumberUnassigned, + LoadOptionTypeBoot, + IsBootCategory ? LOAD_OPTION_ACTIVE : LOAD_OPTION_CATEGORY_APP, + Description, + DevicePath, + NULL, + 0 + ); + ASSERT_EFI_ERROR (Status); + FreePool (DevicePath); + + Status = EfiBootManagerAddLoadOptionVariable (&NewOption, Position); + ASSERT_EFI_ERROR (Status); + + OptionNumber = NewOption.OptionNumber; + + EfiBootManagerFreeLoadOption (&NewOption); + + return OptionNumber; +} + +/** + Check if it's a Device Path pointing to BootManagerMenuApp. + + @param DevicePath Input device path. + + @retval TRUE The device path is BootManagerMenuApp File Device Path. + @retval FALSE The device path is NOT BootManagerMenuApp File Device Path. +**/ +BOOLEAN +IsBootManagerMenuAppFilePath ( + EFI_DEVICE_PATH_PROTOCOL *DevicePath +) +{ + EFI_HANDLE FvHandle; + VOID *NameGuid; + EFI_STATUS Status; + + Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &DevicePath, &FvHandle); + if (!EFI_ERROR (Status)) { + NameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) DevicePath); + if (NameGuid != NULL) { + return CompareGuid (NameGuid, &mBootMenuFile); + } + } + + return FALSE; +} + +/** + Return the boot option number to the BootManagerMenuApp. + + If not found it in the current boot option, create a new one. + + @retval OptionNumber Return the boot option number to the BootManagerMenuApp. + +**/ +UINTN +GetBootManagerMenuAppOption ( + VOID + ) +{ + UINTN BootOptionCount; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; + UINTN Index; + UINTN OptionNumber; + + OptionNumber = 0; + + BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot); + + for (Index = 0; Index < BootOptionCount; Index++) { + if (IsBootManagerMenuAppFilePath (BootOptions[Index].FilePath)) { + OptionNumber = BootOptions[Index].OptionNumber; + break; + } + } + + EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); + + if (Index >= BootOptionCount) { + // + // If not found the BootManagerMenuApp, create it. + // + OptionNumber = (UINT16) RegisterBootManagerMenuAppBootOption (&mBootMenuFile, L"UEFI BootManagerMenuApp", (UINTN) -1, FALSE); + } + + return OptionNumber; +} + VOID PlatformRegisterFvBootOption ( EFI_GUID *FileGuid, CHAR16 *Description, - UINT32 Attributes + UINT32 Attributes, + BOOLEAN BootNow ) { EFI_STATUS Status; @@ -127,6 +276,9 @@ PlatformRegisterFvBootOption ( ASSERT_EFI_ERROR (Status); FreePool (DevicePath); + if (BootNow) + EfiBootManagerBoot (&NewOption); + BootOptions = EfiBootManagerGetLoadOptions ( &BootOptionCount, LoadOptionTypeBoot @@ -147,6 +299,72 @@ PlatformRegisterFvBootOption ( EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); } +VOID +PlatformUnregisterFvBootOption ( + EFI_GUID *FileGuid, + CHAR16 *Description, + UINT32 Attributes + ) +{ + EFI_STATUS Status; + INTN OptionIndex; + EFI_BOOT_MANAGER_LOAD_OPTION NewOption; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; + UINTN BootOptionCount; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + Status = gBS->HandleProtocol ( + gImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **)&LoadedImage + ); + ASSERT_EFI_ERROR (Status); + + EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid); + DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle); + ASSERT (DevicePath != NULL); + DevicePath = AppendDevicePathNode ( + DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *)&FileNode + ); + ASSERT (DevicePath != NULL); + + Status = EfiBootManagerInitializeLoadOption ( + &NewOption, + LoadOptionNumberUnassigned, + LoadOptionTypeBoot, + Attributes, + Description, + DevicePath, + NULL, + 0 + ); + ASSERT_EFI_ERROR (Status); + FreePool (DevicePath); + + BootOptions = EfiBootManagerGetLoadOptions ( + &BootOptionCount, + LoadOptionTypeBoot + ); + + OptionIndex = EfiBootManagerFindLoadOption ( + &NewOption, + BootOptions, + BootOptionCount + ); + + if (OptionIndex >= 0 && OptionIndex < BootOptionCount) { + Status = EfiBootManagerDeleteLoadOptionVariable (BootOptions[OptionIndex].OptionNumber, + BootOptions[OptionIndex].OptionType); + ASSERT_EFI_ERROR (Status); + } + + EfiBootManagerFreeLoadOption (&NewOption); + EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); +} + /** Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options whose device paths do not resolve exactly to an FvFile in the system. @@ -341,6 +559,7 @@ PlatformRegisterOptionsAndKeys ( EFI_INPUT_KEY F2; EFI_INPUT_KEY Esc; EFI_BOOT_MANAGER_LOAD_OPTION BootOption; + UINTN OptionNumber; // // Register ENTER as CONTINUE key @@ -359,11 +578,12 @@ PlatformRegisterOptionsAndKeys ( Esc.UnicodeChar = CHAR_NULL; Status = EfiBootManagerGetBootManagerMenu (&BootOption); ASSERT_EFI_ERROR (Status); + OptionNumber = GetBootManagerMenuAppOption (); Status = EfiBootManagerAddKeyOptionVariable ( NULL, - (UINT16)BootOption.OptionNumber, + (UINT16)OptionNumber, 0, - &F2, + &Esc, NULL ); ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED); @@ -371,7 +591,7 @@ PlatformRegisterOptionsAndKeys ( NULL, (UINT16)BootOption.OptionNumber, 0, - &Esc, + &F2, NULL ); ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED); @@ -426,7 +646,7 @@ PlatformBootManagerBeforeConsole ( EFI_HANDLE Handle; EFI_STATUS Status; UINT16 FrontPageTimeout; - RETURN_STATUS PcdStatus; + UINTN DataSize; DEBUG ((DEBUG_INFO, "PlatformBootManagerBeforeConsole\n")); InstallDevicePathCallback (); @@ -502,29 +722,37 @@ PlatformBootManagerBeforeConsole ( XenDetected () ? gXenPlatformConsole : gPlatformConsole ); - FrontPageTimeout = GetFrontPageTimeoutFromQemu (); - PcdStatus = PcdSet16S (PcdPlatformBootTimeOut, FrontPageTimeout); - ASSERT_RETURN_ERROR (PcdStatus); - // - // Reflect the PCD in the standard Timeout variable. - // - Status = gRT->SetVariable ( + DataSize = sizeof(FrontPageTimeout); + Status = gRT->GetVariable( EFI_TIME_OUT_VARIABLE_NAME, &gEfiGlobalVariableGuid, - (EFI_VARIABLE_NON_VOLATILE | - EFI_VARIABLE_BOOTSERVICE_ACCESS | - EFI_VARIABLE_RUNTIME_ACCESS), - sizeof FrontPageTimeout, + NULL, + &DataSize, &FrontPageTimeout ); - DEBUG (( - EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE, - "%a: SetVariable(%s, %u): %r\n", - __func__, - EFI_TIME_OUT_VARIABLE_NAME, - FrontPageTimeout, - Status - )); + if (EFI_ERROR (Status)) { + FrontPageTimeout = GetFrontPageTimeoutFromQemu (); + // + // Reflect the PCD in the standard Timeout variable. + // + Status = gRT->SetVariable ( + EFI_TIME_OUT_VARIABLE_NAME, + &gEfiGlobalVariableGuid, + (EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS), + sizeof FrontPageTimeout, + &FrontPageTimeout + ); + DEBUG (( + EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE, + "%a: SetVariable(%s, %u): %r\n", + __FUNCTION__, + EFI_TIME_OUT_VARIABLE_NAME, + FrontPageTimeout, + Status + )); + } if (!FeaturePcdGet (PcdBootRestrictToFirmware)) { PlatformRegisterOptionsAndKeys (); @@ -698,6 +926,7 @@ PrepareLpcBridgeDevicePath ( EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + EFI_GUID TerminalTypeGuid; CHAR16 *DevPathStr; DevicePath = NULL; @@ -736,6 +965,10 @@ PrepareLpcBridgeDevicePath ( DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode ); + + TerminalTypeGuid = gEfiTtyTermGuid; + CopyGuid (&gTerminalTypeDeviceNode.Guid, &TerminalTypeGuid); + DevicePath = AppendDevicePathNode ( DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode @@ -1775,9 +2008,18 @@ PlatformBootManagerAfterConsole ( ) { EFI_BOOT_MODE BootMode; + BOOLEAN NetBootEnabled; + UINTN VarSize; + EFI_STATUS Status; DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole\n")); + // This is probably the earliest we can print this, as before the console is + // not ready yet. + Print(L"F2 to enter Setup\n"); + Print(L"ESC to enter Boot Manager Menu\n"); + Print(L"ENTER to boot directly\n"); + if (PcdGetBool (PcdOvmfFlashVariablesEnable)) { DEBUG (( DEBUG_INFO, @@ -1834,13 +2076,51 @@ PlatformBootManagerAfterConsole ( EfiBootManagerRefreshAllBootOption (); } + VarSize = sizeof (NetBootEnabled); + Status = gRT->GetVariable ( + DASHARO_VAR_NETWORK_BOOT, + &gDasharoSystemFeaturesGuid, + NULL, + &VarSize, + &NetBootEnabled + ); + + // + // Register iPXE + // + if ((Status != EFI_NOT_FOUND) && (VarSize == sizeof(NetBootEnabled))) { + if (NetBootEnabled) { + DEBUG((DEBUG_INFO, "Registering iPXE boot option by variable\n")); + PlatformRegisterFvBootOption (PcdGetPtr (PcdiPXEFile), + (CHAR16 *) PcdGetPtr(PcdiPXEOptionName), + LOAD_OPTION_ACTIVE, + FALSE); + } else { + DEBUG((DEBUG_INFO, "Unregistering iPXE boot option by variable\n")); + PlatformUnregisterFvBootOption (PcdGetPtr (PcdiPXEFile), + (CHAR16 *) PcdGetPtr(PcdiPXEOptionName), + LOAD_OPTION_ACTIVE); + } + } else if ((Status == EFI_NOT_FOUND) && FixedPcdGetBool(PcdDefaultNetworkBootEnable)) { + DEBUG((DEBUG_INFO, "Registering iPXE boot option by policy\n")); + PlatformRegisterFvBootOption (PcdGetPtr (PcdiPXEFile), + (CHAR16 *) PcdGetPtr(PcdiPXEOptionName), + LOAD_OPTION_ACTIVE, + FALSE); + } else { + DEBUG((DEBUG_INFO, "Unregistering iPXE boot option\n")); + PlatformUnregisterFvBootOption (PcdGetPtr (PcdiPXEFile), + (CHAR16 *) PcdGetPtr(PcdiPXEOptionName), + LOAD_OPTION_ACTIVE); + } // // Register UEFI Shell // PlatformRegisterFvBootOption ( &gUefiShellFileGuid, - L"EFI Internal Shell", - LOAD_OPTION_ACTIVE + L"UEFI Shell", + LOAD_OPTION_ACTIVE, + FALSE ); // @@ -1849,7 +2129,8 @@ PlatformBootManagerAfterConsole ( PlatformRegisterFvBootOption ( &gGrubFileGuid, L"Grub Bootloader", - LOAD_OPTION_ACTIVE + LOAD_OPTION_ACTIVE, + FALSE ); RemoveStaleFvFileOptions (); @@ -1977,8 +2258,22 @@ PlatformBootManagerWaitCallback ( EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black; EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White; UINT16 TimeoutInitial; + UINTN DataSize; + EFI_STATUS Status; + + DEBUG ((EFI_D_INFO, "[Bds]BdsWait ...Zzzzzzzzzzzz...\n")); - TimeoutInitial = PcdGet16 (PcdPlatformBootTimeOut); + DataSize = sizeof (TimeoutInitial); + Status = gRT->GetVariable( + EFI_TIME_OUT_VARIABLE_NAME, + &gEfiGlobalVariableGuid, + NULL, + &DataSize, + &TimeoutInitial + ); + if (EFI_ERROR (Status)) { + TimeoutInitial = PcdGet16 (PcdPlatformBootTimeOut); + } // // If PcdPlatformBootTimeOut is set to zero, then we consider diff --git a/OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf b/OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf index c6ffc1ed9e..497125a114 100644 --- a/OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf +++ b/OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf @@ -33,6 +33,8 @@ OvmfPkg/OvmfPkg.dec SecurityPkg/SecurityPkg.dec ShellPkg/ShellPkg.dec + DasharoPayloadPkg/DasharoPayloadPkg.dec + DasharoModulePkg/DasharoModulePkg.dec [LibraryClasses] BaseLib @@ -63,6 +65,9 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId gUefiOvmfPkgTokenSpaceGuid.PcdBootRestrictToFirmware gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiS3Enable + gDasharoPayloadPkgTokenSpaceGuid.PcdiPXEFile + gDasharoPayloadPkgTokenSpaceGuid.PcdiPXEOptionName + gDasharoSystemFeaturesTokenSpaceGuid.PcdDefaultNetworkBootEnable gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate ## CONSUMES gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits ## CONSUMES @@ -87,3 +92,5 @@ gRootBridgesConnectedEventGroupGuid gUefiShellFileGuid gGrubFileGuid + gEfiTtyTermGuid + gDasharoSystemFeaturesGuid diff --git a/OvmfPkg/Library/QemuParseLib/QemuParseLib.c b/OvmfPkg/Library/QemuParseLib/QemuParseLib.c new file mode 100644 index 0000000000..c09524d040 --- /dev/null +++ b/OvmfPkg/Library/QemuParseLib/QemuParseLib.c @@ -0,0 +1,119 @@ +/** @file + Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + + Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+ SPDX-License-Identifier: BSD-3-Clause +**/ + +#include +#include +#include + +/** + Find the SMM store information + + @param SMMSTOREInfo Pointer to the SMMSTORE_INFO structure + + @retval RETURN_SUCCESS Successfully find the SMM store buffer information. + @retval RETURN_NOT_FOUND Failed to find the SMM store buffer information . + +**/ +RETURN_STATUS +EFIAPI +ParseSMMSTOREInfo ( + OUT SMMSTORE_INFO *SMMSTOREInfo + ) +{ + return RETURN_UNSUPPORTED; +} + +/** + Find the Tcg Physical Presence store information + + @param PPIInfo Pointer to the TCG_PHYSICAL_PRESENCE_INFO structure + + @retval RETURN_SUCCESS Successfully find the SMM store buffer information. + @retval RETURN_NOT_FOUND Failed to find the SMM store buffer information . + +**/ +RETURN_STATUS +EFIAPI +ParseTPMPPIInfo ( + OUT TCG_PHYSICAL_PRESENCE_INFO *PPIInfo + ) +{ + return RETURN_UNSUPPORTED; +} + +/** + Acquire Vboot recovery information from coreboot + + @param RecoveryCode Recovery reason code, zero if not in recovery mode. + @param RecoveryReason Why are we in recovery boot as a string. + + @retval RETURN_SUCCESS Successfully found VBoot data. + @retval RETURN_NOT_FOUND Failed to find VBoot data. + +**/ +RETURN_STATUS +EFIAPI +ParseVBootWorkbuf ( + OUT UINT8 *RecoveryCode, + OUT CONST CHAR8 **RecoveryReason + ) +{ + return RETURN_UNSUPPORTED; +} + +/** + Parse the coreboot timestamps + + @retval RETURN_SUCCESS Successfully find the timestamps information. + @retval RETURN_NOT_FOUND Failed to find the tiemstamps information . + +**/ +RETURN_STATUS +EFIAPI +ParseTimestampTable ( + OUT FIRMWARE_SEC_PERFORMANCE *Performance + ) +{ + return RETURN_UNSUPPORTED; +} + +/** + Parse update capsules passed in by coreboot + + @param CapsuleCallback The callback routine invoked for each capsule. + + @retval RETURN_SUCCESS Successfully parsed capsules. + @retval RETURN_NOT_FOUND coreboot table is missing. +**/ +RETURN_STATUS +EFIAPI +ParseCapsules ( + IN BL_CAPSULE_CALLBACK CapsuleCallback + ) +{ + return RETURN_UNSUPPORTED; +} + +/** + Acquire boot logo from coreboot + + @param BmpAddress Pointer to the bitmap file + @param BmpSize Size of the image + + @retval RETURN_SUCCESS Successfully find the boot logo. + @retval RETURN_NOT_FOUND Failed to find the boot logo. +**/ +RETURN_STATUS +EFIAPI +ParseBootLogo ( + OUT UINT64 *BmpAddress, + OUT UINT32 *BmpSize + ) +{ + return RETURN_UNSUPPORTED; +} diff --git a/OvmfPkg/Library/QemuParseLib/QemuParseLib.inf b/OvmfPkg/Library/QemuParseLib/QemuParseLib.inf new file mode 100644 index 0000000000..a6d6f14fb8 --- /dev/null +++ b/OvmfPkg/Library/QemuParseLib/QemuParseLib.inf @@ -0,0 +1,32 @@ +## @file +# Coreboot Table Parse Library. +# +# Copyright (c) 2014, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = QemuParseLib + FILE_GUID = 49EDFC9E-5945-4386-9C0B-C9B60CD45BB1 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = BlParseLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + QemuParseLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + DasharoPayloadPkg/DasharoPayloadPkg.dec + +[LibraryClasses] + BaseLib diff --git a/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.c b/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.c index 4038020251..e5e5783492 100644 --- a/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.c +++ b/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.c @@ -26,56 +26,29 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include #include -#include #include +#include #include #include #include #include +#include #include #define CONFIRM_BUFFER_SIZE 4096 +/* Wait 3 minutes for user input */ +#define TIMEOUT (1000 * 1000 * 60 * 3) + EFI_HII_HANDLE mTcg2PpStringPackHandle; #define TPM_PPI_FLAGS (QEMU_TPM_PPI_FUNC_ALLOWED_USR_REQ) STATIC volatile QEMU_TPM_PPI *mPpi; -/** - Reads QEMU PPI config from fw_cfg. - - @param[out] The Config structure to read to. - - @retval EFI_SUCCESS Operation completed successfully. - @retval EFI_PROTOCOL_ERROR Invalid fw_cfg entry size. -**/ -STATIC -EFI_STATUS -QemuTpmReadConfig ( - OUT QEMU_FWCFG_TPM_CONFIG *Config - ) -{ - EFI_STATUS Status; - FIRMWARE_CONFIG_ITEM FwCfgItem; - UINTN FwCfgSize; - - Status = QemuFwCfgFindFile ("etc/tpm/config", &FwCfgItem, &FwCfgSize); - if (EFI_ERROR (Status)) { - return Status; - } - - if (FwCfgSize != sizeof (*Config)) { - return EFI_PROTOCOL_ERROR; - } - - QemuFwCfgSelectItem (FwCfgItem); - QemuFwCfgReadBytes (sizeof (*Config), Config); - return EFI_SUCCESS; -} - /** Initializes QEMU PPI memory region. @@ -90,6 +63,7 @@ QemuTpmInitPPI ( { EFI_STATUS Status; QEMU_FWCFG_TPM_CONFIG Config; + BOOLEAN PPIinMMIO; EFI_PHYSICAL_ADDRESS PpiAddress64; EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; UINTN Idx; @@ -98,7 +72,7 @@ QemuTpmInitPPI ( return EFI_SUCCESS; } - Status = QemuTpmReadConfig (&Config); + Status = TpmPPIPlatformReadConfig (&Config, &PPIinMMIO); if (EFI_ERROR (Status)) { return Status; } @@ -123,15 +97,23 @@ QemuTpmInitPPI ( ASSERT_EFI_ERROR (Status); goto InvalidPpiAddress; } - - if (!EFI_ERROR (Status) && - ((Descriptor.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo) && - (Descriptor.GcdMemoryType != EfiGcdMemoryTypeNonExistent))) - { - DEBUG ((DEBUG_ERROR, "[TPM2PP] mPpi has an invalid memory type\n")); - goto InvalidPpiAddress; + if (PPIinMMIO) { + if (!EFI_ERROR (Status) && + (Descriptor.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo && + Descriptor.GcdMemoryType != EfiGcdMemoryTypeNonExistent)) { + DEBUG ((DEBUG_ERROR, "[TPM2PP] mPpi has an invalid memory type\n")); + goto InvalidPpiAddress; + } + } else { + if (!EFI_ERROR (Status) && + (Descriptor.GcdMemoryType != EfiGcdMemoryTypeReserved && + Descriptor.GcdMemoryType != EfiGcdMemoryTypeSystemMemory)) { + DEBUG ((DEBUG_ERROR, "[TPM2PP] mPpi has an invalid memory type\n")); + goto InvalidPpiAddress; + } } + for (Idx = 0; Idx < ARRAY_SIZE (mPpi->Func); Idx++) { mPpi->Func[Idx] = 0; } @@ -156,6 +138,7 @@ QemuTpmInitPPI ( mPpi->NextStep = TCG2_PHYSICAL_PRESENCE_NO_ACTION; } + WriteBackDataCacheRange((VOID*)mPpi, sizeof(QEMU_TPM_PPI)); return EFI_SUCCESS; InvalidPpiAddress: @@ -359,12 +342,16 @@ Tcg2ExecutePhysicalPresence ( STATIC BOOLEAN Tcg2ReadUserKey ( - IN BOOLEAN CautionKey + IN BOOLEAN CautionKey, + IN UINTN Timeout ) { EFI_STATUS Status; EFI_INPUT_KEY Key; UINT16 InputKey; + UINTN Delay; + + Delay = Timeout / 50; InputKey = 0; do { @@ -383,7 +370,13 @@ Tcg2ReadUserKey ( InputKey = Key.ScanCode; } } - } while (InputKey == 0); + gBS->Stall (50); + Delay--; + } while (InputKey == 0 && Delay > 0); + + if (Delay == 0) { + return FALSE; + } if (InputKey != SCAN_ESC) { return TRUE; @@ -652,7 +645,7 @@ Tcg2UserConfirm ( FreePool (ConfirmText); HiiRemovePackages (mTcg2PpStringPackHandle); - if (Tcg2ReadUserKey (CautionKey)) { + if (Tcg2ReadUserKey (CautionKey, TIMEOUT)) { return TRUE; } @@ -755,6 +748,8 @@ Tcg2ExecutePendingTpmRequest ( mPpi->LastRequest = mPpi->Request; mPpi->Request = TCG2_PHYSICAL_PRESENCE_NO_ACTION; mPpi->RequestParameter = 0; + + WriteBackDataCacheRange((VOID*)mPpi, sizeof(QEMU_TPM_PPI)); return; } @@ -785,6 +780,7 @@ Tcg2ExecutePendingTpmRequest ( mPpi->RequestParameter = 0; if (mPpi->Response == TCG_PP_OPERATION_RESPONSE_USER_ABORT) { + WriteBackDataCacheRange((VOID*)mPpi, sizeof(QEMU_TPM_PPI)); return; } @@ -809,11 +805,13 @@ Tcg2ExecutePendingTpmRequest ( if (mPpi->Request != TCG2_PHYSICAL_PRESENCE_NO_ACTION) { break; } - + WriteBackDataCacheRange((VOID*)mPpi, sizeof(QEMU_TPM_PPI)); return; } Print (L"Rebooting system to make TPM2 settings in effect\n"); + WriteBackDataCacheRange((VOID*)mPpi, sizeof(QEMU_TPM_PPI)); + gBS->Stall(500000); gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); ASSERT (FALSE); } @@ -923,6 +921,38 @@ Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction ( mPpi->Request = OperationRequest; mPpi->RequestParameter = RequestParameter; + WriteBackDataCacheRange((VOID*)mPpi, sizeof(QEMU_TPM_PPI)); return TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS; } + +/** + Return TPM2 ManagementFlags set by PP interface. + + @retval ManagementFlags TPM2 Management Flags. +**/ +UINT32 +EFIAPI +Tcg2PhysicalPresenceLibGetManagementFlags ( + VOID + ) +{ + EFI_STATUS Status; + EFI_TCG2_PHYSICAL_PRESENCE_FLAGS PpiFlags; + UINTN DataSize; + + DEBUG ((EFI_D_INFO, "[TPM2] GetManagementFlags\n")); + + DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS); + Status = gRT->GetVariable ( + TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE, + &gEfiTcg2PhysicalPresenceGuid, + NULL, + &DataSize, + &PpiFlags + ); + if (EFI_ERROR (Status)) { + PpiFlags.PPFlags = PcdGet32(PcdTcg2PhysicalPresenceFlags); + } + return PpiFlags.PPFlags; +} diff --git a/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf b/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf index 5b5417c321..0595639d07 100644 --- a/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf +++ b/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf @@ -57,16 +57,20 @@ HobLib MemoryAllocationLib PrintLib - QemuFwCfgLib Tpm2CommandLib UefiBootManagerLib UefiBootServicesTableLib UefiLib UefiRuntimeServicesTableLib + Tcg2PhysicalPresencePlatformLib + CacheMaintenanceLib [Protocols] gEfiTcg2ProtocolGuid ## SOMETIMES_CONSUMES +[Pcd] + gEfiSecurityPkgTokenSpaceGuid.PcdTcg2PhysicalPresenceFlags ## SOMETIMES_CONSUMES + [Guids] ## SOMETIMES_CONSUMES ## HII gEfiTcg2PhysicalPresenceGuid diff --git a/OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.c b/OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.c new file mode 100644 index 0000000000..baef59d2ef --- /dev/null +++ b/OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.c @@ -0,0 +1,56 @@ +/** @file + Returns the platform specific configuration for the QEMU PPI. + + Caution: This module requires additional review when modified. + This driver will have external input - variable. + This external input must be validated carefully to avoid security issue. + +Copyright (C) 2018, Red Hat, Inc. +Copyright (c) 2018, IBM Corporation. All rights reserved.
+Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include + +#include +#include + +/** + Reads QEMU PPI config from fw_cfg. + + @param[out] The Config structure to read to. + @param[out] The PPIinMMIO is True when the PPI is in MMIO memory space + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_PROTOCOL_ERROR Invalid fw_cfg entry size. +**/ +EFI_STATUS +TpmPPIPlatformReadConfig ( + OUT QEMU_FWCFG_TPM_CONFIG *Config, + OUT BOOLEAN *PPIinMMIO + ) +{ + EFI_STATUS Status; + FIRMWARE_CONFIG_ITEM FwCfgItem; + UINTN FwCfgSize; + + Status = QemuFwCfgFindFile ("etc/tpm/config", &FwCfgItem, &FwCfgSize); + if (EFI_ERROR (Status)) { + return Status; + } + + if (FwCfgSize != sizeof (*Config)) { + return EFI_PROTOCOL_ERROR; + } + + QemuFwCfgSelectItem (FwCfgItem); + QemuFwCfgReadBytes (sizeof (*Config), Config); + + *PPIinMMIO = TRUE; + + return EFI_SUCCESS; +} diff --git a/OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.inf b/OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.inf new file mode 100644 index 0000000000..0ea0c08d4c --- /dev/null +++ b/OvmfPkg/Library/Tcg2PhysicalPresencePlatformLibQemu/DxeTcg2PhysicalPresencePlatformLib.inf @@ -0,0 +1,36 @@ +## @file +# Returns the platform specific configuration for the QEMU PPI. +# +# Caution: This module requires additional review when modified. +# This driver will have external input - variable. +# This external input must be validated carefully to avoid security issue. +# +# Copyright (C) 2018, Red Hat, Inc. +# Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Tcg2PhysicalPresencePlatformLibQemu + FILE_GUID = 9336E7F0-6CA1-4E6D-A0E9-DFE5F077AA02 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = Tcg2PhysicalPresencePlatformLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + DxeTcg2PhysicalPresencePlatformLib.c + +[Packages] + OvmfPkg/OvmfPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + QemuFwCfgLib diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc index 5e9eee628a..1b04a902ff 100644 --- a/OvmfPkg/OvmfPkgIa32X64.dsc +++ b/OvmfPkg/OvmfPkgIa32X64.dsc @@ -231,7 +231,7 @@ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf VariableFlashInfoLib|MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseVariableFlashInfoLib.inf - + BlParseLib|OvmfPkg/Library/QemuParseLib/QemuParseLib.inf # # Network libraries diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index bf4c7906c4..3710af15a0 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -29,8 +29,8 @@ # Defines for default states. These can be changed on the command line. # -D FLAG=VALUE # - DEFINE SECURE_BOOT_ENABLE = FALSE - DEFINE SMM_REQUIRE = FALSE + DEFINE SECURE_BOOT_ENABLE = TRUE + DEFINE SMM_REQUIRE = TRUE DEFINE SOURCE_DEBUG_ENABLE = FALSE DEFINE CC_MEASUREMENT_ENABLE = FALSE @@ -41,16 +41,37 @@ # DEFINE BUILD_SHELL = TRUE + DEFINE SATA_PASSWORD_ENABLE = TRUE + DEFINE OPAL_PASSWORD_ENABLE = TRUE + DEFINE DASHARO_SYSTEM_FEATURES_ENABLE = TRUE + DEFINE SETUP_PASSWORD_ENABLE = TRUE + # # Network definition # + DEFINE NETWORK_PXE_BOOT = FALSE + DEFINE NETWORK_ENABLE = FALSE DEFINE NETWORK_TLS_ENABLE = FALSE DEFINE NETWORK_IP6_ENABLE = FALSE + DEFINE NETWORK_IP4_ENABLE = TRUE + DEFINE NETWORK_LAN_ROM = FALSE + +!if $(NETWORK_PXE_BOOT) == TRUE + DEFINE NETWORK_SNP_ENABLE = TRUE DEFINE NETWORK_HTTP_BOOT_ENABLE = FALSE + DEFINE NETWORK_ISCSI_ENABLE = FALSE +!else + DEFINE NETWORK_SNP_ENABLE = FALSE + DEFINE NETWORK_HTTP_BOOT_ENABLE = TRUE DEFINE NETWORK_ALLOW_HTTP_CONNECTIONS = TRUE DEFINE NETWORK_ISCSI_ENABLE = TRUE +!endif !include NetworkPkg/NetworkDefines.dsc.inc + # + # IPXE support + # + DEFINE NETWORK_IPXE = TRUE # # Device drivers @@ -210,6 +231,7 @@ LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf CcProbeLib|OvmfPkg/Library/CcProbeLib/DxeCcProbeLib.inf !else + LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf CcProbeLib|MdePkg/Library/CcProbeLibNull/CcProbeLibNull.inf !endif CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf @@ -227,11 +249,14 @@ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf -!if $(NETWORK_TLS_ENABLE) == TRUE - OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf -!else - OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf + +!if $(OPAL_PASSWORD_ENABLE) == TRUE + TcgStorageCoreLib|SecurityPkg/Library/TcgStorageCoreLib/TcgStorageCoreLib.inf + TcgStorageOpalLib|SecurityPkg/Library/TcgStorageOpalLib/TcgStorageOpalLib.inf !endif + + MbedTlsLib|CryptoPkg/Library/MbedTlsLib/MbedTlsLib.inf + MbedTlsCrtLib|CryptoPkg/Library/MbedTlsCrtLib/MbedTlsCrtLib.inf RngLib|MdeModulePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf !if $(SECURE_BOOT_ENABLE) == TRUE @@ -248,6 +273,8 @@ VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf VariableFlashInfoLib|MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseVariableFlashInfoLib.inf + DasharoVariablesLib|DasharoModulePkg/Library/DasharoVariablesLib/DasharoVariablesLib.inf + BlParseLib|OvmfPkg/Library/QemuParseLib/QemuParseLib.inf # # Network libraries @@ -270,7 +297,7 @@ !include OvmfPkg/Include/Dsc/OvmfTpmLibs.dsc.inc [LibraryClasses.common] - BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLibMbedTls/BaseCryptLib.inf CcExitLib|OvmfPkg/Library/CcExitLib/CcExitLib.inf TdxLib|MdePkg/Library/TdxLib/TdxLib.inf TdxMailboxLib|OvmfPkg/Library/TdxMailboxLib/TdxMailboxLib.inf @@ -344,6 +371,10 @@ MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf CcProbeLib|OvmfPkg/Library/CcProbeLib/SecPeiCcProbeLib.inf +!if $(TPM2_ENABLE) == TRUE + Tcg2PhysicalPresenceLib|SecurityPkg/Library/PeiTcg2PhysicalPresenceLib/PeiTcg2PhysicalPresenceLib.inf +!endif + [LibraryClasses.common.DXE_CORE] HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf @@ -375,13 +406,14 @@ DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf !endif UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf - BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLibMbedTls/BaseCryptLib.inf PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/DxeQemuFwCfgS3LibFwCfg.inf VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf !if $(SMM_REQUIRE) == TRUE MmUnblockMemoryLib|MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.inf !endif + MbedTlsCrtLib|CryptoPkg/Library/MbedTlsCrtRuntimeLib/MbedTlsCrtRuntimeLib.inf [LibraryClasses.common.UEFI_DRIVER] PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf @@ -464,7 +496,7 @@ !if $(SOURCE_DEBUG_ENABLE) == TRUE DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgentLib.inf !endif - BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLibMbedTls/BaseCryptLib.inf PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf SmmCpuRendezvousLib|UefiCpuPkg/Library/SmmCpuRendezvousLib/SmmCpuRendezvousLib.inf @@ -509,6 +541,7 @@ [PcdsFixedAtBuild] gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1 + gEfiMdeModulePkgTokenSpaceGuid.PcdCreatePreInstalledBootOptions|TRUE !if $(SMM_REQUIRE) == FALSE gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE !endif @@ -618,6 +651,30 @@ # gUefiCpuPkgTokenSpaceGuid.PcdFirstTimeWakeUpAPsBySipi|FALSE + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowMenu|TRUE + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowSecurityMenu|TRUE + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowIntelMeMenu|TRUE + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowUsbMenu|TRUE + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowNetworkMenu|TRUE + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowChipsetMenu|TRUE + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowPowerMenu|TRUE + gDasharoSystemFeaturesTokenSpaceGuid.PcdPowerMenuShowFanCurve|TRUE + gDasharoSystemFeaturesTokenSpaceGuid.PcdDefaultPowerFailureState|0 + gDasharoSystemFeaturesTokenSpaceGuid.PcdDefaultNetworkBootEnable|FALSE + gDasharoSystemFeaturesTokenSpaceGuid.PcdDasharoEnterprise|TRUE + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowIommuOptions|TRUE + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowOcWdtOptions|TRUE + gDasharoSystemFeaturesTokenSpaceGuid.PcdPowerMenuShowSleepType|TRUE + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowPciMenu|TRUE + gDasharoSystemFeaturesTokenSpaceGuid.PcdPciMenuShowResizeableBars|TRUE + gDasharoSystemFeaturesTokenSpaceGuid.PcdPowerMenuShowBatteryThresholds|TRUE + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowMemoryMenu|TRUE + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowSerialPortMenu|TRUE + gDasharoSystemFeaturesTokenSpaceGuid.PcdSerialRedirectionDefaultState|TRUE + gDasharoSystemFeaturesTokenSpaceGuid.PcdSecurityShowWiFiBtOption|TRUE + gDasharoSystemFeaturesTokenSpaceGuid.PcdSecurityShowCameraOption|TRUE + + gEfiSecurityPkgTokenSpaceGuid.PcdSecureBootDefaultEnable|0 ################################################################################ # # Pcd Dynamic Section - list of all EDK II PCD Entries defined by this Platform @@ -650,7 +707,7 @@ gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Base|0x0 gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Size|0x800000000 - gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0 + gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|2 # Set video resolution for text setup. gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution|640 @@ -698,6 +755,10 @@ gEfiMdePkgTokenSpaceGuid.PcdFSBClock|1000000000 +!if $(USE_EDK2_PLATFORMS) == TRUE + gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask|1 +!endif + [PcdsDynamicHii] !include OvmfPkg/Include/Dsc/OvmfTpmPcdsHii.dsc.inc @@ -716,7 +777,7 @@ NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf NULL|OvmfPkg/IntelTdx/TdxHelperLib/SecTdxHelperLib.inf - BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SecCryptLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLibMbedTls/SecCryptLib.inf } # @@ -778,6 +839,10 @@ !include OvmfPkg/Include/Dsc/OvmfTpmComponentsPei.dsc.inc +!if $(SATA_PASSWORD_ENABLE) == TRUE + SecurityPkg/HddPassword/HddPasswordPei.inf +!endif + # # DXE Phase modules # @@ -804,6 +869,13 @@ !include OvmfPkg/Include/Dsc/OvmfTpmSecurityStub.dsc.inc } +!if $(SETUP_PASSWORD_ENABLE) == TRUE + DasharoModulePkg/UserAuthenticationDxe/UserAuthenticationDxe.inf { + + PlatformPasswordLib|DasharoModulePkg/Library/PlatformPasswordLibNull/PlatformPasswordLibNull.inf + } +!endif + MdeModulePkg/Universal/EbcDxe/EbcDxe.inf UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf @@ -855,13 +927,20 @@ MdeModulePkg/Application/UiApp/UiApp.inf { NULL|MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf + NULL|DasharoModulePkg/Library/DasharoSystemFeaturesUiLib/DasharoSystemFeaturesUiLib.inf NULL|MdeModulePkg/Library/BootManagerUiLib/BootManagerUiLib.inf NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerUiLib.inf + + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowMenu|$(DASHARO_SYSTEM_FEATURES_ENABLE) + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowSerialPortMenu|TRUE } OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.inf { NULL|OvmfPkg/Library/BlobVerifierLibNull/BlobVerifierLibNull.inf } + + MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuApp.inf + OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf OvmfPkg/Virtio10Dxe/Virtio10.inf OvmfPkg/VirtioBlkDxe/VirtioBlk.inf @@ -923,6 +1002,7 @@ # # SMBIOS Support # + MdeModulePkg/Universal/SmbiosMeasurementDxe/SmbiosMeasurementDxe.inf MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf { NULL|OvmfPkg/Library/SmbiosVersionLib/DetectSmbiosVersionLib.inf @@ -946,6 +1026,34 @@ OvmfPkg/VirtioNetDxe/VirtioNet.inf + +!if $(DASHARO_SYSTEM_FEATURES_ENABLE) == TRUE + DasharoModulePkg/DasharoBootPolicies/DasharoBootPolicies.inf +!if $(USE_EDK2_PLATFORMS) == TRUE + DasharoModulePkg/DasharoBootPoliciesVTd/DasharoBootPoliciesVTd.inf +!endif +!endif + + # + # Hash2 + # + SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.inf { + + BaseCryptLib|CryptoPkg/Library/BaseCryptLibMbedTls/BaseCryptLib.inf + } + + # + # PKCS7 Verification + # + SecurityPkg/Pkcs7Verify/Pkcs7VerifyDxe/Pkcs7VerifyDxe.inf + + # + # SD/eMMC Support + # + MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf + MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.inf + MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf + # # Usb Support # @@ -1001,6 +1109,8 @@ !if $(SECURE_BOOT_ENABLE) == TRUE SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf + SecurityPkg/EnrollFromDefaultKeysApp/EnrollFromDefaultKeysApp.inf + SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.inf OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.inf !endif @@ -1092,3 +1202,14 @@ # TPM support # !include OvmfPkg/Include/Dsc/OvmfTpmComponentsDxe.dsc.inc + +!if $(SATA_PASSWORD_ENABLE) == TRUE + SecurityPkg/HddPassword/HddPasswordDxe.inf +!endif + + CrScreenshotDxe/CrScreenshotDxe.inf { + + GCC:*_*_*_CC_FLAGS = -mmmx -msse + } + + DasharoPayloadPkg/ApuConfigurationUi/ApuConfigurationUi.inf diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf index f47ab1727e..a239411d67 100644 --- a/OvmfPkg/OvmfPkgX64.fdf +++ b/OvmfPkg/OvmfPkgX64.fdf @@ -190,6 +190,10 @@ INF FILE_GUID = $(UP_CPU_PEI_GUID) UefiCpuPkg/CpuMpPei/CpuMpPei.inf !include OvmfPkg/Include/Fdf/OvmfTpmPei.fdf.inc +!if $(SATA_PASSWORD_ENABLE) == TRUE +INF SecurityPkg/HddPassword/HddPasswordPei.inf +!endif + ################################################################################ [FV.DXEFV] @@ -272,6 +276,36 @@ INF OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf !if $(SECURE_BOOT_ENABLE) == TRUE INF SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf + INF SecurityPkg/EnrollFromDefaultKeysApp/EnrollFromDefaultKeysApp.inf + INF SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.inf + + # gDefaultKEKFileGuid + FILE FREEFORM = 6F64916E-9F7A-4C35-B952-CD041EFB05A3 { + SECTION RAW = DasharoPayloadPkg/SecureBootDefaultKeys/MicCorKEKCA2011_2011-06-24.crt + SECTION RAW = DasharoPayloadPkg/SecureBootDefaultKeys/microsoft_corporation_kek_2k_ca_2023.crt + SECTION UI = "DefaultKekCert" + } + + # gDefaultPKFileGuid + FILE FREEFORM = 85254EA7-4759-4FC4-82D4-5EED5FB0A4A0 { + SECTION RAW = DasharoPayloadPkg/SecureBootDefaultKeys/pk.crt + SECTION UI = "DefaultPkCert" + } + + # gDefaultdbFileGuid + FILE FREEFORM = C491D352-7623-4843-ACCC-2791A7574421 { + SECTION RAW = DasharoPayloadPkg/SecureBootDefaultKeys/MicWinProPCA2011_2011-10-19.crt + SECTION RAW = DasharoPayloadPkg/SecureBootDefaultKeys/MicCorUEFCA2011_2011-06-27.crt + SECTION RAW = DasharoPayloadPkg/SecureBootDefaultKeys/windows_uefi_ca_2023.crt + SECTION RAW = DasharoPayloadPkg/SecureBootDefaultKeys/microsoft_uefi_ca_2023.crt + SECTION UI = "DefaultDbCert" + } + + # gDefaultdbxFileGuid + FILE FREEFORM = 5740766A-718E-4DC0-9935-C36F7D3F884F { + SECTION RAW = DasharoPayloadPkg/SecureBootDefaultKeys/DBXUpdate.bin + SECTION UI = "DefaultDbxCert" + } !endif INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf @@ -284,6 +318,7 @@ INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf INF MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.inf INF MdeModulePkg/Universal/BdsDxe/BdsDxe.inf INF MdeModulePkg/Application/UiApp/UiApp.inf +INF MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuApp.inf INF OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.inf INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf @@ -308,6 +343,7 @@ INF MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf INF MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf INF OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf +INF MdeModulePkg/Universal/SmbiosMeasurementDxe/SmbiosMeasurementDxe.inf INF MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf INF OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf @@ -343,6 +379,41 @@ INF OvmfPkg/TdxDxe/TdxDxe.inf !include NetworkPkg/Network.fdf.inc INF OvmfPkg/VirtioNetDxe/VirtioNet.inf +# +# iPXE support +# +!if $(NETWORK_IPXE) == TRUE + # + # build system or user should put the ipxe.efi file here before EDK2 build + # + FILE FREEFORM = B68653C7-EEA1-4435-A199-A44F59E4476C { + SECTION PE32 = ipxe.efi + } +!endif + +INF DasharoModulePkg/DasharoBootPolicies/DasharoBootPolicies.inf + +!if $(USE_EDK2_PLATFORMS) == TRUE +INF DasharoModulePkg/DasharoBootPoliciesVTd/DasharoBootPoliciesVTd.inf +!endif + +# +# Hash2 +# +INF SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.inf + +# +# PKCS7 Verification +# +INF SecurityPkg/Pkcs7Verify/Pkcs7VerifyDxe/Pkcs7VerifyDxe.inf + +# +# SD/eMMC Support +# +INF MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf +INF MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.inf +INF MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf + # # Usb Support # @@ -402,6 +473,18 @@ INF SecurityPkg/Tcg/TdTcg2Dxe/TdTcg2Dxe.inf # !include OvmfPkg/Include/Fdf/OvmfTpmDxe.fdf.inc +!if $(SATA_PASSWORD_ENABLE) == TRUE +INF SecurityPkg/HddPassword/HddPasswordDxe.inf +!endif + +!if $(SETUP_PASSWORD_ENABLE) == TRUE +INF DasharoModulePkg/UserAuthenticationDxe/UserAuthenticationDxe.inf +!endif + +INF CrScreenshotDxe/CrScreenshotDxe.inf + +INF DasharoPayloadPkg/ApuConfigurationUi/ApuConfigurationUi.inf + ################################################################################ [FV.FVMAIN_COMPACT] diff --git a/OvmfPkg/SioBusDxe/SioService.c b/OvmfPkg/SioBusDxe/SioService.c index 66c5a08cf9..eea10db5e5 100644 --- a/OvmfPkg/SioBusDxe/SioService.c +++ b/OvmfPkg/SioBusDxe/SioService.c @@ -43,6 +43,24 @@ SIO_RESOURCES_IO mCom2Resources = { { ACPI_END_TAG_DESCRIPTOR, 0 } }; +// +// COM 3 UART Controller +// +GLOBAL_REMOVE_IF_UNREFERENCED +SIO_RESOURCES_IO mCom3Resources = { + { { ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR }, 0x3E8, 8 }, + { ACPI_END_TAG_DESCRIPTOR, 0 } +}; + +// +// COM 4 UART Controller +// +GLOBAL_REMOVE_IF_UNREFERENCED +SIO_RESOURCES_IO mCom4Resources = { + { { ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR }, 0x2E8, 8 }, + { ACPI_END_TAG_DESCRIPTOR, 0 } +}; + // // PS/2 Keyboard Controller // @@ -69,6 +87,16 @@ SIO_DEVICE_INFO mDevicesInfo[] = { 1, { (ACPI_SMALL_RESOURCE_HEADER *)&mCom2Resources } }, // COM 2 UART Controller + { + EISA_PNP_ID (0x501), + 0, + { (ACPI_SMALL_RESOURCE_HEADER *) &mCom3Resources } + }, // COM 3 UART Controller + { + EISA_PNP_ID (0x501), + 1, + { (ACPI_SMALL_RESOURCE_HEADER *) &mCom4Resources } + }, // COM 4 UART Controller { EISA_PNP_ID (0x303), 0, diff --git a/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c b/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c index ff1b019ce2..1ee6b5ffbd 100644 --- a/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c +++ b/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c @@ -241,8 +241,8 @@ PcRtcInit ( // // Clear RTC register D // - RegisterD.Data = FixedPcdGet8 (PcdInitialValueRtcRegisterD); - RtcWrite (RTC_ADDRESS_REGISTER_D, RegisterD.Data); + RegisterD.Data = RtcRead (RTC_ADDRESS_REGISTER_D); + RtcWrite (RTC_ADDRESS_REGISTER_D, RegisterD.Data & 0x80); // // Wait for up to 0.1 seconds for the RTC to be updated diff --git a/ReadMe.rst b/ReadMe.rst index 808ccd37af..33f0225d8a 100644 --- a/ReadMe.rst +++ b/ReadMe.rst @@ -64,6 +64,12 @@ OvmfPkg_Ubuntu_GCC5_ | IA32 |op32du| |op32ru| |op3 `More OvmfPkg CI Build Information `__ +To use iPXE as payload: + +.. code-block:: bash + + build -D NETWORK_IPXE=TRUE -D SERIAL_TERMINAL=FALSE -D SECURE_BOOT_ENABLE=TRUE -D BOOTLOADER=COREBOOT -D PCIE_BASE=0xe0000000 -DPS2_KEYBOARD_ENABLE -a IA32 -a X64 -t GCC5 -b DEBUG -p DasharoPayloadPkg/DasharoPayloadPkgIa32X64.dsc` + License Details --------------- diff --git a/SecurityPkg/HddPassword/HddPasswordDxe.c b/SecurityPkg/HddPassword/HddPasswordDxe.c index 6f36b5a0a2..7c6aa729a6 100644 --- a/SecurityPkg/HddPassword/HddPasswordDxe.c +++ b/SecurityPkg/HddPassword/HddPasswordDxe.c @@ -2625,10 +2625,14 @@ HddPasswordNotificationEvent ( UINTN DevNum; UINTN FuncNum; - if (mHddPasswordEndOfDxe) { - gBS->CloseEvent (Event); - return; - } + // FIXME: AtaPassThruProtocol is installed in BDS, which makes it impossible + // to create a list of disks for the UI menu before END_OF_DXE signal which + // sets mHddPasswordEndOfDxe via notify function. It creates a dead end + // resulting in empty HDD password menu. + // if (mHddPasswordEndOfDxe) { + // gBS->CloseEvent (Event); + // return; + // } Private = (HDD_PASSWORD_DXE_PRIVATE_DATA *)Context; diff --git a/SecurityPkg/Include/Library/SecureBootVariableLib.h b/SecurityPkg/Include/Library/SecureBootVariableLib.h index c486801c31..5bf91cf141 100644 --- a/SecurityPkg/Include/Library/SecureBootVariableLib.h +++ b/SecurityPkg/Include/Library/SecureBootVariableLib.h @@ -30,6 +30,21 @@ SetSecureBootMode ( IN UINT8 SecureBootMode ); +/** + + Set the platform secure boot state into "Enabled" or "Disabled". + + @param[in] SecureBootMode New secure boot state. + + @return EFI_SUCCESS The platform has switched to the new state successfully. + @return other Fail to operate the secure boot state. + +**/ +EFI_STATUS +SetSecureBootState ( + IN UINT8 SecureBootState +); + /** Fetches the value of SetupMode variable. diff --git a/SecurityPkg/Library/AuthVariableLib/AuthServiceInternal.h b/SecurityPkg/Library/AuthVariableLib/AuthServiceInternal.h index f7bf771d55..2701555859 100644 --- a/SecurityPkg/Library/AuthVariableLib/AuthServiceInternal.h +++ b/SecurityPkg/Library/AuthVariableLib/AuthServiceInternal.h @@ -27,6 +27,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include #include #include diff --git a/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c index dc11f38cb3..658873ec75 100644 --- a/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c +++ b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c @@ -17,6 +17,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "AuthServiceInternal.h" +#include /// /// Global database array for scratch @@ -217,7 +218,7 @@ AuthVariableLibInitialize ( // // "SecureBootEnable" not exist, initialize it in USER_MODE. // - SecureBootEnable = SECURE_BOOT_ENABLE; + SecureBootEnable = FixedPcdGet8 (PcdSecureBootDefaultEnable); Status = AuthServiceInternalUpdateVariable ( EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, @@ -230,6 +231,14 @@ AuthVariableLibInitialize ( } } + Status = AuthServiceInternalFindVariable (DASHARO_VAR_FIRMWARE_UPDATE_MODE, &gDasharoSystemFeaturesGuid, + (VOID **) &Data, &DataSize); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_INFO, "Variable %s does not exist.\n", DASHARO_VAR_FIRMWARE_UPDATE_MODE)); + } else { + DEBUG ((EFI_D_INFO, "Variable %s exists.\n", DASHARO_VAR_FIRMWARE_UPDATE_MODE)); + } + // // Create "SecureBoot" variable with BS+RT attribute set. // @@ -239,6 +248,10 @@ AuthVariableLibInitialize ( SecureBootMode = SECURE_BOOT_MODE_DISABLE; } + // Disable Secure Boot if FUM enabled in the project and currently active + if (PcdGetBool (PcdShowFum) && !EFI_ERROR (Status)) + SecureBootMode = SECURE_BOOT_MODE_DISABLE; + Status = AuthServiceInternalUpdateVariable ( EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, diff --git a/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf index e5985c5f8b..4d3bc7c211 100644 --- a/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf +++ b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf @@ -34,6 +34,7 @@ MdeModulePkg/MdeModulePkg.dec SecurityPkg/SecurityPkg.dec CryptoPkg/CryptoPkg.dec + DasharoModulePkg/DasharoModulePkg.dec [LibraryClasses] BaseLib @@ -43,6 +44,11 @@ BaseCryptLib PlatformSecureLib VariablePolicyLib + PcdLib + +[Pcd] + gEfiSecurityPkgTokenSpaceGuid.PcdSecureBootDefaultEnable + gDasharoSystemFeaturesTokenSpaceGuid.PcdShowFum [Guids] ## CONSUMES ## Variable:L"SetupMode" @@ -82,6 +88,9 @@ ## CONSUMES ## Variable:L"AuthVarKeyDatabase" ## PRODUCES ## Variable:L"AuthVarKeyDatabase" gEfiAuthenticatedVariableGuid + + ## CONSUMES ## Variable:L"FirmwareUpdateMode" + gDasharoSystemFeaturesGuid gEfiCertTypeRsa2048Sha256Guid ## SOMETIMES_CONSUMES ## GUID # Unique ID for the type of the certificate. gEfiCertPkcs7Guid ## SOMETIMES_CONSUMES ## GUID # Unique ID for the type of the certificate. diff --git a/SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.c b/SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.c index 24599c7a0b..7bcb6ed2bf 100644 --- a/SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.c +++ b/SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.c @@ -401,6 +401,45 @@ SetSecureBootMode ( ); } + +/** + + Set the platform secure boot state into "Enabled" or "Disabled". + + @param[in] SecureBootMode New secure boot state. + + @return EFI_SUCCESS The platform has switched to the new state successfully. + @return other Fail to operate the secure boot mode. + +**/ +EFI_STATUS +SetSecureBootState ( + IN UINT8 SecureBootState + ) +{ + EFI_STATUS Status; + + Status = gRT->SetVariable ( + EFI_SECURE_BOOT_MODE_NAME, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof(UINT8), + &SecureBootState + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + return gRT->SetVariable ( + EFI_SECURE_BOOT_ENABLE_NAME, + &gEfiSecureBootEnableDisableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (UINT8), + &SecureBootState + ); +} + /** Fetches the value of SetupMode variable. diff --git a/SecurityPkg/Library/SecureBootVariableProvisionLib/SecureBootVariableProvisionLib.c b/SecurityPkg/Library/SecureBootVariableProvisionLib/SecureBootVariableProvisionLib.c index d6046c85d2..757cab82c4 100644 --- a/SecurityPkg/Library/SecureBootVariableProvisionLib/SecureBootVariableProvisionLib.c +++ b/SecurityPkg/Library/SecureBootVariableProvisionLib/SecureBootVariableProvisionLib.c @@ -23,6 +23,7 @@ #include #include #include +#include /** Create a EFI Signature List with data fetched from section specified as a argument. @@ -79,6 +80,13 @@ SecureBootFetchData ( ); if (Status == EFI_SUCCESS) { + /* dbx file downloaded from uefi.org is a raw variable value, simply return the buffer. */ + if (CompareGuid(KeyFileGuid, &gDefaultdbxFileGuid)) { + *SigListOut = (EFI_SIGNATURE_LIST *)Buffer; + *SigListsSize = Size; + return EFI_SUCCESS; + } + RsaPubKey = NULL; if (RsaGetPublicKeyFromX509 (Buffer, Size, &RsaPubKey) == FALSE) { DEBUG ((DEBUG_ERROR, "%a: Invalid key format: %d\n", __func__, KeyIndex)); @@ -154,6 +162,7 @@ EnrollFromDefault ( ) { VOID *Data; + VOID *EnrollData; UINTN DataSize; EFI_STATUS Status; @@ -166,7 +175,14 @@ EnrollFromDefault ( return Status; } - Status = EnrollFromInput (VariableName, VendorGuid, DataSize, Data); + EnrollData = Data; + /* dbx from uefi.org comes with the time payload. */ + if (StrCmp (DefaultName, EFI_DBX_DEFAULT_VARIABLE_NAME) == 0) { + DataSize -= AUTHINFO2_SIZE (Data); + EnrollData = (UINT8 *) Data + AUTHINFO2_SIZE (Data); + } + + Status = EnrollFromInput (VariableName, VendorGuid, DataSize, EnrollData); if (Data != NULL) { FreePool (Data); diff --git a/SecurityPkg/SecurityPkg.dec b/SecurityPkg/SecurityPkg.dec index 00c4ebdbed..e3c9764692 100644 --- a/SecurityPkg/SecurityPkg.dec +++ b/SecurityPkg/SecurityPkg.dec @@ -325,6 +325,13 @@ gEfiSecurityPkgTokenSpaceGuid.PcdStatusCodeFvVerificationPass|0x0303100A|UINT32|0x00010030 gEfiSecurityPkgTokenSpaceGuid.PcdStatusCodeFvVerificationFail|0x0303100B|UINT32|0x00010031 + ## Specifies the Secure Boot state after settings are reset.

+ # If 0, Disable Secure Boot when settings are reset.
+ # If 1, Enable Secure Boot when settings are reset.
+ # @Prompt Secure Boot default state. + # @ValidRange 0x80000001 | 0x00 - 0x1 + gEfiSecurityPkgTokenSpaceGuid.PcdSecureBootDefaultEnable|1|UINT8|0x0000000A + [PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx] ## Image verification policy for OptionRom. Only following values are valid:

# NOTE: Do NOT use 0x5 and 0x2 since it violates the UEFI specification and has been removed.
diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c b/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c index ba9fa66c60..4c61dcb726 100644 --- a/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c @@ -2418,6 +2418,13 @@ OpalDriverStopDevice ( Dev->Handle ); + gBS->CloseProtocol( + Dev->Handle, + &gEfiBlockIo2ProtocolGuid, + gOpalDriverBinding.DriverBindingHandle, + Dev->Handle + ); + FreePool (Dev); } @@ -2717,10 +2724,6 @@ OpalEfiDriverBindingSupported ( EFI_STATUS Status; EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *SecurityCommand; - if (mOpalEndOfDxe) { - return EFI_UNSUPPORTED; - } - // // Test EFI_STORAGE_SECURITY_COMMAND_PROTOCOL on controller Handle. // @@ -2793,11 +2796,13 @@ OpalEfiDriverBindingStart ( IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { - EFI_STATUS Status; - EFI_BLOCK_IO_PROTOCOL *BlkIo; - OPAL_DRIVER_DEVICE *Dev; - OPAL_DRIVER_DEVICE *Itr; - BOOLEAN Result; + EFI_STATUS Status; + EFI_STATUS Status2; + EFI_BLOCK_IO_PROTOCOL *BlkIo; + EFI_BLOCK_IO2_PROTOCOL *BlkIo2; + OPAL_DRIVER_DEVICE *Dev; + OPAL_DRIVER_DEVICE *Itr; + BOOLEAN Result; Itr = mOpalDriver.DeviceList; while (Itr != NULL) { @@ -2836,8 +2841,8 @@ OpalEfiDriverBindingStart ( } // - // Open EFI_BLOCK_IO_PROTOCOL on controller Handle, required by EFI_STORAGE_SECURITY_COMMAND_PROTOCOL - // function APIs + // Open EFI_BLOCK_IO_PROTOCOL or EFI_BLOCK_IO2_PROTOCOL on controller + // Handle, required by EFI_STORAGE_SECURITY_COMMAND_PROTOCOL function APIs // Status = gBS->OpenProtocol ( Controller, @@ -2847,43 +2852,70 @@ OpalEfiDriverBindingStart ( Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); + + if (Status == EFI_UNSUPPORTED) + BlkIo = NULL; + if (EFI_ERROR (Status)) { - // - // Block_IO not supported on handle - // - if (Status == EFI_UNSUPPORTED) { - BlkIo = NULL; - } else { + Status2 = gBS->OpenProtocol( + Controller, + &gEfiBlockIo2ProtocolGuid, + (VOID **)&BlkIo2, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status2)) { // - // Close storage security that was opened + // Block_IO not supported on handle // - gBS->CloseProtocol ( - Controller, - &gEfiStorageSecurityCommandProtocolGuid, - This->DriverBindingHandle, - Controller - ); + if (Status2 == EFI_UNSUPPORTED) + BlkIo2 = NULL; - FreePool (Dev); - return Status; + if (Status != EFI_UNSUPPORTED && Status2 != EFI_UNSUPPORTED) { + // + // Close storage security that was opened + // + gBS->CloseProtocol ( + Controller, + &gEfiStorageSecurityCommandProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + FreePool (Dev); + return Status; + } } } // // Save mediaId // - if (BlkIo == NULL) { + if (BlkIo == NULL && BlkIo2 == NULL) { // If no Block IO present, use defined MediaId value. Dev->MediaId = 0x0; } else { - Dev->MediaId = BlkIo->Media->MediaId; - - gBS->CloseProtocol ( - Controller, - &gEfiBlockIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); + if (BlkIo) { + Dev->MediaId = BlkIo->Media->MediaId; + + gBS->CloseProtocol ( + Controller, + &gEfiBlockIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } else if (BlkIo2) { + Dev->MediaId = BlkIo2->Media->MediaId; + + gBS->CloseProtocol ( + Controller, + &gEfiBlockIo2ProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } } // diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.h b/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.h index 2089bd81b6..d8b2aaec9a 100644 --- a/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.h +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.h @@ -16,6 +16,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include #include #include #include diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf index 87519198c0..b7a573e065 100644 --- a/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf +++ b/SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordDxe.inf @@ -65,6 +65,7 @@ gEfiComponentNameProtocolGuid ## PRODUCES gEfiComponentName2ProtocolGuid ## PRODUCES gEfiBlockIoProtocolGuid ## CONSUMES + gEfiBlockIo2ProtocolGuid ## CONSUMES [Guids] gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event diff --git a/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigStrings.uni b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigStrings.uni index ee7fa081b6..073bdee78c 100644 --- a/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigStrings.uni +++ b/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigStrings.uni @@ -12,7 +12,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #string STR_TCG2_HELP #language en-US "Press to select TCG2 Setup options." #string STR_TCG2_DEVICE_STATE_PROMPT #language en-US "Current TPM Device" -#string STR_TCG2_DEVICE_STATE_HELP #language en-US "Current TPM Device: Disable, TPM1.2, or TPM2.0" +#string STR_TCG2_DEVICE_STATE_HELP #language en-US "Current TPM Device: Not Found, Unknown, TPM1.2, or TPM2.0" #string STR_TCG2_DEVICE_STATE_CONTENT #language en-US "" #string STR_TCG2_DEVICE_PROMPT #language en-US "Attempt TPM Device" diff --git a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c index f6ea8b2bbf..0a6a34986f 100644 --- a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c +++ b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c @@ -44,6 +44,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include #define PERF_ID_TCG2_DXE 0x3120 @@ -2422,6 +2423,11 @@ OnReadyToBoot ( PERF_START_EX (mImageHandle, "EventRec", "Tcg2Dxe", 0, PERF_ID_TCG2_DXE); if (mBootAttempts == 0) { + Status = DasharoMeasureVariables (); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Dasharo variables not Measured. Error: %r!\n", Status)); + } + // // Measure handoff tables. // diff --git a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf index 7dc7a2683d..9c54695efa 100644 --- a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf +++ b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf @@ -45,6 +45,7 @@ MdeModulePkg/MdeModulePkg.dec SecurityPkg/SecurityPkg.dec CryptoPkg/CryptoPkg.dec + DasharoModulePkg/DasharoModulePkg.dec [LibraryClasses] MemoryAllocationLib @@ -64,6 +65,7 @@ ReportStatusCodeLib Tcg2PhysicalPresenceLib PeCoffLib + DasharoVariablesLib [Guids] ## SOMETIMES_CONSUMES ## Variable:L"SecureBoot" diff --git a/SecurityPkg/Tcg/TcgDxe/TcgDxe.c b/SecurityPkg/Tcg/TcgDxe/TcgDxe.c index ee6c627303..67c7ab204a 100644 --- a/SecurityPkg/Tcg/TcgDxe/TcgDxe.c +++ b/SecurityPkg/Tcg/TcgDxe/TcgDxe.c @@ -47,6 +47,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include #define TCG_DXE_DATA_FROM_THIS(this) \ BASE_CR (this, TCG_DXE_DATA, TcgProtocol) @@ -1125,6 +1126,11 @@ OnReadyToBoot ( TPM_PCRINDEX PcrIndex; if (mBootAttempts == 0) { + Status = DasharoMeasureVariables (); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Dasharo variables not Measured. Error: %r!\n", Status)); + } + // // Measure handoff tables. // diff --git a/SecurityPkg/Tcg/TcgDxe/TcgDxe.inf b/SecurityPkg/Tcg/TcgDxe/TcgDxe.inf index c93b377b34..3154dc3f61 100644 --- a/SecurityPkg/Tcg/TcgDxe/TcgDxe.inf +++ b/SecurityPkg/Tcg/TcgDxe/TcgDxe.inf @@ -30,6 +30,7 @@ MdeModulePkg/MdeModulePkg.dec CryptoPkg/CryptoPkg.dec SecurityPkg/SecurityPkg.dec + DasharoModulePkg/DasharoModulePkg.dec [LibraryClasses] MemoryAllocationLib @@ -47,6 +48,7 @@ PcdLib ReportStatusCodeLib Tpm12CommandLib + DasharoVariablesLib [Guids] gEfiGlobalVariableGuid ## SOMETIMES_CONSUMES ## Variable:L"BootXXXX" diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr index e4560c592c..88622f503f 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfig.vfr @@ -32,8 +32,12 @@ formset text = STRING_TOKEN(STR_SECURE_BOOT_STATE_PROMPT), text = STRING_TOKEN(STR_SECURE_BOOT_STATE_CONTENT); + + suppressif ideqval SECUREBOOT_CONFIGURATION.HasPk == 1; + subtitle text = STRING_TOKEN(STR_ENROLL_PK_MSG); + endif; // - // Display of Check Box: Attempt Secure Boot + // Display of Check Box: Enable Secure Boot // grayoutif ideqval SECUREBOOT_CONFIGURATION.HideSecureBoot == 1 OR NOT ideqval SECUREBOOT_CONFIGURATION.PhysicalPresent == 1; checkbox varid = SECUREBOOT_CONFIGURATION.AttemptSecureBoot, @@ -56,24 +60,15 @@ formset option text = STRING_TOKEN(STR_CUSTOM_MODE), value = SECURE_BOOT_MODE_CUSTOM, flags = 0; endoneof; - // - // Display of 'Current Secure Boot Mode' - // suppressif questionref(SecureBootMode) == SECURE_BOOT_MODE_STANDARD; - grayoutif NOT ideqval SECUREBOOT_CONFIGURATION.PhysicalPresent == 1; - goto FORMID_SECURE_BOOT_OPTION_FORM, - prompt = STRING_TOKEN(STR_SECURE_BOOT_OPTION), - help = STRING_TOKEN(STR_SECURE_BOOT_OPTION_HELP), - flags = INTERACTIVE, - key = KEY_SECURE_BOOT_OPTION; + grayoutif NOT ideqval SECUREBOOT_CONFIGURATION.PhysicalPresent == 1; + goto FORMID_SECURE_BOOT_OPTION_FORM, + prompt = STRING_TOKEN(STR_SECURE_BOOT_OPTION), + help = STRING_TOKEN(STR_SECURE_BOOT_OPTION_HELP), + flags = INTERACTIVE, + key = KEY_SECURE_BOOT_OPTION; + endif; endif; - endif; - - text - help = STRING_TOKEN(STR_SECURE_RESET_TO_DEFAULTS_HELP), - text = STRING_TOKEN(STR_SECURE_RESET_TO_DEFAULTS), - flags = INTERACTIVE, - key = KEY_SECURE_BOOT_RESET_TO_DEFAULT; endform; @@ -85,6 +80,23 @@ formset subtitle text = STRING_TOKEN(STR_NULL); + text + help = STRING_TOKEN(STR_SECURE_RESET_TO_DEFAULTS_HELP), + text = STRING_TOKEN(STR_SECURE_RESET_TO_DEFAULTS), + flags = INTERACTIVE | RESET_REQUIRED, + key = KEY_SECURE_BOOT_RESET_TO_DEFAULT; + + text + help = STRING_TOKEN(STR_SECURE_ERASE_ALL_KEYS_HELP), + text = STRING_TOKEN(STR_SECURE_ERASE_ALL_KEYS), + flags = INTERACTIVE | RESET_REQUIRED, + key = KEY_SECURE_BOOT_ERASE_ALL_KEYS; + + + subtitle text = STRING_TOKEN(STR_NULL); + subtitle text = STRING_TOKEN(STR_SECURE_BOOT_MANUAL_KEY_MGMT); + subtitle text = STRING_TOKEN(STR_NULL); + goto FORMID_SECURE_BOOT_PK_OPTION_FORM, prompt = STRING_TOKEN(STR_SECURE_BOOT_PK_OPTION), help = STRING_TOKEN(STR_SECURE_BOOT_PK_OPTION_HELP), @@ -133,6 +145,15 @@ formset subtitle text = STRING_TOKEN(STR_NULL); + // + // Display of 'Currently enrolled PK' + // + suppressif NOT ideqval SECUREBOOT_CONFIGURATION.HasPk == 1; + subtitle text = STRING_TOKEN(STR_PK_INFO); + subtitle text = STRING_TOKEN(STR_PK_NAME); + subtitle text = STRING_TOKEN(STR_NULL); + endif; + // // Display of 'Enroll PK' // @@ -254,7 +275,7 @@ formset goto FORMID_SECURE_BOOT_OPTION_FORM, prompt = STRING_TOKEN(STR_SAVE_AND_EXIT), help = STRING_TOKEN(STR_SAVE_AND_EXIT), - flags = INTERACTIVE, + flags = INTERACTIVE | RESET_REQUIRED, key = KEY_VALUE_SAVE_AND_EXIT_KEK; goto FORMID_SECURE_BOOT_OPTION_FORM, @@ -458,7 +479,7 @@ formset goto FORMID_SECURE_BOOT_OPTION_FORM, prompt = STRING_TOKEN(STR_SAVE_AND_EXIT), help = STRING_TOKEN(STR_SAVE_AND_EXIT), - flags = INTERACTIVE, + flags = INTERACTIVE | RESET_REQUIRED, key = KEY_VALUE_SAVE_AND_EXIT_DB; goto FORMID_SECURE_BOOT_OPTION_FORM, @@ -552,7 +573,7 @@ formset goto FORMID_SECURE_BOOT_OPTION_FORM, prompt = STRING_TOKEN(STR_SAVE_AND_EXIT), help = STRING_TOKEN(STR_SAVE_AND_EXIT), - flags = INTERACTIVE, + flags = INTERACTIVE | RESET_REQUIRED, key = KEY_VALUE_SAVE_AND_EXIT_DBX; goto FORMID_SECURE_BOOT_OPTION_FORM, @@ -597,7 +618,7 @@ formset goto FORMID_SECURE_BOOT_OPTION_FORM, prompt = STRING_TOKEN(STR_SAVE_AND_EXIT), help = STRING_TOKEN(STR_SAVE_AND_EXIT), - flags = INTERACTIVE, + flags = INTERACTIVE | RESET_REQUIRED, key = KEY_VALUE_SAVE_AND_EXIT_DBT; goto FORMID_SECURE_BOOT_OPTION_FORM, diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf index 0602acf702..21be571bf5 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf @@ -50,6 +50,7 @@ UefiHiiServicesLib DebugLib HiiLib + PcdLib PlatformSecureLib DevicePathLib FileExplorerLib @@ -57,6 +58,9 @@ SecureBootVariableLib SecureBootVariableProvisionLib +[FixedPcd] + gEfiSecurityPkgTokenSpaceGuid.PcdSecureBootDefaultEnable + [Guids] ## SOMETIMES_CONSUMES ## Variable:L"CustomMode" ## SOMETIMES_PRODUCES ## Variable:L"CustomMode" diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c index 2c11129526..ecd048a45b 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c @@ -12,6 +12,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include #include #include @@ -2525,6 +2526,7 @@ UpdateDeletePage ( IN EFI_QUESTION_ID QuestionIdBase ) { + EFI_STATUS Status; UINT32 Index; UINTN CertCount; @@ -2538,16 +2540,23 @@ UpdateDeletePage ( EFI_SIGNATURE_LIST *CertList; EFI_SIGNATURE_DATA *Cert; UINT32 ItemDataSize; - CHAR16 *GuidStr; - EFI_STRING_ID GuidID; + CHAR16 *CertificateInfoStr; + CHAR8 *CertificateInfoStr8; + EFI_STRING_ID CertificateInfoID; EFI_STRING_ID Help; + UINTN CertificateInfoStrSize; + CHAR16* UNKNOWN_CERT = L"Unknown Certificate: No Common Name, No Issuer"; + RETURN_STATUS RStatus; - Data = NULL; - CertList = NULL; - Cert = NULL; - GuidStr = NULL; - StartOpCodeHandle = NULL; - EndOpCodeHandle = NULL; + Data = NULL; + CertList = NULL; + Cert = NULL; + CertificateInfoStr = NULL; + CertificateInfoStr8 = NULL; + StartOpCodeHandle = NULL; + EndOpCodeHandle = NULL; + CertificateInfoStrSize = 0; + RStatus = RETURN_SUCCESS; // // Initialize the container for dynamic opcodes. @@ -2605,12 +2614,6 @@ UpdateDeletePage ( goto ON_EXIT; } - GuidStr = AllocateZeroPool (100); - if (GuidStr == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ON_EXIT; - } - // // Enumerate all KEK pub data. // @@ -2648,22 +2651,59 @@ UpdateDeletePage ( + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize + Index * CertList->SignatureSize); + + // Get the required buffer size + X509GetCommonName ( + (UINT8*)Cert->SignatureData, + (UINTN)CertList->SignatureSize, + NULL, + &CertificateInfoStrSize + ); + + CertificateInfoStr8 = AllocateZeroPool (CertificateInfoStrSize * sizeof(CHAR8)); + if (CertificateInfoStr8 == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + CertificateInfoStr = AllocateZeroPool (CertificateInfoStrSize * sizeof(CHAR16)); + if (CertificateInfoStr == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + // // Display GUID and help // - GuidToString (&Cert->SignatureOwner, GuidStr, 100); - GuidID = HiiSetString (PrivateData->HiiHandle, 0, GuidStr, NULL); + RStatus = X509GetCommonName ( + (UINT8*)Cert->SignatureData, + (UINTN)CertList->SignatureSize, + CertificateInfoStr8, + &CertificateInfoStrSize + ); + + if (!EFI_ERROR (RStatus)) { + AsciiStrToUnicodeStrS (CertificateInfoStr8, CertificateInfoStr, CertificateInfoStrSize); + CertificateInfoID = HiiSetString (PrivateData->HiiHandle, 0, CertificateInfoStr, NULL); + } else { + CertificateInfoID = HiiSetString (PrivateData->HiiHandle, 0, UNKNOWN_CERT, NULL); + } + HiiCreateCheckBoxOpCode ( StartOpCodeHandle, (EFI_QUESTION_ID)(QuestionIdBase + GuidIndex++), 0, 0, - GuidID, + CertificateInfoID, Help, - EFI_IFR_FLAG_CALLBACK, + EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED, 0, NULL ); + + FreePool (CertificateInfoStr8); + FreePool (CertificateInfoStr); + CertificateInfoStr8 = NULL; + CertificateInfoStr = NULL; } ItemDataSize -= CertList->SignatureListSize; @@ -2691,8 +2731,12 @@ UpdateDeletePage ( FreePool (Data); } - if (GuidStr != NULL) { - FreePool (GuidStr); + if (CertificateInfoStr != NULL) { + FreePool (CertificateInfoStr); + } + + if (CertificateInfoStr8 != NULL) { + FreePool (CertificateInfoStr8); } return EFI_SUCCESS; @@ -3755,7 +3799,7 @@ LoadSignatureList ( DstFormId, STRING_TOKEN (STR_SECURE_BOOT_DELETE_ALL_LIST), STRING_TOKEN (STR_SECURE_BOOT_DELETE_ALL_LIST), - EFI_IFR_FLAG_CALLBACK, + EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED, KEY_SECURE_BOOT_DELETE_ALL_LIST ); @@ -3834,7 +3878,7 @@ LoadSignatureList ( SECUREBOOT_DELETE_SIGNATURE_DATA_FORM, HiiSetString (PrivateData->HiiHandle, 0, NameBuffer, NULL), HiiSetString (PrivateData->HiiHandle, 0, HelpBuffer, NULL), - EFI_IFR_FLAG_CALLBACK, + EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED, QuestionIdBase + Index++ ); @@ -4487,6 +4531,76 @@ KeyEnrollReset ( return Status; } + +/** + This function reinitializes Secure Boot variables with default values. + + @retval EFI_SUCCESS Success to update the signature list page + @retval others Fail to delete or enroll signature data. +**/ +STATIC EFI_STATUS +EFIAPI +KeyEraseAll ( + VOID + ) +{ + EFI_STATUS Status; + UINT8 SetupMode; + + Status = EFI_SUCCESS; + + Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE); + if (EFI_ERROR(Status)) { + return Status; + } + + // Clear all the keys and databases + Status = DeleteDb (); + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { + DEBUG ((DEBUG_ERROR, "Fail to clear DB: %r\n", Status)); + return Status; + } + + Status = DeleteDbx (); + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { + DEBUG ((DEBUG_ERROR, "Fail to clear DBX: %r\n", Status)); + return Status; + } + + Status = DeleteDbt (); + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { + DEBUG ((DEBUG_ERROR, "Fail to clear DBT: %r\n", Status)); + return Status; + } + + Status = DeleteKEK (); + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { + DEBUG ((DEBUG_ERROR, "Fail to clear KEK: %r\n", Status)); + return Status; + } + + Status = DeletePlatformKey (); + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { + DEBUG ((DEBUG_ERROR, "Fail to clear PK: %r\n", Status)); + return Status; + } + + // After PK clear, Setup Mode shall be enabled + Status = GetSetupMode (&SetupMode); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Cannot get SetupMode variable: %r\n", + Status)); + return Status; + } + + if (SetupMode == USER_MODE) { + DEBUG((DEBUG_INFO, "Skipped - USER_MODE\n")); + return EFI_SUCCESS; + } + + return Status; +} + /** This function is called to provide results data to the driver. @@ -4529,6 +4643,10 @@ SecureBootCallback ( UINT16 LabelId; UINT8 *SecureBootEnable; UINT8 *Pk; + EFI_SIGNATURE_LIST *PkList; + EFI_SIGNATURE_DATA *PkCert; + CHAR8 *PkCN8; + CHAR16 *PkCN16; UINT8 *SecureBootMode; UINT8 *SetupMode; CHAR16 PromptString[100]; @@ -4540,12 +4658,19 @@ SecureBootCallback ( ENROLL_KEY_ERROR EnrollKeyErrorCode; EFI_HII_POPUP_PROTOCOL *HiiPopup; EFI_HII_POPUP_SELECTION UserSelection; + CHAR16* UNKNOWN_CERT = L"Unknown Certificate: No Common Name, No Issuer"; Status = EFI_SUCCESS; + RStatus = RETURN_SUCCESS; SecureBootEnable = NULL; SecureBootMode = NULL; SetupMode = NULL; File = NULL; + PkList = NULL; + PkCert = NULL; + PkCN8 = NULL; + PkCN16 = NULL; + EnrollKeyErrorCode = None_Error; if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) { @@ -4580,8 +4705,51 @@ SecureBootCallback ( // When entering SecureBoot OPTION Form // always close opened file & free resource // - if ((QuestionId == KEY_SECURE_BOOT_PK_OPTION) || - (QuestionId == KEY_SECURE_BOOT_KEK_OPTION) || + if ((QuestionId == KEY_SECURE_BOOT_PK_OPTION)) { + CloseEnrolledFile (Private->FileContext); + + GetVariable2 (EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid, (VOID **)&PkList, NULL); + if (PkList != NULL) { + // Extract the PK certificate from the list + PkCert = (EFI_SIGNATURE_DATA *)((UINT8 *)PkList + sizeof (EFI_SIGNATURE_LIST) + PkList->SignatureHeaderSize); + + // Get the required buffer size + UINTN cnSize = 0; + X509GetCommonName ( + (UINT8*)PkCert->SignatureData, + (UINTN)PkList->SignatureSize, + NULL, + &cnSize + ); + + PkCN8 = AllocateZeroPool (cnSize * sizeof(CHAR8)); + if (PkCN8 == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto EXIT; + } + PkCN16 = AllocateZeroPool (cnSize * sizeof(CHAR16)); + if (PkCN16 == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto EXIT; + } + + RStatus = X509GetCommonName ( + (UINT8*)PkCert->SignatureData, + (UINTN)PkList->SignatureSize, + PkCN8, + &cnSize + ); + + if (!EFI_ERROR (RStatus)) { + AsciiStrToUnicodeStrS (PkCN8, PkCN16, cnSize); + HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_PK_NAME), PkCN16, NULL); + } else { + HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_PK_NAME), UNKNOWN_CERT, NULL); + } + } + } + + if ((QuestionId == KEY_SECURE_BOOT_KEK_OPTION) || (QuestionId == KEY_SECURE_BOOT_DB_OPTION) || (QuestionId == KEY_SECURE_BOOT_DBX_OPTION) || (QuestionId == KEY_SECURE_BOOT_DBT_OPTION)) @@ -5140,12 +5308,40 @@ SecureBootCallback ( Status = UpdateSecureBootString (Private); SecureBootExtractConfigFromVariable (Private, IfrNvData); } + break; + } + case KEY_SECURE_BOOT_ERASE_ALL_KEYS: + { + Status = gBS->LocateProtocol (&gEfiHiiPopupProtocolGuid, NULL, (VOID **) &HiiPopup); + if (EFI_ERROR (Status)) { + return Status; + } + Status = HiiPopup->CreatePopup ( + HiiPopup, + EfiHiiPopupStyleInfo, + EfiHiiPopupTypeYesNo, + Private->HiiHandle, + STRING_TOKEN (STR_ERASE_ALL_KEYS_POPUP), + &UserSelection + ); + if (UserSelection == EfiHiiPopupSelectionYes) { + Status = KeyEraseAll (); + } + // + // Update secure boot strings after key reset + // + if (Status == EFI_SUCCESS) { + Status = UpdateSecureBootString (Private); + SecureBootExtractConfigFromVariable (Private, IfrNvData); + } + break; } default: break; } } else if (Action == EFI_BROWSER_ACTION_DEFAULT_STANDARD) { - if (QuestionId == KEY_HIDE_SECURE_BOOT) { + switch (QuestionId) { + case KEY_HIDE_SECURE_BOOT: { GetVariable2 (EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid, (VOID **)&Pk, NULL); if (Pk == NULL) { IfrNvData->HideSecureBoot = TRUE; @@ -5155,6 +5351,22 @@ SecureBootCallback ( } Value->b = IfrNvData->HideSecureBoot; + break; + } + case KEY_SECURE_BOOT_ENABLE: { + Value->u8 = FixedPcdGet8 (PcdSecureBootDefaultEnable); + if (EFI_ERROR (SaveSecureBootVariable (Value->u8))) { + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"Could not restore Secure Boot to default state!", + NULL + ); + } + break; + } + default: + break; } } else if (Action == EFI_BROWSER_ACTION_FORM_CLOSE) { // @@ -5193,6 +5405,18 @@ SecureBootCallback ( File = NULL; } + if (PkCN8 != NULL) { + FreePool (PkCN8); + } + + if (PkCN16 != NULL) { + FreePool (PkCN16); + } + + if (PkList != NULL) { + FreePool (PkList); + } + return EFI_SUCCESS; } diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigNvData.h b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigNvData.h index 34720bb5e2..a5ed76b6f8 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigNvData.h +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigNvData.h @@ -55,6 +55,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #define KEY_VALUE_FROM_DBX_TO_LIST_FORM 0x100f #define KEY_SECURE_BOOT_RESET_TO_DEFAULT 0x1010 +#define KEY_SECURE_BOOT_ERASE_ALL_KEYS 0x1011 #define KEY_SECURE_BOOT_OPTION 0x1100 #define KEY_SECURE_BOOT_PK_OPTION 0x1101 diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni index 177c585837..17afa9e33b 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni @@ -18,13 +18,21 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #string STR_SECURE_BOOT_STATE_HELP #language en-US "Current Secure Boot state: enabled or disabled." #string STR_SECURE_BOOT_STATE_CONTENT #language en-US " " -#string STR_SECURE_BOOT_PROMPT #language en-US "Attempt Secure Boot" +#string STR_ENROLL_PK_MSG #language en-US "To enable Secure Boot, set Secure Boot Mode to Custom and enroll the keys/PK first." + +#string STR_SECURE_BOOT_PROMPT #language en-US "Enable Secure Boot" #string STR_SECURE_BOOT_HELP #language en-US "Enable/Disable the Secure Boot feature after platform reset" -#string STR_SECURE_RESET_TO_DEFAULTS_HELP #language en-US "Enroll keys with data from default variables" -#string STR_SECURE_RESET_TO_DEFAULTS #language en-US "Reset Secure Boot Keys" +#string STR_SECURE_RESET_TO_DEFAULTS_HELP #language en-US "Enroll keys with data from default variables.\n\nBecause the PK may also be enrolled, the Secure Boot state may automatically switch to enabled state." +#string STR_SECURE_RESET_TO_DEFAULTS #language en-US "> Reset to default Secure Boot Keys" + #string STR_RESET_TO_DEFAULTS_POPUP #language en-US "Secure Boot Keys & databases will be initialized from defaults.\n Are you sure?" +#string STR_SECURE_ERASE_ALL_KEYS_HELP #language en-US "Erases all Secure Boot keys and leaves the related variables empty.\nYou will need to provision the keys to use Secure Boot again or reset the Secure Boot keys to defaults." +#string STR_SECURE_ERASE_ALL_KEYS #language en-US "> Erase all Secure Boot Keys" + +#string STR_ERASE_ALL_KEYS_POPUP #language en-US "Secure Boot Keys & databases will be erased and Secure Boot disabled.\n Are you sure?" + #string STR_SECURE_BOOT_ENROLL_SIGNATURE #language en-US "Enroll Signature" #string STR_SECURE_BOOT_DELETE_SIGNATURE #language en-US "Delete Signature" #string STR_SECURE_BOOT_DELETE_LIST_FORM #language en-US "Delete Signature List Form" @@ -74,10 +82,11 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #string STR_STANDARD_MODE #language en-US "Standard Mode" #string STR_CUSTOM_MODE #language en-US "Custom Mode" -#string STR_SECURE_BOOT_OPTION #language en-US "Custom Secure Boot Options" -#string STR_SECURE_BOOT_OPTION_HELP #language en-US "Enter into Custom Secure Boot Options Form" +#string STR_SECURE_BOOT_OPTION #language en-US "Advanced Secure Boot Keys Management" +#string STR_SECURE_BOOT_OPTION_HELP #language en-US "Enter into Advanced Secure Boot Keys Management Form" -#string STR_SECURE_BOOT_OPTION_TITLE #language en-US "Custom Secure Boot Options" +#string STR_SECURE_BOOT_OPTION_TITLE #language en-US "Advanced Secure Boot Keys Management" +#string STR_SECURE_BOOT_MANUAL_KEY_MGMT #language en-US "Individual key management:" #string STR_SECURE_BOOT_PK_OPTION #language en-US "PK Options" #string STR_SECURE_BOOT_PK_OPTION_HELP #language en-US "Enroll/Delete PK" @@ -90,6 +99,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #string STR_SECURE_BOOT_DBT_OPTION #language en-US "DBT Options" #string STR_SECURE_BOOT_DBT_OPTION_HELP #language en-US "Enroll/Delete DBT" +#string STR_PK_INFO #language en-US "Currently enrolled PK:" +#string STR_PK_NAME #language en-US "*NO COMMON NAME*" #string STR_ENROLL_PK #language en-US "Enroll PK" #string STR_ENROLL_PK_HELP #language en-US "Enter into Enroll PK Form" #string STR_SAVE_PK_FILE #language en-US "Save PK file" diff --git a/SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.c b/SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.c index 2f6f3e6796..0e5044d9e1 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.c +++ b/SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.c @@ -12,12 +12,104 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include #include +#include #include #include #include #include #include +#include + +STATIC +EFI_STATUS +EnrollKeysFromDefaults ( + VOID +) +{ + EFI_STATUS Status; + UINT8 SetupMode; + + Status = EFI_SUCCESS; + + // After PK clear, Setup Mode shall be enabled + Status = GetSetupMode (&SetupMode); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Cannot get SetupMode variable: %r\n", + Status)); + return Status; + } + + if (SetupMode == USER_MODE) { + DEBUG((DEBUG_INFO, "Skipped - USER_MODE\n")); + return EFI_SUCCESS; + } + + Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Cannot set CUSTOM_SECURE_BOOT_MODE: %r\n", + Status)); + return EFI_SUCCESS; + } + + // Enroll all the keys from default variables + Status = EnrollDbFromDefault (); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Cannot enroll db: %r\n", Status)); + goto error; + } + + Status = EnrollDbxFromDefault (); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Cannot enroll dbx: %r\n", Status)); + } + + Status = EnrollDbtFromDefault (); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Cannot enroll dbt: %r\n", Status)); + } + + Status = EnrollKEKFromDefault (); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Cannot enroll KEK: %r\n", Status)); + goto cleardbs; + } + + Status = EnrollPKFromDefault (); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Cannot enroll PK: %r\n", Status)); + goto clearKEK; + } + + DEBUG ((DEBUG_INFO, "Setting Secure Boot state to: %d\n", FixedPcdGet8(PcdSecureBootDefaultEnable))); + Status = SetSecureBootState (FixedPcdGet8(PcdSecureBootDefaultEnable)); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Cannot set Secure Boot state: %r\n", Status)); + } + + Status = SetSecureBootMode (STANDARD_SECURE_BOOT_MODE); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Cannot set CustomMode to STANDARD_SECURE_BOOT_MODE\n" + "Please do it manually, otherwise system can be easily compromised\n")); + } + + return Status; + +clearKEK: + DeleteKEK (); + +cleardbs: + DeleteDbt (); + DeleteDbx (); + DeleteDb (); + +error: + if (SetSecureBootMode (STANDARD_SECURE_BOOT_MODE) != EFI_SUCCESS) { + DEBUG ((DEBUG_ERROR, "Cannot set mode to Secure: %r\n", Status)); + } + return Status; +} /** The entry point for SecureBootDefaultKeys driver. @@ -38,7 +130,8 @@ SecureBootDefaultKeysEntryPoint ( IN EFI_SYSTEM_TABLE *SystemTable ) { - EFI_STATUS Status; + EFI_STATUS Status; + EFI_BOOT_MODE BootMode; Status = SecureBootInitPKDefault (); if (EFI_ERROR (Status)) { @@ -74,5 +167,14 @@ SecureBootDefaultKeysEntryPoint ( return Status; } + BootMode = GetBootModeHob (); + if (BootMode == BOOT_WITH_DEFAULT_SETTINGS || BootMode == BOOT_WITH_MFG_MODE_SETTINGS) { + Status = EnrollKeysFromDefaults (); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Cannot enroll keys from defaults: %r\n", __func__, Status)); + return Status; + } + } + return EFI_SUCCESS; } diff --git a/SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.inf b/SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.inf index 3ed45fa497..e3dcca5da1 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.inf +++ b/SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.inf @@ -30,6 +30,8 @@ MemoryAllocationLib UefiDriverEntryPoint DebugLib + HobLib + PcdLib SecureBootVariableLib SecureBootVariableProvisionLib @@ -41,6 +43,9 @@ ## SOMETIMES_PRODUCES ## Variable:L"dbxDefault" gEfiGlobalVariableGuid +[Pcd] + gEfiSecurityPkgTokenSpaceGuid.PcdSecureBootDefaultEnable + [Depex] gEfiVariableArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c index 748cf8d3bf..4ecfa86f56 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c @@ -157,7 +157,7 @@ CommonExceptionHandlerWorker ( // // Enter a dead loop if needn't to execute old IDT handler further // - if (ReservedVectors[ExceptionType].Attribute != EFI_VECTOR_HANDOFF_HOOK_BEFORE) { + if (ReservedVectors[ExceptionType].Attribute != EFI_VECTOR_HANDOFF_HOOK_BEFORE && ExceptionType != EXCEPT_IA32_DEBUG) { CpuDeadLoop (); } } diff --git a/UefiCpuPkg/Library/MtrrLib/MtrrLib.c b/UefiCpuPkg/Library/MtrrLib/MtrrLib.c index 4d4b52a4c3..ffce10ff0a 100644 --- a/UefiCpuPkg/Library/MtrrLib/MtrrLib.c +++ b/UefiCpuPkg/Library/MtrrLib/MtrrLib.c @@ -161,6 +161,10 @@ MtrrLibIsMtrrSupported ( CPUID_VERSION_INFO_EDX Edx; MSR_IA32_MTRRCAP_REGISTER MtrrCap; + if (PcdGetBool (PcdCpuDisableMtrrProgramming)) { + return FALSE; + } + // // Check CPUID(1).EDX[12] for MTRR capability // diff --git a/UefiCpuPkg/Library/MtrrLib/MtrrLib.inf b/UefiCpuPkg/Library/MtrrLib/MtrrLib.inf index 4c9ea2def3..611fdc7047 100644 --- a/UefiCpuPkg/Library/MtrrLib/MtrrLib.inf +++ b/UefiCpuPkg/Library/MtrrLib/MtrrLib.inf @@ -37,4 +37,4 @@ [Pcd] gUefiCpuPkgTokenSpaceGuid.PcdCpuNumberOfReservedVariableMtrrs ## SOMETIMES_CONSUMES - + gUefiCpuPkgTokenSpaceGuid.PcdCpuDisableMtrrProgramming ## CONSUMES diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec index 571b59b36f..4b94b93c9f 100644 --- a/UefiCpuPkg/UefiCpuPkg.dec +++ b/UefiCpuPkg/UefiCpuPkg.dec @@ -270,6 +270,10 @@ # @Prompt SMM Code Access Check. gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmCodeAccessCheckEnable|TRUE|BOOLEAN|0x60000013 + ## Disables MTRR programming in case it's already programmed by FSB. + # @Prompt Disable MTRR programming. + gUefiCpuPkgTokenSpaceGuid.PcdCpuDisableMtrrProgramming|FALSE|BOOLEAN|0x00000017 + ## Specifies the number of variable MTRRs reserved for OS use. The default number of # MTRRs reserved for OS use is 2. # @Prompt Number of reserved variable MTRRs. diff --git a/UefiCpuPkg/UefiCpuPkg.uni b/UefiCpuPkg/UefiCpuPkg.uni index d17bcfd10c..1a7d3ca5ea 100644 --- a/UefiCpuPkg/UefiCpuPkg.uni +++ b/UefiCpuPkg/UefiCpuPkg.uni @@ -152,6 +152,10 @@ #string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuHotPlugDataAddress_HELP #language en-US "Contains the pointer to a CPU Hot Plug Data structure if CPU hot-plug is supported." +#string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuDisableMtrrProgramming_PROMPT #language en-US "Disable MTRR programming" + +#string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuDisableMtrrProgramming_HELP #language en-US "Disables MTRR programming in case it's already programmed by FSB." + #string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuNumberOfReservedVariableMtrrs_PROMPT #language en-US "Number of reserved variable MTRRs" #string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuNumberOfReservedVariableMtrrs_HELP #language en-US "Specifies the number of variable MTRRs reserved for OS use."