diff --git a/.github/workflows/build_testcases.yml b/.github/workflows/build_testcases.yml new file mode 100644 index 0000000..bcbb6c3 --- /dev/null +++ b/.github/workflows/build_testcases.yml @@ -0,0 +1,54 @@ +--- +name: Build Testcases + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + +jobs: + build_test_artifacts: + name: Build Testcases + runs-on: ubuntu-22.04 + container: + image: ghcr.io/tianocore/containers/ubuntu-22-build + defaults: + run: + shell: bash + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: Install Dependencies + run: | + sudo apt-get -y update && \ + sudo apt-get -y install \ + clang libclang-dev llvm + - name: Retrieve and build EDK2 + run: | + git clone https://github.com/tianocore/edk2.git --recursive && \ + pushd edk2 && make -C BaseTools && \ + source edksetup.sh && popd && \ + export -p > envsave + - name: Setting up HBFA-FL and Build Environment + run: | + source envsave && \ + export WORKSPACE=$(pwd)/ && \ + export PACKAGES_PATH=$WORKSPACE/edk2:$WORKSPACE/HBFA/ && \ + python3 HBFA/UefiHostTestTools/HBFAEnvSetup.py && \ + export -p > envsave + - name: Install AFL-2.52b + run: | + source envsave && \ + wget -q http://lcamtuf.coredump.cx/afl/releases/afl-latest.tgz && \ + tar xf afl-latest.tgz && rm afl-latest.tgz && \ + export AFL_PATH=$WORKSPACE/afl-2.52b && \ + export PATH=$PATH:$AFL_PATH && \ + export -p > envsave && \ + cd afl-2.52b && make && cd .. + - name: Build Fuzzing Harnesses + run: | + source envsave && \ + cp HBFA/UefiHostFuzzTestPkg/Conf/build_rule.txt edk2/Conf/build_rule.txt && \ + cp HBFA/UefiHostFuzzTestPkg/Conf/tools_def.txt edk2/Conf/tools_def.txt && \ + build -p HBFA/UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dsc -a X64 -t AFL && \ + build -p HBFA/UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dsc -a X64 -t LIBFUZZER diff --git a/BOM.txt b/BOM.txt new file mode 100644 index 0000000..e69de29 diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 0000000..34df6cd --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,17 @@ +cff-version: 1.2.0 +message: "If you use this software, please cite it as below." +authors: +- family-names: "Tipton" + given-names: "Earl Lynn" + orcid: "https://orcid.org/0000-0003-0763-173X" +- family-names: "Delgado" + given-names: "Brian" +- family-names: "Bjorge" + given-names: "Erik C." +- family-names: "Gomez-Iglesias" + given-names: "Antonio" +title: "Host Based Firmware Analyzer - Fuzzing Lite (HBFA-FL)" +version: 0.11 +doi: "" +date-released: 2024-02-19 +url: "https://github.com/intel/HBFA-FL" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f682f4e..0f02678 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,7 @@ ### License - is licensed under the terms in [LICENSE]. By contributing to the project, you agree to the license and copyright terms therein and release your contribution under these terms. +HBFA-FL is licensed under the terms in [LICENSE](LICENSE.md). By contributing to the project, you agree to the license and copyright terms therein and release your contribution under these terms. ### Sign your work diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Ata/Raw/IdentifyData.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Ata/Raw/IdentifyData.bin new file mode 100644 index 0000000..7b838ec Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/Ata/Raw/IdentifyData.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/1.bmp b/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/1.bmp new file mode 100644 index 0000000..59262c3 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/1.bmp differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/16.bmp b/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/16.bmp new file mode 100644 index 0000000..9190319 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/16.bmp differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/16_1.bmp b/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/16_1.bmp new file mode 100644 index 0000000..24303e6 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/16_1.bmp differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/24.bmp b/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/24.bmp new file mode 100644 index 0000000..e20d8bd Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/24.bmp differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/32.bmp b/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/32.bmp new file mode 100644 index 0000000..5082735 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/32.bmp differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/4.bmp b/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/4.bmp new file mode 100644 index 0000000..0fd2558 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/4.bmp differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/4_1.bmp b/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/4_1.bmp new file mode 100644 index 0000000..84b619b Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/4_1.bmp differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/8.bmp b/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/8.bmp new file mode 100644 index 0000000..22b24bc Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/8.bmp differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/8_1.bmp b/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/8_1.bmp new file mode 100644 index 0000000..145ea54 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/8_1.bmp differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/sample.bmp b/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/sample.bmp new file mode 100644 index 0000000..a31442f Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/sample.bmp differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Blk/VirtioBlkFuzzSeed0.9.5.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Blk/VirtioBlkFuzzSeed0.9.5.bin new file mode 100644 index 0000000..fb4d7d9 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/Blk/VirtioBlkFuzzSeed0.9.5.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Blk/VirtioBlkFuzzSeed1.0.0.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Blk/VirtioBlkFuzzSeed1.0.0.bin new file mode 100644 index 0000000..519b15d Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/Blk/VirtioBlkFuzzSeed1.0.0.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Blk/VirtioBlkFuzzSeed1.0.0_fix.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Blk/VirtioBlkFuzzSeed1.0.0_fix.bin new file mode 100644 index 0000000..6c34b35 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/Blk/VirtioBlkFuzzSeed1.0.0_fix.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Capsule/MICROCODECAPSULE1.Cap b/HBFA/UefiHostFuzzTestCasePkg/Seed/Capsule/MICROCODECAPSULE1.Cap new file mode 100644 index 0000000..a7ce321 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/Capsule/MICROCODECAPSULE1.Cap differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Capsule/QUARKFIRMWAREUPDATECAPSULEFMPPKCS7.Cap b/HBFA/UefiHostFuzzTestCasePkg/Seed/Capsule/QUARKFIRMWAREUPDATECAPSULEFMPPKCS7.Cap new file mode 100644 index 0000000..c9d151b Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/Capsule/QUARKFIRMWAREUPDATECAPSULEFMPPKCS7.Cap differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Capsule/QUARKREC.Cap b/HBFA/UefiHostFuzzTestCasePkg/Seed/Capsule/QUARKREC.Cap new file mode 100644 index 0000000..6db50fe Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/Capsule/QUARKREC.Cap differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Cfv/cfv01.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Cfv/cfv01.bin new file mode 100644 index 0000000..b9c7023 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/Cfv/cfv01.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Cfv/securebootcfv01.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Cfv/securebootcfv01.bin new file mode 100644 index 0000000..86c96c3 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/Cfv/securebootcfv01.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Gpt/Raw/Gpt.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Gpt/Raw/Gpt.bin new file mode 100644 index 0000000..6f25330 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/Gpt/Raw/Gpt.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Gpt/Raw/Gpt_16384.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Gpt/Raw/Gpt_16384.bin new file mode 100644 index 0000000..ed85484 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/Gpt/Raw/Gpt_16384.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Gpt/Raw/Gpt_error.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Gpt/Raw/Gpt_error.bin new file mode 100644 index 0000000..8794aa4 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/Gpt/Raw/Gpt_error.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Include/Uefi.py b/HBFA/UefiHostFuzzTestCasePkg/Seed/Include/Uefi.py new file mode 100644 index 0000000..4f07156 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/Seed/Include/Uefi.py @@ -0,0 +1,41 @@ +# @file +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +import ctypes + + +class EFI_GUID(ctypes.Structure): + _fields_ = [ + ('Guid1', ctypes.c_uint32), + ('Guid2', ctypes.c_uint16), + ('Guid3', ctypes.c_uint16), + ('Guid4', ctypes.ARRAY(ctypes.c_uint8, 8)), + ] + + +class EFI_TIME(ctypes.Structure): + _fields_ = [ + ('Year', ctypes.c_uint16), + ('Month', ctypes.c_uint8), + ('Day', ctypes.c_uint8), + ('Hour', ctypes.c_uint8), + ('Minute', ctypes.c_uint8), + ('Second', ctypes.c_uint8), + ('Pad1', ctypes.c_uint8), + ('Nanosecond', ctypes.c_uint32), + ('TimeZone', ctypes.c_int16), + ('Daylight', ctypes.c_uint8), + ('Pad2', ctypes.c_uint8), + ] + + +EFI_VARIABLE_NON_VOLATILE = 0x00000001 +EFI_VARIABLE_BOOTSERVICE_ACCESS = 0x00000002 +EFI_VARIABLE_RUNTIME_ACCESS = 0x00000004 +EFI_VARIABLE_HARDWARE_ERROR_RECORD = 0x00000008 +EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS = 0x00000020 +EFI_VARIABLE_APPEND_WRITE = 0x00000040 +EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS = 0x00000010 diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction000.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction000.bin new file mode 100644 index 0000000..2555af5 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction000.bin @@ -0,0 +1 @@ +ˆ \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction001.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction001.bin new file mode 100644 index 0000000..3d305f2 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction001.bin @@ -0,0 +1 @@ +f‰ \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction002.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction002.bin new file mode 100644 index 0000000..d21fd1b --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction002.bin @@ -0,0 +1 @@ +‰ \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction003.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction003.bin new file mode 100644 index 0000000..e02d793 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction003.bin @@ -0,0 +1 @@ +H‰ \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction004.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction004.bin new file mode 100644 index 0000000..6239526 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction004.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction005.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction005.bin new file mode 100644 index 0000000..8f6b929 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction005.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction006.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction006.bin new file mode 100644 index 0000000..8afd49e Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction006.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction007.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction007.bin new file mode 100644 index 0000000..6fe51b3 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction007.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction008.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction008.bin new file mode 100644 index 0000000..26fddd4 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction008.bin @@ -0,0 +1 @@ +Š \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction009.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction009.bin new file mode 100644 index 0000000..f66cf3a --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction009.bin @@ -0,0 +1 @@ +f‹ \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction010.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction010.bin new file mode 100644 index 0000000..56250ef --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction010.bin @@ -0,0 +1 @@ +‹ \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction011.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction011.bin new file mode 100644 index 0000000..b84bb66 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction011.bin @@ -0,0 +1 @@ +H‹ \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction012.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction012.bin new file mode 100644 index 0000000..35d7872 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction012.bin @@ -0,0 +1 @@ +f¶ \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction013.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction013.bin new file mode 100644 index 0000000..defc96a --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction013.bin @@ -0,0 +1 @@ +¶ \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction014.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction014.bin new file mode 100644 index 0000000..260f915 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction014.bin @@ -0,0 +1 @@ +H¶ \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction015.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction015.bin new file mode 100644 index 0000000..c2d5e26 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction015.bin @@ -0,0 +1 @@ +· \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction016.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction016.bin new file mode 100644 index 0000000..af4a857 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction016.bin @@ -0,0 +1 @@ +H· \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction017.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction017.bin new file mode 100644 index 0000000..a318189 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction017.bin @@ -0,0 +1 @@ +f¾ \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction018.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction018.bin new file mode 100644 index 0000000..90d66e2 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction018.bin @@ -0,0 +1 @@ +¾ \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction019.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction019.bin new file mode 100644 index 0000000..e4e8440 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction019.bin @@ -0,0 +1 @@ +H¾ \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction020.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction020.bin new file mode 100644 index 0000000..4295aca --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction020.bin @@ -0,0 +1 @@ +¿ \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction021.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction021.bin new file mode 100644 index 0000000..ada3def --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction021.bin @@ -0,0 +1 @@ +H¿ \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction022.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction022.bin new file mode 100644 index 0000000..8b43442 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction022.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction023.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction023.bin new file mode 100644 index 0000000..4f3893d Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction023.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction024.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction024.bin new file mode 100644 index 0000000..822330d Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction024.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction025.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction025.bin new file mode 100644 index 0000000..7bab811 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction025.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction026.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction026.bin new file mode 100644 index 0000000..3d3553e Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/Instruction/instruction026.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/Mutator/MutatorSimple.py b/HBFA/UefiHostFuzzTestCasePkg/Seed/Mutator/MutatorSimple.py new file mode 100644 index 0000000..7c8e206 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/Seed/Mutator/MutatorSimple.py @@ -0,0 +1,219 @@ +# @file +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +MutatorSimple +''' + +import os +import argparse +import subprocess +import random + +# +# Globals for help information +# +__prog__ = 'MutatorSimple' +__version__ = '%s Version %s' % (__prog__, '0.11 ') +__copyright__ = 'Copyright (c) 2018, Intel Corporation. All rights reserved.' +__usage__ = '%s [options] -e ' % (__prog__) + + +def WriteFile(): + args.OutputFile = open(args.OutputFileName, 'wb') + args.OutputFile.write(args.InputBuffer) + args.OutputFile.close() + + +def GenerateCommand(Command, InputFile): + Template = " " + CommandLine = Template.replace("", + Command).replace("", InputFile) + return CommandLine + + +def CallCommand(CommandLine): + subprocess.Popen(CommandLine, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + shell=False) + + +def RunCase(): + CallCommand(GenerateCommand(args.Executable, args.OutputFileName)) + + +def DelCase(): + os.remove(args.OutputFileName) + + +if __name__ == '__main__': + # + # Create command line argument parser object + # + parser = argparse.ArgumentParser(prog=__prog__, + usage=__usage__, + description=__copyright__, + conflict_handler='resolve') + parser.add_argument('--version', action='version', version=__version__) + parser.add_argument("-v", "--verbose", dest='Verbose', + action="store_true", + help="increase output messages") + parser.add_argument("-q", "--quiet", dest='Quiet', action="store_true", + help="reduce output messages") + parser.add_argument(metavar="input_file", dest='InputFile', + type=argparse.FileType('rb'), + help="specify the input file") + parser.add_argument("--Offset", dest='Offset_Str', type=str, + help="specify the offset of buffer to be mutated.") + parser.add_argument("--Size", dest='Size_Str', type=str, + help="specify the size of buffer to be mutated.") + parser.add_argument("-e", "--exec", dest='Executable', type=str, + metavar='filename', + help="specify the executable filename", + required=True) + + # + # Parse command line arguments + # + args = parser.parse_args() + + # + # Read input file into a buffer and save input filename + # + args.InputFileName = args.InputFile.name + args.InputFileBuffer = args.InputFile.read() + args.InputFile.seek(0, 2) + InputFileSize = args.InputFile.tell() + args.InputFile.close() + + print("file size - 0x%x (%d)" % (InputFileSize, InputFileSize)) + + args.Offset = 0x0 + if args.Offset_Str: + try: + if args.Offset_Str.upper().startswith('0X'): + args.Offset = (int)(args.Offset_Str, 16) + else: + args.Offset = (int)(args.Offset_Str) + except Exception as error: + print("Unexpected format for Offset: %s" % (error)) + pass + + args.Size = InputFileSize + if args.Size_Str: + try: + if args.Size_Str.upper().startswith('0X'): + args.Size = (int)(args.Size_Str, 16) + else: + args.Size = (int)(args.Size_Str) + except Exception as error: + print("Unexpected format for input file size: %s" % (error)) + pass + + print("fuzz offset - 0x%x (%d)" % (args.Offset, args.Offset)) + print("fuzz size - 0x%x (%d)" % (args.Size, args.Size)) + + # + # mutation + # + args.InputBuffer = bytearray(args.InputFileBuffer) + + # UINT8 based mutation + for Index in range(args.Offset, args.Offset + args.Size): + OrgData = args.InputBuffer[Index:Index+1] + + # + # mutate + # + RandomData = random.randint(0, 0xFF) + args.InputBuffer[Index:Index+1] = [RandomData] + + # + # Write output file + # + args.OutputFileName = args.InputFileName + "_b_" + str(Index) + ".bin" + WriteFile() + RunCase() + DelCase() + + args.InputBuffer[Index:Index+1] = OrgData + + # UINT16 based mutation + for Index in range(args.Offset, args.Offset + args.Size - 1): + OrgData = args.InputBuffer[Index:Index+2] + + # + # mutate + # + RandomData = random.randint(0, 0xFF) + RandomData2 = random.randint(0, 0xFF) + args.InputBuffer[Index:Index+2] = [RandomData, RandomData2] + + # + # Write output file + # + args.OutputFileName = args.InputFileName + "_w_" + str(Index) + ".bin" + WriteFile() + RunCase() + DelCase() + + args.InputBuffer[Index:Index+2] = OrgData + + # UINT32 based mutation + for Index in range(args.Offset, args.Offset + args.Size - 3): + OrgData = args.InputBuffer[Index:Index+4] + + # + # mutate + # + RandomData = random.randint(0, 0xFF) + RandomData2 = random.randint(0, 0xFF) + RandomData3 = random.randint(0, 0xFF) + RandomData4 = random.randint(0, 0xFF) + args.InputBuffer[Index:Index+4] = [RandomData, RandomData2, + RandomData3, RandomData4] + + # + # Write output file + # + args.OutputFileName = args.InputFileName + "_d_" + str(Index) + ".bin" + WriteFile() + RunCase() + DelCase() + + args.InputBuffer[Index:Index+4] = OrgData + + # UINT64 based mutation + for Index in range(args.Offset, args.Offset + args.Size - 7): + OrgData = args.InputBuffer[Index:Index+8] + + # + # mutate + # + RandomData = random.randint(0, 0xFF) + RandomData2 = random.randint(0, 0xFF) + RandomData3 = random.randint(0, 0xFF) + RandomData4 = random.randint(0, 0xFF) + RandomData5 = random.randint(0, 0xFF) + RandomData6 = random.randint(0, 0xFF) + RandomData7 = random.randint(0, 0xFF) + RandomData8 = random.randint(0, 0xFF) + args.InputBuffer[Index:Index+8] = [RandomData, RandomData2, + RandomData3, RandomData4, + RandomData5, RandomData6, + RandomData7, RandomData8] + + # + # Write output file + # + args.OutputFileName = args.InputFileName + "_q_" + str(Index) + ".bin" + WriteFile() + RunCase() + DelCase() + + args.InputBuffer[Index:Index+8] = OrgData diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/SignatureList/SignatureList.raw b/HBFA/UefiHostFuzzTestCasePkg/Seed/SignatureList/SignatureList.raw new file mode 100644 index 0000000..1669510 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/SignatureList/SignatureList.raw differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/TPM/Raw/Tpm2Res.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/TPM/Raw/Tpm2Res.bin new file mode 100644 index 0000000..eafa9b4 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/TPM/Raw/Tpm2Res.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/TPM/Script/SeedGenTpm2Response.py b/HBFA/UefiHostFuzzTestCasePkg/Seed/TPM/Script/SeedGenTpm2Response.py new file mode 100644 index 0000000..3f9ea37 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/Seed/TPM/Script/SeedGenTpm2Response.py @@ -0,0 +1,123 @@ +# @file +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +SeedGenTpm2Response +''' + +import os +import sys +import argparse +import socket +import ctypes + +IncludePath = os.path.join(os.path.dirname( + os.path.dirname(os.path.dirname(os.path.realpath(__file__)))), 'Include') +sys.path.append(IncludePath) + +# +# Globals for help information +# +__prog__ = 'SeedGenTpm2Response' +__version__ = '%s Version %s' % (__prog__, '0.11 ') +__copyright__ = 'Copyright (c) 2018, Intel Corporation. All rights reserved.' +__usage__ = '%s [options] -o ' % (__prog__) + +TPM_ALG_SHA1 = 0x0004 +TPM_ALG_SHA256 = 0x000B +TPM_ALG_SHA384 = 0x000C +TPM_ALG_SHA512 = 0x000D +TPM_ALG_SM3_256 = 0x0012 + +TPM_ST_NO_SESSIONS = 0x8001 +TPM_ST_SESSIONS = 0x8002 + +TPM_RC_SUCCESS = 0x000 + + +class TPM2_RESPONSE_HEADER(ctypes.Structure): + _fields_ = [ + ('Dummy', ctypes.c_uint16), + ('tag', ctypes.c_uint16), + ('paramSize', ctypes.c_uint32), + ('responseCode', ctypes.c_uint32), + ] + + +class TPMT_HA(ctypes.Structure): + _fields_ = [ + ('hashAlg', ctypes.c_uint16), + ('digest', ctypes.ARRAY(ctypes.c_uint8, 32)), + ] + + +class TPML_DIGEST_VALUES(ctypes.Structure): + _fields_ = [ + ('count', ctypes.c_uint32), + ('digests', ctypes.ARRAY(TPMT_HA, 100)), + ] + + +class TPMS_AUTH_RESPONSE(ctypes.Structure): + _fields_ = [ + ('dummy', ctypes.ARRAY(ctypes.c_uint8, 10)), + ] + + +class TPM2_PCR_EVENT_RESPONSE(ctypes.Structure): + _fields_ = [ + ('Header', TPM2_RESPONSE_HEADER), + ('ParameterSize', ctypes.c_uint32), + ('Digests', TPML_DIGEST_VALUES), + ('AuthSessionPcr', TPMS_AUTH_RESPONSE), + ] + + +if __name__ == '__main__': + # + # Create command line argument parser object + # + parser = argparse.ArgumentParser(prog=__prog__, + usage=__usage__, + description=__copyright__, + conflict_handler='resolve') + parser.add_argument('--version', action='version', version=__version__) + parser.add_argument("-v", "--verbose", dest='Verbose', + action="store_true", help="increase output messages") + parser.add_argument("-q", "--quiet", dest='Quiet', action="store_true", + help="reduce output messages") + parser.add_argument("-o", "--output", dest='OutputFileName', type=str, + metavar='filename', + help="specify the output filename", required=True) + + # + # Parse command line arguments + # + args = parser.parse_args() + + # + # Write output file + # + args.OutputFile = open(args.OutputFileName, 'wb') + + DummyBuf = ctypes.create_string_buffer( + ctypes.sizeof(TPM2_PCR_EVENT_RESPONSE)) + + Tpm2PcrEventResponse = TPM2_PCR_EVENT_RESPONSE.from_buffer(DummyBuf, 0) + Tpm2PcrEventResponse.Header.tag = socket.ntohs(TPM_ST_SESSIONS) + Tpm2PcrEventResponse.Header.paramSize = socket.ntohl(0x56) \ + # socket.ntohl(sizeof(TPM2_PCR_EVENT_RESPONSE) - 2) + Tpm2PcrEventResponse.Header.responseCode = socket.ntohl(TPM_RC_SUCCESS) + Tpm2PcrEventResponse.ParameterSize = socket.ntohl(0x56) \ + # socket.ntohl(sizeof(TPM2_PCR_EVENT_RESPONSE) - 2) + Tpm2PcrEventResponse.Digests.count = socket.ntohl(0x100) + for i in range(0, 100): + Tpm2PcrEventResponse.Digests.digests[i].hashAlg = \ + socket.ntohs(TPM_ALG_SHA256) + + args.OutputFile.write(DummyBuf[2:]) + + args.OutputFile.close() diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/TdxHob/hob.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/TdxHob/hob.bin new file mode 100644 index 0000000..4dc8248 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/TdxHob/hob.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/0 b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/0 new file mode 100644 index 0000000..e69de29 diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/1 b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/1 new file mode 100644 index 0000000..05ef784 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/1 differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/2 b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/2 new file mode 100644 index 0000000..2531096 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/2 differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/22 b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/22 new file mode 100644 index 0000000..dc77942 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/22 differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/__a b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/__a new file mode 100644 index 0000000..89bccac Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/__a differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/a b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/a new file mode 100644 index 0000000..5c1a217 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/a differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/b b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/b new file mode 100644 index 0000000..98954db Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/b differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/b_a b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/b_a new file mode 100644 index 0000000..fcd633d Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/b_a differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/b_c b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/b_c new file mode 100644 index 0000000..a4b0eb2 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/b_c differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/blink b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/blink new file mode 100644 index 0000000..5853893 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/blink differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/blink_a b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/blink_a new file mode 100644 index 0000000..29d68c6 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/blink_a differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/blink_alink b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/blink_alink new file mode 100644 index 0000000..e939d64 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/blink_alink differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/blink_c_ b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/blink_c_ new file mode 100644 index 0000000..2269686 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName/blink_c_ differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_123.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_123.bin new file mode 100644 index 0000000..8f3f9af Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_123.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_a.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_a.bin new file mode 100644 index 0000000..72f2d5a Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_a.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_a_0.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_a_0.bin new file mode 100644 index 0000000..7df95d5 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_a_0.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_a_e1.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_a_e1.bin new file mode 100644 index 0000000..212db4c Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_a_e1.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_a_mm.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_a_mm.bin new file mode 100644 index 0000000..8ebc101 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_a_mm.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_a_mm_f.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_a_mm_f.bin new file mode 100644 index 0000000..ba333a7 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_a_mm_f.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_a_mm_ff.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_a_mm_ff.bin new file mode 100644 index 0000000..1dc21d6 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_a_mm_ff.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_all.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_all.bin new file mode 100644 index 0000000..51b5a51 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_all.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_ca.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_ca.bin new file mode 100644 index 0000000..97301fd Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_ca.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_udf.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_udf.bin new file mode 100644 index 0000000..d943135 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_udf.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_udf_fid.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_udf_fid.bin new file mode 100644 index 0000000..c300bad Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_udf_fid.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_udf_m.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_udf_m.bin new file mode 100644 index 0000000..f04718b Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_udf_m.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_udf_m1.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_udf_m1.bin new file mode 100644 index 0000000..32f9e42 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_udf_m1.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_udf_m3.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_udf_m3.bin new file mode 100644 index 0000000..6be7652 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_udf_m3.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_udf_m4.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_udf_m4.bin new file mode 100644 index 0000000..21f7f3e Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_udf_m4.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_udf_m5_16.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_udf_m5_16.bin new file mode 100644 index 0000000..4711559 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_udf_m5_16.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_udf_m5_17.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_udf_m5_17.bin new file mode 100644 index 0000000..c869284 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_udf_m5_17.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_udf_m5_double.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_udf_m5_double.bin new file mode 100644 index 0000000..0ae99dc Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem/test_udf_m5_double.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/Udf_1.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/Udf_1.bin new file mode 100644 index 0000000..166e485 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/Udf_1.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/Udf_2.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/Udf_2.bin new file mode 100644 index 0000000..57be701 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/Udf_2.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/Udf_3.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/Udf_3.bin new file mode 100644 index 0000000..7e0ee5a Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/Udf_3.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/Udf_linux.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/Udf_linux.bin new file mode 100644 index 0000000..df6f28d Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/Udf_linux.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000001.seed b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000001.seed new file mode 100644 index 0000000..8dd9b32 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000001.seed differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000002.seed b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000002.seed new file mode 100644 index 0000000..0b8054b Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000002.seed differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000003.seed b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000003.seed new file mode 100644 index 0000000..b88af2f Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000003.seed differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000004.seed b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000004.seed new file mode 100644 index 0000000..06e5989 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000004.seed differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000005.seed b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000005.seed new file mode 100644 index 0000000..f06db4e Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000005.seed differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000006.seed b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000006.seed new file mode 100644 index 0000000..a4bb7f6 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000006.seed differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000007.seed b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000007.seed new file mode 100644 index 0000000..126173f Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000007.seed differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000008.seed b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000008.seed new file mode 100644 index 0000000..bf8e569 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000008.seed differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000009.seed b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000009.seed new file mode 100644 index 0000000..a5dd736 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000009.seed differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000010.seed b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000010.seed new file mode 100644 index 0000000..bacb3b7 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000010.seed differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000011.seed b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000011.seed new file mode 100644 index 0000000..ea12a9d Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000011.seed differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000012.seed b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000012.seed new file mode 100644 index 0000000..526e77a Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000012.seed differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000013.seed b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000013.seed new file mode 100644 index 0000000..33859d4 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000013.seed differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000014.seed b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000014.seed new file mode 100644 index 0000000..341b864 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000014.seed differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000015.seed b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000015.seed new file mode 100644 index 0000000..c4060e7 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000015.seed differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000016.seed b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000016.seed new file mode 100644 index 0000000..b03f2bc Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000016.seed differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000017.seed b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000017.seed new file mode 100644 index 0000000..b1f3604 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000017.seed differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000018.seed b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000018.seed new file mode 100644 index 0000000..d66ffa9 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000018.seed differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000019.seed b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000019.seed new file mode 100644 index 0000000..013fe93 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000019.seed differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000020.seed b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000020.seed new file mode 100644 index 0000000..53d0acd Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000020.seed differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000021.seed b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000021.seed new file mode 100644 index 0000000..31b9663 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000021.seed differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000022.seed b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000022.seed new file mode 100644 index 0000000..fbf9ec2 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000022.seed differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000023.seed b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000023.seed new file mode 100644 index 0000000..71c5653 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000023.seed differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000024.seed b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000024.seed new file mode 100644 index 0000000..3d78d0e Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition/test000024.seed differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/readme.txt b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/readme.txt new file mode 100644 index 0000000..e69de29 diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Script/SeedGenUdf.py b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Script/SeedGenUdf.py new file mode 100644 index 0000000..659a3f1 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Script/SeedGenUdf.py @@ -0,0 +1,108 @@ +# @file +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +SeedGenUdf +''' + +import argparse +import ctypes +import Udf + +# +# Globals for help information +# +__prog__ = 'SeedGenUdf' +__version__ = '%s Version %s' % (__prog__, '0.11 ') +__copyright__ = 'Copyright (c) 2018, Intel Corporation. All rights reserved.' +__usage__ = '%s [options] -o ' % (__prog__) + +TOTAL_SIZE = 1 * 1024 * 1024 +BLOCK_SIZE = 2048 + +if __name__ == '__main__': + # + # Create command line argument parser object + # + parser = argparse.ArgumentParser(prog=__prog__, + usage=__usage__, + description=__copyright__, + conflict_handler='resolve') + parser.add_argument('--version', action='version', version=__version__) + parser.add_argument("-v", "--verbose", dest='Verbose', action="store_true", + help="increase output messages") + parser.add_argument("-q", "--quiet", dest='Quiet', action="store_true", + help="reduce output messages") + parser.add_argument("-o", "--output", dest='OutputFileName', type=str, + metavar='filename', help="specify the output filename", + required=True) + + # + # Parse command line arguments + # + args = parser.parse_args() + + # + # Write output file + # + args.OutputFile = open(args.OutputFileName, 'wb') + + DummyBuf = ctypes.create_string_buffer(TOTAL_SIZE) + Udf.CdromDesc = Udf.CDROM_VOLUME_DESCRIPTOR.from_buffer( + DummyBuf, + Udf.UDF_VRS_START_OFFSET) + Udf.CdromDesc.Id[0] = (ord('B')) + Udf.CdromDesc.Id[1] = (ord('E')) + Udf.CdromDesc.Id[2] = (ord('A')) + Udf.CdromDesc.Id[3] = (ord('0')) + Udf.CdromDesc.Id[4] = (ord('1')) + + Udf.CdromDesc = Udf.CDROM_VOLUME_DESCRIPTOR.from_buffer( + DummyBuf, + Udf.UDF_VRS_START_OFFSET + Udf.UDF_LOGICAL_SECTOR_SIZE) + Udf.CdromDesc.Id[0] = (ord('N')) + Udf.CdromDesc.Id[1] = (ord('S')) + Udf.CdromDesc.Id[2] = (ord('R')) + Udf.CdromDesc.Id[3] = (ord('0')) + Udf.CdromDesc.Id[4] = (ord('2')) + + Udf.CdromDesc = Udf.CDROM_VOLUME_DESCRIPTOR.from_buffer( + DummyBuf, + Udf.UDF_VRS_START_OFFSET + Udf.UDF_LOGICAL_SECTOR_SIZE * 2) + Udf.CdromDesc.Id[0] = (ord('T')) + Udf.CdromDesc.Id[1] = (ord('E')) + Udf.CdromDesc.Id[2] = (ord('A')) + Udf.CdromDesc.Id[3] = (ord('0')) + Udf.CdromDesc.Id[4] = (ord('1')) + + AnchorDesc = Udf.UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER.from_buffer( + DummyBuf, + 0x100 * BLOCK_SIZE) + (AnchorDesc.DescriptorTag.TagIdentifier + ) = Udf.UDF_VOLUME_DESCRIPTOR_ID.UdfAnchorVolumeDescriptorPointer + + LastBlock = (TOTAL_SIZE + BLOCK_SIZE - 1) // BLOCK_SIZE # - 1 + Offset = (LastBlock - Udf.MAX_CORRECTION_BLOCKS_NUM) * BLOCK_SIZE + (AnchorDesc + ) = Udf.UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER.from_buffer(DummyBuf, Offset) + (AnchorDesc.DescriptorTag.TagIdentifier + ) = Udf.UDF_VOLUME_DESCRIPTOR_ID.UdfAnchorVolumeDescriptorPointer + + SeqBlocksNum = 16 + SeqStartBlock = 16 + (AnchorDesc.MainVolumeDescriptorSequenceExtent.ExtentLength + ) = SeqBlocksNum * BLOCK_SIZE + (AnchorDesc.MainVolumeDescriptorSequenceExtent.ExtentLocation + ) = SeqStartBlock + + Offset = SeqStartBlock * BLOCK_SIZE + DescTag = Udf.UDF_DESCRIPTOR_TAG.from_buffer(DummyBuf, Offset) + (DescTag.TagIdentifier + ) = Udf.UDF_VOLUME_DESCRIPTOR_ID.UdfTerminatingDescriptor + + args.OutputFile.write(DummyBuf) + + args.OutputFile.close() diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Script/Udf.py b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Script/Udf.py new file mode 100644 index 0000000..09e3a54 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Script/Udf.py @@ -0,0 +1,334 @@ +# @file +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +import ctypes + +UDF_LOGICAL_SECTOR_SIZE = 0x800 +UDF_VRS_START_OFFSET = 0x8000 + +MAX_CORRECTION_BLOCKS_NUM = 512 + +UDF_BEA_IDENTIFIER = "BEA01" +UDF_NSR2_IDENTIFIER = "NSR02" +UDF_NSR3_IDENTIFIER = "NSR03" +UDF_TEA_IDENTIFIER = "TEA01" + + +class UDF_VOLUME_DESCRIPTOR_ID: + UdfPrimaryVolumeDescriptor = 1 + UdfAnchorVolumeDescriptorPointer = 2 + UdfVolumeDescriptorPointer = 3 + UdfImplemenationUseVolumeDescriptor = 4 + UdfPartitionDescriptor = 5 + UdfLogicalVolumeDescriptor = 6 + UdfUnallocatedSpaceDescriptor = 7 + UdfTerminatingDescriptor = 8 + UdfLogicalVolumeIntegrityDescriptor = 9 + UdfFileSetDescriptor = 256 + UdfFileIdentifierDescriptor = 257 + UdfAllocationExtentDescriptor = 258 + UdfFileEntry = 261 + UdfExtendedFileEntry = 266 + + TagStringTable = [ + [UdfPrimaryVolumeDescriptor, "UdfPrimaryVolumeDescriptor"], + [UdfAnchorVolumeDescriptorPointer, "UdfAnchorVolumeDescriptorPointer"], + [UdfVolumeDescriptorPointer, "UdfVolumeDescriptorPointer"], + [UdfImplemenationUseVolumeDescriptor, + "UdfImplemenationUseVolumeDescriptor"], + [UdfPartitionDescriptor, "UdfPartitionDescriptor"], + [UdfLogicalVolumeDescriptor, "UdfLogicalVolumeDescriptor"], + [UdfUnallocatedSpaceDescriptor, "UdfUnallocatedSpaceDescriptor"], + [UdfTerminatingDescriptor, "UdfTerminatingDescriptor"], + [UdfLogicalVolumeIntegrityDescriptor, + "UdfLogicalVolumeIntegrityDescriptor"], + [UdfFileSetDescriptor, "UdfFileSetDescriptor"], + [UdfFileIdentifierDescriptor, "UdfFileIdentifierDescriptor"], + [UdfAllocationExtentDescriptor, "UdfAllocationExtentDescriptor"], + [UdfFileEntry, "UdfFileEntry"], + [UdfExtendedFileEntry, "UdfExtendedFileEntry"], + ] + + +class CDROM_VOLUME_DESCRIPTOR(ctypes.Structure): + _fields_ = [ + ('Type', ctypes.c_uint8), + ('Id', ctypes.ARRAY(ctypes.c_uint8, 5)), + ('Reserved', ctypes.ARRAY(ctypes.c_uint8, 82)), + ] + + +class UDF_DESCRIPTOR_TAG(ctypes.Structure): + _fields_ = [ + ('TagIdentifier', ctypes.c_uint16), + ('DescriptorVersion', ctypes.c_uint16), + ('TagChecksum', ctypes.c_uint8), + ('Reserved', ctypes.c_uint8), + ('TagSerialNumber', ctypes.c_uint16), + ('DescriptorCRC', ctypes.c_uint16), + ('DescriptorCRCLength', ctypes.c_uint16), + ('TagLocation', ctypes.c_uint32), + ] + + +class UDF_EXTENT_AD(ctypes.Structure): + _fields_ = [ + ('ExtentLength', ctypes.c_uint32), + ('ExtentLocation', ctypes.c_uint32), + ] + + +class UDF_CHAR_SPEC(ctypes.Structure): + _fields_ = [ + ('CharacterSetType', ctypes.c_uint8), + ('CharacterSetInfo', ctypes.ARRAY(ctypes.c_uint8, 63)), + ] + + +class UDF_ENTITY_ID_DOMAIN(ctypes.Structure): + _fields_ = [ + ('Flags', ctypes.c_uint8), + ('Identifier', ctypes.ARRAY(ctypes.c_uint8, 23)), + ('UdfRevision', ctypes.c_uint16), + ('DomainFlags', ctypes.c_uint8), + ('Reserved', ctypes.ARRAY(ctypes.c_uint8, 5)), + ] + + +class UDF_ENTITY_ID_ENTITY(ctypes.Structure): + _fields_ = [ + ('Flags', ctypes.c_uint8), + ('Identifier', ctypes.ARRAY(ctypes.c_uint8, 23)), + ('UdfRevision', ctypes.c_uint16), + ('OSClass', ctypes.c_uint8), + ('OSIdentifier', ctypes.c_uint8), + ('Reserved', ctypes.ARRAY(ctypes.c_uint8, 4)), + ] + + +class UDF_ENTITY_ID_IMPLEMENTATION_ENTITY(ctypes.Structure): + _fields_ = [ + ('Flags', ctypes.c_uint8), + ('Identifier', ctypes.ARRAY(ctypes.c_uint8, 23)), + ('OSClass', ctypes.c_uint8), + ('OSIdentifier', ctypes.c_uint8), + ('ImplementationUseArea', ctypes.ARRAY(ctypes.c_uint8, 6)), + ] + + +class UDF_ENTITY_ID_APPLICATION_ENTITY(ctypes.Structure): + _fields_ = [ + ('Flags', ctypes.c_uint8), + ('Identifier', ctypes.ARRAY(ctypes.c_uint8, 23)), + ('ApplicationUseArea', ctypes.ARRAY(ctypes.c_uint8, 8)), + ] + + +class UDF_ENTITY_ID(ctypes.Structure): + _fields_ = [ + ('Flags', ctypes.c_uint8), + ('Identifier', ctypes.ARRAY(ctypes.c_uint8, 23)), + ('Data', ctypes.ARRAY(ctypes.c_uint8, 8)), + ] + + +class UDF_TIMESTAMP(ctypes.Structure): + _fields_ = [ + ('TypeAndTimezone', ctypes.c_uint16), + ('Year', ctypes.c_int16), + ('Month', ctypes.c_uint8), + ('Day', ctypes.c_uint8), + ('Hour', ctypes.c_uint8), + ('Minute', ctypes.c_uint8), + ('Second', ctypes.c_uint8), + ('Centiseconds', ctypes.c_uint8), + ('HundredsOfMicroseconds', ctypes.c_uint8), + ('Microseconds', ctypes.c_uint8), + ] + + +class UDF_LONG_ALLOCATION_DESCRIPTOR(ctypes.Structure): + _fields_ = [ + ('ExtentLength', ctypes.c_uint32), + ('ExtentLocationLogicalBlockNumber', ctypes.c_uint32), + ('ExtentLocationPartitionReferenceNumber', ctypes.c_uint16), + ('ImplementationUse', ctypes.ARRAY(ctypes.c_uint8, 6)), + ] + + +class UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER(ctypes.Structure): + _fields_ = [ + ('DescriptorTag', UDF_DESCRIPTOR_TAG), + ('MainVolumeDescriptorSequenceExtent', UDF_EXTENT_AD), + ('ReserveVolumeDescriptorSequenceExtent', UDF_EXTENT_AD), + ('Reserved', ctypes.ARRAY(ctypes.c_uint8, 480)), + ] + + +class UDF_LOGICAL_VOLUME_DESCRIPTOR(ctypes.Structure): + _fields_ = [ + ('DescriptorTag', UDF_DESCRIPTOR_TAG), + ('VolumeDescriptorSequenceNumber', ctypes.c_uint32), + ('DescriptorCharacterSet', UDF_CHAR_SPEC), + ('LogicalVolumeIdentifier', ctypes.ARRAY(ctypes.c_uint8, 128)), + ('LogicalBlockSize', ctypes.c_uint32), + ('DomainIdentifier', UDF_ENTITY_ID_DOMAIN), + ('LogicalVolumeContentsUse', UDF_LONG_ALLOCATION_DESCRIPTOR), + ('MapTableLength', ctypes.c_uint32), + ('NumberOfPartitionMaps', ctypes.c_uint32), + ('ImplementationIdentifier', UDF_ENTITY_ID_IMPLEMENTATION_ENTITY), + ('ImplementationUse', ctypes.ARRAY(ctypes.c_uint8, 128)), + ('IntegritySequenceExtent', UDF_EXTENT_AD), + ('PartitionMaps', ctypes.ARRAY(ctypes.c_uint8, 6)), + ] + + +class UDF_PARTITION_DESCRIPTOR(ctypes.Structure): + _fields_ = [ + ('DescriptorTag', UDF_DESCRIPTOR_TAG), + ('VolumeDescriptorSequenceNumber', ctypes.c_uint32), + ('PartitionFlags', ctypes.c_uint16), + ('PartitionNumber', ctypes.c_uint16), + ('PartitionContents', UDF_ENTITY_ID), + ('PartitionContentsUse', ctypes.ARRAY(ctypes.c_uint8, 128)), + ('AccessType', ctypes.c_uint32), + ('PartitionStartingLocation', ctypes.c_uint32), + ('PartitionLength', ctypes.c_uint32), + ('ImplementationIdentifier', UDF_ENTITY_ID_IMPLEMENTATION_ENTITY), + ('ImplementationUse', ctypes.ARRAY(ctypes.c_uint8, 128)), + ('Reserved', ctypes.ARRAY(ctypes.c_uint8, 128)), + ] + + +class UDF_FILE_SET_DESCRIPTOR(ctypes.Structure): + _fields_ = [ + ('DescriptorTag', UDF_DESCRIPTOR_TAG), + ('RecordingDateAndTime', UDF_TIMESTAMP), + ('InterchangeLevel', ctypes.c_uint16), + ('MaximumInterchangeLevel', ctypes.c_uint16), + ('CharacterSetList', ctypes.c_uint32), + ('MaximumCharacterSetList', ctypes.c_uint32), + ('FileSetNumber', ctypes.c_uint32), + ('FileSetDescriptorNumber', ctypes.c_uint32), + ('LogicalVolumeIdentifierCharacterSet', UDF_CHAR_SPEC), + ('LogicalVolumeIdentifier', ctypes.ARRAY(ctypes.c_uint8, 128)), + ('FileSetCharacterSet', UDF_CHAR_SPEC), + ('FileSetIdentifier', ctypes.ARRAY(ctypes.c_uint8, 32)), + ('CopyrightFileIdentifier', ctypes.ARRAY(ctypes.c_uint8, 32)), + ('AbstractFileIdentifier', ctypes.ARRAY(ctypes.c_uint8, 32)), + ('RootDirectoryIcb', UDF_LONG_ALLOCATION_DESCRIPTOR), + ('DomainIdentifier', UDF_ENTITY_ID_DOMAIN), + ('NextExtent', UDF_LONG_ALLOCATION_DESCRIPTOR), + ('SystemStreamDirectoryIcb', UDF_LONG_ALLOCATION_DESCRIPTOR), + ('Reserved', ctypes.ARRAY(ctypes.c_uint8, 32)), + ] + + +class UDF_ICB_TAG(ctypes.Structure): + _fields_ = [ + ('PriorRecordNumberOfDirectEntries', ctypes.c_uint32), + ('StrategyType', ctypes.c_uint16), + ('StrategyParameter', ctypes.c_uint16), + ('MaximumNumberOfEntries', ctypes.c_uint16), + ('Reserved', ctypes.c_uint8), + ('FileType', ctypes.c_uint8), + ('ParentIcbLocationLogicalBlockNumber', ctypes.c_uint32), + ('ParentIcbLocationPartitionReferenceNumber', ctypes.c_uint16), + ('Flags', ctypes.c_uint16), + ] + + +class UDF_EXTENDED_FILE_ENTRY(ctypes.Structure): + _fields_ = [ + ('DescriptorTag', UDF_DESCRIPTOR_TAG), + ('IcbTag', UDF_ICB_TAG), + ('Uid', ctypes.c_uint32), + ('Gid', ctypes.c_uint32), + ('Permissions', ctypes.c_uint32), + ('FileLinkCount', ctypes.c_uint16), + ('RecordFormat', ctypes.c_uint8), + ('RecordDisplayAttributes', ctypes.c_uint8), + ('RecordLength', ctypes.c_uint32), + ('InformationLength', ctypes.c_uint64), + ('ObjectSize', ctypes.c_uint64), + ('LogicalBlocksRecorded', ctypes.c_uint64), + ('AccessTime', UDF_TIMESTAMP), + ('ModificationTime', UDF_TIMESTAMP), + ('CreationTime', UDF_TIMESTAMP), + ('AttributeTime', UDF_TIMESTAMP), + ('CheckPoint', ctypes.c_uint32), + ('Reserved', ctypes.c_uint32), + ('ExtendedAttributeIcb', UDF_LONG_ALLOCATION_DESCRIPTOR), + ('StreamDirectoryIcb', UDF_LONG_ALLOCATION_DESCRIPTOR), + ('ImplementationIdentifier', UDF_ENTITY_ID_IMPLEMENTATION_ENTITY), + ('UniqueId', ctypes.c_uint64), + ('LengthOfExtendedAttributes', ctypes.c_uint32), + ('LengthOfAllocationDescriptors', ctypes.c_uint32), + ] + + +class UDF_FILE_ENTRY(ctypes.Structure): + _fields_ = [ + ('DescriptorTag', UDF_DESCRIPTOR_TAG), + ('IcbTag', UDF_ICB_TAG), + ('Uid', ctypes.c_uint32), + ('Gid', ctypes.c_uint32), + ('Permissions', ctypes.c_uint32), + ('FileLinkCount', ctypes.c_uint16), + ('RecordFormat', ctypes.c_uint8), + ('RecordDisplayAttributes', ctypes.c_uint8), + ('RecordLength', ctypes.c_uint32), + ('InformationLength', ctypes.c_uint64), + ('LogicalBlocksRecorded', ctypes.c_uint64), + ('AccessTime', UDF_TIMESTAMP), + ('ModificationTime', UDF_TIMESTAMP), + ('AttributeTime', UDF_TIMESTAMP), + ('CheckPoint', ctypes.c_uint32), + ('ExtendedAttributeIcb', UDF_LONG_ALLOCATION_DESCRIPTOR), + ('ImplementationIdentifier', UDF_ENTITY_ID_IMPLEMENTATION_ENTITY), + ('UniqueId', ctypes.c_uint64), + ('LengthOfExtendedAttributes', ctypes.c_uint32), + ('LengthOfAllocationDescriptors', ctypes.c_uint32), + ] + + +class UDF_FILE_IDENTIFIER_DESCRIPTOR(ctypes.Structure): + _fields_ = [ + ('DescriptorTag', UDF_DESCRIPTOR_TAG), + ('FileVersionNumber', ctypes.c_uint16), + ('FileCharacteristics', ctypes.c_uint8), + ('LengthOfFileIdentifier', ctypes.c_uint8), + ('Icb', UDF_LONG_ALLOCATION_DESCRIPTOR), + ('LengthOfImplementationUse', ctypes.c_uint16), + ('Pad', ctypes.c_uint16), + ] + + +class UDF_PRIMARY_VOLUME_DESCRIPTOR(ctypes.Structure): + _fields_ = [ + ('DescriptorTag', UDF_DESCRIPTOR_TAG), + ('VolumeDescriptorSequenceNumber', ctypes.c_uint32), + ('PrimaryVolumeDescriptorNumber', ctypes.c_uint32), + ('VolumeIdentifier', ctypes.ARRAY(ctypes.c_uint8, 32)), + ('VolumeSequenceNumber', ctypes.c_uint16), + ('MaximumVolumeSequenceNumber', ctypes.c_uint16), + ('InterchangeLevel', ctypes.c_uint16), + ('MaximumInterchangeLevel', ctypes.c_uint16), + ('CharacterSetList', ctypes.c_uint32), + ('MaximumCharacterSetList', ctypes.c_uint32), + ('VolumeSetIdentifier', ctypes.ARRAY(ctypes.c_uint8, 128)), + ('DescriptorCharacterSet', UDF_CHAR_SPEC), + ('ExplanatoryCharacterSet', UDF_CHAR_SPEC), + ('VolumeAbstract', UDF_EXTENT_AD), + ('VolumeCopyrightNotice', UDF_EXTENT_AD), + ('ApplicationIdentifier', UDF_ENTITY_ID_APPLICATION_ENTITY), + ('RecordingDateAndTime', UDF_TIMESTAMP), + ('ImplementationIdentifier', UDF_ENTITY_ID_IMPLEMENTATION_ENTITY), + ('ImplementationUse', ctypes.ARRAY(ctypes.c_uint8, 64)), + ('PredecessorVolumeDescriptorSequenceLocation', ctypes.c_uint32), + ('Flags', ctypes.c_uint16), + ('Reserved', ctypes.ARRAY(ctypes.c_uint8, 22)), + ] diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Script/__init__.py b/HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Script/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/USB/Raw/Usb.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/USB/Raw/Usb.bin new file mode 100644 index 0000000..4636cd5 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/USB/Raw/Usb.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/VariableSmm/Raw/VarSmm.bin b/HBFA/UefiHostFuzzTestCasePkg/Seed/VariableSmm/Raw/VarSmm.bin new file mode 100644 index 0000000..af69387 Binary files /dev/null and b/HBFA/UefiHostFuzzTestCasePkg/Seed/VariableSmm/Raw/VarSmm.bin differ diff --git a/HBFA/UefiHostFuzzTestCasePkg/Seed/readme.txt b/HBFA/UefiHostFuzzTestCasePkg/Seed/readme.txt new file mode 100644 index 0000000..58eb527 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/Seed/readme.txt @@ -0,0 +1,38 @@ +UDF: +-- SeedGenUdf.py: Generate a simple UDF partition as seed + python SeedGenUdf.py -o Seed\Udf.bin +-- Udf.py: UDF definition + +Mutator: +-- MutatorSimple.py: Randomize UINT8, UINT16, UINT32, UINT64 in a given buffer + python MutatorSimple.py Seed\XXX.bin -e TestXXX.exe + +Include: +-- Uefi.py: UEFI definition + +TPM: +-- SeedGenTpm2Response.py + +==================================================================================== + Mapping List +==================================================================================== +Case Name: Seed Location: +TestTpm2CommandLib HBFA\UefiHostFuzzTestCasePkg\Seed\TPM\Raw +TestBmpSupportLib HBFA\UefiHostFuzzTestCasePkg\Seed\BMP\Raw +TestPartition HBFA\UefiHostFuzzTestCasePkg\Seed\UDF\Raw\Partition +TestUdf HBFA\UefiHostFuzzTestCasePkg\Seed\UDF\Raw\FileSystem +TestUsb HBFA\UefiHostFuzzTestCasePkg\Seed\USB\Raw +TestPeiUsb HBFA\UefiHostFuzzTestCasePkg\Seed\USB\Raw +TestVariableSmm HBFA\UefiHostFuzzTestCasePkg\Seed\VariableSmm\Raw +TestFmpAuthenticationLibPkcs7 HBFA\UefiHostFuzzTestCasePkg\Seed\Capsule +TestFmpAuthenticationLibRsa2048Sha256 HBFA\UefiHostFuzzTestCasePkg\Seed\Capsule +TestCapsulePei HBFA\UefiHostFuzzTestCasePkg\Seed\Capsule +TestFileName HBFA\UefiHostFuzzTestCasePkg\Seed\UDF\Raw\FileName +TestPeiGpt HBFA\UefiHostFuzzTestCasePkg\Seed\Gpt\Raw +TestValidateTdvfCfv HBFA\UefiHostFuzzTestCasePkg\Seed\Cfv +TestTcg2MeasureGptTable HBFA\UefiHostFuzzTestCasePkg\Seed\Gpt +TestTcg2MeasurePeImage # PE format image +TestVirtioPciDevice HBFA\UefiHostFuzzTestCasePkg\Seed\Blk +TestVirtioBlk10 HBFA\UefiHostFuzzTestCasePkg\Seed\Blk +TestVirtioBlk HBFA\UefiHostFuzzTestCasePkg\Seed\Blk +TestVirtioBlkReadWrite HBFA\UefiHostFuzzTestCasePkg\Seed\Blk \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/DeviceSecurityPkg/TestSignatureList/TestSignatureList.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/DeviceSecurityPkg/TestSignatureList/TestSignatureList.c new file mode 100644 index 0000000..2909233 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/DeviceSecurityPkg/TestSignatureList/TestSignatureList.c @@ -0,0 +1,49 @@ +/** @file + +Copyright (c) 2022, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#define TOTAL_SIZE (512 * 1024) +/* 384 kB */ +#define MAX_LEN (384 * 1024) + +VOID +FixBuffer ( + UINT8 *TestBuffer + ) +{ +} + +UINTN +EFIAPI +GetMaxBufferSize ( + VOID + ) +{ + return TOTAL_SIZE; +} + +VOID +EFIAPI +RunTestHarness( + IN VOID *TestBuffer, + IN UINTN TestBufferSize + ) +{ +Traverse_SignatureList(TestBuffer, TestBufferSize); +} diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/DeviceSecurityPkg/TestSignatureList/TestSignatureList.inf b/HBFA/UefiHostFuzzTestCasePkg/TestCase/DeviceSecurityPkg/TestSignatureList/TestSignatureList.inf new file mode 100644 index 0000000..209c285 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/DeviceSecurityPkg/TestSignatureList/TestSignatureList.inf @@ -0,0 +1,44 @@ +## @file +# SPDM library. +# +# Copyright (c) 2020, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TestSignatureList + FILE_GUID = 77D7770D-158E-4354-B813-B8792A0E982F + MODULE_TYPE = USER_DEFINED + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 AARCH64 +# + +[Sources] + TestSignatureList.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + DeviceSecurityPkg/DeviceSecurityPkg.dec + CryptoPkg/CryptoPkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + RngLib + MemoryAllocationLib + ToolChainHarnessLib + TestSignListLib + +[Guids] + gEdkiiDeviceSignatureDatabaseGuid ## CONSUMES + gEfiCertX509Guid ## CONSUMES diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/FatPkg/FatPei/InstrumentHookLibTestPeiGpt/CreateErrorInjectionProfile.py b/HBFA/UefiHostFuzzTestCasePkg/TestCase/FatPkg/FatPei/InstrumentHookLibTestPeiGpt/CreateErrorInjectionProfile.py new file mode 100644 index 0000000..5403f7c --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/FatPkg/FatPei/InstrumentHookLibTestPeiGpt/CreateErrorInjectionProfile.py @@ -0,0 +1,77 @@ +# @file +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +import os +import shutil +import sys +try: + import ConfigParser as ConfigParser +except Exception as e: + print("Import for ConfigParser not found, attempting configparser: " + "%s" % e) + import configparser as ConfigParser +import argparse + +Case_Path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'Case') + + +class myconf(ConfigParser.RawConfigParser): + def __init__(self, defaults=None): + ConfigParser.RawConfigParser.__init__(self, defaults=None) + + def optionxform(self, optionstr): + return optionstr + + +class errorInjection(): + def __init__(self, Num): + self.CallErrorCountNum = int(Num) + + def run(self): + if os.path.exists(Case_Path): + shutil.rmtree(Case_Path) + os.makedirs(Case_Path) + else: + os.makedirs(Case_Path) + Case_Count_Num = 1 + for CountNum in range(1, self.CallErrorCountNum + 1): + print('#######################################') + print('Current CallErrorCountNum: {}'.format(CountNum)) + print('#######################################') + for count in range(2): + CaseName = 'test_' + str(Case_Count_Num) + '.ini' + self.create_tcs(os.path.join(Case_Path, CaseName), CountNum, + count) + Case_Count_Num = Case_Count_Num + 1 + + def create_tcs(self, tcs_file, num, count): + conf = myconf() + if count == 0: + conf.add_section('AllocatePages') + conf.set('AllocatePages', 'CallErrorCount', num) + conf.set('AllocatePages', 'ReturnValue', 0) + elif count == 1: + conf.add_section('FatReadBlock') + conf.set('FatReadBlock', 'CallErrorCount', num) + conf.set('FatReadBlock', 'ReturnValue', 'EFI_DEVICE_ERROR') + else: + pass + + with open(tcs_file, 'w') as f: + conf.write(f) + + +if __name__ == '__main__': + # # # Opt Parser + parser = argparse.ArgumentParser() + parser.add_argument("-c", dest="CallErrorCountNum", + help="CallErrorCount number,if CallErrorCount = N," + "script will try CallErrorCount = 1 ~ CallErrorCount" + " = N", default=None) + + options = parser.parse_args(sys.argv[1:]) + test = errorInjection(options.CallErrorCountNum) + test.run() diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/FatPkg/FatPei/InstrumentHookLibTestPeiGpt/InstrumentHookLibTestPeiGpt.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/FatPkg/FatPei/InstrumentHookLibTestPeiGpt/InstrumentHookLibTestPeiGpt.c new file mode 100644 index 0000000..24d4459 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/FatPkg/FatPei/InstrumentHookLibTestPeiGpt/InstrumentHookLibTestPeiGpt.c @@ -0,0 +1,203 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "../FatLitePeim.h" + +typedef struct _FUNC_HOOK FUNC_HOOK; + +typedef +UINTN +(EFIAPI *HOOK_FUNC_ENTER) ( + IN FUNC_HOOK *FuncHook, + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ); + +typedef +VOID +(EFIAPI *HOOK_FUNC_EXIT) ( + IN FUNC_HOOK *FuncHook, + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ); + +struct _FUNC_HOOK { + CHAR8 *Name; + UINTN Func; + UINTN HookFuncEnter; + UINTN HookFuncExit; + UINTN CallErrorCount; + UINTN ReturnValue; + UINTN CurrentCallCount; +} ; + +BOOLEAN mInitDone; + +UINTN +EFIAPI +CommonEnter ( + IN FUNC_HOOK *FuncHook, + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + FuncHook->CurrentCallCount++; + if (FuncHook->CurrentCallCount == FuncHook->CallErrorCount) { + //SetSkipReturnValue (EntryContext, FuncHook->ReturnValue); + if (FuncHook->Func == (UINTN)AllocatePages) { + SetParameterValue (EntryContext, 1, (UINTN)-1); + } else if (FuncHook->Func == (UINTN)FatReadBlock) { + SetParameterValue64 (EntryContext, 2, PEI_FAT_MAX_BLOCK_DEVICE); + } + return 1; + } + return 0; +} + +VOID +EFIAPI +CommonExit ( + IN FUNC_HOOK *FuncHook, + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + if (FuncHook->CurrentCallCount == FuncHook->CallErrorCount) { + SetReturnValue (ExitContext, FuncHook->ReturnValue); + } + return ; +} + +GLOBAL_REMOVE_IF_UNREFERENCED FUNC_HOOK mFuncHook[] = { + {"AllocatePages", (UINTN)AllocatePages, (UINTN)CommonEnter, (UINTN)CommonExit}, + {"FatReadBlock", (UINTN)FatReadBlock, (UINTN)CommonEnter, (UINTN)CommonExit}, +}; + +FUNC_HOOK * +GetFuncHook ( + IN UINTN FuncAddr + ) +{ + UINTN Index; + for (Index = 0; Index < ARRAY_SIZE(mFuncHook); Index++) { + if (FuncAddr == mFuncHook[Index].Func) { + return &mFuncHook[Index]; + } + } + return NULL; +} + +UINTN +EFIAPI +FunctionEnter ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + FUNC_HOOK *FuncHook; + HOOK_FUNC_ENTER HookFunc; + + if (!mInitDone) { + return 0; + } + + FuncHook = GetFuncHook (FunctionAddress); + if (FuncHook == NULL) { + return 0; + } + if (FuncHook->HookFuncEnter == 0) { + return 0; + } + HookFunc = (HOOK_FUNC_ENTER)(FuncHook->HookFuncEnter); + return HookFunc (FuncHook, EntryContext, FunctionAddress, CallerAddress); +} + +VOID +EFIAPI +FunctionExit ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + FUNC_HOOK *FuncHook; + HOOK_FUNC_EXIT HookFunc; + + if (!mInitDone) { + return ; + } + + FuncHook = GetFuncHook (FunctionAddress); + if (FuncHook == NULL) { + return ; + } + if (FuncHook->HookFuncExit == 0) { + return ; + } + HookFunc = (HOOK_FUNC_EXIT)(FuncHook->HookFuncExit); + HookFunc (FuncHook, ExitContext, FunctionAddress, CallerAddress); +} + +VOID +EFIAPI +InstrumentHookLibInit ( + IN UINT8 *DataBuffer, + IN UINTN BufferSize + ) +{ + VOID *Context; + UINTN Index; + EFI_STATUS Status; + + Context = OpenIniFile (DataBuffer, BufferSize); + + for (Index = 0; Index < ARRAY_SIZE(mFuncHook); Index++) { + Status = GetDecimalUintnFromDataFile ( + Context, + mFuncHook[Index].Name, + "CallErrorCount", + &mFuncHook[Index].CallErrorCount + ); + if (EFI_ERROR(Status)) { + continue ; + } + + Status = GetEfiStatusFromDataFile ( + Context, + mFuncHook[Index].Name, + "ReturnValue", + &mFuncHook[Index].ReturnValue + ); + if (EFI_ERROR(Status)) { + Status = GetHexUintnFromDataFile ( + Context, + mFuncHook[Index].Name, + "ReturnValue", + &mFuncHook[Index].ReturnValue + ); + } + } + + CloseIniFile (Context); + + mInitDone = TRUE; +} \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/FatPkg/FatPei/InstrumentHookLibTestPeiGpt/InstrumentHookLibTestPeiGpt.inf b/HBFA/UefiHostFuzzTestCasePkg/TestCase/FatPkg/FatPei/InstrumentHookLibTestPeiGpt/InstrumentHookLibTestPeiGpt.inf new file mode 100644 index 0000000..a98818f --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/FatPkg/FatPei/InstrumentHookLibTestPeiGpt/InstrumentHookLibTestPeiGpt.inf @@ -0,0 +1,41 @@ +## @file +# Component description file for TestUdf module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = InstrumentHookLibTestPeiGpt + FILE_GUID = 0D208A61-B4BA-488D-85E9-4C12F533EE67 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = InstrumentHookLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + InstrumentHookLibTestPeiGpt.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiInstrumentTestPkg/UefiInstrumentTestPkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib + IniParsingLib + +[BuildOptions] + MSFT:*_*_*_CC_FLAGS = /Od /GL- + GCC:*_*_*_CC_FLAGS = -O0 diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/FatPkg/FatPei/Override/FatLiteLib.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/FatPkg/FatPei/Override/FatLiteLib.c new file mode 100644 index 0000000..6832569 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/FatPkg/FatPei/Override/FatLiteLib.c @@ -0,0 +1,56 @@ +/** @file + General purpose supporting routines for FAT recovery PEIM + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "FatLitePeim.h" + +EFI_STATUS +FatReadBlock ( + IN PEI_FAT_PRIVATE_DATA *PrivateData, + IN UINTN BlockDeviceNo, + IN EFI_PEI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + PEI_FAT_BLOCK_DEVICE *BlockDev; + + if (BlockDeviceNo > PEI_FAT_MAX_BLOCK_DEVICE - 1) { + return EFI_DEVICE_ERROR; + } + + BlockDev = &(PrivateData->BlockDevice[BlockDeviceNo]); + + if (BufferSize > MultU64x32 (BlockDev->LastBlock - Lba + 1, BlockDev->BlockSize)) { + return EFI_DEVICE_ERROR; + } + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize == 0) { + return EFI_SUCCESS; + } + + if ((BufferSize % BlockDev->BlockSize) != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + if (Lba > BlockDev->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + CopyMem( + Buffer, + (VOID *)(UINTN)(BlockDev->StartingPos + MultU64x32(Lba, BlockDev->BlockSize)), + BufferSize + ); + + return EFI_SUCCESS; +} \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/FatPkg/FatPei/Override/FatPei.inf b/HBFA/UefiHostFuzzTestCasePkg/TestCase/FatPkg/FatPei/Override/FatPei.inf new file mode 100644 index 0000000..636a267 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/FatPkg/FatPei/Override/FatPei.inf @@ -0,0 +1,70 @@ +## @file +# Lite Fat driver only used in Pei Phase. +# +# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = FatPei + MODULE_UNI_FILE = FatPei.uni + FILE_GUID = 5B60CCFD-1011-4BCF-B7D1-BB99CA96A603 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + + ENTRY_POINT = FatPeimEntry + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + FatPkg/FatPei/Gpt.c + FatLiteLib.c + FatPkg/FatPei/FatLiteApi.h + FatPkg/FatPei/FatLitePeim.h + FatPkg/FatPei/FatLiteFmt.h + + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + + +[LibraryClasses] + PcdLib + BaseMemoryLib + MemoryAllocationLib + PeimEntryPoint + BaseLib + DebugLib + PeiServicesTablePointerLib + PeiServicesLib + + +[Guids] + gRecoveryOnFatUsbDiskGuid ## SOMETIMES_CONSUMES ## UNDEFINED + gRecoveryOnFatIdeDiskGuid ## SOMETIMES_CONSUMES ## UNDEFINED + gRecoveryOnFatFloppyDiskGuid ## SOMETIMES_CONSUMES ## UNDEFINED + gRecoveryOnFatNvmeDiskGuid ## SOMETIMES_CONSUMES ## UNDEFINED + gEfiPartTypeUnusedGuid ## SOMETIMES_CONSUMES ## UNDEFINED + + +[Ppis] + gEfiPeiVirtualBlockIoPpiGuid ## SOMETIMES_CONSUMES PPI_NOTIFY + gEfiPeiVirtualBlockIo2PpiGuid ## SOMETIMES_CONSUMES PPI_NOTIFY + gEfiPeiDeviceRecoveryModulePpiGuid ## SOMETIMES_PRODUCES + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdRecoveryFileName ## CONSUMES + +[Depex] + gEfiPeiMemoryDiscoveredPpiGuid + +[UserExtensions.TianoCore."ExtraFiles"] + FatPeiExtra.uni diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/FatPkg/FatPei/TestPeiGpt.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/FatPkg/FatPei/TestPeiGpt.c new file mode 100644 index 0000000..c101058 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/FatPkg/FatPei/TestPeiGpt.c @@ -0,0 +1,235 @@ +/** @file + +Copyright (c) 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 "FatLitePeim.h" + +BOOLEAN +FatFindGptPartitions( + IN PEI_FAT_PRIVATE_DATA *PrivateData, + IN UINTN ParentBlockDevNo +); + +#define TOTAL_SIZE (512 * 1024) +#define BLOCK_SIZE (512) + +VOID +FixBuffer ( + UINT8 *TestBuffer, + UINTN BufferSize, + UINT32 BlockSize + ) +{ + EFI_PARTITION_TABLE_HEADER *PrimaryHeader; + EFI_PARTITION_TABLE_HEADER *BackupHeader; + EFI_LBA LastBlock; + UINT8 *Ptr; + + PrimaryHeader = NULL; + BackupHeader = NULL; + + LastBlock = (BufferSize + BlockSize - 1) / BlockSize - 1; + + PrimaryHeader = (EFI_PARTITION_TABLE_HEADER*)(TestBuffer + MultU64x32(PRIMARY_PART_HEADER_LBA, BlockSize)); + if (PrimaryHeader->PartitionEntryLBA <= LastBlock -1 && MultU64x32(PrimaryHeader->PartitionEntryLBA, BlockSize) + MultU64x32(PrimaryHeader->NumberOfPartitionEntries, PrimaryHeader->SizeOfPartitionEntry) < BufferSize) { + Ptr = TestBuffer + MultU64x32(PrimaryHeader->PartitionEntryLBA, BlockSize); + PrimaryHeader->PartitionEntryArrayCRC32 = CalculateCrc32(Ptr, (UINTN)MultU64x32(PrimaryHeader->NumberOfPartitionEntries, PrimaryHeader->SizeOfPartitionEntry)); + } + + if (PrimaryHeader->Header.HeaderSize + MultU64x32(PRIMARY_PART_HEADER_LBA, BlockSize) < BufferSize) { + PrimaryHeader->Header.CRC32 = 0; + PrimaryHeader->Header.CRC32 = CalculateCrc32(PrimaryHeader, PrimaryHeader->Header.HeaderSize); + } + + + BackupHeader = (EFI_PARTITION_TABLE_HEADER*)(TestBuffer + MultU64x32(LastBlock, BlockSize)); + if (BackupHeader->PartitionEntryLBA <= LastBlock - 1 && MultU64x32(BackupHeader->PartitionEntryLBA, BlockSize) + MultU64x32(BackupHeader->NumberOfPartitionEntries, BackupHeader->SizeOfPartitionEntry) < BufferSize) { + Ptr = TestBuffer + MultU64x32(BackupHeader->PartitionEntryLBA, BlockSize); + BackupHeader->PartitionEntryArrayCRC32 = CalculateCrc32(Ptr, (UINTN)MultU64x32(BackupHeader->NumberOfPartitionEntries, BackupHeader->SizeOfPartitionEntry)); + } + + if (BackupHeader->Header.HeaderSize + MultU64x32(LastBlock, BlockSize) < BufferSize) { + BackupHeader->Header.CRC32 = 0; + BackupHeader->Header.CRC32 = CalculateCrc32(BackupHeader, BackupHeader->Header.HeaderSize); + } +} + +VOID +FixBuffer0( + UINT8 *TestBuffer, + UINTN BufferSize, + UINT32 BlockSize +) +{ + EFI_PARTITION_TABLE_HEADER *PrimaryHeader; + EFI_PARTITION_TABLE_HEADER *BackupHeader; + EFI_LBA LastBlock; + + PrimaryHeader = NULL; + BackupHeader = NULL; + + LastBlock = (BufferSize + BlockSize - 1) / BlockSize - 1; + + PrimaryHeader = (EFI_PARTITION_TABLE_HEADER*)(TestBuffer + MultU64x32(PRIMARY_PART_HEADER_LBA, BlockSize)); + PrimaryHeader->PartitionEntryArrayCRC32 = 0; + PrimaryHeader->Header.CRC32 = 0; + + BackupHeader = (EFI_PARTITION_TABLE_HEADER*)(TestBuffer + MultU64x32(LastBlock, BlockSize)); + BackupHeader->PartitionEntryArrayCRC32 = 0; + BackupHeader->Header.CRC32 = 0; +} + +EFI_STATUS +CreatePrivateData( + UINT8 *TestBuffer, + UINTN BufferSize, + UINT32 BlockSize, + UINTN ParentBlockDevNo, + UINTN BlockDeviceCont, + PEI_FAT_PRIVATE_DATA **PrivateData +) +{ + PEI_FAT_PRIVATE_DATA *TestPrivateData; + TestPrivateData = malloc (sizeof(PEI_FAT_PRIVATE_DATA)); + if (TestPrivateData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + memset (TestPrivateData, 0, sizeof(PEI_FAT_PRIVATE_DATA)); + + TestPrivateData->BlockDevice[ParentBlockDevNo].BlockSize = BlockSize; + TestPrivateData->BlockDevice[ParentBlockDevNo].LastBlock = (BufferSize + TestPrivateData->BlockDevice[ParentBlockDevNo].BlockSize - 1) / TestPrivateData->BlockDevice[ParentBlockDevNo].BlockSize - 1; + TestPrivateData->BlockDevice[ParentBlockDevNo].StartingPos = (UINTN)TestBuffer; + TestPrivateData->BlockDevice[ParentBlockDevNo].ParentDevNo = ParentBlockDevNo; + TestPrivateData->BlockDeviceCount = BlockDeviceCont; + + *PrivateData = TestPrivateData; + return EFI_SUCCESS; +} + +VOID +TestGpt( + UINT8 *TestBuffer, + UINTN TestBufferSize, + UINT32 BlockSize, + UINTN ParentBlockDevNo, + UINTN BlockDevCount +) +{ + PEI_FAT_PRIVATE_DATA *PrivateData; + + PrivateData = NULL; + if (EFI_ERROR(CreatePrivateData(TestBuffer, TestBufferSize, BlockSize, ParentBlockDevNo, BlockDevCount, &PrivateData))) + return; + + // fuzz function: + // buffer overflow, crash will be detected at place. + // only care about security, not for function bug. + // + // try to separate EFI lib, use stdlib function. + // no asm code. + FatFindGptPartitions( + PrivateData, + ParentBlockDevNo + ); + free(PrivateData); +} + +#ifndef TEST_WITH_KLEE +VOID +GetBlockSize( + IN UINT8 *TestBuffer, + IN UINTN TestBufferSize, + OUT UINT32 *RtnBlockSize +) +{ + UINT32 BlockSize; + EFI_PARTITION_TABLE_HEADER *PartHdr; + + BlockSize = 512; + if (MultU64x32(PRIMARY_PART_HEADER_LBA, (UINT32)512) >= TestBufferSize) + goto Done; + PartHdr = (EFI_PARTITION_TABLE_HEADER*)(TestBuffer + MultU64x32(PRIMARY_PART_HEADER_LBA, (UINT32)512)); + if (PartHdr->Header.Signature == EFI_PTAB_HEADER_ID) { + BlockSize = 512; + goto Done; + } + if (MultU64x32(PRIMARY_PART_HEADER_LBA, (UINT32)1024) >= TestBufferSize) + goto Done; + PartHdr = (EFI_PARTITION_TABLE_HEADER*)(TestBuffer + MultU64x32(PRIMARY_PART_HEADER_LBA, (UINT32)1024)); + if (PartHdr->Header.Signature == EFI_PTAB_HEADER_ID) { + BlockSize = 1024; + goto Done; + } + if (MultU64x32(PRIMARY_PART_HEADER_LBA, (UINT32)2048) >= TestBufferSize) + goto Done; + PartHdr = (EFI_PARTITION_TABLE_HEADER*)(TestBuffer + MultU64x32(PRIMARY_PART_HEADER_LBA, (UINT32)2048)); + if (PartHdr->Header.Signature == EFI_PTAB_HEADER_ID) { + BlockSize = 2048; + goto Done; + } + if (MultU64x32(PRIMARY_PART_HEADER_LBA, (UINT32)4096) >= TestBufferSize) + goto Done; + PartHdr = (EFI_PARTITION_TABLE_HEADER*)(TestBuffer + MultU64x32(PRIMARY_PART_HEADER_LBA, (UINT32)4096)); + if (PartHdr->Header.Signature == EFI_PTAB_HEADER_ID) { + BlockSize = 4096; + goto Done; + } + if (MultU64x32(PRIMARY_PART_HEADER_LBA, (UINT32)8192) >= TestBufferSize) + goto Done; + PartHdr = (EFI_PARTITION_TABLE_HEADER*)(TestBuffer + MultU64x32(PRIMARY_PART_HEADER_LBA, (UINT32)8192)); + if (PartHdr->Header.Signature == EFI_PTAB_HEADER_ID) { + BlockSize = 8192; + goto Done; + } + BlockSize = 16384; + +Done: + *RtnBlockSize = BlockSize; +} +#endif + +UINTN +EFIAPI +GetMaxBufferSize ( + VOID + ) +{ + return TOTAL_SIZE; +} + +VOID +EFIAPI +RunTestHarness( + IN VOID *TestBuffer, + IN UINTN TestBufferSize + ) +{ + UINT32 BlockSize; + +#ifdef TEST_WITH_KLEE + BlockSize = BLOCK_SIZE; +#else + GetBlockSize(TestBuffer, TestBufferSize, &BlockSize); + FixBuffer (TestBuffer, TestBufferSize, BlockSize); +#endif + TestGpt(TestBuffer, TestBufferSize, BlockSize, 63, 0); + TestGpt(TestBuffer, TestBufferSize, BlockSize, 0, 64); + TestGpt(TestBuffer, TestBufferSize, BlockSize, 0, 0); +} diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/FatPkg/FatPei/TestPeiGpt.inf b/HBFA/UefiHostFuzzTestCasePkg/TestCase/FatPkg/FatPei/TestPeiGpt.inf new file mode 100644 index 0000000..79a6b9d --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/FatPkg/FatPei/TestPeiGpt.inf @@ -0,0 +1,42 @@ +## @file +# Component description file for TestPeiGpt module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TestPeiGpt + FILE_GUID = 70823DB1-63E0-4F4F-9161-ECB21AAEF520 + MODULE_TYPE = USER_DEFINED + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + TestPeiGpt.c + FatPkg/FatPei/FatLiteApi.h + FatPkg/FatPei/FatLitePeim.h + FatPkg/FatPei/FatLiteFmt.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib + ToolChainHarnessLib + +[Guids] + gEfiPartTypeUnusedGuid + diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/AhciMode.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/AhciMode.c new file mode 100644 index 0000000..b5e391e --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/AhciMode.c @@ -0,0 +1,2137 @@ +/** @file + The AhciPei driver is used to manage ATA hard disk device working under AHCI + mode at PEI phase. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "AhciPei.h" + +#define ATA_CMD_TRUST_NON_DATA 0x5B +#define ATA_CMD_TRUST_RECEIVE 0x5C +#define ATA_CMD_TRUST_SEND 0x5E + +// +// Look up table (IsWrite) for EFI_ATA_PASS_THRU_CMD_PROTOCOL +// +EFI_ATA_PASS_THRU_CMD_PROTOCOL mAtaPassThruCmdProtocols[2] = { + EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN, + EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT +}; + +// +// Look up table (Lba48Bit, IsIsWrite) for ATA_CMD +// +UINT8 mAtaCommands[2][2] = { + { + ATA_CMD_READ_SECTORS, // 28-bit LBA; PIO read + ATA_CMD_WRITE_SECTORS // 28-bit LBA; PIO write + }, + { + ATA_CMD_READ_SECTORS_EXT, // 48-bit LBA; PIO read + ATA_CMD_WRITE_SECTORS_EXT // 48-bit LBA; PIO write + } +}; + +// +// Look up table (IsTrustSend) for ATA_CMD +// +UINT8 mAtaTrustCommands[2] = { + ATA_CMD_TRUST_RECEIVE, // PIO read + ATA_CMD_TRUST_SEND // PIO write +}; + +// +// Look up table (Lba48Bit) for maximum transfer block number +// +#define MAX_28BIT_TRANSFER_BLOCK_NUM 0x100 +// +// Due to limited resource on VTd PEI DMA buffer size, driver limits the +// maximum transfer block number for 48-bit addressing. +// Setting to 0x800 here means 1M bytes for device with 512-byte block size. +// +#define MAX_48BIT_TRANSFER_BLOCK_NUM 0x800 + +UINT32 mMaxTransferBlockNumber[2] = { + MAX_28BIT_TRANSFER_BLOCK_NUM, + MAX_48BIT_TRANSFER_BLOCK_NUM +}; + +// +// The maximum total sectors count in 28 bit addressing mode +// +#define MAX_28BIT_ADDRESSING_CAPACITY 0xfffffff + + +/** + Read AHCI Operation register. + + @param[in] AhciBar AHCI bar address. + @param[in] Offset The operation register offset. + + @return The register content read. + +**/ +UINT32 +AhciReadReg ( + IN UINTN AhciBar, + IN UINT32 Offset + ) +{ + UINT32 Data; + + Data = 0; + //Data = MmioRead32 (AhciBar + Offset); // for fuzz + + return Data; +} + +/** + Write AHCI Operation register. + + @param[in] AhciBar AHCI bar address. + @param[in] Offset The operation register offset. + @param[in] Data The Data used to write down. + +**/ +VOID +AhciWriteReg ( + IN UINTN AhciBar, + IN UINT32 Offset, + IN UINT32 Data + ) +{ + //MmioWrite32 (AhciBar + Offset, Data); // for fuzz +} + +/** + Do AND operation with the value of AHCI Operation register. + + @param[in] AhciBar AHCI bar address. + @param[in] Offset The operation register offset. + @param[in] AndData The data used to do AND operation. + +**/ +VOID +AhciAndReg ( + IN UINTN AhciBar, + IN UINT32 Offset, + IN UINT32 AndData + ) +{ + UINT32 Data; + + Data = AhciReadReg (AhciBar, Offset); + Data &= AndData; + + AhciWriteReg (AhciBar, Offset, Data); +} + +/** + Do OR operation with the Value of AHCI Operation register. + + @param[in] AhciBar AHCI bar address. + @param[in] Offset The operation register offset. + @param[in] OrData The Data used to do OR operation. + +**/ +VOID +AhciOrReg ( + IN UINTN AhciBar, + IN UINT32 Offset, + IN UINT32 OrData + ) +{ + UINT32 Data; + + Data = AhciReadReg (AhciBar, Offset); + Data |= OrData; + + AhciWriteReg (AhciBar, Offset, Data); +} + +/** + Wait for memory set to the test Value. + + @param[in] AhciBar AHCI bar address. + @param[in] Offset The memory offset to test. + @param[in] MaskValue The mask Value of memory. + @param[in] TestValue The test Value of memory. + @param[in] Timeout The timeout, in 100ns units, for wait memory set. + + @retval EFI_DEVICE_ERROR The memory is not set. + @retval EFI_TIMEOUT The memory setting is time out. + @retval EFI_SUCCESS The memory is correct set. + +**/ +EFI_STATUS +EFIAPI +AhciWaitMmioSet ( + IN UINTN AhciBar, + IN UINT32 Offset, + IN UINT32 MaskValue, + IN UINT32 TestValue, + IN UINT64 Timeout + ) +{ + UINT32 Value; + UINT32 Delay; + + Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1); + + do { + Value = AhciReadReg (AhciBar, Offset) & MaskValue; + + if (Value == TestValue) { + return EFI_SUCCESS; + } + + // + // Stall for 100 microseconds. + // + MicroSecondDelay (100); + + Delay--; + + } while (Delay > 0); + + return EFI_TIMEOUT; +} + +/** + Check the memory status to the test value. + + @param[in] Address The memory address to test. + @param[in] MaskValue The mask value of memory. + @param[in] TestValue The test value of memory. + + @retval EFI_NOT_READY The memory is not set. + @retval EFI_SUCCESS The memory is correct set. + +**/ +EFI_STATUS +AhciCheckMemSet ( + IN UINTN Address, + IN UINT32 MaskValue, + IN UINT32 TestValue + ) +{ + UINT32 Value; + + Value = *(volatile UINT32 *) Address; + Value &= MaskValue; + + if (Value == TestValue) { + return EFI_SUCCESS; + } else { + return EFI_NOT_READY; + } +} + +/** + Wait for the value of the specified system memory set to the test value. + + @param[in] Address The system memory address to test. + @param[in] MaskValue The mask value of memory. + @param[in] TestValue The test value of memory. + @param[in] Timeout The timeout, in 100ns units, for wait memory set. + + @retval EFI_TIMEOUT The system memory setting is time out. + @retval EFI_SUCCESS The system memory is correct set. + +**/ +EFI_STATUS +AhciWaitMemSet ( + IN EFI_PHYSICAL_ADDRESS Address, + IN UINT32 MaskValue, + IN UINT32 TestValue, + IN UINT64 Timeout + ) +{ + UINT32 Value; + UINT64 Delay; + BOOLEAN InfiniteWait; + + if (Timeout == 0) { + InfiniteWait = TRUE; + } else { + InfiniteWait = FALSE; + } + + Delay = DivU64x32 (Timeout, 1000) + 1; + + do { + // + // Access sytem memory to see if the value is the tested one. + // + // The system memory pointed by Address will be updated by the + // SATA Host Controller, "volatile" is introduced to prevent + // compiler from optimizing the access to the memory address + // to only read once. + // + Value = *(volatile UINT32 *) (UINTN) Address; + Value &= MaskValue; + + if (Value == TestValue) { + return EFI_SUCCESS; + } + + // + // Stall for 100 microseconds. + // + MicroSecondDelay (100); + + Delay--; + + } while (InfiniteWait || (Delay > 0)); + + return EFI_TIMEOUT; +} + +/** + + Clear the port interrupt and error status. It will also clear HBA interrupt + status. + + @param[in] AhciBar AHCI bar address. + @param[in] Port The number of port. + +**/ +VOID +AhciClearPortStatus ( + IN UINTN AhciBar, + IN UINT8 Port + ) +{ + UINT32 Offset; + + // + // Clear any error status + // + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_SERR; + AhciWriteReg (AhciBar, Offset, AhciReadReg (AhciBar, Offset)); + + // + // Clear any port interrupt status + // + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_IS; + AhciWriteReg (AhciBar, Offset, AhciReadReg (AhciBar, Offset)); + + // + // Clear any HBA interrupt status + // + AhciWriteReg (AhciBar, AHCI_IS_OFFSET, AhciReadReg (AhciBar, AHCI_IS_OFFSET)); +} + +/** + Enable the FIS running for giving port. + + @param[in] AhciBar AHCI bar address. + @param[in] Port The number of port. + @param[in] Timeout The timeout, in 100ns units, to enabling FIS. + + @retval EFI_DEVICE_ERROR The FIS enable setting fails. + @retval EFI_TIMEOUT The FIS enable setting is time out. + @retval EFI_SUCCESS The FIS enable successfully. + +**/ +EFI_STATUS +AhciEnableFisReceive ( + IN UINTN AhciBar, + IN UINT8 Port, + IN UINT64 Timeout + ) +{ + UINT32 Offset; + + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD; + AhciOrReg (AhciBar, Offset, AHCI_PORT_CMD_FRE); + + return EFI_SUCCESS; +} + +/** + Disable the FIS running for giving port. + + @param[in] AhciBar AHCI bar address. + @param[in] Port The number of port. + @param[in] Timeout The timeout value of disabling FIS, uses 100ns as a unit. + + @retval EFI_DEVICE_ERROR The FIS disable setting fails. + @retval EFI_TIMEOUT The FIS disable setting is time out. + @retval EFI_UNSUPPORTED The port is in running state. + @retval EFI_SUCCESS The FIS disable successfully. + +**/ +EFI_STATUS +AhciDisableFisReceive ( + IN UINTN AhciBar, + IN UINT8 Port, + IN UINT64 Timeout + ) +{ + UINT32 Offset; + UINT32 Data; + + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD; + Data = AhciReadReg (AhciBar, Offset); + + // + // Before disabling Fis receive, the DMA engine of the port should NOT be in + // running status. + // + if ((Data & (AHCI_PORT_CMD_ST | AHCI_PORT_CMD_CR)) != 0) { + return EFI_UNSUPPORTED; + } + + // + // Check if the Fis receive DMA engine for the port is running. + // + if ((Data & AHCI_PORT_CMD_FR) != AHCI_PORT_CMD_FR) { + return EFI_SUCCESS; + } + + AhciAndReg (AhciBar, Offset, (UINT32)~(AHCI_PORT_CMD_FRE)); + + return AhciWaitMmioSet ( + AhciBar, + Offset, + AHCI_PORT_CMD_FR, + 0, + Timeout + ); +} + +/** + Build the command list, command table and prepare the fis receiver. + + @param[in] Private The pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA. + @param[in] Port The number of port. + @param[in] PortMultiplier The number of port multiplier. + @param[in] FisIndex The offset index of the FIS base address. + @param[in] CommandFis The control fis will be used for the transfer. + @param[in] CommandList The command list will be used for the transfer. + @param[in] CommandSlotNumber The command slot will be used for the transfer. + @param[in,out] DataPhysicalAddr The pointer to the data buffer pci bus master + address. + @param[in] DataLength The data count to be transferred. + +**/ +VOID +AhciBuildCommand ( + IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private, + IN UINT8 Port, + IN UINT8 PortMultiplier, + IN UINT8 FisIndex, + IN EFI_AHCI_COMMAND_FIS *CommandFis, + IN EFI_AHCI_COMMAND_LIST *CommandList, + IN UINT8 CommandSlotNumber, + IN OUT VOID *DataPhysicalAddr, + IN UINT32 DataLength + ) +{ + EFI_AHCI_REGISTERS *AhciRegisters; + UINTN AhciBar; + UINT64 BaseAddr; + UINT32 PrdtNumber; + UINT32 PrdtIndex; + UINTN RemainedData; + UINTN MemAddr; + DATA_64 Data64; + UINT32 Offset; + + AhciRegisters = &Private->AhciRegisters; + AhciBar = Private->MmioBase; + + // + // Filling the PRDT + // + PrdtNumber = (UINT32)DivU64x32 ( + (UINT64)DataLength + AHCI_MAX_DATA_PER_PRDT - 1, + AHCI_MAX_DATA_PER_PRDT + ); + + // + // According to AHCI 1.3 spec, a PRDT entry can point to a maximum 4MB data block. + // It also limits that the maximum amount of the PRDT entry in the command table + // is 65535. + // Current driver implementation supports up to a maximum of AHCI_MAX_PRDT_NUMBER + // PRDT entries. + // + ASSERT (PrdtNumber <= AHCI_MAX_PRDT_NUMBER); + if (PrdtNumber > AHCI_MAX_PRDT_NUMBER) { + return; + } + + Data64.Uint64 = (UINTN) (AhciRegisters->AhciRFis) + sizeof (EFI_AHCI_RECEIVED_FIS) * FisIndex; + + BaseAddr = Data64.Uint64; + + ZeroMem ((VOID *)((UINTN) BaseAddr), sizeof (EFI_AHCI_RECEIVED_FIS)); + + ZeroMem (AhciRegisters->AhciCmdTable, sizeof (EFI_AHCI_COMMAND_TABLE)); + + CommandFis->AhciCFisPmNum = PortMultiplier; + + CopyMem (&AhciRegisters->AhciCmdTable->CommandFis, CommandFis, sizeof (EFI_AHCI_COMMAND_FIS)); + + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD; + AhciAndReg (AhciBar, Offset, (UINT32)~(AHCI_PORT_CMD_DLAE | AHCI_PORT_CMD_ATAPI)); + + RemainedData = (UINTN) DataLength; + MemAddr = (UINTN) DataPhysicalAddr; + CommandList->AhciCmdPrdtl = PrdtNumber; + + for (PrdtIndex = 0; PrdtIndex < PrdtNumber; PrdtIndex++) { + if (RemainedData < AHCI_MAX_DATA_PER_PRDT) { + AhciRegisters->AhciCmdTable->PrdtTable[PrdtIndex].AhciPrdtDbc = (UINT32)RemainedData - 1; + } else { + AhciRegisters->AhciCmdTable->PrdtTable[PrdtIndex].AhciPrdtDbc = AHCI_MAX_DATA_PER_PRDT - 1; + } + + Data64.Uint64 = (UINT64)MemAddr; + AhciRegisters->AhciCmdTable->PrdtTable[PrdtIndex].AhciPrdtDba = Data64.Uint32.Lower32; + AhciRegisters->AhciCmdTable->PrdtTable[PrdtIndex].AhciPrdtDbau = Data64.Uint32.Upper32; + RemainedData -= AHCI_MAX_DATA_PER_PRDT; + MemAddr += AHCI_MAX_DATA_PER_PRDT; + } + + // + // Set the last PRDT to Interrupt On Complete + // + if (PrdtNumber > 0) { + AhciRegisters->AhciCmdTable->PrdtTable[PrdtNumber - 1].AhciPrdtIoc = 1; + } + + CopyMem ( + (VOID *) ((UINTN) AhciRegisters->AhciCmdList + (UINTN) CommandSlotNumber * sizeof (EFI_AHCI_COMMAND_LIST)), + CommandList, + sizeof (EFI_AHCI_COMMAND_LIST) + ); + + Data64.Uint64 = (UINT64)(UINTN) AhciRegisters->AhciCmdTable; + AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdCtba = Data64.Uint32.Lower32; + AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdCtbau = Data64.Uint32.Upper32; + AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdPmp = PortMultiplier; +} + +/** + Buid a command FIS. + + @param[in,out] CmdFis A pointer to the EFI_AHCI_COMMAND_FIS data + structure. + @param[in] AtaCommandBlock A pointer to the EFI_ATA_COMMAND_BLOCK data + structure. + +**/ +VOID +AhciBuildCommandFis ( + IN OUT EFI_AHCI_COMMAND_FIS *CmdFis, + IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock + ) +{ + ZeroMem (CmdFis, sizeof (EFI_AHCI_COMMAND_FIS)); + + CmdFis->AhciCFisType = AHCI_FIS_REGISTER_H2D; + // + // Indicator it's a command + // + CmdFis->AhciCFisCmdInd = 0x1; + CmdFis->AhciCFisCmd = AtaCommandBlock->AtaCommand; + + CmdFis->AhciCFisFeature = AtaCommandBlock->AtaFeatures; + CmdFis->AhciCFisFeatureExp = AtaCommandBlock->AtaFeaturesExp; + + CmdFis->AhciCFisSecNum = AtaCommandBlock->AtaSectorNumber; + CmdFis->AhciCFisSecNumExp = AtaCommandBlock->AtaSectorNumberExp; + + CmdFis->AhciCFisClyLow = AtaCommandBlock->AtaCylinderLow; + CmdFis->AhciCFisClyLowExp = AtaCommandBlock->AtaCylinderLowExp; + + CmdFis->AhciCFisClyHigh = AtaCommandBlock->AtaCylinderHigh; + CmdFis->AhciCFisClyHighExp = AtaCommandBlock->AtaCylinderHighExp; + + CmdFis->AhciCFisSecCount = AtaCommandBlock->AtaSectorCount; + CmdFis->AhciCFisSecCountExp = AtaCommandBlock->AtaSectorCountExp; + + CmdFis->AhciCFisDevHead = (UINT8) (AtaCommandBlock->AtaDeviceHead | 0xE0); +} + +/** + Stop command running for giving port + + @param[in] AhciBar AHCI bar address. + @param[in] Port The number of port. + @param[in] Timeout The timeout value, in 100ns units, to stop. + + @retval EFI_DEVICE_ERROR The command stop unsuccessfully. + @retval EFI_TIMEOUT The operation is time out. + @retval EFI_SUCCESS The command stop successfully. + +**/ +EFI_STATUS +AhciStopCommand ( + IN UINTN AhciBar, + IN UINT8 Port, + IN UINT64 Timeout + ) +{ + UINT32 Offset; + UINT32 Data; + + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD; + Data = AhciReadReg (AhciBar, Offset); + + if ((Data & (AHCI_PORT_CMD_ST | AHCI_PORT_CMD_CR)) == 0) { + return EFI_SUCCESS; + } + + if ((Data & AHCI_PORT_CMD_ST) != 0) { + AhciAndReg (AhciBar, Offset, (UINT32)~(AHCI_PORT_CMD_ST)); + } + + return AhciWaitMmioSet ( + AhciBar, + Offset, + AHCI_PORT_CMD_CR, + 0, + Timeout + ); +} + +/** + Start command for give slot on specific port. + + @param[in] AhciBar AHCI bar address. + @param[in] Port The number of port. + @param[in] CommandSlot The number of Command Slot. + @param[in] Timeout The timeout value, in 100ns units, to start. + + @retval EFI_DEVICE_ERROR The command start unsuccessfully. + @retval EFI_TIMEOUT The operation is time out. + @retval EFI_SUCCESS The command start successfully. + +**/ +EFI_STATUS +AhciStartCommand ( + IN UINTN AhciBar, + IN UINT8 Port, + IN UINT8 CommandSlot, + IN UINT64 Timeout + ) +{ + UINT32 CmdSlotBit; + EFI_STATUS Status; + UINT32 PortStatus; + UINT32 StartCmd; + UINT32 PortTfd; + UINT32 Offset; + UINT32 Capability; + + // + // Collect AHCI controller information + // + Capability = AhciReadReg (AhciBar, AHCI_CAPABILITY_OFFSET); + + CmdSlotBit = (UINT32) (1 << CommandSlot); + + AhciClearPortStatus ( + AhciBar, + Port + ); + + Status = AhciEnableFisReceive ( + AhciBar, + Port, + Timeout + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD; + PortStatus = AhciReadReg (AhciBar, Offset); + + StartCmd = 0; + if ((PortStatus & AHCI_PORT_CMD_ALPE) != 0) { + StartCmd = AhciReadReg (AhciBar, Offset); + StartCmd &= ~AHCI_PORT_CMD_ICC_MASK; + StartCmd |= AHCI_PORT_CMD_ACTIVE; + } + + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_TFD; + PortTfd = AhciReadReg (AhciBar, Offset); + + if ((PortTfd & (AHCI_PORT_TFD_BSY | AHCI_PORT_TFD_DRQ)) != 0) { + if ((Capability & BIT24) != 0) { + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD; + AhciOrReg (AhciBar, Offset, AHCI_PORT_CMD_CLO); + + AhciWaitMmioSet ( + AhciBar, + Offset, + AHCI_PORT_CMD_CLO, + 0, + Timeout + ); + } + } + + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD; + AhciOrReg (AhciBar, Offset, AHCI_PORT_CMD_ST | StartCmd); + + // + // Setting the command + // + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CI; + AhciAndReg (AhciBar, Offset, 0); + AhciOrReg (AhciBar, Offset, CmdSlotBit); + + return EFI_SUCCESS; +} + +/** + Start a PIO Data transfer on specific port. + + @param[in] Private The pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA. + @param[in] Port The number of port. + @param[in] PortMultiplier The number of port multiplier. + @param[in] FisIndex The offset index of the FIS base address. + @param[in] Read The transfer direction. + @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data. + @param[in,out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data. + @param[in,out] MemoryAddr The pointer to the data buffer. + @param[in] DataCount The data count to be transferred. + @param[in] Timeout The timeout value of PIO data transfer, uses + 100ns as a unit. + + @retval EFI_DEVICE_ERROR The PIO data transfer abort with error occurs. + @retval EFI_TIMEOUT The operation is time out. + @retval EFI_UNSUPPORTED The device is not ready for transfer. + @retval EFI_OUT_OF_RESOURCES The operation fails due to lack of resources. + @retval EFI_SUCCESS The PIO data transfer executes successfully. + +**/ +EFI_STATUS +AhciPioTransfer ( + IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private, + IN UINT8 Port, + IN UINT8 PortMultiplier, + IN UINT8 FisIndex, + IN BOOLEAN Read, + IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock, + IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock, + IN OUT VOID *MemoryAddr, + IN UINT32 DataCount, + IN UINT64 Timeout + ) +{ + EFI_STATUS Status; + EDKII_IOMMU_OPERATION MapOp; + UINTN MapLength; + EFI_PHYSICAL_ADDRESS PhyAddr; + VOID *MapData; + EFI_AHCI_REGISTERS *AhciRegisters; + UINTN AhciBar; + BOOLEAN InfiniteWait; + UINT32 Offset; + UINT32 OldRfisLo; + UINT32 OldRfisHi; + UINT32 OldCmdListLo; + UINT32 OldCmdListHi; + DATA_64 Data64; + UINT32 FisBaseAddr; + UINT32 Delay; + EFI_AHCI_COMMAND_FIS CFis; + EFI_AHCI_COMMAND_LIST CmdList; + UINT32 PortTfd; + UINT32 PrdCount; + BOOLEAN PioFisReceived; + BOOLEAN D2hFisReceived; + + // + // Current driver implementation supports up to a maximum of AHCI_MAX_PRDT_NUMBER + // PRDT entries. + // + if (DataCount / (UINT32)AHCI_MAX_PRDT_NUMBER > AHCI_MAX_DATA_PER_PRDT) { + DEBUG (( + DEBUG_ERROR, + "%a: Driver only support a maximum of 0x%x PRDT entries, " + "current number of data byte 0x%x is too large, maximum allowed is 0x%x.\n", + __FUNCTION__, AHCI_MAX_PRDT_NUMBER, DataCount, + AHCI_MAX_PRDT_NUMBER * AHCI_MAX_DATA_PER_PRDT + )); + return EFI_UNSUPPORTED; + } + + MapOp = Read ? EdkiiIoMmuOperationBusMasterWrite : + EdkiiIoMmuOperationBusMasterRead; + MapLength = DataCount; + Status = IoMmuMap ( + MapOp, + MemoryAddr, + &MapLength, + &PhyAddr, + &MapData + ); + if (EFI_ERROR (Status) || (MapLength != DataCount)) { + DEBUG ((DEBUG_ERROR, "%a: Fail to map data buffer.\n", __FUNCTION__)); + return EFI_OUT_OF_RESOURCES; + } + + AhciRegisters = &Private->AhciRegisters; + AhciBar = Private->MmioBase; + InfiniteWait = (Timeout == 0) ? TRUE : FALSE; + + // + // Fill FIS base address register + // + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_FB; + OldRfisLo = AhciReadReg (AhciBar, Offset); + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_FBU; + OldRfisHi = AhciReadReg (AhciBar, Offset); + Data64.Uint64 = (UINTN) (AhciRegisters->AhciRFis) + sizeof (EFI_AHCI_RECEIVED_FIS) * FisIndex; + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_FB; + AhciWriteReg (AhciBar, Offset, Data64.Uint32.Lower32); + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_FBU; + AhciWriteReg (AhciBar, Offset, Data64.Uint32.Upper32); + + // + // Single task envrionment, we only use one command table for all port + // + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CLB; + OldCmdListLo = AhciReadReg (AhciBar, Offset); + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CLBU; + OldCmdListHi = AhciReadReg (AhciBar, Offset); + Data64.Uint64 = (UINTN) (AhciRegisters->AhciCmdList); + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CLB; + AhciWriteReg (AhciBar, Offset, Data64.Uint32.Lower32); + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CLBU; + AhciWriteReg (AhciBar, Offset, Data64.Uint32.Upper32); + + // + // Package read needed + // + AhciBuildCommandFis (&CFis, AtaCommandBlock); + + ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST)); + + CmdList.AhciCmdCfl = AHCI_FIS_REGISTER_H2D_LENGTH / 4; + CmdList.AhciCmdW = Read ? 0 : 1; + + AhciBuildCommand ( + Private, + Port, + PortMultiplier, + FisIndex, + &CFis, + &CmdList, + 0, + (VOID *)(UINTN)PhyAddr, + DataCount + ); + + Status = AhciStartCommand ( + AhciBar, + Port, + 0, + Timeout + ); + if (EFI_ERROR (Status)) { + goto Exit; + } + + // + // Checking the status and wait the driver sending Data + // + FisBaseAddr = (UINT32)(UINTN)AhciRegisters->AhciRFis + sizeof (EFI_AHCI_RECEIVED_FIS) * FisIndex; + if (Read) { + // + // Wait device sends the PIO setup fis before data transfer + // + Status = EFI_TIMEOUT; + Delay = (UINT32) DivU64x32 (Timeout, 1000) + 1; + do { + PioFisReceived = FALSE; + D2hFisReceived = FALSE; + Offset = FisBaseAddr + AHCI_PIO_FIS_OFFSET; + //Status = AhciCheckMemSet (Offset, AHCI_FIS_TYPE_MASK, AHCI_FIS_PIO_SETUP); + Status = EFI_SUCCESS; // for fuzz + if (!EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "%a: PioFisReceived.\n", __FUNCTION__)); + PioFisReceived = TRUE; + } + // + // According to SATA 2.6 spec section 11.7, D2h FIS means an error encountered. + // But Qemu and Marvel 9230 sata controller may just receive a D2h FIS from + // device after the transaction is finished successfully. + // To get better device compatibilities, we further check if the PxTFD's + // ERR bit is set. By this way, we can know if there is a real error happened. + // + Offset = FisBaseAddr + AHCI_D2H_FIS_OFFSET; + Status = AhciCheckMemSet (Offset, AHCI_FIS_TYPE_MASK, AHCI_FIS_REGISTER_D2H); + if (!EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "%a: D2hFisReceived.\n", __FUNCTION__)); + D2hFisReceived = TRUE; + } + + if (PioFisReceived || D2hFisReceived) { + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_TFD; + PortTfd = AhciReadReg (AhciBar, (UINT32) Offset); + // + // PxTFD will be updated if there is a D2H or SetupFIS received. + // + if ((PortTfd & AHCI_PORT_TFD_ERR) != 0) { + Status = EFI_DEVICE_ERROR; + break; + } + + //PrdCount = *(volatile UINT32 *) (&(AhciRegisters->AhciCmdList[0].AhciCmdPrdbc)); + PrdCount = DataCount; // for fuzz + if (PrdCount == DataCount) { + Status = EFI_SUCCESS; + break; + } + } + + // + // Stall for 100 microseconds. + // + MicroSecondDelay(100); + + Delay--; + if (Delay == 0) { + Status = EFI_TIMEOUT; + } + } while (InfiniteWait || (Delay > 0)); + } else { + // + // Wait for D2H Fis is received + // + Offset = FisBaseAddr + AHCI_D2H_FIS_OFFSET; + Status = AhciWaitMemSet ( + Offset, + AHCI_FIS_TYPE_MASK, + AHCI_FIS_REGISTER_D2H, + Timeout + ); + Status = EFI_SUCCESS; // for fuzz + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: AhciWaitMemSet (%r)\n", __FUNCTION__, Status)); + goto Exit; + } + + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_TFD; + PortTfd = AhciReadReg (AhciBar, (UINT32) Offset); + if ((PortTfd & AHCI_PORT_TFD_ERR) != 0) { + Status = EFI_DEVICE_ERROR; + } + } + +Exit: + AhciStopCommand ( + AhciBar, + Port, + Timeout + ); + + AhciDisableFisReceive ( + AhciBar, + Port, + Timeout + ); + + if (MapData != NULL) { + IoMmuUnmap (MapData); + } + + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_FB; + AhciWriteReg (AhciBar, Offset, OldRfisLo); + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_FBU; + AhciWriteReg (AhciBar, Offset, OldRfisHi); + + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CLB; + AhciWriteReg (AhciBar, Offset, OldCmdListLo); + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CLBU; + AhciWriteReg (AhciBar, Offset, OldCmdListHi); + + return Status; +} + +/** + Start a non data transfer on specific port. + + @param[in] Private The pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA. + @param[in] Port The number of port. + @param[in] PortMultiplier The number of port multiplier. + @param[in] FisIndex The offset index of the FIS base address. + @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data. + @param[in,out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data. + @param[in] Timeout The timeout value of non data transfer, uses + 100ns as a unit. + + @retval EFI_DEVICE_ERROR The non data transfer abort with error occurs. + @retval EFI_TIMEOUT The operation is time out. + @retval EFI_UNSUPPORTED The device is not ready for transfer. + @retval EFI_SUCCESS The non data transfer executes successfully. + +**/ +EFI_STATUS +AhciNonDataTransfer ( + IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private, + IN UINT8 Port, + IN UINT8 PortMultiplier, + IN UINT8 FisIndex, + IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock, + IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock, + IN UINT64 Timeout + ) +{ + EFI_STATUS Status; + UINTN AhciBar; + EFI_AHCI_REGISTERS *AhciRegisters; + UINTN FisBaseAddr; + UINTN Offset; + UINT32 PortTfd; + EFI_AHCI_COMMAND_FIS CFis; + EFI_AHCI_COMMAND_LIST CmdList; + + AhciBar = Private->MmioBase; + AhciRegisters = &Private->AhciRegisters; + + // + // Package read needed + // + AhciBuildCommandFis (&CFis, AtaCommandBlock); + + ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST)); + + CmdList.AhciCmdCfl = AHCI_FIS_REGISTER_H2D_LENGTH / 4; + + AhciBuildCommand ( + Private, + Port, + PortMultiplier, + FisIndex, + &CFis, + &CmdList, + 0, + NULL, + 0 + ); + + Status = AhciStartCommand ( + AhciBar, + Port, + 0, + Timeout + ); + if (EFI_ERROR (Status)) { + goto Exit; + } + + // + // Wait device sends the Response Fis + // + FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + sizeof (EFI_AHCI_RECEIVED_FIS) * FisIndex; + Offset = FisBaseAddr + AHCI_D2H_FIS_OFFSET; + Status = AhciWaitMemSet ( + Offset, + AHCI_FIS_TYPE_MASK, + AHCI_FIS_REGISTER_D2H, + Timeout + ); + + if (EFI_ERROR (Status)) { + goto Exit; + } + + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_TFD; + PortTfd = AhciReadReg (AhciBar, (UINT32) Offset); + if ((PortTfd & AHCI_PORT_TFD_ERR) != 0) { + Status = EFI_DEVICE_ERROR; + } + +Exit: + AhciStopCommand ( + AhciBar, + Port, + Timeout + ); + + AhciDisableFisReceive ( + AhciBar, + Port, + Timeout + ); + + return Status; +} + +/** + Do AHCI HBA reset. + + @param[in] AhciBar AHCI bar address. + @param[in] Timeout The timeout, in 100ns units, to reset. + + @retval EFI_DEVICE_ERROR AHCI controller is failed to complete hardware reset. + @retval EFI_TIMEOUT The reset operation is time out. + @retval EFI_SUCCESS AHCI controller is reset successfully. + +**/ +EFI_STATUS +AhciReset ( + IN UINTN AhciBar, + IN UINT64 Timeout + ) +{ + UINT32 Delay; + UINT32 Value; + UINT32 Capability; + + // + // Collect AHCI controller information + // + Capability = AhciReadReg (AhciBar, AHCI_CAPABILITY_OFFSET); + + // + // Enable AE before accessing any AHCI registers if Supports AHCI Mode Only is not set + // + if ((Capability & AHCI_CAP_SAM) == 0) { + AhciOrReg (AhciBar, AHCI_GHC_OFFSET, AHCI_GHC_ENABLE); + } + + AhciOrReg (AhciBar, AHCI_GHC_OFFSET, AHCI_GHC_RESET); + + Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1); + + do { + Value = AhciReadReg(AhciBar, AHCI_GHC_OFFSET); + if ((Value & AHCI_GHC_RESET) == 0) { + return EFI_SUCCESS; + } + + // + // Stall for 100 microseconds. + // + MicroSecondDelay(100); + + Delay--; + } while (Delay > 0); + + return EFI_TIMEOUT; +} + +/** + Send Identify Drive command to a specific device. + + @param[in] Private The pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA. + @param[in] Port The number of port. + @param[in] PortMultiplier The port multiplier port number. + @param[in] FisIndex The offset index of the FIS base address. + @param[in] Buffer The data buffer to store IDENTIFY PACKET data. + + @retval EFI_SUCCESS The cmd executes successfully. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_DEVICE_ERROR The cmd abort with error occurs. + @retval EFI_TIMEOUT The operation is time out. + @retval EFI_UNSUPPORTED The device is not ready for executing. + +**/ +EFI_STATUS +AhciIdentify ( + IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private, + IN UINT8 Port, + IN UINT8 PortMultiplier, + IN UINT8 FisIndex, + IN ATA_IDENTIFY_DATA *Buffer + ) +{ + EFI_STATUS Status; + EFI_ATA_COMMAND_BLOCK Acb; + EFI_ATA_STATUS_BLOCK Asb; + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + ZeroMem (&Acb, sizeof (EFI_ATA_COMMAND_BLOCK)); + ZeroMem (&Asb, sizeof (EFI_ATA_STATUS_BLOCK)); + + Acb.AtaCommand = ATA_CMD_IDENTIFY_DRIVE; + Acb.AtaSectorCount = 1; + + Status = AhciPioTransfer ( + Private, + Port, + PortMultiplier, + FisIndex, + TRUE, + &Acb, + &Asb, + Buffer, + sizeof (ATA_IDENTIFY_DATA), + ATA_TIMEOUT + ); + + return Status; +} + + +/** + Collect the number of bits set within a port bitmap. + + @param[in] PortBitMap A 32-bit wide bit map of ATA AHCI ports. + + @retval The number of bits set in the bitmap. + +**/ +UINT8 +AhciGetNumberOfPortsFromMap ( + IN UINT32 PortBitMap + ) +{ + UINT8 NumberOfPorts; + + NumberOfPorts = 0; + + while (PortBitMap != 0) { + if ((PortBitMap & ((UINT32)BIT0)) != 0) { + NumberOfPorts++; + } + PortBitMap = PortBitMap >> 1; + } + + return NumberOfPorts; +} + +/** + Get the specified port number from a port bitmap. + + @param[in] PortBitMap A 32-bit wide bit map of ATA AHCI ports. + @param[in] PortIndex The specified port index. + @param[out] Port The port number of the port specified by PortIndex. + + @retval EFI_SUCCESS The specified port is found and its port number is + in Port. + @retval EFI_NOT_FOUND Cannot find the specified port within the port bitmap. + +**/ +EFI_STATUS +AhciGetPortFromMap ( + IN UINT32 PortBitMap, + IN UINT8 PortIndex, + OUT UINT8 *Port + ) +{ + if (PortIndex == 0) { + return EFI_NOT_FOUND; + } + + *Port = 0; + + while (PortBitMap != 0) { + if ((PortBitMap & ((UINT32)BIT0)) != 0) { + PortIndex--; + + // + // Found the port specified by PortIndex. + // + if (PortIndex == 0) { + return EFI_SUCCESS; + } + } + PortBitMap = PortBitMap >> 1; + *Port = *Port + 1; + } + + return EFI_NOT_FOUND; +} + +/** + Allocate transfer-related data struct which is used at AHCI mode. + + @param[in,out] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA instance. + + @retval EFI_SUCCESS Data structures are allocated successfully. + @retval Others Data structures are not allocated successfully. + +**/ +EFI_STATUS +AhciCreateTransferDescriptor ( + IN OUT PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private + ) +{ + EFI_STATUS Status; + UINTN AhciBar; + EFI_AHCI_REGISTERS *AhciRegisters; + EFI_PHYSICAL_ADDRESS DeviceAddress; + VOID *Base; + VOID *Mapping; + UINT32 Capability; + UINT32 PortImplementBitMap; + UINT8 MaxPortNumber; + UINT8 MaxCommandSlotNumber; + UINTN MaxRFisSize; + UINTN MaxCmdListSize; + UINTN MaxCmdTableSize; + + AhciBar = Private->MmioBase; + AhciRegisters = &Private->AhciRegisters; + + // + // Collect AHCI controller information + // + Capability = AhciReadReg (AhciBar, AHCI_CAPABILITY_OFFSET); + + // + // Get the number of command slots per port supported by this HBA. + // + MaxCommandSlotNumber = (UINT8) (((Capability & 0x1F00) >> 8) + 1); + ASSERT (MaxCommandSlotNumber > 0); + //if (MaxCommandSlotNumber == 0) { + // return EFI_DEVICE_ERROR; + //} + + // + // Get the highest bit of implemented ports which decides how many bytes are + // allocated for recived FIS. + // + PortImplementBitMap = AhciReadReg (AhciBar, AHCI_PI_OFFSET); + //MaxPortNumber = (UINT8)(UINTN)(HighBitSet32(PortImplementBitMap) + 1); + MaxPortNumber = 1; // for fuzz + //if (MaxPortNumber == 0) { + // return EFI_DEVICE_ERROR; + //} + // + // Get the number of ports that actually needed to be initialized. + // + MaxPortNumber = MIN (MaxPortNumber, AhciGetNumberOfPortsFromMap (Private->PortBitMap)); + + // + // Allocate memory for received FIS. + // + MaxRFisSize = MaxPortNumber * sizeof (EFI_AHCI_RECEIVED_FIS); + Status = IoMmuAllocateBuffer ( + EFI_SIZE_TO_PAGES (MaxRFisSize), + &Base, + &DeviceAddress, + &Mapping + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base)); + AhciRegisters->AhciRFis = Base; + AhciRegisters->AhciRFisMap = Mapping; + AhciRegisters->MaxRFisSize = MaxRFisSize; + ZeroMem (AhciRegisters->AhciRFis, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES (MaxRFisSize)); + + // + // Allocate memory for command list. + // Note that the implemenation is a single task model which only use a command + // list for each port. + // + MaxCmdListSize = 1 * sizeof (EFI_AHCI_COMMAND_LIST); + Status = IoMmuAllocateBuffer ( + EFI_SIZE_TO_PAGES (MaxCmdListSize), + &Base, + &DeviceAddress, + &Mapping + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base)); + AhciRegisters->AhciCmdList = Base; + AhciRegisters->AhciCmdListMap = Mapping; + AhciRegisters->MaxCmdListSize = MaxCmdListSize; + ZeroMem (AhciRegisters->AhciCmdList, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES (MaxCmdListSize)); + + // + // Allocate memory for command table + // According to AHCI 1.3 spec, a PRD table can contain maximum 65535 entries. + // + MaxCmdTableSize = sizeof (EFI_AHCI_COMMAND_TABLE); + Status = IoMmuAllocateBuffer ( + EFI_SIZE_TO_PAGES (MaxCmdTableSize), + &Base, + &DeviceAddress, + &Mapping + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base)); + AhciRegisters->AhciCmdTable = Base; + AhciRegisters->AhciCmdTableMap = Mapping; + AhciRegisters->MaxCmdTableSize = MaxCmdTableSize; + ZeroMem (AhciRegisters->AhciCmdTable, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES (MaxCmdTableSize)); + + return EFI_SUCCESS; + +ErrorExit: + if (AhciRegisters->AhciRFisMap != NULL) { + IoMmuFreeBuffer ( + EFI_SIZE_TO_PAGES (AhciRegisters->MaxRFisSize), + AhciRegisters->AhciRFis, + AhciRegisters->AhciRFisMap + ); + AhciRegisters->AhciRFis = NULL; + } + + if (AhciRegisters->AhciCmdListMap != NULL) { + IoMmuFreeBuffer ( + EFI_SIZE_TO_PAGES (AhciRegisters->MaxCmdListSize), + AhciRegisters->AhciCmdList, + AhciRegisters->AhciCmdListMap + ); + AhciRegisters->AhciCmdList = NULL; + } + + return Status; +} + +/** + Gets ATA device Capacity according to ATA 6. + + This function returns the capacity of the ATA device if it follows + ATA 6 to support 48 bit addressing. + + @param[in] IdentifyData A pointer to ATA_IDENTIFY_DATA structure. + + @return The capacity of the ATA device or 0 if the device does not support + 48-bit addressing defined in ATA 6. + +**/ +EFI_LBA +GetAtapi6Capacity ( + IN ATA_IDENTIFY_DATA *IdentifyData + ) +{ + EFI_LBA Capacity; + EFI_LBA TmpLba; + UINTN Index; + + if ((IdentifyData->command_set_supported_83 & BIT10) == 0) { + // + // The device doesn't support 48 bit addressing + // + return 0; + } + + // + // 48 bit address feature set is supported, get maximum capacity + // + Capacity = 0; + for (Index = 0; Index < 4; Index++) { + // + // Lower byte goes first: word[100] is the lowest word, word[103] is highest + // + TmpLba = IdentifyData->maximum_lba_for_48bit_addressing[Index]; + Capacity |= LShiftU64 (TmpLba, 16 * Index); + } + + return Capacity; +} + +/** + Identifies ATA device via the Identify data. + + This function identifies the ATA device and initializes the media information. + + @attention This is boundary function that may receive untrusted input. + @attention The input is from peripheral hardware device. + + The Identify Drive command response data from an ATA device is the peripheral + hardware input, so this routine will do basic validation for the Identify Drive + command response data. + + @param[in,out] DeviceData A pointer to PEI_AHCI_ATA_DEVICE_DATA structure. + + @retval EFI_SUCCESS The device is successfully identified and media + information is correctly initialized. + @retval EFI_UNSUPPORTED The device is not a valid ATA device (hard disk). + +**/ +EFI_STATUS +IdentifyAtaDevice ( + IN OUT PEI_AHCI_ATA_DEVICE_DATA *DeviceData + ) +{ + ATA_IDENTIFY_DATA *IdentifyData; + EFI_PEI_BLOCK_IO2_MEDIA *Media; + EFI_LBA Capacity; + UINT32 MaxSectorCount; + UINT16 PhyLogicSectorSupport; + + IdentifyData = DeviceData->IdentifyData; + Media = &DeviceData->Media; + + if ((IdentifyData->config & BIT15) != 0) { + DEBUG (( + DEBUG_ERROR, "%a: Not a hard disk device on Port 0x%x PortMultiplierPort 0x%x\n", + __FUNCTION__, DeviceData->Port, DeviceData->PortMultiplier + )); + return EFI_UNSUPPORTED; + } + + DEBUG (( + DEBUG_INFO, "%a: Identify Device: Port 0x%x PortMultiplierPort 0x%x\n", + __FUNCTION__, DeviceData->Port, DeviceData->PortMultiplier + )); + + // + // Skip checking whether the WORD 88 (supported UltraDMA by drive), since the + // driver only support PIO data transfer for now. + // + + // + // Get the capacity information of the device. + // + Capacity = GetAtapi6Capacity (IdentifyData); + if (Capacity > MAX_28BIT_ADDRESSING_CAPACITY) { + // + // Capacity exceeds 120GB. 48-bit addressing is really needed + // + DeviceData->Lba48Bit = TRUE; + } else { + // + // This is a hard disk <= 120GB capacity, treat it as normal hard disk + // + Capacity = ((UINT32)IdentifyData->user_addressable_sectors_hi << 16) | + IdentifyData->user_addressable_sectors_lo; + DeviceData->Lba48Bit = FALSE; + } + + if (Capacity == 0) { + DEBUG ((DEBUG_ERROR, "%a: Invalid Capacity (0) for ATA device.\n", __FUNCTION__)); + return EFI_UNSUPPORTED; + } + Media->LastBlock = (EFI_PEI_LBA) (Capacity - 1); + + Media->BlockSize = 0x200; + // + // Check whether Long Physical Sector Feature is supported + // + PhyLogicSectorSupport = IdentifyData->phy_logic_sector_support; + DEBUG (( + DEBUG_INFO, "%a: PhyLogicSectorSupport = 0x%x\n", + __FUNCTION__, PhyLogicSectorSupport + )); + if ((PhyLogicSectorSupport & (BIT14 | BIT15)) == BIT14) { + // + // Check logical block size + // + if ((PhyLogicSectorSupport & BIT12) != 0) { + Media->BlockSize = (UINT32) (((IdentifyData->logic_sector_size_hi << 16) | + IdentifyData->logic_sector_size_lo) * sizeof (UINT16)); + } + } + + // + // Check BlockSize validity + // + MaxSectorCount = mMaxTransferBlockNumber[DeviceData->Lba48Bit]; + if ((Media->BlockSize == 0) || (Media->BlockSize > MAX_UINT32 / MaxSectorCount)) { + DEBUG ((DEBUG_ERROR, "%a: Invalid BlockSize (0x%x).\n", __FUNCTION__, Media->BlockSize)); + return EFI_UNSUPPORTED; + } + + DEBUG (( + DEBUG_INFO, "%a: BlockSize = 0x%x, LastBlock = 0x%lx\n", + __FUNCTION__, Media->BlockSize, Media->LastBlock + )); + + if ((IdentifyData->trusted_computing_support & BIT0) != 0) { + DEBUG ((DEBUG_INFO, "%a: Found Trust Computing feature support.\n", __FUNCTION__)); + DeviceData->TrustComputing = TRUE; + } + + Media->InterfaceType = MSG_SATA_DP; + Media->RemovableMedia = FALSE; + Media->MediaPresent = TRUE; + Media->ReadOnly = FALSE; + + return EFI_SUCCESS; +} + +/** + Allocate device information data structure to contain device information. + And insert the data structure to the tail of device list for tracing. + + @param[in,out] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA + instance. + @param[in] DeviceIndex The device index. + @param[in] Port The port number of the ATA device to send + the command. + @param[in] PortMultiplierPort The port multiplier port number of the ATA + device to send the command. + If there is no port multiplier, then specify + 0xFFFF. + @param[in] FisIndex The index of the FIS of the ATA device to + send the command. + @param[in] IdentifyData The data buffer to store the output of the + IDENTIFY command. + + @retval EFI_SUCCESS Successfully insert the ATA device to the + tail of device list. + @retval EFI_OUT_OF_RESOURCES Not enough resource. + +**/ +EFI_STATUS +CreateNewDevice ( + IN OUT PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private, + IN UINTN DeviceIndex, + IN UINT16 Port, + IN UINT16 PortMultiplier, + IN UINT8 FisIndex, + IN ATA_IDENTIFY_DATA *IdentifyData + ) +{ + PEI_AHCI_ATA_DEVICE_DATA *DeviceData; + EFI_STATUS Status; + + DeviceData = AllocateZeroPool (sizeof (PEI_AHCI_ATA_DEVICE_DATA)); + if (DeviceData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + if (IdentifyData != NULL) { + DeviceData->IdentifyData = AllocateCopyPool (sizeof (ATA_IDENTIFY_DATA), IdentifyData); + if (DeviceData->IdentifyData == NULL) { + free(DeviceData); + return EFI_OUT_OF_RESOURCES; + } + } + + DeviceData->Signature = AHCI_PEI_ATA_DEVICE_DATA_SIGNATURE; + DeviceData->Port = Port; + DeviceData->PortMultiplier = PortMultiplier; + DeviceData->FisIndex = FisIndex; + DeviceData->DeviceIndex = DeviceIndex; + DeviceData->Private = Private; + + Status = IdentifyAtaDevice (DeviceData); + if (EFI_ERROR (Status)) { + free(DeviceData); + return Status; + } + + if (DeviceData->TrustComputing) { + Private->TrustComputingDevices++; + DeviceData->TrustComputingDeviceIndex = Private->TrustComputingDevices; + } + Private->ActiveDevices++; + InsertTailList (&Private->DeviceList, &DeviceData->Link); + + return EFI_SUCCESS; +} + +/** + Initialize ATA host controller at AHCI mode. + + The function is designed to initialize ATA host controller. + + @param[in,out] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA instance. + + @retval EFI_SUCCESS The ATA AHCI controller is initialized successfully. + @retval EFI_OUT_OF_RESOURCES Not enough resource to complete while initializing + the controller. + @retval Others A device error occurred while initializing the + controller. + +**/ +EFI_STATUS +AhciModeInitialization ( + IN OUT PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private + ) +{ + EFI_STATUS Status; + UINTN AhciBar; + UINT32 Capability; + UINT32 Value; + UINT8 MaxPortNumber; + UINT32 PortImplementBitMap; + UINT32 PortInitializeBitMap; + EFI_AHCI_REGISTERS *AhciRegisters; + UINT8 PortIndex; + UINT8 Port; + DATA_64 Data64; + UINT32 Data; + UINT32 Offset; + UINT32 PhyDetectDelay; + UINTN DeviceIndex; + ATA_IDENTIFY_DATA IdentifyData; + + AhciBar = Private->MmioBase; + + Status = AhciReset (AhciBar, AHCI_PEI_RESET_TIMEOUT); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: AHCI HBA reset failed with %r.\n", __FUNCTION__, Status)); + return EFI_DEVICE_ERROR; + } + + // + // Collect AHCI controller information + // + Capability = AhciReadReg (AhciBar, AHCI_CAPABILITY_OFFSET); + + // + // Make sure that GHC.AE bit is set before accessing any AHCI registers. + // + Value = AhciReadReg (AhciBar, AHCI_GHC_OFFSET); + if ((Value & AHCI_GHC_ENABLE) == 0) { + AhciOrReg (AhciBar, AHCI_GHC_OFFSET, AHCI_GHC_ENABLE); + } + + Status = AhciCreateTransferDescriptor (Private); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: Transfer-related data allocation failed with %r.\n", + __FUNCTION__, Status + )); + return EFI_OUT_OF_RESOURCES; + } + + // + // Get the number of command slots per port supported by this HBA. + // + MaxPortNumber = (UINT8) ((Capability & 0x1F) + 1); + + // + // Get the bit map of those ports exposed by this HBA. + // It indicates which ports that the HBA supports are available for software + // to use. + // + PortImplementBitMap = AhciReadReg (AhciBar, AHCI_PI_OFFSET); + + // + // Get the number of ports that actually needed to be initialized. + // + MaxPortNumber = MIN (MaxPortNumber, (UINT8)(UINTN)(HighBitSet32(PortImplementBitMap) + 1)); + MaxPortNumber = MIN (MaxPortNumber, AhciGetNumberOfPortsFromMap (Private->PortBitMap)); + + PortInitializeBitMap = Private->PortBitMap; + AhciRegisters = &Private->AhciRegisters; + DeviceIndex = 0; + // + // Enumerate ATA ports + // + for (PortIndex = 1; PortIndex <= MaxPortNumber; PortIndex ++) { + Status = AhciGetPortFromMap (PortInitializeBitMap, PortIndex, &Port); + if ((PortImplementBitMap & (BIT0 << Port)) != 0) { + // + // Initialize FIS Base Address Register and Command List Base Address + // Register for use. + // + Data64.Uint64 = (UINTN) (AhciRegisters->AhciRFis) + + sizeof (EFI_AHCI_RECEIVED_FIS) * (PortIndex - 1); + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_FB; + AhciWriteReg (AhciBar, Offset, Data64.Uint32.Lower32); + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_FBU; + AhciWriteReg (AhciBar, Offset, Data64.Uint32.Upper32); + + Data64.Uint64 = (UINTN) (AhciRegisters->AhciCmdList); + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CLB; + AhciWriteReg (AhciBar, Offset, Data64.Uint32.Lower32); + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CLBU; + AhciWriteReg (AhciBar, Offset, Data64.Uint32.Upper32); + + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD; + Data = AhciReadReg (AhciBar, Offset); + if ((Data & AHCI_PORT_CMD_CPD) != 0) { + AhciOrReg (AhciBar, Offset, AHCI_PORT_CMD_POD); + } + + if ((Capability & AHCI_CAP_SSS) != 0) { + AhciOrReg (AhciBar, Offset, AHCI_PORT_CMD_SUD); + } + + // + // Disable aggressive power management. + // + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_SCTL; + AhciOrReg (AhciBar, Offset, AHCI_PORT_SCTL_IPM_INIT); + // + // Disable the reporting of the corresponding interrupt to system software. + // + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_IE; + AhciAndReg (AhciBar, Offset, 0); + + // + // Enable FIS Receive DMA engine for the first D2H FIS. + // + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD; + AhciOrReg (AhciBar, Offset, AHCI_PORT_CMD_FRE); + + // + // Wait no longer than 15 ms to wait the Phy to detect the presence of a device. + // + PhyDetectDelay = AHCI_BUS_PHY_DETECT_TIMEOUT; + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_SSTS; + do { + Data = AhciReadReg (AhciBar, Offset) & AHCI_PORT_SSTS_DET_MASK; + if ((Data == AHCI_PORT_SSTS_DET_PCE) || (Data == AHCI_PORT_SSTS_DET)) { + break; + } + + MicroSecondDelay (1000); + PhyDetectDelay--; + } while (PhyDetectDelay > 0); + + if (PhyDetectDelay == 0) { + // + // No device detected at this port. + // Clear PxCMD.SUD for those ports at which there are no device present. + // + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD; + AhciAndReg (AhciBar, Offset, (UINT32) ~(AHCI_PORT_CMD_SUD)); + DEBUG ((DEBUG_ERROR, "%a: No device detected at Port %d.\n", __FUNCTION__, Port)); + continue; + } + + // + // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY and PxTFD.DRQ + // and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined at ATA spec. + // + PhyDetectDelay = 16 * 1000; + do { + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_SERR; + if (AhciReadReg(AhciBar, Offset) != 0) { + AhciWriteReg (AhciBar, Offset, AhciReadReg (AhciBar, Offset)); + } + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_TFD; + + Data = AhciReadReg (AhciBar, Offset) & AHCI_PORT_TFD_MASK; + if (Data == 0) { + break; + } + + MicroSecondDelay (1000); + PhyDetectDelay--; + } while (PhyDetectDelay > 0); + + if (PhyDetectDelay == 0) { + DEBUG (( + DEBUG_ERROR, + "%a: Port %d device presence detected but phy not ready (TFD=0x%x).\n", + __FUNCTION__, Port, Data + )); + continue; + } + + // + // When the first D2H register FIS is received, the content of PxSIG register is updated. + // + Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_SIG; + Status = AhciWaitMmioSet ( + AhciBar, + Offset, + 0x0000FFFF, + 0x00000101, + 160000000 + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: Error occured when waiting for the first D2H register FIS - %r\n", + __FUNCTION__, Status + )); + continue; + } + + Data = AhciReadReg (AhciBar, Offset); + if ((Data & AHCI_ATAPI_SIG_MASK) == AHCI_ATA_DEVICE_SIG) { + Status = AhciIdentify (Private, Port, 0, PortIndex - 1, &IdentifyData); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: AhciIdentify() failed with %r\n", __FUNCTION__, Status)); + continue; + } + DEBUG ((DEBUG_INFO, "%a: ATA hard disk found on Port %d.\n", __FUNCTION__, Port)); + } else { + continue; + } + + // + // Found an ATA hard disk device, add it into the device list. + // + DeviceIndex++; + CreateNewDevice ( + Private, + DeviceIndex, + Port, + 0xFFFF, + PortIndex - 1, + &IdentifyData + ); + } + } + + return EFI_SUCCESS; +} + +/** + Transfer data from ATA device. + + This function performs one ATA pass through transaction to transfer data from/to + ATA device. It chooses the appropriate ATA command and protocol to invoke PassThru + interface of ATA pass through. + + @param[in] DeviceData A pointer to PEI_AHCI_ATA_DEVICE_DATA structure. + @param[in,out] Buffer The pointer to the current transaction buffer. + @param[in] StartLba The starting logical block address to be accessed. + @param[in] TransferLength The block number or sector count of the transfer. + @param[in] IsWrite Indicates whether it is a write operation. + + @retval EFI_SUCCESS The data transfer is complete successfully. + @return others Some error occurs when transferring data. + +**/ +EFI_STATUS +TransferAtaDevice ( + IN PEI_AHCI_ATA_DEVICE_DATA *DeviceData, + IN OUT VOID *Buffer, + IN EFI_LBA StartLba, + IN UINT32 TransferLength, + IN BOOLEAN IsWrite + ) +{ + PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private; + EDKII_PEI_ATA_PASS_THRU_PPI *AtaPassThru; + EFI_ATA_COMMAND_BLOCK Acb; + EFI_ATA_PASS_THRU_COMMAND_PACKET Packet; + + Private = DeviceData->Private; + AtaPassThru = &Private->AtaPassThruPpi; + + // + // Ensure Lba48Bit and IsWrite are valid boolean values + // + ASSERT ((UINTN) DeviceData->Lba48Bit < 2); + ASSERT ((UINTN) IsWrite < 2); + if (((UINTN) DeviceData->Lba48Bit >= 2) || + ((UINTN) IsWrite >= 2)) { + return EFI_INVALID_PARAMETER; + } + + // + // Prepare for ATA command block. + // + ZeroMem (&Acb, sizeof (EFI_ATA_COMMAND_BLOCK)); + Acb.AtaCommand = mAtaCommands[DeviceData->Lba48Bit][IsWrite]; + Acb.AtaSectorNumber = (UINT8) StartLba; + Acb.AtaCylinderLow = (UINT8) RShiftU64 (StartLba, 8); + Acb.AtaCylinderHigh = (UINT8) RShiftU64 (StartLba, 16); + Acb.AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | + (DeviceData->PortMultiplier == 0xFFFF ? + 0 : (DeviceData->PortMultiplier << 4))); + Acb.AtaSectorCount = (UINT8) TransferLength; + if (DeviceData->Lba48Bit) { + Acb.AtaSectorNumberExp = (UINT8) RShiftU64 (StartLba, 24); + Acb.AtaCylinderLowExp = (UINT8) RShiftU64 (StartLba, 32); + Acb.AtaCylinderHighExp = (UINT8) RShiftU64 (StartLba, 40); + Acb.AtaSectorCountExp = (UINT8) (TransferLength >> 8); + } else { + Acb.AtaDeviceHead = (UINT8) (Acb.AtaDeviceHead | RShiftU64 (StartLba, 24)); + } + + // + // Prepare for ATA pass through packet. + // + ZeroMem (&Packet, sizeof (EFI_ATA_PASS_THRU_COMMAND_PACKET)); + if (IsWrite) { + Packet.OutDataBuffer = Buffer; + Packet.OutTransferLength = TransferLength; + } else { + Packet.InDataBuffer = Buffer; + Packet.InTransferLength = TransferLength; + } + Packet.Asb = NULL; + Packet.Acb = &Acb; + Packet.Protocol = mAtaPassThruCmdProtocols[IsWrite]; + Packet.Length = EFI_ATA_PASS_THRU_LENGTH_SECTOR_COUNT; + // + // |------------------------|-----------------| + // | ATA PIO Transfer Mode | Transfer Rate | + // |------------------------|-----------------| + // | PIO Mode 0 | 3.3Mbytes/sec | + // |------------------------|-----------------| + // | PIO Mode 1 | 5.2Mbytes/sec | + // |------------------------|-----------------| + // | PIO Mode 2 | 8.3Mbytes/sec | + // |------------------------|-----------------| + // | PIO Mode 3 | 11.1Mbytes/sec | + // |------------------------|-----------------| + // | PIO Mode 4 | 16.6Mbytes/sec | + // |------------------------|-----------------| + // + // As AtaBus is used to manage ATA devices, we have to use the lowest transfer + // rate to calculate the possible maximum timeout value for each read/write + // operation. The timout value is rounded up to nearest integar and here an + // additional 30s is added to follow ATA spec in which it mentioned that the + // device may take up to 30s to respond commands in the Standby/Idle mode. + // + // Calculate the maximum timeout value for PIO read/write operation. + // + Packet.Timeout = TIMER_PERIOD_SECONDS ( + DivU64x32 ( + MultU64x32 (TransferLength, DeviceData->Media.BlockSize), + 3300000 + ) + 31 + ); + + return AtaPassThru->PassThru ( + AtaPassThru, + DeviceData->Port, + DeviceData->PortMultiplier, + &Packet + ); +} + +/** + Trust transfer data from/to ATA device. + + This function performs one ATA pass through transaction to do a trust transfer + from/to ATA device. It chooses the appropriate ATA command and protocol to invoke + PassThru interface of ATA pass through. + + @param[in] DeviceData Pointer to PEI_AHCI_ATA_DEVICE_DATA structure. + @param[in,out] Buffer The pointer to the current transaction buffer. + @param[in] SecurityProtocolId + The value of the "Security Protocol" parameter + of the security protocol command to be sent. + @param[in] SecurityProtocolSpecificData + The value of the "Security Protocol Specific" + parameter of the security protocol command to + be sent. + @param[in] TransferLength The block number or sector count of the transfer. + @param[in] IsTrustSend Indicates whether it is a trust send operation + or not. + @param[in] Timeout The timeout, in 100ns units, to use for the execution + of the security protocol command. A Timeout value + of 0 means that this function will wait indefinitely + for the security protocol command to execute. If + Timeout is greater than zero, then this function + will return EFI_TIMEOUT if the time required to + execute the receive data command is greater than + Timeout. + @param[out] TransferLengthOut + A pointer to a buffer to store the size in bytes + of the data written to the buffer. Ignore it when + IsTrustSend is TRUE. + + @retval EFI_SUCCESS The data transfer is complete successfully. + @return others Some error occurs when transferring data. + +**/ +EFI_STATUS +TrustTransferAtaDevice ( + IN PEI_AHCI_ATA_DEVICE_DATA *DeviceData, + IN OUT VOID *Buffer, + IN UINT8 SecurityProtocolId, + IN UINT16 SecurityProtocolSpecificData, + IN UINTN TransferLength, + IN BOOLEAN IsTrustSend, + IN UINT64 Timeout, + OUT UINTN *TransferLengthOut + ) +{ + PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private; + EDKII_PEI_ATA_PASS_THRU_PPI *AtaPassThru; + EFI_ATA_COMMAND_BLOCK Acb; + EFI_ATA_PASS_THRU_COMMAND_PACKET Packet; + EFI_STATUS Status; + VOID *NewBuffer; + + Private = DeviceData->Private; + AtaPassThru = &Private->AtaPassThruPpi; + + // + // Ensure IsTrustSend are valid boolean values + // + ASSERT ((UINTN) IsTrustSend < 2); + if ((UINTN) IsTrustSend >= 2) { + return EFI_INVALID_PARAMETER; + } + + // + // Prepare for ATA command block. + // + ZeroMem (&Acb, sizeof (EFI_ATA_COMMAND_BLOCK)); + if (TransferLength == 0) { + Acb.AtaCommand = ATA_CMD_TRUST_NON_DATA; + } else { + Acb.AtaCommand = mAtaTrustCommands[IsTrustSend]; + } + Acb.AtaFeatures = SecurityProtocolId; + Acb.AtaSectorCount = (UINT8) (TransferLength / 512); + Acb.AtaSectorNumber = (UINT8) ((TransferLength / 512) >> 8); + // + // NOTE: ATA Spec has no explicitly definition for Security Protocol Specific layout. + // Here use big endian for Cylinder register. + // + Acb.AtaCylinderHigh = (UINT8) SecurityProtocolSpecificData; + Acb.AtaCylinderLow = (UINT8) (SecurityProtocolSpecificData >> 8); + Acb.AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | + (DeviceData->PortMultiplier == 0xFFFF ? + 0 : (DeviceData->PortMultiplier << 4))); + + // + // Prepare for ATA pass through packet. + // + ZeroMem (&Packet, sizeof (EFI_ATA_PASS_THRU_COMMAND_PACKET)); + if (TransferLength == 0) { + Packet.InTransferLength = 0; + Packet.OutTransferLength = 0; + Packet.Protocol = EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA; + } else if (IsTrustSend) { + // + // Check the alignment of the incoming buffer prior to invoking underlying + // ATA PassThru PPI. + // + if ((AtaPassThru->Mode->IoAlign > 1) && + !IS_ALIGNED (Buffer, AtaPassThru->Mode->IoAlign)) { + NewBuffer = AllocateAlignedPages ( + EFI_SIZE_TO_PAGES (TransferLength), + AtaPassThru->Mode->IoAlign + ); + if (NewBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CopyMem (NewBuffer, Buffer, TransferLength); + Buffer = NewBuffer; + } + Packet.OutDataBuffer = Buffer; + Packet.OutTransferLength = (UINT32) TransferLength; + Packet.Protocol = mAtaPassThruCmdProtocols[IsTrustSend]; + } else { + Packet.InDataBuffer = Buffer; + Packet.InTransferLength = (UINT32) TransferLength; + Packet.Protocol = mAtaPassThruCmdProtocols[IsTrustSend]; + } + Packet.Asb = NULL; + Packet.Acb = &Acb; + Packet.Timeout = Timeout; + Packet.Length = EFI_ATA_PASS_THRU_LENGTH_BYTES; + + Status = AtaPassThru->PassThru ( + AtaPassThru, + DeviceData->Port, + DeviceData->PortMultiplier, + &Packet + ); + if (TransferLengthOut != NULL) { + if (!IsTrustSend) { + *TransferLengthOut = Packet.InTransferLength; + } + } + return Status; +} diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/AhciPei.h b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/AhciPei.h new file mode 100644 index 0000000..3b13c9b --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/AhciPei.h @@ -0,0 +1,746 @@ +/** @file + The AhciPei driver is used to manage ATA hard disk device working under AHCI + mode at PEI phase. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _AHCI_PEI_H_ +#define _AHCI_PEI_H_ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +// +// Structure forward declarations +// +typedef struct _PEI_AHCI_CONTROLLER_PRIVATE_DATA PEI_AHCI_CONTROLLER_PRIVATE_DATA; + +#include "AhciPeiPassThru.h" +#include "AhciPeiBlockIo.h" +#include "AhciPeiStorageSecurity.h" + +// +// ATA AHCI driver implementation related definitions +// +// +// Refer SATA1.0a spec section 5.2, the Phy detection time should be less than 10ms. +// The value is in millisecond units. Add a bit of margin for robustness. +// +#define AHCI_BUS_PHY_DETECT_TIMEOUT 15 +// +// Refer SATA1.0a spec, the bus reset time should be less than 1s. +// The value is in 100ns units. +// +#define AHCI_PEI_RESET_TIMEOUT 10000000 +// +// Time out Value for ATA pass through protocol, in 100ns units. +// +#define ATA_TIMEOUT 30000000 +// +// Maximal number of Physical Region Descriptor Table entries supported. +// +#define AHCI_MAX_PRDT_NUMBER 8 + +#define AHCI_CAPABILITY_OFFSET 0x0000 +#define AHCI_CAP_SAM BIT18 +#define AHCI_CAP_SSS BIT27 + +#define AHCI_GHC_OFFSET 0x0004 +#define AHCI_GHC_RESET BIT0 +#define AHCI_GHC_ENABLE BIT31 + +#define AHCI_IS_OFFSET 0x0008 +#define AHCI_PI_OFFSET 0x000C + +#define AHCI_MAX_PORTS 32 + +typedef struct { + UINT32 Lower32; + UINT32 Upper32; +} DATA_32; + +typedef union { + DATA_32 Uint32; + UINT64 Uint64; +} DATA_64; + +#define AHCI_ATAPI_SIG_MASK 0xFFFF0000 +#define AHCI_ATA_DEVICE_SIG 0x00000000 + +// +// Each PRDT entry can point to a memory block up to 4M byte +// +#define AHCI_MAX_DATA_PER_PRDT 0x400000 + +#define AHCI_FIS_REGISTER_H2D 0x27 //Register FIS - Host to Device +#define AHCI_FIS_REGISTER_H2D_LENGTH 20 +#define AHCI_FIS_REGISTER_D2H 0x34 //Register FIS - Device to Host +#define AHCI_FIS_PIO_SETUP 0x5F //PIO Setup FIS - Device to Host + +#define AHCI_D2H_FIS_OFFSET 0x40 +#define AHCI_PIO_FIS_OFFSET 0x20 +#define AHCI_FIS_TYPE_MASK 0xFF + +// +// Port register +// +#define AHCI_PORT_START 0x0100 +#define AHCI_PORT_REG_WIDTH 0x0080 +#define AHCI_PORT_CLB 0x0000 +#define AHCI_PORT_CLBU 0x0004 +#define AHCI_PORT_FB 0x0008 +#define AHCI_PORT_FBU 0x000C +#define AHCI_PORT_IS 0x0010 +#define AHCI_PORT_IE 0x0014 +#define AHCI_PORT_CMD 0x0018 +#define AHCI_PORT_CMD_ST BIT0 +#define AHCI_PORT_CMD_SUD BIT1 +#define AHCI_PORT_CMD_POD BIT2 +#define AHCI_PORT_CMD_CLO BIT3 +#define AHCI_PORT_CMD_FRE BIT4 +#define AHCI_PORT_CMD_FR BIT14 +#define AHCI_PORT_CMD_CR BIT15 +#define AHCI_PORT_CMD_CPD BIT20 +#define AHCI_PORT_CMD_ATAPI BIT24 +#define AHCI_PORT_CMD_DLAE BIT25 +#define AHCI_PORT_CMD_ALPE BIT26 +#define AHCI_PORT_CMD_ACTIVE (1 << 28) +#define AHCI_PORT_CMD_ICC_MASK (BIT28 | BIT29 | BIT30 | BIT31) + +#define AHCI_PORT_TFD 0x0020 +#define AHCI_PORT_TFD_ERR BIT0 +#define AHCI_PORT_TFD_DRQ BIT3 +#define AHCI_PORT_TFD_BSY BIT7 +#define AHCI_PORT_TFD_MASK (BIT7 | BIT3 | BIT0) + +#define AHCI_PORT_SIG 0x0024 +#define AHCI_PORT_SSTS 0x0028 +#define AHCI_PORT_SSTS_DET_MASK 0x000F +#define AHCI_PORT_SSTS_DET 0x0001 +#define AHCI_PORT_SSTS_DET_PCE 0x0003 + +#define AHCI_PORT_SCTL 0x002C +#define AHCI_PORT_SCTL_IPM_INIT 0x0300 + +#define AHCI_PORT_SERR 0x0030 +#define AHCI_PORT_CI 0x0038 + +#define IS_ALIGNED(addr, size) (((UINTN) (addr) & (size - 1)) == 0) +#define TIMER_PERIOD_SECONDS(Seconds) MultU64x32((UINT64)(Seconds), 10000000) + +#pragma pack(1) + +// +// Received FIS structure +// +typedef struct { + UINT8 AhciDmaSetupFis[0x1C]; // Dma Setup Fis: offset 0x00 + UINT8 AhciDmaSetupFisRsvd[0x04]; + UINT8 AhciPioSetupFis[0x14]; // Pio Setup Fis: offset 0x20 + UINT8 AhciPioSetupFisRsvd[0x0C]; + UINT8 AhciD2HRegisterFis[0x14]; // D2H Register Fis: offset 0x40 + UINT8 AhciD2HRegisterFisRsvd[0x04]; + UINT64 AhciSetDeviceBitsFis; // Set Device Bits Fix: offset 0x58 + UINT8 AhciUnknownFis[0x40]; // Unkonwn Fis: offset 0x60 + UINT8 AhciUnknownFisRsvd[0x60]; +} EFI_AHCI_RECEIVED_FIS; + +// +// Command List structure includes total 32 entries. +// The entry Data structure is listed at the following. +// +typedef struct { + UINT32 AhciCmdCfl:5; //Command FIS Length + UINT32 AhciCmdA:1; //ATAPI + UINT32 AhciCmdW:1; //Write + UINT32 AhciCmdP:1; //Prefetchable + UINT32 AhciCmdR:1; //Reset + UINT32 AhciCmdB:1; //BIST + UINT32 AhciCmdC:1; //Clear Busy upon R_OK + UINT32 AhciCmdRsvd:1; + UINT32 AhciCmdPmp:4; //Port Multiplier Port + UINT32 AhciCmdPrdtl:16; //Physical Region Descriptor Table Length + UINT32 AhciCmdPrdbc; //Physical Region Descriptor Byte Count + UINT32 AhciCmdCtba; //Command Table Descriptor Base Address + UINT32 AhciCmdCtbau; //Command Table Descriptor Base Address Upper 32-BITs + UINT32 AhciCmdRsvd1[4]; +} EFI_AHCI_COMMAND_LIST; + +// +// This is a software constructed FIS. +// For Data transfer operations, this is the H2D Register FIS format as +// specified in the Serial ATA Revision 2.6 specification. +// +typedef struct { + UINT8 AhciCFisType; + UINT8 AhciCFisPmNum:4; + UINT8 AhciCFisRsvd:1; + UINT8 AhciCFisRsvd1:1; + UINT8 AhciCFisRsvd2:1; + UINT8 AhciCFisCmdInd:1; + UINT8 AhciCFisCmd; + UINT8 AhciCFisFeature; + UINT8 AhciCFisSecNum; + UINT8 AhciCFisClyLow; + UINT8 AhciCFisClyHigh; + UINT8 AhciCFisDevHead; + UINT8 AhciCFisSecNumExp; + UINT8 AhciCFisClyLowExp; + UINT8 AhciCFisClyHighExp; + UINT8 AhciCFisFeatureExp; + UINT8 AhciCFisSecCount; + UINT8 AhciCFisSecCountExp; + UINT8 AhciCFisRsvd3; + UINT8 AhciCFisControl; + UINT8 AhciCFisRsvd4[4]; + UINT8 AhciCFisRsvd5[44]; +} EFI_AHCI_COMMAND_FIS; + +// +// ACMD: ATAPI command (12 or 16 bytes) +// +typedef struct { + UINT8 AtapiCmd[0x10]; +} EFI_AHCI_ATAPI_COMMAND; + +// +// Physical Region Descriptor Table includes up to 65535 entries +// The entry data structure is listed at the following. +// the actual entry number comes from the PRDTL field in the command +// list entry for this command slot. +// +typedef struct { + UINT32 AhciPrdtDba; //Data Base Address + UINT32 AhciPrdtDbau; //Data Base Address Upper 32-BITs + UINT32 AhciPrdtRsvd; + UINT32 AhciPrdtDbc:22; //Data Byte Count + UINT32 AhciPrdtRsvd1:9; + UINT32 AhciPrdtIoc:1; //Interrupt on Completion +} EFI_AHCI_COMMAND_PRDT; + +// +// Command table Data strucute which is pointed to by the entry in the command list +// +typedef struct { + EFI_AHCI_COMMAND_FIS CommandFis; // A software constructed FIS. + EFI_AHCI_ATAPI_COMMAND AtapiCmd; // 12 or 16 bytes ATAPI cmd. + UINT8 Reserved[0x30]; + // + // The scatter/gather list for Data transfer. + // + EFI_AHCI_COMMAND_PRDT PrdtTable[AHCI_MAX_PRDT_NUMBER]; +} EFI_AHCI_COMMAND_TABLE; + +#pragma pack() + +typedef struct { + EFI_AHCI_RECEIVED_FIS *AhciRFis; + EFI_AHCI_COMMAND_LIST *AhciCmdList; + EFI_AHCI_COMMAND_TABLE *AhciCmdTable; + UINTN MaxRFisSize; + UINTN MaxCmdListSize; + UINTN MaxCmdTableSize; + VOID *AhciRFisMap; + VOID *AhciCmdListMap; + VOID *AhciCmdTableMap; +} EFI_AHCI_REGISTERS; + +// +// Unique signature for AHCI ATA device information structure. +// +#define AHCI_PEI_ATA_DEVICE_DATA_SIGNATURE SIGNATURE_32 ('A', 'P', 'A', 'D') + +// +// AHCI mode device information structure. +// +typedef struct { + UINT32 Signature; + LIST_ENTRY Link; + + UINT16 Port; + UINT16 PortMultiplier; + UINT8 FisIndex; + UINTN DeviceIndex; + ATA_IDENTIFY_DATA *IdentifyData; + + BOOLEAN Lba48Bit; + BOOLEAN TrustComputing; + UINTN TrustComputingDeviceIndex; + EFI_PEI_BLOCK_IO2_MEDIA Media; + + PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private; +} PEI_AHCI_ATA_DEVICE_DATA; + +#define AHCI_PEI_ATA_DEVICE_INFO_FROM_THIS(a) \ + CR (a, \ + PEI_AHCI_ATA_DEVICE_DATA, \ + Link, \ + AHCI_PEI_ATA_DEVICE_DATA_SIGNATURE \ + ); + +// +// Unique signature for private data structure. +// +#define AHCI_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('A','P','C','P') + +// +// ATA AHCI controller private data structure. +// +struct _PEI_AHCI_CONTROLLER_PRIVATE_DATA { + UINT32 Signature; + UINTN MmioBase; + UINTN DevicePathLength; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + EFI_ATA_PASS_THRU_MODE AtaPassThruMode; + EDKII_PEI_ATA_PASS_THRU_PPI AtaPassThruPpi; + EFI_PEI_RECOVERY_BLOCK_IO_PPI BlkIoPpi; + EFI_PEI_RECOVERY_BLOCK_IO2_PPI BlkIo2Ppi; + EDKII_PEI_STORAGE_SECURITY_CMD_PPI StorageSecurityPpi; + EFI_PEI_PPI_DESCRIPTOR AtaPassThruPpiList; + EFI_PEI_PPI_DESCRIPTOR BlkIoPpiList; + EFI_PEI_PPI_DESCRIPTOR BlkIo2PpiList; + EFI_PEI_PPI_DESCRIPTOR StorageSecurityPpiList; + EFI_PEI_NOTIFY_DESCRIPTOR EndOfPeiNotifyList; + + EFI_AHCI_REGISTERS AhciRegisters; + + UINT32 PortBitMap; + UINT32 ActiveDevices; + UINT32 TrustComputingDevices; + LIST_ENTRY DeviceList; + + UINT16 PreviousPort; + UINT16 PreviousPortMultiplier; +}; + +#define GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_PASS_THRU(a) \ + CR (a, PEI_AHCI_CONTROLLER_PRIVATE_DATA, AtaPassThruPpi, AHCI_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE) +#define GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO(a) \ + CR (a, PEI_AHCI_CONTROLLER_PRIVATE_DATA, BlkIoPpi, AHCI_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE) +#define GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO2(a) \ + CR (a, PEI_AHCI_CONTROLLER_PRIVATE_DATA, BlkIo2Ppi, AHCI_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE) +#define GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_STROAGE_SECURITY(a) \ + CR (a, PEI_AHCI_CONTROLLER_PRIVATE_DATA, StorageSecurityPpi, AHCI_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE) +#define GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_NOTIFY(a) \ + CR (a, PEI_AHCI_CONTROLLER_PRIVATE_DATA, EndOfPeiNotifyList, AHCI_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE) + +// +// Global variables +// +extern UINT32 mMaxTransferBlockNumber[2]; + +// +// Internal functions +// + +/** + Allocates pages that are suitable for an OperationBusMasterCommonBuffer or + OperationBusMasterCommonBuffer64 mapping. + + @param Pages The number of pages to allocate. + @param HostAddress A pointer to store the base system memory address of the + allocated range. + @param DeviceAddress The resulting map address for the bus master PCI controller to use to + access the hosts HostAddress. + @param Mapping A resulting value to pass to Unmap(). + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are + MEMORY_WRITE_COMBINE and MEMORY_CACHED. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. + +**/ +EFI_STATUS +IoMmuAllocateBuffer ( + IN UINTN Pages, + OUT VOID **HostAddress, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ); + +/** + Frees memory that was allocated with AllocateBuffer(). + + @param Pages The number of pages to free. + @param HostAddress The base system memory address of the allocated range. + @param Mapping The mapping value returned from Map(). + + @retval EFI_SUCCESS The requested memory pages were freed. + @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages + was not allocated with AllocateBuffer(). + +**/ +EFI_STATUS +IoMmuFreeBuffer ( + IN UINTN Pages, + IN VOID *HostAddress, + IN VOID *Mapping + ); + +/** + Provides the controller-specific addresses required to access system memory from a + DMA bus master. + + @param Operation Indicates if the bus master is going to read or write to system memory. + @param HostAddress The system memory address to map to the PCI controller. + @param NumberOfBytes On input the number of bytes to map. On output the number of bytes + that were mapped. + @param DeviceAddress The resulting map address for the bus master PCI controller to use to + access the hosts HostAddress. + @param Mapping A resulting value to pass to Unmap(). + + @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. + +**/ +EFI_STATUS +IoMmuMap ( + IN EDKII_IOMMU_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ); + +/** + Completes the Map() operation and releases any corresponding resources. + + @param Mapping The mapping value returned from Map(). + + @retval EFI_SUCCESS The range was unmapped. + @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map(). + @retval EFI_DEVICE_ERROR The data was not committed to the target system memory. +**/ +EFI_STATUS +IoMmuUnmap ( + IN VOID *Mapping + ); + +/** + One notified function to cleanup the allocated DMA buffers at EndOfPei. + + @param[in] PeiServices Pointer to PEI Services Table. + @param[in] NotifyDescriptor Pointer to the descriptor for the Notification + event that caused this function to execute. + @param[in] Ppi Pointer to the PPI data associated with this function. + + @retval EFI_SUCCESS The function completes successfully + +**/ +EFI_STATUS +EFIAPI +AhciPeimEndOfPei ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + +/** + Collect the number of bits set within a port bitmap. + + @param[in] PortBitMap A 32-bit wide bit map of ATA AHCI ports. + + @retval The number of bits set in the bitmap. + +**/ +UINT8 +AhciGetNumberOfPortsFromMap ( + IN UINT32 PortBitMap + ); + +/** + Start a PIO Data transfer on specific port. + + @param[in] Private The pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA. + @param[in] Port The number of port. + @param[in] PortMultiplier The number of port multiplier. + @param[in] FisIndex The offset index of the FIS base address. + @param[in] Read The transfer direction. + @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data. + @param[in,out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data. + @param[in,out] MemoryAddr The pointer to the data buffer. + @param[in] DataCount The data count to be transferred. + @param[in] Timeout The timeout value of PIO data transfer, uses + 100ns as a unit. + + @retval EFI_DEVICE_ERROR The PIO data transfer abort with error occurs. + @retval EFI_TIMEOUT The operation is time out. + @retval EFI_UNSUPPORTED The device is not ready for transfer. + @retval EFI_OUT_OF_RESOURCES The operation fails due to lack of resources. + @retval EFI_SUCCESS The PIO data transfer executes successfully. + +**/ +EFI_STATUS +AhciPioTransfer ( + IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private, + IN UINT8 Port, + IN UINT8 PortMultiplier, + IN UINT8 FisIndex, + IN BOOLEAN Read, + IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock, + IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock, + IN OUT VOID *MemoryAddr, + IN UINT32 DataCount, + IN UINT64 Timeout + ); + +/** + Start a non data transfer on specific port. + + @param[in] Private The pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA. + @param[in] Port The number of port. + @param[in] PortMultiplier The number of port multiplier. + @param[in] FisIndex The offset index of the FIS base address. + @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data. + @param[in,out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data. + @param[in] Timeout The timeout value of non data transfer, uses + 100ns as a unit. + + @retval EFI_DEVICE_ERROR The non data transfer abort with error occurs. + @retval EFI_TIMEOUT The operation is time out. + @retval EFI_UNSUPPORTED The device is not ready for transfer. + @retval EFI_SUCCESS The non data transfer executes successfully. + +**/ +EFI_STATUS +AhciNonDataTransfer ( + IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private, + IN UINT8 Port, + IN UINT8 PortMultiplier, + IN UINT8 FisIndex, + IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock, + IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock, + IN UINT64 Timeout + ); + +/** + Initialize ATA host controller at AHCI mode. + + The function is designed to initialize ATA host controller. + + @param[in,out] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA instance. + + @retval EFI_SUCCESS The ATA AHCI controller is initialized successfully. + @retval EFI_OUT_OF_RESOURCES Not enough resource to complete while initializing + the controller. + @retval Others A device error occurred while initializing the + controller. + +**/ +EFI_STATUS +AhciModeInitialization ( + IN OUT PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private + ); + +/** + Transfer data from ATA device. + + This function performs one ATA pass through transaction to transfer data from/to + ATA device. It chooses the appropriate ATA command and protocol to invoke PassThru + interface of ATA pass through. + + @param[in] DeviceData A pointer to PEI_AHCI_ATA_DEVICE_DATA structure. + @param[in,out] Buffer The pointer to the current transaction buffer. + @param[in] StartLba The starting logical block address to be accessed. + @param[in] TransferLength The block number or sector count of the transfer. + @param[in] IsWrite Indicates whether it is a write operation. + + @retval EFI_SUCCESS The data transfer is complete successfully. + @return others Some error occurs when transferring data. + +**/ +EFI_STATUS +TransferAtaDevice ( + IN PEI_AHCI_ATA_DEVICE_DATA *DeviceData, + IN OUT VOID *Buffer, + IN EFI_LBA StartLba, + IN UINT32 TransferLength, + IN BOOLEAN IsWrite + ); + +/** + Trust transfer data from/to ATA device. + + This function performs one ATA pass through transaction to do a trust transfer + from/to ATA device. It chooses the appropriate ATA command and protocol to invoke + PassThru interface of ATA pass through. + + @param[in] DeviceData Pointer to PEI_AHCI_ATA_DEVICE_DATA structure. + @param[in,out] Buffer The pointer to the current transaction buffer. + @param[in] SecurityProtocolId + The value of the "Security Protocol" parameter + of the security protocol command to be sent. + @param[in] SecurityProtocolSpecificData + The value of the "Security Protocol Specific" + parameter of the security protocol command to + be sent. + @param[in] TransferLength The block number or sector count of the transfer. + @param[in] IsTrustSend Indicates whether it is a trust send operation + or not. + @param[in] Timeout The timeout, in 100ns units, to use for the execution + of the security protocol command. A Timeout value + of 0 means that this function will wait indefinitely + for the security protocol command to execute. If + Timeout is greater than zero, then this function + will return EFI_TIMEOUT if the time required to + execute the receive data command is greater than + Timeout. + @param[out] TransferLengthOut + A pointer to a buffer to store the size in bytes + of the data written to the buffer. Ignore it when + IsTrustSend is TRUE. + + @retval EFI_SUCCESS The data transfer is complete successfully. + @return others Some error occurs when transferring data. + +**/ +EFI_STATUS +TrustTransferAtaDevice ( + IN PEI_AHCI_ATA_DEVICE_DATA *DeviceData, + IN OUT VOID *Buffer, + IN UINT8 SecurityProtocolId, + IN UINT16 SecurityProtocolSpecificData, + IN UINTN TransferLength, + IN BOOLEAN IsTrustSend, + IN UINT64 Timeout, + OUT UINTN *TransferLengthOut + ); + +/** + Returns a pointer to the next node in a device path. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @return a pointer to the device path node that follows the device path node + specified by Node. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +NextDevicePathNode ( + IN CONST VOID *Node + ); + +/** + Get the size of the current device path instance. + + @param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL + structure. + @param[out] InstanceSize The size of the current device path instance. + @param[out] EntireDevicePathEnd Indicate whether the instance is the last + one in the device path strucure. + + @retval EFI_SUCCESS The size of the current device path instance is fetched. + @retval Others Fails to get the size of the current device path instance. + +**/ +EFI_STATUS +GetDevicePathInstanceSize ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT UINTN *InstanceSize, + OUT BOOLEAN *EntireDevicePathEnd + ); + +/** + Check the validity of the device path of a ATA AHCI host controller. + + @param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL + structure. + @param[in] DevicePathLength The length of the device path. + + @retval EFI_SUCCESS The device path is valid. + @retval EFI_INVALID_PARAMETER The device path is invalid. + +**/ +EFI_STATUS +AhciIsHcDevicePathValid ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN UINTN DevicePathLength + ); + +/** + Build the device path for an ATA device with given port and port multiplier number. + + @param[in] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA + data structure. + @param[in] Port The given port number. + @param[in] PortMultiplierPort The given port multiplier number. + @param[out] DevicePathLength The length of the device path in bytes specified + by DevicePath. + @param[out] DevicePath The device path of ATA device. + + @retval EFI_SUCCESS The operation succeeds. + @retval EFI_INVALID_PARAMETER The parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The operation fails due to lack of resources. + +**/ +EFI_STATUS +AhciBuildDevicePath ( + IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private, + IN UINT16 Port, + IN UINT16 PortMultiplierPort, + OUT UINTN *DevicePathLength, + OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ); + +/** + Collect the ports that need to be enumerated on a controller for S3 phase. + + @param[in] HcDevicePath Device path of the controller. + @param[in] HcDevicePathLength Length of the device path specified by + HcDevicePath. + @param[out] PortBitMap Bitmap that indicates the ports that need + to be enumerated on the controller. + + @retval The number of ports that need to be enumerated. + +**/ +UINT8 +AhciS3GetEumeratePorts ( + IN EFI_DEVICE_PATH_PROTOCOL *HcDevicePath, + IN UINTN HcDevicePathLength, + OUT UINT32 *PortBitMap + ); + +EFI_STATUS +CreateNewDevice ( + IN OUT PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private, + IN UINTN DeviceIndex, + IN UINT16 Port, + IN UINT16 PortMultiplier, + IN UINT8 FisIndex, + IN ATA_IDENTIFY_DATA *IdentifyData + ); + +EFI_STATUS +AhciCreateTransferDescriptor ( + IN OUT PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private + ); + +#endif diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/AhciPei.inf b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/AhciPei.inf new file mode 100644 index 0000000..83b2c17 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/AhciPei.inf @@ -0,0 +1,67 @@ +## @file +# The AhciPei driver is used to manage ATA hard disk device working under AHCI +# mode at PEI phase. +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = AhciPei + MODULE_UNI_FILE = AhciPei.uni + FILE_GUID = 79E5CA15-7A2D-4F37-A63B-D1C7BBCA47AD + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + ENTRY_POINT = AtaAhciPeimEntry + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + AhciPei.h + AhciPeiPassThru.c + AhciPeiPassThru.h + AhciPeiStorageSecurity.c + AhciPeiStorageSecurity.h + AhciMode.c + DevicePath.c + DmaMem.c + AhciPeiBlockIo.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + DebugLib + PeiServicesLib + MemoryAllocationLib + BaseMemoryLib + IoLib + TimerLib + LockBoxLib + PeimEntryPoint + +[Ppis] + gEdkiiPeiAtaAhciHostControllerPpiGuid ## CONSUMES + gEdkiiIoMmuPpiGuid ## CONSUMES + gEfiEndOfPeiSignalPpiGuid ## CONSUMES + gEdkiiPeiAtaPassThruPpiGuid ## SOMETIMES_PRODUCES + gEdkiiPeiStorageSecurityCommandPpiGuid ## SOMETIMES_PRODUCES + +[Guids] + gS3StorageDeviceInitListGuid ## SOMETIMES_CONSUMES ## UNDEFINED + +[Depex] + gEfiPeiMemoryDiscoveredPpiGuid AND + gEfiPeiMasterBootModePpiGuid AND + gEdkiiPeiAtaAhciHostControllerPpiGuid + +[UserExtensions.TianoCore."ExtraFiles"] + AhciPeiExtra.uni diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/AhciPeiBlockIo.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/AhciPeiBlockIo.c new file mode 100644 index 0000000..65ccf09 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/AhciPeiBlockIo.c @@ -0,0 +1,526 @@ +/** @file + The AhciPei driver is used to manage ATA hard disk device working under AHCI + mode at PEI phase. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "AhciPei.h" + +/** + Traverse the attached ATA devices list to find out the device with given index. + + @param[in] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA + instance. + @param[in] DeviceIndex The device index. + + @retval The pointer to the PEI_AHCI_ATA_DEVICE_DATA structure of the device + info to access. + +**/ +PEI_AHCI_ATA_DEVICE_DATA * +SearchDeviceByIndex ( + IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private, + IN UINTN DeviceIndex + ) +{ + PEI_AHCI_ATA_DEVICE_DATA *DeviceData; + LIST_ENTRY *Node; + + Node = GetFirstNode (&Private->DeviceList); + while (!IsNull (&Private->DeviceList, Node)) { + DeviceData = AHCI_PEI_ATA_DEVICE_INFO_FROM_THIS (Node); + + if (DeviceData->DeviceIndex == DeviceIndex) { + return DeviceData; + } + + Node = GetNextNode (&Private->DeviceList, Node); + } + + return NULL; +} + +/** + Read a number of blocks from ATA device. + + This function performs ATA pass through transactions to read data from ATA device. + It may separate the read request into several ATA pass through transactions. + + @param[in] DeviceData The pointer to the PEI_AHCI_ATA_DEVICE_DATA + data structure. + @param[in,out] Buffer The pointer to the current transaction buffer. + @param[in] StartLba The starting logical block address to be accessed. + @param[in] NumberOfBlocks The block number or sector count of the transfer. + + @retval EFI_SUCCESS The data transfer is complete successfully. + @return Others Some error occurs when transferring data. + +**/ +EFI_STATUS +AccessAtaDevice ( + IN PEI_AHCI_ATA_DEVICE_DATA *DeviceData, + IN OUT UINT8 *Buffer, + IN EFI_LBA StartLba, + IN UINTN NumberOfBlocks + ) +{ + EFI_STATUS Status; + UINTN MaxTransferBlockNumber; + UINTN TransferBlockNumber; + UINTN BlockSize; + + // + // Ensure Lba48Bit is a valid boolean value + // + ASSERT ((UINTN) DeviceData->Lba48Bit < 2); + if ((UINTN) DeviceData->Lba48Bit >= 2) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_SUCCESS; + MaxTransferBlockNumber = mMaxTransferBlockNumber[DeviceData->Lba48Bit]; + BlockSize = DeviceData->Media.BlockSize; + + do { + if (NumberOfBlocks > MaxTransferBlockNumber) { + TransferBlockNumber = MaxTransferBlockNumber; + NumberOfBlocks -= MaxTransferBlockNumber; + } else { + TransferBlockNumber = NumberOfBlocks; + NumberOfBlocks = 0; + } + DEBUG (( + DEBUG_BLKIO, "%a: Blocking AccessAtaDevice, TransferBlockNumber = %x; StartLba = %x\n", + __FUNCTION__, TransferBlockNumber, StartLba + )); + + Status = TransferAtaDevice ( + DeviceData, + Buffer, + StartLba, + (UINT32) TransferBlockNumber, + FALSE // Read + ); + if (EFI_ERROR (Status)) { + return Status; + } + + StartLba += TransferBlockNumber; + Buffer += TransferBlockNumber * BlockSize; + } while (NumberOfBlocks > 0); + + return Status; +} + +/** + Read specified bytes from Lba from the device. + + @param[in] DeviceData The pointer to the PEI_AHCI_ATA_DEVICE_DATA data structure. + @param[out] Buffer The Buffer used to store the Data read from the device. + @param[in] StartLba The start block number. + @param[in] BufferSize Total bytes to be read. + + @retval EFI_SUCCESS Data are read from the device. + @retval Others Fail to read all the data. + +**/ +EFI_STATUS +AhciRead ( + IN PEI_AHCI_ATA_DEVICE_DATA *DeviceData, + OUT VOID *Buffer, + IN EFI_LBA StartLba, + IN UINTN BufferSize + ) +{ + EFI_STATUS Status; + UINTN BlockSize; + UINTN NumberOfBlocks; + + // + // Check parameters. + // + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize == 0) { + return EFI_SUCCESS; + } + + BlockSize = DeviceData->Media.BlockSize; + if ((BufferSize % BlockSize) != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + if (StartLba > DeviceData->Media.LastBlock) { + return EFI_INVALID_PARAMETER; + } + NumberOfBlocks = BufferSize / BlockSize; + if (NumberOfBlocks - 1 > DeviceData->Media.LastBlock - StartLba) { + return EFI_INVALID_PARAMETER; + } + + // + // Invoke low level AtaDevice Access Routine. + // + Status = AccessAtaDevice (DeviceData, Buffer, StartLba, NumberOfBlocks); + + return Status; +} + + +/** + Gets the count of block I/O devices that one specific block driver detects. + + This function is used for getting the count of block I/O devices that one + specific block driver detects. If no device is detected, then the function + will return zero. + + @param[in] PeiServices General-purpose services that are available + to every PEIM. + @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI + instance. + @param[out] NumberBlockDevices The number of block I/O devices discovered. + + @retval EFI_SUCCESS The operation performed successfully. + +**/ +EFI_STATUS +EFIAPI +AhciBlockIoGetDeviceNo ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This, + OUT UINTN *NumberBlockDevices + ) +{ + PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private; + + if (This == NULL || NumberBlockDevices == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private = GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO (This); + *NumberBlockDevices = Private->ActiveDevices; + + return EFI_SUCCESS; +} + +/** + Gets a block device's media information. + + This function will provide the caller with the specified block device's media + information. If the media changes, calling this function will update the media + information accordingly. + + @param[in] PeiServices General-purpose services that are available to every + PEIM + @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance. + @param[in] DeviceIndex Specifies the block device to which the function wants + to talk. Because the driver that implements Block I/O + PPIs will manage multiple block devices, the PPIs that + want to talk to a single device must specify the + device index that was assigned during the enumeration + process. This index is a number from one to + NumberBlockDevices. + @param[out] MediaInfo The media information of the specified block media. + The caller is responsible for the ownership of this + data structure. + + @par Note: + The MediaInfo structure describes an enumeration of possible block device + types. This enumeration exists because no device paths are actually passed + across interfaces that describe the type or class of hardware that is publishing + the block I/O interface. This enumeration will allow for policy decisions + in the Recovery PEIM, such as "Try to recover from legacy floppy first, + LS-120 second, CD-ROM third." If there are multiple partitions abstracted + by a given device type, they should be reported in ascending order; this + order also applies to nested partitions, such as legacy MBR, where the + outermost partitions would have precedence in the reporting order. The + same logic applies to systems such as IDE that have precedence relationships + like "Master/Slave" or "Primary/Secondary". The master device should be + reported first, the slave second. + + @retval EFI_SUCCESS Media information about the specified block device + was obtained successfully. + @retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware + error. + +**/ +EFI_STATUS +EFIAPI +AhciBlockIoGetMediaInfo ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This, + IN UINTN DeviceIndex, + OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo + ) +{ + PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private; + PEI_AHCI_ATA_DEVICE_DATA *DeviceData; + + if (This == NULL || MediaInfo == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private = GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO (This); + if ((DeviceIndex == 0) || (DeviceIndex > Private->ActiveDevices)) { + return EFI_INVALID_PARAMETER; + } + + DeviceData = SearchDeviceByIndex (Private, DeviceIndex); + if (DeviceData == NULL) { + return EFI_NOT_FOUND; + } + + MediaInfo->DeviceType = (EFI_PEI_BLOCK_DEVICE_TYPE) EDKII_PEI_BLOCK_DEVICE_TYPE_ATA_HARD_DISK; + MediaInfo->MediaPresent = TRUE; + MediaInfo->LastBlock = (UINTN) DeviceData->Media.LastBlock; + MediaInfo->BlockSize = DeviceData->Media.BlockSize; + + return EFI_SUCCESS; +} + +/** + Reads the requested number of blocks from the specified block device. + + The function reads the requested number of blocks from the device. All the + blocks are read, or an error is returned. If there is no media in the device, + the function returns EFI_NO_MEDIA. + + @param[in] PeiServices General-purpose services that are available to + every PEIM. + @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance. + @param[in] DeviceIndex Specifies the block device to which the function wants + to talk. Because the driver that implements Block I/O + PPIs will manage multiple block devices, PPIs that + want to talk to a single device must specify the device + index that was assigned during the enumeration process. + This index is a number from one to NumberBlockDevices. + @param[in] StartLBA The starting logical block address (LBA) to read from + on the device + @param[in] BufferSize The size of the Buffer in bytes. This number must be + a multiple of the intrinsic block size of the device. + @param[out] Buffer A pointer to the destination buffer for the data. + The caller is responsible for the ownership of the + buffer. + + @retval EFI_SUCCESS The data was read correctly from the device. + @retval EFI_DEVICE_ERROR The device reported an error while attempting + to perform the read operation. + @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not + valid, or the buffer is not properly aligned. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of + the intrinsic block size of the device. + +**/ +EFI_STATUS +EFIAPI +AhciBlockIoReadBlocks ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This, + IN UINTN DeviceIndex, + IN EFI_PEI_LBA StartLBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private; + PEI_AHCI_ATA_DEVICE_DATA *DeviceData; + + Private = GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO (This); + + // + // Check parameters + // + if ((This == NULL) || + (DeviceIndex == 0) || + (DeviceIndex > Private->ActiveDevices)) { + return EFI_INVALID_PARAMETER; + } + + DeviceData = SearchDeviceByIndex (Private, DeviceIndex); + if (DeviceData == NULL) { + return EFI_NOT_FOUND; + } + + return AhciRead (DeviceData, Buffer, StartLBA, BufferSize); +} + +/** + Gets the count of block I/O devices that one specific block driver detects. + + This function is used for getting the count of block I/O devices that one + specific block driver detects. If no device is detected, then the function + will return zero. + + @param[in] PeiServices General-purpose services that are available + to every PEIM. + @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI + instance. + @param[out] NumberBlockDevices The number of block I/O devices discovered. + + @retval EFI_SUCCESS The operation performed successfully. + +**/ +EFI_STATUS +EFIAPI +AhciBlockIoGetDeviceNo2 ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This, + OUT UINTN *NumberBlockDevices + ) +{ + PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private; + + if (This == NULL || NumberBlockDevices == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private = GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO2 (This); + *NumberBlockDevices = Private->ActiveDevices; + + return EFI_SUCCESS; +} + +/** + Gets a block device's media information. + + This function will provide the caller with the specified block device's media + information. If the media changes, calling this function will update the media + information accordingly. + + @param[in] PeiServices General-purpose services that are available to every + PEIM + @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance. + @param[in] DeviceIndex Specifies the block device to which the function wants + to talk. Because the driver that implements Block I/O + PPIs will manage multiple block devices, the PPIs that + want to talk to a single device must specify the + device index that was assigned during the enumeration + process. This index is a number from one to + NumberBlockDevices. + @param[out] MediaInfo The media information of the specified block media. + The caller is responsible for the ownership of this + data structure. + + @par Note: + The MediaInfo structure describes an enumeration of possible block device + types. This enumeration exists because no device paths are actually passed + across interfaces that describe the type or class of hardware that is publishing + the block I/O interface. This enumeration will allow for policy decisions + in the Recovery PEIM, such as "Try to recover from legacy floppy first, + LS-120 second, CD-ROM third." If there are multiple partitions abstracted + by a given device type, they should be reported in ascending order; this + order also applies to nested partitions, such as legacy MBR, where the + outermost partitions would have precedence in the reporting order. The + same logic applies to systems such as IDE that have precedence relationships + like "Master/Slave" or "Primary/Secondary". The master device should be + reported first, the slave second. + + @retval EFI_SUCCESS Media information about the specified block device + was obtained successfully. + @retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware + error. + +**/ +EFI_STATUS +EFIAPI +AhciBlockIoGetMediaInfo2 ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This, + IN UINTN DeviceIndex, + OUT EFI_PEI_BLOCK_IO2_MEDIA *MediaInfo + ) +{ + PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private; + PEI_AHCI_ATA_DEVICE_DATA *DeviceData; + + if (This == NULL || MediaInfo == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private = GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO2 (This); + if ((DeviceIndex == 0) || (DeviceIndex > Private->ActiveDevices)) { + return EFI_INVALID_PARAMETER; + } + + DeviceData = SearchDeviceByIndex (Private, DeviceIndex); + if (DeviceData == NULL) { + return EFI_NOT_FOUND; + } + + CopyMem ( + MediaInfo, + &DeviceData->Media, + sizeof (EFI_PEI_BLOCK_IO2_MEDIA) + ); + + return EFI_SUCCESS; +} + +/** + Reads the requested number of blocks from the specified block device. + + The function reads the requested number of blocks from the device. All the + blocks are read, or an error is returned. If there is no media in the device, + the function returns EFI_NO_MEDIA. + + @param[in] PeiServices General-purpose services that are available to + every PEIM. + @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance. + @param[in] DeviceIndex Specifies the block device to which the function wants + to talk. Because the driver that implements Block I/O + PPIs will manage multiple block devices, PPIs that + want to talk to a single device must specify the device + index that was assigned during the enumeration process. + This index is a number from one to NumberBlockDevices. + @param[in] StartLBA The starting logical block address (LBA) to read from + on the device + @param[in] BufferSize The size of the Buffer in bytes. This number must be + a multiple of the intrinsic block size of the device. + @param[out] Buffer A pointer to the destination buffer for the data. + The caller is responsible for the ownership of the + buffer. + + @retval EFI_SUCCESS The data was read correctly from the device. + @retval EFI_DEVICE_ERROR The device reported an error while attempting + to perform the read operation. + @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not + valid, or the buffer is not properly aligned. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of + the intrinsic block size of the device. + +**/ +EFI_STATUS +EFIAPI +AhciBlockIoReadBlocks2 ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This, + IN UINTN DeviceIndex, + IN EFI_PEI_LBA StartLBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private = GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_BLKIO2 (This); + return AhciBlockIoReadBlocks ( + PeiServices, + &Private->BlkIoPpi, + DeviceIndex, + StartLBA, + BufferSize, + Buffer + ); +} diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/AhciPeiBlockIo.h b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/AhciPeiBlockIo.h new file mode 100644 index 0000000..5896ae5 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/AhciPeiBlockIo.h @@ -0,0 +1,257 @@ +/** @file + The AhciPei driver is used to manage ATA hard disk device working under AHCI + mode at PEI phase. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _AHCI_PEI_BLOCKIO_H_ +#define _AHCI_PEI_BLOCKIO_H_ + +// +// ATA hard disk device for EFI_PEI_BLOCK_DEVICE_TYPE +// +#define EDKII_PEI_BLOCK_DEVICE_TYPE_ATA_HARD_DISK 8 + +/** + Gets the count of block I/O devices that one specific block driver detects. + + This function is used for getting the count of block I/O devices that one + specific block driver detects. If no device is detected, then the function + will return zero. + + @param[in] PeiServices General-purpose services that are available + to every PEIM. + @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI + instance. + @param[out] NumberBlockDevices The number of block I/O devices discovered. + + @retval EFI_SUCCESS The operation performed successfully. + +**/ +EFI_STATUS +EFIAPI +AhciBlockIoGetDeviceNo ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This, + OUT UINTN *NumberBlockDevices + ); + +/** + Gets a block device's media information. + + This function will provide the caller with the specified block device's media + information. If the media changes, calling this function will update the media + information accordingly. + + @param[in] PeiServices General-purpose services that are available to every + PEIM + @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance. + @param[in] DeviceIndex Specifies the block device to which the function wants + to talk. Because the driver that implements Block I/O + PPIs will manage multiple block devices, the PPIs that + want to talk to a single device must specify the + device index that was assigned during the enumeration + process. This index is a number from one to + NumberBlockDevices. + @param[out] MediaInfo The media information of the specified block media. + The caller is responsible for the ownership of this + data structure. + + @par Note: + The MediaInfo structure describes an enumeration of possible block device + types. This enumeration exists because no device paths are actually passed + across interfaces that describe the type or class of hardware that is publishing + the block I/O interface. This enumeration will allow for policy decisions + in the Recovery PEIM, such as "Try to recover from legacy floppy first, + LS-120 second, CD-ROM third." If there are multiple partitions abstracted + by a given device type, they should be reported in ascending order; this + order also applies to nested partitions, such as legacy MBR, where the + outermost partitions would have precedence in the reporting order. The + same logic applies to systems such as IDE that have precedence relationships + like "Master/Slave" or "Primary/Secondary". The master device should be + reported first, the slave second. + + @retval EFI_SUCCESS Media information about the specified block device + was obtained successfully. + @retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware + error. + +**/ +EFI_STATUS +EFIAPI +AhciBlockIoGetMediaInfo ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This, + IN UINTN DeviceIndex, + OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo + ); + +/** + Reads the requested number of blocks from the specified block device. + + The function reads the requested number of blocks from the device. All the + blocks are read, or an error is returned. If there is no media in the device, + the function returns EFI_NO_MEDIA. + + @param[in] PeiServices General-purpose services that are available to + every PEIM. + @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance. + @param[in] DeviceIndex Specifies the block device to which the function wants + to talk. Because the driver that implements Block I/O + PPIs will manage multiple block devices, PPIs that + want to talk to a single device must specify the device + index that was assigned during the enumeration process. + This index is a number from one to NumberBlockDevices. + @param[in] StartLBA The starting logical block address (LBA) to read from + on the device + @param[in] BufferSize The size of the Buffer in bytes. This number must be + a multiple of the intrinsic block size of the device. + @param[out] Buffer A pointer to the destination buffer for the data. + The caller is responsible for the ownership of the + buffer. + + @retval EFI_SUCCESS The data was read correctly from the device. + @retval EFI_DEVICE_ERROR The device reported an error while attempting + to perform the read operation. + @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not + valid, or the buffer is not properly aligned. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of + the intrinsic block size of the device. + +**/ +EFI_STATUS +EFIAPI +AhciBlockIoReadBlocks ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This, + IN UINTN DeviceIndex, + IN EFI_PEI_LBA StartLBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +/** + Gets the count of block I/O devices that one specific block driver detects. + + This function is used for getting the count of block I/O devices that one + specific block driver detects. If no device is detected, then the function + will return zero. + + @param[in] PeiServices General-purpose services that are available + to every PEIM. + @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI + instance. + @param[out] NumberBlockDevices The number of block I/O devices discovered. + + @retval EFI_SUCCESS The operation performed successfully. + +**/ +EFI_STATUS +EFIAPI +AhciBlockIoGetDeviceNo2 ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This, + OUT UINTN *NumberBlockDevices + ); + +/** + Gets a block device's media information. + + This function will provide the caller with the specified block device's media + information. If the media changes, calling this function will update the media + information accordingly. + + @param[in] PeiServices General-purpose services that are available to every + PEIM + @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance. + @param[in] DeviceIndex Specifies the block device to which the function wants + to talk. Because the driver that implements Block I/O + PPIs will manage multiple block devices, the PPIs that + want to talk to a single device must specify the + device index that was assigned during the enumeration + process. This index is a number from one to + NumberBlockDevices. + @param[out] MediaInfo The media information of the specified block media. + The caller is responsible for the ownership of this + data structure. + + @par Note: + The MediaInfo structure describes an enumeration of possible block device + types. This enumeration exists because no device paths are actually passed + across interfaces that describe the type or class of hardware that is publishing + the block I/O interface. This enumeration will allow for policy decisions + in the Recovery PEIM, such as "Try to recover from legacy floppy first, + LS-120 second, CD-ROM third." If there are multiple partitions abstracted + by a given device type, they should be reported in ascending order; this + order also applies to nested partitions, such as legacy MBR, where the + outermost partitions would have precedence in the reporting order. The + same logic applies to systems such as IDE that have precedence relationships + like "Master/Slave" or "Primary/Secondary". The master device should be + reported first, the slave second. + + @retval EFI_SUCCESS Media information about the specified block device + was obtained successfully. + @retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware + error. + +**/ +EFI_STATUS +EFIAPI +AhciBlockIoGetMediaInfo2 ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This, + IN UINTN DeviceIndex, + OUT EFI_PEI_BLOCK_IO2_MEDIA *MediaInfo + ); + +/** + Reads the requested number of blocks from the specified block device. + + The function reads the requested number of blocks from the device. All the + blocks are read, or an error is returned. If there is no media in the device, + the function returns EFI_NO_MEDIA. + + @param[in] PeiServices General-purpose services that are available to + every PEIM. + @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance. + @param[in] DeviceIndex Specifies the block device to which the function wants + to talk. Because the driver that implements Block I/O + PPIs will manage multiple block devices, PPIs that + want to talk to a single device must specify the device + index that was assigned during the enumeration process. + This index is a number from one to NumberBlockDevices. + @param[in] StartLBA The starting logical block address (LBA) to read from + on the device + @param[in] BufferSize The size of the Buffer in bytes. This number must be + a multiple of the intrinsic block size of the device. + @param[out] Buffer A pointer to the destination buffer for the data. + The caller is responsible for the ownership of the + buffer. + + @retval EFI_SUCCESS The data was read correctly from the device. + @retval EFI_DEVICE_ERROR The device reported an error while attempting + to perform the read operation. + @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not + valid, or the buffer is not properly aligned. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of + the intrinsic block size of the device. + +**/ +EFI_STATUS +EFIAPI +AhciBlockIoReadBlocks2 ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This, + IN UINTN DeviceIndex, + IN EFI_PEI_LBA StartLBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +#endif diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/AhciPeiPassThru.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/AhciPeiPassThru.c new file mode 100644 index 0000000..191b78c --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/AhciPeiPassThru.c @@ -0,0 +1,514 @@ +/** @file + The AhciPei driver is used to manage ATA hard disk device working under AHCI + mode at PEI phase. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "AhciPei.h" + +/** + Traverse the attached ATA devices list to find out the device with given Port + and PortMultiplierPort. + + @param[in] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA + instance. + @param[in] Port The port number of the ATA device. + @param[in] PortMultiplierPort The port multiplier port number of the ATA device. + + @retval The pointer to the PEI_AHCI_ATA_DEVICE_DATA structure of the device + info to access. + +**/ +PEI_AHCI_ATA_DEVICE_DATA * +SearchDeviceByPort ( + IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private, + IN UINT16 Port, + IN UINT16 PortMultiplierPort + ) +{ + PEI_AHCI_ATA_DEVICE_DATA *DeviceData; + LIST_ENTRY *Node; + + Node = GetFirstNode (&Private->DeviceList); + while (!IsNull (&Private->DeviceList, Node)) { + DeviceData = AHCI_PEI_ATA_DEVICE_INFO_FROM_THIS (Node); + + if ((DeviceData->Port == Port) && + (DeviceData->PortMultiplier == PortMultiplierPort)) { + return DeviceData; + } + + Node = GetNextNode (&Private->DeviceList, Node); + } + + return NULL; +} + +/** + Sends an ATA command to an ATA device that is attached to the ATA controller. + + @param[in] Private Pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA. + @param[in] Port The port number of the ATA device. + @param[in] PortMultiplierPort The port multiplier port number of the ATA + device. + @param[in] FisIndex The index of the FIS. + @param[in,out] Packet A pointer to the ATA command to send to + the ATA device specified by Port and + PortMultiplierPort. + + @retval EFI_SUCCESS The ATA command was sent by the host. For + bi-directional commands, InTransferLength bytes + were transferred from InDataBuffer. For write + and bi-directional commands, OutTransferLength + bytes were transferred by OutDataBuffer. + @retval EFI_BAD_BUFFER_SIZE The ATA command was not executed. The number + of bytes that could be transferred is returned + in InTransferLength. For write and bi-directional + commands, OutTransferLength bytes were transferred + by OutDataBuffer. + @retval EFI_NOT_READY The ATA command could not be sent because there + are too many ATA commands already queued. The + caller may retry again later. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to + send the ATA command. + @retval EFI_INVALID_PARAMETER Port, PortMultiplierPort, or the contents of + Acb are invalid. The ATA command was not sent, + so no additional status information is available. + +**/ +EFI_STATUS +AhciPassThruExecute ( + IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private, + IN UINT16 Port, + IN UINT16 PortMultiplierPort, + IN UINT8 FisIndex, + IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet + ) +{ + EFI_STATUS Status; + + switch (Packet->Protocol) { + case EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA: + Status = AhciNonDataTransfer ( + Private, + (UINT8) Port, + (UINT8) PortMultiplierPort, + FisIndex, + Packet->Acb, + Packet->Asb, + Packet->Timeout + ); + break; + case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN: + Status = AhciPioTransfer ( + Private, + (UINT8) Port, + (UINT8) PortMultiplierPort, + FisIndex, + TRUE, + Packet->Acb, + Packet->Asb, + Packet->InDataBuffer, + Packet->InTransferLength, + Packet->Timeout + ); + break; + case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT: + Status = AhciPioTransfer ( + Private, + (UINT8) Port, + (UINT8) PortMultiplierPort, + FisIndex, + FALSE, + Packet->Acb, + Packet->Asb, + Packet->OutDataBuffer, + Packet->OutTransferLength, + Packet->Timeout + ); + break; + default: + return EFI_UNSUPPORTED; + } + + return Status; +} + +/** + Sends an ATA command to an ATA device that is attached to the ATA controller. + + @param[in] This The PPI instance pointer. + @param[in] Port The port number of the ATA device to send + the command. + @param[in] PortMultiplierPort The port multiplier port number of the ATA + device to send the command. + If there is no port multiplier, then specify + 0xFFFF. + @param[in,out] Packet A pointer to the ATA command to send to + the ATA device specified by Port and + PortMultiplierPort. + + @retval EFI_SUCCESS The ATA command was sent by the host. For + bi-directional commands, InTransferLength bytes + were transferred from InDataBuffer. For write + and bi-directional commands, OutTransferLength + bytes were transferred by OutDataBuffer. + @retval EFI_NOT_FOUND The specified ATA device is not found. + @retval EFI_INVALID_PARAMETER The contents of Acb are invalid. The ATA command + was not sent, so no additional status information + is available. + @retval EFI_BAD_BUFFER_SIZE The ATA command was not executed. The number + of bytes that could be transferred is returned + in InTransferLength. For write and bi-directional + commands, OutTransferLength bytes were transferred + by OutDataBuffer. + @retval EFI_NOT_READY The ATA command could not be sent because there + are too many ATA commands already queued. The + caller may retry again later. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to + send the ATA command. + +**/ +EFI_STATUS +EFIAPI +AhciAtaPassThruPassThru ( + IN EDKII_PEI_ATA_PASS_THRU_PPI *This, + IN UINT16 Port, + IN UINT16 PortMultiplierPort, + IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet + ) +{ + UINT32 IoAlign; + PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private; + PEI_AHCI_ATA_DEVICE_DATA *DeviceData; + UINT32 MaxSectorCount; + UINT32 BlockSize; + + if (This == NULL || Packet == NULL) { + return EFI_INVALID_PARAMETER; + } + + IoAlign = This->Mode->IoAlign; + if ((IoAlign > 1) && !IS_ALIGNED (Packet->InDataBuffer, IoAlign)) { + return EFI_INVALID_PARAMETER; + } + + if ((IoAlign > 1) && !IS_ALIGNED (Packet->OutDataBuffer, IoAlign)) { + return EFI_INVALID_PARAMETER; + } + + if ((IoAlign > 1) && !IS_ALIGNED (Packet->Asb, IoAlign)) { + return EFI_INVALID_PARAMETER; + } + + Private = GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_PASS_THRU (This); + DeviceData = SearchDeviceByPort (Private, Port, PortMultiplierPort); + if (DeviceData == NULL) { + return EFI_NOT_FOUND; + } + + MaxSectorCount = mMaxTransferBlockNumber[DeviceData->Lba48Bit]; + BlockSize = DeviceData->Media.BlockSize; + + // + // Convert the transfer length from sector count to byte. + // + if (((Packet->Length & EFI_ATA_PASS_THRU_LENGTH_BYTES) == 0) && + (Packet->InTransferLength != 0)) { + Packet->InTransferLength = Packet->InTransferLength * BlockSize; + } + + // + // Convert the transfer length from sector count to byte. + // + if (((Packet->Length & EFI_ATA_PASS_THRU_LENGTH_BYTES) == 0) && + (Packet->OutTransferLength != 0)) { + Packet->OutTransferLength = Packet->OutTransferLength * BlockSize; + } + + // + // If the data buffer described by InDataBuffer/OutDataBuffer and + // InTransferLength/OutTransferLength is too big to be transferred in a single + // command, then no data is transferred and EFI_BAD_BUFFER_SIZE is returned. + // + if (((Packet->InTransferLength != 0) && (Packet->InTransferLength > MaxSectorCount * BlockSize)) || + ((Packet->OutTransferLength != 0) && (Packet->OutTransferLength > MaxSectorCount * BlockSize))) { + return EFI_BAD_BUFFER_SIZE; + } + + return AhciPassThruExecute ( + Private, + DeviceData->Port, + DeviceData->PortMultiplier, + DeviceData->FisIndex, + Packet + ); +} + +/** + Used to retrieve the list of legal port numbers for ATA devices on an ATA controller. + These can either be the list of ports where ATA devices are actually present or the + list of legal port numbers for the ATA controller. Regardless, the caller of this + function must probe the port number returned to see if an ATA device is actually + present at that location on the ATA controller. + + The GetNextPort() function retrieves the port number on an ATA controller. If on + input Port is 0xFFFF, then the port number of the first port on the ATA controller + is returned in Port and EFI_SUCCESS is returned. + + If Port is a port number that was returned on a previous call to GetNextPort(), + then the port number of the next port on the ATA controller is returned in Port, + and EFI_SUCCESS is returned. If Port is not 0xFFFF and Port was not returned on + a previous call to GetNextPort(), then EFI_INVALID_PARAMETER is returned. + + If Port is the port number of the last port on the ATA controller, then EFI_NOT_FOUND + is returned. + + @param[in] This The PPI instance pointer. + @param[in,out] Port On input, a pointer to the port number on the ATA controller. + On output, a pointer to the next port number on the ATA + controller. An input value of 0xFFFF retrieves the first + port number on the ATA controller. + + @retval EFI_SUCCESS The next port number on the ATA controller was + returned in Port. + @retval EFI_NOT_FOUND There are no more ports on this ATA controller. + @retval EFI_INVALID_PARAMETER Port is not 0xFFFF and Port was not returned + on a previous call to GetNextPort(). + +**/ +EFI_STATUS +EFIAPI +AhciAtaPassThruGetNextPort ( + IN EDKII_PEI_ATA_PASS_THRU_PPI *This, + IN OUT UINT16 *Port + ) +{ + PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private; + PEI_AHCI_ATA_DEVICE_DATA *DeviceData; + LIST_ENTRY *Node; + + if (This == NULL || Port == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private = GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_PASS_THRU (This); + + if (*Port == 0xFFFF) { + // + // If the Port is all 0xFF's, start to traverse the device list from the + // beginning. + // + Node = GetFirstNode (&Private->DeviceList); + if (!IsNull (&Private->DeviceList, Node)) { + DeviceData = AHCI_PEI_ATA_DEVICE_INFO_FROM_THIS (Node); + + *Port = DeviceData->Port; + goto Exit; + } + + return EFI_NOT_FOUND; + } else if (*Port == Private->PreviousPort) { + Node = GetFirstNode (&Private->DeviceList); + + while (!IsNull (&Private->DeviceList, Node)) { + DeviceData = AHCI_PEI_ATA_DEVICE_INFO_FROM_THIS (Node); + + if (DeviceData->Port > *Port){ + *Port = DeviceData->Port; + goto Exit; + } + + Node = GetNextNode (&Private->DeviceList, Node); + } + + return EFI_NOT_FOUND; + } else { + // + // Port is not equal to all 0xFF's and not equal to previous return value. + // + return EFI_INVALID_PARAMETER; + } + +Exit: + // + // Update the PreviousPort. + // + Private->PreviousPort = *Port; + + return EFI_SUCCESS; +} + +/** + Used to retrieve the list of legal port multiplier port numbers for ATA devices + on a port of an ATA controller. These can either be the list of port multiplier + ports where ATA devices are actually present on port or the list of legal port + multiplier ports on that port. Regardless, the caller of this function must probe + the port number and port multiplier port number returned to see if an ATA device + is actually present. + + The GetNextDevice() function retrieves the port multiplier port number of an ATA + device present on a port of an ATA controller. + + If PortMultiplierPort points to a port multiplier port number value that was + returned on a previous call to GetNextDevice(), then the port multiplier port + number of the next ATA device on the port of the ATA controller is returned in + PortMultiplierPort, and EFI_SUCCESS is returned. + + If PortMultiplierPort points to 0xFFFF, then the port multiplier port number + of the first ATA device on port of the ATA controller is returned in PortMultiplierPort + and EFI_SUCCESS is returned. + + If PortMultiplierPort is not 0xFFFF and the value pointed to by PortMultiplierPort + was not returned on a previous call to GetNextDevice(), then EFI_INVALID_PARAMETER + is returned. + + If PortMultiplierPort is the port multiplier port number of the last ATA device + on the port of the ATA controller, then EFI_NOT_FOUND is returned. + + @param[in] This The PPI instance pointer. + @param[in] Port The port number present on the ATA controller. + @param[in,out] PortMultiplierPort On input, a pointer to the port multiplier + port number of an ATA device present on the + ATA controller. If on input a PortMultiplierPort + of 0xFFFF is specified, then the port multiplier + port number of the first ATA device is returned. + On output, a pointer to the port multiplier port + number of the next ATA device present on an ATA + controller. + + @retval EFI_SUCCESS The port multiplier port number of the next ATA + device on the port of the ATA controller was + returned in PortMultiplierPort. + @retval EFI_NOT_FOUND There are no more ATA devices on this port of + the ATA controller. + @retval EFI_INVALID_PARAMETER PortMultiplierPort is not 0xFFFF, and PortMultiplierPort + was not returned on a previous call to GetNextDevice(). + +**/ +EFI_STATUS +EFIAPI +AhciAtaPassThruGetNextDevice ( + IN EDKII_PEI_ATA_PASS_THRU_PPI *This, + IN UINT16 Port, + IN OUT UINT16 *PortMultiplierPort + ) +{ + PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private; + PEI_AHCI_ATA_DEVICE_DATA *DeviceData; + LIST_ENTRY *Node; + + if (This == NULL || PortMultiplierPort == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private = GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_PASS_THRU (This); + + if (Private->PreviousPortMultiplier == 0xFFFF) { + // + // If a device is directly attached on a port, previous call to this + // function will return the value 0xFFFF for PortMultiplierPort. In + // this case, there should be no more device on the port multiplier. + // + Private->PreviousPortMultiplier = 0; + return EFI_NOT_FOUND; + } + + if (*PortMultiplierPort == Private->PreviousPortMultiplier) { + Node = GetFirstNode (&Private->DeviceList); + + while (!IsNull (&Private->DeviceList, Node)) { + DeviceData = AHCI_PEI_ATA_DEVICE_INFO_FROM_THIS (Node); + + if ((DeviceData->Port == Port) && + (DeviceData->PortMultiplier > *PortMultiplierPort)){ + *PortMultiplierPort = DeviceData->PortMultiplier; + goto Exit; + } + + Node = GetNextNode (&Private->DeviceList, Node); + } + + return EFI_NOT_FOUND; + } else if (*PortMultiplierPort == 0xFFFF) { + // + // If the PortMultiplierPort is all 0xFF's, start to traverse the device list + // from the beginning. + // + Node = GetFirstNode (&Private->DeviceList); + + while (!IsNull (&Private->DeviceList, Node)) { + DeviceData = AHCI_PEI_ATA_DEVICE_INFO_FROM_THIS (Node); + + if (DeviceData->Port == Port){ + *PortMultiplierPort = DeviceData->PortMultiplier; + goto Exit; + } + + Node = GetNextNode (&Private->DeviceList, Node); + } + + return EFI_NOT_FOUND; + } else { + // + // PortMultiplierPort is not equal to all 0xFF's and not equal to previous + // return value. + // + return EFI_INVALID_PARAMETER; + } + +Exit: + // + // Update the PreviousPortMultiplier. + // + Private->PreviousPortMultiplier = *PortMultiplierPort; + + return EFI_SUCCESS; +} + +/** + Gets the device path information of the underlying ATA host controller. + + @param[in] This The PPI instance pointer. + @param[out] DevicePathLength The length of the device path in bytes specified + by DevicePath. + @param[out] DevicePath The device path of the underlying ATA host controller. + This field re-uses EFI Device Path Protocol as + defined by Section 10.2 EFI Device Path Protocol + of UEFI 2.7 Specification. + + @retval EFI_SUCCESS The device path of the ATA host controller has + been successfully returned. + @retval EFI_INVALID_PARAMETER DevicePathLength or DevicePath is NULL. + @retval EFI_OUT_OF_RESOURCES Not enough resource to return the device path. + +**/ +EFI_STATUS +EFIAPI +AhciAtaPassThruGetDevicePath ( + IN EDKII_PEI_ATA_PASS_THRU_PPI *This, + OUT UINTN *DevicePathLength, + OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ) +{ + PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private; + + if (This == NULL || DevicePathLength == NULL || DevicePath == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private = GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_PASS_THRU (This); + + *DevicePathLength = Private->DevicePathLength; + *DevicePath = AllocateCopyPool (Private->DevicePathLength, Private->DevicePath); + if (*DevicePath == NULL) { + *DevicePathLength = 0; + return EFI_OUT_OF_RESOURCES; + } + + return EFI_SUCCESS; +} diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/AhciPeiPassThru.h b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/AhciPeiPassThru.h new file mode 100644 index 0000000..94395aa --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/AhciPeiPassThru.h @@ -0,0 +1,177 @@ +/** @file + The AhciPei driver is used to manage ATA hard disk device working under AHCI + mode at PEI phase. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _AHCI_PEI_PASSTHRU_H_ +#define _AHCI_PEI_PASSTHRU_H_ + +/** + Sends an ATA command to an ATA device that is attached to the ATA controller. + + @param[in] This The PPI instance pointer. + @param[in] Port The port number of the ATA device to send + the command. + @param[in] PortMultiplierPort The port multiplier port number of the ATA + device to send the command. + If there is no port multiplier, then specify + 0xFFFF. + @param[in,out] Packet A pointer to the ATA command to send to + the ATA device specified by Port and + PortMultiplierPort. + + @retval EFI_SUCCESS The ATA command was sent by the host. For + bi-directional commands, InTransferLength bytes + were transferred from InDataBuffer. For write + and bi-directional commands, OutTransferLength + bytes were transferred by OutDataBuffer. + @retval EFI_NOT_FOUND The specified ATA device is not found. + @retval EFI_INVALID_PARAMETER The contents of Acb are invalid. The ATA command + was not sent, so no additional status information + is available. + @retval EFI_BAD_BUFFER_SIZE The ATA command was not executed. The number + of bytes that could be transferred is returned + in InTransferLength. For write and bi-directional + commands, OutTransferLength bytes were transferred + by OutDataBuffer. + @retval EFI_NOT_READY The ATA command could not be sent because there + are too many ATA commands already queued. The + caller may retry again later. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to + send the ATA command. + +**/ +EFI_STATUS +EFIAPI +AhciAtaPassThruPassThru ( + IN EDKII_PEI_ATA_PASS_THRU_PPI *This, + IN UINT16 Port, + IN UINT16 PortMultiplierPort, + IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet + ); + +/** + Used to retrieve the list of legal port numbers for ATA devices on an ATA controller. + These can either be the list of ports where ATA devices are actually present or the + list of legal port numbers for the ATA controller. Regardless, the caller of this + function must probe the port number returned to see if an ATA device is actually + present at that location on the ATA controller. + + The GetNextPort() function retrieves the port number on an ATA controller. If on + input Port is 0xFFFF, then the port number of the first port on the ATA controller + is returned in Port and EFI_SUCCESS is returned. + + If Port is a port number that was returned on a previous call to GetNextPort(), + then the port number of the next port on the ATA controller is returned in Port, + and EFI_SUCCESS is returned. If Port is not 0xFFFF and Port was not returned on + a previous call to GetNextPort(), then EFI_INVALID_PARAMETER is returned. + + If Port is the port number of the last port on the ATA controller, then EFI_NOT_FOUND + is returned. + + @param[in] This The PPI instance pointer. + @param[in,out] Port On input, a pointer to the port number on the ATA controller. + On output, a pointer to the next port number on the ATA + controller. An input value of 0xFFFF retrieves the first + port number on the ATA controller. + + @retval EFI_SUCCESS The next port number on the ATA controller was + returned in Port. + @retval EFI_NOT_FOUND There are no more ports on this ATA controller. + @retval EFI_INVALID_PARAMETER Port is not 0xFFFF and Port was not returned + on a previous call to GetNextPort(). + +**/ +EFI_STATUS +EFIAPI +AhciAtaPassThruGetNextPort ( + IN EDKII_PEI_ATA_PASS_THRU_PPI *This, + IN OUT UINT16 *Port + ); + +/** + Used to retrieve the list of legal port multiplier port numbers for ATA devices + on a port of an ATA controller. These can either be the list of port multiplier + ports where ATA devices are actually present on port or the list of legal port + multiplier ports on that port. Regardless, the caller of this function must probe + the port number and port multiplier port number returned to see if an ATA device + is actually present. + + The GetNextDevice() function retrieves the port multiplier port number of an ATA + device present on a port of an ATA controller. + + If PortMultiplierPort points to a port multiplier port number value that was + returned on a previous call to GetNextDevice(), then the port multiplier port + number of the next ATA device on the port of the ATA controller is returned in + PortMultiplierPort, and EFI_SUCCESS is returned. + + If PortMultiplierPort points to 0xFFFF, then the port multiplier port number + of the first ATA device on port of the ATA controller is returned in PortMultiplierPort + and EFI_SUCCESS is returned. + + If PortMultiplierPort is not 0xFFFF and the value pointed to by PortMultiplierPort + was not returned on a previous call to GetNextDevice(), then EFI_INVALID_PARAMETER + is returned. + + If PortMultiplierPort is the port multiplier port number of the last ATA device + on the port of the ATA controller, then EFI_NOT_FOUND is returned. + + @param[in] This The PPI instance pointer. + @param[in] Port The port number present on the ATA controller. + @param[in,out] PortMultiplierPort On input, a pointer to the port multiplier + port number of an ATA device present on the + ATA controller. If on input a PortMultiplierPort + of 0xFFFF is specified, then the port multiplier + port number of the first ATA device is returned. + On output, a pointer to the port multiplier port + number of the next ATA device present on an ATA + controller. + + @retval EFI_SUCCESS The port multiplier port number of the next ATA + device on the port of the ATA controller was + returned in PortMultiplierPort. + @retval EFI_NOT_FOUND There are no more ATA devices on this port of + the ATA controller. + @retval EFI_INVALID_PARAMETER PortMultiplierPort is not 0xFFFF, and PortMultiplierPort + was not returned on a previous call to GetNextDevice(). + +**/ +EFI_STATUS +EFIAPI +AhciAtaPassThruGetNextDevice ( + IN EDKII_PEI_ATA_PASS_THRU_PPI *This, + IN UINT16 Port, + IN OUT UINT16 *PortMultiplierPort + ); + +/** + Gets the device path information of the underlying ATA host controller. + + @param[in] This The PPI instance pointer. + @param[out] DevicePathLength The length of the device path in bytes specified + by DevicePath. + @param[out] DevicePath The device path of the underlying ATA host controller. + This field re-uses EFI Device Path Protocol as + defined by Section 10.2 EFI Device Path Protocol + of UEFI 2.7 Specification. + + @retval EFI_SUCCESS The device path of the ATA host controller has + been successfully returned. + @retval EFI_INVALID_PARAMETER DevicePathLength or DevicePath is NULL. + @retval EFI_OUT_OF_RESOURCES Not enough resource to return the device path. + +**/ +EFI_STATUS +EFIAPI +AhciAtaPassThruGetDevicePath ( + IN EDKII_PEI_ATA_PASS_THRU_PPI *This, + OUT UINTN *DevicePathLength, + OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ); + +#endif diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/AhciPeiStorageSecurity.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/AhciPeiStorageSecurity.c new file mode 100644 index 0000000..1bc25a7 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/AhciPeiStorageSecurity.c @@ -0,0 +1,384 @@ +/** @file + The AhciPei driver is used to manage ATA hard disk device working under AHCI + mode at PEI phase. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "AhciPei.h" + +/** + Traverse the attached ATA devices list to find out the device with given trust + computing device index. + + @param[in] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA + instance. + @param[in] TrustComputingDeviceIndex The trust computing device index. + + @retval The pointer to the PEI_AHCI_ATA_DEVICE_DATA structure of the device + info to access. + +**/ +PEI_AHCI_ATA_DEVICE_DATA * +SearchTrustComputingDeviceByIndex ( + IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private, + IN UINTN TrustComputingDeviceIndex + ) +{ + PEI_AHCI_ATA_DEVICE_DATA *DeviceData; + LIST_ENTRY *Node; + + Node = GetFirstNode (&Private->DeviceList); + while (!IsNull (&Private->DeviceList, Node)) { + DeviceData = AHCI_PEI_ATA_DEVICE_INFO_FROM_THIS (Node); + + if (DeviceData->TrustComputingDeviceIndex == TrustComputingDeviceIndex) { + return DeviceData; + } + + Node = GetNextNode (&Private->DeviceList, Node); + } + + return NULL; +} + +/** + Gets the count of storage security devices that one specific driver detects. + + @param[in] This The PPI instance pointer. + @param[out] NumberofDevices The number of storage security devices discovered. + + @retval EFI_SUCCESS The operation performed successfully. + @retval EFI_INVALID_PARAMETER The parameters are invalid. + +**/ +EFI_STATUS +EFIAPI +AhciStorageSecurityGetDeviceNo ( + IN EDKII_PEI_STORAGE_SECURITY_CMD_PPI *This, + OUT UINTN *NumberofDevices + ) +{ + PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private; + + if (This == NULL || NumberofDevices == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private = GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_STROAGE_SECURITY (This); + *NumberofDevices = Private->TrustComputingDevices; + + return EFI_SUCCESS; +} + +/** + Gets the device path of a specific storage security device. + + @param[in] This The PPI instance pointer. + @param[in] DeviceIndex Specifies the storage security device to which + the function wants to talk. Because the driver + that implements Storage Security Command PPIs + will manage multiple storage devices, the PPIs + that want to talk to a single device must specify + the device index that was assigned during the + enumeration process. This index is a number from + one to NumberofDevices. + @param[out] DevicePathLength The length of the device path in bytes specified + by DevicePath. + @param[out] DevicePath The device path of storage security device. + This field re-uses EFI Device Path Protocol as + defined by Section 10.2 EFI Device Path Protocol + of UEFI 2.7 Specification. + + @retval EFI_SUCCESS The operation succeeds. + @retval EFI_INVALID_PARAMETER DevicePathLength or DevicePath is NULL. + @retval EFI_NOT_FOUND The specified storage security device not found. + @retval EFI_OUT_OF_RESOURCES The operation fails due to lack of resources. + +**/ +EFI_STATUS +EFIAPI +AhciStorageSecurityGetDevicePath ( + IN EDKII_PEI_STORAGE_SECURITY_CMD_PPI *This, + IN UINTN DeviceIndex, + OUT UINTN *DevicePathLength, + OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ) +{ + PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private; + PEI_AHCI_ATA_DEVICE_DATA *DeviceData; + EFI_STATUS Status; + + if (This == NULL || DevicePathLength == NULL || DevicePath == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private = GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_STROAGE_SECURITY (This); + if ((DeviceIndex == 0) || (DeviceIndex > Private->TrustComputingDevices)) { + return EFI_INVALID_PARAMETER; + } + + DeviceData = SearchTrustComputingDeviceByIndex (Private, DeviceIndex); + if (DeviceData == NULL) { + return EFI_NOT_FOUND; + } + + Status = AhciBuildDevicePath ( + Private, + DeviceData->Port, + DeviceData->PortMultiplier, + DevicePathLength, + DevicePath + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +/** + Send a security protocol command to a device that receives data and/or the result + of one or more commands sent by SendData. + + The ReceiveData function sends a security protocol command to the given DeviceIndex. + The security protocol command sent is defined by SecurityProtocolId and contains + the security protocol specific data SecurityProtocolSpecificData. The function + returns the data from the security protocol command in PayloadBuffer. + + For devices supporting the SCSI command set, the security protocol command is sent + using the SECURITY PROTOCOL IN command defined in SPC-4. + + For devices supporting the ATA command set, the security protocol command is sent + using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if PayloadBufferSize + is non-zero. + + If the PayloadBufferSize is zero, the security protocol command is sent using the + Trusted Non-Data command defined in ATA8-ACS. + + If PayloadBufferSize is too small to store the available data from the security + protocol command, the function shall copy PayloadBufferSize bytes into the + PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL. + + If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is non-zero, + the function shall return EFI_INVALID_PARAMETER. + + If the given DeviceIndex does not support security protocol commands, the function + shall return EFI_UNSUPPORTED. + + If the security protocol fails to complete within the Timeout period, the function + shall return EFI_TIMEOUT. + + If the security protocol command completes without an error, the function shall + return EFI_SUCCESS. If the security protocol command completes with an error, the + function shall return EFI_DEVICE_ERROR. + + @param[in] This The PPI instance pointer. + @param[in] DeviceIndex Specifies the storage security device to which the + function wants to talk. Because the driver that + implements Storage Security Command PPIs will manage + multiple storage devices, the PPIs that want to talk + to a single device must specify the device index + that was assigned during the enumeration process. + This index is a number from one to NumberofDevices. + @param[in] Timeout The timeout, in 100ns units, to use for the execution + of the security protocol command. A Timeout value + of 0 means that this function will wait indefinitely + for the security protocol command to execute. If + Timeout is greater than zero, then this function + will return EFI_TIMEOUT if the time required to + execute the receive data command is greater than + Timeout. + @param[in] SecurityProtocolId + The value of the "Security Protocol" parameter of + the security protocol command to be sent. + @param[in] SecurityProtocolSpecificData + The value of the "Security Protocol Specific" + parameter of the security protocol command to be + sent. + @param[in] PayloadBufferSize + Size in bytes of the payload data buffer. + @param[out] PayloadBuffer A pointer to a destination buffer to store the + security protocol command specific payload data + for the security protocol command. The caller is + responsible for having either implicit or explicit + ownership of the buffer. + @param[out] PayloadTransferSize + A pointer to a buffer to store the size in bytes + of the data written to the payload data buffer. + + @retval EFI_SUCCESS The security protocol command completed + successfully. + @retval EFI_WARN_BUFFER_TOO_SMALL The PayloadBufferSize was too small to + store the available data from the device. + The PayloadBuffer contains the truncated + data. + @retval EFI_UNSUPPORTED The given DeviceIndex does not support + security protocol commands. + @retval EFI_DEVICE_ERROR The security protocol command completed + with an error. + @retval EFI_INVALID_PARAMETER The PayloadBuffer or PayloadTransferSize + is NULL and PayloadBufferSize is non-zero. + @retval EFI_TIMEOUT A timeout occurred while waiting for the + security protocol command to execute. + +**/ +EFI_STATUS +EFIAPI +AhciStorageSecurityReceiveData ( + IN EDKII_PEI_STORAGE_SECURITY_CMD_PPI *This, + IN UINTN DeviceIndex, + IN UINT64 Timeout, + IN UINT8 SecurityProtocolId, + IN UINT16 SecurityProtocolSpecificData, + IN UINTN PayloadBufferSize, + OUT VOID *PayloadBuffer, + OUT UINTN *PayloadTransferSize + ) +{ + PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private; + PEI_AHCI_ATA_DEVICE_DATA *DeviceData; + + if ((PayloadBuffer == NULL) || (PayloadTransferSize == NULL) || (PayloadBufferSize == 0)) { + return EFI_INVALID_PARAMETER; + } + + Private = GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_STROAGE_SECURITY (This); + if ((DeviceIndex == 0) || (DeviceIndex > Private->TrustComputingDevices)) { + return EFI_INVALID_PARAMETER; + } + + DeviceData = SearchTrustComputingDeviceByIndex (Private, DeviceIndex); + if (DeviceData == NULL) { + return EFI_NOT_FOUND; + } + + ASSERT ((DeviceData->IdentifyData->trusted_computing_support & BIT0) != 0); + if ((DeviceData->IdentifyData->trusted_computing_support & BIT0) == 0) { + return EFI_UNSUPPORTED; + } + + return TrustTransferAtaDevice ( + DeviceData, + PayloadBuffer, + SecurityProtocolId, + SecurityProtocolSpecificData, + PayloadBufferSize, + FALSE, + Timeout, + PayloadTransferSize + ); +} + +/** + Send a security protocol command to a device. + + The SendData function sends a security protocol command containing the payload + PayloadBuffer to the given DeviceIndex. The security protocol command sent is + defined by SecurityProtocolId and contains the security protocol specific data + SecurityProtocolSpecificData. If the underlying protocol command requires a + specific padding for the command payload, the SendData function shall add padding + bytes to the command payload to satisfy the padding requirements. + + For devices supporting the SCSI command set, the security protocol command is + sent using the SECURITY PROTOCOL OUT command defined in SPC-4. + + For devices supporting the ATA command set, the security protocol command is + sent using one of the TRUSTED SEND commands defined in ATA8-ACS if PayloadBufferSize + is non-zero. If the PayloadBufferSize is zero, the security protocol command + is sent using the Trusted Non-Data command defined in ATA8-ACS. + + If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function shall + return EFI_INVALID_PARAMETER. + + If the given DeviceIndex does not support security protocol commands, the function + shall return EFI_UNSUPPORTED. + + If the security protocol fails to complete within the Timeout period, the function + shall return EFI_TIMEOUT. + + If the security protocol command completes without an error, the function shall + return EFI_SUCCESS. If the security protocol command completes with an error, + the functio shall return EFI_DEVICE_ERROR. + + @param[in] This The PPI instance pointer. + @param[in] DeviceIndex The ID of the device. + @param[in] Timeout The timeout, in 100ns units, to use for the execution + of the security protocol command. A Timeout value + of 0 means that this function will wait indefinitely + for the security protocol command to execute. If + Timeout is greater than zero, then this function + will return EFI_TIMEOUT if the time required to + execute the receive data command is greater than + Timeout. + @param[in] SecurityProtocolId + The value of the "Security Protocol" parameter of + the security protocol command to be sent. + @param[in] SecurityProtocolSpecificData + The value of the "Security Protocol Specific" + parameter of the security protocol command to be + sent. + @param[in] PayloadBufferSize Size in bytes of the payload data buffer. + @param[in] PayloadBuffer A pointer to a destination buffer to store the + security protocol command specific payload data + for the security protocol command. + + @retval EFI_SUCCESS The security protocol command completed successfully. + @retval EFI_UNSUPPORTED The given DeviceIndex does not support security + protocol commands. + @retval EFI_DEVICE_ERROR The security protocol command completed with + an error. + @retval EFI_INVALID_PARAMETER The PayloadBuffer is NULL and PayloadBufferSize + is non-zero. + @retval EFI_TIMEOUT A timeout occurred while waiting for the security + protocol command to execute. + +**/ +EFI_STATUS +EFIAPI +AhciStorageSecuritySendData ( + IN EDKII_PEI_STORAGE_SECURITY_CMD_PPI *This, + IN UINTN DeviceIndex, + IN UINT64 Timeout, + IN UINT8 SecurityProtocolId, + IN UINT16 SecurityProtocolSpecificData, + IN UINTN PayloadBufferSize, + IN VOID *PayloadBuffer + ) +{ + PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private; + PEI_AHCI_ATA_DEVICE_DATA *DeviceData; + + if ((PayloadBuffer == NULL) && (PayloadBufferSize != 0)) { + return EFI_INVALID_PARAMETER; + } + + Private = GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_STROAGE_SECURITY (This); + if ((DeviceIndex == 0) || (DeviceIndex > Private->TrustComputingDevices)) { + return EFI_INVALID_PARAMETER; + } + + DeviceData = SearchTrustComputingDeviceByIndex (Private, DeviceIndex); + if (DeviceData == NULL) { + return EFI_NOT_FOUND; + } + + ASSERT ((DeviceData->IdentifyData->trusted_computing_support & BIT0) != 0); + if ((DeviceData->IdentifyData->trusted_computing_support & BIT0) == 0) { + return EFI_UNSUPPORTED; + } + + return TrustTransferAtaDevice ( + DeviceData, + PayloadBuffer, + SecurityProtocolId, + SecurityProtocolSpecificData, + PayloadBufferSize, + TRUE, + Timeout, + NULL + ); +} diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/AhciPeiStorageSecurity.h b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/AhciPeiStorageSecurity.h new file mode 100644 index 0000000..905cdb8 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/AhciPeiStorageSecurity.h @@ -0,0 +1,240 @@ +/** @file + The AhciPei driver is used to manage ATA hard disk device working under AHCI + mode at PEI phase. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _AHCI_PEI_STORAGE_SECURITY_H_ +#define _AHCI_PEI_STORAGE_SECURITY_H_ + +/** + Gets the count of storage security devices that one specific driver detects. + + @param[in] This The PPI instance pointer. + @param[out] NumberofDevices The number of storage security devices discovered. + + @retval EFI_SUCCESS The operation performed successfully. + @retval EFI_INVALID_PARAMETER The parameters are invalid. + +**/ +EFI_STATUS +EFIAPI +AhciStorageSecurityGetDeviceNo ( + IN EDKII_PEI_STORAGE_SECURITY_CMD_PPI *This, + OUT UINTN *NumberofDevices + ); + +/** + Gets the device path of a specific storage security device. + + @param[in] This The PPI instance pointer. + @param[in] DeviceIndex Specifies the storage security device to which + the function wants to talk. Because the driver + that implements Storage Security Command PPIs + will manage multiple storage devices, the PPIs + that want to talk to a single device must specify + the device index that was assigned during the + enumeration process. This index is a number from + one to NumberofDevices. + @param[out] DevicePathLength The length of the device path in bytes specified + by DevicePath. + @param[out] DevicePath The device path of storage security device. + This field re-uses EFI Device Path Protocol as + defined by Section 10.2 EFI Device Path Protocol + of UEFI 2.7 Specification. + + @retval EFI_SUCCESS The operation succeeds. + @retval EFI_INVALID_PARAMETER DevicePathLength or DevicePath is NULL. + @retval EFI_NOT_FOUND The specified storage security device not found. + @retval EFI_OUT_OF_RESOURCES The operation fails due to lack of resources. + +**/ +EFI_STATUS +EFIAPI +AhciStorageSecurityGetDevicePath ( + IN EDKII_PEI_STORAGE_SECURITY_CMD_PPI *This, + IN UINTN DeviceIndex, + OUT UINTN *DevicePathLength, + OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ); + +/** + Send a security protocol command to a device that receives data and/or the result + of one or more commands sent by SendData. + + The ReceiveData function sends a security protocol command to the given DeviceIndex. + The security protocol command sent is defined by SecurityProtocolId and contains + the security protocol specific data SecurityProtocolSpecificData. The function + returns the data from the security protocol command in PayloadBuffer. + + For devices supporting the SCSI command set, the security protocol command is sent + using the SECURITY PROTOCOL IN command defined in SPC-4. + + For devices supporting the ATA command set, the security protocol command is sent + using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if PayloadBufferSize + is non-zero. + + If the PayloadBufferSize is zero, the security protocol command is sent using the + Trusted Non-Data command defined in ATA8-ACS. + + If PayloadBufferSize is too small to store the available data from the security + protocol command, the function shall copy PayloadBufferSize bytes into the + PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL. + + If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is non-zero, + the function shall return EFI_INVALID_PARAMETER. + + If the given DeviceIndex does not support security protocol commands, the function + shall return EFI_UNSUPPORTED. + + If the security protocol fails to complete within the Timeout period, the function + shall return EFI_TIMEOUT. + + If the security protocol command completes without an error, the function shall + return EFI_SUCCESS. If the security protocol command completes with an error, the + function shall return EFI_DEVICE_ERROR. + + @param[in] This The PPI instance pointer. + @param[in] DeviceIndex Specifies the storage security device to which the + function wants to talk. Because the driver that + implements Storage Security Command PPIs will manage + multiple storage devices, the PPIs that want to talk + to a single device must specify the device index + that was assigned during the enumeration process. + This index is a number from one to NumberofDevices. + @param[in] Timeout The timeout, in 100ns units, to use for the execution + of the security protocol command. A Timeout value + of 0 means that this function will wait indefinitely + for the security protocol command to execute. If + Timeout is greater than zero, then this function + will return EFI_TIMEOUT if the time required to + execute the receive data command is greater than + Timeout. + @param[in] SecurityProtocolId + The value of the "Security Protocol" parameter of + the security protocol command to be sent. + @param[in] SecurityProtocolSpecificData + The value of the "Security Protocol Specific" + parameter of the security protocol command to be + sent. + @param[in] PayloadBufferSize + Size in bytes of the payload data buffer. + @param[out] PayloadBuffer A pointer to a destination buffer to store the + security protocol command specific payload data + for the security protocol command. The caller is + responsible for having either implicit or explicit + ownership of the buffer. + @param[out] PayloadTransferSize + A pointer to a buffer to store the size in bytes + of the data written to the payload data buffer. + + @retval EFI_SUCCESS The security protocol command completed + successfully. + @retval EFI_WARN_BUFFER_TOO_SMALL The PayloadBufferSize was too small to + store the available data from the device. + The PayloadBuffer contains the truncated + data. + @retval EFI_UNSUPPORTED The given DeviceIndex does not support + security protocol commands. + @retval EFI_DEVICE_ERROR The security protocol command completed + with an error. + @retval EFI_INVALID_PARAMETER The PayloadBuffer or PayloadTransferSize + is NULL and PayloadBufferSize is non-zero. + @retval EFI_TIMEOUT A timeout occurred while waiting for the + security protocol command to execute. + +**/ +EFI_STATUS +EFIAPI +AhciStorageSecurityReceiveData ( + IN EDKII_PEI_STORAGE_SECURITY_CMD_PPI *This, + IN UINTN DeviceIndex, + IN UINT64 Timeout, + IN UINT8 SecurityProtocolId, + IN UINT16 SecurityProtocolSpecificData, + IN UINTN PayloadBufferSize, + OUT VOID *PayloadBuffer, + OUT UINTN *PayloadTransferSize + ); + +/** + Send a security protocol command to a device. + + The SendData function sends a security protocol command containing the payload + PayloadBuffer to the given DeviceIndex. The security protocol command sent is + defined by SecurityProtocolId and contains the security protocol specific data + SecurityProtocolSpecificData. If the underlying protocol command requires a + specific padding for the command payload, the SendData function shall add padding + bytes to the command payload to satisfy the padding requirements. + + For devices supporting the SCSI command set, the security protocol command is + sent using the SECURITY PROTOCOL OUT command defined in SPC-4. + + For devices supporting the ATA command set, the security protocol command is + sent using one of the TRUSTED SEND commands defined in ATA8-ACS if PayloadBufferSize + is non-zero. If the PayloadBufferSize is zero, the security protocol command + is sent using the Trusted Non-Data command defined in ATA8-ACS. + + If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function shall + return EFI_INVALID_PARAMETER. + + If the given DeviceIndex does not support security protocol commands, the function + shall return EFI_UNSUPPORTED. + + If the security protocol fails to complete within the Timeout period, the function + shall return EFI_TIMEOUT. + + If the security protocol command completes without an error, the function shall + return EFI_SUCCESS. If the security protocol command completes with an error, + the functio shall return EFI_DEVICE_ERROR. + + @param[in] This The PPI instance pointer. + @param[in] DeviceIndex The ID of the device. + @param[in] Timeout The timeout, in 100ns units, to use for the execution + of the security protocol command. A Timeout value + of 0 means that this function will wait indefinitely + for the security protocol command to execute. If + Timeout is greater than zero, then this function + will return EFI_TIMEOUT if the time required to + execute the receive data command is greater than + Timeout. + @param[in] SecurityProtocolId + The value of the "Security Protocol" parameter of + the security protocol command to be sent. + @param[in] SecurityProtocolSpecificData + The value of the "Security Protocol Specific" + parameter of the security protocol command to be + sent. + @param[in] PayloadBufferSize Size in bytes of the payload data buffer. + @param[in] PayloadBuffer A pointer to a destination buffer to store the + security protocol command specific payload data + for the security protocol command. + + @retval EFI_SUCCESS The security protocol command completed successfully. + @retval EFI_UNSUPPORTED The given DeviceIndex does not support security + protocol commands. + @retval EFI_DEVICE_ERROR The security protocol command completed with + an error. + @retval EFI_INVALID_PARAMETER The PayloadBuffer is NULL and PayloadBufferSize + is non-zero. + @retval EFI_TIMEOUT A timeout occurred while waiting for the security + protocol command to execute. + +**/ +EFI_STATUS +EFIAPI +AhciStorageSecuritySendData ( + IN EDKII_PEI_STORAGE_SECURITY_CMD_PPI *This, + IN UINTN DeviceIndex, + IN UINT64 Timeout, + IN UINT8 SecurityProtocolId, + IN UINT16 SecurityProtocolSpecificData, + IN UINTN PayloadBufferSize, + IN VOID *PayloadBuffer + ); + +#endif diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/DevicePath.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/DevicePath.c new file mode 100644 index 0000000..65d6fcb --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/DevicePath.c @@ -0,0 +1,277 @@ +/** @file + The device path help function. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "AhciPei.h" + +// +// Template for a SATA Device Path node +// +SATA_DEVICE_PATH mAhciSataDevicePathNodeTemplate = { + { // Header + MESSAGING_DEVICE_PATH, + MSG_SATA_DP, + { + (UINT8) (sizeof (SATA_DEVICE_PATH)), + (UINT8) ((sizeof (SATA_DEVICE_PATH)) >> 8) + } + }, + 0x0, // HBAPortNumber + 0xFFFF, // PortMultiplierPortNumber + 0x0 // Lun +}; + +// +// Template for an End of entire Device Path node +// +EFI_DEVICE_PATH_PROTOCOL mAhciEndDevicePathNodeTemplate = { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (sizeof (EFI_DEVICE_PATH_PROTOCOL)), + (UINT8) ((sizeof (EFI_DEVICE_PATH_PROTOCOL)) >> 8) + } +}; + +/** + Returns the 16-bit Length field of a device path node. + + Returns the 16-bit Length field of the device path node specified by Node. + Node is not required to be aligned on a 16-bit boundary, so it is recommended + that a function such as ReadUnaligned16() be used to extract the contents of + the Length field. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @return The 16-bit Length field of the device path node specified by Node. + +**/ +UINTN +DevicePathNodeLength ( + IN CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return ReadUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Length[0]); +} + +/** + Returns a pointer to the next node in a device path. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @return a pointer to the device path node that follows the device path node + specified by Node. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +NextDevicePathNode ( + IN CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)(Node) + DevicePathNodeLength(Node)); +} + +/** + Get the size of the current device path instance. + + @param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL + structure. + @param[out] InstanceSize The size of the current device path instance. + @param[out] EntireDevicePathEnd Indicate whether the instance is the last + one in the device path strucure. + + @retval EFI_SUCCESS The size of the current device path instance is fetched. + @retval Others Fails to get the size of the current device path instance. + +**/ +EFI_STATUS +GetDevicePathInstanceSize ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT UINTN *InstanceSize, + OUT BOOLEAN *EntireDevicePathEnd + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Walker; + + if (DevicePath == NULL || InstanceSize == NULL || EntireDevicePathEnd == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Find the end of the device path instance + // + Walker = DevicePath; + while (Walker->Type != END_DEVICE_PATH_TYPE) { + Walker = NextDevicePathNode (Walker); + } + + // + // Check if 'Walker' points to the end of an entire device path + // + if (Walker->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE) { + *EntireDevicePathEnd = TRUE; + } else if (Walker->SubType == END_INSTANCE_DEVICE_PATH_SUBTYPE) { + *EntireDevicePathEnd = FALSE; + } else { + return EFI_INVALID_PARAMETER; + } + + // + // Compute the size of the device path instance + // + *InstanceSize = ((UINTN) Walker - (UINTN) (DevicePath)) + sizeof (EFI_DEVICE_PATH_PROTOCOL); + + return EFI_SUCCESS; +} + +/** + Check the validity of the device path of a ATA AHCI host controller. + + @param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL + structure. + @param[in] DevicePathLength The length of the device path. + + @retval EFI_SUCCESS The device path is valid. + @retval EFI_INVALID_PARAMETER The device path is invalid. + +**/ +EFI_STATUS +AhciIsHcDevicePathValid ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN UINTN DevicePathLength + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Start; + UINTN Size; + + if (DevicePath == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Validate the DevicePathLength is big enough to touch the first node. + // + if (DevicePathLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) { + return EFI_INVALID_PARAMETER; + } + + Start = DevicePath; + while (!(DevicePath->Type == END_DEVICE_PATH_TYPE && + DevicePath->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE)) { + DevicePath = NextDevicePathNode (DevicePath); + + // + // Prevent overflow and invalid zero in the 'Length' field of a device path + // node. + // + if ((UINTN) DevicePath <= (UINTN) Start) { + return EFI_INVALID_PARAMETER; + } + + // + // Prevent touching memory beyond given DevicePathLength. + // + if ((UINTN) DevicePath - (UINTN) Start > + DevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL)) { + return EFI_INVALID_PARAMETER; + } + } + + // + // Check if the device path and its size match each other. + // + Size = ((UINTN) DevicePath - (UINTN) Start) + sizeof (EFI_DEVICE_PATH_PROTOCOL); + if (Size != DevicePathLength) { + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + +/** + Build the device path for an ATA device with given port and port multiplier number. + + @param[in] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA + data structure. + @param[in] Port The given port number. + @param[in] PortMultiplierPort The given port multiplier number. + @param[out] DevicePathLength The length of the device path in bytes specified + by DevicePath. + @param[out] DevicePath The device path of ATA device. + + @retval EFI_SUCCESS The operation succeeds. + @retval EFI_INVALID_PARAMETER The parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The operation fails due to lack of resources. + +**/ +EFI_STATUS +AhciBuildDevicePath ( + IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private, + IN UINT16 Port, + IN UINT16 PortMultiplierPort, + OUT UINTN *DevicePathLength, + OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePathWalker; + SATA_DEVICE_PATH *SataDeviceNode; + + if (DevicePathLength == NULL || DevicePath == NULL) { + return EFI_INVALID_PARAMETER; + } + + *DevicePathLength = Private->DevicePathLength + sizeof (SATA_DEVICE_PATH); + *DevicePath = AllocatePool (*DevicePathLength); + if (*DevicePath == NULL) { + *DevicePathLength = 0; + return EFI_OUT_OF_RESOURCES; + } + + // + // Construct the host controller part device nodes + // + DevicePathWalker = *DevicePath; + CopyMem ( + DevicePathWalker, + Private->DevicePath, + Private->DevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL) + ); + + // + // Construct the SATA device node + // + DevicePathWalker = (EFI_DEVICE_PATH_PROTOCOL *) ((UINT8 *)DevicePathWalker + + (Private->DevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL))); + CopyMem ( + DevicePathWalker, + &mAhciSataDevicePathNodeTemplate, + sizeof (mAhciSataDevicePathNodeTemplate) + ); + SataDeviceNode = (SATA_DEVICE_PATH *)DevicePathWalker; + SataDeviceNode->HBAPortNumber = Port; + SataDeviceNode->PortMultiplierPortNumber = PortMultiplierPort; + + // + // Construct the end device node + // + DevicePathWalker = (EFI_DEVICE_PATH_PROTOCOL *) ((UINT8 *)DevicePathWalker + + sizeof (SATA_DEVICE_PATH)); + CopyMem ( + DevicePathWalker, + &mAhciEndDevicePathNodeTemplate, + sizeof (mAhciEndDevicePathNodeTemplate) + ); + + return EFI_SUCCESS; +} diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/DmaMem.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/DmaMem.c new file mode 100644 index 0000000..748f562 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/DmaMem.c @@ -0,0 +1,269 @@ +/** @file + The DMA memory help function. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "AhciPei.h" + +/** + Get IOMMU PPI. + + @return Pointer to IOMMU PPI. + +**/ +EDKII_IOMMU_PPI * +GetIoMmu ( + VOID + ) +{ +// +// for fuzz +// +/* + EFI_STATUS Status; + EDKII_IOMMU_PPI *IoMmu; + + IoMmu = NULL; + Status = PeiServicesLocatePpi ( + &gEdkiiIoMmuPpiGuid, + 0, + NULL, + (VOID **) &IoMmu + ); + if (!EFI_ERROR (Status) && (IoMmu != NULL)) { + return IoMmu; + } +*/ + + return NULL; +} + +/** + Provides the controller-specific addresses required to access system memory from a + DMA bus master. + + @param Operation Indicates if the bus master is going to read or write to system memory. + @param HostAddress The system memory address to map to the PCI controller. + @param NumberOfBytes On input the number of bytes to map. On output the number of bytes + that were mapped. + @param DeviceAddress The resulting map address for the bus master PCI controller to use to + access the hosts HostAddress. + @param Mapping A resulting value to pass to Unmap(). + + @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. + +**/ +EFI_STATUS +IoMmuMap ( + IN EDKII_IOMMU_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + EFI_STATUS Status; + UINT64 Attribute; + EDKII_IOMMU_PPI *IoMmu; + + IoMmu = GetIoMmu (); + + if (IoMmu != NULL) { + Status = IoMmu->Map ( + IoMmu, + Operation, + HostAddress, + NumberOfBytes, + DeviceAddress, + Mapping + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + switch (Operation) { + case EdkiiIoMmuOperationBusMasterRead: + case EdkiiIoMmuOperationBusMasterRead64: + Attribute = EDKII_IOMMU_ACCESS_READ; + break; + case EdkiiIoMmuOperationBusMasterWrite: + case EdkiiIoMmuOperationBusMasterWrite64: + Attribute = EDKII_IOMMU_ACCESS_WRITE; + break; + case EdkiiIoMmuOperationBusMasterCommonBuffer: + case EdkiiIoMmuOperationBusMasterCommonBuffer64: + Attribute = EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE; + break; + default: + ASSERT(FALSE); + return EFI_INVALID_PARAMETER; + } + Status = IoMmu->SetAttribute ( + IoMmu, + *Mapping, + Attribute + ); + if (EFI_ERROR (Status)) { + return Status; + } + } else { + *DeviceAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress; + *Mapping = NULL; + Status = EFI_SUCCESS; + } + return Status; +} + +/** + Completes the Map() operation and releases any corresponding resources. + + @param Mapping The mapping value returned from Map(). + + @retval EFI_SUCCESS The range was unmapped. + @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map(). + @retval EFI_DEVICE_ERROR The data was not committed to the target system memory. +**/ +EFI_STATUS +IoMmuUnmap ( + IN VOID *Mapping + ) +{ + EFI_STATUS Status; + EDKII_IOMMU_PPI *IoMmu; + + IoMmu = GetIoMmu (); + + if (IoMmu != NULL) { + Status = IoMmu->SetAttribute (IoMmu, Mapping, 0); + Status = IoMmu->Unmap (IoMmu, Mapping); + } else { + Status = EFI_SUCCESS; + } + return Status; +} + +/** + Allocates pages that are suitable for an OperationBusMasterCommonBuffer or + OperationBusMasterCommonBuffer64 mapping. + + @param Pages The number of pages to allocate. + @param HostAddress A pointer to store the base system memory address of the + allocated range. + @param DeviceAddress The resulting map address for the bus master PCI controller to use to + access the hosts HostAddress. + @param Mapping A resulting value to pass to Unmap(). + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are + MEMORY_WRITE_COMBINE and MEMORY_CACHED. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. + +**/ +EFI_STATUS +IoMmuAllocateBuffer ( + IN UINTN Pages, + OUT VOID **HostAddress, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + EFI_STATUS Status; + UINTN NumberOfBytes; + EFI_PHYSICAL_ADDRESS HostPhyAddress; + EDKII_IOMMU_PPI *IoMmu; + + *HostAddress = NULL; + *DeviceAddress = 0; + + IoMmu = GetIoMmu (); + + if (IoMmu != NULL) { + Status = IoMmu->AllocateBuffer ( + IoMmu, + EfiBootServicesData, + Pages, + HostAddress, + 0 + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + NumberOfBytes = EFI_PAGES_TO_SIZE(Pages); + Status = IoMmu->Map ( + IoMmu, + EdkiiIoMmuOperationBusMasterCommonBuffer, + *HostAddress, + &NumberOfBytes, + DeviceAddress, + Mapping + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + Status = IoMmu->SetAttribute ( + IoMmu, + *Mapping, + EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE + ); + if (EFI_ERROR (Status)) { + return Status; + } + } else { + // + // for fuzz + // + HostPhyAddress = (UINTN)AllocatePages (Pages); + if (HostPhyAddress == 0) { + return EFI_OUT_OF_RESOURCES; + } + Status = EFI_SUCCESS; + *HostAddress = (VOID *)(UINTN)HostPhyAddress; + *DeviceAddress = HostPhyAddress; + *Mapping = NULL; + } + return Status; +} + +/** + Frees memory that was allocated with AllocateBuffer(). + + @param Pages The number of pages to free. + @param HostAddress The base system memory address of the allocated range. + @param Mapping The mapping value returned from Map(). + + @retval EFI_SUCCESS The requested memory pages were freed. + @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages + was not allocated with AllocateBuffer(). + +**/ +EFI_STATUS +IoMmuFreeBuffer ( + IN UINTN Pages, + IN VOID *HostAddress, + IN VOID *Mapping + ) +{ + EFI_STATUS Status; + EDKII_IOMMU_PPI *IoMmu; + + IoMmu = GetIoMmu (); + + if (IoMmu != NULL) { + Status = IoMmu->SetAttribute (IoMmu, Mapping, 0); + Status = IoMmu->Unmap (IoMmu, Mapping); + Status = IoMmu->FreeBuffer (IoMmu, Pages, HostAddress); + } else { + FreePages (HostAddress, Pages); // for fuzz + Status = EFI_SUCCESS; + } + return Status; +} diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/IoMmu.h b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/IoMmu.h new file mode 100644 index 0000000..34d7f05 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/IoMmu.h @@ -0,0 +1,201 @@ +/** @file + PEI IOMMU PPI. + +Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#ifndef __PEI_IOMMU_H__ +#define __PEI_IOMMU_H__ + +// +// for EFI_ALLOCATE_TYPE +// +#include + +// +// Include protocol for common definition +// EDKII_IOMMU_ACCESS_xxx +// EDKII_IOMMU_OPERATION +// +#include + +// +// IOMMU Ppi GUID value +// +#define EDKII_IOMMU_PPI_GUID \ + { \ + 0x70b0af26, 0xf847, 0x4bb6, { 0xaa, 0xb9, 0xcd, 0xe8, 0x4f, 0xc6, 0x14, 0x31 } \ + } + +// +// Forward reference for pure ANSI compatability +// +typedef struct _EDKII_IOMMU_PPI EDKII_IOMMU_PPI; + +// +// Revision The revision to which the IOMMU interface adheres. +// All future revisions must be backwards compatible. +// If a future version is not back wards compatible it is not the same GUID. +// +#define EDKII_IOMMU_PPI_REVISION 0x00010000 + +/** + Set IOMMU attribute for a system memory. + + If the IOMMU PPI exists, the system memory cannot be used + for DMA by default. + + When a device requests a DMA access for a system memory, + the device driver need use SetAttribute() to update the IOMMU + attribute to request DMA access (read and/or write). + + @param[in] This The PPI instance pointer. + @param[in] Mapping The mapping value returned from Map(). + @param[in] IoMmuAccess The IOMMU access. + + @retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by DeviceAddress and Length. + @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map(). + @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination of access. + @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported by the IOMMU. + @retval EFI_UNSUPPORTED The IOMMU does not support the memory range specified by Mapping. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to modify the IOMMU access. + @retval EFI_DEVICE_ERROR The IOMMU device reported an error while attempting the operation. + @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are + not available to be allocated yet. + +**/ +typedef +EFI_STATUS +(EFIAPI *EDKII_PEI_IOMMU_SET_ATTRIBUTE)( + IN EDKII_IOMMU_PPI *This, + IN VOID *Mapping, + IN UINT64 IoMmuAccess + ); + +/** + Provides the controller-specific addresses required to access system memory from a + DMA bus master. + + @param This The PPI instance pointer. + @param Operation Indicates if the bus master is going to read or write to system memory. + @param HostAddress The system memory address to map to the PCI controller. + @param NumberOfBytes On input the number of bytes to map. On output the number of bytes + that were mapped. + @param DeviceAddress The resulting map address for the bus master PCI controller to use to + access the hosts HostAddress. + @param Mapping A resulting value to pass to Unmap(). + + @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. + @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are + not available to be allocated yet. + +**/ +typedef +EFI_STATUS +(EFIAPI *EDKII_PEI_IOMMU_MAP)( + IN EDKII_IOMMU_PPI *This, + IN EDKII_IOMMU_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ); + +/** + Completes the Map() operation and releases any corresponding resources. + + @param This The PPI instance pointer. + @param Mapping The mapping value returned from Map(). + + @retval EFI_SUCCESS The range was unmapped. + @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map(). + @retval EFI_DEVICE_ERROR The data was not committed to the target system memory. + @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are + not available to be allocated yet. + +**/ +typedef +EFI_STATUS +(EFIAPI *EDKII_PEI_IOMMU_UNMAP)( + IN EDKII_IOMMU_PPI *This, + IN VOID *Mapping + ); + +/** + Allocates pages that are suitable for an OperationBusMasterCommonBuffer or + OperationBusMasterCommonBuffer64 mapping. + + @param This The PPI instance pointer. + @param MemoryType The type of memory to allocate, EfiBootServicesData or + EfiRuntimeServicesData. + @param Pages The number of pages to allocate. + @param HostAddress A pointer to store the base system memory address of the + allocated range. + @param Attributes The requested bit mask of attributes for the allocated range. + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are + MEMORY_WRITE_COMBINE, MEMORY_CACHED and DUAL_ADDRESS_CYCLE. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. + @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are + not available to be allocated yet. + +**/ +typedef +EFI_STATUS +(EFIAPI *EDKII_PEI_IOMMU_ALLOCATE_BUFFER)( + IN EDKII_IOMMU_PPI *This, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN OUT VOID **HostAddress, + IN UINT64 Attributes + ); + +/** + Frees memory that was allocated with AllocateBuffer(). + + @param This The PPI instance pointer. + @param Pages The number of pages to free. + @param HostAddress The base system memory address of the allocated range. + + @retval EFI_SUCCESS The requested memory pages were freed. + @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages + was not allocated with AllocateBuffer(). + @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are + not available to be allocated yet. + +**/ +typedef +EFI_STATUS +(EFIAPI *EDKII_PEI_IOMMU_FREE_BUFFER)( + IN EDKII_IOMMU_PPI *This, + IN UINTN Pages, + IN VOID *HostAddress + ); + +/// +/// IOMMU PPI structure. +/// +struct _EDKII_IOMMU_PPI { + UINT64 Revision; + EDKII_PEI_IOMMU_SET_ATTRIBUTE SetAttribute; + EDKII_PEI_IOMMU_MAP Map; + EDKII_PEI_IOMMU_UNMAP Unmap; + EDKII_PEI_IOMMU_ALLOCATE_BUFFER AllocateBuffer; + EDKII_PEI_IOMMU_FREE_BUFFER FreeBuffer; +}; + +/// +/// IOMMU PPI GUID variable. +/// +extern EFI_GUID gEdkiiIoMmuPpiGuid; + +#endif diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/TestIdentifyAtaDevice.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/TestIdentifyAtaDevice.c new file mode 100644 index 0000000..fa23995 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/TestIdentifyAtaDevice.c @@ -0,0 +1,150 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +#ifdef TEST_WITH_LIBFUZZER +#include +#include +#endif + +#include +#include "AhciPei.h" + +#include +#include +#include +#include + +#include "AhciPei.h" + +#define TOTAL_SIZE (512 * 1024) +VOID FixBuffer( + UINT8 *TestBuffer, + UINTN TestBufferSize) +{ +} + +UINTN +EFIAPI +GetMaxBufferSize( + VOID) +{ + return TOTAL_SIZE; +} + +VOID + EFIAPI + RunTestHarness( + IN VOID *TestBuffer, + IN UINTN TestBufferSize, + PEI_AHCI_ATA_DEVICE_DATA *DeviceDataPtr) +{ + EFI_STATUS Status; + PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private; + ATA_IDENTIFY_DATA *IdentifyData1; + UINTN DeviceIndex; + UINTN DataBufferSize; + VOID *DataBuffer; + UINTN DataTransferSize; + + FixBuffer(TestBuffer, TestBufferSize); + + IdentifyData1 = (ATA_IDENTIFY_DATA *)TestBuffer; + + Private = AllocateZeroPool (sizeof (PEI_AHCI_CONTROLLER_PRIVATE_DATA)); + ASSERT (Private != NULL); + + Private->Signature = AHCI_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE; + Private->PortBitMap = 0x1; + InitializeListHead (&Private->DeviceList); + + Status = AhciCreateTransferDescriptor (Private); + ASSERT_EFI_ERROR (Status); + + Private->AtaPassThruMode.Attributes = EFI_ATA_PASS_THRU_ATTRIBUTES_PHYSICAL | + EFI_ATA_PASS_THRU_ATTRIBUTES_LOGICAL; + Private->AtaPassThruMode.IoAlign = sizeof (UINTN); + Private->AtaPassThruPpi.Revision = EDKII_PEI_ATA_PASS_THRU_PPI_REVISION; + Private->AtaPassThruPpi.Mode = &Private->AtaPassThruMode; + Private->AtaPassThruPpi.PassThru = AhciAtaPassThruPassThru; + Private->AtaPassThruPpi.GetNextPort = AhciAtaPassThruGetNextPort; + Private->AtaPassThruPpi.GetNextDevice = AhciAtaPassThruGetNextDevice; + Private->AtaPassThruPpi.GetDevicePath = AhciAtaPassThruGetDevicePath; + + DeviceIndex = 1; + Status = CreateNewDevice (Private, DeviceIndex, 1, 0xFFFF, 0, IdentifyData1); + if (EFI_ERROR (Status)) { + return; + } + + // + // Test #1 for Storage Security Command PPI, ReceiveData() + // + DataBufferSize = 0x10; + DataBuffer = AllocatePool (DataBufferSize); + ASSERT (DataBuffer != NULL); + AhciStorageSecurityReceiveData ( + &Private->StorageSecurityPpi, + DeviceIndex, + ATA_TIMEOUT, + 0, + 0, + DataBufferSize, + DataBuffer, + &DataTransferSize + ); + + // + // Test #2 for Storage Security Command PPI, SendData() + // + DataBufferSize = 0x10; + AhciStorageSecuritySendData ( + &Private->StorageSecurityPpi, + DeviceIndex, + ATA_TIMEOUT, + 0, + 0, + DataBufferSize, + DataBuffer + ); + FreePool (DataBuffer); + + // + // Test #1 for Block IO PPI, ReadBlocks() - with small DataBufferSize. + // + DataBuffer = AllocatePool (0x200000); + ASSERT (DataBuffer != NULL); + DataBufferSize = 0x800; + AhciBlockIoReadBlocks ( + NULL, + &Private->BlkIoPpi, + DeviceIndex, + 0, + DataBufferSize, + DataBuffer + ); + + // + // Test #2 for Block IO PPI, ReadBlocks() - with large DataBufferSize. + // + DataBufferSize = 0x200000; + AhciBlockIoReadBlocks ( + NULL, + &Private->BlkIoPpi, + DeviceIndex, + 0, + DataBufferSize, + DataBuffer + ); + FreePool (DataBuffer); + + return; +} diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/TestIdentifyAtaDevice.inf b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/TestIdentifyAtaDevice.inf new file mode 100644 index 0000000..79e4583 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/TestIdentifyAtaDevice.inf @@ -0,0 +1,47 @@ +## @file +# Component description file for TestIdentifyAtaDevice module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TestIdentifyAtaDevice + FILE_GUID = CFDACAD0-E720-4F6F-A023-448851EEFB93 + MODULE_TYPE = USER_DEFINED + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + TestIdentifyAtaDevice.c + Override/AhciPei.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + PeiServicesLib + IoLib + DebugLib + TimerLib + LockBoxLib + ToolChainHarnessLib + +[Ppis] + gEdkiiIoMmuPpiGuid ## CONSUMES + +[BuildOptions] + MSFT:*_*_*_CC_FLAGS = /Od /GL- diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Usb/UsbBusDxe/TestUsb.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Usb/UsbBusDxe/TestUsb.c new file mode 100644 index 0000000..43a5399 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Usb/UsbBusDxe/TestUsb.c @@ -0,0 +1,65 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "UsbBus.h" + +#define TOTAL_SIZE (512 * 1024) + +EFI_STATUS +UsbBuildDescTable ( + IN USB_DEVICE *UsbDev + ); + +VOID +FixBuffer ( + UINT8 *TestBuffer + ) +{ +} + +UINTN +EFIAPI +GetMaxBufferSize ( + VOID + ) +{ + return TOTAL_SIZE; +} + +VOID +EFIAPI +RunTestHarness( + IN VOID *TestBuffer, + IN UINTN TestBufferSize + ) +{ + USB_DEVICE UsbDev; + USB_BUS Bus; + EFI_USB2_HC_PROTOCOL *Usb2Hc; + + Usb2HcStubInitialize (NULL, 0, TestBuffer, TestBufferSize, NULL, 0, &Usb2Hc); + + UsbDev.Bus = &Bus; + Bus.Usb2Hc = Usb2Hc; + + UsbBuildDescTable (&UsbDev); +} + + diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Usb/UsbBusDxe/TestUsb.inf b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Usb/UsbBusDxe/TestUsb.inf new file mode 100644 index 0000000..babc101 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Usb/UsbBusDxe/TestUsb.inf @@ -0,0 +1,38 @@ +## @file +# Component description file for TestUsb module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TestUsb + FILE_GUID = CFDACAD0-E720-4F6F-A023-448851EEFB93 + MODULE_TYPE = USER_DEFINED + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + TestUsb.c + MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h + +[Packages] + MdePkg/MdePkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib + UefiBootServicesTableLib + Usb2HcStubLib + ToolChainHarnessLib diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Usb/UsbBusPei/TestPeiUsb.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Usb/UsbBusPei/TestPeiUsb.c new file mode 100644 index 0000000..681c9c9 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Usb/UsbBusPei/TestPeiUsb.c @@ -0,0 +1,77 @@ +/** @file + +Copyright (c) 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 "UsbPeim.h" +#include "HubPeim.h" +#include "PeiUsbLib.h" + +#define TOTAL_SIZE (512 * 1024) + +UINT32 +GetUsbTransferTimeoutValue ( + VOID + ) +{ + return 1; +} + +EFI_STATUS +PeiUsbGetAllConfiguration ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_USB_DEVICE *PeiUsbDevice + ); + +VOID +FixBuffer ( + UINT8 *TestBuffer + ) +{ +} + +UINTN +EFIAPI +GetMaxBufferSize ( + VOID + ) +{ + return TOTAL_SIZE; +} + +VOID +EFIAPI +RunTestHarness( + IN VOID *TestBuffer, + IN UINTN TestBufferSize + ) +{ + PEI_USB_DEVICE PeiUsbDevice; + PEI_USB_IO_PPI *UsbIoPpi; + + ZeroMem(&PeiUsbDevice, sizeof(PeiUsbDevice)); + + UsbIoPpiStubInitialize(NULL, 0, TestBuffer, TestBufferSize, NULL, 0, &UsbIoPpi); + + CopyMem(&PeiUsbDevice.UsbIoPpi, UsbIoPpi, sizeof(*UsbIoPpi)); + + PeiUsbGetAllConfiguration(NULL, &PeiUsbDevice); +} + + diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Usb/UsbBusPei/TestPeiUsb.inf b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Usb/UsbBusPei/TestPeiUsb.inf new file mode 100644 index 0000000..d613151 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Usb/UsbBusPei/TestPeiUsb.inf @@ -0,0 +1,39 @@ +## @file +# Component description file for TestPeiUsb module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TestPeiUsb + FILE_GUID = E47055D6-D042-4846-83AE-A7AE8AA5D581 + MODULE_TYPE = USER_DEFINED + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + TestPeiUsb.c + MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib + TimerLib + UsbIoPpiStubLib + ToolChainHarnessLib diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library/BaseBmpSupportLib/TestBmpSupportLib.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library/BaseBmpSupportLib/TestBmpSupportLib.c new file mode 100644 index 0000000..f8756a9 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library/BaseBmpSupportLib/TestBmpSupportLib.c @@ -0,0 +1,67 @@ +/** @file + +Copyright (c) 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 +#include + +#define TOTAL_SIZE (1 * 1024) + +VOID +FixBuffer ( + UINT8 *TestBuffer + ) +{ +} + +UINTN +EFIAPI +GetMaxBufferSize ( + VOID + ) +{ + return TOTAL_SIZE; +} + +VOID +EFIAPI +RunTestHarness( + IN VOID *TestBuffer, + IN UINTN TestBufferSize + ) +{ + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *GopBlt; + UINTN GopBltSize; + UINTN PixelHeight; + UINTN PixelWidth; + FixBuffer (TestBuffer); + GopBlt = NULL; + TranslateBmpToGopBlt( + TestBuffer, + TestBufferSize, + &GopBlt, + &GopBltSize, + &PixelHeight, + &PixelWidth + ); + if (GopBlt != NULL) + FreePool (GopBlt); +} diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library/BaseBmpSupportLib/TestBmpSupportLib.inf b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library/BaseBmpSupportLib/TestBmpSupportLib.inf new file mode 100644 index 0000000..7286f83 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library/BaseBmpSupportLib/TestBmpSupportLib.inf @@ -0,0 +1,38 @@ +## @file +# Component description file for TestBmpSupportLib module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TestBmpSupportLib + FILE_GUID = E911AB26-4741-4621-93EF-305FEA98A851 + MODULE_TYPE = USER_DEFINED + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + TestBmpSupportLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib + SafeIntLib + BmpSupportLib + ToolChainHarnessLib diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/CapsulePei/Common/TestCapsulePei.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/CapsulePei/Common/TestCapsulePei.c new file mode 100644 index 0000000..24a85d0 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/CapsulePei/Common/TestCapsulePei.c @@ -0,0 +1,84 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include "CommonHeader.h" + +#define TOTAL_SIZE (512 * 1024) + +EFI_STATUS +EFIAPI +CapsuleDataCoalesce ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS *BlockListBuffer, + IN MEMORY_RESOURCE_DESCRIPTOR *MemoryResource, + IN OUT VOID **MemoryBase, + IN OUT UINTN *MemorySize + ); + +VOID +FixBuffer ( + UINT8 *TestBuffer, + UINTN TestBufferSize + ) +{ + ((EFI_CAPSULE_HEADER *)TestBuffer)->CapsuleImageSize = (UINT32)TestBufferSize; +} + +UINTN +EFIAPI +GetMaxBufferSize ( + VOID + ) +{ + return TOTAL_SIZE; +} + +VOID +EFIAPI +RunTestHarness( + IN VOID *TestBuffer, + IN UINTN TestBufferSize + ) +{ + MEMORY_RESOURCE_DESCRIPTOR MemoryResource[3]; + VOID *MemoryBase; + UINTN MemorySize; + VOID *CapsuleMemoryBase; + UINTN CapsuleMemorySize; + + MemorySize = TOTAL_SIZE; + MemoryBase = AllocatePool (MemorySize); + + MemoryResource[0].PhysicalStart = (UINT64)(UINTN)TestBuffer; + MemoryResource[0].ResourceLength = (UINT64)(UINTN)TOTAL_SIZE; + MemoryResource[1].PhysicalStart = (UINT64)(UINTN)MemoryBase; + MemoryResource[1].ResourceLength = (UINT64)(UINTN)MemorySize; + MemoryResource[2].PhysicalStart = 0; + MemoryResource[2].ResourceLength = 0; + + FixBuffer (TestBuffer, TestBufferSize); + + CapsuleMemoryBase = MemoryBase; + CapsuleMemorySize = MemorySize; + CapsuleDataCoalesce(NULL, TestBuffer, MemoryResource, &CapsuleMemoryBase, &CapsuleMemorySize); + + FreePool (MemoryBase); +} + diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/CapsulePei/Common/TestCapsulePei.inf b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/CapsulePei/Common/TestCapsulePei.inf new file mode 100644 index 0000000..fecdc1f --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/CapsulePei/Common/TestCapsulePei.inf @@ -0,0 +1,36 @@ +## @file +# Component description file for TestDxeCapsulePei module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TestCapsulePei + FILE_GUID = 23C9CE4E-26BB-4850-A3E2-5AEA95963F87 + MODULE_TYPE = USER_DEFINED + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + TestCapsulePei.c + MdeModulePkg/Universal/CapsulePei/Common/CommonHeader.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib + ToolChainHarnessLib diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/PartitionDxe/InstrumentHookLibTestPartition/CreateErrorInjectionProfile.py b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/PartitionDxe/InstrumentHookLibTestPartition/CreateErrorInjectionProfile.py new file mode 100644 index 0000000..827b14a --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/PartitionDxe/InstrumentHookLibTestPartition/CreateErrorInjectionProfile.py @@ -0,0 +1,81 @@ +# @file +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +import os +import shutil +import sys +try: + import ConfigParser as ConfigParser +except Exception as e: + print("Import for ConfigParser not found, attempting configparser: " + "%s" % e) + import configparser as ConfigParser +import argparse + +Case_Path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'Case') + + +class myconf(ConfigParser.RawConfigParser): + def __init__(self, defaults=None): + ConfigParser.RawConfigParser.__init__(self, defaults=None) + + def optionxform(self, optionstr): + return optionstr + + +class errorInjection(): + def __init__(self, Num): + self.CallErrorCountNum = int(Num) + + def run(self): + if os.path.exists(Case_Path): + shutil.rmtree(Case_Path) + os.makedirs(Case_Path) + else: + os.makedirs(Case_Path) + Case_Count_Num = 1 + for CountNum in range(1, self.CallErrorCountNum + 1): + print('#######################################') + print('Current CallErrorCountNum: {}'.format(CountNum)) + print('#######################################') + for count in range(3): + CaseName = 'test_' + str(Case_Count_Num) + '.ini' + self.create_tcs(os.path.join(Case_Path, CaseName), + CountNum, count) + Case_Count_Num = Case_Count_Num + 1 + + def create_tcs(self, tcs_file, num, count): + conf = myconf() + if count == 0: + conf.add_section('AllocateZeroPool') + conf.set('AllocateZeroPool', 'CallErrorCount', num) + conf.set('AllocateZeroPool', 'ReturnValue', 0) + elif count == 1: + conf.add_section('ReadBlocks') + conf.set('ReadBlocks', 'CallErrorCount', num) + conf.set('ReadBlocks', 'ReturnValue', 'EFI_DEVICE_ERROR') + elif count == 2: + conf.add_section('ReadDisk') + conf.set('ReadDisk', 'CallErrorCount', num) + conf.set('ReadDisk', 'ReturnValue', 'EFI_DEVICE_ERROR') + else: + pass + + with open(tcs_file, 'w') as f: + conf.write(f) + + +if __name__ == '__main__': + # # # Opt Parser + parse = argparse.ArgumentParser() + parse.add_argument("-c", dest="CallErrorCountNum", + help="CallErrorCount number,if CallErrorCount = N," + "script will try CallErrorCount = 1 ~ CallErrorCount " + "= N", default=None) + + options = parse.parse_args(sys.argv[1:]) + test = errorInjection(options.CallErrorCountNum) + test.run() diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/PartitionDxe/InstrumentHookLibTestPartition/InstrumentHookLibTestPartition.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/PartitionDxe/InstrumentHookLibTestPartition/InstrumentHookLibTestPartition.c new file mode 100644 index 0000000..4393845 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/PartitionDxe/InstrumentHookLibTestPartition/InstrumentHookLibTestPartition.c @@ -0,0 +1,245 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +typedef struct _FUNC_HOOK FUNC_HOOK; + +typedef +UINTN +(EFIAPI *HOOK_FUNC_ENTER) ( + IN FUNC_HOOK *FuncHook, + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ); + +typedef +VOID +(EFIAPI *HOOK_FUNC_EXIT) ( + IN FUNC_HOOK *FuncHook, + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ); + +struct _FUNC_HOOK { + CHAR8 *Name; + UINTN Func; + UINTN HookFuncEnter; + UINTN HookFuncExit; + UINTN CallErrorCount; + UINTN ReturnValue; + UINTN CurrentCallCount; +} ; + +EFI_STATUS +EFIAPI +ReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +EFI_STATUS +EFIAPI +WriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +EFI_STATUS +EFIAPI +ReadDisk ( + IN EFI_DISK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN UINT64 Offset, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +EFI_STATUS +EFIAPI +WriteDisk ( + IN EFI_DISK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN UINT64 Offset, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +BOOLEAN mInitDone; + +UINTN +EFIAPI +CommonEnter ( + IN FUNC_HOOK *FuncHook, + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + FuncHook->CurrentCallCount++; + if (FuncHook->CurrentCallCount == FuncHook->CallErrorCount) { + //SetSkipReturnValue (EntryContext, FuncHook->ReturnValue); + if (FuncHook->Func == (UINTN)AllocateZeroPool) { + SetParameterValue (EntryContext, 1, (UINTN)-1); + } else if (FuncHook->Func == (UINTN)ReadBlocks) { + SetParameterValue64 (EntryContext, 3, (UINT64)-1); + } else if (FuncHook->Func == (UINTN)ReadDisk) { + SetParameterValue64 (EntryContext, 3, (UINT64)-1); + } + return 1; + } + return 0; +} + +VOID +EFIAPI +CommonExit ( + IN FUNC_HOOK *FuncHook, + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + if (FuncHook->CurrentCallCount == FuncHook->CallErrorCount) { + SetReturnValue (ExitContext, FuncHook->ReturnValue); + } + return ; +} + +GLOBAL_REMOVE_IF_UNREFERENCED FUNC_HOOK mFuncHook[] = { + {"AllocateZeroPool", (UINTN)AllocateZeroPool, (UINTN)CommonEnter, (UINTN)CommonExit}, + {"ReadBlocks", (UINTN)ReadBlocks, (UINTN)CommonEnter, (UINTN)CommonExit}, + {"ReadDisk", (UINTN)ReadDisk, (UINTN)CommonEnter, (UINTN)CommonExit}, +}; + +FUNC_HOOK * +GetFuncHook ( + IN UINTN FuncAddr + ) +{ + UINTN Index; + for (Index = 0; Index < ARRAY_SIZE(mFuncHook); Index++) { + if (FuncAddr == mFuncHook[Index].Func) { + return &mFuncHook[Index]; + } + } + return NULL; +} + +UINTN +EFIAPI +FunctionEnter ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + FUNC_HOOK *FuncHook; + HOOK_FUNC_ENTER HookFunc; + + if (!mInitDone) { + return 0; + } + + FuncHook = GetFuncHook (FunctionAddress); + if (FuncHook == NULL) { + return 0; + } + if (FuncHook->HookFuncEnter == 0) { + return 0; + } + HookFunc = (HOOK_FUNC_ENTER)(FuncHook->HookFuncEnter); + return HookFunc (FuncHook, EntryContext, FunctionAddress, CallerAddress); +} + +VOID +EFIAPI +FunctionExit ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + FUNC_HOOK *FuncHook; + HOOK_FUNC_EXIT HookFunc; + + if (!mInitDone) { + return ; + } + + FuncHook = GetFuncHook (FunctionAddress); + if (FuncHook == NULL) { + return ; + } + if (FuncHook->HookFuncExit == 0) { + return ; + } + HookFunc = (HOOK_FUNC_EXIT)(FuncHook->HookFuncExit); + HookFunc (FuncHook, ExitContext, FunctionAddress, CallerAddress); +} + +VOID +EFIAPI +InstrumentHookLibInit ( + IN UINT8 *DataBuffer, + IN UINTN BufferSize + ) +{ + VOID *Context; + UINTN Index; + EFI_STATUS Status; + + Context = OpenIniFile (DataBuffer, BufferSize); + + for (Index = 0; Index < ARRAY_SIZE(mFuncHook); Index++) { + Status = GetDecimalUintnFromDataFile ( + Context, + mFuncHook[Index].Name, + "CallErrorCount", + &mFuncHook[Index].CallErrorCount + ); + if (EFI_ERROR(Status)) { + continue ; + } + + Status = GetEfiStatusFromDataFile ( + Context, + mFuncHook[Index].Name, + "ReturnValue", + &mFuncHook[Index].ReturnValue + ); + if (EFI_ERROR(Status)) { + Status = GetHexUintnFromDataFile ( + Context, + mFuncHook[Index].Name, + "ReturnValue", + &mFuncHook[Index].ReturnValue + ); + } + } + + CloseIniFile (Context); + + mInitDone = TRUE; +} \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/PartitionDxe/InstrumentHookLibTestPartition/InstrumentHookLibTestPartition.inf b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/PartitionDxe/InstrumentHookLibTestPartition/InstrumentHookLibTestPartition.inf new file mode 100644 index 0000000..14940c2 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/PartitionDxe/InstrumentHookLibTestPartition/InstrumentHookLibTestPartition.inf @@ -0,0 +1,40 @@ +## @file +# Component description file for TestUdf module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = InstrumentHookLibTestPartition + FILE_GUID = B61898FA-92D7-47D9-8751-6E4F82F55B7F + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = InstrumentHookLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + InstrumentHookLibTestPartition.c + +[Packages] + MdePkg/MdePkg.dec + UefiInstrumentTestPkg/UefiInstrumentTestPkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib + IniParsingLib + +[BuildOptions] + MSFT:*_*_*_CC_FLAGS = /Od /GL- + GCC:*_*_*_CC_FLAGS = -O0 diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/PartitionDxe/TestPartition.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/PartitionDxe/TestPartition.c new file mode 100644 index 0000000..0d52983 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/PartitionDxe/TestPartition.c @@ -0,0 +1,85 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#define MAX_CORRECTION_BLOCKS_NUM 512u + +#include +#include +#include +#include +#include + +EFI_STATUS +FindUdfFileSystem ( + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + OUT EFI_LBA *StartingLBA, + OUT EFI_LBA *EndingLBA + ); + +#define TOTAL_SIZE (512 * 1024) +#define BLOCK_SIZE (512) +#define IO_ALIGN (1) + +VOID +FixBuffer ( + UINT8 *TestBuffer + ) +{ +} +UINTN +EFIAPI +GetMaxBufferSize ( + VOID + ) +{ + return TOTAL_SIZE; +} + +VOID +EFIAPI +RunTestHarness( + IN VOID *TestBuffer, + IN UINTN TestBufferSize + ) +{ + EFI_LBA StartingLBA; + EFI_LBA EndingLBA; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_DISK_IO_PROTOCOL *DiskIo; + + FixBuffer (TestBuffer); + + DiskStubInitialize (TestBuffer, TestBufferSize, BLOCK_SIZE, IO_ALIGN, &BlockIo, &DiskIo); + + // fuzz function: + // buffer overflow, crash will be detected at place. + // only care about security, not for function bug. + // + // try to separate EFI lib, use stdlib function. + // no asm code. + FindUdfFileSystem ( + BlockIo, + DiskIo, + &StartingLBA, + &EndingLBA + ); + + DiskStubDestory(); +} diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/PartitionDxe/TestPartition.inf b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/PartitionDxe/TestPartition.inf new file mode 100644 index 0000000..f86365f --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/PartitionDxe/TestPartition.inf @@ -0,0 +1,36 @@ +## @file +# Component description file for TestPartition module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TestPartition + FILE_GUID = 9420FB50-57EC-4609-92B3-A57589037933 + MODULE_TYPE = USER_DEFINED + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + TestPartition.c + +[Packages] + MdePkg/MdePkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib + DiskStubLib + ToolChainHarnessLib diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/InstrumentHookLibTestUdf/CreateErrorInjectionProfile.py b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/InstrumentHookLibTestUdf/CreateErrorInjectionProfile.py new file mode 100644 index 0000000..b0ed609 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/InstrumentHookLibTestUdf/CreateErrorInjectionProfile.py @@ -0,0 +1,82 @@ +# @file +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +import os +import sys +import shutil +try: + import ConfigParser as ConfigParser +except Exception as e: + print("Import for ConfigParser not found, attempting configparser: " + "%s" % e) + import configparser as ConfigParser +import argparse + +Case_Path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'Case') + + +class myconf(ConfigParser.RawConfigParser): + def __init__(self, defaults=None): + ConfigParser.RawConfigParser.__init__(self, defaults=None) + + def optionxform(self, optionstr): + return optionstr + + +class errorInjection(): + def __init__(self, Num): + self.CallErrorCountNum = int(Num) + + def run(self): + if os.path.exists(Case_Path): + shutil.rmtree(Case_Path) + os.makedirs(Case_Path) + else: + os.makedirs(Case_Path) + Case_Count_Num = 1 + for CountNum in range(1, self.CallErrorCountNum + 1): + print('#######################################') + print('Current CallErrorCountNum: {}'.format(CountNum)) + print('#######################################') + for count in range(3): + CaseName = 'test_' + str(Case_Count_Num) + '.ini' + self.create_tcs(os.path.join(Case_Path, CaseName), CountNum, + count) + Case_Count_Num = Case_Count_Num + 1 + + def create_tcs(self, tcs_file, num, count): + conf = myconf() + if count == 0: + conf.add_section('AllocateZeroPool') + conf.set('AllocateZeroPool', 'CallErrorCount', num) + conf.set('AllocateZeroPool', 'ReturnValue', 0) + elif count == 1: + conf.add_section('ReallocatePool') + conf.set('ReallocatePool', 'CallErrorCount', num) + conf.set('ReallocatePool', 'ReturnValue', 0) + elif count == 2: + conf.add_section('AllocatePool') + conf.set('AllocatePool', 'CallErrorCount', num) + conf.set('AllocatePool', 'ReturnValue', 0) + else: + pass + + with open(tcs_file, 'w') as f: + conf.write(f) + + +if __name__ == '__main__': + # # # Opt Parser + parse = argparse.ArgumentParser() + parse.add_argument("-c", dest="CallErrorCountNum", + help="CallErrorCount number,if CallErrorCount = N," + " script will try " + "CallErrorCount = 1 ~ CallErrorCount = N", + default=None) + + options = parse.parse_args(sys.argv[1:]) + test = errorInjection(options.CallErrorCountNum) + test.run() diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/InstrumentHookLibTestUdf/InstrumentHookLibTestUdf.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/InstrumentHookLibTestUdf/InstrumentHookLibTestUdf.c new file mode 100644 index 0000000..431e2b8 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/InstrumentHookLibTestUdf/InstrumentHookLibTestUdf.c @@ -0,0 +1,206 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "../Udf.h" + +typedef struct _FUNC_HOOK FUNC_HOOK; + +typedef +UINTN +(EFIAPI *HOOK_FUNC_ENTER) ( + IN FUNC_HOOK *FuncHook, + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ); + +typedef +VOID +(EFIAPI *HOOK_FUNC_EXIT) ( + IN FUNC_HOOK *FuncHook, + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ); + +struct _FUNC_HOOK { + CHAR8 *Name; + UINTN Func; + UINTN HookFuncEnter; + UINTN HookFuncExit; + UINTN CallErrorCount; + UINTN ReturnValue; + UINTN CurrentCallCount; +} ; + +BOOLEAN mInitDone; + +UINTN +EFIAPI +CommonEnter ( + IN FUNC_HOOK *FuncHook, + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + FuncHook->CurrentCallCount++; + if (FuncHook->CurrentCallCount == FuncHook->CallErrorCount) { + //SetSkipReturnValue (EntryContext, FuncHook->ReturnValue); + if (FuncHook->Func == (UINTN)AllocateZeroPool) { + SetParameterValue (EntryContext, 1, (UINTN)-1); + } else if (FuncHook->Func == (UINTN)AllocatePool) { + SetParameterValue (EntryContext, 1, (UINTN)-1); + } else if (FuncHook->Func == (UINTN)ReallocatePool) { + SetParameterValue (EntryContext, 1, (UINTN)-1); + } + return 1; + } + return 0; +} + +VOID +EFIAPI +CommonExit ( + IN FUNC_HOOK *FuncHook, + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + if (FuncHook->CurrentCallCount == FuncHook->CallErrorCount) { + SetReturnValue (ExitContext, FuncHook->ReturnValue); + } + return ; +} + +GLOBAL_REMOVE_IF_UNREFERENCED FUNC_HOOK mFuncHook[] = { + {"AllocateZeroPool", (UINTN)AllocateZeroPool, (UINTN)CommonEnter, (UINTN)CommonExit}, + {"AllocatePool", (UINTN)AllocatePool, (UINTN)CommonEnter, (UINTN)CommonExit}, + {"ReallocatePool", (UINTN)ReallocatePool, (UINTN)CommonEnter, (UINTN)CommonExit}, +}; + +FUNC_HOOK * +GetFuncHook ( + IN UINTN FuncAddr + ) +{ + UINTN Index; + for (Index = 0; Index < ARRAY_SIZE(mFuncHook); Index++) { + if (FuncAddr == mFuncHook[Index].Func) { + return &mFuncHook[Index]; + } + } + return NULL; +} + +UINTN +EFIAPI +FunctionEnter ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + FUNC_HOOK *FuncHook; + HOOK_FUNC_ENTER HookFunc; + + if (!mInitDone) { + return 0; + } + + FuncHook = GetFuncHook (FunctionAddress); + if (FuncHook == NULL) { + return 0; + } + if (FuncHook->HookFuncEnter == 0) { + return 0; + } + HookFunc = (HOOK_FUNC_ENTER)(FuncHook->HookFuncEnter); + return HookFunc (FuncHook, EntryContext, FunctionAddress, CallerAddress); +} + +VOID +EFIAPI +FunctionExit ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + FUNC_HOOK *FuncHook; + HOOK_FUNC_EXIT HookFunc; + + if (!mInitDone) { + return ; + } + + FuncHook = GetFuncHook (FunctionAddress); + if (FuncHook == NULL) { + return ; + } + if (FuncHook->HookFuncExit == 0) { + return ; + } + HookFunc = (HOOK_FUNC_EXIT)(FuncHook->HookFuncExit); + HookFunc (FuncHook, ExitContext, FunctionAddress, CallerAddress); +} + +VOID +EFIAPI +InstrumentHookLibInit ( + IN UINT8 *DataBuffer, + IN UINTN BufferSize + ) +{ + VOID *Context; + UINTN Index; + EFI_STATUS Status; + + Context = OpenIniFile (DataBuffer, BufferSize); + + for (Index = 0; Index < ARRAY_SIZE(mFuncHook); Index++) { + Status = GetDecimalUintnFromDataFile ( + Context, + mFuncHook[Index].Name, + "CallErrorCount", + &mFuncHook[Index].CallErrorCount + ); + if (EFI_ERROR(Status)) { + continue ; + } + + Status = GetEfiStatusFromDataFile ( + Context, + mFuncHook[Index].Name, + "ReturnValue", + &mFuncHook[Index].ReturnValue + ); + if (EFI_ERROR(Status)) { + Status = GetHexUintnFromDataFile ( + Context, + mFuncHook[Index].Name, + "ReturnValue", + &mFuncHook[Index].ReturnValue + ); + } + } + + CloseIniFile (Context); + + mInitDone = TRUE; +} \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/InstrumentHookLibTestUdf/InstrumentHookLibTestUdf.inf b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/InstrumentHookLibTestUdf/InstrumentHookLibTestUdf.inf new file mode 100644 index 0000000..519530f --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/InstrumentHookLibTestUdf/InstrumentHookLibTestUdf.inf @@ -0,0 +1,40 @@ +## @file +# Component description file for TestUdf module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = InstrumentHookLibTestUdf + FILE_GUID = F9BE464E-3E19-4BE9-B6F1-D560A0031CAD + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = InstrumentHookLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + InstrumentHookLibTestUdf.c + +[Packages] + MdePkg/MdePkg.dec + UefiInstrumentTestPkg/UefiInstrumentTestPkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib + IniParsingLib + +[BuildOptions] + MSFT:*_*_*_CC_FLAGS = /Od /GL- + GCC:*_*_*_CC_FLAGS = -O0 diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/TestFileName.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/TestFileName.c new file mode 100644 index 0000000..a19b2e4 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/TestFileName.c @@ -0,0 +1,43 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define MAX_FILENAME_LEN 4096 + +CHAR16 * +MangleFileName ( + IN CHAR16 *FileName + ); + +UINTN +EFIAPI +GetMaxBufferSize ( + VOID + ) +{ + return MAX_FILENAME_LEN; +} + +VOID +EFIAPI +RunTestHarness( + IN VOID *TestBuffer, + IN UINTN TestBufferSize + ) +{ + MangleFileName((CHAR16*)TestBuffer); +} diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/TestFileName.inf b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/TestFileName.inf new file mode 100644 index 0000000..756dc10 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/TestFileName.inf @@ -0,0 +1,35 @@ +## @file +# Component description file for TestUdf module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TestFileName + FILE_GUID = 451C64D2-84B4-4DC1-BBE7-BBA46603C16B + MODULE_TYPE = USER_DEFINED + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + TestFileName.c + +[Packages] + MdePkg/MdePkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib + UefiBootServicesTableLib + ToolChainHarnessLib diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/TestUdf.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/TestUdf.c new file mode 100644 index 0000000..e747877 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/TestUdf.c @@ -0,0 +1,512 @@ +/** @file + +Copyright (c) 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 "Udf.h" + +extern EFI_SIMPLE_FILE_SYSTEM_PROTOCOL gUdfSimpleFsTemplate; + +EFI_STATUS +FindUdfFileSystem ( + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + OUT EFI_LBA *StartingLBA, + OUT EFI_LBA *EndingLBA + ); + +#define TOTAL_SIZE (1 * 1024 * 1024) +#define BLOCK_SIZE (1024) +#define IO_ALIGN (1) +#define MAX_FILENAME_LEN (4096) + +VOID +FixBuffer ( + UINT8 *TestBuffer + ) +{ +} + +PRIVATE_UDF_SIMPLE_FS_DATA *PrivFsData = NULL; + +EFI_FILE_PROTOCOL * +TestSimpleFileSystem ( + EFI_BLOCK_IO_PROTOCOL *PartitionBlockIo, + EFI_DISK_IO_PROTOCOL *PartitionDiskIo, + UINT8 *TestBuffer + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs; + EFI_FILE_PROTOCOL *Root; + + + PrivFsData->Signature = PRIVATE_UDF_SIMPLE_FS_DATA_SIGNATURE; + PrivFsData->BlockIo = PartitionBlockIo; + PrivFsData->DiskIo = PartitionDiskIo; + // + // Set up SimpleFs protocol + // + CopyMem ((VOID *)&PrivFsData->SimpleFs, (VOID *)&gUdfSimpleFsTemplate, sizeof (EFI_SIMPLE_FILE_SYSTEM_PROTOCOL)); + + SimpleFs = &PrivFsData->SimpleFs; + + // Test SimpleFs == NULL or &Root == NULL + Status = SimpleFs->OpenVolume ( + NULL, + &Root + ); + ASSERT (EFI_ERROR(Status)); + Status = SimpleFs->OpenVolume ( + SimpleFs, + NULL + ); + ASSERT (EFI_ERROR(Status)); + + // Test normal situation + Status = SimpleFs->OpenVolume ( + SimpleFs, + &Root + ); + if (!EFI_ERROR(Status)) { + ASSERT (Root != NULL); + return Root; + } else { + return NULL; + } +} + +VOID +TestFile ( + EFI_FILE_PROTOCOL *Root, + CHAR16 *FileName + ) +{ + EFI_STATUS Status; + EFI_FILE_HANDLE FileHandle; + UINTN BufferSize; + UINTN FileBufferSize; + UINT64 SourceFileSize; + EFI_FILE_INFO *FileInfo = NULL; + VOID *Buffer = NULL; + + FileHandle = NULL; + Status = Root->Open (Root, &FileHandle, FileName, EFI_FILE_MODE_CREATE, 0); + if (EFI_ERROR(Status)) { + Status = Root->Open (Root, &FileHandle, FileName, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(Status)) { + goto Done; + } + } + ASSERT (FileHandle != NULL); + + // + // Test UdfSetPosition + // + Status = FileHandle->SetPosition (FileHandle, (UINT64) -1); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Test UdfGetPosition + // + // Test FileHandle == NULL or &SourceFileSize == NULL + Status = FileHandle->GetPosition (NULL, &SourceFileSize); + ASSERT(EFI_ERROR(Status)); + + Status = FileHandle->GetPosition (FileHandle, NULL); + ASSERT(EFI_ERROR(Status)); + + // Test normal situation + Status = FileHandle->GetPosition (FileHandle, &SourceFileSize); + if (EFI_ERROR (Status)) { + goto Done; + } + ASSERT (SourceFileSize <= MAX_UINTN); + + + // + // Test UdfSetPosition + // + // Test FileHandle == NULL + Status = FileHandle->SetPosition (NULL, 0); + ASSERT(EFI_ERROR(Status)); + + // Test normal situation + Status = FileHandle->SetPosition (FileHandle, 0); + if (EFI_ERROR (Status)) { + goto Done; + } + + + // + // Test UdfRead + // + // Test FileHandle == NULL or &BufferSize == NULL + BufferSize = (UINTN) SourceFileSize; + Buffer = AllocateZeroPool(BufferSize); + if (Buffer == NULL) { + goto Done; + } + + BufferSize = (UINTN) SourceFileSize; + + Status = FileHandle->Read (NULL, &BufferSize, Buffer); + ASSERT(EFI_ERROR(Status)); + Status = FileHandle->Read (FileHandle, NULL, Buffer); + ASSERT(EFI_ERROR(Status)); + + // Test Position > FileSize + Status = FileHandle->SetPosition (FileHandle, SourceFileSize + 1); + if (EFI_ERROR (Status)) { + goto Done; + } + Status = FileHandle->Read (FileHandle, &BufferSize, Buffer); + ASSERT(EFI_ERROR(Status)); + + // Test normal situation + Status = FileHandle->SetPosition (FileHandle, 0); + if (EFI_ERROR (Status)) { + goto Done; + } + Status = FileHandle->Read (FileHandle, &BufferSize, Buffer); + if (EFI_ERROR (Status) || BufferSize != (UINTN) SourceFileSize) { + goto Done; + } + + + // + // Test UdfGetInfo + // + // Test FileHandle == NULL or InfomationType == NULL or FileBufferSize == NULL + FileBufferSize = sizeof(EFI_FILE_INFO) + sizeof(CHAR16) * 1024; + FileInfo = AllocateZeroPool(FileBufferSize); + if (FileInfo == NULL) { + goto Done; + } + + Status = FileHandle->GetInfo (NULL, &gEfiFileSystemInfoGuid, &FileBufferSize, FileInfo); + ASSERT(EFI_ERROR(Status)); + + Status = FileHandle->GetInfo (FileHandle, NULL, &FileBufferSize, FileInfo); + ASSERT(EFI_ERROR(Status)); + + Status = FileHandle->GetInfo (FileHandle, &gEfiFileSystemInfoGuid, NULL, FileInfo); + ASSERT(EFI_ERROR(Status)); + + // Test normal situation + Status = FileHandle->GetInfo (FileHandle, &gEfiFileSystemInfoGuid, &FileBufferSize, FileInfo); + if (EFI_ERROR (Status)) { + goto Done; + } + + Status = FileHandle->GetInfo (FileHandle, &gEfiFileSystemVolumeLabelInfoIdGuid, &FileBufferSize, FileInfo); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Test UdfWrite + // + Status = FileHandle->Write (FileHandle, &FileBufferSize, FileInfo); + ASSERT(EFI_ERROR (Status)); + + + // + // Test SetInfo + // + Status = FileHandle-> SetInfo (FileHandle, &gEfiFileSystemInfoGuid, FileBufferSize, FileInfo); + ASSERT(EFI_ERROR (Status)); + +Done: + if (FileHandle != NULL) { + Status = FileHandle->Close (NULL); + Status = FileHandle->Close (FileHandle); + } + + if (Buffer != NULL) { + FreePool(Buffer); + Buffer = NULL; + } + + if (FileInfo != NULL) { + FreePool(FileInfo); + FileInfo = NULL; + } + return ; +} + +VOID +TestDetele ( + EFI_FILE_PROTOCOL *Root, + CHAR16 *FileName + ) +{ + EFI_STATUS Status; + EFI_FILE_HANDLE FileHandle; + + FileHandle = NULL; + Status = Root->Open (Root, &FileHandle, FileName, EFI_FILE_MODE_CREATE, 0); + if (EFI_ERROR(Status)) { + Status = Root->Open (Root, &FileHandle, FileName, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(Status)) { + goto Done; + } + } + ASSERT (FileHandle != NULL); + + Status = FileHandle->Delete (NULL); + Status = FileHandle->Delete (FileHandle); + if (EFI_ERROR (Status)) { + goto Done; + } + +Done: + return ; +} + +VOID +TestFlush ( + EFI_FILE_PROTOCOL *Root, + CHAR16 *FileName + ) +{ + EFI_STATUS Status; + EFI_FILE_HANDLE FileHandle; + + FileHandle = NULL; + Status = Root->Open (Root, &FileHandle, FileName, EFI_FILE_MODE_CREATE, 0); + if (EFI_ERROR(Status)) { + Status = Root->Open (Root, &FileHandle, FileName, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(Status)) { + goto Done; + } + } + ASSERT (FileHandle != NULL); + + Status = FileHandle->Flush (FileHandle); + ASSERT(EFI_ERROR (Status)); + +Done: + if (FileHandle != NULL) { + Status = FileHandle->Close (FileHandle); + } + return ; +} + +VOID +TestDir ( + EFI_FILE_PROTOCOL *Root, + CHAR16 *FileName + ) +{ + EFI_STATUS Status; + EFI_FILE_HANDLE FileHandle; + UINTN DirBufferSize; + UINTN FileBufferSize; + EFI_FILE_INFO *DirInfo = NULL; + EFI_FILE_INFO *FileInfo = NULL; + UINT64 SourceFileSize; + + FileHandle = NULL; + Status = Root->Open (Root, &FileHandle, FileName, EFI_FILE_MODE_CREATE, 0); + if (EFI_ERROR(Status)) { + Status = Root->Open (Root, &FileHandle, FileName, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(Status)) { + goto Done ; + } + } + ASSERT (FileHandle != NULL); + + // + // Test UdfRead + // + FileBufferSize = sizeof(EFI_FILE_INFO) + sizeof(CHAR16) * 1024; + FileInfo = AllocateZeroPool(FileBufferSize); + if (FileInfo == NULL) { + goto Done ; + } + + FileBufferSize = 0; + Status = FileHandle->Read (FileHandle, &FileBufferSize, FileInfo); + + FileBufferSize = sizeof(EFI_FILE_INFO) + sizeof(CHAR16) * 1024; + Status = FileHandle->Read (FileHandle, &FileBufferSize, FileInfo); + if (EFI_ERROR (Status)) { + goto Done ; + } + + // + // Test UdfGetPosition + // + // As per UEFI spec, if the file handle is a directory, then the current file + // position has no meaning and the operation is not supported. + Status = FileHandle->GetPosition (FileHandle, &SourceFileSize); + + + // + // Test UdfSetPosition + // + Status = FileHandle->SetPosition (FileHandle, 0); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Test UdfGetInfo + // + DirBufferSize = sizeof(EFI_FILE_INFO) + sizeof(CHAR16) * 1024; + DirInfo = AllocateZeroPool(DirBufferSize); + if (DirInfo == NULL) { + goto Done ; + } + + Status = FileHandle->GetInfo (FileHandle, &gEfiFileInfoGuid, &DirBufferSize, DirInfo); + if (EFI_ERROR (Status)) { + goto Done ; + } + + DirBufferSize = 0; + Status = FileHandle->GetInfo (FileHandle, &gEfiFileSystemInfoGuid, &DirBufferSize, DirInfo); + ASSERT (EFI_ERROR (Status)); + + DirBufferSize = 0; + Status = FileHandle->GetInfo (FileHandle, &gEfiFileSystemVolumeLabelInfoIdGuid, &DirBufferSize, DirInfo); + ASSERT (EFI_ERROR (Status)); + + DirBufferSize = sizeof(EFI_FILE_INFO) + sizeof(CHAR16) * 1024; + Status = FileHandle->GetInfo (FileHandle, &gEfiFileSystemInfoGuid, &DirBufferSize, DirInfo); + if (EFI_ERROR (Status)) { + goto Done ; + } + + Status = FileHandle->GetInfo (FileHandle, &gEfiFileSystemVolumeLabelInfoIdGuid, &DirBufferSize, DirInfo); + if (EFI_ERROR (Status)) { + goto Done; + } + +Done: + if (FileHandle != NULL) { + Status = FileHandle-> Close (NULL); + Status = FileHandle-> Close (FileHandle); + } + + if (DirInfo != NULL) { + FreePool(DirInfo); + DirInfo = NULL; + } + + if (FileInfo != NULL) { + FreePool(FileInfo); + FileInfo = NULL; + } + + return ; +} + + +VOID +TestUdfFileSystem ( + EFI_BLOCK_IO_PROTOCOL *PartitionBlockIo, + EFI_DISK_IO_PROTOCOL *PartitionDiskIo, + UINT8 *TestBuffer, + CHAR16 *FileName + ) +{ + EFI_FILE_PROTOCOL *Root; + + PrivFsData = (PRIVATE_UDF_SIMPLE_FS_DATA *)AllocateZeroPool (sizeof (PRIVATE_UDF_SIMPLE_FS_DATA)); + if (PrivFsData == NULL) { + goto Done ; + }; + + Root = TestSimpleFileSystem (PartitionBlockIo, PartitionDiskIo, TestBuffer); + if (Root == NULL) { + goto Done ; + } + + if (FileName == NULL) { + TestFile (Root, L"udf.bin"); + TestFile (Root, L".\\\\b\\\\a"); + TestFile (Root, L"..\\a"); + TestFile (Root, L"b_link\\ a"); + TestFile (Root, L"...a"); + TestFile (Root, NULL); + + TestDir (Root, L"\\"); + TestDir (Root, L"."); + TestDir (Root, L".."); + TestDir (Root, L"b_link"); + TestDir (Root, L"lost+found"); + TestDir (Root, L"b\\c\\"); + + TestDetele (Root, L"b_link\\c"); + TestFlush (Root, L"b_link\\a_link"); + goto Done; + } else { + TestFile (Root, FileName); + TestDir (Root, FileName); + + TestDetele (Root, FileName); + TestFlush (Root, FileName); + goto Done; + } +Done: + if (PrivFsData != NULL) { + FreePool(PrivFsData); + PrivFsData = NULL; + }; + return; +} + +UINTN +EFIAPI +GetMaxBufferSize ( + VOID + ) +{ + return TOTAL_SIZE; +} + +VOID +EFIAPI +RunTestHarness( + IN VOID *TestBuffer, + IN UINTN TestBufferSize + ) +{ + EFI_BLOCK_IO_PROTOCOL *PartitionBlockIo; + EFI_DISK_IO_PROTOCOL *PartitionDiskIo; + CHAR16 *FileName; + + FileName = NULL; + FixBuffer (TestBuffer); + + // + // NOTE: There are 2 partitions: 0x101, and 0x202. + // The files are updated in 0x202. + // + DiskStubInitialize ((UINT8 *)TestBuffer + 0x202 * BLOCK_SIZE, TOTAL_SIZE - 0x202 * BLOCK_SIZE, BLOCK_SIZE, IO_ALIGN, &PartitionBlockIo, &PartitionDiskIo); + + TestUdfFileSystem (PartitionBlockIo, PartitionDiskIo, TestBuffer, FileName); + + DiskStubDestory(); +} diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/TestUdf.inf b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/TestUdf.inf new file mode 100644 index 0000000..f92fa59 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/TestUdf.inf @@ -0,0 +1,44 @@ +## @file +# Component description file for TestUdf module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TestUdf + FILE_GUID = 045C4491-29E5-4357-A939-897A757FB31F + MODULE_TYPE = USER_DEFINED + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + TestUdf.c + MdeModulePkg/Universal/Disk/UdfDxe/Udf.h + +[Packages] + MdePkg/MdePkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec + UefiInstrumentTestPkg/UefiInstrumentTestPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib + UefiBootServicesTableLib + DiskStubLib + ToolChainHarnessLib + +[Guids] + gEfiFileInfoGuid + gEfiFileSystemInfoGuid + gEfiFileSystemVolumeLabelInfoIdGuid diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Variable/RuntimeDxe/TestVariableSmm.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Variable/RuntimeDxe/TestVariableSmm.c new file mode 100644 index 0000000..1c484e8 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Variable/RuntimeDxe/TestVariableSmm.c @@ -0,0 +1,85 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +#ifdef TEST_WITH_LIBFUZZER +#include +#include +#endif + +#include + +#include +#include +#include +#include +#include + +extern BOOLEAN mEndOfDxe; + +#define TOTAL_SIZE (512 * 1024) + +extern UINT8 *mVariableBufferPayload; +extern UINTN mVariableBufferPayloadSize; + +EFI_STATUS +EFIAPI +SmmVariableHandler ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *RegisterContext, + IN OUT VOID *CommBuffer, + IN OUT UINTN *CommBufferSize + ); + +VOID +FixBuffer ( + UINT8 *TestBuffer, + UINTN TestBufferSize + ) +{ +} + +UINTN +EFIAPI +GetMaxBufferSize ( + VOID + ) +{ + return TOTAL_SIZE; +} + +VOID +EFIAPI +RunTestHarness( + IN VOID *TestBuffer, + IN UINTN TestBufferSize + ) +{ + SMM_COMMUNICATION_BUFFER_DESCRIPTOR SmmCommBufferDesc[1]; + + SmmCommBufferDesc[0].Address = (UINTN)TestBuffer; + SmmCommBufferDesc[0].Size = TOTAL_SIZE; + + FixBuffer (TestBuffer, TestBufferSize); + + SmmMemLibInitialize (ARRAY_SIZE(SmmCommBufferDesc), SmmCommBufferDesc); + mEndOfDxe = TRUE; + + mVariableBufferPayloadSize = GetMaxBufferSize(); + mVariableBufferPayload = AllocatePool(mVariableBufferPayloadSize); + if (mVariableBufferPayload == NULL) + return; + + SmmVariableHandler(NULL, NULL, TestBuffer, &TestBufferSize); + + if (mVariableBufferPayload != NULL) + FreePool(mVariableBufferPayload); +} diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Variable/RuntimeDxe/TestVariableSmm.inf b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Variable/RuntimeDxe/TestVariableSmm.inf new file mode 100644 index 0000000..dddb80b --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Variable/RuntimeDxe/TestVariableSmm.inf @@ -0,0 +1,39 @@ +## @file +# Component description file for TestVariableSmm module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TestVariableSmm + FILE_GUID = E911AB26-4741-4621-93EF-305FEA98A851 + MODULE_TYPE = USER_DEFINED + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + TestVariableSmm.c + MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib + SmmMemLib + SmmMemLibStubLib + ToolChainHarnessLib diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.h b/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.h new file mode 100644 index 0000000..7769270 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.h @@ -0,0 +1,140 @@ +/*++ + +Copyright (c) 2006, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +Module Name: + + FwBlockService.h + +Abstract: + + Firmware volume block driver for Intel Firmware Hub (FWH) device + +--*/ + +#ifndef _FW_BLOCK_SERVICE_H +#define _FW_BLOCK_SERVICE_H + +// +// Fvb Protocol instance data +// +#define FVB_DEVICE_FROM_THIS(a) CR (a, EFI_FW_VOL_BLOCK_DEVICE, FwVolBlockInstance, FVB_DEVICE_SIGNATURE) +#define FVB_DEVICE_SIGNATURE SIGNATURE_32 ('F', 'V', 'B', 'N') + +#pragma pack (1) + +typedef struct { + + EFI_FIRMWARE_VOLUME_HEADER FvHdr; + EFI_FV_BLOCK_MAP_ENTRY EndBlockMap; + VARIABLE_STORE_HEADER VarHdr; + +} FVB_FV_HDR_AND_VARS_TEMPLATE; + +typedef struct { + MEMMAP_DEVICE_PATH MemMapDevPath; + EFI_DEVICE_PATH_PROTOCOL EndDevPath; +} FV_DEVICE_PATH; + +#pragma pack () + +typedef struct { + UINTN Signature; + FV_DEVICE_PATH DevicePath; + VOID *BufferPtr; + UINTN BlockSize; + UINTN Size; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL FwVolBlockInstance; +} EFI_FW_VOL_BLOCK_DEVICE; + + +// +// Constants +// +#define EMU_FVB_BLOCK_SIZE \ + EFI_PAGE_SIZE +#define EMU_FVB_NUM_SPARE_BLOCKS \ + EFI_SIZE_TO_PAGES ((UINTN)FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize)) +#define EMU_FVB_NUM_TOTAL_BLOCKS \ + (2 * EMU_FVB_NUM_SPARE_BLOCKS) +#define EMU_FVB_SIZE \ + (EMU_FVB_NUM_TOTAL_BLOCKS * EMU_FVB_BLOCK_SIZE) +#define FTW_WRITE_QUEUE_SIZE \ + (FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize) - \ + sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER)) +#define EMU_FV_HEADER_LENGTH OFFSET_OF (FVB_FV_HDR_AND_VARS_TEMPLATE, VarHdr) + +#define NOT_ERASED_BIT 0 +#define ERASED_BIT 1 +#define ERASED_UINT8 0xff +#define ERASED_UINT32 0xffffffff + +// +// Protocol APIs +// +EFI_STATUS +EFIAPI +FvbProtocolGetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +; + +EFI_STATUS +EFIAPI +FvbProtocolSetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +; + +EFI_STATUS +EFIAPI +FvbProtocolGetPhysicalAddress ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ) +; + +EFI_STATUS +EFIAPI +FvbProtocolGetBlockSize ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumberOfBlocks + ) +; + +EFI_STATUS +EFIAPI +FvbProtocolRead ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN OUT UINT8 *Buffer + ) +; + +EFI_STATUS +EFIAPI +FvbProtocolWrite ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +; + +EFI_STATUS +EFIAPI +FvbProtocolEraseBlocks ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + ... + ) +; + +#endif diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/EmuVariableFvbRuntimeDxe/TestValidateTdxCfv.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/EmuVariableFvbRuntimeDxe/TestValidateTdxCfv.c new file mode 100644 index 0000000..12d4856 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/EmuVariableFvbRuntimeDxe/TestValidateTdxCfv.c @@ -0,0 +1,69 @@ +/** @file + Firmware Block Services to support emulating non-volatile variables + by pretending that a memory buffer is storage for the NV variables. + + Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#define TOTAL_SIZE (1024* 1024) +#define BLOCK_SIZE (512) +#define IO_ALIGN (1) + + +BOOLEAN +EFIAPI +PlatformValidateNvVarStore ( + IN UINT8 *TdvfCfvBase, + IN UINT32 TdvfCfvSize + ); + +VOID +FixBuffer ( + UINT8 *TestBuffer + ) +{ +} +UINTN +EFIAPI +GetMaxBufferSize ( + VOID + ) +{ + return TOTAL_SIZE; +} + +VOID +EFIAPI +RunTestHarness( + IN VOID *TestBuffer, + IN UINTN TestBufferSize + ) +{ + + FixBuffer (TestBuffer); + + + // fuzz function: + // buffer overflow, crash will be detected at place. + // only care about security, not for function bug. + // + // try to separate EFI lib, use stdlib function. + // no asm code. + PlatformValidateNvVarStore (TestBuffer, (UINT32)TestBufferSize); + +} \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/EmuVariableFvbRuntimeDxe/TestValidateTdxCfv.inf b/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/EmuVariableFvbRuntimeDxe/TestValidateTdxCfv.inf new file mode 100644 index 0000000..6178475 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/EmuVariableFvbRuntimeDxe/TestValidateTdxCfv.inf @@ -0,0 +1,46 @@ +## @file +# +# Copyright (c) 2008 - 2021, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TestValidateTdxCfv + FILE_GUID = 22dc2b60-fe40-a2ac-b02f-3ab1fad9aad8 + MODULE_TYPE = USER_DEFINED + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + TestValidateTdxCfv.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + OvmfPkg/OvmfPkg.dec + OvmfPkg/OvmfPkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec +[Pcd] +gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize|0x40000 +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + MemoryAllocationLib + DxeServicesTableLib + HobLib + PcdLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiLib + ToolChainHarnessLib + PlatformInitLib diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/Virtio10BlkDxe/TestVirtio10Blk.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/Virtio10BlkDxe/TestVirtio10Blk.c new file mode 100644 index 0000000..16adfda --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/Virtio10BlkDxe/TestVirtio10Blk.c @@ -0,0 +1,64 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#define TOTAL_SIZE (512 * 1024) +#define BLOCK_SIZE (512) +#define IO_ALIGN (1) + +UINTN +EFIAPI +GetMaxBufferSize ( + VOID + ) +{ + return TOTAL_SIZE; +} + +VOID +EFIAPI +RunTestHarness( + IN VOID *TestBuffer, + IN UINTN TestBufferSize + ) +{ + VBLK_DEV *VblkDev; + VIRTIO_1_0_DEV *VirtioDev; + VOID *ConfigRegion; + EFI_STATUS Status; + + VirtioDev = (VIRTIO_1_0_DEV *) AllocateZeroPool (sizeof *VirtioDev); + VblkDev = (VBLK_DEV *) AllocateZeroPool (sizeof *VblkDev); + ConfigRegion = (VOID *) AllocatePool(sizeof (PCI_CFG_SPACE) + sizeof(VIRTIO_PCI_CAP_COMMON_CONFIG) + sizeof (VIRTIO_BLK_CONFIG) + 0x100); + + Status = ParseBufferAndInitVirtioPciDev10 (TestBuffer, TestBufferSize, ConfigRegion, (VIRTIO_1_0_DEV *) VirtioDev); + + if (!EFI_ERROR(Status)) { + if (VirtioDev->VirtIo.SubSystemDeviceId == VIRTIO_SUBSYSTEM_BLOCK_DEVICE) { + VblkDev->Signature = VBLK_SIG; + VblkDev->VirtIo = &VirtioDev->VirtIo; + VirtioBlkInit (VblkDev); + } + } + + FreePool (ConfigRegion); + FreePool (VirtioDev); + FreePool (VblkDev); +} \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/Virtio10BlkDxe/TestVirtio10Blk.inf b/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/Virtio10BlkDxe/TestVirtio10Blk.inf new file mode 100644 index 0000000..1c8f015 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/Virtio10BlkDxe/TestVirtio10Blk.inf @@ -0,0 +1,40 @@ +## @file +# Component description file for TestUsb module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TestVirtio10Blk + FILE_GUID = 7AF4DF33-6FED-4FCD-A393-C80D76BA9702 + MODULE_TYPE = USER_DEFINED + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + TestVirtio10Blk.c + +[Packages] + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + MemoryAllocationLib + UefiDriverEntryPoint + UefiLib + VirtioLib + VirtioPciDevice10StubLib + VirtioBlkStubLib + ToolChainHarnessLib \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioBlkDxe/TestVirtioBlk.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioBlkDxe/TestVirtioBlk.c new file mode 100644 index 0000000..feb7284 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioBlkDxe/TestVirtioBlk.c @@ -0,0 +1,67 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#define TOTAL_SIZE (512 * 1024) +#define BLOCK_SIZE (512) +#define IO_ALIGN (1) + +UINTN +EFIAPI +GetMaxBufferSize ( + VOID + ) +{ + return TOTAL_SIZE; +} + +VOID +EFIAPI +RunTestHarness( + IN VOID *TestBuffer, + IN UINTN TestBufferSize + ) +{ + VBLK_DEV *VblkDev; + VIRTIO_PCI_DEVICE *VirtioDev; + EFI_PCI_IO_PROTOCOL *PciIo; + VOID *ConfigRegion; + EFI_STATUS Status; + + VirtioDev = (VIRTIO_PCI_DEVICE *) AllocateZeroPool (sizeof *VirtioDev); + VblkDev = (VBLK_DEV *) AllocateZeroPool (sizeof *VblkDev); + PciIo = (EFI_PCI_IO_PROTOCOL *)AllocateZeroPool(sizeof (*PciIo)); + ConfigRegion = (VOID *) AllocatePool(sizeof (PCI_CFG_SPACE) + sizeof(VIRTIO_HDR) + sizeof (VIRTIO_BLK_CONFIG)); + + Status = ParseBufferAndInitVirtioPciDev (TestBuffer, TestBufferSize, PciIo, ConfigRegion, VirtioDev); + + if (!EFI_ERROR(Status)) { + if (VirtioDev->VirtioDevice.SubSystemDeviceId == VIRTIO_SUBSYSTEM_BLOCK_DEVICE) { + VblkDev->Signature = VBLK_SIG; + VblkDev->VirtIo = &VirtioDev->VirtioDevice; + VirtioBlkInit (VblkDev); + } + } + + FreePool (ConfigRegion); + FreePool (VirtioDev); + FreePool (VblkDev); + FreePool (PciIo); +} \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioBlkDxe/TestVirtioBlk.inf b/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioBlkDxe/TestVirtioBlk.inf new file mode 100644 index 0000000..d9706e0 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioBlkDxe/TestVirtioBlk.inf @@ -0,0 +1,40 @@ +## @file +# Component description file for TestUsb module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TestVirtioBlk + FILE_GUID = 7AF4DF33-6FED-4FCD-A393-C80D76BA9702 + MODULE_TYPE = USER_DEFINED + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + TestVirtioBlk.c + +[Packages] + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + MemoryAllocationLib + UefiDriverEntryPoint + UefiLib + VirtioLib + VirtioPciDevice10StubLib + VirtioBlkStubLib + ToolChainHarnessLib \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioBlkReadWrite/TestVirtioBlkReadWrite.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioBlkReadWrite/TestVirtioBlkReadWrite.c new file mode 100644 index 0000000..db6f8cc --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioBlkReadWrite/TestVirtioBlkReadWrite.c @@ -0,0 +1,74 @@ +/** @file + +Copyright (c) 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 + +#define TOTAL_SIZE (512 * 1024) +#define BLOCK_SIZE (512) +#define IO_ALIGN (1) + +UINTN +EFIAPI +GetMaxBufferSize ( + VOID + ) +{ + return TOTAL_SIZE; +} + +VOID +EFIAPI +RunTestHarness( + IN VOID *TestBuffer, + IN UINTN TestBufferSize + ) +{ + VBLK_DEV *VblkDev; + VIRTIO_PCI_DEVICE *VirtioDev; + EFI_PCI_IO_PROTOCOL *PciIo; + VOID *ConfigRegion; + EFI_STATUS Status; + + VirtioDev = (VIRTIO_PCI_DEVICE *) AllocateZeroPool (sizeof *VirtioDev); + VblkDev = (VBLK_DEV *) AllocateZeroPool (sizeof *VblkDev); + PciIo = (EFI_PCI_IO_PROTOCOL *)AllocateZeroPool(sizeof (*PciIo)); + ConfigRegion = (VOID *) AllocatePool(sizeof (PCI_CFG_SPACE) + sizeof(VIRTIO_HDR) + sizeof (VIRTIO_BLK_CONFIG)); + + Status = InitVirtioPciDev (PciIo, ConfigRegion, VirtioDev); + + if (!EFI_ERROR(Status)) { + if (VirtioDev->VirtioDevice.SubSystemDeviceId == VIRTIO_SUBSYSTEM_BLOCK_DEVICE) { + VblkDev->Signature = VBLK_SIG; + VblkDev->VirtIo = &VirtioDev->VirtioDevice; + Status = VirtioBlkInit (VblkDev); + if (!EFI_ERROR(Status)) { + VblkDev->BlockIo.WriteBlocks(&VblkDev->BlockIo, 0, 0, TestBufferSize, TestBuffer); + VblkDev->BlockIo.ReadBlocks(&VblkDev->BlockIo, 0, 0, TestBufferSize, TestBuffer); + VblkDev->BlockIo.FlushBlocks(&VblkDev->BlockIo); + } + } + } + + VirtioRingUninit (VblkDev->VirtIo, &VblkDev->Ring); + FreePool (ConfigRegion); + FreePool (VirtioDev); + FreePool (VblkDev); + FreePool (PciIo); +} \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioBlkReadWrite/TestVirtioBlkReadWrite.inf b/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioBlkReadWrite/TestVirtioBlkReadWrite.inf new file mode 100644 index 0000000..34803a9 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioBlkReadWrite/TestVirtioBlkReadWrite.inf @@ -0,0 +1,40 @@ +## @file +# Component description file for TestUsb module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TestVirtioBlkReadWrite + FILE_GUID = 7AF4DF33-6FED-44CD-A393-C80D76BA9701 + MODULE_TYPE = USER_DEFINED + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + TestVirtioBlkReadWrite.c + +[Packages] + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + MemoryAllocationLib + UefiDriverEntryPoint + UefiLib + VirtioLib + VirtioPciDevice10StubLib + VirtioBlkStubLib + ToolChainHarnessLib \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioPciDeviceDxe/TestVirtioPciDevice.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioPciDeviceDxe/TestVirtioPciDevice.c new file mode 100644 index 0000000..bc45223 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioPciDeviceDxe/TestVirtioPciDevice.c @@ -0,0 +1,181 @@ +/** @file + +Copyright (c) 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 + +#define TOTAL_SIZE (512 * 1024) +#define BLOCK_SIZE (512) +#define IO_ALIGN (1) + +UINTN +EFIAPI +GetMaxBufferSize ( + VOID + ) +{ + return TOTAL_SIZE; +} + +EFI_STATUS +EFIAPI +ParseCapabilities ( + IN OUT VIRTIO_1_0_DEV *Device + ) +{ + EFI_STATUS Status; + PCI_CAP_DEV *PciDevice; + PCI_CAP_LIST *CapList; + UINT16 VendorInstance; + PCI_CAP *VendorCap; + + Status = PciCapPciIoDeviceInit (Device->PciIo, &PciDevice); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = PciCapListInit (PciDevice, &CapList); + if (EFI_ERROR (Status)) { + goto UninitPciDevice; + } + + for (VendorInstance = 0; + !EFI_ERROR (PciCapListFindCap (CapList, PciCapNormal, + EFI_PCI_CAPABILITY_ID_VENDOR, VendorInstance, + &VendorCap)); + VendorInstance++) { + UINT8 CapLen; + VIRTIO_PCI_CAP VirtIoCap; + VIRTIO_1_0_CONFIG *ParsedConfig; + + // + // Big enough to accommodate a VIRTIO_PCI_CAP structure? + // + Status = PciCapRead (PciDevice, VendorCap, + OFFSET_OF (EFI_PCI_CAPABILITY_VENDOR_HDR, Length), &CapLen, + sizeof CapLen); + if (EFI_ERROR (Status)) { + goto UninitCapList; + } + if (CapLen < sizeof VirtIoCap) { + // + // Too small, move to next. + // + continue; + } + + // + // Read interesting part of capability. + // + Status = PciCapRead (PciDevice, VendorCap, 0, &VirtIoCap, sizeof VirtIoCap); + if (EFI_ERROR (Status)) { + goto UninitCapList; + } + + switch (VirtIoCap.ConfigType) { + case VIRTIO_PCI_CAP_COMMON_CFG: + ParsedConfig = &Device->CommonConfig; + break; + case VIRTIO_PCI_CAP_NOTIFY_CFG: + ParsedConfig = &Device->NotifyConfig; + break; + case VIRTIO_PCI_CAP_DEVICE_CFG: + ParsedConfig = &Device->SpecificConfig; + break; + default: + // + // Capability is not interesting. + // + continue; + } + + // + // Save the location of the register block into ParsedConfig. + // + Status = GetBarType (Device->PciIo, VirtIoCap.Bar, &ParsedConfig->BarType); + if (EFI_ERROR (Status)) { + goto UninitCapList; + } + ParsedConfig->Bar = VirtIoCap.Bar; + ParsedConfig->Offset = VirtIoCap.Offset; + ParsedConfig->Length = VirtIoCap.Length; + + if (VirtIoCap.ConfigType == VIRTIO_PCI_CAP_NOTIFY_CFG) { + // + // This capability has an additional field called NotifyOffsetMultiplier; + // parse it too. + // + if (CapLen < sizeof VirtIoCap + sizeof Device->NotifyOffsetMultiplier) { + // + // Too small, move to next. + // + continue; + } + + Status = PciCapRead (PciDevice, VendorCap, sizeof VirtIoCap, + &Device->NotifyOffsetMultiplier, + sizeof Device->NotifyOffsetMultiplier); + if (EFI_ERROR (Status)) { + goto UninitCapList; + } + } + + // + // Capability parsed successfully. + // + ParsedConfig->Exists = TRUE; + } + + ASSERT_EFI_ERROR (Status); + +UninitCapList: + PciCapListUninit (CapList); + +UninitPciDevice: + PciCapPciIoDeviceUninit (PciDevice); + + return Status; +} + +VOID +EFIAPI +RunTestHarness( + IN VOID *TestBuffer, + IN UINTN TestBufferSize + ) +{ + VIRTIO_1_0_DEV *VirtioPciDevice; + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + + VirtioPciDevice = (VIRTIO_1_0_DEV *) AllocateZeroPool(sizeof (*VirtioPciDevice)); + + PciIo = (EFI_PCI_IO_PROTOCOL *)AllocateZeroPool(sizeof (*PciIo)); + + VirtioPciDevice->PciIo = PciIo; + + Status = InitVirtioPciDevice (VirtioPciDevice, TestBuffer, TestBufferSize, PciIo); + + if (!EFI_ERROR(Status)) { + ParseCapabilities (VirtioPciDevice); + } + + FreePool (PciIo); + FreePool (VirtioPciDevice); +} \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioPciDeviceDxe/TestVirtioPciDevice.inf b/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioPciDeviceDxe/TestVirtioPciDevice.inf new file mode 100644 index 0000000..761cf07 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioPciDeviceDxe/TestVirtioPciDevice.inf @@ -0,0 +1,39 @@ +## @file +# Component description file for TestUsb module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TestVirtioPciDevice + FILE_GUID = 7AF4DF33-6FED-4FCD-A313-C80D76BA9602 + MODULE_TYPE = USER_DEFINED + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + TestVirtioPciDevice.c + +[Packages] + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + MemoryAllocationLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiLib + ToolChainHarnessLib + VirtioPciDevice10StubLib diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/DxeTpm2MeasureBootLib/TestTcg2MeasureGptTable.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/DxeTpm2MeasureBootLib/TestTcg2MeasureGptTable.c new file mode 100644 index 0000000..4261716 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/DxeTpm2MeasureBootLib/TestTcg2MeasureGptTable.c @@ -0,0 +1,111 @@ +/** @file + Firmware Block Services to support emulating non-volatile variables + by pretending that a memory buffer is storage for the NV variables. + + Copyright (c) 2006 - 2021, 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 +#include +#include + + +#define TOTAL_SIZE (512 * 1024) +#define BLOCK_SIZE (512) +#define IO_ALIGN (1) + + +typedef struct { + EFI_TCG2_PROTOCOL *Tcg2Protocol; + EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol; +} MEASURE_BOOT_PROTOCOLS; + +EFI_STATUS +EFIAPI +Tcg2MeasureGptTable ( + IN MEASURE_BOOT_PROTOCOLS *MeasureBootProtocols, + IN EFI_HANDLE GptHandle + ); + +VOID +FixBuffer ( + UINT8 *TestBuffer + ) +{ +} +UINTN +EFIAPI +GetMaxBufferSize ( + VOID + ) +{ + return TOTAL_SIZE; +} + +VOID +EFIAPI +RunTestHarness( + IN VOID *TestBuffer, + IN UINTN TestBufferSize + ) +{ + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_DISK_IO_PROTOCOL *DiskIo; + MEASURE_BOOT_PROTOCOLS MeasureBootProtocols; + EFI_TCG2_PROTOCOL *Tcg2Protocol; + EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol; + EFI_HANDLE GptHandle; + EFI_STATUS Status; + + FixBuffer (TestBuffer); + DiskStubInitialize (TestBuffer, TestBufferSize, BLOCK_SIZE, IO_ALIGN, &BlockIo, &DiskIo); + Tcg2StubInitlize(); + + MeasureBootProtocols.Tcg2Protocol = NULL; + MeasureBootProtocols.CcProtocol = NULL; + // fuzz function: + // buffer overflow, crash will be detected at place. + // only care about security, not for function bug. + // + // try to separate EFI lib, use stdlib function. + // no asm code. + + GptHandle =NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &GptHandle, + &gEfiBlockIoProtocolGuid, + BlockIo, + &gEfiDiskIoProtocolGuid, + DiskIo, + NULL + ); + + Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &Tcg2Protocol); + Status = gBS->LocateProtocol (&gEfiCcMeasurementProtocolGuid, NULL, (VOID **) &CcProtocol); + + //case 1: set MeasureBootProtocols.CcProtocol = NULL + MeasureBootProtocols.Tcg2Protocol = Tcg2Protocol; + Tcg2MeasureGptTable (&MeasureBootProtocols, GptHandle); + + //case2:set MeasureBootProtocols.Tcg2Protocol = NULL + MeasureBootProtocols.Tcg2Protocol = NULL; + MeasureBootProtocols.CcProtocol = CcProtocol; + Tcg2MeasureGptTable (&MeasureBootProtocols, GptHandle); + +} \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/DxeTpm2MeasureBootLib/TestTcg2MeasureGptTable.inf b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/DxeTpm2MeasureBootLib/TestTcg2MeasureGptTable.inf new file mode 100644 index 0000000..7960023 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/DxeTpm2MeasureBootLib/TestTcg2MeasureGptTable.inf @@ -0,0 +1,50 @@ +## @file +# Provides security service for Tdvf measured boot +# +# This library instance hooks LoadImage() API to measure every image that +# is not measured in PEI phase. And, it will also measure GPT partition. +# +# Caution: This module requires additional review when modified. +# This library will have external input - PE/COFF image and GPT partition. +# This external input must be validated carefully to avoid security issues such +# as buffer overflow or integer overflow. +# +# Copyright (c) 2020, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TestTcg2MeasureGptTable + FILE_GUID = 778DF4F4-36BD-4ae7-B2F0-10B434B0D164 + MODULE_TYPE = USER_DEFINED + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = X64 +# + +[Sources] + TestTcg2MeasureGptTable.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + OvmfPkg/OvmfPkg.dec + SecurityPkg/SecurityPkg.dec + CryptoPkg/CryptoPkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + MemoryAllocationLib + BaseLib + DiskStubLib + Tcg2StubLib + UefiBootServicesTableLib + ToolChainHarnessLib \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/DxeTpm2MeasureBootLib/TestTcg2MeasurePeImage.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/DxeTpm2MeasureBootLib/TestTcg2MeasurePeImage.c new file mode 100644 index 0000000..119f11c --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/DxeTpm2MeasureBootLib/TestTcg2MeasurePeImage.c @@ -0,0 +1,154 @@ +/** @file + + Copyright (c) 2006 - 2013, 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 +#include +#include +#include +#include + + + +#define TOTAL_SIZE (512 * 1024) +#define BLOCK_SIZE (512) +#define IO_ALIGN (1) + +typedef struct { + EFI_TCG2_PROTOCOL *Tcg2Protocol; + EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol; +} MEASURE_BOOT_PROTOCOLS; + +EFI_STATUS +EFIAPI +Tcg2MeasurePeImage ( + IN MEASURE_BOOT_PROTOCOLS *MeasureBootProtocols, + IN EFI_PHYSICAL_ADDRESS ImageAddress, + IN UINTN ImageSize, + IN UINTN LinkTimeBase, + IN UINT16 ImageType, + IN EFI_DEVICE_PATH_PROTOCOL *FilePath + ); + + +VOID +FixBuffer ( + UINT8 *TestBuffer + ) +{ +} +UINTN +EFIAPI +GetMaxBufferSize ( + VOID + ) +{ + return TOTAL_SIZE; +} + +VOID +EFIAPI +RunTestHarness( + IN VOID *TestBuffer, + IN UINTN TestBufferSize + ) +{ + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_DISK_IO_PROTOCOL *DiskIo; + MEASURE_BOOT_PROTOCOLS MeasureBootProtocols; + EFI_TCG2_PROTOCOL *Tcg2Protocol; + EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol; + EFI_HANDLE GptHandle; + EFI_STATUS Status; + + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + EFI_DEVICE_PATH_PROTOCOL *OrigDevicePathNode; + //HARDDRIVE_DEVICE_PATH *Hd; + UINT8 DeviceArray[]={0x03,0x17,0x10,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0x7F,0xFF,0x04,0x00}; + + FixBuffer (TestBuffer); + DiskStubInitialize (TestBuffer, TestBufferSize, BLOCK_SIZE, IO_ALIGN, &BlockIo, &DiskIo); + Tcg2StubInitlize(); + + MeasureBootProtocols.Tcg2Protocol = NULL; + MeasureBootProtocols.CcProtocol = NULL; + // fuzz function: + // buffer overflow, crash will be detected at place. + // only care about security, not for function bug. + // + // try to separate EFI lib, use stdlib function. + // no asm code. + + GptHandle =NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &GptHandle, + &gEfiBlockIoProtocolGuid, + BlockIo, + &gEfiDiskIoProtocolGuid, + DiskIo, + NULL + ); + Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &Tcg2Protocol); + Status = gBS->LocateProtocol (&gEfiCcMeasurementProtocolGuid, NULL, (VOID **) &CcProtocol); + + MeasureBootProtocols.Tcg2Protocol = Tcg2Protocol; + /* + Hd = (HARDDRIVE_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_HARDDRIVE_DP, + (UINT16) sizeof (HARDDRIVE_DEVICE_PATH) + ); + */ + OrigDevicePathNode= (EFI_DEVICE_PATH_PROTOCOL*) DeviceArray; + #pragma warning(disable: 4700) + + //test case 1:set MeasureBootProtocols.CcProtocol = NULL; + ImageContext.ImageType = 0x1; + ImageContext.ImageAddress = 0x1234; + Tcg2MeasurePeImage (&MeasureBootProtocols, (EFI_PHYSICAL_ADDRESS)TestBuffer, TestBufferSize,(UINTN) ImageContext.ImageAddress,ImageContext.ImageType,OrigDevicePathNode ); + ImageContext.ImageType = 10; + Tcg2MeasurePeImage (&MeasureBootProtocols, (EFI_PHYSICAL_ADDRESS)TestBuffer, TestBufferSize,(UINTN) ImageContext.ImageAddress,ImageContext.ImageType,OrigDevicePathNode ); + ImageContext.ImageType = 11; + + Tcg2MeasurePeImage (&MeasureBootProtocols, (EFI_PHYSICAL_ADDRESS)TestBuffer, TestBufferSize,(UINTN) ImageContext.ImageAddress,ImageContext.ImageType,OrigDevicePathNode); + ImageContext.ImageType = 12; + Tcg2MeasurePeImage (&MeasureBootProtocols, (EFI_PHYSICAL_ADDRESS)TestBuffer, TestBufferSize,(UINTN) ImageContext.ImageAddress,ImageContext.ImageType,OrigDevicePathNode ); + ImageContext.ImageType = 13; + Tcg2MeasurePeImage (&MeasureBootProtocols, (EFI_PHYSICAL_ADDRESS)TestBuffer, TestBufferSize,(UINTN) ImageContext.ImageAddress,ImageContext.ImageType,OrigDevicePathNode ); + + //test case 2:set MeasureBootProtocols.Tcg2Protocol = NULL; + MeasureBootProtocols.Tcg2Protocol = NULL; + MeasureBootProtocols.CcProtocol = CcProtocol; + + ImageContext.ImageType = 0x1; + ImageContext.ImageAddress = 0x1234; + Tcg2MeasurePeImage (&MeasureBootProtocols, (EFI_PHYSICAL_ADDRESS)TestBuffer, TestBufferSize,(UINTN) ImageContext.ImageAddress,ImageContext.ImageType,OrigDevicePathNode ); + ImageContext.ImageType = 10; + Tcg2MeasurePeImage (&MeasureBootProtocols, (EFI_PHYSICAL_ADDRESS)TestBuffer, TestBufferSize,(UINTN) ImageContext.ImageAddress,ImageContext.ImageType,OrigDevicePathNode ); + ImageContext.ImageType = 11; + + Tcg2MeasurePeImage (&MeasureBootProtocols, (EFI_PHYSICAL_ADDRESS)TestBuffer, TestBufferSize,(UINTN) ImageContext.ImageAddress,ImageContext.ImageType,OrigDevicePathNode); + ImageContext.ImageType = 12; + Tcg2MeasurePeImage (&MeasureBootProtocols, (EFI_PHYSICAL_ADDRESS)TestBuffer, TestBufferSize,(UINTN) ImageContext.ImageAddress,ImageContext.ImageType,OrigDevicePathNode ); + ImageContext.ImageType = 13; + Tcg2MeasurePeImage (&MeasureBootProtocols, (EFI_PHYSICAL_ADDRESS)TestBuffer, TestBufferSize,(UINTN) ImageContext.ImageAddress,ImageContext.ImageType,OrigDevicePathNode ); + +} \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/DxeTpm2MeasureBootLib/TestTcg2MeasurePeImage.inf b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/DxeTpm2MeasureBootLib/TestTcg2MeasurePeImage.inf new file mode 100644 index 0000000..6e88af4 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/DxeTpm2MeasureBootLib/TestTcg2MeasurePeImage.inf @@ -0,0 +1,42 @@ +## @file +# +# Copyright (c) 2020, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TestTcg2MeasurePeImage + FILE_GUID = 778DF4F4-36BD-4ae7-B2F0-10B434B0D164 + MODULE_TYPE = USER_DEFINED + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = X64 +# + +[Sources] + TestTcg2MeasurePeImage.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + OvmfPkg/OvmfPkg.dec + SecurityPkg/SecurityPkg.dec + CryptoPkg/CryptoPkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + MemoryAllocationLib + BaseLib + DiskStubLib + Tcg2StubLib + UefiBootServicesTableLib + DevicePathLib + ToolChainHarnessLib \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibPkcs7/CryptoLibStubPkcs7.inf b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibPkcs7/CryptoLibStubPkcs7.inf new file mode 100644 index 0000000..3720806 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibPkcs7/CryptoLibStubPkcs7.inf @@ -0,0 +1,43 @@ +## @file +# Component description file for TestTpm2CommandLib module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = CryptoLibStubPkcs7 + FILE_GUID = C9FE7135-3EDA-4E4A-AB1F-EB4DD74A85CA + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = BaseCryptLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + CryptoStubPkcs7.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + CryptoPkg/CryptoPkg.dec + SecurityPkg/SecurityPkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib + ToolChainHarnessLib + +[Guids] + gEfiCertPkcs7Guid + diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibPkcs7/CryptoStubPkcs7.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibPkcs7/CryptoStubPkcs7.c new file mode 100644 index 0000000..0276ee1 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibPkcs7/CryptoStubPkcs7.c @@ -0,0 +1,22 @@ +/** @file + + Copyright (c) 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +BOOLEAN +EFIAPI +Pkcs7Verify ( + IN CONST UINT8 *P7Data, + IN UINTN P7Length, + IN CONST UINT8 *TrustedCert, + IN UINTN CertLength, + IN CONST UINT8 *InData, + IN UINTN DataLength + ) +{ + return TRUE; +} diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibPkcs7/SamplePkcs7.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibPkcs7/SamplePkcs7.c new file mode 100644 index 0000000..a8eff48 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibPkcs7/SamplePkcs7.c @@ -0,0 +1,11 @@ +/** @file + + Copyright (c) 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +UINT8 mPkcs7PublicKeyData[] = {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}; +UINTN mPkcs7PublicKeyDataSize = sizeof(mPkcs7PublicKeyData); diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibPkcs7/TestFmpAuthenticationLibPkcs7.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibPkcs7/TestFmpAuthenticationLibPkcs7.c new file mode 100644 index 0000000..913de0a --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibPkcs7/TestFmpAuthenticationLibPkcs7.c @@ -0,0 +1,55 @@ +/** @file + +Copyright (c) 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 + +#define TOTAL_SIZE (512 * 1024) + +extern UINT8 mPkcs7PublicKeyData[]; +extern UINTN mPkcs7PublicKeyDataSize; + +VOID +FixBuffer ( + UINT8 *TestBuffer + ) +{ +} + +UINTN +EFIAPI +GetMaxBufferSize ( + VOID + ) +{ + return TOTAL_SIZE; +} + +VOID +EFIAPI +RunTestHarness( + IN VOID *TestBuffer, + IN UINTN TestBufferSize + ) +{ + FixBuffer (TestBuffer); + AuthenticateFmpImage (TestBuffer, TestBufferSize, mPkcs7PublicKeyData, mPkcs7PublicKeyDataSize); +} diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibPkcs7/TestFmpAuthenticationLibPkcs7.inf b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibPkcs7/TestFmpAuthenticationLibPkcs7.inf new file mode 100644 index 0000000..5b86a0f --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibPkcs7/TestFmpAuthenticationLibPkcs7.inf @@ -0,0 +1,44 @@ +## @file +# Component description file for TestTpm2CommandLib module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TestFmpAuthenticationLibPkcs7 + FILE_GUID = 671711BA-ED88-46D3-99E6-A690E7C301F0 + MODULE_TYPE = USER_DEFINED + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + TestFmpAuthenticationLibPkcs7.c + SamplePkcs7.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + CryptoPkg/CryptoPkg.dec + SecurityPkg/SecurityPkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib + FmpAuthenticationLib + ToolChainHarnessLib + +[Guids] + gEfiCertPkcs7Guid + diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibRsa2048Sha256/CryptoLibStubRsa2048Sha256.inf b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibRsa2048Sha256/CryptoLibStubRsa2048Sha256.inf new file mode 100644 index 0000000..5e2acc6 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibRsa2048Sha256/CryptoLibStubRsa2048Sha256.inf @@ -0,0 +1,43 @@ +## @file +# Component description file for TestTpm2CommandLib module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = CryptoLibStubRsa2048Sha256 + FILE_GUID = 2826B09D-AEEA-4BB4-876F-1A025BF43752 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = BaseCryptLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + CryptoStubRsa2048Sha256.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + CryptoPkg/CryptoPkg.dec + SecurityPkg/SecurityPkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib + ToolChainHarnessLib + +[Guids] + gEfiCertPkcs7Guid + diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibRsa2048Sha256/CryptoStubRsa2048Sha256.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibRsa2048Sha256/CryptoStubRsa2048Sha256.c new file mode 100644 index 0000000..7afcaaf --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibRsa2048Sha256/CryptoStubRsa2048Sha256.c @@ -0,0 +1,90 @@ +/** @file + + Copyright (c) 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +VOID * +EFIAPI +RsaNew ( + VOID + ) +{ + return NULL; +} + +VOID +EFIAPI +RsaFree ( + IN VOID *RsaContext + ) +{ +} + +BOOLEAN +EFIAPI +RsaSetKey ( + IN OUT VOID *RsaContext, + IN RSA_KEY_TAG KeyTag, + IN CONST UINT8 *BigNumber, + IN UINTN BnSize + ) +{ + return FALSE; +} + +BOOLEAN +EFIAPI +RsaPkcs1Verify ( + IN VOID *RsaContext, + IN CONST UINT8 *MessageHash, + IN UINTN HashSize, + IN CONST UINT8 *Signature, + IN UINTN SigSize + ) +{ + return FALSE; +} + +UINTN +EFIAPI +Sha256GetContextSize ( + VOID + ) +{ + return 0; +} + +BOOLEAN +EFIAPI +Sha256Init ( + OUT VOID *Sha256Context + ) +{ + return FALSE; +} + +BOOLEAN +EFIAPI +Sha256Update ( + IN OUT VOID *Sha256Context, + IN CONST VOID *Data, + IN UINTN DataSize + ) +{ + return FALSE; +} + +BOOLEAN +EFIAPI +Sha256Final ( + IN OUT VOID *Sha256Context, + OUT UINT8 *HashValue + ) +{ + return FALSE; +} diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibRsa2048Sha256/SampleRsa2048Sha256.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibRsa2048Sha256/SampleRsa2048Sha256.c new file mode 100644 index 0000000..8a5fd9a --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibRsa2048Sha256/SampleRsa2048Sha256.c @@ -0,0 +1,11 @@ +/** @file + + Copyright (c) 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +UINT8 mRsa2048Sha256PublicKeyData[] = {0x91, 0x29, 0xc4, 0xbd, 0xea, 0x6d, 0xda, 0xb3, 0xaa, 0x6f, 0x50, 0x16, 0xfc, 0xdb, 0x4b, 0x7e, 0x3c, 0xd6, 0xdc, 0xa4, 0x7a, 0x0e, 0xdd, 0xe6, 0x15, 0x8c, 0x73, 0x96, 0xa2, 0xd4, 0xa6, 0x4d}; +UINTN mRsa2048Sha256PublicKeyDataSize = sizeof(mRsa2048Sha256PublicKeyData); diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibRsa2048Sha256/TestFmpAuthenticationLibRsa2048Sha256.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibRsa2048Sha256/TestFmpAuthenticationLibRsa2048Sha256.c new file mode 100644 index 0000000..696f5e8 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibRsa2048Sha256/TestFmpAuthenticationLibRsa2048Sha256.c @@ -0,0 +1,55 @@ +/** @file + +Copyright (c) 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 + +#define TOTAL_SIZE (512 * 1024) + +extern UINT8 mRsa2048Sha256PublicKeyData[]; +extern UINTN mRsa2048Sha256PublicKeyDataSize; + +VOID +FixBuffer ( + UINT8 *TestBuffer + ) +{ +} + +UINTN +EFIAPI +GetMaxBufferSize ( + VOID + ) +{ + return TOTAL_SIZE; +} + +VOID +EFIAPI +RunTestHarness( + IN VOID *TestBuffer, + IN UINTN TestBufferSize + ) +{ + FixBuffer (TestBuffer); + AuthenticateFmpImage (TestBuffer, TestBufferSize, mRsa2048Sha256PublicKeyData, mRsa2048Sha256PublicKeyDataSize); +} diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibRsa2048Sha256/TestFmpAuthenticationLibRsa2048Sha256.inf b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibRsa2048Sha256/TestFmpAuthenticationLibRsa2048Sha256.inf new file mode 100644 index 0000000..bea19be --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibRsa2048Sha256/TestFmpAuthenticationLibRsa2048Sha256.inf @@ -0,0 +1,44 @@ +## @file +# Component description file for TestTpm2CommandLib module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TestFmpAuthenticationLibRsa2048Sha256 + FILE_GUID = 22914CAE-62CD-450E-BCC7-9A69C0EF9C93 + MODULE_TYPE = USER_DEFINED + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + TestFmpAuthenticationLibRsa2048Sha256.c + SampleRsa2048Sha256.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + CryptoPkg/CryptoPkg.dec + SecurityPkg/SecurityPkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib + FmpAuthenticationLib + ToolChainHarnessLib + +[Guids] + gEfiCertTypeRsa2048Sha256Guid + gEfiHashAlgorithmSha256Guid diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/Tpm2CommandLib/TestTpm2CommandLib.c b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/Tpm2CommandLib/TestTpm2CommandLib.c new file mode 100644 index 0000000..abe815f --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/Tpm2CommandLib/TestTpm2CommandLib.c @@ -0,0 +1,86 @@ +/** @file + +Copyright (c) 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 + +#define TOTAL_SIZE (512 * 1024) + +#pragma pack(1) + +typedef struct { + TPM2_RESPONSE_HEADER Header; + UINT32 ParameterSize; + TPML_DIGEST_VALUES Digests; + TPMS_AUTH_RESPONSE AuthSessionPcr; +} TPM2_PCR_EVENT_RESPONSE; + +#pragma pack() + +VOID +FixBuffer ( + UINT8 *TestBuffer + ) +{ + TPM2_PCR_EVENT_RESPONSE *Res; + + Res = (VOID *)TestBuffer; + Res->Header.responseCode = SwapBytes32(TPM_RC_SUCCESS); + Res->Header.paramSize = SwapBytes32 (sizeof(TPM2_PCR_EVENT_RESPONSE)); +} + +VOID +TestTpm2PcrEve ( + VOID + ) +{ + TPMI_DH_PCR PcrHandle; + TPM2B_EVENT EventData; + TPML_DIGEST_VALUES Digests; + + PcrHandle = 0; + ZeroMem (&EventData, sizeof(EventData)); + EventData.size = 4; + ZeroMem (&Digests, sizeof(Digests)); + Tpm2PcrEvent (PcrHandle, &EventData, &Digests); +} +UINTN +EFIAPI +GetMaxBufferSize ( + VOID + ) +{ + return TOTAL_SIZE; +} + +VOID +EFIAPI +RunTestHarness( + IN VOID *TestBuffer, + IN UINTN TestBufferSize + ) +{ + FixBuffer (TestBuffer); + Tpm2ResponseInitialize (TestBuffer, TestBufferSize); + + TestTpm2PcrEve (); +} diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/Tpm2CommandLib/TestTpm2CommandLib.inf b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/Tpm2CommandLib/TestTpm2CommandLib.inf new file mode 100644 index 0000000..5920228 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/Tpm2CommandLib/TestTpm2CommandLib.inf @@ -0,0 +1,38 @@ +## @file +# Component description file for TestTpm2CommandLib module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TestTpm2CommandLib + FILE_GUID = 671711BA-ED88-46D3-99E6-A690E7C301F0 + MODULE_TYPE = USER_DEFINED + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + TestTpm2CommandLib.c + +[Packages] + MdePkg/MdePkg.dec + SecurityPkg/SecurityPkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib + Tpm2CommandLib + Tpm2DeviceStubLib + ToolChainHarnessLib diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestStub/DiskStubLib/DiskStubLib.c b/HBFA/UefiHostFuzzTestCasePkg/TestStub/DiskStubLib/DiskStubLib.c new file mode 100644 index 0000000..b0101c9 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestStub/DiskStubLib/DiskStubLib.c @@ -0,0 +1,735 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +#include +#include +#include +#include + +typedef struct { + UINTN Signature; + EFI_BLOCK_IO_PROTOCOL BlockIo; + EFI_BLOCK_IO_MEDIA Media; + EFI_DISK_IO_PROTOCOL DiskIo; + UINT64 StartingAddr; + UINT64 Size; +} UDF_TEST_PRIVATE; + +UDF_TEST_PRIVATE *UdfTestPrivate = NULL; + +#define DATA_BUFFER_BLOCK_NUM (64) + +#define UDF_TEST_PRIVATE_SIGNATURE SIGNATURE_32 ('U', 'D', 'F', 'T') + +#define UDF_TEST_PRIVATE_FROM_BLOCK_IO(a) CR (a, UDF_TEST_PRIVATE, BlockIo, UDF_TEST_PRIVATE_SIGNATURE) +#define UDF_TEST_PRIVATE_FROM_DISK_IO(a) CR (a, UDF_TEST_PRIVATE, DiskIo, UDF_TEST_PRIVATE_SIGNATURE) + +/** + Reset the Block Device. + + @param This Indicates a pointer to the calling context. + @param ExtendedVerification Driver may perform diagnostics on reset. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The device is not functioning properly and could + not be reset. + +**/ +EFI_STATUS +EFIAPI +Reset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + return EFI_SUCCESS; +} + +/** + Read BufferSize bytes from Lba into Buffer. + + @param This Indicates a pointer to the calling context. + @param MediaId Id of the media, changes every time the media is replaced. + @param Lba The starting Logical Block Address to read from + @param BufferSize Size of Buffer, must be a multiple of device block size. + @param Buffer A pointer to the destination buffer for the data. The caller is + responsible for either having implicit or explicit ownership of the buffer. + + @retval EFI_SUCCESS The data was read correctly from the device. + @retval EFI_DEVICE_ERROR The device reported an error while performing the read. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device. + @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device. + @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, + or the buffer is not on proper alignment. + +**/ +EFI_STATUS +EFIAPI +ReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + UDF_TEST_PRIVATE *PrivateData; + UINTN NumberOfBlocks; + + PrivateData = UDF_TEST_PRIVATE_FROM_BLOCK_IO (This); + + if (MediaId != PrivateData->Media.MediaId) { + return EFI_MEDIA_CHANGED; + } + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize == 0) { + return EFI_SUCCESS; + } + + if ((BufferSize % PrivateData->Media.BlockSize) != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + if (Lba > PrivateData->Media.LastBlock) { + return EFI_INVALID_PARAMETER; + } + + NumberOfBlocks = BufferSize / PrivateData->Media.BlockSize; + if ((Lba + NumberOfBlocks - 1) > PrivateData->Media.LastBlock) { + return EFI_INVALID_PARAMETER; + } + + CopyMem ( + Buffer, + (VOID *)(UINTN)(PrivateData->StartingAddr + MultU64x32 (Lba, PrivateData->Media.BlockSize)), + BufferSize + ); + + return EFI_SUCCESS; +} + +/** + Write BufferSize bytes from Lba into Buffer. + + @param This Indicates a pointer to the calling context. + @param MediaId The media ID that the write request is for. + @param Lba The starting logical block address to be written. The caller is + responsible for writing to only legitimate locations. + @param BufferSize Size of Buffer, must be a multiple of device block size. + @param Buffer A pointer to the source buffer for the data. + + @retval EFI_SUCCESS The data was written correctly to the device. + @retval EFI_WRITE_PROTECTED The device can not be written to. + @retval EFI_DEVICE_ERROR The device reported an error while performing the write. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device. + @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device. + @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, + or the buffer is not on proper alignment. + +**/ +EFI_STATUS +EFIAPI +WriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer + ) +{ + UDF_TEST_PRIVATE *PrivateData; + UINTN NumberOfBlocks; + + PrivateData = UDF_TEST_PRIVATE_FROM_BLOCK_IO (This); + + if (MediaId != PrivateData->Media.MediaId) { + return EFI_MEDIA_CHANGED; + } + + if (TRUE == PrivateData->Media.ReadOnly) { + return EFI_WRITE_PROTECTED; + } + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize == 0) { + return EFI_SUCCESS; + } + + if ((BufferSize % PrivateData->Media.BlockSize) != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + if (Lba > PrivateData->Media.LastBlock) { + return EFI_INVALID_PARAMETER; + } + + NumberOfBlocks = BufferSize / PrivateData->Media.BlockSize; + if ((Lba + NumberOfBlocks - 1) > PrivateData->Media.LastBlock) { + return EFI_INVALID_PARAMETER; + } + + CopyMem ( + (VOID *)(UINTN)(PrivateData->StartingAddr + MultU64x32 (Lba, PrivateData->Media.BlockSize)), + Buffer, + BufferSize + ); + + return EFI_SUCCESS; +} + +/** + Flush the Block Device. + + @param This Indicates a pointer to the calling context. + + @retval EFI_SUCCESS All outstanding data was written to the device + @retval EFI_DEVICE_ERROR The device reported an error while writting back the data + @retval EFI_NO_MEDIA There is no media in the device. + +**/ +EFI_STATUS +EFIAPI +FlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ) +{ + return EFI_SUCCESS; +} + +/** + Read BufferSize bytes from Offset into Buffer. + + @param This Protocol instance pointer. + @param MediaId Id of the media, changes every time the media is replaced. + @param Offset The starting byte offset to read from + @param BufferSize Size of Buffer + @param Buffer Buffer containing read data + + @retval EFI_SUCCESS The data was read correctly from the device. + @retval EFI_DEVICE_ERROR The device reported an error while performing the read. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device. + @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not + valid for the device. + +**/ +EFI_STATUS +EFIAPI +ReadDisk ( + IN EFI_DISK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN UINT64 Offset, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + UDF_TEST_PRIVATE *Private; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_BLOCK_IO_MEDIA *Media; + UINT32 BlockSize; + UINT64 Lba; + UINT64 OverRunLba; + UINT32 UnderRun; + UINT32 OverRun; + BOOLEAN TransactionComplete; + UINTN WorkingBufferSize; + UINT8 *WorkingBuffer; + UINTN Length; + UINT8 *Data; + UINT8 *PreData; + UINTN IsBufferAligned; + UINTN DataBufferSize; + BOOLEAN LastRead; + + Private = UDF_TEST_PRIVATE_FROM_DISK_IO (This); + + BlockIo = &Private->BlockIo; + Media = BlockIo->Media; + BlockSize = Media->BlockSize; + + if (Media->MediaId != MediaId) { + return EFI_MEDIA_CHANGED; + } + + WorkingBuffer = Buffer; + WorkingBufferSize = BufferSize; + + // + // Allocate a temporary buffer for operation + // + DataBufferSize = BlockSize * DATA_BUFFER_BLOCK_NUM; + + if (Media->IoAlign > 1) { + PreData = AllocatePool (DataBufferSize + Media->IoAlign); + Data = PreData - ((UINTN) PreData & (Media->IoAlign - 1)) + Media->IoAlign; + } else { + PreData = AllocatePool (DataBufferSize); + Data = PreData; + } + + if (PreData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Lba = DivU64x32Remainder (Offset, BlockSize, &UnderRun); + + Length = BlockSize - UnderRun; + TransactionComplete = FALSE; + + Status = EFI_SUCCESS; + if (UnderRun != 0) { + // + // Offset starts in the middle of an Lba, so read the entire block. + // + Status = BlockIo->ReadBlocks ( + BlockIo, + MediaId, + Lba, + BlockSize, + Data + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + if (Length > BufferSize) { + Length = BufferSize; + TransactionComplete = TRUE; + } + + CopyMem (WorkingBuffer, Data + UnderRun, Length); + + WorkingBuffer += Length; + + WorkingBufferSize -= Length; + if (WorkingBufferSize == 0) { + goto Done; + } + + Lba += 1; + } + + OverRunLba = Lba + DivU64x32Remainder (WorkingBufferSize, BlockSize, &OverRun); + + if (!TransactionComplete && WorkingBufferSize >= BlockSize) { + // + // If the DiskIo maps directly to a BlockIo device do the read. + // + if (OverRun != 0) { + WorkingBufferSize -= OverRun; + } + // + // Check buffer alignment + // + IsBufferAligned = (UINTN) WorkingBuffer & (UINTN) (Media->IoAlign - 1); + + if (Media->IoAlign <= 1 || IsBufferAligned == 0) { + // + // Alignment is satisfied, so read them together + // + Status = BlockIo->ReadBlocks ( + BlockIo, + MediaId, + Lba, + WorkingBufferSize, + WorkingBuffer + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + WorkingBuffer += WorkingBufferSize; + + } else { + // + // Use the allocated buffer instead of the original buffer + // to avoid alignment issue. + // Here, the allocated buffer (8-byte align) can satisfy the alignment + // + LastRead = FALSE; + do { + if (WorkingBufferSize <= DataBufferSize) { + // + // It is the last calling to readblocks in this loop + // + DataBufferSize = WorkingBufferSize; + LastRead = TRUE; + } + + Status = BlockIo->ReadBlocks ( + BlockIo, + MediaId, + Lba, + DataBufferSize, + Data + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + CopyMem (WorkingBuffer, Data, DataBufferSize); + WorkingBufferSize -= DataBufferSize; + WorkingBuffer += DataBufferSize; + Lba += DATA_BUFFER_BLOCK_NUM; + } while (!LastRead); + } + } + + if (!TransactionComplete && OverRun != 0) { + // + // Last read is not a complete block. + // + Status = BlockIo->ReadBlocks ( + BlockIo, + MediaId, + OverRunLba, + BlockSize, + Data + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + CopyMem (WorkingBuffer, Data, OverRun); + } + +Done: + if (PreData != NULL) { + FreePool (PreData); + } + + return Status; +} + +/** + Writes a specified number of bytes to a device. + + @param This Indicates a pointer to the calling context. + @param MediaId ID of the medium to be written. + @param Offset The starting byte offset on the logical block I/O device to write. + @param BufferSize The size in bytes of Buffer. The number of bytes to write to the device. + @param Buffer A pointer to the buffer containing the data to be written. + + @retval EFI_SUCCESS The data was written correctly to the device. + @retval EFI_WRITE_PROTECTED The device can not be written to. + @retval EFI_DEVICE_ERROR The device reported an error while performing the write. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device. + @retval EFI_INVALID_PARAMETER The write request contains device addresses that are not + valid for the device. + +**/ +EFI_STATUS +EFIAPI +WriteDisk ( + IN EFI_DISK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN UINT64 Offset, + IN UINTN BufferSize, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + UDF_TEST_PRIVATE *Private; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_BLOCK_IO_MEDIA *Media; + UINT32 BlockSize; + UINT64 Lba; + UINT64 OverRunLba; + UINT32 UnderRun; + UINT32 OverRun; + BOOLEAN TransactionComplete; + UINTN WorkingBufferSize; + UINT8 *WorkingBuffer; + UINTN Length; + UINT8 *Data; + UINT8 *PreData; + UINTN IsBufferAligned; + UINTN DataBufferSize; + BOOLEAN LastWrite; + + Private = UDF_TEST_PRIVATE_FROM_DISK_IO (This); + + BlockIo = &Private->BlockIo; + Media = BlockIo->Media; + BlockSize = Media->BlockSize; + + if (Media->ReadOnly) { + return EFI_WRITE_PROTECTED; + } + + if (Media->MediaId != MediaId) { + return EFI_MEDIA_CHANGED; + } + + DataBufferSize = BlockSize * DATA_BUFFER_BLOCK_NUM; + + if (Media->IoAlign > 1) { + PreData = AllocatePool (DataBufferSize + Media->IoAlign); + Data = PreData - ((UINTN) PreData & (Media->IoAlign - 1)) + Media->IoAlign; + } else { + PreData = AllocatePool (DataBufferSize); + Data = PreData; + } + + if (PreData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + WorkingBuffer = Buffer; + WorkingBufferSize = BufferSize; + + Lba = DivU64x32Remainder (Offset, BlockSize, &UnderRun); + + Length = BlockSize - UnderRun; + TransactionComplete = FALSE; + + Status = EFI_SUCCESS; + if (UnderRun != 0) { + // + // Offset starts in the middle of an Lba, so do read modify write. + // + Status = BlockIo->ReadBlocks ( + BlockIo, + MediaId, + Lba, + BlockSize, + Data + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + if (Length > BufferSize) { + Length = BufferSize; + TransactionComplete = TRUE; + } + + CopyMem (Data + UnderRun, WorkingBuffer, Length); + + Status = BlockIo->WriteBlocks ( + BlockIo, + MediaId, + Lba, + BlockSize, + Data + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + WorkingBuffer += Length; + WorkingBufferSize -= Length; + if (WorkingBufferSize == 0) { + goto Done; + } + + Lba += 1; + } + + OverRunLba = Lba + DivU64x32Remainder (WorkingBufferSize, BlockSize, &OverRun); + + if (!TransactionComplete && WorkingBufferSize >= BlockSize) { + // + // If the DiskIo maps directly to a BlockIo device do the write. + // + if (OverRun != 0) { + WorkingBufferSize -= OverRun; + } + // + // Check buffer alignment + // + IsBufferAligned = (UINTN) WorkingBuffer & (UINTN) (Media->IoAlign - 1); + + if (Media->IoAlign <= 1 || IsBufferAligned == 0) { + // + // Alignment is satisfied, so write them together + // + Status = BlockIo->WriteBlocks ( + BlockIo, + MediaId, + Lba, + WorkingBufferSize, + WorkingBuffer + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + WorkingBuffer += WorkingBufferSize; + + } else { + // + // The buffer parameter is not aligned with the request + // So use the allocated instead. + // It can fit almost all the cases. + // + LastWrite = FALSE; + do { + if (WorkingBufferSize <= DataBufferSize) { + // + // It is the last calling to writeblocks in this loop + // + DataBufferSize = WorkingBufferSize; + LastWrite = TRUE; + } + + CopyMem (Data, WorkingBuffer, DataBufferSize); + Status = BlockIo->WriteBlocks ( + BlockIo, + MediaId, + Lba, + DataBufferSize, + Data + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + WorkingBufferSize -= DataBufferSize; + WorkingBuffer += DataBufferSize; + Lba += DATA_BUFFER_BLOCK_NUM; + } while (!LastWrite); + } + } + + if (!TransactionComplete && OverRun != 0) { + // + // Last bit is not a complete block, so do a read modify write. + // + Status = BlockIo->ReadBlocks ( + BlockIo, + MediaId, + OverRunLba, + BlockSize, + Data + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + CopyMem (Data, WorkingBuffer, OverRun); + + Status = BlockIo->WriteBlocks ( + BlockIo, + MediaId, + OverRunLba, + BlockSize, + Data + ); + if (EFI_ERROR (Status)) { + goto Done; + } + } + +Done: + if (PreData != NULL) { + FreePool (PreData); + } + + return Status; +} + +UDF_TEST_PRIVATE mUdfTestPrivate = { + UDF_TEST_PRIVATE_SIGNATURE, + { + EFI_BLOCK_IO_PROTOCOL_REVISION, + &mUdfTestPrivate.Media, + Reset, + ReadBlocks, + WriteBlocks, + FlushBlocks, + }, + { + 0, // MediaId; + FALSE, // RemovableMedia; + TRUE, // MediaPresent; + FALSE, // LogicalPartition; + FALSE, // ReadOnly; + FALSE, // WriteCaching; + 0, // BlockSize; + 1, // IoAlign; + 0, // LastBlock; + 0, // LowestAlignedLba; + 0, // LogicalBlocksPerPhysicalBlock; + 0, // OptimalTransferLengthGranularity; + }, + { + EFI_DISK_IO_PROTOCOL_REVISION, + ReadDisk, + WriteDisk, + }, + 0, // StartingAddr + 0, // Size +}; + +EFI_STATUS +EFIAPI +DiskStubInitialize ( + IN VOID *Buffer, + IN UINTN BufferSize, + IN UINT32 BlockSize, + IN UINT32 IoAlign, + OUT EFI_BLOCK_IO_PROTOCOL **BlockIo, + OUT EFI_DISK_IO_PROTOCOL **DiskIo + ) +{ + UdfTestPrivate = AllocatePool (sizeof(UDF_TEST_PRIVATE)); + CopyMem (UdfTestPrivate, &mUdfTestPrivate, sizeof(UDF_TEST_PRIVATE)); + + UdfTestPrivate->BlockIo.Media = &UdfTestPrivate->Media; + + UdfTestPrivate->StartingAddr = (UINTN)Buffer; + UdfTestPrivate->Size = BufferSize; + + UdfTestPrivate->Media.IoAlign = IoAlign; + UdfTestPrivate->Media.BlockSize = BlockSize; + UdfTestPrivate->Media.LastBlock = (BufferSize + BlockSize - 1) / BlockSize - 1; + + if (BlockIo != NULL) { + *BlockIo = &UdfTestPrivate->BlockIo; + } + if (DiskIo != NULL) { + *DiskIo = &UdfTestPrivate->DiskIo; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +DiskStubDestory ( + VOID + ) +{ + if (UdfTestPrivate != NULL) { + FreePool(UdfTestPrivate); + UdfTestPrivate = NULL; + } + + return EFI_SUCCESS; +} \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestStub/DiskStubLib/DiskStubLib.inf b/HBFA/UefiHostFuzzTestCasePkg/TestStub/DiskStubLib/DiskStubLib.inf new file mode 100644 index 0000000..9838e73 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestStub/DiskStubLib/DiskStubLib.inf @@ -0,0 +1,35 @@ +## @file +# Component description file for TestUdf module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DiskStubLib + FILE_GUID = 746FA64E-1095-44A6-BC15-5729E0335A49 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = DiskStubLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + DiskStubLib.c + +[Packages] + MdePkg/MdePkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestStub/Include/Library/DiskStubLib.h b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Include/Library/DiskStubLib.h new file mode 100644 index 0000000..03a7852 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Include/Library/DiskStubLib.h @@ -0,0 +1,32 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _DISK_STUB_LIB_H_ +#define _DISK_STUB_LIB_H_ + +#include +#include +#include + +EFI_STATUS +EFIAPI +DiskStubInitialize ( + IN VOID *Buffer, + IN UINTN BufferSize, + IN UINT32 BlockSize, + IN UINT32 IoAlign, + OUT EFI_BLOCK_IO_PROTOCOL **BlockIo, + OUT EFI_DISK_IO_PROTOCOL **DiskIo + ); + +EFI_STATUS +EFIAPI +DiskStubDestory ( + VOID + ); + +#endif diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestStub/Include/Library/SmmMemLibStubLib.h b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Include/Library/SmmMemLibStubLib.h new file mode 100644 index 0000000..8f6e84c --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Include/Library/SmmMemLibStubLib.h @@ -0,0 +1,25 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _SMM_MEM_LIB_LIB_LIB_H_ +#define _SMM_MEM_LIB_LIB_LIB_H_ + +#include + +typedef struct { + EFI_PHYSICAL_ADDRESS Address; + UINT64 Size; +} SMM_COMMUNICATION_BUFFER_DESCRIPTOR; + +VOID +EFIAPI +SmmMemLibInitialize ( + IN UINTN SmmCommBufferDescCount, + IN SMM_COMMUNICATION_BUFFER_DESCRIPTOR *SmmCommBufferDesc + ); + +#endif diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestStub/Include/Library/Tcg2StubLib.h b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Include/Library/Tcg2StubLib.h new file mode 100644 index 0000000..95f18d2 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Include/Library/Tcg2StubLib.h @@ -0,0 +1,12 @@ +#ifndef _TCG2_STUB_LIB_H_ +#define _TCG2_STUB_LIB_H_ + +#include + +EFI_STATUS +EFIAPI +Tcg2StubInitlize( + VOID +); + +#endif \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestStub/Include/Library/Tpm2DeviceStubLib.h b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Include/Library/Tpm2DeviceStubLib.h new file mode 100644 index 0000000..febc0e9 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Include/Library/Tpm2DeviceStubLib.h @@ -0,0 +1,20 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _TPM2_DEVICE_STUB_LIB_H_ +#define _TPM2_DEVICE_STUB_LIB_H_ + +#include + +EFI_STATUS +EFIAPI +Tpm2ResponseInitialize ( + IN VOID *Buffer, + IN UINTN BufferSize + ); + +#endif diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestStub/Include/Library/Usb2HcPpiStubLib.h b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Include/Library/Usb2HcPpiStubLib.h new file mode 100644 index 0000000..073bf8a --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Include/Library/Usb2HcPpiStubLib.h @@ -0,0 +1,26 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _USB2_HC_PPI_STUB_LIB_H_ +#define _USB2_HC_PPI_STUB_LIB_H_ + +#include +#include + +EFI_STATUS +EFIAPI +Usb2HcPpiStubInitialize ( + IN VOID *DeviceDescBuffer, + IN UINTN DeviceDescBufferSize, + IN VOID *ConfigDescBuffer, + IN UINTN ConfigDescBufferSize, + IN VOID *StringDescBuffer, + IN UINTN StringDescBufferSize, + OUT PEI_USB2_HOST_CONTROLLER_PPI **Usb2HcPpi + ); + +#endif diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestStub/Include/Library/Usb2HcStubLib.h b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Include/Library/Usb2HcStubLib.h new file mode 100644 index 0000000..1a61b20 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Include/Library/Usb2HcStubLib.h @@ -0,0 +1,26 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _USB2_HC_STUB_LIB_H_ +#define _USB2_HC_STUB_LIB_H_ + +#include +#include + +EFI_STATUS +EFIAPI +Usb2HcStubInitialize ( + IN VOID *DeviceDescBuffer, + IN UINTN DeviceDescBufferSize, + IN VOID *ConfigDescBuffer, + IN UINTN ConfigDescBufferSize, + IN VOID *StringDescBuffer, + IN UINTN StringDescBufferSize, + OUT EFI_USB2_HC_PROTOCOL **Usb2Hc + ); + +#endif diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestStub/Include/Library/UsbIoPpiStubLib.h b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Include/Library/UsbIoPpiStubLib.h new file mode 100644 index 0000000..0549b61 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Include/Library/UsbIoPpiStubLib.h @@ -0,0 +1,26 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _USB_IO_PPI_STUB_LIB_H_ +#define _USB_IO_PPI_STUB_LIB_H_ + +#include +#include + +EFI_STATUS +EFIAPI +UsbIoPpiStubInitialize ( + IN VOID *DeviceDescBuffer, + IN UINTN DeviceDescBufferSize, + IN VOID *ConfigDescBuffer, + IN UINTN ConfigDescBufferSize, + IN VOID *StringDescBuffer, + IN UINTN StringDescBufferSize, + OUT PEI_USB_IO_PPI **UsbIoPpi + ); + +#endif diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestStub/Include/Library/VirtioBlkStubLib.h b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Include/Library/VirtioBlkStubLib.h new file mode 100644 index 0000000..8eaeb4e --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Include/Library/VirtioBlkStubLib.h @@ -0,0 +1,41 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _VIRTIOBLK_STUB_LIB_H_ +#define _VIRTIOBLK_STUB_LIB_H_ + +#include + +#include +#include + +#define VBLK_SIG SIGNATURE_32 ('V', 'B', 'L', 'K') + +typedef struct { + // + // Parts of this structure are initialized / torn down in various functions + // at various call depths. The table to the right should make it easier to + // track them. + // + // field init function init dpth + // --------------------- ------------------ --------- + UINT32 Signature; // DriverBindingStart 0 + VIRTIO_DEVICE_PROTOCOL *VirtIo; // DriverBindingStart 0 + EFI_EVENT ExitBoot; // DriverBindingStart 0 + VRING Ring; // VirtioRingInit 2 + EFI_BLOCK_IO_PROTOCOL BlockIo; // VirtioBlkInit 1 + EFI_BLOCK_IO_MEDIA BlockIoMedia; // VirtioBlkInit 1 + VOID *RingMap; // VirtioRingMap 2 +} VBLK_DEV; + +EFI_STATUS +EFIAPI +VirtioBlkInit ( + IN OUT VBLK_DEV *Dev +); + +#endif \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestStub/Include/Library/VirtioPciDeviceStubLib.h b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Include/Library/VirtioPciDeviceStubLib.h new file mode 100644 index 0000000..5529771 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Include/Library/VirtioPciDeviceStubLib.h @@ -0,0 +1,152 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _VIRTIOPCI_DEV_STUB_LIB_H_ +#define _VIRTIOPCI_DEV_STUB_LIB_H_ + +#include +#include +#include + +#include +#include + + +#define VIRTIO_1_0_SIGNATURE SIGNATURE_32 ('V', 'I', 'O', '1') + +#define VIRTIO_PCI_DEVICE_SIGNATURE SIGNATURE_32 ('V', 'P', 'C', 'I') + +// +// Type of the PCI BAR that contains a VirtIo 1.0 config structure. +// +typedef enum { + Virtio10BarTypeMem, + Virtio10BarTypeIo +} VIRTIO_1_0_BAR_TYPE; + +// +// The type below defines the access to a VirtIo 1.0 config structure. +// +typedef struct { + BOOLEAN Exists; // The device exposes this structure + VIRTIO_1_0_BAR_TYPE BarType; + UINT8 Bar; + UINT32 Offset; // Offset into BAR where structure starts + UINT32 Length; // Length of structure in BAR. + UINT64 ConfigBase; +} VIRTIO_1_0_CONFIG; + +typedef struct { + UINT32 Signature; + VIRTIO_DEVICE_PROTOCOL VirtIo; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT64 OriginalPciAttributes; + VIRTIO_1_0_CONFIG CommonConfig; // Common settings + VIRTIO_1_0_CONFIG NotifyConfig; // Notifications + UINT32 NotifyOffsetMultiplier; + VIRTIO_1_0_CONFIG SpecificConfig; // Device specific settings +} VIRTIO_1_0_DEV; + +#define VIRTIO_1_0_FROM_VIRTIO_DEVICE(Device) \ + CR (Device, VIRTIO_1_0_DEV, VirtIo, VIRTIO_1_0_SIGNATURE) + +typedef struct { + VIRTIO_PCI_CAP Cap; + UINT32 Notify_Off_Multiplier; +} VIRTIO_PCI_NOTIFY_CAP; + +typedef struct +{ + PCI_TYPE00 PciBasicCfg; + UINT8 Element[0x100 - sizeof(PCI_TYPE00)]; + } PCI_CFG_SPACE; + +// Virtio 1.0 +typedef struct { + UINT32 Device_Feature_Select; + UINT32 Device_Feature; + UINT32 Driver_Feature_Select; + UINT32 Driver_Feature; + UINT16 Msix_Config; + UINT16 Num_Queues; + UINT8 Device_Status; + UINT8 Config_Generation; + UINT16 Queue_Select; + UINT16 Queue_Size; + UINT16 Queue_Msix_Vector; + UINT16 Queue_Enable; + UINT16 Queue_Notify_Off; + UINT64 Queue_Desc; + UINT64 Queue_Avail; + UINT64 Queue_Used; +} VIRTIO_PCI_CAP_COMMON_CONFIG; + +// Virtio 0.9.5 +typedef struct { + UINT32 Device_Features; + UINT32 Guest_Features; + UINT32 Queue_Address; + UINT16 Queue_Size; + UINT16 Queue_Select; + UINT16 Queue_Notify; + UINT8 Device_Status; + UINT8 ISR_Status; +} VIRTIO_HDR; + +EFI_STATUS +GetBarType ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT8 BarIndex, + OUT VIRTIO_1_0_BAR_TYPE *BarType + ); + +EFI_STATUS +EFIAPI +InitVirtioPciDevice ( + IN OUT VIRTIO_1_0_DEV *Device, + IN UINT8 *TestBuffer, + IN UINTN BufferSize, + IN EFI_PCI_IO_PROTOCOL *PciIo +); + + +EFI_STATUS +EFIAPI +ParseBufferAndInitVirtioPciDev10 ( + IN UINT8 *TestBuffer, + IN UINTN BufferSize, + IN VOID *ConfigRegion, + IN OUT VIRTIO_1_0_DEV *Device +); + +// Virtio 0.9.5 +typedef struct { + UINT32 Signature; + VIRTIO_DEVICE_PROTOCOL VirtioDevice; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT64 OriginalPciAttributes; + UINT32 DeviceSpecificConfigurationOffset; +} VIRTIO_PCI_DEVICE; + +EFI_STATUS +EFIAPI +InitVirtioPciDev ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN VOID *ConfigRegion, + IN OUT VIRTIO_PCI_DEVICE *Device +); + +EFI_STATUS +EFIAPI +ParseBufferAndInitVirtioPciDev ( + IN UINT8 *TestBuffer, + IN UINTN BufferSize, + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN VOID *ConfigRegion, + IN OUT VIRTIO_PCI_DEVICE *Device +); +#endif \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestStub/Tcg2StubLib/Tcg2StubLib.c b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Tcg2StubLib/Tcg2StubLib.c new file mode 100644 index 0000000..f9e92a7 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Tcg2StubLib/Tcg2StubLib.c @@ -0,0 +1,318 @@ +/** @file + +Copyright (c) 2021, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/** + Add a new entry to the Event Log. + + @param[in] DigestList A list of digest. + @param[in,out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure. + @param[in] NewEventData Pointer to the new event data. + + @retval EFI_SUCCESS The new event log entry was added. + @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event. +**/ +EFI_STATUS +TcgDxeLogHashEvent ( + IN TPML_DIGEST_VALUES *DigestList, + IN OUT TCG_PCR_EVENT_HDR *NewEventHdr, + IN UINT8 *NewEventData + ) +{ + + return EFI_SUCCESS; +} + +/** + Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result, + and add an entry to the Event Log. + + @param[in] Flags Bitmap providing additional information. + @param[in] HashData Physical address of the start of the data buffer + to be hashed, extended, and logged. + @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData + @param[in, out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure. + @param[in] NewEventData Pointer to the new event data. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event. + @retval EFI_DEVICE_ERROR The command was unsuccessful. + +**/ +EFI_STATUS +TcgDxeHashLogExtendEvent ( + IN UINT64 Flags, + IN UINT8 *HashData, + IN UINT64 HashDataLen, + IN OUT TCG_PCR_EVENT_HDR *NewEventHdr, + IN UINT8 *NewEventData + ) +{ + + + return EFI_SUCCESS; +} + +/** + The EFI_TCG2_PROTOCOL HashLogExtendEvent function call provides callers with + an opportunity to extend and optionally log events without requiring + knowledge of actual TPM commands. + The extend operation will occur even if this function cannot create an event + log entry (e.g. due to the event log being full). + + @param[in] This Indicates the calling context + @param[in] Flags Bitmap providing additional information. + @param[in] DataToHash Physical address of the start of the data buffer to be hashed. + @param[in] DataToHashLen The length in bytes of the buffer referenced by DataToHash. + @param[in] Event Pointer to data buffer containing information about the event. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_DEVICE_ERROR The command was unsuccessful. + @retval EFI_VOLUME_FULL The extend operation occurred, but the event could not be written to one or more event logs. + @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect. + @retval EFI_UNSUPPORTED The PE/COFF image type is not supported. +**/ +EFI_STATUS +EFIAPI +Tcg2HashLogExtendEvent ( + IN EFI_TCG2_PROTOCOL *This, + IN UINT64 Flags, + IN EFI_PHYSICAL_ADDRESS DataToHash, + IN UINT64 DataToHashLen, + IN EFI_TCG2_EVENT *Event + ) +{ + + return EFI_SUCCESS; +} + +/** + This service enables the sending of commands to the TPM. + TODO For TDVF the commands should be submitted to RTMR + + @param[in] This Indicates the calling context + @param[in] InputParameterBlockSize Size of the TPM input parameter block. + @param[in] InputParameterBlock Pointer to the TPM input parameter block. + @param[in] OutputParameterBlockSize Size of the TPM output parameter block. + @param[in] OutputParameterBlock Pointer to the TPM output parameter block. + + @retval EFI_SUCCESS The command byte stream was successfully sent to the device and a response was successfully received. + @retval EFI_DEVICE_ERROR The command was not successfully sent to the device or a response was not successfully received from the device. + @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect. + @retval EFI_BUFFER_TOO_SMALL The output parameter block is too small. +**/ +EFI_STATUS +EFIAPI +Tcg2SubmitCommand ( + IN EFI_TCG2_PROTOCOL *This, + IN UINT32 InputParameterBlockSize, + IN UINT8 *InputParameterBlock, + IN UINT32 OutputParameterBlockSize, + IN UINT8 *OutputParameterBlock + ) +{ + return EFI_SUCCESS; +} + +/** + This service returns the currently active PCR banks. + + @param[in] This Indicates the calling context + @param[out] ActivePcrBanks Pointer to the variable receiving the bitmap of currently active PCR banks. + + @retval EFI_SUCCESS The bitmap of active PCR banks was stored in the ActivePcrBanks parameter. + @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect. +**/ +EFI_STATUS +EFIAPI +Tcg2GetActivePCRBanks ( + IN EFI_TCG2_PROTOCOL *This, + OUT UINT32 *ActivePcrBanks + ) +{ + return EFI_SUCCESS; +} + +/** + This service sets the currently active PCR banks. + TODO Can PCR banks be set externally? + + @param[in] This Indicates the calling context + @param[in] ActivePcrBanks Bitmap of the requested active PCR banks. At least one bit SHALL be set. + + @retval EFI_SUCCESS The bitmap in ActivePcrBank parameter is already active. + @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect. +**/ +EFI_STATUS +EFIAPI +Tcg2SetActivePCRBanks ( + IN EFI_TCG2_PROTOCOL *This, + IN UINT32 ActivePcrBanks + ) +{ + + return EFI_SUCCESS; + +} + +/** + This service retrieves the result of a previous invocation of SetActivePcrBanks. + + @param[in] This Indicates the calling context + @param[out] OperationPresent Non-zero value to indicate a SetActivePcrBank operation was invoked during the last boot. + @param[out] Response The response from the SetActivePcrBank request. + + @retval EFI_SUCCESS The result value could be returned. + @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect. +**/ +EFI_STATUS +EFIAPI +Tcg2GetResultOfSetActivePcrBanks ( + IN EFI_TCG2_PROTOCOL *This, + OUT UINT32 *OperationPresent, + OUT UINT32 *Response + ) +{ + + return EFI_SUCCESS; +} +EFI_STATUS +EFIAPI +Tcg2GetCapability ( + IN EFI_TCG2_PROTOCOL *This, + IN OUT EFI_TCG2_BOOT_SERVICE_CAPABILITY *ProtocolCapability + ) +{ + return EFI_SUCCESS; +} + +/** + The EFI_TCG2_PROTOCOL Get Event Log function call allows a caller to + retrieve the address of a given event log and its last entry. + + @param[in] This Indicates the calling context + @param[in] EventLogFormat The type of the event log for which the information is requested. + @param[out] EventLogLocation A pointer to the memory address of the event log. + @param[out] EventLogLastEntry If the Event Log contains more than one entry, this is a pointer to the + address of the start of the last entry in the event log in memory. + @param[out] EventLogTruncated If the Event Log is missing at least one entry because an event would + have exceeded the area allocated for events, this value is set to TRUE. + Otherwise, the value will be FALSE and the Event Log will be complete. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect + (e.g. asking for an event log whose format is not supported). +**/ +EFI_STATUS +EFIAPI +Tcg2GetEventLog ( + IN EFI_TCG2_PROTOCOL *This, + IN EFI_TCG2_EVENT_LOG_FORMAT EventLogFormat, + OUT EFI_PHYSICAL_ADDRESS *EventLogLocation, + OUT EFI_PHYSICAL_ADDRESS *EventLogLastEntry, + OUT BOOLEAN *EventLogTruncated + ) +{ + return EFI_SUCCESS; +} +EFI_TCG2_PROTOCOL mTcg2Protocol = { + Tcg2GetCapability, + Tcg2GetEventLog, + Tcg2HashLogExtendEvent, + Tcg2SubmitCommand, + Tcg2GetActivePCRBanks, + Tcg2SetActivePCRBanks, + Tcg2GetResultOfSetActivePcrBanks, +}; + +EFI_STATUS +EFIAPI +CcGetCapability ( + IN EFI_CC_MEASUREMENT_PROTOCOL *This, + IN OUT EFI_CC_BOOT_SERVICE_CAPABILITY *ProtocolCapability + ) +{ + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +CcGetEventlog ( + IN EFI_CC_MEASUREMENT_PROTOCOL *This, + IN EFI_CC_EVENT_LOG_FORMAT EventLogFormat, + OUT EFI_PHYSICAL_ADDRESS *EventLogLocation, + OUT EFI_PHYSICAL_ADDRESS *EventLogLastEntry, + OUT BOOLEAN *EventLogTruncated + ) +{ + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +CcHashLogExtendEvent ( + IN EFI_CC_MEASUREMENT_PROTOCOL *This, + IN UINT64 Flags, + IN EFI_PHYSICAL_ADDRESS DataToHash, + IN UINT64 DataToHashLen, + IN EFI_CC_EVENT *EfiCcEvent + ) +{ + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +CcMapPcrToMrIndex ( + IN EFI_CC_MEASUREMENT_PROTOCOL *This, + IN TCG_PCRINDEX PcrIndex, + OUT EFI_CC_MR_INDEX *MrIndex + ) +{ + MrIndex = 0; + return EFI_SUCCESS; +} + +EFI_CC_MEASUREMENT_PROTOCOL mCcProtocol = { + CcGetCapability, + CcGetEventlog, + CcHashLogExtendEvent, + CcMapPcrToMrIndex, +}; + +EFI_STATUS +EFIAPI +Tcg2StubInitlize( + VOID +){ + EFI_STATUS Status; + EFI_HANDLE Handle; + + Handle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &Handle, + &gEfiTcg2ProtocolGuid, + &mTcg2Protocol, + &gEfiCcMeasurementProtocolGuid, + &mCcProtocol, + NULL + ); + return Status; + +} diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestStub/Tcg2StubLib/Tcg2StubLib.inf b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Tcg2StubLib/Tcg2StubLib.inf new file mode 100644 index 0000000..60f92f8 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Tcg2StubLib/Tcg2StubLib.inf @@ -0,0 +1,35 @@ +## @file +# Component description file for Tcg2StubLib. +# +# Copyright (c) 2021, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Tcg2StubLib + FILE_GUID = 520FA64E-1318-44A6-BC15-5729E0335A49 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = Tcg2StubLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + Tcg2StubLib.c + +[Packages] + MdePkg/MdePkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestStub/Tpm2DeviceLibStub/Tpm2DeviceLibStub.c b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Tpm2DeviceLibStub/Tpm2DeviceLibStub.c new file mode 100644 index 0000000..c6717bd --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Tpm2DeviceLibStub/Tpm2DeviceLibStub.c @@ -0,0 +1,72 @@ +/** @file + This library is TPM2 DTPM device lib. + Choosing this library means platform uses and only uses DTPM device as TPM2 engine. + +Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +VOID *mTpm2TestBuffer; +UINTN mTpm2TestBufferSize; + +/** + This service enables the sending of commands to the TPM2. + + @param[in] InputParameterBlockSize Size of the TPM2 input parameter block. + @param[in] InputParameterBlock Pointer to the TPM2 input parameter block. + @param[in,out] OutputParameterBlockSize Size of the TPM2 output parameter block. + @param[in] OutputParameterBlock Pointer to the TPM2 output parameter block. + + @retval EFI_SUCCESS The command byte stream was successfully sent to the device and a response was successfully received. + @retval EFI_DEVICE_ERROR The command was not successfully sent to the device or a response was not successfully received from the device. + @retval EFI_BUFFER_TOO_SMALL The output parameter block is too small. +**/ +EFI_STATUS +EFIAPI +Tpm2SubmitCommand ( + IN UINT32 InputParameterBlockSize, + IN UINT8 *InputParameterBlock, + IN OUT UINT32 *OutputParameterBlockSize, + IN UINT8 *OutputParameterBlock + ) +{ + if (*OutputParameterBlockSize > mTpm2TestBufferSize) { + *OutputParameterBlockSize = (UINT32)mTpm2TestBufferSize; + } + CopyMem (OutputParameterBlock, mTpm2TestBuffer, *OutputParameterBlockSize); + return EFI_SUCCESS; +} + +/** + This service requests use TPM2. + + @retval EFI_SUCCESS Get the control of TPM2 chip. + @retval EFI_NOT_FOUND TPM2 not found. + @retval EFI_DEVICE_ERROR Unexpected device behavior. +**/ +EFI_STATUS +EFIAPI +Tpm2RequestUseTpm ( + VOID + ) +{ + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +Tpm2ResponseInitialize ( + IN VOID *Buffer, + IN UINTN BufferSize + ) +{ + mTpm2TestBuffer = Buffer; + mTpm2TestBufferSize = BufferSize; + return EFI_SUCCESS; +} diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestStub/Tpm2DeviceLibStub/Tpm2DeviceLibStub.inf b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Tpm2DeviceLibStub/Tpm2DeviceLibStub.inf new file mode 100644 index 0000000..383ce77 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Tpm2DeviceLibStub/Tpm2DeviceLibStub.inf @@ -0,0 +1,34 @@ +## @file +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Tpm2DeviceLibStub + FILE_GUID = E54A3327-A345-4068-8842-70AC0D519855 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = Tpm2DeviceLib + LIBRARY_CLASS = Tpm2DeviceStubLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + Tpm2DeviceLibStub.c + +[Packages] + MdePkg/MdePkg.dec + SecurityPkg/SecurityPkg.dec + UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestStub/Usb2HcPpiStubLib/Usb2HcPpiStubLib.c b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Usb2HcPpiStubLib/Usb2HcPpiStubLib.c new file mode 100644 index 0000000..229fb27 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Usb2HcPpiStubLib/Usb2HcPpiStubLib.c @@ -0,0 +1,369 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +#include +#include +#include +#include + +VOID *mDeviceDescBuffer; +UINTN mDeviceDescBufferSize; +VOID *mConfigDescBuffer; +UINTN mConfigDescBufferSize; +VOID *mStringDescBuffer; +UINTN mStringDescBufferSize; + +// +// USB Keyboard example +// +USB_DEVICE_DESCRIPTOR mDeviceDesc = { + 0x12, // Length; + 0x01, // DescriptorType; - USB_DESC_TYPE_DEVICE + 0x0110, // BcdUSB; + 0x00, // DeviceClass; + 0x00, // DeviceSubClass; + 0x00, // DeviceProtocol; + 0x08, // MaxPacketSize0; + 0x03F0, // IdVendor; + 0x0325, // IdProduct; + 0x0103, // BcdDevice; + 0x01, // StrManufacturer; + 0x02, // StrProduct; + 0x00, // StrSerialNumber; + 0x01, // NumConfigurations; +}; + +typedef struct { + USB_CONFIG_DESCRIPTOR ConfigDesc; + USB_INTERFACE_DESCRIPTOR InterfaceDesc; + EFI_USB_HID_DESCRIPTOR HidDesc; + USB_ENDPOINT_DESCRIPTOR EndpointDesc; +} FULL_USB_CONFIG_DESCRIPTOR; + +FULL_USB_CONFIG_DESCRIPTOR mConfigDesc = { + { + 0x09, // Length; + 0x02, // DescriptorType; - USB_DESC_TYPE_CONFIG + 0x0022, // TotalLength; + 0x01, // NumInterfaces; + 0x01, // ConfigurationValue; + 0x00, // Configuration; + 0xA0, // Attributes; + 0x32, // MaxPower; + }, + { + 0x09, // Length; + 0x04, // DescriptorType; - USB_DESC_TYPE_INTERFACE + 0x00, // InterfaceNumber; + 0x00, // AlternateSetting; + 0x01, // NumEndpoints; + 0x03, // InterfaceClass; + 0x01, // InterfaceSubClass; + 0x01, // InterfaceProtocol; + 0x00, // Interface; + }, + { + 0x09, // Length; + 0x21, // DescriptorType; - USB_DESC_TYPE_HID + 0x0110, // BcdHID; + 0x00, // CountryCode; + 0x01, // NumDescriptors; + {{0x22, 0x0041}}, // HidClassDesc[0]; + }, + { + 0x07, // Length; + 0x05, // DescriptorType; - USB_DESC_TYPE_ENDPOINT + 0x81, // EndpointAddress; + 0x03, // Attributes; + 0x0008, // MaxPacketSize; + 0x0A, // Interval; + }, +}; + +EFI_USB_STRING_DESCRIPTOR mStringDesc = { + 0x04, // Length; + 0x03, // DescriptorType; - USB_DESC_TYPE_STRING + {0x0409}, // String[0]; +}; + +typedef struct { + UINT8 Length; + UINT8 DescriptorType; + CHAR16 String[4]; +} FULL_EFI_USB_STRING_DESCRIPTOR; + +FULL_EFI_USB_STRING_DESCRIPTOR mStringDesc_2 = { + 0x0A, // Length; + 0x03, // DescriptorType; - USB_DESC_TYPE_STRING + {0x2000, 0x2000, 0x2000, 0x2000}, // String +}; + +// +// USB Key example +// +USB_DEVICE_DESCRIPTOR mDeviceDesc2 = { + 0x12, // Length; + 0x01, // DescriptorType; - USB_DESC_TYPE_DEVICE + 0x0200, // BcdUSB; + 0x00, // DeviceClass; + 0x00, // DeviceSubClass; + 0x00, // DeviceProtocol; + 0x40, // MaxPacketSize0; + 0x0781, // IdVendor; + 0x5151, // IdProduct; + 0x0010, // BcdDevice; + 0x01, // StrManufacturer; + 0x02, // StrProduct; + 0x03, // StrSerialNumber; + 0x01, // NumConfigurations; +}; + +typedef struct { + USB_CONFIG_DESCRIPTOR ConfigDesc; + USB_INTERFACE_DESCRIPTOR InterfaceDesc; + USB_ENDPOINT_DESCRIPTOR EndpointDesc1; + USB_ENDPOINT_DESCRIPTOR EndpointDesc2; +} FULL_USB_CONFIG_DESCRIPTOR2; + +FULL_USB_CONFIG_DESCRIPTOR2 mConfigDesc2 = { + { + 0x09, // Length; + 0x02, // DescriptorType; - USB_DESC_TYPE_CONFIG + 0x0020, // TotalLength; + 0x01, // NumInterfaces; + 0x01, // ConfigurationValue; + 0x00, // Configuration; + 0x80, // Attributes; + 0x64, // MaxPower; + }, + { + 0x09, // Length; + 0x04, // DescriptorType; - USB_DESC_TYPE_INTERFACE + 0x00, // InterfaceNumber; + 0x00, // AlternateSetting; + 0x02, // NumEndpoints; + 0x08, // InterfaceClass; + 0x06, // InterfaceSubClass; + 0x50, // InterfaceProtocol; + 0x00, // Interface; + }, + { + 0x07, // Length; + 0x05, // DescriptorType; - USB_DESC_TYPE_ENDPOINT + 0x81, // EndpointAddress; + 0x02, // Attributes; + 0x0200, // MaxPacketSize; + 0x00, // Interval; + }, + { + 0x07, // Length; + 0x05, // DescriptorType; - USB_DESC_TYPE_ENDPOINT + 0x01, // EndpointAddress; + 0x02, // Attributes; + 0x0200, // MaxPacketSize; + 0x01, // Interval; + }, +}; + +EFI_USB_STRING_DESCRIPTOR mStringDesc2 = { + 0x04, // Length; + 0x03, // DescriptorType; - USB_DESC_TYPE_STRING + {0x0409}, // String[0]; +}; + +typedef struct { + UINT8 Length; + UINT8 DescriptorType; + CHAR16 String[4]; +} FULL_EFI_USB_STRING_DESCRIPTOR2; + +FULL_EFI_USB_STRING_DESCRIPTOR2 mStringDesc2_2 = { + 0x0A, // Length; + 0x03, // DescriptorType; - USB_DESC_TYPE_STRING + {0x2000, 0x2000, 0x2000, 0x2000}, // String +}; + +EFI_STATUS +EFIAPI +Usb2HcPpiStubControlTransfer ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_USB2_HOST_CONTROLLER_PPI *This, + IN UINT8 DeviceAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN USB_DEVICE_REQUEST *Request, + IN EFI_USB_DATA_DIRECTION TransferDirection, + IN OUT VOID *Data OPTIONAL, + IN OUT UINTN *DataLength OPTIONAL, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +{ + DEBUG ((DEBUG_INFO, "USB_STUB: ControlTransfer\n")); + + if ((TransferDirection == EfiUsbDataIn) && + (Request->RequestType == 0x80) && + (Request->Request == USB_REQ_GET_DESCRIPTOR)) { + switch (Request->Value >> 8) { + case USB_DESC_TYPE_DEVICE: + DEBUG ((DEBUG_INFO, "DEVICE - 0x%x\n", *DataLength)); + if (mDeviceDescBuffer != NULL) { + if (*DataLength > mDeviceDescBufferSize) { + *DataLength = mDeviceDescBufferSize; + } + CopyMem (Data, mDeviceDescBuffer, *DataLength); + } else { + if (*DataLength > sizeof(mDeviceDesc)) { + *DataLength = sizeof(mDeviceDesc); + } + CopyMem (Data, &mDeviceDesc, *DataLength); + } + break; + case USB_DESC_TYPE_CONFIG: + DEBUG ((DEBUG_INFO, "CONFIG - 0x%x\n", *DataLength)); + if (mConfigDescBuffer != NULL) { + if (*DataLength > mConfigDescBufferSize) { + *DataLength = mConfigDescBufferSize; + } + CopyMem (Data, mConfigDescBuffer, *DataLength); + } else { + if (*DataLength > sizeof(mConfigDesc)) { + *DataLength = sizeof(mConfigDesc); + } + CopyMem (Data, &mConfigDesc, *DataLength); + } + break; + case USB_DESC_TYPE_STRING: + DEBUG ((DEBUG_INFO, "STRING - 0x%x\n", *DataLength)); + if (mStringDescBuffer != NULL) { + if (*DataLength > mStringDescBufferSize) { + *DataLength = mStringDescBufferSize; + } + CopyMem (Data, mStringDescBuffer, *DataLength); + } else { + if (*DataLength > sizeof(mStringDesc)) { + *DataLength = sizeof(mStringDesc); + } + CopyMem (Data, &mStringDesc, *DataLength); + } + break; + } + } + + *TransferResult = EFI_USB_NOERROR; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +Usb2HcPpiStubBulkTransfer ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_USB2_HOST_CONTROLLER_PPI *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM], + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +{ + DEBUG ((DEBUG_INFO, "USB_STUB: BulkTransfer\n")); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +Usb2HcPpiStubGetRootHubPortNumber ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_USB2_HOST_CONTROLLER_PPI *This, + OUT UINT8 *PortNumber + ) +{ + DEBUG ((DEBUG_INFO, "USB_STUB: GetRootHubPortNumber\n")); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +Usb2HcPpiStubGetRootHubPortStatus ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_USB2_HOST_CONTROLLER_PPI *This, + IN UINT8 PortNumber, + OUT EFI_USB_PORT_STATUS *PortStatus + ) +{ + DEBUG ((DEBUG_INFO, "USB_STUB: GetRootHubPortStatus\n")); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +Usb2HcPpiStubSetRootHubPortFeature ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_USB2_HOST_CONTROLLER_PPI *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ) +{ + DEBUG ((DEBUG_INFO, "USB_STUB: SetRootHubPortFeature\n")); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +Usb2HcPpiStubClearRootHubPortFeature ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_USB2_HOST_CONTROLLER_PPI *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ) +{ + DEBUG ((DEBUG_INFO, "USB_STUB: ClearRootHubPortFeature\n")); + return EFI_UNSUPPORTED; +} + +PEI_USB2_HOST_CONTROLLER_PPI mUsb2HcPpiStub = { + Usb2HcPpiStubControlTransfer, + Usb2HcPpiStubBulkTransfer, + Usb2HcPpiStubGetRootHubPortNumber, + Usb2HcPpiStubGetRootHubPortStatus, + Usb2HcPpiStubSetRootHubPortFeature, + Usb2HcPpiStubClearRootHubPortFeature, +}; + +EFI_STATUS +EFIAPI +Usb2HcPpiStubInitialize ( + IN VOID *DeviceDescBuffer, + IN UINTN DeviceDescBufferSize, + IN VOID *ConfigDescBuffer, + IN UINTN ConfigDescBufferSize, + IN VOID *StringDescBuffer, + IN UINTN StringDescBufferSize, + OUT PEI_USB2_HOST_CONTROLLER_PPI **Usb2HcPpi + ) +{ + mDeviceDescBuffer = DeviceDescBuffer; + mDeviceDescBufferSize = DeviceDescBufferSize; + mConfigDescBuffer = ConfigDescBuffer; + mConfigDescBufferSize = ConfigDescBufferSize; + mStringDescBuffer = StringDescBuffer; + mStringDescBufferSize = StringDescBufferSize; + *Usb2HcPpi = &mUsb2HcPpiStub; + return EFI_SUCCESS; +} diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestStub/Usb2HcPpiStubLib/Usb2HcPpiStubLib.inf b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Usb2HcPpiStubLib/Usb2HcPpiStubLib.inf new file mode 100644 index 0000000..fd53093 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Usb2HcPpiStubLib/Usb2HcPpiStubLib.inf @@ -0,0 +1,36 @@ +## @file +# Component description file for TestUdf module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Usb2HcPpiStubLib + FILE_GUID = A139202F-6BAA-4ED9-95CF-C5267D50208F + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = Usb2HcPpiStubLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + Usb2HcPpiStubLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestStub/Usb2HcStubLib/Usb2HcStubLib.c b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Usb2HcStubLib/Usb2HcStubLib.c new file mode 100644 index 0000000..f0ad6bb --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Usb2HcStubLib/Usb2HcStubLib.c @@ -0,0 +1,485 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +#include +#include +#include +#include + +VOID *mDeviceDescBuffer; +UINTN mDeviceDescBufferSize; +VOID *mConfigDescBuffer; +UINTN mConfigDescBufferSize; +VOID *mStringDescBuffer; +UINTN mStringDescBufferSize; + +// +// USB Keyboard example +// +USB_DEVICE_DESCRIPTOR mDeviceDesc = { + 0x12, // Length; + 0x01, // DescriptorType; - USB_DESC_TYPE_DEVICE + 0x0110, // BcdUSB; + 0x00, // DeviceClass; + 0x00, // DeviceSubClass; + 0x00, // DeviceProtocol; + 0x08, // MaxPacketSize0; + 0x03F0, // IdVendor; + 0x0325, // IdProduct; + 0x0103, // BcdDevice; + 0x01, // StrManufacturer; + 0x02, // StrProduct; + 0x00, // StrSerialNumber; + 0x01, // NumConfigurations; +}; + +typedef struct { + USB_CONFIG_DESCRIPTOR ConfigDesc; + USB_INTERFACE_DESCRIPTOR InterfaceDesc; + EFI_USB_HID_DESCRIPTOR HidDesc; + USB_ENDPOINT_DESCRIPTOR EndpointDesc; +} FULL_USB_CONFIG_DESCRIPTOR; + +FULL_USB_CONFIG_DESCRIPTOR mConfigDesc = { + { + 0x09, // Length; + 0x02, // DescriptorType; - USB_DESC_TYPE_CONFIG + 0x0022, // TotalLength; + 0x01, // NumInterfaces; + 0x01, // ConfigurationValue; + 0x00, // Configuration; + 0xA0, // Attributes; + 0x32, // MaxPower; + }, + { + 0x09, // Length; + 0x04, // DescriptorType; - USB_DESC_TYPE_INTERFACE + 0x00, // InterfaceNumber; + 0x00, // AlternateSetting; + 0x01, // NumEndpoints; + 0x03, // InterfaceClass; + 0x01, // InterfaceSubClass; + 0x01, // InterfaceProtocol; + 0x00, // Interface; + }, + { + 0x09, // Length; + 0x21, // DescriptorType; - USB_DESC_TYPE_HID + 0x0110, // BcdHID; + 0x00, // CountryCode; + 0x01, // NumDescriptors; + {{0x22, 0x0041}}, // HidClassDesc[0]; + }, + { + 0x07, // Length; + 0x05, // DescriptorType; - USB_DESC_TYPE_ENDPOINT + 0x81, // EndpointAddress; + 0x03, // Attributes; + 0x0008, // MaxPacketSize; + 0x0A, // Interval; + }, +}; + +EFI_USB_STRING_DESCRIPTOR mStringDesc = { + 0x04, // Length; + 0x03, // DescriptorType; - USB_DESC_TYPE_STRING + {0x0409}, // String[0]; +}; + +typedef struct { + UINT8 Length; + UINT8 DescriptorType; + CHAR16 String[4]; +} FULL_EFI_USB_STRING_DESCRIPTOR; + +FULL_EFI_USB_STRING_DESCRIPTOR mStringDesc_2 = { + 0x0A, // Length; + 0x03, // DescriptorType; - USB_DESC_TYPE_STRING + {0x2000, 0x2000, 0x2000, 0x2000}, // String +}; + +// +// USB Key example +// +USB_DEVICE_DESCRIPTOR mDeviceDesc2 = { + 0x12, // Length; + 0x01, // DescriptorType; - USB_DESC_TYPE_DEVICE + 0x0200, // BcdUSB; + 0x00, // DeviceClass; + 0x00, // DeviceSubClass; + 0x00, // DeviceProtocol; + 0x40, // MaxPacketSize0; + 0x0781, // IdVendor; + 0x5151, // IdProduct; + 0x0010, // BcdDevice; + 0x01, // StrManufacturer; + 0x02, // StrProduct; + 0x03, // StrSerialNumber; + 0x01, // NumConfigurations; +}; + +typedef struct { + USB_CONFIG_DESCRIPTOR ConfigDesc; + USB_INTERFACE_DESCRIPTOR InterfaceDesc; + USB_ENDPOINT_DESCRIPTOR EndpointDesc1; + USB_ENDPOINT_DESCRIPTOR EndpointDesc2; +} FULL_USB_CONFIG_DESCRIPTOR2; + +FULL_USB_CONFIG_DESCRIPTOR2 mConfigDesc2 = { + { + 0x09, // Length; + 0x02, // DescriptorType; - USB_DESC_TYPE_CONFIG + 0x0020, // TotalLength; + 0x01, // NumInterfaces; + 0x01, // ConfigurationValue; + 0x00, // Configuration; + 0x80, // Attributes; + 0x64, // MaxPower; + }, + { + 0x09, // Length; + 0x04, // DescriptorType; - USB_DESC_TYPE_INTERFACE + 0x00, // InterfaceNumber; + 0x00, // AlternateSetting; + 0x02, // NumEndpoints; + 0x08, // InterfaceClass; + 0x06, // InterfaceSubClass; + 0x50, // InterfaceProtocol; + 0x00, // Interface; + }, + { + 0x07, // Length; + 0x05, // DescriptorType; - USB_DESC_TYPE_ENDPOINT + 0x81, // EndpointAddress; + 0x02, // Attributes; + 0x0200, // MaxPacketSize; + 0x00, // Interval; + }, + { + 0x07, // Length; + 0x05, // DescriptorType; - USB_DESC_TYPE_ENDPOINT + 0x01, // EndpointAddress; + 0x02, // Attributes; + 0x0200, // MaxPacketSize; + 0x01, // Interval; + }, +}; + +EFI_USB_STRING_DESCRIPTOR mStringDesc2 = { + 0x04, // Length; + 0x03, // DescriptorType; - USB_DESC_TYPE_STRING + {0x0409}, // String[0]; +}; + +typedef struct { + UINT8 Length; + UINT8 DescriptorType; + CHAR16 String[4]; +} FULL_EFI_USB_STRING_DESCRIPTOR2; + +FULL_EFI_USB_STRING_DESCRIPTOR2 mStringDesc2_2 = { + 0x0A, // Length; + 0x03, // DescriptorType; - USB_DESC_TYPE_STRING + {0x2000, 0x2000, 0x2000, 0x2000}, // String +}; + +EFI_STATUS +EFIAPI +Usb2HcStubGetCapability ( + IN EFI_USB2_HC_PROTOCOL *This, + OUT UINT8 *MaxSpeed, + OUT UINT8 *PortNumber, + OUT UINT8 *Is64BitCapable + ) +{ + DEBUG ((DEBUG_INFO, "USB_STUB: GetCapability\n")); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +Usb2HcStubReset ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT16 Attributes + ) +{ + DEBUG ((DEBUG_INFO, "USB_STUB: Reset\n")); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +Usb2HcStubGetState ( + IN EFI_USB2_HC_PROTOCOL *This, + OUT EFI_USB_HC_STATE *State + ) +{ + DEBUG ((DEBUG_INFO, "USB_STUB: GetState\n")); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +Usb2HcStubSetState ( + IN EFI_USB2_HC_PROTOCOL *This, + IN EFI_USB_HC_STATE State + ) +{ + DEBUG ((DEBUG_INFO, "USB_STUB: SetState\n")); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +Usb2HcStubControlTransfer ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN EFI_USB_DEVICE_REQUEST *Request, + IN EFI_USB_DATA_DIRECTION TransferDirection, + IN OUT VOID *Data OPTIONAL, + IN OUT UINTN *DataLength OPTIONAL, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +{ + DEBUG ((DEBUG_INFO, "USB_STUB: ControlTransfer\n")); + + if ((TransferDirection == EfiUsbDataIn) && + (Request->RequestType == 0x80) && + (Request->Request == USB_REQ_GET_DESCRIPTOR)) { + switch (Request->Value >> 8) { + case USB_DESC_TYPE_DEVICE: + DEBUG ((DEBUG_INFO, "DEVICE - 0x%x\n", *DataLength)); + if (mDeviceDescBuffer != NULL) { + if (*DataLength > mDeviceDescBufferSize) { + *DataLength = mDeviceDescBufferSize; + } + CopyMem (Data, mDeviceDescBuffer, *DataLength); + } else { + if (*DataLength > sizeof(mDeviceDesc)) { + *DataLength = sizeof(mDeviceDesc); + } + CopyMem (Data, &mDeviceDesc, *DataLength); + } + break; + case USB_DESC_TYPE_CONFIG: + DEBUG ((DEBUG_INFO, "CONFIG - 0x%x\n", *DataLength)); + if (mConfigDescBuffer != NULL) { + if (*DataLength > mConfigDescBufferSize) { + *DataLength = mConfigDescBufferSize; + } + CopyMem (Data, mConfigDescBuffer, *DataLength); + } else { + if (*DataLength > sizeof(mConfigDesc)) { + *DataLength = sizeof(mConfigDesc); + } + CopyMem (Data, &mConfigDesc, *DataLength); + } + break; + case USB_DESC_TYPE_STRING: + DEBUG ((DEBUG_INFO, "STRING - 0x%x\n", *DataLength)); + if (mStringDescBuffer != NULL) { + if (*DataLength > mStringDescBufferSize) { + *DataLength = mStringDescBufferSize; + } + CopyMem (Data, mStringDescBuffer, *DataLength); + } else { + if (*DataLength > sizeof(mStringDesc)) { + *DataLength = sizeof(mStringDesc); + } + CopyMem (Data, &mStringDesc, *DataLength); + } + break; + } + } + + *TransferResult = EFI_USB_NOERROR; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +Usb2HcStubBulkTransfer ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM], + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +{ + DEBUG ((DEBUG_INFO, "USB_STUB: BulkTransfer\n")); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +Usb2HcStubAsyncInterruptTransfer ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaxiumPacketLength, + IN BOOLEAN IsNewTransfer, + IN OUT UINT8 *DataToggle, + IN UINTN PollingInterval OPTIONAL, + IN UINTN DataLength OPTIONAL, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator OPTIONAL, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction OPTIONAL, + IN VOID *Context OPTIONAL + ) +{ + DEBUG ((DEBUG_INFO, "USB_STUB: AsyncInterruptTransfer\n")); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +Usb2HcStubSyncInterruptTransfer ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +{ + DEBUG ((DEBUG_INFO, "USB_STUB: SyncInterruptTransfer\n")); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +Usb2HcStubIsochronousTransfer ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM], + IN UINTN DataLength, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +{ + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +Usb2HcStubAsyncIsochronousTransfer ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM], + IN UINTN DataLength, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack, + IN VOID *Context OPTIONAL + ) +{ + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +Usb2HcStubGetRootHubPortStatus ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 PortNumber, + OUT EFI_USB_PORT_STATUS *PortStatus + ) +{ + DEBUG ((DEBUG_INFO, "USB_STUB: GetRootHubPortStatus\n")); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +Usb2HcStubSetRootHubPortFeature ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ) +{ + DEBUG ((DEBUG_INFO, "USB_STUB: SetRootHubPortFeature\n")); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +Usb2HcStubClearRootHubPortFeature ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ) +{ + DEBUG ((DEBUG_INFO, "USB_STUB: ClearRootHubPortFeature\n")); + return EFI_UNSUPPORTED; +} + +EFI_USB2_HC_PROTOCOL mUsb2HcStub = { + Usb2HcStubGetCapability, + Usb2HcStubReset, + Usb2HcStubGetState, + Usb2HcStubSetState, + Usb2HcStubControlTransfer, + Usb2HcStubBulkTransfer, + Usb2HcStubAsyncInterruptTransfer, + Usb2HcStubSyncInterruptTransfer, + Usb2HcStubIsochronousTransfer, + Usb2HcStubAsyncIsochronousTransfer, + Usb2HcStubGetRootHubPortStatus, + Usb2HcStubSetRootHubPortFeature, + Usb2HcStubClearRootHubPortFeature, + 0x2, + 0x0 +}; + +EFI_STATUS +EFIAPI +Usb2HcStubInitialize ( + IN VOID *DeviceDescBuffer, + IN UINTN DeviceDescBufferSize, + IN VOID *ConfigDescBuffer, + IN UINTN ConfigDescBufferSize, + IN VOID *StringDescBuffer, + IN UINTN StringDescBufferSize, + OUT EFI_USB2_HC_PROTOCOL **Usb2Hc + ) +{ + mDeviceDescBuffer = DeviceDescBuffer; + mDeviceDescBufferSize = DeviceDescBufferSize; + mConfigDescBuffer = ConfigDescBuffer; + mConfigDescBufferSize = ConfigDescBufferSize; + mStringDescBuffer = StringDescBuffer; + mStringDescBufferSize = StringDescBufferSize; + *Usb2Hc = &mUsb2HcStub; + return EFI_SUCCESS; +} diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestStub/Usb2HcStubLib/Usb2HcStubLib.inf b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Usb2HcStubLib/Usb2HcStubLib.inf new file mode 100644 index 0000000..8f0bbd0 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestStub/Usb2HcStubLib/Usb2HcStubLib.inf @@ -0,0 +1,35 @@ +## @file +# Component description file for TestUdf module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Usb2HcStubLib + FILE_GUID = A139202F-6BAA-4ED9-95CF-C5267D50208F + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = Usb2HcStubLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + Usb2HcStubLib.c + +[Packages] + MdePkg/MdePkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestStub/UsbIoPpiStubLib/UsbIoPpiStubLib.c b/HBFA/UefiHostFuzzTestCasePkg/TestStub/UsbIoPpiStubLib/UsbIoPpiStubLib.c new file mode 100644 index 0000000..fa44963 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestStub/UsbIoPpiStubLib/UsbIoPpiStubLib.c @@ -0,0 +1,340 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +#include +#include +#include +#include + +VOID *mDeviceDescBuffer; +UINTN mDeviceDescBufferSize; +VOID *mConfigDescBuffer; +UINTN mConfigDescBufferSize; +VOID *mStringDescBuffer; +UINTN mStringDescBufferSize; + +// +// USB Keyboard example +// +USB_DEVICE_DESCRIPTOR mDeviceDesc = { + 0x12, // Length; + 0x01, // DescriptorType; - USB_DESC_TYPE_DEVICE + 0x0110, // BcdUSB; + 0x00, // DeviceClass; + 0x00, // DeviceSubClass; + 0x00, // DeviceProtocol; + 0x08, // MaxPacketSize0; + 0x03F0, // IdVendor; + 0x0325, // IdProduct; + 0x0103, // BcdDevice; + 0x01, // StrManufacturer; + 0x02, // StrProduct; + 0x00, // StrSerialNumber; + 0x01, // NumConfigurations; +}; + +typedef struct { + USB_CONFIG_DESCRIPTOR ConfigDesc; + USB_INTERFACE_DESCRIPTOR InterfaceDesc; + EFI_USB_HID_DESCRIPTOR HidDesc; + USB_ENDPOINT_DESCRIPTOR EndpointDesc; +} FULL_USB_CONFIG_DESCRIPTOR; + +FULL_USB_CONFIG_DESCRIPTOR mConfigDesc = { + { + 0x09, // Length; + 0x02, // DescriptorType; - USB_DESC_TYPE_CONFIG + 0x0022, // TotalLength; + 0x01, // NumInterfaces; + 0x01, // ConfigurationValue; + 0x00, // Configuration; + 0xA0, // Attributes; + 0x32, // MaxPower; + }, + { + 0x09, // Length; + 0x04, // DescriptorType; - USB_DESC_TYPE_INTERFACE + 0x00, // InterfaceNumber; + 0x00, // AlternateSetting; + 0x01, // NumEndpoints; + 0x03, // InterfaceClass; + 0x01, // InterfaceSubClass; + 0x01, // InterfaceProtocol; + 0x00, // Interface; + }, + { + 0x09, // Length; + 0x21, // DescriptorType; - USB_DESC_TYPE_HID + 0x0110, // BcdHID; + 0x00, // CountryCode; + 0x01, // NumDescriptors; + {{0x22, 0x0041}}, // HidClassDesc[0]; + }, + { + 0x07, // Length; + 0x05, // DescriptorType; - USB_DESC_TYPE_ENDPOINT + 0x81, // EndpointAddress; + 0x03, // Attributes; + 0x0008, // MaxPacketSize; + 0x0A, // Interval; + }, +}; + +EFI_USB_STRING_DESCRIPTOR mStringDesc = { + 0x04, // Length; + 0x03, // DescriptorType; - USB_DESC_TYPE_STRING + {0x0409}, // String[0]; +}; + +typedef struct { + UINT8 Length; + UINT8 DescriptorType; + CHAR16 String[4]; +} FULL_EFI_USB_STRING_DESCRIPTOR; + +FULL_EFI_USB_STRING_DESCRIPTOR mStringDesc_2 = { + 0x0A, // Length; + 0x03, // DescriptorType; - USB_DESC_TYPE_STRING + {0x2000, 0x2000, 0x2000, 0x2000}, // String +}; + +// +// USB Key example +// +USB_DEVICE_DESCRIPTOR mDeviceDesc2 = { + 0x12, // Length; + 0x01, // DescriptorType; - USB_DESC_TYPE_DEVICE + 0x0200, // BcdUSB; + 0x00, // DeviceClass; + 0x00, // DeviceSubClass; + 0x00, // DeviceProtocol; + 0x40, // MaxPacketSize0; + 0x0781, // IdVendor; + 0x5151, // IdProduct; + 0x0010, // BcdDevice; + 0x01, // StrManufacturer; + 0x02, // StrProduct; + 0x03, // StrSerialNumber; + 0x01, // NumConfigurations; +}; + +typedef struct { + USB_CONFIG_DESCRIPTOR ConfigDesc; + USB_INTERFACE_DESCRIPTOR InterfaceDesc; + USB_ENDPOINT_DESCRIPTOR EndpointDesc1; + USB_ENDPOINT_DESCRIPTOR EndpointDesc2; +} FULL_USB_CONFIG_DESCRIPTOR2; + +FULL_USB_CONFIG_DESCRIPTOR2 mConfigDesc2 = { + { + 0x09, // Length; + 0x02, // DescriptorType; - USB_DESC_TYPE_CONFIG + 0x0020, // TotalLength; + 0x01, // NumInterfaces; + 0x01, // ConfigurationValue; + 0x00, // Configuration; + 0x80, // Attributes; + 0x64, // MaxPower; + }, + { + 0x09, // Length; + 0x04, // DescriptorType; - USB_DESC_TYPE_INTERFACE + 0x00, // InterfaceNumber; + 0x00, // AlternateSetting; + 0x02, // NumEndpoints; + 0x08, // InterfaceClass; + 0x06, // InterfaceSubClass; + 0x50, // InterfaceProtocol; + 0x00, // Interface; + }, + { + 0x07, // Length; + 0x05, // DescriptorType; - USB_DESC_TYPE_ENDPOINT + 0x81, // EndpointAddress; + 0x02, // Attributes; + 0x0200, // MaxPacketSize; + 0x00, // Interval; + }, + { + 0x07, // Length; + 0x05, // DescriptorType; - USB_DESC_TYPE_ENDPOINT + 0x01, // EndpointAddress; + 0x02, // Attributes; + 0x0200, // MaxPacketSize; + 0x01, // Interval; + }, +}; + +EFI_USB_STRING_DESCRIPTOR mStringDesc2 = { + 0x04, // Length; + 0x03, // DescriptorType; - USB_DESC_TYPE_STRING + {0x0409}, // String[0]; +}; + +typedef struct { + UINT8 Length; + UINT8 DescriptorType; + CHAR16 String[4]; +} FULL_EFI_USB_STRING_DESCRIPTOR2; + +FULL_EFI_USB_STRING_DESCRIPTOR2 mStringDesc2_2 = { + 0x0A, // Length; + 0x03, // DescriptorType; - USB_DESC_TYPE_STRING + {0x2000, 0x2000, 0x2000, 0x2000}, // String +}; + +EFI_STATUS +EFIAPI +UsbIoPpiStubControlTransfer ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_USB_IO_PPI *This, + IN EFI_USB_DEVICE_REQUEST *Request, + IN EFI_USB_DATA_DIRECTION Direction, + IN UINT32 Timeout, + IN OUT VOID *Data OPTIONAL, + IN UINTN DataLength OPTIONAL + ) +{ + DEBUG ((DEBUG_INFO, "USB_STUB: ControlTransfer\n")); + + if ((Direction == EfiUsbDataIn) && + (Request->RequestType == 0x80) && + (Request->Request == USB_REQ_GET_DESCRIPTOR)) { + switch (Request->Value >> 8) { + case USB_DESC_TYPE_DEVICE: + DEBUG ((DEBUG_INFO, "DEVICE - 0x%x\n", DataLength)); + if (mDeviceDescBuffer != NULL) { + if (DataLength > mDeviceDescBufferSize) { + DataLength = mDeviceDescBufferSize; + } + CopyMem (Data, mDeviceDescBuffer, DataLength); + } else { + if (DataLength > sizeof(mDeviceDesc)) { + DataLength = sizeof(mDeviceDesc); + } + CopyMem (Data, &mDeviceDesc, DataLength); + } + break; + case USB_DESC_TYPE_CONFIG: + DEBUG ((DEBUG_INFO, "CONFIG - 0x%x\n", DataLength)); + if (mConfigDescBuffer != NULL) { + if (DataLength > mConfigDescBufferSize) { + DataLength = mConfigDescBufferSize; + } + CopyMem (Data, mConfigDescBuffer, DataLength); + } else { + if (DataLength > sizeof(mConfigDesc)) { + DataLength = sizeof(mConfigDesc); + } + CopyMem (Data, &mConfigDesc, DataLength); + } + break; + case USB_DESC_TYPE_STRING: + DEBUG ((DEBUG_INFO, "STRING - 0x%x\n", DataLength)); + if (mStringDescBuffer != NULL) { + if (DataLength > mStringDescBufferSize) { + DataLength = mStringDescBufferSize; + } + CopyMem (Data, mStringDescBuffer, DataLength); + } else { + if (DataLength > sizeof(mStringDesc)) { + DataLength = sizeof(mStringDesc); + } + CopyMem (Data, &mStringDesc, DataLength); + } + break; + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +UsbIoPpiStubBulkTransfer ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_USB_IO_PPI *This, + IN UINT8 DeviceEndpoint, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN UINTN Timeout + ) +{ + DEBUG ((DEBUG_INFO, "USB_STUB: BulkTransfer\n")); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +UsbIoPpiStubGetInterfaceDescriptor ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_USB_IO_PPI *This, + IN EFI_USB_INTERFACE_DESCRIPTOR **InterfaceDescriptor + ) +{ + DEBUG ((DEBUG_INFO, "USB_STUB: GetInterfaceDescriptor\n")); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +UsbIoPpiStubGetEndpointDescriptor ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_USB_IO_PPI *This, + IN UINT8 EndpointIndex, + IN EFI_USB_ENDPOINT_DESCRIPTOR **EndpointDescriptor + ) +{ + DEBUG ((DEBUG_INFO, "USB_STUB: GetEndpointDescriptor\n")); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +UsbIoPpiStubPortReset ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_USB_IO_PPI *This + ) +{ + DEBUG ((DEBUG_INFO, "USB_IO_STUB: PortReset\n")); + return EFI_UNSUPPORTED; +} + +PEI_USB_IO_PPI mUsbIoPpiStub = { + UsbIoPpiStubControlTransfer, + UsbIoPpiStubBulkTransfer, + UsbIoPpiStubGetInterfaceDescriptor, + UsbIoPpiStubGetEndpointDescriptor, + UsbIoPpiStubPortReset, +}; + +EFI_STATUS +EFIAPI +UsbIoPpiStubInitialize ( + IN VOID *DeviceDescBuffer, + IN UINTN DeviceDescBufferSize, + IN VOID *ConfigDescBuffer, + IN UINTN ConfigDescBufferSize, + IN VOID *StringDescBuffer, + IN UINTN StringDescBufferSize, + OUT PEI_USB_IO_PPI **UsbIoPpi + ) +{ + mDeviceDescBuffer = DeviceDescBuffer; + mDeviceDescBufferSize = DeviceDescBufferSize; + mConfigDescBuffer = ConfigDescBuffer; + mConfigDescBufferSize = ConfigDescBufferSize; + mStringDescBuffer = StringDescBuffer; + mStringDescBufferSize = StringDescBufferSize; + *UsbIoPpi = &mUsbIoPpiStub; + return EFI_SUCCESS; +} diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestStub/UsbIoPpiStubLib/UsbIoPpiStubLib.inf b/HBFA/UefiHostFuzzTestCasePkg/TestStub/UsbIoPpiStubLib/UsbIoPpiStubLib.inf new file mode 100644 index 0000000..07d4bf3 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestStub/UsbIoPpiStubLib/UsbIoPpiStubLib.inf @@ -0,0 +1,36 @@ +## @file +# Component description file for TestUdf module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UsbIoPpiStubLib + FILE_GUID = A84AF093-3CAF-424E-BCEC-3E1606030A5F + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = UsbIoPpiStubLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + UsbIoPpiStubLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestStub/VirtioBlkStubLib/VirtioBlkStubLib.c b/HBFA/UefiHostFuzzTestCasePkg/TestStub/VirtioBlkStubLib/VirtioBlkStubLib.c new file mode 100644 index 0000000..1640072 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestStub/VirtioBlkStubLib/VirtioBlkStubLib.c @@ -0,0 +1,324 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include + +#include +#include +#include +#include +#include + +#include +#include + +EFI_STATUS +EFIAPI +VirtioBlkReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +EFI_STATUS +EFIAPI +VirtioBlkReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +EFI_STATUS +EFIAPI +VirtioBlkWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer + ); + + +EFI_STATUS +EFIAPI +VirtioBlkFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ); + +#define VIRTIO_CFG_WRITE(Dev, Field, Value) ((Dev)->VirtIo->WriteDevice ( \ + (Dev)->VirtIo, \ + OFFSET_OF_VBLK (Field), \ + SIZE_OF_VBLK (Field), \ + (Value) \ + )) + +#define VIRTIO_CFG_READ(Dev, Field, Pointer) ((Dev)->VirtIo->ReadDevice ( \ + (Dev)->VirtIo, \ + OFFSET_OF_VBLK (Field), \ + SIZE_OF_VBLK (Field), \ + sizeof *(Pointer), \ + (Pointer) \ + )) + +EFI_STATUS +EFIAPI +VirtioBlkInit ( + IN OUT VBLK_DEV *Dev +) +{ + UINT8 NextDevStat; + EFI_STATUS Status; + + UINT64 Features; + UINT64 NumSectors; + UINT32 BlockSize; + UINT8 PhysicalBlockExp; + UINT8 AlignmentOffset; + UINT32 OptIoSize; + UINT16 QueueSize; + UINT64 RingBaseShift; + + PhysicalBlockExp = 0; + AlignmentOffset = 0; + OptIoSize = 0; + // + // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence. + // + NextDevStat = 0; // step 1 -- reset device + Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); + if (EFI_ERROR (Status)) { + goto Failed; + } + + NextDevStat |= VSTAT_ACK; // step 2 -- acknowledge device presence + Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); + if (EFI_ERROR (Status)) { + goto Failed; + } + + NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it + Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); + if (EFI_ERROR (Status)) { + goto Failed; + } + // printf ("Set page size\n"); + // + // Set Page Size - MMIO VirtIo Specific + // + Status = Dev->VirtIo->SetPageSize (Dev->VirtIo, EFI_PAGE_SIZE); + if (EFI_ERROR (Status)) { + goto Failed; + } + // printf ("get device features\n"); + // + // step 4a -- retrieve and validate features + // + Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features); + if (EFI_ERROR (Status)) { + goto Failed; + } + // printf ("read device features\n"); + Status = VIRTIO_CFG_READ (Dev, Capacity, &NumSectors); + if (EFI_ERROR (Status)) { + goto Failed; + } + if (NumSectors == 0) { + Status = EFI_UNSUPPORTED; + goto Failed; + } + if (Features & VIRTIO_BLK_F_BLK_SIZE) { + Status = VIRTIO_CFG_READ (Dev, BlkSize, &BlockSize); + if (EFI_ERROR (Status)) { + goto Failed; + } + if (BlockSize == 0 || BlockSize % 512 != 0 || + ModU64x32 (NumSectors, BlockSize / 512) != 0) { + // + // We can only handle a logical block consisting of whole sectors, + // and only a disk composed of whole logical blocks. + // + Status = EFI_UNSUPPORTED; + goto Failed; + } + } + else { + BlockSize = 512; + } + if (Features & VIRTIO_BLK_F_TOPOLOGY) { + Status = VIRTIO_CFG_READ (Dev, Topology.PhysicalBlockExp, + &PhysicalBlockExp); + if (EFI_ERROR (Status)) { + goto Failed; + } + if (PhysicalBlockExp >= 32) { + Status = EFI_UNSUPPORTED; + goto Failed; + } + + Status = VIRTIO_CFG_READ (Dev, Topology.AlignmentOffset, &AlignmentOffset); + if (EFI_ERROR (Status)) { + goto Failed; + } + + Status = VIRTIO_CFG_READ (Dev, Topology.OptIoSize, &OptIoSize); + if (EFI_ERROR (Status)) { + goto Failed; + } + } + + Features &= VIRTIO_BLK_F_BLK_SIZE | VIRTIO_BLK_F_TOPOLOGY | VIRTIO_BLK_F_RO | + VIRTIO_BLK_F_FLUSH | VIRTIO_F_VERSION_1 | + VIRTIO_F_IOMMU_PLATFORM; + + // printf ("write features\n"); + // + // In virtio-1.0, feature negotiation is expected to complete before queue + // discovery, and the device can also reject the selected set of features. + // + if (Dev->VirtIo->Revision >= VIRTIO_SPEC_REVISION (1, 0, 0)) { + Status = Virtio10WriteFeatures (Dev->VirtIo, Features, &NextDevStat); + if (EFI_ERROR (Status)) { + goto Failed; + } + } + // + // step 4b -- allocate virtqueue + // + Status = Dev->VirtIo->SetQueueSel (Dev->VirtIo, 0); + if (EFI_ERROR (Status)) { + goto Failed; + } + Status = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize); + if (EFI_ERROR (Status)) { + goto Failed; + } + if (QueueSize < 3) { // SynchronousRequest() uses at most three descriptors + Status = EFI_UNSUPPORTED; + goto Failed; + } + + Status = VirtioRingInit (Dev->VirtIo, QueueSize, &Dev->Ring); + if (EFI_ERROR (Status)) { + goto Failed; + } + // + // If anything fails from here on, we must release the ring resources + // + Status = VirtioRingMap ( + Dev->VirtIo, + &Dev->Ring, + &RingBaseShift, + &Dev->RingMap + ); + if (EFI_ERROR (Status)) { + goto ReleaseQueue; + } + + // + // Additional steps for MMIO: align the queue appropriately, and set the + // size. If anything fails from here on, we must unmap the ring resources. + // + Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize); + if (EFI_ERROR (Status)) { + goto UnmapQueue; + } + + Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE); + if (EFI_ERROR (Status)) { + goto UnmapQueue; + } + // + // step 4c -- Report GPFN (guest-physical frame number) of queue. + // + Status = Dev->VirtIo->SetQueueAddress ( + Dev->VirtIo, + &Dev->Ring, + RingBaseShift + ); + if (EFI_ERROR (Status)) { + goto UnmapQueue; + } + + + // + // step 5 -- Report understood features. + // + if (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) { + Features &= ~(UINT64)(VIRTIO_F_VERSION_1 | VIRTIO_F_IOMMU_PLATFORM); + Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features); + if (EFI_ERROR (Status)) { + goto UnmapQueue; + } + } + + // + // step 6 -- initialization complete + // + NextDevStat |= VSTAT_DRIVER_OK; + Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); + if (EFI_ERROR (Status)) { + goto UnmapQueue; + } + + + + // + // Populate the exported interface's attributes; see UEFI spec v2.4, 12.9 EFI + // Block I/O Protocol. + // + Dev->BlockIo.Revision = 0; + Dev->BlockIo.Media = &Dev->BlockIoMedia; + Dev->BlockIo.Reset = &VirtioBlkReset; + Dev->BlockIo.ReadBlocks = &VirtioBlkReadBlocks; + Dev->BlockIo.WriteBlocks = &VirtioBlkWriteBlocks; + Dev->BlockIo.FlushBlocks = &VirtioBlkFlushBlocks; + Dev->BlockIoMedia.MediaId = 0; + Dev->BlockIoMedia.RemovableMedia = FALSE; + Dev->BlockIoMedia.MediaPresent = TRUE; + Dev->BlockIoMedia.LogicalPartition = FALSE; + Dev->BlockIoMedia.ReadOnly = (BOOLEAN) ((Features & VIRTIO_BLK_F_RO) != 0); + Dev->BlockIoMedia.WriteCaching = (BOOLEAN) ((Features & VIRTIO_BLK_F_FLUSH) != 0); + Dev->BlockIoMedia.BlockSize = BlockSize; + Dev->BlockIoMedia.IoAlign = 0; + Dev->BlockIoMedia.LastBlock = DivU64x32 (NumSectors, + BlockSize / 512) - 1; + + DEBUG ((DEBUG_INFO, "%a: LbaSize=0x%x[B] NumBlocks=0x%Lx[Lba]\n", + __FUNCTION__, Dev->BlockIoMedia.BlockSize, + Dev->BlockIoMedia.LastBlock + 1)); + + if (Features & VIRTIO_BLK_F_TOPOLOGY) { + Dev->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3; + + Dev->BlockIoMedia.LowestAlignedLba = AlignmentOffset; + Dev->BlockIoMedia.LogicalBlocksPerPhysicalBlock = 1u << PhysicalBlockExp; + Dev->BlockIoMedia.OptimalTransferLengthGranularity = OptIoSize; + + DEBUG ((DEBUG_INFO, "%a: FirstAligned=0x%Lx[Lba] PhysBlkSize=0x%x[Lba]\n", + __FUNCTION__, Dev->BlockIoMedia.LowestAlignedLba, + Dev->BlockIoMedia.LogicalBlocksPerPhysicalBlock)); + DEBUG ((DEBUG_INFO, "%a: OptimalTransferLengthGranularity=0x%x[Lba]\n", + __FUNCTION__, Dev->BlockIoMedia.OptimalTransferLengthGranularity)); + } + return EFI_SUCCESS; + +UnmapQueue: + Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap); + +ReleaseQueue: + VirtioRingUninit (Dev->VirtIo, &Dev->Ring); + +Failed: + // + // Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device + // Status. VirtIo access failure here should not mask the original error. + // + NextDevStat |= VSTAT_FAILED; + Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); + + return Status; // reached only via Failed above +} \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestStub/VirtioBlkStubLib/VirtioBlkStubLib.inf b/HBFA/UefiHostFuzzTestCasePkg/TestStub/VirtioBlkStubLib/VirtioBlkStubLib.inf new file mode 100644 index 0000000..3476140 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestStub/VirtioBlkStubLib/VirtioBlkStubLib.inf @@ -0,0 +1,36 @@ +## @file +# Component description file for TestUdf module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = VirtioBlkStubLib + FILE_GUID = 1C7BD8C1-C26C-764C-0977-D8BF49A10DDA + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = VirtioBlkStubLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + VirtioBlkStubLib.c + +[Packages] + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestStub/VirtioPciDevice10StubLib/VirtioPciDevice10StubLib.c b/HBFA/UefiHostFuzzTestCasePkg/TestStub/VirtioPciDevice10StubLib/VirtioPciDevice10StubLib.c new file mode 100644 index 0000000..68d0fcf --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestStub/VirtioPciDevice10StubLib/VirtioPciDevice10StubLib.c @@ -0,0 +1,968 @@ +/** @file + +Copyright (c) 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 +#include + +PCI_CFG_SPACE *PciCfg; + +// VOID +// EFIAPI +// PrintByByte(UINT8* Content, UINT32 Len) { +// UINT32 i; +// for (i = 0; i < Len; i++) { +// if (i % 16 == 0) printf ("\n"); +// printf ("%02x ", Content[i]); +// } +// printf ("\n"); +// } + +EFI_STATUS +EFIAPI +PciCapPciIoDeviceInit ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + OUT PCI_CAP_DEV **PciDevice + ); + +VOID +EFIAPI +PciCapPciIoDeviceUninit ( + IN PCI_CAP_DEV *PciDevice + ); + +RETURN_STATUS +EFIAPI +PciCapListInit ( + IN PCI_CAP_DEV *PciDevice, + OUT PCI_CAP_LIST **CapList + ); + +RETURN_STATUS +EFIAPI +PciCapListFindCap ( + IN PCI_CAP_LIST *CapList, + IN PCI_CAP_DOMAIN Domain, + IN UINT16 CapId, + IN UINT16 Instance, + OUT PCI_CAP **Cap OPTIONAL + ); + +RETURN_STATUS +EFIAPI +PciCapRead ( + IN PCI_CAP_DEV *PciDevice, + IN PCI_CAP *Cap, + IN UINT16 SourceOffsetInCap, + OUT VOID *DestinationBuffer, + IN UINT16 Size + ); + +VOID +EFIAPI +PciCapListUninit ( + IN PCI_CAP_LIST *CapList + ); + +EFI_STATUS +GetBarType ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT8 BarIndex, + OUT VIRTIO_1_0_BAR_TYPE *BarType + ) +{ + if (PciCfg->PciBasicCfg.Device.Bar[BarIndex] & BIT0) { + *BarType = Virtio10BarTypeIo; + } + else { + *BarType = Virtio10BarTypeMem; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +Virtio10Transfer ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN VIRTIO_1_0_CONFIG *Config, + IN BOOLEAN Write, + IN UINTN FieldOffset, + IN UINTN FieldSize, + IN OUT VOID *Buffer + ) +{ + if (!Config->Exists || + (FieldSize > Config->Length) || + (FieldOffset > Config->Length - FieldSize)) + { + return EFI_INVALID_PARAMETER; + } + + if (Write) { + CopyMem ((void *) (((UINT64) PciCfg->PciBasicCfg.Device.Bar[1] << 32) | PciCfg->PciBasicCfg.Device.Bar[0] + Config->Offset + FieldOffset), Buffer, FieldSize); + } + else { + CopyMem (Buffer, (void *) (((UINT64) PciCfg->PciBasicCfg.Device.Bar[1] << 32) | PciCfg->PciBasicCfg.Device.Bar[0] + Config->Offset + FieldOffset), FieldSize); + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +Virtio10GetDeviceFeatures ( + IN VIRTIO_DEVICE_PROTOCOL *This, + OUT UINT64 *DeviceFeatures + ) +{ + VIRTIO_1_0_DEV *Dev; + UINT32 Selector; + UINT32 Features32[2]; + + Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This); + + for (Selector = 0; Selector < 2; ++Selector) { + EFI_STATUS Status; + + // + // Select the low or high half of the features. + // + Status = Virtio10Transfer ( + Dev->PciIo, + &Dev->CommonConfig, + TRUE, + OFFSET_OF (VIRTIO_PCI_COMMON_CFG, DeviceFeatureSelect), + sizeof Selector, + &Selector + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Fetch that half. + // + Status = Virtio10Transfer ( + Dev->PciIo, + &Dev->CommonConfig, + FALSE, + OFFSET_OF (VIRTIO_PCI_COMMON_CFG, DeviceFeature), + sizeof Features32[Selector], + &Features32[Selector] + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + + *DeviceFeatures = LShiftU64 (Features32[1], 32) | Features32[0]; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +Virtio10SetGuestFeatures ( + IN VIRTIO_DEVICE_PROTOCOL *This, + IN UINT64 Features + ) +{ + VIRTIO_1_0_DEV *Dev; + UINT32 Selector; + UINT32 Features32[2]; + + Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This); + + Features32[0] = (UINT32)Features; + Features32[1] = (UINT32)RShiftU64 (Features, 32); + + for (Selector = 0; Selector < 2; ++Selector) { + EFI_STATUS Status; + + // + // Select the low or high half of the features. + // + Status = Virtio10Transfer ( + Dev->PciIo, + &Dev->CommonConfig, + TRUE, + OFFSET_OF (VIRTIO_PCI_COMMON_CFG, DriverFeatureSelect), + sizeof Selector, + &Selector + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Write that half. + // + Status = Virtio10Transfer ( + Dev->PciIo, + &Dev->CommonConfig, + TRUE, + OFFSET_OF (VIRTIO_PCI_COMMON_CFG, DriverFeature), + sizeof Features32[Selector], + &Features32[Selector] + ); + + if (EFI_ERROR (Status)) { + return Status; + } + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +Virtio10SetQueueAddress ( + IN VIRTIO_DEVICE_PROTOCOL *This, + IN VRING *Ring, + IN UINT64 RingBaseShift + ) +{ + VIRTIO_1_0_DEV *Dev; + EFI_STATUS Status; + UINT64 Address; + UINT16 Enable; + + Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This); + + Address = (UINTN)Ring->Desc; + Address += RingBaseShift; + Status = Virtio10Transfer ( + Dev->PciIo, + &Dev->CommonConfig, + TRUE, + OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueDesc), + sizeof Address, + &Address + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Address = (UINTN)Ring->Avail.Flags; + Address += RingBaseShift; + Status = Virtio10Transfer ( + Dev->PciIo, + &Dev->CommonConfig, + TRUE, + OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueAvail), + sizeof Address, + &Address + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Address = (UINTN)Ring->Used.Flags; + Address += RingBaseShift; + Status = Virtio10Transfer ( + Dev->PciIo, + &Dev->CommonConfig, + TRUE, + OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueUsed), + sizeof Address, + &Address + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Enable = 1; + Status = Virtio10Transfer ( + Dev->PciIo, + &Dev->CommonConfig, + TRUE, + OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueEnable), + sizeof Enable, + &Enable + ); + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +Virtio10SetQueueSel ( + IN VIRTIO_DEVICE_PROTOCOL *This, + IN UINT16 Index + ) +{ + VIRTIO_1_0_DEV *Dev; + EFI_STATUS Status; + + Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This); + + Status = Virtio10Transfer ( + Dev->PciIo, + &Dev->CommonConfig, + TRUE, + OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueSelect), + sizeof Index, + &Index + ); + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +Virtio10SetQueueNotify ( + IN VIRTIO_DEVICE_PROTOCOL *This, + IN UINT16 Index + ) +{ + VIRTIO_1_0_DEV *Dev; + EFI_STATUS Status; + UINT16 SavedQueueSelect; + UINT16 NotifyOffset; + + Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This); + + // + // Read NotifyOffset first. NotifyOffset is queue specific, so we have + // to stash & restore the current queue selector around it. + // + // So, start with saving the current queue selector. + // + Status = Virtio10Transfer ( + Dev->PciIo, + &Dev->CommonConfig, + FALSE, + OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueSelect), + sizeof SavedQueueSelect, + &SavedQueueSelect + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Select the requested queue. + // + Status = Virtio10Transfer ( + Dev->PciIo, + &Dev->CommonConfig, + TRUE, + OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueSelect), + sizeof Index, + &Index + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Read the QueueNotifyOff field. + // + Status = Virtio10Transfer ( + Dev->PciIo, + &Dev->CommonConfig, + FALSE, + OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueNotifyOff), + sizeof NotifyOffset, + &NotifyOffset + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Re-select the original queue. + // + Status = Virtio10Transfer ( + Dev->PciIo, + &Dev->CommonConfig, + TRUE, + OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueSelect), + sizeof SavedQueueSelect, + &SavedQueueSelect + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // We can now kick the queue. + // + Status = Virtio10Transfer ( + Dev->PciIo, + &Dev->NotifyConfig, + TRUE, + (UINTN)NotifyOffset * Dev->NotifyOffsetMultiplier, + sizeof Index, + &Index + ); + + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +Virtio10SetQueueAlign ( + IN VIRTIO_DEVICE_PROTOCOL *This, + IN UINT32 Alignment + ) +{ + return (Alignment == EFI_PAGE_SIZE) ? EFI_SUCCESS : EFI_UNSUPPORTED; +} + +STATIC +EFI_STATUS +EFIAPI +Virtio10SetPageSize ( + IN VIRTIO_DEVICE_PROTOCOL *This, + IN UINT32 PageSize + ) +{ + return (PageSize == EFI_PAGE_SIZE) ? EFI_SUCCESS : EFI_UNSUPPORTED; +} + +STATIC +EFI_STATUS +EFIAPI +Virtio10GetQueueNumMax ( + IN VIRTIO_DEVICE_PROTOCOL *This, + OUT UINT16 *QueueNumMax + ) +{ + VIRTIO_1_0_DEV *Dev; + EFI_STATUS Status; + + Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This); + + Status = Virtio10Transfer ( + Dev->PciIo, + &Dev->CommonConfig, + FALSE, + OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueSize), + sizeof *QueueNumMax, + QueueNumMax + ); + + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +Virtio10SetQueueNum ( + IN VIRTIO_DEVICE_PROTOCOL *This, + IN UINT16 QueueSize + ) +{ + EFI_STATUS Status; + UINT16 CurrentSize; + + // + // This member function is required for VirtIo MMIO, and a no-op in + // VirtIo PCI 0.9.5. In VirtIo 1.0, drivers can theoretically use this + // member to reduce memory consumption, but none of our drivers do. So + // just check that they set the size that is already in effect. + // + Status = Virtio10GetQueueNumMax (This, &CurrentSize); + if (EFI_ERROR (Status)) { + return Status; + } + + return (CurrentSize == QueueSize) ? EFI_SUCCESS : EFI_UNSUPPORTED; +} + +STATIC +EFI_STATUS +EFIAPI +Virtio10GetDeviceStatus ( + IN VIRTIO_DEVICE_PROTOCOL *This, + OUT UINT8 *DeviceStatus + ) +{ + VIRTIO_1_0_DEV *Dev; + EFI_STATUS Status; + + Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This); + + Status = Virtio10Transfer ( + Dev->PciIo, + &Dev->CommonConfig, + FALSE, + OFFSET_OF (VIRTIO_PCI_COMMON_CFG, DeviceStatus), + sizeof *DeviceStatus, + DeviceStatus + ); + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +Virtio10SetDeviceStatus ( + IN VIRTIO_DEVICE_PROTOCOL *This, + IN UINT8 DeviceStatus + ) +{ + VIRTIO_1_0_DEV *Dev; + EFI_STATUS Status; + + Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This); + + Status = Virtio10Transfer ( + Dev->PciIo, + &Dev->CommonConfig, + TRUE, + OFFSET_OF (VIRTIO_PCI_COMMON_CFG, DeviceStatus), + sizeof DeviceStatus, + &DeviceStatus + ); + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +Virtio10WriteDevice ( + IN VIRTIO_DEVICE_PROTOCOL *This, + IN UINTN FieldOffset, + IN UINTN FieldSize, + IN UINT64 Value + ) +{ + VIRTIO_1_0_DEV *Dev; + EFI_STATUS Status; + + Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This); + + Status = Virtio10Transfer ( + Dev->PciIo, + &Dev->SpecificConfig, + TRUE, + FieldOffset, + FieldSize, + &Value + ); + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +Virtio10ReadDevice ( + IN VIRTIO_DEVICE_PROTOCOL *This, + IN UINTN FieldOffset, + IN UINTN FieldSize, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + VIRTIO_1_0_DEV *Dev; + EFI_STATUS Status; + + if (FieldSize != BufferSize) { + return EFI_INVALID_PARAMETER; + } + + Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This); + + Status = Virtio10Transfer ( + Dev->PciIo, + &Dev->SpecificConfig, + FALSE, + FieldOffset, + FieldSize, + Buffer + ); + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +Virtio10AllocateSharedPages ( + IN VIRTIO_DEVICE_PROTOCOL *This, + IN UINTN Pages, + IN OUT VOID **HostAddress + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + + *HostAddress = AllocatePages (Pages); + + if (*HostAddress == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } + + return Status; +} + +STATIC +VOID +EFIAPI +Virtio10FreeSharedPages ( + IN VIRTIO_DEVICE_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress + ) +{ + FreePages(HostAddress, Pages); +} + +STATIC +EFI_STATUS +EFIAPI +Virtio10MapSharedBuffer ( + IN VIRTIO_DEVICE_PROTOCOL *This, + IN VIRTIO_MAP_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +Virtio10UnmapSharedBuffer ( + IN VIRTIO_DEVICE_PROTOCOL *This, + IN VOID *Mapping + ) +{ + return EFI_SUCCESS; +} + +STATIC CONST VIRTIO_DEVICE_PROTOCOL mVirtIoTemplate = { + VIRTIO_SPEC_REVISION (1, 0, 0), + 0, // SubSystemDeviceId, filled in dynamically + Virtio10GetDeviceFeatures, + Virtio10SetGuestFeatures, + Virtio10SetQueueAddress, + Virtio10SetQueueSel, + Virtio10SetQueueNotify, + Virtio10SetQueueAlign, + Virtio10SetPageSize, + Virtio10GetQueueNumMax, + Virtio10SetQueueNum, + Virtio10GetDeviceStatus, + Virtio10SetDeviceStatus, + Virtio10WriteDevice, + Virtio10ReadDevice, + Virtio10AllocateSharedPages, + Virtio10FreeSharedPages, + Virtio10MapSharedBuffer, + Virtio10UnmapSharedBuffer +}; + +EFI_STATUS +EFIAPI +FixPciCfg ( + IN OUT PCI_CFG_SPACE *PciCfg, + IN VIRTIO_PCI_CAP_COMMON_CONFIG *PciCommonConfig +) +{ + PciCfg->PciBasicCfg.Device.Bar[0] = (UINT32) ((UINT64)PciCommonConfig); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ParseCapabilities ( + IN OUT VIRTIO_1_0_DEV *Device + ) +{ + EFI_STATUS Status; + PCI_CAP_DEV *PciDevice; + PCI_CAP_LIST *CapList; + UINT16 VendorInstance; + PCI_CAP *VendorCap; + + Status = PciCapPciIoDeviceInit (Device->PciIo, &PciDevice); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = PciCapListInit (PciDevice, &CapList); + if (EFI_ERROR (Status)) { + goto UninitPciDevice; + } + + for (VendorInstance = 0; + !EFI_ERROR (PciCapListFindCap (CapList, PciCapNormal, + EFI_PCI_CAPABILITY_ID_VENDOR, VendorInstance, + &VendorCap)); + VendorInstance++) { + UINT8 CapLen; + VIRTIO_PCI_CAP VirtIoCap; + VIRTIO_1_0_CONFIG *ParsedConfig; + + // + // Big enough to accommodate a VIRTIO_PCI_CAP structure? + // + Status = PciCapRead (PciDevice, VendorCap, + OFFSET_OF (EFI_PCI_CAPABILITY_VENDOR_HDR, Length), &CapLen, + sizeof CapLen); + if (EFI_ERROR (Status)) { + goto UninitCapList; + } + if (CapLen < sizeof VirtIoCap) { + // + // Too small, move to next. + // + continue; + } + + // + // Read interesting part of capability. + // + Status = PciCapRead (PciDevice, VendorCap, 0, &VirtIoCap, sizeof VirtIoCap); + if (EFI_ERROR (Status)) { + goto UninitCapList; + } + + switch (VirtIoCap.ConfigType) { + case VIRTIO_PCI_CAP_COMMON_CFG: + ParsedConfig = &Device->CommonConfig; + break; + case VIRTIO_PCI_CAP_NOTIFY_CFG: + ParsedConfig = &Device->NotifyConfig; + break; + case VIRTIO_PCI_CAP_DEVICE_CFG: + ParsedConfig = &Device->SpecificConfig; + break; + default: + // + // Capability is not interesting. + // + continue; + } + + // + // Save the location of the register block into ParsedConfig. + // + Status = GetBarType (Device->PciIo, VirtIoCap.Bar, &ParsedConfig->BarType); + if (EFI_ERROR (Status)) { + goto UninitCapList; + } + ParsedConfig->Bar = VirtIoCap.Bar; + ParsedConfig->Offset = VirtIoCap.Offset; + ParsedConfig->Length = VirtIoCap.Length; + + if (VirtIoCap.ConfigType == VIRTIO_PCI_CAP_NOTIFY_CFG) { + // + // This capability has an additional field called NotifyOffsetMultiplier; + // parse it too. + // + if (CapLen < sizeof VirtIoCap + sizeof Device->NotifyOffsetMultiplier) { + // + // Too small, move to next. + // + continue; + } + + Status = PciCapRead (PciDevice, VendorCap, sizeof VirtIoCap, + &Device->NotifyOffsetMultiplier, + sizeof Device->NotifyOffsetMultiplier); + if (EFI_ERROR (Status)) { + goto UninitCapList; + } + } + + // + // Capability parsed successfully. + // + ParsedConfig->Exists = TRUE; + } + + ASSERT_EFI_ERROR (Status); + +UninitCapList: + PciCapListUninit (CapList); + +UninitPciDevice: + PciCapPciIoDeviceUninit (PciDevice); + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoRead ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT16 Offset, + IN UINT16 Count, + IN OUT UINT8 *Buffer +) { + UINT16 Len = 0; + + switch (Width) + { + case EfiPciIoWidthUint32: + Len = Count * sizeof(UINT32); + break; + case EfiPciIoWidthUint16: + Len = Count * sizeof(UINT16); + break; + case EfiPciIoWidthUint8: + Len = Count * sizeof(UINT8); + break; + default: + break; + } + + CopyMem (Buffer, (void *) ((UINT64) PciCfg + Offset), Len); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +InitVirtioPciDevice ( + IN OUT VIRTIO_1_0_DEV *Device, + IN UINT8 *TestBuffer, + IN UINTN BufferSize, + IN EFI_PCI_IO_PROTOCOL *PciIo +) +{ + // VOID *ConfigRegion; + + // ConfigRegion = (VOID *) AllocateZeroPool (sizeof (PCI_CFG_SPACE)); + PciCfg = (PCI_CFG_SPACE *) TestBuffer; + + // CopyMem (PciCfg, (void *) TestBuffer, sizeof (PCI_CFG_SPACE)); + + PciIo->Pci.Read = &PciIoRead; + + if ((PciCfg->PciBasicCfg.Hdr.VendorId == VIRTIO_VENDOR_ID) && + (PciCfg->PciBasicCfg.Hdr.DeviceId >= 0x1040) && + (PciCfg->PciBasicCfg.Hdr.DeviceId <= 0x107F) && + (PciCfg->PciBasicCfg.Hdr.RevisionID >= 0x01) && + (PciCfg->PciBasicCfg.Device.SubsystemID >= 0x40) && + ((PciCfg->PciBasicCfg.Hdr.Status & EFI_PCI_STATUS_CAPABILITY) != 0)) + { + if (!((PciCfg->PciBasicCfg.Hdr.DeviceId != 0x1050) || !(PciCfg->PciBasicCfg.Hdr.ClassCode == PciCfg))) { + return EFI_OUT_OF_RESOURCES; + } + } + else { + return EFI_OUT_OF_RESOURCES; + } + + ParseCapabilities (Device); + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +ParseBufferAndInitVirtioPciDev10 ( + IN UINT8 *TestBuffer, + IN UINTN BufferSize, + IN VOID *ConfigRegion, + IN OUT VIRTIO_1_0_DEV *Device +) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + VIRTIO_BLK_CONFIG *BlkConfig; + VIRTIO_PCI_CAP_COMMON_CONFIG *PciCommonConfig; + VOID *PciNotifyConfig; + // VOID *ConfigRegion; + + // ConfigRegion = (VOID *) AllocatePool(sizeof (PCI_CFG_SPACE) + sizeof(VIRTIO_PCI_CAP_COMMON_CONFIG) + sizeof (VIRTIO_BLK_CONFIG) + 0x100); + if (ConfigRegion == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + if (BufferSize != sizeof (PCI_CFG_SPACE) + sizeof(VIRTIO_PCI_CAP_COMMON_CONFIG) + sizeof (VIRTIO_BLK_CONFIG)) { + goto FreeDevice; + } + + Device->Signature = VIRTIO_1_0_SIGNATURE; + CopyMem (&Device->VirtIo, &mVirtIoTemplate, sizeof (VIRTIO_DEVICE_PROTOCOL)); + + PciCfg = (PCI_CFG_SPACE *) ConfigRegion; + PciCommonConfig = (VIRTIO_PCI_CAP_COMMON_CONFIG *) ((UINT64) ConfigRegion + sizeof (PCI_CFG_SPACE)); + BlkConfig = (VIRTIO_BLK_CONFIG *) ((UINT64) ConfigRegion + sizeof (PCI_CFG_SPACE) + sizeof(VIRTIO_PCI_CAP_COMMON_CONFIG)); + PciNotifyConfig = (VOID *) ((UINT64) ConfigRegion + sizeof (PCI_CFG_SPACE) + sizeof(VIRTIO_PCI_CAP_COMMON_CONFIG) + sizeof (VIRTIO_BLK_CONFIG)); + + CopyMem (PciCfg, (void *) TestBuffer, sizeof (PCI_CFG_SPACE)); + + CopyMem (PciCommonConfig, + (void *) ((UINT64)TestBuffer + sizeof (PCI_CFG_SPACE)), + sizeof (VIRTIO_PCI_CAP_COMMON_CONFIG)); + + CopyMem (BlkConfig, + (void *) ((UINT64)TestBuffer + sizeof (PCI_CFG_SPACE) + sizeof (VIRTIO_PCI_CAP_COMMON_CONFIG)), + sizeof (VIRTIO_BLK_CONFIG)); + + if ((PciCfg->PciBasicCfg.Hdr.VendorId == VIRTIO_VENDOR_ID) && + (PciCfg->PciBasicCfg.Hdr.DeviceId >= 0x1040) && + (PciCfg->PciBasicCfg.Hdr.DeviceId <= 0x107F) && + (PciCfg->PciBasicCfg.Hdr.RevisionID >= 0x01) && + (PciCfg->PciBasicCfg.Device.SubsystemID >= 0x40) && + ((PciCfg->PciBasicCfg.Hdr.Status & EFI_PCI_STATUS_CAPABILITY) != 0)) + { + if (!((PciCfg->PciBasicCfg.Hdr.DeviceId != 0x1050) || !(PciCfg->PciBasicCfg.Hdr.ClassCode == PciCfg))) { + goto FreeDevice; + } + } + else { + goto FreeDevice; + } + + PciCfg->PciBasicCfg.Device.Bar[0] = (UINT32) ((UINT64)PciCommonConfig); + PciCfg->PciBasicCfg.Device.Bar[1] = (UINT32) ((UINT64)PciCommonConfig >> 32); + + Device->VirtIo.SubSystemDeviceId = PciCfg->PciBasicCfg.Hdr.DeviceId - 0x1040; + + Device->CommonConfig.Offset = 0; + Device->CommonConfig.Bar = 0; + Device->CommonConfig.Exists = TRUE; + Device->CommonConfig.Length = sizeof(VIRTIO_PCI_CAP_COMMON_CONFIG); + + Device->NotifyConfig.Offset = sizeof(VIRTIO_PCI_CAP_COMMON_CONFIG) + sizeof (VIRTIO_BLK_CONFIG); + Device->NotifyConfig.Bar = 0; + Device->NotifyConfig.Exists = TRUE; + Device->NotifyConfig.Length = 0x100; + + Device->SpecificConfig.Offset = sizeof(VIRTIO_PCI_CAP_COMMON_CONFIG); + Device->SpecificConfig.Bar = 0; + Device->SpecificConfig.Exists = TRUE; + Device->SpecificConfig.Length = sizeof (VIRTIO_BLK_CONFIG); + + // if (Device->NotifyConfig.Length < (Device->CommonConfig.Offset * Device->NotifyOffsetMultiplier + 4)) { + // goto FreeDevice; + // } + + return EFI_SUCCESS; + +FreeDevice: + // FreePool (ConfigRegion); + + return EFI_OUT_OF_RESOURCES; +} diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestStub/VirtioPciDevice10StubLib/VirtioPciDevice10StubLib.inf b/HBFA/UefiHostFuzzTestCasePkg/TestStub/VirtioPciDevice10StubLib/VirtioPciDevice10StubLib.inf new file mode 100644 index 0000000..3835167 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestStub/VirtioPciDevice10StubLib/VirtioPciDevice10StubLib.inf @@ -0,0 +1,39 @@ +## @file +# Component description file for TestUdf module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = VirtioPciDevice10StubLib + FILE_GUID = 1C7BD2C1-C26C-764C-0927-D8BF49A30DDA + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = VirtioPciDevice10StubLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + VirtioPciDevice10StubLib.c + +[Packages] + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib + UefiPciCapPciIoLib + BasePciCapLib + OrderedCollectionLib \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestStub/VirtioPciDeviceStubLib/VirtioPciDeviceStubLib.c b/HBFA/UefiHostFuzzTestCasePkg/TestStub/VirtioPciDeviceStubLib/VirtioPciDeviceStubLib.c new file mode 100644 index 0000000..94cbb08 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestStub/VirtioPciDeviceStubLib/VirtioPciDeviceStubLib.c @@ -0,0 +1,404 @@ +/** @file + +Copyright (c) 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 + +PCI_CFG_SPACE *PciCfg; + +VOID +EFIAPI +PrintByByte(UINT8* Content, UINT32 Len) { + UINT32 i; + for (i = 0; i < Len; i++) { + if (i % 16 == 0) printf ("\n"); + printf ("%02x ", Content[i]); + } + printf ("\n"); +} + +EFI_STATUS +EFIAPI +VirtioPciIoRead ( + IN VIRTIO_PCI_DEVICE *Dev, + IN UINTN FieldOffset, + IN UINTN FieldSize, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +EFI_STATUS +EFIAPI +VirtioPciIoWrite ( + IN VIRTIO_PCI_DEVICE *Dev, + IN UINTN FieldOffset, + IN UINTN FieldSize, + IN UINT64 Value + ); + +/******************************************** + * PCI Functions for VIRTIO_DEVICE_PROTOCOL + *******************************************/ +EFI_STATUS +EFIAPI +VirtioPciDeviceRead ( + IN VIRTIO_DEVICE_PROTOCOL *This, + IN UINTN FieldOffset, + IN UINTN FieldSize, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +EFI_STATUS +EFIAPI +VirtioPciDeviceWrite ( + IN VIRTIO_DEVICE_PROTOCOL *This, + IN UINTN FieldOffset, + IN UINTN FieldSize, + IN UINT64 Value + ); + +EFI_STATUS +EFIAPI +VirtioPciGetDeviceFeatures ( + IN VIRTIO_DEVICE_PROTOCOL *This, + OUT UINT64 *DeviceFeatures + ); + +EFI_STATUS +EFIAPI +VirtioPciGetQueueSize ( + IN VIRTIO_DEVICE_PROTOCOL *This, + OUT UINT16 *QueueNumMax + ); + +EFI_STATUS +EFIAPI +VirtioPciSetQueueAlignment ( + IN VIRTIO_DEVICE_PROTOCOL *This, + IN UINT32 Alignment + ); + +EFI_STATUS +EFIAPI +VirtioPciSetPageSize ( + IN VIRTIO_DEVICE_PROTOCOL *This, + IN UINT32 PageSize + ); + +EFI_STATUS +EFIAPI +VirtioPciGetDeviceStatus ( + IN VIRTIO_DEVICE_PROTOCOL *This, + OUT UINT8 *DeviceStatus + ); + +EFI_STATUS +EFIAPI +VirtioPciSetGuestFeatures ( + IN VIRTIO_DEVICE_PROTOCOL *This, + IN UINT64 Features + ); + +EFI_STATUS +EFIAPI +VirtioPciSetQueueAddress ( + IN VIRTIO_DEVICE_PROTOCOL *This, + IN VRING *Ring, + IN UINT64 RingBaseShift + ); + +EFI_STATUS +EFIAPI +VirtioPciSetQueueSel ( + IN VIRTIO_DEVICE_PROTOCOL *This, + IN UINT16 Sel + ); + +EFI_STATUS +EFIAPI +VirtioPciSetQueueNotify ( + IN VIRTIO_DEVICE_PROTOCOL *This, + IN UINT16 Index + ); + +EFI_STATUS +EFIAPI +VirtioPciSetQueueSize ( + IN VIRTIO_DEVICE_PROTOCOL *This, + IN UINT16 Size + ); + +EFI_STATUS +EFIAPI +VirtioPciSetDeviceStatus ( + IN VIRTIO_DEVICE_PROTOCOL *This, + IN UINT8 DeviceStatus + ); + +EFI_STATUS +EFIAPI +VirtioPciAllocateSharedPages ( + IN VIRTIO_DEVICE_PROTOCOL *This, + IN UINTN NumPages, + OUT VOID **HostAddress + ); + +VOID +EFIAPI +VirtioPciFreeSharedPages ( + IN VIRTIO_DEVICE_PROTOCOL *This, + IN UINTN NumPages, + IN VOID *HostAddress + ); + +EFI_STATUS +EFIAPI +VirtioPciMapSharedBuffer ( + IN VIRTIO_DEVICE_PROTOCOL *This, + IN VIRTIO_MAP_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ); + +EFI_STATUS +EFIAPI +VirtioPciUnmapSharedBuffer ( + IN VIRTIO_DEVICE_PROTOCOL *This, + IN VOID *Mapping + ); + +EFI_STATUS +EFIAPI +PciIoRead ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BAR_IDX, + IN UINT16 Offset, + IN UINT16 Count, + IN OUT UINT8 *Buffer +) { + UINT16 Len = 0; + + switch (Width) + { + case EfiPciIoWidthUint32: + Len = Count * sizeof(UINT32); + break; + case EfiPciIoWidthUint16: + Len = Count * sizeof(UINT16); + break; + case EfiPciIoWidthUint8: + Len = Count * sizeof(UINT8); + break; + default: + break; + } + CopyMem (Buffer, (void *) ((UINT64) (PciCfg->PciBasicCfg.Device.Bar[1]) << 32 | PciCfg->PciBasicCfg.Device.Bar[0] + Offset), Len); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PciIoWrite ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BAR_IDX, + IN UINT16 Offset, + IN UINT16 Count, + IN OUT UINT8 *Buffer +) { + UINT16 Len = 0; + + switch (Width) + { + case EfiPciIoWidthUint32: + Len = Count * sizeof(UINT32); + break; + case EfiPciIoWidthUint16: + Len = Count * sizeof(UINT16); + break; + case EfiPciIoWidthUint8: + Len = Count * sizeof(UINT8); + break; + default: + break; + } + CopyMem ((void *) ((UINT64) (PciCfg->PciBasicCfg.Device.Bar[1]) << 32 | PciCfg->PciBasicCfg.Device.Bar[0] + Offset), Buffer, Len); + return EFI_SUCCESS; +} + +STATIC VIRTIO_DEVICE_PROTOCOL mDeviceProtocolTemplate = { + 0, // Revision + 0, // SubSystemDeviceId + VirtioPciGetDeviceFeatures, // GetDeviceFeatures + VirtioPciSetGuestFeatures, // SetGuestFeatures + VirtioPciSetQueueAddress, // SetQueueAddress + VirtioPciSetQueueSel, // SetQueueSel + VirtioPciSetQueueNotify, // SetQueueNotify + VirtioPciSetQueueAlignment, // SetQueueAlignment + VirtioPciSetPageSize, // SetPageSize + VirtioPciGetQueueSize, // GetQueueNumMax + VirtioPciSetQueueSize, // SetQueueNum + VirtioPciGetDeviceStatus, // GetDeviceStatus + VirtioPciSetDeviceStatus, // SetDeviceStatus + VirtioPciDeviceWrite, // WriteDevice + VirtioPciDeviceRead, // ReadDevice + VirtioPciAllocateSharedPages, // AllocateSharedPages + VirtioPciFreeSharedPages, // FreeSharedPages + VirtioPciMapSharedBuffer, // MapSharedBuffer + VirtioPciUnmapSharedBuffer, // UnmapSharedBuffer +}; + +EFI_STATUS +EFIAPI +InitVirtioPciDev ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN VOID *ConfigRegion, + IN OUT VIRTIO_PCI_DEVICE *Device +) { + // VOID *ConfigRegion; + + // ConfigRegion = (VOID *) AllocatePool(sizeof (PCI_CFG_SPACE) + sizeof(VIRTIO_HDR) + sizeof (VIRTIO_BLK_CONFIG)); + if (ConfigRegion == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Device->Signature = VIRTIO_PCI_DEVICE_SIGNATURE; + // + // Copy protocol template + // + CopyMem (&Device->VirtioDevice, &mDeviceProtocolTemplate, sizeof (VIRTIO_DEVICE_PROTOCOL)); + + PciCfg = (PCI_CFG_SPACE *) ConfigRegion; + + //This test expects this binary file to exist in the current execution folder + FILE *f = fopen("VirtioBlkFuzzSeed0.9.5.bin", "rb"); + if (f==NULL) { + fputs ("File error",stderr); + goto FreeDevice; + } + + fseek(f, 0, SEEK_END); + + long int fsize = ftell(f); + rewind(f); + if (fsize<0) { + fputs ("Error on reading file size",stderr); + fclose(f); + goto FreeDevice; + } + + size_t bytes_read = fread((void *)ConfigRegion, 1, (size_t)fsize, f); + fclose(f); + if ((UINTN)bytes_read!=fsize) { + fputs ("File error",stderr); + goto FreeDevice; + } + + PciCfg->PciBasicCfg.Device.Bar[0] = (UINT32) ((UINT64)PciCfg + sizeof(PCI_CFG_SPACE)); + PciCfg->PciBasicCfg.Device.Bar[1] = (UINT32) (((UINT64)PciCfg + sizeof(PCI_CFG_SPACE)) >> 32); + + Device->VirtioDevice.SubSystemDeviceId = PciCfg->PciBasicCfg.Device.SubsystemID; + + PciIo->Io.Read = &PciIoRead; + PciIo->Io.Write = &PciIoWrite; + Device->PciIo = PciIo; + + // + // Note: We don't support the MSI-X capability. If we did, + // the offset would become 24 after enabling MSI-X. + // + Device->DeviceSpecificConfigurationOffset = VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_PCI; + + return EFI_SUCCESS; + +FreeDevice: + // FreePool (ConfigRegion); + + return EFI_OUT_OF_RESOURCES; +} + +EFI_STATUS +EFIAPI +ParseBufferAndInitVirtioPciDev ( + IN UINT8 *TestBuffer, + IN UINTN BufferSize, + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN VOID *ConfigRegion, + IN OUT VIRTIO_PCI_DEVICE *Device +) +{ + VIRTIO_HDR *VirtioHdr; + + + // ConfigRegion = (VOID *) AllocatePool(sizeof (PCI_CFG_SPACE) + sizeof(VIRTIO_HDR) + sizeof (VIRTIO_BLK_CONFIG)); + if (ConfigRegion == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + if (BufferSize != sizeof (PCI_CFG_SPACE) + sizeof(VIRTIO_HDR) + sizeof (VIRTIO_BLK_CONFIG)) { + goto FreeDevice; + } + + Device->Signature = VIRTIO_PCI_DEVICE_SIGNATURE; + + PciCfg = (PCI_CFG_SPACE *) ConfigRegion; + + // + // Copy protocol template + // + CopyMem (&Device->VirtioDevice, &mDeviceProtocolTemplate, sizeof (VIRTIO_DEVICE_PROTOCOL)); + + CopyMem ((void *)PciCfg, (void *) TestBuffer, sizeof (PCI_CFG_SPACE) + sizeof(VIRTIO_HDR) + sizeof (VIRTIO_BLK_CONFIG)); + + Device->VirtioDevice.Revision = VIRTIO_SPEC_REVISION (0, 9, 5); + Device->VirtioDevice.SubSystemDeviceId = PciCfg->PciBasicCfg.Device.SubsystemID; + + // + // virtio-0.9.5, 2.1 PCI Discovery + // + if (!((PciCfg->PciBasicCfg.Hdr.VendorId == VIRTIO_VENDOR_ID) && + (PciCfg->PciBasicCfg.Hdr.DeviceId >= 0x1000) && + (PciCfg->PciBasicCfg.Hdr.DeviceId <= 0x103F) && + (PciCfg->PciBasicCfg.Hdr.RevisionID == 0x00))) { + goto FreeDevice; + } + + PciCfg->PciBasicCfg.Device.Bar[0] = (UINT32) ((UINT64)PciCfg + sizeof(PCI_CFG_SPACE)); + PciCfg->PciBasicCfg.Device.Bar[1] = (UINT32) (((UINT64)PciCfg + sizeof(PCI_CFG_SPACE)) >> 32); + + Device->VirtioDevice.SubSystemDeviceId = PciCfg->PciBasicCfg.Device.SubsystemID; + + PciIo->Io.Read = &PciIoRead; + PciIo->Io.Write = &PciIoWrite; + Device->PciIo = PciIo; + + // + // Note: We don't support the MSI-X capability. If we did, + // the offset would become 24 after enabling MSI-X. + // + Device->DeviceSpecificConfigurationOffset = VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_PCI; + + return EFI_SUCCESS; + +FreeDevice: + return EFI_OUT_OF_RESOURCES; +} diff --git a/HBFA/UefiHostFuzzTestCasePkg/TestStub/VirtioPciDeviceStubLib/VirtioPciDeviceStubLib.inf b/HBFA/UefiHostFuzzTestCasePkg/TestStub/VirtioPciDeviceStubLib/VirtioPciDeviceStubLib.inf new file mode 100644 index 0000000..3ebb1cc --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/TestStub/VirtioPciDeviceStubLib/VirtioPciDeviceStubLib.inf @@ -0,0 +1,36 @@ +## @file +# Component description file for TestUdf module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = VirtioPciDeviceStubLib + FILE_GUID = 1C7BD2C1-C26C-764C-0927-D8BF49A30DDA + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = VirtioPciDeviceStubLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + VirtioPciDeviceStubLib.c + +[Packages] + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib diff --git a/HBFA/UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec b/HBFA/UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec new file mode 100644 index 0000000..af0e2d0 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dec @@ -0,0 +1,15 @@ +## @file UefiHostFuzzTestCasePkg.dec +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = UefiHostFuzzTestCasePkg + PACKAGE_GUID = C8C2F32C-35BC-4D74-9467-178BC9325EBE + PACKAGE_VERSION = 0.11 + +[Includes.common] + TestStub/Include diff --git a/HBFA/UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dsc b/HBFA/UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dsc new file mode 100644 index 0000000..4f8bd6d --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dsc @@ -0,0 +1,296 @@ +## @file UefiHostTestPkg.dsc +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + PLATFORM_NAME = UefiHostFuzzTestCasePkg + PLATFORM_GUID = 9497CEE4-EEEB-4B38-B0EF-03E01920F040 + PLATFORM_VERSION = 0.11 + DSC_SPECIFICATION = 0x00010005 + OUTPUT_DIRECTORY = Build/UefiHostFuzzTestCasePkg + SUPPORTED_ARCHITECTURES = IA32|X64 + BUILD_TARGETS = DEBUG|RELEASE|NOOPT + SKUID_IDENTIFIER = DEFAULT + + DEFINE TEST_WITH_INSTRUMENT = FALSE + +[LibraryClasses] + BaseLib|UefiHostTestPkg/Library/BaseLibHost/BaseLibHost.inf + CacheMaintenanceLib|UefiHostTestPkg/Library/BaseCacheMaintenanceLibHost/BaseCacheMaintenanceLibHost.inf + BaseMemoryLib|UefiHostTestPkg/Library/BaseMemoryLibHost/BaseMemoryLibHost.inf + MemoryAllocationLib|UefiHostTestPkg/Library/MemoryAllocationLibHost/MemoryAllocationLibHost.inf + DebugLib|UefiHostTestPkg/Library/DebugLibHost/DebugLibHost.inf + UefiBootServicesTableLib|UefiHostTestPkg/Library/UefiBootServicesTableLibHost/UefiBootServicesTableLibHost.inf + HobLib|UefiHostTestPkg/Library/HobLibHost/HobLibHost.inf + SmmMemLib|UefiHostTestPkg/Library/SmmMemLibHost/SmmMemLibHost.inf + SmmMemLibStubLib|UefiHostTestPkg/Library/SmmMemLibHost/SmmMemLibHost.inf + DevicePathLib|UefiHostTestPkg/Library/UefiDevicePathLibHost/UefiDevicePathLibHost.inf + DxeServicesTableLib|UefiHostTestPkg/Library/DxeServicesTableLibHost/DxeServicesTableLibHost.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + SmmServicesTableLib|UefiHostTestPkg/Library/SmmServicesTableLibHost/SmmServicesTableLibHost.inf + MmServicesTableLib|UefiHostTestPkg/Library/SmmServicesTableLibHost/SmmServicesTableLibHost.inf + PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf + PeiServicesTablePointerLib|UefiHostTestPkg/Library/PeiServicesTablePointerLibHost/PeiServicesTablePointerLibHost.inf + UefiDriverEntryPoint|UefiHostTestPkg/Library/UefiDriverEntryPointHost/UefiDriverEntryPointHost.inf + PeimEntryPoint|UefiHostTestPkg/Library/PeimEntryPointHost/PeimEntryPointHost.inf + ToolChainHarnessLib|UefiHostFuzzTestPkg/Library/ToolChainHarnessLib/ToolChainHarnessLib.inf + + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf + SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf + SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf + TimerLib|UefiHostTestPkg/Library/BaseTimerLibHost/BaseTimerLibHost.inf + + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + + SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf + + DiskStubLib|UefiHostFuzzTestCasePkg/TestStub/DiskStubLib/DiskStubLib.inf + Usb2HcStubLib|UefiHostFuzzTestCasePkg/TestStub/Usb2HcStubLib/Usb2HcStubLib.inf + Usb2HcPpiStubLib|UefiHostFuzzTestCasePkg/TestStub/Usb2HcPpiStubLib/Usb2HcPpiStubLib.inf + UsbIoPpiStubLib|UefiHostFuzzTestCasePkg/TestStub/UsbIoPpiStubLib/UsbIoPpiStubLib.inf + Tcg2StubLib|UefiHostFuzzTestCasePkg/TestStub/Tcg2StubLib/Tcg2StubLib.inf + # Add below libs due to Edk2 update + VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf + VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf +!if $(TEST_WITH_INSTRUMENT) + IniParsingLib|UefiInstrumentTestPkg/Library/IniParsingLib/IniParsingLib.inf + NULL|UefiInstrumentTestPkg/Library/InstrumentLib/InstrumentLib.inf + InstrumentHookLib|UefiInstrumentTestPkg/Library/InstrumentHookLibNull/InstrumentHookLibNull.inf +!endif + +!if $(TEST_WITH_KLEE) + BaseLib|UefiHostTestPkg/Library/BaseLibHost/BaseLibHostNoAsm.inf +!endif + +[LibraryClasses.common.USER_DEFINED] + +[Components] +!if $(TEST_WITH_INSTRUMENT) + UefiHostFuzzTestCasePkg/TestStub/DiskStubLib/DiskStubLib.inf { + + MSFT: *_*_*_CC_FLAGS = /Gh /GH /Od /GL- + GCC:*_*_*_CC_FLAGS = -O0 -finstrument-functions + } + UefiHostTestPkg/Library/MemoryAllocationLibHost/MemoryAllocationLibHost.inf { + + MSFT: *_*_*_CC_FLAGS = /Gh /GH /Od /GL- + GCC:*_*_*_CC_FLAGS = -O0 -finstrument-functions + } + UefiHostFuzzTestPkg/Library/ToolChainHarnessLib/ToolChainHarnessLib.inf { + + MSFT: *_*_*_CC_FLAGS = "-DTEST_WITH_INSTRUMENT=TRUE" + GCC:*_*_*_CC_FLAGS = "-DTEST_WITH_INSTRUMENT=TRUE" + } +!endif + + UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/PartitionDxe/TestPartition.inf { + + NULL|MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf +!if $(TEST_WITH_INSTRUMENT) + + MSFT: *_*_*_CC_FLAGS = "-DTEST_WITH_INSTRUMENT=TRUE" + GCC:*_*_*_CC_FLAGS = "-DTEST_WITH_INSTRUMENT=TRUE" + + InstrumentHookLib|UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/PartitionDxe/InstrumentHookLibTestPartition/InstrumentHookLibTestPartition.inf +!endif + } + + UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/TestUdf.inf { + + NULL|MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf +!if $(TEST_WITH_INSTRUMENT) + + MSFT: *_*_*_CC_FLAGS = "-DTEST_WITH_INSTRUMENT=TRUE" + GCC:*_*_*_CC_FLAGS = "-DTEST_WITH_INSTRUMENT=TRUE" + + InstrumentHookLib|UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/InstrumentHookLibTestUdf/InstrumentHookLibTestUdf.inf +!endif + } + UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/TestFileName.inf { + + NULL|MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf + } + + UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library/BaseBmpSupportLib/TestBmpSupportLib.inf { + + BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf + } + + UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/CapsulePei/Common/TestCapsulePei.inf { + + NULL|MdeModulePkg/Universal/CapsulePei/CapsulePei.inf + } + + UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Variable/RuntimeDxe/TestVariableSmm.inf { + + NULL|MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf + NULL|UefiHostTestPkg/Library/BaseLibNullCpuid/BaseLibNullCpuid.inf + AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf + VarCheckLib|UefiHostTestPkg/Library/VarCheckLibNull/VarCheckLibNull.inf + VariableFlashInfoLib|MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseVariableFlashInfoLib.inf + } + + UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/Tpm2CommandLib/TestTpm2CommandLib.inf { + + Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf + Tpm2DeviceLib|UefiHostFuzzTestCasePkg/TestStub/Tpm2DeviceLibStub/Tpm2DeviceLibStub.inf + Tpm2DeviceStubLib|UefiHostFuzzTestCasePkg/TestStub/Tpm2DeviceLibStub/Tpm2DeviceLibStub.inf + } + + UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Usb/UsbBusDxe/TestUsb.inf { + + NULL|MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf + } + UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Usb/UsbBusPei/TestPeiUsb.inf { + + NULL|MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf + } + + UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibPkcs7/TestFmpAuthenticationLibPkcs7.inf { + + FmpAuthenticationLib|SecurityPkg/Library/FmpAuthenticationLibPkcs7/FmpAuthenticationLibPkcs7.inf + BaseCryptLib|UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibPkcs7/CryptoLibStubPkcs7.inf + } + UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibRsa2048Sha256/TestFmpAuthenticationLibRsa2048Sha256.inf { + + FmpAuthenticationLib|SecurityPkg/Library/FmpAuthenticationLibRsa2048Sha256/FmpAuthenticationLibRsa2048Sha256.inf + BaseCryptLib|UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibRsa2048Sha256/CryptoLibStubRsa2048Sha256.inf + } + + UefiHostFuzzTestCasePkg/TestCase/FatPkg/FatPei/TestPeiGpt.inf { + + NULL|UefiHostFuzzTestCasePkg/TestCase/FatPkg/FatPei/Override/FatPei.inf +!if $(TEST_WITH_INSTRUMENT) + + MSFT: *_*_*_CC_FLAGS = "-DTEST_WITH_INSTRUMENT=TRUE" + GCC:*_*_*_CC_FLAGS = "-DTEST_WITH_INSTRUMENT=TRUE" + + InstrumentHookLib|UefiHostFuzzTestCasePkg/TestCase/FatPkg/FatPei/InstrumentHookLibTestPeiGpt/InstrumentHookLibTestPeiGpt.inf +!endif + } + + UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/TestIdentifyAtaDevice.inf{ + + NULL|UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/AhciPei.inf + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf + LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf + PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf + TdxLib|MdePkg/Library/TdxLib/TdxLib.inf + CcProbeLib|OvmfPkg/Library/CcProbeLib/DxeCcProbeLib.inf + RegisterFilterLib|MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf + } + + UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/DxeTpm2MeasureBootLib/TestTcg2MeasureGptTable.inf{ + + NULL|SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf + BaseCryptLib|UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibPkcs7/CryptoLibStubPkcs7.inf + PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf + SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf + CcProbeLib|OvmfPkg/Library/CcProbeLib/DxeCcProbeLib.inf + } + + UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/DxeTpm2MeasureBootLib/TestTcg2MeasurePeImage.inf{ + + NULL|SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf + BaseCryptLib|UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibPkcs7/CryptoLibStubPkcs7.inf + PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf + SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf + CcProbeLib|OvmfPkg/Library/CcProbeLib/DxeCcProbeLib.inf + } + UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/EmuVariableFvbRuntimeDxe/TestValidateTdxCfv.inf{ + + NULL|OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf + UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf + PlatformFvbLib|OvmfPkg/Library/EmuVariableFvbLib/EmuVariableFvbLib.inf + CcProbeLib|OvmfPkg/Library/CcProbeLib/DxeCcProbeLib.inf + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf + PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf + RegisterFilterLib|MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf + #UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf + LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf + CcExitLib|OvmfPkg/Library/CcExitLib/CcExitLib.inf + MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf + MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf + CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf + PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf + PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf + TdxLib|MdePkg/Library/TdxLib/TdxLib.inf + PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf + MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf + QemuFwCfgSimpleParserLib|OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFwCfgSimpleParserLib.inf + QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf + PlatformInitLib|OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf + } + + UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioPciDeviceDxe/TestVirtioPciDevice.inf{ + + UefiPciCapPciIoLib|OvmfPkg/Library/UefiPciCapPciIoLib/UefiPciCapPciIoLib.inf + BasePciCapLib|OvmfPkg/Library/BasePciCapLib/BasePciCapLib.inf + VirtioPciDevice10StubLib|UefiHostFuzzTestCasePkg/TestStub/VirtioPciDevice10StubLib/VirtioPciDevice10StubLib.inf + VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf + UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf + OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf + } + + UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/Virtio10BlkDxe/TestVirtio10Blk.inf{ + + NULL|OvmfPkg/VirtioBlkDxe/VirtioBlk.inf + UefiPciCapPciIoLib|OvmfPkg/Library/UefiPciCapPciIoLib/UefiPciCapPciIoLib.inf + BasePciCapLib|OvmfPkg/Library/BasePciCapLib/BasePciCapLib.inf + VirtioBlkStubLib|UefiHostFuzzTestCasePkg/TestStub/VirtioBlkStubLib/VirtioBlkStubLib.inf + VirtioPciDevice10StubLib|UefiHostFuzzTestCasePkg/TestStub/VirtioPciDevice10StubLib/VirtioPciDevice10StubLib.inf + VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf + UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf + OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf + } + + UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioBlkDxe/TestVirtioBlk.inf{ + + NULL|OvmfPkg/VirtioBlkDxe/VirtioBlk.inf + NULL|OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf + VirtioBlkStubLib|UefiHostFuzzTestCasePkg/TestStub/VirtioBlkStubLib/VirtioBlkStubLib.inf + VirtioPciDevice10StubLib|UefiHostFuzzTestCasePkg/TestStub/VirtioPciDeviceStubLib/VirtioPciDeviceStubLib.inf + VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf + UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf + OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf + } + + UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioBlkReadWrite/TestVirtioBlkReadWrite.inf{ + + NULL|OvmfPkg/VirtioBlkDxe/VirtioBlk.inf + NULL|OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf + VirtioBlkStubLib|UefiHostFuzzTestCasePkg/TestStub/VirtioBlkStubLib/VirtioBlkStubLib.inf + VirtioPciDevice10StubLib|UefiHostFuzzTestCasePkg/TestStub/VirtioPciDeviceStubLib/VirtioPciDeviceStubLib.inf + VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf + UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf + OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf + } + + [PcdsDynamicDefault] + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|0 + [PcdsFixedAtBuild] + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbSize|0x002000 +!include UefiHostFuzzTestPkg/UefiHostFuzzTestBuildOption.dsc diff --git a/HBFA/UefiHostFuzzTestCasePkg/UefiHostFuzzTestDeviceSecurityPkg.dsc b/HBFA/UefiHostFuzzTestCasePkg/UefiHostFuzzTestDeviceSecurityPkg.dsc new file mode 100644 index 0000000..937de65 --- /dev/null +++ b/HBFA/UefiHostFuzzTestCasePkg/UefiHostFuzzTestDeviceSecurityPkg.dsc @@ -0,0 +1,83 @@ +## @file UefiHostFuzzTestCasePkg +# +# Copyright (c) 2022, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + PLATFORM_NAME = UefiHostFuzzTestDeviceSecurityPkg + PLATFORM_GUID = 9497CEE4-EEEB-4B38-B0EF-03E01920F042 + PLATFORM_VERSION = 0.11 + DSC_SPECIFICATION = 0x00010005 + OUTPUT_DIRECTORY = Build/UefiHostFuzzTestDeviceSecurityPkg + SUPPORTED_ARCHITECTURES = IA32|X64 + BUILD_TARGETS = DEBUG|RELEASE|NOOPT + SKUID_IDENTIFIER = DEFAULT + + DEFINE TEST_WITH_INSTRUMENT = FALSE + +[LibraryClasses] + BaseLib|UefiHostTestPkg/Library/BaseLibHost/BaseLibHost.inf + BaseMemoryLib|UefiHostTestPkg/Library/BaseMemoryLibHost/BaseMemoryLibHost.inf + MemoryAllocationLib|UefiHostTestPkg/Library/MemoryAllocationLibHost/MemoryAllocationLibHost.inf + DebugLib|UefiHostTestPkg/Library/DebugLibHost/DebugLibHost.inf + UefiBootServicesTableLib|UefiHostTestPkg/Library/UefiBootServicesTableLibHost/UefiBootServicesTableLibHost.inf + DevicePathLib|UefiHostTestPkg/Library/UefiDevicePathLibHost/UefiDevicePathLibHost.inf + DxeServicesTableLib|UefiHostTestPkg/Library/DxeServicesTableLibHost/DxeServicesTableLibHost.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + SmmServicesTableLib|UefiHostTestPkg/Library/SmmServicesTableLibHost/SmmServicesTableLibHost.inf + MmServicesTableLib|UefiHostTestPkg/Library/SmmServicesTableLibHost/SmmServicesTableLibHost.inf + UefiDriverEntryPoint|UefiHostTestPkg/Library/UefiDriverEntryPointHost/UefiDriverEntryPointHost.inf + ToolChainHarnessLib|UefiHostFuzzTestPkg/Library/ToolChainHarnessLib/ToolChainHarnessLib.inf + + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf + SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf + TimerLib|UefiHostTestPkg/Library/BaseTimerLibHost/BaseTimerLibHost.inf + + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + SmmServicesTableLib|UefiHostTestPkg/Library/SmmServicesTableLibHost/SmmServicesTableLibHost.inf + MmServicesTableLib|UefiHostTestPkg/Library/SmmServicesTableLibHost/SmmServicesTableLibHost.inf + PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf + PeiServicesTablePointerLib|UefiHostTestPkg/Library/PeiServicesTablePointerLibHost/PeiServicesTablePointerLibHost.inf + UefiDriverEntryPoint|UefiHostTestPkg/Library/UefiDriverEntryPointHost/UefiDriverEntryPointHost.inf + PeimEntryPoint|UefiHostTestPkg/Library/PeimEntryPointHost/PeimEntryPointHost.inf + ToolChainHarnessLib|UefiHostFuzzTestPkg/Library/ToolChainHarnessLib/ToolChainHarnessLib.inf + SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + + RngLib|MdePkg/Library/BaseRngLibNull/BaseRngLibNull.inf + TestSignListLib|DeviceSecurityPkg/Library/TestSignListLib/TestSignListLib.inf + SpdmSecuredMessageLib|DeviceSecurityPkg/Library/SpdmLib/SpdmSecuredMessageLib.inf + MemLibWrapper|DeviceSecurityPkg/Library/OsStub/MemLibWrapper/MemLibWrapper.inf + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLibFull.inf + #BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf + SpdmCommonLib|DeviceSecurityPkg/Library/SpdmLib/SpdmCommonLib.inf + SpdmCryptLib|DeviceSecurityPkg/Library/SpdmLib/SpdmCryptLib.inf + SpdmDeviceSecretLib|DeviceSecurityPkg/Library/SpdmLib/SpdmDeviceSecretLibNull.inf + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + CryptlibWrapper|DeviceSecurityPkg/Library/OsStub/CryptlibWrapper/CryptlibWrapper.inf + +!if $(TEST_WITH_INSTRUMENT) + IniParsingLib|UefiInstrumentTestPkg/Library/IniParsingLib/IniParsingLib.inf + NULL|UefiInstrumentTestPkg/Library/InstrumentLib/InstrumentLib.inf + InstrumentHookLib|UefiInstrumentTestPkg/Library/InstrumentHookLibNull/InstrumentHookLibNull.inf +!endif + +!if $(TEST_WITH_KLEE) + BaseLib|UefiHostTestPkg/Library/BaseLibHost/BaseLibHostNoAsm.inf +!endif + +[LibraryClasses.common.USER_DEFINED] + +[PcdsFixedAtBuild] + #gEfiCryptoPkgTokenSpaceGuid.PcdOpensslEcEnabled|TRUE + +[Components] + UefiHostFuzzTestCasePkg/TestCase/DeviceSecurityPkg/TestSignatureList/TestSignatureList.inf +!include UefiHostFuzzTestPkg/UefiHostFuzzTestBuildOption.dsc diff --git a/HBFA/UefiHostFuzzTestPkg/Conf/LLVMLink.py b/HBFA/UefiHostFuzzTestPkg/Conf/LLVMLink.py new file mode 100644 index 0000000..919802a --- /dev/null +++ b/HBFA/UefiHostFuzzTestPkg/Conf/LLVMLink.py @@ -0,0 +1,90 @@ +# @file +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +import os +import subprocess +import sys +from shutil import which +import argparse + +# python version +python_version = sys.version_info[0] + + +def GetObjFile(TargetPath): + ObjFileList = [] + static_library_files = open(os.path.join(TargetPath, + r'static_library_files.lst'), 'r') + static_library_files_list = static_library_files.readlines() + static_library_files.close() + + for file in static_library_files_list: + object_files = open(os.path.join(os.path.dirname(file.replace( + '.lib\n', '.lib')), r'object_files.lst'), 'r') + object_files_list = object_files.readlines() + object_files.close() + for objfile in object_files_list: + ObjFileList.append(objfile.replace('.obj\n', '.obj')) + + return ObjFileList + + +def VerifyCommand(command): + # Find full path of command binary / verity it is present + # return command with full path + try: + full_path_command = which(command) + except FileNotFoundError as e: + print(f"[!] Error finding command binary on system: {e}") + exit(1) + return full_path_command + + +def GenerateCommand(Command, Flags, InputFileList, OutputFile): + Template = " -o " + InputFile = ' '.join(InputFileList) + VerifiedCommand = VerifyCommand(Command) + CommandLine = Template.replace("", VerifiedCommand).replace( + "", Flags).replace("", InputFile).replace( + "", OutputFile) + print(CommandLine) + return CommandLine + + +def CallCommand(CommandLine): + CommandList = [item for item in CommandLine.split(' ') if len(item) > 0] + Cm = subprocess.Popen(CommandList, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + shell=False) + msg = Cm.communicate() + for m in msg: + print(m) + + +if __name__ == '__main__': + # # # Opt Parser + parse = argparse.ArgumentParser() + parse.add_argument("-o", dest="output", + help="output file name", default=None) + parse.add_argument("-d", dest="targetpath", + help="target path", default=None) + parse.add_argument("-t", dest="tool", + help="the tool you use", default=None) + options = parse.parse_args(sys.argv[1:]) + if options.tool: + if options.targetpath: + if options.output: + CallCommand(GenerateCommand(options.tool, "", + GetObjFile(options.targetpath), + options.output)) + else: + raise Exception("Please input -o output file name") + else: + raise Exception("Plesase input -d target file path") + else: + raise Exception("Please input -t tool you use.") diff --git a/HBFA/UefiHostFuzzTestPkg/Conf/build_rule.customized b/HBFA/UefiHostFuzzTestPkg/Conf/build_rule.customized new file mode 100644 index 0000000..660b496 --- /dev/null +++ b/HBFA/UefiHostFuzzTestPkg/Conf/build_rule.customized @@ -0,0 +1,646 @@ +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2010, Apple Inc. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +## Syntax +# +# "*" is used to indicate that the source files will be processed at the same time. +# "?" is used to indicate that the source files will be processed one by one. +# +# "[" [.][.][, [.][.]] "]" +# ]> +# (?|*). [(\n|,) (?|*).] +# +# ]> +# +# +# +# +# +# ]> +# +# [] +# +# is the MODULE_TYPE in EDK2 or COMPONENT_TYPE in EDK. +# Missing will cause an exception and break build. +# Missing will cause that related build target won't be generated but +# won't break build. +# + +## Placeholders for string substitution +# +# ${src} Source file(s) to be built (full path) +# ${s_path} Source file directory (absolute path) +# ${s_dir} Source file relative directory within a module +# (Note: ${s_dir} is always equals to "." if source file is given in absolute path.) +# ${s_name} Source file name without path +# ${s_base} Source file name without extension and path +# ${s_ext} Source file extension +# +# ${dst} Destination file(s) built from ${src} (full path) +# ${d_path} Destination file directory (absolute path) +# ${d_name} Destination file name without path +# ${d_base} Destination file name without extension and path +# ${d_ext} Destination file extension +# +# (+) Directory separator +# + +## Macro +# $(WORKSPACE) Workspace directory +# $(OUTPUT_DIR) Directory for intermediate files for building a module +# $(DEBUG_DIR) Directory for files used to debug a module +# $(BUILD_DIR) All files for building a platform will be put in this directory +# $(BIN_DIR) Common directory for executable files +# $(FV_DIR) Directory to store flash image files +# $(INC) Search path of current module +# $(NASM_INC) Search nasm file path of current module +# $(INC_LIST) A file containing search paths of current module +# $(LIBS) Static library files of current module +# $(_FLAGS) Tools flags of current module +# $(MODULE_NAME) Current module name +# $(MODULE_NAME_GUID) Current module name with module FILE_GUID if same $(MODULE_NAME) exists +# in different modules, otherwise its value is same as $(MODULE_NAME) +# $(MODULE_TYPE) Current module type +# $(MODULE_GUID) Current module guid +# $(ARCH) Architecture of current module +# $(TOOLCHAIN) Toolchain used to build current module +# $(TARGET) Target of current module (DEBUG/RELEASE) +# $() Path of tool +# $(EDK_TOOLS_PATH) Path of build tools +# $() File list of each file type +# (Note: The macro name is derived from file type name. For example, +# C-Code-File will have C_CODE_FILES macro.) +# $() Macro point to a file containing list of files of a file type +# ( +# Note: The macro and file name are derived from file type name. +# For example, C-Code-File will have C_CODE_FILES_LIST macro pointing +# to $(OUTPUT_DIR)/c_code_files.lst. The list file and macro name +# will be generated only when this macro is used in command line. +# This is intended to get over the long command line limitation. +# ) +# +# $(CP) copy command +# $(MV) move command +# $(RM) delete command +# $(MD) create dir command +# $(RD) remove dir command +# + +## Reserved File-Type +# +# Don't change following names of file types and their associated files, +# which are also used in tools' code +# +# C-Code-File +# C-Header-File +# Dynamic-Library-File +# Static-Library-File +# Visual-Form-Representation-File +# Unicode-Text-File +# + +## Build Rule Version Number +# build_rule_version=0.1 +# + +[C-Code-File] + + ?.c + ?.C + ?.cc + ?.CC + ?.cpp + ?.Cpp + ?.CPP + + + $(MAKE_FILE) + + + $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj + + + "$(CC)" /Fo${dst} $(CC_FLAGS) $(INC) ${src} + + + # For RVCTCYGWIN CC_FLAGS must be first to work around pathing issues + "$(CC)" $(CC_FLAGS) -c -o ${dst} $(INC) ${src} + + + "$(CC)" $(CC_FLAGS) -o ${dst} $(INC) ${src} + +[C-Code-File.BASE.AARCH64,C-Code-File.SEC.AARCH64,C-Code-File.PEI_CORE.AARCH64,C-Code-File.PEIM.AARCH64,C-Code-File.BASE.ARM,C-Code-File.SEC.ARM,C-Code-File.PEI_CORE.ARM,C-Code-File.PEIM.ARM] + + ?.c + + + $(MAKE_FILE) + + + $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj + + + "$(CC)" $(CC_FLAGS) $(CC_XIPFLAGS) -c -o ${dst} $(INC) ${src} + +[C-Header-File] + + *.h, *.H + + + + + +[Assembly-Code-File.COMMON.COMMON] + + ?.asm, ?.Asm, ?.ASM + + + ?.S, ?.s + + + $(MAKE_FILE) + + + $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj + + + "$(PP)" $(PP_FLAGS) $(INC) ${src} > ${d_path}(+)${s_base}.i + Trim --source-code --convert-hex --trim-long -o ${d_path}(+)${s_base}.iii ${d_path}(+)${s_base}.i + "$(ASM)" /Fo${dst} $(ASM_FLAGS) /I${s_path} $(INC) ${d_path}(+)${s_base}.iii + + + "$(PP)" $(PP_FLAGS) $(INC) ${src} > ${d_path}(+)${s_base}.i + Trim --trim-long --source-code -o ${d_path}(+)${s_base}.iii ${d_path}(+)${s_base}.i + # For RVCTCYGWIN ASM_FLAGS must be first to work around pathing issues + "$(ASM)" $(ASM_FLAGS) -o ${dst} $(INC) ${d_path}(+)${s_base}.iii + +[Assembly-Code-File.COMMON.ARM,Assembly-Code-File.COMMON.AARCH64] + # Remove --convert-hex for ARM as it breaks MSFT assemblers + + ?.asm, ?.Asm, ?.ASM + + + ?.S, ?.s + + + $(MAKE_FILE) + + + $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj + + + "$(PP)" $(PP_FLAGS) $(INC) ${src} > ${d_path}(+)${s_base}.i + Trim --source-code --convert-hex --trim-long -o ${d_path}(+)${s_base}.iii ${d_path}(+)${s_base}.i + "$(ASM)" /Fo${dst} $(ASM_FLAGS) /I${s_path} $(INC) ${d_path}(+)${s_base}.iii + + + "$(PP)" $(PP_FLAGS) $(INC) ${src} > ${d_path}(+)${s_base}.i + Trim --source-code --trim-long -o ${d_path}(+)${s_base}.iii ${d_path}(+)${s_base}.i + "$(ASM)" /Fo${dst} $(ASM_FLAGS) /I${s_path} $(INC) ${d_path}(+)${s_base}.iii + + + "$(PP)" $(PP_FLAGS) $(INC) ${src} > ${d_path}(+)${s_base}.i + Trim --trim-long --source-code -o ${d_path}(+)${s_base}.iii ${d_path}(+)${s_base}.i + # For RVCTCYGWIN ASM_FLAGS must be first to work around pathing issues + "$(ASM)" $(ASM_FLAGS) -o ${dst} $(INC) ${d_path}(+)${s_base}.iii + +[Nasm-Assembly-Code-File.COMMON.COMMON] + + ?.nasm + + + $(MAKE_FILE) + + + $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj + + + "$(PP)" $(PP_FLAGS) $(INC) ${src} > ${d_path}(+)${s_base}.i + Trim --trim-long --source-code -o ${d_path}(+)${s_base}.iii ${d_path}(+)${s_base}.i + "$(NASM)" -I${s_path}(+) $(NASM_INC) $(NASM_FLAGS) -o $dst ${d_path}(+)${s_base}.iii + +[Device-Tree-Source-File] + + ?.dts + + + $(MAKE_FILE) + + + $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dtb + + + "$(DTCPP)" $(DTCPP_FLAGS) $(INC) ${src} > ${d_path}(+)${s_base}.i + "$(DTC)" $(DTC_FLAGS) -I dts -O dtb -o ${dst} ${d_path}(+)${s_base}.i + +[Visual-Form-Representation-File] + + ?.vfr + ?.Vfr + ?.VFR + + + $(MAKE_FILE) + + + $(DEBUG_DIR)(+)${s_dir}(+)${s_base}.c + + + "$(VFRPP)" $(VFRPP_FLAGS) $(INC) ${src} > $(OUTPUT_DIR)(+)${s_base}.i + "$(VFR)" $(VFR_FLAGS) --string-db $(OUTPUT_DIR)(+)$(MODULE_NAME)StrDefs.hpk --output-directory ${d_path} $(OUTPUT_DIR)(+)${s_base}.i + +[Object-File] + + *.obj + *.o + + + $(OUTPUT_DIR)(+)$(MODULE_NAME).lib + + + "$(SLINK)" $(SLINK_FLAGS) /OUT:${dst} @$(OBJECT_FILES_LIST) + + + $(RM) ${dst} + "$(SLINK)" cr ${dst} $(SLINK_FLAGS) @$(OBJECT_FILES_LIST) + + + "$(SLINK)" $(SLINK_FLAGS) ${dst} --via $(OBJECT_FILES_LIST) + + + # $(OBJECT_FILES_LIST) has wrong paths for cygwin + "$(SLINK)" $(SLINK_FLAGS) ${dst} $(OBJECT_FILES) + + + "$(SLINK)" $(SLINK_FLAGS) ${dst} -filelist $(OBJECT_FILES_LIST) + +[Static-Library-File] + + *.lib + + + $(MAKE_FILE) + + + $(DEBUG_DIR)(+)$(MODULE_NAME).dll + + + "$(DLINK)" /OUT:${dst} $(DLINK_FLAGS) $(DLINK2_FLAGS) $(DLINK_SPATH) @$(STATIC_LIBRARY_FILES_LIST) + "$(DLINK)" /OUT:${dst} $(DLINK_FLAGS) $(DLINK_SPATH) @$(STATIC_LIBRARY_FILES_LIST) + + + "$(DLINK)" -o ${dst} $(DLINK_FLAGS) -Wl,--start-group,@$(STATIC_LIBRARY_FILES_LIST),--end-group $(CC_FLAGS) $(DLINK2_FLAGS) + "$(OBJCOPY)" $(OBJCOPY_FLAGS) ${dst} + + + "$(DLINK)" $(DLINK_FLAGS) -o ${dst} $(DLINK_SPATH) --via $(STATIC_LIBRARY_FILES_LIST) $(DLINK2_FLAGS) + + + #$(STATIC_LIBRARY_FILES_LIST) has wrong paths for cygwin + "$(DLINK)" $(DLINK_FLAGS) -o ${dst} $(DLINK_SPATH) $(STATIC_LIBRARY_FILES) $(DLINK2_FLAGS) + + + "$(DLINK)" $(DLINK_FLAGS) -o ${dst} $(DLINK_SPATH) -filelist $(STATIC_LIBRARY_FILES_LIST) $(DLINK2_FLAGS) + + +[Static-Library-File.SEC.AARCH64, Static-Library-File.PEI_CORE.AARCH64, Static-Library-File.PEIM.AARCH64,Static-Library-File.SEC.ARM, Static-Library-File.PEI_CORE.ARM, Static-Library-File.PEIM.ARM] + + *.lib + + + $(MAKE_FILE) + + + $(DEBUG_DIR)(+)$(MODULE_NAME).dll + + + "$(DLINK)" -o ${dst} $(DLINK_FLAGS) $(DLINK_XIPFLAGS) -Wl,--start-group,@$(STATIC_LIBRARY_FILES_LIST),--end-group $(CC_FLAGS) $(CC_XIPFLAGS) $(DLINK2_FLAGS) + "$(OBJCOPY)" $(OBJCOPY_FLAGS) ${dst} + + +[Static-Library-File.USER_DEFINED, Static-Library-File.HOST_APPLICATION] + + *.lib + + + $(MAKE_FILE) + + + $(DEBUG_DIR)(+)$(MODULE_NAME) + + + "$(DLINK)" $(DLINK_FLAGS) $(DLINK_SPATH) @$(STATIC_LIBRARY_FILES_LIST) + + + "$(DLINK)" $(DLINK_FLAGS) -Wl,--start-group,@$(STATIC_LIBRARY_FILES_LIST),--end-group $(DLINK2_FLAGS) + + + echo $(STATIC_LIBRARY_FILES_LIST) + python $(SCRIPT_PATH) ${DLINK_FLAGS} -t $(DLINK) -d $(OUTPUT_DIR) + + + "$(DLINK)" $(DLINK_FLAGS) -o ${dst} $(DLINK_SPATH) --via $(STATIC_LIBRARY_FILES_LIST) $(DLINK2_FLAGS) + + + #$(STATIC_LIBRARY_FILES_LIST) has the wrong paths for cygwin + "$(DLINK)" $(DLINK_FLAGS) -o ${dst} $(DLINK_SPATH) $(STATIC_LIBRARY_FILES) $(DLINK2_FLAGS) + + + "$(DLINK)" -o ${dst} $(DLINK_FLAGS) $(DLINK_SPATH) -filelist $(STATIC_LIBRARY_FILES_LIST) $(DLINK2_FLAGS) + + +[Dynamic-Library-File] + + ?.dll + + + $(OUTPUT_DIR)(+)$(MODULE_NAME).efi + + + "$(GENFW)" -e $(MODULE_TYPE) -o ${dst} ${src} $(GENFW_FLAGS) + $(CP) ${dst} $(DEBUG_DIR) + $(CP) ${dst} $(BIN_DIR)(+)$(MODULE_NAME_GUID).efi + -$(CP) $(DEBUG_DIR)(+)*.map $(OUTPUT_DIR) + -$(CP) $(DEBUG_DIR)(+)*.pdb $(OUTPUT_DIR) + + $(CP) ${src} $(DEBUG_DIR)(+)$(MODULE_NAME).debug + $(OBJCOPY) --strip-unneeded -R .eh_frame ${src} + + # + #The below 2 lines are only needed for UNIXGCC tool chain, which generates PE image directly + # + -$(OBJCOPY) $(OBJCOPY_ADDDEBUGFLAG) ${src} + -$(CP) $(DEBUG_DIR)(+)$(MODULE_NAME).debug $(BIN_DIR)(+)$(MODULE_NAME_GUID).debug + + "$(GENFW)" -e $(MODULE_TYPE) -o ${dst} ${src} $(GENFW_FLAGS) + $(CP) ${dst} $(DEBUG_DIR) + $(CP) ${dst} $(BIN_DIR)(+)$(MODULE_NAME_GUID).efi + -$(CP) $(DEBUG_DIR)(+)*.map $(OUTPUT_DIR) + + + # tool to convert Mach-O to PE/COFF + "$(MTOC)" -subsystem $(MODULE_TYPE) $(MTOC_FLAGS) ${src} $(DEBUG_DIR)(+)$(MODULE_NAME).pecoff + # create symbol file for GDB debug + -$(DSYMUTIL) ${src} + "$(GENFW)" -e $(MODULE_TYPE) -o ${dst} $(DEBUG_DIR)(+)$(MODULE_NAME).pecoff $(GENFW_FLAGS) + $(CP) ${dst} $(DEBUG_DIR) + $(CP) ${dst} $(BIN_DIR)(+)$(MODULE_NAME_GUID).efi + -$(CP) $(DEBUG_DIR)(+)*.map $(OUTPUT_DIR) + +[Dependency-Expression-File] + + ?.dxs, ?.Dxs, ?.DXS + + + $(OUTPUT_DIR)(+)$(MODULE_NAME).depex + + + $(MAKE_FILE) + + + "$(PP)" $(APP_FLAGS) $(INC) ${src} > $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.i + Trim --source-code -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iii $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.i + GenDepex -t $(MODULE_TYPE) -o ${dst} $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iii + +[Acpi-Source-Language-File] + + ?.asl, ?.Asl, ?.ASL + + + $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.aml + + + $(MAKE_FILE) + + + Trim --asl-file -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.i -i $(INC_LIST) ${src} + "$(ASLPP)" $(ASLPP_FLAGS) $(INC) /I${s_path} $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.i > $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iii + Trim --source-code -l -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iiii $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iii + "$(ASL)" $(ASL_FLAGS) $(ASL_OUTFLAGS)${dst} $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iiii + + + Trim --asl-file -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.i -i $(INC_LIST) ${src} + "$(ASLPP)" $(ASLPP_FLAGS) $(INC) -I${s_path} $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.i > $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iii + Trim --source-code -l -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iiii $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iii + "$(ASL)" $(ASL_FLAGS) $(ASL_OUTFLAGS)${dst} $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iiii + +[C-Code-File.AcpiTable] + + ?.c + + + $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.acpi + + + $(MAKE_FILE) + + + "$(ASLCC)" /Fo$(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(ASLCC_FLAGS) $(INC) ${src} + "$(ASLDLINK)" /OUT:$(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(ASLDLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj + "$(GENFW)" -o ${dst} -c $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(GENFW_FLAGS) + + + "$(ASLCC)" -c -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(CC_FLAGS) $(ASLCC_FLAGS) $(INC) ${src} + "$(ASLDLINK)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(ASLDLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj + "$(GENFW)" -o ${dst} -c $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(GENFW_FLAGS) + +[Acpi-Table-Code-File] + + ?.aslc, ?.act + + + $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.acpi + + + $(MAKE_FILE) + + + "$(ASLCC)" /Fo$(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(ASLCC_FLAGS) $(INC) ${src} + "$(ASLDLINK)" /OUT:$(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(ASLDLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj + "$(GENFW)" -o ${dst} -c $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(GENFW_FLAGS) + + + "$(ASLCC)" -c -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(CC_FLAGS) $(ASLCC_FLAGS) $(INC) ${src} + "$(ASLDLINK)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(ASLDLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj + "$(GENFW)" -o ${dst} -c $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(GENFW_FLAGS) + + + "$(ASLCC)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(ASLCC_FLAGS) $(INC) ${src} + "$(ASLDLINK)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(ASLDLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj + "$(MTOC)" -subsystem $(MODULE_TYPE) $(MTOC_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.dll $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.pecoff + "$(GENFW)" -o ${dst} -c $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.pecoff $(GENFW_FLAGS) + + +[Masm16-Code-File] + + ?.asm16, ?.Asm16, ?.ASM16, ?.s16, ?.S16 + + + $(MAKE_FILE) + + + $(OUTPUT_DIR)(+)${s_base}.com + + + "$(PP)" $(PP_FLAGS) $(INC) ${src} > ${d_path}(+)${s_base}.i + Trim --source-code --convert-hex --trim-long -o ${d_path}(+)${s_base}.iii ${d_path}(+)${s_base}.i + cd $(OUTPUT_DIR)(+)${s_dir} + "$(ASM16)" /nologo /c /omf $(INC) /Fo$(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj ${d_path}(+)${s_base}.iii + "$(ASMLINK)" $(ASMLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj,${dst},,,, + + + "$(PP)" $(PP_FLAGS) $(INC) ${src} > ${d_path}(+)${s_base}.i + Trim --source-code -o ${d_path}(+)${s_base}.iii ${d_path}(+)${s_base}.i + "$(ASM)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(ASM_FLAGS) $(INC) ${d_path}(+)${s_base}.iii + "$(DLINK)" -o ${dst} $(DLINK_FLAGS) --start-group $(DLINK_SPATH) $(LIBS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj --end-group + + + "$(PP)" $(PP_FLAGS) $(INC) ${src} > ${d_path}(+)${s_base}.i + Trim --source-code -o ${d_path}(+)${s_base}.iii ${d_path}(+)${s_base}.i + "$(ASM)" -o $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj $(ASM_FLAGS) $(INC) ${d_path}(+)${s_base}.iii + "$(SLINK)" $(SLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.slib $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj + otool -t $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.slib | hex2bin.py ${dst} + + +[Nasm-to-Binary-Code-File] + + ?.nasmb + + + $(MAKE_FILE) + + + $(OUTPUT_DIR)(+)${s_base}.bin + + + "$(PP)" $(PP_FLAGS) $(INC) ${src} > ${d_path}(+)${s_base}.i + Trim --source-code --convert-hex -o ${d_path}(+)${s_base}.iii ${d_path}(+)${s_base}.i + "$(NASM)" -I${s_path}(+) -l ${d_path}(+)${s_base}.lst $(NASMB_FLAGS) -o $dst ${d_path}(+)${s_base}.iii + # copy the output file with .com postfix that be same to the output file of .asm16 + $(CP) ${dst} $(OUTPUT_DIR)(+)${s_base}.com + +[Microcode-File.USER_DEFINED, Microcode-File.Microcode] + + ?.txt, ?.TXT, ?.Txt, ?.mut, ?.inc + + + $(OUTPUT_DIR)(+)${s_base}.mcb + + + "$(GENFW)" -o ${dst} -m ${src} $(GENFW_FLAGS) + +[Microcode-Binary-File] + + *.mcb + + + $(MAKE_FILE) + + + $(OUTPUT_DIR)(+)$(MODULE_NAME).bin + + + "$(GENFW)" -o ${dst} -j $(MICROCODE_BINARY_FILES) $(GENFW_FLAGS) + -$(CP) ${dst} $(BIN_DIR)(+)$(MODULE_NAME_GUID).bin + +[EFI-Image-File] + + ?.efi, ?.Efi, ?.EFI + + + + + +[Unicode-Text-File] + + *.uni, *.Uni, *.UNI + + + $(DEBUG_DIR)(+)AutoGen.c + $(DEBUG_DIR)(+)$(MODULE_NAME)StrDefs.h + $(OUTPUT_DIR)(+)$(MODULE_NAME)StrDefs.hpk + + + +[Image-Definition-File] + + *.idf, *.Idf, *.IDF + + + $(DEBUG_DIR)(+)AutoGen.c + $(DEBUG_DIR)(+)$(MODULE_NAME)ImgDefs.h + $(OUTPUT_DIR)(+)$(MODULE_NAME)Idf.hpk + + + +[Efi-Image.UEFI_OPTIONROM] + + ?.efi, ?.EFI, ?.Efi + + + $(BIN_DIR)(+)$(MODULE_NAME_GUID).rom + + + $(OPTROM) -i $(PCI_DEVICE_ID) -f $(PCI_VENDOR_ID) -l $(PCI_CLASS_CODE) -r $(PCI_REVISION) -o $dst $(OPTROM_FLAGS) $src + +[Unicode-Text-File.UEFI_HII] + + *.uni, *.Uni, *.UNI + + + $(OUTPUT_DIR)(+)$(MODULE_NAME)StrDefs.hpk + $(DEBUG_DIR)(+)$(MODULE_NAME)StrDefs.h + + + +[Image-Definition-File.UEFI_HII] + + *.idf, *.Idf, *.IDF + + + $(DEBUG_DIR)(+)$(MODULE_NAME)ImgDefs.h + $(OUTPUT_DIR)(+)$(MODULE_NAME)Idf.hpk + + + +[Visual-Form-Representation-File.UEFI_HII] + + ?.vfr + ?.Vfr + ?.VFR + + + $(MAKE_FILE) + + + $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.hpk + + + "$(VFRPP)" $(VFRPP_FLAGS) $(INC) ${src} > $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.i + "$(VFR)" $(VFR_FLAGS) --create-ifr-package --string-db $(OUTPUT_DIR)(+)$(MODULE_NAME)StrDefs.hpk --output-directory $(OUTPUT_DIR)(+)${s_dir} $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.i + +[Hii-Binary-Package.UEFI_HII] + + *.hpk + + + $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.lib + + + $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc + + + "$(GENFW)" -o $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc -g $(MODULE_GUID) --hiipackage $(HII_BINARY_PACKAGES) $(GENFW_FLAGS) + "$(RC)" /Fo${dst} $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc + + + "$(GENFW)" -o $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc -g $(MODULE_GUID) --hiibinpackage $(HII_BINARY_PACKAGES) $(GENFW_FLAGS) + "$(RC)" $(RC_FLAGS) $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc ${dst} + + + GenFw -o $(OUTPUT_DIR)(+)$(MODULE_NAME)hii.rc -g $(MODULE_GUID) --hiibinpackage $(HII_BINARY_PACKAGES) + + diff --git a/HBFA/UefiHostFuzzTestPkg/Conf/tools_def.customized b/HBFA/UefiHostFuzzTestPkg/Conf/tools_def.customized new file mode 100644 index 0000000..db954d9 --- /dev/null +++ b/HBFA/UefiHostFuzzTestPkg/Conf/tools_def.customized @@ -0,0 +1,614 @@ +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +#################################################################################### +# GCC Common for AFL/Klee +#################################################################################### +DEFINE AFL_IA32_PREFIX = ENV(AFL_BIN) +DEFINE AFL_X64_PREFIX = ENV(AFL_BIN) + +DEFINE KLEE_IA32_PREFIX = ENV(KLEE_BIN) +DEFINE KLEE_X64_PREFIX = ENV(KLEE_BIN) + +DEFINE AFL_IA32_CC_FLAGS = DEF(GCC5_IA32_CC_FLAGS) -fno-pic -fno-pie +DEFINE AFL_X64_CC_FLAGS = DEF(GCC5_X64_CC_FLAGS) +DEFINE AFL_IA32_X64_DLINK_COMMON = DEF(GCC5_IA32_X64_DLINK_COMMON) +DEFINE AFL_IA32_X64_ASLDLINK_FLAGS = DEF(GCC5_IA32_X64_ASLDLINK_FLAGS) +DEFINE AFL_IA32_X64_DLINK_FLAGS = DEF(GCC5_IA32_X64_DLINK_FLAGS) +DEFINE AFL_IA32_DLINK2_FLAGS = DEF(GCC5_IA32_DLINK2_FLAGS) -Wno-error +DEFINE AFL_X64_DLINK_FLAGS = DEF(GCC5_X64_DLINK_FLAGS) +DEFINE AFL_X64_DLINK2_FLAGS = DEF(GCC5_X64_DLINK2_FLAGS) -Wno-error +DEFINE AFL_ASM_FLAGS = DEF(GCC5_ASM_FLAGS) +DEFINE AFL_ARM_ASM_FLAGS = DEF(GCC5_ARM_ASM_FLAGS) +DEFINE AFL_AARCH64_ASM_FLAGS = DEF(GCC5_AARCH64_ASM_FLAGS) +DEFINE AFL_ARM_CC_FLAGS = DEF(GCC5_ARM_CC_FLAGS) +DEFINE AFL_ARM_CC_XIPFLAGS = DEF(GCC5_ARM_CC_XIPFLAGS) +DEFINE AFL_AARCH64_CC_FLAGS = DEF(GCC5_AARCH64_CC_FLAGS) +DEFINE AFL_AARCH64_CC_XIPFLAGS = DEF(GCC5_AARCH64_CC_XIPFLAGS) +DEFINE AFL_ARM_DLINK_FLAGS = DEF(GCC5_ARM_DLINK_FLAGS) +DEFINE AFL_ARM_DLINK2_FLAGS = DEF(GCC5_ARM_DLINK2_FLAGS) -Wno-error +DEFINE AFL_AARCH64_DLINK_FLAGS = DEF(GCC5_AARCH64_DLINK_FLAGS) +DEFINE AFL_AARCH64_DLINK2_FLAGS = DEF(GCC5_AARCH64_DLINK2_FLAGS) -Wno-error +DEFINE AFL_ARM_ASLDLINK_FLAGS = DEF(GCC5_ARM_ASLDLINK_FLAGS) +DEFINE AFL_AARCH64_ASLDLINK_FLAGS = DEF(GCC5_AARCH64_ASLDLINK_FLAGS) + + +DEFINE KLEE_IA32_CC_FLAGS = DEF(GCC48_ALL_CC_FLAGS) -MD -Wno-deprecated-declarations -Wno-unused-result -Wno-error -Wno-int-to-void-pointer-cast -Wno-int-to-pointer-cast -g -O2 -O0 -emit-llvm +DEFINE KLEE_X64_CC_FLAGS = DEF(GCC48_ALL_CC_FLAGS) -MD -Wno-deprecated-declarations -Wno-unused-result -g -O2 -O0 -emit-llvm +DEFINE KLEE_IA32_X64_DLINK_COMMON = DEF(GCC5_IA32_X64_DLINK_COMMON) +DEFINE KLEE_IA32_X64_ASLDLINK_FLAGS = DEF(GCC5_IA32_X64_ASLDLINK_FLAGS) +DEFINE KLEE_IA32_X64_DLINK_FLAGS = DEF(GCC5_IA32_X64_DLINK_FLAGS) +DEFINE KLEE_IA32_DLINK2_FLAGS = DEF(GCC5_IA32_DLINK2_FLAGS) -Wno-error +DEFINE KLEE_X64_DLINK_FLAGS = DEF(GCC5_X64_DLINK_FLAGS) +DEFINE KLEE_X64_DLINK2_FLAGS = DEF(GCC5_X64_DLINK2_FLAGS) -Wno-error +DEFINE KLEE_ASM_FLAGS = DEF(GCC5_ASM_FLAGS) +DEFINE KLEE_ARM_ASM_FLAGS = DEF(GCC5_ARM_ASM_FLAGS) +DEFINE KLEE_AARCH64_ASM_FLAGS = DEF(GCC5_AARCH64_ASM_FLAGS) +DEFINE KLEE_ARM_CC_FLAGS = DEF(GCC5_ARM_CC_FLAGS) +DEFINE KLEE_ARM_CC_XIPFLAGS = DEF(GCC5_ARM_CC_XIPFLAGS) +DEFINE KLEE_AARCH64_CC_FLAGS = DEF(GCC5_AARCH64_CC_FLAGS) +DEFINE KLEE_AARCH64_CC_XIPFLAGS = DEF(GCC5_AARCH64_CC_XIPFLAGS) +DEFINE KLEE_ARM_DLINK_FLAGS = DEF(GCC5_ARM_DLINK_FLAGS) +DEFINE KLEE_ARM_DLINK2_FLAGS = DEF(GCC5_ARM_DLINK2_FLAGS) -Wno-error +DEFINE KLEE_AARCH64_DLINK_FLAGS = DEF(GCC5_AARCH64_DLINK_FLAGS) +DEFINE KLEE_AARCH64_DLINK2_FLAGS = DEF(GCC5_AARCH64_DLINK2_FLAGS) -Wno-error +DEFINE KLEE_ARM_ASLDLINK_FLAGS = DEF(GCC5_ARM_ASLDLINK_FLAGS) +DEFINE KLEE_AARCH64_ASLDLINK_FLAGS = DEF(GCC5_AARCH64_ASLDLINK_FLAGS) + +#################################################################################### +# +# AFL - This configuration is used to compile under Linux to produce +# PE/COFF binaries using AFL with Link Time Optimization enabled +# +#################################################################################### +*_AFL_*_*_FAMILY = GCC + +*_AFL_*_MAKE_PATH = DEF(GCC_HOST_PREFIX)make +*_AFL_*_*_DLL = ENV(AFL_DLL) +*_AFL_*_ASL_PATH = DEF(UNIX_IASL_BIN) + +*_AFL_*_PP_FLAGS = DEF(GCC_PP_FLAGS) +*_AFL_*_ASLPP_FLAGS = DEF(GCC_ASLPP_FLAGS) +*_AFL_*_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) +*_AFL_*_VFRPP_FLAGS = DEF(GCC_VFRPP_FLAGS) +*_AFL_*_APP_FLAGS = +*_AFL_*_ASL_FLAGS = DEF(IASL_FLAGS) +*_AFL_*_ASL_OUTFLAGS = DEF(IASL_OUTFLAGS) + +################## +# AFL IA32 definitions +################## +*_AFL_IA32_OBJCOPY_PATH = DEF(AFL_IA32_PREFIX)objcopy +*_AFL_IA32_CC_PATH = DEF(AFL_IA32_PREFIX)gcc +*_AFL_IA32_SLINK_PATH = DEF(AFL_IA32_PREFIX)gcc-ar +*_AFL_IA32_DLINK_PATH = DEF(AFL_IA32_PREFIX)gcc +*_AFL_IA32_ASLDLINK_PATH = DEF(AFL_IA32_PREFIX)gcc +*_AFL_IA32_ASM_PATH = DEF(AFL_IA32_PREFIX)gcc +*_AFL_IA32_PP_PATH = DEF(AFL_IA32_PREFIX)gcc +*_AFL_IA32_VFRPP_PATH = DEF(AFL_IA32_PREFIX)gcc +*_AFL_IA32_ASLCC_PATH = DEF(AFL_IA32_PREFIX)gcc +*_AFL_IA32_ASLPP_PATH = DEF(AFL_IA32_PREFIX)gcc +*_AFL_IA32_RC_PATH = DEF(AFL_IA32_PREFIX)objcopy + +*_AFL_IA32_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m32 -fno-lto +*_AFL_IA32_ASLDLINK_FLAGS = DEF(AFL_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_i386 -no-pie +*_AFL_IA32_ASM_FLAGS = DEF(AFL_ASM_FLAGS) -m32 -march=i386 +*_AFL_IA32_DLINK2_FLAGS = DEF(AFL_IA32_DLINK2_FLAGS) -no-pie +*_AFL_IA32_RC_FLAGS = DEF(GCC_IA32_RC_FLAGS) +*_AFL_IA32_OBJCOPY_FLAGS = +*_AFL_IA32_NASM_FLAGS = -f elf32 + +DEBUG_AFL_IA32_CC_FLAGS = DEF(AFL_IA32_CC_FLAGS) -flto -Os +DEBUG_AFL_IA32_DLINK_FLAGS = DEF(AFL_IA32_X64_DLINK_FLAGS) -flto -Os -Wl,-m,elf_i386,--oformat=elf32-i386 + +RELEASE_AFL_IA32_CC_FLAGS = DEF(AFL_IA32_CC_FLAGS) -flto -Os -Wno-unused-but-set-variable -Wno-unused-const-variable +RELEASE_AFL_IA32_DLINK_FLAGS = DEF(AFL_IA32_X64_DLINK_FLAGS) -flto -Os -Wl,-m,elf_i386,--oformat=elf32-i386 + +NOOPT_AFL_IA32_CC_FLAGS = DEF(AFL_IA32_CC_FLAGS) -O0 +NOOPT_AFL_IA32_DLINK_FLAGS = DEF(AFL_IA32_X64_DLINK_FLAGS) -Wl,-m,elf_i386,--oformat=elf32-i386 -O0 + +################## +# AFL X64 definitions +################## +*_AFL_X64_OBJCOPY_PATH = DEF(AFL_X64_PREFIX)objcopy +*_AFL_X64_CC_PATH = DEF(AFL_X64_PREFIX)gcc +*_AFL_X64_SLINK_PATH = DEF(AFL_X64_PREFIX)gcc-ar +*_AFL_X64_DLINK_PATH = DEF(AFL_X64_PREFIX)gcc +*_AFL_X64_ASLDLINK_PATH = DEF(AFL_X64_PREFIX)gcc +*_AFL_X64_ASM_PATH = DEF(AFL_X64_PREFIX)gcc +*_AFL_X64_PP_PATH = DEF(AFL_X64_PREFIX)gcc +*_AFL_X64_VFRPP_PATH = DEF(AFL_X64_PREFIX)gcc +*_AFL_X64_ASLCC_PATH = DEF(AFL_X64_PREFIX)gcc +*_AFL_X64_ASLPP_PATH = DEF(AFL_X64_PREFIX)gcc +*_AFL_X64_RC_PATH = DEF(AFL_X64_PREFIX)objcopy + +*_AFL_X64_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m64 -fno-lto +*_AFL_X64_ASLDLINK_FLAGS = DEF(AFL_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_x86_64 +*_AFL_X64_ASM_FLAGS = DEF(AFL_ASM_FLAGS) -m64 +*_AFL_X64_DLINK2_FLAGS = DEF(AFL_X64_DLINK2_FLAGS) +*_AFL_X64_RC_FLAGS = DEF(GCC_X64_RC_FLAGS) +*_AFL_X64_OBJCOPY_FLAGS = +*_AFL_X64_NASM_FLAGS = -f elf64 + +DEBUG_AFL_X64_CC_FLAGS = DEF(AFL_X64_CC_FLAGS) -flto -DUSING_LTO -Os +DEBUG_AFL_X64_DLINK_FLAGS = DEF(AFL_X64_DLINK_FLAGS) -flto -Os + +RELEASE_AFL_X64_CC_FLAGS = DEF(AFL_X64_CC_FLAGS) -flto -DUSING_LTO -Os -Wno-unused-but-set-variable -Wno-unused-const-variable +RELEASE_AFL_X64_DLINK_FLAGS = DEF(AFL_X64_DLINK_FLAGS) -flto -Os + +NOOPT_AFL_X64_CC_FLAGS = DEF(AFL_X64_CC_FLAGS) -O0 +NOOPT_AFL_X64_DLINK_FLAGS = DEF(AFL_X64_DLINK_FLAGS) -O0 + +#################################################################################### +# +# Klee - This configuration is used to compile under Linux to produce +# PE/COFF binaries using Klee with Link Time Optimization enabled +# +#################################################################################### +*_KLEE_*_*_FAMILY = GCC +*_KLEE_*_*_BUILDRULEFAMILY = KLEE + +*_KLEE_*_MAKE_PATH = DEF(GCC_HOST_PREFIX)make +*_KLEE_*_*_DLL = ENV(KLEE_DLL) +*_KLEE_*_ASL_PATH = DEF(UNIX_IASL_BIN) + +*_KLEE_*_PP_FLAGS = DEF(GCC_PP_FLAGS) +*_KLEE_*_ASLPP_FLAGS = DEF(GCC_ASLPP_FLAGS) +*_KLEE_*_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) +*_KLEE_*_VFRPP_FLAGS = DEF(GCC_VFRPP_FLAGS) +*_KLEE_*_APP_FLAGS = +*_KLEE_*_ASL_FLAGS = DEF(IASL_FLAGS) +*_KLEE_*_ASL_OUTFLAGS = DEF(IASL_OUTFLAGS) + +################## +# KLEE IA32 definitions +################## +*_KLEE_IA32_OBJCOPY_PATH = DEF(KLEE_IA32_PREFIX)objcopy +*_KLEE_IA32_CC_PATH = DEF(KLEE_IA32_PREFIX)wllvm +*_KLEE_IA32_SLINK_PATH = DEF(KLEE_IA32_PREFIX)llvm-ar +*_KLEE_IA32_DLINK_PATH = DEF(KLEE_IA32_PREFIX)llvm-link +*_KLEE_IA32_ASLDLINK_PATH = DEF(KLEE_IA32_PREFIX)wllvm +*_KLEE_IA32_ASM_PATH = DEF(KLEE_IA32_PREFIX)wllvm +*_KLEE_IA32_PP_PATH = DEF(KLEE_IA32_PREFIX)wllvm +*_KLEE_IA32_VFRPP_PATH = DEF(KLEE_IA32_PREFIX)wllvm +*_KLEE_IA32_ASLCC_PATH = DEF(KLEE_IA32_PREFIX)wllvm +*_KLEE_IA32_ASLPP_PATH = DEF(KLEE_IA32_PREFIX)wllvm +*_KLEE_IA32_RC_PATH = DEF(KLEE_IA32_PREFIX)objcopy + +*_KLEE_IA32_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m32 -fno-lto +*_KLEE_IA32_ASLDLINK_FLAGS = DEF(KLEE_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_i386 -no-pie +*_KLEE_IA32_ASM_FLAGS = DEF(KLEE_ASM_FLAGS) -m32 -march=i386 +*_KLEE_IA32_DLINK2_FLAGS = DEF(KLEE_IA32_DLINK2_FLAGS) -no-pie +*_KLEE_IA32_RC_FLAGS = DEF(GCC_IA32_RC_FLAGS) +*_KLEE_IA32_OBJCOPY_FLAGS = +*_KLEE_IA32_NASM_FLAGS = -f elf32 + + DEBUG_KLEE_IA32_CC_FLAGS = DEF(KLEE_IA32_CC_FLAGS) -flto -Os + DEBUG_KLEE_IA32_DLINK_FLAGS = DEF(KLEE_IA32_X64_DLINK_FLAGS) -flto -Os -Wl,-m,elf_i386,--oformat=elf32-i386 + +RELEASE_KLEE_IA32_CC_FLAGS = DEF(KLEE_IA32_CC_FLAGS) -flto -Os -Wno-unused-but-set-variable -Wno-unused-const-variable +RELEASE_KLEE_IA32_DLINK_FLAGS = DEF(KLEE_IA32_X64_DLINK_FLAGS) -flto -Os -Wl,-m,elf_i386,--oformat=elf32-i386 + + NOOPT_KLEE_IA32_CC_FLAGS = DEF(KLEE_IA32_CC_FLAGS) -O0 + NOOPT_KLEE_IA32_DLINK_FLAGS = DEF(KLEE_IA32_X64_DLINK_FLAGS) -Wl,-m,elf_i386,--oformat=elf32-i386 -O0 + +################## +# KLEE X64 definitions +################## +*_KLEE_X64_OBJCOPY_PATH = DEF(KLEE_X64_PREFIX)objcopy +*_KLEE_X64_CC_PATH = DEF(KLEE_X64_PREFIX)wllvm +*_KLEE_X64_SLINK_PATH = DEF(KLEE_X64_PREFIX)llvm-ar +*_KLEE_X64_DLINK_PATH = DEF(KLEE_X64_PREFIX)llvm-link +*_KLEE_X64_ASLDLINK_PATH = DEF(KLEE_X64_PREFIX)wllvm +*_KLEE_X64_ASM_PATH = DEF(KLEE_X64_PREFIX)wllvm +*_KLEE_X64_PP_PATH = DEF(KLEE_X64_PREFIX)wllvm +*_KLEE_X64_VFRPP_PATH = DEF(KLEE_X64_PREFIX)wllvm +*_KLEE_X64_ASLCC_PATH = DEF(KLEE_X64_PREFIX)wllvm +*_KLEE_X64_ASLPP_PATH = DEF(KLEE_X64_PREFIX)wllvm +*_KLEE_X64_RC_PATH = DEF(KLEE_X64_PREFIX)objcopy + +*_KLEE_X64_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m64 -fno-lto +*_KLEE_X64_ASLDLINK_FLAGS = DEF(KLEE_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_x86_64 +*_KLEE_X64_ASM_FLAGS = DEF(KLEE_ASM_FLAGS) -m64 +*_KLEE_X64_DLINK2_FLAGS = DEF(KLEE_X64_DLINK2_FLAGS) +*_KLEE_X64_RC_FLAGS = DEF(GCC_X64_RC_FLAGS) +*_KLEE_X64_OBJCOPY_FLAGS = +*_KLEE_X64_NASM_FLAGS = -f elf64 + +DEBUG_KLEE_X64_CC_FLAGS = DEF(KLEE_X64_CC_FLAGS) -flto -DUSING_LTO -Os +DEBUG_KLEE_X64_DLINK_FLAGS = DEF(KLEE_X64_DLINK_FLAGS) -flto -Os + +RELEASE_KLEE_X64_CC_FLAGS = DEF(KLEE_X64_CC_FLAGS) -flto -DUSING_LTO -Os -Wno-unused-but-set-variable -Wno-unused-const-variable +RELEASE_KLEE_X64_DLINK_FLAGS = DEF(KLEE_X64_DLINK_FLAGS) -flto -Os + +NOOPT_KLEE_X64_CC_FLAGS = DEF(KLEE_X64_CC_FLAGS) -O0 +NOOPT_KLEE_X64_DLINK_FLAGS = DEF(KLEE_X64_DLINK_FLAGS) -O0 + +#################################################################################### +# +# Clang 8 - This configuration is used to compile under Linux to produce +# PE/COFF binaries using LLVM/Clang 8 with Link Time Optimization enabled +# +#################################################################################### +*_CLANG8_*_*_FAMILY = GCC +*_CLANG8_*_MAKE_PATH = make +*_CLANG8_*_*_DLL = ENV(CLANG8_DLL) +*_CLANG8_*_ASL_PATH = DEF(UNIX_IASL_BIN) + +*_CLANG8_*_APP_FLAGS = +*_CLANG8_*_ASL_FLAGS = DEF(IASL_FLAGS) +*_CLANG8_*_ASL_OUTFLAGS = DEF(IASL_OUTFLAGS) + +DEFINE CLANG8_IA32_PREFIX = ENV(CLANG8_BIN) +DEFINE CLANG8_X64_PREFIX = ENV(CLANG8_BIN) + +DEFINE CLANG8_IA32_TARGET = -target i686-pc-linux-gnu +DEFINE CLANG8_X64_TARGET = -target x86_64-pc-linux-gnu + +DEFINE CLANG8_WARNING_OVERRIDES = -Wno-parentheses-equality -Wno-tautological-compare -Wno-tautological-constant-out-of-range-compare -Wno-empty-body -Wno-unused-const-variable -Wno-varargs -Wno-unknown-warning-option +DEFINE CLANG8_ALL_CC_FLAGS = DEF(GCC48_ALL_CC_FLAGS) DEF(CLANG8_WARNING_OVERRIDES) -fno-stack-protector -mms-bitfields -Wno-address -Wno-shift-negative-value -Wno-unknown-pragmas -Wno-incompatible-library-redeclaration -fno-asynchronous-unwind-tables -mno-sse -mno-mmx -msoft-float -mno-implicit-float -ftrap-function=undefined_behavior_has_been_optimized_away_by_clang -funsigned-char -fno-ms-extensions -Wno-null-dereference + +########################### +# CLANG8 IA32 definitions +########################### +*_CLANG8_IA32_OBJCOPY_PATH = objcopy +*_CLANG8_IA32_CC_PATH = DEF(CLANG8_IA32_PREFIX)clang +*_CLANG8_IA32_SLINK_PATH = DEF(CLANG8_IA32_PREFIX)llvm-ar +*_CLANG8_IA32_DLINK_PATH = DEF(CLANG8_IA32_PREFIX)clang +*_CLANG8_IA32_ASLDLINK_PATH = DEF(CLANG8_IA32_PREFIX)clang +*_CLANG8_IA32_ASM_PATH = DEF(CLANG8_IA32_PREFIX)clang +*_CLANG8_IA32_PP_PATH = DEF(CLANG8_IA32_PREFIX)clang +*_CLANG8_IA32_VFRPP_PATH = DEF(CLANG8_IA32_PREFIX)clang +*_CLANG8_IA32_ASLCC_PATH = DEF(CLANG8_IA32_PREFIX)clang +*_CLANG8_IA32_ASLPP_PATH = DEF(CLANG8_IA32_PREFIX)clang +*_CLANG8_IA32_RC_PATH = objcopy + +*_CLANG8_IA32_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m32 -fno-lto DEF(CLANG8_IA32_TARGET) +*_CLANG8_IA32_ASLDLINK_FLAGS = DEF(GCC5_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_i386 +*_CLANG8_IA32_ASM_FLAGS = DEF(GCC5_ASM_FLAGS) -m32 -march=i386 DEF(CLANG8_IA32_TARGET) +*_CLANG8_IA32_RC_FLAGS = DEF(GCC_IA32_RC_FLAGS) +*_CLANG8_IA32_OBJCOPY_FLAGS = +*_CLANG8_IA32_NASM_FLAGS = -f elf32 +*_CLANG8_IA32_PP_FLAGS = DEF(GCC_PP_FLAGS) DEF(CLANG8_IA32_TARGET) +*_CLANG8_IA32_ASLPP_FLAGS = DEF(GCC_ASLPP_FLAGS) DEF(CLANG8_IA32_TARGET) +*_CLANG8_IA32_VFRPP_FLAGS = DEF(GCC_VFRPP_FLAGS) DEF(CLANG8_IA32_TARGET) + +DEBUG_CLANG8_IA32_CC_FLAGS = DEF(CLANG8_ALL_CC_FLAGS) -m32 -Oz -flto -march=i586 DEF(CLANG8_IA32_TARGET) -g +DEBUG_CLANG8_IA32_DLINK_FLAGS = DEF(GCC5_IA32_X64_DLINK_FLAGS) -flto -Wl,-Oz -Wl,-melf_i386 -Wl,--oformat=elf32-i386 +DEBUG_CLANG8_IA32_DLINK2_FLAGS = DEF(GCC5_IA32_DLINK2_FLAGS) -O3 + +RELEASE_CLANG8_IA32_CC_FLAGS = DEF(CLANG8_ALL_CC_FLAGS) -m32 -Oz -flto -march=i586 DEF(CLANG8_IA32_TARGET) +RELEASE_CLANG8_IA32_DLINK_FLAGS = DEF(GCC5_IA32_X64_DLINK_FLAGS) -flto -Wl,-Oz -Wl,-melf_i386 -Wl,--oformat=elf32-i386 +RELEASE_CLANG8_IA32_DLINK2_FLAGS = DEF(GCC5_IA32_DLINK2_FLAGS) -O3 + +NOOPT_CLANG8_IA32_CC_FLAGS = DEF(CLANG8_ALL_CC_FLAGS) -m32 -O0 -march=i586 DEF(CLANG8_IA32_TARGET) -g +NOOPT_CLANG8_IA32_DLINK_FLAGS = DEF(GCC5_IA32_X64_DLINK_FLAGS) -Wl,-O0 -Wl,-melf_i386 -Wl,--oformat=elf32-i386 +NOOPT_CLANG8_IA32_DLINK2_FLAGS = DEF(GCC5_IA32_DLINK2_FLAGS) -O0 + +########################## +# CLANG8 X64 definitions +########################## +*_CLANG8_X64_OBJCOPY_PATH = objcopy +*_CLANG8_X64_CC_PATH = DEF(CLANG8_X64_PREFIX)clang +*_CLANG8_X64_SLINK_PATH = DEF(CLANG8_X64_PREFIX)llvm-ar +*_CLANG8_X64_DLINK_PATH = DEF(CLANG8_X64_PREFIX)clang +*_CLANG8_X64_ASLDLINK_PATH = DEF(CLANG8_X64_PREFIX)clang +*_CLANG8_X64_ASM_PATH = DEF(CLANG8_X64_PREFIX)clang +*_CLANG8_X64_PP_PATH = DEF(CLANG8_X64_PREFIX)clang +*_CLANG8_X64_VFRPP_PATH = DEF(CLANG8_X64_PREFIX)clang +*_CLANG8_X64_ASLCC_PATH = DEF(CLANG8_X64_PREFIX)clang +*_CLANG8_X64_ASLPP_PATH = DEF(CLANG8_X64_PREFIX)clang +*_CLANG8_X64_RC_PATH = objcopy + +*_CLANG8_X64_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m64 -fno-lto DEF(CLANG8_X64_TARGET) +*_CLANG8_X64_ASLDLINK_FLAGS = DEF(GCC5_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_x86_64 +*_CLANG8_X64_ASM_FLAGS = DEF(GCC5_ASM_FLAGS) -m64 DEF(CLANG8_X64_TARGET) +*_CLANG8_X64_RC_FLAGS = DEF(GCC_X64_RC_FLAGS) +*_CLANG8_X64_OBJCOPY_FLAGS = +*_CLANG8_X64_NASM_FLAGS = -f elf64 +*_CLANG8_X64_PP_FLAGS = DEF(GCC_PP_FLAGS) DEF(CLANG8_X64_TARGET) +*_CLANG8_X64_ASLPP_FLAGS = DEF(GCC_ASLPP_FLAGS) DEF(CLANG8_X64_TARGET) +*_CLANG8_X64_VFRPP_FLAGS = DEF(GCC_VFRPP_FLAGS) DEF(CLANG8_X64_TARGET) + +DEBUG_CLANG8_X64_CC_FLAGS = DEF(CLANG8_ALL_CC_FLAGS) -m64 "-DEFIAPI=__attribute__((ms_abi))" -mno-red-zone -mcmodel=small -fpie -Oz -flto DEF(CLANG8_X64_TARGET) -g +DEBUG_CLANG8_X64_DLINK_FLAGS = DEF(GCC5_IA32_X64_DLINK_FLAGS) -flto -Wl,-Oz -Wl,-melf_x86_64 -Wl,--oformat=elf64-x86-64 -Wl,-pie -mcmodel=small +DEBUG_CLANG8_X64_DLINK2_FLAGS = DEF(GCC5_X64_DLINK2_FLAGS) -O3 + +RELEASE_CLANG8_X64_CC_FLAGS = DEF(CLANG8_ALL_CC_FLAGS) -m64 "-DEFIAPI=__attribute__((ms_abi))" -mno-red-zone -mcmodel=small -fpie -Oz -flto DEF(CLANG8_X64_TARGET) +RELEASE_CLANG8_X64_DLINK_FLAGS = DEF(GCC5_IA32_X64_DLINK_FLAGS) -flto -Wl,-Oz -Wl,-melf_x86_64 -Wl,--oformat=elf64-x86-64 -Wl,-pie -mcmodel=small +RELEASE_CLANG8_X64_DLINK2_FLAGS = DEF(GCC5_X64_DLINK2_FLAGS) -O3 + +NOOPT_CLANG8_X64_CC_FLAGS = DEF(CLANG8_ALL_CC_FLAGS) -m64 "-DEFIAPI=__attribute__((ms_abi))" -mno-red-zone -mcmodel=small -fpie -O0 DEF(CLANG8_X64_TARGET) -g +NOOPT_CLANG8_X64_DLINK_FLAGS = DEF(GCC5_IA32_X64_DLINK_FLAGS) -Wl,-O0 -Wl,-melf_x86_64 -Wl,--oformat=elf64-x86-64 -Wl,-pie -mcmodel=small +NOOPT_CLANG8_X64_DLINK2_FLAGS = DEF(GCC5_X64_DLINK2_FLAGS) -O0 + +#################################################################################### +# +# LIBFUZZER - This configuration is used to compile under Linux to produce +# PE/COFF binaries using LLVM/Clang 8 with Link Time Optimization enabled +# +#################################################################################### +*_LIBFUZZER_*_*_FAMILY = GCC +*_LIBFUZZER_*_MAKE_PATH = make +*_LIBFUZZER_*_*_DLL = ENV(LIBFUZZER_DLL) +*_LIBFUZZER_*_ASL_PATH = DEF(UNIX_IASL_BIN) + +*_LIBFUZZER_*_APP_FLAGS = +*_LIBFUZZER_*_ASL_FLAGS = DEF(IASL_FLAGS) +*_LIBFUZZER_*_ASL_OUTFLAGS = DEF(IASL_OUTFLAGS) + +DEFINE LIBFUZZER_IA32_PREFIX = ENV(LIBFUZZER_BIN) +DEFINE LIBFUZZER_X64_PREFIX = ENV(LIBFUZZER_BIN) + +DEFINE LIBFUZZER_IA32_TARGET = -target i686-pc-linux-gnu +DEFINE LIBFUZZER_X64_TARGET = -target x86_64-pc-linux-gnu + +DEFINE LIBFUZZER_WARNING_OVERRIDES = -Wno-parentheses-equality -Wno-tautological-compare -Wno-tautological-constant-out-of-range-compare -Wno-empty-body -Wno-unused-const-variable -Wno-varargs -Wno-unknown-warning-option +DEFINE LIBFUZZER_ALL_CC_FLAGS = DEF(GCC48_ALL_CC_FLAGS) DEF(LIBFUZZER_WARNING_OVERRIDES) -fno-stack-protector -mms-bitfields -Wno-address -Wno-shift-negative-value -Wno-unknown-pragmas -Wno-incompatible-library-redeclaration -fno-asynchronous-unwind-tables -mno-sse -mno-mmx -msoft-float -mno-implicit-float -ftrap-function=undefined_behavior_has_been_optimized_away_by_clang -funsigned-char -fno-ms-extensions -Wno-null-dereference + +########################### +# LIBFUZZER IA32 definitions +########################### +*_LIBFUZZER_IA32_OBJCOPY_PATH = objcopy +*_LIBFUZZER_IA32_CC_PATH = DEF(LIBFUZZER_IA32_PREFIX)clang +*_LIBFUZZER_IA32_SLINK_PATH = DEF(LIBFUZZER_IA32_PREFIX)llvm-ar +*_LIBFUZZER_IA32_DLINK_PATH = DEF(LIBFUZZER_IA32_PREFIX)clang +*_LIBFUZZER_IA32_ASLDLINK_PATH = DEF(LIBFUZZER_IA32_PREFIX)clang +*_LIBFUZZER_IA32_ASM_PATH = DEF(LIBFUZZER_IA32_PREFIX)clang +*_LIBFUZZER_IA32_PP_PATH = DEF(LIBFUZZER_IA32_PREFIX)clang +*_LIBFUZZER_IA32_VFRPP_PATH = DEF(LIBFUZZER_IA32_PREFIX)clang +*_LIBFUZZER_IA32_ASLCC_PATH = DEF(LIBFUZZER_IA32_PREFIX)clang +*_LIBFUZZER_IA32_ASLPP_PATH = DEF(LIBFUZZER_IA32_PREFIX)clang +*_LIBFUZZER_IA32_RC_PATH = objcopy + +*_LIBFUZZER_IA32_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m32 -fno-lto DEF(LIBFUZZER_IA32_TARGET) +*_LIBFUZZER_IA32_ASLDLINK_FLAGS = DEF(GCC5_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_i386 +*_LIBFUZZER_IA32_ASM_FLAGS = DEF(GCC5_ASM_FLAGS) -m32 -march=i386 DEF(LIBFUZZER_IA32_TARGET) +*_LIBFUZZER_IA32_RC_FLAGS = DEF(GCC_IA32_RC_FLAGS) +*_LIBFUZZER_IA32_OBJCOPY_FLAGS = +*_LIBFUZZER_IA32_NASM_FLAGS = -f elf32 +*_LIBFUZZER_IA32_PP_FLAGS = DEF(GCC_PP_FLAGS) DEF(LIBFUZZER_IA32_TARGET) +*_LIBFUZZER_IA32_ASLPP_FLAGS = DEF(GCC_ASLPP_FLAGS) DEF(LIBFUZZER_IA32_TARGET) +*_LIBFUZZER_IA32_VFRPP_FLAGS = DEF(GCC_VFRPP_FLAGS) DEF(LIBFUZZER_IA32_TARGET) + +DEBUG_LIBFUZZER_IA32_CC_FLAGS = DEF(LIBFUZZER_ALL_CC_FLAGS) -m32 -Oz -flto -march=i586 DEF(LIBFUZZER_IA32_TARGET) -g +DEBUG_LIBFUZZER_IA32_DLINK_FLAGS = DEF(GCC5_IA32_X64_DLINK_FLAGS) -flto -Wl,-Oz -Wl,-melf_i386 -Wl,--oformat=elf32-i386 +DEBUG_LIBFUZZER_IA32_DLINK2_FLAGS = DEF(GCC5_IA32_DLINK2_FLAGS) -O3 + +RELEASE_LIBFUZZER_IA32_CC_FLAGS = DEF(LIBFUZZER_ALL_CC_FLAGS) -m32 -Oz -flto -march=i586 DEF(LIBFUZZER_IA32_TARGET) +RELEASE_LIBFUZZER_IA32_DLINK_FLAGS = DEF(GCC5_IA32_X64_DLINK_FLAGS) -flto -Wl,-Oz -Wl,-melf_i386 -Wl,--oformat=elf32-i386 +RELEASE_LIBFUZZER_IA32_DLINK2_FLAGS = DEF(GCC5_IA32_DLINK2_FLAGS) -O3 + +NOOPT_LIBFUZZER_IA32_CC_FLAGS = DEF(LIBFUZZER_ALL_CC_FLAGS) -m32 -O0 -march=i586 DEF(LIBFUZZER_IA32_TARGET) -g +NOOPT_LIBFUZZER_IA32_DLINK_FLAGS = DEF(GCC5_IA32_X64_DLINK_FLAGS) -Wl,-O0 -Wl,-melf_i386 -Wl,--oformat=elf32-i386 +NOOPT_LIBFUZZER_IA32_DLINK2_FLAGS = DEF(GCC5_IA32_DLINK2_FLAGS) -O0 + +########################## +# LIBFUZZER X64 definitions +########################## +*_LIBFUZZER_X64_OBJCOPY_PATH = objcopy +*_LIBFUZZER_X64_CC_PATH = DEF(LIBFUZZER_X64_PREFIX)clang +*_LIBFUZZER_X64_SLINK_PATH = DEF(LIBFUZZER_X64_PREFIX)llvm-ar +*_LIBFUZZER_X64_DLINK_PATH = DEF(LIBFUZZER_X64_PREFIX)clang +*_LIBFUZZER_X64_ASLDLINK_PATH = DEF(LIBFUZZER_X64_PREFIX)clang +*_LIBFUZZER_X64_ASM_PATH = DEF(LIBFUZZER_X64_PREFIX)clang +*_LIBFUZZER_X64_PP_PATH = DEF(LIBFUZZER_X64_PREFIX)clang +*_LIBFUZZER_X64_VFRPP_PATH = DEF(LIBFUZZER_X64_PREFIX)clang +*_LIBFUZZER_X64_ASLCC_PATH = DEF(LIBFUZZER_X64_PREFIX)clang +*_LIBFUZZER_X64_ASLPP_PATH = DEF(LIBFUZZER_X64_PREFIX)clang +*_LIBFUZZER_X64_RC_PATH = objcopy + +*_LIBFUZZER_X64_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m64 -fno-lto DEF(LIBFUZZER_X64_TARGET) +*_LIBFUZZER_X64_ASLDLINK_FLAGS = DEF(GCC5_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_x86_64 +*_LIBFUZZER_X64_ASM_FLAGS = DEF(GCC5_ASM_FLAGS) -m64 DEF(LIBFUZZER_X64_TARGET) +*_LIBFUZZER_X64_RC_FLAGS = DEF(GCC_X64_RC_FLAGS) +*_LIBFUZZER_X64_OBJCOPY_FLAGS = +*_LIBFUZZER_X64_NASM_FLAGS = -f elf64 +*_LIBFUZZER_X64_PP_FLAGS = DEF(GCC_PP_FLAGS) DEF(LIBFUZZER_X64_TARGET) +*_LIBFUZZER_X64_ASLPP_FLAGS = DEF(GCC_ASLPP_FLAGS) DEF(LIBFUZZER_X64_TARGET) +*_LIBFUZZER_X64_VFRPP_FLAGS = DEF(GCC_VFRPP_FLAGS) DEF(LIBFUZZER_X64_TARGET) + +DEBUG_LIBFUZZER_X64_CC_FLAGS = DEF(LIBFUZZER_ALL_CC_FLAGS) -m64 "-DEFIAPI=__attribute__((ms_abi))" -mno-red-zone -mcmodel=small -fpie -Oz -flto DEF(LIBFUZZER_X64_TARGET) -g +DEBUG_LIBFUZZER_X64_DLINK_FLAGS = DEF(GCC5_IA32_X64_DLINK_FLAGS) -flto -Wl,-Oz -Wl,-melf_x86_64 -Wl,--oformat=elf64-x86-64 -Wl,-pie -mcmodel=small +DEBUG_LIBFUZZER_X64_DLINK2_FLAGS = DEF(GCC5_X64_DLINK2_FLAGS) -O3 + +RELEASE_LIBFUZZER_X64_CC_FLAGS = DEF(LIBFUZZER_ALL_CC_FLAGS) -m64 "-DEFIAPI=__attribute__((ms_abi))" -mno-red-zone -mcmodel=small -fpie -Oz -flto DEF(LIBFUZZER_X64_TARGET) +RELEASE_LIBFUZZER_X64_DLINK_FLAGS = DEF(GCC5_IA32_X64_DLINK_FLAGS) -flto -Wl,-Oz -Wl,-melf_x86_64 -Wl,--oformat=elf64-x86-64 -Wl,-pie -mcmodel=small +RELEASE_LIBFUZZER_X64_DLINK2_FLAGS = DEF(GCC5_X64_DLINK2_FLAGS) -O3 + +NOOPT_LIBFUZZER_X64_CC_FLAGS = DEF(LIBFUZZER_ALL_CC_FLAGS) -m64 "-DEFIAPI=__attribute__((ms_abi))" -mno-red-zone -mcmodel=small -fpie -O0 DEF(LIBFUZZER_X64_TARGET) -g +NOOPT_LIBFUZZER_X64_DLINK_FLAGS = DEF(GCC5_IA32_X64_DLINK_FLAGS) -Wl,-O0 -Wl,-melf_x86_64 -Wl,--oformat=elf64-x86-64 -Wl,-pie -mcmodel=small +NOOPT_LIBFUZZER_X64_DLINK2_FLAGS = DEF(GCC5_X64_DLINK2_FLAGS) -O0 + +#################################################################################### +# +# Clang Win - This configuration is used to compile under Windows to produce +# PE/COFF binaries using LLVM/Clang with Link Time Optimization enabled +# +#################################################################################### +*_CLANGWIN_*_*_FAMILY = GCC +*_CLANGWIN_*_*_BUILDRULEFAMILY = CLANGWIN +*_CLANGWIN_*_MAKE_PATH = nmake +*_CLANGWIN_*_*_DLL = ENV(CLANGWIN_DLL) +*_CLANGWIN_*_ASL_PATH = DEF(DEFAULT_WIN_ASL_BIN) + +*_CLANGWIN_*_APP_FLAGS = +*_CLANGWIN_*_ASL_FLAGS = DEF(DEFAULT_WIN_ASL_FLAGS) +*_CLANGWIN_*_ASL_OUTFLAGS = DEF(DEFAULT_WIN_ASL_OUTFLAGS) + +DEFINE CLANGWIN_IA32_PREFIX = ENV(CLANGWIN_BIN) +DEFINE CLANGWIN_X64_PREFIX = ENV(CLANGWIN_BIN) + +DEFINE CLANGWIN_IA32_TARGET = -target i686-pc-windows-msvc +DEFINE CLANGWIN_X64_TARGET = -target x86_64-pc-windows-msvc + +DEFINE CLANGWIN_WARNING_OVERRIDES = -Wno-parentheses-equality -Wno-tautological-compare -Wno-tautological-constant-out-of-range-compare -Wno-empty-body -Wno-unused-const-variable -Wno-varargs -Wno-unknown-warning-option +DEFINE CLANGWIN_ALL_CC_FLAGS = DEF(GCC48_ALL_CC_FLAGS) DEF(CLANGWIN_WARNING_OVERRIDES) -fno-stack-protector -mms-bitfields -Wno-address -Wno-shift-negative-value -Wno-unknown-pragmas -Wno-incompatible-library-redeclaration -fno-asynchronous-unwind-tables -mno-sse -mno-mmx -msoft-float -mno-implicit-float -ftrap-function=undefined_behavior_has_been_optimized_away_by_clang -funsigned-char -fno-ms-extensions -Wno-null-dereference -Wno-microsoft -fms-compatibility + +########################### +# CLANGWIN IA32 definitions +########################### +*_CLANGWIN_IA32_CC_PATH = DEF(CLANGWIN_IA32_PREFIX)clang +*_CLANGWIN_IA32_SLINK_PATH = lib.exe +*_CLANGWIN_IA32_DLINK_PATH = link.exe +*_CLANGWIN_IA32_ASLDLINK_PATH = DEF(CLANGWIN_IA32_PREFIX)clang +*_CLANGWIN_IA32_ASM_PATH = DEF(CLANGWIN_IA32_PREFIX)clang +*_CLANGWIN_IA32_PP_PATH = DEF(CLANGWIN_IA32_PREFIX)clang +*_CLANGWIN_IA32_VFRPP_PATH = DEF(CLANGWIN_IA32_PREFIX)clang +*_CLANGWIN_IA32_ASLCC_PATH = DEF(CLANGWIN_IA32_PREFIX)clang +*_CLANGWIN_IA32_ASLPP_PATH = DEF(CLANGWIN_IA32_PREFIX)clang +*_CLANGWIN_IA32_RC_PATH = rc.exe + +*_CLANGWIN_IA32_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m32 -fno-lto DEF(CLANGWIN_IA32_TARGET) +*_CLANGWIN_IA32_ASLDLINK_FLAGS = DEF(GCC5_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_i386 +*_CLANGWIN_IA32_ASM_FLAGS = DEF(GCC5_ASM_FLAGS) -m32 -march=i386 DEF(CLANGWIN_IA32_TARGET) +*_CLANGWIN_IA32_OBJCOPY_FLAGS = +*_CLANGWIN_IA32_NASM_FLAGS = -f win32 +*_CLANGWIN_IA32_PP_FLAGS = DEF(GCC_PP_FLAGS) DEF(CLANGWIN_IA32_TARGET) +*_CLANGWIN_IA32_ASLPP_FLAGS = DEF(GCC_ASLPP_FLAGS) DEF(CLANGWIN_IA32_TARGET) +*_CLANGWIN_IA32_VFRPP_FLAGS = DEF(GCC_VFRPP_FLAGS) DEF(CLANGWIN_IA32_TARGET) + +DEBUG_CLANGWIN_IA32_CC_FLAGS = DEF(CLANGWIN_ALL_CC_FLAGS) -m32 -Oz -march=i586 DEF(CLANGWIN_IA32_TARGET) -g +DEBUG_CLANGWIN_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG +DEBUG_CLANGWIN_IA32_DLINK2_FLAGS = + +RELEASE_CLANGWIN_IA32_CC_FLAGS = DEF(CLANGWIN_ALL_CC_FLAGS) -m32 -Oz -march=i586 DEF(CLANGWIN_IA32_TARGET) +RELEASE_CLANGWIN_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.rdata=.data +RELEASE_CLANGWIN_IA32_DLINK2_FLAGS = + +NOOPT_CLANGWIN_IA32_CC_FLAGS = DEF(CLANGWIN_ALL_CC_FLAGS) -m32 -O0 -march=i586 DEF(CLANGWIN_IA32_TARGET) -g +NOOPT_CLANGWIN_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG +NOOPT_CLANGWIN_IA32_DLINK2_FLAGS = + +########################## +# CLANGWIN X64 definitions +########################## +*_CLANGWIN_X64_CC_PATH = DEF(CLANGWIN_X64_PREFIX)clang +*_CLANGWIN_X64_SLINK_PATH = lib.exe +*_CLANGWIN_X64_DLINK_PATH = link.exe +*_CLANGWIN_X64_ASLDLINK_PATH = DEF(CLANGWIN_X64_PREFIX)clang +*_CLANGWIN_X64_ASM_PATH = DEF(CLANGWIN_X64_PREFIX)clang +*_CLANGWIN_X64_PP_PATH = DEF(CLANGWIN_X64_PREFIX)clang +*_CLANGWIN_X64_VFRPP_PATH = DEF(CLANGWIN_X64_PREFIX)clang +*_CLANGWIN_X64_ASLCC_PATH = DEF(CLANGWIN_X64_PREFIX)clang +*_CLANGWIN_X64_ASLPP_PATH = DEF(CLANGWIN_X64_PREFIX)clang +*_CLANGWIN_X64_RC_PATH = rc.exe + +*_CLANGWIN_X64_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m64 -fno-lto DEF(CLANGWIN_X64_TARGET) +*_CLANGWIN_X64_ASLDLINK_FLAGS = DEF(GCC5_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_x86_64 +*_CLANGWIN_X64_ASM_FLAGS = DEF(GCC5_ASM_FLAGS) -m64 DEF(CLANGWIN_X64_TARGET) +*_CLANGWIN_X64_OBJCOPY_FLAGS = +*_CLANGWIN_X64_NASM_FLAGS = -f win64 +*_CLANGWIN_X64_PP_FLAGS = DEF(GCC_PP_FLAGS) DEF(CLANGWIN_X64_TARGET) +*_CLANGWIN_X64_ASLPP_FLAGS = DEF(GCC_ASLPP_FLAGS) DEF(CLANGWIN_X64_TARGET) +*_CLANGWIN_X64_VFRPP_FLAGS = DEF(GCC_VFRPP_FLAGS) DEF(CLANGWIN_X64_TARGET) + +DEBUG_CLANGWIN_X64_CC_FLAGS = DEF(CLANGWIN_ALL_CC_FLAGS) -m64 "-DEFIAPI=__attribute__((ms_abi))" -mno-red-zone -mcmodel=small -Oz DEF(CLANGWIN_X64_TARGET) -g +DEBUG_CLANGWIN_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG +DEBUG_CLANGWIN_X64_DLINK2_FLAGS = + +RELEASE_CLANGWIN_X64_CC_FLAGS = DEF(CLANGWIN_ALL_CC_FLAGS) -m64 "-DEFIAPI=__attribute__((ms_abi))" -mno-red-zone -mcmodel=small -Oz DEF(CLANGWIN_X64_TARGET) +RELEASE_CLANGWIN_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.rdata=.data +RELEASE_CLANGWIN_X64_DLINK2_FLAGS = + +NOOPT_CLANGWIN_X64_CC_FLAGS = DEF(CLANGWIN_ALL_CC_FLAGS) -m64 "-DEFIAPI=__attribute__((ms_abi))" -mno-red-zone -mcmodel=small -O0 DEF(CLANGWIN_X64_TARGET) -g +NOOPT_CLANGWIN_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG +NOOPT_CLANGWIN_X64_DLINK2_FLAGS = + +#################################################################################### +# +# LIBFUZZER Win - This configuration is used to compile under Windows to produce +# PE/COFF binaries using LLVM/Clang with Link Time Optimization enabled +# +#################################################################################### +*_LIBFUZZERWIN_*_*_FAMILY = GCC +*_LIBFUZZERWIN_*_*_BUILDRULEFAMILY = CLANGWIN +*_LIBFUZZERWIN_*_MAKE_PATH = nmake +*_LIBFUZZERWIN_*_*_DLL = ENV(LIBFUZZERWIN_DLL) +*_LIBFUZZERWIN_*_ASL_PATH = DEF(DEFAULT_WIN_ASL_BIN) + +*_LIBFUZZERWIN_*_APP_FLAGS = +*_LIBFUZZERWIN_*_ASL_FLAGS = DEF(DEFAULT_WIN_ASL_FLAGS) +*_LIBFUZZERWIN_*_ASL_OUTFLAGS = DEF(DEFAULT_WIN_ASL_OUTFLAGS) + +DEFINE LIBFUZZERWIN_IA32_PREFIX = ENV(LIBFUZZERWIN_BIN) +DEFINE LIBFUZZERWIN_X64_PREFIX = ENV(LIBFUZZERWIN_BIN) + +DEFINE LIBFUZZERWIN_IA32_TARGET = -target i686-pc-windows-msvc +DEFINE LIBFUZZERWIN_X64_TARGET = -target x86_64-pc-windows-msvc + +DEFINE LIBFUZZERWIN_WARNING_OVERRIDES = -Wno-parentheses-equality -Wno-tautological-compare -Wno-tautological-constant-out-of-range-compare -Wno-empty-body -Wno-unused-const-variable -Wno-varargs -Wno-unknown-warning-option +DEFINE LIBFUZZERWIN_ALL_CC_FLAGS = DEF(GCC48_ALL_CC_FLAGS) DEF(LIBFUZZERWIN_WARNING_OVERRIDES) -fno-stack-protector -mms-bitfields -Wno-address -Wno-shift-negative-value -Wno-unknown-pragmas -Wno-incompatible-library-redeclaration -fno-asynchronous-unwind-tables -mno-sse -mno-mmx -msoft-float -mno-implicit-float -ftrap-function=undefined_behavior_has_been_optimized_away_by_LIBFUZZER -funsigned-char -fno-ms-extensions -Wno-null-dereference -Wno-microsoft -fms-compatibility + +########################### +# LIBFUZZERWIN IA32 definitions +########################### +*_LIBFUZZERWIN_IA32_CC_PATH = DEF(LIBFUZZERWIN_IA32_PREFIX)clang +*_LIBFUZZERWIN_IA32_SLINK_PATH = lib.exe +*_LIBFUZZERWIN_IA32_DLINK_PATH = link.exe +*_LIBFUZZERWIN_IA32_ASLDLINK_PATH = DEF(LIBFUZZERWIN_IA32_PREFIX)clang +*_LIBFUZZERWIN_IA32_ASM_PATH = DEF(LIBFUZZERWIN_IA32_PREFIX)clang +*_LIBFUZZERWIN_IA32_PP_PATH = DEF(LIBFUZZERWIN_IA32_PREFIX)clang +*_LIBFUZZERWIN_IA32_VFRPP_PATH = DEF(LIBFUZZERWIN_IA32_PREFIX)clang +*_LIBFUZZERWIN_IA32_ASLCC_PATH = DEF(LIBFUZZERWIN_IA32_PREFIX)clang +*_LIBFUZZERWIN_IA32_ASLPP_PATH = DEF(LIBFUZZERWIN_IA32_PREFIX)clang +*_LIBFUZZERWIN_IA32_RC_PATH = rc.exe + +*_LIBFUZZERWIN_IA32_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m32 -fno-lto DEF(LIBFUZZERWIN_IA32_TARGET) +*_LIBFUZZERWIN_IA32_ASLDLINK_FLAGS = DEF(GCC5_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_i386 +*_LIBFUZZERWIN_IA32_ASM_FLAGS = DEF(GCC5_ASM_FLAGS) -m32 -march=i386 DEF(LIBFUZZERWIN_IA32_TARGET) +*_LIBFUZZERWIN_IA32_OBJCOPY_FLAGS = +*_LIBFUZZERWIN_IA32_NASM_FLAGS = -f win32 +*_LIBFUZZERWIN_IA32_PP_FLAGS = DEF(GCC_PP_FLAGS) DEF(LIBFUZZERWIN_IA32_TARGET) +*_LIBFUZZERWIN_IA32_ASLPP_FLAGS = DEF(GCC_ASLPP_FLAGS) DEF(LIBFUZZERWIN_IA32_TARGET) +*_LIBFUZZERWIN_IA32_VFRPP_FLAGS = DEF(GCC_VFRPP_FLAGS) DEF(LIBFUZZERWIN_IA32_TARGET) + +DEBUG_LIBFUZZERWIN_IA32_CC_FLAGS = DEF(LIBFUZZERWIN_ALL_CC_FLAGS) -m32 -Oz -march=i586 DEF(LIBFUZZERWIN_IA32_TARGET) -g +DEBUG_LIBFUZZERWIN_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG +DEBUG_LIBFUZZERWIN_IA32_DLINK2_FLAGS = + +RELEASE_LIBFUZZERWIN_IA32_CC_FLAGS = DEF(LIBFUZZERWIN_ALL_CC_FLAGS) -m32 -Oz -march=i586 DEF(LIBFUZZERWIN_IA32_TARGET) +RELEASE_LIBFUZZERWIN_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.rdata=.data +RELEASE_LIBFUZZERWIN_IA32_DLINK2_FLAGS = + +NOOPT_LIBFUZZERWIN_IA32_CC_FLAGS = DEF(LIBFUZZERWIN_ALL_CC_FLAGS) -m32 -O0 -march=i586 DEF(LIBFUZZERWIN_IA32_TARGET) -g +NOOPT_LIBFUZZERWIN_IA32_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG +NOOPT_LIBFUZZERWIN_IA32_DLINK2_FLAGS = + +########################## +# LIBFUZZERWIN X64 definitions +########################## +*_LIBFUZZERWIN_X64_CC_PATH = DEF(LIBFUZZERWIN_X64_PREFIX)clang +*_LIBFUZZERWIN_X64_SLINK_PATH = lib.exe +*_LIBFUZZERWIN_X64_DLINK_PATH = link.exe +*_LIBFUZZERWIN_X64_ASLDLINK_PATH = DEF(LIBFUZZERWIN_X64_PREFIX)clang +*_LIBFUZZERWIN_X64_ASM_PATH = DEF(LIBFUZZERWIN_X64_PREFIX)clang +*_LIBFUZZERWIN_X64_PP_PATH = DEF(LIBFUZZERWIN_X64_PREFIX)clang +*_LIBFUZZERWIN_X64_VFRPP_PATH = DEF(LIBFUZZERWIN_X64_PREFIX)clang +*_LIBFUZZERWIN_X64_ASLCC_PATH = DEF(LIBFUZZERWIN_X64_PREFIX)clang +*_LIBFUZZERWIN_X64_ASLPP_PATH = DEF(LIBFUZZERWIN_X64_PREFIX)clang +*_LIBFUZZERWIN_X64_RC_PATH = rc.exe + +*_LIBFUZZERWIN_X64_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m64 -fno-lto DEF(LIBFUZZERWIN_X64_TARGET) +*_LIBFUZZERWIN_X64_ASLDLINK_FLAGS = DEF(GCC5_IA32_X64_ASLDLINK_FLAGS) -Wl,-m,elf_x86_64 +*_LIBFUZZERWIN_X64_ASM_FLAGS = DEF(GCC5_ASM_FLAGS) -m64 DEF(LIBFUZZERWIN_X64_TARGET) +*_LIBFUZZERWIN_X64_OBJCOPY_FLAGS = +*_LIBFUZZERWIN_X64_NASM_FLAGS = -f win64 +*_LIBFUZZERWIN_X64_PP_FLAGS = DEF(GCC_PP_FLAGS) DEF(LIBFUZZERWIN_X64_TARGET) +*_LIBFUZZERWIN_X64_ASLPP_FLAGS = DEF(GCC_ASLPP_FLAGS) DEF(LIBFUZZERWIN_X64_TARGET) +*_LIBFUZZERWIN_X64_VFRPP_FLAGS = DEF(GCC_VFRPP_FLAGS) DEF(LIBFUZZERWIN_X64_TARGET) + +DEBUG_LIBFUZZERWIN_X64_CC_FLAGS = DEF(LIBFUZZERWIN_ALL_CC_FLAGS) -m64 "-DEFIAPI=__attribute__((ms_abi))" -mno-red-zone -mcmodel=small -Oz DEF(LIBFUZZERWIN_X64_TARGET) -g +DEBUG_LIBFUZZERWIN_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG +DEBUG_LIBFUZZERWIN_X64_DLINK2_FLAGS = + +RELEASE_LIBFUZZERWIN_X64_CC_FLAGS = DEF(LIBFUZZERWIN_ALL_CC_FLAGS) -m64 "-DEFIAPI=__attribute__((ms_abi))" -mno-red-zone -mcmodel=small -Oz DEF(LIBFUZZERWIN_X64_TARGET) +RELEASE_LIBFUZZERWIN_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.rdata=.data +RELEASE_LIBFUZZERWIN_X64_DLINK2_FLAGS = + +NOOPT_LIBFUZZERWIN_X64_CC_FLAGS = DEF(LIBFUZZERWIN_ALL_CC_FLAGS) -m64 "-DEFIAPI=__attribute__((ms_abi))" -mno-red-zone -mcmodel=small -O0 DEF(LIBFUZZERWIN_X64_TARGET) -g +NOOPT_LIBFUZZERWIN_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG +NOOPT_LIBFUZZERWIN_X64_DLINK2_FLAGS = diff --git a/HBFA/UefiHostFuzzTestPkg/Include/Library/ToolChainHarnessLib.h b/HBFA/UefiHostFuzzTestPkg/Include/Library/ToolChainHarnessLib.h new file mode 100644 index 0000000..023841e --- /dev/null +++ b/HBFA/UefiHostFuzzTestPkg/Include/Library/ToolChainHarnessLib.h @@ -0,0 +1,24 @@ +/** @file + +Copyright (c) 2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _TOOLCHAIN_HARNESS_LIB_ +#define _TOOLCHAIN_HARNESS_LIB_ + +VOID +EFIAPI +RunTestHarness ( + IN VOID *TestBuffer, + IN UINTN TestBufferSize + ); + +UINTN +EFIAPI +GetMaxBufferSize ( + VOID + ); + +#endif \ No newline at end of file diff --git a/HBFA/UefiHostFuzzTestPkg/Library/ToolChainHarnessLib/ToolChainHarnessLib.c b/HBFA/UefiHostFuzzTestPkg/Library/ToolChainHarnessLib/ToolChainHarnessLib.c new file mode 100644 index 0000000..29b84f2 --- /dev/null +++ b/HBFA/UefiHostFuzzTestPkg/Library/ToolChainHarnessLib/ToolChainHarnessLib.c @@ -0,0 +1,185 @@ +/** @file + +Copyright (c) 2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#ifdef TEST_WITH_INSTRUMENT +#include +#endif + +#ifdef TEST_WITH_LIBFUZZER +#include +#include +#endif + +#ifdef TEST_WITH_KLEE +#include +#endif + +// TODO: xxx Improve coding style: naming, data type, etc + +#ifdef TEST_WITH_INSTRUMENT +VOID +ReadInstrumentProfile ( + IN CHAR8 *FileName + ) +{ + VOID *Buffer; + + FILE *f = fopen(FileName, "rb"); + if (f==NULL) { + fputs ("File error",stderr); + exit (1); + } + fseek(f, 0, SEEK_END); + + UINTN fsize = ftell(f); + rewind(f); + + Buffer = malloc (fsize); + size_t bytes_read = fread((void *)Buffer, 1, fsize, f); + if ((UINTN)bytes_read!=fsize) { + fputs ("File error",stderr); + exit (1); + } + fclose(f); + + InstrumentHookLibInit (Buffer, fsize); +} +#endif + +VOID +InitTestBuffer ( + int argc, + char **argv, + IN UINTN MaxBufferSize, + IN VOID **TestBuffer, + OUT UINTN *BufferSize + ) +{ + // 1. Allocate buffer + VOID *Buffer = AllocatePool (MaxBufferSize); + + // 2. Assign to TestBuffer and BufferSize + *TestBuffer = Buffer; + if (BufferSize != NULL) { + *BufferSize = MaxBufferSize; + } else { + printf ("error - Null pointer for Buffersize"); + exit(1); + } + + // 3. Initialize TestBuffer +#ifdef TEST_WITH_KLEE + // 3.1 For test with KLEE: write symbolic values to TestBuffer + klee_make_symbolic((UINT8 *)Buffer, MaxBufferSize, "Buffer"); + return; +#endif + + // 3.2 For other tests: read values from file to TestBuffer + // (may also update the value of BufferSize) + if (argc == 1) { + printf ("error - missing input file\n"); + exit(1); + } + CHAR8 *FileName = argv[1]; + + FILE *f = fopen(FileName, "rb"); + if (f==NULL) { + fputs ("File error",stderr); + exit (1); + } + fseek(f, 0, SEEK_END); + + UINTN fsize = ftell(f); + rewind(f); + + fsize = fsize > MaxBufferSize ? MaxBufferSize : fsize; + size_t bytes_read = fread((void *)Buffer, 1, fsize, f); + if ((UINTN)bytes_read!=fsize) { + fputs ("File error",stderr); + exit (1); + } + fclose(f); + if (BufferSize != NULL) { + *BufferSize = fsize; + } else { + printf ("error - Null pointer for Buffersize"); + exit(1); + } + + // 3.3 For ErrorInjection: read instrument profile for initialization +#ifdef TEST_WITH_INSTRUMENT + if (argc >= 3) { + ReadInstrumentProfile (argv[2]); + } +#endif +} + +#ifdef TEST_WITH_LIBFUZZER +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + VOID *TestBuffer; + UINTN MaxBufferSize; + + // 1. Initialize TestBuffer + MaxBufferSize = GetMaxBufferSize(); + TestBuffer = AllocateZeroPool (MaxBufferSize); + if (Size > MaxBufferSize) { + Size = MaxBufferSize; + } + CopyMem (TestBuffer, Data, Size); + // 2. Run test + RunTestHarness(TestBuffer, Size); + // 3. Clean up + FreePool (TestBuffer); + return 0; +} +#else +#ifdef TEST_WITH_LIBFUZZERWIN +int LLVMFuzzerTestOneInput(const wint_t *Data, size_t Size) { + VOID *TestBuffer; + UINTN MaxBufferSize; + + // 1. Initialize TestBuffer + MaxBufferSize = GetMaxBufferSize(); + TestBuffer = AllocateZeroPool (MaxBufferSize); + if (Size > MaxBufferSize) { + Size = MaxBufferSize; + } + CopyMem (TestBuffer, Data, Size); + // 2. Run test + RunTestHarness(TestBuffer, Size); + // 3. Clean up + FreePool (TestBuffer); + return 0; +} +#else +int main(int argc, char **argv) +{ + VOID *TestBuffer; + UINTN TestBufferSize; + + // 1. Initialize TestBuffer + InitTestBuffer (argc, argv, GetMaxBufferSize(), &TestBuffer, &TestBufferSize); + // 2. Run test + RunTestHarness(TestBuffer, TestBufferSize); + // 3. Clean up + FreePool (TestBuffer); + return 0; +} +#endif +#endif diff --git a/HBFA/UefiHostFuzzTestPkg/Library/ToolChainHarnessLib/ToolChainHarnessLib.inf b/HBFA/UefiHostFuzzTestPkg/Library/ToolChainHarnessLib/ToolChainHarnessLib.inf new file mode 100644 index 0000000..e3affc9 --- /dev/null +++ b/HBFA/UefiHostFuzzTestPkg/Library/ToolChainHarnessLib/ToolChainHarnessLib.inf @@ -0,0 +1,32 @@ +## @file +# Component description file for ToolChainHarnessLib module. +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ToolChainHarnessLib + FILE_GUID = 053c6bc3-5ad4-491a-94c9-c4f5e3c91e39 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = ToolChainHarnessLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + ToolChainHarnessLib.c + +[Packages] + MdePkg/MdePkg.dec + UefiHostFuzzTestPkg/UefiHostFuzzTestPkg.dec + UefiInstrumentTestPkg/UefiInstrumentTestPkg.dec + +[LibraryClasses] + BaseLib diff --git a/HBFA/UefiHostFuzzTestPkg/ReadME-AFLTurbo.txt b/HBFA/UefiHostFuzzTestPkg/ReadME-AFLTurbo.txt new file mode 100644 index 0000000..8843626 --- /dev/null +++ b/HBFA/UefiHostFuzzTestPkg/ReadME-AFLTurbo.txt @@ -0,0 +1,68 @@ +How to run AFLTurbo with UefiHostTestPkg in OS? +============== +AFLTurbo: +Prepare AFLTurbo in Linux +1) Install crypto dependency + sudo apt-get install libssl-dev +2) Goto https://github.com/sleicasper/aflturbo +3) Clone the repository and build the aflturbo code + git clone https://github.com/sleicasper/aflturbo.git + cd aflturbo/ + make + cp afl-fuzz afl-turbo-fuzz + +> Build AFLTurbo with `make` command & ensure AFLTurbo binary is in PATH environment variable. + +4) Add below content at the end of ~/.bashrc: + export AFL_PATH= + export PATH=$PATH:$AFL_PATH + For example: + export AFL_PATH=/home//Env/aflturbo + export PATH=$PATH:$AFL_PATH + +5) Run these commands as root (these command need to be ran every time you reboot your OS): + sudo bash -c 'echo core >/proc/sys/kernel/core_pattern' + cd /sys/devices/system/cpu/ + sudo bash -c 'echo performance | tee cpu*/cpufreq/scaling_governor' + +Build EDKII test case in Linux +1) python edk2-staging/HBFA/UefiHostTestTools/HBFAEnvSetup.py +2) cp edk2-staging/HBFA/UefiHostFuzzTestPkg/Conf/build_rule.txt edk2/Conf/build_rule.txt +3) cp edk2-staging/HBFA/UefiHostFuzzTestPkg/Conf/tools_def.txt edk2/Conf/tools_def.txt +4) build -p UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dsc -a IA32 -t AFL + + +Run AFLTurbo in Linux +1) mkdir testcase_dir +2) mkdir /dev/shm/findings_dir + Note:'/dev/shm' is tmpfs, so 'findings_dir' will disappear after reboot system, please backup test result before reboot system. +3) cp edk2-staging/HBFA/UefiHostFuzzTestCasePkg/Seed//xxx.bin testcase_dir + NOTE: mapping list please refer to edk2-staging/HBFA/UefiHostFuzzTestCasePkg/Seed/readme.txt +4) afl-turbo-fuzz -i testcase_dir -o /dev/shm/findings_dir Build/UefiHostFuzzTestCasePkg/DEBUG_AFL/IA32/TestPartition @@ +5) You will see something like below. Have fun! + + + AFL-BSO 2.52b (TestPartition) + +lq process timing qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqwq overall results qqqqqk +x run time : 0 days, 0 hrs, 0 min, 5 sec x cycles done : 40 x +x last new path : none yet (odd, check syntax!) x total paths : 1 x +x last uniq crash : none seen yet x uniq crashes : 0 x +x last uniq hang : none seen yet x uniq hangs : 0 x +tq cycle progress qqqqqqqqqqqqqqqqqqqqwq map coverage qvqqqqqqqqqqqqqqqqqqqqqqqu +x now processing : 0 (0.00%) x map density : 0.00% / 0.00% x +x paths timed out : 0 (0.00%) x count coverage : 1.00 bits/tuple x +tq stage progress qqqqqqqqqqqqqqqqqqqqnq findings in depth qqqqqqqqqqqqqqqqqqqqu +x now trying : havoc x favored paths : 1 (100.00%) x +x stage execs : 164/256 (64.06%) x new edges on : 1 (100.00%) x +x total execs : 11.8k x total crashes : 0 (0 unique) x +x exec speed : 2092/sec x total tmouts : 0 (0 unique) x +tq fuzzing strategy yields qqqqqqqqqqqvqqqqqqqqqqqqqqqwq path geometry qqqqqqqqu +x bit flips : 0/32, 0/31, 0/29 x levels : 1 x +x byte flips : 0/4, 0/3, 0/1 x pending : 0 x +x arithmetics : 0/224, 0/204, 0/68 x pend fav : 0 x +x known ints : 0/8, 0/18, 0/10 x own finds : 0 x +x dictionary : 0/0, 0/0, 0/0 x imported : n/a x +x havoc : 0/11.0k, 0/0 x stability : 100.00% x +x trim : 100.00%/29, 0.00% tqqqqqqqqqqqqqqqqqqqqqqqqj +^Cqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj [cpu000: 70%] diff --git a/HBFA/UefiHostFuzzTestPkg/ReadMe-AFL.txt b/HBFA/UefiHostFuzzTestPkg/ReadMe-AFL.txt new file mode 100644 index 0000000..15ab054 --- /dev/null +++ b/HBFA/UefiHostFuzzTestPkg/ReadMe-AFL.txt @@ -0,0 +1,115 @@ +How to run AFL with UefiHostTestPkg in OS? +============== +AFL: +Prepare AFL in Linux +1) Goto http://lcamtuf.coredump.cx/afl/, download http://lcamtuf.coredump.cx/afl/releases/afl-latest.tgz +2) Extract afl-latest.tgz: + mv afl-latest.tgz /home//Env + cd /home//Env + tar xzvf afl-latest.tgz +3) Follow docs\QuickStartGuide.txt in AFL package to quickly make AFL: + cd afl-2.5.2b + make +4) Add below content at the end of ~/.bashrc: + export AFL_PATH= + export PATH=$PATH:$AFL_PATH + For example: + export AFL_PATH=/home//Env/afl-2.52b + export PATH=$PATH:$AFL_PATH +5) Run these commands as root (these command need to be ran every time you reboot your OS): + sudo bash -c 'echo core >/proc/sys/kernel/core_pattern' + cd /sys/devices/system/cpu/ + sudo bash -c 'echo performance | tee cpu*/cpufreq/scaling_governor' + +Prepare AFL in Windows +NOTE: as known issue https://github.com/googleprojectzero/winafl/issues/145 that cause compatibility issues in recent Windows versions, the author has disabled Drsyms in recent WinAFL builds, if you want you use the newest version, please according to Method.2 to rebuild winafl yourself. +Method.1: +1) goto https://github.com/googleprojectzero/winafl, clone the project and checkout version d501350f02147860604b5d755960fe3fc201653a + git clone https://github.com/googleprojectzero/winafl.git + cd winafl + git checkout -b Branch_d501350f d501350f02147860604b5d755960fe3fc201653a +2) download DynamoRIO release 6.2.0-2 from https://github.com/DynamoRIO/dynamorio/releases/tag/release_6_2_0 +3) setup AFL_PATH=<...>\winafl, DRIO_PATH=<...>\DynamoRIO-Windows-6.2.0-2 +Method.2: +1) get newest winafl + git clone https://github.com/googleprojectzero/winafl.git +2) download newest DynamoRIO release from https://github.com/DynamoRIO/dynamorio/wiki/Downloads +3) build winafl + cd winafl + mkdir build32 + cd build32 + cmake -G"Visual Studio 14 2015" .. -DDynamoRIO_DIR=%DRIO_PATH%\cmake -DUSE_DRSYMS=1 + cmake --build . --config Release + cd .. + mkdir build64 + cmake -G"Visual Studio 14 2015 Win64" .. -DDynamoRIO_DIR=%DRIO_PATH%\cmake -DUSE_DRSYMS=1 + cmake --build . --config Release + NOTE: If you get errors where the linker couldn't find certain .lib files. please refer to https://github.com/googleprojectzero/winafl/issues/145 and delete the nonexistent files from "Additional Dependencies". +4) copy all binary under build32/bin/Release to bin32, copy all binary under build64/bin/Release to bin64 + robocopy /E /is /it build32/bin/Release bin32 + robocopy /E /is /it build64/bin/Release bin64 +5) setup AFL_PATH=<...>\winafl, DRIO_PATH=<...>\DynamoRIO-Windows-x.x.x-x + + + +Build EDKII test case in Linux +1) python edk2-staging/HBFA/UefiHostTestTools/HBFAEnvSetup.py +2) cp edk2-staging/HBFA/UefiHostFuzzTestPkg/Conf/build_rule.txt edk2/Conf/build_rule.txt +3) cp edk2-staging/HBFA/UefiHostFuzzTestPkg/Conf/tools_def.txt edk2/Conf/tools_def.txt +4) build -p UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dsc -a IA32 -t AFL + +Build EDKII test case in Windows +1) build -p UefiHostFuzzTestCasePkg\UefiHostFuzzTestCasePkg.dsc -a IA32 -t VS2015x86 + + + +Run AFL in Linux +1) mkdir testcase_dir +2) mkdir /dev/shm/findings_dir + Note:'/dev/shm' is tmpfs, so 'findings_dir' will disappear after reboot system, please backup test result before reboot system. +3) cp edk2-staging/HBFA/UefiHostFuzzTestCasePkg/Seed//xxx.bin testcase_dir + NOTE: mapping list please refer to edk2-staging/HBFA/UefiHostFuzzTestCasePkg/Seed/readme.txt +4) afl-fuzz -i testcase_dir -o /dev/shm/findings_dir Build/UefiHostFuzzTestCasePkg/DEBUG_AFL/IA32/TestPartition @@ +5) You will see something like below. Have fun! + +Run AFL in Windows +1) mkdir %AFL_PATH%\bin32\in +2) mkdir %AFL_PATH%\bin32\out +3) cp edk2-staging/HBFA/UefiHostFuzzTestCasePkg\Seed\\xxx.bin %AFL_PATH%\bin32\in + NOTE: mapping list please refer to edk2-staging/HBFA\UefiHostFuzzTestCasePkg\Seed\readme.txt +4) Copy xxx.exe and xxx.pdb to the same dir as %AFL_PATH%\bin32 or %AFL_PATH%\bin64, for example: TestPartition.exe and TestPartition.pdb. (NOTE: xxx.pdb must be copied) +5) cd %AFL_PATH%\bin32 + afl-fuzz.exe -i in -o out -D %DRIO_PATH%\bin32 -t 20000 -- -coverage_module xxx.exe -fuzz_iterations 1000 -target_module xxx.exe -target_method main -nargs 2 -- xxx.exe @@ + or + cd %AFL_PATH%\bin64 + afl-fuzz.exe -i in -o out -D %DRIO_PATH%\bin64 -t 20000 -- -coverage_module xxx.exe -fuzz_iterations 1000 -target_module xxx.exe -target_method main -nargs 2 -- xxx.exe @@ +6) You will see similar output, although it is slower than Linux. + + + american fuzzy lop 2.52b (TestPartition) + +lq process timing qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqwq overall results qqqqqk +x run time : 0 days, 0 hrs, 0 min, 5 sec x cycles done : 40 x +x last new path : none yet (odd, check syntax!) x total paths : 1 x +x last uniq crash : none seen yet x uniq crashes : 0 x +x last uniq hang : none seen yet x uniq hangs : 0 x +tq cycle progress qqqqqqqqqqqqqqqqqqqqwq map coverage qvqqqqqqqqqqqqqqqqqqqqqqqu +x now processing : 0 (0.00%) x map density : 0.00% / 0.00% x +x paths timed out : 0 (0.00%) x count coverage : 1.00 bits/tuple x +tq stage progress qqqqqqqqqqqqqqqqqqqqnq findings in depth qqqqqqqqqqqqqqqqqqqqu +x now trying : havoc x favored paths : 1 (100.00%) x +x stage execs : 164/256 (64.06%) x new edges on : 1 (100.00%) x +x total execs : 11.8k x total crashes : 0 (0 unique) x +x exec speed : 2092/sec x total tmouts : 0 (0 unique) x +tq fuzzing strategy yields qqqqqqqqqqqvqqqqqqqqqqqqqqqwq path geometry qqqqqqqqu +x bit flips : 0/32, 0/31, 0/29 x levels : 1 x +x byte flips : 0/4, 0/3, 0/1 x pending : 0 x +x arithmetics : 0/224, 0/204, 0/68 x pend fav : 0 x +x known ints : 0/8, 0/18, 0/10 x own finds : 0 x +x dictionary : 0/0, 0/0, 0/0 x imported : n/a x +x havoc : 0/11.0k, 0/0 x stability : 100.00% x +x trim : 100.00%/29, 0.00% tqqqqqqqqqqqqqqqqqqqqqqqqj +^Cqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj [cpu000: 70%] + + + diff --git a/HBFA/UefiHostFuzzTestPkg/ReadMe-ErrorInjection.txt b/HBFA/UefiHostFuzzTestPkg/ReadMe-ErrorInjection.txt new file mode 100644 index 0000000..ef9ea7a --- /dev/null +++ b/HBFA/UefiHostFuzzTestPkg/ReadMe-ErrorInjection.txt @@ -0,0 +1,36 @@ +How to do error injection? +============== +Build +1) Make sure UefiInstrumentTestPkg is in PACKAGES_PATH. +2) build -p UefiHostFuzzTestCasePkg\UefiHostFuzzTestCasePkg.dsc -a IA32 -t XXX -D TEST_WITH_INSTRUMENT + +Write Error Injection Profile +1) Create .Ini file like below: (test.ini) +####################### +# CallErrorCount=N means which call returns error. N means the Nth call returns error. +# N start from 1. CallErrorCount = 0 means disable. +# ReturnValue=X means when error happens, which value is returned. +####################### + +[AllocateZeroPool] + CallErrorCount = 1 + ReturnValue = 0 + +[ReadBlocks] + CallErrorCount = 1 + ReturnValue = EFI_DEVICE_ERROR + +[ReadDisk] + CallErrorCount = 1 + ReturnValue = EFI_DEVICE_ERROR +####################### + +Run +1) +for example: Build\UefiHostFuzzTestCasePkg\DEBUG_VS2015x86\IA32\TestPartition.exe UefiHostFuzzTestCasePkg\Seed\UDF\Raw\Udf_linux.bin test.ini + +Recommendation: +1) We had better provide a set of seeds, which already have high coverage. Only error handling path is not covered. +2) We had better have a script to increase CallErrorCount from 1 to N. And run the TestApp again and again. + As such, all the error can be returned. + diff --git a/HBFA/UefiHostFuzzTestPkg/ReadMe-KLEE.txt b/HBFA/UefiHostFuzzTestPkg/ReadMe-KLEE.txt new file mode 100644 index 0000000..94d13f5 --- /dev/null +++ b/HBFA/UefiHostFuzzTestPkg/ReadMe-KLEE.txt @@ -0,0 +1,122 @@ +How to run KLEE with UefiHostTestPkg in Linux? +============== +KLEE: +Prepare Env +1) "cd /home/" + "mkdir Env" +2) "sudo apt-get install build-essential curl libcap-dev cmake libncurses5-dev unzip libtcmalloc-minimal4 libgoogle-perftools-dev zlib1g-dev sqlite3 libsqlite3-dev uuid-dev texinfo bison flex libgmp3-dev libmpfr-dev libc6-dev-i386 doxygen python-pip" + +Prepare KLEE +1) install LLVM 3.8 + "sudo apt-get install clang-3.8 llvm-3.8 llvm-3.8-dev" +2) install constraint solver STP + a) "sudo apt-get install libboost-all-dev perl minisat" + b) "cd /home//Env" + c) "git clone https://github.com/stp/stp" + d) "cd stp" + e) "mkdir build" + f) "cd build" + g) "cmake .." + h) "make" + i) "sudo make install" +3) build uclibc and the POSIX environment model: + a) "cd /home//Env" + b) "git clone https://github.com/klee/klee-uclibc.git" + c) "cd klee-uclibc" + d) "./configure --make-llvm-lib" + e) "make -j2" +4) get Google test sources + a) "cd /home//Env" + b) "curl -OL https://github.com/google/googletest/archive/release-1.7.0.zip" + c) "unzip release-1.7.0.zip" +5) install lit + a) "cd /home//Env" + b) get lit source from https://pypi.org/project/lit/#files + c) "sudo pip install lit-0.6.0.tar.gz" +6) get and configure KLEE + a) "cd /home//Env" + b) "git clone https://github.com/klee/klee.git" + c) "mkdir klee_build_dir" + NOTE: this directory must out of KLEE source code + d) "cd klee_build_dir" + e) "cmake \ + -DENABLE_SOLVER_STP=ON \ + -DENABLE_POSIX_RUNTIME=ON \ + -DENABLE_KLEE_UCLIBC=ON \ + -DKLEE_UCLIBC_PATH= \ + -DGTEST_SRC_DIR= \ + -DENABLE_SYSTEM_TESTS=ON \ + -DENABLE_UNIT_TESTS=ON \ + -DLLVM_CONFIG_BINARY= \ + -DLLVMCC= \ + -DLLVMCXX= + " + NOTE: where is the absolute path the klee-uclibc source tree, is the absolute path to the Google Test source tree, is the absolute path the klee source tree. + e.g. + "cmake \ + -DENABLE_SOLVER_STP=ON \ + -DENABLE_POSIX_RUNTIME=ON \ + -DENABLE_KLEE_UCLIBC=ON \ + -DKLEE_UCLIBC_PATH=/home//Env/klee-uclibc \ + -DGTEST_SRC_DIR=/home//Env/googletest-release-1.7.0 \ + -DENABLE_SYSTEM_TESTS=ON \ + -DENABLE_UNIT_TESTS=ON \ + -DLLVM_CONFIG_BINARY=/usr/bin/llvm-config \ + -DLLVMCC=/usr/bin/clang-3.8 \ + -DLLVMCXX=/usr/bin/clang++-3.8 \ + /home//Env/klee" + f) "make" +7) you can varify whether your environment is setup correctly by running the first tutorial http://klee.github.io/tutorials/testing-function/ +8) Add below content at the end of ~/.bashrc: + export KLEE_BIN_PATH=/bin + export KLEE_SRC_PATH= + export PATH=$PATH:$KLEE_BIN_PATH + For example: + export KLEE_BIN_PATH=/home//Env/klee_build_dir/bin + export KLEE_SRC_PATH=/home//Env/klee + export PATH=$PATH:$KLEE_BIN_PATH + NOTE: is the directory you clone klee from github in step 6 b), is the directory you build klee in step 6 c) + +Prepare wllvm +1) get whole-program-llvm + "cd /home/xxx/Env" + "git clone https://github.com/travitch/whole-program-llvm.git" +2) "cd whole-program-llvm" +3) "sudo pip install -e ." + +Build EDKII test case +1) "python edk2-staging/HBFA/UefiHostTestTools/HBFAEnvSetup.py" +2) "cp edk2-staging/HBFA/UefiHostFuzzTestPkg/Conf/build_rule.txt edk2/Conf/build_rule.txt" +3) "cp edk2-staging/HBFA/UefiHostFuzzTestPkg/Conf/tools_def.txt edk2/Conf/tools_def.txt" +4) "export SCRIPT_PATH=/edk2-staging/HBFA/UefiHostFuzzTestPkg/Conf/LLVMLink.py" +5) "export LLVM_COMPILER=clang" + NOTE: if you can't find clang in /usr/bin, you can use clang-3.8 (clang-3.x) +6) "build -p UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dsc -a IA32 -t KLEE -DTEST_WITH_KLEE --disable-include-path-check" + +Run KLEE +1) klee --only-output-states-covering-new Build/UefiHostFuzzTestCasePkg/DEBUG_KLEE/IA32/TestPartition" +2) You will see something like below. + +KLEE: output directory is "Build/UefiHostFuzzTestCasePkg/DEBUG_KLEE/IA32/klee-out-0" +KLEE: Using STP solver backend +KLEE: WARNING ONCE: Alignment of memory from call "malloc" is not modelled. Using alignment of 8. +KLEE: WARNING: killing 400 states (over memory cap) +KLEE: WARNING ONCE: skipping fork (memory cap exceeded) +KLEE: WARNING: killing 321 states (over memory cap) +KLEE: WARNING: killing 1291 states (over memory cap) +KLEE: WARNING: killing 860 states (over memory cap) +KLEE: WARNING: killing 996 states (over memory cap) +KLEE: WARNING: killing 946 states (over memory cap) +KLEE: WARNING: killing 839 states (over memory cap) +KLEE: WARNING: killing 500 states (over memory cap) +KLEE: WARNING: killing 802 states (over memory cap) +KLEE: WARNING: killing 629 states (over memory cap) +KLEE: WARNING: killing 789 states (over memory cap) +KLEE: WARNING: killing 634 states (over memory cap) +KLEE: WARNING: killing 753 states (over memory cap) +KLEE: WARNING: killing 552 states (over memory cap) + +Transfer generated .ktest to seed file +1) "python edk2-staging/HBFA/UefiHostTestTools/Script/TransferKtestToSeed.py " +2) generate .seed file can be used as seeds for AFL-Fuzzer. + diff --git a/HBFA/UefiHostFuzzTestPkg/ReadMe-LibFuzzer.txt b/HBFA/UefiHostFuzzTestPkg/ReadMe-LibFuzzer.txt new file mode 100644 index 0000000..8f8df7e --- /dev/null +++ b/HBFA/UefiHostFuzzTestPkg/ReadMe-LibFuzzer.txt @@ -0,0 +1,73 @@ +How to run LibFuzzer in OS? +============== +Install LLVM in Linux +1) Download LLVM 8.0.0 Linux pre build binary from http://releases.llvm.org/download.html +2) Extract clang+llvm-x.x.x-.tar.xz + mv clang+llvm-x.x.x-.tar.xz /home//Env + cd /home//Env + xz -d clang+llvm-x.x.x-.tar.xz +3) Extract clang+llvm-x.x.x-.tar + tar xvf clang+llvm-x.x.x-.tar +4) Add below content at the end of ~/.bashrc: + export CLANG_PATH=/bin + export ASAN_SYMBOLIZER_PATH=$CLANG_PATH/llvm-symbolizer + For example: + export CLANG_PATH=/home/tiano/Env/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-16.04/bin + export ASAN_SYMBOLIZER_PATH=$CLANG_PATH/llvm-symbolizer + +=============== +Install LLVM in Windows (currently CLAGN8) +***NOTE: current CLAGN8 support Sanitizer (IA32/X64) and LIBFUZZER (X64) in Windows. +1) Download LLVM 8.0.0 windows pre build binary from http://releases.llvm.org/download.html and setup LLVM environment. +Note: Please install 64bit exe for X64 build and 32bit exe for IA32 build. +2) After LLVM setup done, please add LLVM installed location to system environment variable: + set LLVM_PATH=<64_LLVM_PATH> + set LLVMx86_PATH =<32_LLVM_PATH> + For example: + set LLVM_PATH=C:\Program Files\LLVM + set LLVMx86_PATH =C:\Program Files (x86)\LLVM +3) Add %LLVM_PATH%\bin, %LLVM_PATH%\lib\clang\8.0.0\lib\windows and %LLVMx86_PATH%\lib\clang\8.0.0\lib\windows to system environment variable PATH. + + +=========================== +Run Clang in Linux +1) python edk2-staging/HBFA/UefiHostTestTools/HBFAEnvSetup.py +2) cp edk2-staging/HBFA/UefiHostFuzzTestPkg/Conf/build_rule.txt edk2/Conf/build_rule.txt +3) cp edk2-staging/HBFA/UefiHostFuzzTestPkg/Conf/tools_def.txt edk2/Conf/tools_def.txt +4) export PATH=$CLANG_PATH:$PATH +5) build with "CLANG8" as toolchain. + build -p UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dsc -a X64 -t CLANG8 + +Run Clang in Windows +1) python edk2-staging\HBFA\UefiHostTestTools\HBFAEnvSetup.py +2) copy edk2-staging\HBFA\UefiHostFuzzTestPkg\Conf\build_rule.txt edk2\Conf\build_rule.txt +3) copy edk2-staging\HBFA\UefiHostFuzzTestPkg\Conf\tools_def.txt edk2\Conf\tools_def.txt +4) build with "CLANGWIN" as toolchain. + build -p UefiHostFuzzTestCasePkg\UefiHostFuzzTestCasePkg.dsc -a X64 -t CLANGWIN + +=========================== +Run LibFuzzer in Linux: +1) python edk2-staging/HBFA/UefiHostTestTools/HBFAEnvSetup.py +2) cp edk2-staging/HBFA/UefiHostFuzzTestPkg/Conf/build_rule.txt edk2/Conf/build_rule.txt +3) cp edk2-staging/HBFA/UefiHostFuzzTestPkg/Conf/tools_def.txt edk2/Conf/tools_def.txt +4) export PATH=$CLANG_PATH:$PATH +5) build -p UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dsc -a X64 -t LIBFUZZER +6) mkdir NEW_CORPUS_DIR +7) cp HBFA/UefiHostFuzzTestCasePkg/Seed/XXX/Raw/Xxx.bin NEW_CORPUS_DIR +8) ./Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestXxx NEW_CORPUS_DIR -rss_limit_mb=0 -artifact_prefix=/ + +Run Clang in Windows +1) python edk2-staging\HBFA\UefiHostTestTools\HBFAEnvSetup.py +2) copy edk2-staging\HBFA\UefiHostFuzzTestPkg\Conf\build_rule.txt edk2\Conf\build_rule.txt +3) copy edk2-staging\HBFA\UefiHostFuzzTestPkg\Conf\tools_def.txt edk2\Conf\tools_def.txt +4) build -p UefiHostFuzzTestCasePkg\UefiHostFuzzTestCasePkg.dsc -a X64 -t LIBFUZZERWIN +5) mkdir NEW_CORPUS_DIR +6) copy HBFA\UefiHostFuzzTestCasePkg\Seed\XXX\Raw\Xxx.bin NEW_CORPUS_DIR +7) .\Build\UefiHostFuzzTestCasePkg\DEBUG_LIBFUZZERWIN\X64\TestXxx.exe NEW_CORPUS_DIR -rss_limit_mb=0 -artifact_prefix=\ + +=========================== +Sanitizer Coverage: +1) goto http://clang.llvm.org/docs/SanitizerCoverage.html, read the content. +2) ASAN_OPTIONS=coverage=1 ./Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestXxx +3) sancov -symbolize TestXxx.123.sancov my_program > TestXxx.123.symcov +4) python3 tools/sancov/coverage-report-server.py --symcov TestXxx.123.symcov --srcpath diff --git a/HBFA/UefiHostFuzzTestPkg/UefiHostFuzzTestBuildOption.dsc b/HBFA/UefiHostFuzzTestPkg/UefiHostFuzzTestBuildOption.dsc new file mode 100644 index 0000000..77f41f1 --- /dev/null +++ b/HBFA/UefiHostFuzzTestPkg/UefiHostFuzzTestBuildOption.dsc @@ -0,0 +1,170 @@ +## @file UefiHostFuzzTestBuildOption.dsc +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[BuildOptions] + MSFT:*_*_*_CC_FLAGS = /D _CRT_SECURE_NO_WARNINGS + + GCC:*_*_IA32_CC_FLAGS == -m32 -g -fshort-wchar -fno-strict-aliasing -Wall -malign-double -idirafter/usr/include -c -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_*_IA32_PP_FLAGS == -m32 -E -x assembler-with-cpp -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_*_IA32_ASM_FLAGS == -m32 -c -x assembler -imacros $(DEST_DIR_DEBUG)/AutoGen.h + + GCC:*_*_X64_CC_FLAGS == -m64 -g -fshort-wchar -fno-strict-aliasing -Wall -malign-double -idirafter/usr/include -c -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_GCC49_X64_CC_FLAGS = "-DEFIAPI=__attribute__((ms_abi))" + GCC:*_GCC5_X64_CC_FLAGS = "-DEFIAPI=__attribute__((ms_abi))" -DUSING_LTO -Os + GCC:*_*_X64_PP_FLAGS == -m64 -E -x assembler-with-cpp -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_*_X64_ASM_FLAGS == -m64 -c -x assembler -imacros $(DEST_DIR_DEBUG)/AutoGen.h + + GCC:*_GCC5_*_CC_FLAGS = --coverage + GCC:*_GCC5_*_DLINK_FLAGS = --coverage + + GCC:*_GCC5_X64_CC_FLAGS = "-DNO_MSABI_VA_FUNCS=TRUE" + + GCC:*_LIBFUZZER_IA32_CC_FLAGS == -m32 -g -fshort-wchar -fno-strict-aliasing -Wall -idirafter/usr/include -c -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_LIBFUZZER_X64_CC_FLAGS == -m64 -g -fshort-wchar -fno-strict-aliasing -Wall -idirafter/usr/include -c -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_LIBFUZZER_X64_CC_FLAGS = "-DNO_MSABI_VA_FUNCS=TRUE" + + GCC:*_LIBFUZZER_*_CC_FLAGS = "-DTEST_WITH_LIBFUZZER=TRUE" -O1 -fsanitize=fuzzer,address + GCC:*_LIBFUZZER_*_DLINK2_FLAGS = -fsanitize=fuzzer,address + + GCC:*_CLANG8_IA32_CC_FLAGS == -m32 -g -fshort-wchar -fno-strict-aliasing -Wall -idirafter/usr/include -c -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_CLANG8_X64_CC_FLAGS == -m64 -g -fshort-wchar -fno-strict-aliasing -Wall -idirafter/usr/include -c -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_CLANG8_X64_CC_FLAGS = "-DNO_MSABI_VA_FUNCS=TRUE" + + GCC:*_CLANG8_*_CC_FLAGS = -O1 -fsanitize=address -fprofile-arcs -ftest-coverage + GCC:*_CLANG8_*_DLINK2_FLAGS = -fsanitize=address --coverage + GCC:*_CLANGWIN_IA32_DLINK_FLAGS == /out:"$(BIN_DIR)\$(BASE_NAME).exe" /base:0x10000000 /pdb:"$(BIN_DIR)\$(BASE_NAME).pdb" /LIBPATH:"$(VCINSTALLDIR)\Lib" /LIBPATH:"$(VCINSTALLDIR)\PlatformSdk\Lib" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x86" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x86" /NOLOGO /SUBSYSTEM:CONSOLE /NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:I386 /LTCG Kernel32.lib MSVCRTD.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib + GCC:*_CLANGWIN_X64_DLINK_FLAGS == /out:"$(BIN_DIR)\$(BASE_NAME).exe" /base:0x10000000 /pdb:"$(BIN_DIR)\$(BASE_NAME).pdb" /LIBPATH:"$(VCINSTALLDIR)\Lib\AMD64" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x64" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x64" /NOLOGO /SUBSYSTEM:CONSOLE /NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:AMD64 /LTCG Kernel32.lib MSVCRTD.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib + GCC:*_CLANGWIN_IA32_CC_FLAGS == -m32 -g -fshort-wchar -fno-strict-aliasing -Wall -c -include $(DEST_DIR_DEBUG)\AutoGen.h -D_CRT_SECURE_NO_WARNINGS -Wnonportable-include-path + GCC:*_CLANGWIN_X64_CC_FLAGS == -m64 -g -fshort-wchar -fno-strict-aliasing -Wall -c -include $(DEST_DIR_DEBUG)\AutoGen.h -D_CRT_SECURE_NO_WARNINGS -Wnonportable-include-path + GCC:*_CLANGWIN_X64_CC_FLAGS = "-DNO_MSABI_VA_FUNCS=TRUE" + + GCC:*_CLANGWIN_*_CC_FLAGS = -O1 + GCC:*_CLANGWIN_*_DLINK2_FLAGS == + + GCC:*_LIBFUZZERWIN_IA32_DLINK_FLAGS == /out:"$(BIN_DIR)\$(BASE_NAME).exe" /base:0x10000000 /pdb:"$(BIN_DIR)\$(BASE_NAME).pdb" /LIBPATH:"$(VCINSTALLDIR)\Lib" /LIBPATH:"$(VCINSTALLDIR)\PlatformSdk\Lib" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x86" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x86" /NOLOGO /SUBSYSTEM:CONSOLE /NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:I386 /LTCG Kernel32.lib MSVCRTD.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib + GCC:*_LIBFUZZERWIN_X64_DLINK_FLAGS == /out:"$(BIN_DIR)\$(BASE_NAME).exe" /base:0x10000000 /pdb:"$(BIN_DIR)\$(BASE_NAME).pdb" /LIBPATH:"$(VCINSTALLDIR)\Lib\AMD64" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x64" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x64" /NOLOGO /SUBSYSTEM:CONSOLE /NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:AMD64 /LTCG Kernel32.lib MSVCRTD.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib + GCC:*_LIBFUZZERWIN_IA32_CC_FLAGS == -m32 -g -fshort-wchar -fno-strict-aliasing -Wall -c -include $(DEST_DIR_DEBUG)\AutoGen.h -D_CRT_SECURE_NO_WARNINGS -Wnonportable-include-path + GCC:*_LIBFUZZERWIN_X64_CC_FLAGS == -m64 -g -fshort-wchar -fno-strict-aliasing -Wall -c -include $(DEST_DIR_DEBUG)\AutoGen.h -D_CRT_SECURE_NO_WARNINGS -Wnonportable-include-path + GCC:*_LIBFUZZERWIN_X64_CC_FLAGS = "-DNO_MSABI_VA_FUNCS=TRUE" + + GCC:*_LIBFUZZERWIN_*_CC_FLAGS = "-DTEST_WITH_LIBFUZZERWIN=TRUE" -O1 -fsanitize=fuzzer,address + GCC:*_LIBFUZZERWIN_*_DLINK2_FLAGS == -fsanitize=fuzzer,address + + GCC:*_AFL_*_CC_PATH = afl-gcc + GCC:*_AFL_X64_CC_FLAGS = -DUSING_LTO + + GCC:*_KLEE_IA32_DLINK_FLAGS == -o $(BIN_DIR)/$(BASE_NAME) + GCC:*_KLEE_IA32_CC_FLAGS == -m32 -MD -g -fshort-wchar -fno-strict-aliasing -Wno-int-to-void-pointer-cast -Wall -c -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_KLEE_IA32_PP_FLAGS == -m32 -E -x assembler-with-cpp -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_KLEE_IA32_ASM_FLAGS == -m32 -c -x assembler -imacros $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_KLEE_IA32_DLINK2_FLAGS == + + GCC:*_KLEE_X64_DLINK_FLAGS == -o $(BIN_DIR)/$(BASE_NAME) + GCC:*_KLEE_X64_CC_FLAGS == -m64 -MD -g -fshort-wchar -fno-strict-aliasing -Wno-int-to-void-pointer-cast -Wall -c -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_KLEE_X64_CC_FLAGS = "-DEFIAPI=__attribute__((ms_abi))" + GCC:*_KLEE_X64_CC_FLAGS = "-DEFIAPI=__attribute__((ms_abi))" -DUSING_LTO -Os + GCC:*_KLEE_X64_PP_FLAGS == -m64 -E -x assembler-with-cpp -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_KLEE_X64_ASM_FLAGS == -m64 -c -x assembler -imacros $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_KLEE_X64_DLINK2_FLAGS == + + GCC:*_KLEE_*_CC_PATH = wllvm + GCC:*_KLEE_*_CC_FLAGS = "-DTEST_WITH_KLEE=TRUE" -O2 -O0 -emit-llvm -I"$(KLEE_SRC_PATH)/include" + +[BuildOptions.common.EDKII.USER_DEFINED] + MSFT:*_*_IA32_DLINK_FLAGS == /out:"$(BIN_DIR)\$(BASE_NAME).exe" /base:0x10000000 /pdb:"$(BIN_DIR)\$(BASE_NAME).pdb" /LIBPATH:"$(VCINSTALLDIR)\Lib" /LIBPATH:"$(VCINSTALLDIR)\PlatformSdk\Lib" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x86" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x86" /NOLOGO /SUBSYSTEM:CONSOLE /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:I386 /LTCG Kernel32.lib MSVCRTD.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib + MSFT:*_VS2015_IA32_DLINK_FLAGS == /out:"$(BIN_DIR)\$(BASE_NAME).exe" /base:0x10000000 /pdb:"$(BIN_DIR)\$(BASE_NAME).pdb" /LIBPATH:"$(VCINSTALLDIR)\Lib" /LIBPATH:"$(VCINSTALLDIR)\PlatformSdk\Lib" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x86" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x86" /NOLOGO /SUBSYSTEM:CONSOLE /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:I386 /LTCG Kernel32.lib MSVCRTD.lib vcruntimed.lib ucrtd.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib + MSFT:*_VS2015x86_IA32_DLINK_FLAGS == /out:"$(BIN_DIR)\$(BASE_NAME).exe" /base:0x10000000 /pdb:"$(BIN_DIR)\$(BASE_NAME).pdb" /LIBPATH:"$(VCINSTALLDIR)\Lib" /LIBPATH:"$(VCINSTALLDIR)\PlatformSdk\Lib" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x86" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x86" /NOLOGO /SUBSYSTEM:CONSOLE /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:I386 /LTCG Kernel32.lib MSVCRTD.lib vcruntimed.lib ucrtd.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib + MSFT:*_VS2017_IA32_DLINK_FLAGS == /out:"$(BIN_DIR)\$(BASE_NAME).exe" /base:0x10000000 /pdb:"$(BIN_DIR)\$(BASE_NAME).pdb" /LIBPATH:"%VCToolsInstallDir%lib\x86" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x86" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x86" /NOLOGO /SUBSYSTEM:CONSOLE /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:I386 /LTCG Kernel32.lib MSVCRTD.lib vcruntimed.lib ucrtd.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib + MSFT:*_*_IA32_CC_FLAGS == /nologo /W4 /WX /Gy /c /D UNICODE /Od /FIAutoGen.h /EHs-c- /GF /Gs8192 /Zi /Gm /D _CRT_SECURE_NO_WARNINGS /D _CRT_SECURE_NO_DEPRECATE + MSFT:*_*_IA32_PP_FLAGS == /nologo /E /TC /FIAutoGen.h + MSFT:*_*_IA32_ASM_FLAGS == /nologo /W3 /WX /c /coff /Cx /Zd /W0 /Zi + MSFT:*_*_IA32_ASMLINK_FLAGS == /link /nologo /tiny + + MSFT:*_*_X64_DLINK_FLAGS == /out:"$(BIN_DIR)\$(BASE_NAME).exe" /base:0x10000000 /pdb:"$(BIN_DIR)\$(BASE_NAME).pdb" /LIBPATH:"$(VCINSTALLDIR)\Lib\AMD64" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x64" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x64" /NOLOGO /SUBSYSTEM:CONSOLE /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:AMD64 /LTCG Kernel32.lib MSVCRTD.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib + MSFT:*_VS2015_X64_DLINK_FLAGS == /out:"$(BIN_DIR)\$(BASE_NAME).exe" /base:0x10000000 /pdb:"$(BIN_DIR)\$(BASE_NAME).pdb" /LIBPATH:"$(VCINSTALLDIR)\Lib\AMD64" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x64" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x64" /NOLOGO /SUBSYSTEM:CONSOLE /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:AMD64 /LTCG Kernel32.lib MSVCRTD.lib vcruntimed.lib ucrtd.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib + MSFT:*_VS2015x86_X64_DLINK_FLAGS == /out:"$(BIN_DIR)\$(BASE_NAME).exe" /base:0x10000000 /pdb:"$(BIN_DIR)\$(BASE_NAME).pdb" /LIBPATH:"$(VCINSTALLDIR)\Lib\AMD64" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x64" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x64" /NOLOGO /SUBSYSTEM:CONSOLE /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:AMD64 /LTCG Kernel32.lib MSVCRTD.lib vcruntimed.lib ucrtd.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib + MSFT:*_VS2017_X64_DLINK_FLAGS == /out:"$(BIN_DIR)\$(BASE_NAME).exe" /base:0x10000000 /pdb:"$(BIN_DIR)\$(BASE_NAME).pdb" /LIBPATH:"%VCToolsInstallDir%lib\x64" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x64" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x64" /NOLOGO /SUBSYSTEM:CONSOLE /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:AMD64 /LTCG Kernel32.lib MSVCRTD.lib vcruntimed.lib ucrtd.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib + MSFT:*_*_X64_CC_FLAGS == /nologo /W4 /WX /Gy /c /D UNICODE /Od /FIAutoGen.h /EHs-c- /GF /Gs8192 /Zi /Gm /D _CRT_SECURE_NO_WARNINGS /D _CRT_SECURE_NO_DEPRECATE + MSFT:*_*_X64_PP_FLAGS == /nologo /E /TC /FIAutoGen.h + MSFT:*_*_X64_ASM_FLAGS == /nologo /W3 /WX /c /Cx /Zd /W0 /Zi + MSFT:*_*_X64_ASMLINK_FLAGS == /link /nologo + + GCC:*_*_IA32_DLINK_FLAGS == -o $(BIN_DIR)/$(BASE_NAME) -m32 -L/usr/X11R6/lib + GCC:*_*_IA32_CC_FLAGS == -m32 -g -fshort-wchar -fno-strict-aliasing -Wall -malign-double -idirafter/usr/include -c -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_*_IA32_PP_FLAGS == -m32 -E -x assembler-with-cpp -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_*_IA32_ASM_FLAGS == -m32 -c -x assembler -imacros $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_*_IA32_DLINK2_FLAGS == -Wno-error -no-pie + + GCC:*_*_X64_DLINK_FLAGS == -o $(BIN_DIR)/$(BASE_NAME) -m64 -L/usr/X11R6/lib + GCC:*_GCC5_X64_DLINK_FLAGS == -o $(BIN_DIR)/$(BASE_NAME) -m64 -L/usr/X11R6/lib + GCC:*_*_X64_CC_FLAGS == -m64 -g -fshort-wchar -fno-strict-aliasing -Wall -malign-double -idirafter/usr/include -c -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_GCC49_X64_CC_FLAGS = "-DEFIAPI=__attribute__((ms_abi))" + GCC:*_GCC5_X64_CC_FLAGS = "-DEFIAPI=__attribute__((ms_abi))" -DUSING_LTO -Os + GCC:*_*_X64_PP_FLAGS == -m64 -E -x assembler-with-cpp -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_*_X64_ASM_FLAGS == -m64 -c -x assembler -imacros $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_*_X64_DLINK2_FLAGS == -Wno-error -no-pie + + GCC:*_GCC5_*_CC_FLAGS = -fstack-protector -fstack-protector-strong -fstack-protector-all + + GCC:*_GCC5_*_CC_FLAGS = --coverage + GCC:*_GCC5_*_DLINK_FLAGS = --coverage + + GCC:*_GCC5_X64_CC_FLAGS = "-DNO_MSABI_VA_FUNCS=TRUE" + + GCC:*_LIBFUZZER_IA32_CC_FLAGS == -m32 -g -fshort-wchar -fno-strict-aliasing -Wall -idirafter/usr/include -c -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_LIBFUZZER_X64_CC_FLAGS == -m64 -g -fshort-wchar -fno-strict-aliasing -Wall -idirafter/usr/include -c -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_LIBFUZZER_X64_CC_FLAGS = "-DNO_MSABI_VA_FUNCS=TRUE" + + GCC:*_LIBFUZZER_*_CC_FLAGS = "-DTEST_WITH_LIBFUZZER=TRUE" -O1 -fsanitize=fuzzer,address + GCC:*_LIBFUZZER_*_DLINK2_FLAGS = -fsanitize=fuzzer,address + + GCC:*_CLANG8_IA32_CC_FLAGS == -m32 -g -fshort-wchar -fno-strict-aliasing -Wall -idirafter/usr/include -c -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_CLANG8_X64_CC_FLAGS == -m64 -g -fshort-wchar -fno-strict-aliasing -Wall -idirafter/usr/include -c -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_CLANG8_X64_CC_FLAGS = "-DNO_MSABI_VA_FUNCS=TRUE" + + GCC:*_CLANG8_*_CC_FLAGS = -O1 -fsanitize=address -fprofile-arcs -ftest-coverage + GCC:*_CLANG8_*_DLINK2_FLAGS = -fsanitize=address --coverage + + + GCC:*_CLANGWIN_IA32_DLINK_FLAGS == /out:"$(BIN_DIR)\$(BASE_NAME).exe" /base:0x10000000 /pdb:"$(BIN_DIR)\$(BASE_NAME).pdb" /LIBPATH:"$(VCINSTALLDIR)\Lib" /LIBPATH:"$(VCINSTALLDIR)\PlatformSdk\Lib" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x86" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x86" /LIBPATH:"%LLVMx86_PATH%\lib\clang\8.0.0\lib\windows" /NOLOGO /SUBSYSTEM:CONSOLE /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:I386 /LTCG Kernel32.lib MSVCRTD.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib clang_rt.asan_dynamic-i386.lib clang_rt.asan_dynamic_runtime_thunk-i386.lib + GCC:*_CLANGWIN_X64_DLINK_FLAGS == /out:"$(BIN_DIR)\$(BASE_NAME).exe" /base:0x10000000 /pdb:"$(BIN_DIR)\$(BASE_NAME).pdb" /LIBPATH:"$(VCINSTALLDIR)\Lib\AMD64" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x64" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x64" /LIBPATH:"%LLVM_PATH%\lib\clang\8.0.0\lib\windows" /NOLOGO /SUBSYSTEM:CONSOLE /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:AMD64 /LTCG Kernel32.lib MSVCRTD.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib clang_rt.asan_dynamic-x86_64.lib clang_rt.asan_dynamic_runtime_thunk-x86_64.lib + GCC:*_CLANGWIN_IA32_CC_FLAGS == -m32 -g -fshort-wchar -fno-strict-aliasing -Wall -c -include $(DEST_DIR_DEBUG)\AutoGen.h -D_CRT_SECURE_NO_WARNINGS -Wnonportable-include-path + GCC:*_CLANGWIN_X64_CC_FLAGS == -m64 -g -fshort-wchar -fno-strict-aliasing -Wall -c -include $(DEST_DIR_DEBUG)\AutoGen.h -D_CRT_SECURE_NO_WARNINGS -Wnonportable-include-path + GCC:*_CLANGWIN_X64_CC_FLAGS = "-DNO_MSABI_VA_FUNCS=TRUE" + + GCC:*_CLANGWIN_*_CC_FLAGS = -O1 + GCC:*_CLANGWIN_*_DLINK2_FLAGS == + + GCC:*_CLANGWIN_*_CC_FLAGS = -fsanitize=address + + GCC:*_LIBFUZZERWIN_IA32_DLINK_FLAGS == /out:"$(BIN_DIR)\$(BASE_NAME).exe" /base:0x10000000 /pdb:"$(BIN_DIR)\$(BASE_NAME).pdb" /LIBPATH:"$(VCINSTALLDIR)\Lib" /LIBPATH:"$(VCINSTALLDIR)\PlatformSdk\Lib" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x86" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x86" /LIBPATH:"%LLVMx86_PATH%\lib\clang\8.0.0\lib\windows" /NOLOGO /SUBSYSTEM:CONSOLE /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:I386 /LTCG Kernel32.lib MSVCRTD.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib clang_rt.asan_dynamic-i386.lib clang_rt.asan_dynamic_runtime_thunk-i386.lib clang_rt.fuzzer-i386.lib + GCC:*_LIBFUZZERWIN_X64_DLINK_FLAGS == /out:"$(BIN_DIR)\$(BASE_NAME).exe" /base:0x10000000 /pdb:"$(BIN_DIR)\$(BASE_NAME).pdb" /LIBPATH:"$(VCINSTALLDIR)\Lib\AMD64" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x64" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x64" /LIBPATH:"%LLVM_PATH%\lib\clang\8.0.0\lib\windows" /NOLOGO /SUBSYSTEM:CONSOLE /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:AMD64 /LTCG Kernel32.lib MSVCRTD.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib clang_rt.asan_dynamic-x86_64.lib clang_rt.asan_dynamic_runtime_thunk-x86_64.lib clang_rt.fuzzer-x86_64.lib + GCC:*_LIBFUZZERWIN_IA32_CC_FLAGS == -m32 -g -fshort-wchar -fno-strict-aliasing -Wall -c -include $(DEST_DIR_DEBUG)\AutoGen.h -D_CRT_SECURE_NO_WARNINGS -Wnonportable-include-path + GCC:*_LIBFUZZERWIN_X64_CC_FLAGS == -m64 -g -fshort-wchar -fno-strict-aliasing -Wall -c -include $(DEST_DIR_DEBUG)\AutoGen.h -D_CRT_SECURE_NO_WARNINGS -Wnonportable-include-path + GCC:*_LIBFUZZERWIN_X64_CC_FLAGS = "-DNO_MSABI_VA_FUNCS=TRUE" + + GCC:*_LIBFUZZERWIN_*_CC_FLAGS = "-DTEST_WITH_LIBFUZZERWIN=TRUE" -O1 -fsanitize=fuzzer,address + GCC:*_LIBFUZZERWIN_*_DLINK2_FLAGS == -fsanitize=fuzzer,address + + GCC:*_AFL_*_CC_PATH = afl-gcc + + GCC:*_KLEE_IA32_DLINK_FLAGS == -o $(BIN_DIR)/$(BASE_NAME) + GCC:*_KLEE_IA32_CC_FLAGS == -m32 -MD -g -fshort-wchar -fno-strict-aliasing -Wno-int-to-void-pointer-cast -Wall -c -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_KLEE_IA32_PP_FLAGS == -m32 -E -x assembler-with-cpp -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_KLEE_IA32_ASM_FLAGS == -m32 -c -x assembler -imacros $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_KLEE_IA32_DLINK2_FLAGS == + + GCC:*_KLEE_X64_DLINK_FLAGS == -o $(BIN_DIR)/$(BASE_NAME) + GCC:*_KLEE_X64_CC_FLAGS == -m64 -MD -g -fshort-wchar -fno-strict-aliasing -Wno-int-to-void-pointer-cast -Wall -c -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_KLEE_X64_CC_FLAGS = "-DEFIAPI=__attribute__((ms_abi))" + GCC:*_KLEE_X64_CC_FLAGS = "-DEFIAPI=__attribute__((ms_abi))" -DUSING_LTO -Os + GCC:*_KLEE_X64_PP_FLAGS == -m64 -E -x assembler-with-cpp -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_KLEE_X64_ASM_FLAGS == -m64 -c -x assembler -imacros $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_KLEE_X64_DLINK2_FLAGS == + + GCC:*_KLEE_*_CC_PATH = wllvm + GCC:*_KLEE_*_CC_FLAGS = "-DTEST_WITH_KLEE=TRUE" -O2 -O0 -emit-llvm -I"$(KLEE_SRC_PATH)/include" diff --git a/HBFA/UefiHostFuzzTestPkg/UefiHostFuzzTestPkg.dec b/HBFA/UefiHostFuzzTestPkg/UefiHostFuzzTestPkg.dec new file mode 100644 index 0000000..9fa3ac0 --- /dev/null +++ b/HBFA/UefiHostFuzzTestPkg/UefiHostFuzzTestPkg.dec @@ -0,0 +1,15 @@ +## @file UefiHostFuzzTestPkg.dec +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = UefiHostFuzzTestPkg + PACKAGE_GUID = 9996C2CE-80B4-473E-B7C3-E326BA6B5D73 + PACKAGE_VERSION = 0.11 + +[Includes] + Include \ No newline at end of file diff --git a/HBFA/UefiHostTestPkg/Include/Library/OsServiceLib.h b/HBFA/UefiHostTestPkg/Include/Library/OsServiceLib.h new file mode 100644 index 0000000..a50b892 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Include/Library/OsServiceLib.h @@ -0,0 +1,24 @@ +/** + +Implement UnitTestLib + +Copyright (c) Microsoft +**/ + +#ifndef _OS_SERVICE_LIB_H_ +#define _OS_SERVICE_LIB_H_ + +#include + +VOID * +AllocateExecutableMemory ( + IN UINTN Size + ); + +VOID +FreeExecutableMemory ( + IN VOID *Buffer, + IN UINTN Size + ); + +#endif diff --git a/HBFA/UefiHostTestPkg/Library/BaseCacheMaintenanceLibHost/BaseCacheMaintenanceLibHost.inf b/HBFA/UefiHostTestPkg/Library/BaseCacheMaintenanceLibHost/BaseCacheMaintenanceLibHost.inf new file mode 100644 index 0000000..3ef2f30 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseCacheMaintenanceLibHost/BaseCacheMaintenanceLibHost.inf @@ -0,0 +1,31 @@ +## @file +# Instance of Cache Maintenance Library using Base Library services. +# +# Cache Maintenance Library that uses Base Library services to maintain caches. +# This library assumes there are no chipset dependencies required to maintain caches. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseCacheMaintenanceLibHost + FILE_GUID = 0F652FA7-946D-4737-A6D7-4B8B97AD0EA3 + MODULE_TYPE = BASE + VERSION_STRING = 1.1 + LIBRARY_CLASS = CacheMaintenanceLib + +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC ARM AARCH64 +# + +[Sources] + Cache.c + +[Packages] + MdePkg/MdePkg.dec diff --git a/HBFA/UefiHostTestPkg/Library/BaseCacheMaintenanceLibHost/Cache.c b/HBFA/UefiHostTestPkg/Library/BaseCacheMaintenanceLibHost/Cache.c new file mode 100644 index 0000000..a350df3 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseCacheMaintenanceLibHost/Cache.c @@ -0,0 +1,226 @@ +/** @file + Cache Maintenance Functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + + +**/ + +#include +#include +#include + +/** + Invalidates the entire instruction cache in cache coherency domain of the + calling CPU. + +**/ +VOID +EFIAPI +InvalidateInstructionCache ( + VOID + ) +{ +} + +/** + Invalidates a range of instruction cache lines in the cache coherency domain + of the calling CPU. + + Invalidates the instruction cache lines specified by Address and Length. If + Address is not aligned on a cache line boundary, then entire instruction + cache line containing Address is invalidated. If Address + Length is not + aligned on a cache line boundary, then the entire instruction cache line + containing Address + Length -1 is invalidated. This function may choose to + invalidate the entire instruction cache if that is more efficient than + invalidating the specified range. If Length is 0, then no instruction cache + lines are invalidated. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the instruction cache lines to + invalidate. If the CPU is in a physical addressing mode, then + Address is a physical address. If the CPU is in a virtual + addressing mode, then Address is a virtual address. + + @param Length The number of bytes to invalidate from the instruction cache. + + @return Address. + +**/ +VOID * +EFIAPI +InvalidateInstructionCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + return Address; +} + +/** + Writes back and invalidates the entire data cache in cache coherency domain + of the calling CPU. + + Writes back and invalidates the entire data cache in cache coherency domain + of the calling CPU. This function guarantees that all dirty cache lines are + written back to system memory, and also invalidates all the data cache lines + in the cache coherency domain of the calling CPU. + +**/ +VOID +EFIAPI +WriteBackInvalidateDataCache ( + VOID + ) +{ + +} + +/** + Writes back and invalidates a range of data cache lines in the cache + coherency domain of the calling CPU. + + Writes back and invalidates the data cache lines specified by Address and + Length. If Address is not aligned on a cache line boundary, then entire data + cache line containing Address is written back and invalidated. If Address + + Length is not aligned on a cache line boundary, then the entire data cache + line containing Address + Length -1 is written back and invalidated. This + function may choose to write back and invalidate the entire data cache if + that is more efficient than writing back and invalidating the specified + range. If Length is 0, then no data cache lines are written back and + invalidated. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to write back and + invalidate. If the CPU is in a physical addressing mode, then + Address is a physical address. If the CPU is in a virtual + addressing mode, then Address is a virtual address. + @param Length The number of bytes to write back and invalidate from the + data cache. + + @return Address of cache invalidation. + +**/ +VOID * +EFIAPI +WriteBackInvalidateDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + return Address; +} + +/** + Writes back the entire data cache in cache coherency domain of the calling + CPU. + + Writes back the entire data cache in cache coherency domain of the calling + CPU. This function guarantees that all dirty cache lines are written back to + system memory. This function may also invalidate all the data cache lines in + the cache coherency domain of the calling CPU. + +**/ +VOID +EFIAPI +WriteBackDataCache ( + VOID + ) +{ + WriteBackInvalidateDataCache (); +} + +/** + Writes back a range of data cache lines in the cache coherency domain of the + calling CPU. + + Writes back the data cache lines specified by Address and Length. If Address + is not aligned on a cache line boundary, then entire data cache line + containing Address is written back. If Address + Length is not aligned on a + cache line boundary, then the entire data cache line containing Address + + Length -1 is written back. This function may choose to write back the entire + data cache if that is more efficient than writing back the specified range. + If Length is 0, then no data cache lines are written back. This function may + also invalidate all the data cache lines in the specified range of the cache + coherency domain of the calling CPU. Address is returned. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to write back. If + the CPU is in a physical addressing mode, then Address is a + physical address. If the CPU is in a virtual addressing + mode, then Address is a virtual address. + @param Length The number of bytes to write back from the data cache. + + @return Address of cache written in main memory. + +**/ +VOID * +EFIAPI +WriteBackDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + return WriteBackInvalidateDataCacheRange (Address, Length); +} + +/** + Invalidates the entire data cache in cache coherency domain of the calling + CPU. + + Invalidates the entire data cache in cache coherency domain of the calling + CPU. This function must be used with care because dirty cache lines are not + written back to system memory. It is typically used for cache diagnostics. If + the CPU does not support invalidation of the entire data cache, then a write + back and invalidate operation should be performed on the entire data cache. + +**/ +VOID +EFIAPI +InvalidateDataCache ( + VOID + ) +{ + +} + +/** + Invalidates a range of data cache lines in the cache coherency domain of the + calling CPU. + + Invalidates the data cache lines specified by Address and Length. If Address + is not aligned on a cache line boundary, then entire data cache line + containing Address is invalidated. If Address + Length is not aligned on a + cache line boundary, then the entire data cache line containing Address + + Length -1 is invalidated. This function must never invalidate any cache lines + outside the specified range. If Length is 0, then no data cache lines are + invalidated. Address is returned. This function must be used with care + because dirty cache lines are not written back to system memory. It is + typically used for cache diagnostics. If the CPU does not support + invalidation of a data cache range, then a write back and invalidate + operation should be performed on the data cache range. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the data cache lines to invalidate. If + the CPU is in a physical addressing mode, then Address is a + physical address. If the CPU is in a virtual addressing mode, + then Address is a virtual address. + @param Length The number of bytes to invalidate from the data cache. + + @return Address. + +**/ +VOID * +EFIAPI +InvalidateDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + return WriteBackInvalidateDataCacheRange (Address, Length); +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseCpuLibHost/BaseCpuLibHost.c b/HBFA/UefiHostTestPkg/Library/BaseCpuLibHost/BaseCpuLibHost.c new file mode 100644 index 0000000..ab0ef3c --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseCpuLibHost/BaseCpuLibHost.c @@ -0,0 +1,38 @@ +/** @file + Base Library CPU Functions for EBC + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include + +/** + Flushes all the Translation Lookaside Buffers(TLB) entries in a CPU. + + Flushes all the Translation Lookaside Buffers(TLB) entries in a CPU. + +**/ +VOID +EFIAPI +CpuFlushTlb ( + VOID + ) +{ +} + +/** + Places the CPU in a sleep state until an interrupt is received. + + Places the CPU in a sleep state until an interrupt is received. If interrupts + are disabled prior to calling this function, then the CPU will be placed in a + sleep state indefinitely. + +**/ +VOID +EFIAPI +CpuSleep ( + VOID + ) +{ +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseCpuLibHost/BaseCpuLibHost.inf b/HBFA/UefiHostTestPkg/Library/BaseCpuLibHost/BaseCpuLibHost.inf new file mode 100644 index 0000000..07ac365 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseCpuLibHost/BaseCpuLibHost.inf @@ -0,0 +1,25 @@ +## @file +# Instance of CPU Library for various architecture. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseCpuLibHost + FILE_GUID = 197E7CD0-2C4A-4AF1-A84D-DCAC0A1D7EF8 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = CpuLib + +[Sources] + BaseCpuLibHost.c + +[Packages] + MdePkg/MdePkg.dec + + diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/ARShiftU64.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/ARShiftU64.c new file mode 100644 index 0000000..82aa010 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/ARShiftU64.c @@ -0,0 +1,44 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +UINT64 +EFIAPI +InternalMathARShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + +/** + Shifts a 64-bit integer right between 0 and 63 bits. The high bits are filled + with the original integer's bit 63. The shifted value is returned. + + This function shifts the 64-bit value Operand to the right by Count bits. The + high Count bits are set to bit 63 of Operand. The shifted value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to shift right. + @param Count The number of bits to shift right. + + @return Operand >> Count + +**/ +UINT64 +EFIAPI +ARShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + ASSERT (Count < 64); + return InternalMathARShiftU64 (Operand, Count); +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/BaseLibHost.inf b/HBFA/UefiHostTestPkg/Library/BaseLibHost/BaseLibHost.inf new file mode 100644 index 0000000..29db48f --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/BaseLibHost.inf @@ -0,0 +1,80 @@ +## @file +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseLibHost + FILE_GUID = FA4A8DE0-8D55-44AA-8368-07D24BDA6A7D + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = BaseLib + +[Sources] + Math64.c + RShiftU64.c + LShiftU64.c + ARShiftU64.c + MultU64x64.c + MultS64x64.c + MultU64x32.c + DivS64x64Remainder.c + DivU64x64Remainder.c + DivU64x32Remainder.c + DivU64x32.c + ModU64x32.c + SwapBytes16.c + SwapBytes32.c + SwapBytes64.c + BitField.c + GetPowerOfTwo32.c + GetPowerOfTwo64.c + HighBitSet32.c + HighBitSet64.c + LowBitSet32.c + LowBitSet64.c + LRotU32.c + LRotU64.c + RRotU32.c + RRotU64.c + SafeString.c + String.c + CheckSum.c + CpuDeadLoop.c + LinkedList.c + Unaligned.c + SetJump.c + LongJump.c + X86MemoryFenceMsvc.c | MSFT + X86MemoryFenceGcc.c | GCC + CpuBreakpointMsvc.c | MSFT + CpuBreakpointGcc.c | GCC + Cpu.c + Cache.c + X86Cr.c + X86Dr.c + X86RdRand.c + X86PatchInstruction.c + X86GdtrNull.c + X86IdtrNull.c + X86SegmentNull.c + X86DisablePaging64Null.c + SwitchStackNull.c + +[Sources.Ia32] + Ia32/RdRand.nasm + Ia32/ReadTsc.nasm + +[Sources.X64] + X64/RdRand.nasm + X64/ReadTsc.nasm + +[Packages] + MdePkg/MdePkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + +[LibraryClasses] + BaseMemoryLib diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/BaseLibHostNoAsm.inf b/HBFA/UefiHostTestPkg/Library/BaseLibHost/BaseLibHostNoAsm.inf new file mode 100644 index 0000000..bd93a24 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/BaseLibHostNoAsm.inf @@ -0,0 +1,76 @@ +## @file +# +# this is a special build to pass KLEE build, because KLEE cannot use ASM. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseLibHost + FILE_GUID = FA4A8DE0-8D55-44AA-8368-07D24BDA6A7D + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = BaseLib + +[Sources] + Math64.c + RShiftU64.c + LShiftU64.c + ARShiftU64.c + MultU64x64.c + MultS64x64.c + MultU64x32.c + DivS64x64Remainder.c + DivU64x64Remainder.c + DivU64x32Remainder.c + DivU64x32.c + ModU64x32.c + SwapBytes16.c + SwapBytes32.c + SwapBytes64.c + BitField.c + GetPowerOfTwo32.c + GetPowerOfTwo64.c + HighBitSet32.c + HighBitSet64.c + LowBitSet32.c + LowBitSet64.c + LRotU32.c + LRotU64.c + RRotU32.c + RRotU64.c + SafeString.c + String.c + CheckSum.c + CpuDeadLoop.c + LinkedList.c + Unaligned.c + SetJump.c + LongJump.c + X86MemoryFenceMsvc.c | MSFT + X86MemoryFenceGcc.c | GCC + CpuBreakpointMsvc.c | MSFT + CpuBreakpointGcc.c | GCC + Cpu.c + Cache.c + X86Cr.c + X86Dr.c + X86RdRand.c + X86PatchInstruction.c + X86GdtrNull.c + X86IdtrNull.c + X86SegmentNull.c + X86DisablePaging64Null.c + SwitchStackNull.c + DummyRdRand.c + DummyReadTsc.c + +[Packages] + MdePkg/MdePkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + +[LibraryClasses] + BaseMemoryLib diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/BitField.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/BitField.c new file mode 100644 index 0000000..8d044e0 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/BitField.c @@ -0,0 +1,1004 @@ +/** @file + Bit field functions of BaseLib. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +/** + Worker function that returns a bit field from Operand. + + Returns the bitfield specified by the StartBit and the EndBit from Operand. + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + @param EndBit The ordinal of the most significant bit in the bit field. + + @return The bit field read. + +**/ +UINTN +EFIAPI +InternalBaseLibBitFieldReadUint ( + IN UINTN Operand, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + // + // ~((UINTN)-2 << EndBit) is a mask in which bit[0] thru bit[EndBit] + // are 1's while bit[EndBit + 1] thru the most significant bit are 0's. + // + return (Operand & ~((UINTN)-2 << EndBit)) >> StartBit; +} + +/** + Worker function that reads a bit field from Operand, performs a bitwise OR, + and returns the result. + + Performs a bitwise OR between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new value is returned. + + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + @param EndBit The ordinal of the most significant bit in the bit field. + @param OrData The value to OR with the read value from the value. + + @return The new value. + +**/ +UINTN +EFIAPI +InternalBaseLibBitFieldOrUint ( + IN UINTN Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINTN OrData + ) +{ + // + // Higher bits in OrData those are not used must be zero. + // + // EndBit - StartBit + 1 might be 32 while the result right shifting 32 on a 32bit integer is undefined, + // So the logic is updated to right shift (EndBit - StartBit) bits and compare the last bit directly. + // + ASSERT ((OrData >> (EndBit - StartBit)) == ((OrData >> (EndBit - StartBit)) & 1)); + + // + // ~((UINTN)-2 << EndBit) is a mask in which bit[0] thru bit[EndBit] + // are 1's while bit[EndBit + 1] thru the most significant bit are 0's. + // + return Operand | ((OrData << StartBit) & ~((UINTN) -2 << EndBit)); +} + +/** + Worker function that reads a bit field from Operand, performs a bitwise AND, + and returns the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new value is returned. + + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + @param EndBit The ordinal of the most significant bit in the bit field. + @param AndData The value to And with the read value from the value. + + @return The new value. + +**/ +UINTN +EFIAPI +InternalBaseLibBitFieldAndUint ( + IN UINTN Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINTN AndData + ) +{ + // + // Higher bits in AndData those are not used must be zero. + // + // EndBit - StartBit + 1 might be 32 while the result right shifting 32 on a 32bit integer is undefined, + // So the logic is updated to right shift (EndBit - StartBit) bits and compare the last bit directly. + // + ASSERT ((AndData >> (EndBit - StartBit)) == ((AndData >> (EndBit - StartBit)) & 1)); + + // + // ~((UINTN)-2 << EndBit) is a mask in which bit[0] thru bit[EndBit] + // are 1's while bit[EndBit + 1] thru the most significant bit are 0's. + // + return Operand & ~((~AndData << StartBit) & ~((UINTN)-2 << EndBit)); +} + +/** + Returns a bit field from an 8-bit value. + + Returns the bitfield specified by the StartBit and the EndBit from Operand. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The bit field read. + +**/ +UINT8 +EFIAPI +BitFieldRead8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + ASSERT (EndBit < 8); + ASSERT (StartBit <= EndBit); + return (UINT8)InternalBaseLibBitFieldReadUint (Operand, StartBit, EndBit); +} + +/** + Writes a bit field to an 8-bit value, and returns the result. + + Writes Value to the bit field specified by the StartBit and the EndBit in + Operand. All other bits in Operand are preserved. The new 8-bit value is + returned. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value The new value of the bit field. + + @return The new 8-bit value. + +**/ +UINT8 +EFIAPI +BitFieldWrite8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + ASSERT (EndBit < 8); + ASSERT (StartBit <= EndBit); + return BitFieldAndThenOr8 (Operand, StartBit, EndBit, 0, Value); +} + +/** + Reads a bit field from an 8-bit value, performs a bitwise OR, and returns the + result. + + Performs a bitwise OR between the bit field specified by StartBit + and EndBit in Operand and the value specified by OrData. All other bits in + Operand are preserved. The new 8-bit value is returned. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the read value from the value. + + @return The new 8-bit value. + +**/ +UINT8 +EFIAPI +BitFieldOr8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + ASSERT (EndBit < 8); + ASSERT (StartBit <= EndBit); + return (UINT8)InternalBaseLibBitFieldOrUint (Operand, StartBit, EndBit, OrData); +} + +/** + Reads a bit field from an 8-bit value, performs a bitwise AND, and returns + the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new 8-bit value is returned. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the value. + + @return The new 8-bit value. + +**/ +UINT8 +EFIAPI +BitFieldAnd8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + ASSERT (EndBit < 8); + ASSERT (StartBit <= EndBit); + return (UINT8)InternalBaseLibBitFieldAndUint (Operand, StartBit, EndBit, AndData); +} + +/** + Reads a bit field from an 8-bit value, performs a bitwise AND followed by a + bitwise OR, and returns the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData, followed by a bitwise + OR with value specified by OrData. All other bits in Operand are + preserved. The new 8-bit value is returned. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the value. + @param OrData The value to OR with the result of the AND operation. + + @return The new 8-bit value. + +**/ +UINT8 +EFIAPI +BitFieldAndThenOr8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + ASSERT (EndBit < 8); + ASSERT (StartBit <= EndBit); + return BitFieldOr8 ( + BitFieldAnd8 (Operand, StartBit, EndBit, AndData), + StartBit, + EndBit, + OrData + ); +} + +/** + Returns a bit field from a 16-bit value. + + Returns the bitfield specified by the StartBit and the EndBit from Operand. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The bit field read. + +**/ +UINT16 +EFIAPI +BitFieldRead16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + ASSERT (EndBit < 16); + ASSERT (StartBit <= EndBit); + return (UINT16)InternalBaseLibBitFieldReadUint (Operand, StartBit, EndBit); +} + +/** + Writes a bit field to a 16-bit value, and returns the result. + + Writes Value to the bit field specified by the StartBit and the EndBit in + Operand. All other bits in Operand are preserved. The new 16-bit value is + returned. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value The new value of the bit field. + + @return The new 16-bit value. + +**/ +UINT16 +EFIAPI +BitFieldWrite16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + ASSERT (EndBit < 16); + ASSERT (StartBit <= EndBit); + return BitFieldAndThenOr16 (Operand, StartBit, EndBit, 0, Value); +} + +/** + Reads a bit field from a 16-bit value, performs a bitwise OR, and returns the + result. + + Performs a bitwise OR between the bit field specified by StartBit + and EndBit in Operand and the value specified by OrData. All other bits in + Operand are preserved. The new 16-bit value is returned. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the read value from the value. + + @return The new 16-bit value. + +**/ +UINT16 +EFIAPI +BitFieldOr16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + ASSERT (EndBit < 16); + ASSERT (StartBit <= EndBit); + return (UINT16)InternalBaseLibBitFieldOrUint (Operand, StartBit, EndBit, OrData); +} + +/** + Reads a bit field from a 16-bit value, performs a bitwise AND, and returns + the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new 16-bit value is returned. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the value. + + @return The new 16-bit value. + +**/ +UINT16 +EFIAPI +BitFieldAnd16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + ASSERT (EndBit < 16); + ASSERT (StartBit <= EndBit); + return (UINT16)InternalBaseLibBitFieldAndUint (Operand, StartBit, EndBit, AndData); +} + +/** + Reads a bit field from a 16-bit value, performs a bitwise AND followed by a + bitwise OR, and returns the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData, followed by a bitwise + OR with value specified by OrData. All other bits in Operand are + preserved. The new 16-bit value is returned. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the value. + @param OrData The value to OR with the result of the AND operation. + + @return The new 16-bit value. + +**/ +UINT16 +EFIAPI +BitFieldAndThenOr16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + ASSERT (EndBit < 16); + ASSERT (StartBit <= EndBit); + return BitFieldOr16 ( + BitFieldAnd16 (Operand, StartBit, EndBit, AndData), + StartBit, + EndBit, + OrData + ); +} + +/** + Returns a bit field from a 32-bit value. + + Returns the bitfield specified by the StartBit and the EndBit from Operand. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The bit field read. + +**/ +UINT32 +EFIAPI +BitFieldRead32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + ASSERT (EndBit < 32); + ASSERT (StartBit <= EndBit); + return (UINT32)InternalBaseLibBitFieldReadUint (Operand, StartBit, EndBit); +} + +/** + Writes a bit field to a 32-bit value, and returns the result. + + Writes Value to the bit field specified by the StartBit and the EndBit in + Operand. All other bits in Operand are preserved. The new 32-bit value is + returned. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value The new value of the bit field. + + @return The new 32-bit value. + +**/ +UINT32 +EFIAPI +BitFieldWrite32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + ASSERT (EndBit < 32); + ASSERT (StartBit <= EndBit); + return BitFieldAndThenOr32 (Operand, StartBit, EndBit, 0, Value); +} + +/** + Reads a bit field from a 32-bit value, performs a bitwise OR, and returns the + result. + + Performs a bitwise OR between the bit field specified by StartBit + and EndBit in Operand and the value specified by OrData. All other bits in + Operand are preserved. The new 32-bit value is returned. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the read value from the value. + + @return The new 32-bit value. + +**/ +UINT32 +EFIAPI +BitFieldOr32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + ASSERT (EndBit < 32); + ASSERT (StartBit <= EndBit); + return (UINT32)InternalBaseLibBitFieldOrUint (Operand, StartBit, EndBit, OrData); +} + +/** + Reads a bit field from a 32-bit value, performs a bitwise AND, and returns + the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new 32-bit value is returned. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the value. + + @return The new 32-bit value. + +**/ +UINT32 +EFIAPI +BitFieldAnd32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + ASSERT (EndBit < 32); + ASSERT (StartBit <= EndBit); + return (UINT32)InternalBaseLibBitFieldAndUint (Operand, StartBit, EndBit, AndData); +} + +/** + Reads a bit field from a 32-bit value, performs a bitwise AND followed by a + bitwise OR, and returns the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData, followed by a bitwise + OR with value specified by OrData. All other bits in Operand are + preserved. The new 32-bit value is returned. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the value. + @param OrData The value to OR with the result of the AND operation. + + @return The new 32-bit value. + +**/ +UINT32 +EFIAPI +BitFieldAndThenOr32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + ASSERT (EndBit < 32); + ASSERT (StartBit <= EndBit); + return BitFieldOr32 ( + BitFieldAnd32 (Operand, StartBit, EndBit, AndData), + StartBit, + EndBit, + OrData + ); +} + +/** + Returns a bit field from a 64-bit value. + + Returns the bitfield specified by the StartBit and the EndBit from Operand. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The bit field read. + +**/ +UINT64 +EFIAPI +BitFieldRead64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + ASSERT (EndBit < 64); + ASSERT (StartBit <= EndBit); + return RShiftU64 (Operand & ~LShiftU64 ((UINT64)-2, EndBit), StartBit); +} + +/** + Writes a bit field to a 64-bit value, and returns the result. + + Writes Value to the bit field specified by the StartBit and the EndBit in + Operand. All other bits in Operand are preserved. The new 64-bit value is + returned. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param Value The new value of the bit field. + + @return The new 64-bit value. + +**/ +UINT64 +EFIAPI +BitFieldWrite64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ) +{ + ASSERT (EndBit < 64); + ASSERT (StartBit <= EndBit); + return BitFieldAndThenOr64 (Operand, StartBit, EndBit, 0, Value); +} + +/** + Reads a bit field from a 64-bit value, performs a bitwise OR, and returns the + result. + + Performs a bitwise OR between the bit field specified by StartBit + and EndBit in Operand and the value specified by OrData. All other bits in + Operand are preserved. The new 64-bit value is returned. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param OrData The value to OR with the read value from the value + + @return The new 64-bit value. + +**/ +UINT64 +EFIAPI +BitFieldOr64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData + ) +{ + UINT64 Value1; + UINT64 Value2; + + ASSERT (EndBit < 64); + ASSERT (StartBit <= EndBit); + // + // Higher bits in OrData those are not used must be zero. + // + // EndBit - StartBit + 1 might be 64 while the result right shifting 64 on RShiftU64() API is invalid, + // So the logic is updated to right shift (EndBit - StartBit) bits and compare the last bit directly. + // + ASSERT (RShiftU64 (OrData, EndBit - StartBit) == (RShiftU64 (OrData, EndBit - StartBit) & 1)); + + Value1 = LShiftU64 (OrData, StartBit); + Value2 = LShiftU64 ((UINT64) - 2, EndBit); + + return Operand | (Value1 & ~Value2); +} + +/** + Reads a bit field from a 64-bit value, performs a bitwise AND, and returns + the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new 64-bit value is returned. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the value. + + @return The new 64-bit value. + +**/ +UINT64 +EFIAPI +BitFieldAnd64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData + ) +{ + UINT64 Value1; + UINT64 Value2; + + ASSERT (EndBit < 64); + ASSERT (StartBit <= EndBit); + // + // Higher bits in AndData those are not used must be zero. + // + // EndBit - StartBit + 1 might be 64 while the right shifting 64 on RShiftU64() API is invalid, + // So the logic is updated to right shift (EndBit - StartBit) bits and compare the last bit directly. + // + ASSERT (RShiftU64 (AndData, EndBit - StartBit) == (RShiftU64 (AndData, EndBit - StartBit) & 1)); + + Value1 = LShiftU64 (~AndData, StartBit); + Value2 = LShiftU64 ((UINT64)-2, EndBit); + + return Operand & ~(Value1 & ~Value2); +} + +/** + Reads a bit field from a 64-bit value, performs a bitwise AND followed by a + bitwise OR, and returns the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData, followed by a bitwise + OR with value specified by OrData. All other bits in Operand are + preserved. The new 64-bit value is returned. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the value. + @param OrData The value to OR with the result of the AND operation. + + @return The new 64-bit value. + +**/ +UINT64 +EFIAPI +BitFieldAndThenOr64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + ASSERT (EndBit < 64); + ASSERT (StartBit <= EndBit); + return BitFieldOr64 ( + BitFieldAnd64 (Operand, StartBit, EndBit, AndData), + StartBit, + EndBit, + OrData + ); +} + +/** + Reads a bit field from a 32-bit value, counts and returns + the number of set bits. + + Counts the number of set bits in the bit field specified by + StartBit and EndBit in Operand. The count is returned. + + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The number of bits set between StartBit and EndBit. + +**/ +UINT8 +EFIAPI +BitFieldCountOnes32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + UINT32 Count; + + ASSERT (EndBit < 32); + ASSERT (StartBit <= EndBit); + + Count = BitFieldRead32 (Operand, StartBit, EndBit); + Count -= ((Count >> 1) & 0x55555555); + Count = (Count & 0x33333333) + ((Count >> 2) & 0x33333333); + Count += Count >> 4; + Count &= 0x0F0F0F0F; + Count += Count >> 8; + Count += Count >> 16; + + return (UINT8) Count & 0x3F; +} + +/** + Reads a bit field from a 64-bit value, counts and returns + the number of set bits. + + Counts the number of set bits in the bit field specified by + StartBit and EndBit in Operand. The count is returned. + + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The number of bits set between StartBit and EndBit. + +**/ +UINT8 +EFIAPI +BitFieldCountOnes64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + UINT64 BitField; + UINT8 Count; + + ASSERT (EndBit < 64); + ASSERT (StartBit <= EndBit); + + BitField = BitFieldRead64 (Operand, StartBit, EndBit); + Count = BitFieldCountOnes32 ((UINT32) BitField, 0, 31); + Count += BitFieldCountOnes32 ((UINT32) RShiftU64(BitField, 32), 0, 31); + + return Count; +} + diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/Cache.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/Cache.c new file mode 100644 index 0000000..ff787e3 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/Cache.c @@ -0,0 +1,40 @@ +/** @file + Base Library CPU Functions for all architectures. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +/** + Set CD bit and clear NW bit of CR0 followed by a WBINVD. + + Disables the caches by setting the CD bit of CR0 to 1, clearing the NW bit of CR0 to 0, + and executing a WBINVD instruction. This function is only available on IA-32 and x64. + +**/ +VOID +EFIAPI +AsmDisableCache ( + VOID + ) +{ +} + + +/** + Perform a WBINVD and clear both the CD and NW bits of CR0. + + Enables the caches by executing a WBINVD instruction and then clear both the CD and NW + bits of CR0 to 0. This function is only available on IA-32 and x64. + +**/ +VOID +EFIAPI +AsmEnableCache ( + VOID + ) +{ +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/CheckSum.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/CheckSum.c new file mode 100644 index 0000000..0dd3cc9 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/CheckSum.c @@ -0,0 +1,628 @@ +/** @file + Utility functions to generate checksum based on 2's complement + algorithm. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +/** + Returns the sum of all elements in a buffer in unit of UINT8. + During calculation, the carry bits are dropped. + + This function calculates the sum of all elements in a buffer + in unit of UINT8. The carry bits in result of addition are dropped. + The result is returned as UINT8. If Length is Zero, then Zero is + returned. + + If Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the sum operation. + @param Length The size, in bytes, of Buffer. + + @return Sum The sum of Buffer with carry bits dropped during additions. + +**/ +UINT8 +EFIAPI +CalculateSum8 ( + IN CONST UINT8 *Buffer, + IN UINTN Length + ) +{ + UINT8 Sum; + UINTN Count; + + ASSERT (Buffer != NULL); + ASSERT (Length <= (MAX_ADDRESS - ((UINTN) Buffer) + 1)); + + for (Sum = 0, Count = 0; Count < Length; Count++) { + Sum = (UINT8) (Sum + *(Buffer + Count)); + } + + return Sum; +} + + +/** + Returns the two's complement checksum of all elements in a buffer + of 8-bit values. + + This function first calculates the sum of the 8-bit values in the + buffer specified by Buffer and Length. The carry bits in the result + of addition are dropped. Then, the two's complement of the sum is + returned. If Length is 0, then 0 is returned. + + If Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the checksum operation. + @param Length The size, in bytes, of Buffer. + + @return Checksum The 2's complement checksum of Buffer. + +**/ +UINT8 +EFIAPI +CalculateCheckSum8 ( + IN CONST UINT8 *Buffer, + IN UINTN Length + ) +{ + UINT8 CheckSum; + + CheckSum = CalculateSum8 (Buffer, Length); + + // + // Return the checksum based on 2's complement. + // + return (UINT8) (0x100 - CheckSum); +} + +/** + Returns the sum of all elements in a buffer of 16-bit values. During + calculation, the carry bits are dropped. + + This function calculates the sum of the 16-bit values in the buffer + specified by Buffer and Length. The carry bits in result of addition are dropped. + The 16-bit result is returned. If Length is 0, then 0 is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the sum operation. + @param Length The size, in bytes, of Buffer. + + @return Sum The sum of Buffer with carry bits dropped during additions. + +**/ +UINT16 +EFIAPI +CalculateSum16 ( + IN CONST UINT16 *Buffer, + IN UINTN Length + ) +{ + UINT16 Sum; + UINTN Count; + UINTN Total; + + ASSERT (Buffer != NULL); + ASSERT (((UINTN) Buffer & 0x1) == 0); + ASSERT ((Length & 0x1) == 0); + ASSERT (Length <= (MAX_ADDRESS - ((UINTN) Buffer) + 1)); + + Total = Length / sizeof (*Buffer); + for (Sum = 0, Count = 0; Count < Total; Count++) { + Sum = (UINT16) (Sum + *(Buffer + Count)); + } + + return Sum; +} + + +/** + Returns the two's complement checksum of all elements in a buffer of + 16-bit values. + + This function first calculates the sum of the 16-bit values in the buffer + specified by Buffer and Length. The carry bits in the result of addition + are dropped. Then, the two's complement of the sum is returned. If Length + is 0, then 0 is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the checksum operation. + @param Length The size, in bytes, of Buffer. + + @return Checksum The 2's complement checksum of Buffer. + +**/ +UINT16 +EFIAPI +CalculateCheckSum16 ( + IN CONST UINT16 *Buffer, + IN UINTN Length + ) +{ + UINT16 CheckSum; + + CheckSum = CalculateSum16 (Buffer, Length); + + // + // Return the checksum based on 2's complement. + // + return (UINT16) (0x10000 - CheckSum); +} + + +/** + Returns the sum of all elements in a buffer of 32-bit values. During + calculation, the carry bits are dropped. + + This function calculates the sum of the 32-bit values in the buffer + specified by Buffer and Length. The carry bits in result of addition are dropped. + The 32-bit result is returned. If Length is 0, then 0 is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the sum operation. + @param Length The size, in bytes, of Buffer. + + @return Sum The sum of Buffer with carry bits dropped during additions. + +**/ +UINT32 +EFIAPI +CalculateSum32 ( + IN CONST UINT32 *Buffer, + IN UINTN Length + ) +{ + UINT32 Sum; + UINTN Count; + UINTN Total; + + ASSERT (Buffer != NULL); + ASSERT (((UINTN) Buffer & 0x3) == 0); + ASSERT ((Length & 0x3) == 0); + ASSERT (Length <= (MAX_ADDRESS - ((UINTN) Buffer) + 1)); + + Total = Length / sizeof (*Buffer); + for (Sum = 0, Count = 0; Count < Total; Count++) { + Sum = Sum + *(Buffer + Count); + } + + return Sum; +} + + +/** + Returns the two's complement checksum of all elements in a buffer of + 32-bit values. + + This function first calculates the sum of the 32-bit values in the buffer + specified by Buffer and Length. The carry bits in the result of addition + are dropped. Then, the two's complement of the sum is returned. If Length + is 0, then 0 is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the checksum operation. + @param Length The size, in bytes, of Buffer. + + @return Checksum The 2's complement checksum of Buffer. + +**/ +UINT32 +EFIAPI +CalculateCheckSum32 ( + IN CONST UINT32 *Buffer, + IN UINTN Length + ) +{ + UINT32 CheckSum; + + CheckSum = CalculateSum32 (Buffer, Length); + + // + // Return the checksum based on 2's complement. + // + return (UINT32) ((UINT32)(-1) - CheckSum + 1); +} + + +/** + Returns the sum of all elements in a buffer of 64-bit values. During + calculation, the carry bits are dropped. + + This function calculates the sum of the 64-bit values in the buffer + specified by Buffer and Length. The carry bits in result of addition are dropped. + The 64-bit result is returned. If Length is 0, then 0 is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the sum operation. + @param Length The size, in bytes, of Buffer. + + @return Sum The sum of Buffer with carry bits dropped during additions. + +**/ +UINT64 +EFIAPI +CalculateSum64 ( + IN CONST UINT64 *Buffer, + IN UINTN Length + ) +{ + UINT64 Sum; + UINTN Count; + UINTN Total; + + ASSERT (Buffer != NULL); + ASSERT (((UINTN) Buffer & 0x7) == 0); + ASSERT ((Length & 0x7) == 0); + ASSERT (Length <= (MAX_ADDRESS - ((UINTN) Buffer) + 1)); + + Total = Length / sizeof (*Buffer); + for (Sum = 0, Count = 0; Count < Total; Count++) { + Sum = Sum + *(Buffer + Count); + } + + return Sum; +} + + +/** + Returns the two's complement checksum of all elements in a buffer of + 64-bit values. + + This function first calculates the sum of the 64-bit values in the buffer + specified by Buffer and Length. The carry bits in the result of addition + are dropped. Then, the two's complement of the sum is returned. If Length + is 0, then 0 is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the checksum operation. + @param Length The size, in bytes, of Buffer. + + @return Checksum The 2's complement checksum of Buffer. + +**/ +UINT64 +EFIAPI +CalculateCheckSum64 ( + IN CONST UINT64 *Buffer, + IN UINTN Length + ) +{ + UINT64 CheckSum; + + CheckSum = CalculateSum64 (Buffer, Length); + + // + // Return the checksum based on 2's complement. + // + return (UINT64) ((UINT64)(-1) - CheckSum + 1); +} + +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 mCrcTable[256] = { + 0x00000000, + 0x77073096, + 0xEE0E612C, + 0x990951BA, + 0x076DC419, + 0x706AF48F, + 0xE963A535, + 0x9E6495A3, + 0x0EDB8832, + 0x79DCB8A4, + 0xE0D5E91E, + 0x97D2D988, + 0x09B64C2B, + 0x7EB17CBD, + 0xE7B82D07, + 0x90BF1D91, + 0x1DB71064, + 0x6AB020F2, + 0xF3B97148, + 0x84BE41DE, + 0x1ADAD47D, + 0x6DDDE4EB, + 0xF4D4B551, + 0x83D385C7, + 0x136C9856, + 0x646BA8C0, + 0xFD62F97A, + 0x8A65C9EC, + 0x14015C4F, + 0x63066CD9, + 0xFA0F3D63, + 0x8D080DF5, + 0x3B6E20C8, + 0x4C69105E, + 0xD56041E4, + 0xA2677172, + 0x3C03E4D1, + 0x4B04D447, + 0xD20D85FD, + 0xA50AB56B, + 0x35B5A8FA, + 0x42B2986C, + 0xDBBBC9D6, + 0xACBCF940, + 0x32D86CE3, + 0x45DF5C75, + 0xDCD60DCF, + 0xABD13D59, + 0x26D930AC, + 0x51DE003A, + 0xC8D75180, + 0xBFD06116, + 0x21B4F4B5, + 0x56B3C423, + 0xCFBA9599, + 0xB8BDA50F, + 0x2802B89E, + 0x5F058808, + 0xC60CD9B2, + 0xB10BE924, + 0x2F6F7C87, + 0x58684C11, + 0xC1611DAB, + 0xB6662D3D, + 0x76DC4190, + 0x01DB7106, + 0x98D220BC, + 0xEFD5102A, + 0x71B18589, + 0x06B6B51F, + 0x9FBFE4A5, + 0xE8B8D433, + 0x7807C9A2, + 0x0F00F934, + 0x9609A88E, + 0xE10E9818, + 0x7F6A0DBB, + 0x086D3D2D, + 0x91646C97, + 0xE6635C01, + 0x6B6B51F4, + 0x1C6C6162, + 0x856530D8, + 0xF262004E, + 0x6C0695ED, + 0x1B01A57B, + 0x8208F4C1, + 0xF50FC457, + 0x65B0D9C6, + 0x12B7E950, + 0x8BBEB8EA, + 0xFCB9887C, + 0x62DD1DDF, + 0x15DA2D49, + 0x8CD37CF3, + 0xFBD44C65, + 0x4DB26158, + 0x3AB551CE, + 0xA3BC0074, + 0xD4BB30E2, + 0x4ADFA541, + 0x3DD895D7, + 0xA4D1C46D, + 0xD3D6F4FB, + 0x4369E96A, + 0x346ED9FC, + 0xAD678846, + 0xDA60B8D0, + 0x44042D73, + 0x33031DE5, + 0xAA0A4C5F, + 0xDD0D7CC9, + 0x5005713C, + 0x270241AA, + 0xBE0B1010, + 0xC90C2086, + 0x5768B525, + 0x206F85B3, + 0xB966D409, + 0xCE61E49F, + 0x5EDEF90E, + 0x29D9C998, + 0xB0D09822, + 0xC7D7A8B4, + 0x59B33D17, + 0x2EB40D81, + 0xB7BD5C3B, + 0xC0BA6CAD, + 0xEDB88320, + 0x9ABFB3B6, + 0x03B6E20C, + 0x74B1D29A, + 0xEAD54739, + 0x9DD277AF, + 0x04DB2615, + 0x73DC1683, + 0xE3630B12, + 0x94643B84, + 0x0D6D6A3E, + 0x7A6A5AA8, + 0xE40ECF0B, + 0x9309FF9D, + 0x0A00AE27, + 0x7D079EB1, + 0xF00F9344, + 0x8708A3D2, + 0x1E01F268, + 0x6906C2FE, + 0xF762575D, + 0x806567CB, + 0x196C3671, + 0x6E6B06E7, + 0xFED41B76, + 0x89D32BE0, + 0x10DA7A5A, + 0x67DD4ACC, + 0xF9B9DF6F, + 0x8EBEEFF9, + 0x17B7BE43, + 0x60B08ED5, + 0xD6D6A3E8, + 0xA1D1937E, + 0x38D8C2C4, + 0x4FDFF252, + 0xD1BB67F1, + 0xA6BC5767, + 0x3FB506DD, + 0x48B2364B, + 0xD80D2BDA, + 0xAF0A1B4C, + 0x36034AF6, + 0x41047A60, + 0xDF60EFC3, + 0xA867DF55, + 0x316E8EEF, + 0x4669BE79, + 0xCB61B38C, + 0xBC66831A, + 0x256FD2A0, + 0x5268E236, + 0xCC0C7795, + 0xBB0B4703, + 0x220216B9, + 0x5505262F, + 0xC5BA3BBE, + 0xB2BD0B28, + 0x2BB45A92, + 0x5CB36A04, + 0xC2D7FFA7, + 0xB5D0CF31, + 0x2CD99E8B, + 0x5BDEAE1D, + 0x9B64C2B0, + 0xEC63F226, + 0x756AA39C, + 0x026D930A, + 0x9C0906A9, + 0xEB0E363F, + 0x72076785, + 0x05005713, + 0x95BF4A82, + 0xE2B87A14, + 0x7BB12BAE, + 0x0CB61B38, + 0x92D28E9B, + 0xE5D5BE0D, + 0x7CDCEFB7, + 0x0BDBDF21, + 0x86D3D2D4, + 0xF1D4E242, + 0x68DDB3F8, + 0x1FDA836E, + 0x81BE16CD, + 0xF6B9265B, + 0x6FB077E1, + 0x18B74777, + 0x88085AE6, + 0xFF0F6A70, + 0x66063BCA, + 0x11010B5C, + 0x8F659EFF, + 0xF862AE69, + 0x616BFFD3, + 0x166CCF45, + 0xA00AE278, + 0xD70DD2EE, + 0x4E048354, + 0x3903B3C2, + 0xA7672661, + 0xD06016F7, + 0x4969474D, + 0x3E6E77DB, + 0xAED16A4A, + 0xD9D65ADC, + 0x40DF0B66, + 0x37D83BF0, + 0xA9BCAE53, + 0xDEBB9EC5, + 0x47B2CF7F, + 0x30B5FFE9, + 0xBDBDF21C, + 0xCABAC28A, + 0x53B39330, + 0x24B4A3A6, + 0xBAD03605, + 0xCDD70693, + 0x54DE5729, + 0x23D967BF, + 0xB3667A2E, + 0xC4614AB8, + 0x5D681B02, + 0x2A6F2B94, + 0xB40BBE37, + 0xC30C8EA1, + 0x5A05DF1B, + 0x2D02EF8D +}; + +/** + Computes and returns a 32-bit CRC for a data buffer. + CRC32 value bases on ITU-T V.42. + + If Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param[in] Buffer A pointer to the buffer on which the 32-bit CRC is to be computed. + @param[in] Length The number of bytes in the buffer Data. + + @retval Crc32 The 32-bit CRC was computed for the data buffer. + +**/ +UINT32 +EFIAPI +CalculateCrc32( + IN VOID *Buffer, + IN UINTN Length + ) +{ + UINTN Index; + UINT32 Crc; + UINT8 *Ptr; + + ASSERT (Buffer != NULL); + ASSERT (Length <= (MAX_ADDRESS - ((UINTN) Buffer) + 1)); + + // + // Compute CRC + // + Crc = 0xffffffff; + for (Index = 0, Ptr = Buffer; Index < Length; Index++, Ptr++) { + Crc = (Crc >> 8) ^ mCrcTable[(UINT8) Crc ^ *Ptr]; + } + + return Crc ^ 0xffffffff; +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/Cpu.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/Cpu.c new file mode 100644 index 0000000..727fd90 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/Cpu.c @@ -0,0 +1,95 @@ +/** @file + Base Library CPU Functions for all architectures. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +/** + Disables CPU interrupts and returns the interrupt state prior to the disable + operation. + + @retval TRUE CPU interrupts were enabled on entry to this call. + @retval FALSE CPU interrupts were disabled on entry to this call. + +**/ +BOOLEAN +EFIAPI +SaveAndDisableInterrupts ( + VOID + ) +{ + return FALSE; +} + +/** + Set the current CPU interrupt state. + + Sets the current CPU interrupt state to the state specified by + InterruptState. If InterruptState is TRUE, then interrupts are enabled. If + InterruptState is FALSE, then interrupts are disabled. InterruptState is + returned. + + @param InterruptState TRUE if interrupts should be enabled. FALSE if + interrupts should be disabled. + + @return InterruptState + +**/ +BOOLEAN +EFIAPI +SetInterruptState ( + IN BOOLEAN InterruptState + ) +{ + return InterruptState; +} + +/** + Uses as a barrier to stop speculative execution. + + Ensures that no later instruction will execute speculatively, until all prior + instructions have completed. + +**/ +VOID +EFIAPI +SpeculationBarrier ( + VOID + ) +{ +} + +/** + Requests CPU to pause for a short period of time. + + Requests CPU to pause for a short period of time. Typically used in MP + systems to prevent memory starvation while waiting for a spin lock. + +**/ +VOID +EFIAPI +CpuPause ( + VOID + ) +{ +} + +/** + Performs a serializing operation on all load-from-memory instructions that + were issued prior the AsmLfence function. + + Executes a LFENCE instruction. This function is only available on IA-32 and x64. + +**/ +VOID +EFIAPI +AsmLfence ( + VOID + ) +{ + return; +} \ No newline at end of file diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/CpuBreakpointGcc.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/CpuBreakpointGcc.c new file mode 100644 index 0000000..20edc0c --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/CpuBreakpointGcc.c @@ -0,0 +1,26 @@ +/** @file + CpuBreakpoint function. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Generates a breakpoint on the CPU. + + Generates a breakpoint on the CPU. The breakpoint must be implemented such + that code can resume normal execution after the breakpoint. + +**/ +VOID +EFIAPI +CpuBreakpoint ( + VOID + ) +{ + __asm__ __volatile__ ("int $3"); +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/CpuBreakpointMsvc.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/CpuBreakpointMsvc.c new file mode 100644 index 0000000..a59da0c --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/CpuBreakpointMsvc.c @@ -0,0 +1,35 @@ +/** @file + CpuBreakpoint function. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics. +**/ + +void __debugbreak (VOID); + +#pragma intrinsic(__debugbreak) + +/** + Generates a breakpoint on the CPU. + + Generates a breakpoint on the CPU. The breakpoint must be implemented such + that code can resume normal execution after the breakpoint. + +**/ +VOID +EFIAPI +CpuBreakpoint ( + VOID + ) +{ + __debugbreak (); +} + diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/CpuDeadLoop.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/CpuDeadLoop.c new file mode 100644 index 0000000..9e110ca --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/CpuDeadLoop.c @@ -0,0 +1,32 @@ +/** @file + Base Library CPU Functions for all architectures. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + +#include +#include + +/** + Executes an infinite loop. + + Forces the CPU to execute an infinite loop. A debugger may be used to skip + past the loop and the code that follows the loop must execute properly. This + implies that the infinite loop must not cause the code that follow it to be + optimized away. + +**/ +VOID +EFIAPI +CpuDeadLoop ( + VOID + ) +{ + volatile UINTN Index; + + for (Index = 0; Index == 0;); +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/DivS64x64Remainder.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/DivS64x64Remainder.c new file mode 100644 index 0000000..3048df5 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/DivS64x64Remainder.c @@ -0,0 +1,54 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +INT64 +EFIAPI +InternalMathDivRemS64x64 ( + IN INT64 Dividend, + IN INT64 Divisor, + OUT INT64 *Remainder OPTIONAL + ); + +/** + Divides a 64-bit signed integer by a 64-bit signed integer and generates a + 64-bit signed result and a optional 64-bit signed remainder. + + This function divides the 64-bit signed value Dividend by the 64-bit signed + value Divisor and generates a 64-bit signed quotient. If Remainder is not + NULL, then the 64-bit signed remainder is returned in Remainder. This + function returns the 64-bit signed quotient. + + It is the caller's responsibility to not call this function with a Divisor of 0. + If Divisor is 0, then the quotient and remainder should be assumed to be + the largest negative integer. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit signed value. + @param Divisor A 64-bit signed value. + @param Remainder A pointer to a 64-bit signed value. This parameter is + optional and may be NULL. + + @return Dividend / Divisor + +**/ +INT64 +EFIAPI +DivS64x64Remainder ( + IN INT64 Dividend, + IN INT64 Divisor, + OUT INT64 *Remainder OPTIONAL + ) +{ + ASSERT (Divisor != 0); + return InternalMathDivRemS64x64 (Dividend, Divisor, Remainder); +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/DivU64x32.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/DivU64x32.c new file mode 100644 index 0000000..b63fb6d --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/DivU64x32.c @@ -0,0 +1,45 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +UINT64 +EFIAPI +InternalMathDivU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor + ); + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and generates + a 64-bit unsigned result. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 64-bit unsigned quotient. This + function returns the 64-bit unsigned quotient. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + + @return Dividend / Divisor + +**/ +UINT64 +EFIAPI +DivU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor + ) +{ + ASSERT (Divisor != 0); + return InternalMathDivU64x32 (Dividend, Divisor); +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/DivU64x32Remainder.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/DivU64x32Remainder.c new file mode 100644 index 0000000..03ce598 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/DivU64x32Remainder.c @@ -0,0 +1,50 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +UINT64 +EFIAPI +InternalMathDivRemU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor, + OUT UINT32 *Remainder OPTIONAL + ); + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and generates + a 64-bit unsigned result and an optional 32-bit unsigned remainder. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 64-bit unsigned quotient. If Remainder + is not NULL, then the 32-bit unsigned remainder is returned in Remainder. + This function returns the 64-bit unsigned quotient. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + @param Remainder A pointer to a 32-bit unsigned value. This parameter is + optional and may be NULL. + + @return Dividend / Divisor + +**/ +UINT64 +EFIAPI +DivU64x32Remainder ( + IN UINT64 Dividend, + IN UINT32 Divisor, + OUT UINT32 *Remainder OPTIONAL + ) +{ + ASSERT (Divisor != 0); + return InternalMathDivRemU64x32 (Dividend, Divisor, Remainder); +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/DivU64x64Remainder.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/DivU64x64Remainder.c new file mode 100644 index 0000000..ee3fd26 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/DivU64x64Remainder.c @@ -0,0 +1,50 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +UINT64 +EFIAPI +InternalMathDivRemU64x64 ( + IN UINT64 Dividend, + IN UINT64 Divisor, + OUT UINT64 *Remainder OPTIONAL + ); + +/** + Divides a 64-bit unsigned integer by a 64-bit unsigned integer and generates + a 64-bit unsigned result and an optional 64-bit unsigned remainder. + + This function divides the 64-bit unsigned value Dividend by the 64-bit + unsigned value Divisor and generates a 64-bit unsigned quotient. If Remainder + is not NULL, then the 64-bit unsigned remainder is returned in Remainder. + This function returns the 64-bit unsigned quotient. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit unsigned value. + @param Divisor A 64-bit unsigned value. + @param Remainder A pointer to a 64-bit unsigned value. This parameter is + optional and may be NULL. + + @return Dividend / Divisor + +**/ +UINT64 +EFIAPI +DivU64x64Remainder ( + IN UINT64 Dividend, + IN UINT64 Divisor, + OUT UINT64 *Remainder OPTIONAL + ) +{ + ASSERT (Divisor != 0); + return InternalMathDivRemU64x64 (Dividend, Divisor, Remainder); +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/DummyRdRand.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/DummyRdRand.c new file mode 100644 index 0000000..1e880d5 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/DummyRdRand.c @@ -0,0 +1,65 @@ +/** @file + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +/** + Generates a 16-bit random number through RDRAND instruction. + + @param[out] Rand Buffer pointer to store the random result. + + @retval TRUE RDRAND call was successful. + @retval FALSE Failed attempts to call RDRAND. + + **/ +BOOLEAN +EFIAPI +InternalX86RdRand16 ( + OUT UINT16 *Rand + ) +{ + return TRUE; +} + +/** + Generates a 32-bit random number through RDRAND instruction. + + @param[out] Rand Buffer pointer to store the random result. + + @retval TRUE RDRAND call was successful. + @retval FALSE Failed attempts to call RDRAND. + +**/ +BOOLEAN +EFIAPI +InternalX86RdRand32 ( + OUT UINT32 *Rand + ) +{ + return TRUE; +} + +/** + Generates a 64-bit random number through RDRAND instruction. + + + @param[out] Rand Buffer pointer to store the random result. + + @retval TRUE RDRAND call was successful. + @retval FALSE Failed attempts to call RDRAND. + +**/ +BOOLEAN +EFIAPI +InternalX86RdRand64 ( + OUT UINT64 *Rand + ) +{ + return TRUE; +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/DummyReadTsc.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/DummyReadTsc.c new file mode 100644 index 0000000..62650dd --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/DummyReadTsc.c @@ -0,0 +1,19 @@ +/** @file + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +UINT64 +EFIAPI +AsmReadTsc ( + VOID + ) +{ + return 0; +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/GetPowerOfTwo32.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/GetPowerOfTwo32.c new file mode 100644 index 0000000..90e5d5f --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/GetPowerOfTwo32.c @@ -0,0 +1,37 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +/** + Returns the value of the highest bit set in a 32-bit value. Equivalent to + 1 << log2(x). + + This function computes the value of the highest bit set in the 32-bit value + specified by Operand. If Operand is zero, then zero is returned. + + @param Operand The 32-bit operand to evaluate. + + @return 1 << HighBitSet32(Operand) + @retval 0 Operand is zero. + +**/ +UINT32 +EFIAPI +GetPowerOfTwo32 ( + IN UINT32 Operand + ) +{ + if (0 == Operand) { + return 0; + } + + return 1ul << HighBitSet32 (Operand); +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/GetPowerOfTwo64.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/GetPowerOfTwo64.c new file mode 100644 index 0000000..680a82d --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/GetPowerOfTwo64.c @@ -0,0 +1,37 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +/** + Returns the value of the highest bit set in a 64-bit value. Equivalent to + 1 << log2(x). + + This function computes the value of the highest bit set in the 64-bit value + specified by Operand. If Operand is zero, then zero is returned. + + @param Operand The 64-bit operand to evaluate. + + @return 1 << HighBitSet64(Operand) + @retval 0 Operand is zero. + +**/ +UINT64 +EFIAPI +GetPowerOfTwo64 ( + IN UINT64 Operand + ) +{ + if (Operand == 0) { + return 0; + } + + return LShiftU64 (1, (UINTN) HighBitSet64 (Operand)); +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/HighBitSet32.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/HighBitSet32.c new file mode 100644 index 0000000..610de67 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/HighBitSet32.c @@ -0,0 +1,40 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +/** + Returns the bit position of the highest bit set in a 32-bit value. Equivalent + to log2(x). + + This function computes the bit position of the highest bit set in the 32-bit + value specified by Operand. If Operand is zero, then -1 is returned. + Otherwise, a value between 0 and 31 is returned. + + @param Operand The 32-bit operand to evaluate. + + @retval 0..31 Position of the highest bit set in Operand if found. + @retval -1 Operand is zero. + +**/ +INTN +EFIAPI +HighBitSet32 ( + IN UINT32 Operand + ) +{ + INTN BitIndex; + + if (Operand == 0) { + return - 1; + } + for (BitIndex = 31; (INT32)Operand > 0; BitIndex--, Operand <<= 1); + return BitIndex; +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/HighBitSet64.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/HighBitSet64.c new file mode 100644 index 0000000..28be7cf --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/HighBitSet64.c @@ -0,0 +1,47 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +/** + Returns the bit position of the highest bit set in a 64-bit value. Equivalent + to log2(x). + + This function computes the bit position of the highest bit set in the 64-bit + value specified by Operand. If Operand is zero, then -1 is returned. + Otherwise, a value between 0 and 63 is returned. + + @param Operand The 64-bit operand to evaluate. + + @retval 0..63 Position of the highest bit set in Operand if found. + @retval -1 Operand is zero. + +**/ +INTN +EFIAPI +HighBitSet64 ( + IN UINT64 Operand + ) +{ + if (Operand == (UINT32)Operand) { + // + // Operand is just a 32-bit integer + // + return HighBitSet32 ((UINT32)Operand); + } + + // + // Operand is really a 64-bit integer + // + if (sizeof (UINTN) == sizeof (UINT32)) { + return HighBitSet32 (((UINT32*)&Operand)[1]) + 32; + } else { + return HighBitSet32 ((UINT32)RShiftU64 (Operand, 32)) + 32; + } +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/Ia32/RdRand.nasm b/HBFA/UefiHostTestPkg/Library/BaseLibHost/Ia32/RdRand.nasm new file mode 100644 index 0000000..e12b8e9 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/Ia32/RdRand.nasm @@ -0,0 +1,84 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; RdRand.nasm +; +; Abstract: +; +; Generates random number through CPU RdRand instruction under 32-bit platform. +; +; Notes: +; +;------------------------------------------------------------------------------ + +SECTION .text + +;------------------------------------------------------------------------------ +; Generates a 16 bit random number through RDRAND instruction. +; Return TRUE if Rand generated successfully, or FALSE if not. +; +; BOOLEAN EFIAPI InternalX86RdRand16 (UINT16 *Rand); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalX86RdRand16) +ASM_PFX(InternalX86RdRand16): + ; rdrand ax ; generate a 16 bit RN into ax + ; CF=1 if RN generated ok, otherwise CF=0 + db 0xf, 0xc7, 0xf0 ; rdrand r16: "0f c7 /6 ModRM:r/m(w)" + jc rn16_ok ; jmp if CF=1 + xor eax, eax ; reg=0 if CF=0 + ret ; return with failure status +rn16_ok: + mov edx, dword [esp + 4] + mov [edx], ax + mov eax, 1 + ret + +;------------------------------------------------------------------------------ +; Generates a 32 bit random number through RDRAND instruction. +; Return TRUE if Rand generated successfully, or FALSE if not. +; +; BOOLEAN EFIAPI InternalX86RdRand32 (UINT32 *Rand); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalX86RdRand32) +ASM_PFX(InternalX86RdRand32): + ; rdrand eax ; generate a 32 bit RN into eax + ; CF=1 if RN generated ok, otherwise CF=0 + db 0xf, 0xc7, 0xf0 ; rdrand r32: "0f c7 /6 ModRM:r/m(w)" + jc rn32_ok ; jmp if CF=1 + xor eax, eax ; reg=0 if CF=0 + ret ; return with failure status +rn32_ok: + mov edx, dword [esp + 4] + mov [edx], eax + mov eax, 1 + ret + +;------------------------------------------------------------------------------ +; Generates a 64 bit random number through RDRAND instruction. +; Return TRUE if Rand generated successfully, or FALSE if not. +; +; BOOLEAN EFIAPI InternalX86RdRand64 (UINT64 *Rand); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalX86RdRand64) +ASM_PFX(InternalX86RdRand64): + ; rdrand eax ; generate a 32 bit RN into eax + ; CF=1 if RN generated ok, otherwise CF=0 + db 0xf, 0xc7, 0xf0 ; rdrand r32: "0f c7 /6 ModRM:r/m(w)" + jnc rn64_ret ; jmp if CF=0 + mov edx, dword [esp + 4] + mov [edx], eax + + db 0xf, 0xc7, 0xf0 ; generate another 32 bit RN + jnc rn64_ret ; jmp if CF=0 + mov [edx + 4], eax + + mov eax, 1 + ret +rn64_ret: + xor eax, eax + ret ; return with failure status + diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/Ia32/ReadTsc.nasm b/HBFA/UefiHostTestPkg/Library/BaseLibHost/Ia32/ReadTsc.nasm new file mode 100644 index 0000000..1bc875b --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/Ia32/ReadTsc.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadTsc.Asm +; +; Abstract: +; +; AsmReadTsc function +; +; Notes: +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadTsc ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadTsc) +ASM_PFX(AsmReadTsc): + rdtsc + ret + diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/LRotU32.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/LRotU32.c new file mode 100644 index 0000000..8c18981 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/LRotU32.c @@ -0,0 +1,38 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +/** + Rotates a 32-bit integer left between 0 and 31 bits, filling the low bits + with the high bits that were rotated. + + This function rotates the 32-bit value Operand to the left by Count bits. The + low Count bits are fill with the high Count bits of Operand. The rotated + value is returned. + + If Count is greater than 31, then ASSERT(). + + @param Operand The 32-bit operand to rotate left. + @param Count The number of bits to rotate left. + + @return Operand << Count + +**/ +UINT32 +EFIAPI +LRotU32 ( + IN UINT32 Operand, + IN UINTN Count + ) +{ + ASSERT (Count < 32); + return (Operand << Count) | (Operand >> (32 - Count)); +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/LRotU64.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/LRotU64.c new file mode 100644 index 0000000..c58cdeb --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/LRotU64.c @@ -0,0 +1,45 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +UINT64 +EFIAPI +InternalMathLRotU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + +/** + Rotates a 64-bit integer left between 0 and 63 bits, filling the low bits + with the high bits that were rotated. + + This function rotates the 64-bit value Operand to the left by Count bits. The + low Count bits are fill with the high Count bits of Operand. The rotated + value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to rotate left. + @param Count The number of bits to rotate left. + + @return Operand << Count + +**/ +UINT64 +EFIAPI +LRotU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + ASSERT (Count < 64); + return InternalMathLRotU64 (Operand, Count); +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/LShiftU64.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/LShiftU64.c new file mode 100644 index 0000000..220e5c1 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/LShiftU64.c @@ -0,0 +1,44 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +UINT64 +EFIAPI +InternalMathLShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + +/** + Shifts a 64-bit integer left between 0 and 63 bits. The low bits are filled + with zeros. The shifted value is returned. + + This function shifts the 64-bit value Operand to the left by Count bits. The + low Count bits are set to zero. The shifted value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to shift left. + @param Count The number of bits to shift left. + + @return Operand << Count. + +**/ +UINT64 +EFIAPI +LShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + ASSERT (Count < 64); + return InternalMathLShiftU64 (Operand, Count); +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/Lfence.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/Lfence.c new file mode 100644 index 0000000..e894b4e --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/Lfence.c @@ -0,0 +1,10 @@ +/** @file + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/LinkedList.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/LinkedList.c new file mode 100644 index 0000000..550d5de --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/LinkedList.c @@ -0,0 +1,536 @@ +/** @file + Linked List Library Functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +#define ASSERT_VERIFY_NODE_IN_VALID_LIST(FirstEntry, SecondEntry, InList) + +/** + Worker function that verifies the validity of this list. + + If List is NULL, then ASSERT(). + If List->ForwardLink is NULL, then ASSERT(). + If List->BackLink is NULL, then ASSERT(). + If PcdMaximumLinkedListLength is not zero, and List contains more than + PcdMaximumLinkedListLength nodes, then ASSERT(). + + @param List A pointer to a node in a linked list. + + @retval TRUE if PcdVerifyNodeInList is FALSE + @retval TRUE if DoMembershipCheck is FALSE + @retval TRUE if PcdVerifyNodeInList is TRUE and DoMembershipCheck is TRUE + and Node is a member of List. + @retval FALSE if PcdVerifyNodeInList is TRUE and DoMembershipCheck is TRUE + and Node is in not a member of List. + +**/ +BOOLEAN +EFIAPI +InternalBaseLibIsListValid ( + IN CONST LIST_ENTRY *List + ) +{ + // + // Test the validity of List and Node + // + ASSERT (List != NULL); + ASSERT (List->ForwardLink != NULL); + ASSERT (List->BackLink != NULL); + + return TRUE; +} + +/** + Checks whether FirstEntry and SecondEntry are part of the same doubly-linked + list. + + If FirstEntry is NULL, then ASSERT(). + If FirstEntry->ForwardLink is NULL, then ASSERT(). + If FirstEntry->BackLink is NULL, then ASSERT(). + If SecondEntry is NULL, then ASSERT(); + If PcdMaximumLinkedListLength is not zero, and List contains more than + PcdMaximumLinkedListLength nodes, then ASSERT(). + + @param FirstEntry A pointer to a node in a linked list. + @param SecondEntry A pointer to the node to locate. + + @retval TRUE SecondEntry is in the same doubly-linked list as FirstEntry. + @retval FALSE SecondEntry isn't in the same doubly-linked list as FirstEntry, + or FirstEntry is invalid. + +**/ +BOOLEAN +EFIAPI +IsNodeInList ( + IN CONST LIST_ENTRY *FirstEntry, + IN CONST LIST_ENTRY *SecondEntry + ) +{ + CONST LIST_ENTRY *Ptr; + + // + // ASSERT List not too long + // + ASSERT (InternalBaseLibIsListValid (FirstEntry)); + + ASSERT (SecondEntry != NULL); + + Ptr = FirstEntry; + + // + // Check to see if SecondEntry is a member of FirstEntry. + // Exit early if the number of nodes in List >= PcdMaximumLinkedListLength + // + do { + Ptr = Ptr->ForwardLink; + if (Ptr == SecondEntry) { + return TRUE; + } + } while (Ptr != FirstEntry); + + return FALSE; +} + +/** + Initializes the head node of a doubly-linked list, and returns the pointer to + the head node of the doubly-linked list. + + Initializes the forward and backward links of a new linked list. After + initializing a linked list with this function, the other linked list + functions may be used to add and remove nodes from the linked list. It is up + to the caller of this function to allocate the memory for ListHead. + + If ListHead is NULL, then ASSERT(). + + @param ListHead A pointer to the head node of a new doubly-linked list. + + @return ListHead + +**/ +LIST_ENTRY * +EFIAPI +InitializeListHead ( + IN OUT LIST_ENTRY *ListHead + ) + +{ + ASSERT (ListHead != NULL); + + ListHead->ForwardLink = ListHead; + ListHead->BackLink = ListHead; + return ListHead; +} + +/** + Adds a node to the beginning of a doubly-linked list, and returns the pointer + to the head node of the doubly-linked list. + + Adds the node Entry at the beginning of the doubly-linked list denoted by + ListHead, and returns ListHead. + + If ListHead is NULL, then ASSERT(). + If Entry is NULL, then ASSERT(). + If ListHead was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or + InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLength is not zero, and prior to insertion the number + of nodes in ListHead, including the ListHead node, is greater than or + equal to PcdMaximumLinkedListLength, then ASSERT(). + + @param ListHead A pointer to the head node of a doubly-linked list. + @param Entry A pointer to a node that is to be inserted at the beginning + of a doubly-linked list. + + @return ListHead + +**/ +LIST_ENTRY * +EFIAPI +InsertHeadList ( + IN OUT LIST_ENTRY *ListHead, + IN OUT LIST_ENTRY *Entry + ) +{ + // + // ASSERT List not too long and Entry is not one of the nodes of List + // + ASSERT_VERIFY_NODE_IN_VALID_LIST (ListHead, Entry, FALSE); + + Entry->ForwardLink = ListHead->ForwardLink; + Entry->BackLink = ListHead; + Entry->ForwardLink->BackLink = Entry; + ListHead->ForwardLink = Entry; + return ListHead; +} + +/** + Adds a node to the end of a doubly-linked list, and returns the pointer to + the head node of the doubly-linked list. + + Adds the node Entry to the end of the doubly-linked list denoted by ListHead, + and returns ListHead. + + If ListHead is NULL, then ASSERT(). + If Entry is NULL, then ASSERT(). + If ListHead was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or + InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLength is not zero, and prior to insertion the number + of nodes in ListHead, including the ListHead node, is greater than or + equal to PcdMaximumLinkedListLength, then ASSERT(). + + @param ListHead A pointer to the head node of a doubly-linked list. + @param Entry A pointer to a node that is to be added at the end of the + doubly-linked list. + + @return ListHead + +**/ +LIST_ENTRY * +EFIAPI +InsertTailList ( + IN OUT LIST_ENTRY *ListHead, + IN OUT LIST_ENTRY *Entry + ) +{ + // + // ASSERT List not too long and Entry is not one of the nodes of List + // + ASSERT_VERIFY_NODE_IN_VALID_LIST (ListHead, Entry, FALSE); + + Entry->ForwardLink = ListHead; + Entry->BackLink = ListHead->BackLink; + Entry->BackLink->ForwardLink = Entry; + ListHead->BackLink = Entry; + return ListHead; +} + +/** + Retrieves the first node of a doubly-linked list. + + Returns the first node of a doubly-linked list. List must have been + initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(). + If List is empty, then List is returned. + + If List is NULL, then ASSERT(). + If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or + InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLength is not zero, and the number of nodes + in List, including the List node, is greater than or equal to + PcdMaximumLinkedListLength, then ASSERT(). + + @param List A pointer to the head node of a doubly-linked list. + + @return The first node of a doubly-linked list. + @retval List The list is empty. + +**/ +LIST_ENTRY * +EFIAPI +GetFirstNode ( + IN CONST LIST_ENTRY *List + ) +{ + // + // ASSERT List not too long + // + ASSERT (InternalBaseLibIsListValid (List)); + + return List->ForwardLink; +} + +/** + Retrieves the next node of a doubly-linked list. + + Returns the node of a doubly-linked list that follows Node. + List must have been initialized with INTIALIZE_LIST_HEAD_VARIABLE() + or InitializeListHead(). If List is empty, then List is returned. + + If List is NULL, then ASSERT(). + If Node is NULL, then ASSERT(). + If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or + InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLength is not zero, and List contains more than + PcdMaximumLinkedListLength nodes, then ASSERT(). + If PcdVerifyNodeInList is TRUE and Node is not a node in List, then ASSERT(). + + @param List A pointer to the head node of a doubly-linked list. + @param Node A pointer to a node in the doubly-linked list. + + @return A pointer to the next node if one exists. Otherwise List is returned. + +**/ +LIST_ENTRY * +EFIAPI +GetNextNode ( + IN CONST LIST_ENTRY *List, + IN CONST LIST_ENTRY *Node + ) +{ + // + // ASSERT List not too long and Node is one of the nodes of List + // + ASSERT_VERIFY_NODE_IN_VALID_LIST (List, Node, TRUE); + + return Node->ForwardLink; +} + +/** + Retrieves the previous node of a doubly-linked list. + + Returns the node of a doubly-linked list that precedes Node. + List must have been initialized with INTIALIZE_LIST_HEAD_VARIABLE() + or InitializeListHead(). If List is empty, then List is returned. + + If List is NULL, then ASSERT(). + If Node is NULL, then ASSERT(). + If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or + InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLength is not zero, and List contains more than + PcdMaximumLinkedListLength nodes, then ASSERT(). + If PcdVerifyNodeInList is TRUE and Node is not a node in List, then ASSERT(). + + @param List A pointer to the head node of a doubly-linked list. + @param Node A pointer to a node in the doubly-linked list. + + @return A pointer to the previous node if one exists. Otherwise List is returned. + +**/ +LIST_ENTRY * +EFIAPI +GetPreviousNode ( + IN CONST LIST_ENTRY *List, + IN CONST LIST_ENTRY *Node + ) +{ + // + // ASSERT List not too long and Node is one of the nodes of List + // + ASSERT_VERIFY_NODE_IN_VALID_LIST (List, Node, TRUE); + + return Node->BackLink; +} + +/** + Checks to see if a doubly-linked list is empty or not. + + Checks to see if the doubly-linked list is empty. If the linked list contains + zero nodes, this function returns TRUE. Otherwise, it returns FALSE. + + If ListHead is NULL, then ASSERT(). + If ListHead was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or + InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLength is not zero, and the number of nodes + in List, including the List node, is greater than or equal to + PcdMaximumLinkedListLength, then ASSERT(). + + @param ListHead A pointer to the head node of a doubly-linked list. + + @retval TRUE The linked list is empty. + @retval FALSE The linked list is not empty. + +**/ +BOOLEAN +EFIAPI +IsListEmpty ( + IN CONST LIST_ENTRY *ListHead + ) +{ + // + // ASSERT List not too long + // + ASSERT (InternalBaseLibIsListValid (ListHead)); + + return (BOOLEAN)(ListHead->ForwardLink == ListHead); +} + +/** + Determines if a node in a doubly-linked list is the head node of a the same + doubly-linked list. This function is typically used to terminate a loop that + traverses all the nodes in a doubly-linked list starting with the head node. + + Returns TRUE if Node is equal to List. Returns FALSE if Node is one of the + nodes in the doubly-linked list specified by List. List must have been + initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(). + + If List is NULL, then ASSERT(). + If Node is NULL, then ASSERT(). + If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(), + then ASSERT(). + If PcdMaximumLinkedListLength is not zero, and the number of nodes + in List, including the List node, is greater than or equal to + PcdMaximumLinkedListLength, then ASSERT(). + If PcdVerifyNodeInList is TRUE and Node is not a node in List and Node is not + equal to List, then ASSERT(). + + @param List A pointer to the head node of a doubly-linked list. + @param Node A pointer to a node in the doubly-linked list. + + @retval TRUE Node is the head of the doubly-linked list pointed by List. + @retval FALSE Node is not the head of the doubly-linked list pointed by List. + +**/ +BOOLEAN +EFIAPI +IsNull ( + IN CONST LIST_ENTRY *List, + IN CONST LIST_ENTRY *Node + ) +{ + // + // ASSERT List not too long and Node is one of the nodes of List + // + ASSERT_VERIFY_NODE_IN_VALID_LIST (List, Node, TRUE); + + return (BOOLEAN)(Node == List); +} + +/** + Determines if a node the last node in a doubly-linked list. + + Returns TRUE if Node is the last node in the doubly-linked list specified by + List. Otherwise, FALSE is returned. List must have been initialized with + INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(). + + If List is NULL, then ASSERT(). + If Node is NULL, then ASSERT(). + If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or + InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLength is not zero, and the number of nodes + in List, including the List node, is greater than or equal to + PcdMaximumLinkedListLength, then ASSERT(). + If PcdVerifyNodeInList is TRUE and Node is not a node in List, then ASSERT(). + + @param List A pointer to the head node of a doubly-linked list. + @param Node A pointer to a node in the doubly-linked list. + + @retval TRUE Node is the last node in the linked list. + @retval FALSE Node is not the last node in the linked list. + +**/ +BOOLEAN +EFIAPI +IsNodeAtEnd ( + IN CONST LIST_ENTRY *List, + IN CONST LIST_ENTRY *Node + ) +{ + // + // ASSERT List not too long and Node is one of the nodes of List + // + ASSERT_VERIFY_NODE_IN_VALID_LIST (List, Node, TRUE); + + return (BOOLEAN)(!IsNull (List, Node) && List->BackLink == Node); +} + +/** + Swaps the location of two nodes in a doubly-linked list, and returns the + first node after the swap. + + If FirstEntry is identical to SecondEntry, then SecondEntry is returned. + Otherwise, the location of the FirstEntry node is swapped with the location + of the SecondEntry node in a doubly-linked list. SecondEntry must be in the + same double linked list as FirstEntry and that double linked list must have + been initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(). + SecondEntry is returned after the nodes are swapped. + + If FirstEntry is NULL, then ASSERT(). + If SecondEntry is NULL, then ASSERT(). + If PcdVerifyNodeInList is TRUE and SecondEntry and FirstEntry are not in the + same linked list, then ASSERT(). + If PcdMaximumLinkedListLength is not zero, and the number of nodes in the + linked list containing the FirstEntry and SecondEntry nodes, including + the FirstEntry and SecondEntry nodes, is greater than or equal to + PcdMaximumLinkedListLength, then ASSERT(). + + @param FirstEntry A pointer to a node in a linked list. + @param SecondEntry A pointer to another node in the same linked list. + + @return SecondEntry. + +**/ +LIST_ENTRY * +EFIAPI +SwapListEntries ( + IN OUT LIST_ENTRY *FirstEntry, + IN OUT LIST_ENTRY *SecondEntry + ) +{ + LIST_ENTRY *Ptr; + + if (FirstEntry == SecondEntry) { + return SecondEntry; + } + + // + // ASSERT Entry1 and Entry2 are in the same linked list + // + ASSERT_VERIFY_NODE_IN_VALID_LIST (FirstEntry, SecondEntry, TRUE); + + // + // Ptr is the node pointed to by FirstEntry->ForwardLink + // + Ptr = RemoveEntryList (FirstEntry); + + // + // If FirstEntry immediately follows SecondEntry, FirstEntry will be placed + // immediately in front of SecondEntry + // + if (Ptr->BackLink == SecondEntry) { + return InsertTailList (SecondEntry, FirstEntry); + } + + // + // Ptr == SecondEntry means SecondEntry immediately follows FirstEntry, + // then there are no further steps necessary + // + if (Ptr == InsertHeadList (SecondEntry, FirstEntry)) { + return Ptr; + } + + // + // Move SecondEntry to the front of Ptr + // + RemoveEntryList (SecondEntry); + InsertTailList (Ptr, SecondEntry); + return SecondEntry; +} + +/** + Removes a node from a doubly-linked list, and returns the node that follows + the removed node. + + Removes the node Entry from a doubly-linked list. It is up to the caller of + this function to release the memory used by this node if that is required. On + exit, the node following Entry in the doubly-linked list is returned. If + Entry is the only node in the linked list, then the head node of the linked + list is returned. + + If Entry is NULL, then ASSERT(). + If Entry is the head node of an empty list, then ASSERT(). + If PcdMaximumLinkedListLength is not zero, and the number of nodes in the + linked list containing Entry, including the Entry node, is greater than + or equal to PcdMaximumLinkedListLength, then ASSERT(). + + @param Entry A pointer to a node in a linked list. + + @return Entry. + +**/ +LIST_ENTRY * +EFIAPI +RemoveEntryList ( + IN CONST LIST_ENTRY *Entry + ) +{ + ASSERT (!IsListEmpty (Entry)); + + Entry->ForwardLink->BackLink = Entry->BackLink; + Entry->BackLink->ForwardLink = Entry->ForwardLink; + return Entry->ForwardLink; +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/LongJump.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/LongJump.c new file mode 100644 index 0000000..fec7056 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/LongJump.c @@ -0,0 +1,46 @@ +/** @file + Long Jump functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include +#include +#include +#include +#include + +/** + Restores the CPU context that was saved with SetJump(). + + Restores the CPU context from the buffer specified by JumpBuffer. This + function never returns to the caller. Instead is resumes execution based on + the state of JumpBuffer. + + If JumpBuffer is NULL, then ASSERT(). + For Itanium processors, if JumpBuffer is not aligned on a 16-byte boundary, then ASSERT(). + If Value is 0, then ASSERT(). + + @param JumpBuffer A pointer to CPU context buffer. + @param Value The value to return when the SetJump() context is + restored and must be non-zero. + +**/ +VOID +EFIAPI +LongJump ( + IN BASE_LIBRARY_JUMP_BUFFER *JumpBuffer, + IN UINTN Value + ) +{ + jmp_buf local_buf; + jmp_buf *buf; + + buf = *(VOID **)JumpBuffer; + memcpy (&local_buf, buf, sizeof(jmp_buf)); + free (buf); + longjmp (local_buf, (int)Value); +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/LowBitSet32.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/LowBitSet32.c new file mode 100644 index 0000000..bb7f49d --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/LowBitSet32.c @@ -0,0 +1,40 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +/** + Returns the bit position of the lowest bit set in a 32-bit value. + + This function computes the bit position of the lowest bit set in the 32-bit + value specified by Operand. If Operand is zero, then -1 is returned. + Otherwise, a value between 0 and 31 is returned. + + @param Operand The 32-bit operand to evaluate. + + @retval 0..31 The lowest bit set in Operand was found. + @retval -1 Operand is zero. + +**/ +INTN +EFIAPI +LowBitSet32 ( + IN UINT32 Operand + ) +{ + INTN BitIndex; + + if (Operand == 0) { + return -1; + } + + for (BitIndex = 0; 0 == (Operand & 1); BitIndex++, Operand >>= 1); + return BitIndex; +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/LowBitSet64.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/LowBitSet64.c new file mode 100644 index 0000000..860670f --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/LowBitSet64.c @@ -0,0 +1,43 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +/** + Returns the bit position of the lowest bit set in a 64-bit value. + + This function computes the bit position of the lowest bit set in the 64-bit + value specified by Operand. If Operand is zero, then -1 is returned. + Otherwise, a value between 0 and 63 is returned. + + @param Operand The 64-bit operand to evaluate. + + @retval 0..63 The lowest bit set in Operand was found. + @retval -1 Operand is zero. + + +**/ +INTN +EFIAPI +LowBitSet64 ( + IN UINT64 Operand + ) +{ + INTN BitIndex; + + if (Operand == 0) { + return -1; + } + + for (BitIndex = 0; + (Operand & 1) == 0; + BitIndex++, Operand = RShiftU64 (Operand, 1)); + return BitIndex; +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/Math64.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/Math64.c new file mode 100644 index 0000000..7308dec --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/Math64.c @@ -0,0 +1,364 @@ +/** @file + Leaf math worker functions that require 64-bit arithmetic support from the + compiler. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +/** + Shifts a 64-bit integer left between 0 and 63 bits. The low bits + are filled with zeros. The shifted value is returned. + + This function shifts the 64-bit value Operand to the left by Count bits. The + low Count bits are set to zero. The shifted value is returned. + + @param Operand The 64-bit operand to shift left. + @param Count The number of bits to shift left. + + @return Operand << Count. + +**/ +UINT64 +EFIAPI +InternalMathLShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + return Operand << Count; +} + +/** + Shifts a 64-bit integer right between 0 and 63 bits. This high bits + are filled with zeros. The shifted value is returned. + + This function shifts the 64-bit value Operand to the right by Count bits. The + high Count bits are set to zero. The shifted value is returned. + + @param Operand The 64-bit operand to shift right. + @param Count The number of bits to shift right. + + @return Operand >> Count. + +**/ +UINT64 +EFIAPI +InternalMathRShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + return Operand >> Count; +} + +/** + Shifts a 64-bit integer right between 0 and 63 bits. The high bits + are filled with original integer's bit 63. The shifted value is returned. + + This function shifts the 64-bit value Operand to the right by Count bits. The + high Count bits are set to bit 63 of Operand. The shifted value is returned. + + @param Operand The 64-bit operand to shift right. + @param Count The number of bits to shift right. + + @return Operand arithmetically shifted right by Count. + +**/ +UINT64 +EFIAPI +InternalMathARShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + INTN TestValue; + + // + // Test if this compiler supports arithmetic shift + // + TestValue = (INTN)((INT64)(1ULL << 63) >> 63); + if (TestValue == -1) { + // + // Arithmetic shift is supported + // + return (UINT64)((INT64)Operand >> Count); + } + + // + // Arithmetic is not supported + // + return (Operand >> Count) | + ((INTN)Operand < 0 ? ~((UINTN)-1 >> Count) : 0); +} + + +/** + Rotates a 64-bit integer left between 0 and 63 bits, filling + the low bits with the high bits that were rotated. + + This function rotates the 64-bit value Operand to the left by Count bits. The + low Count bits are fill with the high Count bits of Operand. The rotated + value is returned. + + @param Operand The 64-bit operand to rotate left. + @param Count The number of bits to rotate left. + + @return Operand <<< Count. + +**/ +UINT64 +EFIAPI +InternalMathLRotU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + return (Operand << Count) | (Operand >> (64 - Count)); +} + +/** + Rotates a 64-bit integer right between 0 and 63 bits, filling + the high bits with the high low bits that were rotated. + + This function rotates the 64-bit value Operand to the right by Count bits. + The high Count bits are fill with the low Count bits of Operand. The rotated + value is returned. + + @param Operand The 64-bit operand to rotate right. + @param Count The number of bits to rotate right. + + @return Operand >>> Count. + +**/ +UINT64 +EFIAPI +InternalMathRRotU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + return (Operand >> Count) | (Operand << (64 - Count)); +} + +/** + Switches the endianess of a 64-bit integer. + + This function swaps the bytes in a 64-bit unsigned value to switch the value + from little endian to big endian or vice versa. The byte swapped value is + returned. + + @param Operand A 64-bit unsigned value. + + @return The byte swapped Operand. + +**/ +UINT64 +EFIAPI +InternalMathSwapBytes64 ( + IN UINT64 Operand + ) +{ + UINT64 LowerBytes; + UINT64 HigherBytes; + + LowerBytes = (UINT64) SwapBytes32 ((UINT32) Operand); + HigherBytes = (UINT64) SwapBytes32 ((UINT32) (Operand >> 32)); + + return (LowerBytes << 32 | HigherBytes); +} + +/** + Multiplies a 64-bit unsigned integer by a 32-bit unsigned integer + and generates a 64-bit unsigned result. + + This function multiplies the 64-bit unsigned value Multiplicand by the 32-bit + unsigned value Multiplier and generates a 64-bit unsigned result. This 64- + bit unsigned result is returned. + + @param Multiplicand A 64-bit unsigned value. + @param Multiplier A 32-bit unsigned value. + + @return Multiplicand * Multiplier + +**/ +UINT64 +EFIAPI +InternalMathMultU64x32 ( + IN UINT64 Multiplicand, + IN UINT32 Multiplier + ) +{ + return Multiplicand * Multiplier; +} + + +/** + Multiplies a 64-bit unsigned integer by a 64-bit unsigned integer + and generates a 64-bit unsigned result. + + This function multiplies the 64-bit unsigned value Multiplicand by the 64-bit + unsigned value Multiplier and generates a 64-bit unsigned result. This 64- + bit unsigned result is returned. + + @param Multiplicand A 64-bit unsigned value. + @param Multiplier A 64-bit unsigned value. + + @return Multiplicand * Multiplier. + +**/ +UINT64 +EFIAPI +InternalMathMultU64x64 ( + IN UINT64 Multiplicand, + IN UINT64 Multiplier + ) +{ + return Multiplicand * Multiplier; +} + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and + generates a 64-bit unsigned result. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 64-bit unsigned quotient. This + function returns the 64-bit unsigned quotient. + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + + @return Dividend / Divisor. + +**/ +UINT64 +EFIAPI +InternalMathDivU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor + ) +{ + return Dividend / Divisor; +} + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and + generates a 32-bit unsigned remainder. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 32-bit remainder. This function + returns the 32-bit unsigned remainder. + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + + @return Dividend % Divisor. + +**/ +UINT32 +EFIAPI +InternalMathModU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor + ) +{ + return (UINT32)(Dividend % Divisor); +} + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and + generates a 64-bit unsigned result and an optional 32-bit unsigned remainder. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 64-bit unsigned quotient. If Remainder + is not NULL, then the 32-bit unsigned remainder is returned in Remainder. + This function returns the 64-bit unsigned quotient. + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + @param Remainder A pointer to a 32-bit unsigned value. This parameter is + optional and may be NULL. + + @return Dividend / Divisor. + +**/ +UINT64 +EFIAPI +InternalMathDivRemU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor, + OUT UINT32 *Remainder OPTIONAL + ) +{ + if (Remainder != NULL) { + *Remainder = (UINT32)(Dividend % Divisor); + } + return Dividend / Divisor; +} + +/** + Divides a 64-bit unsigned integer by a 64-bit unsigned integer and + generates a 64-bit unsigned result and an optional 64-bit unsigned remainder. + + This function divides the 64-bit unsigned value Dividend by the 64-bit + unsigned value Divisor and generates a 64-bit unsigned quotient. If Remainder + is not NULL, then the 64-bit unsigned remainder is returned in Remainder. + This function returns the 64-bit unsigned quotient. + + @param Dividend A 64-bit unsigned value. + @param Divisor A 64-bit unsigned value. + @param Remainder A pointer to a 64-bit unsigned value. This parameter is + optional and may be NULL. + + @return Dividend / Divisor + +**/ +UINT64 +EFIAPI +InternalMathDivRemU64x64 ( + IN UINT64 Dividend, + IN UINT64 Divisor, + OUT UINT64 *Remainder OPTIONAL + ) +{ + if (Remainder != NULL) { + *Remainder = Dividend % Divisor; + } + return Dividend / Divisor; +} + +/** + Divides a 64-bit signed integer by a 64-bit signed integer and + generates a 64-bit signed result and an optional 64-bit signed remainder. + + This function divides the 64-bit signed value Dividend by the 64-bit + signed value Divisor and generates a 64-bit signed quotient. If Remainder + is not NULL, then the 64-bit signed remainder is returned in Remainder. + This function returns the 64-bit signed quotient. + + @param Dividend A 64-bit signed value. + @param Divisor A 64-bit signed value. + @param Remainder A pointer to a 64-bit signed value. This parameter is + optional and may be NULL. + + @return Dividend / Divisor. + +**/ +INT64 +EFIAPI +InternalMathDivRemS64x64 ( + IN INT64 Dividend, + IN INT64 Divisor, + OUT INT64 *Remainder OPTIONAL + ) +{ + if (Remainder != NULL) { + *Remainder = Dividend % Divisor; + } + return Dividend / Divisor; +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/ModU64x32.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/ModU64x32.c new file mode 100644 index 0000000..b64a1fc --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/ModU64x32.c @@ -0,0 +1,45 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +UINT32 +EFIAPI +InternalMathModU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor + ); + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and generates + a 32-bit unsigned remainder. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 32-bit remainder. This function + returns the 32-bit unsigned remainder. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + + @return Dividend % Divisor. + +**/ +UINT32 +EFIAPI +ModU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor + ) +{ + ASSERT (Divisor != 0); + return InternalMathModU64x32 (Dividend, Divisor); +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/MultS64x64.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/MultS64x64.c new file mode 100644 index 0000000..a64790f --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/MultS64x64.c @@ -0,0 +1,35 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +/** + Multiplies a 64-bit signed integer by a 64-bit signed integer and generates a + 64-bit signed result. + + This function multiplies the 64-bit signed value Multiplicand by the 64-bit + signed value Multiplier and generates a 64-bit signed result. This 64-bit + signed result is returned. + + @param Multiplicand A 64-bit signed value. + @param Multiplier A 64-bit signed value. + + @return Multiplicand * Multiplier. + +**/ +INT64 +EFIAPI +MultS64x64 ( + IN INT64 Multiplicand, + IN INT64 Multiplier + ) +{ + return (INT64)MultU64x64 ((UINT64) Multiplicand, (UINT64) Multiplier); +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/MultU64x32.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/MultU64x32.c new file mode 100644 index 0000000..ba56b3a --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/MultU64x32.c @@ -0,0 +1,46 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +UINT64 +EFIAPI +InternalMathMultU64x32 ( + IN UINT64 Multiplicand, + IN UINT32 Multiplier + ); + +/** + Multiplies a 64-bit unsigned integer by a 32-bit unsigned integer and + generates a 64-bit unsigned result. + + This function multiplies the 64-bit unsigned value Multiplicand by the 32-bit + unsigned value Multiplier and generates a 64-bit unsigned result. This 64- + bit unsigned result is returned. + + @param Multiplicand A 64-bit unsigned value. + @param Multiplier A 32-bit unsigned value. + + @return Multiplicand * Multiplier. + +**/ +UINT64 +EFIAPI +MultU64x32 ( + IN UINT64 Multiplicand, + IN UINT32 Multiplier + ) +{ + UINT64 Result; + + Result = InternalMathMultU64x32 (Multiplicand, Multiplier); + + return Result; +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/MultU64x64.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/MultU64x64.c new file mode 100644 index 0000000..0d30efe --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/MultU64x64.c @@ -0,0 +1,46 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +UINT64 +EFIAPI +InternalMathMultU64x64 ( + IN UINT64 Multiplicand, + IN UINT64 Multiplier + ); + +/** + Multiplies a 64-bit unsigned integer by a 64-bit unsigned integer and + generates a 64-bit unsigned result. + + This function multiplies the 64-bit unsigned value Multiplicand by the 64-bit + unsigned value Multiplier and generates a 64-bit unsigned result. This 64- + bit unsigned result is returned. + + @param Multiplicand A 64-bit unsigned value. + @param Multiplier A 64-bit unsigned value. + + @return Multiplicand * Multiplier. + +**/ +UINT64 +EFIAPI +MultU64x64 ( + IN UINT64 Multiplicand, + IN UINT64 Multiplier + ) +{ + UINT64 Result; + + Result = InternalMathMultU64x64 (Multiplicand, Multiplier); + + return Result; +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/RRotU32.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/RRotU32.c new file mode 100644 index 0000000..8dddf95 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/RRotU32.c @@ -0,0 +1,38 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +/** + Rotates a 32-bit integer right between 0 and 31 bits, filling the high bits + with the low bits that were rotated. + + This function rotates the 32-bit value Operand to the right by Count bits. + The high Count bits are fill with the low Count bits of Operand. The rotated + value is returned. + + If Count is greater than 31, then ASSERT(). + + @param Operand The 32-bit operand to rotate right. + @param Count The number of bits to rotate right. + + @return Operand >> Count. + +**/ +UINT32 +EFIAPI +RRotU32 ( + IN UINT32 Operand, + IN UINTN Count + ) +{ + ASSERT (Count < 32); + return (Operand >> Count) | (Operand << (32 - Count)); +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/RRotU64.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/RRotU64.c new file mode 100644 index 0000000..88fe762 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/RRotU64.c @@ -0,0 +1,45 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +UINT64 +EFIAPI +InternalMathRRotU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + +/** + Rotates a 64-bit integer right between 0 and 63 bits, filling the high bits + with the high low bits that were rotated. + + This function rotates the 64-bit value Operand to the right by Count bits. + The high Count bits are fill with the low Count bits of Operand. The rotated + value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to rotate right. + @param Count The number of bits to rotate right. + + @return Operand >> Count. + +**/ +UINT64 +EFIAPI +RRotU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + ASSERT (Count < 64); + return InternalMathRRotU64 (Operand, Count); +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/RShiftU64.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/RShiftU64.c new file mode 100644 index 0000000..0a081b3 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/RShiftU64.c @@ -0,0 +1,44 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +UINT64 +EFIAPI +InternalMathRShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + +/** + Shifts a 64-bit integer right between 0 and 63 bits. This high bits are + filled with zeros. The shifted value is returned. + + This function shifts the 64-bit value Operand to the right by Count bits. The + high Count bits are set to zero. The shifted value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to shift right. + @param Count The number of bits to shift right. + + @return Operand >> Count. + +**/ +UINT64 +EFIAPI +RShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + ASSERT (Count < 64); + return InternalMathRShiftU64 (Operand, Count); +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/SafeString.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/SafeString.c new file mode 100644 index 0000000..954cf2c --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/SafeString.c @@ -0,0 +1,3693 @@ +/** @file + Safe String functions. + + Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +#ifndef RSIZE_MAX +#define RSIZE_MAX (0x1000000) +#endif + +#ifndef ASCII_RSIZE_MAX +#define ASCII_RSIZE_MAX (0x1000000) +#endif + +#define SAFE_STRING_CONSTRAINT_CHECK(Expression, Status) \ + do { \ + ASSERT (Expression); \ + if (!(Expression)) { \ + return Status; \ + } \ + } while (FALSE) + +BOOLEAN +EFIAPI +InternalIsDecimalDigitCharacter ( + IN CHAR16 Char + ); +CHAR16 +EFIAPI +InternalCharToUpper ( + IN CHAR16 Char + ); +BOOLEAN +EFIAPI +InternalIsHexaDecimalDigitCharacter ( + IN CHAR16 Char + ); +UINTN +EFIAPI +InternalHexCharToUintn ( + IN CHAR16 Char + ); +BOOLEAN +EFIAPI +InternalAsciiIsDecimalDigitCharacter ( + IN CHAR8 Char + ); +CHAR8 +EFIAPI +InternalBaseLibAsciiToUpper ( + IN CHAR8 Chr + ); +BOOLEAN +EFIAPI +InternalAsciiIsHexaDecimalDigitCharacter ( + IN CHAR8 Char + ); +UINTN +EFIAPI +InternalAsciiHexCharToUintn ( + IN CHAR8 Char + ); + + +/** + Returns if 2 memory blocks are overlapped. + + @param Base1 Base address of 1st memory block. + @param Size1 Size of 1st memory block. + @param Base2 Base address of 2nd memory block. + @param Size2 Size of 2nd memory block. + + @retval TRUE 2 memory blocks are overlapped. + @retval FALSE 2 memory blocks are not overlapped. +**/ +BOOLEAN +InternalSafeStringIsOverlap ( + IN VOID *Base1, + IN UINTN Size1, + IN VOID *Base2, + IN UINTN Size2 + ) +{ + if ((((UINTN)Base1 >= (UINTN)Base2) && ((UINTN)Base1 < (UINTN)Base2 + Size2)) || + (((UINTN)Base2 >= (UINTN)Base1) && ((UINTN)Base2 < (UINTN)Base1 + Size1))) { + return TRUE; + } + return FALSE; +} + +/** + Returns if 2 Unicode strings are not overlapped. + + @param Str1 Start address of 1st Unicode string. + @param Size1 The number of char in 1st Unicode string, + including terminating null char. + @param Str2 Start address of 2nd Unicode string. + @param Size2 The number of char in 2nd Unicode string, + including terminating null char. + + @retval TRUE 2 Unicode strings are NOT overlapped. + @retval FALSE 2 Unicode strings are overlapped. +**/ +BOOLEAN +InternalSafeStringNoStrOverlap ( + IN CHAR16 *Str1, + IN UINTN Size1, + IN CHAR16 *Str2, + IN UINTN Size2 + ) +{ + return !InternalSafeStringIsOverlap (Str1, Size1 * sizeof(CHAR16), Str2, Size2 * sizeof(CHAR16)); +} + +/** + Returns if 2 Ascii strings are not overlapped. + + @param Str1 Start address of 1st Ascii string. + @param Size1 The number of char in 1st Ascii string, + including terminating null char. + @param Str2 Start address of 2nd Ascii string. + @param Size2 The number of char in 2nd Ascii string, + including terminating null char. + + @retval TRUE 2 Ascii strings are NOT overlapped. + @retval FALSE 2 Ascii strings are overlapped. +**/ +BOOLEAN +InternalSafeStringNoAsciiStrOverlap ( + IN CHAR8 *Str1, + IN UINTN Size1, + IN CHAR8 *Str2, + IN UINTN Size2 + ) +{ + return !InternalSafeStringIsOverlap (Str1, Size1, Str2, Size2); +} + +/** + Returns the length of a Null-terminated Unicode string. + + This function is similar as strlen_s defined in C11. + + If String is not aligned on a 16-bit boundary, then ASSERT(). + + @param String A pointer to a Null-terminated Unicode string. + @param MaxSize The maximum number of Destination Unicode + char, including terminating null char. + + @retval 0 If String is NULL. + @retval MaxSize If there is no null character in the first MaxSize characters of String. + @return The number of characters that percede the terminating null character. + +**/ +UINTN +EFIAPI +StrnLenS ( + IN CONST CHAR16 *String, + IN UINTN MaxSize + ) +{ + UINTN Length; + + ASSERT (((UINTN) String & BIT0) == 0); + + // + // If String is a null pointer or MaxSize is 0, then the StrnLenS function returns zero. + // + if ((String == NULL) || (MaxSize == 0)) { + return 0; + } + + // + // Otherwise, the StrnLenS function returns the number of characters that precede the + // terminating null character. If there is no null character in the first MaxSize characters of + // String then StrnLenS returns MaxSize. At most the first MaxSize characters of String shall + // be accessed by StrnLenS. + // + Length = 0; + while (String[Length] != 0) { + if (Length >= MaxSize - 1) { + return MaxSize; + } + Length++; + } + return Length; +} + +/** + Returns the size of a Null-terminated Unicode string in bytes, including the + Null terminator. + + This function returns the size of the Null-terminated Unicode string + specified by String in bytes, including the Null terminator. + + If String is not aligned on a 16-bit boundary, then ASSERT(). + + @param String A pointer to a Null-terminated Unicode string. + @param MaxSize The maximum number of Destination Unicode + char, including the Null terminator. + + @retval 0 If String is NULL. + @retval (sizeof (CHAR16) * (MaxSize + 1)) + If there is no Null terminator in the first MaxSize characters of + String. + @return The size of the Null-terminated Unicode string in bytes, including + the Null terminator. + +**/ +UINTN +EFIAPI +StrnSizeS ( + IN CONST CHAR16 *String, + IN UINTN MaxSize + ) +{ + // + // If String is a null pointer, then the StrnSizeS function returns zero. + // + if (String == NULL) { + return 0; + } + + // + // Otherwise, the StrnSizeS function returns the size of the Null-terminated + // Unicode string in bytes, including the Null terminator. If there is no + // Null terminator in the first MaxSize characters of String, then StrnSizeS + // returns (sizeof (CHAR16) * (MaxSize + 1)) to keep a consistent map with + // the StrnLenS function. + // + return (StrnLenS (String, MaxSize) + 1) * sizeof (*String); +} + +/** + Copies the string pointed to by Source (including the terminating null char) + to the array pointed to by Destination. + + This function is similar as strcpy_s defined in C11. + + If Destination is not aligned on a 16-bit boundary, then ASSERT(). + If Source is not aligned on a 16-bit boundary, then ASSERT(). + If an error would be returned, then the function will also ASSERT(). + + If an error is returned, then the Destination is unmodified. + + @param Destination A pointer to a Null-terminated Unicode string. + @param DestMax The maximum number of Destination Unicode + char, including terminating null char. + @param Source A pointer to a Null-terminated Unicode string. + + @retval RETURN_SUCCESS String is copied. + @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than StrLen(Source). + @retval RETURN_INVALID_PARAMETER If Destination is NULL. + If Source is NULL. + If PcdMaximumUnicodeStringLength is not zero, + and DestMax is greater than + PcdMaximumUnicodeStringLength. + If DestMax is 0. + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. +**/ +RETURN_STATUS +EFIAPI +StrCpyS ( + OUT CHAR16 *Destination, + IN UINTN DestMax, + IN CONST CHAR16 *Source + ) +{ + UINTN SourceLen; + + ASSERT (((UINTN) Destination & BIT0) == 0); + ASSERT (((UINTN) Source & BIT0) == 0); + + // + // 1. Neither Destination nor Source shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. DestMax shall not be greater than RSIZE_MAX. + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. DestMax shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER); + + // + // 4. DestMax shall be greater than StrnLenS(Source, DestMax). + // + SourceLen = StrnLenS (Source, DestMax); + SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL); + + // + // 5. Copying shall not take place between objects that overlap. + // + SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoStrOverlap (Destination, DestMax, (CHAR16 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED); + + // + // The StrCpyS function copies the string pointed to by Source (including the terminating + // null character) into the array pointed to by Destination. + // + while (*Source != 0) { + *(Destination++) = *(Source++); + } + *Destination = 0; + + return RETURN_SUCCESS; +} + +/** + Copies not more than Length successive char from the string pointed to by + Source to the array pointed to by Destination. If no null char is copied from + Source, then Destination[Length] is always set to null. + + This function is similar as strncpy_s defined in C11. + + If Length > 0 and Destination is not aligned on a 16-bit boundary, then ASSERT(). + If Length > 0 and Source is not aligned on a 16-bit boundary, then ASSERT(). + If an error would be returned, then the function will also ASSERT(). + + If an error is returned, then the Destination is unmodified. + + @param Destination A pointer to a Null-terminated Unicode string. + @param DestMax The maximum number of Destination Unicode + char, including terminating null char. + @param Source A pointer to a Null-terminated Unicode string. + @param Length The maximum number of Unicode characters to copy. + + @retval RETURN_SUCCESS String is copied. + @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than + MIN(StrLen(Source), Length). + @retval RETURN_INVALID_PARAMETER If Destination is NULL. + If Source is NULL. + If PcdMaximumUnicodeStringLength is not zero, + and DestMax is greater than + PcdMaximumUnicodeStringLength. + If DestMax is 0. + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. +**/ +RETURN_STATUS +EFIAPI +StrnCpyS ( + OUT CHAR16 *Destination, + IN UINTN DestMax, + IN CONST CHAR16 *Source, + IN UINTN Length + ) +{ + UINTN SourceLen; + + ASSERT (((UINTN) Destination & BIT0) == 0); + ASSERT (((UINTN) Source & BIT0) == 0); + + // + // 1. Neither Destination nor Source shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. Neither DestMax nor Length shall be greater than RSIZE_MAX + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. DestMax shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER); + + // + // 4. If Length is not less than DestMax, then DestMax shall be greater than StrnLenS(Source, DestMax). + // + SourceLen = StrnLenS (Source, MIN (DestMax, Length)); + if (Length >= DestMax) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL); + } + + // + // 5. Copying shall not take place between objects that overlap. + // + if (SourceLen > Length) { + SourceLen = Length; + } + SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoStrOverlap (Destination, DestMax, (CHAR16 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED); + + // + // The StrnCpyS function copies not more than Length successive characters (characters that + // follow a null character are not copied) from the array pointed to by Source to the array + // pointed to by Destination. If no null character was copied from Source, then Destination[Length] is set to a null + // character. + // + while ((SourceLen > 0) && (*Source != 0)) { + *(Destination++) = *(Source++); + SourceLen--; + } + *Destination = 0; + + return RETURN_SUCCESS; +} + +/** + Appends a copy of the string pointed to by Source (including the terminating + null char) to the end of the string pointed to by Destination. + + This function is similar as strcat_s defined in C11. + + If Destination is not aligned on a 16-bit boundary, then ASSERT(). + If Source is not aligned on a 16-bit boundary, then ASSERT(). + If an error would be returned, then the function will also ASSERT(). + + If an error is returned, then the Destination is unmodified. + + @param Destination A pointer to a Null-terminated Unicode string. + @param DestMax The maximum number of Destination Unicode + char, including terminating null char. + @param Source A pointer to a Null-terminated Unicode string. + + @retval RETURN_SUCCESS String is appended. + @retval RETURN_BAD_BUFFER_SIZE If DestMax is NOT greater than + StrLen(Destination). + @retval RETURN_BUFFER_TOO_SMALL If (DestMax - StrLen(Destination)) is NOT + greater than StrLen(Source). + @retval RETURN_INVALID_PARAMETER If Destination is NULL. + If Source is NULL. + If PcdMaximumUnicodeStringLength is not zero, + and DestMax is greater than + PcdMaximumUnicodeStringLength. + If DestMax is 0. + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. +**/ +RETURN_STATUS +EFIAPI +StrCatS ( + IN OUT CHAR16 *Destination, + IN UINTN DestMax, + IN CONST CHAR16 *Source + ) +{ + UINTN DestLen; + UINTN CopyLen; + UINTN SourceLen; + + ASSERT (((UINTN) Destination & BIT0) == 0); + ASSERT (((UINTN) Source & BIT0) == 0); + + // + // Let CopyLen denote the value DestMax - StrnLenS(Destination, DestMax) upon entry to StrCatS. + // + DestLen = StrnLenS (Destination, DestMax); + CopyLen = DestMax - DestLen; + + // + // 1. Neither Destination nor Source shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. DestMax shall not be greater than RSIZE_MAX. + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. DestMax shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER); + + // + // 4. CopyLen shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((CopyLen != 0), RETURN_BAD_BUFFER_SIZE); + + // + // 5. CopyLen shall be greater than StrnLenS(Source, CopyLen). + // + SourceLen = StrnLenS (Source, CopyLen); + SAFE_STRING_CONSTRAINT_CHECK ((CopyLen > SourceLen), RETURN_BUFFER_TOO_SMALL); + + // + // 6. Copying shall not take place between objects that overlap. + // + SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoStrOverlap (Destination, DestMax, (CHAR16 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED); + + // + // The StrCatS function appends a copy of the string pointed to by Source (including the + // terminating null character) to the end of the string pointed to by Destination. The initial character + // from Source overwrites the null character at the end of Destination. + // + Destination = Destination + DestLen; + while (*Source != 0) { + *(Destination++) = *(Source++); + } + *Destination = 0; + + return RETURN_SUCCESS; +} + +/** + Appends not more than Length successive char from the string pointed to by + Source to the end of the string pointed to by Destination. If no null char is + copied from Source, then Destination[StrLen(Destination) + Length] is always + set to null. + + This function is similar as strncat_s defined in C11. + + If Destination is not aligned on a 16-bit boundary, then ASSERT(). + If Source is not aligned on a 16-bit boundary, then ASSERT(). + If an error would be returned, then the function will also ASSERT(). + + If an error is returned, then the Destination is unmodified. + + @param Destination A pointer to a Null-terminated Unicode string. + @param DestMax The maximum number of Destination Unicode + char, including terminating null char. + @param Source A pointer to a Null-terminated Unicode string. + @param Length The maximum number of Unicode characters to copy. + + @retval RETURN_SUCCESS String is appended. + @retval RETURN_BAD_BUFFER_SIZE If DestMax is NOT greater than + StrLen(Destination). + @retval RETURN_BUFFER_TOO_SMALL If (DestMax - StrLen(Destination)) is NOT + greater than MIN(StrLen(Source), Length). + @retval RETURN_INVALID_PARAMETER If Destination is NULL. + If Source is NULL. + If PcdMaximumUnicodeStringLength is not zero, + and DestMax is greater than + PcdMaximumUnicodeStringLength. + If DestMax is 0. + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. +**/ +RETURN_STATUS +EFIAPI +StrnCatS ( + IN OUT CHAR16 *Destination, + IN UINTN DestMax, + IN CONST CHAR16 *Source, + IN UINTN Length + ) +{ + UINTN DestLen; + UINTN CopyLen; + UINTN SourceLen; + + ASSERT (((UINTN) Destination & BIT0) == 0); + ASSERT (((UINTN) Source & BIT0) == 0); + + // + // Let CopyLen denote the value DestMax - StrnLenS(Destination, DestMax) upon entry to StrnCatS. + // + DestLen = StrnLenS (Destination, DestMax); + CopyLen = DestMax - DestLen; + + // + // 1. Neither Destination nor Source shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. Neither DestMax nor Length shall be greater than RSIZE_MAX. + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. DestMax shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER); + + // + // 4. CopyLen shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((CopyLen != 0), RETURN_BAD_BUFFER_SIZE); + + // + // 5. If Length is not less than CopyLen, then CopyLen shall be greater than StrnLenS(Source, CopyLen). + // + SourceLen = StrnLenS (Source, MIN (CopyLen, Length)); + if (Length >= CopyLen) { + SAFE_STRING_CONSTRAINT_CHECK ((CopyLen > SourceLen), RETURN_BUFFER_TOO_SMALL); + } + + // + // 6. Copying shall not take place between objects that overlap. + // + if (SourceLen > Length) { + SourceLen = Length; + } + SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoStrOverlap (Destination, DestMax, (CHAR16 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED); + + // + // The StrnCatS function appends not more than Length successive characters (characters + // that follow a null character are not copied) from the array pointed to by Source to the end of + // the string pointed to by Destination. The initial character from Source overwrites the null character at + // the end of Destination. If no null character was copied from Source, then Destination[DestMax-CopyLen+Length] is set to + // a null character. + // + Destination = Destination + DestLen; + while ((SourceLen > 0) && (*Source != 0)) { + *(Destination++) = *(Source++); + SourceLen--; + } + *Destination = 0; + + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Unicode decimal string to a value of type UINTN. + + This function outputs a value of type UINTN by interpreting the contents of + the Unicode string specified by String as a decimal number. The format of the + input Unicode string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The function will + ignore the pad space, which includes spaces or tab characters, before + [decimal digits]. The running zero in the beginning of [decimal digits] will + be ignored. Then, the function stops at the first character that is a not a + valid decimal character or a Null-terminator, whichever one comes first. + + If String is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + If String has no valid decimal digits in the above format, then 0 is stored + at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINTN, then + MAX_UINTN is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + decimal digits right after the optional pad spaces, the value of String is + stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Unicode string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumUnicodeStringLength is not + zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINTN. + +**/ +RETURN_STATUS +EFIAPI +StrDecimalToUintnS ( + IN CONST CHAR16 *String, + OUT CHAR16 **EndPointer, OPTIONAL + OUT UINTN *Data + ) +{ + ASSERT (((UINTN) String & BIT0) == 0); + + // + // 1. Neither String nor Data shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. The length of String shall not be greater than RSIZE_MAX. + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + + // + // Ignore the pad spaces (space or tab) + // + while ((*String == L' ') || (*String == L'\t')) { + String++; + } + + // + // Ignore leading Zeros after the spaces + // + while (*String == L'0') { + String++; + } + + *Data = 0; + + while (InternalIsDecimalDigitCharacter (*String)) { + // + // If the number represented by String overflows according to the range + // defined by UINTN, then MAX_UINTN is stored in *Data and + // RETURN_UNSUPPORTED is returned. + // + if (*Data > ((MAX_UINTN - (*String - L'0')) / 10)) { + *Data = MAX_UINTN; + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + return RETURN_UNSUPPORTED; + } + + *Data = *Data * 10 + (*String - L'0'); + String++; + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Unicode decimal string to a value of type UINT64. + + This function outputs a value of type UINT64 by interpreting the contents of + the Unicode string specified by String as a decimal number. The format of the + input Unicode string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The function will + ignore the pad space, which includes spaces or tab characters, before + [decimal digits]. The running zero in the beginning of [decimal digits] will + be ignored. Then, the function stops at the first character that is a not a + valid decimal character or a Null-terminator, whichever one comes first. + + If String is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + If String has no valid decimal digits in the above format, then 0 is stored + at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINT64, then + MAX_UINT64 is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + decimal digits right after the optional pad spaces, the value of String is + stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Unicode string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumUnicodeStringLength is not + zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINT64. + +**/ +RETURN_STATUS +EFIAPI +StrDecimalToUint64S ( + IN CONST CHAR16 *String, + OUT CHAR16 **EndPointer, OPTIONAL + OUT UINT64 *Data + ) +{ + ASSERT (((UINTN) String & BIT0) == 0); + + // + // 1. Neither String nor Data shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. The length of String shall not be greater than RSIZE_MAX. + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + + // + // Ignore the pad spaces (space or tab) + // + while ((*String == L' ') || (*String == L'\t')) { + String++; + } + + // + // Ignore leading Zeros after the spaces + // + while (*String == L'0') { + String++; + } + + *Data = 0; + + while (InternalIsDecimalDigitCharacter (*String)) { + // + // If the number represented by String overflows according to the range + // defined by UINT64, then MAX_UINT64 is stored in *Data and + // RETURN_UNSUPPORTED is returned. + // + if (*Data > DivU64x32 (MAX_UINT64 - (*String - L'0'), 10)) { + *Data = MAX_UINT64; + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + return RETURN_UNSUPPORTED; + } + + *Data = MultU64x32 (*Data, 10) + (*String - L'0'); + String++; + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Unicode hexadecimal string to a value of type + UINTN. + + This function outputs a value of type UINTN by interpreting the contents of + the Unicode string specified by String as a hexadecimal number. The format of + the input Unicode string String is: + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. + If "x" appears in the input string, it must be prefixed with at least one 0. + The function will ignore the pad space, which includes spaces or tab + characters, before [zeros], [x] or [hexadecimal digit]. The running zero + before [x] or [hexadecimal digit] will be ignored. Then, the decoding starts + after [x] or the first valid hexadecimal digit. Then, the function stops at + the first character that is a not a valid hexadecimal character or NULL, + whichever one comes first. + + If String is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + If String has no valid hexadecimal digits in the above format, then 0 is + stored at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINTN, then + MAX_UINTN is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + hexadecimal digits right after the optional pad spaces, the value of String + is stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Unicode string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumUnicodeStringLength is not + zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINTN. + +**/ +RETURN_STATUS +EFIAPI +StrHexToUintnS ( + IN CONST CHAR16 *String, + OUT CHAR16 **EndPointer, OPTIONAL + OUT UINTN *Data + ) +{ + ASSERT (((UINTN) String & BIT0) == 0); + + // + // 1. Neither String nor Data shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. The length of String shall not be greater than RSIZE_MAX. + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + + // + // Ignore the pad spaces (space or tab) + // + while ((*String == L' ') || (*String == L'\t')) { + String++; + } + + // + // Ignore leading Zeros after the spaces + // + while (*String == L'0') { + String++; + } + + if (InternalCharToUpper (*String) == L'X') { + if (*(String - 1) != L'0') { + *Data = 0; + return RETURN_SUCCESS; + } + // + // Skip the 'X' + // + String++; + } + + *Data = 0; + + while (InternalIsHexaDecimalDigitCharacter (*String)) { + // + // If the number represented by String overflows according to the range + // defined by UINTN, then MAX_UINTN is stored in *Data and + // RETURN_UNSUPPORTED is returned. + // + if (*Data > ((MAX_UINTN - InternalHexCharToUintn (*String)) >> 4)) { + *Data = MAX_UINTN; + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + return RETURN_UNSUPPORTED; + } + + *Data = (*Data << 4) + InternalHexCharToUintn (*String); + String++; + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Unicode hexadecimal string to a value of type + UINT64. + + This function outputs a value of type UINT64 by interpreting the contents of + the Unicode string specified by String as a hexadecimal number. The format of + the input Unicode string String is: + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. + If "x" appears in the input string, it must be prefixed with at least one 0. + The function will ignore the pad space, which includes spaces or tab + characters, before [zeros], [x] or [hexadecimal digit]. The running zero + before [x] or [hexadecimal digit] will be ignored. Then, the decoding starts + after [x] or the first valid hexadecimal digit. Then, the function stops at + the first character that is a not a valid hexadecimal character or NULL, + whichever one comes first. + + If String is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + If String has no valid hexadecimal digits in the above format, then 0 is + stored at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINT64, then + MAX_UINT64 is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + hexadecimal digits right after the optional pad spaces, the value of String + is stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Unicode string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumUnicodeStringLength is not + zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINT64. + +**/ +RETURN_STATUS +EFIAPI +StrHexToUint64S ( + IN CONST CHAR16 *String, + OUT CHAR16 **EndPointer, OPTIONAL + OUT UINT64 *Data + ) +{ + ASSERT (((UINTN) String & BIT0) == 0); + + // + // 1. Neither String nor Data shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. The length of String shall not be greater than RSIZE_MAX. + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + + // + // Ignore the pad spaces (space or tab) + // + while ((*String == L' ') || (*String == L'\t')) { + String++; + } + + // + // Ignore leading Zeros after the spaces + // + while (*String == L'0') { + String++; + } + + if (InternalCharToUpper (*String) == L'X') { + if (*(String - 1) != L'0') { + *Data = 0; + return RETURN_SUCCESS; + } + // + // Skip the 'X' + // + String++; + } + + *Data = 0; + + while (InternalIsHexaDecimalDigitCharacter (*String)) { + // + // If the number represented by String overflows according to the range + // defined by UINT64, then MAX_UINT64 is stored in *Data and + // RETURN_UNSUPPORTED is returned. + // + if (*Data > RShiftU64 (MAX_UINT64 - InternalHexCharToUintn (*String), 4)) { + *Data = MAX_UINT64; + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + return RETURN_UNSUPPORTED; + } + + *Data = LShiftU64 (*Data, 4) + InternalHexCharToUintn (*String); + String++; + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Unicode string to IPv6 address and prefix length. + + This function outputs a value of type IPv6_ADDRESS and may output a value + of type UINT8 by interpreting the contents of the Unicode string specified + by String. The format of the input Unicode string String is as follows: + + X:X:X:X:X:X:X:X[/P] + + X contains one to four hexadecimal digit characters in the range [0-9], [a-f] and + [A-F]. X is converted to a value of type UINT16, whose low byte is stored in low + memory address and high byte is stored in high memory address. P contains decimal + digit characters in the range [0-9]. The running zero in the beginning of P will + be ignored. /P is optional. + + When /P is not in the String, the function stops at the first character that is + not a valid hexadecimal digit character after eight X's are converted. + + When /P is in the String, the function stops at the first character that is not + a valid decimal digit character after P is converted. + + "::" can be used to compress one or more groups of X when X contains only 0. + The "::" can only appear once in the String. + + If String is NULL, then ASSERT(). + + If Address is NULL, then ASSERT(). + + If String is not aligned in a 16-bit boundary, then ASSERT(). + + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + If EndPointer is not NULL and Address is translated from String, a pointer + to the character that stopped the scan is stored at the location pointed to + by EndPointer. + + @param String Pointer to a Null-terminated Unicode string. + @param EndPointer Pointer to character that stops scan. + @param Address Pointer to the converted IPv6 address. + @param PrefixLength Pointer to the converted IPv6 address prefix + length. MAX_UINT8 is returned when /P is + not in the String. + + @retval RETURN_SUCCESS Address is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + @retval RETURN_UNSUPPORTED If X contains more than four hexadecimal + digit characters. + If String contains "::" and number of X + is not less than 8. + If P starts with character that is not a + valid decimal digit character. + If the decimal number converted from P + exceeds 128. + +**/ +RETURN_STATUS +EFIAPI +StrToIpv6Address ( + IN CONST CHAR16 *String, + OUT CHAR16 **EndPointer, OPTIONAL + OUT IPv6_ADDRESS *Address, + OUT UINT8 *PrefixLength OPTIONAL + ) +{ + RETURN_STATUS Status; + UINTN AddressIndex; + UINTN Uintn; + IPv6_ADDRESS LocalAddress; + UINT8 LocalPrefixLength; + CONST CHAR16 *Pointer; + CHAR16 *End; + UINTN CompressStart; + BOOLEAN ExpectPrefix; + + LocalPrefixLength = MAX_UINT8; + CompressStart = ARRAY_SIZE (Address->Addr); + ExpectPrefix = FALSE; + + ASSERT (((UINTN) String & BIT0) == 0); + + // + // 1. None of String or Guid shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Address != NULL), RETURN_INVALID_PARAMETER); + + for (Pointer = String, AddressIndex = 0; AddressIndex < ARRAY_SIZE (Address->Addr) + 1;) { + if (!InternalIsHexaDecimalDigitCharacter (*Pointer)) { + if (*Pointer != L':') { + // + // ":" or "/" should be followed by digit characters. + // + return RETURN_UNSUPPORTED; + } + + // + // Meet second ":" after previous ":" or "/" + // or meet first ":" in the beginning of String. + // + if (ExpectPrefix) { + // + // ":" shall not be after "/" + // + return RETURN_UNSUPPORTED; + } + + if (CompressStart != ARRAY_SIZE (Address->Addr) || AddressIndex == ARRAY_SIZE (Address->Addr)) { + // + // "::" can only appear once. + // "::" can only appear when address is not full length. + // + return RETURN_UNSUPPORTED; + } else { + // + // Remember the start of zero compressing. + // + CompressStart = AddressIndex; + Pointer++; + + if (CompressStart == 0) { + if (*Pointer != L':') { + // + // Single ":" shall not be in the beginning of String. + // + return RETURN_UNSUPPORTED; + } + Pointer++; + } + } + } + + if (!InternalIsHexaDecimalDigitCharacter (*Pointer)) { + if (*Pointer == L'/') { + // + // Might be optional "/P" after "::". + // + if (CompressStart != AddressIndex) { + return RETURN_UNSUPPORTED; + } + } else { + break; + } + } else { + if (!ExpectPrefix) { + // + // Get X. + // + Status = StrHexToUintnS (Pointer, &End, &Uintn); + if (RETURN_ERROR (Status) || End - Pointer > 4) { + // + // Number of hexadecimal digit characters is no more than 4. + // + return RETURN_UNSUPPORTED; + } + Pointer = End; + // + // Uintn won't exceed MAX_UINT16 if number of hexadecimal digit characters is no more than 4. + // + ASSERT (AddressIndex + 1 < ARRAY_SIZE (Address->Addr)); + LocalAddress.Addr[AddressIndex] = (UINT8) ((UINT16) Uintn >> 8); + LocalAddress.Addr[AddressIndex + 1] = (UINT8) Uintn; + AddressIndex += 2; + } else { + // + // Get P, then exit the loop. + // + Status = StrDecimalToUintnS (Pointer, &End, &Uintn); + if (RETURN_ERROR (Status) || End == Pointer || Uintn > 128) { + // + // Prefix length should not exceed 128. + // + return RETURN_UNSUPPORTED; + } + LocalPrefixLength = (UINT8) Uintn; + Pointer = End; + break; + } + } + + // + // Skip ':' or "/" + // + if (*Pointer == L'/') { + ExpectPrefix = TRUE; + } else if (*Pointer == L':') { + if (AddressIndex == ARRAY_SIZE (Address->Addr)) { + // + // Meet additional ":" after all 8 16-bit address + // + break; + } + } else { + // + // Meet other character that is not "/" or ":" after all 8 16-bit address + // + break; + } + Pointer++; + } + + if ((AddressIndex == ARRAY_SIZE (Address->Addr) && CompressStart != ARRAY_SIZE (Address->Addr)) || + (AddressIndex != ARRAY_SIZE (Address->Addr) && CompressStart == ARRAY_SIZE (Address->Addr)) + ) { + // + // Full length of address shall not have compressing zeros. + // Non-full length of address shall have compressing zeros. + // + return RETURN_UNSUPPORTED; + } + CopyMem (&Address->Addr[0], &LocalAddress.Addr[0], CompressStart); + ZeroMem (&Address->Addr[CompressStart], ARRAY_SIZE (Address->Addr) - AddressIndex); + if (AddressIndex > CompressStart) { + CopyMem ( + &Address->Addr[CompressStart + ARRAY_SIZE (Address->Addr) - AddressIndex], + &LocalAddress.Addr[CompressStart], + AddressIndex - CompressStart + ); + } + + if (PrefixLength != NULL) { + *PrefixLength = LocalPrefixLength; + } + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) Pointer; + } + + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Unicode string to IPv4 address and prefix length. + + This function outputs a value of type IPv4_ADDRESS and may output a value + of type UINT8 by interpreting the contents of the Unicode string specified + by String. The format of the input Unicode string String is as follows: + + D.D.D.D[/P] + + D and P are decimal digit characters in the range [0-9]. The running zero in + the beginning of D and P will be ignored. /P is optional. + + When /P is not in the String, the function stops at the first character that is + not a valid decimal digit character after four D's are converted. + + When /P is in the String, the function stops at the first character that is not + a valid decimal digit character after P is converted. + + If String is NULL, then ASSERT(). + + If Address is NULL, then ASSERT(). + + If String is not aligned in a 16-bit boundary, then ASSERT(). + + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + If EndPointer is not NULL and Address is translated from String, a pointer + to the character that stopped the scan is stored at the location pointed to + by EndPointer. + + @param String Pointer to a Null-terminated Unicode string. + @param EndPointer Pointer to character that stops scan. + @param Address Pointer to the converted IPv4 address. + @param PrefixLength Pointer to the converted IPv4 address prefix + length. MAX_UINT8 is returned when /P is + not in the String. + + @retval RETURN_SUCCESS Address is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + @retval RETURN_UNSUPPORTED If String is not in the correct format. + If any decimal number converted from D + exceeds 255. + If the decimal number converted from P + exceeds 32. + +**/ +RETURN_STATUS +EFIAPI +StrToIpv4Address ( + IN CONST CHAR16 *String, + OUT CHAR16 **EndPointer, OPTIONAL + OUT IPv4_ADDRESS *Address, + OUT UINT8 *PrefixLength OPTIONAL + ) +{ + RETURN_STATUS Status; + UINTN AddressIndex; + UINTN Uintn; + IPv4_ADDRESS LocalAddress; + UINT8 LocalPrefixLength; + CHAR16 *Pointer; + + LocalPrefixLength = MAX_UINT8; + + ASSERT (((UINTN) String & BIT0) == 0); + + // + // 1. None of String or Guid shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Address != NULL), RETURN_INVALID_PARAMETER); + + for (Pointer = (CHAR16 *) String, AddressIndex = 0; AddressIndex < ARRAY_SIZE (Address->Addr) + 1;) { + if (!InternalIsDecimalDigitCharacter (*Pointer)) { + // + // D or P contains invalid characters. + // + break; + } + + // + // Get D or P. + // + Status = StrDecimalToUintnS ((CONST CHAR16 *) Pointer, &Pointer, &Uintn); + if (RETURN_ERROR (Status)) { + return RETURN_UNSUPPORTED; + } + if (AddressIndex == ARRAY_SIZE (Address->Addr)) { + // + // It's P. + // + if (Uintn > 32) { + return RETURN_UNSUPPORTED; + } + LocalPrefixLength = (UINT8) Uintn; + } else { + // + // It's D. + // + if (Uintn > MAX_UINT8) { + return RETURN_UNSUPPORTED; + } + LocalAddress.Addr[AddressIndex] = (UINT8) Uintn; + AddressIndex++; + } + + // + // Check the '.' or '/', depending on the AddressIndex. + // + if (AddressIndex == ARRAY_SIZE (Address->Addr)) { + if (*Pointer == L'/') { + // + // '/P' is in the String. + // Skip "/" and get P in next loop. + // + Pointer++; + } else { + // + // '/P' is not in the String. + // + break; + } + } else if (AddressIndex < ARRAY_SIZE (Address->Addr)) { + if (*Pointer == L'.') { + // + // D should be followed by '.' + // + Pointer++; + } else { + return RETURN_UNSUPPORTED; + } + } + } + + if (AddressIndex < ARRAY_SIZE (Address->Addr)) { + return RETURN_UNSUPPORTED; + } + + CopyMem (Address, &LocalAddress, sizeof (*Address)); + if (PrefixLength != NULL) { + *PrefixLength = LocalPrefixLength; + } + if (EndPointer != NULL) { + *EndPointer = Pointer; + } + + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Unicode GUID string to a value of type + EFI_GUID. + + This function outputs a GUID value by interpreting the contents of + the Unicode string specified by String. The format of the input + Unicode string String consists of 36 characters, as follows: + + aabbccdd-eeff-gghh-iijj-kkllmmnnoopp + + The pairs aa - pp are two characters in the range [0-9], [a-f] and + [A-F], with each pair representing a single byte hexadecimal value. + + The mapping between String and the EFI_GUID structure is as follows: + aa Data1[24:31] + bb Data1[16:23] + cc Data1[8:15] + dd Data1[0:7] + ee Data2[8:15] + ff Data2[0:7] + gg Data3[8:15] + hh Data3[0:7] + ii Data4[0:7] + jj Data4[8:15] + kk Data4[16:23] + ll Data4[24:31] + mm Data4[32:39] + nn Data4[40:47] + oo Data4[48:55] + pp Data4[56:63] + + If String is NULL, then ASSERT(). + If Guid is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + + @param String Pointer to a Null-terminated Unicode string. + @param Guid Pointer to the converted GUID. + + @retval RETURN_SUCCESS Guid is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + @retval RETURN_UNSUPPORTED If String is not as the above format. + +**/ +RETURN_STATUS +EFIAPI +StrToGuid ( + IN CONST CHAR16 *String, + OUT GUID *Guid + ) +{ + RETURN_STATUS Status; + GUID LocalGuid; + + ASSERT (((UINTN) String & BIT0) == 0); + + // + // 1. None of String or Guid shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Guid != NULL), RETURN_INVALID_PARAMETER); + + // + // Get aabbccdd in big-endian. + // + Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data1), (UINT8 *) &LocalGuid.Data1, sizeof (LocalGuid.Data1)); + if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data1)] != L'-') { + return RETURN_UNSUPPORTED; + } + // + // Convert big-endian to little-endian. + // + LocalGuid.Data1 = SwapBytes32 (LocalGuid.Data1); + String += 2 * sizeof (LocalGuid.Data1) + 1; + + // + // Get eeff in big-endian. + // + Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data2), (UINT8 *) &LocalGuid.Data2, sizeof (LocalGuid.Data2)); + if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data2)] != L'-') { + return RETURN_UNSUPPORTED; + } + // + // Convert big-endian to little-endian. + // + LocalGuid.Data2 = SwapBytes16 (LocalGuid.Data2); + String += 2 * sizeof (LocalGuid.Data2) + 1; + + // + // Get gghh in big-endian. + // + Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data3), (UINT8 *) &LocalGuid.Data3, sizeof (LocalGuid.Data3)); + if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data3)] != L'-') { + return RETURN_UNSUPPORTED; + } + // + // Convert big-endian to little-endian. + // + LocalGuid.Data3 = SwapBytes16 (LocalGuid.Data3); + String += 2 * sizeof (LocalGuid.Data3) + 1; + + // + // Get iijj. + // + Status = StrHexToBytes (String, 2 * 2, &LocalGuid.Data4[0], 2); + if (RETURN_ERROR (Status) || String[2 * 2] != L'-') { + return RETURN_UNSUPPORTED; + } + String += 2 * 2 + 1; + + // + // Get kkllmmnnoopp. + // + Status = StrHexToBytes (String, 2 * 6, &LocalGuid.Data4[2], 6); + if (RETURN_ERROR (Status)) { + return RETURN_UNSUPPORTED; + } + + CopyGuid (Guid, &LocalGuid); + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Unicode hexadecimal string to a byte array. + + This function outputs a byte array by interpreting the contents of + the Unicode string specified by String in hexadecimal format. The format of + the input Unicode string String is: + + [XX]* + + X is a hexadecimal digit character in the range [0-9], [a-f] and [A-F]. + The function decodes every two hexadecimal digit characters as one byte. The + decoding stops after Length of characters and outputs Buffer containing + (Length / 2) bytes. + + If String is not aligned in a 16-bit boundary, then ASSERT(). + + If String is NULL, then ASSERT(). + + If Buffer is NULL, then ASSERT(). + + If Length is not multiple of 2, then ASSERT(). + + If PcdMaximumUnicodeStringLength is not zero and Length is greater than + PcdMaximumUnicodeStringLength, then ASSERT(). + + If MaxBufferSize is less than (Length / 2), then ASSERT(). + + @param String Pointer to a Null-terminated Unicode string. + @param Length The number of Unicode characters to decode. + @param Buffer Pointer to the converted bytes array. + @param MaxBufferSize The maximum size of Buffer. + + @retval RETURN_SUCCESS Buffer is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If Length is not multiple of 2. + If PcdMaximumUnicodeStringLength is not zero, + and Length is greater than + PcdMaximumUnicodeStringLength. + @retval RETURN_UNSUPPORTED If Length of characters from String contain + a character that is not valid hexadecimal + digit characters, or a Null-terminator. + @retval RETURN_BUFFER_TOO_SMALL If MaxBufferSize is less than (Length / 2). +**/ +RETURN_STATUS +EFIAPI +StrHexToBytes ( + IN CONST CHAR16 *String, + IN UINTN Length, + OUT UINT8 *Buffer, + IN UINTN MaxBufferSize + ) +{ + UINTN Index; + + ASSERT (((UINTN) String & BIT0) == 0); + + // + // 1. None of String or Buffer shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Buffer != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. Length shall not be greater than RSIZE_MAX. + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. Length shall not be odd. + // + SAFE_STRING_CONSTRAINT_CHECK (((Length & BIT0) == 0), RETURN_INVALID_PARAMETER); + + // + // 4. MaxBufferSize shall equal to or greater than Length / 2. + // + SAFE_STRING_CONSTRAINT_CHECK ((MaxBufferSize >= Length / 2), RETURN_BUFFER_TOO_SMALL); + + // + // 5. String shall not contains invalid hexadecimal digits. + // + for (Index = 0; Index < Length; Index++) { + if (!InternalIsHexaDecimalDigitCharacter (String[Index])) { + break; + } + } + if (Index != Length) { + return RETURN_UNSUPPORTED; + } + + // + // Convert the hex string to bytes. + // + for(Index = 0; Index < Length; Index++) { + + // + // For even characters, write the upper nibble for each buffer byte, + // and for even characters, the lower nibble. + // + if ((Index & BIT0) == 0) { + Buffer[Index / 2] = (UINT8) InternalHexCharToUintn (String[Index]) << 4; + } else { + Buffer[Index / 2] |= (UINT8) InternalHexCharToUintn (String[Index]); + } + } + return RETURN_SUCCESS; +} + +/** + Returns the length of a Null-terminated Ascii string. + + This function is similar as strlen_s defined in C11. + + @param String A pointer to a Null-terminated Ascii string. + @param MaxSize The maximum number of Destination Ascii + char, including terminating null char. + + @retval 0 If String is NULL. + @retval MaxSize If there is no null character in the first MaxSize characters of String. + @return The number of characters that percede the terminating null character. + +**/ +UINTN +EFIAPI +AsciiStrnLenS ( + IN CONST CHAR8 *String, + IN UINTN MaxSize + ) +{ + UINTN Length; + + // + // If String is a null pointer or MaxSize is 0, then the AsciiStrnLenS function returns zero. + // + if ((String == NULL) || (MaxSize == 0)) { + return 0; + } + + // + // Otherwise, the AsciiStrnLenS function returns the number of characters that precede the + // terminating null character. If there is no null character in the first MaxSize characters of + // String then AsciiStrnLenS returns MaxSize. At most the first MaxSize characters of String shall + // be accessed by AsciiStrnLenS. + // + Length = 0; + while (String[Length] != 0) { + if (Length >= MaxSize - 1) { + return MaxSize; + } + Length++; + } + return Length; +} + +/** + Returns the size of a Null-terminated Ascii string in bytes, including the + Null terminator. + + This function returns the size of the Null-terminated Ascii string specified + by String in bytes, including the Null terminator. + + @param String A pointer to a Null-terminated Ascii string. + @param MaxSize The maximum number of Destination Ascii + char, including the Null terminator. + + @retval 0 If String is NULL. + @retval (sizeof (CHAR8) * (MaxSize + 1)) + If there is no Null terminator in the first MaxSize characters of + String. + @return The size of the Null-terminated Ascii string in bytes, including the + Null terminator. + +**/ +UINTN +EFIAPI +AsciiStrnSizeS ( + IN CONST CHAR8 *String, + IN UINTN MaxSize + ) +{ + // + // If String is a null pointer, then the AsciiStrnSizeS function returns + // zero. + // + if (String == NULL) { + return 0; + } + + // + // Otherwise, the AsciiStrnSizeS function returns the size of the + // Null-terminated Ascii string in bytes, including the Null terminator. If + // there is no Null terminator in the first MaxSize characters of String, + // then AsciiStrnSizeS returns (sizeof (CHAR8) * (MaxSize + 1)) to keep a + // consistent map with the AsciiStrnLenS function. + // + return (AsciiStrnLenS (String, MaxSize) + 1) * sizeof (*String); +} + +/** + Copies the string pointed to by Source (including the terminating null char) + to the array pointed to by Destination. + + This function is similar as strcpy_s defined in C11. + + If an error would be returned, then the function will also ASSERT(). + + If an error is returned, then the Destination is unmodified. + + @param Destination A pointer to a Null-terminated Ascii string. + @param DestMax The maximum number of Destination Ascii + char, including terminating null char. + @param Source A pointer to a Null-terminated Ascii string. + + @retval RETURN_SUCCESS String is copied. + @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than StrLen(Source). + @retval RETURN_INVALID_PARAMETER If Destination is NULL. + If Source is NULL. + If PcdMaximumAsciiStringLength is not zero, + and DestMax is greater than + PcdMaximumAsciiStringLength. + If DestMax is 0. + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. +**/ +RETURN_STATUS +EFIAPI +AsciiStrCpyS ( + OUT CHAR8 *Destination, + IN UINTN DestMax, + IN CONST CHAR8 *Source + ) +{ + UINTN SourceLen; + + // + // 1. Neither Destination nor Source shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. DestMax shall not be greater than ASCII_RSIZE_MAX. + // + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. DestMax shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER); + + // + // 4. DestMax shall be greater than AsciiStrnLenS(Source, DestMax). + // + SourceLen = AsciiStrnLenS (Source, DestMax); + SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL); + + // + // 5. Copying shall not take place between objects that overlap. + // + SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoAsciiStrOverlap (Destination, DestMax, (CHAR8 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED); + + // + // The AsciiStrCpyS function copies the string pointed to by Source (including the terminating + // null character) into the array pointed to by Destination. + // + while (*Source != 0) { + *(Destination++) = *(Source++); + } + *Destination = 0; + + return RETURN_SUCCESS; +} + +/** + Copies not more than Length successive char from the string pointed to by + Source to the array pointed to by Destination. If no null char is copied from + Source, then Destination[Length] is always set to null. + + This function is similar as strncpy_s defined in C11. + + If an error would be returned, then the function will also ASSERT(). + + If an error is returned, then the Destination is unmodified. + + @param Destination A pointer to a Null-terminated Ascii string. + @param DestMax The maximum number of Destination Ascii + char, including terminating null char. + @param Source A pointer to a Null-terminated Ascii string. + @param Length The maximum number of Ascii characters to copy. + + @retval RETURN_SUCCESS String is copied. + @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than + MIN(StrLen(Source), Length). + @retval RETURN_INVALID_PARAMETER If Destination is NULL. + If Source is NULL. + If PcdMaximumAsciiStringLength is not zero, + and DestMax is greater than + PcdMaximumAsciiStringLength. + If DestMax is 0. + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. +**/ +RETURN_STATUS +EFIAPI +AsciiStrnCpyS ( + OUT CHAR8 *Destination, + IN UINTN DestMax, + IN CONST CHAR8 *Source, + IN UINTN Length + ) +{ + UINTN SourceLen; + + // + // 1. Neither Destination nor Source shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. Neither DestMax nor Length shall be greater than ASCII_RSIZE_MAX + // + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Length <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. DestMax shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER); + + // + // 4. If Length is not less than DestMax, then DestMax shall be greater than AsciiStrnLenS(Source, DestMax). + // + SourceLen = AsciiStrnLenS (Source, MIN (DestMax, Length)); + if (Length >= DestMax) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL); + } + + // + // 5. Copying shall not take place between objects that overlap. + // + if (SourceLen > Length) { + SourceLen = Length; + } + SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoAsciiStrOverlap (Destination, DestMax, (CHAR8 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED); + + // + // The AsciiStrnCpyS function copies not more than Length successive characters (characters that + // follow a null character are not copied) from the array pointed to by Source to the array + // pointed to by Destination. If no null character was copied from Source, then Destination[Length] is set to a null + // character. + // + while ((SourceLen > 0) && (*Source != 0)) { + *(Destination++) = *(Source++); + SourceLen--; + } + *Destination = 0; + + return RETURN_SUCCESS; +} + +/** + Appends a copy of the string pointed to by Source (including the terminating + null char) to the end of the string pointed to by Destination. + + This function is similar as strcat_s defined in C11. + + If an error would be returned, then the function will also ASSERT(). + + If an error is returned, then the Destination is unmodified. + + @param Destination A pointer to a Null-terminated Ascii string. + @param DestMax The maximum number of Destination Ascii + char, including terminating null char. + @param Source A pointer to a Null-terminated Ascii string. + + @retval RETURN_SUCCESS String is appended. + @retval RETURN_BAD_BUFFER_SIZE If DestMax is NOT greater than + StrLen(Destination). + @retval RETURN_BUFFER_TOO_SMALL If (DestMax - StrLen(Destination)) is NOT + greater than StrLen(Source). + @retval RETURN_INVALID_PARAMETER If Destination is NULL. + If Source is NULL. + If PcdMaximumAsciiStringLength is not zero, + and DestMax is greater than + PcdMaximumAsciiStringLength. + If DestMax is 0. + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. +**/ +RETURN_STATUS +EFIAPI +AsciiStrCatS ( + IN OUT CHAR8 *Destination, + IN UINTN DestMax, + IN CONST CHAR8 *Source + ) +{ + UINTN DestLen; + UINTN CopyLen; + UINTN SourceLen; + + // + // Let CopyLen denote the value DestMax - AsciiStrnLenS(Destination, DestMax) upon entry to AsciiStrCatS. + // + DestLen = AsciiStrnLenS (Destination, DestMax); + CopyLen = DestMax - DestLen; + + // + // 1. Neither Destination nor Source shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. DestMax shall not be greater than ASCII_RSIZE_MAX. + // + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. DestMax shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER); + + // + // 4. CopyLen shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((CopyLen != 0), RETURN_BAD_BUFFER_SIZE); + + // + // 5. CopyLen shall be greater than AsciiStrnLenS(Source, CopyLen). + // + SourceLen = AsciiStrnLenS (Source, CopyLen); + SAFE_STRING_CONSTRAINT_CHECK ((CopyLen > SourceLen), RETURN_BUFFER_TOO_SMALL); + + // + // 6. Copying shall not take place between objects that overlap. + // + SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoAsciiStrOverlap (Destination, DestMax, (CHAR8 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED); + + // + // The AsciiStrCatS function appends a copy of the string pointed to by Source (including the + // terminating null character) to the end of the string pointed to by Destination. The initial character + // from Source overwrites the null character at the end of Destination. + // + Destination = Destination + DestLen; + while (*Source != 0) { + *(Destination++) = *(Source++); + } + *Destination = 0; + + return RETURN_SUCCESS; +} + +/** + Appends not more than Length successive char from the string pointed to by + Source to the end of the string pointed to by Destination. If no null char is + copied from Source, then Destination[StrLen(Destination) + Length] is always + set to null. + + This function is similar as strncat_s defined in C11. + + If an error would be returned, then the function will also ASSERT(). + + If an error is returned, then the Destination is unmodified. + + @param Destination A pointer to a Null-terminated Ascii string. + @param DestMax The maximum number of Destination Ascii + char, including terminating null char. + @param Source A pointer to a Null-terminated Ascii string. + @param Length The maximum number of Ascii characters to copy. + + @retval RETURN_SUCCESS String is appended. + @retval RETURN_BAD_BUFFER_SIZE If DestMax is NOT greater than + StrLen(Destination). + @retval RETURN_BUFFER_TOO_SMALL If (DestMax - StrLen(Destination)) is NOT + greater than MIN(StrLen(Source), Length). + @retval RETURN_INVALID_PARAMETER If Destination is NULL. + If Source is NULL. + If PcdMaximumAsciiStringLength is not zero, + and DestMax is greater than + PcdMaximumAsciiStringLength. + If DestMax is 0. + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. +**/ +RETURN_STATUS +EFIAPI +AsciiStrnCatS ( + IN OUT CHAR8 *Destination, + IN UINTN DestMax, + IN CONST CHAR8 *Source, + IN UINTN Length + ) +{ + UINTN DestLen; + UINTN CopyLen; + UINTN SourceLen; + + // + // Let CopyLen denote the value DestMax - AsciiStrnLenS(Destination, DestMax) upon entry to AsciiStrnCatS. + // + DestLen = AsciiStrnLenS (Destination, DestMax); + CopyLen = DestMax - DestLen; + + // + // 1. Neither Destination nor Source shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. Neither DestMax nor Length shall be greater than ASCII_RSIZE_MAX. + // + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Length <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. DestMax shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER); + + // + // 4. CopyLen shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((CopyLen != 0), RETURN_BAD_BUFFER_SIZE); + + // + // 5. If Length is not less than CopyLen, then CopyLen shall be greater than AsciiStrnLenS(Source, CopyLen). + // + SourceLen = AsciiStrnLenS (Source, MIN (CopyLen, Length)); + if (Length >= CopyLen) { + SAFE_STRING_CONSTRAINT_CHECK ((CopyLen > SourceLen), RETURN_BUFFER_TOO_SMALL); + } + + // + // 6. Copying shall not take place between objects that overlap. + // + if (SourceLen > Length) { + SourceLen = Length; + } + SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoAsciiStrOverlap (Destination, DestMax, (CHAR8 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED); + + // + // The AsciiStrnCatS function appends not more than Length successive characters (characters + // that follow a null character are not copied) from the array pointed to by Source to the end of + // the string pointed to by Destination. The initial character from Source overwrites the null character at + // the end of Destination. If no null character was copied from Source, then Destination[DestMax-CopyLen+Length] is set to + // a null character. + // + Destination = Destination + DestLen; + while ((SourceLen > 0) && (*Source != 0)) { + *(Destination++) = *(Source++); + SourceLen--; + } + *Destination = 0; + + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Ascii decimal string to a value of type UINTN. + + This function outputs a value of type UINTN by interpreting the contents of + the Ascii string specified by String as a decimal number. The format of the + input Ascii string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The function will + ignore the pad space, which includes spaces or tab characters, before + [decimal digits]. The running zero in the beginning of [decimal digits] will + be ignored. Then, the function stops at the first character that is a not a + valid decimal character or a Null-terminator, whichever one comes first. + + If String is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and String contains more than + PcdMaximumAsciiStringLength Ascii characters, not including the + Null-terminator, then ASSERT(). + + If String has no valid decimal digits in the above format, then 0 is stored + at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINTN, then + MAX_UINTN is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + decimal digits right after the optional pad spaces, the value of String is + stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Ascii string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumAsciiStringLength is not zero, + and String contains more than + PcdMaximumAsciiStringLength Ascii + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINTN. + +**/ +RETURN_STATUS +EFIAPI +AsciiStrDecimalToUintnS ( + IN CONST CHAR8 *String, + OUT CHAR8 **EndPointer, OPTIONAL + OUT UINTN *Data + ) +{ + // + // 1. Neither String nor Data shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. The length of String shall not be greater than ASCII_RSIZE_MAX. + // + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((AsciiStrnLenS (String, ASCII_RSIZE_MAX + 1) <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + + // + // Ignore the pad spaces (space or tab) + // + while ((*String == ' ') || (*String == '\t')) { + String++; + } + + // + // Ignore leading Zeros after the spaces + // + while (*String == '0') { + String++; + } + + *Data = 0; + + while (InternalAsciiIsDecimalDigitCharacter (*String)) { + // + // If the number represented by String overflows according to the range + // defined by UINTN, then MAX_UINTN is stored in *Data and + // RETURN_UNSUPPORTED is returned. + // + if (*Data > ((MAX_UINTN - (*String - '0')) / 10)) { + *Data = MAX_UINTN; + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + return RETURN_UNSUPPORTED; + } + + *Data = *Data * 10 + (*String - '0'); + String++; + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Ascii decimal string to a value of type UINT64. + + This function outputs a value of type UINT64 by interpreting the contents of + the Ascii string specified by String as a decimal number. The format of the + input Ascii string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The function will + ignore the pad space, which includes spaces or tab characters, before + [decimal digits]. The running zero in the beginning of [decimal digits] will + be ignored. Then, the function stops at the first character that is a not a + valid decimal character or a Null-terminator, whichever one comes first. + + If String is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and String contains more than + PcdMaximumAsciiStringLength Ascii characters, not including the + Null-terminator, then ASSERT(). + + If String has no valid decimal digits in the above format, then 0 is stored + at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINT64, then + MAX_UINT64 is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + decimal digits right after the optional pad spaces, the value of String is + stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Ascii string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumAsciiStringLength is not zero, + and String contains more than + PcdMaximumAsciiStringLength Ascii + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINT64. + +**/ +RETURN_STATUS +EFIAPI +AsciiStrDecimalToUint64S ( + IN CONST CHAR8 *String, + OUT CHAR8 **EndPointer, OPTIONAL + OUT UINT64 *Data + ) +{ + // + // 1. Neither String nor Data shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. The length of String shall not be greater than ASCII_RSIZE_MAX. + // + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((AsciiStrnLenS (String, ASCII_RSIZE_MAX + 1) <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + + // + // Ignore the pad spaces (space or tab) + // + while ((*String == ' ') || (*String == '\t')) { + String++; + } + + // + // Ignore leading Zeros after the spaces + // + while (*String == '0') { + String++; + } + + *Data = 0; + + while (InternalAsciiIsDecimalDigitCharacter (*String)) { + // + // If the number represented by String overflows according to the range + // defined by UINT64, then MAX_UINT64 is stored in *Data and + // RETURN_UNSUPPORTED is returned. + // + if (*Data > DivU64x32 (MAX_UINT64 - (*String - '0'), 10)) { + *Data = MAX_UINT64; + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + return RETURN_UNSUPPORTED; + } + + *Data = MultU64x32 (*Data, 10) + (*String - '0'); + String++; + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Ascii hexadecimal string to a value of type UINTN. + + This function outputs a value of type UINTN by interpreting the contents of + the Ascii string specified by String as a hexadecimal number. The format of + the input Ascii string String is: + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. If + "x" appears in the input string, it must be prefixed with at least one 0. The + function will ignore the pad space, which includes spaces or tab characters, + before [zeros], [x] or [hexadecimal digits]. The running zero before [x] or + [hexadecimal digits] will be ignored. Then, the decoding starts after [x] or + the first valid hexadecimal digit. Then, the function stops at the first + character that is a not a valid hexadecimal character or Null-terminator, + whichever on comes first. + + If String is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and String contains more than + PcdMaximumAsciiStringLength Ascii characters, not including the + Null-terminator, then ASSERT(). + + If String has no valid hexadecimal digits in the above format, then 0 is + stored at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINTN, then + MAX_UINTN is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + hexadecimal digits right after the optional pad spaces, the value of String + is stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Ascii string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumAsciiStringLength is not zero, + and String contains more than + PcdMaximumAsciiStringLength Ascii + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINTN. + +**/ +RETURN_STATUS +EFIAPI +AsciiStrHexToUintnS ( + IN CONST CHAR8 *String, + OUT CHAR8 **EndPointer, OPTIONAL + OUT UINTN *Data + ) +{ + // + // 1. Neither String nor Data shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. The length of String shall not be greater than ASCII_RSIZE_MAX. + // + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((AsciiStrnLenS (String, ASCII_RSIZE_MAX + 1) <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + + // + // Ignore the pad spaces (space or tab) + // + while ((*String == ' ') || (*String == '\t')) { + String++; + } + + // + // Ignore leading Zeros after the spaces + // + while (*String == '0') { + String++; + } + + if (InternalBaseLibAsciiToUpper (*String) == 'X') { + if (*(String - 1) != '0') { + *Data = 0; + return RETURN_SUCCESS; + } + // + // Skip the 'X' + // + String++; + } + + *Data = 0; + + while (InternalAsciiIsHexaDecimalDigitCharacter (*String)) { + // + // If the number represented by String overflows according to the range + // defined by UINTN, then MAX_UINTN is stored in *Data and + // RETURN_UNSUPPORTED is returned. + // + if (*Data > ((MAX_UINTN - InternalAsciiHexCharToUintn (*String)) >> 4)) { + *Data = MAX_UINTN; + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + return RETURN_UNSUPPORTED; + } + + *Data = (*Data << 4) + InternalAsciiHexCharToUintn (*String); + String++; + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Ascii hexadecimal string to a value of type UINT64. + + This function outputs a value of type UINT64 by interpreting the contents of + the Ascii string specified by String as a hexadecimal number. The format of + the input Ascii string String is: + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. If + "x" appears in the input string, it must be prefixed with at least one 0. The + function will ignore the pad space, which includes spaces or tab characters, + before [zeros], [x] or [hexadecimal digits]. The running zero before [x] or + [hexadecimal digits] will be ignored. Then, the decoding starts after [x] or + the first valid hexadecimal digit. Then, the function stops at the first + character that is a not a valid hexadecimal character or Null-terminator, + whichever on comes first. + + If String is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and String contains more than + PcdMaximumAsciiStringLength Ascii characters, not including the + Null-terminator, then ASSERT(). + + If String has no valid hexadecimal digits in the above format, then 0 is + stored at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINT64, then + MAX_UINT64 is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + hexadecimal digits right after the optional pad spaces, the value of String + is stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Ascii string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumAsciiStringLength is not zero, + and String contains more than + PcdMaximumAsciiStringLength Ascii + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINT64. + +**/ +RETURN_STATUS +EFIAPI +AsciiStrHexToUint64S ( + IN CONST CHAR8 *String, + OUT CHAR8 **EndPointer, OPTIONAL + OUT UINT64 *Data + ) +{ + // + // 1. Neither String nor Data shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. The length of String shall not be greater than ASCII_RSIZE_MAX. + // + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((AsciiStrnLenS (String, ASCII_RSIZE_MAX + 1) <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + + // + // Ignore the pad spaces (space or tab) + // + while ((*String == ' ') || (*String == '\t')) { + String++; + } + + // + // Ignore leading Zeros after the spaces + // + while (*String == '0') { + String++; + } + + if (InternalBaseLibAsciiToUpper (*String) == 'X') { + if (*(String - 1) != '0') { + *Data = 0; + return RETURN_SUCCESS; + } + // + // Skip the 'X' + // + String++; + } + + *Data = 0; + + while (InternalAsciiIsHexaDecimalDigitCharacter (*String)) { + // + // If the number represented by String overflows according to the range + // defined by UINT64, then MAX_UINT64 is stored in *Data and + // RETURN_UNSUPPORTED is returned. + // + if (*Data > RShiftU64 (MAX_UINT64 - InternalAsciiHexCharToUintn (*String), 4)) { + *Data = MAX_UINT64; + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + return RETURN_UNSUPPORTED; + } + + *Data = LShiftU64 (*Data, 4) + InternalAsciiHexCharToUintn (*String); + String++; + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) String; + } + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Unicode string to a Null-terminated + ASCII string. + + This function is similar to AsciiStrCpyS. + + This function converts the content of the Unicode string Source + to the ASCII string Destination by copying the lower 8 bits of + each Unicode character. The function terminates the ASCII string + Destination by appending a Null-terminator character at the end. + + The caller is responsible to make sure Destination points to a buffer with size + equal or greater than ((StrLen (Source) + 1) * sizeof (CHAR8)) in bytes. + + If any Unicode characters in Source contain non-zero value in + the upper 8 bits, then ASSERT(). + + If Source is not aligned on a 16-bit boundary, then ASSERT(). + If an error would be returned, then the function will also ASSERT(). + + If an error is returned, then the Destination is unmodified. + + @param Source The pointer to a Null-terminated Unicode string. + @param Destination The pointer to a Null-terminated ASCII string. + @param DestMax The maximum number of Destination Ascii + char, including terminating null char. + + @retval RETURN_SUCCESS String is converted. + @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than StrLen(Source). + @retval RETURN_INVALID_PARAMETER If Destination is NULL. + If Source is NULL. + If PcdMaximumAsciiStringLength is not zero, + and DestMax is greater than + PcdMaximumAsciiStringLength. + If PcdMaximumUnicodeStringLength is not zero, + and DestMax is greater than + PcdMaximumUnicodeStringLength. + If DestMax is 0. + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. + +**/ +RETURN_STATUS +EFIAPI +UnicodeStrToAsciiStrS ( + IN CONST CHAR16 *Source, + OUT CHAR8 *Destination, + IN UINTN DestMax + ) +{ + UINTN SourceLen; + + ASSERT (((UINTN) Source & BIT0) == 0); + + // + // 1. Neither Destination nor Source shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. DestMax shall not be greater than ASCII_RSIZE_MAX or RSIZE_MAX. + // + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. DestMax shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER); + + // + // 4. DestMax shall be greater than StrnLenS (Source, DestMax). + // + SourceLen = StrnLenS (Source, DestMax); + SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL); + + // + // 5. Copying shall not take place between objects that overlap. + // + SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap (Destination, DestMax, (VOID *)Source, (SourceLen + 1) * sizeof(CHAR16)), RETURN_ACCESS_DENIED); + + // + // convert string + // + while (*Source != '\0') { + // + // If any Unicode characters in Source contain + // non-zero value in the upper 8 bits, then ASSERT(). + // + ASSERT (*Source < 0x100); + *(Destination++) = (CHAR8) *(Source++); + } + *Destination = '\0'; + + return RETURN_SUCCESS; +} + +/** + Convert not more than Length successive characters from a Null-terminated + Unicode string to a Null-terminated Ascii string. If no null char is copied + from Source, then Destination[Length] is always set to null. + + This function converts not more than Length successive characters from the + Unicode string Source to the Ascii string Destination by copying the lower 8 + bits of each Unicode character. The function terminates the Ascii string + Destination by appending a Null-terminator character at the end. + + The caller is responsible to make sure Destination points to a buffer with + size not smaller than ((MIN(StrLen(Source), Length) + 1) * sizeof (CHAR8)) + in bytes. + + If any Unicode characters in Source contain non-zero value in the upper 8 + bits, then ASSERT(). + If Source is not aligned on a 16-bit boundary, then ASSERT(). + If an error would be returned, then the function will also ASSERT(). + + If an error is returned, then Destination and DestinationLength are + unmodified. + + @param Source The pointer to a Null-terminated Unicode string. + @param Length The maximum number of Unicode characters to + convert. + @param Destination The pointer to a Null-terminated Ascii string. + @param DestMax The maximum number of Destination Ascii char, + including terminating null char. + @param DestinationLength The number of Unicode characters converted. + + @retval RETURN_SUCCESS String is converted. + @retval RETURN_INVALID_PARAMETER If Destination is NULL. + If Source is NULL. + If DestinationLength is NULL. + If PcdMaximumAsciiStringLength is not zero, + and Length or DestMax is greater than + PcdMaximumAsciiStringLength. + If PcdMaximumUnicodeStringLength is not + zero, and Length or DestMax is greater than + PcdMaximumUnicodeStringLength. + If DestMax is 0. + @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than + MIN(StrLen(Source), Length). + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. + +**/ +RETURN_STATUS +EFIAPI +UnicodeStrnToAsciiStrS ( + IN CONST CHAR16 *Source, + IN UINTN Length, + OUT CHAR8 *Destination, + IN UINTN DestMax, + OUT UINTN *DestinationLength + ) +{ + UINTN SourceLen; + + ASSERT (((UINTN) Source & BIT0) == 0); + + // + // 1. None of Destination, Source or DestinationLength shall be a null + // pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((DestinationLength != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. Neither Length nor DestMax shall be greater than ASCII_RSIZE_MAX or + // RSIZE_MAX. + // + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((Length <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. DestMax shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER); + + // + // 4. If Length is not less than DestMax, then DestMax shall be greater than + // StrnLenS(Source, DestMax). + // + SourceLen = StrnLenS (Source, DestMax); + if (Length >= DestMax) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL); + } + + // + // 5. Copying shall not take place between objects that overlap. + // + if (SourceLen > Length) { + SourceLen = Length; + } + SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap (Destination, DestMax, (VOID *)Source, (SourceLen + 1) * sizeof(CHAR16)), RETURN_ACCESS_DENIED); + + *DestinationLength = 0; + + // + // Convert string + // + while ((*Source != 0) && (SourceLen > 0)) { + // + // If any Unicode characters in Source contain non-zero value in the upper + // 8 bits, then ASSERT(). + // + ASSERT (*Source < 0x100); + *(Destination++) = (CHAR8) *(Source++); + SourceLen--; + (*DestinationLength)++; + } + *Destination = 0; + + return RETURN_SUCCESS; +} + +/** + Convert one Null-terminated ASCII string to a Null-terminated + Unicode string. + + This function is similar to StrCpyS. + + This function converts the contents of the ASCII string Source to the Unicode + string Destination. The function terminates the Unicode string Destination by + appending a Null-terminator character at the end. + + The caller is responsible to make sure Destination points to a buffer with size + equal or greater than ((AsciiStrLen (Source) + 1) * sizeof (CHAR16)) in bytes. + + If Destination is not aligned on a 16-bit boundary, then ASSERT(). + If an error would be returned, then the function will also ASSERT(). + + If an error is returned, then the Destination is unmodified. + + @param Source The pointer to a Null-terminated ASCII string. + @param Destination The pointer to a Null-terminated Unicode string. + @param DestMax The maximum number of Destination Unicode + char, including terminating null char. + + @retval RETURN_SUCCESS String is converted. + @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than StrLen(Source). + @retval RETURN_INVALID_PARAMETER If Destination is NULL. + If Source is NULL. + If PcdMaximumUnicodeStringLength is not zero, + and DestMax is greater than + PcdMaximumUnicodeStringLength. + If PcdMaximumAsciiStringLength is not zero, + and DestMax is greater than + PcdMaximumAsciiStringLength. + If DestMax is 0. + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. + +**/ +RETURN_STATUS +EFIAPI +AsciiStrToUnicodeStrS ( + IN CONST CHAR8 *Source, + OUT CHAR16 *Destination, + IN UINTN DestMax + ) +{ + UINTN SourceLen; + + ASSERT (((UINTN) Destination & BIT0) == 0); + + // + // 1. Neither Destination nor Source shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. DestMax shall not be greater than RSIZE_MAX or ASCII_RSIZE_MAX. + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. DestMax shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER); + + // + // 4. DestMax shall be greater than AsciiStrnLenS(Source, DestMax). + // + SourceLen = AsciiStrnLenS (Source, DestMax); + SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL); + + // + // 5. Copying shall not take place between objects that overlap. + // + SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap (Destination, DestMax * sizeof(CHAR16), (VOID *)Source, SourceLen + 1), RETURN_ACCESS_DENIED); + + // + // Convert string + // + while (*Source != '\0') { + *(Destination++) = (CHAR16)*(Source++); + } + *Destination = '\0'; + + return RETURN_SUCCESS; +} + +/** + Convert not more than Length successive characters from a Null-terminated + Ascii string to a Null-terminated Unicode string. If no null char is copied + from Source, then Destination[Length] is always set to null. + + This function converts not more than Length successive characters from the + Ascii string Source to the Unicode string Destination. The function + terminates the Unicode string Destination by appending a Null-terminator + character at the end. + + The caller is responsible to make sure Destination points to a buffer with + size not smaller than + ((MIN(AsciiStrLen(Source), Length) + 1) * sizeof (CHAR8)) in bytes. + + If Destination is not aligned on a 16-bit boundary, then ASSERT(). + If an error would be returned, then the function will also ASSERT(). + + If an error is returned, then Destination and DestinationLength are + unmodified. + + @param Source The pointer to a Null-terminated Ascii string. + @param Length The maximum number of Ascii characters to convert. + @param Destination The pointer to a Null-terminated Unicode string. + @param DestMax The maximum number of Destination Unicode char, + including terminating null char. + @param DestinationLength The number of Ascii characters converted. + + @retval RETURN_SUCCESS String is converted. + @retval RETURN_INVALID_PARAMETER If Destination is NULL. + If Source is NULL. + If DestinationLength is NULL. + If PcdMaximumUnicodeStringLength is not + zero, and Length or DestMax is greater than + PcdMaximumUnicodeStringLength. + If PcdMaximumAsciiStringLength is not zero, + and Length or DestMax is greater than + PcdMaximumAsciiStringLength. + If DestMax is 0. + @retval RETURN_BUFFER_TOO_SMALL If DestMax is NOT greater than + MIN(AsciiStrLen(Source), Length). + @retval RETURN_ACCESS_DENIED If Source and Destination overlap. + +**/ +RETURN_STATUS +EFIAPI +AsciiStrnToUnicodeStrS ( + IN CONST CHAR8 *Source, + IN UINTN Length, + OUT CHAR16 *Destination, + IN UINTN DestMax, + OUT UINTN *DestinationLength + ) +{ + UINTN SourceLen; + + ASSERT (((UINTN) Destination & BIT0) == 0); + + // + // 1. None of Destination, Source or DestinationLength shall be a null + // pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((DestinationLength != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. Neither Length nor DestMax shall be greater than ASCII_RSIZE_MAX or + // RSIZE_MAX. + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((Length <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. DestMax shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER); + + // + // 4. If Length is not less than DestMax, then DestMax shall be greater than + // AsciiStrnLenS(Source, DestMax). + // + SourceLen = AsciiStrnLenS (Source, DestMax); + if (Length >= DestMax) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL); + } + + // + // 5. Copying shall not take place between objects that overlap. + // + if (SourceLen > Length) { + SourceLen = Length; + } + SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap (Destination, DestMax * sizeof(CHAR16), (VOID *)Source, SourceLen + 1), RETURN_ACCESS_DENIED); + + *DestinationLength = 0; + + // + // Convert string + // + while ((*Source != 0) && (SourceLen > 0)) { + *(Destination++) = (CHAR16)*(Source++); + SourceLen--; + (*DestinationLength)++; + } + *Destination = 0; + + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated ASCII string to IPv6 address and prefix length. + + This function outputs a value of type IPv6_ADDRESS and may output a value + of type UINT8 by interpreting the contents of the ASCII string specified + by String. The format of the input ASCII string String is as follows: + + X:X:X:X:X:X:X:X[/P] + + X contains one to four hexadecimal digit characters in the range [0-9], [a-f] and + [A-F]. X is converted to a value of type UINT16, whose low byte is stored in low + memory address and high byte is stored in high memory address. P contains decimal + digit characters in the range [0-9]. The running zero in the beginning of P will + be ignored. /P is optional. + + When /P is not in the String, the function stops at the first character that is + not a valid hexadecimal digit character after eight X's are converted. + + When /P is in the String, the function stops at the first character that is not + a valid decimal digit character after P is converted. + + "::" can be used to compress one or more groups of X when X contains only 0. + The "::" can only appear once in the String. + + If String is NULL, then ASSERT(). + + If Address is NULL, then ASSERT(). + + If EndPointer is not NULL and Address is translated from String, a pointer + to the character that stopped the scan is stored at the location pointed to + by EndPointer. + + @param String Pointer to a Null-terminated ASCII string. + @param EndPointer Pointer to character that stops scan. + @param Address Pointer to the converted IPv6 address. + @param PrefixLength Pointer to the converted IPv6 address prefix + length. MAX_UINT8 is returned when /P is + not in the String. + + @retval RETURN_SUCCESS Address is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + @retval RETURN_UNSUPPORTED If X contains more than four hexadecimal + digit characters. + If String contains "::" and number of X + is not less than 8. + If P starts with character that is not a + valid decimal digit character. + If the decimal number converted from P + exceeds 128. + +**/ +RETURN_STATUS +EFIAPI +AsciiStrToIpv6Address ( + IN CONST CHAR8 *String, + OUT CHAR8 **EndPointer, OPTIONAL + OUT IPv6_ADDRESS *Address, + OUT UINT8 *PrefixLength OPTIONAL + ) +{ + RETURN_STATUS Status; + UINTN AddressIndex; + UINTN Uintn; + IPv6_ADDRESS LocalAddress; + UINT8 LocalPrefixLength; + CONST CHAR8 *Pointer; + CHAR8 *End; + UINTN CompressStart; + BOOLEAN ExpectPrefix; + + LocalPrefixLength = MAX_UINT8; + CompressStart = ARRAY_SIZE (Address->Addr); + ExpectPrefix = FALSE; + + // + // None of String or Address shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Address != NULL), RETURN_INVALID_PARAMETER); + + for (Pointer = String, AddressIndex = 0; AddressIndex < ARRAY_SIZE (Address->Addr) + 1;) { + if (!InternalAsciiIsHexaDecimalDigitCharacter (*Pointer)) { + if (*Pointer != ':') { + // + // ":" or "/" should be followed by digit characters. + // + return RETURN_UNSUPPORTED; + } + + // + // Meet second ":" after previous ":" or "/" + // or meet first ":" in the beginning of String. + // + if (ExpectPrefix) { + // + // ":" shall not be after "/" + // + return RETURN_UNSUPPORTED; + } + + if (CompressStart != ARRAY_SIZE (Address->Addr) || AddressIndex == ARRAY_SIZE (Address->Addr)) { + // + // "::" can only appear once. + // "::" can only appear when address is not full length. + // + return RETURN_UNSUPPORTED; + } else { + // + // Remember the start of zero compressing. + // + CompressStart = AddressIndex; + Pointer++; + + if (CompressStart == 0) { + if (*Pointer != ':') { + // + // Single ":" shall not be in the beginning of String. + // + return RETURN_UNSUPPORTED; + } + Pointer++; + } + } + } + + if (!InternalAsciiIsHexaDecimalDigitCharacter (*Pointer)) { + if (*Pointer == '/') { + // + // Might be optional "/P" after "::". + // + if (CompressStart != AddressIndex) { + return RETURN_UNSUPPORTED; + } + } else { + break; + } + } else { + if (!ExpectPrefix) { + // + // Get X. + // + Status = AsciiStrHexToUintnS (Pointer, &End, &Uintn); + if (RETURN_ERROR (Status) || End - Pointer > 4) { + // + // Number of hexadecimal digit characters is no more than 4. + // + return RETURN_UNSUPPORTED; + } + Pointer = End; + // + // Uintn won't exceed MAX_UINT16 if number of hexadecimal digit characters is no more than 4. + // + ASSERT (AddressIndex + 1 < ARRAY_SIZE (Address->Addr)); + LocalAddress.Addr[AddressIndex] = (UINT8) ((UINT16) Uintn >> 8); + LocalAddress.Addr[AddressIndex + 1] = (UINT8) Uintn; + AddressIndex += 2; + } else { + // + // Get P, then exit the loop. + // + Status = AsciiStrDecimalToUintnS (Pointer, &End, &Uintn); + if (RETURN_ERROR (Status) || End == Pointer || Uintn > 128) { + // + // Prefix length should not exceed 128. + // + return RETURN_UNSUPPORTED; + } + LocalPrefixLength = (UINT8) Uintn; + Pointer = End; + break; + } + } + + // + // Skip ':' or "/" + // + if (*Pointer == '/') { + ExpectPrefix = TRUE; + } else if (*Pointer == ':') { + if (AddressIndex == ARRAY_SIZE (Address->Addr)) { + // + // Meet additional ":" after all 8 16-bit address + // + break; + } + } else { + // + // Meet other character that is not "/" or ":" after all 8 16-bit address + // + break; + } + Pointer++; + } + + if ((AddressIndex == ARRAY_SIZE (Address->Addr) && CompressStart != ARRAY_SIZE (Address->Addr)) || + (AddressIndex != ARRAY_SIZE (Address->Addr) && CompressStart == ARRAY_SIZE (Address->Addr)) + ) { + // + // Full length of address shall not have compressing zeros. + // Non-full length of address shall have compressing zeros. + // + return RETURN_UNSUPPORTED; + } + CopyMem (&Address->Addr[0], &LocalAddress.Addr[0], CompressStart); + ZeroMem (&Address->Addr[CompressStart], ARRAY_SIZE (Address->Addr) - AddressIndex); + if (AddressIndex > CompressStart) { + CopyMem ( + &Address->Addr[CompressStart + ARRAY_SIZE (Address->Addr) - AddressIndex], + &LocalAddress.Addr[CompressStart], + AddressIndex - CompressStart + ); + + } + + if (PrefixLength != NULL) { + *PrefixLength = LocalPrefixLength; + } + if (EndPointer != NULL) { + *EndPointer = (CHAR8 *) Pointer; + } + + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated ASCII string to IPv4 address and prefix length. + + This function outputs a value of type IPv4_ADDRESS and may output a value + of type UINT8 by interpreting the contents of the ASCII string specified + by String. The format of the input ASCII string String is as follows: + + D.D.D.D[/P] + + D and P are decimal digit characters in the range [0-9]. The running zero in + the beginning of D and P will be ignored. /P is optional. + + When /P is not in the String, the function stops at the first character that is + not a valid decimal digit character after four D's are converted. + + When /P is in the String, the function stops at the first character that is not + a valid decimal digit character after P is converted. + + If String is NULL, then ASSERT(). + + If Address is NULL, then ASSERT(). + + If EndPointer is not NULL and Address is translated from String, a pointer + to the character that stopped the scan is stored at the location pointed to + by EndPointer. + + @param String Pointer to a Null-terminated ASCII string. + @param EndPointer Pointer to character that stops scan. + @param Address Pointer to the converted IPv4 address. + @param PrefixLength Pointer to the converted IPv4 address prefix + length. MAX_UINT8 is returned when /P is + not in the String. + + @retval RETURN_SUCCESS Address is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + @retval RETURN_UNSUPPORTED If String is not in the correct format. + If any decimal number converted from D + exceeds 255. + If the decimal number converted from P + exceeds 32. + +**/ +RETURN_STATUS +EFIAPI +AsciiStrToIpv4Address ( + IN CONST CHAR8 *String, + OUT CHAR8 **EndPointer, OPTIONAL + OUT IPv4_ADDRESS *Address, + OUT UINT8 *PrefixLength OPTIONAL + ) +{ + RETURN_STATUS Status; + UINTN AddressIndex; + UINTN Uintn; + IPv4_ADDRESS LocalAddress; + UINT8 LocalPrefixLength; + CHAR8 *Pointer; + + LocalPrefixLength = MAX_UINT8; + + // + // None of String or Address shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Address != NULL), RETURN_INVALID_PARAMETER); + + for (Pointer = (CHAR8 *) String, AddressIndex = 0; AddressIndex < ARRAY_SIZE (Address->Addr) + 1;) { + if (!InternalAsciiIsDecimalDigitCharacter (*Pointer)) { + // + // D or P contains invalid characters. + // + break; + } + + // + // Get D or P. + // + Status = AsciiStrDecimalToUintnS ((CONST CHAR8 *) Pointer, &Pointer, &Uintn); + if (RETURN_ERROR (Status)) { + return RETURN_UNSUPPORTED; + } + if (AddressIndex == ARRAY_SIZE (Address->Addr)) { + // + // It's P. + // + if (Uintn > 32) { + return RETURN_UNSUPPORTED; + } + LocalPrefixLength = (UINT8) Uintn; + } else { + // + // It's D. + // + if (Uintn > MAX_UINT8) { + return RETURN_UNSUPPORTED; + } + LocalAddress.Addr[AddressIndex] = (UINT8) Uintn; + AddressIndex++; + } + + // + // Check the '.' or '/', depending on the AddressIndex. + // + if (AddressIndex == ARRAY_SIZE (Address->Addr)) { + if (*Pointer == '/') { + // + // '/P' is in the String. + // Skip "/" and get P in next loop. + // + Pointer++; + } else { + // + // '/P' is not in the String. + // + break; + } + } else if (AddressIndex < ARRAY_SIZE (Address->Addr)) { + if (*Pointer == '.') { + // + // D should be followed by '.' + // + Pointer++; + } else { + return RETURN_UNSUPPORTED; + } + } + } + + if (AddressIndex < ARRAY_SIZE (Address->Addr)) { + return RETURN_UNSUPPORTED; + } + + CopyMem (Address, &LocalAddress, sizeof (*Address)); + if (PrefixLength != NULL) { + *PrefixLength = LocalPrefixLength; + } + if (EndPointer != NULL) { + *EndPointer = Pointer; + } + + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated ASCII GUID string to a value of type + EFI_GUID. + + This function outputs a GUID value by interpreting the contents of + the ASCII string specified by String. The format of the input + ASCII string String consists of 36 characters, as follows: + + aabbccdd-eeff-gghh-iijj-kkllmmnnoopp + + The pairs aa - pp are two characters in the range [0-9], [a-f] and + [A-F], with each pair representing a single byte hexadecimal value. + + The mapping between String and the EFI_GUID structure is as follows: + aa Data1[24:31] + bb Data1[16:23] + cc Data1[8:15] + dd Data1[0:7] + ee Data2[8:15] + ff Data2[0:7] + gg Data3[8:15] + hh Data3[0:7] + ii Data4[0:7] + jj Data4[8:15] + kk Data4[16:23] + ll Data4[24:31] + mm Data4[32:39] + nn Data4[40:47] + oo Data4[48:55] + pp Data4[56:63] + + If String is NULL, then ASSERT(). + If Guid is NULL, then ASSERT(). + + @param String Pointer to a Null-terminated ASCII string. + @param Guid Pointer to the converted GUID. + + @retval RETURN_SUCCESS Guid is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + @retval RETURN_UNSUPPORTED If String is not as the above format. + +**/ +RETURN_STATUS +EFIAPI +AsciiStrToGuid ( + IN CONST CHAR8 *String, + OUT GUID *Guid + ) +{ + RETURN_STATUS Status; + GUID LocalGuid; + + // + // None of String or Guid shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Guid != NULL), RETURN_INVALID_PARAMETER); + + // + // Get aabbccdd in big-endian. + // + Status = AsciiStrHexToBytes (String, 2 * sizeof (LocalGuid.Data1), (UINT8 *) &LocalGuid.Data1, sizeof (LocalGuid.Data1)); + if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data1)] != '-') { + return RETURN_UNSUPPORTED; + } + // + // Convert big-endian to little-endian. + // + LocalGuid.Data1 = SwapBytes32 (LocalGuid.Data1); + String += 2 * sizeof (LocalGuid.Data1) + 1; + + // + // Get eeff in big-endian. + // + Status = AsciiStrHexToBytes (String, 2 * sizeof (LocalGuid.Data2), (UINT8 *) &LocalGuid.Data2, sizeof (LocalGuid.Data2)); + if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data2)] != '-') { + return RETURN_UNSUPPORTED; + } + // + // Convert big-endian to little-endian. + // + LocalGuid.Data2 = SwapBytes16 (LocalGuid.Data2); + String += 2 * sizeof (LocalGuid.Data2) + 1; + + // + // Get gghh in big-endian. + // + Status = AsciiStrHexToBytes (String, 2 * sizeof (LocalGuid.Data3), (UINT8 *) &LocalGuid.Data3, sizeof (LocalGuid.Data3)); + if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data3)] != '-') { + return RETURN_UNSUPPORTED; + } + // + // Convert big-endian to little-endian. + // + LocalGuid.Data3 = SwapBytes16 (LocalGuid.Data3); + String += 2 * sizeof (LocalGuid.Data3) + 1; + + // + // Get iijj. + // + Status = AsciiStrHexToBytes (String, 2 * 2, &LocalGuid.Data4[0], 2); + if (RETURN_ERROR (Status) || String[2 * 2] != '-') { + return RETURN_UNSUPPORTED; + } + String += 2 * 2 + 1; + + // + // Get kkllmmnnoopp. + // + Status = AsciiStrHexToBytes (String, 2 * 6, &LocalGuid.Data4[2], 6); + if (RETURN_ERROR (Status)) { + return RETURN_UNSUPPORTED; + } + + CopyGuid (Guid, &LocalGuid); + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated ASCII hexadecimal string to a byte array. + + This function outputs a byte array by interpreting the contents of + the ASCII string specified by String in hexadecimal format. The format of + the input ASCII string String is: + + [XX]* + + X is a hexadecimal digit character in the range [0-9], [a-f] and [A-F]. + The function decodes every two hexadecimal digit characters as one byte. The + decoding stops after Length of characters and outputs Buffer containing + (Length / 2) bytes. + + If String is NULL, then ASSERT(). + + If Buffer is NULL, then ASSERT(). + + If Length is not multiple of 2, then ASSERT(). + + If PcdMaximumAsciiStringLength is not zero and Length is greater than + PcdMaximumAsciiStringLength, then ASSERT(). + + If MaxBufferSize is less than (Length / 2), then ASSERT(). + + @param String Pointer to a Null-terminated ASCII string. + @param Length The number of ASCII characters to decode. + @param Buffer Pointer to the converted bytes array. + @param MaxBufferSize The maximum size of Buffer. + + @retval RETURN_SUCCESS Buffer is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If Length is not multiple of 2. + If PcdMaximumAsciiStringLength is not zero, + and Length is greater than + PcdMaximumAsciiStringLength. + @retval RETURN_UNSUPPORTED If Length of characters from String contain + a character that is not valid hexadecimal + digit characters, or a Null-terminator. + @retval RETURN_BUFFER_TOO_SMALL If MaxBufferSize is less than (Length / 2). +**/ +RETURN_STATUS +EFIAPI +AsciiStrHexToBytes ( + IN CONST CHAR8 *String, + IN UINTN Length, + OUT UINT8 *Buffer, + IN UINTN MaxBufferSize + ) +{ + UINTN Index; + + // + // 1. None of String or Buffer shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Buffer != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. Length shall not be greater than ASCII_RSIZE_MAX. + // + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((Length <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. Length shall not be odd. + // + SAFE_STRING_CONSTRAINT_CHECK (((Length & BIT0) == 0), RETURN_INVALID_PARAMETER); + + // + // 4. MaxBufferSize shall equal to or greater than Length / 2. + // + SAFE_STRING_CONSTRAINT_CHECK ((MaxBufferSize >= Length / 2), RETURN_BUFFER_TOO_SMALL); + + // + // 5. String shall not contains invalid hexadecimal digits. + // + for (Index = 0; Index < Length; Index++) { + if (!InternalAsciiIsHexaDecimalDigitCharacter (String[Index])) { + break; + } + } + if (Index != Length) { + return RETURN_UNSUPPORTED; + } + + // + // Convert the hex string to bytes. + // + for(Index = 0; Index < Length; Index++) { + + // + // For even characters, write the upper nibble for each buffer byte, + // and for even characters, the lower nibble. + // + if ((Index & BIT0) == 0) { + Buffer[Index / 2] = (UINT8) InternalAsciiHexCharToUintn (String[Index]) << 4; + } else { + Buffer[Index / 2] |= (UINT8) InternalAsciiHexCharToUintn (String[Index]); + } + } + return RETURN_SUCCESS; +} + diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/SetJump.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/SetJump.c new file mode 100644 index 0000000..6d61e93 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/SetJump.c @@ -0,0 +1,54 @@ +/** @file + Internal ASSERT () functions for SetJump. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include +#include +#include +#include +#include + +/** + Saves the current CPU context that can be restored with a call to LongJump() + and returns 0. + + Saves the current CPU context in the buffer specified by JumpBuffer and + returns 0. The initial call to SetJump() must always return 0. Subsequent + calls to LongJump() cause a non-zero value to be returned by SetJump(). + + If JumpBuffer is NULL, then ASSERT(). + For Itanium processors, if JumpBuffer is not aligned on a 16-byte boundary, then ASSERT(). + + NOTE: The structure BASE_LIBRARY_JUMP_BUFFER is CPU architecture specific. + The same structure must never be used for more than one CPU architecture context. + For example, a BASE_LIBRARY_JUMP_BUFFER allocated by an IA-32 module must never be used from an x64 module. + SetJump()/LongJump() is not currently supported for the EBC processor type. + + @param JumpBuffer A pointer to CPU context buffer. + + @retval 0 Indicates a return from SetJump(). + +**/ +UINTN +EFIAPI +SetJump ( + OUT BASE_LIBRARY_JUMP_BUFFER *JumpBuffer + ) +{ + jmp_buf local_buf; + jmp_buf *buf; + UINTN Value; + + buf = malloc (sizeof(jmp_buf)); + *(VOID **)JumpBuffer = buf; + Value = setjmp (local_buf); + if (Value == 0) { + memcpy (buf, &local_buf, sizeof(jmp_buf)); + } + return Value; +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/String.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/String.c new file mode 100644 index 0000000..4f5fa47 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/String.c @@ -0,0 +1,1163 @@ +/** @file + Unicode and ASCII string primitives. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +/** + Returns the length of a Null-terminated Unicode string. + + This function returns the number of Unicode characters in the Null-terminated + Unicode string specified by String. + + If String is NULL, then ASSERT(). + If String is not aligned on a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + @param String A pointer to a Null-terminated Unicode string. + + @return The length of String. + +**/ +UINTN +EFIAPI +StrLen ( + IN CONST CHAR16 *String + ) +{ + UINTN Length; + + ASSERT (String != NULL); + ASSERT (((UINTN) String & BIT0) == 0); + + for (Length = 0; *String != L'\0'; String++, Length++) { + // + // If PcdMaximumUnicodeStringLength is not zero, + // length should not more than PcdMaximumUnicodeStringLength + // + } + return Length; +} + +/** + Returns the size of a Null-terminated Unicode string in bytes, including the + Null terminator. + + This function returns the size, in bytes, of the Null-terminated Unicode string + specified by String. + + If String is NULL, then ASSERT(). + If String is not aligned on a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + @param String A pointer to a Null-terminated Unicode string. + + @return The size of String. + +**/ +UINTN +EFIAPI +StrSize ( + IN CONST CHAR16 *String + ) +{ + return (StrLen (String) + 1) * sizeof (*String); +} + +/** + Compares two Null-terminated Unicode strings, and returns the difference + between the first mismatched Unicode characters. + + This function compares the Null-terminated Unicode string FirstString to the + Null-terminated Unicode string SecondString. If FirstString is identical to + SecondString, then 0 is returned. Otherwise, the value returned is the first + mismatched Unicode character in SecondString subtracted from the first + mismatched Unicode character in FirstString. + + If FirstString is NULL, then ASSERT(). + If FirstString is not aligned on a 16-bit boundary, then ASSERT(). + If SecondString is NULL, then ASSERT(). + If SecondString is not aligned on a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and FirstString contains more + than PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and SecondString contains more + than PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + @param FirstString A pointer to a Null-terminated Unicode string. + @param SecondString A pointer to a Null-terminated Unicode string. + + @retval 0 FirstString is identical to SecondString. + @return others FirstString is not identical to SecondString. + +**/ +INTN +EFIAPI +StrCmp ( + IN CONST CHAR16 *FirstString, + IN CONST CHAR16 *SecondString + ) +{ + // + // ASSERT both strings are less long than PcdMaximumUnicodeStringLength + // + ASSERT (StrSize (FirstString) != 0); + ASSERT (StrSize (SecondString) != 0); + + while ((*FirstString != L'\0') && (*FirstString == *SecondString)) { + FirstString++; + SecondString++; + } + return *FirstString - *SecondString; +} + +/** + Compares up to a specified length the contents of two Null-terminated Unicode strings, + and returns the difference between the first mismatched Unicode characters. + + This function compares the Null-terminated Unicode string FirstString to the + Null-terminated Unicode string SecondString. At most, Length Unicode + characters will be compared. If Length is 0, then 0 is returned. If + FirstString is identical to SecondString, then 0 is returned. Otherwise, the + value returned is the first mismatched Unicode character in SecondString + subtracted from the first mismatched Unicode character in FirstString. + + If Length > 0 and FirstString is NULL, then ASSERT(). + If Length > 0 and FirstString is not aligned on a 16-bit boundary, then ASSERT(). + If Length > 0 and SecondString is NULL, then ASSERT(). + If Length > 0 and SecondString is not aligned on a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Length is greater than + PcdMaximumUnicodeStringLength, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and FirstString contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator, + then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and SecondString contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator, + then ASSERT(). + + @param FirstString A pointer to a Null-terminated Unicode string. + @param SecondString A pointer to a Null-terminated Unicode string. + @param Length The maximum number of Unicode characters to compare. + + @retval 0 FirstString is identical to SecondString. + @return others FirstString is not identical to SecondString. + +**/ +INTN +EFIAPI +StrnCmp ( + IN CONST CHAR16 *FirstString, + IN CONST CHAR16 *SecondString, + IN UINTN Length + ) +{ + if (Length == 0) { + return 0; + } + + // + // ASSERT both strings are less long than PcdMaximumUnicodeStringLength. + // Length tests are performed inside StrLen(). + // + ASSERT (StrSize (FirstString) != 0); + ASSERT (StrSize (SecondString) != 0); + + while ((*FirstString != L'\0') && + (*SecondString != L'\0') && + (*FirstString == *SecondString) && + (Length > 1)) { + FirstString++; + SecondString++; + Length--; + } + + return *FirstString - *SecondString; +} + +/** + Returns the first occurrence of a Null-terminated Unicode sub-string + in a Null-terminated Unicode string. + + This function scans the contents of the Null-terminated Unicode string + specified by String and returns the first occurrence of SearchString. + If SearchString is not found in String, then NULL is returned. If + the length of SearchString is zero, then String is + returned. + + If String is NULL, then ASSERT(). + If String is not aligned on a 16-bit boundary, then ASSERT(). + If SearchString is NULL, then ASSERT(). + If SearchString is not aligned on a 16-bit boundary, then ASSERT(). + + If PcdMaximumUnicodeStringLength is not zero, and SearchString + or String contains more than PcdMaximumUnicodeStringLength Unicode + characters, not including the Null-terminator, then ASSERT(). + + @param String A pointer to a Null-terminated Unicode string. + @param SearchString A pointer to a Null-terminated Unicode string to search for. + + @retval NULL If the SearchString does not appear in String. + @return others If there is a match. + +**/ +CHAR16 * +EFIAPI +StrStr ( + IN CONST CHAR16 *String, + IN CONST CHAR16 *SearchString + ) +{ + CONST CHAR16 *FirstMatch; + CONST CHAR16 *SearchStringTmp; + + // + // ASSERT both strings are less long than PcdMaximumUnicodeStringLength. + // Length tests are performed inside StrLen(). + // + ASSERT (StrSize (String) != 0); + ASSERT (StrSize (SearchString) != 0); + + if (*SearchString == L'\0') { + return (CHAR16 *) String; + } + + while (*String != L'\0') { + SearchStringTmp = SearchString; + FirstMatch = String; + + while ((*String == *SearchStringTmp) + && (*String != L'\0')) { + String++; + SearchStringTmp++; + } + + if (*SearchStringTmp == L'\0') { + return (CHAR16 *) FirstMatch; + } + + if (*String == L'\0') { + return NULL; + } + + String = FirstMatch + 1; + } + + return NULL; +} + +/** + Check if a Unicode character is a decimal character. + + This internal function checks if a Unicode character is a + decimal character. The valid decimal character is from + L'0' to L'9'. + + @param Char The character to check against. + + @retval TRUE If the Char is a decmial character. + @retval FALSE If the Char is not a decmial character. + +**/ +BOOLEAN +EFIAPI +InternalIsDecimalDigitCharacter ( + IN CHAR16 Char + ) +{ + return (BOOLEAN) (Char >= L'0' && Char <= L'9'); +} + +/** + Convert a Unicode character to upper case only if + it maps to a valid small-case ASCII character. + + This internal function only deal with Unicode character + which maps to a valid small-case ASCII character, i.e. + L'a' to L'z'. For other Unicode character, the input character + is returned directly. + + @param Char The character to convert. + + @retval LowerCharacter If the Char is with range L'a' to L'z'. + @retval Unchanged Otherwise. + +**/ +CHAR16 +EFIAPI +InternalCharToUpper ( + IN CHAR16 Char + ) +{ + if (Char >= L'a' && Char <= L'z') { + return (CHAR16) (Char - (L'a' - L'A')); + } + + return Char; +} + +/** + Convert a Unicode character to numerical value. + + This internal function only deal with Unicode character + which maps to a valid hexadecimal ASII character, i.e. + L'0' to L'9', L'a' to L'f' or L'A' to L'F'. For other + Unicode character, the value returned does not make sense. + + @param Char The character to convert. + + @return The numerical value converted. + +**/ +UINTN +EFIAPI +InternalHexCharToUintn ( + IN CHAR16 Char + ) +{ + if (InternalIsDecimalDigitCharacter (Char)) { + return Char - L'0'; + } + + return (10 + InternalCharToUpper (Char) - L'A'); +} + +/** + Check if a Unicode character is a hexadecimal character. + + This internal function checks if a Unicode character is a + decimal character. The valid hexadecimal character is + L'0' to L'9', L'a' to L'f', or L'A' to L'F'. + + + @param Char The character to check against. + + @retval TRUE If the Char is a hexadecmial character. + @retval FALSE If the Char is not a hexadecmial character. + +**/ +BOOLEAN +EFIAPI +InternalIsHexaDecimalDigitCharacter ( + IN CHAR16 Char + ) +{ + + return (BOOLEAN) (InternalIsDecimalDigitCharacter (Char) || + (Char >= L'A' && Char <= L'F') || + (Char >= L'a' && Char <= L'f')); +} + +/** + Convert a Null-terminated Unicode decimal string to a value of + type UINTN. + + This function returns a value of type UINTN by interpreting the contents + of the Unicode string specified by String as a decimal number. The format + of the input Unicode string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The + function will ignore the pad space, which includes spaces or + tab characters, before [decimal digits]. The running zero in the + beginning of [decimal digits] will be ignored. Then, the function + stops at the first character that is a not a valid decimal character + or a Null-terminator, whichever one comes first. + + If String is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If String has only pad spaces, then 0 is returned. + If String has no pad spaces or valid decimal digits, + then 0 is returned. + If the number represented by String overflows according + to the range defined by UINTN, then MAX_UINTN is returned. + + If PcdMaximumUnicodeStringLength is not zero, and String contains + more than PcdMaximumUnicodeStringLength Unicode characters, not including + the Null-terminator, then ASSERT(). + + @param String A pointer to a Null-terminated Unicode string. + + @retval Value translated from String. + +**/ +UINTN +EFIAPI +StrDecimalToUintn ( + IN CONST CHAR16 *String + ) +{ + UINTN Result; + + StrDecimalToUintnS (String, (CHAR16 **) NULL, &Result); + return Result; +} + + +/** + Convert a Null-terminated Unicode decimal string to a value of + type UINT64. + + This function returns a value of type UINT64 by interpreting the contents + of the Unicode string specified by String as a decimal number. The format + of the input Unicode string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The + function will ignore the pad space, which includes spaces or + tab characters, before [decimal digits]. The running zero in the + beginning of [decimal digits] will be ignored. Then, the function + stops at the first character that is a not a valid decimal character + or a Null-terminator, whichever one comes first. + + If String is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If String has only pad spaces, then 0 is returned. + If String has no pad spaces or valid decimal digits, + then 0 is returned. + If the number represented by String overflows according + to the range defined by UINT64, then MAX_UINT64 is returned. + + If PcdMaximumUnicodeStringLength is not zero, and String contains + more than PcdMaximumUnicodeStringLength Unicode characters, not including + the Null-terminator, then ASSERT(). + + @param String A pointer to a Null-terminated Unicode string. + + @retval Value translated from String. + +**/ +UINT64 +EFIAPI +StrDecimalToUint64 ( + IN CONST CHAR16 *String + ) +{ + UINT64 Result; + + StrDecimalToUint64S (String, (CHAR16 **) NULL, &Result); + return Result; +} + +/** + Convert a Null-terminated Unicode hexadecimal string to a value of type UINTN. + + This function returns a value of type UINTN by interpreting the contents + of the Unicode string specified by String as a hexadecimal number. + The format of the input Unicode string String is: + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. + If "x" appears in the input string, it must be prefixed with at least one 0. + The function will ignore the pad space, which includes spaces or tab characters, + before [zeros], [x] or [hexadecimal digit]. The running zero before [x] or + [hexadecimal digit] will be ignored. Then, the decoding starts after [x] or the + first valid hexadecimal digit. Then, the function stops at the first character that is + a not a valid hexadecimal character or NULL, whichever one comes first. + + If String is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If String has only pad spaces, then zero is returned. + If String has no leading pad spaces, leading zeros or valid hexadecimal digits, + then zero is returned. + If the number represented by String overflows according to the range defined by + UINTN, then MAX_UINTN is returned. + + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator, + then ASSERT(). + + @param String A pointer to a Null-terminated Unicode string. + + @retval Value translated from String. + +**/ +UINTN +EFIAPI +StrHexToUintn ( + IN CONST CHAR16 *String + ) +{ + UINTN Result; + + StrHexToUintnS (String, (CHAR16 **) NULL, &Result); + return Result; +} + + +/** + Convert a Null-terminated Unicode hexadecimal string to a value of type UINT64. + + This function returns a value of type UINT64 by interpreting the contents + of the Unicode string specified by String as a hexadecimal number. + The format of the input Unicode string String is + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. + If "x" appears in the input string, it must be prefixed with at least one 0. + The function will ignore the pad space, which includes spaces or tab characters, + before [zeros], [x] or [hexadecimal digit]. The running zero before [x] or + [hexadecimal digit] will be ignored. Then, the decoding starts after [x] or the + first valid hexadecimal digit. Then, the function stops at the first character that is + a not a valid hexadecimal character or NULL, whichever one comes first. + + If String is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If String has only pad spaces, then zero is returned. + If String has no leading pad spaces, leading zeros or valid hexadecimal digits, + then zero is returned. + If the number represented by String overflows according to the range defined by + UINT64, then MAX_UINT64 is returned. + + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator, + then ASSERT(). + + @param String A pointer to a Null-terminated Unicode string. + + @retval Value translated from String. + +**/ +UINT64 +EFIAPI +StrHexToUint64 ( + IN CONST CHAR16 *String + ) +{ + UINT64 Result; + + StrHexToUint64S (String, (CHAR16 **) NULL, &Result); + return Result; +} + +/** + Check if a ASCII character is a decimal character. + + This internal function checks if a Unicode character is a + decimal character. The valid decimal character is from + '0' to '9'. + + @param Char The character to check against. + + @retval TRUE If the Char is a decmial character. + @retval FALSE If the Char is not a decmial character. + +**/ +BOOLEAN +EFIAPI +InternalAsciiIsDecimalDigitCharacter ( + IN CHAR8 Char + ) +{ + return (BOOLEAN) (Char >= '0' && Char <= '9'); +} + +/** + Check if a ASCII character is a hexadecimal character. + + This internal function checks if a ASCII character is a + decimal character. The valid hexadecimal character is + L'0' to L'9', L'a' to L'f', or L'A' to L'F'. + + + @param Char The character to check against. + + @retval TRUE If the Char is a hexadecmial character. + @retval FALSE If the Char is not a hexadecmial character. + +**/ +BOOLEAN +EFIAPI +InternalAsciiIsHexaDecimalDigitCharacter ( + IN CHAR8 Char + ) +{ + + return (BOOLEAN) (InternalAsciiIsDecimalDigitCharacter (Char) || + (Char >= 'A' && Char <= 'F') || + (Char >= 'a' && Char <= 'f')); +} + +/** + Returns the length of a Null-terminated ASCII string. + + This function returns the number of ASCII characters in the Null-terminated + ASCII string specified by String. + + If Length > 0 and Destination is NULL, then ASSERT(). + If Length > 0 and Source is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and String contains more than + PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, + then ASSERT(). + + @param String A pointer to a Null-terminated ASCII string. + + @return The length of String. + +**/ +UINTN +EFIAPI +AsciiStrLen ( + IN CONST CHAR8 *String + ) +{ + UINTN Length; + + ASSERT (String != NULL); + + for (Length = 0; *String != '\0'; String++, Length++) { + // + // If PcdMaximumUnicodeStringLength is not zero, + // length should not more than PcdMaximumUnicodeStringLength + // + } + return Length; +} + +/** + Returns the size of a Null-terminated ASCII string in bytes, including the + Null terminator. + + This function returns the size, in bytes, of the Null-terminated ASCII string + specified by String. + + If String is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and String contains more than + PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, + then ASSERT(). + + @param String A pointer to a Null-terminated ASCII string. + + @return The size of String. + +**/ +UINTN +EFIAPI +AsciiStrSize ( + IN CONST CHAR8 *String + ) +{ + return (AsciiStrLen (String) + 1) * sizeof (*String); +} + +/** + Compares two Null-terminated ASCII strings, and returns the difference + between the first mismatched ASCII characters. + + This function compares the Null-terminated ASCII string FirstString to the + Null-terminated ASCII string SecondString. If FirstString is identical to + SecondString, then 0 is returned. Otherwise, the value returned is the first + mismatched ASCII character in SecondString subtracted from the first + mismatched ASCII character in FirstString. + + If FirstString is NULL, then ASSERT(). + If SecondString is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and FirstString contains more than + PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, + then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and SecondString contains more + than PcdMaximumAsciiStringLength ASCII characters, not including the + Null-terminator, then ASSERT(). + + @param FirstString A pointer to a Null-terminated ASCII string. + @param SecondString A pointer to a Null-terminated ASCII string. + + @retval ==0 FirstString is identical to SecondString. + @retval !=0 FirstString is not identical to SecondString. + +**/ +INTN +EFIAPI +AsciiStrCmp ( + IN CONST CHAR8 *FirstString, + IN CONST CHAR8 *SecondString + ) +{ + // + // ASSERT both strings are less long than PcdMaximumAsciiStringLength + // + ASSERT (AsciiStrSize (FirstString)); + ASSERT (AsciiStrSize (SecondString)); + + while ((*FirstString != '\0') && (*FirstString == *SecondString)) { + FirstString++; + SecondString++; + } + + return *FirstString - *SecondString; +} + +/** + Converts a lowercase Ascii character to upper one. + + If Chr is lowercase Ascii character, then converts it to upper one. + + If Value >= 0xA0, then ASSERT(). + If (Value & 0x0F) >= 0x0A, then ASSERT(). + + @param Chr one Ascii character + + @return The uppercase value of Ascii character + +**/ +CHAR8 +EFIAPI +InternalBaseLibAsciiToUpper ( + IN CHAR8 Chr + ) +{ + return (UINT8) ((Chr >= 'a' && Chr <= 'z') ? Chr - ('a' - 'A') : Chr); +} + +/** + Convert a ASCII character to numerical value. + + This internal function only deal with Unicode character + which maps to a valid hexadecimal ASII character, i.e. + '0' to '9', 'a' to 'f' or 'A' to 'F'. For other + ASCII character, the value returned does not make sense. + + @param Char The character to convert. + + @return The numerical value converted. + +**/ +UINTN +EFIAPI +InternalAsciiHexCharToUintn ( + IN CHAR8 Char + ) +{ + if (InternalIsDecimalDigitCharacter (Char)) { + return Char - '0'; + } + + return (10 + InternalBaseLibAsciiToUpper (Char) - 'A'); +} + + +/** + Performs a case insensitive comparison of two Null-terminated ASCII strings, + and returns the difference between the first mismatched ASCII characters. + + This function performs a case insensitive comparison of the Null-terminated + ASCII string FirstString to the Null-terminated ASCII string SecondString. If + FirstString is identical to SecondString, then 0 is returned. Otherwise, the + value returned is the first mismatched lower case ASCII character in + SecondString subtracted from the first mismatched lower case ASCII character + in FirstString. + + If FirstString is NULL, then ASSERT(). + If SecondString is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and FirstString contains more than + PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, + then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and SecondString contains more + than PcdMaximumAsciiStringLength ASCII characters, not including the + Null-terminator, then ASSERT(). + + @param FirstString A pointer to a Null-terminated ASCII string. + @param SecondString A pointer to a Null-terminated ASCII string. + + @retval ==0 FirstString is identical to SecondString using case insensitive + comparisons. + @retval !=0 FirstString is not identical to SecondString using case + insensitive comparisons. + +**/ +INTN +EFIAPI +AsciiStriCmp ( + IN CONST CHAR8 *FirstString, + IN CONST CHAR8 *SecondString + ) +{ + CHAR8 UpperFirstString; + CHAR8 UpperSecondString; + + // + // ASSERT both strings are less long than PcdMaximumAsciiStringLength + // + ASSERT (AsciiStrSize (FirstString)); + ASSERT (AsciiStrSize (SecondString)); + + UpperFirstString = InternalBaseLibAsciiToUpper (*FirstString); + UpperSecondString = InternalBaseLibAsciiToUpper (*SecondString); + while ((*FirstString != '\0') && (*SecondString != '\0') && (UpperFirstString == UpperSecondString)) { + FirstString++; + SecondString++; + UpperFirstString = InternalBaseLibAsciiToUpper (*FirstString); + UpperSecondString = InternalBaseLibAsciiToUpper (*SecondString); + } + + return UpperFirstString - UpperSecondString; +} + +/** + Compares two Null-terminated ASCII strings with maximum lengths, and returns + the difference between the first mismatched ASCII characters. + + This function compares the Null-terminated ASCII string FirstString to the + Null-terminated ASCII string SecondString. At most, Length ASCII characters + will be compared. If Length is 0, then 0 is returned. If FirstString is + identical to SecondString, then 0 is returned. Otherwise, the value returned + is the first mismatched ASCII character in SecondString subtracted from the + first mismatched ASCII character in FirstString. + + If Length > 0 and FirstString is NULL, then ASSERT(). + If Length > 0 and SecondString is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and Length is greater than + PcdMaximumAsciiStringLength, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and FirstString contains more than + PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, + then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and SecondString contains more than + PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, + then ASSERT(). + + @param FirstString A pointer to a Null-terminated ASCII string. + @param SecondString A pointer to a Null-terminated ASCII string. + @param Length The maximum number of ASCII characters for compare. + + @retval ==0 FirstString is identical to SecondString. + @retval !=0 FirstString is not identical to SecondString. + +**/ +INTN +EFIAPI +AsciiStrnCmp ( + IN CONST CHAR8 *FirstString, + IN CONST CHAR8 *SecondString, + IN UINTN Length + ) +{ + if (Length == 0) { + return 0; + } + + // + // ASSERT both strings are less long than PcdMaximumAsciiStringLength + // + ASSERT (AsciiStrSize (FirstString)); + ASSERT (AsciiStrSize (SecondString)); + + while ((*FirstString != '\0') && + (*SecondString != '\0') && + (*FirstString == *SecondString) && + (Length > 1)) { + FirstString++; + SecondString++; + Length--; + } + return *FirstString - *SecondString; +} + +/** + Returns the first occurrence of a Null-terminated ASCII sub-string + in a Null-terminated ASCII string. + + This function scans the contents of the ASCII string specified by String + and returns the first occurrence of SearchString. If SearchString is not + found in String, then NULL is returned. If the length of SearchString is zero, + then String is returned. + + If String is NULL, then ASSERT(). + If SearchString is NULL, then ASSERT(). + + If PcdMaximumAsciiStringLength is not zero, and SearchString or + String contains more than PcdMaximumAsciiStringLength Unicode characters + not including the Null-terminator, then ASSERT(). + + @param String A pointer to a Null-terminated ASCII string. + @param SearchString A pointer to a Null-terminated ASCII string to search for. + + @retval NULL If the SearchString does not appear in String. + @retval others If there is a match return the first occurrence of SearchingString. + If the length of SearchString is zero,return String. + +**/ +CHAR8 * +EFIAPI +AsciiStrStr ( + IN CONST CHAR8 *String, + IN CONST CHAR8 *SearchString + ) +{ + CONST CHAR8 *FirstMatch; + CONST CHAR8 *SearchStringTmp; + + // + // ASSERT both strings are less long than PcdMaximumAsciiStringLength + // + ASSERT (AsciiStrSize (String) != 0); + ASSERT (AsciiStrSize (SearchString) != 0); + + if (*SearchString == '\0') { + return (CHAR8 *) String; + } + + while (*String != '\0') { + SearchStringTmp = SearchString; + FirstMatch = String; + + while ((*String == *SearchStringTmp) + && (*String != '\0')) { + String++; + SearchStringTmp++; + } + + if (*SearchStringTmp == '\0') { + return (CHAR8 *) FirstMatch; + } + + if (*String == '\0') { + return NULL; + } + + String = FirstMatch + 1; + } + + return NULL; +} + +/** + Convert a Null-terminated ASCII decimal string to a value of type + UINTN. + + This function returns a value of type UINTN by interpreting the contents + of the ASCII string String as a decimal number. The format of the input + ASCII string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The function will + ignore the pad space, which includes spaces or tab characters, before the digits. + The running zero in the beginning of [decimal digits] will be ignored. Then, the + function stops at the first character that is a not a valid decimal character or + Null-terminator, whichever on comes first. + + If String has only pad spaces, then 0 is returned. + If String has no pad spaces or valid decimal digits, then 0 is returned. + If the number represented by String overflows according to the range defined by + UINTN, then MAX_UINTN is returned. + If String is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and String contains more than + PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, + then ASSERT(). + + @param String A pointer to a Null-terminated ASCII string. + + @retval Value translated from String. + +**/ +UINTN +EFIAPI +AsciiStrDecimalToUintn ( + IN CONST CHAR8 *String + ) +{ + UINTN Result; + + AsciiStrDecimalToUintnS (String, (CHAR8 **) NULL, &Result); + return Result; +} + + +/** + Convert a Null-terminated ASCII decimal string to a value of type + UINT64. + + This function returns a value of type UINT64 by interpreting the contents + of the ASCII string String as a decimal number. The format of the input + ASCII string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The function will + ignore the pad space, which includes spaces or tab characters, before the digits. + The running zero in the beginning of [decimal digits] will be ignored. Then, the + function stops at the first character that is a not a valid decimal character or + Null-terminator, whichever on comes first. + + If String has only pad spaces, then 0 is returned. + If String has no pad spaces or valid decimal digits, then 0 is returned. + If the number represented by String overflows according to the range defined by + UINT64, then MAX_UINT64 is returned. + If String is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and String contains more than + PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, + then ASSERT(). + + @param String A pointer to a Null-terminated ASCII string. + + @retval Value translated from String. + +**/ +UINT64 +EFIAPI +AsciiStrDecimalToUint64 ( + IN CONST CHAR8 *String + ) +{ + UINT64 Result; + + AsciiStrDecimalToUint64S (String, (CHAR8 **) NULL, &Result); + return Result; +} + +/** + Convert a Null-terminated ASCII hexadecimal string to a value of type UINTN. + + This function returns a value of type UINTN by interpreting the contents of + the ASCII string String as a hexadecimal number. The format of the input ASCII + string String is: + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. If "x" + appears in the input string, it must be prefixed with at least one 0. The function + will ignore the pad space, which includes spaces or tab characters, before [zeros], + [x] or [hexadecimal digits]. The running zero before [x] or [hexadecimal digits] + will be ignored. Then, the decoding starts after [x] or the first valid hexadecimal + digit. Then, the function stops at the first character that is a not a valid + hexadecimal character or Null-terminator, whichever on comes first. + + If String has only pad spaces, then 0 is returned. + If String has no leading pad spaces, leading zeros or valid hexadecimal digits, then + 0 is returned. + + If the number represented by String overflows according to the range defined by UINTN, + then MAX_UINTN is returned. + If String is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, + and String contains more than PcdMaximumAsciiStringLength ASCII characters not including + the Null-terminator, then ASSERT(). + + @param String A pointer to a Null-terminated ASCII string. + + @retval Value translated from String. + +**/ +UINTN +EFIAPI +AsciiStrHexToUintn ( + IN CONST CHAR8 *String + ) +{ + UINTN Result; + + AsciiStrHexToUintnS (String, (CHAR8 **) NULL, &Result); + return Result; +} + + +/** + Convert a Null-terminated ASCII hexadecimal string to a value of type UINT64. + + This function returns a value of type UINT64 by interpreting the contents of + the ASCII string String as a hexadecimal number. The format of the input ASCII + string String is: + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. If "x" + appears in the input string, it must be prefixed with at least one 0. The function + will ignore the pad space, which includes spaces or tab characters, before [zeros], + [x] or [hexadecimal digits]. The running zero before [x] or [hexadecimal digits] + will be ignored. Then, the decoding starts after [x] or the first valid hexadecimal + digit. Then, the function stops at the first character that is a not a valid + hexadecimal character or Null-terminator, whichever on comes first. + + If String has only pad spaces, then 0 is returned. + If String has no leading pad spaces, leading zeros or valid hexadecimal digits, then + 0 is returned. + + If the number represented by String overflows according to the range defined by UINT64, + then MAX_UINT64 is returned. + If String is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, + and String contains more than PcdMaximumAsciiStringLength ASCII characters not including + the Null-terminator, then ASSERT(). + + @param String A pointer to a Null-terminated ASCII string. + + @retval Value translated from String. + +**/ +UINT64 +EFIAPI +AsciiStrHexToUint64 ( + IN CONST CHAR8 *String + ) +{ + UINT64 Result; + + AsciiStrHexToUint64S (String, (CHAR8 **) NULL, &Result); + return Result; +} + +/** + Converts an 8-bit value to an 8-bit BCD value. + + Converts the 8-bit value specified by Value to BCD. The BCD value is + returned. + + If Value >= 100, then ASSERT(). + + @param Value The 8-bit value to convert to BCD. Range 0..99. + + @return The BCD value. + +**/ +UINT8 +EFIAPI +DecimalToBcd8 ( + IN UINT8 Value + ) +{ + ASSERT (Value < 100); + return (UINT8) (((Value / 10) << 4) | (Value % 10)); +} + +/** + Converts an 8-bit BCD value to an 8-bit value. + + Converts the 8-bit BCD value specified by Value to an 8-bit value. The 8-bit + value is returned. + + If Value >= 0xA0, then ASSERT(). + If (Value & 0x0F) >= 0x0A, then ASSERT(). + + @param Value The 8-bit BCD value to convert to an 8-bit value. + + @return The 8-bit value is returned. + +**/ +UINT8 +EFIAPI +BcdToDecimal8 ( + IN UINT8 Value + ) +{ + ASSERT (Value < 0xa0); + ASSERT ((Value & 0xf) < 0xa); + return (UINT8) ((Value >> 4) * 10 + (Value & 0xf)); +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/SwapBytes16.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/SwapBytes16.c new file mode 100644 index 0000000..c044447 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/SwapBytes16.c @@ -0,0 +1,31 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +/** + Switches the endianess of a 16-bit integer. + + This function swaps the bytes in a 16-bit unsigned value to switch the value + from little endian to big endian or vice versa. The byte swapped value is + returned. + + @param Value A 16-bit unsigned value. + + @return The byte swapped Value. + +**/ +UINT16 +EFIAPI +SwapBytes16 ( + IN UINT16 Value + ) +{ + return (UINT16) ((Value<< 8) | (Value>> 8)); +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/SwapBytes32.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/SwapBytes32.c new file mode 100644 index 0000000..5e2d0ed --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/SwapBytes32.c @@ -0,0 +1,37 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +/** + Switches the endianess of a 32-bit integer. + + This function swaps the bytes in a 32-bit unsigned value to switch the value + from little endian to big endian or vice versa. The byte swapped value is + returned. + + @param Value A 32-bit unsigned value. + + @return The byte swapped Value. + +**/ +UINT32 +EFIAPI +SwapBytes32 ( + IN UINT32 Value + ) +{ + UINT32 LowerBytes; + UINT32 HigherBytes; + + LowerBytes = (UINT32) SwapBytes16 ((UINT16) Value); + HigherBytes = (UINT32) SwapBytes16 ((UINT16) (Value >> 16)); + + return (LowerBytes << 16 | HigherBytes); +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/SwapBytes64.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/SwapBytes64.c new file mode 100644 index 0000000..f565801 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/SwapBytes64.c @@ -0,0 +1,37 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +UINT64 +EFIAPI +InternalMathSwapBytes64 ( + IN UINT64 Operand + ); + +/** + Switches the endianess of a 64-bit integer. + + This function swaps the bytes in a 64-bit unsigned value to switch the value + from little endian to big endian or vice versa. The byte swapped value is + returned. + + @param Value A 64-bit unsigned value. + + @return The byte swapped Value. + +**/ +UINT64 +EFIAPI +SwapBytes64 ( + IN UINT64 Value + ) +{ + return InternalMathSwapBytes64 (Value); +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/SwitchStackNull.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/SwitchStackNull.c new file mode 100644 index 0000000..b011c14 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/SwitchStackNull.c @@ -0,0 +1,52 @@ +/** @file + Switch Stack functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +/** + Transfers control to a function starting with a new stack. + + Transfers control to the function specified by EntryPoint using the + new stack specified by NewStack and passing in the parameters specified + by Context1 and Context2. Context1 and Context2 are optional and may + be NULL. The function EntryPoint must never return. This function + supports a variable number of arguments following the NewStack parameter. + These additional arguments are ignored on IA-32, x64, and EBC. + IPF CPUs expect one additional parameter of type VOID * that specifies + the new backing store pointer. + + If EntryPoint is NULL, then ASSERT(). + If NewStack is NULL, then ASSERT(). + + @param EntryPoint A pointer to function to call with the new stack. + @param Context1 A pointer to the context to pass into the EntryPoint + function. + @param Context2 A pointer to the context to pass into the EntryPoint + function. + @param NewStack A pointer to the new stack to use for the EntryPoint + function. + @param ... This variable argument list is ignored for IA32, x64, and EBC. + For IPF, this variable argument list is expected to contain + a single parameter of type VOID * that specifies the new backing + store pointer. + + +**/ +VOID +EFIAPI +SwitchStack ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack, + ... + ) +{ + ASSERT (FALSE); +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/Unaligned.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/Unaligned.c new file mode 100644 index 0000000..fda732b --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/Unaligned.c @@ -0,0 +1,216 @@ +/** @file + Unaligned access functions of BaseLib. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +/** + Reads a 16-bit value from memory that may be unaligned. + + This function returns the 16-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer A pointer to a 16-bit value that may be unaligned. + + @return The 16-bit value read from Buffer. + +**/ +UINT16 +EFIAPI +ReadUnaligned16 ( + IN CONST UINT16 *Buffer + ) +{ + ASSERT (Buffer != NULL); + + return *Buffer; +} + +/** + Writes a 16-bit value to memory that may be unaligned. + + This function writes the 16-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer A pointer to a 16-bit value that may be unaligned. + @param Value 16-bit value to write to Buffer. + + @return The 16-bit value to write to Buffer. + +**/ +UINT16 +EFIAPI +WriteUnaligned16 ( + OUT UINT16 *Buffer, + IN UINT16 Value + ) +{ + ASSERT (Buffer != NULL); + + return *Buffer = Value; +} + +/** + Reads a 24-bit value from memory that may be unaligned. + + This function returns the 24-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer A pointer to a 24-bit value that may be unaligned. + + @return The 24-bit value read from Buffer. + +**/ +UINT32 +EFIAPI +ReadUnaligned24 ( + IN CONST UINT32 *Buffer + ) +{ + ASSERT (Buffer != NULL); + + return *Buffer & 0xffffff; +} + +/** + Writes a 24-bit value to memory that may be unaligned. + + This function writes the 24-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer A pointer to a 24-bit value that may be unaligned. + @param Value 24-bit value to write to Buffer. + + @return The 24-bit value to write to Buffer. + +**/ +UINT32 +EFIAPI +WriteUnaligned24 ( + OUT UINT32 *Buffer, + IN UINT32 Value + ) +{ + ASSERT (Buffer != NULL); + + *Buffer = BitFieldWrite32 (*Buffer, 0, 23, Value); + return Value; +} + +/** + Reads a 32-bit value from memory that may be unaligned. + + This function returns the 32-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer A pointer to a 32-bit value that may be unaligned. + + @return The 32-bit value read from Buffer. + +**/ +UINT32 +EFIAPI +ReadUnaligned32 ( + IN CONST UINT32 *Buffer + ) +{ + ASSERT (Buffer != NULL); + + return *Buffer; +} + +/** + Writes a 32-bit value to memory that may be unaligned. + + This function writes the 32-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer A pointer to a 32-bit value that may be unaligned. + @param Value The 32-bit value to write to Buffer. + + @return The 32-bit value to write to Buffer. + +**/ +UINT32 +EFIAPI +WriteUnaligned32 ( + OUT UINT32 *Buffer, + IN UINT32 Value + ) +{ + ASSERT (Buffer != NULL); + + return *Buffer = Value; +} + +/** + Reads a 64-bit value from memory that may be unaligned. + + This function returns the 64-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer A pointer to a 64-bit value that may be unaligned. + + @return The 64-bit value read from Buffer. + +**/ +UINT64 +EFIAPI +ReadUnaligned64 ( + IN CONST UINT64 *Buffer + ) +{ + ASSERT (Buffer != NULL); + + return *Buffer; +} + +/** + Writes a 64-bit value to memory that may be unaligned. + + This function writes the 64-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer A pointer to a 64-bit value that may be unaligned. + @param Value The 64-bit value to write to Buffer. + + @return The 64-bit value to write to Buffer. + +**/ +UINT64 +EFIAPI +WriteUnaligned64 ( + OUT UINT64 *Buffer, + IN UINT64 Value + ) +{ + ASSERT (Buffer != NULL); + + return *Buffer = Value; +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/X64/RdRand.nasm b/HBFA/UefiHostTestPkg/Library/BaseLibHost/X64/RdRand.nasm new file mode 100644 index 0000000..7e7fe99 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/X64/RdRand.nasm @@ -0,0 +1,77 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; RdRand.nasm +; +; Abstract: +; +; Generates random number through CPU RdRand instruction under 64-bit platform. +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; Generates a 16 bit random number through RDRAND instruction. +; Return TRUE if Rand generated successfully, or FALSE if not. +; +; BOOLEAN EFIAPI InternalX86RdRand16 (UINT16 *Rand); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalX86RdRand16) +ASM_PFX(InternalX86RdRand16): + ; rdrand ax ; generate a 16 bit RN into eax, + ; CF=1 if RN generated ok, otherwise CF=0 + db 0xf, 0xc7, 0xf0 ; rdrand r16: "0f c7 /6 ModRM:r/m(w)" + jc rn16_ok ; jmp if CF=1 + xor rax, rax ; reg=0 if CF=0 + ret ; return with failure status +rn16_ok: + mov [rcx], ax + mov rax, 1 + ret + +;------------------------------------------------------------------------------ +; Generates a 32 bit random number through RDRAND instruction. +; Return TRUE if Rand generated successfully, or FALSE if not. +; +; BOOLEAN EFIAPI InternalX86RdRand32 (UINT32 *Rand); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalX86RdRand32) +ASM_PFX(InternalX86RdRand32): + ; rdrand eax ; generate a 32 bit RN into eax, + ; CF=1 if RN generated ok, otherwise CF=0 + db 0xf, 0xc7, 0xf0 ; rdrand r32: "0f c7 /6 ModRM:r/m(w)" + jc rn32_ok ; jmp if CF=1 + xor rax, rax ; reg=0 if CF=0 + ret ; return with failure status +rn32_ok: + mov [rcx], eax + mov rax, 1 + ret + +;------------------------------------------------------------------------------ +; Generates a 64 bit random number through one RDRAND instruction. +; Return TRUE if Rand generated successfully, or FALSE if not. +; +; BOOLEAN EFIAPI InternalX86RdRand64 (UINT64 *Random); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalX86RdRand64) +ASM_PFX(InternalX86RdRand64): + ; rdrand rax ; generate a 64 bit RN into rax, + ; CF=1 if RN generated ok, otherwise CF=0 + db 0x48, 0xf, 0xc7, 0xf0 ; rdrand r64: "REX.W + 0f c7 /6 ModRM:r/m(w)" + jc rn64_ok ; jmp if CF=1 + xor rax, rax ; reg=0 if CF=0 + ret ; return with failure status +rn64_ok: + mov [rcx], rax + mov rax, 1 + ret + diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/X64/ReadTsc.nasm b/HBFA/UefiHostTestPkg/Library/BaseLibHost/X64/ReadTsc.nasm new file mode 100644 index 0000000..45672d6 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/X64/ReadTsc.nasm @@ -0,0 +1,34 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ReadTsc.Asm +; +; Abstract: +; +; AsmReadTsc function +; +; Notes: +; +;------------------------------------------------------------------------------ + + DEFAULT REL + SECTION .text + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadTsc ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(AsmReadTsc) +ASM_PFX(AsmReadTsc): + rdtsc + shl rdx, 0x20 + or rax, rdx + ret + diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86Cr.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86Cr.c new file mode 100644 index 0000000..ab16ca6 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86Cr.c @@ -0,0 +1,180 @@ +/** @file + Base Library CPU Functions for all architectures. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +UINTN gCr0; +UINTN gCr2; +UINTN gCr3; +UINTN gCr4; + +/** + Reads the current value of the Control Register 0 (CR0). + + Reads and returns the current value of CR0. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of the Control Register 0 (CR0). + +**/ +UINTN +EFIAPI +AsmReadCr0 ( + VOID + ) +{ + return gCr0; +} + + +/** + Reads the current value of the Control Register 2 (CR2). + + Reads and returns the current value of CR2. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of the Control Register 2 (CR2). + +**/ +UINTN +EFIAPI +AsmReadCr2 ( + VOID + ) +{ + return gCr2; +} + + +/** + Reads the current value of the Control Register 3 (CR3). + + Reads and returns the current value of CR3. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of the Control Register 3 (CR3). + +**/ +UINTN +EFIAPI +AsmReadCr3 ( + VOID + ) +{ + return gCr3; +} + + +/** + Reads the current value of the Control Register 4 (CR4). + + Reads and returns the current value of CR4. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of the Control Register 4 (CR4). + +**/ +UINTN +EFIAPI +AsmReadCr4 ( + VOID + ) +{ + return gCr4; +} + + +/** + Writes a value to Control Register 0 (CR0). + + Writes and returns a new value to CR0. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Cr0 The value to write to CR0. + + @return The value written to CR0. + +**/ +UINTN +EFIAPI +AsmWriteCr0 ( + UINTN Cr0 + ) +{ + gCr0 = Cr0; + return Cr0; +} + +/** + Writes a value to Control Register 2 (CR2). + + Writes and returns a new value to CR2. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Cr2 The value to write to CR2. + + @return The value written to CR2. + +**/ +UINTN +EFIAPI +AsmWriteCr2 ( + UINTN Cr2 + ) +{ + gCr2 = Cr2; + return Cr2; +} + + +/** + Writes a value to Control Register 3 (CR3). + + Writes and returns a new value to CR3. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Cr3 The value to write to CR3. + + @return The value written to CR3. + +**/ +UINTN +EFIAPI +AsmWriteCr3 ( + UINTN Cr3 + ) +{ + gCr3 = Cr3; + return Cr3; +} + + +/** + Writes a value to Control Register 4 (CR4). + + Writes and returns a new value to CR4. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Cr4 The value to write to CR4. + + @return The value written to CR4. + +**/ +UINTN +EFIAPI +AsmWriteCr4 ( + UINTN Cr4 + ) +{ + gCr4 = Cr4; + return Cr4; +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86DisablePaging64Null.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86DisablePaging64Null.c new file mode 100644 index 0000000..255264f --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86DisablePaging64Null.c @@ -0,0 +1,53 @@ +/** @file + IA-32/x64 AsmDisablePaging64() + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +/** + Disables the 64-bit paging mode on the CPU. + + Disables the 64-bit paging mode on the CPU and returns to 32-bit protected + mode. This function assumes the current execution mode is 64-paging mode. + This function is only available on x64. After the 64-bit paging mode is + disabled, control is transferred to the function specified by EntryPoint + using the new stack specified by NewStack and passing in the parameters + specified by Context1 and Context2. Context1 and Context2 are optional and + may be 0. The function EntryPoint must never return. + + If the current execution mode is not 64-bit paged mode, then ASSERT(). + If EntryPoint is 0, then ASSERT(). + If NewStack is 0, then ASSERT(). + + @param Cs The 16-bit selector to load in the CS before EntryPoint + is called. The descriptor in the GDT that this selector + references must be setup for 32-bit protected mode. + @param EntryPoint The 64-bit virtual address of the function to call with + the new stack after paging is disabled. + @param Context1 The 64-bit virtual address of the context to pass into + the EntryPoint function as the first parameter after + paging is disabled. + @param Context2 The 64-bit virtual address of the context to pass into + the EntryPoint function as the second parameter after + paging is disabled. + @param NewStack The 64-bit virtual address of the new stack to use for + the EntryPoint function after paging is disabled. + +**/ +VOID +EFIAPI +AsmDisablePaging64 ( + IN UINT16 Cs, + IN UINT32 EntryPoint, + IN UINT32 Context1, OPTIONAL + IN UINT32 Context2, OPTIONAL + IN UINT32 NewStack + ) +{ + ASSERT (FALSE); +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86Dr.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86Dr.c new file mode 100644 index 0000000..057ec97 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86Dr.c @@ -0,0 +1,170 @@ +/** @file + Base Library CPU Functions for all architectures. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +UINTN gDr0; +UINTN gDr1; +UINTN gDr2; +UINTN gDr3; +UINTN gDr4; +UINTN gDr5; +UINTN gDr6; +UINTN gDr7; + +UINTN +EFIAPI +AsmReadDr0 ( + VOID + ) +{ + return gDr0; +} + +UINTN +EFIAPI +AsmReadDr1 ( + VOID + ) +{ + return gDr1; +} + +UINTN +EFIAPI +AsmReadDr2 ( + VOID + ) +{ + return gDr2; +} + +UINTN +EFIAPI +AsmReadDr3 ( + VOID + ) +{ + return gDr3; +} + +UINTN +EFIAPI +AsmReadDr4 ( + VOID + ) +{ + return gDr4; +} + +UINTN +EFIAPI +AsmReadDr5 ( + VOID + ) +{ + return gDr5; +} + +UINTN +EFIAPI +AsmReadDr6 ( + VOID + ) +{ + return gDr6; +} + +UINTN +EFIAPI +AsmReadDr7 ( + VOID + ) +{ + return gDr7; +} + +UINTN +EFIAPI +AsmWriteDr0 ( + UINTN Dr0 + ) +{ + gDr0 = Dr0; + return Dr0; +} + +UINTN +EFIAPI +AsmWriteDr1 ( + UINTN Dr1 + ) +{ + gDr1 = Dr1; + return Dr1; +} + +UINTN +EFIAPI +AsmWriteDr2 ( + UINTN Dr2 + ) +{ + gDr2 = Dr2; + return Dr2; +} + +UINTN +EFIAPI +AsmWriteDr3 ( + UINTN Dr3 + ) +{ + gDr3 = Dr3; + return Dr3; +} + +UINTN +EFIAPI +AsmWriteDr4 ( + UINTN Dr4 + ) +{ + gDr4 = Dr4; + return Dr4; +} + +UINTN +EFIAPI +AsmWriteDr5 ( + UINTN Dr5 + ) +{ + gDr5 = Dr5; + return Dr5; +} + +UINTN +EFIAPI +AsmWriteDr6 ( + UINTN Dr6 + ) +{ + gDr6 = Dr6; + return Dr6; +} + +UINTN +EFIAPI +AsmWriteDr7 ( + UINTN Dr7 + ) +{ + gDr7 = Dr7; + return Dr7; +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86GdtrNull.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86GdtrNull.c new file mode 100644 index 0000000..9a7a7da --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86GdtrNull.c @@ -0,0 +1,50 @@ +/** @file + IA-32/x64 AsmReadGdtr() + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +/** + Reads the current Global Descriptor Table Register(GDTR) descriptor. + + Reads and returns the current GDTR descriptor and returns it in Gdtr. This + function is only available on IA-32 and x64. + + If Gdtr is NULL, then ASSERT(). + + @param Gdtr The pointer to a GDTR descriptor. + +**/ +VOID +EFIAPI +AsmReadGdtr ( + OUT IA32_DESCRIPTOR *Gdtr + ) +{ + ASSERT (FALSE); +} + +/** + Writes the current Global Descriptor Table Register (GDTR) descriptor. + + Writes and the current GDTR descriptor specified by Gdtr. This function is + only available on IA-32 and x64. + + If Gdtr is NULL, then ASSERT(). + + @param Gdtr The pointer to a GDTR descriptor. + +**/ +VOID +EFIAPI +AsmWriteGdtr ( + IN CONST IA32_DESCRIPTOR *Gdtr + ) +{ + ASSERT (FALSE); +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86IdtrNull.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86IdtrNull.c new file mode 100644 index 0000000..3fb1aa8 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86IdtrNull.c @@ -0,0 +1,50 @@ +/** @file + IA-32/x64 AsmReadIdtr() + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +/** + Reads the current Interrupt Descriptor Table Register(IDTR) descriptor. + + Reads and returns the current IDTR descriptor and returns it in Idtr. This + function is only available on IA-32 and x64. + + If Idtr is NULL, then ASSERT(). + + @param Idtr The pointer to a IDTR descriptor. + +**/ +VOID +EFIAPI +AsmReadIdtr ( + OUT IA32_DESCRIPTOR *Idtr + ) +{ + ASSERT (FALSE); +} + +/** + Writes the current Interrupt Descriptor Table Register(IDTR) descriptor. + + Writes the current IDTR descriptor and returns it in Idtr. This function is + only available on IA-32 and x64. + + If Idtr is NULL, then ASSERT(). + + @param Idtr The pointer to a IDTR descriptor. + +**/ +VOID +EFIAPI +AsmWriteIdtr ( + IN CONST IA32_DESCRIPTOR *Idtr + ) +{ + ASSERT (FALSE); +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86MemoryFenceGcc.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86MemoryFenceGcc.c new file mode 100644 index 0000000..da85c1b --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86MemoryFenceGcc.c @@ -0,0 +1,29 @@ +/** @file + GCC inline implementation of BaseLib processor specific functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +/** + Used to serialize load and store operations. + + All loads and stores that proceed calls to this function are guaranteed to be + globally visible when this function returns. + +**/ +VOID +EFIAPI +MemoryFence ( + VOID + ) +{ + // This is a little bit of overkill and it is more about the compiler that it is + // actually processor synchronization. This is like the _ReadWriteBarrier + // Microsoft specific intrinsic + __asm__ __volatile__ ("":::"memory"); +} + diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86MemoryFenceMsvc.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86MemoryFenceMsvc.c new file mode 100644 index 0000000..5e61a4a --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86MemoryFenceMsvc.c @@ -0,0 +1,27 @@ +/** @file + IA-32/x64 MemoryFence(). + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +void _ReadWriteBarrier (void); +#pragma intrinsic(_ReadWriteBarrier) + +/** + Used to serialize load and store operations. + + All loads and stores that proceed calls to this function are guaranteed to be + globally visible when this function returns. + +**/ +VOID +EFIAPI +MemoryFence ( + VOID + ) +{ + _ReadWriteBarrier (); + return; +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86PatchInstruction.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86PatchInstruction.c new file mode 100644 index 0000000..e833afb --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86PatchInstruction.c @@ -0,0 +1,84 @@ +/** @file + IA-32/x64 PatchInstructionX86() + + Copyright (C) 2018, Intel Corporation. All rights reserved.
+ Copyright (C) 2018, Red Hat, Inc. + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include + +/** + Patch the immediate operand of an IA32 or X64 instruction such that the byte, + word, dword or qword operand is encoded at the end of the instruction's + binary representation. + + This function should be used to update object code that was compiled with + NASM from assembly source code. Example: + + NASM source code: + + mov eax, strict dword 0 ; the imm32 zero operand will be patched + ASM_PFX(gPatchCr3): + mov cr3, eax + + C source code: + + X86_ASSEMBLY_PATCH_LABEL gPatchCr3; + PatchInstructionX86 (gPatchCr3, AsmReadCr3 (), 4); + + @param[out] InstructionEnd Pointer right past the instruction to patch. The + immediate operand to patch is expected to + comprise the trailing bytes of the instruction. + If InstructionEnd is closer to address 0 than + ValueSize permits, then ASSERT(). + + @param[in] PatchValue The constant to write to the immediate operand. + The caller is responsible for ensuring that + PatchValue can be represented in the byte, word, + dword or qword operand (as indicated through + ValueSize); otherwise ASSERT(). + + @param[in] ValueSize The size of the operand in bytes; must be 1, 2, + 4, or 8. ASSERT() otherwise. +**/ +VOID +EFIAPI +PatchInstructionX86 ( + OUT X86_ASSEMBLY_PATCH_LABEL *InstructionEnd, + IN UINT64 PatchValue, + IN UINTN ValueSize + ) +{ + // + // The equality ((UINTN)InstructionEnd == ValueSize) would assume a zero-size + // instruction at address 0; forbid it. + // + ASSERT ((UINTN)InstructionEnd > ValueSize); + + switch (ValueSize) { + case 1: + ASSERT (PatchValue <= MAX_UINT8); + *((UINT8 *)(UINTN)InstructionEnd - 1) = (UINT8)PatchValue; + break; + + case 2: + ASSERT (PatchValue <= MAX_UINT16); + WriteUnaligned16 ((UINT16 *)(UINTN)InstructionEnd - 1, (UINT16)PatchValue); + break; + + case 4: + ASSERT (PatchValue <= MAX_UINT32); + WriteUnaligned32 ((UINT32 *)(UINTN)InstructionEnd - 1, (UINT32)PatchValue); + break; + + case 8: + WriteUnaligned64 ((UINT64 *)(UINTN)InstructionEnd - 1, PatchValue); + break; + + default: + ASSERT (FALSE); + } +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86RdRand.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86RdRand.c new file mode 100644 index 0000000..5f5fa85 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86RdRand.c @@ -0,0 +1,121 @@ +/** @file + IA-32/x64 AsmRdRandxx() + Generates random number through CPU RdRand instruction. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +/** + Generates a 16-bit random number through RDRAND instruction. + + @param[out] Rand Buffer pointer to store the random result. + + @retval TRUE RDRAND call was successful. + @retval FALSE Failed attempts to call RDRAND. + + **/ +BOOLEAN +EFIAPI +InternalX86RdRand16 ( + OUT UINT16 *Rand + ); + +/** + Generates a 32-bit random number through RDRAND instruction. + + @param[out] Rand Buffer pointer to store the random result. + + @retval TRUE RDRAND call was successful. + @retval FALSE Failed attempts to call RDRAND. + +**/ +BOOLEAN +EFIAPI +InternalX86RdRand32 ( + OUT UINT32 *Rand + ); + +/** + Generates a 64-bit random number through RDRAND instruction. + + + @param[out] Rand Buffer pointer to store the random result. + + @retval TRUE RDRAND call was successful. + @retval FALSE Failed attempts to call RDRAND. + +**/ +BOOLEAN +EFIAPI +InternalX86RdRand64 ( + OUT UINT64 *Rand + ); + +/** + Generates a 16-bit random number through RDRAND instruction. + + if Rand is NULL, then ASSERT(). + + @param[out] Rand Buffer pointer to store the random result. + + @retval TRUE RDRAND call was successful. + @retval FALSE Failed attempts to call RDRAND. + + **/ +BOOLEAN +EFIAPI +AsmRdRand16 ( + OUT UINT16 *Rand + ) +{ + ASSERT (Rand != NULL); + return InternalX86RdRand16 (Rand); +} + +/** + Generates a 32-bit random number through RDRAND instruction. + + if Rand is NULL, then ASSERT(). + + @param[out] Rand Buffer pointer to store the random result. + + @retval TRUE RDRAND call was successful. + @retval FALSE Failed attempts to call RDRAND. + +**/ +BOOLEAN +EFIAPI +AsmRdRand32 ( + OUT UINT32 *Rand + ) +{ + ASSERT (Rand != NULL); + return InternalX86RdRand32 (Rand); +} + +/** + Generates a 64-bit random number through RDRAND instruction. + + if Rand is NULL, then ASSERT(). + + @param[out] Rand Buffer pointer to store the random result. + + @retval TRUE RDRAND call was successful. + @retval FALSE Failed attempts to call RDRAND. + +**/ +BOOLEAN +EFIAPI +AsmRdRand64 ( + OUT UINT64 *Rand + ) +{ + ASSERT (Rand != NULL); + return InternalX86RdRand64 (Rand); +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86SegmentNull.c b/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86SegmentNull.c new file mode 100644 index 0000000..b369095 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibHost/X86SegmentNull.c @@ -0,0 +1,163 @@ +/** @file + IA-32/x64 AsmReadGdtr() + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +/** + Reads the current value of Code Segment Register (CS). + + Reads and returns the current value of CS. This function is only available on + IA-32 and x64. + + @return The current value of CS. + +**/ +UINT16 +EFIAPI +AsmReadCs ( + VOID + ) +{ + ASSERT (FALSE); + return 0; +} + + +/** + Reads the current value of Data Segment Register (DS). + + Reads and returns the current value of DS. This function is only available on + IA-32 and x64. + + @return The current value of DS. + +**/ +UINT16 +EFIAPI +AsmReadDs ( + VOID + ) +{ + ASSERT (FALSE); + return 0; +} + + +/** + Reads the current value of Extra Segment Register (ES). + + Reads and returns the current value of ES. This function is only available on + IA-32 and x64. + + @return The current value of ES. + +**/ +UINT16 +EFIAPI +AsmReadEs ( + VOID + ) +{ + ASSERT (FALSE); + return 0; +} + + +/** + Reads the current value of FS Data Segment Register (FS). + + Reads and returns the current value of FS. This function is only available on + IA-32 and x64. + + @return The current value of FS. + +**/ +UINT16 +EFIAPI +AsmReadFs ( + VOID + ) +{ + ASSERT (FALSE); + return 0; +} + + +/** + Reads the current value of GS Data Segment Register (GS). + + Reads and returns the current value of GS. This function is only available on + IA-32 and x64. + + @return The current value of GS. + +**/ +UINT16 +EFIAPI +AsmReadGs ( + VOID + ) +{ + ASSERT (FALSE); + return 0; +} + + +/** + Reads the current value of Stack Segment Register (SS). + + Reads and returns the current value of SS. This function is only available on + IA-32 and x64. + + @return The current value of SS. + +**/ +UINT16 +EFIAPI +AsmReadSs ( + VOID + ) +{ + ASSERT (FALSE); + return 0; +} + + +/** + Reads the current value of Task Register (TR). + + Reads and returns the current value of TR. This function is only available on + IA-32 and x64. + + @return The current value of TR. + +**/ +UINT16 +EFIAPI +AsmReadTr ( + VOID + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Load given selector into TR register. + + @param[in] Selector Task segment selector +**/ +VOID +EFIAPI +AsmWriteTr ( + IN UINT16 Selector + ) +{ + ASSERT (FALSE); +} \ No newline at end of file diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibNullCpuid/BaseLibNullCpuid.c b/HBFA/UefiHostTestPkg/Library/BaseLibNullCpuid/BaseLibNullCpuid.c new file mode 100644 index 0000000..785ca95 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibNullCpuid/BaseLibNullCpuid.c @@ -0,0 +1,39 @@ +/** @file + + Copyright (c) 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +UINT32 +EFIAPI +AsmCpuidEx ( + IN UINT32 Index, + IN UINT32 SubIndex, + OUT UINT32 *RegisterEax, OPTIONAL + OUT UINT32 *RegisterEbx, OPTIONAL + OUT UINT32 *RegisterEcx, OPTIONAL + OUT UINT32 *RegisterEdx OPTIONAL + ) +{ + ASSERT (FALSE); + return 0; +} + +UINT32 +EFIAPI +AsmCpuid ( + IN UINT32 Index, + OUT UINT32 *RegisterEax, OPTIONAL + OUT UINT32 *RegisterEbx, OPTIONAL + OUT UINT32 *RegisterEcx, OPTIONAL + OUT UINT32 *RegisterEdx OPTIONAL + ) +{ + ASSERT (FALSE); + return 0; +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibNullCpuid/BaseLibNullCpuid.inf b/HBFA/UefiHostTestPkg/Library/BaseLibNullCpuid/BaseLibNullCpuid.inf new file mode 100644 index 0000000..fdbde90 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibNullCpuid/BaseLibNullCpuid.inf @@ -0,0 +1,31 @@ +## @file +# Component description file for TestUdf module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseLibNullCpuid + FILE_GUID = 9099E2A7-8A28-4115-9F8E-B2865AECEF8A + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = NULL + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + BaseLibNullCpuid.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + DebugLib diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibNullMsr/BaseLibNullMsr.c b/HBFA/UefiHostTestPkg/Library/BaseLibNullMsr/BaseLibNullMsr.c new file mode 100644 index 0000000..585d4c7 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibNullMsr/BaseLibNullMsr.c @@ -0,0 +1,99 @@ +/** @file + + Copyright (c) 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +UINT64 +EFIAPI +AsmReadMsr64 ( + IN UINT32 Index + ) +{ + ASSERT (FALSE); + return 0; +} + +UINT32 +EFIAPI +AsmReadMsr32 ( + IN UINT32 Index + ) +{ + ASSERT (FALSE); + return 0; +} + +UINT64 +EFIAPI +AsmWriteMsr64 ( + IN UINT32 Index, + IN UINT64 Value + ) +{ + ASSERT (FALSE); + return 0; +} + +UINT32 +EFIAPI +AsmWriteMsr32 ( + IN UINT32 Index, + IN UINT32 Value + ) +{ + ASSERT (FALSE); + return 0; +} + +UINT64 +EFIAPI +AsmMsrOr64 ( + IN UINT32 Index, + IN UINT64 OrData + ) +{ + ASSERT (FALSE); + return 0; +} + +UINT64 +EFIAPI +AsmMsrAnd64 ( + IN UINT32 Index, + IN UINT64 AndData + ) +{ + ASSERT (FALSE); + return 0; +} + +UINT64 +EFIAPI +AsmMsrAndThenOr64 ( + IN UINT32 Index, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + ASSERT (FALSE); + return 0; +} + +UINT64 +EFIAPI +AsmMsrBitFieldWrite64 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ) +{ + ASSERT (FALSE); + return 0; +} \ No newline at end of file diff --git a/HBFA/UefiHostTestPkg/Library/BaseLibNullMsr/BaseLibNullMsr.inf b/HBFA/UefiHostTestPkg/Library/BaseLibNullMsr/BaseLibNullMsr.inf new file mode 100644 index 0000000..f990e8b --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseLibNullMsr/BaseLibNullMsr.inf @@ -0,0 +1,31 @@ +## @file +# Component description file for TestUdf module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseLibNullMsr + FILE_GUID = 24DFBE26-ED67-47F3-B4FC-F23C59C7AAD3 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = NULL + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + BaseLibNullMsr.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + DebugLib diff --git a/HBFA/UefiHostTestPkg/Library/BaseMemoryLibHost/BaseMemoryLibHost.c b/HBFA/UefiHostTestPkg/Library/BaseMemoryLibHost/BaseMemoryLibHost.c new file mode 100644 index 0000000..abb6345 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseMemoryLibHost/BaseMemoryLibHost.c @@ -0,0 +1,232 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +#include +#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFFULL +VOID * +EFIAPI +SetMem ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + memset (Buffer, Value, Length); + return Buffer; +} + +VOID * +EFIAPI +SetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + for (; Length != 0; Length--) { + ((UINT16*)Buffer)[Length - 1] = Value; + } + return Buffer; +} + +VOID * +EFIAPI +SetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + for (; Length != 0; Length--) { + ((UINT32*)Buffer)[Length - 1] = Value; + } + return Buffer; +} + +VOID * +EFIAPI +SetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + for (; Length != 0; Length--) { + ((UINT64*)Buffer)[Length - 1] = Value; + } + return Buffer; +} + +VOID * +EFIAPI +SetMemN ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINTN Value + ) +{ + if (sizeof (UINTN) == sizeof (UINT64)) { + return SetMem64 (Buffer, Length, (UINT64)Value); + } else { + return SetMem32 (Buffer, Length, (UINT32)Value); + } +} + +VOID * +EFIAPI +ZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + memset (Buffer, 0, Length); + return Buffer; +} + +VOID * +EFIAPI +CopyMem ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + memmove (DestinationBuffer, SourceBuffer, Length); + return DestinationBuffer; +} + +INTN +EFIAPI +CompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + return memcmp (DestinationBuffer, SourceBuffer, Length); +} + +BOOLEAN +EFIAPI +CompareGuid ( + IN CONST GUID *Guid1, + IN CONST GUID *Guid2 + ) +{ + return ((BOOLEAN)(memcmp (Guid1, Guid2, sizeof (GUID)) == 0)); +} + +GUID * +EFIAPI +CopyGuid ( + OUT GUID *DestinationGuid, + IN CONST GUID *SourceGuid + ) +{ + memmove (DestinationGuid, SourceGuid, sizeof(GUID)); + return DestinationGuid; +} + +UINT8 mZeroGuid[sizeof(GUID)] = {0}; + +BOOLEAN +EFIAPI +IsZeroGuid ( + IN CONST GUID *Guid + ) +{ + return ((BOOLEAN)(memcmp (Guid, mZeroGuid, sizeof (GUID)) == 0)); +} + +VOID * +EFIAPI +ScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + return memchr (Buffer, Value, Length); +} + +VOID +EFIAPI +CpuBreakpoint ( + VOID + ); +/** + Checks whether the contents of a buffer are all zeros. + + @param Buffer The pointer to the buffer to be checked. + @param Length The size of the buffer (in bytes) to be checked. + + @retval TRUE Contents of the buffer are all zeros. + @retval FALSE Contents of the buffer are not all zeros. + +**/ +BOOLEAN +EFIAPI +InternalMemIsZeroBuffer ( + IN CONST VOID *Buffer, + IN UINTN Length + ) +{ + CONST UINT8 *BufferData; + UINTN Index; + + if ((Buffer == NULL || Length <= 0)) { + printf ("ASSERT: Buffer is null or length <=0\n"); + CpuBreakpoint (); + } + BufferData = Buffer; + for (Index = 0; Index < Length; Index++) { + if (BufferData[Index] != 0) { + return FALSE; + } + } + return TRUE; +} + +/** + Checks if the contents of a buffer are all zeros. + + This function checks whether the contents of a buffer are all zeros. If the + contents are all zeros, return TRUE. Otherwise, return FALSE. + + If Length > 0 and Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to be checked. + @param Length The size of the buffer (in bytes) to be checked. + + @retval TRUE Contents of the buffer are all zeros. + @retval FALSE Contents of the buffer are not all zeros. + +**/ +BOOLEAN +EFIAPI +IsZeroBuffer ( + IN CONST VOID *Buffer, + IN UINTN Length + ) +{ + if ((Buffer == NULL || Length <= 0)) + { + printf ("ASSERT: Buffer is null or length <=0\n"); + CpuBreakpoint (); + } + if ((Length - 1) > (MAX_ADDRESS - (UINTN)Buffer)){ + printf ("ASSERT: Buffer address is out of Max Address limilation\n"); + CpuBreakpoint (); + } + return InternalMemIsZeroBuffer (Buffer, Length); +} \ No newline at end of file diff --git a/HBFA/UefiHostTestPkg/Library/BaseMemoryLibHost/BaseMemoryLibHost.inf b/HBFA/UefiHostTestPkg/Library/BaseMemoryLibHost/BaseMemoryLibHost.inf new file mode 100644 index 0000000..de9c944 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseMemoryLibHost/BaseMemoryLibHost.inf @@ -0,0 +1,25 @@ +## @file +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseMemoryLibHost + FILE_GUID = 90B7948B-DFED-46FB-BABE-770A5A464BA5 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = BaseMemoryLib + +[Sources] + BaseMemoryLibHost.c + +[Packages] + MdePkg/MdePkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + +[LibraryClasses] + BaseLib + diff --git a/HBFA/UefiHostTestPkg/Library/BasePcdLibHost/BasePcdLibHost.c b/HBFA/UefiHostTestPkg/Library/BasePcdLibHost/BasePcdLibHost.c new file mode 100644 index 0000000..a1cb7ea --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BasePcdLibHost/BasePcdLibHost.c @@ -0,0 +1,1456 @@ +/** @file + A emptry template implementation of PCD Library. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +#include +#include +#include +#include +#include + +#define PCD_INFO_PRIVATE_SIGNATURE SIGNATURE_32 ('P', 'I', 'P', 'S') + +typedef enum { + PcdTypeUnknown, + PcdTypeBool, + PcdTypeUint8, + PcdTypeUint16, + PcdTypeUint32, + PcdTypeUint64, + PcdTypePtr, +} PCD_TYPE_PRIVATE; + +typedef struct { + UINTN Signature; + LIST_ENTRY Link; + + UINTN TokenNumber; + GUID Guid; + PCD_TYPE_PRIVATE Type; + UINTN Size; + UINT8 *Buffer; +} PCD_INFO_PRIVATE; + +#define PCD_INFO_PRIVATE_FROM_LINK(a) CR (a, PCD_INFO_PRIVATE, Link, PCD_INFO_PRIVATE_SIGNATURE) + +LIST_ENTRY mPcdListEntry = INITIALIZE_LIST_HEAD_VARIABLE(mPcdListEntry); +LIST_ENTRY mPcdExListEntry = INITIALIZE_LIST_HEAD_VARIABLE(mPcdExListEntry); + +LIST_ENTRY * +FindPcdList ( + IN LIST_ENTRY *StorageListHead, + IN GUID *Guid, + IN UINTN TokenNumber, + IN PCD_TYPE_PRIVATE Type + ) +{ + LIST_ENTRY *Link; + PCD_INFO_PRIVATE *Storage; + + if (StorageListHead->ForwardLink != NULL) { + Link = GetFirstNode (StorageListHead); + while (!IsNull (StorageListHead, Link)) { + Storage = PCD_INFO_PRIVATE_FROM_LINK (Link); + if ((Storage->TokenNumber == TokenNumber) && + ((Guid == NULL) || (CompareGuid (&Storage->Guid, Guid))) ) { + if (Type != PcdTypeUnknown) { + ASSERT (Storage->Type == Type); + if (Storage->Type != Type) { + return NULL; + } + } + return Link; + } + Link = GetNextNode (StorageListHead, Link); + } + } + return NULL; +} + +PCD_INFO_PRIVATE* +FindPcdInfoPtr( + IN UINTN TokenNumber, + IN PCD_TYPE_PRIVATE Type + ) +{ + LIST_ENTRY *ListEntry; + + // + // Try to get auth variable by name and GUID. + // + ListEntry = FindPcdList (&mPcdListEntry, NULL, TokenNumber, Type); + if (ListEntry != NULL) { + return PCD_INFO_PRIVATE_FROM_LINK (ListEntry); + } + + return NULL; +} + +PCD_INFO_PRIVATE* +FindPcdExInfoPtr( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN PCD_TYPE_PRIVATE Type + ) +{ + LIST_ENTRY *ListEntry; + + // + // Try to get auth variable by name and GUID. + // + ListEntry = FindPcdList (&mPcdExListEntry, (GUID *)Guid, TokenNumber, Type); + if (ListEntry != NULL) { + return PCD_INFO_PRIVATE_FROM_LINK (ListEntry); + } + + return NULL; +} + +RETURN_STATUS +CreatePcdInfo ( + IN GUID *Guid, + IN UINTN TokenNumber, + IN PCD_TYPE_PRIVATE Type, + IN VOID *Buffer, + IN UINTN Size, + OUT PCD_INFO_PRIVATE **PcdInfoPrivate + ) +{ + PCD_INFO_PRIVATE *PcdInfo; + + switch (Type) { + case PcdTypeUnknown: + default: + ASSERT(FALSE); + return RETURN_INVALID_PARAMETER; + break; + case PcdTypeUint8: + case PcdTypeBool: + ASSERT(Size == sizeof(UINT8)); + if (Size != sizeof(UINT8)) { + return RETURN_INVALID_PARAMETER; + } + break; + case PcdTypeUint16: + ASSERT(Size == sizeof(UINT16)); + if (Size != sizeof(UINT16)) { + return RETURN_INVALID_PARAMETER; + } + break; + case PcdTypeUint32: + ASSERT(Size == sizeof(UINT32)); + if (Size != sizeof(UINT32)) { + return RETURN_INVALID_PARAMETER; + } + break; + case PcdTypeUint64: + ASSERT(Size == sizeof(UINT64)); + if (Size != sizeof(UINT64)) { + return RETURN_INVALID_PARAMETER; + } + break; + case PcdTypePtr: + break; + } + + if (Guid == NULL) { + PcdInfo = FindPcdInfoPtr(TokenNumber, Type); + } else { + PcdInfo = FindPcdExInfoPtr(Guid, TokenNumber, Type); + } + + if (PcdInfo == NULL) { + PcdInfo = malloc (sizeof(PCD_INFO_PRIVATE)); + if (PcdInfo == NULL) { + return RETURN_OUT_OF_RESOURCES; + } + ZeroMem (PcdInfo, sizeof(PCD_INFO_PRIVATE)); + PcdInfo->Signature = PCD_INFO_PRIVATE_SIGNATURE; + if (Guid != NULL) { + CopyMem (&PcdInfo->Guid, Guid, sizeof(GUID)); + } + PcdInfo->TokenNumber = TokenNumber; + PcdInfo->Type = Type; + PcdInfo->Size = Size; + PcdInfo->Buffer = malloc(Size); + if (PcdInfo->Buffer == NULL) { + free (PcdInfo); + return RETURN_OUT_OF_RESOURCES; + } + CopyMem (PcdInfo->Buffer, Buffer, Size); + *PcdInfoPrivate = PcdInfo; + return RETURN_SUCCESS; + } else { + if (Type != PcdInfo->Type) { + ASSERT(FALSE); + return RETURN_INVALID_PARAMETER; + } + if (Type != PcdTypePtr && (Size != PcdInfo->Size)) { + ASSERT(FALSE); + return RETURN_INVALID_PARAMETER; + } + if (Type == PcdTypePtr) { + VOID *NewBuf; + NewBuf = malloc(Size); + if (NewBuf == NULL) { + return RETURN_OUT_OF_RESOURCES; + } + free (PcdInfo->Buffer); + PcdInfo->Buffer = NewBuf; + PcdInfo->Size = Size; + } + CopyMem (PcdInfo->Buffer, Buffer, Size); + *PcdInfoPrivate = NULL; + return RETURN_SUCCESS; + } +} + +RETURN_STATUS +InsertPcd ( + IN UINTN TokenNumber, + IN PCD_TYPE_PRIVATE Type, + IN VOID *Buffer, + IN UINTN Size + ) +{ + PCD_INFO_PRIVATE *PcdInfo; + RETURN_STATUS Status; + + Status = CreatePcdInfo (NULL, TokenNumber, Type, Buffer, Size, &PcdInfo); + if (Status != RETURN_SUCCESS) { + ASSERT(FALSE); + return Status; + } + if (PcdInfo != NULL) { + InsertTailList(&mPcdListEntry, &PcdInfo->Link); + } + + return RETURN_SUCCESS; +} + +RETURN_STATUS +InsertPcdEx ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN PCD_TYPE_PRIVATE Type, + IN VOID *Buffer, + IN UINTN Size + ) +{ + PCD_INFO_PRIVATE *PcdInfo; + RETURN_STATUS Status; + + Status = CreatePcdInfo ((GUID *)Guid, TokenNumber, Type, Buffer, Size, &PcdInfo); + if (Status != RETURN_SUCCESS) { + ASSERT(FALSE); + return RETURN_OUT_OF_RESOURCES; + } + if (PcdInfo != NULL) { + InsertTailList(&mPcdExListEntry, &PcdInfo->Link); + } + + return RETURN_SUCCESS; +} + +/** + This function provides a means by which SKU support can be established in the PCD infrastructure. + + Sets the current SKU in the PCD database to the value specified by SkuId. SkuId is returned. + + @param[in] SkuId The SKU value that will be used when the PCD service will retrieve and + set values associated with a PCD token. + + @return Return the SKU ID that just be set. + +**/ +UINTN +EFIAPI +LibPcdSetSku ( + IN UINTN SkuId + ) +{ + ASSERT (FALSE); + + return 0; +} + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the 8-bit value for the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Returns the 8-bit value for the token specified by TokenNumber. + +**/ +UINT8 +EFIAPI +LibPcdGet8 ( + IN UINTN TokenNumber + ) +{ + PCD_INFO_PRIVATE *PcdInfo; + + PcdInfo = FindPcdInfoPtr (TokenNumber, PcdTypeUint8); + if (PcdInfo != NULL) { + return *(UINT8 *)PcdInfo->Buffer; + } + + ASSERT (PcdInfo != NULL); + return 0; +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the 16-bit value for the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Returns the 16-bit value for the token specified by TokenNumber. + +**/ +UINT16 +EFIAPI +LibPcdGet16 ( + IN UINTN TokenNumber + ) +{ + PCD_INFO_PRIVATE *PcdInfo; + + PcdInfo = FindPcdInfoPtr (TokenNumber, PcdTypeUint16); + if (PcdInfo != NULL) { + return *(UINT16 *)PcdInfo->Buffer; + } + + ASSERT (PcdInfo != NULL); + return 0; +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the 32-bit value for the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Returns the 32-bit value for the token specified by TokenNumber. + +**/ +UINT32 +EFIAPI +LibPcdGet32 ( + IN UINTN TokenNumber + ) +{ + PCD_INFO_PRIVATE *PcdInfo; + + PcdInfo = FindPcdInfoPtr (TokenNumber, PcdTypeUint32); + if (PcdInfo != NULL) { + return *(UINT32 *)PcdInfo->Buffer; + } + + ASSERT (PcdInfo != NULL); + return 0; +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the 64-bit value for the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Returns the 64-bit value for the token specified by TokenNumber. + +**/ +UINT64 +EFIAPI +LibPcdGet64 ( + IN UINTN TokenNumber + ) +{ + PCD_INFO_PRIVATE *PcdInfo; + + PcdInfo = FindPcdInfoPtr (TokenNumber, PcdTypeUint64); + if (PcdInfo != NULL) { + return *(UINT64 *)PcdInfo->Buffer; + } + + ASSERT (PcdInfo != NULL); + return 0; +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the pointer to the buffer of the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Returns the pointer to the token specified by TokenNumber. + +**/ +VOID * +EFIAPI +LibPcdGetPtr ( + IN UINTN TokenNumber + ) +{ + PCD_INFO_PRIVATE *PcdInfo; + + PcdInfo = FindPcdInfoPtr (TokenNumber, PcdTypePtr); + if (PcdInfo != NULL) { + return PcdInfo->Buffer; + } + + ASSERT (PcdInfo != NULL); + return 0; +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the Boolean value of the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Returns the Boolean value of the token specified by TokenNumber. + +**/ +BOOLEAN +EFIAPI +LibPcdGetBool ( + IN UINTN TokenNumber + ) +{ + PCD_INFO_PRIVATE *PcdInfo; + + PcdInfo = FindPcdInfoPtr (TokenNumber, PcdTypeBool); + if (PcdInfo != NULL) { + return *(BOOLEAN *)PcdInfo->Buffer; + } + + ASSERT (PcdInfo != NULL); + return 0; +} + + + +/** + This function provides a means by which to retrieve the size of a given PCD token. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Returns the size of the token specified by TokenNumber. + +**/ +UINTN +EFIAPI +LibPcdGetSize ( + IN UINTN TokenNumber + ) +{ + PCD_INFO_PRIVATE *PcdInfo; + + PcdInfo = FindPcdInfoPtr (TokenNumber, PcdTypeUnknown); + if (PcdInfo != NULL) { + return PcdInfo->Size; + } + + ASSERT (PcdInfo != NULL); + return 0; +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the 8-bit value for the token specified by TokenNumber and Guid. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Return the UINT8. + +**/ +UINT8 +EFIAPI +LibPcdGetEx8 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + PCD_INFO_PRIVATE *PcdInfo; + + PcdInfo = FindPcdExInfoPtr (Guid, TokenNumber, PcdTypeUint8); + if (PcdInfo != NULL) { + return *(UINT8 *)PcdInfo->Buffer; + } + + ASSERT (PcdInfo != NULL); + return 0; +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the 16-bit value for the token specified by TokenNumber and Guid. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Return the UINT16. + +**/ +UINT16 +EFIAPI +LibPcdGetEx16 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + PCD_INFO_PRIVATE *PcdInfo; + + PcdInfo = FindPcdExInfoPtr (Guid, TokenNumber, PcdTypeUint16); + if (PcdInfo != NULL) { + return *(UINT16 *)PcdInfo->Buffer; + } + + ASSERT (PcdInfo != NULL); + return 0; +} + + + +/** + Returns the 32-bit value for the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Return the UINT32. + +**/ +UINT32 +EFIAPI +LibPcdGetEx32 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + PCD_INFO_PRIVATE *PcdInfo; + + PcdInfo = FindPcdExInfoPtr (Guid, TokenNumber, PcdTypeUint32); + if (PcdInfo != NULL) { + return *(UINT32 *)PcdInfo->Buffer; + } + + ASSERT (PcdInfo != NULL); + return 0; +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the 64-bit value for the token specified by TokenNumber and Guid. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Return the UINT64. + +**/ +UINT64 +EFIAPI +LibPcdGetEx64 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + PCD_INFO_PRIVATE *PcdInfo; + + PcdInfo = FindPcdExInfoPtr (Guid, TokenNumber, PcdTypeUint64); + if (PcdInfo != NULL) { + return *(UINT64 *)PcdInfo->Buffer; + } + + ASSERT (PcdInfo != NULL); + return 0; +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the pointer to the buffer of token specified by TokenNumber and Guid. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Return the VOID* pointer. + +**/ +VOID * +EFIAPI +LibPcdGetExPtr ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + PCD_INFO_PRIVATE *PcdInfo; + + PcdInfo = FindPcdExInfoPtr (Guid, TokenNumber, PcdTypePtr); + if (PcdInfo != NULL) { + return PcdInfo->Buffer; + } + + ASSERT (PcdInfo != NULL); + return 0; +} + + + +/** + This function provides a means by which to retrieve a value for a given PCD token. + + Returns the Boolean value of the token specified by TokenNumber and Guid. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Return the BOOLEAN. + +**/ +BOOLEAN +EFIAPI +LibPcdGetExBool ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + PCD_INFO_PRIVATE *PcdInfo; + + PcdInfo = FindPcdExInfoPtr (Guid, TokenNumber, PcdTypeBool); + if (PcdInfo != NULL) { + return *(BOOLEAN *)PcdInfo->Buffer; + } + + ASSERT (PcdInfo != NULL); + return 0; +} + + + +/** + This function provides a means by which to retrieve the size of a given PCD token. + + Returns the size of the token specified by TokenNumber and Guid. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @return Return the size. + +**/ +UINTN +EFIAPI +LibPcdGetExSize ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + PCD_INFO_PRIVATE *PcdInfo; + + PcdInfo = FindPcdExInfoPtr (Guid, TokenNumber, PcdTypeUnknown); + if (PcdInfo != NULL) { + return PcdInfo->Size; + } + + ASSERT (PcdInfo != NULL); + return 0; +} + + + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 8-bit value for the token specified by TokenNumber + to the value specified by Value. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 8-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSet8S ( + IN UINTN TokenNumber, + IN UINT8 Value + ) +{ + RETURN_STATUS Status; + + Status = InsertPcd (TokenNumber, PcdTypeUint8, &Value, sizeof(UINT8)); + return Status; +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 16-bit value for the token specified by TokenNumber + to the value specified by Value. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 16-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSet16S ( + IN UINTN TokenNumber, + IN UINT16 Value + ) +{ + RETURN_STATUS Status; + + Status = InsertPcd (TokenNumber, PcdTypeUint16, &Value, sizeof(UINT16)); + return Status; +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 32-bit value for the token specified by TokenNumber + to the value specified by Value. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 32-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSet32S ( + IN UINTN TokenNumber, + IN UINT32 Value + ) +{ + RETURN_STATUS Status; + + Status = InsertPcd (TokenNumber, PcdTypeUint32, &Value, sizeof(UINT32)); + return Status; +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 64-bit value for the token specified by TokenNumber + to the value specified by Value. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 64-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSet64S ( + IN UINTN TokenNumber, + IN UINT64 Value + ) +{ + RETURN_STATUS Status; + + Status = InsertPcd (TokenNumber, PcdTypeUint64, &Value, sizeof(UINT64)); + return Status; +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets a buffer for the token specified by TokenNumber to the value specified + by Buffer and SizeOfBuffer. If SizeOfBuffer is greater than the maximum size + support by TokenNumber, then set SizeOfBuffer to the maximum size supported by + TokenNumber and return EFI_INVALID_PARAMETER to indicate that the set operation + was not actually performed. + + If SizeOfBuffer is set to MAX_ADDRESS, then SizeOfBuffer must be set to the + maximum size supported by TokenName and EFI_INVALID_PARAMETER must be returned. + + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in, out] SizeOfBuffer The size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetPtrS ( + IN UINTN TokenNumber, + IN OUT UINTN *SizeOfBuffer, + IN CONST VOID *Buffer + ) +{ + RETURN_STATUS Status; + + Status = InsertPcd (TokenNumber, PcdTypePtr, (VOID *)Buffer, *SizeOfBuffer); + return Status; +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the boolean value for the token specified by TokenNumber + to the value specified by Value. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The boolean value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetBoolS ( + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +{ + RETURN_STATUS Status; + + Status = InsertPcd (TokenNumber, PcdTypeBool, &Value, sizeof(BOOLEAN)); + return Status; +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 8-bit value for the token specified by TokenNumber + to the value specified by Value. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 8-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetEx8S ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT8 Value + ) +{ + RETURN_STATUS Status; + + Status = InsertPcdEx (Guid, TokenNumber, PcdTypeUint8, &Value, sizeof(UINT8)); + return Status; +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 16-bit value for the token specified by TokenNumber + to the value specified by Value. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 16-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetEx16S ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT16 Value + ) +{ + RETURN_STATUS Status; + + Status = InsertPcdEx (Guid, TokenNumber, PcdTypeUint16, &Value, sizeof(UINT16)); + return Status; +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 32-bit value for the token specified by TokenNumber + to the value specified by Value. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 32-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetEx32S ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT32 Value + ) +{ + RETURN_STATUS Status; + + Status = InsertPcdEx (Guid, TokenNumber, PcdTypeUint32, &Value, sizeof(UINT32)); + return Status; +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the 64-bit value for the token specified by TokenNumber + to the value specified by Value. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 64-bit value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetEx64S ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT64 Value + ) +{ + RETURN_STATUS Status; + + Status = InsertPcdEx (Guid, TokenNumber, PcdTypeUint64, &Value, sizeof(UINT64)); + return Status; +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets a buffer for the token specified by TokenNumber to the value specified by + Buffer and SizeOfBuffer. If SizeOfBuffer is greater than the maximum size + support by TokenNumber, then set SizeOfBuffer to the maximum size supported by + TokenNumber and return EFI_INVALID_PARAMETER to indicate that the set operation + was not actually performed. + + If Guid is NULL, then ASSERT(). + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in, out] SizeOfBuffer The size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetExPtrS ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN OUT UINTN *SizeOfBuffer, + IN VOID *Buffer + ) +{ + RETURN_STATUS Status; + + Status = InsertPcdEx (Guid, TokenNumber, PcdTypePtr, Buffer, *SizeOfBuffer); + return Status; +} + +/** + This function provides a means by which to set a value for a given PCD token. + + Sets the boolean value for the token specified by TokenNumber + to the value specified by Value. + + If Guid is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The boolean value to set. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPcdSetExBoolS ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +{ + RETURN_STATUS Status; + + Status = InsertPcdEx (Guid, TokenNumber, PcdTypeBool, &Value, sizeof(BOOLEAN)); + return Status; +} + +/** + Set up a notification function that is called when a specified token is set. + + When the token specified by TokenNumber and Guid is set, + then notification function specified by NotificationFunction is called. + If Guid is NULL, then the default token space is used. + + If NotificationFunction is NULL, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates which + namespace to set a value from. If NULL, then the default + token space is used. + @param[in] TokenNumber The PCD token number to monitor. + @param[in] NotificationFunction The function to call when the token + specified by Guid and TokenNumber is set. + +**/ +VOID +EFIAPI +LibPcdCallbackOnSet ( + IN CONST GUID *Guid, OPTIONAL + IN UINTN TokenNumber, + IN PCD_CALLBACK NotificationFunction + ) +{ + ASSERT (FALSE); +} + + + +/** + Disable a notification function that was established with LibPcdCallbackonSet(). + + Disable a notification function that was previously established with LibPcdCallbackOnSet(). + + If NotificationFunction is NULL, then ASSERT(). + If LibPcdCallbackOnSet() was not previously called with Guid, TokenNumber, + and NotificationFunction, then ASSERT(). + + @param[in] Guid Specify the GUID token space. + @param[in] TokenNumber Specify the token number. + @param[in] NotificationFunction The callback function to be unregistered. + +**/ +VOID +EFIAPI +LibPcdCancelCallback ( + IN CONST GUID *Guid, OPTIONAL + IN UINTN TokenNumber, + IN PCD_CALLBACK NotificationFunction + ) +{ + ASSERT (FALSE); +} + + + +/** + Retrieves the next token in a token space. + + Retrieves the next PCD token number from the token space specified by Guid. + If Guid is NULL, then the default token space is used. If TokenNumber is 0, + then the first token number is returned. Otherwise, the token number that + follows TokenNumber in the token space is returned. If TokenNumber is the last + token number in the token space, then 0 is returned. + + If TokenNumber is not 0 and is not in the token space specified by Guid, then ASSERT(). + + @param[in] Guid The pointer to a 128-bit unique value that designates which namespace + to set a value from. If NULL, then the default token space is used. + @param[in] TokenNumber The previous PCD token number. If 0, then retrieves the first PCD + token number. + + @return The next valid token number. + +**/ +UINTN +EFIAPI +LibPcdGetNextToken ( + IN CONST GUID *Guid, OPTIONAL + IN UINTN TokenNumber + ) +{ + ASSERT (FALSE); + + return 0; +} + + + +/** + Used to retrieve the list of available PCD token space GUIDs. + + Returns the PCD token space GUID that follows TokenSpaceGuid in the list of token spaces + in the platform. + If TokenSpaceGuid is NULL, then a pointer to the first PCD token spaces returned. + If TokenSpaceGuid is the last PCD token space GUID in the list, then NULL is returned. + + @param TokenSpaceGuid The pointer to a PCD token space GUID. + + @return The next valid token namespace. + +**/ +GUID * +EFIAPI +LibPcdGetNextTokenSpace ( + IN CONST GUID *TokenSpaceGuid + ) +{ + ASSERT (FALSE); + + return NULL; +} + + +/** + Sets a value of a patchable PCD entry that is type pointer. + + Sets the PCD entry specified by PatchVariable to the value specified by Buffer + and SizeOfBuffer. Buffer is returned. If SizeOfBuffer is greater than + MaximumDatumSize, then set SizeOfBuffer to MaximumDatumSize and return + NULL to indicate that the set operation was not actually performed. + If SizeOfBuffer is set to MAX_ADDRESS, then SizeOfBuffer must be set to + MaximumDatumSize and NULL must be returned. + + If PatchVariable is NULL, then ASSERT(). + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[out] PatchVariable A pointer to the global variable in a module that is + the target of the set operation. + @param[in] MaximumDatumSize The maximum size allowed for the PCD entry specified by PatchVariable. + @param[in, out] SizeOfBuffer A pointer to the size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to used to set the target variable. + + @return Return the pointer to the buffer that was set. + +**/ +VOID * +EFIAPI +LibPatchPcdSetPtr ( + OUT VOID *PatchVariable, + IN UINTN MaximumDatumSize, + IN OUT UINTN *SizeOfBuffer, + IN CONST VOID *Buffer + ) +{ + ASSERT (PatchVariable != NULL); + ASSERT (SizeOfBuffer != NULL); + + if (*SizeOfBuffer > 0) { + ASSERT (Buffer != NULL); + } + + if ((*SizeOfBuffer > MaximumDatumSize) || + (*SizeOfBuffer == MAX_ADDRESS)) { + *SizeOfBuffer = MaximumDatumSize; + return NULL; + } + + CopyMem (PatchVariable, Buffer, *SizeOfBuffer); + + return (VOID *) Buffer; +} + +/** + Sets a value of a patchable PCD entry that is type pointer. + + Sets the PCD entry specified by PatchVariable to the value specified + by Buffer and SizeOfBuffer. If SizeOfBuffer is greater than MaximumDatumSize, + then set SizeOfBuffer to MaximumDatumSize and return RETURN_INVALID_PARAMETER + to indicate that the set operation was not actually performed. + If SizeOfBuffer is set to MAX_ADDRESS, then SizeOfBuffer must be set to + MaximumDatumSize and RETURN_INVALID_PARAMETER must be returned. + + If PatchVariable is NULL, then ASSERT(). + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[out] PatchVariable A pointer to the global variable in a module that is + the target of the set operation. + @param[in] MaximumDatumSize The maximum size allowed for the PCD entry specified by PatchVariable. + @param[in, out] SizeOfBuffer A pointer to the size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to used to set the target variable. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPatchPcdSetPtrS ( + OUT VOID *PatchVariable, + IN UINTN MaximumDatumSize, + IN OUT UINTN *SizeOfBuffer, + IN CONST VOID *Buffer + ) +{ + ASSERT (PatchVariable != NULL); + ASSERT (SizeOfBuffer != NULL); + + if (*SizeOfBuffer > 0) { + ASSERT (Buffer != NULL); + } + + if ((*SizeOfBuffer > MaximumDatumSize) || + (*SizeOfBuffer == MAX_ADDRESS)) { + *SizeOfBuffer = MaximumDatumSize; + return RETURN_INVALID_PARAMETER; + } + + CopyMem (PatchVariable, Buffer, *SizeOfBuffer); + + return RETURN_SUCCESS; +} + +/** + Sets a value and size of a patchable PCD entry that is type pointer. + + Sets the PCD entry specified by PatchVariable to the value specified by Buffer + and SizeOfBuffer. Buffer is returned. If SizeOfBuffer is greater than + MaximumDatumSize, then set SizeOfBuffer to MaximumDatumSize and return + NULL to indicate that the set operation was not actually performed. + If SizeOfBuffer is set to MAX_ADDRESS, then SizeOfBuffer must be set to + MaximumDatumSize and NULL must be returned. + + If PatchVariable is NULL, then ASSERT(). + If SizeOfPatchVariable is NULL, then ASSERT(). + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[out] PatchVariable A pointer to the global variable in a module that is + the target of the set operation. + @param[out] SizeOfPatchVariable A pointer to the size, in bytes, of PatchVariable. + @param[in] MaximumDatumSize The maximum size allowed for the PCD entry specified by PatchVariable. + @param[in, out] SizeOfBuffer A pointer to the size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to used to set the target variable. + + @return Return the pointer to the buffer been set. + +**/ +VOID * +EFIAPI +LibPatchPcdSetPtrAndSize ( + OUT VOID *PatchVariable, + OUT UINTN *SizeOfPatchVariable, + IN UINTN MaximumDatumSize, + IN OUT UINTN *SizeOfBuffer, + IN CONST VOID *Buffer + ) +{ + ASSERT (PatchVariable != NULL); + ASSERT (SizeOfPatchVariable != NULL); + ASSERT (SizeOfBuffer != NULL); + + if (*SizeOfBuffer > 0) { + ASSERT (Buffer != NULL); + } + + if ((*SizeOfBuffer > MaximumDatumSize) || + (*SizeOfBuffer == MAX_ADDRESS)) { + *SizeOfBuffer = MaximumDatumSize; + return NULL; + } + + CopyMem (PatchVariable, Buffer, *SizeOfBuffer); + *SizeOfPatchVariable = *SizeOfBuffer; + + return (VOID *) Buffer; +} + +/** + Sets a value and size of a patchable PCD entry that is type pointer. + + Sets the PCD entry specified by PatchVariable to the value specified + by Buffer and SizeOfBuffer. If SizeOfBuffer is greater than MaximumDatumSize, + then set SizeOfBuffer to MaximumDatumSize and return RETURN_INVALID_PARAMETER + to indicate that the set operation was not actually performed. + If SizeOfBuffer is set to MAX_ADDRESS, then SizeOfBuffer must be set to + MaximumDatumSize and RETURN_INVALID_PARAMETER must be returned. + + If PatchVariable is NULL, then ASSERT(). + If SizeOfPatchVariable is NULL, then ASSERT(). + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param[out] PatchVariable A pointer to the global variable in a module that is + the target of the set operation. + @param[out] SizeOfPatchVariable A pointer to the size, in bytes, of PatchVariable. + @param[in] MaximumDatumSize The maximum size allowed for the PCD entry specified by PatchVariable. + @param[in, out] SizeOfBuffer A pointer to the size, in bytes, of Buffer. + @param[in] Buffer A pointer to the buffer to used to set the target variable. + + @return The status of the set operation. + +**/ +RETURN_STATUS +EFIAPI +LibPatchPcdSetPtrAndSizeS ( + OUT VOID *PatchVariable, + OUT UINTN *SizeOfPatchVariable, + IN UINTN MaximumDatumSize, + IN OUT UINTN *SizeOfBuffer, + IN CONST VOID *Buffer + ) +{ + ASSERT (PatchVariable != NULL); + ASSERT (SizeOfPatchVariable != NULL); + ASSERT (SizeOfBuffer != NULL); + + if (*SizeOfBuffer > 0) { + ASSERT (Buffer != NULL); + } + + if ((*SizeOfBuffer > MaximumDatumSize) || + (*SizeOfBuffer == MAX_ADDRESS)) { + *SizeOfBuffer = MaximumDatumSize; + return RETURN_INVALID_PARAMETER; + } + + CopyMem (PatchVariable, Buffer, *SizeOfBuffer); + *SizeOfPatchVariable = *SizeOfBuffer; + + return RETURN_SUCCESS; +} + +/** + Retrieve additional information associated with a PCD token. + + This includes information such as the type of value the TokenNumber is associated with as well as possible + human readable name that is associated with the token. + + If TokenNumber is not in the default token space specified, then ASSERT(). + + @param[in] TokenNumber The PCD token number. + @param[out] PcdInfo The returned information associated with the requested TokenNumber. + The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName. +**/ +VOID +EFIAPI +LibPcdGetInfo ( + IN UINTN TokenNumber, + OUT PCD_INFO *PcdInfo + ) +{ + ASSERT (FALSE); +} + +/** + Retrieve additional information associated with a PCD token. + + This includes information such as the type of value the TokenNumber is associated with as well as possible + human readable name that is associated with the token. + + If TokenNumber is not in the token space specified by Guid, then ASSERT(). + + @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value. + @param[in] TokenNumber The PCD token number. + @param[out] PcdInfo The returned information associated with the requested TokenNumber. + The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName. +**/ +VOID +EFIAPI +LibPcdGetInfoEx ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + OUT PCD_INFO *PcdInfo + ) +{ + ASSERT (FALSE); +} + +/** + Retrieve the currently set SKU Id. + + @return The currently set SKU Id. If the platform has not set at a SKU Id, then the + default SKU Id value of 0 is returned. If the platform has set a SKU Id, then the currently set SKU + Id is returned. +**/ +UINTN +EFIAPI +LibPcdGetSku ( + VOID + ) +{ + ASSERT (FALSE); + + return 0; +} + diff --git a/HBFA/UefiHostTestPkg/Library/BasePcdLibHost/BasePcdLibHost.inf b/HBFA/UefiHostTestPkg/Library/BasePcdLibHost/BasePcdLibHost.inf new file mode 100644 index 0000000..ae5ed26 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BasePcdLibHost/BasePcdLibHost.inf @@ -0,0 +1,35 @@ +## @file +# Instance of PCD Library without support of dynamic PCD entries. +# +# PCD Library that only provides access to Feature Flag, Fixed At Build, +# and Binary Patch typed PCD entries. Access to Dynamic PCD entries is ignored. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BasePcdLibHost + FILE_GUID = 388756FE-4860-44D2-81DB-1DD4E712F1BD + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PcdLib + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + BasePcdLibHost.c + +[LibraryClasses] + DebugLib + BaseMemoryLib + +[Packages] + MdePkg/MdePkg.dec + diff --git a/HBFA/UefiHostTestPkg/Library/BaseTimerLibHost/BaseTimerLibHost.c b/HBFA/UefiHostTestPkg/Library/BaseTimerLibHost/BaseTimerLibHost.c new file mode 100644 index 0000000..5bca559 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseTimerLibHost/BaseTimerLibHost.c @@ -0,0 +1,121 @@ +/** @file + + Copyright (c) 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +/** + Stalls the CPU for at least the given number of microseconds. + + Stalls the CPU for the number of microseconds specified by MicroSeconds. + + @param MicroSeconds The minimum number of microseconds to delay. + + @return The value of MicroSeconds inputted. + +**/ +UINTN +EFIAPI +MicroSecondDelay ( + IN UINTN MicroSeconds + ) +{ + return MicroSeconds; +} + +/** + Stalls the CPU for at least the given number of nanoseconds. + + Stalls the CPU for the number of nanoseconds specified by NanoSeconds. + + @param NanoSeconds The minimum number of nanoseconds to delay. + + @return The value of NanoSeconds inputted. + +**/ +UINTN +EFIAPI +NanoSecondDelay ( + IN UINTN NanoSeconds + ) +{ + return 0; +} + +/** + Retrieves the current value of a 64-bit free running performance counter. + + The counter can either count up by 1 or count down by 1. If the physical + performance counter counts by a larger increment, then the counter values + must be translated. The properties of the counter can be retrieved from + GetPerformanceCounterProperties(). + + @return The current value of the free running performance counter. + +**/ +UINT64 +EFIAPI +GetPerformanceCounter ( + VOID + ) +{ + return 0; +} + +/** + Retrieves the 64-bit frequency in Hz and the range of performance counter + values. + + If StartValue is not NULL, then the value that the performance counter starts + with immediately after is it rolls over is returned in StartValue. If + EndValue is not NULL, then the value that the performance counter end with + immediately before it rolls over is returned in EndValue. The 64-bit + frequency of the performance counter in Hz is always returned. If StartValue + is less than EndValue, then the performance counter counts up. If StartValue + is greater than EndValue, then the performance counter counts down. For + example, a 64-bit free running counter that counts up would have a StartValue + of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter + that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0. + + @param StartValue The value the performance counter starts with when it + rolls over. + @param EndValue The value that the performance counter ends with before + it rolls over. + + @return The frequency in Hz. + +**/ +UINT64 +EFIAPI +GetPerformanceCounterProperties ( + OUT UINT64 *StartValue, OPTIONAL + OUT UINT64 *EndValue OPTIONAL + ) +{ + return (UINT64)(-1); +} + +/** + Converts elapsed ticks of performance counter to time in nanoseconds. + + This function converts the elapsed ticks of running performance counter to + time value in unit of nanoseconds. + + @param Ticks The number of elapsed ticks of running performance counter. + + @return The elapsed time in nanoseconds. + +**/ +UINT64 +EFIAPI +GetTimeInNanoSecond ( + IN UINT64 Ticks + ) +{ + return 0; +} diff --git a/HBFA/UefiHostTestPkg/Library/BaseTimerLibHost/BaseTimerLibHost.inf b/HBFA/UefiHostTestPkg/Library/BaseTimerLibHost/BaseTimerLibHost.inf new file mode 100644 index 0000000..69939a3 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/BaseTimerLibHost/BaseTimerLibHost.inf @@ -0,0 +1,33 @@ +## @file +# Base Timer Library +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseTimerLibHost + FILE_GUID = 5E659347-D32A-4E8F-9299-7FEE78E645E9 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = TimerLib + +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + BaseTimerLibHost.c + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + DebugLib + diff --git a/HBFA/UefiHostTestPkg/Library/DebugLibHost/DebugLibHost.c b/HBFA/UefiHostTestPkg/Library/DebugLibHost/DebugLibHost.c new file mode 100644 index 0000000..1bc306c --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/DebugLibHost/DebugLibHost.c @@ -0,0 +1,182 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifndef HOST_DEBUG_MESSAGE +#define HOST_DEBUG_MESSAGE 0 +#endif + +// +// Define the maximum debug and assert message length that this library supports +// +#define MAX_DEBUG_MESSAGE_LENGTH 0x100 + +VOID +EFIAPI +DebugAssert ( + IN CONST CHAR8 *FileName, + IN UINTN LineNumber, + IN CONST CHAR8 *Description + ) +{ +#ifndef TEST_WITH_KLEE + printf ("ASSERT: %s(%d): %s\n", FileName, (INT32)(UINT32)LineNumber, Description); + CpuBreakpoint (); +#endif +} + +BOOLEAN +EFIAPI +DebugAssertEnabled ( + VOID + ) +{ + return TRUE; +} + +VOID +PatchFormat ( + IN CONST CHAR8 *Format, + IN CHAR8 *MyFormat + ) +{ + UINTN Index; + UINTN MyIndex; + + Index = 0; + MyIndex = 0; + while (Format[Index] != 0) { + MyFormat[MyIndex] = Format[Index]; + if (Format[Index] == '%') { + Index++; + MyIndex++; + switch (Format[Index]) { + case 'a': + MyFormat[MyIndex] = 's'; + break; + case 's': + MyFormat[MyIndex] = 'w'; + MyIndex++; + MyFormat[MyIndex] = 's'; + break; + case 'g': + case 't': + MyFormat[MyIndex] = 'p'; + break; + case 'r': + MyFormat[MyIndex] = 'x'; + break; + case 'L': + case 'l': + MyFormat[MyIndex] = 'I'; + MyIndex++; + MyFormat[MyIndex] = '6'; + MyIndex++; + MyFormat[MyIndex] = '4'; + break; + case '0': + MyFormat[MyIndex] = Format[Index]; + if (Format[Index + 1] == '1') { + Index++; + MyIndex++; + MyFormat[MyIndex] = Format[Index]; + } + case '1': + MyFormat[MyIndex] = Format[Index]; + if (Format[Index + 1] == '6') { + Index++; + MyIndex++; + MyFormat[MyIndex] = Format[Index]; + } + if (Format[Index + 1] == 'l') { + Index++; + MyIndex++; + MyFormat[MyIndex] = 'I'; + MyIndex++; + MyFormat[MyIndex] = '6'; + MyIndex++; + MyFormat[MyIndex] = '4'; + } + if (Format[Index + 1] == 'l') { + Index++; + } + break; + default: + MyFormat[MyIndex] = Format[Index]; + break; + } + } + Index++; + MyIndex++; + } + MyFormat[MyIndex] = 0; +} + +VOID +EFIAPI +DebugPrint ( + IN UINTN ErrorLevel, + IN CONST CHAR8 *Format, + ... + ) +{ +#ifndef TEST_WITH_KLEE +#if HOST_DEBUG_MESSAGE + CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; + CHAR8 MyFormat[MAX_DEBUG_MESSAGE_LENGTH]; + VA_LIST Marker; + + VA_START (Marker, Format); + + if (0) { + PatchFormat (Format, MyFormat); + vsprintf (Buffer, MyFormat, Marker); + } else { + AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker); + } + VA_END (Marker); + + printf ("%s", Buffer); +#endif +#endif +} + +BOOLEAN +EFIAPI +DebugPrintEnabled ( + VOID + ) +{ + return TRUE; +} + +BOOLEAN +EFIAPI +DebugPrintLevelEnabled ( + IN CONST UINTN ErrorLevel + ) +{ + return TRUE; +} + +BOOLEAN +EFIAPI +DebugCodeEnabled ( + VOID + ) +{ + return TRUE; +} diff --git a/HBFA/UefiHostTestPkg/Library/DebugLibHost/DebugLibHost.inf b/HBFA/UefiHostTestPkg/Library/DebugLibHost/DebugLibHost.inf new file mode 100644 index 0000000..292c8b5 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/DebugLibHost/DebugLibHost.inf @@ -0,0 +1,31 @@ +## @file +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DebugLibHost + FILE_GUID = 6A77CE89-C1B6-4A6B-9561-07D7127514A7 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = DebugLib + +[Sources] + DebugLibHost.c + +[Packages] + MdePkg/MdePkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + +[LibraryClasses] + BaseLib + PrintLib + +[BuildOptions] + MSFT:*_*_*_CC_FLAGS = /D _CRT_SECURE_NO_WARNINGS + GCC:*_KLEE_*_CC_FLAGS = "-DTEST_WITH_KLEE=TRUE" + + diff --git a/HBFA/UefiHostTestPkg/Library/DxeServicesTableLibHost/DxeServicesTableLibHost.c b/HBFA/UefiHostTestPkg/Library/DxeServicesTableLibHost/DxeServicesTableLibHost.c new file mode 100644 index 0000000..0eb6009 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/DxeServicesTableLibHost/DxeServicesTableLibHost.c @@ -0,0 +1,192 @@ +/** @file + This library implement library class DxeServiceTableLib. + It produce EFI_DXE_SERVICE pointer in global variable gDS in library's constructure. + + A DXE driver can use gDS pointer to access services in EFI_DXE_SERVICE, if this + DXE driver declare that use DxeServicesTableLib library class and link to this + library instance. + + Please attention this library instance can not be used util EFI_SYSTEM_TABLE was + initialized. + + This library contains contruct function to retrieve EFI_DXE_SERIVCE, this construct + function will be invoked in DXE driver's autogen file. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Gcd.h" + +EFI_STATUS +CoreInitializeGcdServices ( + IN UINT8 SizeOfMemorySpace, + IN UINT8 SizeOfIoSpace + ); + +extern EFI_DXE_SERVICES mDxeServices; + +// +// Cache copy of the DXE Services Table +// +EFI_DXE_SERVICES *gDS = &mDxeServices; + +BOOLEAN mOnGuarding = FALSE; +EFI_CPU_ARCH_PROTOCOL *gCpu = NULL; + +/** + This is the main Dispatcher for DXE and it exits when there are no more + drivers to run. Drain the mScheduledQueue and load and start a PE + image for each driver. Search the mDiscoveredList to see if any driver can + be placed on the mScheduledQueue. If no drivers are placed on the + mScheduledQueue exit the function. On exit it is assumed the Bds() + will be called, and when the Bds() exits the Dispatcher will be called + again. + + @retval EFI_ALREADY_STARTED The DXE Dispatcher is already running + @retval EFI_NOT_FOUND No DXE Drivers were dispatched + @retval EFI_SUCCESS One or more DXE Drivers were dispatched + +**/ +EFI_STATUS +EFIAPI +CoreDispatcher ( + VOID + ) +{ + ASSERT(FALSE); + return EFI_UNSUPPORTED; +} + +/** + Check every driver and locate a matching one. If the driver is found, the Unrequested + state flag is cleared. + + @param FirmwareVolumeHandle The handle of the Firmware Volume that contains + the firmware file specified by DriverName. + @param DriverName The Driver name to put in the Dependent state. + + @retval EFI_SUCCESS The DriverName was found and it's SOR bit was + cleared + @retval EFI_NOT_FOUND The DriverName does not exist or it's SOR bit was + not set. + +**/ +EFI_STATUS +EFIAPI +CoreSchedule ( + IN EFI_HANDLE FirmwareVolumeHandle, + IN EFI_GUID *DriverName + ) +{ + ASSERT(FALSE); + return EFI_UNSUPPORTED; +} + + +/** + Convert a driver from the Untrused back to the Scheduled state. + + @param FirmwareVolumeHandle The handle of the Firmware Volume that contains + the firmware file specified by DriverName. + @param DriverName The Driver name to put in the Scheduled state + + @retval EFI_SUCCESS The file was found in the untrusted state, and it + was promoted to the trusted state. + @retval EFI_NOT_FOUND The file was not found in the untrusted state. + +**/ +EFI_STATUS +EFIAPI +CoreTrust ( + IN EFI_HANDLE FirmwareVolumeHandle, + IN EFI_GUID *DriverName + ) +{ + ASSERT(FALSE); + return EFI_UNSUPPORTED; +} + +/** + This DXE service routine is used to process a firmware volume. In + particular, it can be called by BDS to process a single firmware + volume found in a capsule. + + @param FvHeader pointer to a firmware volume header + @param Size the size of the buffer pointed to by FvHeader + @param FVProtocolHandle the handle on which a firmware volume protocol + was produced for the firmware volume passed in. + + @retval EFI_OUT_OF_RESOURCES if an FVB could not be produced due to lack of + system resources + @retval EFI_VOLUME_CORRUPTED if the volume was corrupted + @retval EFI_SUCCESS a firmware volume protocol was produced for the + firmware volume + +**/ +EFI_STATUS +EFIAPI +CoreProcessFirmwareVolume ( + IN VOID *FvHeader, + IN UINTN Size, + OUT EFI_HANDLE *FVProtocolHandle + ) +{ + ASSERT(FALSE); + return EFI_UNSUPPORTED; +} + +/** + Called to initialize the memory map and add descriptors to + the current descriptor list. + The first descriptor that is added must be general usable + memory as the addition allocates heap. + + @param Type The type of memory to add + @param Start The starting address in the memory range Must be + page aligned + @param NumberOfPages The number of pages in the range + @param Attribute Attributes of the memory to add + + @return None. The range is added to the memory map + +**/ +VOID +CoreAddMemoryDescriptor ( + IN EFI_MEMORY_TYPE Type, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 NumberOfPages, + IN UINT64 Attribute + ) +{ + ASSERT(FALSE); +} + +/** + Internal function. Converts a memory range to use new attributes. + + @param Start The first address of the range Must be page + aligned + @param NumberOfPages The number of pages to convert + @param NewAttributes The new attributes value for the range. + +**/ +VOID +CoreUpdateMemoryAttributes ( + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 NumberOfPages, + IN UINT64 NewAttributes + ) +{ + ASSERT(FALSE); +} + +EFI_STATUS +EFIAPI +DxeServicesTableLibConstructor ( + VOID + ) +{ + return CoreInitializeGcdServices (48, 36); +} \ No newline at end of file diff --git a/HBFA/UefiHostTestPkg/Library/DxeServicesTableLibHost/DxeServicesTableLibHost.inf b/HBFA/UefiHostTestPkg/Library/DxeServicesTableLibHost/DxeServicesTableLibHost.inf new file mode 100644 index 0000000..0eb3194 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/DxeServicesTableLibHost/DxeServicesTableLibHost.inf @@ -0,0 +1,40 @@ +## @file +# Instance of DXE Services Table Library using EFI Configuration Table. +# +# DXE Services Table Library that retrieves a pointer to the DXE Services +# Table from the Configuration Table in the EFI System Table. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DxeServicesTableLib + FILE_GUID = 3F614DC7-4B8B-4181-9AEF-995427F4E0A1 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = DxeServicesTableLib + CONSTRUCTOR = DxeServicesTableLibConstructor + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + DxeServicesTableLibHost.c + Gcd.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib + UefiBootServicesTableLib + diff --git a/HBFA/UefiHostTestPkg/Library/DxeServicesTableLibHost/Gcd.c b/HBFA/UefiHostTestPkg/Library/DxeServicesTableLibHost/Gcd.c new file mode 100644 index 0000000..ed9c935 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/DxeServicesTableLibHost/Gcd.c @@ -0,0 +1,2158 @@ +/** @file + The file contains the GCD related services in the EFI Boot Services Table. + The GCD services are used to manage the memory and I/O regions that + are accessible to the CPU that is executing the DXE core. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Gcd.h" + +#define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \ + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \ + EFI_RESOURCE_ATTRIBUTE_TESTED | \ + EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | \ + EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | \ + EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \ + EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED | \ + EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \ + EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \ + EFI_RESOURCE_ATTRIBUTE_64_BIT_IO | \ + EFI_RESOURCE_ATTRIBUTE_PERSISTENT ) + +#define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \ + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \ + EFI_RESOURCE_ATTRIBUTE_TESTED ) + +#define INITIALIZED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \ + EFI_RESOURCE_ATTRIBUTE_INITIALIZED ) + +#define PRESENT_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT) + +#define EXCLUSIVE_MEMORY_ATTRIBUTES (EFI_MEMORY_UC | EFI_MEMORY_WC | \ + EFI_MEMORY_WT | EFI_MEMORY_WB | \ + EFI_MEMORY_WP | EFI_MEMORY_UCE) + +#define NONEXCLUSIVE_MEMORY_ATTRIBUTES (EFI_MEMORY_XP | EFI_MEMORY_RP | \ + EFI_MEMORY_RO) + +// +// Module Variables +// +EFI_LOCK mGcdMemorySpaceLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY); +EFI_LOCK mGcdIoSpaceLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY); +LIST_ENTRY mGcdMemorySpaceMap = INITIALIZE_LIST_HEAD_VARIABLE (mGcdMemorySpaceMap); +LIST_ENTRY mGcdIoSpaceMap = INITIALIZE_LIST_HEAD_VARIABLE (mGcdIoSpaceMap); + +EFI_GCD_MAP_ENTRY mGcdMemorySpaceMapEntryTemplate = { + EFI_GCD_MAP_SIGNATURE, + { + NULL, + NULL + }, + 0, + 0, + 0, + 0, + EfiGcdMemoryTypeNonExistent, + (EFI_GCD_IO_TYPE) 0, + NULL, + NULL +}; + +EFI_GCD_MAP_ENTRY mGcdIoSpaceMapEntryTemplate = { + EFI_GCD_MAP_SIGNATURE, + { + NULL, + NULL + }, + 0, + 0, + 0, + 0, + (EFI_GCD_MEMORY_TYPE) 0, + EfiGcdIoTypeNonExistent, + NULL, + NULL +}; + +GCD_ATTRIBUTE_CONVERSION_ENTRY mAttributeConversionTable[] = { + { EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE, EFI_MEMORY_UC, TRUE }, + { EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED, EFI_MEMORY_UCE, TRUE }, + { EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE, EFI_MEMORY_WC, TRUE }, + { EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE, EFI_MEMORY_WT, TRUE }, + { EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE, EFI_MEMORY_WB, TRUE }, + { EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE, EFI_MEMORY_RP, TRUE }, + { EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE, EFI_MEMORY_WP, TRUE }, + { EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE, EFI_MEMORY_XP, TRUE }, + { EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE, EFI_MEMORY_RO, TRUE }, + { EFI_RESOURCE_ATTRIBUTE_PRESENT, EFI_MEMORY_PRESENT, FALSE }, + { EFI_RESOURCE_ATTRIBUTE_INITIALIZED, EFI_MEMORY_INITIALIZED, FALSE }, + { EFI_RESOURCE_ATTRIBUTE_TESTED, EFI_MEMORY_TESTED, FALSE }, + { EFI_RESOURCE_ATTRIBUTE_PERSISTABLE, EFI_MEMORY_NV, TRUE }, + { EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE, EFI_MEMORY_MORE_RELIABLE, TRUE }, + { 0, 0, FALSE } +}; + +/// +/// Lookup table used to print GCD Memory Space Map +/// +GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mGcdMemoryTypeNames[] = { + "NonExist ", // EfiGcdMemoryTypeNonExistent + "Reserved ", // EfiGcdMemoryTypeReserved + "SystemMem", // EfiGcdMemoryTypeSystemMemory + "MMIO ", // EfiGcdMemoryTypeMemoryMappedIo + "PersisMem", // EfiGcdMemoryTypePersistent + "MoreRelia", // EfiGcdMemoryTypeMoreReliable + "Unknown " // EfiGcdMemoryTypeMaximum +}; + +/// +/// Lookup table used to print GCD I/O Space Map +/// +GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mGcdIoTypeNames[] = { + "NonExist", // EfiGcdIoTypeNonExistent + "Reserved", // EfiGcdIoTypeReserved + "I/O ", // EfiGcdIoTypeIo + "Unknown " // EfiGcdIoTypeMaximum +}; + +/// +/// Lookup table used to print GCD Allocation Types +/// +GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mGcdAllocationTypeNames[] = { + "AnySearchBottomUp ", // EfiGcdAllocateAnySearchBottomUp + "MaxAddressSearchBottomUp ", // EfiGcdAllocateMaxAddressSearchBottomUp + "AtAddress ", // EfiGcdAllocateAddress + "AnySearchTopDown ", // EfiGcdAllocateAnySearchTopDown + "MaxAddressSearchTopDown ", // EfiGcdAllocateMaxAddressSearchTopDown + "Unknown " // EfiGcdMaxAllocateType +}; + +/** + Dump the entire contents if the GCD Memory Space Map using DEBUG() macros when + PcdDebugPrintErrorLevel has the DEBUG_GCD bit set. + + @param InitialMap TRUE if the initial GCD Memory Map is being dumped. Otherwise, FALSE. + +**/ +VOID +EFIAPI +CoreDumpGcdMemorySpaceMap ( + BOOLEAN InitialMap + ) +{ + DEBUG_CODE ( + EFI_STATUS Status; + UINTN NumberOfDescriptors; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap; + UINTN Index; + + Status = CoreGetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap); + ASSERT (Status == EFI_SUCCESS && MemorySpaceMap != NULL); + + if (InitialMap) { + DEBUG ((DEBUG_GCD, "GCD:Initial GCD Memory Space Map\n")); + } + DEBUG ((DEBUG_GCD, "GCDMemType Range Capabilities Attributes \n")); + DEBUG ((DEBUG_GCD, "========== ================================= ================ ================\n")); + for (Index = 0; Index < NumberOfDescriptors; Index++) { + DEBUG ((DEBUG_GCD, "%a %016lx-%016lx %016lx %016lx%c\n", + mGcdMemoryTypeNames[MIN (MemorySpaceMap[Index].GcdMemoryType, EfiGcdMemoryTypeMaximum-1)], + MemorySpaceMap[Index].BaseAddress, + MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - 1, + MemorySpaceMap[Index].Capabilities, + MemorySpaceMap[Index].Attributes, + MemorySpaceMap[Index].ImageHandle == NULL ? ' ' : '*' + )); + } + DEBUG ((DEBUG_GCD, "\n")); + FreePool (MemorySpaceMap); + ); +} + +/** + Dump the entire contents if the GCD I/O Space Map using DEBUG() macros when + PcdDebugPrintErrorLevel has the DEBUG_GCD bit set. + + @param InitialMap TRUE if the initial GCD I/O Map is being dumped. Otherwise, FALSE. + +**/ +VOID +EFIAPI +CoreDumpGcdIoSpaceMap ( + BOOLEAN InitialMap + ) +{ + DEBUG_CODE ( + EFI_STATUS Status; + UINTN NumberOfDescriptors; + EFI_GCD_IO_SPACE_DESCRIPTOR *IoSpaceMap; + UINTN Index; + + Status = CoreGetIoSpaceMap (&NumberOfDescriptors, &IoSpaceMap); + ASSERT (Status == EFI_SUCCESS && IoSpaceMap != NULL); + + if (InitialMap) { + DEBUG ((DEBUG_GCD, "GCD:Initial GCD I/O Space Map\n")); + } + + DEBUG ((DEBUG_GCD, "GCDIoType Range \n")); + DEBUG ((DEBUG_GCD, "========== =================================\n")); + for (Index = 0; Index < NumberOfDescriptors; Index++) { + DEBUG ((DEBUG_GCD, "%a %016lx-%016lx%c\n", + mGcdIoTypeNames[MIN (IoSpaceMap[Index].GcdIoType, EfiGcdIoTypeMaximum)], + IoSpaceMap[Index].BaseAddress, + IoSpaceMap[Index].BaseAddress + IoSpaceMap[Index].Length - 1, + IoSpaceMap[Index].ImageHandle == NULL ? ' ' : '*' + )); + } + DEBUG ((DEBUG_GCD, "\n")); + FreePool (IoSpaceMap); + ); +} + +/** + Validate resource descriptor HOB's attributes. + + If Attributes includes some memory resource's settings, it should include + the corresponding capabilites also. + + @param Attributes Resource descriptor HOB attributes. + +**/ +VOID +CoreValidateResourceDescriptorHobAttributes ( + IN UINT64 Attributes + ) +{ + ASSERT (((Attributes & EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED) == 0) || + ((Attributes & EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE) != 0)); + ASSERT (((Attributes & EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED) == 0) || + ((Attributes & EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE) != 0)); + ASSERT (((Attributes & EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED) == 0) || + ((Attributes & EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE) != 0)); + ASSERT (((Attributes & EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED) == 0) || + ((Attributes & EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE) != 0)); + ASSERT (((Attributes & EFI_RESOURCE_ATTRIBUTE_PERSISTENT) == 0) || + ((Attributes & EFI_RESOURCE_ATTRIBUTE_PERSISTABLE) != 0)); +} + +/** + Acquire memory lock on mGcdMemorySpaceLock. + +**/ +VOID +CoreAcquireGcdMemoryLock ( + VOID + ) +{ + CoreAcquireLock (&mGcdMemorySpaceLock); +} + + + +/** + Release memory lock on mGcdMemorySpaceLock. + +**/ +VOID +CoreReleaseGcdMemoryLock ( + VOID + ) +{ + CoreReleaseLock (&mGcdMemorySpaceLock); +} + + + +/** + Acquire memory lock on mGcdIoSpaceLock. + +**/ +VOID +CoreAcquireGcdIoLock ( + VOID + ) +{ + CoreAcquireLock (&mGcdIoSpaceLock); +} + + +/** + Release memory lock on mGcdIoSpaceLock. + +**/ +VOID +CoreReleaseGcdIoLock ( + VOID + ) +{ + CoreReleaseLock (&mGcdIoSpaceLock); +} + + + +// +// GCD Initialization Worker Functions +// +/** + Aligns a value to the specified boundary. + + @param Value 64 bit value to align + @param Alignment Log base 2 of the boundary to align Value to + @param RoundUp TRUE if Value is to be rounded up to the nearest + aligned boundary. FALSE is Value is to be + rounded down to the nearest aligned boundary. + + @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment. + +**/ +UINT64 +AlignValue ( + IN UINT64 Value, + IN UINTN Alignment, + IN BOOLEAN RoundUp + ) +{ + UINT64 AlignmentMask; + + AlignmentMask = LShiftU64 (1, Alignment) - 1; + if (RoundUp) { + Value += AlignmentMask; + } + return Value & (~AlignmentMask); +} + + +/** + Aligns address to the page boundary. + + @param Value 64 bit address to align + + @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment. + +**/ +UINT64 +PageAlignAddress ( + IN UINT64 Value + ) +{ + return AlignValue (Value, EFI_PAGE_SHIFT, TRUE); +} + + +/** + Aligns length to the page boundary. + + @param Value 64 bit length to align + + @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment. + +**/ +UINT64 +PageAlignLength ( + IN UINT64 Value + ) +{ + return AlignValue (Value, EFI_PAGE_SHIFT, FALSE); +} + +// +// GCD Memory Space Worker Functions +// + +/** + Allocate pool for two entries. + + @param TopEntry An entry of GCD map + @param BottomEntry An entry of GCD map + + @retval EFI_OUT_OF_RESOURCES No enough buffer to be allocated. + @retval EFI_SUCCESS Both entries successfully allocated. + +**/ +EFI_STATUS +CoreAllocateGcdMapEntry ( + IN OUT EFI_GCD_MAP_ENTRY **TopEntry, + IN OUT EFI_GCD_MAP_ENTRY **BottomEntry + ) +{ + // + // Set to mOnGuarding to TRUE before memory allocation. This will make sure + // that the entry memory is not "guarded" by HeapGuard. Otherwise it might + // cause problem when it's freed (if HeapGuard is enabled). + // + mOnGuarding = TRUE; + *TopEntry = AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY)); + mOnGuarding = FALSE; + if (*TopEntry == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + mOnGuarding = TRUE; + *BottomEntry = AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY)); + mOnGuarding = FALSE; + if (*BottomEntry == NULL) { + CoreFreePool (*TopEntry); + return EFI_OUT_OF_RESOURCES; + } + + return EFI_SUCCESS; +} + + +/** + Internal function. Inserts a new descriptor into a sorted list + + @param Link The linked list to insert the range BaseAddress + and Length into + @param Entry A pointer to the entry that is inserted + @param BaseAddress The base address of the new range + @param Length The length of the new range in bytes + @param TopEntry Top pad entry to insert if needed. + @param BottomEntry Bottom pad entry to insert if needed. + + @retval EFI_SUCCESS The new range was inserted into the linked list + +**/ +EFI_STATUS +CoreInsertGcdMapEntry ( + IN LIST_ENTRY *Link, + IN EFI_GCD_MAP_ENTRY *Entry, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_GCD_MAP_ENTRY *TopEntry, + IN EFI_GCD_MAP_ENTRY *BottomEntry + ) +{ + ASSERT (Length != 0); + + if (BaseAddress > Entry->BaseAddress) { + ASSERT (BottomEntry->Signature == 0); + + CopyMem (BottomEntry, Entry, sizeof (EFI_GCD_MAP_ENTRY)); + Entry->BaseAddress = BaseAddress; + BottomEntry->EndAddress = BaseAddress - 1; + InsertTailList (Link, &BottomEntry->Link); + } + + if ((BaseAddress + Length - 1) < Entry->EndAddress) { + ASSERT (TopEntry->Signature == 0); + + CopyMem (TopEntry, Entry, sizeof (EFI_GCD_MAP_ENTRY)); + TopEntry->BaseAddress = BaseAddress + Length; + Entry->EndAddress = BaseAddress + Length - 1; + InsertHeadList (Link, &TopEntry->Link); + } + + return EFI_SUCCESS; +} + + +/** + Merge the Gcd region specified by Link and its adjacent entry. + + @param Link Specify the entry to be merged (with its + adjacent entry). + @param Forward Direction (forward or backward). + @param Map Boundary. + + @retval EFI_SUCCESS Successfully returned. + @retval EFI_UNSUPPORTED These adjacent regions could not merge. + +**/ +EFI_STATUS +CoreMergeGcdMapEntry ( + IN LIST_ENTRY *Link, + IN BOOLEAN Forward, + IN LIST_ENTRY *Map + ) +{ + LIST_ENTRY *AdjacentLink; + EFI_GCD_MAP_ENTRY *Entry; + EFI_GCD_MAP_ENTRY *AdjacentEntry; + + // + // Get adjacent entry + // + if (Forward) { + AdjacentLink = Link->ForwardLink; + } else { + AdjacentLink = Link->BackLink; + } + + // + // If AdjacentLink is the head of the list, then no merge can be performed + // + if (AdjacentLink == Map) { + return EFI_SUCCESS; + } + + Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + AdjacentEntry = CR (AdjacentLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + + if (Entry->Capabilities != AdjacentEntry->Capabilities) { + return EFI_UNSUPPORTED; + } + if (Entry->Attributes != AdjacentEntry->Attributes) { + return EFI_UNSUPPORTED; + } + if (Entry->GcdMemoryType != AdjacentEntry->GcdMemoryType) { + return EFI_UNSUPPORTED; + } + if (Entry->GcdIoType != AdjacentEntry->GcdIoType) { + return EFI_UNSUPPORTED; + } + if (Entry->ImageHandle != AdjacentEntry->ImageHandle) { + return EFI_UNSUPPORTED; + } + if (Entry->DeviceHandle != AdjacentEntry->DeviceHandle) { + return EFI_UNSUPPORTED; + } + + if (Forward) { + Entry->EndAddress = AdjacentEntry->EndAddress; + } else { + Entry->BaseAddress = AdjacentEntry->BaseAddress; + } + RemoveEntryList (AdjacentLink); + CoreFreePool (AdjacentEntry); + + return EFI_SUCCESS; +} + + +/** + Merge adjacent entries on total chain. + + @param TopEntry Top entry of GCD map. + @param BottomEntry Bottom entry of GCD map. + @param StartLink Start link of the list for this loop. + @param EndLink End link of the list for this loop. + @param Map Boundary. + + @retval EFI_SUCCESS GCD map successfully cleaned up. + +**/ +EFI_STATUS +CoreCleanupGcdMapEntry ( + IN EFI_GCD_MAP_ENTRY *TopEntry, + IN EFI_GCD_MAP_ENTRY *BottomEntry, + IN LIST_ENTRY *StartLink, + IN LIST_ENTRY *EndLink, + IN LIST_ENTRY *Map + ) +{ + LIST_ENTRY *Link; + + if (TopEntry->Signature == 0) { + CoreFreePool (TopEntry); + } + if (BottomEntry->Signature == 0) { + CoreFreePool (BottomEntry); + } + + Link = StartLink; + while (Link != EndLink->ForwardLink) { + CoreMergeGcdMapEntry (Link, FALSE, Map); + Link = Link->ForwardLink; + } + CoreMergeGcdMapEntry (EndLink, TRUE, Map); + + return EFI_SUCCESS; +} + + +/** + Search a segment of memory space in GCD map. The result is a range of GCD entry list. + + @param BaseAddress The start address of the segment. + @param Length The length of the segment. + @param StartLink The first GCD entry involves this segment of + memory space. + @param EndLink The first GCD entry involves this segment of + memory space. + @param Map Points to the start entry to search. + + @retval EFI_SUCCESS Successfully found the entry. + @retval EFI_NOT_FOUND Not found. + +**/ +EFI_STATUS +CoreSearchGcdMapEntry ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + OUT LIST_ENTRY **StartLink, + OUT LIST_ENTRY **EndLink, + IN LIST_ENTRY *Map + ) +{ + LIST_ENTRY *Link; + EFI_GCD_MAP_ENTRY *Entry; + + ASSERT (Length != 0); + if ((Map == NULL) || (Length == 0)) { + DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER)); + return EFI_INVALID_PARAMETER; + } + + *StartLink = NULL; + *EndLink = NULL; + + Link = Map->ForwardLink; + while (Link != Map) { + Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + if (BaseAddress >= Entry->BaseAddress && BaseAddress <= Entry->EndAddress) { + *StartLink = Link; + } + if (*StartLink != NULL) { + if ((BaseAddress + Length - 1) >= Entry->BaseAddress && + (BaseAddress + Length - 1) <= Entry->EndAddress ) { + *EndLink = Link; + return EFI_SUCCESS; + } + } + Link = Link->ForwardLink; + } + + return EFI_NOT_FOUND; +} + + +/** + Count the amount of GCD map entries. + + @param Map Points to the start entry to do the count loop. + + @return The count. + +**/ +UINTN +CoreCountGcdMapEntry ( + IN LIST_ENTRY *Map + ) +{ + UINTN Count; + LIST_ENTRY *Link; + + Count = 0; + Link = Map->ForwardLink; + while (Link != Map) { + Count++; + Link = Link->ForwardLink; + } + + return Count; +} + + + +/** + Return the memory attribute specified by Attributes + + @param Attributes A num with some attribute bits on. + + @return The enum value of memory attribute. + +**/ +UINT64 +ConverToCpuArchAttributes ( + UINT64 Attributes + ) +{ + UINT64 CpuArchAttributes; + + CpuArchAttributes = Attributes & NONEXCLUSIVE_MEMORY_ATTRIBUTES; + + if ( (Attributes & EFI_MEMORY_UC) == EFI_MEMORY_UC) { + CpuArchAttributes |= EFI_MEMORY_UC; + } else if ( (Attributes & EFI_MEMORY_WC ) == EFI_MEMORY_WC) { + CpuArchAttributes |= EFI_MEMORY_WC; + } else if ( (Attributes & EFI_MEMORY_WT ) == EFI_MEMORY_WT) { + CpuArchAttributes |= EFI_MEMORY_WT; + } else if ( (Attributes & EFI_MEMORY_WB) == EFI_MEMORY_WB) { + CpuArchAttributes |= EFI_MEMORY_WB; + } else if ( (Attributes & EFI_MEMORY_UCE) == EFI_MEMORY_UCE) { + CpuArchAttributes |= EFI_MEMORY_UCE; + } else if ( (Attributes & EFI_MEMORY_WP) == EFI_MEMORY_WP) { + CpuArchAttributes |= EFI_MEMORY_WP; + } + + return CpuArchAttributes; +} + + +/** + Do operation on a segment of memory space specified (add, free, remove, change attribute ...). + + @param Operation The type of the operation + @param GcdMemoryType Additional information for the operation + @param GcdIoType Additional information for the operation + @param BaseAddress Start address of the segment + @param Length length of the segment + @param Capabilities The alterable attributes of a newly added entry + @param Attributes The attributes needs to be set + + @retval EFI_INVALID_PARAMETER Length is 0 or address (length) not aligned when + setting attribute. + @retval EFI_SUCCESS Action successfully done. + @retval EFI_UNSUPPORTED Could not find the proper descriptor on this + segment or set an upsupported attribute. + @retval EFI_ACCESS_DENIED Operate on an space non-exist or is used for an + image. + @retval EFI_NOT_FOUND Free a non-using space or remove a non-exist + space, and so on. + @retval EFI_OUT_OF_RESOURCES No buffer could be allocated. + @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol + is not available yet. +**/ +EFI_STATUS +CoreConvertSpace ( + IN UINTN Operation, + IN EFI_GCD_MEMORY_TYPE GcdMemoryType, + IN EFI_GCD_IO_TYPE GcdIoType, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Capabilities, + IN UINT64 Attributes + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Map; + LIST_ENTRY *Link; + EFI_GCD_MAP_ENTRY *Entry; + EFI_GCD_MAP_ENTRY *TopEntry; + EFI_GCD_MAP_ENTRY *BottomEntry; + LIST_ENTRY *StartLink; + LIST_ENTRY *EndLink; + UINT64 CpuArchAttributes; + + if (Length == 0) { + DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER)); + return EFI_INVALID_PARAMETER; + } + + Map = NULL; + if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) { + CoreAcquireGcdMemoryLock (); + Map = &mGcdMemorySpaceMap; + } else if ((Operation & GCD_IO_SPACE_OPERATION) != 0) { + CoreAcquireGcdIoLock (); + Map = &mGcdIoSpaceMap; + } else { + ASSERT (FALSE); + } + + // + // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length + // + Status = CoreSearchGcdMapEntry (BaseAddress, Length, &StartLink, &EndLink, Map); + if (EFI_ERROR (Status)) { + Status = EFI_UNSUPPORTED; + + goto Done; + } + ASSERT (StartLink != NULL && EndLink != NULL); + + // + // Verify that the list of descriptors are unallocated non-existent memory. + // + Link = StartLink; + while (Link != EndLink->ForwardLink) { + Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + switch (Operation) { + // + // Add operations + // + case GCD_ADD_MEMORY_OPERATION: + if (Entry->GcdMemoryType != EfiGcdMemoryTypeNonExistent || + Entry->ImageHandle != NULL ) { + Status = EFI_ACCESS_DENIED; + goto Done; + } + break; + case GCD_ADD_IO_OPERATION: + if (Entry->GcdIoType != EfiGcdIoTypeNonExistent || + Entry->ImageHandle != NULL ) { + Status = EFI_ACCESS_DENIED; + goto Done; + } + break; + // + // Free operations + // + case GCD_FREE_MEMORY_OPERATION: + case GCD_FREE_IO_OPERATION: + if (Entry->ImageHandle == NULL) { + Status = EFI_NOT_FOUND; + goto Done; + } + break; + // + // Remove operations + // + case GCD_REMOVE_MEMORY_OPERATION: + if (Entry->GcdMemoryType == EfiGcdMemoryTypeNonExistent) { + Status = EFI_NOT_FOUND; + goto Done; + } + if (Entry->ImageHandle != NULL) { + Status = EFI_ACCESS_DENIED; + goto Done; + } + break; + case GCD_REMOVE_IO_OPERATION: + if (Entry->GcdIoType == EfiGcdIoTypeNonExistent) { + Status = EFI_NOT_FOUND; + goto Done; + } + if (Entry->ImageHandle != NULL) { + Status = EFI_ACCESS_DENIED; + goto Done; + } + break; + // + // Set attributes operation + // + case GCD_SET_ATTRIBUTES_MEMORY_OPERATION: + if ((Attributes & EFI_MEMORY_RUNTIME) != 0) { + if ((BaseAddress & EFI_PAGE_MASK) != 0 || (Length & EFI_PAGE_MASK) != 0) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + } + if ((Entry->Capabilities & Attributes) != Attributes) { + Status = EFI_UNSUPPORTED; + goto Done; + } + break; + // + // Set capabilities operation + // + case GCD_SET_CAPABILITIES_MEMORY_OPERATION: + if ((BaseAddress & EFI_PAGE_MASK) != 0 || (Length & EFI_PAGE_MASK) != 0) { + Status = EFI_INVALID_PARAMETER; + + goto Done; + } + // + // Current attributes must still be supported with new capabilities + // + if ((Capabilities & Entry->Attributes) != Entry->Attributes) { + Status = EFI_UNSUPPORTED; + goto Done; + } + break; + } + Link = Link->ForwardLink; + } + + // + // Allocate work space to perform this operation + // + Status = CoreAllocateGcdMapEntry (&TopEntry, &BottomEntry); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + ASSERT (TopEntry != NULL && BottomEntry != NULL); + + // + // Initialize CpuArchAttributes to suppress incorrect compiler/analyzer warnings. + // + CpuArchAttributes = 0; + if (Operation == GCD_SET_ATTRIBUTES_MEMORY_OPERATION) { + // + // Call CPU Arch Protocol to attempt to set attributes on the range + // + CpuArchAttributes = ConverToCpuArchAttributes (Attributes); + // + // CPU arch attributes include page attributes and cache attributes. + // Only page attributes supports to be cleared, but not cache attributes. + // Caller is expected to use GetMemorySpaceDescriptor() to get the current + // attributes, AND/OR attributes, and then calls SetMemorySpaceAttributes() + // to set the new attributes. + // So 0 CPU arch attributes should not happen as memory should always have + // a cache attribute (no matter UC or WB, etc). + // + // Here, 0 CPU arch attributes will be filtered to be compatible with the + // case that caller just calls SetMemorySpaceAttributes() with none CPU + // arch attributes (for example, RUNTIME) as the purpose of the case is not + // to clear CPU arch attributes. + // + if (CpuArchAttributes != 0) { + if (gCpu == NULL) { + Status = EFI_NOT_AVAILABLE_YET; + } else { + Status = gCpu->SetMemoryAttributes ( + gCpu, + BaseAddress, + Length, + CpuArchAttributes + ); + } + if (EFI_ERROR (Status)) { + CoreFreePool (TopEntry); + CoreFreePool (BottomEntry); + goto Done; + } + } + } + + // + // Convert/Insert the list of descriptors from StartLink to EndLink + // + Link = StartLink; + while (Link != EndLink->ForwardLink) { + Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + CoreInsertGcdMapEntry (Link, Entry, BaseAddress, Length, TopEntry, BottomEntry); + switch (Operation) { + // + // Add operations + // + case GCD_ADD_MEMORY_OPERATION: + Entry->GcdMemoryType = GcdMemoryType; + if (GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) { + Entry->Capabilities = Capabilities | EFI_MEMORY_RUNTIME | EFI_MEMORY_PORT_IO; + } else { + Entry->Capabilities = Capabilities | EFI_MEMORY_RUNTIME; + } + break; + case GCD_ADD_IO_OPERATION: + Entry->GcdIoType = GcdIoType; + break; + // + // Free operations + // + case GCD_FREE_MEMORY_OPERATION: + case GCD_FREE_IO_OPERATION: + Entry->ImageHandle = NULL; + Entry->DeviceHandle = NULL; + break; + // + // Remove operations + // + case GCD_REMOVE_MEMORY_OPERATION: + Entry->GcdMemoryType = EfiGcdMemoryTypeNonExistent; + Entry->Capabilities = 0; + break; + case GCD_REMOVE_IO_OPERATION: + Entry->GcdIoType = EfiGcdIoTypeNonExistent; + break; + // + // Set attributes operation + // + case GCD_SET_ATTRIBUTES_MEMORY_OPERATION: + if (CpuArchAttributes == 0) { + // + // Keep original CPU arch attributes when caller just calls + // SetMemorySpaceAttributes() with none CPU arch attributes (for example, RUNTIME). + // + Attributes |= (Entry->Attributes & (EXCLUSIVE_MEMORY_ATTRIBUTES | NONEXCLUSIVE_MEMORY_ATTRIBUTES)); + } + Entry->Attributes = Attributes; + break; + // + // Set capabilities operation + // + case GCD_SET_CAPABILITIES_MEMORY_OPERATION: + Entry->Capabilities = Capabilities; + break; + } + Link = Link->ForwardLink; + } + + // + // Cleanup + // + Status = CoreCleanupGcdMapEntry (TopEntry, BottomEntry, StartLink, EndLink, Map); + +Done: + DEBUG ((DEBUG_GCD, " Status = %r\n", Status)); + + if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) { + CoreReleaseGcdMemoryLock (); + CoreDumpGcdMemorySpaceMap (FALSE); + } + if ((Operation & GCD_IO_SPACE_OPERATION) != 0) { + CoreReleaseGcdIoLock (); + CoreDumpGcdIoSpaceMap (FALSE); + } + + return Status; +} + + +/** + Check whether an entry could be used to allocate space. + + @param Operation Allocate memory or IO + @param Entry The entry to be tested + @param GcdMemoryType The desired memory type + @param GcdIoType The desired IO type + + @retval EFI_NOT_FOUND The memory type does not match or there's an + image handle on the entry. + @retval EFI_UNSUPPORTED The operation unsupported. + @retval EFI_SUCCESS It's ok for this entry to be used to allocate + space. + +**/ +EFI_STATUS +CoreAllocateSpaceCheckEntry ( + IN UINTN Operation, + IN EFI_GCD_MAP_ENTRY *Entry, + IN EFI_GCD_MEMORY_TYPE GcdMemoryType, + IN EFI_GCD_IO_TYPE GcdIoType + ) +{ + if (Entry->ImageHandle != NULL) { + return EFI_NOT_FOUND; + } + switch (Operation) { + case GCD_ALLOCATE_MEMORY_OPERATION: + if (Entry->GcdMemoryType != GcdMemoryType) { + return EFI_NOT_FOUND; + } + break; + case GCD_ALLOCATE_IO_OPERATION: + if (Entry->GcdIoType != GcdIoType) { + return EFI_NOT_FOUND; + } + break; + default: + return EFI_UNSUPPORTED; + } + return EFI_SUCCESS; +} + + +/** + Allocate space on specified address and length. + + @param Operation The type of operation (memory or IO) + @param GcdAllocateType The type of allocate operation + @param GcdMemoryType The desired memory type + @param GcdIoType The desired IO type + @param Alignment Align with 2^Alignment + @param Length Length to allocate + @param BaseAddress Base address to allocate + @param ImageHandle The image handle consume the allocated space. + @param DeviceHandle The device handle consume the allocated space. + + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_NOT_FOUND No descriptor for the desired space exists. + @retval EFI_SUCCESS Space successfully allocated. + +**/ +EFI_STATUS +CoreAllocateSpace ( + IN UINTN Operation, + IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType, + IN EFI_GCD_MEMORY_TYPE GcdMemoryType, + IN EFI_GCD_IO_TYPE GcdIoType, + IN UINTN Alignment, + IN UINT64 Length, + IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress, + IN EFI_HANDLE ImageHandle, + IN EFI_HANDLE DeviceHandle OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS AlignmentMask; + EFI_PHYSICAL_ADDRESS MaxAddress; + LIST_ENTRY *Map; + LIST_ENTRY *Link; + LIST_ENTRY *SubLink; + EFI_GCD_MAP_ENTRY *Entry; + EFI_GCD_MAP_ENTRY *TopEntry; + EFI_GCD_MAP_ENTRY *BottomEntry; + LIST_ENTRY *StartLink; + LIST_ENTRY *EndLink; + BOOLEAN Found; + + // + // Make sure parameters are valid + // + if ((UINT32)GcdAllocateType >= EfiGcdMaxAllocateType) { + DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER)); + return EFI_INVALID_PARAMETER; + } + if ((UINT32)GcdMemoryType >= EfiGcdMemoryTypeMaximum) { + DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER)); + return EFI_INVALID_PARAMETER; + } + if ((UINT32)GcdIoType >= EfiGcdIoTypeMaximum) { + DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER)); + return EFI_INVALID_PARAMETER; + } + if (BaseAddress == NULL) { + DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER)); + return EFI_INVALID_PARAMETER; + } + if (ImageHandle == NULL) { + DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER)); + return EFI_INVALID_PARAMETER; + } + if (Alignment >= 64) { + DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_NOT_FOUND)); + return EFI_NOT_FOUND; + } + if (Length == 0) { + DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER)); + return EFI_INVALID_PARAMETER; + } + + Map = NULL; + if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) { + CoreAcquireGcdMemoryLock (); + Map = &mGcdMemorySpaceMap; + } else if ((Operation & GCD_IO_SPACE_OPERATION) != 0) { + CoreAcquireGcdIoLock (); + Map = &mGcdIoSpaceMap; + } else { + ASSERT (FALSE); + } + + Found = FALSE; + StartLink = NULL; + EndLink = NULL; + // + // Compute alignment bit mask + // + AlignmentMask = LShiftU64 (1, Alignment) - 1; + + if (GcdAllocateType == EfiGcdAllocateAddress) { + // + // Verify that the BaseAddress passed in is aligned correctly + // + if ((*BaseAddress & AlignmentMask) != 0) { + Status = EFI_NOT_FOUND; + goto Done; + } + + // + // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length + // + Status = CoreSearchGcdMapEntry (*BaseAddress, Length, &StartLink, &EndLink, Map); + if (EFI_ERROR (Status)) { + Status = EFI_NOT_FOUND; + goto Done; + } + ASSERT (StartLink != NULL && EndLink != NULL); + + // + // Verify that the list of descriptors are unallocated memory matching GcdMemoryType. + // + Link = StartLink; + while (Link != EndLink->ForwardLink) { + Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + Link = Link->ForwardLink; + Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType); + if (EFI_ERROR (Status)) { + goto Done; + } + } + Found = TRUE; + } else { + + Entry = CR (Map->BackLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + + // + // Compute the maximum address to use in the search algorithm + // + if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchBottomUp || + GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ) { + MaxAddress = *BaseAddress; + } else { + MaxAddress = Entry->EndAddress; + } + + // + // Verify that the list of descriptors are unallocated memory matching GcdMemoryType. + // + if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown || + GcdAllocateType == EfiGcdAllocateAnySearchTopDown ) { + Link = Map->BackLink; + } else { + Link = Map->ForwardLink; + } + while (Link != Map) { + Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + + if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown || + GcdAllocateType == EfiGcdAllocateAnySearchTopDown ) { + Link = Link->BackLink; + } else { + Link = Link->ForwardLink; + } + + Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType); + if (EFI_ERROR (Status)) { + continue; + } + + if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown || + GcdAllocateType == EfiGcdAllocateAnySearchTopDown) { + if ((Entry->BaseAddress + Length) > MaxAddress) { + continue; + } + if (Length > (Entry->EndAddress + 1)) { + Status = EFI_NOT_FOUND; + goto Done; + } + if (Entry->EndAddress > MaxAddress) { + *BaseAddress = MaxAddress; + } else { + *BaseAddress = Entry->EndAddress; + } + *BaseAddress = (*BaseAddress + 1 - Length) & (~AlignmentMask); + } else { + *BaseAddress = (Entry->BaseAddress + AlignmentMask) & (~AlignmentMask); + if ((*BaseAddress + Length - 1) > MaxAddress) { + Status = EFI_NOT_FOUND; + goto Done; + } + } + + // + // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length + // + Status = CoreSearchGcdMapEntry (*BaseAddress, Length, &StartLink, &EndLink, Map); + if (EFI_ERROR (Status)) { + Status = EFI_NOT_FOUND; + goto Done; + } + ASSERT (StartLink != NULL && EndLink != NULL); + + Link = StartLink; + // + // Verify that the list of descriptors are unallocated memory matching GcdMemoryType. + // + Found = TRUE; + SubLink = StartLink; + while (SubLink != EndLink->ForwardLink) { + Entry = CR (SubLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType); + if (EFI_ERROR (Status)) { + Link = SubLink; + Found = FALSE; + break; + } + SubLink = SubLink->ForwardLink; + } + if (Found) { + break; + } + } + } + if (!Found) { + Status = EFI_NOT_FOUND; + goto Done; + } + + // + // Allocate work space to perform this operation + // + Status = CoreAllocateGcdMapEntry (&TopEntry, &BottomEntry); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + ASSERT (TopEntry != NULL && BottomEntry != NULL); + + // + // Convert/Insert the list of descriptors from StartLink to EndLink + // + Link = StartLink; + while (Link != EndLink->ForwardLink) { + Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + CoreInsertGcdMapEntry (Link, Entry, *BaseAddress, Length, TopEntry, BottomEntry); + Entry->ImageHandle = ImageHandle; + Entry->DeviceHandle = DeviceHandle; + Link = Link->ForwardLink; + } + + // + // Cleanup + // + Status = CoreCleanupGcdMapEntry (TopEntry, BottomEntry, StartLink, EndLink, Map); + +Done: + DEBUG ((DEBUG_GCD, " Status = %r", Status)); + if (!EFI_ERROR (Status)) { + DEBUG ((DEBUG_GCD, " (BaseAddress = %016lx)", *BaseAddress)); + } + DEBUG ((DEBUG_GCD, "\n")); + + if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) { + CoreReleaseGcdMemoryLock (); + CoreDumpGcdMemorySpaceMap (FALSE); + } + if ((Operation & GCD_IO_SPACE_OPERATION) !=0) { + CoreReleaseGcdIoLock (); + CoreDumpGcdIoSpaceMap (FALSE); + } + + return Status; +} + + +/** + Add a segment of memory to GCD map. + + @param GcdMemoryType Memory type of the segment. + @param BaseAddress Base address of the segment. + @param Length Length of the segment. + @param Capabilities alterable attributes of the segment. + + @retval EFI_INVALID_PARAMETER Invalid parameters. + @retval EFI_SUCCESS Successfully add a segment of memory space. + +**/ +EFI_STATUS +CoreInternalAddMemorySpace ( + IN EFI_GCD_MEMORY_TYPE GcdMemoryType, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Capabilities + ) +{ + DEBUG ((DEBUG_GCD, "GCD:AddMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length)); + DEBUG ((DEBUG_GCD, " GcdMemoryType = %a\n", mGcdMemoryTypeNames[MIN (GcdMemoryType, EfiGcdMemoryTypeMaximum-1)])); + DEBUG ((DEBUG_GCD, " Capabilities = %016lx\n", Capabilities)); + + // + // Make sure parameters are valid + // + if (GcdMemoryType <= EfiGcdMemoryTypeNonExistent || GcdMemoryType >= EfiGcdMemoryTypeMaximum) { + return EFI_INVALID_PARAMETER; + } + + return CoreConvertSpace (GCD_ADD_MEMORY_OPERATION, GcdMemoryType, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, Capabilities, 0); +} + +// +// GCD Core Services +// + +/** + Allocates nonexistent memory, reserved memory, system memory, or memorymapped + I/O resources from the global coherency domain of the processor. + + @param GcdAllocateType The type of allocate operation + @param GcdMemoryType The desired memory type + @param Alignment Align with 2^Alignment + @param Length Length to allocate + @param BaseAddress Base address to allocate + @param ImageHandle The image handle consume the allocated space. + @param DeviceHandle The device handle consume the allocated space. + + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_NOT_FOUND No descriptor contains the desired space. + @retval EFI_SUCCESS Memory space successfully allocated. + +**/ +EFI_STATUS +EFIAPI +CoreAllocateMemorySpace ( + IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType, + IN EFI_GCD_MEMORY_TYPE GcdMemoryType, + IN UINTN Alignment, + IN UINT64 Length, + IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress, + IN EFI_HANDLE ImageHandle, + IN EFI_HANDLE DeviceHandle OPTIONAL + ) +{ + if (BaseAddress != NULL) { + DEBUG ((DEBUG_GCD, "GCD:AllocateMemorySpace(Base=%016lx,Length=%016lx)\n", *BaseAddress, Length)); + } else { + DEBUG ((DEBUG_GCD, "GCD:AllocateMemorySpace(Base=,Length=%016lx)\n", Length)); + } + DEBUG ((DEBUG_GCD, " GcdAllocateType = %a\n", mGcdAllocationTypeNames[MIN (GcdAllocateType, EfiGcdMaxAllocateType)])); + DEBUG ((DEBUG_GCD, " GcdMemoryType = %a\n", mGcdMemoryTypeNames[MIN (GcdMemoryType, EfiGcdMemoryTypeMaximum-1)])); + DEBUG ((DEBUG_GCD, " Alignment = %016lx\n", LShiftU64 (1, Alignment))); + DEBUG ((DEBUG_GCD, " ImageHandle = %p\n", ImageHandle)); + DEBUG ((DEBUG_GCD, " DeviceHandle = %p\n", DeviceHandle)); + + return CoreAllocateSpace ( + GCD_ALLOCATE_MEMORY_OPERATION, + GcdAllocateType, + GcdMemoryType, + (EFI_GCD_IO_TYPE) 0, + Alignment, + Length, + BaseAddress, + ImageHandle, + DeviceHandle + ); +} + + +/** + Adds reserved memory, system memory, or memory-mapped I/O resources to the + global coherency domain of the processor. + + @param GcdMemoryType Memory type of the memory space. + @param BaseAddress Base address of the memory space. + @param Length Length of the memory space. + @param Capabilities alterable attributes of the memory space. + + @retval EFI_SUCCESS Merged this memory space into GCD map. + +**/ +EFI_STATUS +EFIAPI +CoreAddMemorySpace ( + IN EFI_GCD_MEMORY_TYPE GcdMemoryType, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Capabilities + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS PageBaseAddress; + UINT64 PageLength; + + Status = CoreInternalAddMemorySpace (GcdMemoryType, BaseAddress, Length, Capabilities); + + if (!EFI_ERROR (Status) && ((GcdMemoryType == EfiGcdMemoryTypeSystemMemory) || (GcdMemoryType == EfiGcdMemoryTypeMoreReliable))) { + + PageBaseAddress = PageAlignAddress (BaseAddress); + PageLength = PageAlignLength (BaseAddress + Length - PageBaseAddress); + + Status = CoreAllocateMemorySpace ( + EfiGcdAllocateAddress, + GcdMemoryType, + EFI_PAGE_SHIFT, + PageLength, + &PageBaseAddress, + gDxeCoreImageHandle, + NULL + ); + + if (!EFI_ERROR (Status)) { + CoreAddMemoryDescriptor ( + EfiConventionalMemory, + PageBaseAddress, + RShiftU64 (PageLength, EFI_PAGE_SHIFT), + Capabilities + ); + } else { + for (; PageLength != 0; PageLength -= EFI_PAGE_SIZE, PageBaseAddress += EFI_PAGE_SIZE) { + Status = CoreAllocateMemorySpace ( + EfiGcdAllocateAddress, + GcdMemoryType, + EFI_PAGE_SHIFT, + EFI_PAGE_SIZE, + &PageBaseAddress, + gDxeCoreImageHandle, + NULL + ); + + if (!EFI_ERROR (Status)) { + CoreAddMemoryDescriptor ( + EfiConventionalMemory, + PageBaseAddress, + 1, + Capabilities + ); + } + } + } + } + return Status; +} + + +/** + Frees nonexistent memory, reserved memory, system memory, or memory-mapped + I/O resources from the global coherency domain of the processor. + + @param BaseAddress Base address of the memory space. + @param Length Length of the memory space. + + @retval EFI_SUCCESS Space successfully freed. + +**/ +EFI_STATUS +EFIAPI +CoreFreeMemorySpace ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + DEBUG ((DEBUG_GCD, "GCD:FreeMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length)); + + return CoreConvertSpace (GCD_FREE_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0); +} + + +/** + Removes reserved memory, system memory, or memory-mapped I/O resources from + the global coherency domain of the processor. + + @param BaseAddress Base address of the memory space. + @param Length Length of the memory space. + + @retval EFI_SUCCESS Successfully remove a segment of memory space. + +**/ +EFI_STATUS +EFIAPI +CoreRemoveMemorySpace ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + DEBUG ((DEBUG_GCD, "GCD:RemoveMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length)); + + return CoreConvertSpace (GCD_REMOVE_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0); +} + + +/** + Build a memory descriptor according to an entry. + + @param Descriptor The descriptor to be built + @param Entry According to this entry + +**/ +VOID +BuildMemoryDescriptor ( + IN OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor, + IN EFI_GCD_MAP_ENTRY *Entry + ) +{ + Descriptor->BaseAddress = Entry->BaseAddress; + Descriptor->Length = Entry->EndAddress - Entry->BaseAddress + 1; + Descriptor->Capabilities = Entry->Capabilities; + Descriptor->Attributes = Entry->Attributes; + Descriptor->GcdMemoryType = Entry->GcdMemoryType; + Descriptor->ImageHandle = Entry->ImageHandle; + Descriptor->DeviceHandle = Entry->DeviceHandle; +} + + +/** + Retrieves the descriptor for a memory region containing a specified address. + + @param BaseAddress Specified start address + @param Descriptor Specified length + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_SUCCESS Successfully get memory space descriptor. + +**/ +EFI_STATUS +EFIAPI +CoreGetMemorySpaceDescriptor ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor + ) +{ + EFI_STATUS Status; + LIST_ENTRY *StartLink; + LIST_ENTRY *EndLink; + EFI_GCD_MAP_ENTRY *Entry; + + // + // Make sure parameters are valid + // + if (Descriptor == NULL) { + return EFI_INVALID_PARAMETER; + } + + CoreAcquireGcdMemoryLock (); + + // + // Search for the list of descriptors that contain BaseAddress + // + Status = CoreSearchGcdMapEntry (BaseAddress, 1, &StartLink, &EndLink, &mGcdMemorySpaceMap); + if (EFI_ERROR (Status)) { + Status = EFI_NOT_FOUND; + } else { + ASSERT (StartLink != NULL && EndLink != NULL); + // + // Copy the contents of the found descriptor into Descriptor + // + Entry = CR (StartLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + BuildMemoryDescriptor (Descriptor, Entry); + } + + CoreReleaseGcdMemoryLock (); + + return Status; +} + + +/** + Modifies the attributes for a memory region in the global coherency domain of the + processor. + + @param BaseAddress Specified start address + @param Length Specified length + @param Attributes Specified attributes + + @retval EFI_SUCCESS The attributes were set for the memory region. + @retval EFI_INVALID_PARAMETER Length is zero. + @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory + resource range specified by BaseAddress and Length. + @retval EFI_UNSUPPORTED The bit mask of attributes is not support for the memory resource + range specified by BaseAddress and Length. + @retval EFI_ACCESS_DEFINED The attributes for the memory resource range specified by + BaseAddress and Length cannot be modified. + @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of + the memory resource range. + @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol is + not available yet. + +**/ +EFI_STATUS +EFIAPI +CoreSetMemorySpaceAttributes ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ) +{ + DEBUG ((DEBUG_GCD, "GCD:SetMemorySpaceAttributes(Base=%016lx,Length=%016lx)\n", BaseAddress, Length)); + DEBUG ((DEBUG_GCD, " Attributes = %016lx\n", Attributes)); + + return CoreConvertSpace (GCD_SET_ATTRIBUTES_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, Attributes); +} + + +/** + Modifies the capabilities for a memory region in the global coherency domain of the + processor. + + @param BaseAddress The physical address that is the start address of a memory region. + @param Length The size in bytes of the memory region. + @param Capabilities The bit mask of capabilities that the memory region supports. + + @retval EFI_SUCCESS The capabilities were set for the memory region. + @retval EFI_INVALID_PARAMETER Length is zero. + @retval EFI_UNSUPPORTED The capabilities specified by Capabilities do not include the + memory region attributes currently in use. + @retval EFI_ACCESS_DENIED The capabilities for the memory resource range specified by + BaseAddress and Length cannot be modified. + @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the capabilities + of the memory resource range. +**/ +EFI_STATUS +EFIAPI +CoreSetMemorySpaceCapabilities ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Capabilities + ) +{ + EFI_STATUS Status; + + DEBUG ((DEBUG_GCD, "GCD:CoreSetMemorySpaceCapabilities(Base=%016lx,Length=%016lx)\n", BaseAddress, Length)); + DEBUG ((DEBUG_GCD, " Capabilities = %016lx\n", Capabilities)); + + Status = CoreConvertSpace (GCD_SET_CAPABILITIES_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, Capabilities, 0); + if (!EFI_ERROR(Status)) { + CoreUpdateMemoryAttributes(BaseAddress, RShiftU64(Length, EFI_PAGE_SHIFT), Capabilities & (~EFI_MEMORY_RUNTIME)); + } + + return Status; +} + + +/** + Returns a map of the memory resources in the global coherency domain of the + processor. + + @param NumberOfDescriptors Number of descriptors. + @param MemorySpaceMap Descriptor array + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate + @retval EFI_SUCCESS Successfully get memory space map. + +**/ +EFI_STATUS +EFIAPI +CoreGetMemorySpaceMap ( + OUT UINTN *NumberOfDescriptors, + OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR **MemorySpaceMap + ) +{ + LIST_ENTRY *Link; + EFI_GCD_MAP_ENTRY *Entry; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor; + UINTN DescriptorCount; + + // + // Make sure parameters are valid + // + if (NumberOfDescriptors == NULL) { + return EFI_INVALID_PARAMETER; + } + if (MemorySpaceMap == NULL) { + return EFI_INVALID_PARAMETER; + } + + *NumberOfDescriptors = 0; + *MemorySpaceMap = NULL; + + // + // Take the lock, for entering the loop with the lock held. + // + CoreAcquireGcdMemoryLock (); + while (TRUE) { + // + // Count descriptors. It might be done more than once because the + // AllocatePool() called below has to be running outside the GCD lock. + // + DescriptorCount = CoreCountGcdMapEntry (&mGcdMemorySpaceMap); + if (DescriptorCount == *NumberOfDescriptors) { + // + // Fill in the MemorySpaceMap if no memory space map change. + // + Descriptor = *MemorySpaceMap; + Link = mGcdMemorySpaceMap.ForwardLink; + while (Link != &mGcdMemorySpaceMap) { + Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + BuildMemoryDescriptor (Descriptor, Entry); + Descriptor++; + Link = Link->ForwardLink; + } + // + // We're done; exit the loop with the lock held. + // + break; + } + + // + // Release the lock before memory allocation, because it might cause + // GCD lock conflict in one of calling path in AllocatPool(). + // + CoreReleaseGcdMemoryLock (); + + // + // Allocate memory to store the MemorySpaceMap. Note it might be already + // allocated if there's map descriptor change during memory allocation at + // last time. + // + if (*MemorySpaceMap != NULL) { + FreePool (*MemorySpaceMap); + } + + *MemorySpaceMap = AllocatePool (DescriptorCount * + sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR)); + if (*MemorySpaceMap == NULL) { + *NumberOfDescriptors = 0; + return EFI_OUT_OF_RESOURCES; + } + + // + // Save the descriptor count got before for another round of check to make + // sure we won't miss any, since we have code running outside the GCD lock. + // + *NumberOfDescriptors = DescriptorCount; + // + // Re-acquire the lock, for the next iteration. + // + CoreAcquireGcdMemoryLock (); + } + // + // We exited the loop with the lock held, release it. + // + CoreReleaseGcdMemoryLock (); + + return EFI_SUCCESS; +} + + +/** + Adds reserved I/O or I/O resources to the global coherency domain of the processor. + + @param GcdIoType IO type of the segment. + @param BaseAddress Base address of the segment. + @param Length Length of the segment. + + @retval EFI_SUCCESS Merged this segment into GCD map. + @retval EFI_INVALID_PARAMETER Parameter not valid + +**/ +EFI_STATUS +EFIAPI +CoreAddIoSpace ( + IN EFI_GCD_IO_TYPE GcdIoType, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + DEBUG ((DEBUG_GCD, "GCD:AddIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length)); + DEBUG ((DEBUG_GCD, " GcdIoType = %a\n", mGcdIoTypeNames[MIN (GcdIoType, EfiGcdIoTypeMaximum)])); + + // + // Make sure parameters are valid + // + if (GcdIoType <= EfiGcdIoTypeNonExistent || GcdIoType >= EfiGcdIoTypeMaximum) { + return EFI_INVALID_PARAMETER; + } + return CoreConvertSpace (GCD_ADD_IO_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, GcdIoType, BaseAddress, Length, 0, 0); +} + + +/** + Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency + domain of the processor. + + @param GcdAllocateType The type of allocate operation + @param GcdIoType The desired IO type + @param Alignment Align with 2^Alignment + @param Length Length to allocate + @param BaseAddress Base address to allocate + @param ImageHandle The image handle consume the allocated space. + @param DeviceHandle The device handle consume the allocated space. + + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_NOT_FOUND No descriptor contains the desired space. + @retval EFI_SUCCESS IO space successfully allocated. + +**/ +EFI_STATUS +EFIAPI +CoreAllocateIoSpace ( + IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType, + IN EFI_GCD_IO_TYPE GcdIoType, + IN UINTN Alignment, + IN UINT64 Length, + IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress, + IN EFI_HANDLE ImageHandle, + IN EFI_HANDLE DeviceHandle OPTIONAL + ) +{ + if (BaseAddress != NULL) { + DEBUG ((DEBUG_GCD, "GCD:AllocateIoSpace(Base=%016lx,Length=%016lx)\n", *BaseAddress, Length)); + } else { + DEBUG ((DEBUG_GCD, "GCD:AllocateIoSpace(Base=,Length=%016lx)\n", Length)); + } + DEBUG ((DEBUG_GCD, " GcdAllocateType = %a\n", mGcdAllocationTypeNames[MIN (GcdAllocateType, EfiGcdMaxAllocateType)])); + DEBUG ((DEBUG_GCD, " GcdIoType = %a\n", mGcdIoTypeNames[MIN (GcdIoType, EfiGcdIoTypeMaximum)])); + DEBUG ((DEBUG_GCD, " Alignment = %016lx\n", LShiftU64 (1, Alignment))); + DEBUG ((DEBUG_GCD, " ImageHandle = %p\n", ImageHandle)); + DEBUG ((DEBUG_GCD, " DeviceHandle = %p\n", DeviceHandle)); + + return CoreAllocateSpace ( + GCD_ALLOCATE_IO_OPERATION, + GcdAllocateType, + (EFI_GCD_MEMORY_TYPE) 0, + GcdIoType, + Alignment, + Length, + BaseAddress, + ImageHandle, + DeviceHandle + ); +} + + +/** + Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency + domain of the processor. + + @param BaseAddress Base address of the segment. + @param Length Length of the segment. + + @retval EFI_SUCCESS Space successfully freed. + +**/ +EFI_STATUS +EFIAPI +CoreFreeIoSpace ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + DEBUG ((DEBUG_GCD, "GCD:FreeIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length)); + + return CoreConvertSpace (GCD_FREE_IO_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0); +} + + +/** + Removes reserved I/O or I/O resources from the global coherency domain of the + processor. + + @param BaseAddress Base address of the segment. + @param Length Length of the segment. + + @retval EFI_SUCCESS Successfully removed a segment of IO space. + +**/ +EFI_STATUS +EFIAPI +CoreRemoveIoSpace ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + DEBUG ((DEBUG_GCD, "GCD:RemoveIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length)); + + return CoreConvertSpace (GCD_REMOVE_IO_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0); +} + + +/** + Build a IO descriptor according to an entry. + + @param Descriptor The descriptor to be built + @param Entry According to this entry + +**/ +VOID +BuildIoDescriptor ( + IN EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor, + IN EFI_GCD_MAP_ENTRY *Entry + ) +{ + Descriptor->BaseAddress = Entry->BaseAddress; + Descriptor->Length = Entry->EndAddress - Entry->BaseAddress + 1; + Descriptor->GcdIoType = Entry->GcdIoType; + Descriptor->ImageHandle = Entry->ImageHandle; + Descriptor->DeviceHandle = Entry->DeviceHandle; +} + + +/** + Retrieves the descriptor for an I/O region containing a specified address. + + @param BaseAddress Specified start address + @param Descriptor Specified length + + @retval EFI_INVALID_PARAMETER Descriptor is NULL. + @retval EFI_SUCCESS Successfully get the IO space descriptor. + +**/ +EFI_STATUS +EFIAPI +CoreGetIoSpaceDescriptor ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + OUT EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor + ) +{ + EFI_STATUS Status; + LIST_ENTRY *StartLink; + LIST_ENTRY *EndLink; + EFI_GCD_MAP_ENTRY *Entry; + + // + // Make sure parameters are valid + // + if (Descriptor == NULL) { + return EFI_INVALID_PARAMETER; + } + + CoreAcquireGcdIoLock (); + + // + // Search for the list of descriptors that contain BaseAddress + // + Status = CoreSearchGcdMapEntry (BaseAddress, 1, &StartLink, &EndLink, &mGcdIoSpaceMap); + if (EFI_ERROR (Status)) { + Status = EFI_NOT_FOUND; + } else { + ASSERT (StartLink != NULL && EndLink != NULL); + // + // Copy the contents of the found descriptor into Descriptor + // + Entry = CR (StartLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + BuildIoDescriptor (Descriptor, Entry); + } + + CoreReleaseGcdIoLock (); + + return Status; +} + + +/** + Returns a map of the I/O resources in the global coherency domain of the processor. + + @param NumberOfDescriptors Number of descriptors. + @param IoSpaceMap Descriptor array + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate + @retval EFI_SUCCESS Successfully get IO space map. + +**/ +EFI_STATUS +EFIAPI +CoreGetIoSpaceMap ( + OUT UINTN *NumberOfDescriptors, + OUT EFI_GCD_IO_SPACE_DESCRIPTOR **IoSpaceMap + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Link; + EFI_GCD_MAP_ENTRY *Entry; + EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor; + + // + // Make sure parameters are valid + // + if (NumberOfDescriptors == NULL) { + return EFI_INVALID_PARAMETER; + } + if (IoSpaceMap == NULL) { + return EFI_INVALID_PARAMETER; + } + + CoreAcquireGcdIoLock (); + + // + // Count the number of descriptors + // + *NumberOfDescriptors = CoreCountGcdMapEntry (&mGcdIoSpaceMap); + + // + // Allocate the IoSpaceMap + // + *IoSpaceMap = AllocatePool (*NumberOfDescriptors * sizeof (EFI_GCD_IO_SPACE_DESCRIPTOR)); + if (*IoSpaceMap == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + // + // Fill in the IoSpaceMap + // + Descriptor = *IoSpaceMap; + Link = mGcdIoSpaceMap.ForwardLink; + while (Link != &mGcdIoSpaceMap) { + Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + BuildIoDescriptor (Descriptor, Entry); + Descriptor++; + Link = Link->ForwardLink; + } + Status = EFI_SUCCESS; + +Done: + CoreReleaseGcdIoLock (); + return Status; +} + + +/** + Converts a Resource Descriptor HOB attributes mask to an EFI Memory Descriptor + capabilities mask + + @param GcdMemoryType Type of resource in the GCD memory map. + @param Attributes The attribute mask in the Resource Descriptor + HOB. + + @return The capabilities mask for an EFI Memory Descriptor. + +**/ +UINT64 +CoreConvertResourceDescriptorHobAttributesToCapabilities ( + EFI_GCD_MEMORY_TYPE GcdMemoryType, + UINT64 Attributes + ) +{ + UINT64 Capabilities; + GCD_ATTRIBUTE_CONVERSION_ENTRY *Conversion; + + // + // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask + // + for (Capabilities = 0, Conversion = mAttributeConversionTable; Conversion->Attribute != 0; Conversion++) { + if (Conversion->Memory || ((GcdMemoryType != EfiGcdMemoryTypeSystemMemory) && (GcdMemoryType != EfiGcdMemoryTypeMoreReliable))) { + if (Attributes & Conversion->Attribute) { + Capabilities |= Conversion->Capability; + } + } + } + + return Capabilities; +} + + +/** + External function. Initializes the GCD and memory services based on the memory + descriptor HOBs. This function is responsible for priming the GCD map and the + memory map, so memory allocations and resource allocations can be made. The + HobStart will be relocated to a pool buffer. + + @param HobStart The start address of the HOB + @param MemoryBaseAddress Start address of memory region found to init DXE + core. + @param MemoryLength Length of memory region found to init DXE core. + + @retval EFI_SUCCESS GCD services successfully initialized. + +**/ +EFI_STATUS +CoreInitializeGcdServices ( + IN UINT8 SizeOfMemorySpace, + IN UINT8 SizeOfIoSpace + ) +{ + EFI_GCD_MAP_ENTRY *Entry; + + // + // Initialize the GCD Memory Space Map + // + Entry = AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdMemorySpaceMapEntryTemplate); + ASSERT (Entry != NULL); + + Entry->EndAddress = LShiftU64 (1, SizeOfMemorySpace) - 1; + + InsertHeadList (&mGcdMemorySpaceMap, &Entry->Link); + + CoreDumpGcdMemorySpaceMap (TRUE); + + // + // Initialize the GCD I/O Space Map + // + Entry = AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdIoSpaceMapEntryTemplate); + ASSERT (Entry != NULL); + + Entry->EndAddress = LShiftU64 (1, SizeOfIoSpace) - 1; + + InsertHeadList (&mGcdIoSpaceMap, &Entry->Link); + + CoreDumpGcdIoSpaceMap (TRUE); + + return EFI_SUCCESS; +} + +EFI_DXE_SERVICES mDxeServices = { + { + DXE_SERVICES_SIGNATURE, // Signature + DXE_SERVICES_REVISION, // Revision + sizeof (DXE_SERVICES), // HeaderSize + 0, // CRC32 + 0 // Reserved + }, + (EFI_ADD_MEMORY_SPACE) CoreAddMemorySpace, // AddMemorySpace + (EFI_ALLOCATE_MEMORY_SPACE) CoreAllocateMemorySpace, // AllocateMemorySpace + (EFI_FREE_MEMORY_SPACE) CoreFreeMemorySpace, // FreeMemorySpace + (EFI_REMOVE_MEMORY_SPACE) CoreRemoveMemorySpace, // RemoveMemorySpace + (EFI_GET_MEMORY_SPACE_DESCRIPTOR) CoreGetMemorySpaceDescriptor, // GetMemorySpaceDescriptor + (EFI_SET_MEMORY_SPACE_ATTRIBUTES) CoreSetMemorySpaceAttributes, // SetMemorySpaceAttributes + (EFI_GET_MEMORY_SPACE_MAP) CoreGetMemorySpaceMap, // GetMemorySpaceMap + (EFI_ADD_IO_SPACE) CoreAddIoSpace, // AddIoSpace + (EFI_ALLOCATE_IO_SPACE) CoreAllocateIoSpace, // AllocateIoSpace + (EFI_FREE_IO_SPACE) CoreFreeIoSpace, // FreeIoSpace + (EFI_REMOVE_IO_SPACE) CoreRemoveIoSpace, // RemoveIoSpace + (EFI_GET_IO_SPACE_DESCRIPTOR) CoreGetIoSpaceDescriptor, // GetIoSpaceDescriptor + (EFI_GET_IO_SPACE_MAP) CoreGetIoSpaceMap, // GetIoSpaceMap + (EFI_DISPATCH) CoreDispatcher, // Dispatch + (EFI_SCHEDULE) CoreSchedule, // Schedule + (EFI_TRUST) CoreTrust, // Trust + (EFI_PROCESS_FIRMWARE_VOLUME) CoreProcessFirmwareVolume, // ProcessFirmwareVolume + (EFI_SET_MEMORY_SPACE_CAPABILITIES)CoreSetMemorySpaceCapabilities, // SetMemorySpaceCapabilities +}; diff --git a/HBFA/UefiHostTestPkg/Library/DxeServicesTableLibHost/Gcd.h b/HBFA/UefiHostTestPkg/Library/DxeServicesTableLibHost/Gcd.h new file mode 100644 index 0000000..9b06767 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/DxeServicesTableLibHost/Gcd.h @@ -0,0 +1,588 @@ +/** @file + GCD Operations and data structure used to + convert from GCD attributes to EFI Memory Map attributes. + +Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _GCD_H_ +#define _GCD_H_ + +#include +#include +#include +#include +#include +#include +#include + +// +// GCD Operations +// +#define GCD_MEMORY_SPACE_OPERATION 0x20 +#define GCD_IO_SPACE_OPERATION 0x40 + +#define GCD_ADD_MEMORY_OPERATION (GCD_MEMORY_SPACE_OPERATION | 0) +#define GCD_ALLOCATE_MEMORY_OPERATION (GCD_MEMORY_SPACE_OPERATION | 1) +#define GCD_FREE_MEMORY_OPERATION (GCD_MEMORY_SPACE_OPERATION | 2) +#define GCD_REMOVE_MEMORY_OPERATION (GCD_MEMORY_SPACE_OPERATION | 3) +#define GCD_SET_ATTRIBUTES_MEMORY_OPERATION (GCD_MEMORY_SPACE_OPERATION | 4) +#define GCD_SET_CAPABILITIES_MEMORY_OPERATION (GCD_MEMORY_SPACE_OPERATION | 5) + +#define GCD_ADD_IO_OPERATION (GCD_IO_SPACE_OPERATION | 0) +#define GCD_ALLOCATE_IO_OPERATION (GCD_IO_SPACE_OPERATION | 1) +#define GCD_FREE_IO_OPERATION (GCD_IO_SPACE_OPERATION | 2) +#define GCD_REMOVE_IO_OPERATION (GCD_IO_SPACE_OPERATION | 3) + +// +// The data structure used to convert from GCD attributes to EFI Memory Map attributes +// +typedef struct { + UINT64 Attribute; + UINT64 Capability; + BOOLEAN Memory; +} GCD_ATTRIBUTE_CONVERSION_ENTRY; + +// From DxeMain.h + +// +//The data structure of GCD memory map entry +// +#define EFI_GCD_MAP_SIGNATURE SIGNATURE_32('g','c','d','m') +typedef struct { + UINTN Signature; + LIST_ENTRY Link; + EFI_PHYSICAL_ADDRESS BaseAddress; + UINT64 EndAddress; + UINT64 Capabilities; + UINT64 Attributes; + EFI_GCD_MEMORY_TYPE GcdMemoryType; + EFI_GCD_IO_TYPE GcdIoType; + EFI_HANDLE ImageHandle; + EFI_HANDLE DeviceHandle; +} EFI_GCD_MAP_ENTRY; + + +// +// attributes for reserved memory before it is promoted to system memory +// +#define EFI_MEMORY_PRESENT 0x0100000000000000ULL +#define EFI_MEMORY_INITIALIZED 0x0200000000000000ULL +#define EFI_MEMORY_TESTED 0x0400000000000000ULL + +// +// range for memory mapped port I/O on IPF +// +#define EFI_MEMORY_PORT_IO 0x4000000000000000ULL + + +/** + Adds reserved memory, system memory, or memory-mapped I/O resources to the + global coherency domain of the processor. + + @param GcdMemoryType Memory type of the memory space. + @param BaseAddress Base address of the memory space. + @param Length Length of the memory space. + @param Capabilities alterable attributes of the memory space. + + @retval EFI_SUCCESS Merged this memory space into GCD map. + +**/ +EFI_STATUS +EFIAPI +CoreAddMemorySpace ( + IN EFI_GCD_MEMORY_TYPE GcdMemoryType, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Capabilities + ); + + +/** + Allocates nonexistent memory, reserved memory, system memory, or memorymapped + I/O resources from the global coherency domain of the processor. + + @param GcdAllocateType The type of allocate operation + @param GcdMemoryType The desired memory type + @param Alignment Align with 2^Alignment + @param Length Length to allocate + @param BaseAddress Base address to allocate + @param ImageHandle The image handle consume the allocated space. + @param DeviceHandle The device handle consume the allocated space. + + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_NOT_FOUND No descriptor contains the desired space. + @retval EFI_SUCCESS Memory space successfully allocated. + +**/ +EFI_STATUS +EFIAPI +CoreAllocateMemorySpace ( + IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType, + IN EFI_GCD_MEMORY_TYPE GcdMemoryType, + IN UINTN Alignment, + IN UINT64 Length, + IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress, + IN EFI_HANDLE ImageHandle, + IN EFI_HANDLE DeviceHandle OPTIONAL + ); + + +/** + Frees nonexistent memory, reserved memory, system memory, or memory-mapped + I/O resources from the global coherency domain of the processor. + + @param BaseAddress Base address of the memory space. + @param Length Length of the memory space. + + @retval EFI_SUCCESS Space successfully freed. + +**/ +EFI_STATUS +EFIAPI +CoreFreeMemorySpace ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ); + + +/** + Removes reserved memory, system memory, or memory-mapped I/O resources from + the global coherency domain of the processor. + + @param BaseAddress Base address of the memory space. + @param Length Length of the memory space. + + @retval EFI_SUCCESS Successfully remove a segment of memory space. + +**/ +EFI_STATUS +EFIAPI +CoreRemoveMemorySpace ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ); + + +/** + Retrieves the descriptor for a memory region containing a specified address. + + @param BaseAddress Specified start address + @param Descriptor Specified length + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_SUCCESS Successfully get memory space descriptor. + +**/ +EFI_STATUS +EFIAPI +CoreGetMemorySpaceDescriptor ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor + ); + + +/** + Modifies the attributes for a memory region in the global coherency domain of the + processor. + + @param BaseAddress Specified start address + @param Length Specified length + @param Attributes Specified attributes + + @retval EFI_SUCCESS The attributes were set for the memory region. + @retval EFI_INVALID_PARAMETER Length is zero. + @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory + resource range specified by BaseAddress and Length. + @retval EFI_UNSUPPORTED The bit mask of attributes is not support for the memory resource + range specified by BaseAddress and Length. + @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by + BaseAddress and Length cannot be modified. + @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of + the memory resource range. + @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol is + not available yet. + +**/ +EFI_STATUS +EFIAPI +CoreSetMemorySpaceAttributes ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ); + + +/** + Modifies the capabilities for a memory region in the global coherency domain of the + processor. + + @param BaseAddress The physical address that is the start address of a memory region. + @param Length The size in bytes of the memory region. + @param Capabilities The bit mask of capabilities that the memory region supports. + + @retval EFI_SUCCESS The capabilities were set for the memory region. + @retval EFI_INVALID_PARAMETER Length is zero. + @retval EFI_UNSUPPORTED The capabilities specified by Capabilities do not include the + memory region attributes currently in use. + @retval EFI_ACCESS_DENIED The capabilities for the memory resource range specified by + BaseAddress and Length cannot be modified. + @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the capabilities + of the memory resource range. +**/ +EFI_STATUS +EFIAPI +CoreSetMemorySpaceCapabilities ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Capabilities + ); + + +/** + Returns a map of the memory resources in the global coherency domain of the + processor. + + @param NumberOfDescriptors Number of descriptors. + @param MemorySpaceMap Descriptor array + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate + @retval EFI_SUCCESS Successfully get memory space map. + +**/ +EFI_STATUS +EFIAPI +CoreGetMemorySpaceMap ( + OUT UINTN *NumberOfDescriptors, + OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR **MemorySpaceMap + ); + + +/** + Adds reserved I/O or I/O resources to the global coherency domain of the processor. + + @param GcdIoType IO type of the segment. + @param BaseAddress Base address of the segment. + @param Length Length of the segment. + + @retval EFI_SUCCESS Merged this segment into GCD map. + @retval EFI_INVALID_PARAMETER Parameter not valid + +**/ +EFI_STATUS +EFIAPI +CoreAddIoSpace ( + IN EFI_GCD_IO_TYPE GcdIoType, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ); + + +/** + Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency + domain of the processor. + + @param GcdAllocateType The type of allocate operation + @param GcdIoType The desired IO type + @param Alignment Align with 2^Alignment + @param Length Length to allocate + @param BaseAddress Base address to allocate + @param ImageHandle The image handle consume the allocated space. + @param DeviceHandle The device handle consume the allocated space. + + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_NOT_FOUND No descriptor contains the desired space. + @retval EFI_SUCCESS IO space successfully allocated. + +**/ +EFI_STATUS +EFIAPI +CoreAllocateIoSpace ( + IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType, + IN EFI_GCD_IO_TYPE GcdIoType, + IN UINTN Alignment, + IN UINT64 Length, + IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress, + IN EFI_HANDLE ImageHandle, + IN EFI_HANDLE DeviceHandle OPTIONAL + ); + + +/** + Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency + domain of the processor. + + @param BaseAddress Base address of the segment. + @param Length Length of the segment. + + @retval EFI_SUCCESS Space successfully freed. + +**/ +EFI_STATUS +EFIAPI +CoreFreeIoSpace ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ); + + +/** + Removes reserved I/O or I/O resources from the global coherency domain of the + processor. + + @param BaseAddress Base address of the segment. + @param Length Length of the segment. + + @retval EFI_SUCCESS Successfully removed a segment of IO space. + +**/ +EFI_STATUS +EFIAPI +CoreRemoveIoSpace ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ); + + +/** + Retrieves the descriptor for an I/O region containing a specified address. + + @param BaseAddress Specified start address + @param Descriptor Specified length + + @retval EFI_INVALID_PARAMETER Descriptor is NULL. + @retval EFI_SUCCESS Successfully get the IO space descriptor. + +**/ +EFI_STATUS +EFIAPI +CoreGetIoSpaceDescriptor ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + OUT EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor + ); + + +/** + Returns a map of the I/O resources in the global coherency domain of the processor. + + @param NumberOfDescriptors Number of descriptors. + @param IoSpaceMap Descriptor array + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate + @retval EFI_SUCCESS Successfully get IO space map. + +**/ +EFI_STATUS +EFIAPI +CoreGetIoSpaceMap ( + OUT UINTN *NumberOfDescriptors, + OUT EFI_GCD_IO_SPACE_DESCRIPTOR **IoSpaceMap + ); + +/** + This is the main Dispatcher for DXE and it exits when there are no more + drivers to run. Drain the mScheduledQueue and load and start a PE + image for each driver. Search the mDiscoveredList to see if any driver can + be placed on the mScheduledQueue. If no drivers are placed on the + mScheduledQueue exit the function. On exit it is assumed the Bds() + will be called, and when the Bds() exits the Dispatcher will be called + again. + + @retval EFI_ALREADY_STARTED The DXE Dispatcher is already running + @retval EFI_NOT_FOUND No DXE Drivers were dispatched + @retval EFI_SUCCESS One or more DXE Drivers were dispatched + +**/ +EFI_STATUS +EFIAPI +CoreDispatcher ( + VOID + ); + +/** + Check every driver and locate a matching one. If the driver is found, the Unrequested + state flag is cleared. + + @param FirmwareVolumeHandle The handle of the Firmware Volume that contains + the firmware file specified by DriverName. + @param DriverName The Driver name to put in the Dependent state. + + @retval EFI_SUCCESS The DriverName was found and it's SOR bit was + cleared + @retval EFI_NOT_FOUND The DriverName does not exist or it's SOR bit was + not set. + +**/ +EFI_STATUS +EFIAPI +CoreSchedule ( + IN EFI_HANDLE FirmwareVolumeHandle, + IN EFI_GUID *DriverName + ); + + +/** + Convert a driver from the Untrused back to the Scheduled state. + + @param FirmwareVolumeHandle The handle of the Firmware Volume that contains + the firmware file specified by DriverName. + @param DriverName The Driver name to put in the Scheduled state + + @retval EFI_SUCCESS The file was found in the untrusted state, and it + was promoted to the trusted state. + @retval EFI_NOT_FOUND The file was not found in the untrusted state. + +**/ +EFI_STATUS +EFIAPI +CoreTrust ( + IN EFI_HANDLE FirmwareVolumeHandle, + IN EFI_GUID *DriverName + ); + +/** + This DXE service routine is used to process a firmware volume. In + particular, it can be called by BDS to process a single firmware + volume found in a capsule. + + @param FvHeader pointer to a firmware volume header + @param Size the size of the buffer pointed to by FvHeader + @param FVProtocolHandle the handle on which a firmware volume protocol + was produced for the firmware volume passed in. + + @retval EFI_OUT_OF_RESOURCES if an FVB could not be produced due to lack of + system resources + @retval EFI_VOLUME_CORRUPTED if the volume was corrupted + @retval EFI_SUCCESS a firmware volume protocol was produced for the + firmware volume + +**/ +EFI_STATUS +EFIAPI +CoreProcessFirmwareVolume ( + IN VOID *FvHeader, + IN UINTN Size, + OUT EFI_HANDLE *FVProtocolHandle + ); + +/** + Raising to the task priority level of the mutual exclusion + lock, and then acquires ownership of the lock. + + @param Lock The lock to acquire + + @return Lock owned + +**/ +VOID +CoreAcquireLock ( + IN EFI_LOCK *Lock + ); + +/** + Releases ownership of the mutual exclusion lock, and + restores the previous task priority level. + + @param Lock The lock to release + + @return Lock unowned + +**/ +VOID +CoreReleaseLock ( + IN EFI_LOCK *Lock + ); + +/** + Raise the task priority level to the new level. + High level is implemented by disabling processor interrupts. + + @param NewTpl New task priority level + + @return The previous task priority level + +**/ +EFI_TPL +EFIAPI +CoreRaiseTpl ( + IN EFI_TPL NewTpl + ); + +/** + Lowers the task priority to the previous value. If the new + priority unmasks events at a higher priority, they are dispatched. + + @param NewTpl New, lower, task priority + +**/ +VOID +EFIAPI +CoreRestoreTpl ( + IN EFI_TPL NewTpl + ); + +/** + Frees pool. + + @param Buffer The allocated pool entry to free + + @retval EFI_INVALID_PARAMETER Buffer is not a valid value. + @retval EFI_SUCCESS Pool successfully freed. + +**/ +EFI_STATUS +EFIAPI +CoreFreePool ( + IN VOID *Buffer + ); + +/** + Called to initialize the memory map and add descriptors to + the current descriptor list. + The first descriptor that is added must be general usable + memory as the addition allocates heap. + + @param Type The type of memory to add + @param Start The starting address in the memory range Must be + page aligned + @param NumberOfPages The number of pages in the range + @param Attribute Attributes of the memory to add + + @return None. The range is added to the memory map + +**/ +VOID +CoreAddMemoryDescriptor ( + IN EFI_MEMORY_TYPE Type, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 NumberOfPages, + IN UINT64 Attribute + ); + +/** + Internal function. Converts a memory range to use new attributes. + + @param Start The first address of the range Must be page + aligned + @param NumberOfPages The number of pages to convert + @param NewAttributes The new attributes value for the range. + +**/ +VOID +CoreUpdateMemoryAttributes ( + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 NumberOfPages, + IN UINT64 NewAttributes + ); + +extern EFI_HANDLE gDxeCoreImageHandle; +extern EFI_CPU_ARCH_PROTOCOL *gCpu; + +// From HeapGuard.h +extern BOOLEAN mOnGuarding; + +#endif diff --git a/HBFA/UefiHostTestPkg/Library/HobLibHost/HobLibHost.c b/HBFA/UefiHostTestPkg/Library/HobLibHost/HobLibHost.c new file mode 100644 index 0000000..987be34 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/HobLibHost/HobLibHost.c @@ -0,0 +1,798 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +#include +#include +#include +#include + +VOID *gHobPointer; + +VOID +InitHobPointer ( + VOID + ) +{ + EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; + EFI_HOB_GENERIC_HEADER *HobEnd; + + gHobPointer = AllocatePool (SIZE_64KB); + assert (gHobPointer != NULL); + ZeroMem (gHobPointer, SIZE_64KB); + HandOffHob = gHobPointer; + HandOffHob->Header.HobType = EFI_HOB_TYPE_HANDOFF; + HandOffHob->Header.HobLength = sizeof(EFI_HOB_HANDOFF_INFO_TABLE); + HandOffHob->Version = EFI_HOB_HANDOFF_TABLE_VERSION; + HandOffHob->BootMode = BOOT_WITH_FULL_CONFIGURATION; + HandOffHob->EfiEndOfHobList = (UINTN)(HandOffHob + 1); + + HobEnd = (EFI_HOB_GENERIC_HEADER*) ((UINTN) HandOffHob + sizeof(EFI_HOB_HANDOFF_INFO_TABLE)); + HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST; + HobEnd->HobLength = (UINT16) sizeof (EFI_HOB_GENERIC_HEADER); +} + +/** + Returns the pointer to the HOB list. + + This function returns the pointer to first HOB in the list. + For PEI phase, the PEI service GetHobList() can be used to retrieve the pointer + to the HOB list. For the DXE phase, the HOB list pointer can be retrieved through + the EFI System Table by looking up theHOB list GUID in the System Configuration Table. + Since the System Configuration Table does not exist that the time the DXE Core is + launched, the DXE Core uses a global variable from the DXE Core Entry Point Library + to manage the pointer to the HOB list. + + If the pointer to the HOB list is NULL, then ASSERT(). + + @return The pointer to the HOB list. + +**/ +VOID * +EFIAPI +GetHobList ( + VOID + ) +{ + return gHobPointer; +} + +/** + Returns the next instance of a HOB type from the starting HOB. + + This function searches the first instance of a HOB type from the starting HOB pointer. + If there does not exist such HOB type from the starting HOB pointer, it will return NULL. + In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer + unconditionally: it returns HobStart back if HobStart itself meets the requirement; + caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart. + + If HobStart is NULL, then ASSERT(). + + @param Type The HOB type to return. + @param HobStart The starting HOB pointer to search from. + + @return The next instance of a HOB type from the starting HOB. + +**/ +VOID * +EFIAPI +GetNextHob ( + IN UINT16 Type, + IN CONST VOID *HobStart + ) +{ + EFI_PEI_HOB_POINTERS Hob; + + Hob.Raw = (UINT8 *) HobStart; + // + // Parse the HOB list until end of list or matching type is found. + // + while (!END_OF_HOB_LIST (Hob)) { + if (Hob.Header->HobType == Type) { + return Hob.Raw; + } + Hob.Raw = GET_NEXT_HOB (Hob); + } + return NULL; +} + +/** + Returns the first instance of a HOB type among the whole HOB list. + + This function searches the first instance of a HOB type among the whole HOB list. + If there does not exist such HOB type in the HOB list, it will return NULL. + + If the pointer to the HOB list is NULL, then ASSERT(). + + @param Type The HOB type to return. + + @return The next instance of a HOB type from the starting HOB. + +**/ +VOID * +EFIAPI +GetFirstHob ( + IN UINT16 Type + ) +{ + VOID *HobList; + + HobList = GetHobList (); + return GetNextHob (Type, HobList); +} + +/** + Returns the next instance of the matched GUID HOB from the starting HOB. + + This function searches the first instance of a HOB from the starting HOB pointer. + Such HOB should satisfy two conditions: + its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid. + If there does not exist such HOB from the starting HOB pointer, it will return NULL. + Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE () + to extract the data section and its size information, respectively. + In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer + unconditionally: it returns HobStart back if HobStart itself meets the requirement; + caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart. + + If Guid is NULL, then ASSERT(). + If HobStart is NULL, then ASSERT(). + + @param Guid The GUID to match with in the HOB list. + @param HobStart A pointer to a Guid. + + @return The next instance of the matched GUID HOB from the starting HOB. + +**/ +VOID * +EFIAPI +GetNextGuidHob ( + IN CONST EFI_GUID *Guid, + IN CONST VOID *HobStart + ) +{ + EFI_PEI_HOB_POINTERS GuidHob; + + GuidHob.Raw = (UINT8 *) HobStart; + while ((GuidHob.Raw = GetNextHob (EFI_HOB_TYPE_GUID_EXTENSION, GuidHob.Raw)) != NULL) { + if (CompareGuid (Guid, &GuidHob.Guid->Name)) { + break; + } + GuidHob.Raw = GET_NEXT_HOB (GuidHob); + } + return GuidHob.Raw; +} + +/** + Returns the first instance of the matched GUID HOB among the whole HOB list. + + This function searches the first instance of a HOB among the whole HOB list. + Such HOB should satisfy two conditions: + its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid. + If there does not exist such HOB from the starting HOB pointer, it will return NULL. + Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE () + to extract the data section and its size information, respectively. + + If the pointer to the HOB list is NULL, then ASSERT(). + If Guid is NULL, then ASSERT(). + + @param Guid The GUID to match with in the HOB list. + + @return The first instance of the matched GUID HOB among the whole HOB list. + +**/ +VOID * +EFIAPI +GetFirstGuidHob ( + IN CONST EFI_GUID *Guid + ) +{ + VOID *HobList; + + HobList = GetHobList (); + return GetNextGuidHob (Guid, HobList); +} + +/** + Get the system boot mode from the HOB list. + + This function returns the system boot mode information from the + PHIT HOB in HOB list. + + If the pointer to the HOB list is NULL, then ASSERT(). + + @param VOID. + + @return The Boot Mode. + +**/ +EFI_BOOT_MODE +EFIAPI +GetBootModeHob ( + VOID + ) +{ + EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; + + if (gHobPointer == NULL) { + InitHobPointer (); + } + + HandOffHob = gHobPointer; + + return HandOffHob->BootMode; +} + +/** + Adds a new HOB to the HOB List. + + This internal function enables PEIMs to create various types of HOBs. + + @param Type Type of the new HOB. + @param Length Length of the new HOB to allocate. + + @retval NULL The HOB could not be allocated. + @retval others The address of new HOB. + +**/ +VOID * +EFIAPI +InternalPeiCreateHob ( + IN UINT16 Type, + IN UINT16 Length + ) +{ + VOID *Hob; + EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; + EFI_HOB_GENERIC_HEADER *HobEnd; + + if (gHobPointer == NULL) { + InitHobPointer (); + } + + HandOffHob = gHobPointer; + + if ((UINTN)HandOffHob->EfiEndOfHobList + sizeof(EFI_HOB_GENERIC_HEADER) + Length > (UINTN)gHobPointer + SIZE_64KB) { + assert (FALSE); + return NULL; + } + + Hob = (VOID*) (UINTN) HandOffHob->EfiEndOfHobList; + ((EFI_HOB_GENERIC_HEADER*) Hob)->HobType = Type; + ((EFI_HOB_GENERIC_HEADER*) Hob)->HobLength = Length; + ((EFI_HOB_GENERIC_HEADER*) Hob)->Reserved = 0; + + HobEnd = (EFI_HOB_GENERIC_HEADER*) ((UINTN) Hob + Length); + HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd; + + HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST; + HobEnd->HobLength = (UINT16) sizeof (EFI_HOB_GENERIC_HEADER); + HobEnd->Reserved = 0; + + return Hob; +} + + +/** + Builds a HOB for a loaded PE32 module. + + This function builds a HOB for a loaded PE32 module. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If ModuleName is NULL, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + + @param ModuleName The GUID File Name of the module. + @param MemoryAllocationModule The 64 bit physical address of the module. + @param ModuleLength The length of the module in bytes. + @param EntryPoint The 64 bit physical address of the module entry point. + +**/ +VOID +EFIAPI +BuildModuleHob ( + IN CONST EFI_GUID *ModuleName, + IN EFI_PHYSICAL_ADDRESS MemoryAllocationModule, + IN UINT64 ModuleLength, + IN EFI_PHYSICAL_ADDRESS EntryPoint + ) +{ + EFI_HOB_MEMORY_ALLOCATION_MODULE *Hob; + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, (UINT16) sizeof (EFI_HOB_MEMORY_ALLOCATION_MODULE)); + if (Hob == NULL) { + return; + } + + CopyGuid (&(Hob->MemoryAllocationHeader.Name), &gEfiHobMemoryAllocModuleGuid); + Hob->MemoryAllocationHeader.MemoryBaseAddress = MemoryAllocationModule; + Hob->MemoryAllocationHeader.MemoryLength = ModuleLength; + Hob->MemoryAllocationHeader.MemoryType = EfiBootServicesCode; + + // + // Zero the reserved space to match HOB spec + // + ZeroMem (Hob->MemoryAllocationHeader.Reserved, sizeof (Hob->MemoryAllocationHeader.Reserved)); + + CopyGuid (&Hob->ModuleName, ModuleName); + Hob->EntryPoint = EntryPoint; +} + +/** + Builds a HOB that describes a chunk of system memory with Owner GUID. + + This function builds a HOB that describes a chunk of system memory. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param ResourceType The type of resource described by this HOB. + @param ResourceAttribute The resource attributes of the memory described by this HOB. + @param PhysicalStart The 64 bit physical address of memory described by this HOB. + @param NumberOfBytes The length of the memory described by this HOB in bytes. + @param OwnerGUID GUID for the owner of this resource. + +**/ +VOID +EFIAPI +BuildResourceDescriptorWithOwnerHob ( + IN EFI_RESOURCE_TYPE ResourceType, + IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute, + IN EFI_PHYSICAL_ADDRESS PhysicalStart, + IN UINT64 NumberOfBytes, + IN EFI_GUID *OwnerGUID + ) +{ + EFI_HOB_RESOURCE_DESCRIPTOR *Hob; + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, (UINT16) sizeof (EFI_HOB_RESOURCE_DESCRIPTOR)); + if (Hob == NULL) { + return; + } + + Hob->ResourceType = ResourceType; + Hob->ResourceAttribute = ResourceAttribute; + Hob->PhysicalStart = PhysicalStart; + Hob->ResourceLength = NumberOfBytes; + + CopyGuid (&Hob->Owner, OwnerGUID); +} + +/** + Builds a HOB that describes a chunk of system memory. + + This function builds a HOB that describes a chunk of system memory. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param ResourceType The type of resource described by this HOB. + @param ResourceAttribute The resource attributes of the memory described by this HOB. + @param PhysicalStart The 64 bit physical address of memory described by this HOB. + @param NumberOfBytes The length of the memory described by this HOB in bytes. + +**/ +VOID +EFIAPI +BuildResourceDescriptorHob ( + IN EFI_RESOURCE_TYPE ResourceType, + IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute, + IN EFI_PHYSICAL_ADDRESS PhysicalStart, + IN UINT64 NumberOfBytes + ) +{ + EFI_HOB_RESOURCE_DESCRIPTOR *Hob; + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, (UINT16) sizeof (EFI_HOB_RESOURCE_DESCRIPTOR)); + if (Hob == NULL) { + return; + } + + Hob->ResourceType = ResourceType; + Hob->ResourceAttribute = ResourceAttribute; + Hob->PhysicalStart = PhysicalStart; + Hob->ResourceLength = NumberOfBytes; + ZeroMem (&(Hob->Owner), sizeof (EFI_GUID)); +} + +/** + Builds a customized HOB tagged with a GUID for identification and returns + the start address of GUID HOB data. + + This function builds a customized HOB tagged with a GUID for identification + and returns the start address of GUID HOB data so that caller can fill the customized data. + The HOB Header and Name field is already stripped. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If Guid is NULL, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + If DataLength > (0xFFF8 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT(). + HobLength is UINT16 and multiples of 8 bytes, so the max HobLength is 0xFFF8. + + @param Guid The GUID to tag the customized HOB. + @param DataLength The size of the data payload for the GUID HOB. + + @retval NULL The GUID HOB could not be allocated. + @retval others The start address of GUID HOB data. + +**/ +VOID * +EFIAPI +BuildGuidHob ( + IN CONST EFI_GUID *Guid, + IN UINTN DataLength + ) +{ + EFI_HOB_GUID_TYPE *Hob; + + // + // Make sure that data length is not too long. + // + assert (DataLength <= (0xFFF8 - sizeof (EFI_HOB_GUID_TYPE))); + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_GUID_EXTENSION, (UINT16) (sizeof (EFI_HOB_GUID_TYPE) + DataLength)); + if (Hob == NULL) { + return Hob; + } + CopyGuid (&Hob->Name, Guid); + return Hob + 1; +} + +/** + Builds a customized HOB tagged with a GUID for identification, copies the input data to the HOB + data field, and returns the start address of the GUID HOB data. + + This function builds a customized HOB tagged with a GUID for identification and copies the input + data to the HOB data field and returns the start address of the GUID HOB data. It can only be + invoked during PEI phase; for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + The HOB Header and Name field is already stripped. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If Guid is NULL, then ASSERT(). + If Data is NULL and DataLength > 0, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + If DataLength > (0xFFF8 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT(). + HobLength is UINT16 and multiples of 8 bytes, so the max HobLength is 0xFFF8. + + @param Guid The GUID to tag the customized HOB. + @param Data The data to be copied into the data field of the GUID HOB. + @param DataLength The size of the data payload for the GUID HOB. + + @retval NULL The GUID HOB could not be allocated. + @retval others The start address of GUID HOB data. + +**/ +VOID * +EFIAPI +BuildGuidDataHob ( + IN CONST EFI_GUID *Guid, + IN VOID *Data, + IN UINTN DataLength + ) +{ + VOID *HobData; + + HobData = BuildGuidHob (Guid, DataLength); + if (HobData == NULL) { + return HobData; + } + + return CopyMem (HobData, Data, DataLength); +} + + +/** + Builds a Firmware Volume HOB. + + This function builds a Firmware Volume HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + If the FvImage buffer is not at its required alignment, then ASSERT(). + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + +**/ +VOID +EFIAPI +BuildFvHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + EFI_HOB_FIRMWARE_VOLUME *Hob; + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_FV, (UINT16) sizeof (EFI_HOB_FIRMWARE_VOLUME)); + if (Hob == NULL) { + return; + } + + Hob->BaseAddress = BaseAddress; + Hob->Length = Length; +} + +/** + Builds a EFI_HOB_TYPE_FV2 HOB. + + This function builds a EFI_HOB_TYPE_FV2 HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + If the FvImage buffer is not at its required alignment, then ASSERT(). + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + @param FvName The name of the Firmware Volume. + @param FileName The name of the file. + +**/ +VOID +EFIAPI +BuildFv2Hob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN CONST EFI_GUID *FvName, + IN CONST EFI_GUID *FileName + ) +{ + EFI_HOB_FIRMWARE_VOLUME2 *Hob; + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_FV2, (UINT16) sizeof (EFI_HOB_FIRMWARE_VOLUME2)); + if (Hob == NULL) { + return; + } + + Hob->BaseAddress = BaseAddress; + Hob->Length = Length; + CopyGuid (&Hob->FvName, FvName); + CopyGuid (&Hob->FileName, FileName); +} + +/** + Builds a EFI_HOB_TYPE_FV3 HOB. + + This function builds a EFI_HOB_TYPE_FV3 HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + If the FvImage buffer is not at its required alignment, then ASSERT(). + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + @param AuthenticationStatus The authentication status. + @param ExtractedFv TRUE if the FV was extracted as a file within + another firmware volume. FALSE otherwise. + @param FvName The name of the Firmware Volume. + Valid only if IsExtractedFv is TRUE. + @param FileName The name of the file. + Valid only if IsExtractedFv is TRUE. + +**/ +VOID +EFIAPI +BuildFv3Hob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT32 AuthenticationStatus, + IN BOOLEAN ExtractedFv, + IN CONST EFI_GUID *FvName, OPTIONAL + IN CONST EFI_GUID *FileName OPTIONAL + ) +{ + EFI_HOB_FIRMWARE_VOLUME3 *Hob; + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_FV3, (UINT16) sizeof (EFI_HOB_FIRMWARE_VOLUME3)); + if (Hob == NULL) { + return; + } + + Hob->BaseAddress = BaseAddress; + Hob->Length = Length; + Hob->AuthenticationStatus = AuthenticationStatus; + Hob->ExtractedFv = ExtractedFv; + if (ExtractedFv) { + CopyGuid (&Hob->FvName, FvName); + CopyGuid (&Hob->FileName, FileName); + } +} + +/** + Builds a Capsule Volume HOB. + + This function builds a Capsule Volume HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If the platform does not support Capsule Volume HOBs, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The base address of the Capsule Volume. + @param Length The size of the Capsule Volume in bytes. + +**/ +VOID +EFIAPI +BuildCvHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + EFI_HOB_UEFI_CAPSULE *Hob; + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_UEFI_CAPSULE, (UINT16) sizeof (EFI_HOB_UEFI_CAPSULE)); + if (Hob == NULL) { + return; + } + + Hob->BaseAddress = BaseAddress; + Hob->Length = Length; +} + +/** + Builds a HOB for the CPU. + + This function builds a HOB for the CPU. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param SizeOfMemorySpace The maximum physical memory addressability of the processor. + @param SizeOfIoSpace The maximum physical I/O addressability of the processor. + +**/ +VOID +EFIAPI +BuildCpuHob ( + IN UINT8 SizeOfMemorySpace, + IN UINT8 SizeOfIoSpace + ) +{ + EFI_HOB_CPU *Hob; + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_CPU, (UINT16) sizeof (EFI_HOB_CPU)); + if (Hob == NULL) { + return; + } + + Hob->SizeOfMemorySpace = SizeOfMemorySpace; + Hob->SizeOfIoSpace = SizeOfIoSpace; + + // + // Zero the reserved space to match HOB spec + // + ZeroMem (Hob->Reserved, sizeof (Hob->Reserved)); +} + +/** + Builds a HOB for the Stack. + + This function builds a HOB for the stack. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The 64 bit physical address of the Stack. + @param Length The length of the stack in bytes. + +**/ +VOID +EFIAPI +BuildStackHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + EFI_HOB_MEMORY_ALLOCATION_STACK *Hob; + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, (UINT16) sizeof (EFI_HOB_MEMORY_ALLOCATION_STACK)); + if (Hob == NULL) { + return; + } + + CopyGuid (&(Hob->AllocDescriptor.Name), &gEfiHobMemoryAllocStackGuid); + Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress; + Hob->AllocDescriptor.MemoryLength = Length; + Hob->AllocDescriptor.MemoryType = EfiBootServicesData; + + // + // Zero the reserved space to match HOB spec + // + ZeroMem (Hob->AllocDescriptor.Reserved, sizeof (Hob->AllocDescriptor.Reserved)); +} + +/** + Builds a HOB for the BSP store. + + This function builds a HOB for BSP store. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The 64 bit physical address of the BSP. + @param Length The length of the BSP store in bytes. + @param MemoryType The type of memory allocated by this HOB. + +**/ +VOID +EFIAPI +BuildBspStoreHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ) +{ + EFI_HOB_MEMORY_ALLOCATION_BSP_STORE *Hob; + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, (UINT16) sizeof (EFI_HOB_MEMORY_ALLOCATION_BSP_STORE)); + if (Hob == NULL) { + return; + } + + CopyGuid (&(Hob->AllocDescriptor.Name), &gEfiHobMemoryAllocBspStoreGuid); + Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress; + Hob->AllocDescriptor.MemoryLength = Length; + Hob->AllocDescriptor.MemoryType = MemoryType; + + // + // Zero the reserved space to match HOB spec + // + ZeroMem (Hob->AllocDescriptor.Reserved, sizeof (Hob->AllocDescriptor.Reserved)); +} + +/** + Builds a HOB for the memory allocation. + + This function builds a HOB for the memory allocation. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The 64 bit physical address of the memory. + @param Length The length of the memory allocation in bytes. + @param MemoryType The type of memory allocated by this HOB. + +**/ +VOID +EFIAPI +BuildMemoryAllocationHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ) +{ + EFI_HOB_MEMORY_ALLOCATION *Hob; + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, (UINT16) sizeof (EFI_HOB_MEMORY_ALLOCATION)); + if (Hob == NULL) { + return; + } + + ZeroMem (&(Hob->AllocDescriptor.Name), sizeof (EFI_GUID)); + Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress; + Hob->AllocDescriptor.MemoryLength = Length; + Hob->AllocDescriptor.MemoryType = MemoryType; + // + // Zero the reserved space to match HOB spec + // + ZeroMem (Hob->AllocDescriptor.Reserved, sizeof (Hob->AllocDescriptor.Reserved)); +} diff --git a/HBFA/UefiHostTestPkg/Library/HobLibHost/HobLibHost.inf b/HBFA/UefiHostTestPkg/Library/HobLibHost/HobLibHost.inf new file mode 100644 index 0000000..2a3648e --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/HobLibHost/HobLibHost.inf @@ -0,0 +1,31 @@ +## @file +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = HobLibHost + FILE_GUID = 05DA0183-444E-497D-8B4F-76E910F1E12C + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = HobLib + +[Sources] + HobLibHost.c + +[Packages] + MdePkg/MdePkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + +[Guids] + gEfiHobMemoryAllocStackGuid + gEfiHobMemoryAllocBspStoreGuid + gEfiHobMemoryAllocModuleGuid diff --git a/HBFA/UefiHostTestPkg/Library/MemoryAllocationLibHost/MemoryAllocationLibHost.c b/HBFA/UefiHostTestPkg/Library/MemoryAllocationLibHost/MemoryAllocationLibHost.c new file mode 100644 index 0000000..8a92a88 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/MemoryAllocationLibHost/MemoryAllocationLibHost.c @@ -0,0 +1,302 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +#include + +#define PAGE_HEAD_PRIVATE_SIGNATURE SIGNATURE_32 ('P', 'H', 'D', 'R') + +typedef struct { + UINT32 Signature; + VOID *AllocatedBufffer; + UINTN TotalPages; + VOID *AlignedBuffer; + UINTN AlignedPages; +} PAGE_HEAD; + +VOID * +EFIAPI +AllocateAlignedPages ( + IN UINTN Pages, + IN UINTN Alignment + ); + +VOID +EFIAPI +FreeAlignedPages ( + IN VOID *Buffer, + IN UINTN Pages + ); + +VOID * +EFIAPI +AllocatePages ( + IN UINTN Pages + ) +{ + return AllocateAlignedPages (Pages, SIZE_4KB); +} + +VOID * +EFIAPI +AllocateRuntimePages ( + IN UINTN Pages + ) +{ + return AllocatePages (Pages); +} + +VOID * +EFIAPI +AllocateReservedPages ( + IN UINTN Pages + ) +{ + return AllocatePages (Pages); +} + +VOID +EFIAPI +FreePages ( + IN VOID *Buffer, + IN UINTN Pages + ) +{ + FreeAlignedPages (Buffer, Pages); +} + +VOID * +EFIAPI +AllocateAlignedPages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + PAGE_HEAD PageHead; + PAGE_HEAD *PageHeadPtr; + UINTN AlignmentMask; + + assert ((Alignment & (Alignment - 1)) == 0); + + if (Alignment < SIZE_4KB) { + Alignment = SIZE_4KB; + } + AlignmentMask = Alignment - 1; + + // + // We need reserve Alignment pages for PAGE_HEAD, as meta data. + // + + PageHead.Signature = PAGE_HEAD_PRIVATE_SIGNATURE; + PageHead.TotalPages = Pages + EFI_SIZE_TO_PAGES(Alignment) * 2; + PageHead.AlignedPages = Pages; + PageHead.AllocatedBufffer = malloc (EFI_PAGES_TO_SIZE(PageHead.TotalPages)); + if (PageHead.AllocatedBufffer == NULL) { + return NULL; + } + PageHead.AlignedBuffer = (VOID *)(((UINTN) PageHead.AllocatedBufffer + AlignmentMask) & ~AlignmentMask); + if ((UINTN)PageHead.AlignedBuffer - (UINTN)PageHead.AllocatedBufffer < sizeof(PAGE_HEAD)) { + PageHead.AlignedBuffer = (VOID *)((UINTN)PageHead.AlignedBuffer + Alignment); + } + + PageHeadPtr = (VOID *)((UINTN)PageHead.AlignedBuffer - sizeof(PAGE_HEAD)); + memcpy (PageHeadPtr, &PageHead, sizeof(PAGE_HEAD)); + + return PageHead.AlignedBuffer; +} + +VOID * +EFIAPI +AllocateAlignedRuntimePages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + return AllocateAlignedPages (Pages, Alignment); +} + +VOID * +EFIAPI +AllocateAlignedReservedPages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + return AllocateAlignedPages (Pages, Alignment); +} + +VOID +EFIAPI +FreeAlignedPages ( + IN VOID *Buffer, + IN UINTN Pages + ) +{ + PAGE_HEAD *PageHeadPtr; + + // + // NOTE: Partial free is not supported. Just keep it. + // + + PageHeadPtr = (VOID *)((UINTN)Buffer - sizeof(PAGE_HEAD)); + if (PageHeadPtr->Signature != PAGE_HEAD_PRIVATE_SIGNATURE) { + return ; + } + if (PageHeadPtr->AlignedPages != Pages) { + return ; + } + + PageHeadPtr->Signature = 0; + free (PageHeadPtr->AllocatedBufffer); +} + +VOID * +EFIAPI +AllocatePool ( + IN UINTN AllocationSize + ) +{ + return malloc (AllocationSize); +} + +VOID * +EFIAPI +AllocateRuntimePool ( + IN UINTN AllocationSize + ) +{ + return AllocatePool (AllocationSize); +} + +VOID * +EFIAPI +AllocateReservedPool ( + IN UINTN AllocationSize + ) +{ + return AllocatePool (AllocationSize); +} + +VOID * +EFIAPI +AllocateZeroPool ( + IN UINTN AllocationSize + ) +{ + VOID *Buffer; + Buffer = malloc (AllocationSize); + if (Buffer == NULL) { + return NULL; + } + memset (Buffer, 0, AllocationSize); + return Buffer; +} + +VOID * +EFIAPI +AllocateRuntimeZeroPool ( + IN UINTN AllocationSize + ) +{ + return AllocateZeroPool (AllocationSize); +} + +VOID * +EFIAPI +AllocateReservedZeroPool ( + IN UINTN AllocationSize + ) +{ + return AllocateZeroPool (AllocationSize); +} + +VOID * +EFIAPI +AllocateCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + VOID *Memory; + Memory = malloc (AllocationSize); + if (Memory == NULL) { + return NULL; + } + memcpy (Memory, Buffer, AllocationSize); + return Memory; +} + +VOID * +EFIAPI +AllocateRuntimeCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + return AllocateCopyPool (AllocationSize, Buffer); +} + +VOID * +EFIAPI +AllocateReservedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + return AllocateCopyPool (AllocationSize, Buffer); +} + +VOID * +EFIAPI +ReallocatePool ( + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) +{ + VOID *NewBuffer; + NewBuffer = malloc (NewSize); + if (NewBuffer != NULL && OldBuffer != NULL) { + memcpy (NewBuffer, OldBuffer, MIN (OldSize, NewSize)); + } + return NewBuffer; +} + +VOID * +EFIAPI +ReallocateRuntimePool ( + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) +{ + return ReallocatePool (OldSize, NewSize, OldBuffer); +} + +VOID * +EFIAPI +ReallocateReservedPool ( + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) +{ + return ReallocatePool (OldSize, NewSize, OldBuffer); +} + +VOID +EFIAPI +FreePool ( + IN VOID *Buffer + ) +{ + free (Buffer); +} diff --git a/HBFA/UefiHostTestPkg/Library/MemoryAllocationLibHost/MemoryAllocationLibHost.inf b/HBFA/UefiHostTestPkg/Library/MemoryAllocationLibHost/MemoryAllocationLibHost.inf new file mode 100644 index 0000000..a01e709 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/MemoryAllocationLibHost/MemoryAllocationLibHost.inf @@ -0,0 +1,25 @@ +## @file +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = MemoryAllocationLibHost + FILE_GUID = A1672454-A3D3-4AAC-A86B-8D63132BBB91 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = MemoryAllocationLib + +[Sources] + MemoryAllocationLibHost.c + +[Packages] + MdePkg/MdePkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + +[LibraryClasses] + BaseLib + diff --git a/HBFA/UefiHostTestPkg/Library/OsServiceLibHost/OsServiceLibGcc.c b/HBFA/UefiHostTestPkg/Library/OsServiceLibHost/OsServiceLibGcc.c new file mode 100644 index 0000000..e4d4d80 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/OsServiceLibHost/OsServiceLibGcc.c @@ -0,0 +1,45 @@ +/**@file + +Copyright (c) 2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +VOID * +AllocateExecutableMemory ( + IN UINTN Size + ) +{ + VOID *Buffer; + size_t FinalSize; + size_t PageSize; + + PageSize = getpagesize(); + + FinalSize = (Size + PageSize - 1) / PageSize * PageSize; + + Buffer = mmap(NULL, FinalSize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); + if (Buffer == NULL) { + return NULL; + } + + return Buffer; +} + +VOID +FreeExecutableMemory ( + IN VOID *Buffer, + IN UINTN Size + ) +{ + size_t FinalSize; + size_t PageSize; + + PageSize = getpagesize(); + + FinalSize = (Size + PageSize - 1) / PageSize * PageSize; + + munmap (Buffer, FinalSize); +} diff --git a/HBFA/UefiHostTestPkg/Library/OsServiceLibHost/OsServiceLibHost.inf b/HBFA/UefiHostTestPkg/Library/OsServiceLibHost/OsServiceLibHost.inf new file mode 100644 index 0000000..d7c44a9 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/OsServiceLibHost/OsServiceLibHost.inf @@ -0,0 +1,26 @@ +## @file +# +# Copyright (c) 2017, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = OsServiceLibHost + FILE_GUID = 56DCD496-CD73-42D0-B145-B7C100CE5877 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = OsServiceLib + +[Sources] + OsServiceLibMsvc.c | MSFT + OsServiceLibGcc.c | GCC + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + +[BuildOptions] + diff --git a/HBFA/UefiHostTestPkg/Library/OsServiceLibHost/OsServiceLibMsvc.c b/HBFA/UefiHostTestPkg/Library/OsServiceLibHost/OsServiceLibMsvc.c new file mode 100644 index 0000000..80cd3fe --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/OsServiceLibHost/OsServiceLibMsvc.c @@ -0,0 +1,41 @@ +/**@file + +Copyright (c) 2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +VOID * +AllocateExecutableMemory ( + IN UINTN Size + ) +{ + VOID *Buffer; + SIZE_T FinalSize; + UINT32 PageSize; + SYSTEM_INFO SystemInfo; + + GetSystemInfo(&SystemInfo); + PageSize = SystemInfo.dwPageSize; + + FinalSize = (Size + PageSize - 1) / PageSize * PageSize; + + Buffer = VirtualAlloc(NULL, FinalSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + if (Buffer == NULL) { + return NULL; + } + + return Buffer; +} + +VOID +FreeExecutableMemory ( + IN VOID *Buffer, + IN UINTN Size + ) +{ + VirtualFree(Buffer, 0, MEM_RELEASE); +} diff --git a/HBFA/UefiHostTestPkg/Library/OsServiceLibHost/WinNTInclude.h b/HBFA/UefiHostTestPkg/Library/OsServiceLibHost/WinNTInclude.h new file mode 100644 index 0000000..345d15d --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/OsServiceLibHost/WinNTInclude.h @@ -0,0 +1,74 @@ +/**@file + +Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +Module Name: + WinNtLib.h + +Abstract: + Public include file for the WinNt Library + +**/ + +#ifndef __WIN_NT_INCLUDE_H__ +#define __WIN_NT_INCLUDE_H__ + +// +// Win32 include files do not compile clean with /W4, so we use the warning +// pragma to suppress the warnings for Win32 only. This way our code can stil +// compile at /W4 (highest warning level) with /WX (warnings cause build +// errors). +// +#pragma warning(disable : 4115) +#pragma warning(disable : 4201) +#pragma warning(disable : 4028) +#pragma warning(disable : 4133) + +#define GUID _WINNT_DUP_GUID_____ +#define _LIST_ENTRY _WINNT_DUP_LIST_ENTRY_FORWARD +#define LIST_ENTRY _WINNT_DUP_LIST_ENTRY +#if defined (MDE_CPU_IA32) && (_MSC_VER < 1800) +#define InterlockedIncrement _WINNT_DUP_InterlockedIncrement +#define InterlockedDecrement _WINNT_DUP_InterlockedDecrement +#define InterlockedCompareExchange64 _WINNT_DUP_InterlockedCompareExchange64 +#endif +#undef UNALIGNED +#undef CONST +#undef VOID +#undef DEBUG_EVENT + +// WQBugBug: This typedef is to make "windows.h" buildable. +// It should be removed after the root cause why +// size_t is undefined when go into the line below is found. +#if defined (MDE_CPU_IA32) +typedef UINT32 size_t ; +#endif + +#include "windows.h" + +#undef GUID +#undef _LIST_ENTRY +#undef LIST_ENTRY +#undef InterlockedIncrement +#undef InterlockedDecrement +#undef InterlockedCompareExchange64 +#undef InterlockedCompareExchangePointer +#undef CreateEventEx + +#define VOID void + +// +// Prevent collisions with Windows API name macros that deal with Unicode/Not issues +// +#undef LoadImage +#undef CreateEvent + +// +// Set the warnings back on as the EFI code must be /W4. +// +#pragma warning(default : 4115) +#pragma warning(default : 4201) + + +#endif diff --git a/HBFA/UefiHostTestPkg/Library/PeiServicesTablePointerLibHost/CpuIo.c b/HBFA/UefiHostTestPkg/Library/PeiServicesTablePointerLibHost/CpuIo.c new file mode 100644 index 0000000..0420c22 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/PeiServicesTablePointerLibHost/CpuIo.c @@ -0,0 +1,535 @@ +/** @file + The default version of EFI_PEI_CPU_IO_PPI support published by PeiServices in + PeiCore initialization phase. + + EFI_PEI_CPU_IO_PPI is installed by some platform or chipset-specific PEIM that + abstracts the processor-visible I/O operations. When PeiCore is started, the + default version of EFI_PEI_CPU_IO_PPI will be assigned to PeiServices table. + +Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +/** + Memory-based read services. + + This function is to perform the Memory Access Read service based on installed + instance of the EFI_PEI_CPU_IO_PPI. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return EFI_NOT_YET_AVAILABLE. + + @param PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Width The width of the access. Enumerated in bytes. + @param Address The physical address of the access. + @param Count The number of accesses to perform. + @param Buffer A pointer to the buffer of data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_YET_AVAILABLE The service has not been installed. +**/ +EFI_STATUS +EFIAPI +PeiDefaultMemRead ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN EFI_PEI_CPU_IO_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +/** + Memory-based write services. + + This function is to perform the Memory Access Write service based on installed + instance of the EFI_PEI_CPU_IO_PPI. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return EFI_NOT_YET_AVAILABLE. + + @param PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Width The width of the access. Enumerated in bytes. + @param Address The physical address of the access. + @param Count The number of accesses to perform. + @param Buffer A pointer to the buffer of data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_YET_AVAILABLE The service has not been installed. +**/ +EFI_STATUS +EFIAPI +PeiDefaultMemWrite ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN EFI_PEI_CPU_IO_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +/** + IO-based read services. + + This function is to perform the IO-base read service for the EFI_PEI_CPU_IO_PPI. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return EFI_NOT_YET_AVAILABLE. + + @param PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Width The width of the access. Enumerated in bytes. + @param Address The physical address of the access. + @param Count The number of accesses to perform. + @param Buffer A pointer to the buffer of data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_YET_AVAILABLE The service has not been installed. +**/ +EFI_STATUS +EFIAPI +PeiDefaultIoRead ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN EFI_PEI_CPU_IO_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +/** + IO-based write services. + + This function is to perform the IO-base write service for the EFI_PEI_CPU_IO_PPI. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return EFI_NOT_YET_AVAILABLE. + + @param PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Width The width of the access. Enumerated in bytes. + @param Address The physical address of the access. + @param Count The number of accesses to perform. + @param Buffer A pointer to the buffer of data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_YET_AVAILABLE The service has not been installed. +**/ +EFI_STATUS +EFIAPI +PeiDefaultIoWrite ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN EFI_PEI_CPU_IO_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +/** + 8-bit I/O read operations. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return An 8-bit value returned from the I/O space. +**/ +UINT8 +EFIAPI +PeiDefaultIoRead8 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ) +{ + return 0; +} + +/** + Reads an 16-bit I/O port. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return A 16-bit value returned from the I/O space. +**/ +UINT16 +EFIAPI +PeiDefaultIoRead16 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ) +{ + return 0; +} + +/** + Reads an 32-bit I/O port. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return A 32-bit value returned from the I/O space. +**/ +UINT32 +EFIAPI +PeiDefaultIoRead32 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ) +{ + return 0; +} + +/** + Reads an 64-bit I/O port. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return A 64-bit value returned from the I/O space. +**/ +UINT64 +EFIAPI +PeiDefaultIoRead64 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ) +{ + return 0; +} + +/** + 8-bit I/O write operations. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then do + nothing. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. +**/ +VOID +EFIAPI +PeiDefaultIoWrite8 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT8 Data + ) +{ +} + +/** + 16-bit I/O write operations. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then do + nothing. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. +**/ +VOID +EFIAPI +PeiDefaultIoWrite16 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT16 Data + ) +{ +} + +/** + 32-bit I/O write operations. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then do + nothing. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. +**/ +VOID +EFIAPI +PeiDefaultIoWrite32 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT32 Data + ) +{ +} + +/** + 64-bit I/O write operations. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then do + nothing. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. +**/ +VOID +EFIAPI +PeiDefaultIoWrite64 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT64 Data + ) +{ +} + +/** + 8-bit memory read operations. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return An 8-bit value returned from the memory space. + +**/ +UINT8 +EFIAPI +PeiDefaultMemRead8 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ) +{ + return 0; +} + +/** + 16-bit memory read operations. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return An 16-bit value returned from the memory space. + +**/ +UINT16 +EFIAPI +PeiDefaultMemRead16 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ) +{ + return 0; +} + +/** + 32-bit memory read operations. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return An 32-bit value returned from the memory space. + +**/ +UINT32 +EFIAPI +PeiDefaultMemRead32 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ) +{ + return 0; +} + +/** + 64-bit memory read operations. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return An 64-bit value returned from the memory space. + +**/ +UINT64 +EFIAPI +PeiDefaultMemRead64 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ) +{ + return 0; +} + +/** + 8-bit memory write operations. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then do + nothing. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. + +**/ +VOID +EFIAPI +PeiDefaultMemWrite8 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT8 Data + ) +{ +} + +/** + 16-bit memory write operations. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then do + nothing. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. + +**/ +VOID +EFIAPI +PeiDefaultMemWrite16 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT16 Data + ) +{ +} + +/** + 32-bit memory write operations. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then do + nothing. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. + +**/ +VOID +EFIAPI +PeiDefaultMemWrite32 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT32 Data + ) +{ +} + +/** + 64-bit memory write operations. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then do + nothing. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. + +**/ +VOID +EFIAPI +PeiDefaultMemWrite64 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT64 Data + ) +{ +} + +/// +/// This default instance of EFI_PEI_CPU_IO_PPI install assigned to EFI_PEI_SERVICE.CpuIo +/// when PeiCore's initialization. +/// +EFI_PEI_CPU_IO_PPI mPeiDefaultCpuIoPpi = { + { + PeiDefaultMemRead, + PeiDefaultMemWrite + }, + { + PeiDefaultIoRead, + PeiDefaultIoWrite + }, + PeiDefaultIoRead8, + PeiDefaultIoRead16, + PeiDefaultIoRead32, + PeiDefaultIoRead64, + PeiDefaultIoWrite8, + PeiDefaultIoWrite16, + PeiDefaultIoWrite32, + PeiDefaultIoWrite64, + PeiDefaultMemRead8, + PeiDefaultMemRead16, + PeiDefaultMemRead32, + PeiDefaultMemRead64, + PeiDefaultMemWrite8, + PeiDefaultMemWrite16, + PeiDefaultMemWrite32, + PeiDefaultMemWrite64 +}; diff --git a/HBFA/UefiHostTestPkg/Library/PeiServicesTablePointerLibHost/PciCfg2.c b/HBFA/UefiHostTestPkg/Library/PeiServicesTablePointerLibHost/PciCfg2.c new file mode 100644 index 0000000..c6e93c6 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/PeiServicesTablePointerLibHost/PciCfg2.c @@ -0,0 +1,122 @@ +/** @file + The default version of EFI_PEI_PCI_CFG2_PPI support published by PeiServices in + PeiCore initialization phase. + + EFI_PEI_PCI_CFG2_PPI is installed by the PEIM which supports a PCI root bridge. + When PeiCore is started, the default version of EFI_PEI_PCI_CFG2_PPI will be assigned + to PeiServices table. + +Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +/** + Reads from a given location in the PCI configuration space. + + If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM, then + return EFI_NOT_YET_AVAILABLE. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Width The width of the access. Enumerated in bytes. + See EFI_PEI_PCI_CFG_PPI_WIDTH above. + @param Address The physical address of the access. The format of + the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS. + @param Buffer A pointer to the buffer of data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER The invalid access width. + @retval EFI_NOT_YET_AVAILABLE If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM. + +**/ +EFI_STATUS +EFIAPI +PeiDefaultPciCfg2Read ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PCI_CFG2_PPI *This, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, + IN OUT VOID *Buffer + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +/** + Write to a given location in the PCI configuration space. + + If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM, then + return EFI_NOT_YET_AVAILABLE. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Width The width of the access. Enumerated in bytes. + See EFI_PEI_PCI_CFG_PPI_WIDTH above. + @param Address The physical address of the access. The format of + the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS. + @param Buffer A pointer to the buffer of data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER The invalid access width. + @retval EFI_NOT_YET_AVAILABLE If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM. +**/ +EFI_STATUS +EFIAPI +PeiDefaultPciCfg2Write ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PCI_CFG2_PPI *This, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, + IN OUT VOID *Buffer + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +/** + This function performs a read-modify-write operation on the contents from a given + location in the PCI configuration space. + If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM, then + return EFI_NOT_YET_AVAILABLE. + + @param PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Width The width of the access. Enumerated in bytes. Type + EFI_PEI_PCI_CFG_PPI_WIDTH is defined in Read(). + @param Address The physical address of the access. + @param SetBits Points to value to bitwise-OR with the read configuration value. + The size of the value is determined by Width. + @param ClearBits Points to the value to negate and bitwise-AND with the read configuration value. + The size of the value is determined by Width. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER The invalid access width. + @retval EFI_NOT_YET_AVAILABLE If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM. +**/ +EFI_STATUS +EFIAPI +PeiDefaultPciCfg2Modify ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PCI_CFG2_PPI *This, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, + IN VOID *SetBits, + IN VOID *ClearBits + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +/// +/// This default instance of EFI_PEI_PCI_CFG2_PPI install assigned to EFI_PEI_SERVICE.PciCfg +/// when PeiCore's initialization. +/// +EFI_PEI_PCI_CFG2_PPI mPeiDefaultPciCfg2Ppi = { + PeiDefaultPciCfg2Read, + PeiDefaultPciCfg2Write, + PeiDefaultPciCfg2Modify +}; diff --git a/HBFA/UefiHostTestPkg/Library/PeiServicesTablePointerLibHost/PeiMain.h b/HBFA/UefiHostTestPkg/Library/PeiServicesTablePointerLibHost/PeiMain.h new file mode 100644 index 0000000..14034f7 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/PeiServicesTablePointerLibHost/PeiMain.h @@ -0,0 +1,1867 @@ +/** @file + Definition of Pei Core Structures and Services + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _PEI_MAIN_H_ +#define _PEI_MAIN_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/// +/// It is an FFS type extension used for PeiFindFileEx. It indicates current +/// Ffs searching is for all PEIMs can be dispatched by PeiCore. +/// +#define PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE 0xff + +/// +/// Pei Core private data structures +/// +typedef union { + EFI_PEI_PPI_DESCRIPTOR *Ppi; + EFI_PEI_NOTIFY_DESCRIPTOR *Notify; + VOID *Raw; +} PEI_PPI_LIST_POINTERS; + +/// +/// Number of PEI_PPI_LIST_POINTERS to grow by each time we run out of room +/// +#define PPI_GROWTH_STEP 64 +#define CALLBACK_NOTIFY_GROWTH_STEP 32 +#define DISPATCH_NOTIFY_GROWTH_STEP 8 + +typedef struct { + UINTN CurrentCount; + UINTN MaxCount; + UINTN LastDispatchedCount; + /// + /// MaxCount number of entries. + /// + PEI_PPI_LIST_POINTERS *PpiPtrs; +} PEI_PPI_LIST; + +typedef struct { + UINTN CurrentCount; + UINTN MaxCount; + /// + /// MaxCount number of entries. + /// + PEI_PPI_LIST_POINTERS *NotifyPtrs; +} PEI_CALLBACK_NOTIFY_LIST; + +typedef struct { + UINTN CurrentCount; + UINTN MaxCount; + UINTN LastDispatchedCount; + /// + /// MaxCount number of entries. + /// + PEI_PPI_LIST_POINTERS *NotifyPtrs; +} PEI_DISPATCH_NOTIFY_LIST; + +/// +/// PPI database structure which contains three links: +/// PpiList, CallbackNotifyList and DispatchNotifyList. +/// +typedef struct { + /// + /// PPI List. + /// + PEI_PPI_LIST PpiList; + /// + /// Notify List at dispatch level. + /// + PEI_CALLBACK_NOTIFY_LIST CallbackNotifyList; + /// + /// Notify List at callback level. + /// + PEI_DISPATCH_NOTIFY_LIST DispatchNotifyList; +} PEI_PPI_DATABASE; + +// +// PEI_CORE_FV_HANDE.PeimState +// Do not change these values as there is code doing math to change states. +// Look for Private->Fv[FvCount].PeimState[PeimCount]++; +// +#define PEIM_STATE_NOT_DISPATCHED 0x00 +#define PEIM_STATE_DISPATCHED 0x01 +#define PEIM_STATE_REGISTER_FOR_SHADOW 0x02 +#define PEIM_STATE_DONE 0x03 + +// +// Number of FV instances to grow by each time we run out of room +// +#define FV_GROWTH_STEP 8 + +typedef struct { + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi; + EFI_PEI_FV_HANDLE FvHandle; + UINTN PeimCount; + // + // Ponter to the buffer with the PeimCount number of Entries. + // + UINT8 *PeimState; + // + // Ponter to the buffer with the PeimCount number of Entries. + // + EFI_PEI_FILE_HANDLE *FvFileHandles; + BOOLEAN ScanFv; + UINT32 AuthenticationStatus; +} PEI_CORE_FV_HANDLE; + +typedef struct { + EFI_GUID FvFormat; + VOID *FvInfo; + UINT32 FvInfoSize; + UINT32 AuthenticationStatus; + EFI_PEI_NOTIFY_DESCRIPTOR NotifyDescriptor; +} PEI_CORE_UNKNOW_FORMAT_FV_INFO; + +#define CACHE_SETION_MAX_NUMBER 0x10 +typedef struct { + EFI_COMMON_SECTION_HEADER* Section[CACHE_SETION_MAX_NUMBER]; + VOID* SectionData[CACHE_SETION_MAX_NUMBER]; + UINTN SectionSize[CACHE_SETION_MAX_NUMBER]; + UINT32 AuthenticationStatus[CACHE_SETION_MAX_NUMBER]; + UINTN AllSectionCount; + UINTN SectionIndex; +} CACHE_SECTION_DATA; + +#define HOLE_MAX_NUMBER 0x3 +typedef struct { + EFI_PHYSICAL_ADDRESS Base; + UINTN Size; + UINTN Offset; + BOOLEAN OffsetPositive; +} HOLE_MEMORY_DATA; + +/// +/// Forward declaration for PEI_CORE_INSTANCE +/// +typedef struct _PEI_CORE_INSTANCE PEI_CORE_INSTANCE; + + +/** + Function Pointer type for PeiCore function. + @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size + and location of temporary RAM, the stack location and the BFV location. + @param PpiList Points to a list of one or more PPI descriptors to be installed initially by the PEI core. + An empty PPI list consists of a single descriptor with the end-tag + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST. As part of its initialization + phase, the PEI Foundation will add these SEC-hosted PPIs to its PPI database such + that both the PEI Foundation and any modules can leverage the associated service + calls and/or code in these early PPIs + @param OldCoreData Pointer to old core data that is used to initialize the + core's data areas. +**/ +typedef +EFI_STATUS +(EFIAPI *PEICORE_FUNCTION_POINTER)( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList, + IN PEI_CORE_INSTANCE *OldCoreData + ); + +// +// Number of files to grow by each time we run out of room +// +#define TEMP_FILE_GROWTH_STEP 32 + +#define PEI_CORE_HANDLE_SIGNATURE SIGNATURE_32('P','e','i','C') + +/// +/// Pei Core private data structure instance +/// +struct _PEI_CORE_INSTANCE { + UINTN Signature; + + /// + /// Point to ServiceTableShadow + /// + EFI_PEI_SERVICES *Ps; + PEI_PPI_DATABASE PpiData; + + /// + /// The count of FVs which contains FFS and could be dispatched by PeiCore. + /// + UINTN FvCount; + + /// + /// The max count of FVs which contains FFS and could be dispatched by PeiCore. + /// + UINTN MaxFvCount; + + /// + /// Pointer to the buffer with the MaxFvCount number of entries. + /// Each entry is for one FV which contains FFS and could be dispatched by PeiCore. + /// + PEI_CORE_FV_HANDLE *Fv; + + /// + /// Pointer to the buffer with the MaxUnknownFvInfoCount number of entries. + /// Each entry is for one FV which could not be dispatched by PeiCore. + /// + PEI_CORE_UNKNOW_FORMAT_FV_INFO *UnknownFvInfo; + UINTN MaxUnknownFvInfoCount; + UINTN UnknownFvInfoCount; + + /// + /// Pointer to the buffer FvFileHandlers in PEI_CORE_FV_HANDLE specified by CurrentPeimFvCount. + /// + EFI_PEI_FILE_HANDLE *CurrentFvFileHandles; + UINTN AprioriCount; + UINTN CurrentPeimFvCount; + UINTN CurrentPeimCount; + EFI_PEI_FILE_HANDLE CurrentFileHandle; + BOOLEAN PeimNeedingDispatch; + BOOLEAN PeimDispatchOnThisPass; + BOOLEAN PeimDispatcherReenter; + EFI_PEI_HOB_POINTERS HobList; + BOOLEAN SwitchStackSignal; + BOOLEAN PeiMemoryInstalled; + VOID *CpuIo; + EFI_PEI_SECURITY2_PPI *PrivateSecurityPpi; + EFI_PEI_SERVICES ServiceTableShadow; + EFI_PEI_PPI_DESCRIPTOR *XipLoadFile; + EFI_PHYSICAL_ADDRESS PhysicalMemoryBegin; + UINT64 PhysicalMemoryLength; + EFI_PHYSICAL_ADDRESS FreePhysicalMemoryTop; + UINTN HeapOffset; + BOOLEAN HeapOffsetPositive; + UINTN StackOffset; + BOOLEAN StackOffsetPositive; + // + // Information for migrating memory pages allocated in pre-memory phase. + // + HOLE_MEMORY_DATA MemoryPages; + PEICORE_FUNCTION_POINTER ShadowedPeiCore; + CACHE_SECTION_DATA CacheSection; + // + // For Loading modules at fixed address feature to cache the top address below which the + // Runtime code, boot time code and PEI memory will be placed. Please note that the offset between this field + // and Ps should not be changed since maybe user could get this top address by using the offet to Ps. + // + EFI_PHYSICAL_ADDRESS LoadModuleAtFixAddressTopAddress; + // + // The field is define for Loading modules at fixed address feature to tracker the PEI code + // memory range usage. It is a bit mapped array in which every bit indicates the correspoding memory page + // available or not. + // + UINT64 *PeiCodeMemoryRangeUsageBitMap; + // + // This field points to the shadowed image read function + // + PE_COFF_LOADER_READ_FILE ShadowedImageRead; + + UINTN TempPeimCount; + + // + // Pointer to the temp buffer with the TempPeimCount number of entries. + // + EFI_PEI_FILE_HANDLE *TempFileHandles; + // + // Pointer to the temp buffer with the TempPeimCount number of entries. + // + EFI_GUID *TempFileGuid; + + // + // Temp Memory Range is not covered by PeiTempMem and Stack. + // Those Memory Range will be migrated into physical memory. + // + HOLE_MEMORY_DATA HoleData[HOLE_MAX_NUMBER]; +}; + +/// +/// Pei Core Instance Data Macros +/// +#define PEI_CORE_INSTANCE_FROM_PS_THIS(a) \ + CR(a, PEI_CORE_INSTANCE, Ps, PEI_CORE_HANDLE_SIGNATURE) + +/// +/// Union of temporarily used function pointers (to save stack space) +/// +typedef union { + PEICORE_FUNCTION_POINTER PeiCore; + EFI_PEIM_ENTRY_POINT2 PeimEntry; + EFI_PEIM_NOTIFY_ENTRY_POINT PeimNotifyEntry; + EFI_DXE_IPL_PPI *DxeIpl; + EFI_PEI_PPI_DESCRIPTOR *PpiDescriptor; + EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor; + VOID *Raw; +} PEI_CORE_TEMP_POINTERS; + +typedef struct { + CONST EFI_SEC_PEI_HAND_OFF *SecCoreData; + EFI_PEI_PPI_DESCRIPTOR *PpiList; + VOID *Data; +} PEI_CORE_PARAMETERS; + +// +// PeiCore function +// +/** + + The entry routine to Pei Core, invoked by PeiMain during transition + from SEC to PEI. After switching stack in the PEI core, it will restart + with the old core data. + + + @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size + and location of temporary RAM, the stack location and the BFV location. + @param PpiList Points to a list of one or more PPI descriptors to be installed initially by the PEI core. + An empty PPI list consists of a single descriptor with the end-tag + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST. As part of its initialization + phase, the PEI Foundation will add these SEC-hosted PPIs to its PPI database such + that both the PEI Foundation and any modules can leverage the associated service + calls and/or code in these early PPIs + @param Data Pointer to old core data that is used to initialize the + core's data areas. + +**/ +VOID +EFIAPI +PeiCore ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList, + IN VOID *Data + ); + +// +// Dispatcher support functions +// + +/** + + This is the POSTFIX version of the dependency evaluator. When a + PUSH [PPI GUID] is encountered, a pointer to the GUID is stored on + the evaluation stack. When that entry is poped from the evaluation + stack, the PPI is checked if it is installed. This method allows + some time savings as not all PPIs must be checked for certain + operation types (AND, OR). + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param DependencyExpression Pointer to a dependency expression. The Grammar adheres to + the BNF described above and is stored in postfix notation. + + @retval TRUE if it is a well-formed Grammar + @retval FALSE if the dependency expression overflows the evaluation stack + if the dependency expression underflows the evaluation stack + if the dependency expression is not a well-formed Grammar. + +**/ +BOOLEAN +PeimDispatchReadiness ( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *DependencyExpression + ); + +/** + Conduct PEIM dispatch. + + @param SecCoreData Pointer to the data structure containing SEC to PEI handoff data + @param PrivateData Pointer to the private data passed in from caller + +**/ +VOID +PeiDispatcher ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN PEI_CORE_INSTANCE *PrivateData + ); + +/** + Initialize the Dispatcher's data members + + @param PrivateData PeiCore's private data structure + @param OldCoreData Old data from SecCore + NULL if being run in non-permament memory mode. + @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size + and location of temporary RAM, the stack location and the BFV location. + +**/ +VOID +InitializeDispatcherData ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_INSTANCE *OldCoreData, + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData + ); + +/** + This routine parses the Dependency Expression, if available, and + decides if the module can be executed. + + + @param Private PeiCore's private data structure + @param FileHandle PEIM's file handle + @param PeimCount The index of last dispatched PEIM. + + @retval TRUE Can be dispatched + @retval FALSE Cannot be dispatched + +**/ +BOOLEAN +DepexSatisfied ( + IN PEI_CORE_INSTANCE *Private, + IN EFI_PEI_FILE_HANDLE FileHandle, + IN UINTN PeimCount + ); + +// +// PPI support functions +// +/** + + Initialize PPI services. + + @param PrivateData Pointer to the PEI Core data. + @param OldCoreData Pointer to old PEI Core data. + NULL if being run in non-permament memory mode. + +**/ +VOID +InitializePpiServices ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_INSTANCE *OldCoreData + ); + +/** + + Migrate the Hob list from the temporary memory to PEI installed memory. + + @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size + and location of temporary RAM, the stack location and the BFV location. + @param PrivateData Pointer to PeiCore's private data structure. + +**/ +VOID +ConvertPpiPointers ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN PEI_CORE_INSTANCE *PrivateData + ); + +/** + + Install PPI services. It is implementation of EFI_PEI_SERVICE.InstallPpi. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param PpiList Pointer to ppi array that want to be installed. + + @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed. + @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer + if any PPI in PpiList is not valid + @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI + +**/ +EFI_STATUS +EFIAPI +PeiInstallPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList + ); + +/** + + Re-Install PPI services. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param OldPpi Pointer to the old PEI PPI Descriptors. + @param NewPpi Pointer to the new PEI PPI Descriptors. + + @retval EFI_SUCCESS if the operation was successful + @retval EFI_INVALID_PARAMETER if OldPpi or NewPpi is NULL + if NewPpi is not valid + @retval EFI_NOT_FOUND if the PPI was not in the database + +**/ +EFI_STATUS +EFIAPI +PeiReInstallPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR *OldPpi, + IN CONST EFI_PEI_PPI_DESCRIPTOR *NewPpi + ); + +/** + + Locate a given named PPI. + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param Guid Pointer to GUID of the PPI. + @param Instance Instance Number to discover. + @param PpiDescriptor Pointer to reference the found descriptor. If not NULL, + returns a pointer to the descriptor (includes flags, etc) + @param Ppi Pointer to reference the found PPI + + @retval EFI_SUCCESS if the PPI is in the database + @retval EFI_NOT_FOUND if the PPI is not in the database + +**/ +EFI_STATUS +EFIAPI +PeiLocatePpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_GUID *Guid, + IN UINTN Instance, + IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor, + IN OUT VOID **Ppi + ); + +/** + + Install a notification for a given PPI. + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param NotifyList Pointer to list of Descriptors to notify upon. + + @retval EFI_SUCCESS if successful + @retval EFI_OUT_OF_RESOURCES if no space in the database + @retval EFI_INVALID_PARAMETER if not a good decriptor + +**/ +EFI_STATUS +EFIAPI +PeiNotifyPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList + ); + +/** + + Process the Notify List at dispatch level. + + @param PrivateData PeiCore's private data structure. + +**/ +VOID +ProcessDispatchNotifyList ( + IN PEI_CORE_INSTANCE *PrivateData + ); + +/** + + Process notifications. + + @param PrivateData PeiCore's private data structure + @param NotifyType Type of notify to fire. + @param InstallStartIndex Install Beginning index. + @param InstallStopIndex Install Ending index. + @param NotifyStartIndex Notify Beginning index. + @param NotifyStopIndex Notify Ending index. + +**/ +VOID +ProcessNotify ( + IN PEI_CORE_INSTANCE *PrivateData, + IN UINTN NotifyType, + IN INTN InstallStartIndex, + IN INTN InstallStopIndex, + IN INTN NotifyStartIndex, + IN INTN NotifyStopIndex + ); + +/** + Process PpiList from SEC phase. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param PpiList Points to a list of one or more PPI descriptors to be installed initially by the PEI core. + These PPI's will be installed and/or immediately signaled if they are notification type. + +**/ +VOID +ProcessPpiListFromSec ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList + ); + +// +// Boot mode support functions +// +/** + This service enables PEIMs to ascertain the present value of the boot mode. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param BootMode A pointer to contain the value of the boot mode. + + @retval EFI_SUCCESS The boot mode was returned successfully. + @retval EFI_INVALID_PARAMETER BootMode is NULL. + +**/ +EFI_STATUS +EFIAPI +PeiGetBootMode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_BOOT_MODE *BootMode + ); + +/** + This service enables PEIMs to update the boot mode variable. + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param BootMode The value of the boot mode to set. + + @return EFI_SUCCESS The value was successfully updated + +**/ +EFI_STATUS +EFIAPI +PeiSetBootMode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_BOOT_MODE BootMode + ); + +// +// Security support functions +// +/** + + Initialize the security services. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param OldCoreData Pointer to the old core data. + NULL if being run in non-permament memory mode. + +**/ +VOID +InitializeSecurityServices ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *OldCoreData + ); + +/** + Verify a Firmware volume. + + @param CurrentFvAddress Pointer to the current Firmware Volume under consideration + + @retval EFI_SUCCESS Firmware Volume is legal + @retval EFI_SECURITY_VIOLATION Firmware Volume fails integrity test + +**/ +EFI_STATUS +VerifyFv ( + IN EFI_FIRMWARE_VOLUME_HEADER *CurrentFvAddress + ); + +/** + Provide a callout to the security verification service. + + @param PrivateData PeiCore's private data structure + @param VolumeHandle Handle of FV + @param FileHandle Handle of PEIM's ffs + @param AuthenticationStatus Authentication status + + @retval EFI_SUCCESS Image is OK + @retval EFI_SECURITY_VIOLATION Image is illegal + @retval EFI_NOT_FOUND If security PPI is not installed. +**/ +EFI_STATUS +VerifyPeim ( + IN PEI_CORE_INSTANCE *PrivateData, + IN EFI_PEI_FV_HANDLE VolumeHandle, + IN EFI_PEI_FILE_HANDLE FileHandle, + IN UINT32 AuthenticationStatus + ); + +/** + + Gets the pointer to the HOB List. + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param HobList Pointer to the HOB List. + + @retval EFI_SUCCESS Get the pointer of HOB List + @retval EFI_NOT_AVAILABLE_YET the HOB List is not yet published + @retval EFI_INVALID_PARAMETER HobList is NULL (in debug mode) + +**/ +EFI_STATUS +EFIAPI +PeiGetHobList ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT VOID **HobList + ); + +/** + Add a new HOB to the HOB List. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param Type Type of the new HOB. + @param Length Length of the new HOB to allocate. + @param Hob Pointer to the new HOB. + + @return EFI_SUCCESS Success to create hob. + @retval EFI_INVALID_PARAMETER if Hob is NULL + @retval EFI_NOT_AVAILABLE_YET if HobList is still not available. + @retval EFI_OUT_OF_RESOURCES if there is no more memory to grow the Hoblist. + +**/ +EFI_STATUS +EFIAPI +PeiCreateHob ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINT16 Type, + IN UINT16 Length, + IN OUT VOID **Hob + ); + +/** + + Builds a Handoff Information Table HOB + + @param BootMode - Current Bootmode + @param MemoryBegin - Start Memory Address. + @param MemoryLength - Length of Memory. + + @return EFI_SUCCESS Always success to initialize HOB. + +**/ +EFI_STATUS +PeiCoreBuildHobHandoffInfoTable ( + IN EFI_BOOT_MODE BootMode, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ); + +/** + Install SEC HOB data to the HOB List. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param SecHobList Pointer to SEC HOB List. + + @return EFI_SUCCESS Success to install SEC HOB data. + @retval EFI_OUT_OF_RESOURCES If there is no more memory to grow the Hoblist. + +**/ +EFI_STATUS +PeiInstallSecHobData ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_HOB_GENERIC_HEADER *SecHobList + ); + + +// +// FFS Fw Volume support functions +// +/** + Searches for the next matching file in the firmware volume. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param SearchType Filter to find only files of this type. + Type EFI_FV_FILETYPE_ALL causes no filtering to be done. + @param FvHandle Handle of firmware volume in which to search. + @param FileHandle On entry, points to the current handle from which to begin searching or NULL to start + at the beginning of the firmware volume. On exit, points the file handle of the next file + in the volume or NULL if there are no more files. + + @retval EFI_NOT_FOUND The file was not found. + @retval EFI_NOT_FOUND The header checksum was not zero. + @retval EFI_SUCCESS The file was found. + +**/ +EFI_STATUS +EFIAPI +PeiFfsFindNextFile ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINT8 SearchType, + IN EFI_PEI_FV_HANDLE FvHandle, + IN OUT EFI_PEI_FILE_HANDLE *FileHandle + ); + +/** + Searches for the next matching section within the specified file. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation + @param SectionType Filter to find only sections of this type. + @param FileHandle Pointer to the current file to search. + @param SectionData A pointer to the discovered section, if successful. + NULL if section not found + + @retval EFI_NOT_FOUND The section was not found. + @retval EFI_SUCCESS The section was found. + +**/ +EFI_STATUS +EFIAPI +PeiFfsFindSectionData ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **SectionData + ); + +/** + Searches for the next matching section within the specified file. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param SectionType The value of the section type to find. + @param SectionInstance Section instance to find. + @param FileHandle Handle of the firmware file to search. + @param SectionData A pointer to the discovered section, if successful. + @param AuthenticationStatus A pointer to the authentication status for this section. + + @retval EFI_SUCCESS The section was found. + @retval EFI_NOT_FOUND The section was not found. + +**/ +EFI_STATUS +EFIAPI +PeiFfsFindSectionData3 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN UINTN SectionInstance, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **SectionData, + OUT UINT32 *AuthenticationStatus + ); + +/** + Search the firmware volumes by index + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation + @param Instance This instance of the firmware volume to find. The value 0 is the Boot Firmware + Volume (BFV). + @param VolumeHandle On exit, points to the next volume handle or NULL if it does not exist. + + @retval EFI_INVALID_PARAMETER VolumeHandle is NULL + @retval EFI_NOT_FOUND The volume was not found. + @retval EFI_SUCCESS The volume was found. + +**/ +EFI_STATUS +EFIAPI +PeiFfsFindNextVolume ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN Instance, + IN OUT EFI_PEI_FV_HANDLE *VolumeHandle + ); + +// +// Memory support functions +// +/** + + Initialize the memory services. + + @param PrivateData PeiCore's private data structure + @param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size + and location of temporary RAM, the stack location and the BFV location. + @param OldCoreData Pointer to the PEI Core data. + NULL if being run in non-permament memory mode. + +**/ +VOID +InitializeMemoryServices ( + IN PEI_CORE_INSTANCE *PrivateData, + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN PEI_CORE_INSTANCE *OldCoreData + ); + +/** + + Install the permanent memory is now available. + Creates HOB (PHIT and Stack). + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param MemoryBegin Start of memory address. + @param MemoryLength Length of memory. + + @return EFI_SUCCESS Always success. + +**/ +EFI_STATUS +EFIAPI +PeiInstallPeiMemory ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ); + +/** + Migrate memory pages allocated in pre-memory phase. + Copy memory pages at temporary heap top to permanent heap top. + + @param[in] Private Pointer to the private data passed in from caller. + @param[in] TemporaryRamMigrated Temporary memory has been migrated to permanent memory. + +**/ +VOID +MigrateMemoryPages ( + IN PEI_CORE_INSTANCE *Private, + IN BOOLEAN TemporaryRamMigrated + ); + +/** + Migrate MemoryBaseAddress in memory allocation HOBs + from the temporary memory to PEI installed memory. + + @param[in] PrivateData Pointer to PeiCore's private data structure. + +**/ +VOID +ConvertMemoryAllocationHobs ( + IN PEI_CORE_INSTANCE *PrivateData + ); + +/** + The purpose of the service is to publish an interface that allows + PEIMs to allocate memory ranges that are managed by the PEI Foundation. + + Prior to InstallPeiMemory() being called, PEI will allocate pages from the heap. + After InstallPeiMemory() is called, PEI will allocate pages within the region + of memory provided by InstallPeiMemory() service in a best-effort fashion. + Location-specific allocations are not managed by the PEI foundation code. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param MemoryType The type of memory to allocate. + @param Pages The number of contiguous 4 KB pages to allocate. + @param Memory Pointer to a physical address. On output, the address is set to the base + of the page range that was allocated. + + @retval EFI_SUCCESS The memory range was successfully allocated. + @retval EFI_OUT_OF_RESOURCES The pages could not be allocated. + @retval EFI_INVALID_PARAMETER Type is not equal to EfiLoaderCode, EfiLoaderData, EfiRuntimeServicesCode, + EfiRuntimeServicesData, EfiBootServicesCode, EfiBootServicesData, + EfiACPIReclaimMemory, EfiReservedMemoryType, or EfiACPIMemoryNVS. + +**/ +EFI_STATUS +EFIAPI +PeiAllocatePages ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT EFI_PHYSICAL_ADDRESS *Memory + ); + +/** + Frees memory pages. + + @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param[in] Memory The base physical address of the pages to be freed. + @param[in] Pages The number of contiguous 4 KB pages to free. + + @retval EFI_SUCCESS The requested pages were freed. + @retval EFI_INVALID_PARAMETER Memory is not a page-aligned address or Pages is invalid. + @retval EFI_NOT_FOUND The requested memory pages were not allocated with + AllocatePages(). + +**/ +EFI_STATUS +EFIAPI +PeiFreePages ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN Pages + ); + +/** + + Memory allocation service on the temporary memory. + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param Size Amount of memory required + @param Buffer Address of pointer to the buffer + + @retval EFI_SUCCESS The allocation was successful + @retval EFI_OUT_OF_RESOURCES There is not enough heap to satisfy the requirement + to allocate the requested size. + +**/ +EFI_STATUS +EFIAPI +PeiAllocatePool ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN Size, + OUT VOID **Buffer + ); + +/** + + Routine for load image file. + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param FileHandle Pointer to the FFS file header of the image. + @param PeimState The dispatch state of the input PEIM handle. + @param EntryPoint Pointer to entry point of specified image file for output. + @param AuthenticationState Pointer to attestation authentication state of image. + + @retval EFI_SUCCESS Image is successfully loaded. + @retval EFI_NOT_FOUND Fail to locate necessary PPI + @retval Others Fail to load file. + +**/ +EFI_STATUS +PeiLoadImage ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_FILE_HANDLE FileHandle, + IN UINT8 PeimState, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState + ); + +/** + + Core version of the Status Code reporter + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param CodeType Type of Status Code. + @param Value Value to output for Status Code. + @param Instance Instance Number of this status code. + @param CallerId ID of the caller of this status code. + @param Data Optional data associated with this status code. + + @retval EFI_SUCCESS if status code is successfully reported + @retval EFI_NOT_AVAILABLE_YET if StatusCodePpi has not been installed + +**/ +EFI_STATUS +EFIAPI +PeiReportStatusCode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN CONST EFI_GUID *CallerId, + IN CONST EFI_STATUS_CODE_DATA *Data OPTIONAL + ); + +/** + + Core version of the Reset System + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + + @retval EFI_NOT_AVAILABLE_YET PPI not available yet. + @retval EFI_DEVICE_ERROR Did not reset system. + Otherwise, resets the system. + +**/ +EFI_STATUS +EFIAPI +PeiResetSystem ( + IN CONST EFI_PEI_SERVICES **PeiServices + ); + +/** + Resets the entire platform. + + @param[in] ResetType The type of reset to perform. + @param[in] ResetStatus The status code for the reset. + @param[in] DataSize The size, in bytes, of ResetData. + @param[in] ResetData For a ResetType of EfiResetCold, EfiResetWarm, or EfiResetShutdown + the data buffer starts with a Null-terminated string, optionally + followed by additional binary data. The string is a description + that the caller may use to further indicate the reason for the + system reset. ResetData is only valid if ResetStatus is something + other than EFI_SUCCESS unless the ResetType is EfiResetPlatformSpecific + where a minimum amount of ResetData is always required. + +**/ +VOID +EFIAPI +PeiResetSystem2 ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN VOID *ResetData OPTIONAL + ); + +/** + + Initialize PeiCore Fv List. + + + @param PrivateData - Pointer to PEI_CORE_INSTANCE. + @param SecCoreData - Pointer to EFI_SEC_PEI_HAND_OFF. + +**/ +VOID +PeiInitializeFv ( + IN PEI_CORE_INSTANCE *PrivateData, + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData + ); + +/** + Process Firmware Volum Information once FvInfoPPI install. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param NotifyDescriptor Address of the notification descriptor data structure. + @param Ppi Address of the PPI that was installed. + + @retval EFI_SUCCESS if the interface could be successfully installed + +**/ +EFI_STATUS +EFIAPI +FirmwareVolmeInfoPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + +/** + + Given the input VolumeHandle, search for the next matching name file. + + @param FileName File name to search. + @param VolumeHandle The current FV to search. + @param FileHandle Pointer to the file matching name in VolumeHandle. + NULL if file not found + + @retval EFI_NOT_FOUND No files matching the search criteria were found + @retval EFI_SUCCESS Success to search given file + +**/ +EFI_STATUS +EFIAPI +PeiFfsFindFileByName ( + IN CONST EFI_GUID *FileName, + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_PEI_FILE_HANDLE *FileHandle + ); + +/** + Returns information about a specific file. + + @param FileHandle Handle of the file. + @param FileInfo Upon exit, points to the file's information. + + @retval EFI_INVALID_PARAMETER If FileInfo is NULL. + @retval EFI_INVALID_PARAMETER If FileHandle does not represent a valid file. + @retval EFI_SUCCESS File information returned. + +**/ +EFI_STATUS +EFIAPI +PeiFfsGetFileInfo ( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO *FileInfo + ); + +/** + Returns information about a specific file. + + @param FileHandle Handle of the file. + @param FileInfo Upon exit, points to the file's information. + + @retval EFI_INVALID_PARAMETER If FileInfo is NULL. + @retval EFI_INVALID_PARAMETER If FileHandle does not represent a valid file. + @retval EFI_SUCCESS File information returned. + +**/ +EFI_STATUS +EFIAPI +PeiFfsGetFileInfo2 ( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO2 *FileInfo + ); + +/** + Returns information about the specified volume. + + @param VolumeHandle Handle of the volume. + @param VolumeInfo Upon exit, points to the volume's information. + + @retval EFI_INVALID_PARAMETER If VolumeHandle does not represent a valid volume. + @retval EFI_INVALID_PARAMETER If VolumeInfo is NULL. + @retval EFI_SUCCESS Volume information returned. +**/ +EFI_STATUS +EFIAPI +PeiFfsGetVolumeInfo ( + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_FV_INFO *VolumeInfo + ); + +/** + This routine enable a PEIM to register itself to shadow when PEI Foundation + discovery permanent memory. + + @param FileHandle File handle of a PEIM. + + @retval EFI_NOT_FOUND The file handle doesn't point to PEIM itself. + @retval EFI_ALREADY_STARTED Indicate that the PEIM has been registered itself. + @retval EFI_SUCCESS Successfully to register itself. + +**/ +EFI_STATUS +EFIAPI +PeiRegisterForShadow ( + IN EFI_PEI_FILE_HANDLE FileHandle + ); + +/** + Initialize image service that install PeiLoadFilePpi. + + @param PrivateData Pointer to PeiCore's private data structure PEI_CORE_INSTANCE. + @param OldCoreData Pointer to Old PeiCore's private data. + If NULL, PeiCore is entered at first time, stack/heap in temporary memory. + If not NULL, PeiCore is entered at second time, stack/heap has been moved + to permanent memory. + +**/ +VOID +InitializeImageServices ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_INSTANCE *OldCoreData + ); + +/** + The wrapper function of PeiLoadImageLoadImage(). + + @param This Pointer to EFI_PEI_LOAD_FILE_PPI. + @param FileHandle Pointer to the FFS file header of the image. + @param ImageAddressArg Pointer to PE/TE image. + @param ImageSizeArg Size of PE/TE image. + @param EntryPoint Pointer to entry point of specified image file for output. + @param AuthenticationState Pointer to attestation authentication state of image. + + @return Status of PeiLoadImageLoadImage(). + +**/ +EFI_STATUS +EFIAPI +PeiLoadImageLoadImageWrapper ( + IN CONST EFI_PEI_LOAD_FILE_PPI *This, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL + OUT UINT64 *ImageSizeArg, OPTIONAL + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState + ); + +/** + + Provide a callback for when the security PPI is installed. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param NotifyDescriptor The descriptor for the notification event. + @param Ppi Pointer to the PPI in question. + + @return Always success + +**/ +EFI_STATUS +EFIAPI +SecurityPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + +/** + Get Fv image(s) from the FV type file, then install FV INFO(2) ppi, Build FV(2, 3) hob. + + @param PrivateData PeiCore's private data structure + @param ParentFvCoreHandle Pointer of EFI_CORE_FV_HANDLE to parent Fv image that contain this Fv image. + @param ParentFvFileHandle File handle of a Fv type file that contain this Fv image. + + @retval EFI_NOT_FOUND FV image can't be found. + @retval EFI_SUCCESS Successfully to process it. + @retval EFI_OUT_OF_RESOURCES Can not allocate page when aligning FV image + @retval EFI_SECURITY_VIOLATION Image is illegal + @retval Others Can not find EFI_SECTION_FIRMWARE_VOLUME_IMAGE section + +**/ +EFI_STATUS +ProcessFvFile ( + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_FV_HANDLE *ParentFvCoreHandle, + IN EFI_PEI_FILE_HANDLE ParentFvFileHandle + ); + +/** + Get instance of PEI_CORE_FV_HANDLE for next volume according to given index. + + This routine also will install FvInfo ppi for FV hob in PI ways. + + @param Private Pointer of PEI_CORE_INSTANCE + @param Instance The index of FV want to be searched. + + @return Instance of PEI_CORE_FV_HANDLE. +**/ +PEI_CORE_FV_HANDLE * +FindNextCoreFvHandle ( + IN PEI_CORE_INSTANCE *Private, + IN UINTN Instance + ); + +// +// Default EFI_PEI_CPU_IO_PPI support for EFI_PEI_SERVICES table when PeiCore initialization. +// + +/** + Memory-based read services. + + This function is to perform the Memory Access Read service based on installed + instance of the EFI_PEI_CPU_IO_PPI. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return EFI_NOT_YET_AVAILABLE. + + @param PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Width The width of the access. Enumerated in bytes. + @param Address The physical address of the access. + @param Count The number of accesses to perform. + @param Buffer A pointer to the buffer of data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_YET_AVAILABLE The service has not been installed. +**/ +EFI_STATUS +EFIAPI +PeiDefaultMemRead ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN EFI_PEI_CPU_IO_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +/** + Memory-based write services. + + This function is to perform the Memory Access Write service based on installed + instance of the EFI_PEI_CPU_IO_PPI. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return EFI_NOT_YET_AVAILABLE. + + @param PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Width The width of the access. Enumerated in bytes. + @param Address The physical address of the access. + @param Count The number of accesses to perform. + @param Buffer A pointer to the buffer of data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_YET_AVAILABLE The service has not been installed. +**/ +EFI_STATUS +EFIAPI +PeiDefaultMemWrite ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN EFI_PEI_CPU_IO_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +/** + IO-based read services. + + This function is to perform the IO-base read service for the EFI_PEI_CPU_IO_PPI. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return EFI_NOT_YET_AVAILABLE. + + @param PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Width The width of the access. Enumerated in bytes. + @param Address The physical address of the access. + @param Count The number of accesses to perform. + @param Buffer A pointer to the buffer of data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_YET_AVAILABLE The service has not been installed. +**/ +EFI_STATUS +EFIAPI +PeiDefaultIoRead ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN EFI_PEI_CPU_IO_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +/** + IO-based write services. + + This function is to perform the IO-base write service for the EFI_PEI_CPU_IO_PPI. + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return EFI_NOT_YET_AVAILABLE. + + @param PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Width The width of the access. Enumerated in bytes. + @param Address The physical address of the access. + @param Count The number of accesses to perform. + @param Buffer A pointer to the buffer of data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_YET_AVAILABLE The service has not been installed. +**/ +EFI_STATUS +EFIAPI +PeiDefaultIoWrite ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN EFI_PEI_CPU_IO_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +/** + 8-bit I/O read operations. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return An 8-bit value returned from the I/O space. +**/ +UINT8 +EFIAPI +PeiDefaultIoRead8 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + Reads an 16-bit I/O port. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return A 16-bit value returned from the I/O space. +**/ +UINT16 +EFIAPI +PeiDefaultIoRead16 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + Reads an 32-bit I/O port. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return A 32-bit value returned from the I/O space. +**/ +UINT32 +EFIAPI +PeiDefaultIoRead32 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + Reads an 64-bit I/O port. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return A 64-bit value returned from the I/O space. +**/ +UINT64 +EFIAPI +PeiDefaultIoRead64 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + 8-bit I/O write operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. +**/ +VOID +EFIAPI +PeiDefaultIoWrite8 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT8 Data + ); + +/** + 16-bit I/O write operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. +**/ +VOID +EFIAPI +PeiDefaultIoWrite16 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT16 Data + ); + +/** + 32-bit I/O write operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. +**/ +VOID +EFIAPI +PeiDefaultIoWrite32 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT32 Data + ); + +/** + 64-bit I/O write operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. +**/ +VOID +EFIAPI +PeiDefaultIoWrite64 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT64 Data + ); + +/** + 8-bit memory read operations. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return An 8-bit value returned from the memory space. + +**/ +UINT8 +EFIAPI +PeiDefaultMemRead8 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + 16-bit memory read operations. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return An 16-bit value returned from the memory space. + +**/ +UINT16 +EFIAPI +PeiDefaultMemRead16 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + 32-bit memory read operations. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return An 32-bit value returned from the memory space. + +**/ +UINT32 +EFIAPI +PeiDefaultMemRead32 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + 64-bit memory read operations. + + If the EFI_PEI_CPU_IO_PPI is not installed by platform/chipset PEIM, then + return 0. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + + @return An 64-bit value returned from the memory space. + +**/ +UINT64 +EFIAPI +PeiDefaultMemRead64 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + 8-bit memory write operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. + +**/ +VOID +EFIAPI +PeiDefaultMemWrite8 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT8 Data + ); + +/** + 16-bit memory write operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. + +**/ +VOID +EFIAPI +PeiDefaultMemWrite16 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT16 Data + ); + +/** + 32-bit memory write operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. + +**/ +VOID +EFIAPI +PeiDefaultMemWrite32 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT32 Data + ); + +/** + 64-bit memory write operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Address The physical address of the access. + @param Data The data to write. + +**/ +VOID +EFIAPI +PeiDefaultMemWrite64 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT64 Data + ); + +extern EFI_PEI_CPU_IO_PPI gPeiDefaultCpuIoPpi; + +// +// Default EFI_PEI_PCI_CFG2_PPI support for EFI_PEI_SERVICES table when PeiCore initialization. +// + +/** + Reads from a given location in the PCI configuration space. + + If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM, then + return EFI_NOT_YET_AVAILABLE. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Width The width of the access. Enumerated in bytes. + See EFI_PEI_PCI_CFG_PPI_WIDTH above. + @param Address The physical address of the access. The format of + the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS. + @param Buffer A pointer to the buffer of data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER The invalid access width. + @retval EFI_NOT_YET_AVAILABLE If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM. + +**/ +EFI_STATUS +EFIAPI +PeiDefaultPciCfg2Read ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PCI_CFG2_PPI *This, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, + IN OUT VOID *Buffer + ); + +/** + Write to a given location in the PCI configuration space. + + If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM, then + return EFI_NOT_YET_AVAILABLE. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Width The width of the access. Enumerated in bytes. + See EFI_PEI_PCI_CFG_PPI_WIDTH above. + @param Address The physical address of the access. The format of + the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS. + @param Buffer A pointer to the buffer of data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER The invalid access width. + @retval EFI_NOT_YET_AVAILABLE If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM. +**/ +EFI_STATUS +EFIAPI +PeiDefaultPciCfg2Write ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PCI_CFG2_PPI *This, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, + IN OUT VOID *Buffer + ); + +/** + This function performs a read-modify-write operation on the contents from a given + location in the PCI configuration space. + + @param PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + @param This Pointer to local data for the interface. + @param Width The width of the access. Enumerated in bytes. Type + EFI_PEI_PCI_CFG_PPI_WIDTH is defined in Read(). + @param Address The physical address of the access. + @param SetBits Points to value to bitwise-OR with the read configuration value. + The size of the value is determined by Width. + @param ClearBits Points to the value to negate and bitwise-AND with the read configuration value. + The size of the value is determined by Width. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER The invalid access width. + @retval EFI_NOT_YET_AVAILABLE If the EFI_PEI_PCI_CFG2_PPI is not installed by platform/chipset PEIM. +**/ +EFI_STATUS +EFIAPI +PeiDefaultPciCfg2Modify ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PCI_CFG2_PPI *This, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, + IN VOID *SetBits, + IN VOID *ClearBits + ); + +extern EFI_PEI_PCI_CFG2_PPI gPeiDefaultPciCfg2Ppi; + +/** + After PeiCore image is shadowed into permanent memory, all build-in FvPpi should + be re-installed with the instance in permanent memory and all cached FvPpi pointers in + PrivateData->Fv[] array should be fixed up to be pointed to the one in permanent + memory. + + @param PrivateData Pointer to PEI_CORE_INSTANCE. +**/ +VOID +PeiReinitializeFv ( + IN PEI_CORE_INSTANCE *PrivateData + ); + +#endif diff --git a/HBFA/UefiHostTestPkg/Library/PeiServicesTablePointerLibHost/PeiServicesTablePointerLibHost.c b/HBFA/UefiHostTestPkg/Library/PeiServicesTablePointerLibHost/PeiServicesTablePointerLibHost.c new file mode 100644 index 0000000..4f4b2e3 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/PeiServicesTablePointerLibHost/PeiServicesTablePointerLibHost.c @@ -0,0 +1,416 @@ +/** @file + PEI Services Table Pointer Library. + + This library is used for PEIM which does executed from flash device directly but + executed in memory. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +#include "PeiMain.h" + +extern EFI_PEI_CPU_IO_PPI mPeiDefaultCpuIoPpi; +extern EFI_PEI_PCI_CFG2_PPI mPeiDefaultPciCfg2Ppi; +extern EFI_PEI_SERVICES mPeiServices; + +PEI_CORE_INSTANCE mPrivateData = { + PEI_CORE_HANDLE_SIGNATURE, + &mPeiServices, +}; + +CONST EFI_PEI_SERVICES **gPeiServices = &mPrivateData.Ps; + +/** + Caches a pointer PEI Services Table. + + Caches the pointer to the PEI Services Table specified by PeiServicesTablePointer + in a CPU specific manner as specified in the CPU binding section of the Platform Initialization + Pre-EFI Initialization Core Interface Specification. + + If PeiServicesTablePointer is NULL, then ASSERT(). + + @param PeiServicesTablePointer The address of PeiServices pointer. +**/ +VOID +EFIAPI +SetPeiServicesTablePointer ( + IN CONST EFI_PEI_SERVICES ** PeiServicesTablePointer + ) +{ + ASSERT (FALSE); + ASSERT (PeiServicesTablePointer != NULL); + gPeiServices = PeiServicesTablePointer; +} + +/** + Retrieves the cached value of the PEI Services Table pointer. + + Returns the cached value of the PEI Services Table pointer in a CPU specific manner + as specified in the CPU binding section of the Platform Initialization Pre-EFI + Initialization Core Interface Specification. + + If the cached PEI Services Table pointer is NULL, then ASSERT(). + + @return The pointer to PeiServices. + +**/ +CONST EFI_PEI_SERVICES ** +EFIAPI +GetPeiServicesTablePointer ( + VOID + ) +{ + return gPeiServices; +} + +/** + Perform CPU specific actions required to migrate the PEI Services Table + pointer from temporary RAM to permanent RAM. + + For IA32 CPUs, the PEI Services Table pointer is stored in the 4 bytes + immediately preceding the Interrupt Descriptor Table (IDT) in memory. + For X64 CPUs, the PEI Services Table pointer is stored in the 8 bytes + immediately preceding the Interrupt Descriptor Table (IDT) in memory. + For Itanium and ARM CPUs, a the PEI Services Table Pointer is stored in + a dedicated CPU register. This means that there is no memory storage + associated with storing the PEI Services Table pointer, so no additional + migration actions are required for Itanium or ARM CPUs. + +**/ +VOID +EFIAPI +MigratePeiServicesTablePointer ( + VOID + ) +{ + // + // PEI Services Table pointer is cached in the global variable. No additional + // migration actions are required. + // + ASSERT (FALSE); + return; +} + +EFI_STATUS +EFIAPI +PeiInstallPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList + ); + +EFI_STATUS +EFIAPI +PeiReInstallPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR *OldPpi, + IN CONST EFI_PEI_PPI_DESCRIPTOR *NewPpi + ); + +EFI_STATUS +EFIAPI +PeiLocatePpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_GUID *Guid, + IN UINTN Instance, + IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor, + IN OUT VOID **Ppi + ); + +EFI_STATUS +EFIAPI +PeiNotifyPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList + ); + +EFI_STATUS +EFIAPI +PeiGetBootMode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_BOOT_MODE *BootMode + ) +{ + ASSERT (FALSE); + return EFI_NOT_AVAILABLE_YET; +} + +EFI_STATUS +EFIAPI +PeiSetBootMode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_BOOT_MODE BootMode + ) +{ + ASSERT (FALSE); + return EFI_NOT_AVAILABLE_YET; +} + +EFI_STATUS +EFIAPI +PeiGetHobList ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT VOID **HobList + ) +{ + ASSERT (FALSE); + return EFI_NOT_AVAILABLE_YET; +} + +EFI_STATUS +EFIAPI +PeiCreateHob ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINT16 Type, + IN UINT16 Length, + IN OUT VOID **Hob + ) +{ + ASSERT (FALSE); + return EFI_NOT_AVAILABLE_YET; +} + +EFI_STATUS +EFIAPI +PeiFfsFindNextVolume ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN Instance, + IN OUT EFI_PEI_FV_HANDLE *VolumeHandle + ) +{ + ASSERT (FALSE); + return EFI_NOT_AVAILABLE_YET; +} + +EFI_STATUS +EFIAPI +PeiFfsFindNextFile ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINT8 SearchType, + IN EFI_PEI_FV_HANDLE FvHandle, + IN OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +{ + ASSERT (FALSE); + return EFI_NOT_AVAILABLE_YET; +} + +EFI_STATUS +EFIAPI +PeiFfsFindSectionData ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **SectionData + ) +{ + ASSERT (FALSE); + return EFI_NOT_AVAILABLE_YET; +} + +EFI_STATUS +EFIAPI +PeiInstallPeiMemory ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +{ + ASSERT (FALSE); + return EFI_NOT_AVAILABLE_YET; +} + +EFI_STATUS +EFIAPI +PeiAllocatePages ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT EFI_PHYSICAL_ADDRESS *Memory + ) +{ + ASSERT (FALSE); + return EFI_NOT_AVAILABLE_YET; +} + +EFI_STATUS +EFIAPI +PeiAllocatePool ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN Size, + OUT VOID **Buffer + ) +{ + ASSERT (FALSE); + return EFI_NOT_AVAILABLE_YET; +} + +EFI_STATUS +EFIAPI +PeiReportStatusCode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN CONST EFI_GUID *CallerId, + IN CONST EFI_STATUS_CODE_DATA *Data OPTIONAL + ) +{ + ASSERT (FALSE); + return EFI_NOT_AVAILABLE_YET; +} + +EFI_STATUS +EFIAPI +PeiResetSystem ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + ASSERT (FALSE); + return EFI_NOT_AVAILABLE_YET; +} + +EFI_STATUS +EFIAPI +PeiFfsFindFileByName ( + IN CONST EFI_GUID *FileName, + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_PEI_FILE_HANDLE *FileHandle + ) +{ + ASSERT (FALSE); + return EFI_NOT_AVAILABLE_YET; +} + +EFI_STATUS +EFIAPI +PeiFfsGetFileInfo ( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO *FileInfo + ) +{ + ASSERT (FALSE); + return EFI_NOT_AVAILABLE_YET; +} + +EFI_STATUS +EFIAPI +PeiFfsGetVolumeInfo ( + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_FV_INFO *VolumeInfo + ) +{ + ASSERT (FALSE); + return EFI_NOT_AVAILABLE_YET; +} + +EFI_STATUS +EFIAPI +PeiRegisterForShadow ( + IN EFI_PEI_FILE_HANDLE FileHandle + ) +{ + ASSERT (FALSE); + return EFI_NOT_AVAILABLE_YET; +} + +EFI_STATUS +EFIAPI +PeiFfsFindSectionData3 ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN UINTN SectionInstance, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **SectionData, + OUT UINT32 *AuthenticationStatus + ) +{ + ASSERT (FALSE); + return EFI_NOT_AVAILABLE_YET; +} + +EFI_STATUS +EFIAPI +PeiFfsGetFileInfo2 ( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO2 *FileInfo + ) +{ + ASSERT (FALSE); + return EFI_NOT_AVAILABLE_YET; +} + +VOID +EFIAPI +PeiResetSystem2 ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN VOID *ResetData OPTIONAL + ) +{ + ASSERT (FALSE); +} + +EFI_STATUS +EFIAPI +PeiFreePages ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN Pages + ) +{ + ASSERT (FALSE); + return EFI_NOT_AVAILABLE_YET; +} + +EFI_PEI_SERVICES mPeiServices = { + { + PEI_SERVICES_SIGNATURE, + PEI_SERVICES_REVISION, + sizeof (EFI_PEI_SERVICES), + 0, + 0 + }, + PeiInstallPpi, + PeiReInstallPpi, + PeiLocatePpi, + PeiNotifyPpi, + + PeiGetBootMode, + PeiSetBootMode, + + PeiGetHobList, + PeiCreateHob, + + PeiFfsFindNextVolume, + PeiFfsFindNextFile, + PeiFfsFindSectionData, + + PeiInstallPeiMemory, + PeiAllocatePages, + PeiAllocatePool, + (EFI_PEI_COPY_MEM)CopyMem, + (EFI_PEI_SET_MEM)SetMem, + + PeiReportStatusCode, + PeiResetSystem, + + &mPeiDefaultCpuIoPpi, + &mPeiDefaultPciCfg2Ppi, + + PeiFfsFindFileByName, + PeiFfsGetFileInfo, + PeiFfsGetVolumeInfo, + PeiRegisterForShadow, + PeiFfsFindSectionData3, + PeiFfsGetFileInfo2, + PeiResetSystem2, + PeiFreePages, +}; diff --git a/HBFA/UefiHostTestPkg/Library/PeiServicesTablePointerLibHost/PeiServicesTablePointerLibHost.inf b/HBFA/UefiHostTestPkg/Library/PeiServicesTablePointerLibHost/PeiServicesTablePointerLibHost.inf new file mode 100644 index 0000000..4437214 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/PeiServicesTablePointerLibHost/PeiServicesTablePointerLibHost.inf @@ -0,0 +1,39 @@ +## @file +# Instance of PEI Services Table Pointer Library using global variable for the table pointer. +# +# PEI Services Table Pointer Library implementation that retrieves a pointer to the +# PEI Services Table from a global variable. Not available to modules that execute from +# read-only memory. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PeiServicesTablePointerLibHost + FILE_GUID = AFA925DB-1728-4CE3-9171-E72548E8526A + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = PeiServicesTablePointerLibHost|PEIM PEI_CORE SEC + +# +# VALID_ARCHITECTURES = IA32 X64 EBC (EBC is for build only) +# + +[Sources] + PeiServicesTablePointerLibHost.c + Ppi.c + CpuIo.c + PciCfg2.c + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + DebugLib + diff --git a/HBFA/UefiHostTestPkg/Library/PeiServicesTablePointerLibHost/Ppi.c b/HBFA/UefiHostTestPkg/Library/PeiServicesTablePointerLibHost/Ppi.c new file mode 100644 index 0000000..2b88455 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/PeiServicesTablePointerLibHost/Ppi.c @@ -0,0 +1,583 @@ +/** @file + EFI PEI Core PPI services + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PeiMain.h" + +/** + + This function installs an interface in the PEI PPI database by GUID. + The purpose of the service is to publish an interface that other parties + can use to call additional PEIMs. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param PpiList Pointer to a list of PEI PPI Descriptors. + @param Single TRUE if only single entry in the PpiList. + FALSE if the PpiList is ended with an entry which has the + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST flag set in its Flags field. + + @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed. + @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer + if any PPI in PpiList is not valid + @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI + +**/ +EFI_STATUS +InternalPeiInstallPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList, + IN BOOLEAN Single + ) +{ + PEI_CORE_INSTANCE *PrivateData; + PEI_PPI_LIST *PpiListPointer; + UINTN Index; + UINTN LastCount; + VOID *TempPtr; + + if (PpiList == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + PpiListPointer = &PrivateData->PpiData.PpiList; + Index = PpiListPointer->CurrentCount; + LastCount = Index; + + // + // This is loop installs all PPI descriptors in the PpiList. It is terminated + // by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last + // EFI_PEI_PPI_DESCRIPTOR in the list. + // + + for (;;) { + // + // Check if it is a valid PPI. + // If not, rollback list to exclude all in this list. + // Try to indicate which item failed. + // + if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) { + PpiListPointer->CurrentCount = LastCount; + DEBUG((EFI_D_ERROR, "ERROR -> InstallPpi: %g %p\n", PpiList->Guid, PpiList->Ppi)); + return EFI_INVALID_PARAMETER; + } + + if (Index >= PpiListPointer->MaxCount) { + // + // Run out of room, grow the buffer. + // + TempPtr = AllocateZeroPool ( + sizeof (PEI_PPI_LIST_POINTERS) * (PpiListPointer->MaxCount + PPI_GROWTH_STEP) + ); + ASSERT (TempPtr != NULL); + CopyMem ( + TempPtr, + PpiListPointer->PpiPtrs, + sizeof (PEI_PPI_LIST_POINTERS) * PpiListPointer->MaxCount + ); + PpiListPointer->PpiPtrs = TempPtr; + PpiListPointer->MaxCount = PpiListPointer->MaxCount + PPI_GROWTH_STEP; + } + + DEBUG((EFI_D_INFO, "Install PPI: %g\n", PpiList->Guid)); + PpiListPointer->PpiPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR *) PpiList; + Index++; + PpiListPointer->CurrentCount++; + + if (Single) { + // + // Only single entry in the PpiList. + // + break; + } else if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) { + // + // Continue until the end of the PPI List. + // + break; + } + // + // Go to the next descriptor. + // + PpiList++; + } + + // + // Process any callback level notifies for newly installed PPIs. + // + ProcessNotify ( + PrivateData, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + LastCount, + PpiListPointer->CurrentCount, + 0, + PrivateData->PpiData.CallbackNotifyList.CurrentCount + ); + + return EFI_SUCCESS; +} + +/** + + This function installs an interface in the PEI PPI database by GUID. + The purpose of the service is to publish an interface that other parties + can use to call additional PEIMs. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param PpiList Pointer to a list of PEI PPI Descriptors. + + @retval EFI_SUCCESS if all PPIs in PpiList are successfully installed. + @retval EFI_INVALID_PARAMETER if PpiList is NULL pointer + if any PPI in PpiList is not valid + @retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI + +**/ +EFI_STATUS +EFIAPI +PeiInstallPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList + ) +{ + return InternalPeiInstallPpi (PeiServices, PpiList, FALSE); +} + +/** + + This function reinstalls an interface in the PEI PPI database by GUID. + The purpose of the service is to publish an interface that other parties can + use to replace an interface of the same name in the protocol database with a + different interface. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param OldPpi Pointer to the old PEI PPI Descriptors. + @param NewPpi Pointer to the new PEI PPI Descriptors. + + @retval EFI_SUCCESS if the operation was successful + @retval EFI_INVALID_PARAMETER if OldPpi or NewPpi is NULL + @retval EFI_INVALID_PARAMETER if NewPpi is not valid + @retval EFI_NOT_FOUND if the PPI was not in the database + +**/ +EFI_STATUS +EFIAPI +PeiReInstallPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR *OldPpi, + IN CONST EFI_PEI_PPI_DESCRIPTOR *NewPpi + ) +{ + PEI_CORE_INSTANCE *PrivateData; + UINTN Index; + + + if ((OldPpi == NULL) || (NewPpi == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((NewPpi->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + // + // Find the old PPI instance in the database. If we can not find it, + // return the EFI_NOT_FOUND error. + // + for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) { + if (OldPpi == PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi) { + break; + } + } + if (Index == PrivateData->PpiData.PpiList.CurrentCount) { + return EFI_NOT_FOUND; + } + + // + // Replace the old PPI with the new one. + // + DEBUG((EFI_D_INFO, "Reinstall PPI: %g\n", NewPpi->Guid)); + PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi = (EFI_PEI_PPI_DESCRIPTOR *) NewPpi; + + // + // Process any callback level notifies for the newly installed PPI. + // + ProcessNotify ( + PrivateData, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + Index, + Index+1, + 0, + PrivateData->PpiData.CallbackNotifyList.CurrentCount + ); + + return EFI_SUCCESS; +} + +/** + + Locate a given named PPI. + + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param Guid Pointer to GUID of the PPI. + @param Instance Instance Number to discover. + @param PpiDescriptor Pointer to reference the found descriptor. If not NULL, + returns a pointer to the descriptor (includes flags, etc) + @param Ppi Pointer to reference the found PPI + + @retval EFI_SUCCESS if the PPI is in the database + @retval EFI_NOT_FOUND if the PPI is not in the database + +**/ +EFI_STATUS +EFIAPI +PeiLocatePpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_GUID *Guid, + IN UINTN Instance, + IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor, + IN OUT VOID **Ppi + ) +{ + PEI_CORE_INSTANCE *PrivateData; + UINTN Index; + EFI_GUID *CheckGuid; + EFI_PEI_PPI_DESCRIPTOR *TempPtr; + + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + // + // Search the data base for the matching instance of the GUIDed PPI. + // + for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) { + TempPtr = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi; + CheckGuid = TempPtr->Guid; + + // + // Don't use CompareGuid function here for performance reasons. + // Instead we compare the GUID as INT32 at a time and branch + // on the first failed comparison. + // + if ((((INT32 *)Guid)[0] == ((INT32 *)CheckGuid)[0]) && + (((INT32 *)Guid)[1] == ((INT32 *)CheckGuid)[1]) && + (((INT32 *)Guid)[2] == ((INT32 *)CheckGuid)[2]) && + (((INT32 *)Guid)[3] == ((INT32 *)CheckGuid)[3])) { + if (Instance == 0) { + + if (PpiDescriptor != NULL) { + *PpiDescriptor = TempPtr; + } + + if (Ppi != NULL) { + *Ppi = TempPtr->Ppi; + } + + + return EFI_SUCCESS; + } + Instance--; + } + } + + return EFI_NOT_FOUND; +} + +/** + + This function installs a notification service to be called back when a given + interface is installed or reinstalled. The purpose of the service is to publish + an interface that other parties can use to call additional PPIs that may materialize later. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param NotifyList Pointer to list of Descriptors to notify upon. + @param Single TRUE if only single entry in the NotifyList. + FALSE if the NotifyList is ended with an entry which has the + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST flag set in its Flags field. + + @retval EFI_SUCCESS if successful + @retval EFI_OUT_OF_RESOURCES if no space in the database + @retval EFI_INVALID_PARAMETER if not a good descriptor + +**/ +EFI_STATUS +InternalPeiNotifyPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList, + IN BOOLEAN Single + ) +{ + PEI_CORE_INSTANCE *PrivateData; + PEI_CALLBACK_NOTIFY_LIST *CallbackNotifyListPointer; + UINTN CallbackNotifyIndex; + UINTN LastCallbackNotifyCount; + PEI_DISPATCH_NOTIFY_LIST *DispatchNotifyListPointer; + UINTN DispatchNotifyIndex; + UINTN LastDispatchNotifyCount; + VOID *TempPtr; + + if (NotifyList == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + CallbackNotifyListPointer = &PrivateData->PpiData.CallbackNotifyList; + CallbackNotifyIndex = CallbackNotifyListPointer->CurrentCount; + LastCallbackNotifyCount = CallbackNotifyIndex; + + DispatchNotifyListPointer = &PrivateData->PpiData.DispatchNotifyList; + DispatchNotifyIndex = DispatchNotifyListPointer->CurrentCount; + LastDispatchNotifyCount = DispatchNotifyIndex; + + // + // This is loop installs all Notify descriptors in the NotifyList. It is + // terminated by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last + // EFI_PEI_NOTIFY_DESCRIPTOR in the list. + // + + for (;;) { + // + // If some of the PPI data is invalid restore original Notify PPI database value + // + if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) == 0) { + CallbackNotifyListPointer->CurrentCount = LastCallbackNotifyCount; + DispatchNotifyListPointer->CurrentCount = LastDispatchNotifyCount; + DEBUG((DEBUG_ERROR, "ERROR -> NotifyPpi: %g %p\n", NotifyList->Guid, NotifyList->Notify)); + return EFI_INVALID_PARAMETER; + } + + if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK) != 0) { + if (CallbackNotifyIndex >= CallbackNotifyListPointer->MaxCount) { + // + // Run out of room, grow the buffer. + // + TempPtr = AllocateZeroPool ( + sizeof (PEI_PPI_LIST_POINTERS) * (CallbackNotifyListPointer->MaxCount + CALLBACK_NOTIFY_GROWTH_STEP) + ); + ASSERT (TempPtr != NULL); + CopyMem ( + TempPtr, + CallbackNotifyListPointer->NotifyPtrs, + sizeof (PEI_PPI_LIST_POINTERS) * CallbackNotifyListPointer->MaxCount + ); + CallbackNotifyListPointer->NotifyPtrs = TempPtr; + CallbackNotifyListPointer->MaxCount = CallbackNotifyListPointer->MaxCount + CALLBACK_NOTIFY_GROWTH_STEP; + } + CallbackNotifyListPointer->NotifyPtrs[CallbackNotifyIndex].Notify = (EFI_PEI_NOTIFY_DESCRIPTOR *) NotifyList; + CallbackNotifyIndex++; + CallbackNotifyListPointer->CurrentCount++; + } else { + if (DispatchNotifyIndex >= DispatchNotifyListPointer->MaxCount) { + // + // Run out of room, grow the buffer. + // + TempPtr = AllocateZeroPool ( + sizeof (PEI_PPI_LIST_POINTERS) * (DispatchNotifyListPointer->MaxCount + DISPATCH_NOTIFY_GROWTH_STEP) + ); + ASSERT (TempPtr != NULL); + CopyMem ( + TempPtr, + DispatchNotifyListPointer->NotifyPtrs, + sizeof (PEI_PPI_LIST_POINTERS) * DispatchNotifyListPointer->MaxCount + ); + DispatchNotifyListPointer->NotifyPtrs = TempPtr; + DispatchNotifyListPointer->MaxCount = DispatchNotifyListPointer->MaxCount + DISPATCH_NOTIFY_GROWTH_STEP; + } + DispatchNotifyListPointer->NotifyPtrs[DispatchNotifyIndex].Notify = (EFI_PEI_NOTIFY_DESCRIPTOR *) NotifyList; + DispatchNotifyIndex++; + DispatchNotifyListPointer->CurrentCount++; + } + + DEBUG((EFI_D_INFO, "Register PPI Notify: %g\n", NotifyList->Guid)); + + if (Single) { + // + // Only single entry in the NotifyList. + // + break; + } else if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) { + // + // Continue until the end of the Notify List. + // + break; + } + // + // Go to the next descriptor. + // + NotifyList++; + } + + // + // Process any callback level notifies for all previously installed PPIs. + // + ProcessNotify ( + PrivateData, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + 0, + PrivateData->PpiData.PpiList.CurrentCount, + LastCallbackNotifyCount, + CallbackNotifyListPointer->CurrentCount + ); + + return EFI_SUCCESS; +} + +/** + + This function installs a notification service to be called back when a given + interface is installed or reinstalled. The purpose of the service is to publish + an interface that other parties can use to call additional PPIs that may materialize later. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param NotifyList Pointer to list of Descriptors to notify upon. + + @retval EFI_SUCCESS if successful + @retval EFI_OUT_OF_RESOURCES if no space in the database + @retval EFI_INVALID_PARAMETER if not a good descriptor + +**/ +EFI_STATUS +EFIAPI +PeiNotifyPpi ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList + ) +{ + return InternalPeiNotifyPpi (PeiServices, NotifyList, FALSE); +} + +/** + + Process the Notify List at dispatch level. + + @param PrivateData PeiCore's private data structure. + +**/ +VOID +ProcessDispatchNotifyList ( + IN PEI_CORE_INSTANCE *PrivateData + ) +{ + UINTN TempValue; + + while (TRUE) { + // + // Check if the PEIM that was just dispatched resulted in any + // Notifies getting installed. If so, go process any dispatch + // level Notifies that match the previouly installed PPIs. + // Use "while" instead of "if" since ProcessNotify can modify + // DispatchNotifyList.CurrentCount (with NotifyPpi) so we have + // to iterate until the same. + // + while (PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount != PrivateData->PpiData.DispatchNotifyList.CurrentCount) { + TempValue = PrivateData->PpiData.DispatchNotifyList.CurrentCount; + ProcessNotify ( + PrivateData, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH, + 0, + PrivateData->PpiData.PpiList.LastDispatchedCount, + PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount, + PrivateData->PpiData.DispatchNotifyList.CurrentCount + ); + PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount = TempValue; + } + + // + // Check if the PEIM that was just dispatched resulted in any + // PPIs getting installed. If so, go process any dispatch + // level Notifies that match the installed PPIs. + // Use "while" instead of "if" since ProcessNotify can modify + // PpiList.CurrentCount (with InstallPpi) so we have to iterate + // until the same. + // + while (PrivateData->PpiData.PpiList.LastDispatchedCount != PrivateData->PpiData.PpiList.CurrentCount) { + TempValue = PrivateData->PpiData.PpiList.CurrentCount; + ProcessNotify ( + PrivateData, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH, + PrivateData->PpiData.PpiList.LastDispatchedCount, + PrivateData->PpiData.PpiList.CurrentCount, + 0, + PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount + ); + PrivateData->PpiData.PpiList.LastDispatchedCount = TempValue; + } + + if (PrivateData->PpiData.DispatchNotifyList.LastDispatchedCount == PrivateData->PpiData.DispatchNotifyList.CurrentCount) { + break; + } + } + return; +} + +/** + + Process notifications. + + @param PrivateData PeiCore's private data structure + @param NotifyType Type of notify to fire. + @param InstallStartIndex Install Beginning index. + @param InstallStopIndex Install Ending index. + @param NotifyStartIndex Notify Beginning index. + @param NotifyStopIndex Notify Ending index. + +**/ +VOID +ProcessNotify ( + IN PEI_CORE_INSTANCE *PrivateData, + IN UINTN NotifyType, + IN INTN InstallStartIndex, + IN INTN InstallStopIndex, + IN INTN NotifyStartIndex, + IN INTN NotifyStopIndex + ) +{ + INTN Index1; + INTN Index2; + EFI_GUID *SearchGuid; + EFI_GUID *CheckGuid; + EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor; + + for (Index1 = NotifyStartIndex; Index1 < NotifyStopIndex; Index1++) { + if (NotifyType == EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK) { + NotifyDescriptor = PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index1].Notify; + } else { + NotifyDescriptor = PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index1].Notify; + } + + CheckGuid = NotifyDescriptor->Guid; + + for (Index2 = InstallStartIndex; Index2 < InstallStopIndex; Index2++) { + SearchGuid = PrivateData->PpiData.PpiList.PpiPtrs[Index2].Ppi->Guid; + // + // Don't use CompareGuid function here for performance reasons. + // Instead we compare the GUID as INT32 at a time and branch + // on the first failed comparison. + // + if ((((INT32 *)SearchGuid)[0] == ((INT32 *)CheckGuid)[0]) && + (((INT32 *)SearchGuid)[1] == ((INT32 *)CheckGuid)[1]) && + (((INT32 *)SearchGuid)[2] == ((INT32 *)CheckGuid)[2]) && + (((INT32 *)SearchGuid)[3] == ((INT32 *)CheckGuid)[3])) { + DEBUG ((EFI_D_INFO, "Notify: PPI Guid: %g, Peim notify entry point: %p\n", + SearchGuid, + NotifyDescriptor->Notify + )); + NotifyDescriptor->Notify ( + (EFI_PEI_SERVICES **) GetPeiServicesTablePointer (), + NotifyDescriptor, + (PrivateData->PpiData.PpiList.PpiPtrs[Index2].Ppi)->Ppi + ); + } + } + } +} + diff --git a/HBFA/UefiHostTestPkg/Library/PeimEntryPointHost/PeimEntryPointHost.c b/HBFA/UefiHostTestPkg/Library/PeimEntryPointHost/PeimEntryPointHost.c new file mode 100644 index 0000000..2e35cc6 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/PeimEntryPointHost/PeimEntryPointHost.c @@ -0,0 +1,39 @@ +/** @file + Entry point to a PEIM. + +Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + + +#include +#include + +/** + The entry point of PE/COFF Image for a PEIM. + + This function is the entry point for a PEIM. This function must call ProcessLibraryConstructorList() + and ProcessModuleEntryPointList(). The return value from ProcessModuleEntryPointList() is returned. + If _gPeimRevision is not zero and PeiServices->Hdr.Revision is less than _gPeimRevison, then ASSERT(). + + @param FileHandle Handle of the file being invoked. + @param PeiServices Describes the list of possible PEI Services. + + @retval EFI_SUCCESS The PEIM executed normally. + @retval !EFI_SUCCESS The PEIM failed to execute normally. +**/ +EFI_STATUS +EFIAPI +_ModuleEntryPoint ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + ASSERT(FALSE); + return EFI_UNSUPPORTED; +} + diff --git a/HBFA/UefiHostTestPkg/Library/PeimEntryPointHost/PeimEntryPointHost.inf b/HBFA/UefiHostTestPkg/Library/PeimEntryPointHost/PeimEntryPointHost.inf new file mode 100644 index 0000000..26eab4b --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/PeimEntryPointHost/PeimEntryPointHost.inf @@ -0,0 +1,33 @@ +## @file +# Module entry point library for PEIM. +# +# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PeimEntryPointHost + FILE_GUID = CC3E60E7-92EC-4475-BFE2-A608E1776B73 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = PeimEntryPoint|PEIM + +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC (EBC is for build only) +# + +[Sources] + PeimEntryPointHost.c + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + DebugLib + diff --git a/HBFA/UefiHostTestPkg/Library/SmmMemLibHost/SmmMemLibHost.c b/HBFA/UefiHostTestPkg/Library/SmmMemLibHost/SmmMemLibHost.c new file mode 100644 index 0000000..70a3fb7 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/SmmMemLibHost/SmmMemLibHost.c @@ -0,0 +1,218 @@ +/** @file + Instance of SMM memory check library. + + SMM memory check library library implementation. This library consumes SMM_ACCESS2_PROTOCOL + to get SMRAM information. In order to use this library instance, the platform should produce + all SMRAM range via SMM_ACCESS2_PROTOCOL, including the range for firmware (like SMM Core + and SMM driver) and/or specific dedicated hardware. + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include + +#include +#include +#include + +typedef struct { + EFI_PHYSICAL_ADDRESS Address; + UINT64 Size; +} SMM_COMMUNICATION_BUFFER_DESCRIPTOR; + +UINTN mSmmCommBufferDescCount; +SMM_COMMUNICATION_BUFFER_DESCRIPTOR *mSmmCommBufferDesc; + +/** + This function check if the buffer is valid per processor architecture and not overlap with SMRAM. + + @param Buffer The buffer start address to be checked. + @param Length The buffer length to be checked. + + @retval TRUE This buffer is valid per processor architecture and not overlap with SMRAM. + @retval FALSE This buffer is not valid per processor architecture or overlap with SMRAM. +**/ +BOOLEAN +EFIAPI +SmmIsBufferOutsideSmmValid ( + IN EFI_PHYSICAL_ADDRESS Buffer, + IN UINT64 Length + ) +{ + UINTN Index; + SMM_COMMUNICATION_BUFFER_DESCRIPTOR *SmmCommBufferDesc; + BOOLEAN InValidCommunicationRegion; + + InValidCommunicationRegion = FALSE; + SmmCommBufferDesc = mSmmCommBufferDesc; + for (Index = 0; Index < mSmmCommBufferDescCount; Index++) { + if ((Buffer >= SmmCommBufferDesc->Address) && + (Buffer + Length <= SmmCommBufferDesc->Address + SmmCommBufferDesc->Size)) { + InValidCommunicationRegion = TRUE; + } + SmmCommBufferDesc++; + } + + if (!InValidCommunicationRegion) { + DEBUG (( + EFI_D_ERROR, + "SmmIsBufferOutsideSmmValid: Not in ValidCommunicationRegion: Buffer (0x%lx) - Length (0x%lx)\n", + Buffer, + Length + )); + return FALSE; + } + + return TRUE; +} + +/** + Copies a source buffer (non-SMRAM) to a destination buffer (SMRAM). + + This function copies a source buffer (non-SMRAM) to a destination buffer (SMRAM). + It checks if source buffer is valid per processor architecture and not overlap with SMRAM. + If the check passes, it copies memory and returns EFI_SUCCESS. + If the check fails, it return EFI_SECURITY_VIOLATION. + The implementation must be reentrant. + + @param DestinationBuffer The pointer to the destination buffer of the memory copy. + @param SourceBuffer The pointer to the source buffer of the memory copy. + @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer. + + @retval EFI_SECURITY_VIOLATION The SourceBuffer is invalid per processor architecture or overlap with SMRAM. + @retval EFI_SUCCESS Memory is copied. + +**/ +EFI_STATUS +EFIAPI +SmmCopyMemToSmram ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)SourceBuffer, Length)) { + DEBUG ((EFI_D_ERROR, "SmmCopyMemToSmram: Security Violation: Source (0x%x), Length (0x%x)\n", SourceBuffer, Length)); + return EFI_SECURITY_VIOLATION; + } + CopyMem (DestinationBuffer, SourceBuffer, Length); + return EFI_SUCCESS; +} + +/** + Copies a source buffer (SMRAM) to a destination buffer (NON-SMRAM). + + This function copies a source buffer (non-SMRAM) to a destination buffer (SMRAM). + It checks if destination buffer is valid per processor architecture and not overlap with SMRAM. + If the check passes, it copies memory and returns EFI_SUCCESS. + If the check fails, it returns EFI_SECURITY_VIOLATION. + The implementation must be reentrant. + + @param DestinationBuffer The pointer to the destination buffer of the memory copy. + @param SourceBuffer The pointer to the source buffer of the memory copy. + @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer. + + @retval EFI_SECURITY_VIOLATION The DesinationBuffer is invalid per processor architecture or overlap with SMRAM. + @retval EFI_SUCCESS Memory is copied. + +**/ +EFI_STATUS +EFIAPI +SmmCopyMemFromSmram ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)DestinationBuffer, Length)) { + DEBUG ((EFI_D_ERROR, "SmmCopyMemFromSmram: Security Violation: Destination (0x%x), Length (0x%x)\n", DestinationBuffer, Length)); + return EFI_SECURITY_VIOLATION; + } + CopyMem (DestinationBuffer, SourceBuffer, Length); + return EFI_SUCCESS; +} + +/** + Copies a source buffer (NON-SMRAM) to a destination buffer (NON-SMRAM). + + This function copies a source buffer (non-SMRAM) to a destination buffer (SMRAM). + It checks if source buffer and destination buffer are valid per processor architecture and not overlap with SMRAM. + If the check passes, it copies memory and returns EFI_SUCCESS. + If the check fails, it returns EFI_SECURITY_VIOLATION. + The implementation must be reentrant, and it must handle the case where source buffer overlaps destination buffer. + + @param DestinationBuffer The pointer to the destination buffer of the memory copy. + @param SourceBuffer The pointer to the source buffer of the memory copy. + @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer. + + @retval EFI_SECURITY_VIOLATION The DesinationBuffer is invalid per processor architecture or overlap with SMRAM. + @retval EFI_SECURITY_VIOLATION The SourceBuffer is invalid per processor architecture or overlap with SMRAM. + @retval EFI_SUCCESS Memory is copied. + +**/ +EFI_STATUS +EFIAPI +SmmCopyMem ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)DestinationBuffer, Length)) { + DEBUG ((EFI_D_ERROR, "SmmCopyMem: Security Violation: Destination (0x%x), Length (0x%x)\n", DestinationBuffer, Length)); + return EFI_SECURITY_VIOLATION; + } + if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)SourceBuffer, Length)) { + DEBUG ((EFI_D_ERROR, "SmmCopyMem: Security Violation: Source (0x%x), Length (0x%x)\n", SourceBuffer, Length)); + return EFI_SECURITY_VIOLATION; + } + CopyMem (DestinationBuffer, SourceBuffer, Length); + return EFI_SUCCESS; +} + +/** + Fills a target buffer (NON-SMRAM) with a byte value. + + This function fills a target buffer (non-SMRAM) with a byte value. + It checks if target buffer is valid per processor architecture and not overlap with SMRAM. + If the check passes, it fills memory and returns EFI_SUCCESS. + If the check fails, it returns EFI_SECURITY_VIOLATION. + + @param Buffer The memory to set. + @param Length The number of bytes to set. + @param Value The value with which to fill Length bytes of Buffer. + + @retval EFI_SECURITY_VIOLATION The Buffer is invalid per processor architecture or overlap with SMRAM. + @retval EFI_SUCCESS Memory is set. + +**/ +EFI_STATUS +EFIAPI +SmmSetMem ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, Length)) { + DEBUG ((EFI_D_ERROR, "SmmSetMem: Security Violation: Source (0x%x), Length (0x%x)\n", Buffer, Length)); + return EFI_SECURITY_VIOLATION; + } + SetMem (Buffer, Length, Value); + return EFI_SUCCESS; +} + +VOID +EFIAPI +SmmMemLibInitialize ( + IN UINTN SmmCommBufferDescCount, + IN SMM_COMMUNICATION_BUFFER_DESCRIPTOR *SmmCommBufferDesc + ) +{ + mSmmCommBufferDescCount = SmmCommBufferDescCount; + mSmmCommBufferDesc = SmmCommBufferDesc; +} + diff --git a/HBFA/UefiHostTestPkg/Library/SmmMemLibHost/SmmMemLibHost.inf b/HBFA/UefiHostTestPkg/Library/SmmMemLibHost/SmmMemLibHost.inf new file mode 100644 index 0000000..5383813 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/SmmMemLibHost/SmmMemLibHost.inf @@ -0,0 +1,33 @@ +## @file +# Instance of SMM memory check library. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmmMemLibHost + FILE_GUID = 7F23F839-C81C-4B89-8132-69746FCBCE52 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = SmmMemLib + LIBRARY_CLASS = SmmMemLibStubLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + SmmMemLibHost.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + diff --git a/HBFA/UefiHostTestPkg/Library/SmmServicesTableLibHost/Handle.c b/HBFA/UefiHostTestPkg/Library/SmmServicesTableLibHost/Handle.c new file mode 100644 index 0000000..a8e1564 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/SmmServicesTableLibHost/Handle.c @@ -0,0 +1,528 @@ +/** @file + SMM handle & protocol handling. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PiSmmCore.h" + +// +// mSmmProtocolDatabase - A list of all protocols in the system. (simple list for now) +// gSmmHandleList - A list of all the handles in the system +// +LIST_ENTRY mSmmProtocolDatabase = INITIALIZE_LIST_HEAD_VARIABLE (mSmmProtocolDatabase); +LIST_ENTRY gSmmHandleList = INITIALIZE_LIST_HEAD_VARIABLE (gSmmHandleList); + +/** + Check whether a handle is a valid EFI_HANDLE + + @param UserHandle The handle to check + + @retval EFI_INVALID_PARAMETER The handle is NULL or not a valid EFI_HANDLE. + @retval EFI_SUCCESS The handle is valid EFI_HANDLE. + +**/ +EFI_STATUS +SmmValidateHandle ( + IN EFI_HANDLE UserHandle + ) +{ + IHANDLE *Handle; + + Handle = (IHANDLE *)UserHandle; + if (Handle == NULL) { + return EFI_INVALID_PARAMETER; + } + if (Handle->Signature != EFI_HANDLE_SIGNATURE) { + return EFI_INVALID_PARAMETER; + } + return EFI_SUCCESS; +} + +/** + Finds the protocol entry for the requested protocol. + + @param Protocol The ID of the protocol + @param Create Create a new entry if not found + + @return Protocol entry + +**/ +PROTOCOL_ENTRY * +SmmFindProtocolEntry ( + IN EFI_GUID *Protocol, + IN BOOLEAN Create + ) +{ + LIST_ENTRY *Link; + PROTOCOL_ENTRY *Item; + PROTOCOL_ENTRY *ProtEntry; + + // + // Search the database for the matching GUID + // + + ProtEntry = NULL; + for (Link = mSmmProtocolDatabase.ForwardLink; + Link != &mSmmProtocolDatabase; + Link = Link->ForwardLink) { + + Item = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE); + if (CompareGuid (&Item->ProtocolID, Protocol)) { + // + // This is the protocol entry + // + ProtEntry = Item; + break; + } + } + + // + // If the protocol entry was not found and Create is TRUE, then + // allocate a new entry + // + if ((ProtEntry == NULL) && Create) { + ProtEntry = AllocatePool (sizeof(PROTOCOL_ENTRY)); + if (ProtEntry != NULL) { + // + // Initialize new protocol entry structure + // + ProtEntry->Signature = PROTOCOL_ENTRY_SIGNATURE; + CopyGuid ((VOID *)&ProtEntry->ProtocolID, Protocol); + InitializeListHead (&ProtEntry->Protocols); + InitializeListHead (&ProtEntry->Notify); + + // + // Add it to protocol database + // + InsertTailList (&mSmmProtocolDatabase, &ProtEntry->AllEntries); + } + } + return ProtEntry; +} + +/** + Finds the protocol instance for the requested handle and protocol. + Note: This function doesn't do parameters checking, it's caller's responsibility + to pass in valid parameters. + + @param Handle The handle to search the protocol on + @param Protocol GUID of the protocol + @param Interface The interface for the protocol being searched + + @return Protocol instance (NULL: Not found) + +**/ +PROTOCOL_INTERFACE * +SmmFindProtocolInterface ( + IN IHANDLE *Handle, + IN EFI_GUID *Protocol, + IN VOID *Interface + ) +{ + PROTOCOL_INTERFACE *Prot; + PROTOCOL_ENTRY *ProtEntry; + LIST_ENTRY *Link; + + Prot = NULL; + + // + // Lookup the protocol entry for this protocol ID + // + ProtEntry = SmmFindProtocolEntry (Protocol, FALSE); + if (ProtEntry != NULL) { + // + // Look at each protocol interface for any matches + // + for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link=Link->ForwardLink) { + // + // If this protocol interface matches, remove it + // + Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE); + if (Prot->Interface == Interface && Prot->Protocol == ProtEntry) { + break; + } + Prot = NULL; + } + } + return Prot; +} + +/** + Wrapper function to SmmInstallProtocolInterfaceNotify. This is the public API which + Calls the private one which contains a BOOLEAN parameter for notifications + + @param UserHandle The handle to install the protocol handler on, + or NULL if a new handle is to be allocated + @param Protocol The protocol to add to the handle + @param InterfaceType Indicates whether Interface is supplied in + native form. + @param Interface The interface for the protocol being added + + @return Status code + +**/ +EFI_STATUS +EFIAPI +SmmInstallProtocolInterface ( + IN OUT EFI_HANDLE *UserHandle, + IN EFI_GUID *Protocol, + IN EFI_INTERFACE_TYPE InterfaceType, + IN VOID *Interface + ) +{ + return SmmInstallProtocolInterfaceNotify ( + UserHandle, + Protocol, + InterfaceType, + Interface, + TRUE + ); +} + +/** + Installs a protocol interface into the boot services environment. + + @param UserHandle The handle to install the protocol handler on, + or NULL if a new handle is to be allocated + @param Protocol The protocol to add to the handle + @param InterfaceType Indicates whether Interface is supplied in + native form. + @param Interface The interface for the protocol being added + @param Notify indicates whether notify the notification list + for this protocol + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate + @retval EFI_SUCCESS Protocol interface successfully installed + +**/ +EFI_STATUS +SmmInstallProtocolInterfaceNotify ( + IN OUT EFI_HANDLE *UserHandle, + IN EFI_GUID *Protocol, + IN EFI_INTERFACE_TYPE InterfaceType, + IN VOID *Interface, + IN BOOLEAN Notify + ) +{ + PROTOCOL_INTERFACE *Prot; + PROTOCOL_ENTRY *ProtEntry; + IHANDLE *Handle; + EFI_STATUS Status; + VOID *ExistingInterface; + + // + // returns EFI_INVALID_PARAMETER if InterfaceType is invalid. + // Also added check for invalid UserHandle and Protocol pointers. + // + if (UserHandle == NULL || Protocol == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (InterfaceType != EFI_NATIVE_INTERFACE) { + return EFI_INVALID_PARAMETER; + } + + // + // Print debug message + // + DEBUG((DEBUG_LOAD | DEBUG_INFO, "SmmInstallProtocolInterface: %g %p\n", Protocol, Interface)); + + Status = EFI_OUT_OF_RESOURCES; + Prot = NULL; + Handle = NULL; + + if (*UserHandle != NULL) { + Status = SmmHandleProtocol (*UserHandle, Protocol, (VOID **)&ExistingInterface); + if (!EFI_ERROR (Status)) { + return EFI_INVALID_PARAMETER; + } + } + + // + // Lookup the Protocol Entry for the requested protocol + // + ProtEntry = SmmFindProtocolEntry (Protocol, TRUE); + if (ProtEntry == NULL) { + goto Done; + } + + // + // Allocate a new protocol interface structure + // + Prot = AllocateZeroPool (sizeof(PROTOCOL_INTERFACE)); + if (Prot == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + // + // If caller didn't supply a handle, allocate a new one + // + Handle = (IHANDLE *)*UserHandle; + if (Handle == NULL) { + Handle = AllocateZeroPool (sizeof(IHANDLE)); + if (Handle == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + // + // Initialize new handler structure + // + Handle->Signature = EFI_HANDLE_SIGNATURE; + InitializeListHead (&Handle->Protocols); + + // + // Add this handle to the list global list of all handles + // in the system + // + InsertTailList (&gSmmHandleList, &Handle->AllHandles); + } else { + Status = SmmValidateHandle (Handle); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "SmmInstallProtocolInterface: input handle at 0x%x is invalid\n", Handle)); + goto Done; + } + } + + // + // Each interface that is added must be unique + // + ASSERT (SmmFindProtocolInterface (Handle, Protocol, Interface) == NULL); + + // + // Initialize the protocol interface structure + // + Prot->Signature = PROTOCOL_INTERFACE_SIGNATURE; + Prot->Handle = Handle; + Prot->Protocol = ProtEntry; + Prot->Interface = Interface; + + // + // Add this protocol interface to the head of the supported + // protocol list for this handle + // + InsertHeadList (&Handle->Protocols, &Prot->Link); + + // + // Add this protocol interface to the tail of the + // protocol entry + // + InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol); + + // + // Notify the notification list for this protocol + // + if (Notify) { + SmmNotifyProtocol (Prot); + } + Status = EFI_SUCCESS; + +Done: + if (!EFI_ERROR (Status)) { + // + // Return the new handle back to the caller + // + *UserHandle = Handle; + } else { + // + // There was an error, clean up + // + if (Prot != NULL) { + FreePool (Prot); + } + DEBUG((DEBUG_ERROR, "SmmInstallProtocolInterface: %g %p failed with %r\n", Protocol, Interface, Status)); + } + return Status; +} + +/** + Uninstalls all instances of a protocol:interfacer from a handle. + If the last protocol interface is remove from the handle, the + handle is freed. + + @param UserHandle The handle to remove the protocol handler from + @param Protocol The protocol, of protocol:interface, to remove + @param Interface The interface, of protocol:interface, to remove + + @retval EFI_INVALID_PARAMETER Protocol is NULL. + @retval EFI_SUCCESS Protocol interface successfully uninstalled. + +**/ +EFI_STATUS +EFIAPI +SmmUninstallProtocolInterface ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + IN VOID *Interface + ) +{ + EFI_STATUS Status; + IHANDLE *Handle; + PROTOCOL_INTERFACE *Prot; + + // + // Check that Protocol is valid + // + if (Protocol == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check that UserHandle is a valid handle + // + Status = SmmValidateHandle (UserHandle); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Check that Protocol exists on UserHandle, and Interface matches the interface in the database + // + Prot = SmmFindProtocolInterface (UserHandle, Protocol, Interface); + if (Prot == NULL) { + return EFI_NOT_FOUND; + } + + // + // Remove the protocol interface from the protocol + // + Status = EFI_NOT_FOUND; + Handle = (IHANDLE *)UserHandle; + Prot = SmmRemoveInterfaceFromProtocol (Handle, Protocol, Interface); + + if (Prot != NULL) { + // + // Remove the protocol interface from the handle + // + RemoveEntryList (&Prot->Link); + + // + // Free the memory + // + Prot->Signature = 0; + FreePool (Prot); + Status = EFI_SUCCESS; + } + + // + // If there are no more handlers for the handle, free the handle + // + if (IsListEmpty (&Handle->Protocols)) { + Handle->Signature = 0; + RemoveEntryList (&Handle->AllHandles); + FreePool (Handle); + } + return Status; +} + +/** + Locate a certain GUID protocol interface in a Handle's protocols. + + @param UserHandle The handle to obtain the protocol interface on + @param Protocol The GUID of the protocol + + @return The requested protocol interface for the handle + +**/ +PROTOCOL_INTERFACE * +SmmGetProtocolInterface ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol + ) +{ + EFI_STATUS Status; + PROTOCOL_ENTRY *ProtEntry; + PROTOCOL_INTERFACE *Prot; + IHANDLE *Handle; + LIST_ENTRY *Link; + + Status = SmmValidateHandle (UserHandle); + if (EFI_ERROR (Status)) { + return NULL; + } + + Handle = (IHANDLE *)UserHandle; + + // + // Look at each protocol interface for a match + // + for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) { + Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE); + ProtEntry = Prot->Protocol; + if (CompareGuid (&ProtEntry->ProtocolID, Protocol)) { + return Prot; + } + } + return NULL; +} + +/** + Queries a handle to determine if it supports a specified protocol. + + @param UserHandle The handle being queried. + @param Protocol The published unique identifier of the protocol. + @param Interface Supplies the address where a pointer to the + corresponding Protocol Interface is returned. + + @retval EFI_SUCCESS The interface information for the specified protocol was returned. + @retval EFI_UNSUPPORTED The device does not support the specified protocol. + @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE.. + @retval EFI_INVALID_PARAMETER Protocol is NULL. + @retval EFI_INVALID_PARAMETER Interface is NULL. + +**/ +EFI_STATUS +EFIAPI +SmmHandleProtocol ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + OUT VOID **Interface + ) +{ + EFI_STATUS Status; + PROTOCOL_INTERFACE *Prot; + + // + // Check for invalid Protocol + // + if (Protocol == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check for invalid Interface + // + if (Interface == NULL) { + return EFI_INVALID_PARAMETER; + } else { + *Interface = NULL; + } + + // + // Check for invalid UserHandle + // + Status = SmmValidateHandle (UserHandle); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Look at each protocol interface for a match + // + Prot = SmmGetProtocolInterface (UserHandle, Protocol); + if (Prot == NULL) { + return EFI_UNSUPPORTED; + } + + // + // This is the protocol interface entry for this protocol + // + *Interface = Prot->Interface; + + return EFI_SUCCESS; +} diff --git a/HBFA/UefiHostTestPkg/Library/SmmServicesTableLibHost/InstallConfigurationTable.c b/HBFA/UefiHostTestPkg/Library/SmmServicesTableLibHost/InstallConfigurationTable.c new file mode 100644 index 0000000..57f31fa --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/SmmServicesTableLibHost/InstallConfigurationTable.c @@ -0,0 +1,171 @@ +/** @file + System Management System Table Services SmmInstallConfigurationTable service + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PiSmmCore.h" + +#define CONFIG_TABLE_SIZE_INCREASED 0x10 + +UINTN mSmmSystemTableAllocateSize = 0; + +/** + The SmmInstallConfigurationTable() function is used to maintain the list + of configuration tables that are stored in the System Management System + Table. The list is stored as an array of (GUID, Pointer) pairs. The list + must be allocated from pool memory with PoolType set to EfiRuntimeServicesData. + + @param SystemTable A pointer to the SMM System Table (SMST). + @param Guid A pointer to the GUID for the entry to add, update, or remove. + @param Table A pointer to the buffer of the table to add. + @param TableSize The size of the table to install. + + @retval EFI_SUCCESS The (Guid, Table) pair was added, updated, or removed. + @retval EFI_INVALID_PARAMETER Guid is not valid. + @retval EFI_NOT_FOUND An attempt was made to delete a non-existent entry. + @retval EFI_OUT_OF_RESOURCES There is not enough memory available to complete the operation. + +**/ +EFI_STATUS +EFIAPI +SmmInstallConfigurationTable ( + IN CONST EFI_SMM_SYSTEM_TABLE2 *SystemTable, + IN CONST EFI_GUID *Guid, + IN VOID *Table, + IN UINTN TableSize + ) +{ + UINTN Index; + EFI_CONFIGURATION_TABLE *ConfigurationTable; + EFI_CONFIGURATION_TABLE *OldTable; + + // + // If Guid is NULL, then this operation cannot be performed + // + if (Guid == NULL) { + return EFI_INVALID_PARAMETER; + } + + ConfigurationTable = gSmmCoreSmst.SmmConfigurationTable; + + // + // Search all the table for an entry that matches Guid + // + for (Index = 0; Index < gSmmCoreSmst.NumberOfTableEntries; Index++) { + if (CompareGuid (Guid, &(ConfigurationTable[Index].VendorGuid))) { + break; + } + } + + if (Index < gSmmCoreSmst.NumberOfTableEntries) { + // + // A match was found, so this is either a modify or a delete operation + // + if (Table != NULL) { + // + // If Table is not NULL, then this is a modify operation. + // Modify the table entry and return. + // + ConfigurationTable[Index].VendorTable = Table; + return EFI_SUCCESS; + } + + // + // A match was found and Table is NULL, so this is a delete operation. + // + gSmmCoreSmst.NumberOfTableEntries--; + + // + // Copy over deleted entry + // + CopyMem ( + &(ConfigurationTable[Index]), + &(ConfigurationTable[Index + 1]), + (gSmmCoreSmst.NumberOfTableEntries - Index) * sizeof (EFI_CONFIGURATION_TABLE) + ); + + } else { + // + // No matching GUIDs were found, so this is an add operation. + // + if (Table == NULL) { + // + // If Table is NULL on an add operation, then return an error. + // + return EFI_NOT_FOUND; + } + + // + // Assume that Index == gSmmCoreSmst.NumberOfTableEntries + // + if ((Index * sizeof (EFI_CONFIGURATION_TABLE)) >= mSmmSystemTableAllocateSize) { + // + // Allocate a table with one additional entry. + // + mSmmSystemTableAllocateSize += (CONFIG_TABLE_SIZE_INCREASED * sizeof (EFI_CONFIGURATION_TABLE)); + ConfigurationTable = AllocatePool (mSmmSystemTableAllocateSize); + if (ConfigurationTable == NULL) { + // + // If a new table could not be allocated, then return an error. + // + return EFI_OUT_OF_RESOURCES; + } + + if (gSmmCoreSmst.SmmConfigurationTable != NULL) { + // + // Copy the old table to the new table. + // + CopyMem ( + ConfigurationTable, + gSmmCoreSmst.SmmConfigurationTable, + Index * sizeof (EFI_CONFIGURATION_TABLE) + ); + + // + // Record the old table pointer. + // + OldTable = gSmmCoreSmst.SmmConfigurationTable; + + // + // As the SmmInstallConfigurationTable() may be re-entered by FreePool() in + // its calling stack, updating System table to the new table pointer must + // be done before calling FreePool() to free the old table. + // It can make sure the gSmmCoreSmst.SmmConfigurationTable point to the new + // table and avoid the errors of use-after-free to the old table by the + // reenter of SmmInstallConfigurationTable() in FreePool()'s calling stack. + // + gSmmCoreSmst.SmmConfigurationTable = ConfigurationTable; + + // + // Free the old table after updating System Table to the new table pointer. + // + FreePool (OldTable); + } else { + // + // Update System Table + // + gSmmCoreSmst.SmmConfigurationTable = ConfigurationTable; + } + } + + // + // Fill in the new entry + // + CopyGuid ((VOID *)&ConfigurationTable[Index].VendorGuid, Guid); + ConfigurationTable[Index].VendorTable = Table; + + // + // This is an add operation, so increment the number of table entries + // + gSmmCoreSmst.NumberOfTableEntries++; + } + + // + // CRC-32 field is ignorable for SMM System Table and should be set to zero + // + + return EFI_SUCCESS; +} diff --git a/HBFA/UefiHostTestPkg/Library/SmmServicesTableLibHost/Locate.c b/HBFA/UefiHostTestPkg/Library/SmmServicesTableLibHost/Locate.c new file mode 100644 index 0000000..fe2b9c9 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/SmmServicesTableLibHost/Locate.c @@ -0,0 +1,489 @@ +/** @file + Locate handle functions + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PiSmmCore.h" + +// +// ProtocolRequest - Last LocateHandle request ID +// +UINTN mSmmLocateHandleRequest = 0; + +// +// Internal prototypes +// + +typedef struct { + EFI_GUID *Protocol; + VOID *SearchKey; + LIST_ENTRY *Position; + PROTOCOL_ENTRY *ProtEntry; +} LOCATE_POSITION; + +typedef +IHANDLE * +(* CORE_GET_NEXT) ( + IN OUT LOCATE_POSITION *Position, + OUT VOID **Interface + ); + +/** + Routine to get the next Handle, when you are searching for all handles. + + @param Position Information about which Handle to seach for. + @param Interface Return the interface structure for the matching + protocol. + + @return An pointer to IHANDLE if the next Position is not the end of the list. + Otherwise,NULL is returned. + +**/ +IHANDLE * +SmmGetNextLocateAllHandles ( + IN OUT LOCATE_POSITION *Position, + OUT VOID **Interface + ) +{ + IHANDLE *Handle; + + // + // Next handle + // + Position->Position = Position->Position->ForwardLink; + + // + // If not at the end of the list, get the handle + // + Handle = NULL; + *Interface = NULL; + if (Position->Position != &gSmmHandleList) { + Handle = CR (Position->Position, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE); + } + return Handle; +} + +/** + Routine to get the next Handle, when you are searching for register protocol + notifies. + + @param Position Information about which Handle to seach for. + @param Interface Return the interface structure for the matching + protocol. + + @return An pointer to IHANDLE if the next Position is not the end of the list. + Otherwise,NULL is returned. + +**/ +IHANDLE * +SmmGetNextLocateByRegisterNotify ( + IN OUT LOCATE_POSITION *Position, + OUT VOID **Interface + ) +{ + IHANDLE *Handle; + PROTOCOL_NOTIFY *ProtNotify; + PROTOCOL_INTERFACE *Prot; + LIST_ENTRY *Link; + + Handle = NULL; + *Interface = NULL; + ProtNotify = Position->SearchKey; + + // + // If this is the first request, get the next handle + // + if (ProtNotify != NULL) { + ASSERT(ProtNotify->Signature == PROTOCOL_NOTIFY_SIGNATURE); + Position->SearchKey = NULL; + + // + // If not at the end of the list, get the next handle + // + Link = ProtNotify->Position->ForwardLink; + if (Link != &ProtNotify->Protocol->Protocols) { + Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE); + Handle = Prot->Handle; + *Interface = Prot->Interface; + } + } + return Handle; +} + +/** + Routine to get the next Handle, when you are searching for a given protocol. + + @param Position Information about which Handle to seach for. + @param Interface Return the interface structure for the matching + protocol. + + @return An pointer to IHANDLE if the next Position is not the end of the list. + Otherwise,NULL is returned. + +**/ +IHANDLE * +SmmGetNextLocateByProtocol ( + IN OUT LOCATE_POSITION *Position, + OUT VOID **Interface + ) +{ + IHANDLE *Handle; + LIST_ENTRY *Link; + PROTOCOL_INTERFACE *Prot; + + Handle = NULL; + *Interface = NULL; + for (; ;) { + // + // Next entry + // + Link = Position->Position->ForwardLink; + Position->Position = Link; + + // + // If not at the end, return the handle + // + if (Link == &Position->ProtEntry->Protocols) { + Handle = NULL; + break; + } + + // + // Get the handle + // + Prot = CR(Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE); + Handle = Prot->Handle; + *Interface = Prot->Interface; + + // + // If this handle has not been returned this request, then + // return it now + // + if (Handle->LocateRequest != mSmmLocateHandleRequest) { + Handle->LocateRequest = mSmmLocateHandleRequest; + break; + } + } + return Handle; +} + +/** + Return the first Protocol Interface that matches the Protocol GUID. If + Registration is pasased in return a Protocol Instance that was just add + to the system. If Retistration is NULL return the first Protocol Interface + you find. + + @param Protocol The protocol to search for + @param Registration Optional Registration Key returned from + RegisterProtocolNotify() + @param Interface Return the Protocol interface (instance). + + @retval EFI_SUCCESS If a valid Interface is returned + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_NOT_FOUND Protocol interface not found + +**/ +EFI_STATUS +EFIAPI +SmmLocateProtocol ( + IN EFI_GUID *Protocol, + IN VOID *Registration OPTIONAL, + OUT VOID **Interface + ) +{ + EFI_STATUS Status; + LOCATE_POSITION Position; + PROTOCOL_NOTIFY *ProtNotify; + IHANDLE *Handle; + + if ((Interface == NULL) || (Protocol == NULL)) { + return EFI_INVALID_PARAMETER; + } + + *Interface = NULL; + Status = EFI_SUCCESS; + + // + // Set initial position + // + Position.Protocol = Protocol; + Position.SearchKey = Registration; + Position.Position = &gSmmHandleList; + + mSmmLocateHandleRequest += 1; + + if (Registration == NULL) { + // + // Look up the protocol entry and set the head pointer + // + Position.ProtEntry = SmmFindProtocolEntry (Protocol, FALSE); + if (Position.ProtEntry == NULL) { + return EFI_NOT_FOUND; + } + Position.Position = &Position.ProtEntry->Protocols; + + Handle = SmmGetNextLocateByProtocol (&Position, Interface); + } else { + Handle = SmmGetNextLocateByRegisterNotify (&Position, Interface); + } + + if (Handle == NULL) { + Status = EFI_NOT_FOUND; + } else if (Registration != NULL) { + // + // If this is a search by register notify and a handle was + // returned, update the register notification position + // + ProtNotify = Registration; + ProtNotify->Position = ProtNotify->Position->ForwardLink; + } + + return Status; +} + +/** + Locates the requested handle(s) and returns them in Buffer. + + @param SearchType The type of search to perform to locate the + handles + @param Protocol The protocol to search for + @param SearchKey Dependant on SearchType + @param BufferSize On input the size of Buffer. On output the + size of data returned. + @param Buffer The buffer to return the results in + + @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is + returned in BufferSize. + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_SUCCESS Successfully found the requested handle(s) and + returns them in Buffer. + +**/ +EFI_STATUS +EFIAPI +SmmLocateHandle ( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol OPTIONAL, + IN VOID *SearchKey OPTIONAL, + IN OUT UINTN *BufferSize, + OUT EFI_HANDLE *Buffer + ) +{ + EFI_STATUS Status; + LOCATE_POSITION Position; + PROTOCOL_NOTIFY *ProtNotify; + CORE_GET_NEXT GetNext; + UINTN ResultSize; + IHANDLE *Handle; + IHANDLE **ResultBuffer; + VOID *Interface; + + if (BufferSize == NULL) { + return EFI_INVALID_PARAMETER; + } + + if ((*BufferSize > 0) && (Buffer == NULL)) { + return EFI_INVALID_PARAMETER; + } + + GetNext = NULL; + + // + // Set initial position + // + Position.Protocol = Protocol; + Position.SearchKey = SearchKey; + Position.Position = &gSmmHandleList; + + ResultSize = 0; + ResultBuffer = (IHANDLE **) Buffer; + Status = EFI_SUCCESS; + + // + // Get the search function based on type + // + switch (SearchType) { + case AllHandles: + GetNext = SmmGetNextLocateAllHandles; + break; + + case ByRegisterNotify: + GetNext = SmmGetNextLocateByRegisterNotify; + // + // Must have SearchKey for locate ByRegisterNotify + // + if (SearchKey == NULL) { + Status = EFI_INVALID_PARAMETER; + } + break; + + case ByProtocol: + GetNext = SmmGetNextLocateByProtocol; + if (Protocol == NULL) { + Status = EFI_INVALID_PARAMETER; + break; + } + // + // Look up the protocol entry and set the head pointer + // + Position.ProtEntry = SmmFindProtocolEntry (Protocol, FALSE); + if (Position.ProtEntry == NULL) { + Status = EFI_NOT_FOUND; + break; + } + Position.Position = &Position.ProtEntry->Protocols; + break; + + default: + Status = EFI_INVALID_PARAMETER; + break; + } + + if (EFI_ERROR(Status)) { + return Status; + } + + // + // Enumerate out the matching handles + // + mSmmLocateHandleRequest += 1; + for (; ;) { + // + // Get the next handle. If no more handles, stop + // + Handle = GetNext (&Position, &Interface); + if (NULL == Handle) { + break; + } + + // + // Increase the resulting buffer size, and if this handle + // fits return it + // + ResultSize += sizeof(Handle); + if (ResultSize <= *BufferSize) { + *ResultBuffer = Handle; + ResultBuffer += 1; + } + } + + // + // If the result is a zero length buffer, then there were no + // matching handles + // + if (ResultSize == 0) { + Status = EFI_NOT_FOUND; + } else { + // + // Return the resulting buffer size. If it's larger than what + // was passed, then set the error code + // + if (ResultSize > *BufferSize) { + Status = EFI_BUFFER_TOO_SMALL; + } + + *BufferSize = ResultSize; + + if (SearchType == ByRegisterNotify && !EFI_ERROR(Status)) { + ASSERT (SearchKey != NULL); + // + // If this is a search by register notify and a handle was + // returned, update the register notification position + // + ProtNotify = SearchKey; + ProtNotify->Position = ProtNotify->Position->ForwardLink; + } + } + + return Status; +} + +/** + Function returns an array of handles that support the requested protocol + in a buffer allocated from pool. This is a version of SmmLocateHandle() + that allocates a buffer for the caller. + + @param SearchType Specifies which handle(s) are to be returned. + @param Protocol Provides the protocol to search by. This + parameter is only valid for SearchType + ByProtocol. + @param SearchKey Supplies the search key depending on the + SearchType. + @param NumberHandles The number of handles returned in Buffer. + @param Buffer A pointer to the buffer to return the requested + array of handles that support Protocol. + + @retval EFI_SUCCESS The result array of handles was returned. + @retval EFI_NOT_FOUND No handles match the search. + @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the + matching results. + @retval EFI_INVALID_PARAMETER One or more parameters are not valid. + +**/ +EFI_STATUS +EFIAPI +SmmLocateHandleBuffer ( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol OPTIONAL, + IN VOID *SearchKey OPTIONAL, + IN OUT UINTN *NumberHandles, + OUT EFI_HANDLE **Buffer + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + + if (NumberHandles == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + BufferSize = 0; + *NumberHandles = 0; + *Buffer = NULL; + Status = SmmLocateHandle ( + SearchType, + Protocol, + SearchKey, + &BufferSize, + *Buffer + ); + // + // LocateHandleBuffer() returns incorrect status code if SearchType is + // invalid. + // + // Add code to correctly handle expected errors from SmmLocateHandle(). + // + if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) { + if (Status != EFI_INVALID_PARAMETER) { + Status = EFI_NOT_FOUND; + } + return Status; + } + + *Buffer = AllocatePool (BufferSize); + if (*Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = SmmLocateHandle ( + SearchType, + Protocol, + SearchKey, + &BufferSize, + *Buffer + ); + + *NumberHandles = BufferSize / sizeof(EFI_HANDLE); + if (EFI_ERROR(Status)) { + *NumberHandles = 0; + } + + return Status; +} diff --git a/HBFA/UefiHostTestPkg/Library/SmmServicesTableLibHost/Notify.c b/HBFA/UefiHostTestPkg/Library/SmmServicesTableLibHost/Notify.c new file mode 100644 index 0000000..8e078f7 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/SmmServicesTableLibHost/Notify.c @@ -0,0 +1,196 @@ +/** @file + Support functions for UEFI protocol notification infrastructure. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PiSmmCore.h" + +/** + Signal event for every protocol in protocol entry. + + @param Prot Protocol interface + +**/ +VOID +SmmNotifyProtocol ( + IN PROTOCOL_INTERFACE *Prot + ) +{ + PROTOCOL_ENTRY *ProtEntry; + PROTOCOL_NOTIFY *ProtNotify; + LIST_ENTRY *Link; + + ProtEntry = Prot->Protocol; + for (Link=ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) { + ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE); + ProtNotify->Function (&ProtEntry->ProtocolID, Prot->Interface, Prot->Handle); + } +} + +/** + Removes Protocol from the protocol list (but not the handle list). + + @param Handle The handle to remove protocol on. + @param Protocol GUID of the protocol to be moved + @param Interface The interface of the protocol + + @return Protocol Entry + +**/ +PROTOCOL_INTERFACE * +SmmRemoveInterfaceFromProtocol ( + IN IHANDLE *Handle, + IN EFI_GUID *Protocol, + IN VOID *Interface + ) +{ + PROTOCOL_INTERFACE *Prot; + PROTOCOL_NOTIFY *ProtNotify; + PROTOCOL_ENTRY *ProtEntry; + LIST_ENTRY *Link; + + Prot = SmmFindProtocolInterface (Handle, Protocol, Interface); + if (Prot != NULL) { + + ProtEntry = Prot->Protocol; + + // + // If there's a protocol notify location pointing to this entry, back it up one + // + for(Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) { + ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE); + + if (ProtNotify->Position == &Prot->ByProtocol) { + ProtNotify->Position = Prot->ByProtocol.BackLink; + } + } + + // + // Remove the protocol interface entry + // + RemoveEntryList (&Prot->ByProtocol); + } + + return Prot; +} + +/** + Add a new protocol notification record for the request protocol. + + @param Protocol The requested protocol to add the notify + registration + @param Function Points to the notification function + @param Registration Returns the registration record + + @retval EFI_SUCCESS Successfully returned the registration record + that has been added or unhooked + @retval EFI_INVALID_PARAMETER Protocol is NULL or Registration is NULL + @retval EFI_OUT_OF_RESOURCES Not enough memory resource to finish the request + @retval EFI_NOT_FOUND If the registration is not found when Function == NULL + +**/ +EFI_STATUS +EFIAPI +SmmRegisterProtocolNotify ( + IN CONST EFI_GUID *Protocol, + IN EFI_SMM_NOTIFY_FN Function, + OUT VOID **Registration + ) +{ + PROTOCOL_ENTRY *ProtEntry; + PROTOCOL_NOTIFY *ProtNotify; + LIST_ENTRY *Link; + EFI_STATUS Status; + + if (Protocol == NULL || Registration == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Function == NULL) { + // + // Get the protocol entry per Protocol + // + ProtEntry = SmmFindProtocolEntry ((EFI_GUID *) Protocol, FALSE); + if (ProtEntry != NULL) { + ProtNotify = (PROTOCOL_NOTIFY * )*Registration; + for (Link = ProtEntry->Notify.ForwardLink; + Link != &ProtEntry->Notify; + Link = Link->ForwardLink) { + // + // Compare the notification record + // + if (ProtNotify == (CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE))){ + // + // If Registration is an existing registration, then unhook it + // + ProtNotify->Signature = 0; + RemoveEntryList (&ProtNotify->Link); + FreePool (ProtNotify); + return EFI_SUCCESS; + } + } + } + // + // If the registration is not found + // + return EFI_NOT_FOUND; + } + + ProtNotify = NULL; + + // + // Get the protocol entry to add the notification too + // + ProtEntry = SmmFindProtocolEntry ((EFI_GUID *) Protocol, TRUE); + if (ProtEntry != NULL) { + // + // Find whether notification already exist + // + for (Link = ProtEntry->Notify.ForwardLink; + Link != &ProtEntry->Notify; + Link = Link->ForwardLink) { + + ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE); + if (CompareGuid (&ProtNotify->Protocol->ProtocolID, Protocol) && + (ProtNotify->Function == Function)) { + + // + // Notification already exist + // + *Registration = ProtNotify; + + return EFI_SUCCESS; + } + } + + // + // Allocate a new notification record + // + ProtNotify = AllocatePool (sizeof(PROTOCOL_NOTIFY)); + if (ProtNotify != NULL) { + ProtNotify->Signature = PROTOCOL_NOTIFY_SIGNATURE; + ProtNotify->Protocol = ProtEntry; + ProtNotify->Function = Function; + // + // Start at the ending + // + ProtNotify->Position = ProtEntry->Protocols.BackLink; + + InsertTailList (&ProtEntry->Notify, &ProtNotify->Link); + } + } + + // + // Done. If we have a protocol notify entry, then return it. + // Otherwise, we must have run out of resources trying to add one + // + Status = EFI_OUT_OF_RESOURCES; + if (ProtNotify != NULL) { + *Registration = ProtNotify; + Status = EFI_SUCCESS; + } + return Status; +} diff --git a/HBFA/UefiHostTestPkg/Library/SmmServicesTableLibHost/PiSmmCore.c b/HBFA/UefiHostTestPkg/Library/SmmServicesTableLibHost/PiSmmCore.c new file mode 100644 index 0000000..8edf7b3 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/SmmServicesTableLibHost/PiSmmCore.c @@ -0,0 +1,85 @@ +/** @file + SMM Core Main Entry Point + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PiSmmCore.h" + +// +// SMM Core global variable for SMM System Table. Only accessed as a physical structure in SMRAM. +// +EFI_SMM_SYSTEM_TABLE2 gSmmCoreSmst = { + { + SMM_SMST_SIGNATURE, + EFI_SMM_SYSTEM_TABLE2_REVISION, + sizeof (gSmmCoreSmst.Hdr) + }, + NULL, // SmmFirmwareVendor + 0, // SmmFirmwareRevision + SmmInstallConfigurationTable, + { + { + (EFI_SMM_CPU_IO2) SmmEfiNotAvailableYetArg5, // SmmMemRead + (EFI_SMM_CPU_IO2) SmmEfiNotAvailableYetArg5 // SmmMemWrite + }, + { + (EFI_SMM_CPU_IO2) SmmEfiNotAvailableYetArg5, // SmmIoRead + (EFI_SMM_CPU_IO2) SmmEfiNotAvailableYetArg5 // SmmIoWrite + } + }, + SmmAllocatePool, + SmmFreePool, + SmmAllocatePages, + SmmFreePages, + NULL, // SmmStartupThisAp + 0, // CurrentlyExecutingCpu + 0, // NumberOfCpus + NULL, // CpuSaveStateSize + NULL, // CpuSaveState + 0, // NumberOfTableEntries + NULL, // SmmConfigurationTable + SmmInstallProtocolInterface, + SmmUninstallProtocolInterface, + SmmHandleProtocol, + SmmRegisterProtocolNotify, + SmmLocateHandle, + SmmLocateProtocol, + SmiManage, + SmiHandlerRegister, + SmiHandlerUnRegister +}; + +/** + Place holder function until all the SMM System Table Service are available. + + Note: This function is only used by SMRAM invocation. It is never used by DXE invocation. + + @param Arg1 Undefined + @param Arg2 Undefined + @param Arg3 Undefined + @param Arg4 Undefined + @param Arg5 Undefined + + @return EFI_NOT_AVAILABLE_YET + +**/ +EFI_STATUS +EFIAPI +SmmEfiNotAvailableYetArg5 ( + UINTN Arg1, + UINTN Arg2, + UINTN Arg3, + UINTN Arg4, + UINTN Arg5 + ) +{ + // + // This function should never be executed. If it does, then the architectural protocols + // have not been designed correctly. + // + return EFI_NOT_AVAILABLE_YET; +} + diff --git a/HBFA/UefiHostTestPkg/Library/SmmServicesTableLibHost/PiSmmCore.h b/HBFA/UefiHostTestPkg/Library/SmmServicesTableLibHost/PiSmmCore.h new file mode 100644 index 0000000..bb9efb4 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/SmmServicesTableLibHost/PiSmmCore.h @@ -0,0 +1,1352 @@ +/** @file + The internal header file includes the common header files, defines + internal structure and functions used by SmmCore module. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _SMM_CORE_H_ +#define _SMM_CORE_H_ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#include "PiSmmCorePrivateData.h" +//#include "HeapGuard.h" + +// +// Used to build a table of SMI Handlers that the SMM Core registers +// +typedef struct { + EFI_SMM_HANDLER_ENTRY_POINT2 Handler; + EFI_GUID *HandlerType; + EFI_HANDLE DispatchHandle; + BOOLEAN UnRegister; +} SMM_CORE_SMI_HANDLERS; + +// +// SMM_HANDLER - used for each SMM handler +// + +#define SMI_ENTRY_SIGNATURE SIGNATURE_32('s','m','i','e') + + typedef struct { + UINTN Signature; + LIST_ENTRY AllEntries; // All entries + + EFI_GUID HandlerType; // Type of interrupt + LIST_ENTRY SmiHandlers; // All handlers +} SMI_ENTRY; + +#define SMI_HANDLER_SIGNATURE SIGNATURE_32('s','m','i','h') + + typedef struct { + UINTN Signature; + LIST_ENTRY Link; // Link on SMI_ENTRY.SmiHandlers + EFI_SMM_HANDLER_ENTRY_POINT2 Handler; // The smm handler's entry point + UINTN CallerAddr; // The address of caller who register the SMI handler. + SMI_ENTRY *SmiEntry; + VOID *Context; // for profile + UINTN ContextSize; // for profile +} SMI_HANDLER; + +// +// Structure for recording the state of an SMM Driver +// +#define EFI_SMM_DRIVER_ENTRY_SIGNATURE SIGNATURE_32('s', 'd','r','v') + +typedef struct { + UINTN Signature; + LIST_ENTRY Link; // mDriverList + + LIST_ENTRY ScheduledLink; // mScheduledQueue + + EFI_HANDLE FvHandle; + EFI_GUID FileName; + EFI_DEVICE_PATH_PROTOCOL *FvFileDevicePath; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; + + VOID *Depex; + UINTN DepexSize; + + BOOLEAN Before; + BOOLEAN After; + EFI_GUID BeforeAfterGuid; + + BOOLEAN Dependent; + BOOLEAN Scheduled; + BOOLEAN Initialized; + BOOLEAN DepexProtocolError; + + EFI_HANDLE ImageHandle; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + // + // Image EntryPoint in SMRAM + // + PHYSICAL_ADDRESS ImageEntryPoint; + // + // Image Buffer in SMRAM + // + PHYSICAL_ADDRESS ImageBuffer; + // + // Image Page Number + // + UINTN NumberOfPage; + EFI_HANDLE SmmImageHandle; + EFI_LOADED_IMAGE_PROTOCOL SmmLoadedImage; +} EFI_SMM_DRIVER_ENTRY; + +#define EFI_HANDLE_SIGNATURE SIGNATURE_32('h','n','d','l') + +/// +/// IHANDLE - contains a list of protocol handles +/// +typedef struct { + UINTN Signature; + /// All handles list of IHANDLE + LIST_ENTRY AllHandles; + /// List of PROTOCOL_INTERFACE's for this handle + LIST_ENTRY Protocols; + UINTN LocateRequest; +} IHANDLE; + +#define ASSERT_IS_HANDLE(a) ASSERT((a)->Signature == EFI_HANDLE_SIGNATURE) + +#define PROTOCOL_ENTRY_SIGNATURE SIGNATURE_32('p','r','t','e') + +/// +/// PROTOCOL_ENTRY - each different protocol has 1 entry in the protocol +/// database. Each handler that supports this protocol is listed, along +/// with a list of registered notifies. +/// +typedef struct { + UINTN Signature; + /// Link Entry inserted to mSmmProtocolDatabase + LIST_ENTRY AllEntries; + /// ID of the protocol + EFI_GUID ProtocolID; + /// All protocol interfaces + LIST_ENTRY Protocols; + /// Registerd notification handlers + LIST_ENTRY Notify; +} PROTOCOL_ENTRY; + +#define PROTOCOL_INTERFACE_SIGNATURE SIGNATURE_32('p','i','f','c') + +/// +/// PROTOCOL_INTERFACE - each protocol installed on a handle is tracked +/// with a protocol interface structure +/// +typedef struct { + UINTN Signature; + /// Link on IHANDLE.Protocols + LIST_ENTRY Link; + /// Back pointer + IHANDLE *Handle; + /// Link on PROTOCOL_ENTRY.Protocols + LIST_ENTRY ByProtocol; + /// The protocol ID + PROTOCOL_ENTRY *Protocol; + /// The interface value + VOID *Interface; +} PROTOCOL_INTERFACE; + +#define PROTOCOL_NOTIFY_SIGNATURE SIGNATURE_32('p','r','t','n') + +/// +/// PROTOCOL_NOTIFY - used for each register notification for a protocol +/// +typedef struct { + UINTN Signature; + PROTOCOL_ENTRY *Protocol; + /// All notifications for this protocol + LIST_ENTRY Link; + /// Notification function + EFI_SMM_NOTIFY_FN Function; + /// Last position notified + LIST_ENTRY *Position; +} PROTOCOL_NOTIFY; + +// +// SMM Core Global Variables +// +extern EFI_SMM_SYSTEM_TABLE2 gSmmCoreSmst; +extern LIST_ENTRY gSmmHandleList; +extern EFI_PHYSICAL_ADDRESS gLoadModuleAtFixAddressSmramBase; + +/** + Called to initialize the memory service. + + @param SmramRangeCount Number of SMRAM Regions + @param SmramRanges Pointer to SMRAM Descriptors + +**/ +VOID +SmmInitializeMemoryServices ( + IN UINTN SmramRangeCount, + IN EFI_SMRAM_DESCRIPTOR *SmramRanges + ); + +/** + The SmmInstallConfigurationTable() function is used to maintain the list + of configuration tables that are stored in the System Management System + Table. The list is stored as an array of (GUID, Pointer) pairs. The list + must be allocated from pool memory with PoolType set to EfiRuntimeServicesData. + + @param SystemTable A pointer to the SMM System Table (SMST). + @param Guid A pointer to the GUID for the entry to add, update, or remove. + @param Table A pointer to the buffer of the table to add. + @param TableSize The size of the table to install. + + @retval EFI_SUCCESS The (Guid, Table) pair was added, updated, or removed. + @retval EFI_INVALID_PARAMETER Guid is not valid. + @retval EFI_NOT_FOUND An attempt was made to delete a non-existent entry. + @retval EFI_OUT_OF_RESOURCES There is not enough memory available to complete the operation. + +**/ +EFI_STATUS +EFIAPI +SmmInstallConfigurationTable ( + IN CONST EFI_SMM_SYSTEM_TABLE2 *SystemTable, + IN CONST EFI_GUID *Guid, + IN VOID *Table, + IN UINTN TableSize + ); + +/** + Wrapper function to SmmInstallProtocolInterfaceNotify. This is the public API which + Calls the private one which contains a BOOLEAN parameter for notifications + + @param UserHandle The handle to install the protocol handler on, + or NULL if a new handle is to be allocated + @param Protocol The protocol to add to the handle + @param InterfaceType Indicates whether Interface is supplied in + native form. + @param Interface The interface for the protocol being added + + @return Status code + +**/ +EFI_STATUS +EFIAPI +SmmInstallProtocolInterface ( + IN OUT EFI_HANDLE *UserHandle, + IN EFI_GUID *Protocol, + IN EFI_INTERFACE_TYPE InterfaceType, + IN VOID *Interface + ); + +/** + Allocates pages from the memory map. + + @param Type The type of allocation to perform + @param MemoryType The type of memory to turn the allocated pages + into + @param NumberOfPages The number of pages to allocate + @param Memory A pointer to receive the base allocated memory + address + + @retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in spec. + @retval EFI_NOT_FOUND Could not allocate pages match the requirement. + @retval EFI_OUT_OF_RESOURCES No enough pages to allocate. + @retval EFI_SUCCESS Pages successfully allocated. + +**/ +EFI_STATUS +EFIAPI +SmmAllocatePages ( + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN NumberOfPages, + OUT EFI_PHYSICAL_ADDRESS *Memory + ); + +/** + Allocates pages from the memory map. + + @param Type The type of allocation to perform + @param MemoryType The type of memory to turn the allocated pages + into + @param NumberOfPages The number of pages to allocate + @param Memory A pointer to receive the base allocated memory + address + @param NeedGuard Flag to indicate Guard page is needed or not + + @retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in spec. + @retval EFI_NOT_FOUND Could not allocate pages match the requirement. + @retval EFI_OUT_OF_RESOURCES No enough pages to allocate. + @retval EFI_SUCCESS Pages successfully allocated. + +**/ +EFI_STATUS +EFIAPI +SmmInternalAllocatePages ( + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN NumberOfPages, + OUT EFI_PHYSICAL_ADDRESS *Memory, + IN BOOLEAN NeedGuard + ); + +/** + Frees previous allocated pages. + + @param Memory Base address of memory being freed + @param NumberOfPages The number of pages to free + + @retval EFI_NOT_FOUND Could not find the entry that covers the range + @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero or NumberOfPages is zero. + @return EFI_SUCCESS Pages successfully freed. + +**/ +EFI_STATUS +EFIAPI +SmmFreePages ( + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN NumberOfPages + ); + +/** + Frees previous allocated pages. + + @param Memory Base address of memory being freed + @param NumberOfPages The number of pages to free + @param IsGuarded Flag to indicate if the memory is guarded + or not + + @retval EFI_NOT_FOUND Could not find the entry that covers the range + @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero or NumberOfPages is zero. + @return EFI_SUCCESS Pages successfully freed. + +**/ +EFI_STATUS +EFIAPI +SmmInternalFreePages ( + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN NumberOfPages, + IN BOOLEAN IsGuarded + ); + +/** + Allocate pool of a particular type. + + @param PoolType Type of pool to allocate + @param Size The amount of pool to allocate + @param Buffer The address to return a pointer to the allocated + pool + + @retval EFI_INVALID_PARAMETER PoolType not valid + @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed. + @retval EFI_SUCCESS Pool successfully allocated. + +**/ +EFI_STATUS +EFIAPI +SmmAllocatePool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN Size, + OUT VOID **Buffer + ); + +/** + Allocate pool of a particular type. + + @param PoolType Type of pool to allocate + @param Size The amount of pool to allocate + @param Buffer The address to return a pointer to the allocated + pool + + @retval EFI_INVALID_PARAMETER PoolType not valid + @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed. + @retval EFI_SUCCESS Pool successfully allocated. + +**/ +EFI_STATUS +EFIAPI +SmmInternalAllocatePool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN Size, + OUT VOID **Buffer + ); + +/** + Frees pool. + + @param Buffer The allocated pool entry to free + + @retval EFI_INVALID_PARAMETER Buffer is not a valid value. + @retval EFI_SUCCESS Pool successfully freed. + +**/ +EFI_STATUS +EFIAPI +SmmFreePool ( + IN VOID *Buffer + ); + +/** + Frees pool. + + @param Buffer The allocated pool entry to free + + @retval EFI_INVALID_PARAMETER Buffer is not a valid value. + @retval EFI_SUCCESS Pool successfully freed. + +**/ +EFI_STATUS +EFIAPI +SmmInternalFreePool ( + IN VOID *Buffer + ); + +/** + Installs a protocol interface into the boot services environment. + + @param UserHandle The handle to install the protocol handler on, + or NULL if a new handle is to be allocated + @param Protocol The protocol to add to the handle + @param InterfaceType Indicates whether Interface is supplied in + native form. + @param Interface The interface for the protocol being added + @param Notify indicates whether notify the notification list + for this protocol + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate + @retval EFI_SUCCESS Protocol interface successfully installed + +**/ +EFI_STATUS +SmmInstallProtocolInterfaceNotify ( + IN OUT EFI_HANDLE *UserHandle, + IN EFI_GUID *Protocol, + IN EFI_INTERFACE_TYPE InterfaceType, + IN VOID *Interface, + IN BOOLEAN Notify + ); + +/** + Uninstalls all instances of a protocol:interfacer from a handle. + If the last protocol interface is remove from the handle, the + handle is freed. + + @param UserHandle The handle to remove the protocol handler from + @param Protocol The protocol, of protocol:interface, to remove + @param Interface The interface, of protocol:interface, to remove + + @retval EFI_INVALID_PARAMETER Protocol is NULL. + @retval EFI_SUCCESS Protocol interface successfully uninstalled. + +**/ +EFI_STATUS +EFIAPI +SmmUninstallProtocolInterface ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + IN VOID *Interface + ); + +/** + Queries a handle to determine if it supports a specified protocol. + + @param UserHandle The handle being queried. + @param Protocol The published unique identifier of the protocol. + @param Interface Supplies the address where a pointer to the + corresponding Protocol Interface is returned. + + @return The requested protocol interface for the handle + +**/ +EFI_STATUS +EFIAPI +SmmHandleProtocol ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + OUT VOID **Interface + ); + +/** + Add a new protocol notification record for the request protocol. + + @param Protocol The requested protocol to add the notify + registration + @param Function Points to the notification function + @param Registration Returns the registration record + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_SUCCESS Successfully returned the registration record + that has been added + +**/ +EFI_STATUS +EFIAPI +SmmRegisterProtocolNotify ( + IN CONST EFI_GUID *Protocol, + IN EFI_SMM_NOTIFY_FN Function, + OUT VOID **Registration + ); + +/** + Locates the requested handle(s) and returns them in Buffer. + + @param SearchType The type of search to perform to locate the + handles + @param Protocol The protocol to search for + @param SearchKey Dependant on SearchType + @param BufferSize On input the size of Buffer. On output the + size of data returned. + @param Buffer The buffer to return the results in + + @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is + returned in BufferSize. + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_SUCCESS Successfully found the requested handle(s) and + returns them in Buffer. + +**/ +EFI_STATUS +EFIAPI +SmmLocateHandle ( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol OPTIONAL, + IN VOID *SearchKey OPTIONAL, + IN OUT UINTN *BufferSize, + OUT EFI_HANDLE *Buffer + ); + +/** + Return the first Protocol Interface that matches the Protocol GUID. If + Registration is pasased in return a Protocol Instance that was just add + to the system. If Retistration is NULL return the first Protocol Interface + you find. + + @param Protocol The protocol to search for + @param Registration Optional Registration Key returned from + RegisterProtocolNotify() + @param Interface Return the Protocol interface (instance). + + @retval EFI_SUCCESS If a valid Interface is returned + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_NOT_FOUND Protocol interface not found + +**/ +EFI_STATUS +EFIAPI +SmmLocateProtocol ( + IN EFI_GUID *Protocol, + IN VOID *Registration OPTIONAL, + OUT VOID **Interface + ); + +/** + Function returns an array of handles that support the requested protocol + in a buffer allocated from pool. This is a version of SmmLocateHandle() + that allocates a buffer for the caller. + + @param SearchType Specifies which handle(s) are to be returned. + @param Protocol Provides the protocol to search by. This + parameter is only valid for SearchType + ByProtocol. + @param SearchKey Supplies the search key depending on the + SearchType. + @param NumberHandles The number of handles returned in Buffer. + @param Buffer A pointer to the buffer to return the requested + array of handles that support Protocol. + + @retval EFI_SUCCESS The result array of handles was returned. + @retval EFI_NOT_FOUND No handles match the search. + @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the + matching results. + @retval EFI_INVALID_PARAMETER One or more paramters are not valid. + +**/ +EFI_STATUS +EFIAPI +SmmLocateHandleBuffer ( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol OPTIONAL, + IN VOID *SearchKey OPTIONAL, + IN OUT UINTN *NumberHandles, + OUT EFI_HANDLE **Buffer + ); + +/** + Manage SMI of a particular type. + + @param HandlerType Points to the handler type or NULL for root SMI handlers. + @param Context Points to an optional context buffer. + @param CommBuffer Points to the optional communication buffer. + @param CommBufferSize Points to the size of the optional communication buffer. + + @retval EFI_SUCCESS Interrupt source was processed successfully but not quiesced. + @retval EFI_INTERRUPT_PENDING One or more SMI sources could not be quiesced. + @retval EFI_WARN_INTERRUPT_SOURCE_PENDING Interrupt source was not handled or quiesced. + @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED Interrupt source was handled and quiesced. + +**/ +EFI_STATUS +EFIAPI +SmiManage ( + IN CONST EFI_GUID *HandlerType, + IN CONST VOID *Context OPTIONAL, + IN OUT VOID *CommBuffer OPTIONAL, + IN OUT UINTN *CommBufferSize OPTIONAL + ); + +/** + Registers a handler to execute within SMM. + + @param Handler Handler service funtion pointer. + @param HandlerType Points to the handler type or NULL for root SMI handlers. + @param DispatchHandle On return, contains a unique handle which can be used to later unregister the handler function. + + @retval EFI_SUCCESS Handler register success. + @retval EFI_INVALID_PARAMETER Handler or DispatchHandle is NULL. + +**/ +EFI_STATUS +EFIAPI +SmiHandlerRegister ( + IN EFI_SMM_HANDLER_ENTRY_POINT2 Handler, + IN CONST EFI_GUID *HandlerType OPTIONAL, + OUT EFI_HANDLE *DispatchHandle + ); + +/** + Unregister a handler in SMM. + + @param DispatchHandle The handle that was specified when the handler was registered. + + @retval EFI_SUCCESS Handler function was successfully unregistered. + @retval EFI_INVALID_PARAMETER DispatchHandle does not refer to a valid handle. + +**/ +EFI_STATUS +EFIAPI +SmiHandlerUnRegister ( + IN EFI_HANDLE DispatchHandle + ); + +/** + This function is the main entry point for an SMM handler dispatch + or communicate-based callback. + + @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister(). + @param Context Points to an optional handler context which was specified when the handler was registered. + @param CommBuffer A pointer to a collection of data in memory that will + be conveyed from a non-SMM environment into an SMM environment. + @param CommBufferSize The size of the CommBuffer. + + @return Status Code + +**/ +EFI_STATUS +EFIAPI +SmmDriverDispatchHandler ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *Context, OPTIONAL + IN OUT VOID *CommBuffer, OPTIONAL + IN OUT UINTN *CommBufferSize OPTIONAL + ); + +/** + This function is the main entry point for an SMM handler dispatch + or communicate-based callback. + + @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister(). + @param Context Points to an optional handler context which was specified when the handler was registered. + @param CommBuffer A pointer to a collection of data in memory that will + be conveyed from a non-SMM environment into an SMM environment. + @param CommBufferSize The size of the CommBuffer. + + @return Status Code + +**/ +EFI_STATUS +EFIAPI +SmmLegacyBootHandler ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *Context, OPTIONAL + IN OUT VOID *CommBuffer, OPTIONAL + IN OUT UINTN *CommBufferSize OPTIONAL + ); + +/** + This function is the main entry point for an SMM handler dispatch + or communicate-based callback. + + @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister(). + @param Context Points to an optional handler context which was specified when the handler was registered. + @param CommBuffer A pointer to a collection of data in memory that will + be conveyed from a non-SMM environment into an SMM environment. + @param CommBufferSize The size of the CommBuffer. + + @return Status Code + +**/ +EFI_STATUS +EFIAPI +SmmReadyToLockHandler ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *Context, OPTIONAL + IN OUT VOID *CommBuffer, OPTIONAL + IN OUT UINTN *CommBufferSize OPTIONAL + ); + +/** + This function is the main entry point for an SMM handler dispatch + or communicate-based callback. + + @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister(). + @param Context Points to an optional handler context which was specified when the handler was registered. + @param CommBuffer A pointer to a collection of data in memory that will + be conveyed from a non-SMM environment into an SMM environment. + @param CommBufferSize The size of the CommBuffer. + + @return Status Code + +**/ +EFI_STATUS +EFIAPI +SmmEndOfDxeHandler ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *Context, OPTIONAL + IN OUT VOID *CommBuffer, OPTIONAL + IN OUT UINTN *CommBufferSize OPTIONAL + ); + +/** + This function is the main entry point for an SMM handler dispatch + or communicate-based callback. + + @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister(). + @param Context Points to an optional handler context which was specified when the handler was registered. + @param CommBuffer A pointer to a collection of data in memory that will + be conveyed from a non-SMM environment into an SMM environment. + @param CommBufferSize The size of the CommBuffer. + + @return Status Code + +**/ +EFI_STATUS +EFIAPI +SmmExitBootServicesHandler ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *Context, OPTIONAL + IN OUT VOID *CommBuffer, OPTIONAL + IN OUT UINTN *CommBufferSize OPTIONAL + ); + +/** + This function is the main entry point for an SMM handler dispatch + or communicate-based callback. + + @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister(). + @param Context Points to an optional handler context which was specified when the handler was registered. + @param CommBuffer A pointer to a collection of data in memory that will + be conveyed from a non-SMM environment into an SMM environment. + @param CommBufferSize The size of the CommBuffer. + + @return Status Code + +**/ +EFI_STATUS +EFIAPI +SmmReadyToBootHandler ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *Context, OPTIONAL + IN OUT VOID *CommBuffer, OPTIONAL + IN OUT UINTN *CommBufferSize OPTIONAL + ); + +/** + Software SMI handler that is called when the S3SmmInitDone signal is triggered. + This function installs the SMM S3SmmInitDone Protocol so SMM Drivers are informed that + S3 SMM initialization has been done. + + @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister(). + @param Context Points to an optional handler context which was specified when the handler was registered. + @param CommBuffer A pointer to a collection of data in memory that will + be conveyed from a non-SMM environment into an SMM environment. + @param CommBufferSize The size of the CommBuffer. + + @return Status Code + +**/ +EFI_STATUS +EFIAPI +SmmS3SmmInitDoneHandler ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *Context, OPTIONAL + IN OUT VOID *CommBuffer, OPTIONAL + IN OUT UINTN *CommBufferSize OPTIONAL + ); + +/** + Software SMI handler that is called when the EndOfS3Resume event is trigged. + This function installs the SMM EndOfS3Resume Protocol so SMM Drivers are informed that + S3 resume has finished. + + @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister(). + @param Context Points to an optional handler context which was specified when the handler was registered. + @param CommBuffer A pointer to a collection of data in memory that will + be conveyed from a non-SMM environment into an SMM environment. + @param CommBufferSize The size of the CommBuffer. + + @return Status Code + +**/ +EFI_STATUS +EFIAPI +SmmEndOfS3ResumeHandler ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *Context, OPTIONAL + IN OUT VOID *CommBuffer, OPTIONAL + IN OUT UINTN *CommBufferSize OPTIONAL + ); + +/** + Place holder function until all the SMM System Table Service are available. + + @param Arg1 Undefined + @param Arg2 Undefined + @param Arg3 Undefined + @param Arg4 Undefined + @param Arg5 Undefined + + @return EFI_NOT_AVAILABLE_YET + +**/ +EFI_STATUS +EFIAPI +SmmEfiNotAvailableYetArg5 ( + UINTN Arg1, + UINTN Arg2, + UINTN Arg3, + UINTN Arg4, + UINTN Arg5 + ); + +// +//Functions used during debug buils +// + +/** + Traverse the discovered list for any drivers that were discovered but not loaded + because the dependency experessions evaluated to false. + +**/ +VOID +SmmDisplayDiscoveredNotDispatched ( + VOID + ); + +/** + Add free SMRAM region for use by memory service. + + @param MemBase Base address of memory region. + @param MemLength Length of the memory region. + @param Type Memory type. + @param Attributes Memory region state. + +**/ +VOID +SmmAddMemoryRegion ( + IN EFI_PHYSICAL_ADDRESS MemBase, + IN UINT64 MemLength, + IN EFI_MEMORY_TYPE Type, + IN UINT64 Attributes + ); + +/** + Finds the protocol entry for the requested protocol. + + @param Protocol The ID of the protocol + @param Create Create a new entry if not found + + @return Protocol entry + +**/ +PROTOCOL_ENTRY * +SmmFindProtocolEntry ( + IN EFI_GUID *Protocol, + IN BOOLEAN Create + ); + +/** + Signal event for every protocol in protocol entry. + + @param Prot Protocol interface + +**/ +VOID +SmmNotifyProtocol ( + IN PROTOCOL_INTERFACE *Prot + ); + +/** + Finds the protocol instance for the requested handle and protocol. + Note: This function doesn't do parameters checking, it's caller's responsibility + to pass in valid parameters. + + @param Handle The handle to search the protocol on + @param Protocol GUID of the protocol + @param Interface The interface for the protocol being searched + + @return Protocol instance (NULL: Not found) + +**/ +PROTOCOL_INTERFACE * +SmmFindProtocolInterface ( + IN IHANDLE *Handle, + IN EFI_GUID *Protocol, + IN VOID *Interface + ); + +/** + Removes Protocol from the protocol list (but not the handle list). + + @param Handle The handle to remove protocol on. + @param Protocol GUID of the protocol to be moved + @param Interface The interface of the protocol + + @return Protocol Entry + +**/ +PROTOCOL_INTERFACE * +SmmRemoveInterfaceFromProtocol ( + IN IHANDLE *Handle, + IN EFI_GUID *Protocol, + IN VOID *Interface + ); + +/** + This is the POSTFIX version of the dependency evaluator. This code does + not need to handle Before or After, as it is not valid to call this + routine in this case. POSTFIX means all the math is done on top of the stack. + + @param DriverEntry DriverEntry element to update. + + @retval TRUE If driver is ready to run. + @retval FALSE If driver is not ready to run or some fatal error + was found. + +**/ +BOOLEAN +SmmIsSchedulable ( + IN EFI_SMM_DRIVER_ENTRY *DriverEntry + ); + +// +// SmramProfile +// + +/** + Initialize SMRAM profile. + +**/ +VOID +SmramProfileInit ( + VOID + ); + +/** + Install SMRAM profile protocol. + +**/ +VOID +SmramProfileInstallProtocol ( + VOID + ); + +/** + Register SMM image to SMRAM profile. + + @param DriverEntry SMM image info. + @param RegisterToDxe Register image to DXE. + + @return EFI_SUCCESS Register successfully. + @return EFI_UNSUPPORTED Memory profile unsupported, + or memory profile for the image is not required. + @return EFI_OUT_OF_RESOURCES No enough resource for this register. + +**/ +EFI_STATUS +RegisterSmramProfileImage ( + IN EFI_SMM_DRIVER_ENTRY *DriverEntry, + IN BOOLEAN RegisterToDxe + ); + +/** + Unregister image from SMRAM profile. + + @param DriverEntry SMM image info. + @param UnregisterToDxe Unregister image from DXE. + + @return EFI_SUCCESS Unregister successfully. + @return EFI_UNSUPPORTED Memory profile unsupported, + or memory profile for the image is not required. + @return EFI_NOT_FOUND The image is not found. + +**/ +EFI_STATUS +UnregisterSmramProfileImage ( + IN EFI_SMM_DRIVER_ENTRY *DriverEntry, + IN BOOLEAN UnregisterToDxe + ); + +/** + Update SMRAM profile information. + + @param CallerAddress Address of caller who call Allocate or Free. + @param Action This Allocate or Free action. + @param MemoryType Memory type. + EfiMaxMemoryType means the MemoryType is unknown. + @param Size Buffer size. + @param Buffer Buffer address. + @param ActionString String for memory profile action. + Only needed for user defined allocate action. + + @return EFI_SUCCESS Memory profile is updated. + @return EFI_UNSUPPORTED Memory profile is unsupported, + or memory profile for the image is not required, + or memory profile for the memory type is not required. + @return EFI_ACCESS_DENIED It is during memory profile data getting. + @return EFI_ABORTED Memory profile recording is not enabled. + @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action. + @return EFI_NOT_FOUND No matched allocate info found for free action. + +**/ +EFI_STATUS +EFIAPI +SmmCoreUpdateProfile ( + IN PHYSICAL_ADDRESS CallerAddress, + IN MEMORY_PROFILE_ACTION Action, + IN EFI_MEMORY_TYPE MemoryType, // Valid for AllocatePages/AllocatePool + IN UINTN Size, // Valid for AllocatePages/FreePages/AllocatePool + IN VOID *Buffer, + IN CHAR8 *ActionString OPTIONAL + ); + +/** + Register SMRAM profile handler. + +**/ +VOID +RegisterSmramProfileHandler ( + VOID + ); + +/** + SMRAM profile ready to lock callback function. + +**/ +VOID +SmramProfileReadyToLock ( + VOID + ); + +/** + Initialize MemoryAttributes support. +**/ +VOID +EFIAPI +SmmCoreInitializeMemoryAttributesTable ( + VOID + ); + +/** + This function returns a copy of the current memory map. The map is an array of + memory descriptors, each of which describes a contiguous block of memory. + + @param[in, out] MemoryMapSize A pointer to the size, in bytes, of the + MemoryMap buffer. On input, this is the size of + the buffer allocated by the caller. On output, + it is the size of the buffer returned by the + firmware if the buffer was large enough, or the + size of the buffer needed to contain the map if + the buffer was too small. + @param[in, out] MemoryMap A pointer to the buffer in which firmware places + the current memory map. + @param[out] MapKey A pointer to the location in which firmware + returns the key for the current memory map. + @param[out] DescriptorSize A pointer to the location in which firmware + returns the size, in bytes, of an individual + EFI_MEMORY_DESCRIPTOR. + @param[out] DescriptorVersion A pointer to the location in which firmware + returns the version number associated with the + EFI_MEMORY_DESCRIPTOR. + + @retval EFI_SUCCESS The memory map was returned in the MemoryMap + buffer. + @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current + buffer size needed to hold the memory map is + returned in MemoryMapSize. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + +**/ +EFI_STATUS +EFIAPI +SmmCoreGetMemoryMap ( + IN OUT UINTN *MemoryMapSize, + IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, + OUT UINTN *MapKey, + OUT UINTN *DescriptorSize, + OUT UINT32 *DescriptorVersion + ); + +/** + Initialize SmiHandler profile feature. +**/ +VOID +SmmCoreInitializeSmiHandlerProfile ( + VOID + ); + +/** + This function is called by SmmChildDispatcher module to report + a new SMI handler is registered, to SmmCore. + + @param This The protocol instance + @param HandlerGuid The GUID to identify the type of the handler. + For the SmmChildDispatch protocol, the HandlerGuid + must be the GUID of SmmChildDispatch protocol. + @param Handler The SMI handler. + @param CallerAddress The address of the module who registers the SMI handler. + @param Context The context of the SMI handler. + For the SmmChildDispatch protocol, the Context + must match the one defined for SmmChildDispatch protocol. + @param ContextSize The size of the context in bytes. + For the SmmChildDispatch protocol, the Context + must match the one defined for SmmChildDispatch protocol. + + @retval EFI_SUCCESS The information is recorded. + @retval EFI_OUT_OF_RESOURCES There is no enough resource to record the information. +**/ +EFI_STATUS +EFIAPI +SmiHandlerProfileRegisterHandler ( + IN SMI_HANDLER_PROFILE_PROTOCOL *This, + IN EFI_GUID *HandlerGuid, + IN EFI_SMM_HANDLER_ENTRY_POINT2 Handler, + IN PHYSICAL_ADDRESS CallerAddress, + IN VOID *Context, OPTIONAL + IN UINTN ContextSize OPTIONAL + ); + +/** + This function is called by SmmChildDispatcher module to report + an existing SMI handler is unregistered, to SmmCore. + + @param This The protocol instance + @param HandlerGuid The GUID to identify the type of the handler. + For the SmmChildDispatch protocol, the HandlerGuid + must be the GUID of SmmChildDispatch protocol. + @param Handler The SMI handler. + @param Context The context of the SMI handler. + If it is NOT NULL, it will be used to check what is registered. + @param ContextSize The size of the context in bytes. + If Context is NOT NULL, it will be used to check what is registered. + + @retval EFI_SUCCESS The original record is removed. + @retval EFI_NOT_FOUND There is no record for the HandlerGuid and handler. +**/ +EFI_STATUS +EFIAPI +SmiHandlerProfileUnregisterHandler ( + IN SMI_HANDLER_PROFILE_PROTOCOL *This, + IN EFI_GUID *HandlerGuid, + IN EFI_SMM_HANDLER_ENTRY_POINT2 Handler, + IN VOID *Context, OPTIONAL + IN UINTN ContextSize OPTIONAL + ); + +extern UINTN mFullSmramRangeCount; +extern EFI_SMRAM_DESCRIPTOR *mFullSmramRanges; + +extern EFI_SMM_DRIVER_ENTRY *mSmmCoreDriverEntry; + +extern EFI_LOADED_IMAGE_PROTOCOL *mSmmCoreLoadedImage; + +// +// Page management +// + +typedef struct { + LIST_ENTRY Link; + UINTN NumberOfPages; +} FREE_PAGE_LIST; + +extern LIST_ENTRY mSmmMemoryMap; + +// +// Pool management +// + +// +// MIN_POOL_SHIFT must not be less than 5 +// +#define MIN_POOL_SHIFT 6 +#define MIN_POOL_SIZE (1 << MIN_POOL_SHIFT) + +// +// MAX_POOL_SHIFT must not be less than EFI_PAGE_SHIFT - 1 +// +#define MAX_POOL_SHIFT (EFI_PAGE_SHIFT - 1) +#define MAX_POOL_SIZE (1 << MAX_POOL_SHIFT) + +// +// MAX_POOL_INDEX are calculated by maximum and minimum pool sizes +// +#define MAX_POOL_INDEX (MAX_POOL_SHIFT - MIN_POOL_SHIFT + 1) + +#define POOL_HEAD_SIGNATURE SIGNATURE_32('p','h','d','0') + +typedef struct { + UINT32 Signature; + BOOLEAN Available; + EFI_MEMORY_TYPE Type; + UINTN Size; +} POOL_HEADER; + +#define POOL_TAIL_SIGNATURE SIGNATURE_32('p','t','a','l') + +typedef struct { + UINT32 Signature; + UINT32 Reserved; + UINTN Size; +} POOL_TAIL; + +#define POOL_OVERHEAD (sizeof(POOL_HEADER) + sizeof(POOL_TAIL)) + +#define HEAD_TO_TAIL(a) \ + ((POOL_TAIL *) (((CHAR8 *) (a)) + (a)->Size - sizeof(POOL_TAIL))); + +typedef struct { + POOL_HEADER Header; + LIST_ENTRY Link; +} FREE_POOL_HEADER; + +typedef enum { + SmmPoolTypeCode, + SmmPoolTypeData, + SmmPoolTypeMax, +} SMM_POOL_TYPE; + +extern LIST_ENTRY mSmmPoolLists[SmmPoolTypeMax][MAX_POOL_INDEX]; + +/** + Internal Function. Allocate n pages from given free page node. + + @param Pages The free page node. + @param NumberOfPages Number of pages to be allocated. + @param MaxAddress Request to allocate memory below this address. + + @return Memory address of allocated pages. + +**/ +UINTN +InternalAllocPagesOnOneNode ( + IN OUT FREE_PAGE_LIST *Pages, + IN UINTN NumberOfPages, + IN UINTN MaxAddress + ); + +/** + Update SMM memory map entry. + + @param[in] Type The type of allocation to perform. + @param[in] Memory The base of memory address. + @param[in] NumberOfPages The number of pages to allocate. + @param[in] AddRegion If this memory is new added region. +**/ +VOID +ConvertSmmMemoryMapEntry ( + IN EFI_MEMORY_TYPE Type, + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN NumberOfPages, + IN BOOLEAN AddRegion + ); + +/** + Internal function. Moves any memory descriptors that are on the + temporary descriptor stack to heap. + +**/ +VOID +CoreFreeMemoryMapStack ( + VOID + ); + +/** + Frees previous allocated pages. + + @param[in] Memory Base address of memory being freed. + @param[in] NumberOfPages The number of pages to free. + @param[in] AddRegion If this memory is new added region. + + @retval EFI_NOT_FOUND Could not find the entry that covers the range. + @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero or NumberOfPages is zero. + @return EFI_SUCCESS Pages successfully freed. + +**/ +EFI_STATUS +SmmInternalFreePagesEx ( + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN NumberOfPages, + IN BOOLEAN AddRegion + ); + +/** + Hook function used to set all Guard pages after entering SMM mode. +**/ +VOID +SmmEntryPointMemoryManagementHook ( + VOID + ); + +#endif diff --git a/HBFA/UefiHostTestPkg/Library/SmmServicesTableLibHost/SmmServicesTableLibHost.c b/HBFA/UefiHostTestPkg/Library/SmmServicesTableLibHost/SmmServicesTableLibHost.c new file mode 100644 index 0000000..5089293 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/SmmServicesTableLibHost/SmmServicesTableLibHost.c @@ -0,0 +1,112 @@ +/** @file + SMM Services Table Library. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +#include "PiSmmCore.h" + +extern EFI_SMM_SYSTEM_TABLE2 gSmmCoreSmst; + +EFI_SMM_SYSTEM_TABLE2 *gSmst = &gSmmCoreSmst; +EFI_MM_SYSTEM_TABLE *gMmst = (EFI_MM_SYSTEM_TABLE *)&gSmmCoreSmst; + +EFI_STATUS +EFIAPI +SmmAllocatePages ( + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN NumberOfPages, + OUT EFI_PHYSICAL_ADDRESS *Memory + ) +{ + VOID *Buffer; + + if ((NumberOfPages == 0) || + (NumberOfPages > RShiftU64 ((UINTN)-1, EFI_PAGE_SHIFT))) { + return EFI_NOT_FOUND; + } + + Buffer = malloc (EFI_PAGES_TO_SIZE(NumberOfPages)); + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + *Memory = (UINTN)Buffer; + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +SmmFreePages ( + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN NumberOfPages + ) +{ + free ((VOID *)(UINTN)Memory); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +SmmAllocatePool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN Size, + OUT VOID **Buffer + ) +{ + *Buffer = malloc (Size); + if (*Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +SmmFreePool ( + IN VOID *Buffer + ) +{ + free (Buffer); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +SmiManage ( + IN CONST EFI_GUID *HandlerType, + IN CONST VOID *Context OPTIONAL, + IN OUT VOID *CommBuffer OPTIONAL, + IN OUT UINTN *CommBufferSize OPTIONAL + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +EFI_STATUS +EFIAPI +SmiHandlerRegister ( + IN EFI_SMM_HANDLER_ENTRY_POINT2 Handler, + IN CONST EFI_GUID *HandlerType OPTIONAL, + OUT EFI_HANDLE *DispatchHandle + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + +EFI_STATUS +EFIAPI +SmiHandlerUnRegister ( + IN EFI_HANDLE DispatchHandle + ) +{ + return EFI_NOT_AVAILABLE_YET; +} + diff --git a/HBFA/UefiHostTestPkg/Library/SmmServicesTableLibHost/SmmServicesTableLibHost.inf b/HBFA/UefiHostTestPkg/Library/SmmServicesTableLibHost/SmmServicesTableLibHost.inf new file mode 100644 index 0000000..d5d67bd --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/SmmServicesTableLibHost/SmmServicesTableLibHost.inf @@ -0,0 +1,43 @@ +## @file +# SMM Services Table Library. +# +# Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmmServicesTableLibHost + FILE_GUID = BC01EA4A-7CD7-456F-9BD3-1EF71FD0E026 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = SmmServicesTableLib + LIBRARY_CLASS = MmServicesTableLib + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + SmmServicesTableLibHost.c + PiSmmCore.c + Handle.c + Locate.c + Notify.c + InstallConfigurationTable.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib + + diff --git a/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/DriverSupport.c b/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/DriverSupport.c new file mode 100644 index 0000000..bee1de9 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/DriverSupport.c @@ -0,0 +1,953 @@ +/** @file + Support functions to connect/disconnect UEFI Driver model Protocol + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "DxeMain.h" +#include "Handle.h" + + +// +// Driver Support Functions +// +/** + Connects one or more drivers to a controller. + + @param ControllerHandle The handle of the controller to which driver(s) are to be connected. + @param DriverImageHandle A pointer to an ordered list handles that support the + EFI_DRIVER_BINDING_PROTOCOL. + @param RemainingDevicePath A pointer to the device path that specifies a child of the + controller specified by ControllerHandle. + @param Recursive If TRUE, then ConnectController() is called recursively + until the entire tree of controllers below the controller specified + by ControllerHandle have been created. If FALSE, then + the tree of controllers is only expanded one level. + + @retval EFI_SUCCESS 1) One or more drivers were connected to ControllerHandle. + 2) No drivers were connected to ControllerHandle, but + RemainingDevicePath is not NULL, and it is an End Device + Path Node. + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + @retval EFI_NOT_FOUND 1) There are no EFI_DRIVER_BINDING_PROTOCOL instances + present in the system. + 2) No drivers were connected to ControllerHandle. + @retval EFI_SECURITY_VIOLATION + The user has no permission to start UEFI device drivers on the device path + associated with the ControllerHandle or specified by the RemainingDevicePath. + +**/ +EFI_STATUS +EFIAPI +CoreConnectController ( + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE *DriverImageHandle OPTIONAL, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL, + IN BOOLEAN Recursive + ) +{ + EFI_STATUS Status; + EFI_STATUS ReturnStatus; + IHANDLE *Handle; + PROTOCOL_INTERFACE *Prot; + LIST_ENTRY *Link; + LIST_ENTRY *ProtLink; + OPEN_PROTOCOL_DATA *OpenData; + EFI_DEVICE_PATH_PROTOCOL *AlignedRemainingDevicePath; + EFI_HANDLE *ChildHandleBuffer; + UINTN ChildHandleCount; + UINTN Index; + UINTN HandleFilePathSize; + UINTN RemainingDevicePathSize; + EFI_DEVICE_PATH_PROTOCOL *HandleFilePath; + EFI_DEVICE_PATH_PROTOCOL *FilePath; + EFI_DEVICE_PATH_PROTOCOL *TempFilePath; + + // + // Make sure ControllerHandle is valid + // + Status = CoreValidateHandle (ControllerHandle); + if (EFI_ERROR (Status)) { + return Status; + } + + if (gSecurity2 != NULL) { + // + // Check whether the user has permission to start UEFI device drivers. + // + Status = CoreHandleProtocol (ControllerHandle, &gEfiDevicePathProtocolGuid, (VOID **)&HandleFilePath); + if (!EFI_ERROR (Status)) { + ASSERT (HandleFilePath != NULL); + FilePath = HandleFilePath; + TempFilePath = NULL; + if (RemainingDevicePath != NULL && !Recursive) { + HandleFilePathSize = GetDevicePathSize (HandleFilePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL); + RemainingDevicePathSize = GetDevicePathSize (RemainingDevicePath); + TempFilePath = AllocateZeroPool (HandleFilePathSize + RemainingDevicePathSize); + ASSERT (TempFilePath != NULL); + CopyMem (TempFilePath, HandleFilePath, HandleFilePathSize); + CopyMem ((UINT8 *) TempFilePath + HandleFilePathSize, RemainingDevicePath, RemainingDevicePathSize); + FilePath = TempFilePath; + } + Status = gSecurity2->FileAuthentication ( + gSecurity2, + FilePath, + NULL, + 0, + FALSE + ); + if (TempFilePath != NULL) { + FreePool (TempFilePath); + } + if (EFI_ERROR (Status)) { + return Status; + } + } + } + + Handle = ControllerHandle; + + // + // Make a copy of RemainingDevicePath to guanatee it is aligned + // + AlignedRemainingDevicePath = NULL; + if (RemainingDevicePath != NULL) { + AlignedRemainingDevicePath = DuplicateDevicePath (RemainingDevicePath); + + if (AlignedRemainingDevicePath == NULL) { + return EFI_OUT_OF_RESOURCES; + } + } + + // + // Connect all drivers to ControllerHandle + // If CoreConnectSingleController returns EFI_NOT_READY, then the number of + // Driver Binding Protocols in the handle database has increased during the call + // so the connect operation must be restarted + // + do { + ReturnStatus = CoreConnectSingleController ( + ControllerHandle, + DriverImageHandle, + AlignedRemainingDevicePath + ); + } while (ReturnStatus == EFI_NOT_READY); + + // + // Free the aligned copy of RemainingDevicePath + // + if (AlignedRemainingDevicePath != NULL) { + CoreFreePool (AlignedRemainingDevicePath); + } + + // + // If recursive, then connect all drivers to all of ControllerHandle's children + // + if (Recursive) { + // + // Acquire the protocol lock on the handle database so the child handles can be collected + // + CoreAcquireProtocolLock (); + + // + // Make sure the DriverBindingHandle is valid + // + Status = CoreValidateHandle (ControllerHandle); + if (EFI_ERROR (Status)) { + // + // Release the protocol lock on the handle database + // + CoreReleaseProtocolLock (); + + return ReturnStatus; + } + + + // + // Count ControllerHandle's children + // + for (Link = Handle->Protocols.ForwardLink, ChildHandleCount = 0; Link != &Handle->Protocols; Link = Link->ForwardLink) { + Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE); + for (ProtLink = Prot->OpenList.ForwardLink; + ProtLink != &Prot->OpenList; + ProtLink = ProtLink->ForwardLink) { + OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); + if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { + ChildHandleCount++; + } + } + } + + // + // Allocate a handle buffer for ControllerHandle's children + // + ChildHandleBuffer = AllocatePool (ChildHandleCount * sizeof(EFI_HANDLE)); + if (ChildHandleBuffer == NULL) { + CoreReleaseProtocolLock (); + return EFI_OUT_OF_RESOURCES; + } + + // + // Fill in a handle buffer with ControllerHandle's children + // + for (Link = Handle->Protocols.ForwardLink, ChildHandleCount = 0; Link != &Handle->Protocols; Link = Link->ForwardLink) { + Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE); + for (ProtLink = Prot->OpenList.ForwardLink; + ProtLink != &Prot->OpenList; + ProtLink = ProtLink->ForwardLink) { + OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); + if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { + ChildHandleBuffer[ChildHandleCount] = OpenData->ControllerHandle; + ChildHandleCount++; + } + } + } + + // + // Release the protocol lock on the handle database + // + CoreReleaseProtocolLock (); + + // + // Recursively connect each child handle + // + for (Index = 0; Index < ChildHandleCount; Index++) { + CoreConnectController ( + ChildHandleBuffer[Index], + NULL, + NULL, + TRUE + ); + } + + // + // Free the handle buffer of ControllerHandle's children + // + CoreFreePool (ChildHandleBuffer); + } + + return ReturnStatus; +} + + +/** + Add Driver Binding Protocols from Context Driver Image Handles to sorted + Driver Binding Protocol list. + + @param DriverBindingHandle Handle of the driver binding + protocol. + @param NumberOfSortedDriverBindingProtocols Number Of sorted driver binding + protocols + @param SortedDriverBindingProtocols The sorted protocol list. + @param DriverBindingHandleCount Driver Binding Handle Count. + @param DriverBindingHandleBuffer The buffer of driver binding + protocol to be modified. + @param IsImageHandle Indicate whether + DriverBindingHandle is an image + handle + + @return None. + +**/ +VOID +AddSortedDriverBindingProtocol ( + IN EFI_HANDLE DriverBindingHandle, + IN OUT UINTN *NumberOfSortedDriverBindingProtocols, + IN OUT EFI_DRIVER_BINDING_PROTOCOL **SortedDriverBindingProtocols, + IN UINTN DriverBindingHandleCount, + IN OUT EFI_HANDLE *DriverBindingHandleBuffer, + IN BOOLEAN IsImageHandle + ) +{ + EFI_STATUS Status; + EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; + UINTN Index; + + // + // Make sure the DriverBindingHandle is valid + // + Status = CoreValidateHandle (DriverBindingHandle); + if (EFI_ERROR (Status)) { + return; + } + + // + // If IsImageHandle is TRUE, then DriverBindingHandle is an image handle + // Find all the DriverBindingHandles associated with that image handle and add them to the sorted list + // + if (IsImageHandle) { + // + // Loop through all the Driver Binding Handles + // + for (Index = 0; Index < DriverBindingHandleCount; Index++) { + // + // Retrieve the Driver Binding Protocol associated with each Driver Binding Handle + // + Status = CoreHandleProtocol ( + DriverBindingHandleBuffer[Index], + &gEfiDriverBindingProtocolGuid, + (VOID **) &DriverBinding + ); + if (EFI_ERROR (Status) || DriverBinding == NULL) { + continue; + } + + // + // If the ImageHandle associated with DriverBinding matches DriverBindingHandle, + // then add the DriverBindingProtocol[Index] to the sorted list + // + if (DriverBinding->ImageHandle == DriverBindingHandle) { + AddSortedDriverBindingProtocol ( + DriverBindingHandleBuffer[Index], + NumberOfSortedDriverBindingProtocols, + SortedDriverBindingProtocols, + DriverBindingHandleCount, + DriverBindingHandleBuffer, + FALSE + ); + } + } + return; + } + + // + // Retrieve the Driver Binding Protocol from DriverBindingHandle + // + Status = CoreHandleProtocol( + DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, + (VOID **) &DriverBinding + ); + // + // If DriverBindingHandle does not support the Driver Binding Protocol then return + // + if (EFI_ERROR (Status) || DriverBinding == NULL) { + return; + } + + // + // See if DriverBinding is already in the sorted list + // + for (Index = 0; Index < *NumberOfSortedDriverBindingProtocols && Index < DriverBindingHandleCount; Index++) { + if (DriverBinding == SortedDriverBindingProtocols[Index]) { + return; + } + } + + // + // Add DriverBinding to the end of the list + // + if (*NumberOfSortedDriverBindingProtocols < DriverBindingHandleCount) { + SortedDriverBindingProtocols[*NumberOfSortedDriverBindingProtocols] = DriverBinding; + } + *NumberOfSortedDriverBindingProtocols = *NumberOfSortedDriverBindingProtocols + 1; + + // + // Mark the cooresponding handle in DriverBindingHandleBuffer as used + // + for (Index = 0; Index < DriverBindingHandleCount; Index++) { + if (DriverBindingHandleBuffer[Index] == DriverBindingHandle) { + DriverBindingHandleBuffer[Index] = NULL; + } + } +} + + +/** + Connects a controller to a driver. + + @param ControllerHandle Handle of the controller to be + connected. + @param ContextDriverImageHandles DriverImageHandle A pointer to an + ordered list of driver image + handles. + @param RemainingDevicePath RemainingDevicePath A pointer to + the device path that specifies a + child of the controller + specified by ControllerHandle. + + @retval EFI_SUCCESS One or more drivers were + connected to ControllerHandle. + @retval EFI_OUT_OF_RESOURCES No enough system resources to + complete the request. + @retval EFI_NOT_FOUND No drivers were connected to + ControllerHandle. + +**/ +EFI_STATUS +CoreConnectSingleController ( + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE *ContextDriverImageHandles OPTIONAL, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +{ + EFI_STATUS Status; + UINTN Index; + EFI_HANDLE DriverImageHandle; + EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *PlatformDriverOverride; + EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride; + UINTN DriverBindingHandleCount; + EFI_HANDLE *DriverBindingHandleBuffer; + UINTN NewDriverBindingHandleCount; + EFI_HANDLE *NewDriverBindingHandleBuffer; + EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; + EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL *DriverFamilyOverride; + UINTN NumberOfSortedDriverBindingProtocols; + EFI_DRIVER_BINDING_PROTOCOL **SortedDriverBindingProtocols; + UINT32 DriverFamilyOverrideVersion; + UINT32 HighestVersion; + UINTN HighestIndex; + UINTN SortIndex; + BOOLEAN OneStarted; + BOOLEAN DriverFound; + + // + // Initialize local variables + // + DriverBindingHandleCount = 0; + DriverBindingHandleBuffer = NULL; + NumberOfSortedDriverBindingProtocols = 0; + SortedDriverBindingProtocols = NULL; + PlatformDriverOverride = NULL; + NewDriverBindingHandleBuffer = NULL; + + // + // Get list of all Driver Binding Protocol Instances + // + Status = CoreLocateHandleBuffer ( + ByProtocol, + &gEfiDriverBindingProtocolGuid, + NULL, + &DriverBindingHandleCount, + &DriverBindingHandleBuffer + ); + if (EFI_ERROR (Status) || (DriverBindingHandleCount == 0)) { + return EFI_NOT_FOUND; + } + + // + // Allocate a duplicate array for the sorted Driver Binding Protocol Instances + // + SortedDriverBindingProtocols = AllocatePool (sizeof (VOID *) * DriverBindingHandleCount); + if (SortedDriverBindingProtocols == NULL) { + CoreFreePool (DriverBindingHandleBuffer); + return EFI_OUT_OF_RESOURCES; + } + + // + // Add Driver Binding Protocols from Context Driver Image Handles first + // + if (ContextDriverImageHandles != NULL) { + for (Index = 0; ContextDriverImageHandles[Index] != NULL; Index++) { + AddSortedDriverBindingProtocol ( + ContextDriverImageHandles[Index], + &NumberOfSortedDriverBindingProtocols, + SortedDriverBindingProtocols, + DriverBindingHandleCount, + DriverBindingHandleBuffer, + FALSE + ); + } + } + + // + // Add the Platform Driver Override Protocol drivers for ControllerHandle next + // + Status = CoreLocateProtocol ( + &gEfiPlatformDriverOverrideProtocolGuid, + NULL, + (VOID **) &PlatformDriverOverride + ); + if (!EFI_ERROR (Status) && (PlatformDriverOverride != NULL)) { + DriverImageHandle = NULL; + do { + Status = PlatformDriverOverride->GetDriver ( + PlatformDriverOverride, + ControllerHandle, + &DriverImageHandle + ); + if (!EFI_ERROR (Status)) { + AddSortedDriverBindingProtocol ( + DriverImageHandle, + &NumberOfSortedDriverBindingProtocols, + SortedDriverBindingProtocols, + DriverBindingHandleCount, + DriverBindingHandleBuffer, + TRUE + ); + } + } while (!EFI_ERROR (Status)); + } + + // + // Add the Driver Family Override Protocol drivers for ControllerHandle + // + while (TRUE) { + HighestIndex = DriverBindingHandleCount; + HighestVersion = 0; + for (Index = 0; Index < DriverBindingHandleCount; Index++) { + Status = CoreHandleProtocol ( + DriverBindingHandleBuffer[Index], + &gEfiDriverFamilyOverrideProtocolGuid, + (VOID **) &DriverFamilyOverride + ); + if (!EFI_ERROR (Status) && (DriverFamilyOverride != NULL)) { + DriverFamilyOverrideVersion = DriverFamilyOverride->GetVersion (DriverFamilyOverride); + if ((HighestIndex == DriverBindingHandleCount) || (DriverFamilyOverrideVersion > HighestVersion)) { + HighestVersion = DriverFamilyOverrideVersion; + HighestIndex = Index; + } + } + } + + if (HighestIndex == DriverBindingHandleCount) { + break; + } + + AddSortedDriverBindingProtocol ( + DriverBindingHandleBuffer[HighestIndex], + &NumberOfSortedDriverBindingProtocols, + SortedDriverBindingProtocols, + DriverBindingHandleCount, + DriverBindingHandleBuffer, + FALSE + ); + } + + // + // Get the Bus Specific Driver Override Protocol instance on the Controller Handle + // + Status = CoreHandleProtocol ( + ControllerHandle, + &gEfiBusSpecificDriverOverrideProtocolGuid, + (VOID **) &BusSpecificDriverOverride + ); + if (!EFI_ERROR (Status) && (BusSpecificDriverOverride != NULL)) { + DriverImageHandle = NULL; + do { + Status = BusSpecificDriverOverride->GetDriver ( + BusSpecificDriverOverride, + &DriverImageHandle + ); + if (!EFI_ERROR (Status)) { + AddSortedDriverBindingProtocol ( + DriverImageHandle, + &NumberOfSortedDriverBindingProtocols, + SortedDriverBindingProtocols, + DriverBindingHandleCount, + DriverBindingHandleBuffer, + TRUE + ); + } + } while (!EFI_ERROR (Status)); + } + + // + // Then add all the remaining Driver Binding Protocols + // + SortIndex = NumberOfSortedDriverBindingProtocols; + for (Index = 0; Index < DriverBindingHandleCount; Index++) { + AddSortedDriverBindingProtocol ( + DriverBindingHandleBuffer[Index], + &NumberOfSortedDriverBindingProtocols, + SortedDriverBindingProtocols, + DriverBindingHandleCount, + DriverBindingHandleBuffer, + FALSE + ); + } + + // + // Free the Driver Binding Handle Buffer + // + CoreFreePool (DriverBindingHandleBuffer); + + // + // If the number of Driver Binding Protocols has increased since this function started, then return + // EFI_NOT_READY, so it will be restarted + // + Status = CoreLocateHandleBuffer ( + ByProtocol, + &gEfiDriverBindingProtocolGuid, + NULL, + &NewDriverBindingHandleCount, + &NewDriverBindingHandleBuffer + ); + CoreFreePool (NewDriverBindingHandleBuffer); + if (NewDriverBindingHandleCount > DriverBindingHandleCount) { + // + // Free any buffers that were allocated with AllocatePool() + // + CoreFreePool (SortedDriverBindingProtocols); + + return EFI_NOT_READY; + } + + // + // Sort the remaining DriverBinding Protocol based on their Version field from + // highest to lowest. + // + for ( ; SortIndex < NumberOfSortedDriverBindingProtocols; SortIndex++) { + HighestVersion = SortedDriverBindingProtocols[SortIndex]->Version; + HighestIndex = SortIndex; + for (Index = SortIndex + 1; Index < NumberOfSortedDriverBindingProtocols; Index++) { + if (SortedDriverBindingProtocols[Index]->Version > HighestVersion) { + HighestVersion = SortedDriverBindingProtocols[Index]->Version; + HighestIndex = Index; + } + } + if (SortIndex != HighestIndex) { + DriverBinding = SortedDriverBindingProtocols[SortIndex]; + SortedDriverBindingProtocols[SortIndex] = SortedDriverBindingProtocols[HighestIndex]; + SortedDriverBindingProtocols[HighestIndex] = DriverBinding; + } + } + + // + // Loop until no more drivers can be started on ControllerHandle + // + OneStarted = FALSE; + do { + + // + // Loop through the sorted Driver Binding Protocol Instances in order, and see if + // any of the Driver Binding Protocols support the controller specified by + // ControllerHandle. + // + DriverBinding = NULL; + DriverFound = FALSE; + for (Index = 0; (Index < NumberOfSortedDriverBindingProtocols) && !DriverFound; Index++) { + if (SortedDriverBindingProtocols[Index] != NULL) { + DriverBinding = SortedDriverBindingProtocols[Index]; + Status = DriverBinding->Supported( + DriverBinding, + ControllerHandle, + RemainingDevicePath + ); + if (!EFI_ERROR (Status)) { + SortedDriverBindingProtocols[Index] = NULL; + DriverFound = TRUE; + + // + // A driver was found that supports ControllerHandle, so attempt to start the driver + // on ControllerHandle. + // + Status = DriverBinding->Start ( + DriverBinding, + ControllerHandle, + RemainingDevicePath + ); + if (!EFI_ERROR (Status)) { + // + // The driver was successfully started on ControllerHandle, so set a flag + // + OneStarted = TRUE; + } + } + } + } + } while (DriverFound); + + // + // Free any buffers that were allocated with AllocatePool() + // + CoreFreePool (SortedDriverBindingProtocols); + + // + // If at least one driver was started on ControllerHandle, then return EFI_SUCCESS. + // + if (OneStarted) { + return EFI_SUCCESS; + } + + // + // If no drivers started and RemainingDevicePath is an End Device Path Node, then return EFI_SUCCESS + // + if (RemainingDevicePath != NULL) { + if (IsDevicePathEnd (RemainingDevicePath)) { + return EFI_SUCCESS; + } + } + + // + // Otherwise, no drivers were started on ControllerHandle, so return EFI_NOT_FOUND + // + return EFI_NOT_FOUND; +} + + + +/** + Disonnects a controller from a driver + + @param ControllerHandle ControllerHandle The handle of + the controller from which + driver(s) are to be + disconnected. + @param DriverImageHandle DriverImageHandle The driver to + disconnect from ControllerHandle. + @param ChildHandle ChildHandle The handle of the + child to destroy. + + @retval EFI_SUCCESS One or more drivers were + disconnected from the controller. + @retval EFI_SUCCESS On entry, no drivers are managing + ControllerHandle. + @retval EFI_SUCCESS DriverImageHandle is not NULL, + and on entry DriverImageHandle is + not managing ControllerHandle. + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + @retval EFI_INVALID_PARAMETER DriverImageHandle is not NULL, + and it is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL, and it + is not a valid EFI_HANDLE. + @retval EFI_OUT_OF_RESOURCES There are not enough resources + available to disconnect any + drivers from ControllerHandle. + @retval EFI_DEVICE_ERROR The controller could not be + disconnected because of a device + error. + +**/ +EFI_STATUS +EFIAPI +CoreDisconnectController ( + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE DriverImageHandle OPTIONAL, + IN EFI_HANDLE ChildHandle OPTIONAL + ) +{ + EFI_STATUS Status; + IHANDLE *Handle; + EFI_HANDLE *DriverImageHandleBuffer; + EFI_HANDLE *ChildBuffer; + UINTN Index; + UINTN HandleIndex; + UINTN DriverImageHandleCount; + UINTN ChildrenToStop; + UINTN ChildBufferCount; + UINTN StopCount; + BOOLEAN Duplicate; + BOOLEAN ChildHandleValid; + BOOLEAN DriverImageHandleValid; + LIST_ENTRY *Link; + LIST_ENTRY *ProtLink; + OPEN_PROTOCOL_DATA *OpenData; + PROTOCOL_INTERFACE *Prot; + EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; + + // + // Make sure ControllerHandle is valid + // + Status = CoreValidateHandle (ControllerHandle); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Make sure ChildHandle is valid if it is not NULL + // + if (ChildHandle != NULL) { + Status = CoreValidateHandle (ChildHandle); + if (EFI_ERROR (Status)) { + return Status; + } + } + + Handle = ControllerHandle; + + // + // Get list of drivers that are currently managing ControllerHandle + // + DriverImageHandleBuffer = NULL; + DriverImageHandleCount = 1; + + if (DriverImageHandle == NULL) { + // + // Look at each protocol interface for a match + // + DriverImageHandleCount = 0; + + CoreAcquireProtocolLock (); + for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) { + Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE); + for (ProtLink = Prot->OpenList.ForwardLink; + ProtLink != &Prot->OpenList; + ProtLink = ProtLink->ForwardLink) { + OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); + if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) { + DriverImageHandleCount++; + } + } + } + CoreReleaseProtocolLock (); + + // + // If there are no drivers managing this controller, then return EFI_SUCCESS + // + if (DriverImageHandleCount == 0) { + Status = EFI_SUCCESS; + goto Done; + } + + DriverImageHandleBuffer = AllocatePool (sizeof (EFI_HANDLE) * DriverImageHandleCount); + if (DriverImageHandleBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + DriverImageHandleCount = 0; + + CoreAcquireProtocolLock (); + for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) { + Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE); + for (ProtLink = Prot->OpenList.ForwardLink; + ProtLink != &Prot->OpenList; + ProtLink = ProtLink->ForwardLink) { + OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); + if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) { + Duplicate = FALSE; + for (Index = 0; Index< DriverImageHandleCount; Index++) { + if (DriverImageHandleBuffer[Index] == OpenData->AgentHandle) { + Duplicate = TRUE; + break; + } + } + if (!Duplicate) { + DriverImageHandleBuffer[DriverImageHandleCount] = OpenData->AgentHandle; + DriverImageHandleCount++; + } + } + } + } + CoreReleaseProtocolLock (); + } + + StopCount = 0; + for (HandleIndex = 0; HandleIndex < DriverImageHandleCount; HandleIndex++) { + + if (DriverImageHandleBuffer != NULL) { + DriverImageHandle = DriverImageHandleBuffer[HandleIndex]; + } + + // + // Get the Driver Binding Protocol of the driver that is managing this controller + // + Status = CoreHandleProtocol ( + DriverImageHandle, + &gEfiDriverBindingProtocolGuid, + (VOID **)&DriverBinding + ); + if (EFI_ERROR (Status) || DriverBinding == NULL) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + // + // Look at each protocol interface for a match + // + DriverImageHandleValid = FALSE; + ChildBufferCount = 0; + + CoreAcquireProtocolLock (); + for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) { + Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE); + for (ProtLink = Prot->OpenList.ForwardLink; + ProtLink != &Prot->OpenList; + ProtLink = ProtLink->ForwardLink) { + OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); + if (OpenData->AgentHandle == DriverImageHandle) { + if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { + ChildBufferCount++; + } + if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) { + DriverImageHandleValid = TRUE; + } + } + } + } + CoreReleaseProtocolLock (); + + if (DriverImageHandleValid) { + ChildHandleValid = FALSE; + ChildBuffer = NULL; + if (ChildBufferCount != 0) { + ChildBuffer = AllocatePool (sizeof (EFI_HANDLE) * ChildBufferCount); + if (ChildBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + ChildBufferCount = 0; + + CoreAcquireProtocolLock (); + for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) { + Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE); + for (ProtLink = Prot->OpenList.ForwardLink; + ProtLink != &Prot->OpenList; + ProtLink = ProtLink->ForwardLink) { + OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); + if ((OpenData->AgentHandle == DriverImageHandle) && + ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0)) { + Duplicate = FALSE; + for (Index = 0; Index < ChildBufferCount; Index++) { + if (ChildBuffer[Index] == OpenData->ControllerHandle) { + Duplicate = TRUE; + break; + } + } + if (!Duplicate) { + ChildBuffer[ChildBufferCount] = OpenData->ControllerHandle; + if (ChildHandle == ChildBuffer[ChildBufferCount]) { + ChildHandleValid = TRUE; + } + ChildBufferCount++; + } + } + } + } + CoreReleaseProtocolLock (); + } + + if (ChildHandle == NULL || ChildHandleValid) { + ChildrenToStop = 0; + Status = EFI_SUCCESS; + if (ChildBufferCount > 0) { + if (ChildHandle != NULL) { + ChildrenToStop = 1; + Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, &ChildHandle); + } else { + ChildrenToStop = ChildBufferCount; + Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, ChildBuffer); + } + } + if (!EFI_ERROR (Status) && ((ChildHandle == NULL) || (ChildBufferCount == ChildrenToStop))) { + Status = DriverBinding->Stop (DriverBinding, ControllerHandle, 0, NULL); + } + if (!EFI_ERROR (Status)) { + StopCount++; + } + } + + if (ChildBuffer != NULL) { + CoreFreePool (ChildBuffer); + } + } + } + + if (StopCount > 0) { + Status = EFI_SUCCESS; + } else { + Status = EFI_NOT_FOUND; + } + +Done: + + if (DriverImageHandleBuffer != NULL) { + CoreFreePool (DriverImageHandleBuffer); + } + + return Status; +} diff --git a/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/DxeMain.h b/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/DxeMain.h new file mode 100644 index 0000000..966c285 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/DxeMain.h @@ -0,0 +1,2949 @@ +/** @file + The internal header file includes the common header files, defines + internal structure and functions used by DxeCore module. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _DXE_MAIN_H_ +#define _DXE_MAIN_H_ + + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +// +// attributes for reserved memory before it is promoted to system memory +// +#define EFI_MEMORY_PRESENT 0x0100000000000000ULL +#define EFI_MEMORY_INITIALIZED 0x0200000000000000ULL +#define EFI_MEMORY_TESTED 0x0400000000000000ULL + +// +// range for memory mapped port I/O on IPF +// +#define EFI_MEMORY_PORT_IO 0x4000000000000000ULL + + +/// +/// EFI_DEP_REPLACE_TRUE - Used to dynamically patch the dependency expression +/// to save time. A EFI_DEP_PUSH is evaluated one an +/// replaced with EFI_DEP_REPLACE_TRUE. If PI spec's Vol 2 +/// Driver Execution Environment Core Interface use 0xff +/// as new DEPEX opcode. EFI_DEP_REPLACE_TRUE should be +/// defined to a new value that is not conflicting with PI spec. +/// +#define EFI_DEP_REPLACE_TRUE 0xff + +/// +/// Define the initial size of the dependency expression evaluation stack +/// +#define DEPEX_STACK_SIZE_INCREMENT 0x1000 + +typedef struct { + EFI_GUID *ProtocolGuid; + VOID **Protocol; + EFI_EVENT Event; + VOID *Registration; + BOOLEAN Present; +} EFI_CORE_PROTOCOL_NOTIFY_ENTRY; + +// +// DXE Dispatcher Data structures +// + +#define KNOWN_HANDLE_SIGNATURE SIGNATURE_32('k','n','o','w') +typedef struct { + UINTN Signature; + LIST_ENTRY Link; // mFvHandleList + EFI_HANDLE Handle; + EFI_GUID FvNameGuid; +} KNOWN_HANDLE; + + +#define EFI_CORE_DRIVER_ENTRY_SIGNATURE SIGNATURE_32('d','r','v','r') +typedef struct { + UINTN Signature; + LIST_ENTRY Link; // mDriverList + + LIST_ENTRY ScheduledLink; // mScheduledQueue + + EFI_HANDLE FvHandle; + EFI_GUID FileName; + EFI_DEVICE_PATH_PROTOCOL *FvFileDevicePath; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; + + VOID *Depex; + UINTN DepexSize; + + BOOLEAN Before; + BOOLEAN After; + EFI_GUID BeforeAfterGuid; + + BOOLEAN Dependent; + BOOLEAN Unrequested; + BOOLEAN Scheduled; + BOOLEAN Untrusted; + BOOLEAN Initialized; + BOOLEAN DepexProtocolError; + + EFI_HANDLE ImageHandle; + BOOLEAN IsFvImage; + +} EFI_CORE_DRIVER_ENTRY; + +// +//The data structure of GCD memory map entry +// +#define EFI_GCD_MAP_SIGNATURE SIGNATURE_32('g','c','d','m') +typedef struct { + UINTN Signature; + LIST_ENTRY Link; + EFI_PHYSICAL_ADDRESS BaseAddress; + UINT64 EndAddress; + UINT64 Capabilities; + UINT64 Attributes; + EFI_GCD_MEMORY_TYPE GcdMemoryType; + EFI_GCD_IO_TYPE GcdIoType; + EFI_HANDLE ImageHandle; + EFI_HANDLE DeviceHandle; +} EFI_GCD_MAP_ENTRY; + + +#define LOADED_IMAGE_PRIVATE_DATA_SIGNATURE SIGNATURE_32('l','d','r','i') + +typedef struct { + UINTN Signature; + /// Image handle + EFI_HANDLE Handle; + /// Image type + UINTN Type; + /// If entrypoint has been called + BOOLEAN Started; + /// The image's entry point + EFI_IMAGE_ENTRY_POINT EntryPoint; + /// loaded image protocol + EFI_LOADED_IMAGE_PROTOCOL Info; + /// Location in memory + EFI_PHYSICAL_ADDRESS ImageBasePage; + /// Number of pages + UINTN NumberOfPages; + /// Original fixup data + CHAR8 *FixupData; + /// Tpl of started image + EFI_TPL Tpl; + /// Status returned by started image + EFI_STATUS Status; + /// Size of ExitData from started image + UINTN ExitDataSize; + /// Pointer to exit data from started image + VOID *ExitData; + /// Pointer to pool allocation for context save/restore + VOID *JumpBuffer; + /// Pointer to buffer for context save/restore + BASE_LIBRARY_JUMP_BUFFER *JumpContext; + /// Machine type from PE image + UINT16 Machine; + /// EBC Protocol pointer + EFI_EBC_PROTOCOL *Ebc; + /// Runtime image list + EFI_RUNTIME_IMAGE_ENTRY *RuntimeData; + /// Pointer to Loaded Image Device Path Protocol + EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath; + /// PeCoffLoader ImageContext + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + /// Status returned by LoadImage() service. + EFI_STATUS LoadImageStatus; +} LOADED_IMAGE_PRIVATE_DATA; + +#define LOADED_IMAGE_PRIVATE_DATA_FROM_THIS(a) \ + CR(a, LOADED_IMAGE_PRIVATE_DATA, Info, LOADED_IMAGE_PRIVATE_DATA_SIGNATURE) + +#define IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE SIGNATURE_32 ('I','P','R','C') + +typedef struct { + UINT32 Signature; + LIST_ENTRY Link; + EFI_PHYSICAL_ADDRESS CodeSegmentBase; + UINT64 CodeSegmentSize; +} IMAGE_PROPERTIES_RECORD_CODE_SECTION; + +#define IMAGE_PROPERTIES_RECORD_SIGNATURE SIGNATURE_32 ('I','P','R','D') + +typedef struct { + UINT32 Signature; + LIST_ENTRY Link; + EFI_PHYSICAL_ADDRESS ImageBase; + UINT64 ImageSize; + UINTN CodeSegmentCount; + LIST_ENTRY CodeSegmentList; +} IMAGE_PROPERTIES_RECORD; + +// +// DXE Core Global Variables +// +extern EFI_SYSTEM_TABLE *gDxeCoreST; +extern EFI_RUNTIME_SERVICES *gDxeCoreRT; +extern EFI_DXE_SERVICES *gDxeCoreDS; +extern EFI_HANDLE gDxeCoreImageHandle; + +extern BOOLEAN gMemoryMapTerminated; + +extern EFI_DECOMPRESS_PROTOCOL gEfiDecompress; + +extern EFI_RUNTIME_ARCH_PROTOCOL *gRuntime; +extern EFI_CPU_ARCH_PROTOCOL *gCpu; +extern EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *gWatchdogTimer; +extern EFI_METRONOME_ARCH_PROTOCOL *gMetronome; +extern EFI_TIMER_ARCH_PROTOCOL *gTimer; +extern EFI_SECURITY_ARCH_PROTOCOL *gSecurity; +extern EFI_SECURITY2_ARCH_PROTOCOL *gSecurity2; +extern EFI_BDS_ARCH_PROTOCOL *gBds; +extern EFI_SMM_BASE2_PROTOCOL *gSmmBase2; + +extern EFI_TPL gEfiCurrentTpl; + +extern EFI_GUID *gDxeCoreFileName; +extern EFI_LOADED_IMAGE_PROTOCOL *gDxeCoreLoadedImage; + +extern EFI_MEMORY_TYPE_INFORMATION gMemoryTypeInformation[EfiMaxMemoryType + 1]; + +extern BOOLEAN gDispatcherRunning; +extern EFI_RUNTIME_ARCH_PROTOCOL gRuntimeTemplate; + +extern EFI_LOAD_FIXED_ADDRESS_CONFIGURATION_TABLE gLoadModuleAtFixAddressConfigurationTable; +extern BOOLEAN gLoadFixedAddressCodeMemoryReady; +// +// Service Initialization Functions +// + + + +/** + Called to initialize the pool. + +**/ +VOID +CoreInitializePool ( + VOID + ); + + +/** + Called to initialize the memory map and add descriptors to + the current descriptor list. + The first descriptor that is added must be general usable + memory as the addition allocates heap. + + @param Type The type of memory to add + @param Start The starting address in the memory range Must be + page aligned + @param NumberOfPages The number of pages in the range + @param Attribute Attributes of the memory to add + + @return None. The range is added to the memory map + +**/ +VOID +CoreAddMemoryDescriptor ( + IN EFI_MEMORY_TYPE Type, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 NumberOfPages, + IN UINT64 Attribute + ); + + +/** + Release memory lock on mGcdMemorySpaceLock. + +**/ +VOID +CoreReleaseGcdMemoryLock ( + VOID + ); + + +/** + Acquire memory lock on mGcdMemorySpaceLock. + +**/ +VOID +CoreAcquireGcdMemoryLock ( + VOID + ); + + +/** + External function. Initializes memory services based on the memory + descriptor HOBs. This function is responsible for priming the memory + map, so memory allocations and resource allocations can be made. + The first part of this function can not depend on any memory services + until at least one memory descriptor is provided to the memory services. + + @param HobStart The start address of the HOB. + @param MemoryBaseAddress Start address of memory region found to init DXE + core. + @param MemoryLength Length of memory region found to init DXE core. + + @retval EFI_SUCCESS Memory services successfully initialized. + +**/ +EFI_STATUS +CoreInitializeMemoryServices ( + IN VOID **HobStart, + OUT EFI_PHYSICAL_ADDRESS *MemoryBaseAddress, + OUT UINT64 *MemoryLength + ); + + + +/** + External function. Initializes the GCD and memory services based on the memory + descriptor HOBs. This function is responsible for priming the GCD map and the + memory map, so memory allocations and resource allocations can be made. The + HobStart will be relocated to a pool buffer. + + @param HobStart The start address of the HOB + @param MemoryBaseAddress Start address of memory region found to init DXE + core. + @param MemoryLength Length of memory region found to init DXE core. + + @retval EFI_SUCCESS GCD services successfully initialized. + +**/ +EFI_STATUS +CoreInitializeGcdServices ( + IN OUT VOID **HobStart, + IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress, + IN UINT64 MemoryLength + ); + + +/** + Initializes "event" support. + + @retval EFI_SUCCESS Always return success + +**/ +EFI_STATUS +CoreInitializeEventServices ( + VOID + ); + + +/** + Add the Image Services to EFI Boot Services Table and install the protocol + interfaces for this image. + + @param HobStart The HOB to initialize + + @return Status code. + +**/ +EFI_STATUS +CoreInitializeImageServices ( + IN VOID *HobStart + ); + + +/** + Creates an event that is fired everytime a Protocol of a specific type is installed. + +**/ +VOID +CoreNotifyOnProtocolInstallation ( + VOID + ); + + +/** + Return TRUE if all AP services are available. + + @retval EFI_SUCCESS All AP services are available + @retval EFI_NOT_FOUND At least one AP service is not available + +**/ +EFI_STATUS +CoreAllEfiServicesAvailable ( + VOID + ); + + +/** + Calcualte the 32-bit CRC in a EFI table using the service provided by the + gRuntime service. + + @param Hdr Pointer to an EFI standard header + +**/ +VOID +CalculateEfiHdrCrc ( + IN OUT EFI_TABLE_HEADER *Hdr + ); + + +/** + Called by the platform code to process a tick. + + @param Duration The number of 100ns elapsed since the last call + to TimerTick + +**/ +VOID +EFIAPI +CoreTimerTick ( + IN UINT64 Duration + ); + + +/** + Initialize the dispatcher. Initialize the notification function that runs when + an FV2 protocol is added to the system. + +**/ +VOID +CoreInitializeDispatcher ( + VOID + ); + + +/** + This is the POSTFIX version of the dependency evaluator. This code does + not need to handle Before or After, as it is not valid to call this + routine in this case. The SOR is just ignored and is a nop in the grammer. + POSTFIX means all the math is done on top of the stack. + + @param DriverEntry DriverEntry element to update. + + @retval TRUE If driver is ready to run. + @retval FALSE If driver is not ready to run or some fatal error + was found. + +**/ +BOOLEAN +CoreIsSchedulable ( + IN EFI_CORE_DRIVER_ENTRY *DriverEntry + ); + + +/** + Preprocess dependency expression and update DriverEntry to reflect the + state of Before, After, and SOR dependencies. If DriverEntry->Before + or DriverEntry->After is set it will never be cleared. If SOR is set + it will be cleared by CoreSchedule(), and then the driver can be + dispatched. + + @param DriverEntry DriverEntry element to update . + + @retval EFI_SUCCESS It always works. + +**/ +EFI_STATUS +CorePreProcessDepex ( + IN EFI_CORE_DRIVER_ENTRY *DriverEntry + ); + + + +/** + Terminates all boot services. + + @param ImageHandle Handle that identifies the exiting image. + @param MapKey Key to the latest memory map. + + @retval EFI_SUCCESS Boot Services terminated + @retval EFI_INVALID_PARAMETER MapKey is incorrect. + +**/ +EFI_STATUS +EFIAPI +CoreExitBootServices ( + IN EFI_HANDLE ImageHandle, + IN UINTN MapKey + ); + + +/** + Make sure the memory map is following all the construction rules, + it is the last time to check memory map error before exit boot services. + + @param MapKey Memory map key + + @retval EFI_INVALID_PARAMETER Memory map not consistent with construction + rules. + @retval EFI_SUCCESS Valid memory map. + +**/ +EFI_STATUS +CoreTerminateMemoryMap ( + IN UINTN MapKey + ); + + +/** + Signals all events in the EventGroup. + + @param EventGroup The list to signal + +**/ +VOID +CoreNotifySignalList ( + IN EFI_GUID *EventGroup + ); + + + +/** + Boot Service called to add, modify, or remove a system configuration table from + the EFI System Table. + + @param Guid Pointer to the GUID for the entry to add, update, or + remove + @param Table Pointer to the configuration table for the entry to add, + update, or remove, may be NULL. + + @return EFI_SUCCESS Guid, Table pair added, updated, or removed. + @return EFI_INVALID_PARAMETER Input GUID not valid. + @return EFI_NOT_FOUND Attempted to delete non-existant entry + @return EFI_OUT_OF_RESOURCES Not enough memory available + +**/ +EFI_STATUS +EFIAPI +CoreInstallConfigurationTable ( + IN EFI_GUID *Guid, + IN VOID *Table + ); + + + +/** + Raise the task priority level to the new level. + High level is implemented by disabling processor interrupts. + + @param NewTpl New task priority level + + @return The previous task priority level + +**/ +EFI_TPL +EFIAPI +CoreRaiseTpl ( + IN EFI_TPL NewTpl + ); + + + +/** + Lowers the task priority to the previous value. If the new + priority unmasks events at a higher priority, they are dispatched. + + @param NewTpl New, lower, task priority + +**/ +VOID +EFIAPI +CoreRestoreTpl ( + IN EFI_TPL NewTpl + ); + + + +/** + Introduces a fine-grained stall. + + @param Microseconds The number of microseconds to stall execution. + + @retval EFI_SUCCESS Execution was stalled for at least the requested + amount of microseconds. + @retval EFI_NOT_AVAILABLE_YET gMetronome is not available yet + +**/ +EFI_STATUS +EFIAPI +CoreStall ( + IN UINTN Microseconds + ); + + + +/** + Sets the system's watchdog timer. + + @param Timeout The number of seconds to set the watchdog timer to. + A value of zero disables the timer. + @param WatchdogCode The numeric code to log on a watchdog timer timeout + event. The firmware reserves codes 0x0000 to 0xFFFF. + Loaders and operating systems may use other timeout + codes. + @param DataSize The size, in bytes, of WatchdogData. + @param WatchdogData A data buffer that includes a Null-terminated Unicode + string, optionally followed by additional binary data. + The string is a description that the call may use to + further indicate the reason to be logged with a + watchdog event. + + @return EFI_SUCCESS Timeout has been set + @return EFI_NOT_AVAILABLE_YET WatchdogTimer is not available yet + @return EFI_UNSUPPORTED System does not have a timer (currently not used) + @return EFI_DEVICE_ERROR Could not complete due to hardware error + +**/ +EFI_STATUS +EFIAPI +CoreSetWatchdogTimer ( + IN UINTN Timeout, + IN UINT64 WatchdogCode, + IN UINTN DataSize, + IN CHAR16 *WatchdogData OPTIONAL + ); + + + +/** + Wrapper function to CoreInstallProtocolInterfaceNotify. This is the public API which + Calls the private one which contains a BOOLEAN parameter for notifications + + @param UserHandle The handle to install the protocol handler on, + or NULL if a new handle is to be allocated + @param Protocol The protocol to add to the handle + @param InterfaceType Indicates whether Interface is supplied in + native form. + @param Interface The interface for the protocol being added + + @return Status code + +**/ +EFI_STATUS +EFIAPI +CoreInstallProtocolInterface ( + IN OUT EFI_HANDLE *UserHandle, + IN EFI_GUID *Protocol, + IN EFI_INTERFACE_TYPE InterfaceType, + IN VOID *Interface + ); + + +/** + Installs a protocol interface into the boot services environment. + + @param UserHandle The handle to install the protocol handler on, + or NULL if a new handle is to be allocated + @param Protocol The protocol to add to the handle + @param InterfaceType Indicates whether Interface is supplied in + native form. + @param Interface The interface for the protocol being added + @param Notify indicates whether notify the notification list + for this protocol + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate + @retval EFI_SUCCESS Protocol interface successfully installed + +**/ +EFI_STATUS +CoreInstallProtocolInterfaceNotify ( + IN OUT EFI_HANDLE *UserHandle, + IN EFI_GUID *Protocol, + IN EFI_INTERFACE_TYPE InterfaceType, + IN VOID *Interface, + IN BOOLEAN Notify + ); + + + +/** + Installs a list of protocol interface into the boot services environment. + This function calls InstallProtocolInterface() in a loop. If any error + occures all the protocols added by this function are removed. This is + basically a lib function to save space. + + @param Handle The handle to install the protocol handlers on, + or NULL if a new handle is to be allocated + @param ... EFI_GUID followed by protocol instance. A NULL + terminates the list. The pairs are the + arguments to InstallProtocolInterface(). All the + protocols are added to Handle. + + @retval EFI_SUCCESS All the protocol interface was installed. + @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols. + @retval EFI_ALREADY_STARTED A Device Path Protocol instance was passed in that is already present in + the handle database. + @retval EFI_INVALID_PARAMETER Handle is NULL. + @retval EFI_INVALID_PARAMETER Protocol is already installed on the handle specified by Handle. + +**/ +EFI_STATUS +EFIAPI +CoreInstallMultipleProtocolInterfaces ( + IN OUT EFI_HANDLE *Handle, + ... + ); + + + +/** + Uninstalls a list of protocol interface in the boot services environment. + This function calls UnisatllProtocolInterface() in a loop. This is + basically a lib function to save space. + + @param Handle The handle to uninstall the protocol + @param ... EFI_GUID followed by protocol instance. A NULL + terminates the list. The pairs are the + arguments to UninstallProtocolInterface(). All + the protocols are added to Handle. + + @return Status code + +**/ +EFI_STATUS +EFIAPI +CoreUninstallMultipleProtocolInterfaces ( + IN EFI_HANDLE Handle, + ... + ); + + + +/** + Reinstall a protocol interface on a device handle. The OldInterface for Protocol is replaced by the NewInterface. + + @param UserHandle Handle on which the interface is to be + reinstalled + @param Protocol The numeric ID of the interface + @param OldInterface A pointer to the old interface + @param NewInterface A pointer to the new interface + + @retval EFI_SUCCESS The protocol interface was installed + @retval EFI_NOT_FOUND The OldInterface on the handle was not found + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value + +**/ +EFI_STATUS +EFIAPI +CoreReinstallProtocolInterface ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + IN VOID *OldInterface, + IN VOID *NewInterface + ); + + + +/** + Uninstalls all instances of a protocol:interfacer from a handle. + If the last protocol interface is remove from the handle, the + handle is freed. + + @param UserHandle The handle to remove the protocol handler from + @param Protocol The protocol, of protocol:interface, to remove + @param Interface The interface, of protocol:interface, to remove + + @retval EFI_INVALID_PARAMETER Protocol is NULL. + @retval EFI_SUCCESS Protocol interface successfully uninstalled. + +**/ +EFI_STATUS +EFIAPI +CoreUninstallProtocolInterface ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + IN VOID *Interface + ); + + + +/** + Queries a handle to determine if it supports a specified protocol. + + @param UserHandle The handle being queried. + @param Protocol The published unique identifier of the protocol. + @param Interface Supplies the address where a pointer to the + corresponding Protocol Interface is returned. + + @return The requested protocol interface for the handle + +**/ +EFI_STATUS +EFIAPI +CoreHandleProtocol ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + OUT VOID **Interface + ); + + + +/** + Locates the installed protocol handler for the handle, and + invokes it to obtain the protocol interface. Usage information + is registered in the protocol data base. + + @param UserHandle The handle to obtain the protocol interface on + @param Protocol The ID of the protocol + @param Interface The location to return the protocol interface + @param ImageHandle The handle of the Image that is opening the + protocol interface specified by Protocol and + Interface. + @param ControllerHandle The controller handle that is requiring this + interface. + @param Attributes The open mode of the protocol interface + specified by Handle and Protocol. + + @retval EFI_INVALID_PARAMETER Protocol is NULL. + @retval EFI_SUCCESS Get the protocol interface. + +**/ +EFI_STATUS +EFIAPI +CoreOpenProtocol ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + OUT VOID **Interface OPTIONAL, + IN EFI_HANDLE ImageHandle, + IN EFI_HANDLE ControllerHandle, + IN UINT32 Attributes + ); + + + +/** + Return information about Opened protocols in the system + + @param UserHandle The handle to close the protocol interface on + @param Protocol The ID of the protocol + @param EntryBuffer A pointer to a buffer of open protocol + information in the form of + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures. + @param EntryCount Number of EntryBuffer entries + +**/ +EFI_STATUS +EFIAPI +CoreOpenProtocolInformation ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer, + OUT UINTN *EntryCount + ); + + + +/** + Closes a protocol on a handle that was opened using OpenProtocol(). + + @param UserHandle The handle for the protocol interface that was + previously opened with OpenProtocol(), and is + now being closed. + @param Protocol The published unique identifier of the protocol. + It is the caller's responsibility to pass in a + valid GUID. + @param AgentHandle The handle of the agent that is closing the + protocol interface. + @param ControllerHandle If the agent that opened a protocol is a driver + that follows the EFI Driver Model, then this + parameter is the controller handle that required + the protocol interface. If the agent does not + follow the EFI Driver Model, then this parameter + is optional and may be NULL. + + @retval EFI_SUCCESS The protocol instance was closed. + @retval EFI_INVALID_PARAMETER Handle, AgentHandle or ControllerHandle is not a + valid EFI_HANDLE. + @retval EFI_NOT_FOUND Can not find the specified protocol or + AgentHandle. + +**/ +EFI_STATUS +EFIAPI +CoreCloseProtocol ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + IN EFI_HANDLE AgentHandle, + IN EFI_HANDLE ControllerHandle + ); + + + +/** + Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated + from pool. + + @param UserHandle The handle from which to retrieve the list of + protocol interface GUIDs. + @param ProtocolBuffer A pointer to the list of protocol interface GUID + pointers that are installed on Handle. + @param ProtocolBufferCount A pointer to the number of GUID pointers present + in ProtocolBuffer. + + @retval EFI_SUCCESS The list of protocol interface GUIDs installed + on Handle was returned in ProtocolBuffer. The + number of protocol interface GUIDs was returned + in ProtocolBufferCount. + @retval EFI_INVALID_PARAMETER Handle is NULL. + @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ProtocolBuffer is NULL. + @retval EFI_INVALID_PARAMETER ProtocolBufferCount is NULL. + @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the + results. + +**/ +EFI_STATUS +EFIAPI +CoreProtocolsPerHandle ( + IN EFI_HANDLE UserHandle, + OUT EFI_GUID ***ProtocolBuffer, + OUT UINTN *ProtocolBufferCount + ); + + + +/** + Add a new protocol notification record for the request protocol. + + @param Protocol The requested protocol to add the notify + registration + @param Event The event to signal + @param Registration Returns the registration record + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_SUCCESS Successfully returned the registration record + that has been added + +**/ +EFI_STATUS +EFIAPI +CoreRegisterProtocolNotify ( + IN EFI_GUID *Protocol, + IN EFI_EVENT Event, + OUT VOID **Registration + ); + + +/** + Removes all the events in the protocol database that match Event. + + @param Event The event to search for in the protocol + database. + + @return EFI_SUCCESS when done searching the entire database. + +**/ +EFI_STATUS +CoreUnregisterProtocolNotify ( + IN EFI_EVENT Event + ); + + +/** + Locates the requested handle(s) and returns them in Buffer. + + @param SearchType The type of search to perform to locate the + handles + @param Protocol The protocol to search for + @param SearchKey Dependant on SearchType + @param BufferSize On input the size of Buffer. On output the + size of data returned. + @param Buffer The buffer to return the results in + + @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is + returned in BufferSize. + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_SUCCESS Successfully found the requested handle(s) and + returns them in Buffer. + +**/ +EFI_STATUS +EFIAPI +CoreLocateHandle ( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol OPTIONAL, + IN VOID *SearchKey OPTIONAL, + IN OUT UINTN *BufferSize, + OUT EFI_HANDLE *Buffer + ); + + + +/** + Locates the handle to a device on the device path that best matches the specified protocol. + + @param Protocol The protocol to search for. + @param DevicePath On input, a pointer to a pointer to the device + path. On output, the device path pointer is + modified to point to the remaining part of the + devicepath. + @param Device A pointer to the returned device handle. + + @retval EFI_SUCCESS The resulting handle was returned. + @retval EFI_NOT_FOUND No handles matched the search. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + +**/ +EFI_STATUS +EFIAPI +CoreLocateDevicePath ( + IN EFI_GUID *Protocol, + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, + OUT EFI_HANDLE *Device + ); + + + +/** + Function returns an array of handles that support the requested protocol + in a buffer allocated from pool. This is a version of CoreLocateHandle() + that allocates a buffer for the caller. + + @param SearchType Specifies which handle(s) are to be returned. + @param Protocol Provides the protocol to search by. This + parameter is only valid for SearchType + ByProtocol. + @param SearchKey Supplies the search key depending on the + SearchType. + @param NumberHandles The number of handles returned in Buffer. + @param Buffer A pointer to the buffer to return the requested + array of handles that support Protocol. + + @retval EFI_SUCCESS The result array of handles was returned. + @retval EFI_NOT_FOUND No handles match the search. + @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the + matching results. + @retval EFI_INVALID_PARAMETER One or more parameters are not valid. + +**/ +EFI_STATUS +EFIAPI +CoreLocateHandleBuffer ( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol OPTIONAL, + IN VOID *SearchKey OPTIONAL, + IN OUT UINTN *NumberHandles, + OUT EFI_HANDLE **Buffer + ); + + + +/** + Return the first Protocol Interface that matches the Protocol GUID. If + Registration is passed in, return a Protocol Instance that was just add + to the system. If Registration is NULL return the first Protocol Interface + you find. + + @param Protocol The protocol to search for + @param Registration Optional Registration Key returned from + RegisterProtocolNotify() + @param Interface Return the Protocol interface (instance). + + @retval EFI_SUCCESS If a valid Interface is returned + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_NOT_FOUND Protocol interface not found + +**/ +EFI_STATUS +EFIAPI +CoreLocateProtocol ( + IN EFI_GUID *Protocol, + IN VOID *Registration OPTIONAL, + OUT VOID **Interface + ); + + +/** + return handle database key. + + + @return Handle database key. + +**/ +UINT64 +CoreGetHandleDatabaseKey ( + VOID + ); + + +/** + Go connect any handles that were created or modified while a image executed. + + @param Key The Key to show that the handle has been + created/modified + +**/ +VOID +CoreConnectHandlesByKey ( + UINT64 Key + ); + + + +/** + Connects one or more drivers to a controller. + + @param ControllerHandle The handle of the controller to which driver(s) are to be connected. + @param DriverImageHandle A pointer to an ordered list handles that support the + EFI_DRIVER_BINDING_PROTOCOL. + @param RemainingDevicePath A pointer to the device path that specifies a child of the + controller specified by ControllerHandle. + @param Recursive If TRUE, then ConnectController() is called recursively + until the entire tree of controllers below the controller specified + by ControllerHandle have been created. If FALSE, then + the tree of controllers is only expanded one level. + + @retval EFI_SUCCESS 1) One or more drivers were connected to ControllerHandle. + 2) No drivers were connected to ControllerHandle, but + RemainingDevicePath is not NULL, and it is an End Device + Path Node. + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + @retval EFI_NOT_FOUND 1) There are no EFI_DRIVER_BINDING_PROTOCOL instances + present in the system. + 2) No drivers were connected to ControllerHandle. + @retval EFI_SECURITY_VIOLATION + The user has no permission to start UEFI device drivers on the device path + associated with the ControllerHandle or specified by the RemainingDevicePath. + +**/ +EFI_STATUS +EFIAPI +CoreConnectController ( + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE *DriverImageHandle OPTIONAL, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL, + IN BOOLEAN Recursive + ); + + + +/** + Disonnects a controller from a driver + + @param ControllerHandle ControllerHandle The handle of + the controller from which + driver(s) are to be + disconnected. + @param DriverImageHandle DriverImageHandle The driver to + disconnect from ControllerHandle. + @param ChildHandle ChildHandle The handle of the + child to destroy. + + @retval EFI_SUCCESS One or more drivers were + disconnected from the controller. + @retval EFI_SUCCESS On entry, no drivers are managing + ControllerHandle. + @retval EFI_SUCCESS DriverImageHandle is not NULL, + and on entry DriverImageHandle is + not managing ControllerHandle. + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + @retval EFI_INVALID_PARAMETER DriverImageHandle is not NULL, + and it is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL, and it + is not a valid EFI_HANDLE. + @retval EFI_OUT_OF_RESOURCES There are not enough resources + available to disconnect any + drivers from ControllerHandle. + @retval EFI_DEVICE_ERROR The controller could not be + disconnected because of a device + error. + +**/ +EFI_STATUS +EFIAPI +CoreDisconnectController ( + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE DriverImageHandle OPTIONAL, + IN EFI_HANDLE ChildHandle OPTIONAL + ); + + + +/** + Allocates pages from the memory map. + + @param Type The type of allocation to perform + @param MemoryType The type of memory to turn the allocated pages + into + @param NumberOfPages The number of pages to allocate + @param Memory A pointer to receive the base allocated memory + address + + @return Status. On success, Memory is filled in with the base address allocated + @retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in + spec. + @retval EFI_NOT_FOUND Could not allocate pages match the requirement. + @retval EFI_OUT_OF_RESOURCES No enough pages to allocate. + @retval EFI_SUCCESS Pages successfully allocated. + +**/ +EFI_STATUS +EFIAPI +CoreAllocatePages ( + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN NumberOfPages, + IN OUT EFI_PHYSICAL_ADDRESS *Memory + ); + +/** + Frees previous allocated pages. + + @param Memory Base address of memory being freed + @param NumberOfPages The number of pages to free + + @retval EFI_NOT_FOUND Could not find the entry that covers the range + @retval EFI_INVALID_PARAMETER Address not aligned + @return EFI_SUCCESS -Pages successfully freed. + +**/ +EFI_STATUS +EFIAPI +CoreFreePages ( + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN NumberOfPages + ); + +/** + This function returns a copy of the current memory map. The map is an array of + memory descriptors, each of which describes a contiguous block of memory. + + @param MemoryMapSize A pointer to the size, in bytes, of the + MemoryMap buffer. On input, this is the size of + the buffer allocated by the caller. On output, + it is the size of the buffer returned by the + firmware if the buffer was large enough, or the + size of the buffer needed to contain the map if + the buffer was too small. + @param MemoryMap A pointer to the buffer in which firmware places + the current memory map. + @param MapKey A pointer to the location in which firmware + returns the key for the current memory map. + @param DescriptorSize A pointer to the location in which firmware + returns the size, in bytes, of an individual + EFI_MEMORY_DESCRIPTOR. + @param DescriptorVersion A pointer to the location in which firmware + returns the version number associated with the + EFI_MEMORY_DESCRIPTOR. + + @retval EFI_SUCCESS The memory map was returned in the MemoryMap + buffer. + @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current + buffer size needed to hold the memory map is + returned in MemoryMapSize. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + +**/ +EFI_STATUS +EFIAPI +CoreGetMemoryMap ( + IN OUT UINTN *MemoryMapSize, + IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, + OUT UINTN *MapKey, + OUT UINTN *DescriptorSize, + OUT UINT32 *DescriptorVersion + ); + + + +/** + Allocate pool of a particular type. + + @param PoolType Type of pool to allocate + @param Size The amount of pool to allocate + @param Buffer The address to return a pointer to the allocated + pool + + @retval EFI_INVALID_PARAMETER PoolType not valid or Buffer is NULL + @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed. + @retval EFI_SUCCESS Pool successfully allocated. + +**/ +EFI_STATUS +EFIAPI +CoreAllocatePool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN Size, + OUT VOID **Buffer + ); + +/** + Allocate pool of a particular type. + + @param PoolType Type of pool to allocate + @param Size The amount of pool to allocate + @param Buffer The address to return a pointer to the allocated + pool + + @retval EFI_INVALID_PARAMETER PoolType not valid or Buffer is NULL + @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed. + @retval EFI_SUCCESS Pool successfully allocated. + +**/ +EFI_STATUS +EFIAPI +CoreInternalAllocatePool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN Size, + OUT VOID **Buffer + ); + +/** + Frees pool. + + @param Buffer The allocated pool entry to free + + @retval EFI_INVALID_PARAMETER Buffer is not a valid value. + @retval EFI_SUCCESS Pool successfully freed. + +**/ +EFI_STATUS +EFIAPI +CoreFreePool ( + IN VOID *Buffer + ); + +/** + Frees pool. + + @param Buffer The allocated pool entry to free + @param PoolType Pointer to pool type + + @retval EFI_INVALID_PARAMETER Buffer is not a valid value. + @retval EFI_SUCCESS Pool successfully freed. + +**/ +EFI_STATUS +EFIAPI +CoreInternalFreePool ( + IN VOID *Buffer, + OUT EFI_MEMORY_TYPE *PoolType OPTIONAL + ); + +/** + Loads an EFI image into memory and returns a handle to the image. + + @param BootPolicy If TRUE, indicates that the request originates + from the boot manager, and that the boot + manager is attempting to load FilePath as a + boot selection. + @param ParentImageHandle The caller's image handle. + @param FilePath The specific file path from which the image is + loaded. + @param SourceBuffer If not NULL, a pointer to the memory location + containing a copy of the image to be loaded. + @param SourceSize The size in bytes of SourceBuffer. + @param ImageHandle Pointer to the returned image handle that is + created when the image is successfully loaded. + + @retval EFI_SUCCESS The image was loaded into memory. + @retval EFI_NOT_FOUND The FilePath was not found. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + @retval EFI_UNSUPPORTED The image type is not supported, or the device + path cannot be parsed to locate the proper + protocol for loading the file. + @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient + resources. + @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not + understood. + @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error. + @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the + image from being loaded. NULL is returned in *ImageHandle. + @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a + valid EFI_LOADED_IMAGE_PROTOCOL. However, the current + platform policy specifies that the image should not be started. + +**/ +EFI_STATUS +EFIAPI +CoreLoadImage ( + IN BOOLEAN BootPolicy, + IN EFI_HANDLE ParentImageHandle, + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, + IN VOID *SourceBuffer OPTIONAL, + IN UINTN SourceSize, + OUT EFI_HANDLE *ImageHandle + ); + + + +/** + Unloads an image. + + @param ImageHandle Handle that identifies the image to be + unloaded. + + @retval EFI_SUCCESS The image has been unloaded. + @retval EFI_UNSUPPORTED The image has been started, and does not support + unload. + @retval EFI_INVALID_PARAMPETER ImageHandle is not a valid image handle. + +**/ +EFI_STATUS +EFIAPI +CoreUnloadImage ( + IN EFI_HANDLE ImageHandle + ); + + + +/** + Transfer control to a loaded image's entry point. + + @param ImageHandle Handle of image to be started. + @param ExitDataSize Pointer of the size to ExitData + @param ExitData Pointer to a pointer to a data buffer that + includes a Null-terminated string, + optionally followed by additional binary data. + The string is a description that the caller may + use to further indicate the reason for the + image's exit. + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate + @retval EFI_SECURITY_VIOLATION The current platform policy specifies that the image should not be started. + @retval EFI_SUCCESS Successfully transfer control to the image's + entry point. + +**/ +EFI_STATUS +EFIAPI +CoreStartImage ( + IN EFI_HANDLE ImageHandle, + OUT UINTN *ExitDataSize, + OUT CHAR16 **ExitData OPTIONAL + ); + + + +/** + Terminates the currently loaded EFI image and returns control to boot services. + + @param ImageHandle Handle that identifies the image. This + parameter is passed to the image on entry. + @param Status The image's exit code. + @param ExitDataSize The size, in bytes, of ExitData. Ignored if + ExitStatus is EFI_SUCCESS. + @param ExitData Pointer to a data buffer that includes a + Null-terminated Unicode string, optionally + followed by additional binary data. The string + is a description that the caller may use to + further indicate the reason for the image's + exit. + + @retval EFI_INVALID_PARAMETER Image handle is NULL or it is not current + image. + @retval EFI_SUCCESS Successfully terminates the currently loaded + EFI image. + @retval EFI_ACCESS_DENIED Should never reach there. + @retval EFI_OUT_OF_RESOURCES Could not allocate pool + +**/ +EFI_STATUS +EFIAPI +CoreExit ( + IN EFI_HANDLE ImageHandle, + IN EFI_STATUS Status, + IN UINTN ExitDataSize, + IN CHAR16 *ExitData OPTIONAL + ); + + + +/** + Creates an event. + + @param Type The type of event to create and its mode and + attributes + @param NotifyTpl The task priority level of event notifications + @param NotifyFunction Pointer to the events notification function + @param NotifyContext Pointer to the notification functions context; + corresponds to parameter "Context" in the + notification function + @param Event Pointer to the newly created event if the call + succeeds; undefined otherwise + + @retval EFI_SUCCESS The event structure was created + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value + @retval EFI_OUT_OF_RESOURCES The event could not be allocated + +**/ +EFI_STATUS +EFIAPI +CoreCreateEvent ( + IN UINT32 Type, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction, OPTIONAL + IN VOID *NotifyContext, OPTIONAL + OUT EFI_EVENT *Event + ); + + + +/** + Creates an event in a group. + + @param Type The type of event to create and its mode and + attributes + @param NotifyTpl The task priority level of event notifications + @param NotifyFunction Pointer to the events notification function + @param NotifyContext Pointer to the notification functions context; + corresponds to parameter "Context" in the + notification function + @param EventGroup GUID for EventGroup if NULL act the same as + gBS->CreateEvent(). + @param Event Pointer to the newly created event if the call + succeeds; undefined otherwise + + @retval EFI_SUCCESS The event structure was created + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value + @retval EFI_OUT_OF_RESOURCES The event could not be allocated + +**/ +EFI_STATUS +EFIAPI +CoreCreateEventEx ( + IN UINT32 Type, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction, OPTIONAL + IN CONST VOID *NotifyContext, OPTIONAL + IN CONST EFI_GUID *EventGroup, OPTIONAL + OUT EFI_EVENT *Event + ); + +/** + Creates a general-purpose event structure + + @param Type The type of event to create and its mode and + attributes + @param NotifyTpl The task priority level of event notifications + @param NotifyFunction Pointer to the events notification function + @param NotifyContext Pointer to the notification functions context; + corresponds to parameter "Context" in the + notification function + @param EventGroup GUID for EventGroup if NULL act the same as + gBS->CreateEvent(). + @param Event Pointer to the newly created event if the call + succeeds; undefined otherwise + + @retval EFI_SUCCESS The event structure was created + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value + @retval EFI_OUT_OF_RESOURCES The event could not be allocated + +**/ +EFI_STATUS +EFIAPI +CoreCreateEventInternal ( + IN UINT32 Type, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction, OPTIONAL + IN CONST VOID *NotifyContext, OPTIONAL + IN CONST EFI_GUID *EventGroup, OPTIONAL + OUT EFI_EVENT *Event + ); + +/** + Sets the type of timer and the trigger time for a timer event. + + @param UserEvent The timer event that is to be signaled at the + specified time + @param Type The type of time that is specified in + TriggerTime + @param TriggerTime The number of 100ns units until the timer + expires + + @retval EFI_SUCCESS The event has been set to be signaled at the + requested time + @retval EFI_INVALID_PARAMETER Event or Type is not valid + +**/ +EFI_STATUS +EFIAPI +CoreSetTimer ( + IN EFI_EVENT UserEvent, + IN EFI_TIMER_DELAY Type, + IN UINT64 TriggerTime + ); + + + +/** + Signals the event. Queues the event to be notified if needed. + + @param UserEvent The event to signal . + + @retval EFI_INVALID_PARAMETER Parameters are not valid. + @retval EFI_SUCCESS The event was signaled. + +**/ +EFI_STATUS +EFIAPI +CoreSignalEvent ( + IN EFI_EVENT UserEvent + ); + + + +/** + Stops execution until an event is signaled. + + @param NumberOfEvents The number of events in the UserEvents array + @param UserEvents An array of EFI_EVENT + @param UserIndex Pointer to the index of the event which + satisfied the wait condition + + @retval EFI_SUCCESS The event indicated by Index was signaled. + @retval EFI_INVALID_PARAMETER The event indicated by Index has a notification + function or Event was not a valid type + @retval EFI_UNSUPPORTED The current TPL is not TPL_APPLICATION + +**/ +EFI_STATUS +EFIAPI +CoreWaitForEvent ( + IN UINTN NumberOfEvents, + IN EFI_EVENT *UserEvents, + OUT UINTN *UserIndex + ); + + + +/** + Closes an event and frees the event structure. + + @param UserEvent Event to close + + @retval EFI_INVALID_PARAMETER Parameters are not valid. + @retval EFI_SUCCESS The event has been closed + +**/ +EFI_STATUS +EFIAPI +CoreCloseEvent ( + IN EFI_EVENT UserEvent + ); + + + +/** + Check the status of an event. + + @param UserEvent The event to check + + @retval EFI_SUCCESS The event is in the signaled state + @retval EFI_NOT_READY The event is not in the signaled state + @retval EFI_INVALID_PARAMETER Event is of type EVT_NOTIFY_SIGNAL + +**/ +EFI_STATUS +EFIAPI +CoreCheckEvent ( + IN EFI_EVENT UserEvent + ); + + +/** + Adds reserved memory, system memory, or memory-mapped I/O resources to the + global coherency domain of the processor. + + @param GcdMemoryType Memory type of the memory space. + @param BaseAddress Base address of the memory space. + @param Length Length of the memory space. + @param Capabilities alterable attributes of the memory space. + + @retval EFI_SUCCESS Merged this memory space into GCD map. + +**/ +EFI_STATUS +EFIAPI +CoreAddMemorySpace ( + IN EFI_GCD_MEMORY_TYPE GcdMemoryType, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Capabilities + ); + + +/** + Allocates nonexistent memory, reserved memory, system memory, or memorymapped + I/O resources from the global coherency domain of the processor. + + @param GcdAllocateType The type of allocate operation + @param GcdMemoryType The desired memory type + @param Alignment Align with 2^Alignment + @param Length Length to allocate + @param BaseAddress Base address to allocate + @param ImageHandle The image handle consume the allocated space. + @param DeviceHandle The device handle consume the allocated space. + + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_NOT_FOUND No descriptor contains the desired space. + @retval EFI_SUCCESS Memory space successfully allocated. + +**/ +EFI_STATUS +EFIAPI +CoreAllocateMemorySpace ( + IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType, + IN EFI_GCD_MEMORY_TYPE GcdMemoryType, + IN UINTN Alignment, + IN UINT64 Length, + IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress, + IN EFI_HANDLE ImageHandle, + IN EFI_HANDLE DeviceHandle OPTIONAL + ); + + +/** + Frees nonexistent memory, reserved memory, system memory, or memory-mapped + I/O resources from the global coherency domain of the processor. + + @param BaseAddress Base address of the memory space. + @param Length Length of the memory space. + + @retval EFI_SUCCESS Space successfully freed. + +**/ +EFI_STATUS +EFIAPI +CoreFreeMemorySpace ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ); + + +/** + Removes reserved memory, system memory, or memory-mapped I/O resources from + the global coherency domain of the processor. + + @param BaseAddress Base address of the memory space. + @param Length Length of the memory space. + + @retval EFI_SUCCESS Successfully remove a segment of memory space. + +**/ +EFI_STATUS +EFIAPI +CoreRemoveMemorySpace ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ); + + +/** + Retrieves the descriptor for a memory region containing a specified address. + + @param BaseAddress Specified start address + @param Descriptor Specified length + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_SUCCESS Successfully get memory space descriptor. + +**/ +EFI_STATUS +EFIAPI +CoreGetMemorySpaceDescriptor ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor + ); + + +/** + Modifies the attributes for a memory region in the global coherency domain of the + processor. + + @param BaseAddress Specified start address + @param Length Specified length + @param Attributes Specified attributes + + @retval EFI_SUCCESS The attributes were set for the memory region. + @retval EFI_INVALID_PARAMETER Length is zero. + @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory + resource range specified by BaseAddress and Length. + @retval EFI_UNSUPPORTED The bit mask of attributes is not support for the memory resource + range specified by BaseAddress and Length. + @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by + BaseAddress and Length cannot be modified. + @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of + the memory resource range. + @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol is + not available yet. + +**/ +EFI_STATUS +EFIAPI +CoreSetMemorySpaceAttributes ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ); + + +/** + Modifies the capabilities for a memory region in the global coherency domain of the + processor. + + @param BaseAddress The physical address that is the start address of a memory region. + @param Length The size in bytes of the memory region. + @param Capabilities The bit mask of capabilities that the memory region supports. + + @retval EFI_SUCCESS The capabilities were set for the memory region. + @retval EFI_INVALID_PARAMETER Length is zero. + @retval EFI_UNSUPPORTED The capabilities specified by Capabilities do not include the + memory region attributes currently in use. + @retval EFI_ACCESS_DENIED The capabilities for the memory resource range specified by + BaseAddress and Length cannot be modified. + @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the capabilities + of the memory resource range. +**/ +EFI_STATUS +EFIAPI +CoreSetMemorySpaceCapabilities ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Capabilities + ); + + +/** + Returns a map of the memory resources in the global coherency domain of the + processor. + + @param NumberOfDescriptors Number of descriptors. + @param MemorySpaceMap Descriptor array + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate + @retval EFI_SUCCESS Successfully get memory space map. + +**/ +EFI_STATUS +EFIAPI +CoreGetMemorySpaceMap ( + OUT UINTN *NumberOfDescriptors, + OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR **MemorySpaceMap + ); + + +/** + Adds reserved I/O or I/O resources to the global coherency domain of the processor. + + @param GcdIoType IO type of the segment. + @param BaseAddress Base address of the segment. + @param Length Length of the segment. + + @retval EFI_SUCCESS Merged this segment into GCD map. + @retval EFI_INVALID_PARAMETER Parameter not valid + +**/ +EFI_STATUS +EFIAPI +CoreAddIoSpace ( + IN EFI_GCD_IO_TYPE GcdIoType, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ); + + +/** + Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency + domain of the processor. + + @param GcdAllocateType The type of allocate operation + @param GcdIoType The desired IO type + @param Alignment Align with 2^Alignment + @param Length Length to allocate + @param BaseAddress Base address to allocate + @param ImageHandle The image handle consume the allocated space. + @param DeviceHandle The device handle consume the allocated space. + + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_NOT_FOUND No descriptor contains the desired space. + @retval EFI_SUCCESS IO space successfully allocated. + +**/ +EFI_STATUS +EFIAPI +CoreAllocateIoSpace ( + IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType, + IN EFI_GCD_IO_TYPE GcdIoType, + IN UINTN Alignment, + IN UINT64 Length, + IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress, + IN EFI_HANDLE ImageHandle, + IN EFI_HANDLE DeviceHandle OPTIONAL + ); + + +/** + Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency + domain of the processor. + + @param BaseAddress Base address of the segment. + @param Length Length of the segment. + + @retval EFI_SUCCESS Space successfully freed. + +**/ +EFI_STATUS +EFIAPI +CoreFreeIoSpace ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ); + + +/** + Removes reserved I/O or I/O resources from the global coherency domain of the + processor. + + @param BaseAddress Base address of the segment. + @param Length Length of the segment. + + @retval EFI_SUCCESS Successfully removed a segment of IO space. + +**/ +EFI_STATUS +EFIAPI +CoreRemoveIoSpace ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ); + + +/** + Retrieves the descriptor for an I/O region containing a specified address. + + @param BaseAddress Specified start address + @param Descriptor Specified length + + @retval EFI_INVALID_PARAMETER Descriptor is NULL. + @retval EFI_SUCCESS Successfully get the IO space descriptor. + +**/ +EFI_STATUS +EFIAPI +CoreGetIoSpaceDescriptor ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + OUT EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor + ); + + +/** + Returns a map of the I/O resources in the global coherency domain of the processor. + + @param NumberOfDescriptors Number of descriptors. + @param IoSpaceMap Descriptor array + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate + @retval EFI_SUCCESS Successfully get IO space map. + +**/ +EFI_STATUS +EFIAPI +CoreGetIoSpaceMap ( + OUT UINTN *NumberOfDescriptors, + OUT EFI_GCD_IO_SPACE_DESCRIPTOR **IoSpaceMap + ); + + +/** + This is the main Dispatcher for DXE and it exits when there are no more + drivers to run. Drain the mScheduledQueue and load and start a PE + image for each driver. Search the mDiscoveredList to see if any driver can + be placed on the mScheduledQueue. If no drivers are placed on the + mScheduledQueue exit the function. On exit it is assumed the Bds() + will be called, and when the Bds() exits the Dispatcher will be called + again. + + @retval EFI_ALREADY_STARTED The DXE Dispatcher is already running + @retval EFI_NOT_FOUND No DXE Drivers were dispatched + @retval EFI_SUCCESS One or more DXE Drivers were dispatched + +**/ +EFI_STATUS +EFIAPI +CoreDispatcher ( + VOID + ); + +/** + Check every driver and locate a matching one. If the driver is found, the Unrequested + state flag is cleared. + + @param FirmwareVolumeHandle The handle of the Firmware Volume that contains + the firmware file specified by DriverName. + @param DriverName The Driver name to put in the Dependent state. + + @retval EFI_SUCCESS The DriverName was found and it's SOR bit was + cleared + @retval EFI_NOT_FOUND The DriverName does not exist or it's SOR bit was + not set. + +**/ +EFI_STATUS +EFIAPI +CoreSchedule ( + IN EFI_HANDLE FirmwareVolumeHandle, + IN EFI_GUID *DriverName + ); + + +/** + Convert a driver from the Untrused back to the Scheduled state. + + @param FirmwareVolumeHandle The handle of the Firmware Volume that contains + the firmware file specified by DriverName. + @param DriverName The Driver name to put in the Scheduled state + + @retval EFI_SUCCESS The file was found in the untrusted state, and it + was promoted to the trusted state. + @retval EFI_NOT_FOUND The file was not found in the untrusted state. + +**/ +EFI_STATUS +EFIAPI +CoreTrust ( + IN EFI_HANDLE FirmwareVolumeHandle, + IN EFI_GUID *DriverName + ); + + +/** + This routine is the driver initialization entry point. It initializes the + libraries, and registers two notification functions. These notification + functions are responsible for building the FV stack dynamically. + + @param ImageHandle The image handle. + @param SystemTable The system table. + + @retval EFI_SUCCESS Function successfully returned. + +**/ +EFI_STATUS +EFIAPI +FwVolDriverInit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + + +/** + Entry point of the section extraction code. Initializes an instance of the + section extraction interface and installs it on a new handle. + + @param ImageHandle A handle for the image that is initializing this driver + @param SystemTable A pointer to the EFI system table + + @retval EFI_SUCCESS Driver initialized successfully + @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources + +**/ +EFI_STATUS +EFIAPI +InitializeSectionExtraction ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + + +/** + This DXE service routine is used to process a firmware volume. In + particular, it can be called by BDS to process a single firmware + volume found in a capsule. + + @param FvHeader pointer to a firmware volume header + @param Size the size of the buffer pointed to by FvHeader + @param FVProtocolHandle the handle on which a firmware volume protocol + was produced for the firmware volume passed in. + + @retval EFI_OUT_OF_RESOURCES if an FVB could not be produced due to lack of + system resources + @retval EFI_VOLUME_CORRUPTED if the volume was corrupted + @retval EFI_SUCCESS a firmware volume protocol was produced for the + firmware volume + +**/ +EFI_STATUS +EFIAPI +CoreProcessFirmwareVolume ( + IN VOID *FvHeader, + IN UINTN Size, + OUT EFI_HANDLE *FVProtocolHandle + ); + +// +//Functions used during debug buils +// + +/** + Displays Architectural protocols that were not loaded and are required for DXE + core to function. Only used in Debug Builds. + +**/ +VOID +CoreDisplayMissingArchProtocols ( + VOID + ); + + +/** + Traverse the discovered list for any drivers that were discovered but not loaded + because the dependency experessions evaluated to false. + +**/ +VOID +CoreDisplayDiscoveredNotDispatched ( + VOID + ); + + + +/** + Place holder function until all the Boot Services and Runtime Services are + available. + + @param Arg1 Undefined + + @return EFI_NOT_AVAILABLE_YET + +**/ +EFI_STATUS +EFIAPI +CoreEfiNotAvailableYetArg1 ( + UINTN Arg1 + ); + + +/** + Place holder function until all the Boot Services and Runtime Services are available. + + @param Arg1 Undefined + @param Arg2 Undefined + + @return EFI_NOT_AVAILABLE_YET + +**/ +EFI_STATUS +EFIAPI +CoreEfiNotAvailableYetArg2 ( + UINTN Arg1, + UINTN Arg2 + ); + + +/** + Place holder function until all the Boot Services and Runtime Services are available. + + @param Arg1 Undefined + @param Arg2 Undefined + @param Arg3 Undefined + + @return EFI_NOT_AVAILABLE_YET + +**/ +EFI_STATUS +EFIAPI +CoreEfiNotAvailableYetArg3 ( + UINTN Arg1, + UINTN Arg2, + UINTN Arg3 + ); + + +/** + Place holder function until all the Boot Services and Runtime Services are available. + + @param Arg1 Undefined + @param Arg2 Undefined + @param Arg3 Undefined + @param Arg4 Undefined + + @return EFI_NOT_AVAILABLE_YET + +**/ +EFI_STATUS +EFIAPI +CoreEfiNotAvailableYetArg4 ( + UINTN Arg1, + UINTN Arg2, + UINTN Arg3, + UINTN Arg4 + ); + + +/** + Place holder function until all the Boot Services and Runtime Services are available. + + @param Arg1 Undefined + @param Arg2 Undefined + @param Arg3 Undefined + @param Arg4 Undefined + @param Arg5 Undefined + + @return EFI_NOT_AVAILABLE_YET + +**/ +EFI_STATUS +EFIAPI +CoreEfiNotAvailableYetArg5 ( + UINTN Arg1, + UINTN Arg2, + UINTN Arg3, + UINTN Arg4, + UINTN Arg5 + ); + + +/** + Given a compressed source buffer, this function retrieves the size of the + uncompressed buffer and the size of the scratch buffer required to decompress + the compressed source buffer. + + The GetInfo() function retrieves the size of the uncompressed buffer and the + temporary scratch buffer required to decompress the buffer specified by Source + and SourceSize. If the size of the uncompressed buffer or the size of the + scratch buffer cannot be determined from the compressed data specified by + Source and SourceData, then EFI_INVALID_PARAMETER is returned. Otherwise, the + size of the uncompressed buffer is returned in DestinationSize, the size of + the scratch buffer is returned in ScratchSize, and EFI_SUCCESS is returned. + The GetInfo() function does not have scratch buffer available to perform a + thorough checking of the validity of the source data. It just retrieves the + "Original Size" field from the beginning bytes of the source data and output + it as DestinationSize. And ScratchSize is specific to the decompression + implementation. + + @param This A pointer to the EFI_DECOMPRESS_PROTOCOL instance. + @param Source The source buffer containing the compressed data. + @param SourceSize The size, in bytes, of the source buffer. + @param DestinationSize A pointer to the size, in bytes, of the + uncompressed buffer that will be generated when the + compressed buffer specified by Source and + SourceSize is decompressed. + @param ScratchSize A pointer to the size, in bytes, of the scratch + buffer that is required to decompress the + compressed buffer specified by Source and + SourceSize. + + @retval EFI_SUCCESS The size of the uncompressed data was returned in + DestinationSize and the size of the scratch buffer + was returned in ScratchSize. + @retval EFI_INVALID_PARAMETER The size of the uncompressed data or the size of + the scratch buffer cannot be determined from the + compressed data specified by Source and + SourceSize. + +**/ +EFI_STATUS +EFIAPI +DxeMainUefiDecompressGetInfo ( + IN EFI_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SourceSize, + OUT UINT32 *DestinationSize, + OUT UINT32 *ScratchSize + ); + + +/** + Decompresses a compressed source buffer. + + The Decompress() function extracts decompressed data to its original form. + This protocol is designed so that the decompression algorithm can be + implemented without using any memory services. As a result, the Decompress() + Function is not allowed to call AllocatePool() or AllocatePages() in its + implementation. It is the caller's responsibility to allocate and free the + Destination and Scratch buffers. + If the compressed source data specified by Source and SourceSize is + sucessfully decompressed into Destination, then EFI_SUCCESS is returned. If + the compressed source data specified by Source and SourceSize is not in a + valid compressed data format, then EFI_INVALID_PARAMETER is returned. + + @param This A pointer to the EFI_DECOMPRESS_PROTOCOL instance. + @param Source The source buffer containing the compressed data. + @param SourceSize SourceSizeThe size of source data. + @param Destination On output, the destination buffer that contains + the uncompressed data. + @param DestinationSize The size of the destination buffer. The size of + the destination buffer needed is obtained from + EFI_DECOMPRESS_PROTOCOL.GetInfo(). + @param Scratch A temporary scratch buffer that is used to perform + the decompression. + @param ScratchSize The size of scratch buffer. The size of the + scratch buffer needed is obtained from GetInfo(). + + @retval EFI_SUCCESS Decompression completed successfully, and the + uncompressed buffer is returned in Destination. + @retval EFI_INVALID_PARAMETER The source buffer specified by Source and + SourceSize is corrupted (not in a valid + compressed format). + +**/ +EFI_STATUS +EFIAPI +DxeMainUefiDecompress ( + IN EFI_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SourceSize, + IN OUT VOID *Destination, + IN UINT32 DestinationSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ); + +/** + SEP member function. This function creates and returns a new section stream + handle to represent the new section stream. + + @param SectionStreamLength Size in bytes of the section stream. + @param SectionStream Buffer containing the new section stream. + @param SectionStreamHandle A pointer to a caller allocated UINTN that on + output contains the new section stream handle. + + @retval EFI_SUCCESS The section stream is created successfully. + @retval EFI_OUT_OF_RESOURCES memory allocation failed. + @retval EFI_INVALID_PARAMETER Section stream does not end concident with end + of last section. + +**/ +EFI_STATUS +EFIAPI +OpenSectionStream ( + IN UINTN SectionStreamLength, + IN VOID *SectionStream, + OUT UINTN *SectionStreamHandle + ); + + + +/** + SEP member function. Retrieves requested section from section stream. + + @param SectionStreamHandle The section stream from which to extract the + requested section. + @param SectionType A pointer to the type of section to search for. + @param SectionDefinitionGuid If the section type is EFI_SECTION_GUID_DEFINED, + then SectionDefinitionGuid indicates which of + these types of sections to search for. + @param SectionInstance Indicates which instance of the requested + section to return. + @param Buffer Double indirection to buffer. If *Buffer is + non-null on input, then the buffer is caller + allocated. If Buffer is NULL, then the buffer + is callee allocated. In either case, the + required buffer size is returned in *BufferSize. + @param BufferSize On input, indicates the size of *Buffer if + *Buffer is non-null on input. On output, + indicates the required size (allocated size if + callee allocated) of *Buffer. + @param AuthenticationStatus A pointer to a caller-allocated UINT32 that + indicates the authentication status of the + output buffer. If the input section's + GuidedSectionHeader.Attributes field + has the EFI_GUIDED_SECTION_AUTH_STATUS_VALID + bit as clear, AuthenticationStatus must return + zero. Both local bits (19:16) and aggregate + bits (3:0) in AuthenticationStatus are returned + by ExtractSection(). These bits reflect the + status of the extraction operation. The bit + pattern in both regions must be the same, as + the local and aggregate authentication statuses + have equivalent meaning at this level. If the + function returns anything other than + EFI_SUCCESS, the value of *AuthenticationStatus + is undefined. + @param IsFfs3Fv Indicates the FV format. + + @retval EFI_SUCCESS Section was retrieved successfully + @retval EFI_PROTOCOL_ERROR A GUID defined section was encountered in the + section stream with its + EFI_GUIDED_SECTION_PROCESSING_REQUIRED bit set, + but there was no corresponding GUIDed Section + Extraction Protocol in the handle database. + *Buffer is unmodified. + @retval EFI_NOT_FOUND An error was encountered when parsing the + SectionStream. This indicates the SectionStream + is not correctly formatted. + @retval EFI_NOT_FOUND The requested section does not exist. + @retval EFI_OUT_OF_RESOURCES The system has insufficient resources to process + the request. + @retval EFI_INVALID_PARAMETER The SectionStreamHandle does not exist. + @retval EFI_WARN_TOO_SMALL The size of the caller allocated input buffer is + insufficient to contain the requested section. + The input buffer is filled and section contents + are truncated. + +**/ +EFI_STATUS +EFIAPI +GetSection ( + IN UINTN SectionStreamHandle, + IN EFI_SECTION_TYPE *SectionType, + IN EFI_GUID *SectionDefinitionGuid, + IN UINTN SectionInstance, + IN VOID **Buffer, + IN OUT UINTN *BufferSize, + OUT UINT32 *AuthenticationStatus, + IN BOOLEAN IsFfs3Fv + ); + + +/** + SEP member function. Deletes an existing section stream + + @param StreamHandleToClose Indicates the stream to close + @param FreeStreamBuffer TRUE - Need to free stream buffer; + FALSE - No need to free stream buffer. + + @retval EFI_SUCCESS The section stream is closed sucessfully. + @retval EFI_OUT_OF_RESOURCES Memory allocation failed. + @retval EFI_INVALID_PARAMETER Section stream does not end concident with end + of last section. + +**/ +EFI_STATUS +EFIAPI +CloseSectionStream ( + IN UINTN StreamHandleToClose, + IN BOOLEAN FreeStreamBuffer + ); + +/** + Creates and initializes the DebugImageInfo Table. Also creates the configuration + table and registers it into the system table. + + Note: + This function allocates memory, frees it, and then allocates memory at an + address within the initial allocation. Since this function is called early + in DXE core initialization (before drivers are dispatched), this should not + be a problem. + +**/ +VOID +CoreInitializeDebugImageInfoTable ( + VOID + ); + + +/** + Update the CRC32 in the Debug Table. + Since the CRC32 service is made available by the Runtime driver, we have to + wait for the Runtime Driver to be installed before the CRC32 can be computed. + This function is called elsewhere by the core when the runtime architectural + protocol is produced. + +**/ +VOID +CoreUpdateDebugTableCrc32 ( + VOID + ); + + +/** + Adds a new DebugImageInfo structure to the DebugImageInfo Table. Re-Allocates + the table if it's not large enough to accomidate another entry. + + @param ImageInfoType type of debug image information + @param LoadedImage pointer to the loaded image protocol for the image being + loaded + @param ImageHandle image handle for the image being loaded + +**/ +VOID +CoreNewDebugImageInfoEntry ( + IN UINT32 ImageInfoType, + IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage, + IN EFI_HANDLE ImageHandle + ); + + +/** + Removes and frees an entry from the DebugImageInfo Table. + + @param ImageHandle image handle for the image being unloaded + +**/ +VOID +CoreRemoveDebugImageInfoEntry ( + EFI_HANDLE ImageHandle + ); + + +/** + This routine consumes FV hobs and produces instances of FW_VOL_BLOCK_PROTOCOL as appropriate. + + @param ImageHandle The image handle. + @param SystemTable The system table. + + @retval EFI_SUCCESS Successfully initialized firmware volume block + driver. + +**/ +EFI_STATUS +EFIAPI +FwVolBlockDriverInit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + + Get FVB authentication status + + @param FvbProtocol FVB protocol. + + @return Authentication status. + +**/ +UINT32 +GetFvbAuthenticationStatus ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol + ); + +/** + This routine produces a firmware volume block protocol on a given + buffer. + + @param BaseAddress base address of the firmware volume image + @param Length length of the firmware volume image + @param ParentHandle handle of parent firmware volume, if this image + came from an FV image file and section in another firmware + volume (ala capsules) + @param AuthenticationStatus Authentication status inherited, if this image + came from an FV image file and section in another firmware volume. + @param FvProtocol Firmware volume block protocol produced. + + @retval EFI_VOLUME_CORRUPTED Volume corrupted. + @retval EFI_OUT_OF_RESOURCES No enough buffer to be allocated. + @retval EFI_SUCCESS Successfully produced a FVB protocol on given + buffer. + +**/ +EFI_STATUS +ProduceFVBProtocolOnBuffer ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_HANDLE ParentHandle, + IN UINT32 AuthenticationStatus, + OUT EFI_HANDLE *FvProtocol OPTIONAL + ); + + +/** + Raising to the task priority level of the mutual exclusion + lock, and then acquires ownership of the lock. + + @param Lock The lock to acquire + + @return Lock owned + +**/ +VOID +CoreAcquireLock ( + IN EFI_LOCK *Lock + ); + + +/** + Initialize a basic mutual exclusion lock. Each lock + provides mutual exclusion access at it's task priority + level. Since there is no-premption (at any TPL) or + multiprocessor support, acquiring the lock only consists + of raising to the locks TPL. + + @param Lock The EFI_LOCK structure to initialize + + @retval EFI_SUCCESS Lock Owned. + @retval EFI_ACCESS_DENIED Reentrant Lock Acquisition, Lock not Owned. + +**/ +EFI_STATUS +CoreAcquireLockOrFail ( + IN EFI_LOCK *Lock + ); + + +/** + Releases ownership of the mutual exclusion lock, and + restores the previous task priority level. + + @param Lock The lock to release + + @return Lock unowned + +**/ +VOID +CoreReleaseLock ( + IN EFI_LOCK *Lock + ); + +/** + Read data from Firmware Block by FVB protocol Read. + The data may cross the multi block ranges. + + @param Fvb The FW_VOL_BLOCK_PROTOCOL instance from which to read data. + @param StartLba Pointer to StartLba. + On input, the start logical block index from which to read. + On output,the end logical block index after reading. + @param Offset Pointer to Offset + On input, offset into the block at which to begin reading. + On output, offset into the end block after reading. + @param DataSize Size of data to be read. + @param Data Pointer to Buffer that the data will be read into. + + @retval EFI_SUCCESS Successfully read data from firmware block. + @retval others +**/ +EFI_STATUS +ReadFvbData ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb, + IN OUT EFI_LBA *StartLba, + IN OUT UINTN *Offset, + IN UINTN DataSize, + OUT UINT8 *Data + ); + +/** + Given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and + copy the real length volume header into it. + + @param Fvb The FW_VOL_BLOCK_PROTOCOL instance from which to + read the volume header + @param FwVolHeader Pointer to pointer to allocated buffer in which + the volume header is returned. + + @retval EFI_OUT_OF_RESOURCES No enough buffer could be allocated. + @retval EFI_SUCCESS Successfully read volume header to the allocated + buffer. + @retval EFI_INVALID_PARAMETER The FV Header signature is not as expected or + the file system could not be understood. + +**/ +EFI_STATUS +GetFwVolHeader ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb, + OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader + ); + +/** + Verify checksum of the firmware volume header. + + @param FvHeader Points to the firmware volume header to be checked + + @retval TRUE Checksum verification passed + @retval FALSE Checksum verification failed + +**/ +BOOLEAN +VerifyFvHeaderChecksum ( + IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader + ); + +/** + Initialize memory profile. + + @param HobStart The start address of the HOB. + +**/ +VOID +MemoryProfileInit ( + IN VOID *HobStart + ); + +/** + Install memory profile protocol. + +**/ +VOID +MemoryProfileInstallProtocol ( + VOID + ); + +/** + Register image to memory profile. + + @param DriverEntry Image info. + @param FileType Image file type. + + @return EFI_SUCCESS Register successfully. + @return EFI_UNSUPPORTED Memory profile unsupported, + or memory profile for the image is not required. + @return EFI_OUT_OF_RESOURCES No enough resource for this register. + +**/ +EFI_STATUS +RegisterMemoryProfileImage ( + IN LOADED_IMAGE_PRIVATE_DATA *DriverEntry, + IN EFI_FV_FILETYPE FileType + ); + +/** + Unregister image from memory profile. + + @param DriverEntry Image info. + + @return EFI_SUCCESS Unregister successfully. + @return EFI_UNSUPPORTED Memory profile unsupported, + or memory profile for the image is not required. + @return EFI_NOT_FOUND The image is not found. + +**/ +EFI_STATUS +UnregisterMemoryProfileImage ( + IN LOADED_IMAGE_PRIVATE_DATA *DriverEntry + ); + +/** + Update memory profile information. + + @param CallerAddress Address of caller who call Allocate or Free. + @param Action This Allocate or Free action. + @param MemoryType Memory type. + EfiMaxMemoryType means the MemoryType is unknown. + @param Size Buffer size. + @param Buffer Buffer address. + @param ActionString String for memory profile action. + Only needed for user defined allocate action. + + @return EFI_SUCCESS Memory profile is updated. + @return EFI_UNSUPPORTED Memory profile is unsupported, + or memory profile for the image is not required, + or memory profile for the memory type is not required. + @return EFI_ACCESS_DENIED It is during memory profile data getting. + @return EFI_ABORTED Memory profile recording is not enabled. + @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action. + @return EFI_NOT_FOUND No matched allocate info found for free action. + +**/ +EFI_STATUS +EFIAPI +CoreUpdateProfile ( + IN EFI_PHYSICAL_ADDRESS CallerAddress, + IN MEMORY_PROFILE_ACTION Action, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Size, // Valid for AllocatePages/FreePages/AllocatePool + IN VOID *Buffer, + IN CHAR8 *ActionString OPTIONAL + ); + +/** + Internal function. Converts a memory range to use new attributes. + + @param Start The first address of the range Must be page + aligned + @param NumberOfPages The number of pages to convert + @param NewAttributes The new attributes value for the range. + +**/ +VOID +CoreUpdateMemoryAttributes ( + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 NumberOfPages, + IN UINT64 NewAttributes + ); + +/** + Initialize PropertiesTable support. +**/ +VOID +EFIAPI +CoreInitializePropertiesTable ( + VOID + ); + +/** + Initialize MemoryAttrubutesTable support. +**/ +VOID +EFIAPI +CoreInitializeMemoryAttributesTable ( + VOID + ); + +/** + Initialize Memory Protection support. +**/ +VOID +EFIAPI +CoreInitializeMemoryProtection ( + VOID + ); + +/** + Install MemoryAttributesTable on memory allocation. + + @param[in] MemoryType EFI memory type. +**/ +VOID +InstallMemoryAttributesTableOnMemoryAllocation ( + IN EFI_MEMORY_TYPE MemoryType + ); + +/** + Insert image record. + + @param RuntimeImage Runtime image information +**/ +VOID +InsertImageRecord ( + IN EFI_RUNTIME_IMAGE_ENTRY *RuntimeImage + ); + +/** + Remove Image record. + + @param RuntimeImage Runtime image information +**/ +VOID +RemoveImageRecord ( + IN EFI_RUNTIME_IMAGE_ENTRY *RuntimeImage + ); + +/** + Protect UEFI image. + + @param[in] LoadedImage The loaded image protocol + @param[in] LoadedImageDevicePath The loaded image device path protocol +**/ +VOID +ProtectUefiImage ( + IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage, + IN EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath + ); + +/** + Unprotect UEFI image. + + @param[in] LoadedImage The loaded image protocol + @param[in] LoadedImageDevicePath The loaded image device path protocol +**/ +VOID +UnprotectUefiImage ( + IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage, + IN EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath + ); + +/** + ExitBootServices Callback function for memory protection. +**/ +VOID +MemoryProtectionExitBootServicesCallback ( + VOID + ); + +/** + Manage memory permission attributes on a memory range, according to the + configured DXE memory protection policy. + + @param OldType The old memory type of the range + @param NewType The new memory type of the range + @param Memory The base address of the range + @param Length The size of the range (in bytes) + + @return EFI_SUCCESS If the the CPU arch protocol is not installed yet + @return EFI_SUCCESS If no DXE memory protection policy has been configured + @return EFI_SUCCESS If OldType and NewType use the same permission attributes + @return other Return value of gCpu->SetMemoryAttributes() + +**/ +EFI_STATUS +EFIAPI +ApplyMemoryProtectionPolicy ( + IN EFI_MEMORY_TYPE OldType, + IN EFI_MEMORY_TYPE NewType, + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINT64 Length + ); + +/** + Merge continous memory map entries whose have same attributes. + + @param MemoryMap A pointer to the buffer in which firmware places + the current memory map. + @param MemoryMapSize A pointer to the size, in bytes, of the + MemoryMap buffer. On input, this is the size of + the current memory map. On output, + it is the size of new memory map after merge. + @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR. +**/ +VOID +MergeMemoryMap ( + IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, + IN OUT UINTN *MemoryMapSize, + IN UINTN DescriptorSize + ); + +#endif diff --git a/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/Event.h b/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/Event.h new file mode 100644 index 0000000..8141c50 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/Event.h @@ -0,0 +1,91 @@ +/** @file + UEFI Event support functions and structure. + +Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+(C) Copyright 2015 Hewlett Packard Enterprise Development LP
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __EVENT_H__ +#define __EVENT_H__ + + +#define VALID_TPL(a) ((a) <= TPL_HIGH_LEVEL) +extern UINTN gEventPending; + +/// +/// Set if Event is part of an event group +/// +#define EVT_EXFLAG_EVENT_GROUP 0x01 +/// +/// Set if Event is registered on a protocol notify +/// +#define EVT_EXFLAG_EVENT_PROTOCOL_NOTIFICATION 0x02 + +// +// EFI_EVENT +// + +/// +/// Timer event information +/// +typedef struct { + LIST_ENTRY Link; + UINT64 TriggerTime; + UINT64 Period; +} TIMER_EVENT_INFO; + +#define EVENT_SIGNATURE SIGNATURE_32('e','v','n','t') +typedef struct { + UINTN Signature; + UINT32 Type; + UINT32 SignalCount; + /// + /// Entry if the event is registered to be signalled + /// + LIST_ENTRY SignalLink; + /// + /// Notification information for this event + /// + EFI_TPL NotifyTpl; + EFI_EVENT_NOTIFY NotifyFunction; + VOID *NotifyContext; + EFI_GUID EventGroup; + LIST_ENTRY NotifyLink; + UINT8 ExFlag; + /// + /// A list of all runtime events + /// + EFI_RUNTIME_EVENT_ENTRY RuntimeData; + TIMER_EVENT_INFO Timer; +} IEVENT; + +// +// Internal prototypes +// + + +/** + Dispatches all pending events. + + @param Priority The task priority level of event notifications + to dispatch + +**/ +VOID +CoreDispatchEventNotifies ( + IN EFI_TPL Priority + ); + + +/** + Initializes timer support. + +**/ +VOID +CoreInitializeTimer ( + VOID + ); + +#endif diff --git a/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/Handle.c b/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/Handle.c new file mode 100644 index 0000000..b2721b3 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/Handle.c @@ -0,0 +1,1568 @@ +/** @file + UEFI handle & protocol handling. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "DxeMain.h" +#include "Handle.h" + + +// +// mProtocolDatabase - A list of all protocols in the system. (simple list for now) +// gHandleList - A list of all the handles in the system +// gProtocolDatabaseLock - Lock to protect the mProtocolDatabase +// gHandleDatabaseKey - The Key to show that the handle has been created/modified +// +LIST_ENTRY mProtocolDatabase = INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase); +LIST_ENTRY gHandleList = INITIALIZE_LIST_HEAD_VARIABLE (gHandleList); +EFI_LOCK gProtocolDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY); +UINT64 gHandleDatabaseKey = 0; + + + +/** + Acquire lock on gProtocolDatabaseLock. + +**/ +VOID +CoreAcquireProtocolLock ( + VOID + ) +{ + CoreAcquireLock (&gProtocolDatabaseLock); +} + + + +/** + Release lock on gProtocolDatabaseLock. + +**/ +VOID +CoreReleaseProtocolLock ( + VOID + ) +{ + CoreReleaseLock (&gProtocolDatabaseLock); +} + + + +/** + Check whether a handle is a valid EFI_HANDLE + + @param UserHandle The handle to check + + @retval EFI_INVALID_PARAMETER The handle is NULL or not a valid EFI_HANDLE. + @retval EFI_SUCCESS The handle is valid EFI_HANDLE. + +**/ +EFI_STATUS +CoreValidateHandle ( + IN EFI_HANDLE UserHandle + ) +{ + IHANDLE *Handle; + LIST_ENTRY *Link; + + if (UserHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + + for (Link = gHandleList.BackLink; Link != &gHandleList; Link = Link->BackLink) { + Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE); + if (Handle == (IHANDLE *) UserHandle) { + return EFI_SUCCESS; + } + } + + return EFI_INVALID_PARAMETER; +} + + + +/** + Finds the protocol entry for the requested protocol. + The gProtocolDatabaseLock must be owned + + @param Protocol The ID of the protocol + @param Create Create a new entry if not found + + @return Protocol entry + +**/ +PROTOCOL_ENTRY * +CoreFindProtocolEntry ( + IN EFI_GUID *Protocol, + IN BOOLEAN Create + ) +{ + LIST_ENTRY *Link; + PROTOCOL_ENTRY *Item; + PROTOCOL_ENTRY *ProtEntry; + + ASSERT_LOCKED(&gProtocolDatabaseLock); + + // + // Search the database for the matching GUID + // + + ProtEntry = NULL; + for (Link = mProtocolDatabase.ForwardLink; + Link != &mProtocolDatabase; + Link = Link->ForwardLink) { + + Item = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE); + if (CompareGuid (&Item->ProtocolID, Protocol)) { + + // + // This is the protocol entry + // + + ProtEntry = Item; + break; + } + } + + // + // If the protocol entry was not found and Create is TRUE, then + // allocate a new entry + // + if ((ProtEntry == NULL) && Create) { + ProtEntry = AllocatePool (sizeof(PROTOCOL_ENTRY)); + + if (ProtEntry != NULL) { + // + // Initialize new protocol entry structure + // + ProtEntry->Signature = PROTOCOL_ENTRY_SIGNATURE; + CopyGuid ((VOID *)&ProtEntry->ProtocolID, Protocol); + InitializeListHead (&ProtEntry->Protocols); + InitializeListHead (&ProtEntry->Notify); + + // + // Add it to protocol database + // + InsertTailList (&mProtocolDatabase, &ProtEntry->AllEntries); + } + } + + return ProtEntry; +} + + + +/** + Finds the protocol instance for the requested handle and protocol. + Note: This function doesn't do parameters checking, it's caller's responsibility + to pass in valid parameters. + + @param Handle The handle to search the protocol on + @param Protocol GUID of the protocol + @param Interface The interface for the protocol being searched + + @return Protocol instance (NULL: Not found) + +**/ +PROTOCOL_INTERFACE * +CoreFindProtocolInterface ( + IN IHANDLE *Handle, + IN EFI_GUID *Protocol, + IN VOID *Interface + ) +{ + PROTOCOL_INTERFACE *Prot; + PROTOCOL_ENTRY *ProtEntry; + LIST_ENTRY *Link; + + ASSERT_LOCKED(&gProtocolDatabaseLock); + Prot = NULL; + + // + // Lookup the protocol entry for this protocol ID + // + + ProtEntry = CoreFindProtocolEntry (Protocol, FALSE); + if (ProtEntry != NULL) { + + // + // Look at each protocol interface for any matches + // + for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link=Link->ForwardLink) { + + // + // If this protocol interface matches, remove it + // + Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE); + if (Prot->Interface == Interface && Prot->Protocol == ProtEntry) { + break; + } + + Prot = NULL; + } + } + + return Prot; +} + + +/** + Removes an event from a register protocol notify list on a protocol. + + @param Event The event to search for in the protocol + database. + + @return EFI_SUCCESS if the event was found and removed. + @return EFI_NOT_FOUND if the event was not found in the protocl database. + +**/ +EFI_STATUS +CoreUnregisterProtocolNotifyEvent ( + IN EFI_EVENT Event + ) +{ + LIST_ENTRY *Link; + PROTOCOL_ENTRY *ProtEntry; + LIST_ENTRY *NotifyLink; + PROTOCOL_NOTIFY *ProtNotify; + + CoreAcquireProtocolLock (); + + for ( Link = mProtocolDatabase.ForwardLink; + Link != &mProtocolDatabase; + Link = Link->ForwardLink) { + + ProtEntry = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE); + + for ( NotifyLink = ProtEntry->Notify.ForwardLink; + NotifyLink != &ProtEntry->Notify; + NotifyLink = NotifyLink->ForwardLink) { + + ProtNotify = CR(NotifyLink, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE); + + if (ProtNotify->Event == Event) { + RemoveEntryList(&ProtNotify->Link); + CoreFreePool(ProtNotify); + CoreReleaseProtocolLock (); + return EFI_SUCCESS; + } + } + } + + CoreReleaseProtocolLock (); + return EFI_NOT_FOUND; +} + + + +/** + Removes all the events in the protocol database that match Event. + + @param Event The event to search for in the protocol + database. + + @return EFI_SUCCESS when done searching the entire database. + +**/ +EFI_STATUS +CoreUnregisterProtocolNotify ( + IN EFI_EVENT Event + ) +{ + EFI_STATUS Status; + + do { + Status = CoreUnregisterProtocolNotifyEvent (Event); + } while (!EFI_ERROR (Status)); + + return EFI_SUCCESS; +} + + + + +/** + Wrapper function to CoreInstallProtocolInterfaceNotify. This is the public API which + Calls the private one which contains a BOOLEAN parameter for notifications + + @param UserHandle The handle to install the protocol handler on, + or NULL if a new handle is to be allocated + @param Protocol The protocol to add to the handle + @param InterfaceType Indicates whether Interface is supplied in + native form. + @param Interface The interface for the protocol being added + + @return Status code + +**/ +EFI_STATUS +EFIAPI +CoreInstallProtocolInterface ( + IN OUT EFI_HANDLE *UserHandle, + IN EFI_GUID *Protocol, + IN EFI_INTERFACE_TYPE InterfaceType, + IN VOID *Interface + ) +{ + return CoreInstallProtocolInterfaceNotify ( + UserHandle, + Protocol, + InterfaceType, + Interface, + TRUE + ); +} + + +/** + Installs a protocol interface into the boot services environment. + + @param UserHandle The handle to install the protocol handler on, + or NULL if a new handle is to be allocated + @param Protocol The protocol to add to the handle + @param InterfaceType Indicates whether Interface is supplied in + native form. + @param Interface The interface for the protocol being added + @param Notify indicates whether notify the notification list + for this protocol + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate + @retval EFI_SUCCESS Protocol interface successfully installed + +**/ +EFI_STATUS +CoreInstallProtocolInterfaceNotify ( + IN OUT EFI_HANDLE *UserHandle, + IN EFI_GUID *Protocol, + IN EFI_INTERFACE_TYPE InterfaceType, + IN VOID *Interface, + IN BOOLEAN Notify + ) +{ + PROTOCOL_INTERFACE *Prot; + PROTOCOL_ENTRY *ProtEntry; + IHANDLE *Handle; + EFI_STATUS Status; + VOID *ExistingInterface; + + // + // returns EFI_INVALID_PARAMETER if InterfaceType is invalid. + // Also added check for invalid UserHandle and Protocol pointers. + // + if (UserHandle == NULL || Protocol == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (InterfaceType != EFI_NATIVE_INTERFACE) { + return EFI_INVALID_PARAMETER; + } + + // + // Print debug message + // + DEBUG((DEBUG_INFO, "InstallProtocolInterface: %g %p\n", Protocol, Interface)); + + Status = EFI_OUT_OF_RESOURCES; + Prot = NULL; + Handle = NULL; + + if (*UserHandle != NULL) { + Status = CoreHandleProtocol (*UserHandle, Protocol, (VOID **)&ExistingInterface); + if (!EFI_ERROR (Status)) { + return EFI_INVALID_PARAMETER; + } + } + + // + // Lock the protocol database + // + CoreAcquireProtocolLock (); + + // + // Lookup the Protocol Entry for the requested protocol + // + ProtEntry = CoreFindProtocolEntry (Protocol, TRUE); + if (ProtEntry == NULL) { + goto Done; + } + + // + // Allocate a new protocol interface structure + // + Prot = AllocateZeroPool (sizeof(PROTOCOL_INTERFACE)); + if (Prot == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + // + // If caller didn't supply a handle, allocate a new one + // + Handle = (IHANDLE *)*UserHandle; + if (Handle == NULL) { + Handle = AllocateZeroPool (sizeof(IHANDLE)); + if (Handle == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + // + // Initialize new handler structure + // + Handle->Signature = EFI_HANDLE_SIGNATURE; + InitializeListHead (&Handle->Protocols); + + // + // Initialize the Key to show that the handle has been created/modified + // + gHandleDatabaseKey++; + Handle->Key = gHandleDatabaseKey; + + // + // Add this handle to the list global list of all handles + // in the system + // + InsertTailList (&gHandleList, &Handle->AllHandles); + } else { + Status = CoreValidateHandle (Handle); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "InstallProtocolInterface: input handle at 0x%x is invalid\n", Handle)); + goto Done; + } + } + + // + // Each interface that is added must be unique + // + ASSERT (CoreFindProtocolInterface (Handle, Protocol, Interface) == NULL); + + // + // Initialize the protocol interface structure + // + Prot->Signature = PROTOCOL_INTERFACE_SIGNATURE; + Prot->Handle = Handle; + Prot->Protocol = ProtEntry; + Prot->Interface = Interface; + + // + // Initalize OpenProtocol Data base + // + InitializeListHead (&Prot->OpenList); + Prot->OpenListCount = 0; + + // + // Add this protocol interface to the head of the supported + // protocol list for this handle + // + InsertHeadList (&Handle->Protocols, &Prot->Link); + + // + // Add this protocol interface to the tail of the + // protocol entry + // + InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol); + + // + // Notify the notification list for this protocol + // + if (Notify) { + CoreNotifyProtocolEntry (ProtEntry); + } + Status = EFI_SUCCESS; + +Done: + // + // Done, unlock the database and return + // + CoreReleaseProtocolLock (); + if (!EFI_ERROR (Status)) { + // + // Return the new handle back to the caller + // + *UserHandle = Handle; + } else { + // + // There was an error, clean up + // + if (Prot != NULL) { + CoreFreePool (Prot); + } + DEBUG((DEBUG_ERROR, "InstallProtocolInterface: %g %p failed with %r\n", Protocol, Interface, Status)); + } + + return Status; +} + + + + +/** + Installs a list of protocol interface into the boot services environment. + This function calls InstallProtocolInterface() in a loop. If any error + occures all the protocols added by this function are removed. This is + basically a lib function to save space. + + @param Handle The pointer to a handle to install the new + protocol interfaces on, or a pointer to NULL + if a new handle is to be allocated. + @param ... EFI_GUID followed by protocol instance. A NULL + terminates the list. The pairs are the + arguments to InstallProtocolInterface(). All the + protocols are added to Handle. + + @retval EFI_SUCCESS All the protocol interface was installed. + @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols. + @retval EFI_ALREADY_STARTED A Device Path Protocol instance was passed in that is already present in + the handle database. + @retval EFI_INVALID_PARAMETER Handle is NULL. + @retval EFI_INVALID_PARAMETER Protocol is already installed on the handle specified by Handle. + +**/ +EFI_STATUS +EFIAPI +CoreInstallMultipleProtocolInterfaces ( + IN OUT EFI_HANDLE *Handle, + ... + ) +{ + VA_LIST Args; + EFI_STATUS Status; + EFI_GUID *Protocol; + VOID *Interface; + EFI_TPL OldTpl; + UINTN Index; + EFI_HANDLE OldHandle; + EFI_HANDLE DeviceHandle; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + if (Handle == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Syncronize with notifcations. + // + OldTpl = CoreRaiseTpl (TPL_NOTIFY); + OldHandle = *Handle; + + // + // Check for duplicate device path and install the protocol interfaces + // + VA_START (Args, Handle); + for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) { + // + // If protocol is NULL, then it's the end of the list + // + Protocol = VA_ARG (Args, EFI_GUID *); + if (Protocol == NULL) { + break; + } + + Interface = VA_ARG (Args, VOID *); + + // + // Make sure you are installing on top a device path that has already been added. + // + if (CompareGuid (Protocol, &gEfiDevicePathProtocolGuid)) { + DeviceHandle = NULL; + DevicePath = Interface; + Status = CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &DeviceHandle); + if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd(DevicePath)) { + Status = EFI_ALREADY_STARTED; + continue; + } + } + + // + // Install it + // + Status = CoreInstallProtocolInterface (Handle, Protocol, EFI_NATIVE_INTERFACE, Interface); + } + VA_END (Args); + + // + // If there was an error, remove all the interfaces that were installed without any errors + // + if (EFI_ERROR (Status)) { + // + // Reset the va_arg back to the first argument. + // + VA_START (Args, Handle); + for (; Index > 1; Index--) { + Protocol = VA_ARG (Args, EFI_GUID *); + Interface = VA_ARG (Args, VOID *); + CoreUninstallProtocolInterface (*Handle, Protocol, Interface); + } + VA_END (Args); + + *Handle = OldHandle; + } + + // + // Done + // + CoreRestoreTpl (OldTpl); + return Status; +} + + +/** + Attempts to disconnect all drivers that are using the protocol interface being queried. + If failed, reconnect all drivers disconnected. + Note: This function doesn't do parameters checking, it's caller's responsibility + to pass in valid parameters. + + @param UserHandle The handle on which the protocol is installed + @param Prot The protocol to disconnect drivers from + + @retval EFI_SUCCESS Drivers using the protocol interface are all + disconnected + @retval EFI_ACCESS_DENIED Failed to disconnect one or all of the drivers + +**/ +EFI_STATUS +CoreDisconnectControllersUsingProtocolInterface ( + IN EFI_HANDLE UserHandle, + IN PROTOCOL_INTERFACE *Prot + ) +{ + EFI_STATUS Status; + BOOLEAN ItemFound; + LIST_ENTRY *Link; + OPEN_PROTOCOL_DATA *OpenData; + + Status = EFI_SUCCESS; + + // + // Attempt to disconnect all drivers from this protocol interface + // + do { + ItemFound = FALSE; + for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) { + OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); + if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) { + CoreReleaseProtocolLock (); + Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL); + CoreAcquireProtocolLock (); + if (!EFI_ERROR (Status)) { + ItemFound = TRUE; + } + break; + } + } + } while (ItemFound); + + if (!EFI_ERROR (Status)) { + // + // Attempt to remove BY_HANDLE_PROTOOCL and GET_PROTOCOL and TEST_PROTOCOL Open List items + // + for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList;) { + OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); + if ((OpenData->Attributes & + (EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL | EFI_OPEN_PROTOCOL_GET_PROTOCOL | EFI_OPEN_PROTOCOL_TEST_PROTOCOL)) != 0) { + Link = RemoveEntryList (&OpenData->Link); + Prot->OpenListCount--; + CoreFreePool (OpenData); + } else { + Link = Link->ForwardLink; + } + } + } + + // + // If there are errors or still has open items in the list, then reconnect all the drivers and return an error + // + if (EFI_ERROR (Status) || (Prot->OpenListCount > 0)) { + CoreReleaseProtocolLock (); + CoreConnectController (UserHandle, NULL, NULL, TRUE); + CoreAcquireProtocolLock (); + Status = EFI_ACCESS_DENIED; + } + + return Status; +} + + + +/** + Uninstalls all instances of a protocol:interfacer from a handle. + If the last protocol interface is remove from the handle, the + handle is freed. + + @param UserHandle The handle to remove the protocol handler from + @param Protocol The protocol, of protocol:interface, to remove + @param Interface The interface, of protocol:interface, to remove + + @retval EFI_INVALID_PARAMETER Protocol is NULL. + @retval EFI_SUCCESS Protocol interface successfully uninstalled. + +**/ +EFI_STATUS +EFIAPI +CoreUninstallProtocolInterface ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + IN VOID *Interface + ) +{ + EFI_STATUS Status; + IHANDLE *Handle; + PROTOCOL_INTERFACE *Prot; + + // + // Check that Protocol is valid + // + if (Protocol == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check that UserHandle is a valid handle + // + Status = CoreValidateHandle (UserHandle); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Lock the protocol database + // + CoreAcquireProtocolLock (); + + // + // Check that Protocol exists on UserHandle, and Interface matches the interface in the database + // + Prot = CoreFindProtocolInterface (UserHandle, Protocol, Interface); + if (Prot == NULL) { + Status = EFI_NOT_FOUND; + goto Done; + } + + // + // Attempt to disconnect all drivers that are using the protocol interface that is about to be removed + // + Status = CoreDisconnectControllersUsingProtocolInterface ( + UserHandle, + Prot + ); + if (EFI_ERROR (Status)) { + // + // One or more drivers refused to release, so return the error + // + goto Done; + } + + // + // Remove the protocol interface from the protocol + // + Status = EFI_NOT_FOUND; + Handle = (IHANDLE *)UserHandle; + Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, Interface); + + if (Prot != NULL) { + // + // Update the Key to show that the handle has been created/modified + // + gHandleDatabaseKey++; + Handle->Key = gHandleDatabaseKey; + + // + // Remove the protocol interface from the handle + // + RemoveEntryList (&Prot->Link); + + // + // Free the memory + // + Prot->Signature = 0; + CoreFreePool (Prot); + Status = EFI_SUCCESS; + } + + // + // If there are no more handlers for the handle, free the handle + // + if (IsListEmpty (&Handle->Protocols)) { + Handle->Signature = 0; + RemoveEntryList (&Handle->AllHandles); + CoreFreePool (Handle); + } + +Done: + // + // Done, unlock the database and return + // + CoreReleaseProtocolLock (); + return Status; +} + + + + +/** + Uninstalls a list of protocol interface in the boot services environment. + This function calls UnisatllProtocolInterface() in a loop. This is + basically a lib function to save space. + + @param Handle The handle to uninstall the protocol + @param ... EFI_GUID followed by protocol instance. A NULL + terminates the list. The pairs are the + arguments to UninstallProtocolInterface(). All + the protocols are added to Handle. + + @return Status code + +**/ +EFI_STATUS +EFIAPI +CoreUninstallMultipleProtocolInterfaces ( + IN EFI_HANDLE Handle, + ... + ) +{ + EFI_STATUS Status; + VA_LIST Args; + EFI_GUID *Protocol; + VOID *Interface; + UINTN Index; + + VA_START (Args, Handle); + for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) { + // + // If protocol is NULL, then it's the end of the list + // + Protocol = VA_ARG (Args, EFI_GUID *); + if (Protocol == NULL) { + break; + } + + Interface = VA_ARG (Args, VOID *); + + // + // Uninstall it + // + Status = CoreUninstallProtocolInterface (Handle, Protocol, Interface); + } + VA_END (Args); + + // + // If there was an error, add all the interfaces that were + // uninstalled without any errors + // + if (EFI_ERROR (Status)) { + // + // Reset the va_arg back to the first argument. + // + VA_START (Args, Handle); + for (; Index > 1; Index--) { + Protocol = VA_ARG(Args, EFI_GUID *); + Interface = VA_ARG(Args, VOID *); + CoreInstallProtocolInterface (&Handle, Protocol, EFI_NATIVE_INTERFACE, Interface); + } + VA_END (Args); + } + + return Status; +} + + +/** + Locate a certain GUID protocol interface in a Handle's protocols. + + @param UserHandle The handle to obtain the protocol interface on + @param Protocol The GUID of the protocol + + @return The requested protocol interface for the handle + +**/ +PROTOCOL_INTERFACE * +CoreGetProtocolInterface ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol + ) +{ + EFI_STATUS Status; + PROTOCOL_ENTRY *ProtEntry; + PROTOCOL_INTERFACE *Prot; + IHANDLE *Handle; + LIST_ENTRY *Link; + + Status = CoreValidateHandle (UserHandle); + if (EFI_ERROR (Status)) { + return NULL; + } + + Handle = (IHANDLE *)UserHandle; + + // + // Look at each protocol interface for a match + // + for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) { + Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE); + ProtEntry = Prot->Protocol; + if (CompareGuid (&ProtEntry->ProtocolID, Protocol)) { + return Prot; + } + } + return NULL; +} + + + +/** + Queries a handle to determine if it supports a specified protocol. + + @param UserHandle The handle being queried. + @param Protocol The published unique identifier of the protocol. + @param Interface Supplies the address where a pointer to the + corresponding Protocol Interface is returned. + + @retval EFI_SUCCESS The interface information for the specified protocol was returned. + @retval EFI_UNSUPPORTED The device does not support the specified protocol. + @retval EFI_INVALID_PARAMETER Handle is NULL.. + @retval EFI_INVALID_PARAMETER Protocol is NULL. + @retval EFI_INVALID_PARAMETER Interface is NULL. + +**/ +EFI_STATUS +EFIAPI +CoreHandleProtocol ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + OUT VOID **Interface + ) +{ + return CoreOpenProtocol ( + UserHandle, + Protocol, + Interface, + gDxeCoreImageHandle, + NULL, + EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL + ); +} + + + +/** + Locates the installed protocol handler for the handle, and + invokes it to obtain the protocol interface. Usage information + is registered in the protocol data base. + + @param UserHandle The handle to obtain the protocol interface on + @param Protocol The ID of the protocol + @param Interface The location to return the protocol interface + @param ImageHandle The handle of the Image that is opening the + protocol interface specified by Protocol and + Interface. + @param ControllerHandle The controller handle that is requiring this + interface. + @param Attributes The open mode of the protocol interface + specified by Handle and Protocol. + + @retval EFI_INVALID_PARAMETER Protocol is NULL. + @retval EFI_SUCCESS Get the protocol interface. + +**/ +EFI_STATUS +EFIAPI +CoreOpenProtocol ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + OUT VOID **Interface OPTIONAL, + IN EFI_HANDLE ImageHandle, + IN EFI_HANDLE ControllerHandle, + IN UINT32 Attributes + ) +{ + EFI_STATUS Status; + PROTOCOL_INTERFACE *Prot; + LIST_ENTRY *Link; + OPEN_PROTOCOL_DATA *OpenData; + BOOLEAN ByDriver; + BOOLEAN Exclusive; + BOOLEAN Disconnect; + BOOLEAN ExactMatch; + + // + // Check for invalid Protocol + // + if (Protocol == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check for invalid Interface + // + if ((Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) && (Interface == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Check for invalid UserHandle + // + Status = CoreValidateHandle (UserHandle); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Check for invalid Attributes + // + switch (Attributes) { + case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER : + Status = CoreValidateHandle (ImageHandle); + if (EFI_ERROR (Status)) { + return Status; + } + Status = CoreValidateHandle (ControllerHandle); + if (EFI_ERROR (Status)) { + return Status; + } + if (UserHandle == ControllerHandle) { + return EFI_INVALID_PARAMETER; + } + break; + case EFI_OPEN_PROTOCOL_BY_DRIVER : + case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE : + Status = CoreValidateHandle (ImageHandle); + if (EFI_ERROR (Status)) { + return Status; + } + Status = CoreValidateHandle (ControllerHandle); + if (EFI_ERROR (Status)) { + return Status; + } + break; + case EFI_OPEN_PROTOCOL_EXCLUSIVE : + Status = CoreValidateHandle (ImageHandle); + if (EFI_ERROR (Status)) { + return Status; + } + break; + case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL : + case EFI_OPEN_PROTOCOL_GET_PROTOCOL : + case EFI_OPEN_PROTOCOL_TEST_PROTOCOL : + break; + default: + return EFI_INVALID_PARAMETER; + } + + // + // Lock the protocol database + // + CoreAcquireProtocolLock (); + + // + // Look at each protocol interface for a match + // + Prot = CoreGetProtocolInterface (UserHandle, Protocol); + if (Prot == NULL) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + Status = EFI_SUCCESS; + + ByDriver = FALSE; + Exclusive = FALSE; + for ( Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) { + OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); + ExactMatch = (BOOLEAN)((OpenData->AgentHandle == ImageHandle) && + (OpenData->Attributes == Attributes) && + (OpenData->ControllerHandle == ControllerHandle)); + if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) { + ByDriver = TRUE; + if (ExactMatch) { + Status = EFI_ALREADY_STARTED; + goto Done; + } + } + if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) != 0) { + Exclusive = TRUE; + } else if (ExactMatch) { + OpenData->OpenCount++; + Status = EFI_SUCCESS; + goto Done; + } + } + + // + // ByDriver TRUE -> A driver is managing (UserHandle, Protocol) + // ByDriver FALSE -> There are no drivers managing (UserHandle, Protocol) + // Exclusive TRUE -> Something has exclusive access to (UserHandle, Protocol) + // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol) + // + + switch (Attributes) { + case EFI_OPEN_PROTOCOL_BY_DRIVER : + if (Exclusive || ByDriver) { + Status = EFI_ACCESS_DENIED; + goto Done; + } + break; + case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE : + case EFI_OPEN_PROTOCOL_EXCLUSIVE : + if (Exclusive) { + Status = EFI_ACCESS_DENIED; + goto Done; + } + if (ByDriver) { + do { + Disconnect = FALSE; + for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) { + OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); + if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) { + Disconnect = TRUE; + CoreReleaseProtocolLock (); + Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL); + CoreAcquireProtocolLock (); + if (EFI_ERROR (Status)) { + Status = EFI_ACCESS_DENIED; + goto Done; + } else { + break; + } + } + } + } while (Disconnect); + } + break; + case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER : + case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL : + case EFI_OPEN_PROTOCOL_GET_PROTOCOL : + case EFI_OPEN_PROTOCOL_TEST_PROTOCOL : + break; + } + + if (ImageHandle == NULL) { + Status = EFI_SUCCESS; + goto Done; + } + // + // Create new entry + // + OpenData = AllocatePool (sizeof(OPEN_PROTOCOL_DATA)); + if (OpenData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + OpenData->Signature = OPEN_PROTOCOL_DATA_SIGNATURE; + OpenData->AgentHandle = ImageHandle; + OpenData->ControllerHandle = ControllerHandle; + OpenData->Attributes = Attributes; + OpenData->OpenCount = 1; + InsertTailList (&Prot->OpenList, &OpenData->Link); + Prot->OpenListCount++; + Status = EFI_SUCCESS; + } + +Done: + + if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) { + // + // Keep Interface unmodified in case of any Error + // except EFI_ALREADY_STARTED and EFI_UNSUPPORTED. + // + if (!EFI_ERROR (Status) || Status == EFI_ALREADY_STARTED) { + // + // According to above logic, if 'Prot' is NULL, then the 'Status' must be + // EFI_UNSUPPORTED. Here the 'Status' is not EFI_UNSUPPORTED, so 'Prot' + // must be not NULL. + // + // The ASSERT here is for addressing a false positive NULL pointer + // dereference issue raised from static analysis. + // + ASSERT (Prot != NULL); + // + // EFI_ALREADY_STARTED is not an error for bus driver. + // Return the corresponding protocol interface. + // + *Interface = Prot->Interface; + } else if (Status == EFI_UNSUPPORTED) { + // + // Return NULL Interface if Unsupported Protocol. + // + *Interface = NULL; + } + } + + // + // Done. Release the database lock and return + // + CoreReleaseProtocolLock (); + return Status; +} + + + +/** + Closes a protocol on a handle that was opened using OpenProtocol(). + + @param UserHandle The handle for the protocol interface that was + previously opened with OpenProtocol(), and is + now being closed. + @param Protocol The published unique identifier of the protocol. + It is the caller's responsibility to pass in a + valid GUID. + @param AgentHandle The handle of the agent that is closing the + protocol interface. + @param ControllerHandle If the agent that opened a protocol is a driver + that follows the EFI Driver Model, then this + parameter is the controller handle that required + the protocol interface. If the agent does not + follow the EFI Driver Model, then this parameter + is optional and may be NULL. + + @retval EFI_SUCCESS The protocol instance was closed. + @retval EFI_INVALID_PARAMETER Handle, AgentHandle or ControllerHandle is not a + valid EFI_HANDLE. + @retval EFI_NOT_FOUND Can not find the specified protocol or + AgentHandle. + +**/ +EFI_STATUS +EFIAPI +CoreCloseProtocol ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + IN EFI_HANDLE AgentHandle, + IN EFI_HANDLE ControllerHandle + ) +{ + EFI_STATUS Status; + PROTOCOL_INTERFACE *ProtocolInterface; + LIST_ENTRY *Link; + OPEN_PROTOCOL_DATA *OpenData; + + // + // Check for invalid parameters + // + Status = CoreValidateHandle (UserHandle); + if (EFI_ERROR (Status)) { + return Status; + } + Status = CoreValidateHandle (AgentHandle); + if (EFI_ERROR (Status)) { + return Status; + } + if (ControllerHandle != NULL) { + Status = CoreValidateHandle (ControllerHandle); + if (EFI_ERROR (Status)) { + return Status; + } + } + if (Protocol == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Lock the protocol database + // + CoreAcquireProtocolLock (); + + // + // Look at each protocol interface for a match + // + Status = EFI_NOT_FOUND; + ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol); + if (ProtocolInterface == NULL) { + goto Done; + } + + // + // Walk the Open data base looking for AgentHandle + // + Link = ProtocolInterface->OpenList.ForwardLink; + while (Link != &ProtocolInterface->OpenList) { + OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); + Link = Link->ForwardLink; + if ((OpenData->AgentHandle == AgentHandle) && (OpenData->ControllerHandle == ControllerHandle)) { + RemoveEntryList (&OpenData->Link); + ProtocolInterface->OpenListCount--; + CoreFreePool (OpenData); + Status = EFI_SUCCESS; + } + } + +Done: + // + // Done. Release the database lock and return. + // + CoreReleaseProtocolLock (); + return Status; +} + + + + +/** + Return information about Opened protocols in the system + + @param UserHandle The handle to close the protocol interface on + @param Protocol The ID of the protocol + @param EntryBuffer A pointer to a buffer of open protocol information in the + form of EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures. + @param EntryCount Number of EntryBuffer entries + + @retval EFI_SUCCESS The open protocol information was returned in EntryBuffer, + and the number of entries was returned EntryCount. + @retval EFI_NOT_FOUND Handle does not support the protocol specified by Protocol. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate EntryBuffer. + +**/ +EFI_STATUS +EFIAPI +CoreOpenProtocolInformation ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer, + OUT UINTN *EntryCount + ) +{ + EFI_STATUS Status; + PROTOCOL_INTERFACE *ProtocolInterface; + LIST_ENTRY *Link; + OPEN_PROTOCOL_DATA *OpenData; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *Buffer; + UINTN Count; + UINTN Size; + + *EntryBuffer = NULL; + *EntryCount = 0; + + // + // Lock the protocol database + // + CoreAcquireProtocolLock (); + + // + // Look at each protocol interface for a match + // + Status = EFI_NOT_FOUND; + ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol); + if (ProtocolInterface == NULL) { + goto Done; + } + + // + // Count the number of Open Entries + // + for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0; + (Link != &ProtocolInterface->OpenList) ; + Link = Link->ForwardLink ) { + Count++; + } + + ASSERT (Count == ProtocolInterface->OpenListCount); + + if (Count == 0) { + Size = sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY); + } else { + Size = Count * sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY); + } + + Buffer = AllocatePool (Size); + if (Buffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + Status = EFI_SUCCESS; + for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0; + (Link != &ProtocolInterface->OpenList); + Link = Link->ForwardLink, Count++ ) { + OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); + + Buffer[Count].AgentHandle = OpenData->AgentHandle; + Buffer[Count].ControllerHandle = OpenData->ControllerHandle; + Buffer[Count].Attributes = OpenData->Attributes; + Buffer[Count].OpenCount = OpenData->OpenCount; + } + + *EntryBuffer = Buffer; + *EntryCount = Count; + +Done: + // + // Done. Release the database lock. + // + CoreReleaseProtocolLock (); + return Status; +} + + + + +/** + Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated + from pool. + + @param UserHandle The handle from which to retrieve the list of + protocol interface GUIDs. + @param ProtocolBuffer A pointer to the list of protocol interface GUID + pointers that are installed on Handle. + @param ProtocolBufferCount A pointer to the number of GUID pointers present + in ProtocolBuffer. + + @retval EFI_SUCCESS The list of protocol interface GUIDs installed + on Handle was returned in ProtocolBuffer. The + number of protocol interface GUIDs was returned + in ProtocolBufferCount. + @retval EFI_INVALID_PARAMETER Handle is NULL. + @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ProtocolBuffer is NULL. + @retval EFI_INVALID_PARAMETER ProtocolBufferCount is NULL. + @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the + results. + +**/ +EFI_STATUS +EFIAPI +CoreProtocolsPerHandle ( + IN EFI_HANDLE UserHandle, + OUT EFI_GUID ***ProtocolBuffer, + OUT UINTN *ProtocolBufferCount + ) +{ + EFI_STATUS Status; + IHANDLE *Handle; + PROTOCOL_INTERFACE *Prot; + LIST_ENTRY *Link; + UINTN ProtocolCount; + EFI_GUID **Buffer; + + Status = CoreValidateHandle (UserHandle); + if (EFI_ERROR (Status)) { + return Status; + } + + Handle = (IHANDLE *)UserHandle; + + if (ProtocolBuffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (ProtocolBufferCount == NULL) { + return EFI_INVALID_PARAMETER; + } + + *ProtocolBufferCount = 0; + + ProtocolCount = 0; + + CoreAcquireProtocolLock (); + + for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) { + ProtocolCount++; + } + + // + // If there are no protocol interfaces installed on Handle, then Handle is not a valid EFI_HANDLE + // + if (ProtocolCount == 0) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + Buffer = AllocatePool (sizeof (EFI_GUID *) * ProtocolCount); + if (Buffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + *ProtocolBuffer = Buffer; + *ProtocolBufferCount = ProtocolCount; + + for ( Link = Handle->Protocols.ForwardLink, ProtocolCount = 0; + Link != &Handle->Protocols; + Link = Link->ForwardLink, ProtocolCount++) { + Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE); + Buffer[ProtocolCount] = &(Prot->Protocol->ProtocolID); + } + Status = EFI_SUCCESS; + +Done: + CoreReleaseProtocolLock (); + return Status; +} + + + +/** + return handle database key. + + + @return Handle database key. + +**/ +UINT64 +CoreGetHandleDatabaseKey ( + VOID + ) +{ + return gHandleDatabaseKey; +} + + + +/** + Go connect any handles that were created or modified while a image executed. + + @param Key The Key to show that the handle has been + created/modified + +**/ +VOID +CoreConnectHandlesByKey ( + UINT64 Key + ) +{ + UINTN Count; + LIST_ENTRY *Link; + EFI_HANDLE *HandleBuffer; + IHANDLE *Handle; + UINTN Index; + + // + // Lock the protocol database + // + CoreAcquireProtocolLock (); + + for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) { + Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE); + if (Handle->Key > Key) { + Count++; + } + } + + HandleBuffer = AllocatePool (Count * sizeof (EFI_HANDLE)); + if (HandleBuffer == NULL) { + CoreReleaseProtocolLock (); + return; + } + + for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) { + Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE); + if (Handle->Key > Key) { + HandleBuffer[Count++] = Handle; + } + } + + // + // Unlock the protocol database + // + CoreReleaseProtocolLock (); + + // + // Connect all handles whose Key value is greater than Key + // + for (Index = 0; Index < Count; Index++) { + CoreConnectController (HandleBuffer[Index], NULL, NULL, TRUE); + } + + CoreFreePool(HandleBuffer); +} diff --git a/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/Handle.h b/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/Handle.h new file mode 100644 index 0000000..83eb2b9 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/Handle.h @@ -0,0 +1,264 @@ +/** @file + Support functions for managing protocol. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _HAND_H_ +#define _HAND_H_ + + +#define EFI_HANDLE_SIGNATURE SIGNATURE_32('h','n','d','l') + +/// +/// IHANDLE - contains a list of protocol handles +/// +typedef struct { + UINTN Signature; + /// All handles list of IHANDLE + LIST_ENTRY AllHandles; + /// List of PROTOCOL_INTERFACE's for this handle + LIST_ENTRY Protocols; + UINTN LocateRequest; + /// The Handle Database Key value when this handle was last created or modified + UINT64 Key; +} IHANDLE; + +#define ASSERT_IS_HANDLE(a) ASSERT((a)->Signature == EFI_HANDLE_SIGNATURE) + +#define PROTOCOL_ENTRY_SIGNATURE SIGNATURE_32('p','r','t','e') + +/// +/// PROTOCOL_ENTRY - each different protocol has 1 entry in the protocol +/// database. Each handler that supports this protocol is listed, along +/// with a list of registered notifies. +/// +typedef struct { + UINTN Signature; + /// Link Entry inserted to mProtocolDatabase + LIST_ENTRY AllEntries; + /// ID of the protocol + EFI_GUID ProtocolID; + /// All protocol interfaces + LIST_ENTRY Protocols; + /// Registerd notification handlers + LIST_ENTRY Notify; +} PROTOCOL_ENTRY; + + +#define PROTOCOL_INTERFACE_SIGNATURE SIGNATURE_32('p','i','f','c') + +/// +/// PROTOCOL_INTERFACE - each protocol installed on a handle is tracked +/// with a protocol interface structure +/// +typedef struct { + UINTN Signature; + /// Link on IHANDLE.Protocols + LIST_ENTRY Link; + /// Back pointer + IHANDLE *Handle; + /// Link on PROTOCOL_ENTRY.Protocols + LIST_ENTRY ByProtocol; + /// The protocol ID + PROTOCOL_ENTRY *Protocol; + /// The interface value + VOID *Interface; + /// OPEN_PROTOCOL_DATA list + LIST_ENTRY OpenList; + UINTN OpenListCount; + +} PROTOCOL_INTERFACE; + +#define OPEN_PROTOCOL_DATA_SIGNATURE SIGNATURE_32('p','o','d','l') + +typedef struct { + UINTN Signature; + ///Link on PROTOCOL_INTERFACE.OpenList + LIST_ENTRY Link; + + EFI_HANDLE AgentHandle; + EFI_HANDLE ControllerHandle; + UINT32 Attributes; + UINT32 OpenCount; +} OPEN_PROTOCOL_DATA; + + +#define PROTOCOL_NOTIFY_SIGNATURE SIGNATURE_32('p','r','t','n') + +/// +/// PROTOCOL_NOTIFY - used for each register notification for a protocol +/// +typedef struct { + UINTN Signature; + PROTOCOL_ENTRY *Protocol; + /// All notifications for this protocol + LIST_ENTRY Link; + /// Event to notify + EFI_EVENT Event; + /// Last position notified + LIST_ENTRY *Position; +} PROTOCOL_NOTIFY; + + + +/** + Finds the protocol entry for the requested protocol. + The gProtocolDatabaseLock must be owned + + @param Protocol The ID of the protocol + @param Create Create a new entry if not found + + @return Protocol entry + +**/ +PROTOCOL_ENTRY * +CoreFindProtocolEntry ( + IN EFI_GUID *Protocol, + IN BOOLEAN Create + ); + + +/** + Signal event for every protocol in protocol entry. + + @param ProtEntry Protocol entry + +**/ +VOID +CoreNotifyProtocolEntry ( + IN PROTOCOL_ENTRY *ProtEntry + ); + + +/** + Finds the protocol instance for the requested handle and protocol. + Note: This function doesn't do parameters checking, it's caller's responsibility + to pass in valid parameters. + + @param Handle The handle to search the protocol on + @param Protocol GUID of the protocol + @param Interface The interface for the protocol being searched + + @return Protocol instance (NULL: Not found) + +**/ +PROTOCOL_INTERFACE * +CoreFindProtocolInterface ( + IN IHANDLE *Handle, + IN EFI_GUID *Protocol, + IN VOID *Interface + ); + + +/** + Removes Protocol from the protocol list (but not the handle list). + + @param Handle The handle to remove protocol on. + @param Protocol GUID of the protocol to be moved + @param Interface The interface of the protocol + + @return Protocol Entry + +**/ +PROTOCOL_INTERFACE * +CoreRemoveInterfaceFromProtocol ( + IN IHANDLE *Handle, + IN EFI_GUID *Protocol, + IN VOID *Interface + ); + + +/** + Connects a controller to a driver. + + @param ControllerHandle Handle of the controller to be + connected. + @param ContextDriverImageHandles DriverImageHandle A pointer to an + ordered list of driver image + handles. + @param RemainingDevicePath RemainingDevicePath A pointer to + the device path that specifies a + child of the controller + specified by ControllerHandle. + + @retval EFI_SUCCESS One or more drivers were + connected to ControllerHandle. + @retval EFI_OUT_OF_RESOURCES No enough system resources to + complete the request. + @retval EFI_NOT_FOUND No drivers were connected to + ControllerHandle. + +**/ +EFI_STATUS +CoreConnectSingleController ( + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE *ContextDriverImageHandles OPTIONAL, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ); + +/** + Attempts to disconnect all drivers that are using the protocol interface being queried. + If failed, reconnect all drivers disconnected. + Note: This function doesn't do parameters checking, it's caller's responsibility + to pass in valid parameters. + + @param UserHandle The handle on which the protocol is installed + @param Prot The protocol to disconnect drivers from + + @retval EFI_SUCCESS Drivers using the protocol interface are all + disconnected + @retval EFI_ACCESS_DENIED Failed to disconnect one or all of the drivers + +**/ +EFI_STATUS +CoreDisconnectControllersUsingProtocolInterface ( + IN EFI_HANDLE UserHandle, + IN PROTOCOL_INTERFACE *Prot + ); + + +/** + Acquire lock on gProtocolDatabaseLock. + +**/ +VOID +CoreAcquireProtocolLock ( + VOID + ); + + +/** + Release lock on gProtocolDatabaseLock. + +**/ +VOID +CoreReleaseProtocolLock ( + VOID + ); + + +/** + Check whether a handle is a valid EFI_HANDLE + + @param UserHandle The handle to check + + @retval EFI_INVALID_PARAMETER The handle is NULL or not a valid EFI_HANDLE. + @retval EFI_SUCCESS The handle is valid EFI_HANDLE. + +**/ +EFI_STATUS +CoreValidateHandle ( + IN EFI_HANDLE UserHandle + ); + +// +// Externs +// +extern EFI_LOCK gProtocolDatabaseLock; +extern LIST_ENTRY gHandleList; +extern UINT64 gHandleDatabaseKey; + +#endif diff --git a/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/Library.c b/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/Library.c new file mode 100644 index 0000000..b7f0781 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/Library.c @@ -0,0 +1,100 @@ +/** @file + DXE Core library services. + +Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "DxeMain.h" + +// +// Lock Stuff +// +/** + Initialize a basic mutual exclusion lock. Each lock + provides mutual exclusion access at it's task priority + level. Since there is no-premption (at any TPL) or + multiprocessor support, acquiring the lock only consists + of raising to the locks TPL. + + @param Lock The EFI_LOCK structure to initialize + + @retval EFI_SUCCESS Lock Owned. + @retval EFI_ACCESS_DENIED Reentrant Lock Acquisition, Lock not Owned. + +**/ +EFI_STATUS +CoreAcquireLockOrFail ( + IN EFI_LOCK *Lock + ) +{ + ASSERT (Lock != NULL); + ASSERT (Lock->Lock != EfiLockUninitialized); + + if (Lock->Lock == EfiLockAcquired) { + // + // Lock is already owned, so bail out + // + return EFI_ACCESS_DENIED; + } + + Lock->OwnerTpl = CoreRaiseTpl (Lock->Tpl); + + Lock->Lock = EfiLockAcquired; + return EFI_SUCCESS; +} + + + +/** + Raising to the task priority level of the mutual exclusion + lock, and then acquires ownership of the lock. + + @param Lock The lock to acquire + + @return Lock owned + +**/ +VOID +CoreAcquireLock ( + IN EFI_LOCK *Lock + ) +{ + ASSERT (Lock != NULL); + ASSERT (Lock->Lock == EfiLockReleased); + + Lock->OwnerTpl = CoreRaiseTpl (Lock->Tpl); + Lock->Lock = EfiLockAcquired; +} + + + +/** + Releases ownership of the mutual exclusion lock, and + restores the previous task priority level. + + @param Lock The lock to release + + @return Lock unowned + +**/ +VOID +CoreReleaseLock ( + IN EFI_LOCK *Lock + ) +{ + EFI_TPL Tpl; + + ASSERT (Lock != NULL); + ASSERT (Lock->Lock == EfiLockAcquired); + + Tpl = Lock->OwnerTpl; + + Lock->Lock = EfiLockReleased; + + CoreRestoreTpl (Tpl); +} + + + diff --git a/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/Locate.c b/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/Locate.c new file mode 100644 index 0000000..be17f4c --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/Locate.c @@ -0,0 +1,702 @@ +/** @file + Locate handle functions + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "DxeMain.h" +#include "Handle.h" + +// +// ProtocolRequest - Last LocateHandle request ID +// +UINTN mEfiLocateHandleRequest = 0; + +// +// Internal prototypes +// + +typedef struct { + EFI_GUID *Protocol; + VOID *SearchKey; + LIST_ENTRY *Position; + PROTOCOL_ENTRY *ProtEntry; +} LOCATE_POSITION; + +typedef +IHANDLE * +(* CORE_GET_NEXT) ( + IN OUT LOCATE_POSITION *Position, + OUT VOID **Interface + ); + +/** + Routine to get the next Handle, when you are searching for all handles. + + @param Position Information about which Handle to seach for. + @param Interface Return the interface structure for the matching + protocol. + + @return An pointer to IHANDLE if the next Position is not the end of the list. + Otherwise,NULL is returned. + +**/ +IHANDLE * +CoreGetNextLocateAllHandles ( + IN OUT LOCATE_POSITION *Position, + OUT VOID **Interface + ); + +/** + Routine to get the next Handle, when you are searching for register protocol + notifies. + + @param Position Information about which Handle to seach for. + @param Interface Return the interface structure for the matching + protocol. + + @return An pointer to IHANDLE if the next Position is not the end of the list. + Otherwise,NULL is returned. + +**/ +IHANDLE * +CoreGetNextLocateByRegisterNotify ( + IN OUT LOCATE_POSITION *Position, + OUT VOID **Interface + ); + +/** + Routine to get the next Handle, when you are searching for a given protocol. + + @param Position Information about which Handle to seach for. + @param Interface Return the interface structure for the matching + protocol. + + @return An pointer to IHANDLE if the next Position is not the end of the list. + Otherwise,NULL is returned. + +**/ +IHANDLE * +CoreGetNextLocateByProtocol ( + IN OUT LOCATE_POSITION *Position, + OUT VOID **Interface + ); + + +/** + Locates the requested handle(s) and returns them in Buffer. + + @param SearchType The type of search to perform to locate the + handles + @param Protocol The protocol to search for + @param SearchKey Dependant on SearchType + @param BufferSize On input the size of Buffer. On output the + size of data returned. + @param Buffer The buffer to return the results in + + @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is + returned in BufferSize. + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_SUCCESS Successfully found the requested handle(s) and + returns them in Buffer. + +**/ +EFI_STATUS +EFIAPI +CoreLocateHandle ( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol OPTIONAL, + IN VOID *SearchKey OPTIONAL, + IN OUT UINTN *BufferSize, + OUT EFI_HANDLE *Buffer + ) +{ + EFI_STATUS Status; + LOCATE_POSITION Position; + PROTOCOL_NOTIFY *ProtNotify; + CORE_GET_NEXT GetNext; + UINTN ResultSize; + IHANDLE *Handle; + IHANDLE **ResultBuffer; + VOID *Interface; + + if (BufferSize == NULL) { + return EFI_INVALID_PARAMETER; + } + + if ((*BufferSize > 0) && (Buffer == NULL)) { + return EFI_INVALID_PARAMETER; + } + + GetNext = NULL; + + // + // Set initial position + // + Position.Protocol = Protocol; + Position.SearchKey = SearchKey; + Position.Position = &gHandleList; + + ResultSize = 0; + ResultBuffer = (IHANDLE **) Buffer; + Status = EFI_SUCCESS; + + // + // Lock the protocol database + // + CoreAcquireProtocolLock (); + + // + // Get the search function based on type + // + switch (SearchType) { + case AllHandles: + GetNext = CoreGetNextLocateAllHandles; + break; + + case ByRegisterNotify: + // + // Must have SearchKey for locate ByRegisterNotify + // + if (SearchKey == NULL) { + Status = EFI_INVALID_PARAMETER; + break; + } + GetNext = CoreGetNextLocateByRegisterNotify; + break; + + case ByProtocol: + GetNext = CoreGetNextLocateByProtocol; + if (Protocol == NULL) { + Status = EFI_INVALID_PARAMETER; + break; + } + // + // Look up the protocol entry and set the head pointer + // + Position.ProtEntry = CoreFindProtocolEntry (Protocol, FALSE); + if (Position.ProtEntry == NULL) { + Status = EFI_NOT_FOUND; + break; + } + Position.Position = &Position.ProtEntry->Protocols; + break; + + default: + Status = EFI_INVALID_PARAMETER; + break; + } + + if (EFI_ERROR(Status)) { + CoreReleaseProtocolLock (); + return Status; + } + + ASSERT (GetNext != NULL); + // + // Enumerate out the matching handles + // + mEfiLocateHandleRequest += 1; + for (; ;) { + // + // Get the next handle. If no more handles, stop + // + Handle = GetNext (&Position, &Interface); + if (NULL == Handle) { + break; + } + + // + // Increase the resulting buffer size, and if this handle + // fits return it + // + ResultSize += sizeof(Handle); + if (ResultSize <= *BufferSize) { + *ResultBuffer = Handle; + ResultBuffer += 1; + } + } + + // + // If the result is a zero length buffer, then there were no + // matching handles + // + if (ResultSize == 0) { + Status = EFI_NOT_FOUND; + } else { + // + // Return the resulting buffer size. If it's larger than what + // was passed, then set the error code + // + if (ResultSize > *BufferSize) { + Status = EFI_BUFFER_TOO_SMALL; + } + + *BufferSize = ResultSize; + + if (SearchType == ByRegisterNotify && !EFI_ERROR(Status)) { + // + // If this is a search by register notify and a handle was + // returned, update the register notification position + // + ASSERT (SearchKey != NULL); + ProtNotify = SearchKey; + ProtNotify->Position = ProtNotify->Position->ForwardLink; + } + } + + CoreReleaseProtocolLock (); + return Status; +} + + + +/** + Routine to get the next Handle, when you are searching for all handles. + + @param Position Information about which Handle to seach for. + @param Interface Return the interface structure for the matching + protocol. + + @return An pointer to IHANDLE if the next Position is not the end of the list. + Otherwise,NULL is returned. + +**/ +IHANDLE * +CoreGetNextLocateAllHandles ( + IN OUT LOCATE_POSITION *Position, + OUT VOID **Interface + ) +{ + IHANDLE *Handle; + + // + // Next handle + // + Position->Position = Position->Position->ForwardLink; + + // + // If not at the end of the list, get the handle + // + Handle = NULL; + *Interface = NULL; + if (Position->Position != &gHandleList) { + Handle = CR (Position->Position, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE); + } + + return Handle; +} + + + +/** + Routine to get the next Handle, when you are searching for register protocol + notifies. + + @param Position Information about which Handle to seach for. + @param Interface Return the interface structure for the matching + protocol. + + @return An pointer to IHANDLE if the next Position is not the end of the list. + Otherwise,NULL is returned. + +**/ +IHANDLE * +CoreGetNextLocateByRegisterNotify ( + IN OUT LOCATE_POSITION *Position, + OUT VOID **Interface + ) +{ + IHANDLE *Handle; + PROTOCOL_NOTIFY *ProtNotify; + PROTOCOL_INTERFACE *Prot; + LIST_ENTRY *Link; + + Handle = NULL; + *Interface = NULL; + ProtNotify = Position->SearchKey; + + // + // If this is the first request, get the next handle + // + if (ProtNotify != NULL) { + ASSERT(ProtNotify->Signature == PROTOCOL_NOTIFY_SIGNATURE); + Position->SearchKey = NULL; + + // + // If not at the end of the list, get the next handle + // + Link = ProtNotify->Position->ForwardLink; + if (Link != &ProtNotify->Protocol->Protocols) { + Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE); + Handle = Prot->Handle; + *Interface = Prot->Interface; + } + } + + return Handle; +} + + +/** + Routine to get the next Handle, when you are searching for a given protocol. + + @param Position Information about which Handle to seach for. + @param Interface Return the interface structure for the matching + protocol. + + @return An pointer to IHANDLE if the next Position is not the end of the list. + Otherwise,NULL is returned. + +**/ +IHANDLE * +CoreGetNextLocateByProtocol ( + IN OUT LOCATE_POSITION *Position, + OUT VOID **Interface + ) +{ + IHANDLE *Handle; + LIST_ENTRY *Link; + PROTOCOL_INTERFACE *Prot; + + Handle = NULL; + *Interface = NULL; + for (; ;) { + // + // Next entry + // + Link = Position->Position->ForwardLink; + Position->Position = Link; + + // + // If not at the end, return the handle + // + if (Link == &Position->ProtEntry->Protocols) { + Handle = NULL; + break; + } + + // + // Get the handle + // + Prot = CR(Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE); + Handle = Prot->Handle; + *Interface = Prot->Interface; + + // + // If this handle has not been returned this request, then + // return it now + // + if (Handle->LocateRequest != mEfiLocateHandleRequest) { + Handle->LocateRequest = mEfiLocateHandleRequest; + break; + } + } + + return Handle; +} + + +/** + Locates the handle to a device on the device path that supports the specified protocol. + + @param Protocol Specifies the protocol to search for. + @param DevicePath On input, a pointer to a pointer to the device path. On output, the device + path pointer is modified to point to the remaining part of the device + path. + @param Device A pointer to the returned device handle. + + @retval EFI_SUCCESS The resulting handle was returned. + @retval EFI_NOT_FOUND No handles match the search. + @retval EFI_INVALID_PARAMETER Protocol is NULL. + @retval EFI_INVALID_PARAMETER DevicePath is NULL. + @retval EFI_INVALID_PARAMETER A handle matched the search and Device is NULL. + +**/ +EFI_STATUS +EFIAPI +CoreLocateDevicePath ( + IN EFI_GUID *Protocol, + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, + OUT EFI_HANDLE *Device + ) +{ + INTN SourceSize; + INTN Size; + INTN BestMatch; + UINTN HandleCount; + UINTN Index; + EFI_STATUS Status; + EFI_HANDLE *Handles; + EFI_HANDLE Handle; + EFI_HANDLE BestDevice; + EFI_DEVICE_PATH_PROTOCOL *SourcePath; + EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath; + + if (Protocol == NULL) { + return EFI_INVALID_PARAMETER; + } + + if ((DevicePath == NULL) || (*DevicePath == NULL)) { + return EFI_INVALID_PARAMETER; + } + + Handles = NULL; + BestDevice = NULL; + SourcePath = *DevicePath; + TmpDevicePath = SourcePath; + while (!IsDevicePathEnd (TmpDevicePath)) { + if (IsDevicePathEndInstance (TmpDevicePath)) { + // + // If DevicePath is a multi-instance device path, + // the function will operate on the first instance + // + break; + } + TmpDevicePath = NextDevicePathNode (TmpDevicePath); + } + + SourceSize = (UINTN) TmpDevicePath - (UINTN) SourcePath; + + // + // Get a list of all handles that support the requested protocol + // + Status = CoreLocateHandleBuffer (ByProtocol, Protocol, NULL, &HandleCount, &Handles); + if (EFI_ERROR (Status) || HandleCount == 0) { + return EFI_NOT_FOUND; + } + + BestMatch = -1; + for(Index = 0; Index < HandleCount; Index += 1) { + Handle = Handles[Index]; + Status = CoreHandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&TmpDevicePath); + if (EFI_ERROR (Status)) { + // + // If this handle doesn't support device path, then skip it + // + continue; + } + + // + // Check if DevicePath is first part of SourcePath + // + Size = GetDevicePathSize (TmpDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL); + ASSERT (Size >= 0); + if ((Size <= SourceSize) && CompareMem (SourcePath, TmpDevicePath, (UINTN) Size) == 0) { + // + // If the size is equal to the best match, then we + // have a duplicate device path for 2 different device + // handles + // + ASSERT (Size != BestMatch); + + // + // We've got a match, see if it's the best match so far + // + if (Size > BestMatch) { + BestMatch = Size; + BestDevice = Handle; + } + } + } + + CoreFreePool (Handles); + + // + // If there wasn't any match, then no parts of the device path was found. + // Which is strange since there is likely a "root level" device path in the system. + // + if (BestMatch == -1) { + return EFI_NOT_FOUND; + } + + if (Device == NULL) { + return EFI_INVALID_PARAMETER; + } + *Device = BestDevice; + + // + // Return the remaining part of the device path + // + *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) SourcePath) + BestMatch); + return EFI_SUCCESS; +} + + +/** + Return the first Protocol Interface that matches the Protocol GUID. If + Registration is passed in, return a Protocol Instance that was just add + to the system. If Registration is NULL return the first Protocol Interface + you find. + + @param Protocol The protocol to search for + @param Registration Optional Registration Key returned from + RegisterProtocolNotify() + @param Interface Return the Protocol interface (instance). + + @retval EFI_SUCCESS If a valid Interface is returned + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_NOT_FOUND Protocol interface not found + +**/ +EFI_STATUS +EFIAPI +CoreLocateProtocol ( + IN EFI_GUID *Protocol, + IN VOID *Registration OPTIONAL, + OUT VOID **Interface + ) +{ + EFI_STATUS Status; + LOCATE_POSITION Position; + PROTOCOL_NOTIFY *ProtNotify; + IHANDLE *Handle; + + if ((Interface == NULL) || (Protocol == NULL)) { + return EFI_INVALID_PARAMETER; + } + + *Interface = NULL; + Status = EFI_SUCCESS; + + // + // Set initial position + // + Position.Protocol = Protocol; + Position.SearchKey = Registration; + Position.Position = &gHandleList; + + // + // Lock the protocol database + // + Status = CoreAcquireLockOrFail (&gProtocolDatabaseLock); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + mEfiLocateHandleRequest += 1; + + if (Registration == NULL) { + // + // Look up the protocol entry and set the head pointer + // + Position.ProtEntry = CoreFindProtocolEntry (Protocol, FALSE); + if (Position.ProtEntry == NULL) { + Status = EFI_NOT_FOUND; + goto Done; + } + Position.Position = &Position.ProtEntry->Protocols; + + Handle = CoreGetNextLocateByProtocol (&Position, Interface); + } else { + Handle = CoreGetNextLocateByRegisterNotify (&Position, Interface); + } + + if (Handle == NULL) { + Status = EFI_NOT_FOUND; + } else if (Registration != NULL) { + // + // If this is a search by register notify and a handle was + // returned, update the register notification position + // + ProtNotify = Registration; + ProtNotify->Position = ProtNotify->Position->ForwardLink; + } + +Done: + CoreReleaseProtocolLock (); + return Status; +} + + +/** + Function returns an array of handles that support the requested protocol + in a buffer allocated from pool. This is a version of CoreLocateHandle() + that allocates a buffer for the caller. + + @param SearchType Specifies which handle(s) are to be returned. + @param Protocol Provides the protocol to search by. This + parameter is only valid for SearchType + ByProtocol. + @param SearchKey Supplies the search key depending on the + SearchType. + @param NumberHandles The number of handles returned in Buffer. + @param Buffer A pointer to the buffer to return the requested + array of handles that support Protocol. + + @retval EFI_SUCCESS The result array of handles was returned. + @retval EFI_NOT_FOUND No handles match the search. + @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the + matching results. + @retval EFI_INVALID_PARAMETER One or more parameters are not valid. + +**/ +EFI_STATUS +EFIAPI +CoreLocateHandleBuffer ( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol OPTIONAL, + IN VOID *SearchKey OPTIONAL, + IN OUT UINTN *NumberHandles, + OUT EFI_HANDLE **Buffer + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + + if (NumberHandles == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + BufferSize = 0; + *NumberHandles = 0; + *Buffer = NULL; + Status = CoreLocateHandle ( + SearchType, + Protocol, + SearchKey, + &BufferSize, + *Buffer + ); + // + // LocateHandleBuffer() returns incorrect status code if SearchType is + // invalid. + // + // Add code to correctly handle expected errors from CoreLocateHandle(). + // + if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) { + if (Status != EFI_INVALID_PARAMETER) { + Status = EFI_NOT_FOUND; + } + return Status; + } + + *Buffer = AllocatePool (BufferSize); + if (*Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = CoreLocateHandle ( + SearchType, + Protocol, + SearchKey, + &BufferSize, + *Buffer + ); + + *NumberHandles = BufferSize / sizeof(EFI_HANDLE); + if (EFI_ERROR(Status)) { + *NumberHandles = 0; + } + + return Status; +} + + + diff --git a/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/Notify.c b/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/Notify.c new file mode 100644 index 0000000..afeac18 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/Notify.c @@ -0,0 +1,285 @@ +/** @file + Support functions for UEFI protocol notification infrastructure. + +Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+(C) Copyright 2015 Hewlett Packard Enterprise Development LP
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "DxeMain.h" +#include "Handle.h" +#include "Event.h" + +/** + Signal event for every protocol in protocol entry. + + @param ProtEntry Protocol entry + +**/ +VOID +CoreNotifyProtocolEntry ( + IN PROTOCOL_ENTRY *ProtEntry + ) +{ + PROTOCOL_NOTIFY *ProtNotify; + LIST_ENTRY *Link; + + ASSERT_LOCKED (&gProtocolDatabaseLock); + + for (Link=ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) { + ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE); + // CoreSignalEvent (ProtNotify->Event); + } +} + + + +/** + Removes Protocol from the protocol list (but not the handle list). + + @param Handle The handle to remove protocol on. + @param Protocol GUID of the protocol to be moved + @param Interface The interface of the protocol + + @return Protocol Entry + +**/ +PROTOCOL_INTERFACE * +CoreRemoveInterfaceFromProtocol ( + IN IHANDLE *Handle, + IN EFI_GUID *Protocol, + IN VOID *Interface + ) +{ + PROTOCOL_INTERFACE *Prot; + PROTOCOL_NOTIFY *ProtNotify; + PROTOCOL_ENTRY *ProtEntry; + LIST_ENTRY *Link; + + ASSERT_LOCKED (&gProtocolDatabaseLock); + + Prot = CoreFindProtocolInterface (Handle, Protocol, Interface); + if (Prot != NULL) { + + ProtEntry = Prot->Protocol; + + // + // If there's a protocol notify location pointing to this entry, back it up one + // + for(Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) { + ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE); + + if (ProtNotify->Position == &Prot->ByProtocol) { + ProtNotify->Position = Prot->ByProtocol.BackLink; + } + } + + // + // Remove the protocol interface entry + // + RemoveEntryList (&Prot->ByProtocol); + } + + return Prot; +} + + +/** + Add a new protocol notification record for the request protocol. + + @param Protocol The requested protocol to add the notify + registration + @param Event The event to signal + @param Registration Returns the registration record + + @retval EFI_INVALID_PARAMETER Invalid parameter + @retval EFI_SUCCESS Successfully returned the registration record + that has been added + +**/ +EFI_STATUS +EFIAPI +CoreRegisterProtocolNotify ( + IN EFI_GUID *Protocol, + IN EFI_EVENT Event, + OUT VOID **Registration + ) +{ + PROTOCOL_ENTRY *ProtEntry; + PROTOCOL_NOTIFY *ProtNotify; + EFI_STATUS Status; + + if ((Protocol == NULL) || (Event == NULL) || (Registration == NULL)) { + return EFI_INVALID_PARAMETER; + } + + CoreAcquireProtocolLock (); + + ProtNotify = NULL; + + // + // Get the protocol entry to add the notification too + // + + ProtEntry = CoreFindProtocolEntry (Protocol, TRUE); + if (ProtEntry != NULL) { + + // + // Allocate a new notification record + // + ProtNotify = AllocatePool (sizeof(PROTOCOL_NOTIFY)); + if (ProtNotify != NULL) { + ((IEVENT *)Event)->ExFlag |= EVT_EXFLAG_EVENT_PROTOCOL_NOTIFICATION; + ProtNotify->Signature = PROTOCOL_NOTIFY_SIGNATURE; + ProtNotify->Protocol = ProtEntry; + ProtNotify->Event = Event; + // + // start at the begining + // + ProtNotify->Position = &ProtEntry->Protocols; + + InsertTailList (&ProtEntry->Notify, &ProtNotify->Link); + } + } + + CoreReleaseProtocolLock (); + + // + // Done. If we have a protocol notify entry, then return it. + // Otherwise, we must have run out of resources trying to add one + // + + Status = EFI_OUT_OF_RESOURCES; + if (ProtNotify != NULL) { + *Registration = ProtNotify; + Status = EFI_SUCCESS; + } + + return Status; +} + + +/** + Reinstall a protocol interface on a device handle. The OldInterface for Protocol is replaced by the NewInterface. + + @param UserHandle Handle on which the interface is to be + reinstalled + @param Protocol The numeric ID of the interface + @param OldInterface A pointer to the old interface + @param NewInterface A pointer to the new interface + + @retval EFI_SUCCESS The protocol interface was installed + @retval EFI_NOT_FOUND The OldInterface on the handle was not found + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value + +**/ +EFI_STATUS +EFIAPI +CoreReinstallProtocolInterface ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + IN VOID *OldInterface, + IN VOID *NewInterface + ) +{ + EFI_STATUS Status; + IHANDLE *Handle; + PROTOCOL_INTERFACE *Prot; + PROTOCOL_ENTRY *ProtEntry; + + Status = CoreValidateHandle (UserHandle); + if (EFI_ERROR (Status)) { + return Status; + } + + if (Protocol == NULL) { + return EFI_INVALID_PARAMETER; + } + + Handle = (IHANDLE *) UserHandle; + + // + // Lock the protocol database + // + CoreAcquireProtocolLock (); + + // + // Check that Protocol exists on UserHandle, and Interface matches the interface in the database + // + Prot = CoreFindProtocolInterface (UserHandle, Protocol, OldInterface); + if (Prot == NULL) { + Status = EFI_NOT_FOUND; + goto Done; + } + + // + // Attempt to disconnect all drivers that are using the protocol interface that is about to be reinstalled + // + Status = CoreDisconnectControllersUsingProtocolInterface ( + UserHandle, + Prot + ); + if (EFI_ERROR (Status)) { + // + // One or more drivers refused to release, so return the error + // + goto Done; + } + + // + // Remove the protocol interface from the protocol + // + Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, OldInterface); + + if (Prot == NULL) { + Status = EFI_NOT_FOUND; + goto Done; + } + + ProtEntry = Prot->Protocol; + + // + // Update the interface on the protocol + // + Prot->Interface = NewInterface; + + // + // Add this protocol interface to the tail of the + // protocol entry + // + InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol); + + // + // Update the Key to show that the handle has been created/modified + // + gHandleDatabaseKey++; + Handle->Key = gHandleDatabaseKey; + + // + // Release the lock and connect all drivers to UserHandle + // + CoreReleaseProtocolLock (); + // + // Return code is ignored on purpose. + // + CoreConnectController ( + UserHandle, + NULL, + NULL, + TRUE + ); + CoreAcquireProtocolLock (); + + // + // Notify the notification list for this protocol + // + CoreNotifyProtocolEntry (ProtEntry); + + Status = EFI_SUCCESS; + +Done: + CoreReleaseProtocolLock (); + + return Status; +} diff --git a/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/Tpl.c b/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/Tpl.c new file mode 100644 index 0000000..ed342a0 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/Tpl.c @@ -0,0 +1,77 @@ +/** @file + Task priority (TPL) functions. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "DxeMain.h" + +#define VALID_TPL(a) ((a) <= TPL_HIGH_LEVEL) + +EFI_TPL gEfiCurrentTpl = TPL_APPLICATION; + + +/** + Raise the task priority level to the new level. + High level is implemented by disabling processor interrupts. + + @param NewTpl New task priority level + + @return The previous task priority level + +**/ +EFI_TPL +EFIAPI +CoreRaiseTpl ( + IN EFI_TPL NewTpl + ) +{ + EFI_TPL OldTpl; + + OldTpl = gEfiCurrentTpl; + if (OldTpl > NewTpl) { + DEBUG ((EFI_D_ERROR, "FATAL ERROR - RaiseTpl with OldTpl(0x%x) > NewTpl(0x%x)\n", OldTpl, NewTpl)); + ASSERT (FALSE); + } + ASSERT (VALID_TPL (NewTpl)); + + // + // Set the new value + // + gEfiCurrentTpl = NewTpl; + + return OldTpl; +} + + + + +/** + Lowers the task priority to the previous value. If the new + priority unmasks events at a higher priority, they are dispatched. + + @param NewTpl New, lower, task priority + +**/ +VOID +EFIAPI +CoreRestoreTpl ( + IN EFI_TPL NewTpl + ) +{ + EFI_TPL OldTpl; + + OldTpl = gEfiCurrentTpl; + if (NewTpl > OldTpl) { + DEBUG ((EFI_D_ERROR, "FATAL ERROR - RestoreTpl with NewTpl(0x%x) > OldTpl(0x%x)\n", NewTpl, OldTpl)); + ASSERT (FALSE); + } + ASSERT (VALID_TPL (NewTpl)); + + // + // Set the new value + // + gEfiCurrentTpl = NewTpl; +} diff --git a/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/UefiBootServicesTableLibHost.c b/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/UefiBootServicesTableLibHost.c new file mode 100644 index 0000000..dd2f4c9 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/UefiBootServicesTableLibHost.c @@ -0,0 +1,294 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +#include +#include +#include + +#include "DxeMain.h" + +extern EFI_BOOT_SERVICES mBootServices; +extern EFI_SYSTEM_TABLE mEfiSystemTableTemplate; + +EFI_SYSTEM_TABLE *gST = &mEfiSystemTableTemplate; +EFI_BOOT_SERVICES *gBS = &mBootServices; +EFI_HANDLE gImageHandle = NULL; + +EFI_HANDLE gDxeCoreImageHandle = NULL; +EFI_SECURITY2_ARCH_PROTOCOL *gSecurity2; + +EFI_STATUS +EFIAPI +CoreAllocatePages ( + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN NumberOfPages, + OUT EFI_PHYSICAL_ADDRESS *Memory + ) +{ + VOID *Buffer; + + Buffer = malloc (EFI_PAGES_TO_SIZE(NumberOfPages)); + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + *Memory = (UINTN)Buffer; + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +CoreFreePages ( + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN NumberOfPages + ) +{ + free ((VOID *)(UINTN)Memory); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +CoreAllocatePool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN Size, + OUT VOID **Buffer + ) +{ + *Buffer = malloc (Size); + if (*Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +CoreFreePool ( + IN VOID *Buffer + ) +{ + free (Buffer); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +CoreEfiNotAvailableYetArg0 ( + VOID + ) +{ + ASSERT(FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +CoreEfiNotAvailableYetArg1 ( + UINTN Arg1 + ) +{ + ASSERT(FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +CoreEfiNotAvailableYetArg2 ( + UINTN Arg1, + UINTN Arg2 + ) +{ + ASSERT(FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +CoreEfiNotAvailableYetArg3 ( + UINTN Arg1, + UINTN Arg2, + UINTN Arg3 + ) +{ + ASSERT(FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +CoreEfiNotAvailableYetArg4 ( + UINTN Arg1, + UINTN Arg2, + UINTN Arg3, + UINTN Arg4 + ) +{ + ASSERT(FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +CoreEfiNotAvailableYetArg5 ( + UINTN Arg1, + UINTN Arg2, + UINTN Arg3, + UINTN Arg4, + UINTN Arg5 + ) +{ + ASSERT(FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +CoreEfiNotAvailableYetArg6 ( + UINTN Arg1, + UINTN Arg2, + UINTN Arg3, + UINTN Arg4, + UINTN Arg5, + UINTN Arg6 + ) +{ + ASSERT(FALSE); + return EFI_UNSUPPORTED; +} + +EFI_BOOT_SERVICES mBootServices = { + { + EFI_BOOT_SERVICES_SIGNATURE, // Signature + EFI_BOOT_SERVICES_REVISION, // Revision + sizeof (EFI_BOOT_SERVICES), // HeaderSize + 0, // CRC32 + 0 // Reserved + }, + (EFI_RAISE_TPL) CoreRaiseTpl, // RaiseTPL + (EFI_RESTORE_TPL) CoreRestoreTpl, // RestoreTPL + (EFI_ALLOCATE_PAGES) CoreAllocatePages, // AllocatePages + (EFI_FREE_PAGES) CoreFreePages, // FreePages + (EFI_GET_MEMORY_MAP) CoreEfiNotAvailableYetArg5, // GetMemoryMap + (EFI_ALLOCATE_POOL) CoreAllocatePool, // AllocatePool + (EFI_FREE_POOL) CoreFreePool, // FreePool + (EFI_CREATE_EVENT) CoreEfiNotAvailableYetArg5, // CreateEvent + (EFI_SET_TIMER) CoreEfiNotAvailableYetArg3, // SetTimer + (EFI_WAIT_FOR_EVENT) CoreEfiNotAvailableYetArg3, // WaitForEvent + (EFI_SIGNAL_EVENT) CoreEfiNotAvailableYetArg1, // SignalEvent + (EFI_CLOSE_EVENT) CoreEfiNotAvailableYetArg1, // CloseEvent + (EFI_CHECK_EVENT) CoreEfiNotAvailableYetArg1, // CheckEvent + (EFI_INSTALL_PROTOCOL_INTERFACE) CoreInstallProtocolInterface, // InstallProtocolInterface + (EFI_REINSTALL_PROTOCOL_INTERFACE) CoreReinstallProtocolInterface, // ReinstallProtocolInterface + (EFI_UNINSTALL_PROTOCOL_INTERFACE) CoreUninstallProtocolInterface, // UninstallProtocolInterface + (EFI_HANDLE_PROTOCOL) CoreHandleProtocol, // HandleProtocol + (VOID *) NULL, // Reserved + (EFI_REGISTER_PROTOCOL_NOTIFY) CoreRegisterProtocolNotify, // RegisterProtocolNotify + (EFI_LOCATE_HANDLE) CoreLocateHandle, // LocateHandle + (EFI_LOCATE_DEVICE_PATH) CoreLocateDevicePath, // LocateDevicePath + (EFI_INSTALL_CONFIGURATION_TABLE) CoreEfiNotAvailableYetArg2, // InstallConfigurationTable + (EFI_IMAGE_LOAD) CoreEfiNotAvailableYetArg6, // LoadImage + (EFI_IMAGE_START) CoreEfiNotAvailableYetArg3, // StartImage + (EFI_EXIT) CoreEfiNotAvailableYetArg4, // Exit + (EFI_IMAGE_UNLOAD) CoreEfiNotAvailableYetArg1, // UnloadImage + (EFI_EXIT_BOOT_SERVICES) CoreEfiNotAvailableYetArg2, // ExitBootServices + (EFI_GET_NEXT_MONOTONIC_COUNT) CoreEfiNotAvailableYetArg1, // GetNextMonotonicCount + (EFI_STALL) CoreEfiNotAvailableYetArg1, // Stall + (EFI_SET_WATCHDOG_TIMER) CoreEfiNotAvailableYetArg4, // SetWatchdogTimer + (EFI_CONNECT_CONTROLLER) CoreEfiNotAvailableYetArg4, // ConnectController + (EFI_DISCONNECT_CONTROLLER) CoreEfiNotAvailableYetArg3, // DisconnectController + (EFI_OPEN_PROTOCOL) CoreOpenProtocol, // OpenProtocol + (EFI_CLOSE_PROTOCOL) CoreCloseProtocol, // CloseProtocol + (EFI_OPEN_PROTOCOL_INFORMATION) CoreOpenProtocolInformation, // OpenProtocolInformation + (EFI_PROTOCOLS_PER_HANDLE) CoreProtocolsPerHandle, // ProtocolsPerHandle + (EFI_LOCATE_HANDLE_BUFFER) CoreLocateHandleBuffer, // LocateHandleBuffer + (EFI_LOCATE_PROTOCOL) CoreLocateProtocol, // LocateProtocol + (EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES) CoreInstallMultipleProtocolInterfaces, // InstallMultipleProtocolInterfaces + (EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES) CoreUninstallMultipleProtocolInterfaces, // UninstallMultipleProtocolInterfaces + (EFI_CALCULATE_CRC32) CoreEfiNotAvailableYetArg3, // CalculateCrc32 + (EFI_COPY_MEM) CopyMem, // CopyMem + (EFI_SET_MEM) SetMem, // SetMem + (EFI_CREATE_EVENT_EX) CoreEfiNotAvailableYetArg6 // CreateEventEx +}; + +EFI_STATUS +EFIAPI +OutputString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *String + ) +{ + DEBUG ((DEBUG_INFO, "%s", String)); + return EFI_SUCCESS; +} + +EFI_SIMPLE_TEXT_OUTPUT_MODE mMode = { + 1, // MaxMode + 0, // Mode + 0, // Attribute + 80, // CursorColumn + 25, // CursorRow + FALSE, // CursorVisible +}; + +EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL mConOut = { + (EFI_TEXT_RESET) CoreEfiNotAvailableYetArg2, // Reset + OutputString, + (EFI_TEXT_TEST_STRING) CoreEfiNotAvailableYetArg2, // TestString + (EFI_TEXT_QUERY_MODE) CoreEfiNotAvailableYetArg4, // QueryMode + (EFI_TEXT_SET_MODE) CoreEfiNotAvailableYetArg2, // SetMode + (EFI_TEXT_SET_ATTRIBUTE) CoreEfiNotAvailableYetArg2, // SetAttribute + (EFI_TEXT_CLEAR_SCREEN) CoreEfiNotAvailableYetArg1, // ClearScreen + (EFI_TEXT_SET_CURSOR_POSITION) CoreEfiNotAvailableYetArg3, // SetCursorPosition + (EFI_TEXT_ENABLE_CURSOR) CoreEfiNotAvailableYetArg2, // EnableCursor + NULL, // Mode +}; + +EFI_SYSTEM_TABLE mEfiSystemTableTemplate = { + { + EFI_SYSTEM_TABLE_SIGNATURE, // Signature + EFI_SYSTEM_TABLE_REVISION, // Revision + sizeof (EFI_SYSTEM_TABLE), // HeaderSize + 0, // CRC32 + 0 // Reserved + }, + NULL, // FirmwareVendor + 0, // FirmwareRevision + NULL, // ConsoleInHandle + NULL, // ConIn + NULL, // ConsoleOutHandle + &mConOut, // ConOut + NULL, // StandardErrorHandle + NULL, // StdErr + NULL, // RuntimeServices + &mBootServices, // BootServices + 0, // NumberOfConfigurationTableEntries + NULL // ConfigurationTable +}; + +EFI_STATUS +EFIAPI +UefiBootServicesTableLibConstructor ( + VOID + ) +{ + EFI_STATUS Status; + + Status = gBS->InstallProtocolInterface ( + &gImageHandle, + &gEfiLoadedImageProtocolGuid, + EFI_NATIVE_INTERFACE, + NULL + ); + + return Status; +} diff --git a/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/UefiBootServicesTableLibHost.inf b/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/UefiBootServicesTableLibHost.inf new file mode 100644 index 0000000..144aa3d --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiBootServicesTableLibHost/UefiBootServicesTableLibHost.inf @@ -0,0 +1,43 @@ +## @file +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UefiBootServicesTableLibHost + FILE_GUID = D440EF07-2EFD-4054-BEAC-88ED18722C8F + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = UefiBootServicesTableLib + CONSTRUCTOR = UefiBootServicesTableLibConstructor + +[Sources] + UefiBootServicesTableLibHost.c + DriverSupport.c + Handle.c + Locate.c + Notify.c + Tpl.c + Library.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DevicePathLib + PerformanceLib + +[Protocols] + gEfiDevicePathProtocolGuid + gEfiPlatformDriverOverrideProtocolGuid + gEfiDriverBindingProtocolGuid + gEfiBusSpecificDriverOverrideProtocolGuid + gEfiDriverFamilyOverrideProtocolGuid + gEfiLoadedImageProtocolGuid diff --git a/HBFA/UefiHostTestPkg/Library/UefiDevicePathLibHost/DevicePathUtilities.c b/HBFA/UefiHostTestPkg/Library/UefiDevicePathLibHost/DevicePathUtilities.c new file mode 100644 index 0000000..903266f --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiDevicePathLibHost/DevicePathUtilities.c @@ -0,0 +1,889 @@ +/** @file + Device Path services. The thing to remember is device paths are built out of + nodes. The device path is terminated by an end node that is length + sizeof(EFI_DEVICE_PATH_PROTOCOL). That would be why there is sizeof(EFI_DEVICE_PATH_PROTOCOL) + all over this file. + + The only place where multi-instance device paths are supported is in + environment varibles. Multi-instance device paths should never be placed + on a Handle. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "UefiDevicePathLib.h" + +// +// Template for an end-of-device path node. +// +GLOBAL_REMOVE_IF_UNREFERENCED CONST EFI_DEVICE_PATH_PROTOCOL mUefiDevicePathLibEndDevicePath = { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } +}; + +/** + Determine whether a given device path is valid. + If DevicePath is NULL, then ASSERT(). + + @param DevicePath A pointer to a device path data structure. + @param MaxSize The maximum size of the device path data structure. + + @retval TRUE DevicePath is valid. + @retval FALSE The length of any node node in the DevicePath is less + than sizeof (EFI_DEVICE_PATH_PROTOCOL). + @retval FALSE If MaxSize is not zero, the size of the DevicePath + exceeds MaxSize. + @retval FALSE If PcdMaximumDevicePathNodeCount is not zero, the node + count of the DevicePath exceeds PcdMaximumDevicePathNodeCount. +**/ +BOOLEAN +EFIAPI +IsDevicePathValid ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN UINTN MaxSize + ) +{ + UINTN Count; + UINTN Size; + UINTN NodeLength; + + ASSERT (DevicePath != NULL); + + if (MaxSize == 0) { + MaxSize = MAX_UINTN; + } + + // + // Validate the input size big enough to touch the first node. + // + if (MaxSize < sizeof (EFI_DEVICE_PATH_PROTOCOL)) { + return FALSE; + } + + for (Count = 0, Size = 0; !IsDevicePathEnd (DevicePath); DevicePath = NextDevicePathNode (DevicePath)) { + NodeLength = DevicePathNodeLength (DevicePath); + if (NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) { + return FALSE; + } + + if (NodeLength > MAX_UINTN - Size) { + return FALSE; + } + Size += NodeLength; + + // + // Validate next node before touch it. + // + if (Size > MaxSize - END_DEVICE_PATH_LENGTH ) { + return FALSE; + } + + if (PcdGet32 (PcdMaximumDevicePathNodeCount) > 0) { + Count++; + if (Count >= PcdGet32 (PcdMaximumDevicePathNodeCount)) { + return FALSE; + } + } + } + + // + // Only return TRUE when the End Device Path node is valid. + // + return (BOOLEAN) (DevicePathNodeLength (DevicePath) == END_DEVICE_PATH_LENGTH); +} + + +/** + Returns the Type field of a device path node. + + Returns the Type field of the device path node specified by Node. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @return The Type field of the device path node specified by Node. + +**/ +UINT8 +EFIAPI +DevicePathType ( + IN CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return ((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Type; +} + +/** + Returns the SubType field of a device path node. + + Returns the SubType field of the device path node specified by Node. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @return The SubType field of the device path node specified by Node. + +**/ +UINT8 +EFIAPI +DevicePathSubType ( + IN CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return ((EFI_DEVICE_PATH_PROTOCOL *)(Node))->SubType; +} + +/** + Returns the 16-bit Length field of a device path node. + + Returns the 16-bit Length field of the device path node specified by Node. + Node is not required to be aligned on a 16-bit boundary, so it is recommended + that a function such as ReadUnaligned16() be used to extract the contents of + the Length field. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @return The 16-bit Length field of the device path node specified by Node. + +**/ +UINTN +EFIAPI +DevicePathNodeLength ( + IN CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return ReadUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Length[0]); +} + +/** + Returns a pointer to the next node in a device path. + + Returns a pointer to the device path node that follows the device path node + specified by Node. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @return a pointer to the device path node that follows the device path node + specified by Node. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +NextDevicePathNode ( + IN CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)(Node) + DevicePathNodeLength(Node)); +} + +/** + Determines if a device path node is an end node of a device path. + This includes nodes that are the end of a device path instance and nodes that + are the end of an entire device path. + + Determines if the device path node specified by Node is an end node of a device path. + This includes nodes that are the end of a device path instance and nodes that are the + end of an entire device path. If Node represents an end node of a device path, + then TRUE is returned. Otherwise, FALSE is returned. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @retval TRUE The device path node specified by Node is an end node of a + device path. + @retval FALSE The device path node specified by Node is not an end node of + a device path. + +**/ +BOOLEAN +EFIAPI +IsDevicePathEndType ( + IN CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return (BOOLEAN) (DevicePathType (Node) == END_DEVICE_PATH_TYPE); +} + +/** + Determines if a device path node is an end node of an entire device path. + + Determines if a device path node specified by Node is an end node of an entire + device path. If Node represents the end of an entire device path, then TRUE is + returned. Otherwise, FALSE is returned. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @retval TRUE The device path node specified by Node is the end of an entire + device path. + @retval FALSE The device path node specified by Node is not the end of an + entire device path. + +**/ +BOOLEAN +EFIAPI +IsDevicePathEnd ( + IN CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return (BOOLEAN) (IsDevicePathEndType (Node) && DevicePathSubType(Node) == END_ENTIRE_DEVICE_PATH_SUBTYPE); +} + +/** + Determines if a device path node is an end node of a device path instance. + + Determines if a device path node specified by Node is an end node of a device + path instance. If Node represents the end of a device path instance, then TRUE + is returned. Otherwise, FALSE is returned. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @retval TRUE The device path node specified by Node is the end of a device + path instance. + @retval FALSE The device path node specified by Node is not the end of a + device path instance. + +**/ +BOOLEAN +EFIAPI +IsDevicePathEndInstance ( + IN CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return (BOOLEAN) (IsDevicePathEndType (Node) && DevicePathSubType(Node) == END_INSTANCE_DEVICE_PATH_SUBTYPE); +} + +/** + Sets the length, in bytes, of a device path node. + + Sets the length of the device path node specified by Node to the value specified + by NodeLength. NodeLength is returned. Node is not required to be aligned on + a 16-bit boundary, so it is recommended that a function such as WriteUnaligned16() + be used to set the contents of the Length field. + + If Node is NULL, then ASSERT(). + If NodeLength >= SIZE_64KB, then ASSERT(). + If NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL), then ASSERT(). + + @param Node A pointer to a device path node data structure. + @param Length The length, in bytes, of the device path node. + + @return Length + +**/ +UINT16 +EFIAPI +SetDevicePathNodeLength ( + IN OUT VOID *Node, + IN UINTN Length + ) +{ + ASSERT (Node != NULL); + ASSERT ((Length >= sizeof (EFI_DEVICE_PATH_PROTOCOL)) && (Length < SIZE_64KB)); + return WriteUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Length[0], (UINT16)(Length)); +} + +/** + Fills in all the fields of a device path node that is the end of an entire device path. + + Fills in all the fields of a device path node specified by Node so Node represents + the end of an entire device path. The Type field of Node is set to + END_DEVICE_PATH_TYPE, the SubType field of Node is set to + END_ENTIRE_DEVICE_PATH_SUBTYPE, and the Length field of Node is set to + END_DEVICE_PATH_LENGTH. Node is not required to be aligned on a 16-bit boundary, + so it is recommended that a function such as WriteUnaligned16() be used to set + the contents of the Length field. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + +**/ +VOID +EFIAPI +SetDevicePathEndNode ( + OUT VOID *Node + ) +{ + ASSERT (Node != NULL); + CopyMem (Node, &mUefiDevicePathLibEndDevicePath, sizeof (mUefiDevicePathLibEndDevicePath)); +} + +/** + Returns the size of a device path in bytes. + + This function returns the size, in bytes, of the device path data structure + specified by DevicePath including the end of device path node. + If DevicePath is NULL or invalid, then 0 is returned. + + @param DevicePath A pointer to a device path data structure. + + @retval 0 If DevicePath is NULL or invalid. + @retval Others The size of a device path in bytes. + +**/ +UINTN +EFIAPI +UefiDevicePathLibGetDevicePathSize ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + CONST EFI_DEVICE_PATH_PROTOCOL *Start; + + if (DevicePath == NULL) { + return 0; + } + + if (!IsDevicePathValid (DevicePath, 0)) { + return 0; + } + + // + // Search for the end of the device path structure + // + Start = DevicePath; + while (!IsDevicePathEnd (DevicePath)) { + DevicePath = NextDevicePathNode (DevicePath); + } + + // + // Compute the size and add back in the size of the end device path structure + // + return ((UINTN) DevicePath - (UINTN) Start) + DevicePathNodeLength (DevicePath); +} + +/** + Creates a new copy of an existing device path. + + This function allocates space for a new copy of the device path specified by DevicePath. + If DevicePath is NULL, then NULL is returned. If the memory is successfully + allocated, then the contents of DevicePath are copied to the newly allocated + buffer, and a pointer to that buffer is returned. Otherwise, NULL is returned. + The memory for the new device path is allocated from EFI boot services memory. + It is the responsibility of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + + @retval NULL DevicePath is NULL or invalid. + @retval Others A pointer to the duplicated device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibDuplicateDevicePath ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + UINTN Size; + + // + // Compute the size + // + Size = GetDevicePathSize (DevicePath); + if (Size == 0) { + return NULL; + } + + // + // Allocate space for duplicate device path + // + + return AllocateCopyPool (Size, DevicePath); +} + +/** + Creates a new device path by appending a second device path to a first device path. + + This function creates a new device path by appending a copy of SecondDevicePath + to a copy of FirstDevicePath in a newly allocated buffer. Only the end-of-device-path + device node from SecondDevicePath is retained. The newly created device path is + returned. If FirstDevicePath is NULL, then it is ignored, and a duplicate of + SecondDevicePath is returned. If SecondDevicePath is NULL, then it is ignored, + and a duplicate of FirstDevicePath is returned. If both FirstDevicePath and + SecondDevicePath are NULL, then a copy of an end-of-device-path is returned. + + If there is not enough memory for the newly allocated buffer, then NULL is returned. + The memory for the new device path is allocated from EFI boot services memory. + It is the responsibility of the caller to free the memory allocated. + + @param FirstDevicePath A pointer to a device path data structure. + @param SecondDevicePath A pointer to a device path data structure. + + @retval NULL If there is not enough memory for the newly allocated buffer. + @retval NULL If FirstDevicePath or SecondDevicePath is invalid. + @retval Others A pointer to the new device path if success. + Or a copy an end-of-device-path if both FirstDevicePath and SecondDevicePath are NULL. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibAppendDevicePath ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath, OPTIONAL + IN CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath OPTIONAL + ) +{ + UINTN Size; + UINTN Size1; + UINTN Size2; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePath2; + + // + // If there's only 1 path, just duplicate it. + // + if (FirstDevicePath == NULL) { + return DuplicateDevicePath ((SecondDevicePath != NULL) ? SecondDevicePath : &mUefiDevicePathLibEndDevicePath); + } + + if (SecondDevicePath == NULL) { + return DuplicateDevicePath (FirstDevicePath); + } + + if (!IsDevicePathValid (FirstDevicePath, 0) || !IsDevicePathValid (SecondDevicePath, 0)) { + return NULL; + } + + // + // Allocate space for the combined device path. It only has one end node of + // length EFI_DEVICE_PATH_PROTOCOL. + // + Size1 = GetDevicePathSize (FirstDevicePath); + Size2 = GetDevicePathSize (SecondDevicePath); + Size = Size1 + Size2 - END_DEVICE_PATH_LENGTH; + + NewDevicePath = AllocatePool (Size); + + if (NewDevicePath != NULL) { + NewDevicePath = CopyMem (NewDevicePath, FirstDevicePath, Size1); + // + // Over write FirstDevicePath EndNode and do the copy + // + DevicePath2 = (EFI_DEVICE_PATH_PROTOCOL *) ((CHAR8 *) NewDevicePath + + (Size1 - END_DEVICE_PATH_LENGTH)); + CopyMem (DevicePath2, SecondDevicePath, Size2); + } + + return NewDevicePath; +} + +/** + Creates a new path by appending the device node to the device path. + + This function creates a new device path by appending a copy of the device node + specified by DevicePathNode to a copy of the device path specified by DevicePath + in an allocated buffer. The end-of-device-path device node is moved after the + end of the appended device node. + If DevicePathNode is NULL then a copy of DevicePath is returned. + If DevicePath is NULL then a copy of DevicePathNode, followed by an end-of-device + path device node is returned. + If both DevicePathNode and DevicePath are NULL then a copy of an end-of-device-path + device node is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + @param DevicePathNode A pointer to a single device path node. + + @retval NULL If there is not enough memory for the new device path. + @retval Others A pointer to the new device path if success. + A copy of DevicePathNode followed by an end-of-device-path node + if both FirstDevicePath and SecondDevicePath are NULL. + A copy of an end-of-device-path node if both FirstDevicePath + and SecondDevicePath are NULL. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibAppendDevicePathNode ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OPTIONAL + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode OPTIONAL + ) +{ + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + EFI_DEVICE_PATH_PROTOCOL *NextNode; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + UINTN NodeLength; + + if (DevicePathNode == NULL) { + return DuplicateDevicePath ((DevicePath != NULL) ? DevicePath : &mUefiDevicePathLibEndDevicePath); + } + // + // Build a Node that has a terminator on it + // + NodeLength = DevicePathNodeLength (DevicePathNode); + + TempDevicePath = AllocatePool (NodeLength + END_DEVICE_PATH_LENGTH); + if (TempDevicePath == NULL) { + return NULL; + } + TempDevicePath = CopyMem (TempDevicePath, DevicePathNode, NodeLength); + // + // Add and end device path node to convert Node to device path + // + NextNode = NextDevicePathNode (TempDevicePath); + SetDevicePathEndNode (NextNode); + // + // Append device paths + // + NewDevicePath = AppendDevicePath (DevicePath, TempDevicePath); + + FreePool (TempDevicePath); + + return NewDevicePath; +} + +/** + Creates a new device path by appending the specified device path instance to the specified device + path. + + This function creates a new device path by appending a copy of the device path + instance specified by DevicePathInstance to a copy of the device path specified + by DevicePath in a allocated buffer. + The end-of-device-path device node is moved after the end of the appended device + path instance and a new end-of-device-path-instance node is inserted between. + If DevicePath is NULL, then a copy if DevicePathInstance is returned. + If DevicePathInstance is NULL, then NULL is returned. + If DevicePath or DevicePathInstance is invalid, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + @param DevicePathInstance A pointer to a device path instance. + + @return A pointer to the new device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibAppendDevicePathInstance ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OPTIONAL + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance OPTIONAL + ) +{ + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + UINTN SrcSize; + UINTN InstanceSize; + + if (DevicePath == NULL) { + return DuplicateDevicePath (DevicePathInstance); + } + + if (DevicePathInstance == NULL) { + return NULL; + } + + if (!IsDevicePathValid (DevicePath, 0) || !IsDevicePathValid (DevicePathInstance, 0)) { + return NULL; + } + + SrcSize = GetDevicePathSize (DevicePath); + InstanceSize = GetDevicePathSize (DevicePathInstance); + + NewDevicePath = AllocatePool (SrcSize + InstanceSize); + if (NewDevicePath != NULL) { + + TempDevicePath = CopyMem (NewDevicePath, DevicePath, SrcSize);; + + while (!IsDevicePathEnd (TempDevicePath)) { + TempDevicePath = NextDevicePathNode (TempDevicePath); + } + + TempDevicePath->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE; + TempDevicePath = NextDevicePathNode (TempDevicePath); + CopyMem (TempDevicePath, DevicePathInstance, InstanceSize); + } + + return NewDevicePath; +} + +/** + Creates a copy of the current device path instance and returns a pointer to the next device path + instance. + + This function creates a copy of the current device path instance. It also updates + DevicePath to point to the next device path instance in the device path (or NULL + if no more) and updates Size to hold the size of the device path instance copy. + If DevicePath is NULL, then NULL is returned. + If DevicePath points to a invalid device path, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + If Size is NULL, then ASSERT(). + + @param DevicePath On input, this holds the pointer to the current + device path instance. On output, this holds + the pointer to the next device path instance + or NULL if there are no more device path + instances in the device path pointer to a + device path data structure. + @param Size On output, this holds the size of the device + path instance, in bytes or zero, if DevicePath + is NULL. + + @return A pointer to the current device path instance. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibGetNextDevicePathInstance ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, + OUT UINTN *Size + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevPath; + EFI_DEVICE_PATH_PROTOCOL *ReturnValue; + UINT8 Temp; + + ASSERT (Size != NULL); + + if (DevicePath == NULL || *DevicePath == NULL) { + *Size = 0; + return NULL; + } + + if (!IsDevicePathValid (*DevicePath, 0)) { + return NULL; + } + + // + // Find the end of the device path instance + // + DevPath = *DevicePath; + while (!IsDevicePathEndType (DevPath)) { + DevPath = NextDevicePathNode (DevPath); + } + + // + // Compute the size of the device path instance + // + *Size = ((UINTN) DevPath - (UINTN) (*DevicePath)) + sizeof (EFI_DEVICE_PATH_PROTOCOL); + + // + // Make a copy and return the device path instance + // + Temp = DevPath->SubType; + DevPath->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE; + ReturnValue = DuplicateDevicePath (*DevicePath); + DevPath->SubType = Temp; + + // + // If DevPath is the end of an entire device path, then another instance + // does not follow, so *DevicePath is set to NULL. + // + if (DevicePathSubType (DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE) { + *DevicePath = NULL; + } else { + *DevicePath = NextDevicePathNode (DevPath); + } + + return ReturnValue; +} + +/** + Creates a device node. + + This function creates a new device node in a newly allocated buffer of size + NodeLength and initializes the device path node header with NodeType and NodeSubType. + The new device path node is returned. + If NodeLength is smaller than a device path header, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param NodeType The device node type for the new device node. + @param NodeSubType The device node sub-type for the new device node. + @param NodeLength The length of the new device node. + + @return The new device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibCreateDeviceNode ( + IN UINT8 NodeType, + IN UINT8 NodeSubType, + IN UINT16 NodeLength + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + if (NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) { + // + // NodeLength is less than the size of the header. + // + return NULL; + } + + DevicePath = AllocateZeroPool (NodeLength); + if (DevicePath != NULL) { + DevicePath->Type = NodeType; + DevicePath->SubType = NodeSubType; + SetDevicePathNodeLength (DevicePath, NodeLength); + } + + return DevicePath; +} + +/** + Determines if a device path is single or multi-instance. + + This function returns TRUE if the device path specified by DevicePath is + multi-instance. + Otherwise, FALSE is returned. + If DevicePath is NULL or invalid, then FALSE is returned. + + @param DevicePath A pointer to a device path data structure. + + @retval TRUE DevicePath is multi-instance. + @retval FALSE DevicePath is not multi-instance, or DevicePath + is NULL or invalid. + +**/ +BOOLEAN +EFIAPI +UefiDevicePathLibIsDevicePathMultiInstance ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + CONST EFI_DEVICE_PATH_PROTOCOL *Node; + + if (DevicePath == NULL) { + return FALSE; + } + + if (!IsDevicePathValid (DevicePath, 0)) { + return FALSE; + } + + Node = DevicePath; + while (!IsDevicePathEnd (Node)) { + if (IsDevicePathEndInstance (Node)) { + return TRUE; + } + + Node = NextDevicePathNode (Node); + } + + return FALSE; +} + + +/** + Retrieves the device path protocol from a handle. + + This function returns the device path protocol from the handle specified by Handle. + If Handle is NULL or Handle does not contain a device path protocol, then NULL + is returned. + + @param Handle The handle from which to retrieve the device + path protocol. + + @return The device path protocol from the handle specified by Handle. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +DevicePathFromHandle ( + IN EFI_HANDLE Handle + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_STATUS Status; + + Status = gBS->HandleProtocol ( + Handle, + &gEfiDevicePathProtocolGuid, + (VOID *) &DevicePath + ); + if (EFI_ERROR (Status)) { + DevicePath = NULL; + } + return DevicePath; +} + +/** + Allocates a device path for a file and appends it to an existing device path. + + If Device is a valid device handle that contains a device path protocol, then a device path for + the file specified by FileName is allocated and appended to the device path associated with the + handle Device. The allocated device path is returned. If Device is NULL or Device is a handle + that does not support the device path protocol, then a device path containing a single device + path node for the file specified by FileName is allocated and returned. + The memory for the new device path is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + If FileName is NULL, then ASSERT(). + If FileName is not aligned on a 16-bit boundary, then ASSERT(). + + @param Device A pointer to a device handle. This parameter + is optional and may be NULL. + @param FileName A pointer to a Null-terminated Unicode string. + + @return The allocated device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +FileDevicePath ( + IN EFI_HANDLE Device, OPTIONAL + IN CONST CHAR16 *FileName + ) +{ + UINTN Size; + FILEPATH_DEVICE_PATH *FilePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *FileDevicePath; + + DevicePath = NULL; + + Size = StrSize (FileName); + FileDevicePath = AllocatePool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + END_DEVICE_PATH_LENGTH); + if (FileDevicePath != NULL) { + FilePath = (FILEPATH_DEVICE_PATH *) FileDevicePath; + FilePath->Header.Type = MEDIA_DEVICE_PATH; + FilePath->Header.SubType = MEDIA_FILEPATH_DP; + CopyMem (&FilePath->PathName, FileName, Size); + SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH); + SetDevicePathEndNode (NextDevicePathNode (&FilePath->Header)); + + if (Device != NULL) { + DevicePath = DevicePathFromHandle (Device); + } + + DevicePath = AppendDevicePath (DevicePath, FileDevicePath); + FreePool (FileDevicePath); + } + + return DevicePath; +} + diff --git a/HBFA/UefiHostTestPkg/Library/UefiDevicePathLibHost/UefiDevicePathLib.c b/HBFA/UefiHostTestPkg/Library/UefiDevicePathLibHost/UefiDevicePathLib.c new file mode 100644 index 0000000..6ec580d --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiDevicePathLibHost/UefiDevicePathLib.c @@ -0,0 +1,354 @@ +/** @file + Device Path services. The thing to remember is device paths are built out of + nodes. The device path is terminated by an end node that is length + sizeof(EFI_DEVICE_PATH_PROTOCOL). That would be why there is sizeof(EFI_DEVICE_PATH_PROTOCOL) + all over this file. + + The only place where multi-instance device paths are supported is in + environment varibles. Multi-instance device paths should never be placed + on a Handle. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include "UefiDevicePathLib.h" + +/** + Returns the size of a device path in bytes. + + This function returns the size, in bytes, of the device path data structure + specified by DevicePath including the end of device path node. + If DevicePath is NULL or invalid, then 0 is returned. + + @param DevicePath A pointer to a device path data structure. + + @retval 0 If DevicePath is NULL or invalid. + @retval Others The size of a device path in bytes. + +**/ +UINTN +EFIAPI +GetDevicePathSize ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + return UefiDevicePathLibGetDevicePathSize (DevicePath); +} + +/** + Creates a new copy of an existing device path. + + This function allocates space for a new copy of the device path specified by DevicePath. + If DevicePath is NULL, then NULL is returned. If the memory is successfully + allocated, then the contents of DevicePath are copied to the newly allocated + buffer, and a pointer to that buffer is returned. Otherwise, NULL is returned. + The memory for the new device path is allocated from EFI boot services memory. + It is the responsibility of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + + @retval NULL DevicePath is NULL or invalid. + @retval Others A pointer to the duplicated device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +DuplicateDevicePath ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + return UefiDevicePathLibDuplicateDevicePath (DevicePath); +} + +/** + Creates a new device path by appending a second device path to a first device path. + + This function creates a new device path by appending a copy of SecondDevicePath + to a copy of FirstDevicePath in a newly allocated buffer. Only the end-of-device-path + device node from SecondDevicePath is retained. The newly created device path is + returned. If FirstDevicePath is NULL, then it is ignored, and a duplicate of + SecondDevicePath is returned. If SecondDevicePath is NULL, then it is ignored, + and a duplicate of FirstDevicePath is returned. If both FirstDevicePath and + SecondDevicePath are NULL, then a copy of an end-of-device-path is returned. + + If there is not enough memory for the newly allocated buffer, then NULL is returned. + The memory for the new device path is allocated from EFI boot services memory. + It is the responsibility of the caller to free the memory allocated. + + @param FirstDevicePath A pointer to a device path data structure. + @param SecondDevicePath A pointer to a device path data structure. + + @retval NULL If there is not enough memory for the newly allocated buffer. + @retval NULL If FirstDevicePath or SecondDevicePath is invalid. + @retval Others A pointer to the new device path if success. + Or a copy an end-of-device-path if both FirstDevicePath and SecondDevicePath are NULL. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +AppendDevicePath ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath, OPTIONAL + IN CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath OPTIONAL + ) +{ + return UefiDevicePathLibAppendDevicePath (FirstDevicePath, SecondDevicePath); +} + +/** + Creates a new path by appending the device node to the device path. + + This function creates a new device path by appending a copy of the device node + specified by DevicePathNode to a copy of the device path specified by DevicePath + in an allocated buffer. The end-of-device-path device node is moved after the + end of the appended device node. + If DevicePathNode is NULL then a copy of DevicePath is returned. + If DevicePath is NULL then a copy of DevicePathNode, followed by an end-of-device + path device node is returned. + If both DevicePathNode and DevicePath are NULL then a copy of an end-of-device-path + device node is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + @param DevicePathNode A pointer to a single device path node. + + @retval NULL If there is not enough memory for the new device path. + @retval Others A pointer to the new device path if success. + A copy of DevicePathNode followed by an end-of-device-path node + if both FirstDevicePath and SecondDevicePath are NULL. + A copy of an end-of-device-path node if both FirstDevicePath + and SecondDevicePath are NULL. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +AppendDevicePathNode ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OPTIONAL + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode OPTIONAL + ) +{ + return UefiDevicePathLibAppendDevicePathNode (DevicePath, DevicePathNode); +} + +/** + Creates a new device path by appending the specified device path instance to the specified device + path. + + This function creates a new device path by appending a copy of the device path + instance specified by DevicePathInstance to a copy of the device path specified + by DevicePath in a allocated buffer. + The end-of-device-path device node is moved after the end of the appended device + path instance and a new end-of-device-path-instance node is inserted between. + If DevicePath is NULL, then a copy if DevicePathInstance is returned. + If DevicePathInstance is NULL, then NULL is returned. + If DevicePath or DevicePathInstance is invalid, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + @param DevicePathInstance A pointer to a device path instance. + + @return A pointer to the new device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +AppendDevicePathInstance ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OPTIONAL + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance OPTIONAL + ) +{ + return UefiDevicePathLibAppendDevicePathInstance (DevicePath, DevicePathInstance); +} + +/** + Creates a copy of the current device path instance and returns a pointer to the next device path + instance. + + This function creates a copy of the current device path instance. It also updates + DevicePath to point to the next device path instance in the device path (or NULL + if no more) and updates Size to hold the size of the device path instance copy. + If DevicePath is NULL, then NULL is returned. + If DevicePath points to a invalid device path, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + If Size is NULL, then ASSERT(). + + @param DevicePath On input, this holds the pointer to the current + device path instance. On output, this holds + the pointer to the next device path instance + or NULL if there are no more device path + instances in the device path pointer to a + device path data structure. + @param Size On output, this holds the size of the device + path instance, in bytes or zero, if DevicePath + is NULL. + + @return A pointer to the current device path instance. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +GetNextDevicePathInstance ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, + OUT UINTN *Size + ) +{ + return UefiDevicePathLibGetNextDevicePathInstance (DevicePath, Size); +} + +/** + Creates a device node. + + This function creates a new device node in a newly allocated buffer of size + NodeLength and initializes the device path node header with NodeType and NodeSubType. + The new device path node is returned. + If NodeLength is smaller than a device path header, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param NodeType The device node type for the new device node. + @param NodeSubType The device node sub-type for the new device node. + @param NodeLength The length of the new device node. + + @return The new device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +CreateDeviceNode ( + IN UINT8 NodeType, + IN UINT8 NodeSubType, + IN UINT16 NodeLength + ) +{ + return UefiDevicePathLibCreateDeviceNode (NodeType, NodeSubType, NodeLength); +} + +/** + Determines if a device path is single or multi-instance. + + This function returns TRUE if the device path specified by DevicePath is + multi-instance. + Otherwise, FALSE is returned. + If DevicePath is NULL or invalid, then FALSE is returned. + + @param DevicePath A pointer to a device path data structure. + + @retval TRUE DevicePath is multi-instance. + @retval FALSE DevicePath is not multi-instance, or DevicePath + is NULL or invalid. + +**/ +BOOLEAN +EFIAPI +IsDevicePathMultiInstance ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + return UefiDevicePathLibIsDevicePathMultiInstance (DevicePath); +} + +/** + Converts a device node to its string representation. + + @param DeviceNode A Pointer to the device node to be converted. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + + @return A pointer to the allocated text representation of the device node or NULL if DeviceNode + is NULL or there was insufficient memory. + +**/ +CHAR16 * +EFIAPI +ConvertDeviceNodeToText ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + return NULL; +} + +/** + Converts a device path to its text representation. + + @param DevicePath A Pointer to the device to be converted. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + + @return A pointer to the allocated text representation of the device path or + NULL if DeviceNode is NULL or there was insufficient memory. + +**/ +CHAR16 * +EFIAPI +ConvertDevicePathToText ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +{ + return NULL; +} + +/** + Convert text to the binary representation of a device node. + + @param TextDeviceNode TextDeviceNode points to the text representation of a device + node. Conversion starts with the first character and continues + until the first non-device node character. + + @return A pointer to the EFI device node or NULL if TextDeviceNode is NULL or there was + insufficient memory or text unsupported. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +ConvertTextToDeviceNode ( + IN CONST CHAR16 *TextDeviceNode + ) +{ + return NULL; +} + +/** + Convert text to the binary representation of a device path. + + + @param TextDevicePath TextDevicePath points to the text representation of a device + path. Conversion starts with the first character and continues + until the first non-device node character. + + @return A pointer to the allocated device path or NULL if TextDeviceNode is NULL or + there was insufficient memory. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +ConvertTextToDevicePath ( + IN CONST CHAR16 *TextDevicePath + ) +{ + return NULL; +} diff --git a/HBFA/UefiHostTestPkg/Library/UefiDevicePathLibHost/UefiDevicePathLib.h b/HBFA/UefiHostTestPkg/Library/UefiDevicePathLibHost/UefiDevicePathLib.h new file mode 100644 index 0000000..8e9b8f8 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiDevicePathLibHost/UefiDevicePathLib.h @@ -0,0 +1,451 @@ +/** @file + Definition for Device Path library. + +Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _UEFI_DEVICE_PATH_LIB_H_ +#define _UEFI_DEVICE_PATH_LIB_H_ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IS_COMMA(a) ((a) == L',') +#define IS_HYPHEN(a) ((a) == L'-') +#define IS_DOT(a) ((a) == L'.') +#define IS_LEFT_PARENTH(a) ((a) == L'(') +#define IS_RIGHT_PARENTH(a) ((a) == L')') +#define IS_SLASH(a) ((a) == L'/') +#define IS_NULL(a) ((a) == L'\0') + + +// +// Private Data structure +// +typedef struct { + CHAR16 *Str; + UINTN Count; + UINTN Capacity; +} POOL_PRINT; + +typedef +EFI_DEVICE_PATH_PROTOCOL * +(*DEVICE_PATH_FROM_TEXT) ( + IN CHAR16 *Str + ); + +typedef +VOID +(*DEVICE_PATH_TO_TEXT) ( + IN OUT POOL_PRINT *Str, + IN VOID *DevicePath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ); + +typedef struct { + UINT8 Type; + UINT8 SubType; + DEVICE_PATH_TO_TEXT Function; +} DEVICE_PATH_TO_TEXT_TABLE; + +typedef struct { + UINT8 Type; + CHAR16 *Text; +} DEVICE_PATH_TO_TEXT_GENERIC_TABLE; + +typedef struct { + CHAR16 *DevicePathNodeText; + DEVICE_PATH_FROM_TEXT Function; +} DEVICE_PATH_FROM_TEXT_TABLE; + +typedef struct { + BOOLEAN ClassExist; + UINT8 Class; + BOOLEAN SubClassExist; + UINT8 SubClass; +} USB_CLASS_TEXT; + +#define USB_CLASS_AUDIO 1 +#define USB_CLASS_CDCCONTROL 2 +#define USB_CLASS_HID 3 +#define USB_CLASS_IMAGE 6 +#define USB_CLASS_PRINTER 7 +#define USB_CLASS_MASS_STORAGE 8 +#define USB_CLASS_HUB 9 +#define USB_CLASS_CDCDATA 10 +#define USB_CLASS_SMART_CARD 11 +#define USB_CLASS_VIDEO 14 +#define USB_CLASS_DIAGNOSTIC 220 +#define USB_CLASS_WIRELESS 224 + +#define USB_CLASS_RESERVE 254 +#define USB_SUBCLASS_FW_UPDATE 1 +#define USB_SUBCLASS_IRDA_BRIDGE 2 +#define USB_SUBCLASS_TEST 3 + +#define RFC_1700_UDP_PROTOCOL 17 +#define RFC_1700_TCP_PROTOCOL 6 + +#pragma pack(1) + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; + UINT8 VendorDefinedData[1]; +} VENDOR_DEFINED_HARDWARE_DEVICE_PATH; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; + UINT8 VendorDefinedData[1]; +} VENDOR_DEFINED_MESSAGING_DEVICE_PATH; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; + UINT8 VendorDefinedData[1]; +} VENDOR_DEFINED_MEDIA_DEVICE_PATH; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 Hid; + UINT32 Uid; + UINT32 Cid; + CHAR8 HidUidCidStr[3]; +} ACPI_EXTENDED_HID_DEVICE_PATH_WITH_STR; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT16 NetworkProtocol; + UINT16 LoginOption; + UINT64 Lun; + UINT16 TargetPortalGroupTag; + CHAR8 TargetName[1]; +} ISCSI_DEVICE_PATH_WITH_NAME; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; + UINT8 VendorDefinedData[1]; +} VENDOR_DEVICE_PATH_WITH_DATA; + +#pragma pack() + +/** + Returns the size of a device path in bytes. + + This function returns the size, in bytes, of the device path data structure + specified by DevicePath including the end of device path node. + If DevicePath is NULL or invalid, then 0 is returned. + + @param DevicePath A pointer to a device path data structure. + + @retval 0 If DevicePath is NULL or invalid. + @retval Others The size of a device path in bytes. + +**/ +UINTN +EFIAPI +UefiDevicePathLibGetDevicePathSize ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +/** + Creates a new copy of an existing device path. + + This function allocates space for a new copy of the device path specified by DevicePath. + If DevicePath is NULL, then NULL is returned. If the memory is successfully + allocated, then the contents of DevicePath are copied to the newly allocated + buffer, and a pointer to that buffer is returned. Otherwise, NULL is returned. + The memory for the new device path is allocated from EFI boot services memory. + It is the responsibility of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + + @retval NULL DevicePath is NULL or invalid. + @retval Others A pointer to the duplicated device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibDuplicateDevicePath ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +/** + Creates a new device path by appending a second device path to a first device path. + + This function creates a new device path by appending a copy of SecondDevicePath + to a copy of FirstDevicePath in a newly allocated buffer. Only the end-of-device-path + device node from SecondDevicePath is retained. The newly created device path is + returned. If FirstDevicePath is NULL, then it is ignored, and a duplicate of + SecondDevicePath is returned. If SecondDevicePath is NULL, then it is ignored, + and a duplicate of FirstDevicePath is returned. If both FirstDevicePath and + SecondDevicePath are NULL, then a copy of an end-of-device-path is returned. + + If there is not enough memory for the newly allocated buffer, then NULL is returned. + The memory for the new device path is allocated from EFI boot services memory. + It is the responsibility of the caller to free the memory allocated. + + @param FirstDevicePath A pointer to a device path data structure. + @param SecondDevicePath A pointer to a device path data structure. + + @retval NULL If there is not enough memory for the newly allocated buffer. + @retval NULL If FirstDevicePath or SecondDevicePath is invalid. + @retval Others A pointer to the new device path if success. + Or a copy an end-of-device-path if both FirstDevicePath and SecondDevicePath are NULL. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibAppendDevicePath ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath, OPTIONAL + IN CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath OPTIONAL + ); + +/** + Creates a new path by appending the device node to the device path. + + This function creates a new device path by appending a copy of the device node + specified by DevicePathNode to a copy of the device path specified by DevicePath + in an allocated buffer. The end-of-device-path device node is moved after the + end of the appended device node. + If DevicePathNode is NULL then a copy of DevicePath is returned. + If DevicePath is NULL then a copy of DevicePathNode, followed by an end-of-device + path device node is returned. + If both DevicePathNode and DevicePath are NULL then a copy of an end-of-device-path + device node is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + @param DevicePathNode A pointer to a single device path node. + + @retval NULL If there is not enough memory for the new device path. + @retval Others A pointer to the new device path if success. + A copy of DevicePathNode followed by an end-of-device-path node + if both FirstDevicePath and SecondDevicePath are NULL. + A copy of an end-of-device-path node if both FirstDevicePath + and SecondDevicePath are NULL. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibAppendDevicePathNode ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OPTIONAL + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode OPTIONAL + ); + +/** + Creates a new device path by appending the specified device path instance to the specified device + path. + + This function creates a new device path by appending a copy of the device path + instance specified by DevicePathInstance to a copy of the device path specified + by DevicePath in a allocated buffer. + The end-of-device-path device node is moved after the end of the appended device + path instance and a new end-of-device-path-instance node is inserted between. + If DevicePath is NULL, then a copy if DevicePathInstance is returned. + If DevicePathInstance is NULL, then NULL is returned. + If DevicePath or DevicePathInstance is invalid, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + @param DevicePathInstance A pointer to a device path instance. + + @return A pointer to the new device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibAppendDevicePathInstance ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OPTIONAL + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance OPTIONAL + ); + +/** + Creates a copy of the current device path instance and returns a pointer to the next device path + instance. + + This function creates a copy of the current device path instance. It also updates + DevicePath to point to the next device path instance in the device path (or NULL + if no more) and updates Size to hold the size of the device path instance copy. + If DevicePath is NULL, then NULL is returned. + If DevicePath points to a invalid device path, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + If Size is NULL, then ASSERT(). + + @param DevicePath On input, this holds the pointer to the current + device path instance. On output, this holds + the pointer to the next device path instance + or NULL if there are no more device path + instances in the device path pointer to a + device path data structure. + @param Size On output, this holds the size of the device + path instance, in bytes or zero, if DevicePath + is NULL. + + @return A pointer to the current device path instance. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibGetNextDevicePathInstance ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, + OUT UINTN *Size + ); + +/** + Creates a device node. + + This function creates a new device node in a newly allocated buffer of size + NodeLength and initializes the device path node header with NodeType and NodeSubType. + The new device path node is returned. + If NodeLength is smaller than a device path header, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param NodeType The device node type for the new device node. + @param NodeSubType The device node sub-type for the new device node. + @param NodeLength The length of the new device node. + + @return The new device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibCreateDeviceNode ( + IN UINT8 NodeType, + IN UINT8 NodeSubType, + IN UINT16 NodeLength + ); + +/** + Determines if a device path is single or multi-instance. + + This function returns TRUE if the device path specified by DevicePath is + multi-instance. + Otherwise, FALSE is returned. + If DevicePath is NULL or invalid, then FALSE is returned. + + @param DevicePath A pointer to a device path data structure. + + @retval TRUE DevicePath is multi-instance. + @retval FALSE DevicePath is not multi-instance, or DevicePath + is NULL or invalid. + +**/ +BOOLEAN +EFIAPI +UefiDevicePathLibIsDevicePathMultiInstance ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + + +/** + Converts a device path to its text representation. + + @param DevicePath A Pointer to the device to be converted. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + + @return A pointer to the allocated text representation of the device path or + NULL if DeviceNode is NULL or there was insufficient memory. + +**/ +CHAR16 * +EFIAPI +UefiDevicePathLibConvertDevicePathToText ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ); + +/** + Converts a device node to its string representation. + + @param DeviceNode A Pointer to the device node to be converted. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + + @return A pointer to the allocated text representation of the device node or NULL if DeviceNode + is NULL or there was insufficient memory. + +**/ +CHAR16 * +EFIAPI +UefiDevicePathLibConvertDeviceNodeToText ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ); + +/** + Convert text to the binary representation of a device node. + + @param TextDeviceNode TextDeviceNode points to the text representation of a device + node. Conversion starts with the first character and continues + until the first non-device node character. + + @return A pointer to the EFI device node or NULL if TextDeviceNode is NULL or there was + insufficient memory or text unsupported. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibConvertTextToDeviceNode ( + IN CONST CHAR16 *TextDeviceNode + ); + +/** + Convert text to the binary representation of a device path. + + + @param TextDevicePath TextDevicePath points to the text representation of a device + path. Conversion starts with the first character and continues + until the first non-device node character. + + @return A pointer to the allocated device path or NULL if TextDeviceNode is NULL or + there was insufficient memory. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +UefiDevicePathLibConvertTextToDevicePath ( + IN CONST CHAR16 *TextDevicePath + ); + +#endif diff --git a/HBFA/UefiHostTestPkg/Library/UefiDevicePathLibHost/UefiDevicePathLibHost.inf b/HBFA/UefiHostTestPkg/Library/UefiDevicePathLibHost/UefiDevicePathLibHost.inf new file mode 100644 index 0000000..536e57b --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiDevicePathLibHost/UefiDevicePathLibHost.inf @@ -0,0 +1,43 @@ +## @file +# Instance of Device Path Library based on Memory Allocation Library. +# +# Device Path Library that layers on top of the Memory Allocation Library. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UefiDevicePathLibHost + FILE_GUID = 91c1677a-e57f-4191-8b8e-eb7711a716e0 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = DevicePathLib + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + DevicePathUtilities.c + UefiDevicePathLib.c + UefiDevicePathLib.h + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + BaseLib + MemoryAllocationLib + DebugLib + BaseMemoryLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdMaximumDevicePathNodeCount ## SOMETIMES_CONSUMES + diff --git a/HBFA/UefiHostTestPkg/Library/UefiDriverEntryPointHost/UefiDriverEntryPointHost.c b/HBFA/UefiHostTestPkg/Library/UefiDriverEntryPointHost/UefiDriverEntryPointHost.c new file mode 100644 index 0000000..ccd40f3 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiDriverEntryPointHost/UefiDriverEntryPointHost.c @@ -0,0 +1,57 @@ +/** @file + Entry point to a EFI/DXE driver. + +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + +#include + +#include + +#include +#include +#include +#include + + +/** + The entry point of PE/COFF Image for a DXE Driver, DXE Runtime Driver, DXE SMM + Driver, or UEFI Driver. + + This function is the entry point for a DXE Driver, DXE Runtime Driver, DXE SMM Driver, + or UEFI Driver. This function must call ProcessLibraryConstructorList() and + ProcessModuleEntryPointList(). If the return status from ProcessModuleEntryPointList() + is an error status, then ProcessLibraryDestructorList() must be called. The return + value from ProcessModuleEntryPointList() is returned. If _gDriverUnloadImageCount + is greater than zero, then an unload handler must be registered for this image + and the unload handler must invoke ProcessModuleUnloadList(). + If _gUefiDriverRevision is not zero and SystemTable->Hdr.Revision is less than + _gUefiDriverRevison, then return EFI_INCOMPATIBLE_VERSION. + + + @param ImageHandle The image handle of the DXE Driver, DXE Runtime Driver, + DXE SMM Driver, or UEFI Driver. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The DXE Driver, DXE Runtime Driver, DXE SMM + Driver, or UEFI Driver exited normally. + @retval EFI_INCOMPATIBLE_VERSION _gUefiDriverRevision is greater than + SystemTable->Hdr.Revision. + @retval Other Return value from ProcessModuleEntryPointList(). + +**/ +EFI_STATUS +EFIAPI +_ModuleEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + ASSERT(FALSE); + return EFI_UNSUPPORTED; +} + diff --git a/HBFA/UefiHostTestPkg/Library/UefiDriverEntryPointHost/UefiDriverEntryPointHost.inf b/HBFA/UefiHostTestPkg/Library/UefiDriverEntryPointHost/UefiDriverEntryPointHost.inf new file mode 100644 index 0000000..0fd220c --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiDriverEntryPointHost/UefiDriverEntryPointHost.inf @@ -0,0 +1,61 @@ +## @file +# Module entry point library for UEFI driver, DXE driver and SMM driver. +# +# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UefiDriverEntryPointHost + FILE_GUID = CB86FEFE-621F-4C9E-98F3-845F7E7BBC2D + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = UefiDriverEntryPoint|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER UEFI_DRIVER SMM_CORE DXE_SMM_DRIVER + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + UefiDriverEntryPointHost.c + + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + UefiBootServicesTableLib + DebugLib + BaseLib + + +[Protocols] + gEfiLoadedImageProtocolGuid ## SOMETIMES_CONSUMES + + +# +# For UEFI drivers, these architectural protocols defined in PI 1.0 spec need +# to be appended and merged to the final dependency section. +# +[Depex.common.UEFI_DRIVER] + gEfiBdsArchProtocolGuid AND + gEfiCpuArchProtocolGuid AND + gEfiMetronomeArchProtocolGuid AND + gEfiMonotonicCounterArchProtocolGuid AND + gEfiRealTimeClockArchProtocolGuid AND + gEfiResetArchProtocolGuid AND + gEfiRuntimeArchProtocolGuid AND + gEfiSecurityArchProtocolGuid AND + gEfiTimerArchProtocolGuid AND + gEfiVariableWriteArchProtocolGuid AND + gEfiVariableArchProtocolGuid AND + gEfiWatchdogTimerArchProtocolGuid + diff --git a/HBFA/UefiHostTestPkg/Library/UefiLibHost/UefiDriverModel.c b/HBFA/UefiHostTestPkg/Library/UefiLibHost/UefiDriverModel.c new file mode 100644 index 0000000..ec63325 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiLibHost/UefiDriverModel.c @@ -0,0 +1,101 @@ +/** @file + Library functions that abstract driver model protocols + installation and uninstallation. + + Copyright (c) 2019, NVIDIA Corporation. All rights reserved. + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include "UefiLibInternal.h" + + +/** + Installs Driver Binding Protocol with optional Component Name and Component Name 2 Protocols. + + Initializes a driver by installing the Driver Binding Protocol together with the + optional Component Name and optional Component Name 2 protocols onto the driver's + DriverBindingHandle. If DriverBindingHandle is NULL, then the protocols are installed + onto a newly created handle. DriverBindingHandle is typically the same as the driver's + ImageHandle, but it can be different if the driver produces multiple Driver Binding Protocols. + If DriverBinding is NULL, then ASSERT(). + If the installation fails, then ASSERT(). + + @param ImageHandle The image handle of the driver. + @param SystemTable The EFI System Table that was passed to the driver's entry point. + @param DriverBinding A Driver Binding Protocol instance that this driver is producing. + @param DriverBindingHandle The handle that DriverBinding is to be installed onto. If this + parameter is NULL, then a new handle is created. + @param ComponentName A Component Name Protocol instance that this driver is producing. + @param ComponentName2 A Component Name 2 Protocol instance that this driver is producing. + + @retval EFI_SUCCESS The protocol installation successfully completed. + @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols. + +**/ +EFI_STATUS +EFIAPI +EfiLibInstallDriverBindingComponentName2 ( + IN CONST EFI_HANDLE ImageHandle, + IN CONST EFI_SYSTEM_TABLE *SystemTable, + IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, + IN EFI_HANDLE DriverBindingHandle, + IN CONST EFI_COMPONENT_NAME_PROTOCOL *ComponentName, OPTIONAL + IN CONST EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2 OPTIONAL + ) +{ + EFI_STATUS Status; + + ASSERT (DriverBinding != NULL); + + // + // Update the ImageHandle and DriverBindingHandle fields of the Driver Binding Protocol + // + DriverBinding->ImageHandle = ImageHandle; + DriverBinding->DriverBindingHandle = DriverBindingHandle; + + if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentName2ProtocolGuid, ComponentName2, + NULL + ); + } + } else { + if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBinding->DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, DriverBinding, + &gEfiComponentNameProtocolGuid, ComponentName, + &gEfiComponentName2ProtocolGuid, ComponentName2, + NULL + ); + } + } + + // + // ASSERT if the call to InstallMultipleProtocolInterfaces() failed + // + ASSERT_EFI_ERROR (Status); + + return Status; +} + + diff --git a/HBFA/UefiHostTestPkg/Library/UefiLibHost/UefiLib.c b/HBFA/UefiHostTestPkg/Library/UefiLibHost/UefiLib.c new file mode 100644 index 0000000..f485540 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiLibHost/UefiLib.c @@ -0,0 +1,157 @@ +/** @file + The UEFI Library provides functions and macros that simplify the development of + UEFI Drivers and UEFI Applications. These functions and macros help manage EFI + events, build simple locks utilizing EFI Task Priority Levels (TPLs), install + EFI Driver Model related protocols, manage Unicode string tables for UEFI Drivers, + and print messages on the console output and standard error devices. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include "UefiLibInternal.h" + +/** + Compare whether two names of languages are identical. + + @param Language1 Name of language 1. + @param Language2 Name of language 2. + + @retval TRUE Language 1 and language 2 are the same. + @retval FALSE Language 1 and language 2 are not the same. + +**/ +BOOLEAN +CompareIso639LanguageCode ( + IN CONST CHAR8 *Language1, + IN CONST CHAR8 *Language2 + ) +{ + UINT32 Name1; + UINT32 Name2; + + Name1 = ReadUnaligned24 ((CONST UINT32 *) Language1); + Name2 = ReadUnaligned24 ((CONST UINT32 *) Language2); + + return (BOOLEAN) (Name1 == Name2); +} + +/** + This function looks up a Unicode string in UnicodeStringTable. + + If Language is a member of SupportedLanguages and a Unicode string is found in + UnicodeStringTable that matches the language code specified by Language, then + it is returned in UnicodeString. + + @param Language A pointer to an ASCII string containing the ISO 639-2 or the + RFC 4646 language code for the Unicode string to look up and + return. If Iso639Language is TRUE, then this ASCII string is + not assumed to be Null-terminated, and only the first three + characters are used. If Iso639Language is FALSE, then this ASCII + string must be Null-terminated. + @param SupportedLanguages A pointer to a Null-terminated ASCII string that contains a + set of ISO 639-2 or RFC 4646 language codes that the Unicode + string table supports. Language must be a member of this set. + If Iso639Language is TRUE, then this string contains one or more + ISO 639-2 language codes with no separator characters. If Iso639Language + is FALSE, then is string contains one or more RFC 4646 language + codes separated by ';'. + @param UnicodeStringTable A pointer to the table of Unicode strings. Type EFI_UNICODE_STRING_TABLE + is defined in "Related Definitions". + @param UnicodeString A pointer to the Null-terminated Unicode string from UnicodeStringTable + that matches the language specified by Language. + @param Iso639Language Specifies the supported language code format. If it is TRUE, then + Language and SupportedLanguages follow ISO 639-2 language code format. + Otherwise, they follow RFC 4646 language code format. + + + @retval EFI_SUCCESS The Unicode string that matches the language specified by Language + was found in the table of Unicode strings UnicodeStringTable, and + it was returned in UnicodeString. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER UnicodeString is NULL. + @retval EFI_UNSUPPORTED SupportedLanguages is NULL. + @retval EFI_UNSUPPORTED UnicodeStringTable is NULL. + @retval EFI_UNSUPPORTED The language specified by Language is not a member of SupportedLanguages. + @retval EFI_UNSUPPORTED The language specified by Language is not supported by UnicodeStringTable. + +**/ +EFI_STATUS +EFIAPI +LookupUnicodeString2 ( + IN CONST CHAR8 *Language, + IN CONST CHAR8 *SupportedLanguages, + IN CONST EFI_UNICODE_STRING_TABLE *UnicodeStringTable, + OUT CHAR16 **UnicodeString, + IN BOOLEAN Iso639Language + ) +{ + BOOLEAN Found; + UINTN Index; + CHAR8 *LanguageString; + + // + // Make sure the parameters are valid + // + if (Language == NULL || UnicodeString == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // If there are no supported languages, or the Unicode String Table is empty, then the + // Unicode String specified by Language is not supported by this Unicode String Table + // + if (SupportedLanguages == NULL || UnicodeStringTable == NULL) { + return EFI_UNSUPPORTED; + } + + // + // Make sure Language is in the set of Supported Languages + // + Found = FALSE; + while (*SupportedLanguages != 0) { + if (Iso639Language) { + if (CompareIso639LanguageCode (Language, SupportedLanguages)) { + Found = TRUE; + break; + } + SupportedLanguages += 3; + } else { + for (Index = 0; SupportedLanguages[Index] != 0 && SupportedLanguages[Index] != ';'; Index++); + if ((AsciiStrnCmp(SupportedLanguages, Language, Index) == 0) && (Language[Index] == 0)) { + Found = TRUE; + break; + } + SupportedLanguages += Index; + for (; *SupportedLanguages != 0 && *SupportedLanguages == ';'; SupportedLanguages++); + } + } + + // + // If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED + // + if (!Found) { + return EFI_UNSUPPORTED; + } + + // + // Search the Unicode String Table for the matching Language specifier + // + while (UnicodeStringTable->Language != NULL) { + LanguageString = UnicodeStringTable->Language; + while (0 != *LanguageString) { + for (Index = 0 ;LanguageString[Index] != 0 && LanguageString[Index] != ';'; Index++); + if (AsciiStrnCmp(LanguageString, Language, Index) == 0) { + *UnicodeString = UnicodeStringTable->UnicodeString; + return EFI_SUCCESS; + } + LanguageString += Index; + for (Index = 0 ;LanguageString[Index] != 0 && LanguageString[Index] == ';'; Index++); + } + UnicodeStringTable++; + } + + return EFI_UNSUPPORTED; +} diff --git a/HBFA/UefiHostTestPkg/Library/UefiLibHost/UefiLibHost.inf b/HBFA/UefiHostTestPkg/Library/UefiLibHost/UefiLibHost.inf new file mode 100644 index 0000000..ac420a7 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiLibHost/UefiLibHost.inf @@ -0,0 +1,47 @@ +## @file +# Instance of UEFI Library. +# +# The UEFI Library provides functions and macros that simplify the development of +# UEFI Drivers and UEFI Applications. These functions and macros help manage EFI +# events, build simple locks utilizing EFI Task Priority Levels (TPLs), install +# EFI Driver Model related protocols, manage Unicode string tables for UEFI Drivers, +# and print messages on the console output and standard error devices. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UefiLibHost + FILE_GUID = 3A6DF65D-806E-49FF-9CE5-074F49028378 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = UefiLib + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + UefiDriverModel.c + UefiLib.c + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + UefiBootServicesTableLib + +[Protocols] + gEfiComponentNameProtocolGuid | NOT gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable ## SOMETIMES_PRODUCES # User chooses to produce it + gEfiComponentName2ProtocolGuid | NOT gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable ## SOMETIMES_PRODUCES # User chooses to produce it + +[FeaturePcd] + gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable ## CONSUMES diff --git a/HBFA/UefiHostTestPkg/Library/UefiLibHost/UefiLibInternal.h b/HBFA/UefiHostTestPkg/Library/UefiLibHost/UefiLibInternal.h new file mode 100644 index 0000000..60b5297 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiLibHost/UefiLibInternal.h @@ -0,0 +1,39 @@ +/** @file + Internal include file for UefiLib. + + Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef __UEFI_LIB_INTERNAL_H_ +#define __UEFI_LIB_INTERNAL_H_ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/AuthVarCertDB.c b/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/AuthVarCertDB.c new file mode 100644 index 0000000..5c2ea7e --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/AuthVarCertDB.c @@ -0,0 +1,385 @@ +/** + Manage trusted certificate database. + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "OsVariable.h" +#include "AuthVarCertDB.h" + +extern LIST_ENTRY mVarListEntry; +CONST UINT32 gEfiCertDBAttr = (UINT32)(EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_RUNTIME_ACCESS | + EFI_VARIABLE_BOOTSERVICE_ACCESS); + +/* + Function to get "certdb" variable according to Attributes parameter. + + @param[in] Attributes Attributes of authenticated variable. + @param[out] CertDBPtr Point to "certdb" variable buffer. + + @retval EFI_SUCCESS Find matching certs and output parameters. + @retval EFI_INVALID_PARAMETER CertDBPtr is NULL or Attributes is invalid. + @retval EFI_SECURITY_VIOLATION CertDB structure has been corrupted. + @retval EFI_NOT_FOUND Fail to find matching certs. +*/ +EFI_STATUS +GetCertDB ( + IN UINT32 Attributes, + OUT VOID **CertDBPtr + ) +{ + CHAR16 *CertDBName; + VARIABLE_INFO_PRIVATE *VariableInfo; + + if (CertDBPtr == NULL) { + return EFI_INVALID_PARAMETER; + } + + if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) { + CertDBName = EFI_CERT_DB; + } else { + return EFI_INVALID_PARAMETER; + } + + VariableInfo = FindVariableInfoPtr (CertDBName, &gEfiCertDbGuid); + if (VariableInfo == NULL || VariableInfo->Size == 0) { + return EFI_NOT_FOUND; + } + + if (*(UINT32 *)(VariableInfo->Buffer) != VariableInfo->Size) { + return EFI_SECURITY_VIOLATION; + } + + *CertDBPtr = VariableInfo; + return EFI_SUCCESS; +} + +/** + Find matching signer's certificates for common authenticated variable + by corresponding VariableName and VendorGuid from "certdb". + + @param[in] VariableName Name of authenticated Variable. + @param[in] VendorGuid Vendor GUID of authenticated Variable. + @param[in] Data Pointer to variable "certdb". + @param[in] DataSize Size of variable "certdb". + @param[out] CertNodeOffset Offset of matching AUTH_CERT_DB_DATA, from starting of Data. + @param[out] CertNodeSize Length of AUTH_CERT_DB_DATA in bytes. + @param[out] CertDataPtr Pointer to the matching CertData. + @param[out] CertDataSize Lenght of CertData in bytes. + + @retval EFI_INVALID_PARAMETER Any input parameter is invalid. + @retval EFI_NOT_FOUND Fail to find matching certs. + @retval EFI_SUCCESS Find matching certs and output parameters. +**/ +EFI_STATUS +FindCertsFromDb ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + OUT UINT32 *CertNodeOffset OPTIONAL, + OUT UINT32 *CertNodeSize OPTIONAL, + OUT UINT8 **CertDataPtr OPTIONAL, + OUT UINT32 *CertDataSize OPTIONAL + ) +{ + EFI_STATUS Status; + VARIABLE_INFO_PRIVATE *VariableInfo; + AUTH_CERT_DB_DATA *Ptr; + UINT32 CertDBListSize; + UINT32 Offset; + UINT32 NodeSize; + UINT32 NameSize; + UINT32 DataSize; + + Status = EFI_SUCCESS; + + if ((VariableName == NULL) || (VendorGuid == NULL)) { + return EFI_INVALID_PARAMETER; + } + + Status = GetCertDB (Attributes, (VOID **)&VariableInfo); + if (EFI_ERROR (Status)) { + return Status; + } + + if (VariableInfo->Buffer == NULL || VariableInfo->Size == 0) { + return EFI_NOT_FOUND; + } + + if (VariableInfo->Size != *((UINT32 *)VariableInfo->Buffer)) { + return EFI_NOT_FOUND; + } + + CertDBListSize = (UINT32)VariableInfo->Size; + Offset = sizeof (UINT32); + + // + // Traverse CertDB and try to matching certs. + // + while (Offset < CertDBListSize) { + Ptr = (AUTH_CERT_DB_DATA *) ((UINT8 *)VariableInfo->Buffer + Offset); + + NodeSize = ReadUnaligned32 (&Ptr->CertNodeSize); + NameSize = ReadUnaligned32 (&Ptr->NameSize); + DataSize = ReadUnaligned32 (&Ptr->CertDataSize); + + if (NodeSize != sizeof (EFI_GUID) + sizeof (UINT32) * 3 + DataSize + NameSize * sizeof (CHAR16)) { + return EFI_NOT_FOUND; + } + + Offset = Offset + sizeof (EFI_GUID) + sizeof (UINT32) * 3; + if ((CompareGuid (&Ptr->VendorGuid, VendorGuid) == 0) && + (NameSize == StrLen (VariableName)) && + (CompareMem (VariableName, VariableInfo->Buffer + Offset, NameSize * sizeof (CHAR16)) == 0) + ) { + if (CertNodeOffset != NULL) { + *CertNodeOffset = (UINT32) ((UINT8 *)Ptr - VariableInfo->Buffer); + } + if (CertNodeSize != NULL) { + *CertNodeSize = NodeSize; + } + if (CertDataPtr != NULL) { + *CertDataPtr = (UINT8 *)Ptr + sizeof (EFI_GUID) + sizeof (UINT32) * 3 + NameSize * sizeof (CHAR16); + } + if (CertDataSize != NULL) { + *CertDataSize = DataSize; + } + return EFI_SUCCESS; + } + Offset = Offset + NameSize * sizeof (CHAR16) + DataSize; + } + + return EFI_NOT_FOUND; +} + +/** + Delete matching signer's certificates when deleting common authenticated + variable by corresponding VariableName and VendorGuid from "certdb". + + @param[in] VariableName Name of authenticated Variable. + @param[in] VendorGuid Vendor GUID of authenticated Variable. + @param[in] Attributes Attributes of authenticated variable. + + @retval EFI_INVALID_PARAMETER Any input parameter is invalid. + @retval EFI_NOT_FOUND Fail to find "certdb" or matching certs. + @retval EFI_OUT_OF_RESOURCES The operation is failed due to lack of resources. + @retval EFI_SUCCESS The operation is completed successfully. +**/ +EFI_STATUS +DeleteCertsFromDb ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes + ) +{ + EFI_STATUS Status; + VARIABLE_INFO_PRIVATE *VariableInfo; + UINT32 CertNodeOffset; + UINT32 CertNodeSize; + UINT8 *NewBuffer; + UINTN NewBufferSize; + + Status = EFI_SUCCESS; + VariableInfo = NULL; + NewBuffer = NULL; + CertNodeOffset = 0; + CertNodeSize = 0; + + if (VariableName == NULL || VendorGuid == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = GetCertDB (Attributes, (VOID **)&VariableInfo); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = FindCertsFromDb ( + VariableName, + VendorGuid, + Attributes, + &CertNodeOffset, + &CertNodeSize, + NULL, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + NewBufferSize = VariableInfo->Size - CertNodeSize; + + // + // If the NewBufferSize == 4, it means no AUTH_CERT_DB_DATA in "certDB". + // + if (NewBufferSize == 4) { + return DeleteVariableList (&mVarListEntry, VariableInfo->Name, &gEfiCertDbGuid); + } + + NewBuffer = (UINT8 *)malloc (NewBufferSize); + if (NewBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Copy first-part from old buffer to new buffer. + // + CopyMem (NewBuffer, VariableInfo->Buffer, CertNodeOffset); + // + // Copy second-part to new buffer. + // + CopyMem ( + NewBuffer + CertNodeOffset, + VariableInfo->Buffer + CertNodeOffset + CertNodeSize, + VariableInfo->Size - CertNodeOffset - CertNodeSize + ); + + Status = CreateVariableList ( + &mVarListEntry, + VariableInfo->Name, + &gEfiCertDbGuid, + gEfiCertDBAttr, + NULL, + NewBufferSize, + NewBuffer, + FALSE + ); + + FREE_NON_NULL_PTR (NewBuffer); + return Status; +} + +/** + Insert signer's certificates for common authenticated variable + with VariableName and VendorGuid in AUTH_CERT_DB_DATA to "certdb". + + @param[in] VariableName Name of authenticated Variable. + @param[in] VendorGuid Vendor GUID of authenticated Variable. + @param[in] Attributes Attributes of authenticated variable. + @param[in] SignerCert Signer certificate data. + @param[in] SignerCertSize Length of signer certificate. + @param[in] TopLevelCert Top-level certificate data. + @param[in] TopLevelCertSize Length of top-level certificate. + + + @retval EFI_INVALID_PARAMETER Any input parameter is invalid. + @retval EFI_ACCESS_DENIED An AUTH_CERT_DB_DATA entry with same VariableName + and VendorGuid already exists. + @retval EFI_OUT_OF_RESOURCES The operation is failed due to lack of resources. + @retval EFI_SUCCESS Insert an AUTH_CERT_DB_DATA entry to "certdb" or "certdbv" +**/ +EFI_STATUS +InsertCertsToDb ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINT8 *SignerCert, + IN UINTN SignerCertSize, + IN UINT8 *TopLevelCert, + IN UINTN TopLevelCertSize + ) +{ + EFI_STATUS Status; + UINT8 Sha256Digest[SHA256_DIGEST_SIZE]; + UINT8 *NewBuffer; + UINTN NewBufferSize; + UINT32 NameSize; + UINT32 NodeSize; + UINT32 DataSize; + UINT32 Offset; + CHAR16 *CertDBName; + + Status = EFI_SUCCESS; + NewBuffer = NULL; + + if (VariableName == NULL || VendorGuid == NULL || SignerCert == NULL || TopLevelCert == NULL) { + return EFI_INVALID_PARAMETER; + } + + if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) { + CertDBName = EFI_CERT_DB; + } else { + return EFI_INVALID_PARAMETER; + } + + Status = FindCertsFromDb (VariableName, VendorGuid, Attributes, NULL, NULL, NULL, NULL); + if (Status == EFI_SUCCESS) { + return EFI_SECURITY_VIOLATION; + } else if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) { + return Status; + } + +#if 0 + Status = CalculatePrivAuthVarSignChainSHA256Digest ( + SignerCert, + SignerCertSize, + TopLevelCert, + TopLevelCertSize, + Sha256Digest + ); + if (EFI_ERROR (Status)) { + return Status; + } +#endif + + /// + /// AUTH_CERT_DB_DATA format: + /// + /// EFI_GUID VendorGuid; + /// UINT32 CertNodeSize; + /// UINT32 NameSize; + /// UINT32 CertDataSize; + /// CHAR16 VariableName[NameSize]; + /// UINT8 CertData[CertDataSize]; + /// + + NameSize = (UINT32)(StrLen (VariableName)); + DataSize = SHA256_DIGEST_SIZE; + NodeSize = sizeof (AUTH_CERT_DB_DATA) + NameSize * sizeof (CHAR16) + DataSize; + + NewBufferSize = sizeof (UINT32) + NodeSize; + + NewBuffer = (UINT8 *)malloc (NewBufferSize); + if (NewBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Offset = 0; + CopyMem (NewBuffer + Offset, &NewBufferSize, sizeof (UINT32)); + Offset = Offset + sizeof (UINT32); + + CopyMem (NewBuffer + Offset, VendorGuid, sizeof (EFI_GUID)); + Offset = Offset + sizeof (EFI_GUID); + + CopyMem (NewBuffer + Offset, &NodeSize, sizeof (UINT32)); + Offset = Offset + sizeof (UINT32); + + CopyMem (NewBuffer + Offset, &NameSize, sizeof (UINT32)); + Offset = Offset + sizeof (UINT32); + + CopyMem (NewBuffer + Offset, &DataSize, sizeof (UINT32)); + Offset = Offset + sizeof (UINT32); + + CopyMem (NewBuffer + Offset, VariableName, NameSize * sizeof (CHAR16)); + Offset = Offset + NameSize * sizeof (CHAR16); + + CopyMem (NewBuffer + Offset, Sha256Digest, DataSize); + + Status = CreateVariableList ( + &mVarListEntry, + CertDBName, + &gEfiCertDbGuid, + gEfiCertDBAttr, + NULL, + NewBufferSize, + NewBuffer, + FALSE + ); + + FREE_NON_NULL_PTR (NewBuffer); + return Status; +} diff --git a/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/AuthVarCertDB.h b/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/AuthVarCertDB.h new file mode 100644 index 0000000..bab74f2 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/AuthVarCertDB.h @@ -0,0 +1,125 @@ +/** + Header file for trusted certificate database Management. + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _AUTH_CERTDB_H +#define _AUTH_CERTDB_H + +#include "VariableCommon.h" + +/// +/// "certdb" variable stores the signer's certificates for non PK/KEK/DB/DBX +/// variables with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS|EFI_VARIABLE_NON_VOLATILE set. +/// +/// GUID: gEfiCertDbGuid +/// +/// We need maintain atomicity. +/// +/// Format: +/// +----------------------------+ +/// | UINT32 | <-- CertDbListSize, including this UINT32 +/// +----------------------------+ +/// | AUTH_CERT_DB_DATA | <-- First CERT +/// +----------------------------+ +/// | ........ | +/// +----------------------------+ +/// | AUTH_CERT_DB_DATA | <-- Last CERT +/// +----------------------------+ +/// + +#define EFI_CERT_DB L"certdb" + +#pragma pack(1) +typedef struct { + EFI_GUID VendorGuid; + UINT32 CertNodeSize; + UINT32 NameSize; + UINT32 CertDataSize; + /// CHAR16 VariableName[NameSize]; + /// UINT8 CertData[CertDataSize]; +} AUTH_CERT_DB_DATA; +#pragma pack() + +/** + Find matching signer's certificates for common authenticated variable + by corresponding VariableName and VendorGuid from "certdb". + + @param[in] VariableName Name of authenticated Variable. + @param[in] VendorGuid Vendor GUID of authenticated Variable. + @param[in] Data Pointer to variable "certdb". + @param[in] DataSize Size of variable "certdb". + @param[out] CertNodeOffset Offset of matching AUTH_CERT_DB_DATA, from starting of Data. + @param[out] CertNodeSize Length of AUTH_CERT_DB_DATA in bytes. + @param[out] CertDataPtr Pointer to the matching CertData. + @param[out] CertDataSize Lenght of CertData in bytes. + + @retval EFI_INVALID_PARAMETER Any input parameter is invalid. + @retval EFI_NOT_FOUND Fail to find matching certs. + @retval EFI_SUCCESS Find matching certs and output parameters. +**/ +EFI_STATUS +FindCertsFromDb ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + OUT UINT32 *CertNodeOffset OPTIONAL, + OUT UINT32 *CertNodeSize OPTIONAL, + OUT UINT8 **CertDataPtr OPTIONAL, + OUT UINT32 *CertDataSize OPTIONAL + ); + +/** + Delete matching signer's certificates when deleting common authenticated + variable by corresponding VariableName and VendorGuid from "certdb". + + @param[in] VariableName Name of authenticated Variable. + @param[in] VendorGuid Vendor GUID of authenticated Variable. + @param[in] Attributes Attributes of authenticated variable. + + @retval EFI_INVALID_PARAMETER Any input parameter is invalid. + @retval EFI_NOT_FOUND Fail to find "certdb" or matching certs. + @retval EFI_OUT_OF_RESOURCES The operation is failed due to lack of resources. + @retval EFI_SUCCESS The operation is completed successfully. +**/ +EFI_STATUS +DeleteCertsFromDb ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes + ); + +/** + Insert signer's certificates for common authenticated variable + with VariableName and VendorGuid in AUTH_CERT_DB_DATA to "certdb". + + @param[in] VariableName Name of authenticated Variable. + @param[in] VendorGuid Vendor GUID of authenticated Variable. + @param[in] Attributes Attributes of authenticated variable. + @param[in] SignerCert Signer certificate data. + @param[in] SignerCertSize Length of signer certificate. + @param[in] TopLevelCert Top-level certificate data. + @param[in] TopLevelCertSize Length of top-level certificate. + + + @retval EFI_INVALID_PARAMETER Any input parameter is invalid. + @retval EFI_ACCESS_DENIED An AUTH_CERT_DB_DATA entry with same VariableName + and VendorGuid already exists. + @retval EFI_OUT_OF_RESOURCES The operation is failed due to lack of resources. + @retval EFI_SUCCESS Insert an AUTH_CERT_DB_DATA entry to "certdb" or "certdbv" +**/ +EFI_STATUS +InsertCertsToDb ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINT8 *SignerCert, + IN UINTN SignerCertSize, + IN UINT8 *TopLevelCert, + IN UINTN TopLevelCertSize + ); + +#endif diff --git a/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/AuthVariable.c b/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/AuthVariable.c new file mode 100644 index 0000000..2b42da7 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/AuthVariable.c @@ -0,0 +1,479 @@ +/** + Manage & verify Timebased Authenticated varaibles. + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "AuthVariable.h" +#include + +extern LIST_ENTRY mVarListEntry; + +/* + Function will split the "Buffer" parameter and getting the Auth2 + descriptor, and doing verification. + + @param[in] Attributes Attribute value of the variable. + @param[in] Buffer Data pointer. + @param[in] BufferSize The size of Data in bytes. + @param[in] OrgTimeStamp Pointer to original time stamp, + original variable is not found if NULL. + + @retval EFI_SECURITY_VIOLATION Verification fail. + @retval EFI_SUCCESS Operation success. +*/ +EFI_STATUS +VerifyAuth2Descriptor ( + IN UINT32 Attributes, + IN VOID *Buffer, + IN UINTN BufferSize, + IN EFI_TIME *OrgTimeStamp, + OUT UINT8 **CertDataPtr, + OUT UINT32 *CertDataSize + ) +{ + EFI_VARIABLE_AUTHENTICATION_2 *Auth2Ptr; + EFI_TIME *Auth2TimeStamp; + + if (Buffer == NULL || CertDataPtr == NULL || CertDataSize == NULL) { + return EFI_INVALID_PARAMETER; + } + + Auth2Ptr = (EFI_VARIABLE_AUTHENTICATION_2 *)Buffer; + + Auth2TimeStamp = &Auth2Ptr->TimeStamp; + if ( (Auth2TimeStamp->Pad1 != 0) || + (Auth2TimeStamp->Pad2 != 0) || + (Auth2TimeStamp->Nanosecond != 0) || + (Auth2TimeStamp->TimeZone != 0) || + (Auth2TimeStamp->Daylight !=0) + ) { + return EFI_SECURITY_VIOLATION; + } + + if ((OrgTimeStamp != NULL) && ((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0)) { + // + // TimeStamp check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION. + // + if (CompareTimeStamp (Auth2TimeStamp, OrgTimeStamp)) { + return EFI_SECURITY_VIOLATION; + } + } + + if ( (Auth2Ptr->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID) || + (!CompareGuid (&Auth2Ptr->AuthInfo.CertType, &gEfiCertPkcs7Guid)) + ) { + // + // Invalid AuthInfo type, return EFI_SECURITY_VIOLATION. + // + return EFI_SECURITY_VIOLATION; + } + + *CertDataPtr = ((UINT8 *)&Auth2Ptr->AuthInfo.CertType) + sizeof (EFI_GUID); + *CertDataSize = Auth2Ptr->AuthInfo.Hdr.dwLength - (UINT32)(OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertType)) - sizeof (EFI_GUID); + + return EFI_SUCCESS; +} + +/* + This function will according to the opeartion type to processing the + certs of auth variable. + + @param[in] VariableName Name of Variable to be found. + @param[in] VendorGuid Variable vendor GUID. + @param[in] Attributes Attribute value of the variable. + @param[in] OperationType Indicate the operation of auth variable. + @param[in] PayloadSize Indicate the size of payload in bytes. + @param[in] SignerCert A pointer to SignerCert data. + @param[in] SignerCertSize Length of SignerCert data. + @param[in] TopLevelCert A pointer to TopLevelCert data. + @param[in] TopLevelCertSize Length of TopLevelCert data. + + @retval EFI_INVALID_PARAMETER Invalid input parameters. + @retval EFI_SECURITY_VIOLATION Verify or update certs failed. + @retval EFI_SUCCESS The operation is finished successfully. + @retval Others Other errors as indicated. +*/ +EFI_STATUS +VerifyCertsAndUpdate ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN EFI_COMMAND_OPER_TYPE OperationType, + IN UINT32 PayloadSize, + IN UINT8 *SignerCert, + IN UINT32 SignerCertSize, + IN UINT8 *TopLevelCert, + IN UINT32 TopLevelCertSize + ) +{ + EFI_STATUS Status; + EFI_CERT_DATA *TempPtr; + UINT8 *CertDataPtr; + UINT32 CertDataSize; + VARIABLE_INFO_PRIVATE *PriVarInfo; + + Status = EFI_SUCCESS; + TempPtr = NULL; + CertDataPtr = NULL; + CertDataSize = 0; + + if ( OperationType >= VariableTypeMax || + VariableName == NULL || + VendorGuid == NULL || + SignerCert == NULL || + TopLevelCert == NULL + ) { + return EFI_INVALID_PARAMETER; + } + + PriVarInfo = FindVariableInfoPtr (VariableName, VendorGuid); + + /* + Add: + 1. Create: certdb, variable. OrgTimeStamp == NULL, payloadsize != 0. + 2. Modify: variable. OrgTimeStamp != NULL, payloadsize != 0. + + Del: + 1. Delete: certdb, variable. payloadsize == 0. + + Append:(No update timestamp) + 1. Create: certdb, variable. OrgTimeStamp == NULL, payloadsize != 0. + 2. Modify: variable. OrgTimeStamp != NULL, payloadsize != 0. + */ + + // + // Specified behavior is not matching the payload buffer. + // In this situation will delete certs from certdb but add variable. + // + if (OperationType == VariableTypeDel && PayloadSize != 0) { + return EFI_SECURITY_VIOLATION; + } + + // + // Specified behavior is not matching the payload buffer. + // In this situation will add certs into certdb but delete variable. + // + if ( (OperationType == VariableTypeAdd || OperationType == VariableTypeAppend) && + (PayloadSize == 0) + ) { + return EFI_SECURITY_VIOLATION; + } + + if ((OperationType == VariableTypeAdd || OperationType == VariableTypeAppend) && (PriVarInfo == NULL)) { + TempPtr = (EFI_CERT_DATA *)(SignerCert + 1); + Status = InsertCertsToDb ( + VariableName, + VendorGuid, + Attributes, + TempPtr->CertDataBuffer, + ReadUnaligned32 ((UINT32 *)&TempPtr->CertDataLength), + TopLevelCert, + TopLevelCertSize + ); + if (EFI_ERROR (Status)) { + return Status; + } + } else { + Status = FindCertsFromDb ( + VariableName, + VendorGuid, + Attributes, + NULL, + NULL, + &CertDataPtr, + &CertDataSize + ); + if (EFI_ERROR (Status)) { + return Status; + } + + if (CertDataSize == SHA256_DIGEST_SIZE) { +#if 0 + UINT8 Sha256Digest[SHA256_DIGEST_SIZE]; + TempPtr = (EFI_CERT_DATA *)(SignerCert + 1); + Status = CalculatePrivAuthVarSignChainSHA256Digest ( + TempPtr->CertDataBuffer, + ReadUnaligned32 ((UINT32 *)&TempPtr->CertDataLength), + TopLevelCert, + TopLevelCertSize, + Sha256Digest + ); + if (EFI_ERROR (Status)) { + return Status; + } + if (CompareMem (Sha256Digest, CertDataPtr, CertDataSize) != 0) { + return EFI_SECURITY_VIOLATION; + } +#endif + } else { + if (CertDataSize != TopLevelCertSize) { + return EFI_SECURITY_VIOLATION; + } + + if (CompareMem (SignerCert, CertDataPtr, CertDataSize) != 0) { + return EFI_SECURITY_VIOLATION; + } + } + } + + return EFI_SUCCESS; +} + +/** + Process variable with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set + + @param[in] VariableName Name of Variable to be found. + @param[in] VendorGuid Variable vendor GUID. + @param[in] Attributes Attribute value of the variable. + @param[in] Buffer Data pointer. + @param[in] BufferSize Size of Data found. If size is less than the + data, this value contains the required size. + @param[in] OrgTimeStamp Pointer to original time stamp, + original variable is not found if NULL. + @param[in] OperationType Indicates how to process the auth variable. + @param[out] VarPayloadPtr Pointer to variable payload address. + @param[out] VarPayloadSize Pointer to variable payload size. + @param[out] CertTimeStamp Pointer to timestamp of auth2 structure. + + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_SECURITY_VIOLATION The variable does NOT pass the validation + check carried out by the firmware. + @retval EFI_OUT_OF_RESOURCES Failed to process variable due to lack + of resources. + @retval EFI_SUCCESS Variable pass validation successfully. +**/ +EFI_STATUS +Auth2VerifyAndUpdate ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN VOID *Buffer, + IN UINTN BufferSize, + IN EFI_TIME *OrgTimeStamp, + IN EFI_COMMAND_OPER_TYPE OperationType, + OUT UINT8 **VarPayloadPtr, + OUT UINTN *VarPayloadSize, + OUT EFI_TIME **CertTimeStamp + ) +{ +#if 0 + EFI_STATUS Status; + BOOLEAN VerifyStatus; + EFI_VARIABLE_AUTHENTICATION_2 *Auth2Ptr; + UINT8 *CertDataPtr; + UINT32 CertDataSize; + UINT8 *PayloadPtr; + UINT32 PayloadSize; + UINT8 *Digest; + UINT32 DigestSize; + UINT8 *SignerCert; + UINT32 SignerCertSize; + UINT8 *TopLevelCert; + UINT32 TopLevelCertSize; + UINT32 Offset; + VARIABLE_INFO_PRIVATE *PriVarInfo; + + Status = EFI_SUCCESS; + Digest = NULL; + Offset = 0; + + PriVarInfo = FindVariableInfoPtr (VariableName, VendorGuid); + + Status = VerifyAuth2Descriptor ( + Attributes, + Buffer, + BufferSize, + PriVarInfo == NULL ? NULL : &PriVarInfo->TimeStamp, + &CertDataPtr, + &CertDataSize + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Auth2Ptr = (EFI_VARIABLE_AUTHENTICATION_2 *)Buffer; + + // + // Find out the new data payload which follows Pkcs7 SignedData directly. + // + PayloadPtr = CertDataPtr + CertDataSize; + PayloadSize = (UINT32)(BufferSize - sizeof (EFI_TIME) - Auth2Ptr->AuthInfo.Hdr.dwLength); + + DigestSize = (UINT32)(PayloadSize + + StrLen (VariableName) * sizeof (CHAR16) + + sizeof (UINT32) + + sizeof (EFI_TIME) + + sizeof (EFI_GUID)); + Digest = (UINT8 *)malloc (DigestSize); + if (Digest == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CopyMem (Digest + Offset, VariableName, StrLen (VariableName) * sizeof (CHAR16)); + Offset = (UINT32)(Offset + StrLen (VariableName) * sizeof (CHAR16)); + + CopyMem (Digest + Offset, VendorGuid, sizeof (EFI_GUID)); + Offset = Offset + sizeof (EFI_GUID); + + CopyMem (Digest + Offset, &Attributes, sizeof (UINT32)); + Offset = Offset + sizeof (UINT32); + + CopyMem (Digest + Offset, &Auth2Ptr->TimeStamp, sizeof (EFI_TIME)); + Offset = Offset + sizeof (EFI_TIME); + + CopyMem (Digest + Offset, PayloadPtr, PayloadSize); + + VerifyStatus = Pkcs7GetSigners ( + CertDataPtr, + CertDataSize, + &SignerCert, + (UINTN *)&SignerCertSize, + &TopLevelCert, + (UINTN *)&TopLevelCertSize + ); + if (!VerifyStatus) { + goto ON_EXIT; + } + + VerifyStatus = Pkcs7Verify ( + CertDataPtr, + CertDataSize, + TopLevelCert, + TopLevelCertSize, + Digest, + DigestSize + ); + if (!VerifyStatus) { + goto ON_EXIT; + } + + Status = VerifyCertsAndUpdate ( + VariableName, + VendorGuid, + Attributes, + OperationType, + PayloadSize, + SignerCert, + SignerCertSize, + TopLevelCert, + TopLevelCertSize + ); + + if (EFI_ERROR (Status)) { + VerifyStatus = FALSE; + } + +ON_EXIT: + Pkcs7FreeSigners (TopLevelCert); + Pkcs7FreeSigners (SignerCert); + + FREE_NON_NULL_PTR (Digest); + + if (!VerifyStatus) { + return EFI_SECURITY_VIOLATION; + } + + // + // Find out the new data payload which follows Pkcs7 SignedData directly. + // + *VarPayloadPtr = CertDataPtr + CertDataSize; + *VarPayloadSize = BufferSize - sizeof (EFI_TIME) - Auth2Ptr->AuthInfo.Hdr.dwLength; + *CertTimeStamp = &Auth2Ptr->TimeStamp; + + return EFI_SUCCESS; +#else + return EFI_UNSUPPORTED; +#endif +} + +/* + Process variable with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set. + + @param[in] Name Name of Variable to be processed. + @param[in] Guid Variable vendor GUID. + @param[in] Data Data pointer. + @param[in] DataSize The size of Data in bytes. + @param[in] Attributes Attribute value of the variable. + @param[in] OperType The operation type about variable. + + @retval EFI_SUCCESS The operation is finished successfully. + @retval EFI_INVALID_PARAMETER Invalid input parameters, Name, Guid or Data is NULL. + @retval EFI_OUT_OF_RESOURCES No more memory for allocation. + @retval Others Other errors as indicated. +*/ +EFI_STATUS +ProcessAuthVar ( + IN CHAR16 *Name, + IN EFI_GUID *Guid, + IN VOID *Data, + IN UINTN DataSize, + IN UINT32 Attributes, + IN EFI_COMMAND_OPER_TYPE OperType + ) +{ + EFI_STATUS Status; + EFI_TIME *CertTimeStamp; + LIST_ENTRY *ListEntry; + VARIABLE_INFO_PRIVATE *PriVarInfo; + UINT8 *PayloadPtr; + UINTN PayloadSize; + + Status = EFI_SUCCESS; + CertTimeStamp = NULL; + ListEntry = NULL; + PriVarInfo = NULL; + PayloadPtr = NULL; + PayloadSize = 0; + + if (Name == NULL || Guid == NULL || Data == NULL || OperType == VariableTypeMax) { + return EFI_INVALID_PARAMETER; + } + + // + // Try to get auth variable. + // + ListEntry = FindVariableList (&mVarListEntry, Name, Guid); + + if (ListEntry != NULL) { + PriVarInfo = VARIABLE_INFO_PRIVATE_FROM_LINK (ListEntry); + } + + Status = Auth2VerifyAndUpdate ( + Name, + Guid, + Attributes, + Data, + DataSize, + PriVarInfo == NULL ? NULL : &PriVarInfo->TimeStamp, + OperType, + &PayloadPtr, + &PayloadSize, + &CertTimeStamp + ); + if (EFI_ERROR (Status)) { + return Status; + } + + if (OperType == VariableTypeDel) { + Status = DeleteVariableList (&mVarListEntry, Name, Guid); + if (Status == EFI_SUCCESS) { + Status = DeleteCertsFromDb (Name, Guid, Attributes); + } + } else { + Status = CreateVariableList ( + &mVarListEntry, + Name, + Guid, + Attributes, + CertTimeStamp, + PayloadSize, + PayloadPtr, + OperType == VariableTypeAppend + ); + } + + return Status; +} diff --git a/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/AuthVariable.h b/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/AuthVariable.h new file mode 100644 index 0000000..18c8823 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/AuthVariable.h @@ -0,0 +1,41 @@ +/** + Header file to Manage & verify Timebased Authenticated varaibles. + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _AUTH_VARIABLE_H +#define _AUTH_VARIABLE_H + +#include "OsVariable.h" +#include "VariableCommon.h" +#include "AuthVarCertDB.h" + +/* + Process variable with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set. + + @param[in] Name Name of Variable to be processed. + @param[in] Guid Variable vendor GUID. + @param[in] Data Data pointer. + @param[in] DataSize The size of Data in bytes. + @param[in] Attributes Attribute value of the variable. + @param[in] OperType The operation type about variable. + + @retval EFI_SUCCESS The operation is finished successfully. + @retval EFI_INVALID_PARAMETER Invalid input parameters, Name, Guid or Data is NULL. + @retval EFI_OUT_OF_RESOURCES No more memory for allocation. + @retval Others Other errors as indicated. +*/ +EFI_STATUS +ProcessAuthVar ( + IN CHAR16 *Name, + IN EFI_GUID *Guid, + IN VOID *Data, + IN UINTN DataSize, + IN UINT32 Attributes, + IN EFI_COMMAND_OPER_TYPE OperType + ); + +#endif diff --git a/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/OsVariable.c b/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/OsVariable.c new file mode 100644 index 0000000..f16f3bc --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/OsVariable.c @@ -0,0 +1,784 @@ +/** + Utility to enroll UEFI value, including PK, KEK, db/dbx/dbt in OS. + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "OsVariable.h" +#include "VariableCommon.h" +#include "AuthVariable.h" + +LIST_ENTRY mVarListEntry = INITIALIZE_LIST_HEAD_VARIABLE(mVarListEntry); + +/** + Compare two EFI_TIME data. + + + @param FirstTime A pointer to the first EFI_TIME data. + @param SecondTime A pointer to the second EFI_TIME data. + + @retval TRUE The FirstTime is not later than the SecondTime. + @retval FALSE The FirstTime is later than the SecondTime. + +**/ +BOOLEAN +CompareTimeStamp ( + IN EFI_TIME *FirstTime, + IN EFI_TIME *SecondTime + ) +{ + if (FirstTime->Year != SecondTime->Year) { + return (BOOLEAN) (FirstTime->Year < SecondTime->Year); + } else if (FirstTime->Month != SecondTime->Month) { + return (BOOLEAN) (FirstTime->Month < SecondTime->Month); + } else if (FirstTime->Day != SecondTime->Day) { + return (BOOLEAN) (FirstTime->Day < SecondTime->Day); + } else if (FirstTime->Hour != SecondTime->Hour) { + return (BOOLEAN) (FirstTime->Hour < SecondTime->Hour); + } else if (FirstTime->Minute != SecondTime->Minute) { + return (BOOLEAN) (FirstTime->Minute < SecondTime->Minute); + } + + return (BOOLEAN) (FirstTime->Second <= SecondTime->Second); +} + +VOID +GetCurrentTime ( + OUT EFI_TIME *TimeStamp + ) +{ + time_t CurTime; + struct tm *GmTime; + + memset (TimeStamp, 0, sizeof (*TimeStamp)); + + time (&CurTime); + GmTime = gmtime (&CurTime); + if (GmTime == NULL) { + return; + } + TimeStamp->Year = (UINT16)GmTime->tm_year + 1900; // Year is 1900-based + TimeStamp->Month = (UINT8)GmTime->tm_mon + 1; // Month is zero based. + TimeStamp->Day = (UINT8)GmTime->tm_mday; + TimeStamp->Hour = (UINT8)GmTime->tm_hour; + TimeStamp->Minute = (UINT8)GmTime->tm_min; + TimeStamp->Second = (UINT8)GmTime->tm_sec; +} + +VOID +DumpHex ( + IN UINT8 *Buffer, + IN UINTN BufferSize + ) +/*++ + +Routine Description: + + Dump hex data + +Arguments: + + Buffer - Buffer address + BufferSize - Buffer size + +Returns: + + None + +--*/ +{ + UINTN Index; + UINTN IndexJ; +#define COL_SIZE 16 + + for (Index = 0; Index < BufferSize/COL_SIZE; Index++) { + DEBUG ((DEBUG_INFO, " %04x: ", (UINT16) Index * COL_SIZE)); + for (IndexJ = 0; IndexJ < COL_SIZE; IndexJ++) { + DEBUG ((DEBUG_INFO, "%02x ", *(Buffer + Index * COL_SIZE + IndexJ))); + } + DEBUG ((DEBUG_INFO, "\n")); + } + if ((BufferSize % COL_SIZE) != 0) { + DEBUG ((DEBUG_INFO, " %04x: ", (UINT16) Index * COL_SIZE)); + for (IndexJ = 0; IndexJ < (BufferSize % COL_SIZE); IndexJ++) { + DEBUG ((DEBUG_INFO, "%02x ", *(Buffer + Index * COL_SIZE + IndexJ))); + } + DEBUG ((DEBUG_INFO, "\n")); + } +} + +LIST_ENTRY * +FindVariableList ( + IN LIST_ENTRY *StorageListHead, + IN CHAR16 *Name, + IN EFI_GUID *Guid + ) +{ + LIST_ENTRY *Link; + VARIABLE_INFO_PRIVATE *Storage; + + if (StorageListHead->ForwardLink != NULL) { + Link = GetFirstNode (StorageListHead); + while (!IsNull (StorageListHead, Link)) { + Storage = VARIABLE_INFO_PRIVATE_FROM_LINK (Link); + if ((CompareGuid (&Storage->Guid, Guid)) && + (StrCmp (Storage->Name, Name) == 0)) { + return Link; + } + Link = GetNextNode (StorageListHead, Link); + } + } + return NULL; +} + +/* + Find out the matching VARIABLE_INFO_PRIVATE by variable name and guid. + + @param[in] VariableName Name of variable to be find. + @param[in] VendorGuid Variable vendor GUID. + + @retval VARIABLE_INFO_PRIVATE A pointer to VARIABLE_INFO_PRIVATE. + @retval NULL Not find. +*/ +VARIABLE_INFO_PRIVATE* +FindVariableInfoPtr( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid + ) +{ + LIST_ENTRY *ListEntry; + + // + // Try to get auth variable by name and GUID. + // + ListEntry = FindVariableList (&mVarListEntry, VariableName, VendorGuid); + if (ListEntry != NULL) { + return VARIABLE_INFO_PRIVATE_FROM_LINK (ListEntry); + } + + return NULL; +} + +/** + Filter out the duplicated EFI_SIGNATURE_DATA from the new data by comparing to the original data. + And copy the combined data to final data. + + @param[in] Data Pointer to original EFI_SIGNATURE_LIST. + @param[in] DataSize Size of Data buffer. + @param[in] NewData Pointer to new EFI_SIGNATURE_LIST. + @param[in] NewDataSize Size of NewData buffer. + @param[out] FinalData Pointer to final combined EFI_SIGNATURE_LIST. + @param[out] FinalDataSize Size of FinalData buffer. + +**/ +VOID +FilterSignatureList ( + IN VOID *Data, + IN UINTN DataSize, + IN VOID *NewData, + IN UINTN NewDataSize, + OUT VOID *FinalData, + OUT UINTN *FinalDataSize + ) +{ + EFI_SIGNATURE_LIST *CertList; + EFI_SIGNATURE_DATA *Cert; + UINTN CertCount; + EFI_SIGNATURE_LIST *NewCertList; + EFI_SIGNATURE_DATA *NewCert; + UINTN NewCertCount; + UINTN Index; + UINTN Index2; + UINTN NewSize; + UINTN Size; + UINT8 *Tail; + UINTN CopiedCount; + UINTN SignatureListSize; + BOOLEAN IsNewCert; + + // + // Copy the original data to final data first. + // + CopyMem (FinalData, Data, DataSize); + *FinalDataSize = DataSize; + + if (NewDataSize == 0) { + return; + } + + Tail = (UINT8 *) FinalData + *FinalDataSize; + + NewSize = NewDataSize; + NewCertList = (EFI_SIGNATURE_LIST *) NewData; + while ((NewSize > 0) && (NewSize >= NewCertList->SignatureListSize)) { + NewCert = (EFI_SIGNATURE_DATA *) ((UINT8 *) NewCertList + sizeof (EFI_SIGNATURE_LIST) + NewCertList->SignatureHeaderSize); + NewCertCount = (NewCertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - NewCertList->SignatureHeaderSize) / NewCertList->SignatureSize; + + CopiedCount = 0; + for (Index = 0; Index < NewCertCount; Index++) { + IsNewCert = TRUE; + + Size = DataSize; + CertList = (EFI_SIGNATURE_LIST *) Data; + while ((Size > 0) && (Size >= CertList->SignatureListSize)) { + if ((CompareGuid (&CertList->SignatureType, &NewCertList->SignatureType)) && + (CertList->SignatureSize == NewCertList->SignatureSize)) { + Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize); + CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize; + for (Index2 = 0; Index2 < CertCount; Index2++) { + // + // Iterate each Signature Data in this Signature List. + // + if (CompareMem (NewCert, Cert, CertList->SignatureSize) == 0) { + IsNewCert = FALSE; + break; + } + Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize); + } + } + + if (!IsNewCert) { + break; + } + Size -= CertList->SignatureListSize; + CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize); + } + + if (IsNewCert) { + DEBUG ((DEBUG_INFO, "found new cert!\n")); + // + // New EFI_SIGNATURE_DATA, keep it. + // + if (CopiedCount == 0) { + // + // Copy EFI_SIGNATURE_LIST header for only once. + // + CopyMem (Tail, NewCertList, sizeof (EFI_SIGNATURE_LIST) + NewCertList->SignatureHeaderSize); + Tail = Tail + sizeof (EFI_SIGNATURE_LIST) + NewCertList->SignatureHeaderSize; + } + + CopyMem (Tail, NewCert, NewCertList->SignatureSize); + Tail += NewCertList->SignatureSize; + CopiedCount++; + } + + NewCert = (EFI_SIGNATURE_DATA *) ((UINT8 *) NewCert + NewCertList->SignatureSize); + } + + // + // Update SignatureListSize in the kept EFI_SIGNATURE_LIST. + // + if (CopiedCount != 0) { + SignatureListSize = sizeof (EFI_SIGNATURE_LIST) + NewCertList->SignatureHeaderSize + (CopiedCount * NewCertList->SignatureSize); + CertList = (EFI_SIGNATURE_LIST *) (Tail - SignatureListSize); + CertList->SignatureListSize = (UINT32) SignatureListSize; + } + + NewSize -= NewCertList->SignatureListSize; + NewCertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) NewCertList + NewCertList->SignatureListSize); + } + + *FinalDataSize = (Tail - (UINT8 *) FinalData); +} + +EFI_STATUS +UpdateVariableList ( + IN LIST_ENTRY *Link, + IN CHAR16 *Name, + IN EFI_GUID *Guid, + IN UINT32 Attributes, + IN EFI_TIME *TimeStamp, + IN UINTN Size, + IN UINT8 *Buffer, + IN BOOLEAN Append + ) +{ + VARIABLE_INFO_PRIVATE *Storage; + UINTN NewSize; + UINT8 *NewBuffer; + + Storage = VARIABLE_INFO_PRIVATE_FROM_LINK (Link); + + Storage->Attributes = Attributes; + if (Append) { + if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) { + // + // When the new TimeStamp value is later than the current timestamp associated + // with the variable, we need associate the new timestamp with the updated value. + // + if (CompareTimeStamp (&Storage->TimeStamp, TimeStamp)) { + CopyMem (&Storage->TimeStamp, TimeStamp, sizeof (*TimeStamp)); + } + } + NewSize = Storage->Size + Size; + NewBuffer = malloc (NewSize); + if (NewBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + ASSERT (Storage->Buffer != NULL); + if (((CompareGuid (Guid, &gEfiImageSecurityDatabaseGuid)) && + ((StrCmp (Name, EFI_IMAGE_SECURITY_DATABASE) == 0) || (StrCmp (Name, EFI_IMAGE_SECURITY_DATABASE1) == 0) || + (StrCmp (Name, EFI_IMAGE_SECURITY_DATABASE2) == 0))) || + ((CompareGuid (Guid, &gEfiGlobalVariableGuid)) && (StrCmp (Name, EFI_KEY_EXCHANGE_KEY_NAME) == 0))) { + FilterSignatureList ( + Storage->Buffer, + Storage->Size, + Buffer, + Size, + NewBuffer, + &NewSize + ); + } else { + CopyMem (NewBuffer, Storage->Buffer, Storage->Size); + CopyMem (NewBuffer + Storage->Size, Buffer, Size); + } + + Storage->Size = NewSize; + free (Storage->Buffer); + Storage->Buffer = NewBuffer; + } else { + if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) { + CopyMem (&Storage->TimeStamp, TimeStamp, sizeof (*TimeStamp)); + } + Storage->Size = Size; + ASSERT (Storage->Buffer != NULL); + free (Storage->Buffer); + Storage->Buffer = malloc (Size); + if (Storage->Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + CopyMem (Storage->Buffer, Buffer, Size); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +CreateVariableList ( + IN LIST_ENTRY *StorageListHead, + IN CHAR16 *Name, + IN EFI_GUID *Guid, + IN UINT32 Attributes, + IN EFI_TIME *TimeStamp, + IN UINTN Size, + IN UINT8 *Buffer, + IN BOOLEAN Append + ) +{ + VARIABLE_INFO_PRIVATE *Storage; + UINTN VarNameSize; + LIST_ENTRY *Link; + EFI_TIME TempTimeStamp; + + if (((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) && + (TimeStamp == NULL)) { + // + // Fetch the current time based on UTC timezone + // + GetCurrentTime (&TempTimeStamp); + TimeStamp = &TempTimeStamp; + } + + // + // Check previous one + // + Link = FindVariableList (StorageListHead, Name, Guid); + if (Link != NULL) { + return UpdateVariableList ( + Link, + Name, + Guid, + Attributes, + TimeStamp, + Size, + Buffer, + Append + ); + } + + // + // Create new one + // + Storage = malloc (sizeof (*Storage)); + if (Storage == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Storage->Signature = VARIABLE_INFO_PRIVATE_SIGNATURE; + CopyMem (&Storage->Guid, Guid, sizeof(*Guid)); + VarNameSize = StrSize (Name); + Storage->Name = malloc (VarNameSize); + if (Storage->Name == NULL) { + free (Storage); + return EFI_OUT_OF_RESOURCES; + } + CopyMem (Storage->Name, Name, VarNameSize); + Storage->Attributes = Attributes; + Storage->Size = Size; + ASSERT (Storage->Size != 0); + Storage->Buffer = malloc (Size); + if (Storage->Buffer == NULL) { + free (Storage->Name); + free (Storage); + return EFI_OUT_OF_RESOURCES; + } + CopyMem (Storage->Buffer, Buffer, Size); + if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) { + CopyMem (&Storage->TimeStamp, TimeStamp, sizeof (*TimeStamp)); + } + + InsertTailList(StorageListHead, &Storage->Link); + + return EFI_SUCCESS; +} + +EFI_STATUS +DeleteVariableList ( + IN LIST_ENTRY *StorageListHead, + IN CHAR16 *Name, + IN EFI_GUID *Guid + ) +{ + VARIABLE_INFO_PRIVATE *Storage; + LIST_ENTRY *Link; + + Link = FindVariableList (StorageListHead, Name, Guid); + if (Link == NULL) { + return EFI_NOT_FOUND; + } + + Storage = VARIABLE_INFO_PRIVATE_FROM_LINK (Link); + RemoveEntryList (&Storage->Link); + + return EFI_SUCCESS; +} + +EFI_STATUS +EnrollVar ( + IN CHAR16 *Name, + IN EFI_GUID *Guid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data, + IN BOOLEAN TimeBased, + IN BOOLEAN Append + ) +{ + EFI_STATUS EfiStatus; + UINT8 *Payload; + UINTN PayloadSize; + EFI_TIME *TimeStamp; + + TimeStamp = NULL; + Payload = (UINT8 *) Data; + PayloadSize = DataSize; + if (TimeBased) { + TimeStamp = &((EFI_VARIABLE_AUTHENTICATION_2 *) Data)->TimeStamp; + Payload = (UINT8 *) Data + AUTHINFO2_SIZE (Data); + PayloadSize = DataSize - AUTHINFO2_SIZE (Data); + } + + EfiStatus = CreateVariableList ( + &mVarListEntry, + Name, + Guid, + Attributes, + TimeStamp, + PayloadSize, + Payload, + Append + ); + return EfiStatus; +} + +EFI_STATUS +DeleteVar ( + IN CHAR16 *Name, + IN EFI_GUID *Guid + ) +{ + EFI_STATUS EfiStatus; + + EfiStatus = DeleteVariableList ( + &mVarListEntry, + Name, + Guid + ); + return EfiStatus; +} + +EFI_STATUS +ProcessVar ( + IN CHAR16 *Name, + IN EFI_GUID *Guid, + IN VOID *Data, + IN UINTN DataSize, + IN UINT32 Attributes + ) +{ + EFI_COMMAND_OPER_TYPE CommandType; + EFI_STATUS Status; + BOOLEAN TimeBased; + + if ((Attributes == 0) || + ((DataSize == 0) && (Data == NULL))) { + CommandType = VariableTypeDel; + } else if ((Attributes & EFI_VARIABLE_APPEND_WRITE) != 0) { + CommandType = VariableTypeAppend; + } else { + CommandType = VariableTypeAdd; + } + + TimeBased = ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0); + + if (CommandType == VariableTypeDel) { + Status = DeleteVar (Name, Guid); + } else { + Status = EnrollVar ( + Name, + Guid, + Attributes, + DataSize, + Data, + TimeBased, + CommandType == VariableTypeAppend ? TRUE : FALSE + ); + } + + return Status; +} + +VOID +DumpTimestamp ( + IN EFI_TIME *TimeOfRevocation + ) +{ + DEBUG ((DEBUG_INFO, " %02d/%02d/%04d %02d:%02d:%02d\n", + TimeOfRevocation->Month, + TimeOfRevocation->Day, + TimeOfRevocation->Year, + TimeOfRevocation->Hour, + TimeOfRevocation->Minute, + TimeOfRevocation->Second + )); +} + +VOID +DumpCert ( + IN UINT8 *Buffer, + IN UINTN Size + ) +{ + EFI_SIGNATURE_LIST *CertList; + EFI_SIGNATURE_DATA *Cert; + UINT32 CertCount; + UINT32 CertListIndex; + UINT32 CertIndex; + + CertListIndex = 0; + CertList = (EFI_SIGNATURE_LIST *)Buffer; + while ((UINTN)CertList < (UINTN)Buffer + Size) { + DEBUG ((DEBUG_INFO, "SIGNATURE_LIST[%d]\n", CertListIndex)); + DEBUG ((DEBUG_INFO, " SignatureType - %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", + CertList->SignatureType.Data1, + CertList->SignatureType.Data2, + CertList->SignatureType.Data3, + CertList->SignatureType.Data4[0], + CertList->SignatureType.Data4[1], + CertList->SignatureType.Data4[2], + CertList->SignatureType.Data4[3], + CertList->SignatureType.Data4[4], + CertList->SignatureType.Data4[5], + CertList->SignatureType.Data4[6], + CertList->SignatureType.Data4[7] + )); + DEBUG ((DEBUG_INFO, " SignatureListSize - %08x\n", CertList->SignatureListSize)); + DEBUG ((DEBUG_INFO, " SignatureHeaderSize - %08x\n", CertList->SignatureHeaderSize)); + DEBUG ((DEBUG_INFO, " SignatureSize - %08x\n", CertList->SignatureSize)); + Cert = (EFI_SIGNATURE_DATA *)((UINT8 *)CertList + sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize); + CertCount = (CertList->SignatureListSize - sizeof(EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize; + for (CertIndex = 0; CertIndex < CertCount; CertIndex++) { + DEBUG ((DEBUG_INFO, " SIGNATURE_DATA[%d]\n", CertIndex)); + DEBUG ((DEBUG_INFO, " SignatureOwner - %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", + Cert->SignatureOwner.Data1, + Cert->SignatureOwner.Data2, + Cert->SignatureOwner.Data3, + Cert->SignatureOwner.Data4[0], + Cert->SignatureOwner.Data4[1], + Cert->SignatureOwner.Data4[2], + Cert->SignatureOwner.Data4[3], + Cert->SignatureOwner.Data4[4], + Cert->SignatureOwner.Data4[5], + Cert->SignatureOwner.Data4[6], + Cert->SignatureOwner.Data4[7] + )); + DEBUG ((DEBUG_INFO, " Signature - \n")); + if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha256Guid)) { + EFI_CERT_X509_SHA256 *CertX509Sha256; + CertX509Sha256 = (EFI_CERT_X509_SHA256 *)Cert->SignatureData; + DEBUG ((DEBUG_INFO, " SHA256 - \n")); + DumpHex (CertX509Sha256->ToBeSignedHash, sizeof(CertX509Sha256->ToBeSignedHash)); + DEBUG ((DEBUG_INFO, " Timestamp - \n")); + DumpTimestamp (&CertX509Sha256->TimeOfRevocation); + } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha384Guid)) { + EFI_CERT_X509_SHA384 *CertX509Sha384; + CertX509Sha384 = (EFI_CERT_X509_SHA384 *)Cert->SignatureData; + DEBUG ((DEBUG_INFO, " SHA384 - \n")); + DumpHex (CertX509Sha384->ToBeSignedHash, sizeof(CertX509Sha384->ToBeSignedHash)); + DEBUG ((DEBUG_INFO, " Timestamp - \n")); + DumpTimestamp (&CertX509Sha384->TimeOfRevocation); + } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha512Guid)) { + EFI_CERT_X509_SHA512 *CertX509Sha512; + CertX509Sha512 = (EFI_CERT_X509_SHA512 *)Cert->SignatureData; + DEBUG ((DEBUG_INFO, " SHA512 - \n")); + DumpHex (CertX509Sha512->ToBeSignedHash, sizeof(CertX509Sha512->ToBeSignedHash)); + DEBUG ((DEBUG_INFO, " Timestamp - \n")); + DumpTimestamp (&CertX509Sha512->TimeOfRevocation); + } else { + DumpHex (Cert->SignatureData, CertList->SignatureSize - (sizeof(EFI_SIGNATURE_DATA) - 1)); + } + Cert = (EFI_SIGNATURE_DATA *)((UINT8 *)Cert + CertList->SignatureSize); + } + CertList = (EFI_SIGNATURE_LIST *)((UINT8 *)CertList + CertList->SignatureListSize); + CertListIndex ++; + } + +} + +VOID +DumpVarStorage ( + IN VARIABLE_INFO_PRIVATE *Storage, + IN BOOLEAN IsDumpCert + ) +{ + DEBUG ((DEBUG_INFO, "Variable:\n")); + DEBUG ((DEBUG_INFO, " Name - %s\n", Storage->Name)); + DEBUG ((DEBUG_INFO, " Guid - %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", + Storage->Guid.Data1, + Storage->Guid.Data2, + Storage->Guid.Data3, + Storage->Guid.Data4[0], + Storage->Guid.Data4[1], + Storage->Guid.Data4[2], + Storage->Guid.Data4[3], + Storage->Guid.Data4[4], + Storage->Guid.Data4[5], + Storage->Guid.Data4[6], + Storage->Guid.Data4[7] + )); + DEBUG ((DEBUG_INFO, " Attributes - %08x\n", Storage->Attributes)); + DEBUG ((DEBUG_INFO, " Size - %08x\n", (UINT32) Storage->Size)); + DEBUG ((DEBUG_INFO, " Buffer - \n")); + if (IsDumpCert) { + DumpCert (Storage->Buffer, Storage->Size); + } else { + DumpHex (Storage->Buffer, Storage->Size); + } + DEBUG ((DEBUG_INFO, "\n")); +} + +VOID +DumpInfo ( + IN CHAR16 *Name, + IN EFI_GUID *Guid + ) +{ + LIST_ENTRY *Link; + VARIABLE_INFO_PRIVATE *Storage; + + Link = FindVariableList ( + &mVarListEntry, + Name, + Guid + ); + if (Link == NULL) { + DEBUG ((DEBUG_INFO, "DumpInfo - not found!\n")); + return ; + } + Storage = VARIABLE_INFO_PRIVATE_FROM_LINK (Link); + + DumpVarStorage (Storage, TRUE); + + return ; +} + +VOID +DumpVariableList ( + IN LIST_ENTRY *StorageListHead + ) +{ + LIST_ENTRY *Link; + VARIABLE_INFO_PRIVATE *Storage; + + if (StorageListHead->ForwardLink != NULL) { + Link = GetFirstNode (StorageListHead); + while (!IsNull (StorageListHead, Link)) { + Storage = VARIABLE_INFO_PRIVATE_FROM_LINK (Link); + DumpVarStorage (Storage, FALSE); + Link = GetNextNode (StorageListHead, Link); + } + } +} + +EFI_STATUS +ProcessKey ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN VOID *Data, + IN UINTN DataSize, + IN UINT32 Attributes + ) +{ + return ProcessVar (VariableName, VendorGuid, Data, DataSize, Attributes); +} + +EFI_STATUS +EFIAPI +CoreSetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data + ) +{ + return ProcessKey (VariableName, VendorGuid, Data, DataSize, Attributes); +} + +EFI_STATUS +EFIAPI +CoreGetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes, OPTIONAL + IN OUT UINTN *DataSize, + OUT VOID *Data OPTIONAL + ) +{ + VARIABLE_INFO_PRIVATE *VariableInfo; + + if (DataSize == NULL) { + return EFI_INVALID_PARAMETER; + } + + VariableInfo = FindVariableInfoPtr (VariableName, VendorGuid); + if (VariableInfo == NULL || VariableInfo->Size == 0) { + return EFI_NOT_FOUND; + } + if (*DataSize < VariableInfo->Size) { + *DataSize = VariableInfo->Size; + return EFI_BUFFER_TOO_SMALL; + } + *DataSize = VariableInfo->Size; + if (Data != NULL) { + CopyMem (Data, VariableInfo->Buffer, VariableInfo->Size); + } + + if (Attributes != NULL) { + *Attributes = VariableInfo->Attributes; + } + + return EFI_SUCCESS; +} diff --git a/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/OsVariable.h b/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/OsVariable.h new file mode 100644 index 0000000..60fa9e4 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/OsVariable.h @@ -0,0 +1,71 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _OS_VARIABLE_H_ +#define _OS_VARIABLE_H_ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +// +// ASN.1 +// +#define TWO_BYTE_ENCODE 0x82 + +#define SHA256_DIGEST_SIZE 32 + +#define VARIABLE_INFO_PRIVATE_SIGNATURE SIGNATURE_32 ('V', 'K', 'E', 'S') + +typedef struct { + UINTN Signature; + LIST_ENTRY Link; + + EFI_GUID Guid; + CHAR16 *Name; + UINT32 Attributes; + EFI_TIME TimeStamp; + UINTN Size; + UINT8 *Buffer; +} VARIABLE_INFO_PRIVATE; + +#define VARIABLE_INFO_PRIVATE_FROM_LINK(a) CR (a, VARIABLE_INFO_PRIVATE, Link, VARIABLE_INFO_PRIVATE_SIGNATURE) + +#define FREE_NON_NULL_PTR(Pointer) \ + do { \ + if ((Pointer) != NULL) { \ + free ((Pointer)); \ + (Pointer) = NULL; \ + } \ + } while(FALSE) + +// +// Command operation type. +// +typedef enum { + VariableTypeAdd, // Indicate to create variable. + VariableTypeDel, // Indicate to delete. + VariableTypeAppend, // Indicate to append. + VariableTypeMax // Invalid type +} EFI_COMMAND_OPER_TYPE; + +BOOLEAN +CompareTimeStamp ( + IN EFI_TIME *FirstTime, + IN EFI_TIME *SecondTime + ); + +#endif diff --git a/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/Time.c b/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/Time.c new file mode 100644 index 0000000..5eb2e67 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/Time.c @@ -0,0 +1,43 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include + +#include +#include +#include + +EFI_STATUS +EFIAPI +CoreGetTime ( + OUT EFI_TIME *Time, + OUT EFI_TIME_CAPABILITIES *Capabilities OPTIONAL + ) +{ + time_t timer; + struct tm *info; + + if (Time != NULL) { + ZeroMem (Time, sizeof(*Time)); + time (&timer); + info = localtime (&timer); + Time->Year = (UINT16)(info->tm_year + 1900); + Time->Month = (UINT8)(info->tm_mon + 1); + Time->Day = (UINT8)info->tm_mday; + Time->Hour = (UINT8)info->tm_hour; + Time->Minute = (UINT8)info->tm_min; + Time->Second = (UINT8)info->tm_sec; + } + if (Capabilities != NULL) { + ZeroMem (Capabilities, sizeof(*Capabilities)); + } + return EFI_SUCCESS; +} diff --git a/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/UefiRuntimeServicesTableLibHost.c b/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/UefiRuntimeServicesTableLibHost.c new file mode 100644 index 0000000..1a73b5a --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/UefiRuntimeServicesTableLibHost.c @@ -0,0 +1,160 @@ +/** @file + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +extern EFI_RUNTIME_SERVICES mEfiRuntimeServicesTableTemplate; + +EFI_RUNTIME_SERVICES *gRT = &mEfiRuntimeServicesTableTemplate; + + +/** + Place holder function until all the Boot Services and Runtime Services are + available. + + @param Arg1 Undefined + + @return EFI_NOT_AVAILABLE_YET + +**/ +EFI_STATUS +EFIAPI +CoreEfiNotAvailableYetArg1 ( + UINTN Arg1 + ); + + +/** + Place holder function until all the Boot Services and Runtime Services are available. + + @param Arg1 Undefined + @param Arg2 Undefined + + @return EFI_NOT_AVAILABLE_YET + +**/ +EFI_STATUS +EFIAPI +CoreEfiNotAvailableYetArg2 ( + UINTN Arg1, + UINTN Arg2 + ); + + +/** + Place holder function until all the Boot Services and Runtime Services are available. + + @param Arg1 Undefined + @param Arg2 Undefined + @param Arg3 Undefined + + @return EFI_NOT_AVAILABLE_YET + +**/ +EFI_STATUS +EFIAPI +CoreEfiNotAvailableYetArg3 ( + UINTN Arg1, + UINTN Arg2, + UINTN Arg3 + ); + + +/** + Place holder function until all the Boot Services and Runtime Services are available. + + @param Arg1 Undefined + @param Arg2 Undefined + @param Arg3 Undefined + @param Arg4 Undefined + + @return EFI_NOT_AVAILABLE_YET + +**/ +EFI_STATUS +EFIAPI +CoreEfiNotAvailableYetArg4 ( + UINTN Arg1, + UINTN Arg2, + UINTN Arg3, + UINTN Arg4 + ); + + +/** + Place holder function until all the Boot Services and Runtime Services are available. + + @param Arg1 Undefined + @param Arg2 Undefined + @param Arg3 Undefined + @param Arg4 Undefined + @param Arg5 Undefined + + @return EFI_NOT_AVAILABLE_YET + +**/ +EFI_STATUS +EFIAPI +CoreEfiNotAvailableYetArg5 ( + UINTN Arg1, + UINTN Arg2, + UINTN Arg3, + UINTN Arg4, + UINTN Arg5 + ); + +EFI_STATUS +EFIAPI +CoreGetTime ( + OUT EFI_TIME *Time, + OUT EFI_TIME_CAPABILITIES *Capabilities OPTIONAL + ); + +EFI_STATUS +EFIAPI +CoreSetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data + ); + +EFI_STATUS +EFIAPI +CoreGetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes, OPTIONAL + IN OUT UINTN *DataSize, + OUT VOID *Data OPTIONAL + ); + +EFI_RUNTIME_SERVICES mEfiRuntimeServicesTableTemplate = { + { + EFI_RUNTIME_SERVICES_SIGNATURE, // Signature + EFI_RUNTIME_SERVICES_REVISION, // Revision + sizeof (EFI_RUNTIME_SERVICES), // HeaderSize + 0, // CRC32 + 0 // Reserved + }, + (EFI_GET_TIME) CoreGetTime, // GetTime + (EFI_SET_TIME) CoreEfiNotAvailableYetArg1, // SetTime + (EFI_GET_WAKEUP_TIME) CoreEfiNotAvailableYetArg3, // GetWakeupTime + (EFI_SET_WAKEUP_TIME) CoreEfiNotAvailableYetArg2, // SetWakeupTime + (EFI_SET_VIRTUAL_ADDRESS_MAP) CoreEfiNotAvailableYetArg4, // SetVirtualAddressMap + (EFI_CONVERT_POINTER) CoreEfiNotAvailableYetArg2, // ConvertPointer + (EFI_GET_VARIABLE) CoreGetVariable, // GetVariable + (EFI_GET_NEXT_VARIABLE_NAME) CoreEfiNotAvailableYetArg3, // GetNextVariableName + (EFI_SET_VARIABLE) CoreSetVariable, // SetVariable + (EFI_GET_NEXT_HIGH_MONO_COUNT) CoreEfiNotAvailableYetArg1, // GetNextHighMonotonicCount + (EFI_RESET_SYSTEM) CoreEfiNotAvailableYetArg4, // ResetSystem + (EFI_UPDATE_CAPSULE) CoreEfiNotAvailableYetArg3, // UpdateCapsule + (EFI_QUERY_CAPSULE_CAPABILITIES) CoreEfiNotAvailableYetArg4, // QueryCapsuleCapabilities + (EFI_QUERY_VARIABLE_INFO) CoreEfiNotAvailableYetArg4 // QueryVariableInfo +}; diff --git a/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/UefiRuntimeServicesTableLibHost.inf b/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/UefiRuntimeServicesTableLibHost.inf new file mode 100644 index 0000000..984e313 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/UefiRuntimeServicesTableLibHost.inf @@ -0,0 +1,43 @@ +## @file +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UefiRuntimeServicesTableLibHost + FILE_GUID = 2F5F71C6-932D-4F91-ACC2-ED886DE088A0 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = UefiRuntimeServicesTableLib + +[Sources] + UefiRuntimeServicesTableLibHost.c + Time.c + OsVariable.c + AuthVariable.c + AuthVarCertDB.c + Variable.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + SecurityPkg/SecurityPkg.dec + CryptoPkg/CryptoPkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + UefiBootServicesTableLib + +[Guids] + gEfiGlobalVariableGuid + gEfiImageSecurityDatabaseGuid + gEfiCertDbGuid + gEfiCertX509Sha256Guid + gEfiCertX509Sha384Guid + gEfiCertX509Sha512Guid + gEfiCertPkcs7Guid diff --git a/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/Variable.c b/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/Variable.c new file mode 100644 index 0000000..41730c1 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/Variable.c @@ -0,0 +1,541 @@ +/** + Read and edit the EFI variable. + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "OsVariable.h" +#include "VariableCommon.h" +#include "Variable.h" +#include + +/** + + Gets the pointer to the first variable header in given variable store area. + + @param VarStoreHeader Pointer to the Variable Store Header. + + @return Pointer to the first variable header. + +**/ +VARIABLE_HEADER * +GetStartPointer ( + IN VARIABLE_STORE_HEADER *VarStoreHeader + ) +{ + // + // The end of variable store. + // + return (VARIABLE_HEADER *) HEADER_ALIGN (VarStoreHeader + 1); +} + +/** + + Gets the pointer to the end of the variable storage area. + + This function gets pointer to the end of the variable storage + area, according to the input variable store header. + + @param VarStoreHeader Pointer to the Variable Store Header. + + @return Pointer to the end of the variable storage area. + +**/ +VARIABLE_HEADER * +GetEndPointer ( + IN VARIABLE_STORE_HEADER *VarStoreHeader + ) +{ + // + // The end of variable store + // + return (VARIABLE_HEADER *) HEADER_ALIGN ((UINTN) VarStoreHeader + VarStoreHeader->Size); +} + + +/** + + This code checks if variable header is valid or not. + + @param Variable Pointer to the Variable Header. + + @retval TRUE Variable header is valid. + @retval FALSE Variable header is not valid. + +**/ +BOOLEAN +IsValidVariableHeader ( + IN VARIABLE_HEADER *Variable + ) +{ + if ((Variable == NULL) || (Variable->Common.StartId != VARIABLE_DATA)) { + return FALSE; + } + + return TRUE; +} + +/** + + This code gets the size of name of variable. + + @param Variable Pointer to the Variable Header. + + @return UINTN Size of variable in bytes. + +**/ +UINTN +NameSizeOfVariable ( + IN VARIABLE_HEADER *Variable, + IN VARIABLE_TYPE VariableType + ) +{ + switch (VariableType) { + case VariableTypeNormal: + if ((Variable->Normal.State == (UINT8) (-1)) || + (Variable->Normal.DataSize == (UINT32) (-1)) || + (Variable->Normal.NameSize == (UINT32) (-1)) || + (Variable->Normal.Attributes == (UINT32) (-1)) + ) { + return 0; + } + return (UINTN) Variable->Normal.NameSize; + case VariableTypeCountBasedAuth: + if ((Variable->CountBasedAuth.State == (UINT8) (-1)) || + (Variable->CountBasedAuth.DataSize == (UINT32) (-1)) || + (Variable->CountBasedAuth.NameSize == (UINT32) (-1)) || + (Variable->CountBasedAuth.Attributes == (UINT32) (-1)) + ) { + return 0; + } + return (UINTN) Variable->CountBasedAuth.NameSize; + case VariableTypeTimeBasedAuth: + if ((Variable->TimeBasedAuth.State == (UINT8) (-1)) || + (Variable->TimeBasedAuth.DataSize == (UINT32) (-1)) || + (Variable->TimeBasedAuth.NameSize == (UINT32) (-1)) || + (Variable->TimeBasedAuth.Attributes == (UINT32) (-1)) + ) { + return 0; + } + return (UINTN) Variable->TimeBasedAuth.NameSize; + default: + return 0; + } +} + +/** + + This code gets the size of variable data. + + @param Variable Pointer to the Variable Header. + + @return Size of variable in bytes. + +**/ +UINTN +DataSizeOfVariable ( + IN VARIABLE_HEADER *Variable, + IN VARIABLE_TYPE VariableType + ) +{ + switch (VariableType) { + case VariableTypeNormal: + if ((Variable->Normal.State == (UINT8) (-1)) || + (Variable->Normal.DataSize == (UINT32) (-1)) || + (Variable->Normal.NameSize == (UINT32) (-1)) || + (Variable->Normal.Attributes == (UINT32) (-1)) + ) { + return 0; + } + return (UINTN) Variable->Normal.DataSize; + case VariableTypeCountBasedAuth: + if ((Variable->CountBasedAuth.State == (UINT8) (-1)) || + (Variable->CountBasedAuth.DataSize == (UINT32) (-1)) || + (Variable->CountBasedAuth.NameSize == (UINT32) (-1)) || + (Variable->CountBasedAuth.Attributes == (UINT32) (-1)) + ) { + return 0; + } + return (UINTN) Variable->CountBasedAuth.DataSize; + case VariableTypeTimeBasedAuth: + if ((Variable->TimeBasedAuth.State == (UINT8) (-1)) || + (Variable->TimeBasedAuth.DataSize == (UINT32) (-1)) || + (Variable->TimeBasedAuth.NameSize == (UINT32) (-1)) || + (Variable->TimeBasedAuth.Attributes == (UINT32) (-1)) + ) { + return 0; + } + return (UINTN) Variable->TimeBasedAuth.DataSize; + default: + return 0; + } +} + +/** + + This code gets the pointer to the variable name. + + @param Variable Pointer to the Variable Header. + + @return Pointer to Variable Name which is Unicode encoding. + +**/ +CHAR16 * +GetVariableNamePtr ( + IN VARIABLE_HEADER *Variable, + IN VARIABLE_TYPE VariableType + ) +{ + switch (VariableType) { + case VariableTypeNormal: + return (CHAR16 *) ((UINTN)Variable + sizeof(VARIABLE_HEADER_NORMAL)); + case VariableTypeCountBasedAuth: + return (CHAR16 *) ((UINTN)Variable + sizeof(VARIABLE_HEADER_COUNT_BASED_AUTH)); + case VariableTypeTimeBasedAuth: + return (CHAR16 *) ((UINTN)Variable + sizeof(VARIABLE_HEADER_TIME_BASED_AUTH)); + default: + return NULL; + } +} + +/** + + This code gets the pointer to the variable data. + + @param Variable Pointer to the Variable Header. + + @return Pointer to Variable Data. + +**/ +UINT8 * +GetVariableDataPtr ( + IN VARIABLE_HEADER *Variable, + IN VARIABLE_TYPE VariableType + ) +{ + UINTN Value; + + // + // Be careful about pad size for alignment. + // + Value = (UINTN) GetVariableNamePtr (Variable, VariableType); + Value += NameSizeOfVariable (Variable, VariableType); + Value += GET_PAD_SIZE (NameSizeOfVariable (Variable, VariableType)); + + return (UINT8 *) Value; +} + +/** + + This code gets the pointer to the next variable header. + + @param Variable Pointer to the Variable Header. + + @return Pointer to next variable header. + +**/ +VARIABLE_HEADER * +GetNextVariablePtr ( + IN VARIABLE_HEADER *Variable, + IN VARIABLE_TYPE VariableType + ) +{ + UINTN Value; + + if (!IsValidVariableHeader (Variable)) { + return NULL; + } + + Value = (UINTN) GetVariableDataPtr (Variable, VariableType); + Value += DataSizeOfVariable (Variable, VariableType); + Value += GET_PAD_SIZE (DataSizeOfVariable (Variable, VariableType)); + + // + // Be careful about pad size for alignment. + // + return (VARIABLE_HEADER *) HEADER_ALIGN (Value); +} + +/** + + This code gets the pointer to the variable GUID. + + @param Variable Pointer to the Variable Header. + + @return Pointer to variable GUID. + +**/ +EFI_GUID * +GetVariableGuidPtr ( + IN VARIABLE_HEADER *Variable, + IN VARIABLE_TYPE VariableType + ) +{ + switch (VariableType) { + case VariableTypeNormal: + return &Variable->Normal.VendorGuid; + case VariableTypeCountBasedAuth: + return &Variable->CountBasedAuth.VendorGuid; + case VariableTypeTimeBasedAuth: + return &Variable->TimeBasedAuth.VendorGuid; + default: + return NULL; + } +} + +/** + + This code gets the Attributes of variable data. + + @param Variable Pointer to the Variable Header. + + @return Attributes of variable. + +**/ +UINT32 +AttributesOfVariable ( + IN VARIABLE_HEADER *Variable, + IN VARIABLE_TYPE VariableType + ) +{ + return Variable->Normal.Attributes; +} + +VOID +SetVariableAttributes ( + IN VARIABLE_HEADER *Variable, + IN VARIABLE_TYPE VariableType, + IN UINT32 Attributes + ) +{ + Variable->Normal.Attributes = Attributes; +} + +VOID +SetVariableNameSize ( + IN VARIABLE_HEADER *Variable, + IN VARIABLE_TYPE VariableType, + IN UINT32 NameSize + ) +{ + switch (VariableType) { + case VariableTypeNormal: + Variable->Normal.NameSize = NameSize; + break; + case VariableTypeCountBasedAuth: + Variable->CountBasedAuth.NameSize = NameSize; + break; + case VariableTypeTimeBasedAuth: + Variable->TimeBasedAuth.NameSize = NameSize; + break; + default: + break; + } +} + +VOID +SetVariableDataSize ( + IN VARIABLE_HEADER *Variable, + IN VARIABLE_TYPE VariableType, + IN UINT32 DataSize + ) +{ + switch (VariableType) { + case VariableTypeNormal: + Variable->Normal.DataSize = DataSize; + break; + case VariableTypeCountBasedAuth: + Variable->CountBasedAuth.DataSize = DataSize; + break; + case VariableTypeTimeBasedAuth: + Variable->TimeBasedAuth.DataSize = DataSize; + break; + default: + break; + } +} + +VOID +SetVariableGuid ( + IN VARIABLE_HEADER *Variable, + IN VARIABLE_TYPE VariableType, + IN EFI_GUID *Guid + ) +{ + EFI_GUID *VendorGuid; + + VendorGuid = GetVariableGuidPtr (Variable, VariableType); + if (VendorGuid != NULL) { + memcpy (VendorGuid, Guid, sizeof (EFI_GUID)); + } +} + +VOID +SetVariableName ( + IN VARIABLE_HEADER *Variable, + IN VARIABLE_TYPE VariableType, + IN CHAR16 *Name, + IN UINTN NameSize + ) +{ + CHAR16 *VariableName; + + VariableName = GetVariableNamePtr (Variable, VariableType); + if (VariableName != NULL) { + memcpy (VariableName, Name, NameSize); + } +} + +VOID +SetVariableData ( + IN VARIABLE_HEADER *Variable, + IN VARIABLE_TYPE VariableType, + IN VOID *Buffer, + IN UINTN BuffferSize + ) +{ + memcpy (GetVariableDataPtr (Variable, VariableType), Buffer, BuffferSize); +} + +UINTN +SizeOfVariableHeader ( + IN VARIABLE_TYPE VariableType + ) +{ + switch (VariableType) { + case VariableTypeNormal: + return sizeof(VARIABLE_HEADER_NORMAL); + case VariableTypeCountBasedAuth: + return sizeof(VARIABLE_HEADER_COUNT_BASED_AUTH); + case VariableTypeTimeBasedAuth: + return sizeof(VARIABLE_HEADER_TIME_BASED_AUTH); + default: + return 0; + } +} + +/** + Search and get a free space in the EFI variable zone + + @param VariableStoreHeader The start of a EFI variable zone. + @param VarListSize The size of a variables needs to be allocated. + @param FreeBeginVar The dual pointer to the free NV space. + + @retval EFI_SUCCESS Return the beginning of a free variable space. + @retval RETURN_BUFFER_TOO_SMALL Failed. +**/ +EFI_STATUS +GetVariableVar ( + IN VARIABLE_STORE_HEADER *VariableStoreHeader, + IN VARIABLE_TYPE VariableType, + IN UINT32 VarListSize, + IN OUT CHAR8 **FreeBeginVar +) +{ + BOOLEAN Flag; + VARIABLE_HEADER *Variable; + VARIABLE_HEADER *EndOfVariable; + CHAR8 *BeginVar; + + BeginVar = NULL; + Flag = FALSE; + Variable = NULL; + EndOfVariable = NULL; + *FreeBeginVar = NULL; + + if (VariableStoreHeader == NULL) { + *FreeBeginVar = NULL; + return RETURN_INVALID_PARAMETER; + } + Variable = GetStartPointer (VariableStoreHeader); + EndOfVariable = GetEndPointer(VariableStoreHeader); + // + //Search the beginning of free NV + // + while (Variable != EndOfVariable) { + BeginVar = (CHAR8 *)Variable; + Variable = GetNextVariablePtr (Variable, VariableType); + if (Variable == NULL) { + Flag = TRUE; + break; + } + } + // + // Check whether the free space is more than what we want + // + if ((CHAR8 *)BeginVar + VarListSize > (CHAR8 *)EndOfVariable) { + return RETURN_BUFFER_TOO_SMALL; + } + // + // If not find the available space, return NULL + // + if (!Flag) { + return RETURN_BUFFER_TOO_SMALL; + } + *FreeBeginVar = BeginVar; + + return EFI_SUCCESS; +} + +/** + Search whether the variable in VarList has existed in current NV. + + Parse the FFS or Fd image, and find the valid variable pointer. + + @param VariableStoreHeader The start of a EFI variable zone. + @param VarList The pointer to the VarList + + @retval address If the variable existed in current NV, return address + @return NULL Otherwise, return NULL +**/ +VARIABLE_HEADER * +FindVariableInNv ( + IN VARIABLE_STORE_HEADER *VariableStoreHeader, + IN VARIABLE_TYPE VariableType, + IN VARIABLE_INFO_PRIVATE *Storage + ) +{ + BOOLEAN Flag; + VARIABLE_HEADER *Variable; + VARIABLE_HEADER *EndOfVariable; + CHAR16 *VariableName; + EFI_GUID *VendorGuid; + + Flag = FALSE; + Variable = NULL; + EndOfVariable = NULL; + VariableName = NULL; + VendorGuid = NULL; + + if ((VariableStoreHeader == NULL) || (Storage == NULL) || (Storage->Name == NULL)) { + return NULL; + } + Variable = GetStartPointer (VariableStoreHeader); + EndOfVariable = GetEndPointer(VariableStoreHeader); + // + // Parse and compare the variable in the NV space one by one + // + while ((Variable != EndOfVariable) && (Variable != NULL)) { + VariableName = (CHAR16 *)GetVariableNamePtr (Variable, VariableType); + if (NULL == VariableName) { + return NULL; + } + VendorGuid = GetVariableGuidPtr (Variable, VariableType); + if (NULL == VendorGuid) { + return NULL; + } + if ((CompareGuid (VendorGuid, &Storage->Guid)) && + (StrCmp (Storage->Name, VariableName) == 0) && + (Variable->Common.State == VAR_ADDED)) { + Flag = TRUE; + break; + } + Variable = GetNextVariablePtr (Variable, VariableType); + } + if (!Flag) { + return NULL; + } + return Variable; +} diff --git a/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/Variable.h b/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/Variable.h new file mode 100644 index 0000000..ca9e2da --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/Variable.h @@ -0,0 +1,257 @@ +/** @file + The header of Variable.c. + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __VARIABLE_FORMAT_H__ +#define __VARIABLE_FORMAT_H__ + +/// +/// Alignment of variable name and data, according to the architecture: +/// * For IA-32 and Intel(R) 64 architectures: 1. +/// * For IA-64 architecture: 8. +/// +#if defined (MDE_CPU_IPF) +#define ALIGNMENT 8 +#else +#define ALIGNMENT 1 +#endif + +/// +/// GET_PAD_SIZE calculates the miminal pad bytes needed to make the current pad size satisfy the alignment requirement. +/// +#if (ALIGNMENT == 1) +#define GET_PAD_SIZE(a) (0) +#else +#define GET_PAD_SIZE(a) (((~a) + 1) & (ALIGNMENT - 1)) +#endif + +/// +/// Alignment of Variable Data Header in Variable Store region. +/// +#define HEADER_ALIGNMENT 4 +#define HEADER_ALIGN(Header) (((UINTN) (Header) + HEADER_ALIGNMENT - 1) & (~(HEADER_ALIGNMENT - 1))) + +/// +/// Status of Variable Store Region. +/// +typedef enum { + EfiRaw, + EfiValid, + EfiInvalid, + EfiUnknown +} VARIABLE_STORE_STATUS; + +#pragma pack(1) + +#define VARIABLE_STORE_SIGNATURE EFI_VARIABLE_GUID + +/// +/// Variable Store Header Format and State. +/// +#define VARIABLE_STORE_FORMATTED 0x5a +#define VARIABLE_STORE_HEALTHY 0xfe + +/// +/// Variable Store region header. +/// +typedef struct { + /// + /// Variable store region signature. + /// + EFI_GUID Signature; + /// + /// Size of entire variable store, + /// including size of variable store header but not including the size of FvHeader. + /// + UINT32 Size; + /// + /// Variable region format state. + /// + UINT8 Format; + /// + /// Variable region healthy state. + /// + UINT8 State; + UINT16 Reserved; + UINT32 Reserved1; +} VARIABLE_STORE_HEADER; + +/// +/// Variable data start flag. +/// +#define VARIABLE_DATA 0x55AA + +/// +/// Variable State flags. +/// +#define VAR_IN_DELETED_TRANSITION 0xfe ///< Variable is in obsolete transition. +#define VAR_DELETED 0xfd ///< Variable is obsolete. +#define VAR_HEADER_VALID_ONLY 0x7f ///< Variable header has been valid. +#define VAR_ADDED 0x3f ///< Variable has been completely added. + +/// +/// Single Variable Data Header Structure. +/// +typedef struct { + /// + /// Variable Data Start Flag. + /// + UINT16 StartId; + /// + /// Variable State defined above. + /// + UINT8 State; + UINT8 Reserved; + /// + /// Attributes of variable defined in UEFI specification. + /// + UINT32 Attributes; + /// + /// Size of variable null-terminated Unicode string name. + /// + UINT32 NameSize; + /// + /// Size of the variable data without this header. + /// + UINT32 DataSize; + /// + /// A unique identifier for the vendor that produces and consumes this varaible. + /// + EFI_GUID VendorGuid; +} VARIABLE_HEADER_NORMAL; + +/// +/// Single Variable Data Header Structure. +/// +typedef struct { + /// + /// Variable Data Start Flag. + /// + UINT16 StartId; + /// + /// Variable State defined above. + /// + UINT8 State; + UINT8 Reserved; + /// + /// Attributes of variable defined in UEFI spec + /// + UINT32 Attributes; + /// + /// Associated monotonic count value against replay attack. + /// + UINT64 MonotonicCount; + /// + /// Index of associated public key in database. + /// + UINT32 PubKeyIndex; + /// + /// Size of variable null-terminated Unicode string name. + /// + UINT32 NameSize; + /// + /// Size of the variable data without this header. + /// + UINT32 DataSize; + /// + /// A unique identifier for the vendor that produces and consumes this varaible. + /// + EFI_GUID VendorGuid; +} VARIABLE_HEADER_COUNT_BASED_AUTH; + +/// +/// Single Variable Data Header Structure. +/// +typedef struct { + /// + /// Variable Data Start Flag. + /// + UINT16 StartId; + /// + /// Variable State defined above. + /// + UINT8 State; + UINT8 Reserved; + /// + /// Attributes of variable defined in UEFI spec + /// + UINT32 Attributes; + /// + /// Associated monotonic count value against replay attack. + /// + UINT64 MonotonicCount; + /// + /// Associated TimeStamp value against replay attack. + /// + EFI_TIME TimeStamp; + /// + /// Index of associated public key in database. + /// + UINT32 PubKeyIndex; + /// + /// Size of variable null-terminated Unicode string name. + /// + UINT32 NameSize; + /// + /// Size of the variable data without this header. + /// + UINT32 DataSize; + /// + /// A unique identifier for the vendor that produces and consumes this varaible. + /// + EFI_GUID VendorGuid; +} VARIABLE_HEADER_TIME_BASED_AUTH; + +/// +/// Single Variable Data Header Structure. +/// +typedef struct { + /// + /// Variable Data Start Flag. + /// + UINT16 StartId; + /// + /// Variable State defined above. + /// + UINT8 State; + UINT8 Reserved; + // ...... +} VARIABLE_HEADER_COMMON; + +typedef union { + VARIABLE_HEADER_COMMON Common; + VARIABLE_HEADER_NORMAL Normal; + VARIABLE_HEADER_COUNT_BASED_AUTH CountBasedAuth; + VARIABLE_HEADER_TIME_BASED_AUTH TimeBasedAuth; +} VARIABLE_HEADER; + +#pragma pack() + +// +// Internal definition +// + +typedef struct _VARIABLE_INFO_ENTRY VARIABLE_INFO_ENTRY; + +/// +/// This structure contains the variable list that is put in EFI system table. +/// The variable driver collects all variables that were used at boot service time and produces this list. +/// This is an optional feature to dump all used variables in shell environment. +/// +struct _VARIABLE_INFO_ENTRY { + VARIABLE_INFO_ENTRY *Next; ///< Pointer to next entry. + EFI_GUID VendorGuid; ///< Guid of Variable. + CHAR16 *Name; ///< Name of Variable. + UINT32 Attributes; ///< Attributes of variable defined in UEFI specification. + UINT32 ReadCount; ///< Number of times to read this variable. + UINT32 WriteCount; ///< Number of times to write this variable. + UINT32 DeleteCount; ///< Number of times to delete this variable. + UINT32 CacheCount; ///< Number of times that cache hits this variable. + BOOLEAN Volatile; ///< TRUE if volatile, FALSE if non-volatile. +}; + +#endif // _EFI_VARIABLE_H_ diff --git a/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/VariableCommon.h b/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/VariableCommon.h new file mode 100644 index 0000000..f751cc8 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/VariableCommon.h @@ -0,0 +1,51 @@ +/** @file + The header of common Variable.c + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __VARIABLE_COMMON_H__ +#define __VARIABLE_COMMON_H__ + +typedef enum { + VariableTypeNormal, + VariableTypeCountBasedAuth, + VariableTypeTimeBasedAuth, + VariableTypeUnknown, +} VARIABLE_TYPE; + +EFI_STATUS +CreateVariableList ( + IN LIST_ENTRY *StorageListHead, + IN CHAR16 *Name, + IN EFI_GUID *Guid, + IN UINT32 Attributes, + IN EFI_TIME *TimeStamp, + IN UINTN Size, + IN UINT8 *Buffer, + IN BOOLEAN Append + ); + +EFI_STATUS +DeleteVariableList ( + IN LIST_ENTRY *StorageListHead, + IN CHAR16 *Name, + IN EFI_GUID *Guid + ); + +LIST_ENTRY * +FindVariableList ( + IN LIST_ENTRY *StorageListHead, + IN CHAR16 *Name, + IN EFI_GUID *Guid + ); + +VARIABLE_INFO_PRIVATE* +FindVariableInfoPtr( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid + ); + +#endif // _EFI_VARIABLE_COMMON_H_ diff --git a/HBFA/UefiHostTestPkg/Library/VarCheckLibNull/VarCheckLibNull.c b/HBFA/UefiHostTestPkg/Library/VarCheckLibNull/VarCheckLibNull.c new file mode 100644 index 0000000..971688c --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/VarCheckLibNull/VarCheckLibNull.c @@ -0,0 +1,78 @@ +/** @file + Implementation functions and structures for var check services. + +Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +/** + Var check initialize at END_OF_DXE. + + This function needs to be called at END_OF_DXE. + Address pointers may be returned, + and caller needs to ConvertPointer() for the pointers. + + @param[in, out] AddressPointerCount Output pointer to address pointer count. + + @return Address pointer buffer, NULL if input AddressPointerCount is NULL. + +**/ +VOID *** +EFIAPI +VarCheckLibInitializeAtEndOfDxe ( + IN OUT UINTN *AddressPointerCount OPTIONAL + ) +{ + return NULL; +} + +EFI_STATUS +EFIAPI +VarCheckLibSetVariableCheck ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data, + IN VAR_CHECK_REQUEST_SOURCE RequestSource + ) +{ + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +VarCheckLibVariablePropertyGet ( + IN CHAR16 *Name, + IN EFI_GUID *Guid, + OUT VAR_CHECK_VARIABLE_PROPERTY *VariableProperty + ) +{ + return EFI_NOT_FOUND; +} + +EFI_STATUS +EFIAPI +VarCheckLibVariablePropertySet ( + IN CHAR16 *Name, + IN EFI_GUID *Guid, + IN VAR_CHECK_VARIABLE_PROPERTY *VariableProperty + ) +{ + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +VarCheckLibRegisterSetVariableCheckHandler ( + IN VAR_CHECK_SET_VARIABLE_CHECK_HANDLER Handler + ) +{ + return EFI_SUCCESS; +} + diff --git a/HBFA/UefiHostTestPkg/Library/VarCheckLibNull/VarCheckLibNull.inf b/HBFA/UefiHostTestPkg/Library/VarCheckLibNull/VarCheckLibNull.inf new file mode 100644 index 0000000..c12bb05 --- /dev/null +++ b/HBFA/UefiHostTestPkg/Library/VarCheckLibNull/VarCheckLibNull.inf @@ -0,0 +1,43 @@ +## @file +# Provides variable check services and database management. +# +# Copyright (c) 2015, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = VarCheckLibNull + FILE_GUID = 531905B9-0DB7-4CB0-82A1-917DCEE51D6F + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = VarCheckLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + VarCheckLibNull.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + MemoryAllocationLib + +[Guids] + ## SOMETIMES_CONSUMES ## Variable:L"Boot####" + ## SOMETIMES_CONSUMES ## Variable:L"Driver####" + ## SOMETIMES_CONSUMES ## Variable:L"SysPrep####" + ## SOMETIMES_CONSUMES ## Variable:L"Key####" + gEfiGlobalVariableGuid + gEfiHardwareErrorVariableGuid ## SOMETIMES_CONSUMES ## Variable:L"HwErrRec####" diff --git a/HBFA/UefiHostTestPkg/UefiHostTestBuildOption.dsc b/HBFA/UefiHostTestPkg/UefiHostTestBuildOption.dsc new file mode 100644 index 0000000..5e0a4c4 --- /dev/null +++ b/HBFA/UefiHostTestPkg/UefiHostTestBuildOption.dsc @@ -0,0 +1,66 @@ +## @file UefiHostTestBuildOption.dsc +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[BuildOptions] + MSFT:*_*_*_CC_FLAGS = /D _CRT_SECURE_NO_WARNINGS + + GCC:*_*_IA32_CC_FLAGS == -m32 -g -fshort-wchar -fno-strict-aliasing -Wall -malign-double -idirafter/usr/include -c -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_*_IA32_PP_FLAGS == -m32 -E -x assembler-with-cpp -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_*_IA32_ASM_FLAGS == -m32 -c -x assembler -imacros $(DEST_DIR_DEBUG)/AutoGen.h + + GCC:*_*_X64_CC_FLAGS == -m64 -g -fshort-wchar -fno-strict-aliasing -Wall -malign-double -idirafter/usr/include -c -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_GCC49_X64_CC_FLAGS = "-DEFIAPI=__attribute__((ms_abi))" + GCC:*_GCC5_X64_CC_FLAGS = "-DEFIAPI=__attribute__((ms_abi))" -DUSING_LTO -Os + GCC:*_*_X64_PP_FLAGS == -m64 -E -x assembler-with-cpp -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_*_X64_ASM_FLAGS == -m64 -c -x assembler -imacros $(DEST_DIR_DEBUG)/AutoGen.h + + GCC:*_GCC5_*_CC_FLAGS = --coverage + GCC:*_GCC5_*_DLINK_FLAGS = --coverage + + GCC:*_GCC5_X64_CC_FLAGS = "-DNO_MSABI_VA_FUNCS=TRUE" + +[BuildOptions.common.EDKII.USER_DEFINED] + MSFT:*_*_IA32_DLINK_FLAGS == /out:"$(BIN_DIR)\$(BASE_NAME).exe" /base:0x10000000 /pdb:"$(BIN_DIR)\$(BASE_NAME).pdb" /LIBPATH:"$(VCINSTALLDIR)\Lib" /LIBPATH:"$(VCINSTALLDIR)\PlatformSdk\Lib" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x86" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x86" /NOLOGO /SUBSYSTEM:CONSOLE /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:I386 /LTCG Kernel32.lib MSVCRTD.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib + MSFT:*_VS2015_IA32_DLINK_FLAGS == /out:"$(BIN_DIR)\$(BASE_NAME).exe" /base:0x10000000 /pdb:"$(BIN_DIR)\$(BASE_NAME).pdb" /LIBPATH:"$(VCINSTALLDIR)\Lib" /LIBPATH:"$(VCINSTALLDIR)\PlatformSdk\Lib" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x86" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x86" /NOLOGO /SUBSYSTEM:CONSOLE /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:I386 /LTCG Kernel32.lib MSVCRTD.lib vcruntimed.lib ucrtd.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib + MSFT:*_VS2015x86_IA32_DLINK_FLAGS == /out:"$(BIN_DIR)\$(BASE_NAME).exe" /base:0x10000000 /pdb:"$(BIN_DIR)\$(BASE_NAME).pdb" /LIBPATH:"$(VCINSTALLDIR)\Lib" /LIBPATH:"$(VCINSTALLDIR)\PlatformSdk\Lib" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x86" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x86" /NOLOGO /SUBSYSTEM:CONSOLE /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:I386 /LTCG Kernel32.lib MSVCRTD.lib vcruntimed.lib ucrtd.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib + MSFT:*_VS2017_IA32_DLINK_FLAGS == /out:"$(BIN_DIR)\$(BASE_NAME).exe" /base:0x10000000 /pdb:"$(BIN_DIR)\$(BASE_NAME).pdb" /LIBPATH:"%VCToolsInstallDir%lib\x86" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x86" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x86" /NOLOGO /SUBSYSTEM:CONSOLE /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:I386 /LTCG Kernel32.lib MSVCRTD.lib vcruntimed.lib ucrtd.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib + MSFT:*_*_IA32_CC_FLAGS == /nologo /W4 /WX /Gy /c /D UNICODE /Od /FIAutoGen.h /EHs-c- /GF /Gs8192 /Zi /Gm /D _CRT_SECURE_NO_WARNINGS /D _CRT_SECURE_NO_DEPRECATE + MSFT:*_*_IA32_PP_FLAGS == /nologo /E /TC /FIAutoGen.h + MSFT:*_*_IA32_ASM_FLAGS == /nologo /W3 /WX /c /coff /Cx /Zd /W0 /Zi + MSFT:*_*_IA32_ASMLINK_FLAGS == /link /nologo /tiny + + MSFT:*_*_X64_DLINK_FLAGS == /out:"$(BIN_DIR)\$(BASE_NAME).exe" /base:0x10000000 /pdb:"$(BIN_DIR)\$(BASE_NAME).pdb" /LIBPATH:"$(VCINSTALLDIR)\Lib\AMD64" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x64" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x64" /NOLOGO /SUBSYSTEM:CONSOLE /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:AMD64 /LTCG Kernel32.lib MSVCRTD.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib + MSFT:*_VS2015_X64_DLINK_FLAGS == /out:"$(BIN_DIR)\$(BASE_NAME).exe" /base:0x10000000 /pdb:"$(BIN_DIR)\$(BASE_NAME).pdb" /LIBPATH:"$(VCINSTALLDIR)\Lib\AMD64" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x64" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x64" /NOLOGO /SUBSYSTEM:CONSOLE /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:AMD64 /LTCG Kernel32.lib MSVCRTD.lib vcruntimed.lib ucrtd.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib + MSFT:*_VS2015x86_X64_DLINK_FLAGS == /out:"$(BIN_DIR)\$(BASE_NAME).exe" /base:0x10000000 /pdb:"$(BIN_DIR)\$(BASE_NAME).pdb" /LIBPATH:"$(VCINSTALLDIR)\Lib\AMD64" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x64" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x64" /NOLOGO /SUBSYSTEM:CONSOLE /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:AMD64 /LTCG Kernel32.lib MSVCRTD.lib vcruntimed.lib ucrtd.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib + MSFT:*_VS2017_X64_DLINK_FLAGS == /out:"$(BIN_DIR)\$(BASE_NAME).exe" /base:0x10000000 /pdb:"$(BIN_DIR)\$(BASE_NAME).pdb" /LIBPATH:"%VCToolsInstallDir%lib\x64" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x64" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x64" /NOLOGO /SUBSYSTEM:CONSOLE /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:AMD64 /LTCG Kernel32.lib MSVCRTD.lib vcruntimed.lib ucrtd.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib + MSFT:*_*_X64_CC_FLAGS == /nologo /W4 /WX /Gy /c /D UNICODE /Od /FIAutoGen.h /EHs-c- /GF /Gs8192 /Zi /Gm /D _CRT_SECURE_NO_WARNINGS /D _CRT_SECURE_NO_DEPRECATE + MSFT:*_*_X64_PP_FLAGS == /nologo /E /TC /FIAutoGen.h + MSFT:*_*_X64_ASM_FLAGS == /nologo /W3 /WX /c /Cx /Zd /W0 /Zi + MSFT:*_*_X64_ASMLINK_FLAGS == /link /nologo + + GCC:*_*_IA32_DLINK_FLAGS == -o $(BIN_DIR)/$(BASE_NAME) -m32 -L/usr/X11R6/lib + GCC:*_*_IA32_CC_FLAGS == -m32 -g -fshort-wchar -fno-strict-aliasing -Wall -malign-double -idirafter/usr/include -c -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_*_IA32_PP_FLAGS == -m32 -E -x assembler-with-cpp -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_*_IA32_ASM_FLAGS == -m32 -c -x assembler -imacros $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_*_IA32_DLINK2_FLAGS == -Wno-error -no-pie + + GCC:*_*_X64_DLINK_FLAGS == -o $(BIN_DIR)/$(BASE_NAME) -m64 -L/usr/X11R6/lib + GCC:*_GCC5_X64_DLINK_FLAGS == -o $(BIN_DIR)/$(BASE_NAME) -m64 -L/usr/X11R6/lib + GCC:*_*_X64_CC_FLAGS == -m64 -g -fshort-wchar -fno-strict-aliasing -Wall -malign-double -idirafter/usr/include -c -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_GCC49_X64_CC_FLAGS = "-DEFIAPI=__attribute__((ms_abi))" + GCC:*_GCC5_X64_CC_FLAGS = "-DEFIAPI=__attribute__((ms_abi))" -DUSING_LTO -Os + GCC:*_*_X64_PP_FLAGS == -m64 -E -x assembler-with-cpp -include $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_*_X64_ASM_FLAGS == -m64 -c -x assembler -imacros $(DEST_DIR_DEBUG)/AutoGen.h + GCC:*_*_X64_DLINK2_FLAGS == -Wno-error -no-pie + + GCC:*_GCC5_*_CC_FLAGS = -fstack-protector -fstack-protector-strong -fstack-protector-all + + GCC:*_GCC5_*_CC_FLAGS = --coverage + GCC:*_GCC5_*_DLINK_FLAGS = --coverage + + GCC:*_GCC5_X64_CC_FLAGS = "-DNO_MSABI_VA_FUNCS=TRUE" + diff --git a/HBFA/UefiHostTestPkg/UefiHostTestPkg.dec b/HBFA/UefiHostTestPkg/UefiHostTestPkg.dec new file mode 100644 index 0000000..f5fe1b7 --- /dev/null +++ b/HBFA/UefiHostTestPkg/UefiHostTestPkg.dec @@ -0,0 +1,15 @@ +## @file UefiHostTestPkg.dec +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = UefiHostTestPkg + PACKAGE_GUID = 1D212CA8-77BF-4957-80DA-75609227E70C + PACKAGE_VERSION = 0.11 + +[Includes.common] + Include \ No newline at end of file diff --git a/HBFA/UefiHostTestPkg/UefiHostTestPkg.dsc b/HBFA/UefiHostTestPkg/UefiHostTestPkg.dsc new file mode 100644 index 0000000..8bf5aaa --- /dev/null +++ b/HBFA/UefiHostTestPkg/UefiHostTestPkg.dsc @@ -0,0 +1,56 @@ +## @file UefiHostTestPkg.dsc +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + PLATFORM_NAME = UefiHostTestPkg + PLATFORM_GUID = C2A9A6F1-57DC-4397-ACB6-BCF5DF454BC0 + PLATFORM_VERSION = 0.11 + DSC_SPECIFICATION = 0x00010005 + OUTPUT_DIRECTORY = Build/UefiHostTestPkg + SUPPORTED_ARCHITECTURES = IA32|X64 + BUILD_TARGETS = DEBUG|RELEASE + SKUID_IDENTIFIER = DEFAULT + +[LibraryClasses] + BaseLib|UefiHostTestPkg/Library/BaseLibHost/BaseLibHost.inf + CacheMaintenanceLib|UefiHostTestPkg/Library/BaseCacheMaintenanceLibHost/BaseCacheMaintenanceLibHost.inf + BaseMemoryLib|UefiHostTestPkg/Library/BaseMemoryLibHost/BaseMemoryLibHost.inf + MemoryAllocationLib|UefiHostTestPkg/Library/MemoryAllocationLibHost/MemoryAllocationLibHost.inf + DebugLib|UefiHostTestPkg/Library/DebugLibHost/DebugLibHost.inf + UefiBootServicesTableLib|UefiHostTestPkg/Library/UefiBootServicesTableLibHost/UefiBootServicesTableLibHost.inf + HobLib|UefiHostTestPkg/Library/HobLibHost/HobLibHost.inf + SmmMemLib|UefiHostTestPkg/Library/SmmMemLibHost/SmmMemLibHost.inf + DevicePathLib|UefiHostTestPkg/Library/UefiDevicePathLibHost/UefiDevicePathLibHost.inf + + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + +[LibraryClasses.common.USER_DEFINED] + +[Components] + UefiHostTestPkg/Library/BaseLibHost/BaseLibHost.inf + UefiHostTestPkg/Library/BaseLibNullCpuid/BaseLibNullCpuid.inf + UefiHostTestPkg/Library/BaseLibNullMsr/BaseLibNullMsr.inf + UefiHostTestPkg/Library/BaseCacheMaintenanceLibHost/BaseCacheMaintenanceLibHost.inf + UefiHostTestPkg/Library/BaseCpuLibHost/BaseCpuLibHost.inf + UefiHostTestPkg/Library/BaseMemoryLibHost/BaseMemoryLibHost.inf + UefiHostTestPkg/Library/BaseTimerLibHost/BaseTimerLibHost.inf + UefiHostTestPkg/Library/MemoryAllocationLibHost/MemoryAllocationLibHost.inf + UefiHostTestPkg/Library/DebugLibHost/DebugLibHost.inf + UefiHostTestPkg/Library/UefiBootServicesTableLibHost/UefiBootServicesTableLibHost.inf + UefiHostTestPkg/Library/UefiRuntimeServicesTableLibHost/UefiRuntimeServicesTableLibHost.inf + UefiHostTestPkg/Library/DxeServicesTableLibHost/DxeServicesTableLibHost.inf + UefiHostTestPkg/Library/PeiServicesTablePointerLibHost/PeiServicesTablePointerLibHost.inf + UefiHostTestPkg/Library/HobLibHost/HobLibHost.inf + UefiHostTestPkg/Library/UefiDevicePathLibHost/UefiDevicePathLibHost.inf + UefiHostTestPkg/Library/SmmMemLibHost/SmmMemLibHost.inf + UefiHostTestPkg/Library/UefiLibHost/UefiLibHost.inf + UefiHostTestPkg/Library/PeimEntryPointHost/PeimEntryPointHost.inf + UefiHostTestPkg/Library/UefiDriverEntryPointHost/UefiDriverEntryPointHost.inf + UefiHostTestPkg/Library/OsServiceLibHost/OsServiceLibHost.inf + +!include UefiHostTestPkg/UefiHostTestBuildOption.dsc diff --git a/HBFA/UefiHostTestTools/HBFAEnvSetup.py b/HBFA/UefiHostTestTools/HBFAEnvSetup.py new file mode 100644 index 0000000..baef88a --- /dev/null +++ b/HBFA/UefiHostTestTools/HBFAEnvSetup.py @@ -0,0 +1,168 @@ +# @file +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +import os +import shutil +import sys +import re + +__copyright__ = '' +__version__ = '0.11' +__prog__ = 'HBFAEnvSetup.py' + + +def HelpInfo(): + print("Usage: %s [Options]\n" % __prog__) + print("Create Conf specified for HBFA.\n") + print("Options: ") + print(" --help, -h, -? Print this help screen and exit.\n") + print(" --reconfig " + "Overwrite the UefiHostFuzzTestPkg/Conf/*.txt") + print(" files with the template " + "files from the BaseTools/Conf directory.\n") + print("Please note: This script must be put under HBFA/UefiHostTestTools," + " so the Conf can be generated.") + + +if len(sys.argv) == 2: + if sys.argv[1] == '-h' or sys.argv[1] == '-?' or \ + sys.argv[1] == '--help' or sys.argv[1] == 'help': + HelpInfo() + os._exit(0) + +# EDK_TOOLS_PATH +if 'EDK_TOOLS_PATH' in os.environ: + edk_tools_path = os.environ['EDK_TOOLS_PATH'] + if not os.path.exists(edk_tools_path): + print("EDK_TOOLS_PATH is incorrect, cannot find this folder.") + os._exit(0) +else: + print("EDK_TOOLS_PATH should be set, or you need to run " + "edksetup.sh/edksetup.bat") + os._exit(0) + +# Conf template path +ConfTemplate = os.path.join(edk_tools_path, 'Conf') +if not os.path.exists(ConfTemplate): + print("EDK_TOOLS_PATH is incorrect, cannot find Conf under this folder.") + os._exit(0) + +# HBFA package path +HBFA_PATH = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + +# extend parts of tools_def.txt +ExtendDefineFile = os.path.join(HBFA_PATH, 'UefiHostFuzzTestPkg', + 'Conf', 'tools_def.customized') + + +def GenerateNewToolsDef(Src, Dst): + src = open(Src, 'r') + lines = src.readlines() + src.close() + FlagVer = "GCC48_ALL_CC_FLAGS" + + for line in lines: + pattern = re.compile(r"GCC\d{1,2}_ALL_CC_FLAGS") + obj = pattern.findall(line) + if len(obj) != 0: + FlagVer = obj[0] + break + + extendSrc = open(ExtendDefineFile, 'r') + ExtendDefine = extendSrc.read() + extendSrc.close() + lines.append(ExtendDefine.replace("GCC48_ALL_CC_FLAGS", FlagVer)) + + dst = open(Dst, 'w+') + dst.writelines(lines) + dst.close() + + +def InsertContentToBuildRules(Src, Dst, SectionName, InsertContent): + src = open(Src, 'r') + lines = src.readlines() + src.close() + for i in range(len(lines)): + if SectionName in lines[i]: + StartPos = i + 1 + break + + lines.insert(StartPos, InsertContent) + + dst = open(Dst, 'w+') + dst.writelines(lines) + dst.close() + + +def ExtendOptionToBuildRules(Src, Dst, SectionName, TargetOption, + ExtendOption): + src = open(Src, 'r') + lines = src.readlines() + src.close() + + Sections = SectionName if isinstance(SectionName, list) else [SectionName] + for section in Sections: + for i in range(len(lines)): + if section in lines[i]: + break + for j in range(i, len(lines)): + if TargetOption in lines[j]: + OptionPos = j + break + lines[OptionPos] = lines[OptionPos].replace('>', ', ' + ExtendOption + + '>') + + dst = open(Dst, 'w+') + dst.writelines(lines) + dst.close() + + +def GenerateConfCustomized(ConfSrc, ConfPath, ReConfig): + if not os.path.exists(ConfPath): + os.makedirs(ConfPath) + if (not os.path.exists(os.path.join(ConfPath, 'target.txt'))) or ReConfig: + shutil.copy(os.path.join(ConfSrc, 'target.template'), + os.path.join(ConfPath, 'target.txt')) + if (not os.path.exists(os.path.join(ConfPath, 'build_rule.txt'))) \ + or ReConfig: + SectionName = '[Static-Library-File.USER_DEFINED, ' \ + + 'Static-Library-File.HOST_APPLICATION]' + InsertContent = ''' + echo $(STATIC_LIBRARY_FILES_LIST) + python $(SCRIPT_PATH) ${DLINK_FLAGS} -t $(DLINK) -d $(OUTPUT_DIR) + +''' + InsertContentToBuildRules(os.path.join(ConfSrc, 'build_rule.template'), + os.path.join(ConfPath, 'build_rule.txt'), + SectionName, InsertContent) + SectionNames = ['[Object-File]', '[Static-Library-File]', + '[Static-Library-File.USER_DEFINED, ' + 'Static-Library-File.HOST_APPLICATION]', + '[Dynamic-Library-File]', + '[Hii-Binary-Package.UEFI_HII]'] + TargetOption = 'Command.MSFT' + ExtendOption = 'Command.CLANGWIN' + ExtendOptionToBuildRules(os.path.join(ConfPath, 'build_rule.txt'), + os.path.join(ConfPath, 'build_rule.txt'), + SectionNames, TargetOption, ExtendOption) + if (not os.path.exists(os.path.join(ConfPath, 'tools_def.txt'))) \ + or ReConfig: + GenerateNewToolsDef(os.path.join(ConfSrc, 'tools_def.template'), + os.path.join(ConfPath, 'tools_def.txt')) + + +def main(ReConfig): + GenerateConfCustomized(ConfTemplate, + os.path.join(HBFA_PATH, 'UefiHostFuzzTestPkg', + 'Conf'), ReConfig) + + +if __name__ == "__main__": + if len(sys.argv) == 2: + if sys.argv[1] == '--reconfig': + main(ReConfig=True) + else: + main(ReConfig=False) diff --git a/HBFA/UefiHostTestTools/Report/GenCodeCoverage.py b/HBFA/UefiHostTestTools/Report/GenCodeCoverage.py new file mode 100644 index 0000000..da7080f --- /dev/null +++ b/HBFA/UefiHostTestTools/Report/GenCodeCoverage.py @@ -0,0 +1,319 @@ +#!/usr/bin/env python3 +# @file +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +import os +import sys +import stat +import subprocess +import shutil +import platform +import argparse +from GenLLVMReport import GenLLVMReport + +__prog__ = 'GenCodeCoverage.py' +__copyright__ = 'Copyright (c) 2019, Intel Corporation. All rights reserved.' +__version__ = '{} Version {}'.format(__prog__, '0.11 ') + +WORK_DIR = os.getcwd() + +# Get System type info +SysType = platform.system() + +# HBFA package path +HBFA_PATH = os.path.dirname(os.path.dirname(os.path.dirname( + os.path.realpath(__file__)))) + +# WORKSPACE +workspace = '' + +# Check EDKII BUILD WORKSPACE whether be set in system environment variable +if 'WORKSPACE' not in os.environ: + print("Please set system environment variable 'WORKSPACE' before run " + "this script.") + os._exit(0) +workspace = os.environ['WORKSPACE'] + + +def CheckTestEnv(): + if SysType == "Windows" and "DRIO_PATH" not in os.environ: + print("Please set DRIO_PATH in system environment variables.") + os._exit(0) + + +def delete_gcda_file(TestModuleBinPath): + for root, dirs, files in os.walk(os.path.dirname(TestModuleBinPath)): + for file in files: + if file.endswith('.gcda'): + file_path = os.path.join(root, file) + try: + os.remove(file_path) + except Exception as err: + print(err) + + +def HasIni(path): + if os.listdir(path) == []: + return False + + for file in os.listdir(path): + if file.endswith(".ini"): + return True + + return False + + +def CreateGcovTool(path): + with open(path, 'w') as fd: + fd.write('#!/bin/bash\nexport PATH=$CLANG_PATH:$PATH\nexec ' + 'llvm-cov gcov "$@"') + os.chmod(path, stat.S_IEXEC) + + +def Run_All_Seeds(TestModuleBinPath, SeedPath, TestIniPath): + TestModuleBinFolder = os.path.dirname(TestModuleBinPath) + if SysType == "Windows": + LogDir = os.path.join(TestModuleBinFolder, "temp", "log") + if os.path.exists(os.path.dirname(LogDir)): + shutil.rmtree(os.path.dirname(LogDir)) + os.makedirs(LogDir) + for file in os.listdir(SeedPath): + SeedFilePath = os.path.join(SeedPath, file) + if os.path.isfile(SeedFilePath): + if "IA32" in TestModuleBinPath: + cmd = r"cd {} && %DRIO_PATH%\bin32".format(LogDir) + \ + r"\drrun.exe -c %DRIO_PATH%\tools\lib32\release" + \ + r"\drcov.dll " \ + r"-- {} {}".format(TestModuleBinPath, SeedFilePath) + elif "X64" in TestModuleBinPath: + cmd = r"cd {} && %DRIO_PATH%\bin64".format(LogDir) + \ + r"\drrun.exe -c %DRIO_PATH%\tools\lib64" + \ + r"\release\drcov.dll -- " + \ + r"{} {}".format(TestModuleBinPath, SeedFilePath) + try: + subprocess.run(cmd.split(' '), shell=False, check=True) + except subprocess.CalledProcessError as err: + print(err) + elif SysType == "Linux": + if TestIniPath != "": + for file in os.listdir(SeedPath): + SeedFilePath = os.path.join(SeedPath, file) + if os.path.isfile(SeedFilePath): + for IniFile in os.listdir(TestIniPath): + IniFilePath = os.path.join(TestIniPath, IniFile) + cmd = TestModuleBinPath + ' ' + SeedFilePath + ' ' \ + + IniFilePath + try: + subprocess.run(cmd.split(' '), shell=False, + check=True) + except subprocess.CalledProcessError as err: + print(err) + else: + for file in os.listdir(SeedPath): + SeedFilePath = os.path.join(SeedPath, file) + if os.path.isfile(SeedFilePath): + cmd = TestModuleBinPath + ' ' + SeedFilePath + try: + subprocess.run(cmd.split(' '), shell=False, + check=True) + except subprocess.CalledProcessError as err: + print(err) + + +def GenCodeCoverage(TestModuleBinPath, ReportPath): + TestModuleBinFolder = os.path.dirname(TestModuleBinPath) + if SysType == "Windows": + LogDir = os.path.join(TestModuleBinFolder, "temp", "log") + TempDir = os.path.join(TestModuleBinFolder, "temp") + if "IA32" in TestModuleBinPath: + run_command = \ + r"cd {} && %DRIO_PATH%\tools".format(TempDir) + \ + r"\bin32\drcov2lcov.exe -dir " + \ + r"{} -src_filter ".format(LogDir) + \ + r"{}".format(workspace.lower()) + try: + subprocess.run(run_command.split(' '), shell=False, + check=True) + except subprocess.CalledProcessError as err: + print(err) + run_command = \ + r"cd {} && perl ".format(TempDir) + \ + r"%DRIO_PATH%\tools\bin32\genhtml " + \ + r"coverage.info" + try: + subprocess.run(run_command.split(' '), + shell=False, check=True) + except subprocess.CalledProcessError as err: + print(err) + elif "X64" in TestModuleBinPath: + run_command = \ + r"cd {} && %DRIO_PATH%\tools".format(TempDir) + \ + r"\bin64\drcov2lcov.exe -dir " + \ + r"{} -src_filter ".format(LogDir) + \ + r"{}".format(workspace.lower()) + try: + subprocess.run(run_command.split(' '), shell=False, + check=True) + except subprocess.CalledProcessError as err: + print(err) + run_command = \ + r"cd {}".format(TempDir) + \ + r" && perl %DRIO_PATH%\tools" + \ + r"\bin64\genhtml coverage.info" + try: + subprocess.run(run_command.split(' '), shell=False, + check=True) + except subprocess.CalledProcessError as err: + print(err) + if os.path.exists(ReportPath): + shutil.rmtree(ReportPath) + shutil.copytree(os.path.join(TestModuleBinFolder, "temp"), ReportPath) + elif SysType == "Linux": + try: + if "LIBFUZZER" in TestModuleBinFolder: + genLLVMReports = GenLLVMReport(TestModuleBinPath, ReportPath) + genLLVMReports.gen_reports() + print("Please view code coverage report in " + "{}".format(ReportPath)) + return + elif "CLANG8" in TestModuleBinFolder: + GcovToolPath = os.path.join(WORK_DIR, 'llvm-gcov.sh') + if not os.path.exists(GcovToolPath): + CreateGcovTool(GcovToolPath) + run_command = \ + "lcov --capture --directory " + \ + "{} --gcov-tool ".format(TestModuleBinFolder) + \ + "{} ".format(GcovToolPath) + \ + "--output-file coverage.info" + try: + subprocess.run(run_command.split(' '), shell=False, + check=True) + except subprocess.CalledProcessError as err: + print(err) + os.remove(GcovToolPath) + os.remove(GcovToolPath) + else: + run_command = \ + "lcov --capture --directory " + \ + "{} ".format(TestModuleBinFolder) + \ + "--output-file coverage.info" + try: + subprocess.run(run_command.split(' '), shell=False, + check=True) + except subprocess.CalledProcessError as err: + print(err) + run_command = \ + "lcov -r coverage.info '*UefiHostTestPkg*' " + \ + "--output-file " + \ + "coverage.info" + try: + subprocess.run(run_command.split(' '), shell=False, + check=True) + except subprocess.CalledProcessError as err: + print(err) + except Exception as err: + print(err) + try: + run_command = \ + "genhtml coverage.info --output-directory " + \ + "{}".format(ReportPath) + try: + subprocess.run(run_command.split(' '), shell=False, + check=True) + except subprocess.CalledProcessError as err: + print(err) + os.remove('coverage.info') + os.remove('coverage.info') + except Exception as err: + print(err) + + print("Please view code coverage report in {}".format(ReportPath)) + return + + +# Parse command line options +def MyOptionParser(): + Parser = argparse.ArgumentParser() + Parser.add_argument("-e", "--execbinary", dest="ModuleBin", + help="Test module binary file name.") + Parser.add_argument("-d", "--dir", dest="SeedPath", + help="Test output seed directory path.") + Parser.add_argument("-t", "--testini", dest="TestIniPath", + help="Test ini files path for ErrorInjection, " + "only for ErrorInjection.") + Parser.add_argument("-r", "--report", dest="ReportPath", + help="Generated code coverage report path.") + + args = Parser.parse_args(sys.argv[1:]) + return args + + +def main(): + Option = MyOptionParser() + + CheckTestEnv() + + if not Option.ModuleBin: + print("Test module binary path should be set once by command -e " + "MODULEBIN, --execbinary=MODULEBIN.") + os._exit(0) + elif not os.path.exists(Option.ModuleBin): + print("Test module binary path: " + "{} does not exist.".format(os.path.abspath(Option.ModuleBin))) + os._exit(0) + else: + ModuleBinPath = Option.ModuleBin + + if not Option.ReportPath: + ReportPath = os.path.join(WORK_DIR, 'CodeCoverageReport') + elif os.path.isabs(Option.ReportPath): + ReportPath = os.path.join(Option.ReportPath, 'CodeCoverageReport') + elif not os.path.isabs(Option.ReportPath): + ReportPath = os.path.join(WORK_DIR, Option.ReportPath, + 'CodeCoverageReport') + else: + print("Please check the input report path.") + os._exit(0) + + if "CLANG8" not in ModuleBinPath: + if not Option.SeedPath: + print("Test output seed directory path should be set once by " + "command -d SEEDPATH, --dir=SEEDPATH.") + os._exit(0) + elif not os.path.exists(Option.SeedPath): + print("Test output seed directory path:" + + "{} ".format(os.path.abspath(Option.SeedPath)) + + "does not exist.") + os._exit(0) + else: + OutputSeedPath = Option.SeedPath + + if not Option.TestIniPath: + TestIniPath = "" + elif not os.path.exists(Option.TestIniPath): + print("Test ini path:" + + "{}".format(os.path.abspath(Option.TestIniPath)) + + " does not exist.") + os._exit(0) + elif not HasIni(Option.TestIniPath): + print("No .ini file in {}".format(Option.TestIniPath)) + os._exit(0) + else: + TestIniPath = Option.TestIniPath + + if SysType == "Linux": + # delete .gcda files before collect code coverage + delete_gcda_file(ModuleBinPath) + + # Run binary with all seeds + Run_All_Seeds(ModuleBinPath, OutputSeedPath, TestIniPath) + + # Generate Code coverage report + GenCodeCoverage(ModuleBinPath, ReportPath) + + +if __name__ == "__main__": + main() diff --git a/HBFA/UefiHostTestTools/Report/GenGdbHtmlReport.py b/HBFA/UefiHostTestTools/Report/GenGdbHtmlReport.py new file mode 100644 index 0000000..7867c53 --- /dev/null +++ b/HBFA/UefiHostTestTools/Report/GenGdbHtmlReport.py @@ -0,0 +1,199 @@ +# @file +# Transfer report.log file into HTML file +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + + +import datetime +import os +import re + +try: + import ConfigParser as ConfigParser +except Exception: + import configparser as ConfigParser + +# report template folder +TemplatePath = os.path.dirname(os.path.realpath(__file__)) + + +class GenGdbHtmlReport(object): + def __init__(self, cfgPath, outputPath, Item): + self.__cfgPath = cfgPath + self.__Item = Item + self.__oldPathFile = os.path.join(TemplatePath, "IndexTemplate.html") + self.__newPathFile = \ + os.path.join(outputPath, + "IndexTemplate.html".replace( + 'Template', self.__Item.capitalize() + if self.__Item else 'Gdb'.capitalize())) + + def __Str2HyperLink(self, oldStr, link): + return oldStr.replace(link, '%s' % (link, link)) \ + if len(link.split('/' if '/' in link else '\\')) > 1 else oldStr + + def __ParseFailure(self, oriInfo): + filePath = "--" + lineNum = "--" + errorMessage = "--" + + stackInfo = oriInfo.split('\n') + InfoList = [fn for fn in stackInfo if fn] + + startPos = 0 + for index in range(len(InfoList)): + if "Program" in InfoList[index]: + startPos = index + errorMessage = InfoList[startPos] + break + + for index in range(startPos, len(InfoList)): + Info = InfoList[index] + if "#0" not in Info: + if " at " in Info: + patten = re.compile(r'/.*.c') + obj = patten.findall(Info) + if len(obj) != 0: + lineNum = \ + Info.split(':')[-1] if Info.split(':')[-1] \ + else "--" + filePath = obj[0] + break + elif " from " in Info: + lineNum = "--" + filePath = Info.split(' from ')[-1] + break + elif " in " in Info: + lineNum = "--" + filePath = Info.split(' in ')[-1] + break + + for index in range(len(InfoList)): + if " at " in InfoList[index]: + patten = re.compile(r'/.*.c') + obj = patten.findall(InfoList[index]) + if len(obj) != 0: + InfoList[index] = \ + self.__Str2HyperLink(InfoList[index], obj[0]) + elif " from " in InfoList[index]: + InfoList[index] = \ + self.__Str2HyperLink(InfoList[index], + InfoList[index].split(' from ')[-1]) + elif " in " in InfoList[index]: + InfoList[index] = \ + self.__Str2HyperLink(InfoList[index], + InfoList[index].split(' in ')[-1]) + InfoList[index] = InfoList[index] + '

' + + stackInfo = "".join(InfoList) if InfoList else "--" + return filePath, lineNum, errorMessage, stackInfo + + def __ContentTable(self): + file = open(self.__oldPathFile, "r") + lines = file.readlines() + file.close() + for i, line in enumerate(lines): + if "" in line: + self.__content_start = i + if '' in line: + self.__content_end = i + return lines[self.__content_start + 1: self.__content_end] + + def __InsertContent(self): + cfg = ConfigParser.ConfigParser() + cfg.read(self.__cfgPath) + sections = cfg.sections() + + # if not self.__Item: + # for index, section in enumerate(sections): + # if "no stack" in cfg.get(section, "stackinfo").lower(): + # sections.pop(index) + # sections.append(section) + + failNum = len(sections) + + file = open(self.__oldPathFile, "r") + fileData = file.readlines() + file.close() + date = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + + itemDetail = "crashes'" if self.__Item.lower() == 'crashes' \ + else ("hangs'" if self.__Item.lower() == 'hangs' else "failures'") + itemNum = "Crash" if self.__Item.lower() == 'crashes' \ + else ("Hang" if self.__Item.lower() == 'hangs' else 'Failure') + + if (self.__Item.lower() in ['crashes', 'hangs']): + testMethod = "AFL" + elif (self.__Item): + testMethod = "libFuzzer" + else: + print("[!] Unexpected testMethod") + exit(1) + for i, line in enumerate(fileData): + if '$itemDetail' in fileData[i]: + fileData[i] = fileData[i].replace('$itemDetail', itemDetail) + if '$testMethod' in fileData[i]: + fileData[i] = fileData[i].replace('$testMethod', testMethod) + if '$itemNum' in fileData[i]: + fileData[i] = fileData[i].replace('$itemNum', itemNum) + if '$Date' in fileData[i]: + fileData[i] = fileData[i].replace('$Date', date) + if '$failNum' in fileData[i]: + fileData[i] = fileData[i].replace('$failNum', str(failNum)) + break + + contentTemplate = self.__ContentTable() + contentList = [] + + for section in sections: + info = cfg.get(section, 'stackinfo') + TotalSeedNum = cfg.get(section, 'totalseedsnum') + failType = section + filePath, lineNum, errorMessage, stackInfo = \ + self.__ParseFailure(info) + for line in contentTemplate: + if '$failure' in line: + line = \ + line.replace('$failure', + os.path.basename(failType).split(',')[0] + if self.__Item + else ('--' if errorMessage == '--' else + os.path.dirname(failType.split( + os.path.dirname( + os.path.dirname( + os.path.dirname(failType))) + + ('/' if '/' in failType + else '\\'))[-1]))) + if '$seedsPath' in line: + line = line.replace('$seedsPath', + os.path.dirname(failType)) + if '$seedsNum' in line: + line = line.replace('$seedsNum', TotalSeedNum) + if '$filePath' in line: + if len(filePath.split('/' if '/' in filePath else '\\')) \ + > 1: + line = \ + line.replace('$filePath', filePath).replace( + '$fileName', os.path.basename(filePath)) + else: + line = line.replace( + '$fileName', + os.path.basename(filePath)) + if '$lineNum' in line: + line = line.replace('$lineNum', lineNum) + if '$error' in line: + line = line.replace('$error', errorMessage) + if '$stack' in line: + line = line.replace('$stack', stackInfo) + contentList.append(line) + fileData[self.__content_start:self.__content_end] = contentList + + s = ''.join(fileData) + file = open(self.__newPathFile, "w") + file.write(s) + file.close() + + def GenerateHtml(self): + self.__InsertContent() diff --git a/HBFA/UefiHostTestTools/Report/GenGdbInfo.py b/HBFA/UefiHostTestTools/Report/GenGdbInfo.py new file mode 100644 index 0000000..b1deda8 --- /dev/null +++ b/HBFA/UefiHostTestTools/Report/GenGdbInfo.py @@ -0,0 +1,208 @@ +# @file +# Transfer report.log file into HTML file +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +import os +import subprocess +import time +import sys +import re +try: + import ConfigParser as ConfigParser +except Exception: + import configparser as ConfigParser + +# python version +python_version = sys.version_info[0] + + +class GenGdbInfo(object): + def __init__(self, execFile, cfgPath): + self.__execFile = execFile + self.__cfgPath = cfgPath + self.__logPath = os.path.splitext(cfgPath)[0] + ".log" + self.__infoList = [] + + def __CompareList(self, list1, list2): + """ + :param list1: [] + :param list2: [] + """ + if len(list1) != len(list2): + return False + for index in range(len(list1)): + if list1[index] != list2[index]: + return False + return True + + def __GenerateCommand(self, file): + """ + :param file: str + """ + Template = "timeout 0.5s \'\' \'\'; " + \ + "if [ $? -eq 124 ]; then cp \'\' /tmp/uefi_hang && " + \ + "( gdb -batch -ex run -ex bt --args /tmp/uefi_hang \'\'" + \ + " & ) && sleep 0.5 && pkill uefi_hang && sleep 0.5 && " + \ + "rm -rf /tmp/uefi_hang; else (gdb -batch -ex run -ex bt " + \ + "--args \'\' \'\'); fi;" + CommandLine = \ + Template.replace("", + self.__execFile + ).replace("", file + ).replace("", + os.path.basename( + self.__execFile)) + return CommandLine + + def __CallCommand(self, CommandLine): + """ + :param CommandLine: str + """ + Cm = subprocess.Popen(CommandLine, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + shell=False) + msg = list(Cm.communicate()) + return msg if python_version == 2 else \ + (msg[0].decode() if msg[0] else msg[0], + msg[1].decode() if msg[1] else msg[1]) + + def __GetKeyInfo(self, oriInfo): + """ + :param oriInfo: output from subprocess ('','') + """ + if "No stack" in oriInfo[-1]: + InfoList = oriInfo[-1].split('\n') + InfoList = [fn for fn in InfoList if fn] + else: + InfoList = oriInfo[0].split('\n') + InfoList = [fn for fn in InfoList if fn] + + DetailInfo = [] + for index in range(len(InfoList)): + if "Program" in InfoList[index]: + DetailInfo.append(InfoList[index]) + if "#" in InfoList[index]: + if " at " in InfoList[index]: + patten = re.compile(r'/.*.c') + obj = patten.findall(InfoList[index]) + if len(obj) != 0: + DetailInfo.append(obj[0] + + InfoList[index].split(obj[0])[-1] + ) + elif " from " in InfoList[index]: + DetailInfo.append(InfoList[index].split('from ')[-1]) + else: + DetailInfo.append(InfoList[index].split(' in ')[-1]) + InfoList = DetailInfo + return InfoList + + def __FilterInfoToCfg(self, newInfo, filterSwitch): + """ + :param newInfo: [seedName, InfoList] + :param filterSwitch: True False + """ + seedName = newInfo[0] + InfoList = newInfo[-1] + newStack = self.__GetKeyInfo(InfoList) + configPath = self.__cfgPath + + cfg = ConfigParser.ConfigParser() + cfg.read(configPath) + searchFlag = False + if filterSwitch: + if 'no stack' in newStack[-1].lower(): + searchFlag = True + else: + for section in cfg.sections(): + oldStack = cfg.get(section, 'stackinfo') + oldStack = self.__GetKeyInfo([oldStack]) + if self.__CompareList(newStack, oldStack): + searchFlag = True + cfg.set(section, 'TotalSeedsNum', + int(cfg.get(section, 'TotalSeedsNum')) + 1) + break + if not searchFlag: + cfg.add_section(seedName) + if 'no stack' in newStack[-1].lower(): + cfg.set(seedName, 'stackinfo', InfoList[-1]) + else: + cfg.set(seedName, 'stackinfo', InfoList[0]) + cfg.set(seedName, 'TotalSeedsNum', 1) + self.__infoList = [] + for section in cfg.sections(): + self.__infoList.append((time.asctime( + time.localtime(os.path.getmtime(section))), + section, + cfg.get(section, 'stackinfo'))) + cfg.write(open(configPath, 'w')) + + def __ClearRedundantInfo(self, oriInfo): + """ + :param oriInfo: output from subprocess ('','') + """ + InfoList = oriInfo[0].split('\n') + InfoList = [fn for fn in InfoList if fn] + Pos = 0 + for index in range(len(InfoList)): + if "Program" in InfoList[index]: + Pos = index + break + if Pos > 100: + InfoList = InfoList[Pos-100:] + oriInfoNew = ('\n'.join(InfoList), oriInfo[-1]) + return oriInfoNew + + def __UpdateInfoList(self, newInputList, filterSwitch): + """ + :param newInputList: [] + :param filterSwitch: True False + """ + for newInput in newInputList: + if os.path.isfile(newInput): + errorInfo = \ + self.__CallCommand(self.__GenerateCommand(newInput)) + errorInfo = self.__ClearRedundantInfo(errorInfo) + self.__FilterInfoToCfg([newInput, errorInfo], filterSwitch) + if filterSwitch: + self.__GenereteInfoFile( + [(time.asctime(time.localtime( + os.path.getmtime(newInput))), + newInput, + errorInfo)], + os.path.join(os.path.dirname(newInput), + os.path.basename(self.__logPath))) + else: + self.__GenereteInfoFile(self.__infoList, self.__logPath) + + def __GenereteInfoFile(self, infoList, infoPath): + """ + :param infoList: [] + :param infoPath: str + """ + info = "Processing \'%s\' :\n\n" % (self.__execFile) + for index in range(len(infoList)): + info += "------------------------------------------------" + \ + "------------\n" + info += "%s\n\'%s/%s/%s\' :\n" % \ + (infoList[index][0], + infoList[index][1].replace('\\', '/').split('/')[-3], + infoList[index][1].replace('\\', '/').split('/')[-2], + infoList[index][1].replace('\\', '/').split('/')[-1]) + for msg in infoList[index][2]: + info += "%s" % msg + info += '\n\n' + output = open(infoPath, 'w+') + output.writelines(info) + output.close() + + def Run(self, newInput, filterSwitch): + """ + :param newInput: [] + :param filterSwitch: True False + """ + self.__UpdateInfoList(newInput, filterSwitch) diff --git a/HBFA/UefiHostTestTools/Report/GenLLVMReport.py b/HBFA/UefiHostTestTools/Report/GenLLVMReport.py new file mode 100644 index 0000000..a7d8092 --- /dev/null +++ b/HBFA/UefiHostTestTools/Report/GenLLVMReport.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +import os +import sys +import subprocess +import re + + +class GenLLVMReport(object): + """A tool help streamline generation and collection of LLVM coverage \ + reports for the HBFA tool-suite.""" + def __init__(self, module_binary, report_path): + self.log_file = None + if self.validate_path_pattern(module_binary): + self.module_binary = module_binary + else: + print("[!] 'module_binary' path not valid: " + "{}".format(module_binary)) + sys.exit(1) + if self.validate_path_pattern(report_path): + self.report_base_path = report_path + else: + print("[!] Report path provided to GenLLVMReport not valid:" + " {}".format(report_path)) + sys.exit(1) + self.module_name = os.path.split(self.module_binary)[-1] + self.profraw_file = os.getenv('LLVM_PROFILE_FILE') + if not os.path.exists(self.profraw_file): + print("[!] Profraw file not found [self.profraw]") + sys.exit(1) + + def validate_path_pattern(self, path_uri): + """ + Apply a simple regex to sanity-check if a directory path URI is + valid + """ + regex_dir_pattern = re.compile('^(/[^/ ]*)+/?$') + return regex_dir_pattern.match(path_uri) + + def check_create_dir(self, dir_name): + """Check if a directory exists, if not then create it.""" + if not os.path.isdir(dir_name): + try: + os.makedirs(dir_name) + except OSError as error_msg: + print("[!] Error when attempting to create directory:" + " {}".format(error_msg)) + sys.exit(1) + + def run_command(self, command): + """Run a Linux OS command and return output.""" + try: + proc = subprocess.Popen(command.split(' '), + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + shell=False) + msg = list(proc.communicate()) + except OSError as error: + print("Exception encountered: {}".format(error)) + sys.exit(1) + return msg + + def gen_reports(self): + """Leverage llvm-profdata and llvm-cov tools to create reports.""" + self.check_create_dir(self.report_base_path) + working_dir = self.report_base_path + '/llvm_coverage_report' + self.check_create_dir(working_dir) + commands = [ + 'llvm-profdata merge -sparse ' + self.profraw_file + ' -o ' + + working_dir + '/default.profdata', + 'llvm-cov show --output-dir=' + working_dir + + ' ' + self.module_binary + ' -instr-profile=' + + working_dir + '/default.profdata -format=html', + 'llvm-cov show --output-dir=' + working_dir + + ' ' + self.module_binary + ' -instr-profile=' + + working_dir + '/default.profdata' + ] + + for command in commands: + msg = self.run_command(command) + print(command) + print(msg) diff --git a/HBFA/UefiHostTestTools/Report/GenSanitizerHtmlReport.py b/HBFA/UefiHostTestTools/Report/GenSanitizerHtmlReport.py new file mode 100644 index 0000000..30b394f --- /dev/null +++ b/HBFA/UefiHostTestTools/Report/GenSanitizerHtmlReport.py @@ -0,0 +1,301 @@ +# @file +# Transfer report.log file into HTML file +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + + +import datetime +import os +import re +try: + import ConfigParser as ConfigParser +except Exception: + import configparser as ConfigParser + + +class GenSanitizerHtmlReport(object): + def __init__(self, reportLogPath, item, outputPath): + self.__reportLogPath = reportLogPath + self.__oldPath = os.path.dirname(os.path.realpath(__file__)) + self.__classification = item + if ( + self.__classification == 'crashes' or + self.__classification == 'hangs' + ): + self.testMethod = 'AFL' + else: + self.testMethod = 'libFuzzer' + self.__oldPathFile = os.path.join(self.__oldPath, "IndexTemplate.html") + self.__newPathFile = os.path.join(outputPath, "IndexSanitizer.html") + self.__cfg = ConfigParser.ConfigParser() + self.__lcfg = ConfigParser.ConfigParser() + self.__AddressSanitizerLog = os.path.join(self.__reportLogPath, + 'AddressSanitizer.cfg') + self.__LeakSanitizerLog = os.path.join(self.__reportLogPath, + 'LeakSanitizer.cfg') + + def __GetContentsInfo(self, contents): + contents_list = contents.split('\n') + error_message = '--' + for content in contents_list: + match1 = re.search(r'ERROR: AddressSanitizer: (\S)+', content) + if match1: + error_message = match1.group(0) + elif 'ERROR: AddressSanitizer' in content: + error_message = content.split('==')[-1] + match2 = re.search(r'#0 0x(.)+', content) + if match2: + FilePath = match2.group().split(' ')[-1] + LineNum = FilePath.replace(':\\', '\\').split(':')[1] + FileName = \ + os.path.basename( + FilePath.replace(':\\', '\\').split(':')[0]) + TmpLink = \ + FilePath.replace(':\\', '\\').split(':')[0].split('\\') + TmpLink[0] = TmpLink[0].replace(TmpLink[0], TmpLink[0] + ':') \ + if len(TmpLink) > 1 else TmpLink[0] + FileLink = '\\'.join(TmpLink) + if 'allocated by' in content or re.search(r'Address 0x(\w)+ is ' + r'located in', content): + break + return FileName, FileLink, LineNum, error_message + + def __GetLContentsInfo(self, contents): + contents_list = contents.split('\n') + error_message = '--' + for content in contents_list: + match1 = re.search('ERROR: LeakSanitizer: (.)+', content) + if match1: + error_message = match1.group(0) + match2 = re.search(r'#0 0x(.)+', content) + if match2: + FilePath = match2.group().split(' ')[-1] + LineNum = FilePath.replace(':\\', '\\').split(':')[1] + FileName = \ + os.path.basename( + FilePath.replace(':\\', '\\').split(':')[0]) + TmpLink = \ + FilePath.replace(':\\', '\\').split(':')[0].split('\\') + TmpLink[0] = TmpLink[0].replace(TmpLink[0], TmpLink[0] + ':') \ + if len(TmpLink) > 1 else TmpLink[0] + FileLink = '\\'.join(TmpLink) + break + return FileName, FileLink, LineNum, error_message + + def __GetContentTable(self): + file = open(self.__oldPathFile, "r") + lines = file.readlines() + file.close() + for i, line in enumerate(lines): + if "" in line: + self.__content_start = i + if '' in line: + self.__content_end = i + return lines[self.__content_start + 1: self.__content_end] + + def __InsertContent(self, insertElem, failNum): + file = open(self.__oldPathFile, "r") + fileData = file.readlines() + file.close() + date = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + for i, line in enumerate(fileData): + if '$Date' in line: + line = line.replace(line, '%s' + % date) + fileData[i] = line + if '$itemDetail' in line: + line = line.replace('$itemDetail', "failures'") + fileData[i] = line + if '$testMethod' in line: + line = line.replace('$testMethod', self.testMethod) + fileData[i] = line + if '$itemNum' in line: + line = line.replace('$itemNum', 'Failure Type') + fileData[i] = line + if '$failNum' in line: + line = line.replace(line, '%s' + % failNum) + fileData[i] = line + break + fileData[self.__content_start:self.__content_end] = insertElem + + s = ''.join(fileData) + file = open(self.__newPathFile, "w") + file.write(s) + file.close() + + def GenHtml(self): + afailNum = 0 + lfailNum = 0 + new_list = [] + contents = self.__GetContentTable() + if os.path.exists(self.__AddressSanitizerLog): + self.__cfg.read(self.__AddressSanitizerLog) + sections = self.__cfg.sections() + for item in sections: + amatch = re.search(r'number(\d)+_AddressSanitizer', item) + lmatch = re.search(r'number(\d)+_LeakSanitizer', item) + if (not amatch) and (not lmatch): + seedsPath = os.path.dirname(item) + if self.__classification != '': + if os.path.basename(seedsPath) in ['crashes', 'hangs']: + failType = os.path.join( + os.path.basename(seedsPath), + os.path.basename(item).split(',')[0]) + else: + failType = os.path.basename(item) + else: + failType = \ + os.path.basename(os.path.dirname( + os.path.dirname(item))) + '/' \ + + os.path.basename(os.path.dirname(item)) + else: + print("[!] Unable to match Sanitizer " + "(not AFL or LibFuzzer output)") + exit(1) + section_contents = self.__cfg.get(item, 'stackinfo') + totalseednum = self.__cfg.get(item, 'totalseedsnum') + afailNum = len(sections) + if section_contents != '': + fileName, fileLink, lineNum, errorMessage = \ + self.__GetContentsInfo(section_contents) + stack_info = section_contents.split('\n') + new_stack_info_list = [] + for sline in stack_info: + match = re.search(r'#\d 0x(.)+', sline) + if match: + FilePath = match.group().split(' ')[-1] + a = ' '.join(match.group().split(' ')[:-1]) + TmpLink = \ + FilePath.replace( + ':\\', '\\').split( + ':')[0].split('\\') + TmpLink[0] = \ + TmpLink[0].replace(TmpLink[0], + TmpLink[0] + + ':') \ + if len(TmpLink) > 1 \ + else TmpLink[0] + FileLink = '\\'.join(TmpLink) + if '(' in FileLink: + FileLink = FileLink.lstrip(r'\(') + FileLink = FileLink.rstrip(r'\)') + sline = sline.replace(sline, a + ('' + % FileLink) + + ' ' + FilePath + '') + sline = sline + '
' + new_stack_info_list.append(sline) + new_stack_info = ''.join(new_stack_info_list) + else: + fileName, fileLink, lineNum, errorMessage = \ + '--', '', '--', '--' + new_stack_info = 'No stack' + contents = self.__GetContentTable() + for line in contents: + if '$failure' in line: + line = line.replace('$failure', failType) + if '$filePath' in line: + if fileLink == '': + line = line.replace('', + '').replace('', '') + else: + line = line.replace('$filePath', fileLink) + if '$seedsNum' in line: + line = line.replace('$seedsNum', totalseednum) + if '$seedsPath' in line: + if seedsPath == '': + line = line.replace('', + '').replace('', '') + else: + line = line.replace('$seedsPath', seedsPath) + if '$fileName' in line: + line = line.replace('$fileName', fileName) + if '$lineNum' in line: + line = line.replace('$lineNum', lineNum) + if '$error' in line: + line = line.replace('$error', errorMessage) + if '$stack' in line: + line = line.replace('$stack', new_stack_info) + + new_list.append(line) + + if os.path.exists(self.__LeakSanitizerLog): + self.__lcfg.read(self.__LeakSanitizerLog) + section_names = self.__lcfg.sections() + for item in section_names: + amatch1 = re.search(r'number(\d)+_AddressSanitizer', item) + lmatch1 = re.search(r'number(\d)+_LeakSanitizer', item) + if (not amatch1) and (not lmatch1): + lseedsPath = os.path.dirname(item) + if self.__classification != '': + if os.path.basename(lseedsPath) in ['crashes', + 'hangs']: + lfailType = \ + os.path.join(os.path.basename(lseedsPath), + os.path.basename(item).split(',') + [0]) + else: + lfailType = os.path.basename(item) + else: + lfailType = \ + os.path.basename(os.path.dirname( + os.path.dirname(item))) + '/' + \ + os.path.basename(os.path.dirname(item)) + else: + lfailType = item + lseedsPath = os.path.join(self.__reportLogPath, + 'FailureSeeds', lfailType) + + section_contents = self.__lcfg.get(item, 'stackinfo') + totalseednum = '--' + lfailNum = len(section_names) + lfileName, lfileLink, llineNum, lerrorMessage = \ + self.__GetLContentsInfo(section_contents) + stack_info = section_contents.split('\n') + lnew_stack_info_list = [] + for sline in stack_info: + match = re.search(r'#\d 0x(.)+', sline) + if match: + FilePath = match.group().split(' ')[-1] + a = ' '.join(match.group().split(' ')[:-1]) + LtmpLink = \ + FilePath.replace(':\\', + '\\').split(':')[0].split('\\') + LtmpLink[0] = \ + LtmpLink[0].replace(LtmpLink[0], + LtmpLink[0] + ':') \ + if len(LtmpLink) > 1 else LtmpLink[0] + lfileLink = '\\'.join(LtmpLink) + if '(' in lfileLink: + lfileLink = lfileLink.lstrip(r'\(') + lfileLink = lfileLink.rstrip(r'\)') + sline = sline.replace(sline, a + + ('' % lfileLink) + + ' ' + FilePath + '') + sline = sline + '
' + lnew_stack_info_list.append(sline) + new_stack_info = ''.join(lnew_stack_info_list) + contents = self.__GetContentTable() + for line in contents: + if '$failure' in line: + line = line.replace('$failure', lfailType) + if '$filePath' in line: + line = line.replace('$filePath', lfileLink) + if '$seedsNum' in line: + line = line.replace('$seedsNum', totalseednum) + if '$seedsPath' in line: + line = line.replace('$seedsPath', lseedsPath) + if '$fileName' in line: + line = line.replace('$fileName', lfileName) + if '$lineNum' in line: + line = line.replace('$lineNum', llineNum) + if '$error' in line: + line = line.replace('$error', lerrorMessage) + if '$stack' in line: + line = line.replace('$stack', new_stack_info) + new_list.append(line) + + failNum = afailNum + lfailNum + self.__InsertContent(''.join(new_list), failNum) diff --git a/HBFA/UefiHostTestTools/Report/GenSanitizerInfo.py b/HBFA/UefiHostTestTools/Report/GenSanitizerInfo.py new file mode 100644 index 0000000..9ee376d --- /dev/null +++ b/HBFA/UefiHostTestTools/Report/GenSanitizerInfo.py @@ -0,0 +1,358 @@ +# @file +# Transfer report.log file into HTML file +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +import sys +import subprocess +import os +import time +try: + import ConfigParser as ConfigParser +except Exception: + import configparser as ConfigParser +import re +import argparse + + +class GenSanitizerInfo(object): + + def __init__(self, exefile, inputpath, output, silence=False, item=''): + self.__exefile = exefile + self.__inputpath = inputpath + self.__output_path = output + self.__silence = silence + self.__classification = item + if not os.path.exists(os.path.join(self.__output_path)): + os.makedirs(os.path.join(self.__output_path)) + self.__scfgPath = os.path.join(self.__output_path, + 'AddressSanitizer.cfg') + self.__lcfgPath = os.path.join(self.__output_path, + 'LeakSanitizer.cfg') + + def __CmpList(self, list1, list2): + + if len(list1) == 0 or len(list2) == 0: + return False + for i in list1: + if i not in list2: + return False + for i in list2: + if i not in list1: + return False + return True + + def __CmpLeakList(self, list1, list2): + list1_temp = [] + result_list = [] + for i in list1: + if ( + ' in ' in i and + (('Indirect leak of ') not in i + and ('Direct leak of') not in i) + ): + i = i.split(' in ')[1] + if ('Indirect leak of ') not in i and ('Direct leak of') not in i: + list1_temp.append(i.strip()) + for sublist in list2: + list2_temp = [] + for j in sublist: + if ( + ' in ' in j and (('Indirect leak of ') + not in j and ('Direct leak of') not in j) + ): + j = j.split(' in ')[1] + if ( + ('Indirect leak of ') not in j and ('Direct leak of') + not in j + ): + list2_temp.append(j.strip()) + result = self.__CmpList(list1_temp, list2_temp) + result_list.append(result) + return result_list + + def __UpdateFileNum(self, filepath, keyword): + file_data = "" + with open(filepath, 'r') as f: + for line in f: + if '%s' % keyword in line: + num = line.split(':')[1].strip() + num = int(num) + 1 + line = line.replace(line, '%s:%s\n' % (keyword, str(num))) + file_data += line + with open(filepath, 'w') as f: + f.write(file_data) + return num + + def __UpdateLFileNum(self, filepath, keyword, number): + file_data = "" + with open(filepath, 'r') as f: + for line in f: + if '%s' % keyword in line: + num = line.split(':')[1].strip() + num = int(num) + number + line = line.replace(line, '%s:%s\n' % (keyword, str(num))) + + file_data += line + with open(filepath, 'w') as f: + f.write(file_data) + return num + + def __GetRunTimes(self): + if not os.path.exists(os.path.join(self.__output_path, '.status')): + file = open(os.path.join(self.__output_path, '.status'), 'w+') + time_stamp = time.strftime("%m/%d/%Y %H:%M:%S", + time.localtime(time.time())) + file.write('start_time: %s\n' % time_stamp) + number = 1 + file.write('number:%s\n' % str(number)) + file.close() + else: + number = self.__UpdateFileNum(os.path.join(self.__output_path, + '.status'), 'number') + return number + + def __GetAcompareList(self, contentlines): + new_list = [] + for line in contentlines: + match1 = re.search(r'ERROR: AddressSanitizer: (\S)+', line) + if match1: + error_message = match1.group(0) + new_list.append(error_message) + match2 = re.search(r'#\d 0x(.)+', line) + if match2: + stack_info = \ + match2.group().split(' in ')[1] if \ + ' in ' in line else match2.group().split(' ')[-1] + new_list.append(stack_info) + if ( + 'allocated by' in line or + re.search(r'Address 0x(\w)+ is located in', line) + ): + break + return new_list + + def __GetLcompareList(self, contentlines): + lcompare_word_list = [] + list_key = [] + index = [] + for i, line in enumerate(contentlines): + match1 = re.search('ERROR: LeakSanitizer: (.)+', line) + if match1: + error_message = match1.group(0) + list_key.append(error_message) + if line == '': + index.append(i) + for i in range(1, len(index)): + if i == len(index) - 2: + break + list = contentlines[index[i] + 1:index[i + 1]] + list.insert(0, list_key[0]) + list = [j.strip() + '\n' for j in list] + lcompare_word_list.append(list) + return lcompare_word_list + + def __UpdateAcfg(self, screenlogs, number, inputpath): + errorlog_lines = screenlogs.split('\n') + compare_word_list = self.__GetAcompareList(errorlog_lines) + cfg = ConfigParser.ConfigParser() + cfg.read(self.__scfgPath) + error_list = cfg.sections() + if len(error_list) == 0: + flag = False + file = open(os.path.join(self.__output_path, '.status'), 'a+') + file.write('Atypenum:0\n') + file.write('Atotalnum:1\n') + file.close() + else: + self.__UpdateFileNum(os.path.join(self.__output_path, '.status'), + 'Atotalnum') + for item in error_list: + contents = cfg.get(item, 'stackinfo') + contents_list = contents.split('\n') + to_be_compared_list = self.__GetAcompareList(contents_list) + flag = self.__CmpList(to_be_compared_list, compare_word_list) + if flag is True: + seedsCount = cfg.get(item, 'TotalSeedsNum') + seedsCount = int(seedsCount) + 1 + cfg.set(item, 'TotalSeedsNum', seedsCount) + break + if flag is False and item == error_list[-1]: + self.__UpdateFileNum(os.path.join(self.__output_path, + '.status'), + 'Atypenum') + + if flag is not True: + item = inputpath + if item not in cfg.sections(): + cfg.add_section(item) + cfg.set(item, 'stackInfo', screenlogs) + seedsCount = 1 + cfg.set(item, 'TotalSeedsNum', seedsCount) + + error_list = cfg.sections() + if not self.__silence: + print('there are %s type errors,and they are : %s' + % (len(error_list), error_list)) + cfg.write(open(self.__scfgPath, "w")) + + def __UpdateLcfg(self, screenlogs, number, inputpath): + errorlog_lines = screenlogs.split('\n') + lcompare_word_list = self.__GetLcompareList(errorlog_lines) + cfg = ConfigParser.ConfigParser() + cfg.read(self.__lcfgPath) + error_list = cfg.sections() + if len(error_list) == 0: + flag = False + Ltypenum = 0 + file = open(os.path.join(self.__output_path, '.status'), 'a+') + file.write('Ltypenum:0\n') + file.write('Ltotalnum:1\n') + file.close() + else: + self.__UpdateFileNum(os.path.join(self.__output_path, + '.status'), 'Ltotalnum') + compare_result_list = [] + all_result_list = [] + for item in error_list: + to_be_compared_contents = cfg.get(item, 'stackinfo') + to_be_compared_list = to_be_compared_contents.split('\n') + flag = self.__CmpLeakList(to_be_compared_list, + lcompare_word_list) + compare_result_list.append(flag) + + for i in range(len(compare_result_list[0])): + column_list = [] + for j in range(len(compare_result_list)): + column_list.append(compare_result_list[j][i]) + + all_result_list.append(column_list) + for i, result in enumerate(all_result_list): + if True not in result: + Ltypenum = \ + self.__UpdateFileNum(os.path.join(self.__output_path, + '.status'), + 'Ltypenum') + item = 'number' + str(Ltypenum) + '_' + 'LeakSanitizer' + if item not in cfg.sections(): + cfg.add_section(item) + stackinfo = ''.join(lcompare_word_list[i]) + if not self.__silence: + print('NEW DIFFERENT STACK INFO: \n%s' % stackinfo) + cfg.set(item, 'stackInfo', stackinfo) + cfg.set(item, 'filepath', os.path.dirname(inputpath)) + + if flag is False: + Ltypenum = len(lcompare_word_list) + self.__UpdateLFileNum(os.path.join(self.__output_path, '.status'), + 'Ltypenum', Ltypenum) + for i in range(0, len(lcompare_word_list)): + Ltypenum = i + 1 + item = 'number' + str(Ltypenum) + '_' + 'LeakSanitizer' + if item not in cfg.sections(): + cfg.add_section(item) + stackinfo = ''.join(lcompare_word_list[i]) + cfg.set(item, 'stackInfo', stackinfo) + cfg.set(item, 'filepath', os.path.dirname(inputpath)) + cfg.write(open(self.__lcfgPath, "w")) + + def __GenSanitizerInfo(self, inputpath): + number = str(self.__GetRunTimes()) + command = [self.__exefile, inputpath] + ret = subprocess.Popen(command, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, shell=False) + error_logs = list(ret.communicate()) + if sys.version_info[0] == 3: + for num, submsg in enumerate(error_logs): + if submsg is not None: + error_logs[num] = submsg.decode() + if not self.__silence: + print(error_logs[0]) + print(error_logs[1]) + + logfile = os.path.splitext(inputpath)[0] + '.HBFA.Sanitizer.log' + error_logs_file = open(logfile, 'w+') + error_logs_file.write("{}\n{}".format(error_logs[0] if + error_logs[0] else '', + error_logs[1] if + error_logs[1] else '')) + error_logs_file.close() + + if 'ERROR: AddressSanitizer' in error_logs[0]: + self.__UpdateAcfg(error_logs[0], number, inputpath) + elif 'ERROR: LeakSanitizer:' in error_logs[0]: + self.__UpdateLcfg(error_logs[0], number, inputpath) + + def __GenAFLSanitizerInfo(self, inputpath): + command = [self.__exefile, inputpath] + ret = subprocess.Popen(command, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, shell=False) + error_logs = list(ret.communicate()) + if sys.version_info[0] == 3: + for num, submsg in enumerate(error_logs): + if submsg is not None: + error_logs[num] = submsg.decode() + if not self.__silence: + print(error_logs[0]) + print(error_logs[1]) + + logfile = os.path.join(self.__output_path, 'HBFA.Sanitizer.log') + error_logs_file = open(logfile, 'a+') + error_logs_file.write("{}\n{}".format(error_logs[0] if + error_logs[0] else '', + error_logs[1] if + error_logs[1] else '')) + error_logs_file.close() + item = inputpath + if 'ERROR: AddressSanitizer' in error_logs[0] or error_logs[0] == '': + cfg = ConfigParser.ConfigParser() + cfg.read(self.__scfgPath) + cfg.add_section(item) + cfg.set(item, 'stackInfo', error_logs[0]) + TotalSeedsNum = 1 + cfg.set(item, 'TotalSeedsNum', TotalSeedsNum) + cfg.write(open(self.__scfgPath, "w")) + elif 'ERROR: LeakSanitizer:' in error_logs[0]: + cfg = ConfigParser.ConfigParser() + cfg.read(self.__lcfgPath) + cfg.add_section(item) + cfg.set(item, 'stackInfo', error_logs[0]) + TotalSeedsNum = 1 + cfg.set(item, 'TotalSeedsNum', TotalSeedsNum) + cfg.write(open(self.__lcfgPath, "w")) + + def Run(self): + if type(self.__inputpath) is list and len(self.__inputpath) != 0: + for seedpath in self.__inputpath: + if self.__classification == '': + self.__GenSanitizerInfo(seedpath) + else: + self.__GenAFLSanitizerInfo(seedpath) + else: + if not self.__silence: + print('please verify input seeds exist') + + +if __name__ == "__main__": + parse = argparse.ArgumentParser() + parse.add_argument("-e", dest="execute", help="executable file path") + parse.add_argument("-i", dest="input", help="seed name") + parse.add_argument("-o", dest="output", help="sanitizer output log path") + parse.add_argument("-s", dest="silence", help="silence", default=False) + parse.add_argument("-t", dest="item", help="item", default='') + + options = parse.parse_args(sys.argv[1:]) + if options.execute: + if options.input: + if options.output: + genSInfo = GenSanitizerInfo(options.execute, options.input, + options.output, False, '') + genSInfo.Run() + else: + raise Exception("Plesase input -o output path.") + else: + raise Exception("Plesase input -i input seed name.") + else: + raise Exception("Please input -e executable file you use.") diff --git a/HBFA/UefiHostTestTools/Report/GenSummaryInfo.py b/HBFA/UefiHostTestTools/Report/GenSummaryInfo.py new file mode 100644 index 0000000..a373911 --- /dev/null +++ b/HBFA/UefiHostTestTools/Report/GenSummaryInfo.py @@ -0,0 +1,177 @@ +# @file +# Transfer report.log file into HTML file +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + + +import os +import sys +try: + import ConfigParser as ConfigParser +except Exception: + import configparser as ConfigParser +import datetime +import time +import argparse + + +class GenSummaryInfo(object): + def __init__(self, inputSeedsPath, debugReportPath, methods, + reportType, silence): + self.__afcfg = os.path.join(debugReportPath, + 'AddressSanitizer.cfg') + self.__lcfg = os.path.join(debugReportPath, + 'LeakSanitizer.cfg') + self.__gdbcfg = os.path.join(debugReportPath, + 'HBFA.GDB.cfg') + self.__afl_gdbCrashcfg = os.path.join(debugReportPath, + 'HBFA.GDB.Crashes.cfg') + self.__afl_gdbHangcfg = os.path.join(debugReportPath, + 'HBFA.GDB.Hangs.cfg') + self.__inputPath = inputSeedsPath + self.__debugReportPath = debugReportPath + self.__methods = methods + self.__reportType = reportType + self.__silence = silence + + def __GetFailedTypeNum(self, logPath): + fail_num = 0 + if os.path.exists(logPath): + cfg = ConfigParser.ConfigParser() + cfg.read(logPath) + sections = cfg.sections() + fail_num = len(sections) + return fail_num + + def __GetCfgSeedsNum(self, logPath): + fail_num = 0 + if os.path.exists(logPath): + cfg = ConfigParser.ConfigParser() + cfg.read(logPath) + sections = cfg.sections() + for section in sections: + fail_num = fail_num + int(cfg.get(section, 'totalseedsnum')) + return fail_num + + def __GetSanitizerlNum(self, keyword, statuspath): + num = 0 + if os.path.exists(os.path.join(statuspath, '.status')): + with open(os.path.join(statuspath, '.status'), 'r') as f: + for line in f: + if keyword in line: + num = int(line.split(':')[1].strip()) + return num + + def __GetSanitizerlTime(self, statuspath): + if os.path.exists(os.path.join(statuspath, '.status')): + with open(os.path.join(statuspath, '.status'), 'r') as f: + for line in f: + if 'start_time' in line: + starttime = line.split(': ')[1].strip() + starttime = datetime.datetime.strptime( + starttime, '%m/%d/%Y %H:%M:%S') + break + endtime = time.localtime(os.path.getmtime(os.path.join(statuspath, + '.status'))) + endtime = time.strftime('%m/%d/%Y %H:%M:%S', endtime) + endtime = datetime.datetime.strptime(endtime, '%m/%d/%Y %H:%M:%S') + execTime = endtime - starttime + return execTime + + def __getAFLTotalSeeds(self): + num = 0 + if os.path.exists(os.path.join(self.__inputPath, 'fuzzer_stats')): + with ( + open(os.path.join(self.__inputPath, 'fuzzer_stats'), 'r') as f + ): + for line in f: + if 'execs_done' in line: + num = int(line.split(':')[-1].strip()) + return num + + def __GetAFLExecTime(self): + if os.path.exists(os.path.join(self.__inputPath, 'plot_data')): + with open(os.path.join(self.__inputPath, 'plot_data'), 'r') as f: + lines = f.readlines() + f.close() + if len(lines) > 1: + line_last = lines[-1] + time_start = int(lines[1].split(',')[0]) + time_start = time.strftime('%m/%d/%Y %H:%M:%S', + time.localtime(time_start)) + time_start = \ + datetime.datetime.strptime(time_start, + '%m/%d/%Y %H:%M:%S') + time_end = int(line_last.split(',')[0]) + time_end = time.strftime('%m/%d/%Y %H:%M:%S', + time.localtime(time_end)) + time_end = datetime.datetime.strptime(time_end, + '%m/%d/%Y %H:%M:%S') + execution_time = time_end - time_start + return execution_time + else: + return 0 + + def GenSumInfo(self): + if self.__methods.lower() == 'afl': + + if self.__reportType == "gdb": + crashNum = self.__GetFailedTypeNum(self.__afl_gdbCrashcfg) + hangNum = self.__GetFailedTypeNum(self.__afl_gdbHangcfg) + failNum = crashNum, hangNum + elif self.__reportType == "sanitizer": + AddressFailedNum = self.__GetFailedTypeNum(self.__acfg) + LeakFailedNum = self.__GetFailedTypeNum(self.__lcfg) + failNum = AddressFailedNum + LeakFailedNum + totalNum = self.__getAFLTotalSeeds() + execTime = self.__GetAFLExecTime() + + else: + if self.__reportType == "gdb": + failNum = self.__GetFailedTypeNum(self.__gdbcfg) + elif self.__reportType == "sanitizer": + AddressFailedNum = self.__GetFailedTypeNum(self.__afcfg) + LeakFailedNum = self.__GetFailedTypeNum(self.__lcfg) + failNum = AddressFailedNum + LeakFailedNum + totalNum = len(os.listdir(self.__inputPath)) + execTime = '--:--:--' + if not self.__silence: + print(str(totalNum) + ';' + str(failNum) + ';' + str(execTime)) + return totalNum, failNum, execTime + + +if __name__ == "__main__": + + parse = argparse.ArgumentParser() + parse.add_argument("-i", dest="input", help="seeds output path") + parse.add_argument("-o", dest="output", help="report output path") + parse.add_argument("-m", dest="method", + choices=['afl', 'libfuzzer'], + default="afl", help="test method") + parse.add_argument("-t", dest="reportType", + choices=['gdb', 'sanitizer'], default="gdb", + help="report type") + parse.add_argument("-s", dest="silence", help="silence") + options = parse.parse_args(sys.argv[1:]) + + if options.input: + if options.output: + if options.method: + if options.reportType: + genSInfo = GenSummaryInfo(options.input, options.output, + options.method, + options.reportType, + options.silence) + genSInfo.GenSumInfo() + else: + raise Exception("Please choose reportType: " + "gdb,sanitizer.") + else: + raise Exception("Please choose method: afl, " + "libfuzzer.") + else: + raise Exception("Please input -o output path.") + else: + raise Exception("Please input -i input path.") diff --git a/HBFA/UefiHostTestTools/Report/GenSummaryReport.py b/HBFA/UefiHostTestTools/Report/GenSummaryReport.py new file mode 100644 index 0000000..41cbddd --- /dev/null +++ b/HBFA/UefiHostTestTools/Report/GenSummaryReport.py @@ -0,0 +1,132 @@ +# @file +# Transfer report.log file into HTML file +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + + +import os +import datetime + + +class GenSummaryReport(object): + def __init__(self, execfile, outputPath, methods, reportType, failNum, + totalNum, execTime): + self.__testCaseName = os.path.basename(execfile) + self.__totalNum = totalNum + self.__failNum = failNum + self.__execTime = str(execTime).split(':')[0] + ' hrs, ' + \ + str(execTime).split(':')[1] + ' mins, ' + \ + str(execTime).split(':')[2] + ' secs' + self.__methods = methods + self.__reportType = reportType + self.__oldPath = os.path.dirname(os.path.realpath(__file__)) + self.__oldPathFile = os.path.join(self.__oldPath, + "IndexSummaryTemplate.html") + self.__newSanitizerPathFile = \ + os.path.join(outputPath, "SanitizerSummaryReport.html") + self.__newGdbPathFile = \ + os.path.join(outputPath, "GdbSummaryReport.html") + self.__debugSanitizerReportlink = "IndexSanitizer.html" + self.__debugGdbReportlink = "IndexGdb.html" + self.__crashreportlink = "IndexCrashes.html" + self.__hangreportlink = "IndexHangs.html" + + def __GetContentTable(self): + file = open(self.__oldPathFile, "r") + lines = file.readlines() + file.close() + for i, line in enumerate(lines): + if "" in line: + self.__content_start = i + if '' in line: + self.__content_end = i + return lines[self.__content_start + 1: self.__content_end] + + def __InsertContent(self, insertElem, newreportPath): + if self.__methods == 'afl': + testMethod = 'AFL' + else: + testMethod = self.__methods.capitalize() + + file = open(self.__oldPathFile, "r") + fileData = file.readlines() + file.close() + date = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + for i, line in enumerate(fileData): + if '$Testcase' in line: + line = line.replace('$Testcase', self.__testCaseName) + fileData[i] = line + if '$TestMethod' in line: + line = line.replace('$TestMethod', testMethod) + fileData[i] = line + if '$Date' in line: + line = line.replace(line, + '%s' % date) + fileData[i] = line + break + fileData[self.__content_start:self.__content_end] = insertElem + + s = ''.join(fileData) + file = open(newreportPath, "w") + file.write(s) + file.close() + + def __AddContentList(self, itemName, value, link): + contents = self.__GetContentTable() + new_list = [] + for line in contents: + if '$Item' in line: + line = line.replace('$Item', itemName) + if '$Value' in line: + line = line.replace('$Value', str(value)) + if '$Link' in line: + if link != '': + line = line.replace('$Link', link) + else: + line = line.replace('', '').replace('', + '') + new_list.append(line) + return new_list + + def __GenAFLGdbSumReport(self): + totalList = self.__AddContentList('Total Case Numbers:', + self.__totalNum, '') + crashesList = self.__AddContentList('Crashes Case Numbers:', + self.__failNum[0], + self.__crashreportlink) + hangsList = self.__AddContentList('Hangs Case Numbers: ', + self.__failNum[1], + self.__hangreportlink) + execTImeList = self.__AddContentList('Execution Time: ', + self.__execTime, '') + contentList = totalList + crashesList + hangsList + execTImeList + self.__InsertContent(''.join(contentList), self.__newGdbPathFile) + + def __GenOtherSumReport(self): + totalList = self.__AddContentList('Total Case Numbers: ', + self.__totalNum, '') + if self.__reportType == 'gdb': + failList = self.__AddContentList('Failure Type Numbers: ', + self.__failNum, + self.__debugGdbReportlink) + execTImeList = self.__AddContentList('Execution Time: ', + self.__execTime, '') + contentList = totalList + failList + execTImeList + self.__InsertContent(''.join(contentList), self.__newGdbPathFile) + elif self.__reportType == 'sanitizer': + failList = self.__AddContentList('Failure Type Numbers: ', + self.__failNum, + self.__debugSanitizerReportlink) + execTImeList = self.__AddContentList('Execution Time: ', + self.__execTime, '') + contentList = totalList + failList + execTImeList + self.__InsertContent(''.join(contentList), + self.__newSanitizerPathFile) + + def GenSumReport(self): + if self.__methods == 'afl' and self.__reportType == 'gdb': + self.__GenAFLGdbSumReport() + else: + self.__GenOtherSumReport() diff --git a/HBFA/UefiHostTestTools/Report/GetSeedsList.py b/HBFA/UefiHostTestTools/Report/GetSeedsList.py new file mode 100644 index 0000000..5bda737 --- /dev/null +++ b/HBFA/UefiHostTestTools/Report/GetSeedsList.py @@ -0,0 +1,72 @@ +# @file +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +import os +import sys +import glob + +# python version +python_version = sys.version_info[0] + + +class GetSeedsList(object): + def __init__(self, seedsType, inputPath, silence): + self.__seedsType = seedsType + self.__inputPath = inputPath + self.__seedList = [[], []] if self.__seedsType.lower() == "afl" else [] + self.__silence = silence + + def __GetList(self): + seedList = [] + if self.__seedsType.lower() == 'afl': + for item in ['crashes', 'hangs']: + lists = [] + subdir = os.path.join(self.__inputPath, item) + if os.path.exists(subdir): + lists = glob.glob(os.path.join(subdir, 'id*')) + lists.sort(key=lambda fn: os.path.getmtime(fn), reverse=False) + seedList.append(lists) + elif self.__seedsType.lower() == 'libfuzzer': + seedList = [fn for fn in + glob.glob(os.path.join(self.__inputPath, '*')) + if os.path.isfile(fn)] + seedList.sort(key=lambda fn: os.path.getmtime(fn), reverse=False) + return seedList + + def SeekNewSeed(self): + """ + :return: afl [[crash], [hang]], libfuzzer [seed] + """ + newSeedList = self.__GetList() + + if self.__seedsType.lower() == 'afl': + newList = [[], []] + for index in range(len(self.__seedList)): + if len(newSeedList[index]) != len(self.__seedList[index]): + newList[index] = [fn for fn in + (newSeedList[index] + + self.__seedList[index]) + if fn not in self.__seedList[index]] + self.__seedList[index] = newSeedList[index] + if not self.__silence: + print('Current crashes number is %d, hangs' + ' number is %d' % + (len(self.__seedList[0]), + len(self.__seedList[1])) + ) + elif ( + self.__seedsType.lower() == 'libfuzzer' + ): + newList = [] + if len(newSeedList) != len(self.__seedList): + newList = [fn for fn in (newSeedList + self.__seedList) + if fn not in self.__seedList] + self.__seedList = newSeedList + if not self.__silence: + print('Current fault number is %d' % + (len(self.__seedList)) + ) + return newList diff --git a/HBFA/UefiHostTestTools/Report/IndexSummaryTemplate.html b/HBFA/UefiHostTestTools/Report/IndexSummaryTemplate.html new file mode 100644 index 0000000..97987ef --- /dev/null +++ b/HBFA/UefiHostTestTools/Report/IndexSummaryTemplate.html @@ -0,0 +1,241 @@ + + + + + + + Host-based Firmware Analyzer Debug Report + + + + +
Host-based Firmware Analyzer $Testcase Summary Report
+ + + + + + + + + +
HighLight:This is Host-based Firmware Analyzer $Testcase Summary Report offered the failure number of $TestMethod.
Date:$Date
+ + +
+ + + + + + + + + + +
+
ItemNameItemValue
+ + + + + + +
$Item   $Value
+ +
+ + +
Generated by: HBFA
+ + + diff --git a/HBFA/UefiHostTestTools/Report/IndexTemplate.html b/HBFA/UefiHostTestTools/Report/IndexTemplate.html new file mode 100644 index 0000000..b40762e --- /dev/null +++ b/HBFA/UefiHostTestTools/Report/IndexTemplate.html @@ -0,0 +1,278 @@ + + + + + Host-based Firmware Analyzer Debug Report + + + + +
Host-based Firmware Analyzer Debug Report
+ + + + + + + + + + + +
HighLight:This is Host-based Firmware Analyzer debug report that offers the $itemDetail detail information of $testMethod.
Date:$Date$itemNum Number:$failNum
+ +
+ + + + + + + + + + + + + + + + + + + + + + +
Case NameFile NameLine NumberError MessageStack
$failure$fileName$lineNum$error+ Detail Stack Information +
$stack +
+

close

+
+
+
+
Generated by: HBFA
+ + + + + diff --git a/HBFA/UefiHostTestTools/Report/ReportMain.py b/HBFA/UefiHostTestTools/Report/ReportMain.py new file mode 100644 index 0000000..daa4d65 --- /dev/null +++ b/HBFA/UefiHostTestTools/Report/ReportMain.py @@ -0,0 +1,203 @@ +#!/usr/bin/env python3 +# @file +# Transfer report.log file into HTML file +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +import os +import sys +import subprocess +import argparse +from GetSeedsList import GetSeedsList +from GenGdbInfo import GenGdbInfo +from GenGdbHtmlReport import GenGdbHtmlReport +from GenSummaryInfo import GenSummaryInfo +from GenSanitizerInfo import GenSanitizerInfo +from GenSanitizerHtmlReport import GenSanitizerHtmlReport +from GenSummaryReport import GenSummaryReport +import time + +__prog__ = 'ReportMain.py' +__copyright__ = 'Copyright (c) 2019, Intel Corporation. All rights reserved.' +__version__ = '{} Version {}'.format(__prog__, '0.11 ') + + +class GenerateFinalReport(object): + def __init__(self, execute, input, output, methods, sleep): + self.__execute = execute + self.__input = input + self.__output = output + self.__methods = methods + self.__sleep = sleep + self.__reportType = self.__ReportType() + + def __ReportType(self): + return "gdb" if "gcc5" in self.__execute.lower() else "sanitizer" + + def __CallCommand(self, CommandLine): + Cm = subprocess.Popen(CommandLine, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + shell=False) + msg = list(Cm.communicate()) + python_version = sys.version_info[0] + return msg if python_version == 2 \ + else (msg[0].decode() if msg[0] else msg[0], msg[1].decode() + if msg[1] else msg[1]) + + def check_proc_status(self, pid): + try: + os.kill(pid, 0) + except OSError: + return False + return True + + def __CheckStatus(self): + Pid = None + if self.__methods.lower() == 'afl': + statusFile = os.path.join(self.__input, 'fuzzer_stats') + if os.path.exists(statusFile): + f = open(statusFile, 'r') + lines = f.readlines() + f.close() + for line in lines: + if 'fuzzer_pid' in line.lower(): + tmpPid = line.split(":")[-1].strip() + if tmpPid.isdigit(): + tmpPid = int(tmpPid) + status = self.check_proc_status(tmpPid) + if status: + Pid = tmpPid + else: + Pid = None + print(status) + break + + # TODO: Check libfuzzer status + return Pid + + def __GenDebugReport(self, seedList, aflError): + if self.__ReportType() == "gdb": + cfgPath = os.path.join(self.__output, "HBFA.GDB{}.cfg".format( + ("." + aflError.capitalize()) if aflError + in ["crashes", "hangs"] else "")) + genCfg = GenGdbInfo(self.__execute, cfgPath) + genCfg.Run(seedList, False if aflError else True) + genHtml = GenGdbHtmlReport(cfgPath, self.__output, aflError) + genHtml.GenerateHtml() + elif self.__ReportType() == 'sanitizer': + genCfg = GenSanitizerInfo(self.__execute, seedList, + self.__output, True, aflError) + genCfg.Run() + genHtml = GenSanitizerHtmlReport(self.__output, + aflError, self.__output) + genHtml.GenHtml() + + def __GenSummaryReport(self): + genSumNum = GenSummaryInfo(self.__input, self.__output, + self.__methods, self.__reportType, True) + totalNum, failNum, execTime = genSumNum.GenSumInfo() + genSummary = GenSummaryReport(self.__execute, self.__output, + self.__methods, self.__reportType, + failNum, totalNum, execTime) + genSummary.GenSumReport() + + def GenerateReport(self): + getSeedsList = GetSeedsList(self.__methods, self.__input, False) + while True: + seedsList = getSeedsList.SeekNewSeed() + if self.__methods.lower() == "afl": + aflErrorType = ["crashes", "hangs"] + try: + for index, subList in enumerate(seedsList): + if len(subList) == 0: + self.__GenDebugReport(subList, aflErrorType[index]) + else: + for seed in subList: + self.__GenDebugReport([seed], + aflErrorType[index]) + self.__GenSummaryReport() + except Exception as e: + print(e) + elif self.__methods.lower() == 'libfuzzer': + try: + if len(seedsList) == 0: + self.__GenDebugReport(seedsList, "sanitizer") + else: + for seed in seedsList: + self.__GenDebugReport([seed], "sanitizer") + self.__GenSummaryReport() + except Exception as e: + print(e) + if self.__sleep: + time.sleep(int(self.__sleep)) + else: + break + if not self.__CheckStatus(): + break + + +if __name__ == '__main__': + parse = argparse.ArgumentParser() + parse.add_argument("-e", "--execbinary", dest="ModuleBin", + help="Test module binary file name.") + parse.add_argument("-i", "--input", dest="ResultPath", + help="Test result path for test method.") + parse.add_argument("-r", "--report", dest="ReportPath", + help="Generated report path.", default=os.getcwd()) + parse.add_argument("-t", "--testmethods", dest="TestMethods", + help="Test method's name. Must be one of [afl, " + "libfuzzer]. Will be auto detected for default.") + parse.add_argument("-s", "--sleep", dest="SleepTime", + help="In run time mode, # of seconds to sleep between " + "checking for new seed files") + + options = parse.parse_args(sys.argv[1:]) + if options.ResultPath: + if options.TestMethods: + if options.TestMethods.lower() == 'afl': + if not os.path.exists(os.path.join(options.ResultPath, + "fuzzer_stats")): + print("Input AFL fuzzing test's output directory: " + "{}".format(os.path.abspath(options.ResultPath)) + + " is illegal, please check the directory.") + os._exit(0) + elif options.TestMethods.lower() == 'libfuzzer': + pass + else: + if os.path.exists(os.path.join(options.ResultPath, + "fuzzer_stats")): + options.TestMethods = 'afl' + else: + options.TestMethods = "libfuzzer" + if options.ModuleBin: + if not os.path.exists(options.ModuleBin): + print("Input executable test binary file path: " + "{}".format(os.path.abspath(options.ModuleBin)) + + " is not existed.") + os._exit(0) + + ReportPath = os.path.join(options.ReportPath, "DebugReport") + if os.path.exists(ReportPath): + timeStamp = time.strftime('%Y%m%d%H%M%S', + time.localtime(os.path.getctime( + ReportPath))) + backupReportPath = os.path.join(options.ReportPath, + "{}_{}".format("DebugReport", + timeStamp)) + os.rename(ReportPath, backupReportPath) + if not os.path.exists(ReportPath): + os.makedirs(ReportPath) + gfr = GenerateFinalReport(options.ModuleBin, options.ResultPath, + ReportPath, options.TestMethods, + options.SleepTime) + gfr.GenerateReport() + else: + print("Please -e input path for executable test binary file.") + os._exit(0) + else: + print("Please -i input directory that generated by test methods.") + os._exit(0) diff --git a/HBFA/UefiHostTestTools/Report/__init__.py b/HBFA/UefiHostTestTools/Report/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/HBFA/UefiHostTestTools/RunAFL.py b/HBFA/UefiHostTestTools/RunAFL.py new file mode 100644 index 0000000..9881c1e --- /dev/null +++ b/HBFA/UefiHostTestTools/RunAFL.py @@ -0,0 +1,329 @@ +#!/usr/bin/env python3 +# @file +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +import os +import sys +import shutil +import platform +import subprocess +import argparse + +__prog__ = 'RunAFL.py' +__copyright__ = 'Copyright (c) 2019, Intel Corporation. All rights reserved.' +__version__ = '{} Version {}'.format(__prog__, '0.11 ') + +# Get System type info +SysType = platform.system() + +# Get System arch info +Is32bit = bool("64" not in platform.machine()) + +# build tool chain +if SysType == "Windows": + ToolChain = "VS2015x86" +elif SysType == "Linux": + ToolChain = "AFL" + +# WORKSPACE +workspace = '' + +# HBFA package path +HBFA_PATH = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + +# Conf directory +Conf_Path = os.path.join(HBFA_PATH, 'UefiHostFuzzTestPkg', 'Conf') + +# Get PYTHON version +PyVersion = sys.version_info[0] + +# Set a CLI command mode +CommandLineMode = None + + +def CheckTestEnv(): + # Check EDKII BUILD WORKSPACE whether be set in system environment + # variable + if 'WORKSPACE' not in os.environ: + print("[!] Please set system environment variable 'WORKSPACE' before " + "run this script.") + os._exit(0) + global workspace + workspace = os.environ['WORKSPACE'] + + # Check whether HBFA environment is set up + if 'build_rule.txt' not in os.listdir(Conf_Path) or 'tools_def.txt' \ + not in os.listdir(Conf_Path) or 'target.txt'\ + not in os.listdir(Conf_Path): + print("[!] Please run HBFAEnvSetup.py before run this script.") + os._exit(0) + + if "AFL_PATH" not in os.environ: + print("[!] Please set AFL_PATH in system environment variables.") + os._exit(0) + + if "EDK_TOOLS_PATH" not in os.environ: + print("[!] Please set EDK_TOOLS_PATH in system environment variables.") + os._exit(0) + global edkToolsPath + edkToolsPath = os.environ['EDK_TOOLS_PATH'] + + if SysType == "Windows" and "DRIO_PATH" not in os.environ: + print("Please set DRIO_PATH in system environment variables.") + os._exit(0) + + +def GetPkgName(path): + return path.split(os.path.sep)[0] + + +def GetModuleBinName(ModuleInfPath): + with open(ModuleInfPath, 'r') as f: + lines = f.readlines() + for line in lines: + if 'BASE_NAME' in line: + if SysType == "Windows": + return line.split('=')[1].strip() + ".exe" + elif SysType == "Linux": + return line.split('=')[1].strip() + + +def CheckBuildResult(ModuleBinPath): + if os.path.exists(ModuleBinPath): + print("Build Successfully !!!\n") + else: + print("Build failure, can not find Module Binary file: " + "{}".format(ModuleBinPath)) + os._exit(0) + + +def CopyFile(src, dst): + try: + shutil.copyfile(src, dst) + except Exception as err: + print(err) + + +def Build(Arch, Target, ModuleFilePath): + PkgName = GetPkgName(ModuleFilePath) + ModuleFileAbsPath = os.path.join(HBFA_PATH, ModuleFilePath) + ModuleBinName = GetModuleBinName(ModuleFileAbsPath) + ModuleBinAbsPath = os.path.join(workspace, 'Build', PkgName, Target + + '_' + ToolChain, Arch, ModuleBinName) + PlatformDsc = os.path.join(HBFA_PATH, PkgName, PkgName+'.dsc') + + BuildCmdList = [] + BuildCmdList.append('-p') + BuildCmdList.append('{}'.format(PlatformDsc)) + BuildCmdList.append('-m') + BuildCmdList.append('{}'.format(ModuleFileAbsPath)) + BuildCmdList.append('-a') + BuildCmdList.append('{}'.format(Arch)) + BuildCmdList.append('-b') + BuildCmdList.append('{}'.format(Target)) + BuildCmdList.append('-t') + BuildCmdList.append('{}'.format(ToolChain)) + BuildCmdList.append('--conf') + BuildCmdList.append('{}'.format(Conf_Path)) + if SysType == 'Linux': + BuildCmdList.append('-t') + BuildCmdList.append('GCC5') + + buildBinary = [edkToolsPath + '/BinWrappers/PosixLike/build'] + ExecCmd = buildBinary + BuildCmdList + p = subprocess.Popen(ExecCmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + shell=False) + msg = list(p.communicate()) + if PyVersion == 3: + for num, submsg in enumerate(msg): + if submsg is not None: + msg[num] = submsg.decode() + + if msg[1]: + print(msg[0] + msg[1]) + os._exit(0) + elif "- Done -" not in msg[0]: + print(msg[0]) + os._exit(0) + else: + pass + CheckBuildResult(ModuleBinAbsPath) + return ModuleBinAbsPath + + +def RunAFL(TestModuleBinPath, InputPath, OutputPath): + TestModuleName = TestModuleBinPath.split('\\')[-1] + if SysType == "Windows": + if "IA32" in TestModuleBinPath: + AFL_PATH = os.path.join(os.environ["AFL_PATH"], "bin32") + # Copy xxx.exe and xxx.pdb to the same dir as winafl\bin32 or + # winafl\bin64 + CopyFile(TestModuleBinPath, os.path.join(AFL_PATH, + TestModuleName)) + CopyFile(TestModuleBinPath, + os.path.join(AFL_PATH, + TestModuleName.replace('.exe', '.pdb'))) + AFL_CMD = "afl-fuzz.exe -i {} ".format(InputPath) + \ + "-o {}".format(OutputPath) + \ + " -D %DRIO_PATH%\\bin32 -t 20000 -- -coverage_module " + \ + "{}".format(TestModuleName) + \ + " -fuzz_iterations 1000 -target_module " + \ + "{}".format(TestModuleName) + \ + " -target_method main -nargs 2 -- " + \ + "{} @@".format(TestModuleName) + elif "X64" in TestModuleBinPath: + AFL_PATH = os.path.join(os.environ["AFL_PATH"], "bin64") + # Copy xxx.exe and xxx.pdb to the same dir as winafl\bin32 + # or winafl\bin64 + CopyFile(TestModuleBinPath, os.path.join(AFL_PATH, TestModuleName)) + CopyFile(TestModuleBinPath, + os.path.join(AFL_PATH, + TestModuleName.replace('.exe', '.pdb'))) + AFL_CMD = "afl-fuzz.exe -i {} ".format(InputPath) + \ + "-o {} ".format(OutputPath) + \ + "-D %DRIO_PATH%\\bin64 -t 20000 -- -coverage_module " + \ + "{}".format(TestModuleName) + \ + " -fuzz_iterations 1000 -target_module " + \ + "{}".format(TestModuleName) + \ + " -target_method main -nargs 2 -- " + \ + "{} @@".format(TestModuleName) + elif SysType == "Linux": + AFL_PATH = os.environ["AFL_PATH"] + AFL_CMD = [] + AFL_CMD.append(AFL_PATH+"/afl-fuzz") + AFL_CMD.append("-i") + AFL_CMD.append("{}".format(InputPath)) + AFL_CMD.append("-o") + AFL_CMD.append("{}".format(OutputPath)) + AFL_CMD.append("{}".format(TestModuleBinPath)) + AFL_CMD.append("@@") + print("Start run AFL test:") + if SysType == "Windows": + print(AFL_CMD) + ExecCmd = 'start cmd /k "cd/d {} && {}"'.format(AFL_PATH, AFL_CMD) + elif SysType == "Linux": + if CommandLineMode == 'rawcommand': + print(AFL_CMD) + ExecCmd = AFL_CMD + try: + p = subprocess.Popen(ExecCmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + shell=False) + while True: + pout = p.stdout.readline() + if pout == b'' and p.poll() is not None: + break + elif pout: + print(pout.decode()) + p.poll() + except Exception as error: + print("Exception encountered: {}".format(error)) + elif CommandLineMode == 'manual': + runCommand = ' '.join(AFL_CMD) + print('Run this command to initiate the fuzzer: ' + '{}'.format(runCommand)) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("-a", "--arch", + choices=['IA32', 'X64', 'ARM', 'AARCH64'], + dest="TargetArch", default="IA32", + help="ARCHS is one of list: IA32, X64, ARM or AARCH64," + " which overrides target.txt's TARGET_ARCH " + "definition.") + parser.add_argument("-b", "--buildtarget", + dest="BuildTarget", default="DEBUG", + help="Using the TARGET to build the platform, " + "overriding target.txt's TARGET definition.") + parser.add_argument("-m", "--module", dest="ModuleFile", + help="Build the module specified by the INF file name " + "argument.") + parser.add_argument("-i", "--input", dest="InputSeed", + help="Test input seed path.") + parser.add_argument("-o", "--output", dest="Output", + help="Test output path for AFL.") + parser.add_argument("-c", "--commandline", dest="CommandLine", + choices=['rawcommand', 'manual'], + default='rawcommand', + help="This specifies how the fuzzer is " + "initiated from command-line for Linux-based " + "distributions. Specify either: " + "'rawcommand' or 'manual'. Using 'rawcommand' " + "will directly initiate " + "the AFL fuzzer after building the test module and is " + "recommended for automated approaches. Alternatively, " + "'manual' may be used to simply build the test case " + "and print out a command that the user can run to " + "start the fuzzer (this will preserve the fuzzing " + "display for AFL.") + args = parser.parse_args(sys.argv[1:]) + TargetArch = args.TargetArch + BuildTarget = args.BuildTarget + + CheckTestEnv() + + if not args.ModuleFile: + print("ModuleFile should be set once by command -m MODULEFILE, " + "--module=MODULEFILE.") + os._exit(0) + elif os.path.isabs(args.ModuleFile): + if args.ModuleFile.startswith(HBFA_PATH): + ModuleFilePath = os.path.relpath(args.ModuleFile, HBFA_PATH) + else: + print("ModuleFile path: {}".format(args.ModuleFile) + + " should start with " + + "{}.".format(HBFA_PATH)) + os._exit(0) + elif not os.path.exists(os.path.join(HBFA_PATH, args.ModuleFile)): + print("ModuleFile path: {}".format(args.ModuleFile) + + " does not exist or is not in the relative path for HBFA") + os._exit(0) + else: + ModuleFilePath = args.ModuleFile + + if not args.InputSeed: + print("InputSeed path should be set once by command -i INPUTSEED, " + "--input=INPUTSEED.") + os._exit(0) + elif not os.path.exists(args.InputSeed): + print("InputSeed path: {}".format(os.path.abspath(args.InputSeed)) + + " does not exist") + os._exit(0) + else: + InputSeedPath = args.InputSeed + + if not args.Output: + print("OutputSeed path should be set once by command -o OUTPUT, " + "--output=OUTPUT.") + os._exit(0) + else: + OutputSeedPath = args.Output + if not os.path.isabs(OutputSeedPath): + OutputSeedPath = os.path.join(os.getcwd(), OutputSeedPath) + if not os.path.exists(OutputSeedPath): + try: + os.makedirs(OutputSeedPath) + except Exception as err: + print(err) + elif os.path.exists(os.path.join(OutputSeedPath, 'fuzzer_stats')): + print("OutputSeedPath:{}".format(OutputSeedPath) + + " is already exists, please change another directory.") + os._exit(0) + + if (SysType == 'Linux'): + global CommandLineMode + CommandLineMode = args.CommandLine + + TestModuleBinPath = Build(TargetArch, BuildTarget, ModuleFilePath) + RunAFL(TestModuleBinPath, InputSeedPath, OutputSeedPath) + + +if __name__ == "__main__": + main() diff --git a/HBFA/UefiHostTestTools/RunAFLTurbo.py b/HBFA/UefiHostTestTools/RunAFLTurbo.py new file mode 100644 index 0000000..625f675 --- /dev/null +++ b/HBFA/UefiHostTestTools/RunAFLTurbo.py @@ -0,0 +1,286 @@ +#!/usr/bin/env python3 +# @file +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +import os +import sys +import shutil +import platform +import subprocess +import argparse + +__prog__ = 'RunAFLTurbo.py' +__copyright__ = 'Copyright (c) 2019, Intel Corporation. All rights reserved.' +__version__ = '{} Version {}'.format(__prog__, '0.11 ') + +# Get System type info +SysType = platform.system() + +# Get System arch info +Is32bit = bool("64" not in platform.machine()) + +# build tool chain +if SysType == "Windows": + ToolChain = "VS2015x86" +elif SysType == "Linux": + ToolChain = "AFL" + +# WORKSPACE +workspace = '' + +# HBFA package path +HBFA_PATH = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + +# Conf directory +Conf_Path = os.path.join(HBFA_PATH, 'UefiHostFuzzTestPkg', 'Conf') + +# Get PYTHON version +PyVersion = sys.version_info[0] + +# Set a CLI command mode +CommandLineMode = None + + +def CheckTestEnv(): + # Check EDKII BUILD WORKSPACE whether be set in system environment variable + if 'WORKSPACE' not in os.environ: + print("Please set system environment variable 'WORKSPACE' before run " + "this script.") + os._exit(0) + global workspace + workspace = os.environ['WORKSPACE'] + + # Check whether HBFA environment is set up + if 'build_rule.txt' not in os.listdir(Conf_Path) or 'tools_def.txt' \ + not in os.listdir(Conf_Path) or 'target.txt'\ + not in os.listdir(Conf_Path): + print("Please run HBFAEnvSetup.py before run this script.") + os._exit(0) + + if "AFL_PATH" not in os.environ: + print("Please set AFL_PATH in system environment variables.") + os._exit(0) + + if "EDK_TOOLS_PATH" not in os.environ: + print("[!] Please set EDK_TOOLS_PATH in system environment variables.") + os._exit(0) + global edkToolsPath + edkToolsPath = os.environ['EDK_TOOLS_PATH'] + + if SysType == "Windows": + print("AFLTurbo doesnt support running in Windows. Please try with " + "linux.") + os._exit(0) + + +def GetPkgName(path): + return path.split(os.path.sep)[0] + + +def GetModuleBinName(ModuleInfPath): + with open(ModuleInfPath, 'r') as f: + lines = f.readlines() + for line in lines: + if 'BASE_NAME' in line: + return line.split('=')[1].strip() + + +def CheckBuildResult(ModuleBinPath): + if os.path.exists(ModuleBinPath): + print("Build Successfully !!!\n") + else: + print("Build failure, can not find Module Binary file: " + "{}".format(ModuleBinPath)) + os._exit(0) + + +def CopyFile(src, dst): + try: + shutil.copyfile(src, dst) + except Exception as err: + print(err) + + +def Build(Arch, Target, ModuleFilePath): + PkgName = GetPkgName(ModuleFilePath) + ModuleFileAbsPath = os.path.join(HBFA_PATH, ModuleFilePath) + ModuleBinName = GetModuleBinName(ModuleFileAbsPath) + ModuleBinAbsPath = os.path.join(workspace, 'Build', PkgName, Target + + '_' + ToolChain, Arch, ModuleBinName) + PlatformDsc = os.path.join(HBFA_PATH, PkgName, PkgName+'.dsc') + + BuildCmdList = [] + BuildCmdList.append('-p') + BuildCmdList.append('{}'.format(PlatformDsc)) + BuildCmdList.append('-m') + BuildCmdList.append('{}'.format(ModuleFileAbsPath)) + BuildCmdList.append('-a') + BuildCmdList.append('{}'.format(Arch)) + BuildCmdList.append('-b') + BuildCmdList.append('{}'.format(Target)) + BuildCmdList.append('-t') + BuildCmdList.append('{}'.format(ToolChain)) + BuildCmdList.append('--conf') + BuildCmdList.append('{}'.format(Conf_Path)) + if SysType == 'Linux': + BuildCmdList.append('-t') + BuildCmdList.append('GCC5') + + buildBinary = [edkToolsPath + '/BinWrappers/PosixLike/build'] + ExecCmd = buildBinary + BuildCmdList + proccess = subprocess.Popen(ExecCmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + shell=False) + msg = list(proccess.communicate()) + if PyVersion == 3: + for num, submsg in enumerate(msg): + if submsg is not None: + msg[num] = submsg.decode() + + if msg[1]: + print(msg[0] + msg[1]) + os._exit(0) + elif "- Done -" not in msg[0]: + print(msg[0]) + os._exit(0) + else: + pass + CheckBuildResult(ModuleBinAbsPath) + return ModuleBinAbsPath + + +def RunAFLTurbo(TestModuleBinPath, InputPath, OutputPath): + AFL_PATH = os.environ["AFL_PATH"] + AFL_CMD = [] + AFL_CMD.append(AFL_PATH+"/afl-turbo-fuzz") + AFL_CMD.append("-i") + AFL_CMD.append("{}".format(InputPath)) + AFL_CMD.append("-o") + AFL_CMD.append("{}".format(OutputPath)) + AFL_CMD.append("{}".format(TestModuleBinPath)) + AFL_CMD.append("@@") + print("Start run AFLTurbo test:") + if CommandLineMode == 'rawcommand': + print(AFL_CMD) + ExecCmd = AFL_CMD + try: + p = subprocess.Popen(ExecCmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + shell=False) + while True: + pout = p.stdout.readline() + if pout == b'' and p.poll() is not None: + break + elif pout: + print(pout.decode()) + p.poll() + except Exception as error: + print("Exception encountered: {}".format(error)) + elif CommandLineMode == 'manual': + runCommand = ' '.join(AFL_CMD) + print('Run this command to initiate the fuzzer: ' + '{}'.format(runCommand)) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("-a", "--arch", + choices=['IA32', 'X64', 'ARM', 'AARCH64'], + dest="TargetArch", default="IA32", + help="ARCHS is one of list: IA32, X64, ARM or AARCH64," + " which overrides target.txt's TARGET_ARCH " + "definition.") + parser.add_argument("-b", "--buildtarget", + dest="BuildTarget", default="DEBUG", + help="Using the TARGET to build the platform, " + "overriding target.txt's TARGET definition.") + parser.add_argument("-m", "--module", dest="ModuleFile", + help="Build the module specified by the INF file name " + "argument.") + parser.add_argument("-i", "--input", dest="InputSeed", + help="Test input seed path.") + parser.add_argument("-o", "--output", dest="Output", + help="Test output path for AFL.") + parser.add_argument("-c", "--commandline", dest="CommandLine", + choices=['rawcommand', 'manual'], + default="rawcommand", + help="This specifies how the fuzzer is " + "initiated from command-line for Linux-based " + "distributions. Specify either: " + "'rawcommand' or 'manual'. Using 'rawcommand' " + "will directly initiate " + "the AFLTurbo fuzzer after building the test " + "module and is recommended for automated " + "approaches. Alternatively, 'manual' may be used" + " to simply build the test case " + "and print out a command that the user can run to " + "start the fuzzer (this will preserve the fuzzing " + "display for AFLTurbo.") + + args = parser.parse_args(sys.argv[1:]) + TargetArch = args.TargetArch + BuildTarget = args.BuildTarget + + CheckTestEnv() + + if not args.ModuleFile: + print("ModuleFile should be set once by command -m MODULEFILE, " + "--module=MODULEFILE.") + os._exit(0) + elif os.path.isabs(args.ModuleFile): + if args.ModuleFile.startswith(HBFA_PATH): + ModuleFilePath = os.path.relpath(args.ModuleFile, HBFA_PATH) + else: + print("ModuleFile path: {}".format(args.ModuleFile) + + " should be start with {}.".format(HBFA_PATH)) + os._exit(0) + elif not os.path.exists(os.path.join(HBFA_PATH, args.ModuleFile)): + print("ModuleFile path: {}".format(args.ModuleFile) + + " is no exits or not the relative path for HBFA") + os._exit(0) + else: + ModuleFilePath = args.ModuleFile + + if not args.InputSeed: + print("InputSeed path should be set once by command -i INPUTSEED, " + "--input=INPUTSEED.") + os._exit(0) + elif not os.path.exists(args.InputSeed): + print("InputSeed path: {}".format(os.path.abspath(args.InputSeed)) + + " is no exists") + os._exit(0) + else: + InputSeedPath = args.InputSeed + + if not args.Output: + print("OutputSeed path should be set once by command -o OUTPUT, " + "--output=OUTPUT.") + os._exit(0) + else: + OutputSeedPath = args.Output + if not os.path.isabs(OutputSeedPath): + OutputSeedPath = os.path.join(os.getcwd(), OutputSeedPath) + if not os.path.exists(OutputSeedPath): + try: + os.makedirs(OutputSeedPath) + except Exception as err: + print(err) + elif os.path.exists(os.path.join(OutputSeedPath, 'fuzzer_stats')): + print("OutputSeedPath:{}".format(OutputSeedPath) + + " is already exists, please change another directory.") + os._exit(0) + + global CommandLineMode + CommandLineMode = args.CommandLine + + TestModuleBinPath = Build(TargetArch, BuildTarget, ModuleFilePath) + RunAFLTurbo(TestModuleBinPath, InputSeedPath, OutputSeedPath) + + +if __name__ == "__main__": + main() diff --git a/HBFA/UefiHostTestTools/RunKLEE.py b/HBFA/UefiHostTestTools/RunKLEE.py new file mode 100644 index 0000000..1a02f10 --- /dev/null +++ b/HBFA/UefiHostTestTools/RunKLEE.py @@ -0,0 +1,258 @@ +#!/usr/bin/env python3 +# @file +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +import os +import sys +import platform +import subprocess +import argparse + +__prog__ = 'RunKLEE.py' +__copyright__ = 'Copyright (c) 2019, Intel Corporation. All rights reserved.' +__version__ = '{} Version {}'.format(__prog__, '0.11 ') + +# Get System type info +SysType = platform.system() + +# build tool chain +ToolChain = "KLEE" + +# WORKSPACE +workspace = "" + +# KLEE_SRC_PATH +klee_src_path = "" + +# HBFA package path +HBFA_PATH = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + +# Conf directory +Conf_Path = os.path.join(HBFA_PATH, 'UefiHostFuzzTestPkg', 'Conf') + +# Get PYTHON version +PyVersion = sys.version_info[0] + +# Set a CLI command mode +CommandLineMode = None + + +def CheckTestEnv(): + # Need to remove if support KLEE in Windows + if SysType == 'Windows': + print("KLEE is not supported in Windows currently.") + os._exit(0) + + # Check whether EDKII BUILD WORKSPACE is set in system environment variable + if 'WORKSPACE' not in os.environ: + print("Please set system environment variable 'WORKSPACE' before run " + "this script.") + os._exit(0) + global workspace + workspace = os.environ['WORKSPACE'] + + # Check whether KLEE_SRC_PATH is set in system environment variable + if 'KLEE_SRC_PATH' not in os.environ: + print("Please set system environment variable 'KLEE_SRC_PATH' before " + "run this script.") + os._exit(0) + global klee_src_path + klee_src_path = os.environ['KLEE_SRC_PATH'] + + if "EDK_TOOLS_PATH" not in os.environ: + print("[!] Please set EDK_TOOLS_PATH in system environment variables.") + os._exit(0) + global edkToolsPath + edkToolsPath = os.environ['EDK_TOOLS_PATH'] + + # Check whether HBFA environment is set up + if 'build_rule.txt' not in os.listdir(Conf_Path) or 'tools_def.txt' \ + not in os.listdir(Conf_Path) or 'target.txt'\ + not in os.listdir(Conf_Path): + print("Please run HBFAEnvSetup.py before run this script.") + os._exit(0) + + +def GetPkgName(path): + return path.split(os.path.sep)[0] + + +def GetModuleBinName(ModuleInfPath): + with open(ModuleInfPath, 'r') as f: + lines = f.readlines() + for line in lines: + if 'BASE_NAME' in line: + return line.split('=')[1].strip() + + +def CheckBuildResult(ModuleBinPath): + if os.path.exists(ModuleBinPath): + print("Build Successfully !!!\n") + else: + print("Can not find Module Binary file: {}".format(ModuleBinPath)) + os._exit(0) + + +def Build(Arch, Target, ModuleFilePath): + PkgName = GetPkgName(ModuleFilePath) + ModuleFileAbsPath = os.path.join(HBFA_PATH, ModuleFilePath) + ModuleBinName = GetModuleBinName(ModuleFileAbsPath) + ModuleBinAbsPath = os.path.join(workspace, 'Build', PkgName, + Target + '_' + ToolChain, Arch, + ModuleBinName) + PlatformDsc = os.path.join(PkgName, PkgName+'.dsc') + + BuildCmdList = [] + + BuildCmdList.append('-p') + BuildCmdList.append('{}'.format(PlatformDsc)) + BuildCmdList.append('-m') + BuildCmdList.append('{}'.format(ModuleFilePath)) + BuildCmdList.append('-a') + BuildCmdList.append('{}'.format(Arch)) + BuildCmdList.append('-b') + BuildCmdList.append('{}'.format(Target)) + BuildCmdList.append('-t') + BuildCmdList.append('{}'.format(ToolChain)) + BuildCmdList.append('--conf') + BuildCmdList.append('{}'.format(Conf_Path)) + BuildCmdList.append('-DTEST_WITH_KLEE') + BuildCmdList.append('--disable-include-path-check') + + BuildCmd = [edkToolsPath + '/BinWrappers/PosixLike/build'] + BuildCmdList + os.environ['SCRIPT_PATH'] = HBFA_PATH \ + + "/UefiHostFuzzTestPkg/Conf/LLVMLink.py" + os.environ['LLVM_COMPILER'] = 'clang' + print("Start build Test Module:") + print(' '.join(BuildCmd)) + p = subprocess.Popen(BuildCmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + shell=False) + msg = list(p.communicate()) + if PyVersion == 3: + for num, submsg in enumerate(msg): + if submsg is not None: + msg[num] = submsg.decode() + + if msg[1]: + print(msg[0] + msg[1]) + os._exit(0) + elif "- Done -" not in msg[0]: + print(msg[0]) + os._exit(0) + else: + pass + CheckBuildResult(ModuleBinAbsPath) + return ModuleBinAbsPath + + +def RunKLEE(TestModuleBinPath, OutPutPath): + SetEnvCmd = "export PATH=$KLEE_BIN_PATH:$PATH\n" + SetLimit = "ulimit -s unlimited\n" + KLEE_CMD = "klee --only-output-states-covering-new " \ + + "-output-dir={} {}".format(OutPutPath, TestModuleBinPath) + print("Start run KLEE test:") + print(KLEE_CMD) + if CommandLineMode == 'rawcommand': + ExecCmd = SetEnvCmd + SetLimit + KLEE_CMD + try: + p = subprocess.Popen(ExecCmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + shell=False) + while True: + pout = p.stdout.readline() + if pout == b'' and p.poll() is not None: + break + elif pout: + print(pout.decode()) + p.poll() + except Exception as error: + print("Exception encountered: {}".format(error)) + elif CommandLineMode == 'manual': + print('Run this command to initiate KLEE: ' + '{}'.format(SetEnvCmd + SetLimit + KLEE_CMD)) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("-a", "--arch", + help="ARCHS is one of the list: IA32, X64, " + "ARM or AARCH64, which overrides target.txt's " + "TARGET_ARCH definition", + choices=['IA32', 'X64', 'ARM', 'AARCH64'], + dest="TargetArch", default="IA32") + parser.add_argument("-b", "--buildtarget", + help="Using the TARGET to build the platform, " + "overriding target.txt's TARGET definition.", + dest="BuildTarget", default="DEBUG") + parser.add_argument("-m", "--module", + help="Build the module specified by the INF file name " + "argument.", + dest="ModuleFile") + parser.add_argument("-o", "--output", + help="Test output path for Klee.", + dest="Output") + parser.add_argument("-c", "--commandline", + help="This specifies how the Klee is initiated from " + "command-line for Linux-based distributions. Specify " + "either: 'rawcommand' or 'manual'. " + "Using the 'rawcommand' mode is recommended. " + "The 'manual' option will build the module and " + "then simply print a command-line option that " + "the end-user can subsequently use to run Klee.", + choices=['rawcommand', 'manual'], + dest="CommandLine", default="rawcommand") + + args = parser.parse_args(sys.argv[1:]) + + TargetArch = args.TargetArch + BuildTarget = args.BuildTarget + + CheckTestEnv() + + if not args.ModuleFile: + print("ModuleFile should be set once by command -m MODULEFILE, " + "--module=MODULEFILE.") + os._exit(0) + elif os.path.isabs(args.ModuleFile): + if args.ModuleFile.startswith(HBFA_PATH): + ModuleFilePath = os.path.relpath(args.ModuleFile, HBFA_PATH) + else: + print("ModuleFile path: {} should start with {}.".format( + args.ModuleFile, HBFA_PATH)) + os._exit(0) + elif not os.path.exists(os.path.join(HBFA_PATH, args.ModuleFile)): + print("ModuleFile path: {}".format(args.ModuleFile) + + " does not exist or is not in the relative path for HBFA") + os._exit(0) + else: + ModuleFilePath = args.ModuleFile + + if not args.Output: + print("OutputSeed path should be set once by command -o OUTPUT, " + "--output=OUTPUT.") + os._exit(0) + else: + OutputSeedPath = args.Output + if os.path.exists(OutputSeedPath): + print("OutputSeedPath:{}".format(OutputSeedPath) + + " already exists, please select another folder.") + os._exit(0) + else: + if not os.path.exists(os.path.dirname(OutputSeedPath)): + os.makedirs(os.path.dirname(OutputSeedPath)) + + global CommandLineMode + CommandLineMode = args.CommandLine + + TestModuleBinPath = Build(TargetArch, BuildTarget, ModuleFilePath) + RunKLEE(TestModuleBinPath, OutputSeedPath) + + +if __name__ == "__main__": + main() diff --git a/HBFA/UefiHostTestTools/RunLibFuzzer.py b/HBFA/UefiHostTestTools/RunLibFuzzer.py new file mode 100644 index 0000000..78edd8f --- /dev/null +++ b/HBFA/UefiHostTestTools/RunLibFuzzer.py @@ -0,0 +1,474 @@ +#!/usr/bin/env python3 +# @file +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +import os +import sys +import platform +import subprocess +import re +import shutil +import argparse + +__prog__ = 'RunLibFuzzer.py' +__copyright__ = 'Copyright (c) 2019, Intel Corporation. All rights reserved.' +__version__ = '{} Version {}'.format(__prog__, '0.11 ') + +# WORKSPACE +workspace = "" + +# HBFA package path +HBFA_PATH = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + +# Conf directory +Conf_Path = os.path.join(HBFA_PATH, 'UefiHostFuzzTestPkg', 'Conf') + +# Get PYTHON version +PyVersion = sys.version_info[0] + +# Get System type info +SysType = platform.system() + +# Get System arch info +Is32bit = bool("64" not in platform.machine()) + +# Set a CLI command mode +CommandLineMode = None + +# build tool chain +if SysType == "Windows": + ToolChain = "LIBFUZZERWIN" +elif SysType == "Linux": + ToolChain = "LIBFUZZER" + + +def CheckTestEnv(Arch): + # Check whether EDKII BUILD WORKSPACE is set in system environment variable + if 'WORKSPACE' not in os.environ: + print("Please set system environment variable 'WORKSPACE' before " + + "run this script.") + os._exit(0) + global workspace + workspace = os.environ['WORKSPACE'] + + # Check whether HBFA environment is set up + if 'build_rule.txt' not in os.listdir(Conf_Path) or 'tools_def.txt' \ + not in os.listdir(Conf_Path) or 'target.txt'\ + not in os.listdir(Conf_Path): + print("Please run HBFAEnvSetup.py before run this script.") + os._exit(0) + + if "EDK_TOOLS_PATH" not in os.environ: + print("[!] Please set EDK_TOOLS_PATH in system environment variables.") + os._exit(0) + global edkToolsPath + edkToolsPath = os.environ['EDK_TOOLS_PATH'] + + if SysType == "Windows": + if Arch == "IA32": + # Need to remove when LLVM support libFuzzer i386 + print("LLVM doesn't support libFuzzer i386 currently.") + os._exit(0) + # Check whether environment variable LLVMx86_PATH has been set + if "LLVMx86_PATH" not in os.environ: + print("Please set LLVMx86_PATH in system environment " + "variable.") + os._exit(0) + elif Arch == "X64": + # Check whether environment variable LLVM_PATH has been set + if "LLVM_PATH" not in os.environ: + print("Please set LLVM_PATH in system environment variable.") + os._exit(0) + else: + # Check whether environment variable CLANG_PATH has been set + if "CLANG_PATH" not in os.environ: + print("Please set CLANG_PATH in system environment variable.") + os._exit(0) + + +def GetPkgName(path): + return path.split(os.path.sep)[0] + + +def GetModuleBinName(ModuleInfPath): + with open(ModuleInfPath, 'r') as f: + lines = f.readlines() + for line in lines: + if 'BASE_NAME' in line: + if SysType == "Windows": + return line.split('=')[1].strip() + '.exe' + elif SysType == "Linux": + return line.split('=')[1].strip() + + +def CheckBuildResult(ModuleBinPath): + if os.path.exists(ModuleBinPath): + print("Build Successful !!!\n") + else: + print("Build failure, cannot find Module Binary file:" + " {}".format(ModuleBinPath)) + os._exit(0) + + +def Build(Arch, Target, ModuleFilePath): + PkgName = GetPkgName(ModuleFilePath) + ModuleFileAbsPath = os.path.join(HBFA_PATH, ModuleFilePath) + ModuleBinName = GetModuleBinName(ModuleFileAbsPath) + ModuleBinAbsPath = os.path.join(workspace, 'Build', PkgName, Target + + '_' + ToolChain, Arch, ModuleBinName) + PlatformDsc = os.path.join(PkgName, PkgName+'.dsc') + + BuildCmdList = [] + BuildCmdList.append('-p') + BuildCmdList.append('{}'.format(PlatformDsc)) + BuildCmdList.append('-m') + BuildCmdList.append('{}'.format(ModuleFilePath)) + BuildCmdList.append('-a') + BuildCmdList.append('{}'.format(Arch)) + BuildCmdList.append('-b') + BuildCmdList.append('{}'.format(Target)) + BuildCmdList.append('-t') + BuildCmdList.append('{}'.format(ToolChain)) + BuildCmdList.append('--conf') + BuildCmdList.append('{}'.format(Conf_Path)) + + if SysType == "Linux": + # Add GCC5 build target for gcov output if Profraw format is used + BuildCmdList.append('-t') + BuildCmdList.append('GCC5') + + BuildCmd = [edkToolsPath + '/BinWrappers/PosixLike/build'] + BuildCmdList + if SysType == "Windows": + ExecCmd = BuildCmd + elif SysType == "Linux": + ExecCmd = BuildCmd + print("Start build Test Module:") + print(' '.join(BuildCmd)) + proccess = subprocess.Popen(ExecCmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + shell=False) + msg = list(proccess.communicate()) + if PyVersion == 3: + for num, submsg in enumerate(msg): + if submsg is not None: + msg[num] = submsg.decode() + + if msg[1]: + print(msg[0] + msg[1]) + os._exit(0) + elif "- Done -" not in msg[0]: + print(msg[0]) + os._exit(0) + else: + pass + CheckBuildResult(ModuleBinAbsPath) + return ModuleBinAbsPath + + +def RunLibFuzzer(TestModuleBinPath, InputPath, OutputPath): + LibFuzzer_CMD = [] + LibFuzzer_CMD.append("{}".format(TestModuleBinPath)) + LibFuzzer_CMD.append("{}".format(InputPath if InputPath + else '')) + LibFuzzer_CMD.append("-rss_limit_mb=0") + LibFuzzer_CMD.append("-artifact_prefix={}".format( + OutputPath + ('/' if SysType == "Linux" else '\\'))) + print("Start run LibFuzzer test:") + if SysType == "Windows": + ExecCmd = 'start cmd /k "{}"'.format(' '.join(LibFuzzer_CMD)) + elif SysType == "Linux": + if CommandLineMode == 'rawcommand': + print(' '.join(LibFuzzer_CMD)) + ExecCmd = LibFuzzer_CMD + try: + p = subprocess.Popen(ExecCmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + shell=False) + while True: + pout = p.stdout.readline() + if pout == b'' and p.poll() is not None: + break + elif pout: + print(pout.decode()) + p.poll() + except Exception as err: + print("Exception encountered: {}".format(err)) + elif CommandLineMode == 'manual': + print('Run this command to initiate the fuzzer: ' + '{}'.format(' '.join(LibFuzzer_CMD))) + + +def checkSanitizers(Sanitizers): + CheckList = Sanitizers.split(',') + CheckedSanitizers = '' + SupportedSanitizers = ('address', 'memory', 'undefined', + 'integer', 'bounds', 'enum', 'function') + AddressMemoryCheck = {"address": False, "memory": False} + for Sanitizer in CheckList: + if Sanitizer in SupportedSanitizers: + CheckedSanitizers += (',' + Sanitizer) + else: + return "[!] Unsupported sanitizer provided in option -s: [ %s ]" \ + % (Sanitizer) + if Sanitizer == 'address' or Sanitizer == 'memory': + AddressMemoryCheck[Sanitizer] = True + if (AddressMemoryCheck['address'] is True) and \ + (AddressMemoryCheck['memory'] is True): + return "[!] Unsupported combination of 'address' (ASAN) and 'memory'" \ + " (MSAN) for option '-s'." + return CheckedSanitizers + + +# Parse command line options +def MyOptionParser(): + parser = argparse.ArgumentParser() + parser.add_argument("-a", "--arch", + choices=['IA32', 'X64', 'ARM', 'AARCH64'], + dest="TargetArch", default="IA32", + help="ARCHS is one of list: IA32, X64, ARM or AARCH64," + " which overrides target.txt's TARGET_ARCH " + "definition.") + parser.add_argument("-b", "--buildtarget", + dest="BuildTarget", default="DEBUG", + help="Using the TARGET to build the platform, " + "overriding target.txt's TARGET definition.") + parser.add_argument("-m", "--module", dest="ModuleFile", + help="Build the module specified by the INF file name " + "argument.") + parser.add_argument("-i", "--input", dest="InputSeed", + help="Test input seed path.") + parser.add_argument("-o", "--output", dest="Output", + help="Test output path for LibFuzzer.") + parser.add_argument("-s", "--sanitizer", dest="SANITIZER", + default='address', help="A comma-separated list of " + "sanitizers to run with LibFuzzer. E.g. '--sanitizer=" + "address'. Included sanitizers are: (ASAN) 'address'; " + "(MSAN) 'memory'; (UBSAN) 'undefined', 'integer', " + "'bounds', 'enum', and 'function'. NOTE: 'address' " + "and 'memory' cannot be used together. The default " + "sanitizer is 'address'. Support for Linux only.") + parser.add_argument("-c", "--commandline", dest="CommandLine", + choices=['rawcommand', 'manual'], + default='rawcommand', + help="This specifies how the fuzzer is initiated from " + "command-line for Linux-based distributions. Specify " + "either: 'rawcommand', or 'manual'. " + "Using the 'rawcommand' mode is recommended/default." + " The 'manual' option will build the module and " + "then simply print a command-line option that the " + "end-user can subsequently use to run LibFuzzer.") + parser.add_argument("-p", "--gen-profraw", dest="BuildProfraw", + choices=['t', 'T', 'true', 'True' or 'f', 'F', 'false', + 'False'], + default='False', help="Generate 'Source Based " + "Coverage' (Profraw) instead of the default " + "compilation option for gcov. Support for Linux " + "only. This setting will invoke the compilation " + "flags '-fprofile-instr-generate and " + "-fcoverage-mapping' for clang and libfuzzer.") + + args = parser.parse_args(sys.argv[1:]) + + # Tokenize and check list input, pass checked list onward to Build + args.SANITIZER = checkSanitizers(args.SANITIZER) + if "[!]" in args.SANITIZER: + print(args.SANITIZER) + parser.print_help() + os._exit(0) + + # Ensure bool + boolStrTrue = ['t', 'T', 'true', 'True'] + boolStrFalse = ['f', 'F', 'false', 'False'] + if (args.BuildProfraw not in boolStrTrue) and \ + (args.BuildProfraw not in boolStrFalse): + print("[!] Error for '-p, --gen-profraw' " + + "option: {}".format(args.BuildProfraw) + + " not supported. Please specify 'true' or 'false'.") + parser.print_help() + os._exit(0) + else: + if args.BuildProfraw in boolStrTrue: + args.BuildProfraw = True + elif args.BuildProfraw in boolStrFalse: + args.BuildProfraw = False + else: + print("[!] Unexpected error parsing input for -p, " + "--gen-profraw argument: {}".format(args.BuildProfraw)) + + return args + + +def updateBuildFlags(SanitizerFlags, buildProfraw): + # Update the build option file for HBFA: + # E.g. HBFA/UefiHostFuzzTestPkg/UefiHostFuzzTestBuildOption.dsc + print("Updating UefiHostFuzzTestBuildOption.dsc") + BasePath = HBFA_PATH + "/UefiHostFuzzTestPkg/" + OriginalBuildOptionFile = BasePath + \ + "UefiHostFuzzTestBuildOption.dsc.original" + # If OriginalBuildOptionFile does not exist, copy + # UefiHostFuzzTestBuildOption.dsc + if not os.path.isfile(OriginalBuildOptionFile): + shutil.copyfile(BasePath + "UefiHostFuzzTestBuildOption.dsc", + OriginalBuildOptionFile) + OutputBuildOptionFile = BasePath + "UefiHostFuzzTestBuildOption.dsc" + try: + frs = open(OriginalBuildOptionFile, 'rb') + raw = frs.read() + + profrawCcCovFlag = rb'-fprofile-instr-generate -fcoverage-mapping' + profrawLdCovFlag = rb'-fprofile-instr-generate -fcoverage-mapping' + + # Patch with appropriate coverage and sanitizer + if buildProfraw: + raw = re.sub(rb'GCC:\*_LIBFUZZER_\*_CC_FLAGS = ' + rb'"-DTEST_WITH_LIBFUZZER=TRUE" -O1 ' + rb'-fsanitize=fuzzer,address', + rb'GCC:*_LIBFUZZER_*_CC_FLAGS = "-DTEST_WITH_' + rb'LIBFUZZER=TRUE" -O1 ' + profrawCcCovFlag + + rb' -fsanitize=fuzzer' + + SanitizerFlags.encode(), raw) + raw = re.sub(rb'GCC:\*_LIBFUZZER_\*_DLINK2_FLAGS = -fsanitize=' + rb'fuzzer,address', + rb'GCC:*_LIBFUZZER_*_DLINK2_FLAGS = ' + + profrawLdCovFlag + + rb' -fsanitize=fuzzer' + SanitizerFlags.encode(), + raw) + raw = re.sub(rb'GCC:\*_CLANG8_\*_CC_FLAGS = -O1 -fsanitize=' + rb'address -fprofile-arcs -ftest-coverage', + rb'GCC:*_CLANG8_*_CC_FLAGS = -O1 ' + + profrawCcCovFlag + rb' -fsanitize=' + + SanitizerFlags[1::].encode(), raw) + raw = re.sub(rb'GCC:\*_CLANG8_\*_DLINK2_FLAGS = -fsanitize=address' + rb' --coverage', rb'GCC:*_CLANG8_*_DLINK2_FLAGS = ' + rb'-fsanitize=' + SanitizerFlags[1::].encode() + rb' ' + + profrawLdCovFlag, raw) + else: + raw = re.sub(rb'GCC:\*_LIBFUZZER_\*_CC_FLAGS = ' + rb'"-DTEST_WITH_LIBFUZZER=TRUE" -O1 ' + rb'-fsanitize=fuzzer,address', + rb'GCC:*_LIBFUZZER_*_CC_FLAGS = ' + rb'"-DTEST_WITH_LIBFUZZER=TRUE" -O1' + rb' -fsanitize=fuzzer' + + SanitizerFlags.encode(), raw) + raw = re.sub(rb'GCC:\*_LIBFUZZER_\*_DLINK2_FLAGS = -fsanitize=' + rb'fuzzer,address', + rb'GCC:*_LIBFUZZER_*_DLINK2_FLAGS = -fsanitize=fuzzer' + + SanitizerFlags.encode(), raw) + raw = re.sub(rb'GCC:\*_CLANG8_\*_CC_FLAGS = -O1 -fsanitize=address' + rb' -fprofile-arcs -ftest-coverage', + rb'GCC:*_CLANG8_*_CC_FLAGS = -O1 -fsanitize=' + + SanitizerFlags[1::].encode() + + rb' -fprofile-arcs -ftest-coverage', raw) + raw = re.sub(rb'GCC:\*_CLANG8_\*_DLINK2_FLAGS = -fsanitize=address' + rb' --coverage', rb'GCC:*_CLANG8_*_DLINK2_FLAGS = ' + rb'-fsanitize=' + SanitizerFlags[1::].encode() + + rb' --coverage', raw) + + # Write out file + fws = open(OutputBuildOptionFile, 'wb') + fws.write(raw) + frs.close() + fws.close() + except Exception as err: + print("[!] Error attempting to patch build description file " + "UefiHostFuzzTestBuildOption.dsc: {}".format(err)) + os._exit(0) + + +def restoreBuildOptionFile(): + # Restore the original UefiHostFuzzTestBuildOption.dsc file for HBFA + BasePath = HBFA_PATH + "/UefiHostFuzzTestPkg/" + OriginalBuildOptionFile = BasePath + \ + "UefiHostFuzzTestBuildOption.dsc.original" + OutputBuildOptionFile = BasePath + "UefiHostFuzzTestBuildOption.dsc" + if os.path.isfile(OriginalBuildOptionFile): + try: + shutil.copyfile(OriginalBuildOptionFile, OutputBuildOptionFile) + except IOError as err: + print("[!] Error making backup of UefiHostFuzzTestBuildOption.dsc" + " file: {}".format(err)) + else: + print("[!] Error: backup copy of UefiHostFuzzTestBuildOption.dsc not " + "found at path: {}".format(OriginalBuildOptionFile)) + + +def main(): + args = MyOptionParser() + TargetArch = args.TargetArch + BuildTarget = args.BuildTarget + + CheckTestEnv(TargetArch) + + if (SysType == 'Linux'): + if (TargetArch == "IA32") ^ Is32bit: + print("For CLANG: {}".format("i386" if Is32bit else "x64_86") + + "system cannot support arch {} build.".format(TargetArch)) + os._exit(0) + + if not args.ModuleFile: + print("ModuleFile should be set once by command -m MODULEFILE, " + "--module=MODULEFILE.") + os._exit(0) + elif os.path.isabs(args.ModuleFile): + if args.ModuleFile.startswith(HBFA_PATH): + ModuleFilePath = os.path.relpath(args.ModuleFile, HBFA_PATH) + else: + print("ModuleFile path: {}".format(args.ModuleFile) + + " should start with {}.".format(HBFA_PATH)) + os._exit(0) + elif not os.path.exists(os.path.join(HBFA_PATH, args.ModuleFile)): + print("ModuleFile path: {}".format(os.path.abspath(args.InputSeed)) + + " does not exist or is not in the relative path for HBFA") + os._exit(0) + else: + ModuleFilePath = args.ModuleFile + + OutputPath = args.Output if args.Output \ + else os.path.join(os.getcwd(), 'failureSeeds') + if not os.path.isabs(OutputPath): + OutputPath = os.path.join(os.getcwd(), OutputPath) + if not os.path.exists(OutputPath): + try: + os.makedirs(OutputPath) + except Exception as err: + print(err) + elif os.path.exists(os.path.join(OutputPath, 'fuzzfile.bin')): + print("OutputPath:{} has already".format(OutputPath) + + " been used for LibFuzzer test, please change another" + " directory.") + os._exit(0) + print("LibFuzzer output will be generated in current " + "directory:{}".format(OutputPath)) + + InputSeedPath = args.InputSeed if args.InputSeed \ + else os.path.join(os.getcwd(), 'Seeds') + if not os.path.isabs(InputSeedPath): + InputSeedPath = os.path.join(os.getcwd(), InputSeedPath) + if not os.path.exists(InputSeedPath): + try: + os.makedirs(InputSeedPath) + except Exception as err: + print(err) + + if (SysType == 'Linux'): + global CommandLineMode + CommandLineMode = args.CommandLine + + if (SysType == 'Linux'): + updateBuildFlags(args.SANITIZER, args.BuildProfraw) + + TestModuleBinPath = Build(TargetArch, BuildTarget, ModuleFilePath) + + if (SysType == 'Linux'): + restoreBuildOptionFile() + + RunLibFuzzer(TestModuleBinPath, InputSeedPath, OutputPath) + + +if __name__ == "__main__": + main() diff --git a/HBFA/UefiHostTestTools/Script/RunAllSeeds.py b/HBFA/UefiHostTestTools/Script/RunAllSeeds.py new file mode 100644 index 0000000..17ac44e --- /dev/null +++ b/HBFA/UefiHostTestTools/Script/RunAllSeeds.py @@ -0,0 +1,35 @@ +# @file +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +import os +import sys +import subprocess + +workdir = os.getcwd() + +tcsbin_path = sys.argv[1] +findings_dir_path = sys.argv[2] + + +def run_all_seeds(): + for root, dirs, files in os.walk(findings_dir_path): + for dir in dirs: + if dir in ['crashed', 'hangs', 'queue']: + dir_path = os.path.join(root, dir) + for file in os.listdir(dir_path): + file_path = os.path.join(dir_path, file) + if os.path.isfile(file_path): + cmd = './' + tcsbin_path + ' ' + file_path + print(cmd) + try: + subprocess.run(cmd.split(' '), shell=False, + check=True) + except subprocess.CalledProcessError as e: + print(e) + + +if __name__ == '__main__': + run_all_seeds() diff --git a/HBFA/UefiHostTestTools/Script/TransferKtestToSeed.py b/HBFA/UefiHostTestTools/Script/TransferKtestToSeed.py new file mode 100644 index 0000000..53ab5e2 --- /dev/null +++ b/HBFA/UefiHostTestTools/Script/TransferKtestToSeed.py @@ -0,0 +1,113 @@ +# @file +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +import os +import struct +import sys + +# python version +python_version = sys.version_info[0] + + +def getPath(): + fileList = [] + for path in sys.argv[1:]: + if not os.path.exists(path): + continue + if os.path.isfile(path): + if checkFile(path): + fileList.append(path) + else: + subPathList = os.listdir(path) + for i in range(0, len(subPathList)): + subPath = os.path.join(path, subPathList[i]) + if os.path.isfile(subPath) and checkFile(subPath): + fileList.append(subPath) + if not fileList: + print("The input is neither ktest format file nor folder that " + "include ktest format file.\n") + printUsage() + return fileList + + +def checkFile(file): + kTestFile = open(file, 'rb') + kTestHeader = kTestFile.read(5) + kTestFile.close() + if kTestHeader == b'KTEST' or kTestHeader == b"BOUT\n": + return True + else: + return False + + +def analyseFile(file): + objectList = [] + kTestFile = open(file, 'rb') + kTestFile.read(5) + kTestVersion = struct.unpack('>i', kTestFile.read(4))[0] + targetNum = struct.unpack('>i', kTestFile.read(4))[0] + for i in range(targetNum): + kTestFile.read(struct.unpack('>i', kTestFile.read(4))[0]) + + if kTestVersion >= 2: + kTestFile.read(8) + + objectNum, = struct.unpack('>i', kTestFile.read(4)) + for i in range(objectNum): + objectName = kTestFile.read(struct.unpack('>i', kTestFile.read(4))[0]) + objectData = kTestFile.read(struct.unpack('>i', kTestFile.read(4))[0]) + if python_version == 3: + objectName = objectName.decode() + objectList.append([i, objectName, objectData]) + kTestFile.close() + return objectList + + +def genNewName(file, objectIndex, objectName): + return os.path.join(os.path.dirname(file), + objectName + str(objectIndex + 1).zfill(6), + os.path.basename(file).split('.')[0] + '.seed') + + +def genSeed(file, data): + if not os.path.exists(os.path.dirname(file)): + os.makedirs(os.path.dirname(file)) + seed = open(file, 'wb') + seed.write(data) + seed.close() + + +def printUsage(): + print("Usage: python TransferKtestToSeed.py [Argument]") + print("Remove header of ktest format file, and save the new binary file " + "as .seed file.\n") + print("Argument:") + print(" the path of .ktest file.") + print(" ... the paths of .ktest files.") + print(" the path of folder contains " + ".ktest file.") + print(" ... the paths of folders contain " + ".ktest file.") + + +if __name__ == '__main__': + if len(sys.argv) < 2: + printUsage() + elif ( + sys.argv[1] == '-h' + or sys.argv[1] == 'help' + or sys.argv[1] == '--help' + ): + printUsage() + else: + fileList = getPath() + + for file in fileList: + objectList = analyseFile(file) + for object in objectList: + NewFileName = genNewName(file, object[0], object[1]) + genSeed(NewFileName, object[2]) + print('generate %s done.' % NewFileName) diff --git a/HBFA/UefiHostTestTools/__init__.py b/HBFA/UefiHostTestTools/__init__.py new file mode 100755 index 0000000..e69de29 diff --git a/HBFA/UefiHostTestTools/__pycache__/RunAFL.cpython-311.pyc b/HBFA/UefiHostTestTools/__pycache__/RunAFL.cpython-311.pyc new file mode 100644 index 0000000..e1235e9 Binary files /dev/null and b/HBFA/UefiHostTestTools/__pycache__/RunAFL.cpython-311.pyc differ diff --git a/HBFA/UefiHostTestTools/__pycache__/RunAFLTurbo.cpython-311.pyc b/HBFA/UefiHostTestTools/__pycache__/RunAFLTurbo.cpython-311.pyc new file mode 100644 index 0000000..e8fcda7 Binary files /dev/null and b/HBFA/UefiHostTestTools/__pycache__/RunAFLTurbo.cpython-311.pyc differ diff --git a/HBFA/UefiHostTestTools/__pycache__/RunKLEE.cpython-311.pyc b/HBFA/UefiHostTestTools/__pycache__/RunKLEE.cpython-311.pyc new file mode 100644 index 0000000..531e511 Binary files /dev/null and b/HBFA/UefiHostTestTools/__pycache__/RunKLEE.cpython-311.pyc differ diff --git a/HBFA/UefiHostTestTools/__pycache__/RunLibFuzzer.cpython-311.pyc b/HBFA/UefiHostTestTools/__pycache__/RunLibFuzzer.cpython-311.pyc new file mode 100644 index 0000000..43ad7e5 Binary files /dev/null and b/HBFA/UefiHostTestTools/__pycache__/RunLibFuzzer.cpython-311.pyc differ diff --git a/HBFA/UefiHostTestTools/__pycache__/__init__.cpython-311.pyc b/HBFA/UefiHostTestTools/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..b336db6 Binary files /dev/null and b/HBFA/UefiHostTestTools/__pycache__/__init__.cpython-311.pyc differ diff --git a/HBFA/UefiInstrumentTestCasePkg/ReadMe-BME.txt b/HBFA/UefiInstrumentTestCasePkg/ReadMe-BME.txt new file mode 100644 index 0000000..90f8239 --- /dev/null +++ b/HBFA/UefiInstrumentTestCasePkg/ReadMe-BME.txt @@ -0,0 +1,32 @@ +How to collect PCI BME access in BIOS? +============== +1) Add below in Platform.dsc + +[LibraryClasses.common] + NULL|UefiInstrumentTestPkg/Library/InstrumentLib/InstrumentLib.inf + InstrumentHookLib|UefiInstrumentTestPkg/TestCase/InstrumentHookLibTracingPci/InstrumentHookLibTracingPci.inf + + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf + SerialPortLib|PcAtChipsetPkg/Library/SerialIoLib/SerialIoLib.inf + +NOTE: The UefiInstrumentTestPkg provides the hook capability. +NOTE: Overriding debug serial port lib is needed, because we want to use simple serial port output to dump the resource access. + +2) Add below in Platform.dsc + +[Components] + + MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf { + + MSFT: *_*_*_CC_FLAGS = /Gh /GH /Od /GL- + } + +3) Build and run the new BIOS image. +You may see some resource access below: + +RSC_TRACE: MmioRead8(0xE00F9004->0x06) - FFF0ACA0 from FFF0AB41 (*** TOUCH PCIE BME ***) +RSC_TRACE: MmioWrite8(0xE00F9004<-0x06) - FFF0ADF0 from FFF0AB57 (*** TOUCH PCIE BME ***) + +RSC_TRACE: IoWrite32(0xCF8<-0x80000004) - 89FEF558 from 89FEE52A (*** TOUCH PCI BME ***) +RSC_TRACE: IoRead32(0xCFC->0x20900006) - 89FEF46C from 89FEE532 diff --git a/HBFA/UefiInstrumentTestCasePkg/TestCase/InstrumentHookLibTracingPci/InstrumentHookLibTracingPci.c b/HBFA/UefiInstrumentTestCasePkg/TestCase/InstrumentHookLibTracingPci/InstrumentHookLibTracingPci.c new file mode 100644 index 0000000..7f32ac3 --- /dev/null +++ b/HBFA/UefiInstrumentTestCasePkg/TestCase/InstrumentHookLibTracingPci/InstrumentHookLibTracingPci.c @@ -0,0 +1,696 @@ +/** @file + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include + +#define PcdPciExpressRegionLength SIZE_1MB +#define PcdPciReservedIobase 0x2000 + +typedef +UINTN +(EFIAPI *HOOK_FUNC_ENTER) ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ); + +typedef +VOID +(EFIAPI *HOOK_FUNC_EXIT) ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ); + +typedef struct { + CHAR16 *Name; + UINTN Func; + UINTN HookFuncEnter; + UINTN HookFuncExit; +} FUNC_HOOK; + +BOOLEAN +ProcessMmioAddress ( + IN UINTN Address + ) +{ + // Skip below: + // IoApic (FEC00000) + // HPET (FED00000) + // TPM (FED40000) + // LocalApic (FEE00000) + if (Address >= 0xFEC00000) { + return FALSE; + } + // Skip normal MMIO + if (Address <= PcdGet64(PcdPciExpressBaseAddress)) { + return FALSE; + } + return TRUE; +} + +BOOLEAN +ProcessIoAddress ( + IN UINTN Address + ) +{ + // Skip the ones in DEBUG path. + // Serial port + if (Address >= 0x3F8 && Address <= 0x3FF) { + return FALSE; + } + // CMOS-RTC + if (Address >= 0x70 && Address <= 0x77) { + return FALSE; + } + // Skip normal IO + if (Address > PcdPciReservedIobase) { + return FALSE; + } + return TRUE; +} + +VOID +CheckPcieBme ( + IN UINTN MmioAddress + ) +{ + UINTN Offset; + if (MmioAddress >= PcdGet64(PcdPciExpressBaseAddress) + PcdPciExpressRegionLength) { + return ; + } + if (MmioAddress < PcdGet64(PcdPciExpressBaseAddress)) { + return ; + } + // BME is in the first byte of CMD + Offset = MmioAddress & 0xFFF; + if (Offset != PCI_COMMAND_OFFSET) { + return ; + } + DEBUG ((DEBUG_INFO, " (*** TOUCH PCIE BME ***)")); +} + +VOID +CheckPciBme ( + IN UINTN IoAddress, + IN UINTN IoValue + ) +{ + UINTN Offset; + if (IoAddress != 0xCF8) { + return ; + } + // BME is in the first byte of CMD + Offset = IoValue & 0xFF; + if (Offset != PCI_COMMAND_OFFSET) { + return ; + } + DEBUG ((DEBUG_INFO, " (*** TOUCH PCI BME ***)")); +} + +UINTN +EFIAPI +MmioRead8Enter ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + UINTN Address; + + Address = GetParameterValue (EntryContext, 1); + if (!ProcessMmioAddress (Address)) { + return 0; + } + DEBUG((DEBUG_INFO, "RSC_TRACE: MmioRead8(0x%x", Address)); + return 0; +} + +VOID +EFIAPI +MmioRead8Exit ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + UINTN Address; + UINT8 Value; + + Value = (UINT8)GetReturnValue (ExitContext); + Address = GetReturnParameterValue (ExitContext, 1); + if (!ProcessMmioAddress (Address)) { + return ; + } + DEBUG((DEBUG_INFO, "->0x%02x) - %x from %x", Value, FunctionAddress, CallerAddress)); + CheckPcieBme (Address); + DEBUG((DEBUG_INFO, "\n")); + return ; +} + +UINTN +EFIAPI +MmioRead16Enter ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + UINTN Address; + + Address = GetParameterValue (EntryContext, 1); + if (!ProcessMmioAddress (Address)) { + return 0; + } + DEBUG((DEBUG_INFO, "RSC_TRACE: MmioRead16(0x%x", Address)); + return 0; +} + +VOID +EFIAPI +MmioRead16Exit ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + UINTN Address; + UINT16 Value; + + Value = (UINT16)GetReturnValue (ExitContext); + Address = GetReturnParameterValue (ExitContext, 1); + if (!ProcessMmioAddress (Address)) { + return ; + } + DEBUG((DEBUG_INFO, "->0x%04x) - %x from %x", Value, FunctionAddress, CallerAddress)); + CheckPcieBme (Address); + DEBUG((DEBUG_INFO, "\n")); + return ; +} + +UINTN +EFIAPI +MmioRead32Enter ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + UINTN Address; + + Address = GetParameterValue (EntryContext, 1); + if (!ProcessMmioAddress (Address)) { + return 0; + } + DEBUG((DEBUG_INFO, "RSC_TRACE: MmioRead32(0x%x", Address)); + return 0; +} + +VOID +EFIAPI +MmioRead32Exit ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + UINTN Address; + UINT32 Value; + + Value = (UINT32)GetReturnValue (ExitContext); + Address = GetReturnParameterValue (ExitContext, 1); + if (!ProcessMmioAddress (Address)) { + return ; + } + DEBUG((DEBUG_INFO, "->0x%08x) - %x from %x", Value, FunctionAddress, CallerAddress)); + CheckPcieBme (Address); + DEBUG((DEBUG_INFO, "\n")); + return ; +} + +UINTN +EFIAPI +MmioRead64Enter ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + UINTN Address; + + Address = GetParameterValue (EntryContext, 1); + if (!ProcessMmioAddress (Address)) { + return 0; + } + DEBUG((DEBUG_INFO, "RSC_TRACE: MmioRead64(0x%x", Address)); + return 0; +} + +VOID +EFIAPI +MmioRead64Exit ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + UINTN Address; + UINT64 Value; + + Value = GetReturnValue64 (ExitContext); + Address = GetReturnParameterValue (ExitContext, 1); + if (!ProcessMmioAddress (Address)) { + return ; + } + DEBUG((DEBUG_INFO, "->0x%016lx) - %x from %x", Value, FunctionAddress, CallerAddress)); + CheckPcieBme (Address); + DEBUG((DEBUG_INFO, "\n")); + return ; +} + +UINTN +EFIAPI +MmioWrite8Enter ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + UINTN Address; + UINT8 Value; + + Address = GetParameterValue (EntryContext, 1); + if (!ProcessMmioAddress (Address)) { + return 0; + } + Value = (UINT8)GetParameterValue (EntryContext, 2); + DEBUG((DEBUG_INFO, "RSC_TRACE: MmioWrite8(0x%x<-0x%02x) - %x from %x", Address, Value, FunctionAddress, CallerAddress)); + CheckPcieBme (Address); + DEBUG((DEBUG_INFO, "\n")); + return 0; +} + +VOID +EFIAPI +MmioWrite8Exit ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ +} + +UINTN +EFIAPI +MmioWrite16Enter ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + UINTN Address; + UINT16 Value; + + Address = GetParameterValue (EntryContext, 1); + if (!ProcessMmioAddress (Address)) { + return 0; + } + Value = (UINT16)GetParameterValue (EntryContext, 2); + DEBUG((DEBUG_INFO, "RSC_TRACE: MmioWrite16(0x%x<-0x%04x) - %x from %x", Address, Value, FunctionAddress, CallerAddress)); + CheckPcieBme (Address); + DEBUG((DEBUG_INFO, "\n")); + return 0; +} + +VOID +EFIAPI +MmioWrite16Exit ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ +} + +UINTN +EFIAPI +MmioWrite32Enter ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + UINTN Address; + UINT32 Value; + + Address = GetParameterValue (EntryContext, 1); + if (!ProcessMmioAddress (Address)) { + return 0; + } + Value = (UINT32)GetParameterValue (EntryContext, 2); + DEBUG((DEBUG_INFO, "RSC_TRACE: MmioWrite32(0x%x<-0x%08x) - %x from %x", Address, Value, FunctionAddress, CallerAddress)); + CheckPcieBme (Address); + DEBUG((DEBUG_INFO, "\n")); + return 0; +} + +VOID +EFIAPI +MmioWrite32Exit ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ +} + +UINTN +EFIAPI +MmioWrite64Enter ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + UINTN Address; + UINT64 Value; + + Address = GetParameterValue (EntryContext, 1); + if (!ProcessMmioAddress (Address)) { + return 0; + } + Value = GetParameterValue64 (EntryContext, 2); + DEBUG((DEBUG_INFO, "RSC_TRACE: MmioWrite64(0x%x<-0x%016lx) - %x from %x", Address, Value, FunctionAddress, CallerAddress)); + CheckPcieBme (Address); + DEBUG((DEBUG_INFO, "\n")); + return 0; +} + +VOID +EFIAPI +MmioWrite64Exit ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ +} + +UINTN +EFIAPI +IoRead8Enter ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + UINTN Address; + + Address = GetParameterValue (EntryContext, 1); + if (!ProcessIoAddress (Address)) { + return 0; + } + DEBUG((DEBUG_INFO, "RSC_TRACE: IoRead8(0x%x", Address)); + return 0; +} + +VOID +EFIAPI +IoRead8Exit ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + UINTN Address; + UINT8 Value; + + Value = (UINT8)GetReturnValue (ExitContext); + Address = GetReturnParameterValue (ExitContext, 1); + if (!ProcessIoAddress (Address)) { + return ; + } + DEBUG((DEBUG_INFO, "->0x%02x) - %x from %x", Value, FunctionAddress, CallerAddress)); + CheckPciBme (Address, Value); + DEBUG((DEBUG_INFO, "\n")); + return ; +} + +UINTN +EFIAPI +IoRead16Enter ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + UINTN Address; + + Address = GetParameterValue (EntryContext, 1); + if (!ProcessIoAddress (Address)) { + return 0; + } + DEBUG((DEBUG_INFO, "RSC_TRACE: IoRead16(0x%x", Address)); + return 0; +} + +VOID +EFIAPI +IoRead16Exit ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + UINTN Address; + UINT16 Value; + + Value = (UINT16)GetReturnValue (ExitContext); + Address = GetReturnParameterValue (ExitContext, 1); + if (!ProcessIoAddress (Address)) { + return ; + } + DEBUG((DEBUG_INFO, "->0x%04x) - %x from %x", Value, FunctionAddress, CallerAddress)); + CheckPciBme (Address, Value); + DEBUG((DEBUG_INFO, "\n")); + return ; +} + +UINTN +EFIAPI +IoRead32Enter ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + UINTN Address; + + Address = GetParameterValue (EntryContext, 1); + if (!ProcessIoAddress (Address)) { + return 0; + } + DEBUG((DEBUG_INFO, "RSC_TRACE: IoRead32(0x%x", Address)); + return 0; +} + +VOID +EFIAPI +IoRead32Exit ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + UINTN Address; + UINT32 Value; + + Value = (UINT32)GetReturnValue (ExitContext); + Address = GetReturnParameterValue (ExitContext, 1); + if (!ProcessIoAddress (Address)) { + return ; + } + DEBUG((DEBUG_INFO, "->0x%08x) - %x from %x", Value, FunctionAddress, CallerAddress)); + CheckPciBme (Address, Value); + DEBUG((DEBUG_INFO, "\n")); + return ; +} + +UINTN +EFIAPI +IoWrite8Enter ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + UINTN Address; + UINT8 Value; + + Address = GetParameterValue (EntryContext, 1); + if (!ProcessIoAddress (Address)) { + return 0; + } + Value = (UINT8)GetParameterValue (EntryContext, 2); + DEBUG((DEBUG_INFO, "RSC_TRACE: IoWrite8(0x%x<-0x%02x) - %x from %x", Address, Value, FunctionAddress, CallerAddress)); + CheckPciBme (Address, Value); + DEBUG((DEBUG_INFO, "\n")); + return 0; +} + +VOID +EFIAPI +IoWrite8Exit ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ +} + +UINTN +EFIAPI +IoWrite16Enter ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + UINTN Address; + UINT16 Value; + + Address = GetParameterValue (EntryContext, 1); + if (!ProcessIoAddress (Address)) { + return 0; + } + Value = (UINT16)GetParameterValue (EntryContext, 2); + DEBUG((DEBUG_INFO, "RSC_TRACE: IoWrite16(0x%x<-0x%04x) - %x from %x", Address, Value, FunctionAddress, CallerAddress)); + CheckPciBme (Address, Value); + DEBUG((DEBUG_INFO, "\n")); + return 0; +} + +VOID +EFIAPI +IoWrite16Exit ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ +} + +UINTN +EFIAPI +IoWrite32Enter ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + UINTN Address; + UINT32 Value; + + Address = GetParameterValue (EntryContext, 1); + if (!ProcessIoAddress (Address)) { + return 0; + } + Value = (UINT32)GetParameterValue (EntryContext, 2); + DEBUG((DEBUG_INFO, "RSC_TRACE: IoWrite32(0x%x<-0x%08x) - %x from %x", Address, Value, FunctionAddress, CallerAddress)); + CheckPciBme (Address, Value); + DEBUG((DEBUG_INFO, "\n")); + return 0; +} + +VOID +EFIAPI +IoWrite32Exit ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ +} + +GLOBAL_REMOVE_IF_UNREFERENCED FUNC_HOOK mFuncHook[] = { + {L"MmioRead8", (UINTN)MmioRead8, (UINTN)MmioRead8Enter, (UINTN)MmioRead8Exit}, + {L"MmioRead16", (UINTN)MmioRead16, (UINTN)MmioRead16Enter, (UINTN)MmioRead16Exit}, + {L"MmioRead32", (UINTN)MmioRead32, (UINTN)MmioRead32Enter, (UINTN)MmioRead32Exit}, + {L"MmioRead64", (UINTN)MmioRead64, (UINTN)MmioRead64Enter, (UINTN)MmioRead64Exit}, + {L"MmioWrite8", (UINTN)MmioWrite8, (UINTN)MmioWrite8Enter, (UINTN)MmioWrite8Exit}, + {L"MmioWrite16", (UINTN)MmioWrite16, (UINTN)MmioWrite16Enter, (UINTN)MmioWrite16Exit}, + {L"MmioWrite32", (UINTN)MmioWrite32, (UINTN)MmioWrite32Enter, (UINTN)MmioWrite32Exit}, + {L"MmioWrite64", (UINTN)MmioWrite64, (UINTN)MmioWrite64Enter, (UINTN)MmioWrite64Exit}, + {L"IoRead8", (UINTN)IoRead8, (UINTN)IoRead8Enter, (UINTN)IoRead8Exit}, + {L"IoRead16", (UINTN)IoRead16, (UINTN)IoRead16Enter, (UINTN)IoRead16Exit}, + {L"IoRead32", (UINTN)IoRead32, (UINTN)IoRead32Enter, (UINTN)IoRead32Exit}, + {L"IoWrite8", (UINTN)IoWrite8, (UINTN)IoWrite8Enter, (UINTN)IoWrite8Exit}, + {L"IoWrite16", (UINTN)IoWrite16, (UINTN)IoWrite16Enter, (UINTN)IoWrite16Exit}, + {L"IoWrite32", (UINTN)IoWrite32, (UINTN)IoWrite32Enter, (UINTN)IoWrite32Exit}, +}; + +FUNC_HOOK * +GetFuncHook ( + IN UINTN FuncAddr + ) +{ + UINTN Index; + for (Index = 0; Index < ARRAY_SIZE(mFuncHook); Index++) { + if (FuncAddr == mFuncHook[Index].Func) { + return &mFuncHook[Index]; + } + } + return NULL; +} + +UINTN +EFIAPI +FunctionEnter ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + FUNC_HOOK *FuncHook; + HOOK_FUNC_ENTER HookFunc; + + FuncHook = GetFuncHook (FunctionAddress); + if (FuncHook == NULL) { + return 0; + } + if (FuncHook->HookFuncEnter == 0) { + return 0; + } + HookFunc = (HOOK_FUNC_ENTER)(FuncHook->HookFuncEnter); + return HookFunc (EntryContext, FunctionAddress, CallerAddress); +} + +VOID +EFIAPI +FunctionExit ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + FUNC_HOOK *FuncHook; + HOOK_FUNC_EXIT HookFunc; + + FuncHook = GetFuncHook (FunctionAddress); + if (FuncHook == NULL) { + return ; + } + if (FuncHook->HookFuncExit == 0) { + return ; + } + HookFunc = (HOOK_FUNC_EXIT)(FuncHook->HookFuncExit); + HookFunc (ExitContext, FunctionAddress, CallerAddress); +} diff --git a/HBFA/UefiInstrumentTestCasePkg/TestCase/InstrumentHookLibTracingPci/InstrumentHookLibTracingPci.inf b/HBFA/UefiInstrumentTestCasePkg/TestCase/InstrumentHookLibTracingPci/InstrumentHookLibTracingPci.inf new file mode 100644 index 0000000..33a27c6 --- /dev/null +++ b/HBFA/UefiInstrumentTestCasePkg/TestCase/InstrumentHookLibTracingPci/InstrumentHookLibTracingPci.inf @@ -0,0 +1,36 @@ +## @file +# +# Copyright (c) 2017, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = InstrumentHookLibTracingPci + FILE_GUID = 7973B1E7-660A-486A-87D9-8EEE17079B9B + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = InstrumentHookLib + +[Sources] + InstrumentHookLibTracingPci.c + +[Packages] + MdePkg/MdePkg.dec + UefiInstrumentTestPkg/UefiInstrumentTestPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib + IoLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress + +[BuildOptions] + MSFT:*_*_*_CC_FLAGS = /Od /GL- + GCC:*_*_*_CC_FLAGS = -O0 + diff --git a/HBFA/UefiInstrumentTestCasePkg/TestCase/Usb2HcHook/Usb2HcHook.c b/HBFA/UefiInstrumentTestCasePkg/TestCase/Usb2HcHook/Usb2HcHook.c new file mode 100644 index 0000000..73e3f3c --- /dev/null +++ b/HBFA/UefiInstrumentTestCasePkg/TestCase/Usb2HcHook/Usb2HcHook.c @@ -0,0 +1,717 @@ +/** @file + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include + +EFI_EVENT mUsbHookEvent; +VOID *mUsbHookRegistration; + +#define USB2_HC_HOOK_PRIVATE_SIGNATURE SIGNATURE_32 ('U', 'H', 'H', 'K') + +typedef struct { + UINTN Signature; + EFI_USB2_HC_PROTOCOL OrgUsb2Hc; + EFI_USB2_HC_PROTOCOL *Usb2Hc; + LIST_ENTRY Link; +} USB2_HC_HOOK_PRIVATE; + +LIST_ENTRY mUsb2HcHookQueue = INITIALIZE_LIST_HEAD_VARIABLE (mUsb2HcHookQueue); + +VOID +InternalDumpData ( + IN UINT8 *Data, + IN UINTN Size + ) +{ + UINTN Index; + for (Index = 0; Index < Size; Index++) { + DEBUG ((EFI_D_INFO, "%02x", (UINTN)Data[Index])); + } +} + +#define USB_REQUEST_TYPE_TYPE_STANDARD 0 + +typedef union { + struct { + UINT8 Recipient:5; + UINT8 Type:2; + UINT8 Direction:1; + } Bits; + UINT8 Data; +} USB_REQUEST_TYPE; + +CHAR8 *mUsbRequestTypeRecipientStr[] = { + "Device", + "Interface", + "Endpoint", + "Other", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Vendor", +}; + +CHAR8 *mUsbRequestTypeTypeStr[] = { + "Standard", + "Class", + "Vendor", + "Reserved", +}; + +CHAR8 *mUsbRequestTypeDirectionStr[] = { + "H-D", + "D-H", +}; + +CHAR8 mRequestTypeStringTemplate[] = "H-D Standard Interface"; + +CHAR8 * +UsbRequestTypeToString ( + IN EFI_USB_DEVICE_REQUEST *Request + ) +{ + USB_REQUEST_TYPE ReqType; + + ReqType.Data = Request->RequestType; + AsciiStrCpyS (mRequestTypeStringTemplate, sizeof(mRequestTypeStringTemplate), mUsbRequestTypeDirectionStr[ReqType.Bits.Direction]); + AsciiStrCatS (mRequestTypeStringTemplate, sizeof(mRequestTypeStringTemplate), " "); + AsciiStrCatS (mRequestTypeStringTemplate, sizeof(mRequestTypeStringTemplate), mUsbRequestTypeTypeStr[ReqType.Bits.Type]); + AsciiStrCatS (mRequestTypeStringTemplate, sizeof(mRequestTypeStringTemplate), " "); + AsciiStrCatS (mRequestTypeStringTemplate, sizeof(mRequestTypeStringTemplate), mUsbRequestTypeRecipientStr[ReqType.Bits.Recipient]); + return mRequestTypeStringTemplate; +} + +CHAR8 *mUsbRequestRequestStr[] = { + "GET_STATUS", + "CLEAR_FEATURE", + "reserved", + "SET_FEATURE", + "reserved", + "SET_ADDRESS", + "GET_DESCRIPTOR", + "SET_DESCRIPTOR", + "GET_CONFIG", + "SET_CONFIG", + "GET_INTERFACE", + "SET_INTERFACE", + "SYNCH_FRAME", +}; + +CHAR8 * +UsbRequestRequestToString ( + IN EFI_USB_DEVICE_REQUEST *Request + ) +{ + USB_REQUEST_TYPE ReqType; + + ReqType.Data = Request->RequestType; + if (ReqType.Bits.Type == USB_REQUEST_TYPE_TYPE_STANDARD) { + if (Request->Request < ARRAY_SIZE(mUsbRequestRequestStr)) { + return mUsbRequestRequestStr[Request->Request]; + } + } + return ""; +} + +typedef union { + struct { + UINT8 DescIndex; + UINT8 DescType; + } Bits; + UINT16 Data; +} USB_REQUEST_DESCRIPTOR; + +CHAR8 *mUsbRequestValueDescriptorTypeStr[] = { + "", + "DEVICE", + "CONFIG", + "STRING", + "INTERFACE", + "ENDPOINT", +}; + +CHAR8 * +UsbRequestValueToString ( + IN EFI_USB_DEVICE_REQUEST *Request + ) +{ + USB_REQUEST_TYPE ReqType; + USB_REQUEST_DESCRIPTOR Descriptor; + + ReqType.Data = Request->RequestType; + if (ReqType.Bits.Type == USB_REQUEST_TYPE_TYPE_STANDARD) { + if (Request->Request == USB_REQ_GET_DESCRIPTOR) { + Descriptor.Data = Request->Value; + if (Descriptor.Bits.DescType < ARRAY_SIZE(mUsbRequestValueDescriptorTypeStr)) { + return mUsbRequestValueDescriptorTypeStr[Descriptor.Bits.DescType]; + } else if (Descriptor.Bits.DescType == USB_DESC_TYPE_HID) { + return "HID"; + } else if (Descriptor.Bits.DescType == USB_DESC_TYPE_REPORT) { + return "REPORT"; + } + } + } + return ""; +} + +USB2_HC_HOOK_PRIVATE * +GetUsb2HcHookPrivateFromThis ( + IN EFI_USB2_HC_PROTOCOL *This + ) +{ + LIST_ENTRY *Usb2HcHookLink; + LIST_ENTRY *Usb2HcHookList; + USB2_HC_HOOK_PRIVATE *Usb2HcHookPrivate; + + Usb2HcHookList = &mUsb2HcHookQueue; + for (Usb2HcHookLink = Usb2HcHookList->ForwardLink; + Usb2HcHookLink != Usb2HcHookList; + Usb2HcHookLink = Usb2HcHookLink->ForwardLink) { + Usb2HcHookPrivate = CR ( + Usb2HcHookLink, + USB2_HC_HOOK_PRIVATE, + Link, + USB2_HC_HOOK_PRIVATE_SIGNATURE + ); + if (Usb2HcHookPrivate->Usb2Hc == This) { + return Usb2HcHookPrivate; + } + } + + ASSERT(FALSE); + return NULL; +} + +EFI_STATUS +EFIAPI +Usb2HcHookGetCapability ( + IN EFI_USB2_HC_PROTOCOL *This, + OUT UINT8 *MaxSpeed, + OUT UINT8 *PortNumber, + OUT UINT8 *Is64BitCapable + ) +{ + USB2_HC_HOOK_PRIVATE *Usb2HcHookPrivate; + EFI_STATUS Status; + + Usb2HcHookPrivate = GetUsb2HcHookPrivateFromThis (This); + Status = Usb2HcHookPrivate->OrgUsb2Hc.GetCapability ( + Usb2HcHookPrivate->Usb2Hc, + MaxSpeed, + PortNumber, + Is64BitCapable + ); + DEBUG ((DEBUG_INFO, "USB_HOOK(0x%x): GetCapability - MaxSpeed - 0x%02x, PortNumber - 0x%02x, Is64BitCapable - 0x%02x\n", Usb2HcHookPrivate->Usb2Hc, *MaxSpeed, *PortNumber, *Is64BitCapable)); + return Status; +} + +EFI_STATUS +EFIAPI +Usb2HcHookReset ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT16 Attributes + ) +{ + USB2_HC_HOOK_PRIVATE *Usb2HcHookPrivate; + EFI_STATUS Status; + + Usb2HcHookPrivate = GetUsb2HcHookPrivateFromThis (This); + DEBUG ((DEBUG_INFO, "USB_HOOK(0x%x): Reset - Attributes - 0x%04x\n", Usb2HcHookPrivate->Usb2Hc, Attributes)); + Status = Usb2HcHookPrivate->OrgUsb2Hc.Reset ( + Usb2HcHookPrivate->Usb2Hc, + Attributes + ); + return Status; +} + +EFI_STATUS +EFIAPI +Usb2HcHookGetState ( + IN EFI_USB2_HC_PROTOCOL *This, + OUT EFI_USB_HC_STATE *State + ) +{ + USB2_HC_HOOK_PRIVATE *Usb2HcHookPrivate; + EFI_STATUS Status; + + Usb2HcHookPrivate = GetUsb2HcHookPrivateFromThis (This); + Status = Usb2HcHookPrivate->OrgUsb2Hc.GetState ( + Usb2HcHookPrivate->Usb2Hc, + State + ); + DEBUG ((DEBUG_INFO, "USB_HOOK(0x%x): GetState - State - 0x%08x\n", Usb2HcHookPrivate->Usb2Hc, State)); + return Status; +} + +EFI_STATUS +EFIAPI +Usb2HcHookSetState ( + IN EFI_USB2_HC_PROTOCOL *This, + IN EFI_USB_HC_STATE State + ) +{ + USB2_HC_HOOK_PRIVATE *Usb2HcHookPrivate; + EFI_STATUS Status; + + Usb2HcHookPrivate = GetUsb2HcHookPrivateFromThis (This); + DEBUG ((DEBUG_INFO, "USB_HOOK(0x%x): SetState - State - 0x%08x\n", Usb2HcHookPrivate->Usb2Hc, State)); + Status = Usb2HcHookPrivate->OrgUsb2Hc.SetState ( + Usb2HcHookPrivate->Usb2Hc, + State + ); + return Status; +} + +EFI_STATUS +EFIAPI +Usb2HcHookControlTransfer ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN EFI_USB_DEVICE_REQUEST *Request, + IN EFI_USB_DATA_DIRECTION TransferDirection, + IN OUT VOID *Data OPTIONAL, + IN OUT UINTN *DataLength OPTIONAL, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +{ + USB2_HC_HOOK_PRIVATE *Usb2HcHookPrivate; + EFI_STATUS Status; + + Usb2HcHookPrivate = GetUsb2HcHookPrivateFromThis (This); + Status = Usb2HcHookPrivate->OrgUsb2Hc.ControlTransfer ( + Usb2HcHookPrivate->Usb2Hc, + DeviceAddress, + DeviceSpeed, + MaximumPacketLength, + Request, + TransferDirection, + Data, + DataLength, + TimeOut, + Translator, + TransferResult + ); + DEBUG ((DEBUG_INFO, "USB_HOOK(0x%x): ControlTransfer: ", Usb2HcHookPrivate->Usb2Hc)); + DEBUG ((DEBUG_INFO, "Addr - 0x%02x, ", DeviceAddress)); + DEBUG ((DEBUG_INFO, "Speed - 0x%02x, ", DeviceSpeed)); + DEBUG ((DEBUG_INFO, "MaxPkgLen - 0x%x, ", MaximumPacketLength)); + DEBUG ((DEBUG_INFO, "Direction - 0x%x, ", TransferDirection)); + DEBUG ((DEBUG_INFO, "Request (Type - 0x%02x(%a), ", Request->RequestType, UsbRequestTypeToString (Request))); + DEBUG ((DEBUG_INFO, "Request - 0x%02x(%a), ", Request->Request, UsbRequestRequestToString (Request))); + DEBUG ((DEBUG_INFO, "Value - 0x%04x(%a), ", Request->Value, UsbRequestValueToString (Request))); + DEBUG ((DEBUG_INFO, "Index - 0x%04x, Length - 0x%04x), ", Request->Index, Request->Length)); + DEBUG ((DEBUG_INFO, "Translator - (Hub - 0x%02x, Port - 0x%02x), ", Translator->TranslatorHubAddress, Translator->TranslatorPortNumber)); + if (TransferDirection == EfiUsbDataOut) { + DEBUG ((DEBUG_INFO, "DataLength - 0x%x, ", *DataLength)); + DEBUG ((DEBUG_INFO, "Data - ")); + InternalDumpData (Data, *DataLength); + DEBUG ((DEBUG_INFO, ", ")); + } + if ((Status == EFI_SUCCESS) && (*TransferResult == EFI_USB_NOERROR)) { + if (TransferDirection == EfiUsbDataIn) { + DEBUG ((DEBUG_INFO, "DataLength - 0x%x, ", *DataLength)); + DEBUG ((DEBUG_INFO, "Data - ")); + InternalDumpData (Data, *DataLength); + DEBUG ((DEBUG_INFO, ", ")); + } + } + DEBUG ((DEBUG_INFO, "Result - %x, ", *TransferResult)); + DEBUG ((DEBUG_INFO, "Status - %x", Status)); + DEBUG ((DEBUG_INFO, "\n")); + return Status; +} + +EFI_STATUS +EFIAPI +Usb2HcHookBulkTransfer ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM], + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +{ + USB2_HC_HOOK_PRIVATE *Usb2HcHookPrivate; + EFI_STATUS Status; + EFI_USB_DATA_DIRECTION TransferDirection; + + if ((EndPointAddress & 0x80) != 0) { + TransferDirection = EfiUsbDataIn; + } else { + TransferDirection = EfiUsbDataOut; + } + + Usb2HcHookPrivate = GetUsb2HcHookPrivateFromThis (This); + Status = Usb2HcHookPrivate->OrgUsb2Hc.BulkTransfer ( + Usb2HcHookPrivate->Usb2Hc, + DeviceAddress, + EndPointAddress, + DeviceSpeed, + MaximumPacketLength, + DataBuffersNumber, + Data, + DataLength, + DataToggle, + TimeOut, + Translator, + TransferResult + ); + DEBUG ((DEBUG_INFO, "USB_HOOK(0x%x): BulkTransfer: ", Usb2HcHookPrivate->Usb2Hc)); + DEBUG ((DEBUG_INFO, "Addr - 0x%02x, ", DeviceAddress)); + DEBUG ((DEBUG_INFO, "EndPoint - 0x%02x, ", EndPointAddress)); + DEBUG ((DEBUG_INFO, "Speed - 0x%02x, ", DeviceSpeed)); + DEBUG ((DEBUG_INFO, "MaxPkgLen - 0x%x, ", MaximumPacketLength)); + DEBUG ((DEBUG_INFO, "DataBufNumber - 0x%x, ", DataBuffersNumber)); + DEBUG ((DEBUG_INFO, "Translator - (Hub - 0x%02x, Port - 0x%02x), ", Translator->TranslatorHubAddress, Translator->TranslatorPortNumber)); + if (TransferDirection == EfiUsbDataOut) { + DEBUG ((DEBUG_INFO, "DataLength - 0x%x, ", *DataLength)); + DEBUG ((DEBUG_INFO, "Data - ")); + InternalDumpData (*Data, *DataLength); + DEBUG ((DEBUG_INFO, ", ")); + } + if ((Status == EFI_SUCCESS) && (*TransferResult == EFI_USB_NOERROR)) { + if (TransferDirection == EfiUsbDataIn) { + DEBUG ((DEBUG_INFO, "DataLength - 0x%x, ", *DataLength)); + DEBUG ((DEBUG_INFO, "Data - ")); + InternalDumpData (*Data, *DataLength); + DEBUG ((DEBUG_INFO, ", ")); + } + } + DEBUG ((DEBUG_INFO, "Result - %x, ", *TransferResult)); + DEBUG ((DEBUG_INFO, "Status - %x", Status)); + DEBUG ((DEBUG_INFO, "\n")); + return Status; +} + +EFI_STATUS +EFIAPI +Usb2HcHookAsyncInterruptTransfer ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaxiumPacketLength, + IN BOOLEAN IsNewTransfer, + IN OUT UINT8 *DataToggle, + IN UINTN PollingInterval OPTIONAL, + IN UINTN DataLength OPTIONAL, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator OPTIONAL, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction OPTIONAL, + IN VOID *Context OPTIONAL + ) +{ + USB2_HC_HOOK_PRIVATE *Usb2HcHookPrivate; + EFI_STATUS Status; + + Usb2HcHookPrivate = GetUsb2HcHookPrivateFromThis (This); + // TBD + Status = Usb2HcHookPrivate->OrgUsb2Hc.AsyncInterruptTransfer ( + Usb2HcHookPrivate->Usb2Hc, + DeviceAddress, + EndPointAddress, + DeviceSpeed, + MaxiumPacketLength, + IsNewTransfer, + DataToggle, + PollingInterval, + DataLength, + Translator, + CallBackFunction, + Context + ); + DEBUG ((DEBUG_INFO, "USB_HOOK(0x%x): AsyncInterruptTransfer: ", Usb2HcHookPrivate->Usb2Hc)); + DEBUG ((DEBUG_INFO, "Addr - 0x%02x, ", DeviceAddress)); + DEBUG ((DEBUG_INFO, "EndPoint - 0x%02x, ", EndPointAddress)); + DEBUG ((DEBUG_INFO, "Speed - 0x%02x, ", DeviceSpeed)); + DEBUG ((DEBUG_INFO, "MaxPkgLen - 0x%x, ", MaxiumPacketLength)); + DEBUG ((DEBUG_INFO, "DataLength - 0x%x, ", DataLength)); + DEBUG ((DEBUG_INFO, "Translator - (Hub - 0x%02x, Port - 0x%02x), ", Translator->TranslatorHubAddress, Translator->TranslatorPortNumber)); + DEBUG ((DEBUG_INFO, "Status - %x", Status)); + DEBUG ((DEBUG_INFO, "\n")); + return Status; +} + +EFI_STATUS +EFIAPI +Usb2HcHookSyncInterruptTransfer ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +{ + USB2_HC_HOOK_PRIVATE *Usb2HcHookPrivate; + EFI_STATUS Status; + EFI_USB_DATA_DIRECTION TransferDirection; + + if ((EndPointAddress & 0x80) != 0) { + TransferDirection = EfiUsbDataIn; + } else { + TransferDirection = EfiUsbDataOut; + } + + Usb2HcHookPrivate = GetUsb2HcHookPrivateFromThis (This); + Status = Usb2HcHookPrivate->OrgUsb2Hc.SyncInterruptTransfer ( + Usb2HcHookPrivate->Usb2Hc, + DeviceAddress, + EndPointAddress, + DeviceSpeed, + MaximumPacketLength, + Data, + DataLength, + DataToggle, + TimeOut, + Translator, + TransferResult + ); + DEBUG ((DEBUG_INFO, "USB_HOOK(0x%x): SyncInterruptTransfer: ", Usb2HcHookPrivate->Usb2Hc)); + DEBUG ((DEBUG_INFO, "Addr - 0x%02x, ", DeviceAddress)); + DEBUG ((DEBUG_INFO, "EndPoint - 0x%02x, ", EndPointAddress)); + DEBUG ((DEBUG_INFO, "Speed - 0x%02x, ", DeviceSpeed)); + DEBUG ((DEBUG_INFO, "MaxPkgLen - 0x%x, ", MaximumPacketLength)); + DEBUG ((DEBUG_INFO, "Translator - (Hub - 0x%02x, Port - 0x%02x), ", Translator->TranslatorHubAddress, Translator->TranslatorPortNumber)); + if (TransferDirection == EfiUsbDataOut) { + DEBUG ((DEBUG_INFO, "DataLength - 0x%x, ", *DataLength)); + DEBUG ((DEBUG_INFO, "Data - ")); + InternalDumpData (Data, *DataLength); + DEBUG ((DEBUG_INFO, ", ")); + } + if ((Status == EFI_SUCCESS) && (*TransferResult == EFI_USB_NOERROR)) { + if (TransferDirection == EfiUsbDataIn) { + DEBUG ((DEBUG_INFO, "DataLength - 0x%x, ", *DataLength)); + DEBUG ((DEBUG_INFO, "Data - ")); + InternalDumpData (Data, *DataLength); + DEBUG ((DEBUG_INFO, ", ")); + } + } + DEBUG ((DEBUG_INFO, "Result - %x, ", *TransferResult)); + DEBUG ((DEBUG_INFO, "Status - %x", Status)); + DEBUG ((DEBUG_INFO, "\n")); + return Status; +} + +EFI_STATUS +EFIAPI +Usb2HcHookIsochronousTransfer ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM], + IN UINTN DataLength, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +{ + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +Usb2HcHookAsyncIsochronousTransfer ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM], + IN UINTN DataLength, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack, + IN VOID *Context OPTIONAL + ) +{ + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +Usb2HcHookGetRootHubPortStatus ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 PortNumber, + OUT EFI_USB_PORT_STATUS *PortStatus + ) +{ + USB2_HC_HOOK_PRIVATE *Usb2HcHookPrivate; + EFI_STATUS Status; + + Usb2HcHookPrivate = GetUsb2HcHookPrivateFromThis (This); + Status = Usb2HcHookPrivate->OrgUsb2Hc.GetRootHubPortStatus ( + Usb2HcHookPrivate->Usb2Hc, + PortNumber, + PortStatus + ); + if (PortStatus->PortChangeStatus != 0) { + DEBUG ((DEBUG_INFO, "USB_HOOK(0x%x): GetRootHubPortStatus - PortNumber - 0x%02x, PortStatus - (0x%04x, Change - 0x%04x)\n", Usb2HcHookPrivate->Usb2Hc, PortNumber, PortStatus->PortStatus, PortStatus->PortChangeStatus)); + } + return Status; +} + +EFI_STATUS +EFIAPI +Usb2HcHookSetRootHubPortFeature ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ) +{ + USB2_HC_HOOK_PRIVATE *Usb2HcHookPrivate; + EFI_STATUS Status; + + Usb2HcHookPrivate = GetUsb2HcHookPrivateFromThis (This); + DEBUG ((DEBUG_INFO, "USB_HOOK(0x%x): SetRootHubPortFeature - PortNumber - 0x%02x, PortFeature - 0x%08x\n", Usb2HcHookPrivate->Usb2Hc, PortNumber, PortFeature)); + Status = Usb2HcHookPrivate->OrgUsb2Hc.SetRootHubPortFeature ( + Usb2HcHookPrivate->Usb2Hc, + PortNumber, + PortFeature + ); + return Status; +} + +EFI_STATUS +EFIAPI +Usb2HcHookClearRootHubPortFeature ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ) +{ + USB2_HC_HOOK_PRIVATE *Usb2HcHookPrivate; + EFI_STATUS Status; + + Usb2HcHookPrivate = GetUsb2HcHookPrivateFromThis (This); + DEBUG ((DEBUG_INFO, "USB_HOOK(0x%x): ClearRootHubPortFeature - PortNumber - 0x%02x, PortFeature - 0x%08x\n", Usb2HcHookPrivate->Usb2Hc, PortNumber, PortFeature)); + Status = Usb2HcHookPrivate->OrgUsb2Hc.ClearRootHubPortFeature ( + Usb2HcHookPrivate->Usb2Hc, + PortNumber, + PortFeature + ); + return Status; +} + +EFI_USB2_HC_PROTOCOL mUsb2HcHookTemplate = { + Usb2HcHookGetCapability, + Usb2HcHookReset, + Usb2HcHookGetState, + Usb2HcHookSetState, + Usb2HcHookControlTransfer, + Usb2HcHookBulkTransfer, + Usb2HcHookAsyncInterruptTransfer, + Usb2HcHookSyncInterruptTransfer, + Usb2HcHookIsochronousTransfer, + Usb2HcHookAsyncIsochronousTransfer, + Usb2HcHookGetRootHubPortStatus, + Usb2HcHookSetRootHubPortFeature, + Usb2HcHookClearRootHubPortFeature, + 0x0, + 0x0 +}; + +VOID +EFIAPI +Usb2HcProtocolCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_USB2_HC_PROTOCOL *Usb2Hc; + USB2_HC_HOOK_PRIVATE *Usb2HcHookPrivate; + EFI_STATUS Status; + + Status = gBS->LocateProtocol ( + &gEfiUsb2HcProtocolGuid, + mUsbHookRegistration, + (VOID **)&Usb2Hc + ); + if (EFI_ERROR(Status)) { + return ; + } + + DEBUG ((DEBUG_INFO, "USB_HOOK(0x%x): start hook\n", Usb2Hc)); + + Usb2HcHookPrivate = AllocatePool (sizeof(USB2_HC_HOOK_PRIVATE)); + ASSERT (Usb2HcHookPrivate != NULL); + + Usb2HcHookPrivate->Signature = USB2_HC_HOOK_PRIVATE_SIGNATURE; + CopyMem (&Usb2HcHookPrivate->OrgUsb2Hc, Usb2Hc, sizeof(EFI_USB2_HC_PROTOCOL)); + Usb2HcHookPrivate->Usb2Hc = Usb2Hc; + mUsb2HcHookTemplate.MajorRevision = Usb2Hc->MajorRevision; + mUsb2HcHookTemplate.MinorRevision = Usb2Hc->MinorRevision; + CopyMem (Usb2Hc, &mUsb2HcHookTemplate, sizeof(EFI_USB2_HC_PROTOCOL)); + InsertTailList (&mUsb2HcHookQueue, &Usb2HcHookPrivate->Link); +} + +EFI_STATUS +EFIAPI +InitializeUsb2HcHook ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + mUsbHookEvent = EfiCreateProtocolNotifyEvent ( + &gEfiUsb2HcProtocolGuid, + TPL_CALLBACK, + Usb2HcProtocolCallback, + NULL, + &mUsbHookRegistration + ); + ASSERT(mUsbHookEvent != NULL); + + return EFI_SUCCESS; +} \ No newline at end of file diff --git a/HBFA/UefiInstrumentTestCasePkg/TestCase/Usb2HcHook/Usb2HcHook.inf b/HBFA/UefiInstrumentTestCasePkg/TestCase/Usb2HcHook/Usb2HcHook.inf new file mode 100644 index 0000000..888124e --- /dev/null +++ b/HBFA/UefiInstrumentTestCasePkg/TestCase/Usb2HcHook/Usb2HcHook.inf @@ -0,0 +1,36 @@ +## @file +# +# Copyright (c) 2017, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Usb2HcHook + FILE_GUID = 55813F94-A25D-4408-BE66-E8F9EDE62310 + MODULE_TYPE = DXE_DRIVER + PI_SPECIFICATION_VERSION = 0x0001000A + VERSION_STRING = 1.0 + ENTRY_POINT = InitializeUsb2HcHook + +[Sources] + Usb2HcHook.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiLib + +[Protocols] + gEfiUsb2HcProtocolGuid + +[Depex] + TRUE \ No newline at end of file diff --git a/HBFA/UefiInstrumentTestCasePkg/UefiInstrumentTestCasePkg.dec b/HBFA/UefiInstrumentTestCasePkg/UefiInstrumentTestCasePkg.dec new file mode 100644 index 0000000..1f0bc3f --- /dev/null +++ b/HBFA/UefiInstrumentTestCasePkg/UefiInstrumentTestCasePkg.dec @@ -0,0 +1,15 @@ +## @file +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = UefiInstrumentTestCasePkg + PACKAGE_GUID = F9F21376-CF30-4DA2-B164-F0035465EC3D + PACKAGE_VERSION = 0.11 + +[Includes] diff --git a/HBFA/UefiInstrumentTestCasePkg/UefiInstrumentTestCasePkg.dsc b/HBFA/UefiInstrumentTestCasePkg/UefiInstrumentTestCasePkg.dsc new file mode 100644 index 0000000..331d512 --- /dev/null +++ b/HBFA/UefiInstrumentTestCasePkg/UefiInstrumentTestCasePkg.dsc @@ -0,0 +1,174 @@ +## @file +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + PLATFORM_NAME = UefiInstrumentTestCasePkg + PLATFORM_GUID = 638FAA73-FB53-4F99-B57F-CBAFDB365C21 + PLATFORM_VERSION = 0.11 + DSC_SPECIFICATION = 0x00010005 + OUTPUT_DIRECTORY = Build/UefiInstrumentTestPkg + SUPPORTED_ARCHITECTURES = IA32|X64 + BUILD_TARGETS = DEBUG|RELEASE|NOOPT + SKUID_IDENTIFIER = DEFAULT + +[LibraryClasses] + # + # Entry point + # + UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf + UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf + # + # Basic + # + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf + BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf + CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf + SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf + PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf + CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf + PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf + + # + # PEI + # + PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf + PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf + PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf + # + # UEFI & PI + # + UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.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 + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf + # + # Generic Modules + # + TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + # + # Misc + # + DebugLib|IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf + DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf + UefiDecompressLib|IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf + + # + # CPU + # + MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf + LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf + UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf + SmmLib|MdePkg/Library/SmmLibNull/SmmLibNull.inf + CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf + + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf + RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf + + PlatformSecureLib|SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.inf + SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf + LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf + SmmMemLib|MdePkg/Library/SmmMemLib/SmmMemLib.inf + +[LibraryClasses.common.PEIM] + ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf + HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf + MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf + +[LibraryClasses.common.PEI_CORE] + PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf + ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf + HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf + MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf + +[LibraryClasses.common.DXE_CORE] + DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf + ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf + HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf + MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf + +[LibraryClasses.common.DXE_DRIVER] + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf + +[LibraryClasses.common.UEFI_DRIVER] + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf + +[LibraryClasses.common.DXE_RUNTIME_DRIVER] + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf + +[LibraryClasses.common.SMM_CORE] + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + MemoryAllocationLib|MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.inf + SmmCorePlatformHookLib|MdeModulePkg/Library/SmmCorePlatformHookLibNull/SmmCorePlatformHookLibNull.inf + SmmServicesTableLib|MdeModulePkg/Library/PiSmmCoreSmmServicesTableLib/PiSmmCoreSmmServicesTableLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf + +[LibraryClasses.common.DXE_SMM_DRIVER] + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf + SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf + +[LibraryClasses.common.UEFI_APPLICATION] + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.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. +# +################################################################################################### + +[PcdsFixedAtBuild.common] + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x1f + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80080046 + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07 + gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask|0x1 + +[Components] + UefiInstrumentTestCasePkg/TestCase/InstrumentHookLibTracingPci/InstrumentHookLibTracingPci.inf + + UefiInstrumentTestCasePkg/TestCase/Usb2HcHook/Usb2HcHook.inf diff --git a/HBFA/UefiInstrumentTestPkg/Include/Library/IniParsingLib.h b/HBFA/UefiInstrumentTestPkg/Include/Library/IniParsingLib.h new file mode 100644 index 0000000..5433c96 --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Include/Library/IniParsingLib.h @@ -0,0 +1,185 @@ +/** @file + INI configuration parsing library. + + The INI file format is: + ================ + [SectionName] + EntryName=EntryValue + ================ + + Where: + 1) SectionName is an ASCII string. The valid format is [A-Za-z0-9_]+ + 2) EntryName is an ASCII string. The valid format is [A-Za-z0-9_]+ + 3) EntryValue can be: + 3.1) an ASCII String. The valid format is [A-Za-z0-9_]+ + 3.2) a GUID. The valid format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, where x is [A-Fa-f0-9] + 3.3) a decimal value. The valid format is [0-9]+ + 3.4) a heximal value. The valid format is 0x[A-Fa-f0-9]+ + 4) '#' or ';' can be used as comment at anywhere. + 5) TAB(0x20) or SPACE(0x9) can be used as separator. + 6) LF(\n, 0xA) or CR(\r, 0xD) can be used as line break. + +Copyright (c) 2016, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#ifndef __INI_PARSING_LIB_H__ +#define __INI_PARSING_LIB_H__ + +/** + Open an INI config file and return a context. + + @param[in] DataBuffer Config raw file buffer. + @param[in] BufferSize Size of raw buffer. + + @return Config data buffer is opened and context is returned. + @retval NULL No enough memory is allocated. + @retval NULL Config data buffer is invalid. +**/ +VOID * +EFIAPI +OpenIniFile ( + IN UINT8 *DataBuffer, + IN UINTN BufferSize + ); + +/** + Get section entry string value. + + @param[in] Context INI Config file context. + @param[in] SectionName Section name. + @param[in] EntryName Section entry name. + @param[out] EntryValue Point to the got entry string value. + + @retval EFI_SUCCESS Section entry string value is got. + @retval EFI_NOT_FOUND Section is not found. +**/ +EFI_STATUS +EFIAPI +GetStringFromDataFile ( + IN VOID *Context, + IN CHAR8 *SectionName, + IN CHAR8 *EntryName, + OUT CHAR8 **EntryValue + ); + +/** + Get section entry GUID value. + + @param[in] Context INI Config file context. + @param[in] SectionName Section name. + @param[in] EntryName Section entry name. + @param[out] Guid Point to the got GUID value. + + @retval EFI_SUCCESS Section entry GUID value is got. + @retval EFI_NOT_FOUND Section is not found. + @retval EFI_INVALID_PARAMETER Section format is invalid. +**/ +EFI_STATUS +EFIAPI +GetGuidFromDataFile ( + IN VOID *Context, + IN CHAR8 *SectionName, + IN CHAR8 *EntryName, + OUT EFI_GUID *Guid + ); + +/** + Get section entry EFI_STATUS value. + + @param[in] Context INI Config file context. + @param[in] SectionName Section name. + @param[in] EntryName Section entry name. + @param[out] Guid Point to the got GUID value. + + @retval EFI_SUCCESS Section entry EFI_STATUS value is got. + @retval EFI_NOT_FOUND Section is not found. + @retval EFI_INVALID_PARAMETER Section format is invalid. +**/ +EFI_STATUS +EFIAPI +GetEfiStatusFromDataFile ( + IN VOID *Context, + IN CHAR8 *SectionName, + IN CHAR8 *EntryName, + OUT EFI_STATUS *EfiStatus + ); + +/** + Get section entry decimal UINTN value. + + @param[in] Context INI Config file context. + @param[in] SectionName Section name. + @param[in] EntryName Section entry name. + @param[out] Data Point to the got decimal UINTN value. + + @retval EFI_SUCCESS Section entry decimal UINTN value is got. + @retval EFI_NOT_FOUND Section is not found. + @retval EFI_INVALID_PARAMETER Section format is invalid. +**/ +EFI_STATUS +EFIAPI +GetDecimalUintnFromDataFile ( + IN VOID *Context, + IN CHAR8 *SectionName, + IN CHAR8 *EntryName, + OUT UINTN *Data + ); + +/** + Get section entry heximal UINTN value. + + @param[in] Context INI Config file context. + @param[in] SectionName Section name. + @param[in] EntryName Section entry name. + @param[out] Data Point to the got heximal UINTN value. + + @retval EFI_SUCCESS Section entry heximal UINTN value is got. + @retval EFI_NOT_FOUND Section is not found. + @retval EFI_INVALID_PARAMETER Section format is invalid. +**/ +EFI_STATUS +EFIAPI +GetHexUintnFromDataFile ( + IN VOID *Context, + IN CHAR8 *SectionName, + IN CHAR8 *EntryName, + OUT UINTN *Data + ); + +/** + Get section entry heximal UINT64 value. + + @param[in] Context INI Config file context. + @param[in] SectionName Section name. + @param[in] EntryName Section entry name. + @param[out] Data Point to the got heximal UINT64 value. + + @retval EFI_SUCCESS Section entry heximal UINT64 value is got. + @retval EFI_NOT_FOUND Section is not found. + @retval EFI_INVALID_PARAMETER Section format is invalid. +**/ +EFI_STATUS +EFIAPI +GetHexUint64FromDataFile ( + IN VOID *Context, + IN CHAR8 *SectionName, + IN CHAR8 *EntryName, + OUT UINT64 *Data + ); + +/** + Close an INI config file and free the context. + + @param[in] Context INI Config file context. +**/ +VOID +EFIAPI +CloseIniFile ( + IN VOID *Context + ); + +#endif + diff --git a/HBFA/UefiInstrumentTestPkg/Include/Library/InstrumentHookLib.h b/HBFA/UefiInstrumentTestPkg/Include/Library/InstrumentHookLib.h new file mode 100644 index 0000000..86ae730 --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Include/Library/InstrumentHookLib.h @@ -0,0 +1,183 @@ +/** @file + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _INSTRUMENT_HOOK_LIB_ +#define _INSTRUMENT_HOOK_LIB_ + +typedef struct { + UINT32 Edi; + UINT32 Esi; + UINT32 Ebp; + UINT32 Esp; // this is ESP after call instruction + UINT32 Ebx; + UINT32 Edx; + UINT32 Ecx; + UINT32 Eax; +} FUNC_CONTEXT_IA32; + +typedef struct { + UINT64 R15; + UINT64 R14; + UINT64 R13; + UINT64 R12; + UINT64 R11; + UINT64 R10; + UINT64 R9; + UINT64 R8; + UINT64 Rdi; + UINT64 Rsi; + UINT64 Rbp; + UINT64 Rsp; // this is RSP after call instruction + UINT64 Rbx; + UINT64 Rdx; + UINT64 Rcx; + UINT64 Rax; +} FUNC_CONTEXT_X64; + +typedef union { + FUNC_CONTEXT_IA32 *Ia32; + FUNC_CONTEXT_X64 *X64; +} FUNC_ENTER_CONTEXT; + +typedef union { + FUNC_CONTEXT_IA32 *Ia32; + FUNC_CONTEXT_X64 *X64; +} FUNC_EXIT_CONTEXT; + +/* + 0 - continue + 1 - skip this function +*/ +UINTN +EFIAPI +FunctionEnter ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ); + +VOID +EFIAPI +FunctionExit ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ); + +VOID +EFIAPI +InstrumentHookLibInit ( + IN UINT8 *DataBuffer, + IN UINTN BufferSize + ); + +// +// external func +// +VOID +EFIAPI +SetReturnValue ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN RetVal + ); + +VOID +EFIAPI +SetReturnValue64 ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINT64 RetVal + ); + +UINTN +EFIAPI +GetReturnValue ( + IN OUT FUNC_EXIT_CONTEXT ExitContext + ); + +UINT64 +EFIAPI +GetReturnValue64 ( + IN OUT FUNC_EXIT_CONTEXT ExitContext + ); + +/* + Index is 1 based. +*/ +UINTN +EFIAPI +GetParameterValue ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN Index + ); + +/* + Index is 1 based. +*/ +UINT64 +EFIAPI +GetParameterValue64 ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN Index + ); + +/* + Index is 1 based. +*/ +UINTN +EFIAPI +GetReturnParameterValue ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN Index + ); + +/* + Index is 1 based. +*/ +UINT64 +EFIAPI +GetReturnParameterValue64 ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN Index + ); + +/* + Index is 1 based. +*/ +VOID +EFIAPI +SetParameterValue ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN Index, + IN UINTN Data + ); + +/* + Index is 1 based. +*/ +VOID +EFIAPI +SetParameterValue64 ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN Index, + IN UINT64 Data + ); + +VOID +EFIAPI +SetSkipReturnValue ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN RetVal + ); + +VOID +EFIAPI +SetSkipReturnValue64 ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINT64 RetVal + ); + +#endif \ No newline at end of file diff --git a/HBFA/UefiInstrumentTestPkg/Library/IniParsingLib/IniParsingLib.c b/HBFA/UefiInstrumentTestPkg/Library/IniParsingLib/IniParsingLib.c new file mode 100644 index 0000000..472a3d4 --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/IniParsingLib/IniParsingLib.c @@ -0,0 +1,1394 @@ +/** @file + This library parses the INI configuration file. + + The INI file format is: + ================ + [SectionName] + EntryName=EntryValue + ================ + + Where: + 1) SectionName is an ASCII string. The valid format is [A-Za-z0-9_]+ + 2) EntryName is an ASCII string. The valid format is [A-Za-z0-9_]+ + 3) EntryValue can be: + 3.1) an ASCII String. The valid format is [A-Za-z0-9_]+ + 3.2) a GUID. The valid format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, where x is [A-Fa-f0-9] + 3.3) a decimal value. The valid format is [0-9]+ + 3.4) a heximal value. The valid format is 0x[A-Fa-f0-9]+ + 3.5) a EFI_STATUS value. The valid value is defined in UEFI specification. Such as EFI_SUCCESS, EFI_INVALID_PARAMETER, etc. + 4) '#' or ';' can be used as comment at anywhere. + 5) TAB(0x20) or SPACE(0x9) can be used as separator. + 6) LF(\n, 0xA) or CR(\r, 0xD) can be used as line break. + + Caution: This module requires additional review when modified. + This driver will have external input - INI data file. + + OpenIniFile(), PreProcessDataFile(), ProfileGetSection(), ProfileGetEntry() + will receive untrusted input and do basic validation. + + Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include + +#define IS_HYPHEN(a) ((a) == '-') +#define IS_NULL(a) ((a) == '\0') + +// This is default allocation. Reallocation will happen if it is not enough. +#define MAX_LINE_LENGTH 512 + +typedef struct _INI_SECTION_ITEM SECTION_ITEM; +struct _INI_SECTION_ITEM { + CHAR8 *PtrSection; + UINTN SecNameLen; + CHAR8 *PtrEntry; + CHAR8 *PtrValue; + SECTION_ITEM *PtrNext; +}; + +typedef struct _INI_COMMENT_LINE COMMENT_LINE; +struct _INI_COMMENT_LINE { + CHAR8 *PtrComment; + COMMENT_LINE *PtrNext; +}; + +typedef struct { + SECTION_ITEM *SectionHead; + COMMENT_LINE *CommentHead; +} INI_PARSING_LIB_CONTEXT; + +/** + Return if the digital char is valid. + + @param[in] DigitalChar The digital char to be checked. + @param[in] IncludeHex If it include HEX char. + + @retval TRUE The digital char is valid. + @retval FALSE The digital char is invalid. +**/ +BOOLEAN +IsValidDigitalChar ( + IN CHAR8 DigitalChar, + IN BOOLEAN IncludeHex + ) +{ + if (DigitalChar >= '0' && DigitalChar <= '9') { + return TRUE; + } + if (IncludeHex) { + if (DigitalChar >= 'a' && DigitalChar <= 'f') { + return TRUE; + } + if (DigitalChar >= 'A' && DigitalChar <= 'F') { + return TRUE; + } + } + return FALSE; +} + +/** + Return if the name char is valid. + + @param[in] NameChar The name char to be checked. + + @retval TRUE The name char is valid. + @retval FALSE The name char is invalid. +**/ +BOOLEAN +IsValidNameChar ( + IN CHAR8 NameChar + ) +{ + if (NameChar >= 'a' && NameChar <= 'z') { + return TRUE; + } + if (NameChar >= 'A' && NameChar <= 'Z') { + return TRUE; + } + if (NameChar >= '0' && NameChar <= '9') { + return TRUE; + } + if (NameChar == '_') { + return TRUE; + } + return FALSE; +} + +/** + Return if the digital string is valid. + + @param[in] Digital The digital to be checked. + @param[in] Length The length of digital string in bytes. + @param[in] IncludeHex If it include HEX char. + + @retval TRUE The digital string is valid. + @retval FALSE The digital string is invalid. +**/ +BOOLEAN +IsValidDigital ( + IN CHAR8 *Digital, + IN UINTN Length, + IN BOOLEAN IncludeHex + ) +{ + UINTN Index; + for (Index = 0; Index < Length; Index++) { + if (!IsValidDigitalChar(Digital[Index], IncludeHex)) { + return FALSE; + } + } + return TRUE; +} + +/** + Return if the decimal string is valid. + + @param[in] Decimal The decimal string to be checked. + @param[in] Length The length of decimal string in bytes. + + @retval TRUE The decimal string is valid. + @retval FALSE The decimal string is invalid. +**/ +BOOLEAN +IsValidDecimalString ( + IN CHAR8 *Decimal, + IN UINTN Length + ) +{ + return IsValidDigital(Decimal, Length, FALSE); +} + +/** + Return if the heximal string is valid. + + @param[in] Hex The heximal string to be checked. + @param[in] Length The length of heximal string in bytes. + + @retval TRUE The heximal string is valid. + @retval FALSE The heximal string is invalid. +**/ +BOOLEAN +IsValidHexString ( + IN CHAR8 *Hex, + IN UINTN Length + ) +{ + if (Length <= 2) { + return FALSE; + } + if (Hex[0] != '0') { + return FALSE; + } + if (Hex[1] != 'x' && Hex[1] != 'X') { + return FALSE; + } + return IsValidDigital(&Hex[2], Length - 2, TRUE); +} + +/** + Return if the name string is valid. + + @param[in] Name The name to be checked. + @param[in] Length The length of name string in bytes. + + @retval TRUE The name string is valid. + @retval FALSE The name string is invalid. +**/ +BOOLEAN +IsValidName ( + IN CHAR8 *Name, + IN UINTN Length + ) +{ + UINTN Index; + for (Index = 0; Index < Length; Index++) { + if (!IsValidNameChar(Name[Index])) { + return FALSE; + } + } + return TRUE; +} + +/** + Return if the value string is valid GUID. + + @param[in] Value The value to be checked. + @param[in] Length The length of value string in bytes. + + @retval TRUE The value string is valid GUID. + @retval FALSE The value string is invalid GUID. +**/ +BOOLEAN +IsValidGuid ( + IN CHAR8 *Value, + IN UINTN Length + ) +{ + if (Length != sizeof("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") - 1) { + return FALSE; + } + if (!IS_HYPHEN(Value[8])) { + return FALSE; + } + if (!IS_HYPHEN(Value[13])) { + return FALSE; + } + if (!IS_HYPHEN(Value[18])) { + return FALSE; + } + if (!IS_HYPHEN(Value[23])) { + return FALSE; + } + if (!IsValidDigital(&Value[0], 8, TRUE)) { + return FALSE; + } + if (!IsValidDigital(&Value[9], 4, TRUE)) { + return FALSE; + } + if (!IsValidDigital(&Value[14], 4, TRUE)) { + return FALSE; + } + if (!IsValidDigital(&Value[19], 4, TRUE)) { + return FALSE; + } + if (!IsValidDigital(&Value[24], 12, TRUE)) { + return FALSE; + } + return TRUE; +} + +/** + Return if the value string is valid. + + @param[in] Value The value to be checked. + @param[in] Length The length of value string in bytes. + + @retval TRUE The name string is valid. + @retval FALSE The name string is invalid. +**/ +BOOLEAN +IsValidValue ( + IN CHAR8 *Value, + IN UINTN Length + ) +{ + if (IsValidName(Value, Length) || IsValidGuid(Value, Length)) { + return TRUE; + } + return FALSE; +} + +/** + Dump an INI config file context. + + @param[in] Context INI Config file context. +**/ +VOID +DumpIniSection ( + IN VOID *Context + ) +{ + INI_PARSING_LIB_CONTEXT *IniContext; + SECTION_ITEM *PtrSection; + SECTION_ITEM *Section; + + if (Context == NULL) { + return; + } + + IniContext = Context; + Section = IniContext->SectionHead; + + while (Section != NULL) { + PtrSection = Section; + Section = Section->PtrNext; + if (PtrSection->PtrSection != NULL) { + DEBUG((DEBUG_VERBOSE, "Section - %a\n", PtrSection->PtrSection)); + } + if (PtrSection->PtrEntry != NULL) { + DEBUG ((DEBUG_VERBOSE, " Entry - %a\n", PtrSection->PtrEntry)); + } + if (PtrSection->PtrValue != NULL) { + DEBUG((DEBUG_VERBOSE, " Value - %a\n", PtrSection->PtrValue)); + } + } +} + +/** + Copy one line data from buffer data to the line buffer. + + @param[in] Buffer Buffer data. + @param[in] BufferSize Buffer Size. + @param[in, out] LineBuffer Line buffer to store the found line data. + @param[in, out] LineSize On input, size of the input line buffer. + On output, size of the actual line buffer. + + @retval EFI_BUFFER_TOO_SMALL The size of input line buffer is not enough. + @retval EFI_SUCCESS Copy line data into the line buffer. + +**/ +EFI_STATUS +ProfileGetLine ( + IN UINT8 *Buffer, + IN UINTN BufferSize, + IN OUT UINT8 *LineBuffer, + IN OUT UINTN *LineSize + ) +{ + UINTN Length; + UINT8 *PtrBuf; + UINTN PtrEnd; + + PtrBuf = Buffer; + PtrEnd = (UINTN)Buffer + BufferSize; + + // + // 0x0D indicates a line break. Otherwise there is no line break + // + while ((UINTN)PtrBuf < PtrEnd) { + if (*PtrBuf == 0x0D || *PtrBuf == 0x0A) { + break; + } + PtrBuf++; + } + + if ((UINTN)PtrBuf >= (PtrEnd - 1)) { + // + // The buffer ends without any line break + // or it is the last character of the buffer + // + Length = BufferSize; + } else if (*(PtrBuf + 1) == 0x0A) { + // + // Further check if a 0x0A follows. If yes, count 0xA + // + Length = (UINTN) PtrBuf - (UINTN) Buffer + 2; + } else { + Length = (UINTN) PtrBuf - (UINTN) Buffer + 1; + } + + if (Length > (*LineSize)) { + *LineSize = Length; + return EFI_BUFFER_TOO_SMALL; + } + + SetMem (LineBuffer, *LineSize, 0x0); + *LineSize = Length; + CopyMem (LineBuffer, Buffer, Length); + + return EFI_SUCCESS; +} + +/** + Trim Buffer by removing all CR, LF, TAB, and SPACE chars in its head and tail. + + @param[in, out] Buffer On input, buffer data to be trimed. + On output, the trimmed buffer. + @param[in, out] BufferSize On input, size of original buffer data. + On output, size of the trimmed buffer. + +**/ +VOID +ProfileTrim ( + IN OUT UINT8 *Buffer, + IN OUT UINTN *BufferSize + ) +{ + UINTN Length; + UINT8 *PtrBuf; + UINT8 *PtrEnd; + + if (*BufferSize == 0) { + return; + } + + // + // Trim the tail first, include CR, LF, TAB, and SPACE. + // + Length = *BufferSize; + PtrBuf = (UINT8 *) ((UINTN) Buffer + Length - 1); + while (PtrBuf >= Buffer) { + if ((*PtrBuf != 0x0D) && (*PtrBuf != 0x0A ) + && (*PtrBuf != 0x20) && (*PtrBuf != 0x09)) { + break; + } + PtrBuf --; + } + + // + // all spaces, a blank line, return directly; + // + if (PtrBuf < Buffer) { + *BufferSize = 0; + return; + } + + Length = (UINTN)PtrBuf - (UINTN)Buffer + 1; + PtrEnd = PtrBuf; + PtrBuf = Buffer; + + // + // Now skip the heading CR, LF, TAB and SPACE + // + while (PtrBuf <= PtrEnd) { + if ((*PtrBuf != 0x0D) && (*PtrBuf != 0x0A ) + && (*PtrBuf != 0x20) && (*PtrBuf != 0x09)) { + break; + } + PtrBuf++; + } + + // + // If no heading CR, LF, TAB or SPACE, directly return + // + if (PtrBuf == Buffer) { + *BufferSize = Length; + return; + } + + *BufferSize = (UINTN)PtrEnd - (UINTN)PtrBuf + 1; + + // + // The first Buffer..PtrBuf characters are CR, LF, TAB or SPACE. + // Now move out all these characters. + // + while (PtrBuf <= PtrEnd) { + *Buffer = *PtrBuf; + Buffer++; + PtrBuf++; + } + + return; +} + +/** + Insert new comment item into comment head. + + @param[in] Buffer Comment buffer to be added. + @param[in] BufferSize Size of comment buffer. + @param[in, out] CommentHead Comment Item head entry. + + @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. + @retval EFI_SUCCESS New comment item is inserted. + +**/ +EFI_STATUS +ProfileGetComments ( + IN UINT8 *Buffer, + IN UINTN BufferSize, + IN OUT COMMENT_LINE **CommentHead + ) +{ + COMMENT_LINE *CommentItem; + + CommentItem = NULL; + CommentItem = AllocatePool (sizeof (COMMENT_LINE)); + if (CommentItem == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CommentItem->PtrNext = *CommentHead; + *CommentHead = CommentItem; + + // + // Add a trailing '\0' + // + CommentItem->PtrComment = AllocatePool (BufferSize + 1); + if (CommentItem->PtrComment == NULL) { + FreePool (CommentItem); + return EFI_OUT_OF_RESOURCES; + } + CopyMem (CommentItem->PtrComment, Buffer, BufferSize); + *(CommentItem->PtrComment + BufferSize) = '\0'; + + return EFI_SUCCESS; +} + +/** + Add new section item into Section head. + + @param[in] Buffer Section item data buffer. + @param[in] BufferSize Size of section item. + @param[in, out] SectionHead Section item head entry. + + @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. + @retval EFI_SUCCESS Section item is NULL or Section item is added. + +**/ +EFI_STATUS +ProfileGetSection ( + IN UINT8 *Buffer, + IN UINTN BufferSize, + IN OUT SECTION_ITEM **SectionHead + ) +{ + SECTION_ITEM *SectionItem; + UINTN Length; + UINT8 *PtrBuf; + UINT8 *PtrEnd; + + ASSERT(BufferSize >= 1); + // + // The first character of Buffer is '[', now we want for ']' + // + PtrEnd = (UINT8 *)((UINTN)Buffer + BufferSize - 1); + PtrBuf = (UINT8 *)((UINTN)Buffer + 1); + while (PtrBuf <= PtrEnd) { + if (*PtrBuf == ']') { + break; + } + PtrBuf ++; + } + if (PtrBuf > PtrEnd) { + // + // Not found. Invalid line + // + return EFI_NOT_FOUND; + } + if (PtrBuf <= Buffer + 1) { + // Empty name + return EFI_NOT_FOUND; + } + + // + // excluding the heading '[' and tailing ']' + // + Length = PtrBuf - Buffer - 1; + ProfileTrim ( + Buffer + 1, + &Length + ); + + // + // Invalid line if the section name is null + // + if (Length == 0) { + return EFI_NOT_FOUND; + } + + if (!IsValidName((CHAR8 *)Buffer + 1, Length)) { + return EFI_INVALID_PARAMETER; + } + + SectionItem = AllocatePool (sizeof (SECTION_ITEM)); + if (SectionItem == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + SectionItem->PtrSection = NULL; + SectionItem->SecNameLen = Length; + SectionItem->PtrEntry = NULL; + SectionItem->PtrValue = NULL; + SectionItem->PtrNext = *SectionHead; + *SectionHead = SectionItem; + + // + // Add a trailing '\0' + // + SectionItem->PtrSection = AllocatePool (Length + 1); + if (SectionItem->PtrSection == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // excluding the heading '[' + // + CopyMem (SectionItem->PtrSection, Buffer + 1, Length); + *(SectionItem->PtrSection + Length) = '\0'; + + return EFI_SUCCESS; +} + +/** + Add new section entry and entry value into Section head. + + @param[in] Buffer Section entry data buffer. + @param[in] BufferSize Size of section entry. + @param[in, out] SectionHead Section item head entry. + + @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. + @retval EFI_SUCCESS Section entry is added. + @retval EFI_NOT_FOUND Section entry is not found. + @retval EFI_INVALID_PARAMETER Section entry is invalid. + +**/ +EFI_STATUS +ProfileGetEntry ( + IN UINT8 *Buffer, + IN UINTN BufferSize, + IN OUT SECTION_ITEM **SectionHead + ) +{ + EFI_STATUS Status; + SECTION_ITEM *SectionItem; + SECTION_ITEM *PtrSection; + UINTN Length; + UINT8 *PtrBuf; + UINT8 *PtrEnd; + + Status = EFI_SUCCESS; + PtrBuf = Buffer; + PtrEnd = (UINT8 *) ((UINTN)Buffer + BufferSize - 1); + + // + // First search for '=' + // + while (PtrBuf <= PtrEnd) { + if (*PtrBuf == '=') { + break; + } + PtrBuf++; + } + if (PtrBuf > PtrEnd) { + // + // Not found. Invalid line + // + return EFI_NOT_FOUND; + } + if (PtrBuf <= Buffer) { + // Empty name + return EFI_NOT_FOUND; + } + + // + // excluding the tailing '=' + // + Length = PtrBuf - Buffer; + ProfileTrim ( + Buffer, + &Length + ); + + // + // Invalid line if the entry name is null + // + if (Length == 0) { + return EFI_NOT_FOUND; + } + + if (!IsValidName((CHAR8 *)Buffer, Length)) { + return EFI_INVALID_PARAMETER; + } + + // + // Omit this line if no section header has been found before + // + if (*SectionHead == NULL) { + return Status; + } + PtrSection = *SectionHead; + + SectionItem = AllocatePool (sizeof (SECTION_ITEM)); + if (SectionItem == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + SectionItem->PtrSection = NULL; + SectionItem->PtrEntry = NULL; + SectionItem->PtrValue = NULL; + SectionItem->SecNameLen = PtrSection->SecNameLen; + SectionItem->PtrNext = *SectionHead; + *SectionHead = SectionItem; + + // + // SectionName, add a trailing '\0' + // + SectionItem->PtrSection = AllocatePool (PtrSection->SecNameLen + 1); + if (SectionItem->PtrSection == NULL) { + return EFI_OUT_OF_RESOURCES; + } + CopyMem (SectionItem->PtrSection, PtrSection->PtrSection, PtrSection->SecNameLen + 1); + + // + // EntryName, add a trailing '\0' + // + SectionItem->PtrEntry = AllocatePool (Length + 1); + if (SectionItem->PtrEntry == NULL) { + FreePool(SectionItem->PtrSection); + return EFI_OUT_OF_RESOURCES; + } + CopyMem (SectionItem->PtrEntry, Buffer, Length); + *(SectionItem->PtrEntry + Length) = '\0'; + + // + // Next search for '#' or ';' + // + PtrBuf = PtrBuf + 1; + Buffer = PtrBuf; + while (PtrBuf <= PtrEnd) { + if (*PtrBuf == '#' || *PtrBuf == ';') { + break; + } + PtrBuf++; + } + if (PtrBuf <= Buffer) { + // Empty name + FreePool(SectionItem->PtrEntry); + FreePool(SectionItem->PtrSection); + return EFI_NOT_FOUND; + } + Length = PtrBuf - Buffer; + ProfileTrim ( + Buffer, + &Length + ); + + // + // Invalid line if the entry value is null + // + if (Length == 0) { + FreePool(SectionItem->PtrEntry); + FreePool(SectionItem->PtrSection); + return EFI_NOT_FOUND; + } + + if (!IsValidValue((CHAR8 *)Buffer, Length)) { + FreePool(SectionItem->PtrEntry); + FreePool(SectionItem->PtrSection); + return EFI_INVALID_PARAMETER; + } + + // + // EntryValue, add a trailing '\0' + // + SectionItem->PtrValue = AllocatePool (Length + 1); + if (SectionItem->PtrValue == NULL) { + FreePool(SectionItem->PtrEntry); + FreePool(SectionItem->PtrSection); + return EFI_OUT_OF_RESOURCES; + } + CopyMem (SectionItem->PtrValue, Buffer, Length); + *(SectionItem->PtrValue + Length) = '\0'; + + return EFI_SUCCESS; +} + +/** + Free all comment entry and section entry. + + @param[in] Section Section entry list. + @param[in] Comment Comment entry list. + +**/ +VOID +FreeAllList ( + IN SECTION_ITEM *Section, + IN COMMENT_LINE *Comment + ) +{ + SECTION_ITEM *PtrSection; + COMMENT_LINE *PtrComment; + + while (Section != NULL) { + PtrSection = Section; + Section = Section->PtrNext; + if (PtrSection->PtrEntry != NULL) { + FreePool (PtrSection->PtrEntry); + } + if (PtrSection->PtrSection != NULL) { + FreePool (PtrSection->PtrSection); + } + if (PtrSection->PtrValue != NULL) { + FreePool (PtrSection->PtrValue); + } + FreePool (PtrSection); + } + + while (Comment != NULL) { + PtrComment = Comment; + Comment = Comment->PtrNext; + if (PtrComment->PtrComment != NULL) { + FreePool (PtrComment->PtrComment); + } + FreePool (PtrComment); + } + + return; +} + +/** + Get section entry value. + + @param[in] Section Section entry list. + @param[in] SectionName Section name. + @param[in] EntryName Section entry name. + @param[out] EntryValue Point to the got entry value. + + @retval EFI_NOT_FOUND Section is not found. + @retval EFI_SUCCESS Section entry value is got. + +**/ +EFI_STATUS +UpdateGetProfileString ( + IN SECTION_ITEM *Section, + IN CHAR8 *SectionName, + IN CHAR8 *EntryName, + OUT CHAR8 **EntryValue + ) +{ + *EntryValue = NULL; + + while (Section != NULL) { + if (AsciiStrCmp ((CONST CHAR8 *) Section->PtrSection, (CONST CHAR8 *) SectionName) == 0) { + if (Section->PtrEntry != NULL) { + if (AsciiStrCmp ((CONST CHAR8 *) Section->PtrEntry, (CONST CHAR8 *) EntryName) == 0) { + break; + } + } + } + Section = Section->PtrNext; + } + + if (Section == NULL) { + return EFI_NOT_FOUND; + } + + *EntryValue = Section->PtrValue; + + return EFI_SUCCESS; +} + +/** + Pre process config data buffer into Section entry list and Comment entry list. + + @param[in] DataBuffer Config raw file buffer. + @param[in] BufferSize Size of raw buffer. + @param[in, out] SectionHead Pointer to the section entry list. + @param[in, out] CommentHead Pointer to the comment entry list. + + @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. + @retval EFI_SUCCESS Config data buffer is preprocessed. + @retval EFI_NOT_FOUND Config data buffer is invalid, because Section or Entry is not found. + @retval EFI_INVALID_PARAMETER Config data buffer is invalid, because Section or Entry is invalid. + +**/ +EFI_STATUS +PreProcessDataFile ( + IN UINT8 *DataBuffer, + IN UINTN BufferSize, + IN OUT SECTION_ITEM **SectionHead, + IN OUT COMMENT_LINE **CommentHead + ) +{ + EFI_STATUS Status; + CHAR8 *Source; + CHAR8 *CurrentPtr; + CHAR8 *BufferEnd; + CHAR8 *PtrLine; + UINTN LineLength; + UINTN SourceLength; + UINTN MaxLineLength; + + *SectionHead = NULL; + *CommentHead = NULL; + BufferEnd = (CHAR8 *) ( (UINTN) DataBuffer + BufferSize); + CurrentPtr = (CHAR8 *) DataBuffer; + MaxLineLength = MAX_LINE_LENGTH; + Status = EFI_SUCCESS; + + PtrLine = AllocatePool (MaxLineLength); + if (PtrLine == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + while (CurrentPtr < BufferEnd) { + Source = CurrentPtr; + SourceLength = (UINTN)BufferEnd - (UINTN)CurrentPtr; + LineLength = MaxLineLength; + // + // With the assumption that line length is less than 512 + // characters. Otherwise BUFFER_TOO_SMALL will be returned. + // + Status = ProfileGetLine ( + (UINT8 *) Source, + SourceLength, + (UINT8 *) PtrLine, + &LineLength + ); + if (EFI_ERROR (Status)) { + if (Status == EFI_BUFFER_TOO_SMALL) { + // + // If buffer too small, re-allocate the buffer according + // to the returned LineLength and try again. + // + FreePool (PtrLine); + PtrLine = NULL; + PtrLine = AllocatePool (LineLength); + if (PtrLine == NULL) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + SourceLength = LineLength; + Status = ProfileGetLine ( + (UINT8 *) Source, + SourceLength, + (UINT8 *) PtrLine, + &LineLength + ); + if (EFI_ERROR (Status)) { + break; + } + MaxLineLength = LineLength; + } else { + break; + } + } + CurrentPtr = (CHAR8 *) ( (UINTN) CurrentPtr + LineLength); + + // + // Line got. Trim the line before processing it. + // + ProfileTrim ( + (UINT8 *) PtrLine, + &LineLength + ); + + // + // Blank line + // + if (LineLength == 0) { + continue; + } + + if (PtrLine[0] == '#' || PtrLine[0] == ';') { + Status = ProfileGetComments ( + (UINT8 *) PtrLine, + LineLength, + CommentHead + ); + } else if (PtrLine[0] == '[') { + Status = ProfileGetSection ( + (UINT8 *) PtrLine, + LineLength, + SectionHead + ); + } else { + Status = ProfileGetEntry ( + (UINT8 *) PtrLine, + LineLength, + SectionHead + ); + } + + if (EFI_ERROR (Status)) { + break; + } + } + + // + // Free buffer + // + FreePool (PtrLine); + + return Status; +} + +typedef struct { + CHAR8 *String; + EFI_STATUS Status; +} EFI_STATUS_STRING; + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_STATUS_STRING mEfiStatusString[] = { + {"EFI_SUCCESS", EFI_SUCCESS}, + {"EFI_LOAD_ERROR", EFI_LOAD_ERROR}, + {"EFI_INVALID_PARAMETER", EFI_INVALID_PARAMETER}, + {"EFI_UNSUPPORTED", EFI_UNSUPPORTED}, + {"EFI_BAD_BUFFER_SIZE", EFI_BAD_BUFFER_SIZE}, + {"EFI_BUFFER_TOO_SMALL", EFI_BUFFER_TOO_SMALL}, + {"EFI_NOT_READY", EFI_NOT_READY}, + {"EFI_DEVICE_ERROR", EFI_DEVICE_ERROR}, + {"EFI_WRITE_PROTECTED", EFI_WRITE_PROTECTED}, + {"EFI_OUT_OF_RESOURCES", EFI_OUT_OF_RESOURCES}, + {"EFI_VOLUME_CORRUPTED", EFI_VOLUME_CORRUPTED}, + {"EFI_VOLUME_FULL", EFI_VOLUME_FULL}, + {"EFI_NO_MEDIA", EFI_NO_MEDIA}, + {"EFI_MEDIA_CHANGED", EFI_MEDIA_CHANGED}, + {"EFI_NOT_FOUND", EFI_NOT_FOUND}, + {"EFI_ACCESS_DENIED", EFI_ACCESS_DENIED}, + {"EFI_NO_RESPONSE", EFI_NO_RESPONSE}, + {"EFI_NO_MAPPING", EFI_NO_MAPPING}, + {"EFI_TIMEOUT", EFI_TIMEOUT}, + {"EFI_NOT_STARTED", EFI_NOT_STARTED}, + {"EFI_ALREADY_STARTED", EFI_ALREADY_STARTED}, + {"EFI_ABORTED", EFI_ABORTED}, + {"EFI_ICMP_ERROR", EFI_ICMP_ERROR}, + {"EFI_TFTP_ERROR", EFI_TFTP_ERROR}, + {"EFI_PROTOCOL_ERROR", EFI_PROTOCOL_ERROR}, + {"EFI_INCOMPATIBLE_VERSION", EFI_INCOMPATIBLE_VERSION}, + {"EFI_SECURITY_VIOLATION", EFI_SECURITY_VIOLATION}, + {"EFI_CRC_ERROR", EFI_CRC_ERROR}, + {"EFI_END_OF_MEDIA", EFI_END_OF_MEDIA}, + {"EFI_END_OF_FILE", EFI_END_OF_FILE}, + {"EFI_INVALID_LANGUAGE", EFI_INVALID_LANGUAGE}, + {"EFI_COMPROMISED_DATA", EFI_COMPROMISED_DATA}, +//{"EFI_IP_ADDRESS_CONFLICT", EFI_IP_ADDRESS_CONFLICT}, + {"EFI_HTTP_ERROR", EFI_HTTP_ERROR}, + {"EFI_WARN_UNKNOWN_GLYPH", EFI_WARN_UNKNOWN_GLYPH}, + {"EFI_WARN_DELETE_FAILURE", EFI_WARN_DELETE_FAILURE}, + {"EFI_WARN_WRITE_FAILURE", EFI_WARN_WRITE_FAILURE}, + {"EFI_WARN_BUFFER_TOO_SMALL", EFI_WARN_BUFFER_TOO_SMALL}, + {"EFI_WARN_STALE_DATA", EFI_WARN_STALE_DATA}, + {"EFI_WARN_FILE_SYSTEM", EFI_WARN_FILE_SYSTEM}, +//{"EFI_WARN_RESET_REQUIRED", EFI_WARN_RESET_REQUIRED}, +}; + +RETURN_STATUS +AsciiStrToEfiStatus ( + IN CONST CHAR8 *String, + OUT EFI_STATUS *Status + ) +{ + UINTN Index; + + for (Index = 0; Index < ARRAY_SIZE(mEfiStatusString); Index++) { + if (AsciiStrCmp (String, mEfiStatusString[Index].String) == 0) { + *Status = mEfiStatusString[Index].Status; + return EFI_SUCCESS; + } + } + return EFI_INVALID_PARAMETER; +} + +/** + Open an INI config file and return a context. + + @param[in] DataBuffer Config raw file buffer. + @param[in] BufferSize Size of raw buffer. + + @return Config data buffer is opened and context is returned. + @retval NULL No enough memory is allocated. + @retval NULL Config data buffer is invalid. +**/ +VOID * +EFIAPI +OpenIniFile ( + IN UINT8 *DataBuffer, + IN UINTN BufferSize + ) +{ + EFI_STATUS Status; + INI_PARSING_LIB_CONTEXT *IniContext; + + if (DataBuffer == NULL || BufferSize == 0) { + return NULL; + } + + IniContext = AllocateZeroPool(sizeof(INI_PARSING_LIB_CONTEXT)); + if (IniContext == NULL) { + return NULL; + } + + // + // First process the data buffer and get all sections and entries + // + Status = PreProcessDataFile ( + DataBuffer, + BufferSize, + &IniContext->SectionHead, + &IniContext->CommentHead + ); + if (EFI_ERROR(Status)) { + FreePool(IniContext); + return NULL; + } + DEBUG_CODE_BEGIN (); + DumpIniSection(IniContext); + DEBUG_CODE_END (); + return IniContext; +} + +/** + Get section entry string value. + + @param[in] Context INI Config file context. + @param[in] SectionName Section name. + @param[in] EntryName Section entry name. + @param[out] EntryValue Point to the got entry string value. + + @retval EFI_SUCCESS Section entry string value is got. + @retval EFI_NOT_FOUND Section is not found. +**/ +EFI_STATUS +EFIAPI +GetStringFromDataFile( + IN VOID *Context, + IN CHAR8 *SectionName, + IN CHAR8 *EntryName, + OUT CHAR8 **EntryValue + ) +{ + INI_PARSING_LIB_CONTEXT *IniContext; + EFI_STATUS Status; + + if (Context == NULL || SectionName == NULL || EntryName == NULL || EntryValue == NULL) { + return EFI_INVALID_PARAMETER; + } + + IniContext = Context; + + *EntryValue = NULL; + Status = UpdateGetProfileString ( + IniContext->SectionHead, + SectionName, + EntryName, + EntryValue + ); + return Status; +} + +/** + Get section entry GUID value. + + @param[in] Context INI Config file context. + @param[in] SectionName Section name. + @param[in] EntryName Section entry name. + @param[out] Guid Point to the got GUID value. + + @retval EFI_SUCCESS Section entry GUID value is got. + @retval EFI_NOT_FOUND Section is not found. + @retval EFI_INVALID_PARAMETER Section format is invalid. +**/ +EFI_STATUS +EFIAPI +GetGuidFromDataFile ( + IN VOID *Context, + IN CHAR8 *SectionName, + IN CHAR8 *EntryName, + OUT EFI_GUID *Guid + ) +{ + CHAR8 *Value; + EFI_STATUS Status; + RETURN_STATUS RStatus; + + if (Context == NULL || SectionName == NULL || EntryName == NULL || Guid == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = GetStringFromDataFile( + Context, + SectionName, + EntryName, + &Value + ); + if (EFI_ERROR(Status)) { + return EFI_NOT_FOUND; + } + ASSERT (Value != NULL); + RStatus = AsciiStrToGuid (Value, Guid); + if (RETURN_ERROR (RStatus) || (Value[GUID_STRING_LENGTH] != '\0')) { + return EFI_INVALID_PARAMETER; + } + return EFI_SUCCESS; +} + +/** + Get section entry EFI_STATUS value. + + @param[in] Context INI Config file context. + @param[in] SectionName Section name. + @param[in] EntryName Section entry name. + @param[out] Guid Point to the got GUID value. + + @retval EFI_SUCCESS Section entry EFI_STATUS value is got. + @retval EFI_NOT_FOUND Section is not found. + @retval EFI_INVALID_PARAMETER Section format is invalid. +**/ +EFI_STATUS +EFIAPI +GetEfiStatusFromDataFile ( + IN VOID *Context, + IN CHAR8 *SectionName, + IN CHAR8 *EntryName, + OUT EFI_STATUS *EfiStatus + ) +{ + CHAR8 *Value; + EFI_STATUS Status; + RETURN_STATUS RStatus; + + if (Context == NULL || SectionName == NULL || EntryName == NULL || EfiStatus == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = GetStringFromDataFile( + Context, + SectionName, + EntryName, + &Value + ); + if (EFI_ERROR(Status)) { + return EFI_NOT_FOUND; + } + ASSERT (Value != NULL); + RStatus = AsciiStrToEfiStatus (Value, EfiStatus); + if (RETURN_ERROR (RStatus)) { + return EFI_INVALID_PARAMETER; + } + return EFI_SUCCESS; +} + +/** + Get section entry decimal UINTN value. + + @param[in] Context INI Config file context. + @param[in] SectionName Section name. + @param[in] EntryName Section entry name. + @param[out] Data Point to the got decimal UINTN value. + + @retval EFI_SUCCESS Section entry decimal UINTN value is got. + @retval EFI_NOT_FOUND Section is not found. + @retval EFI_INVALID_PARAMETER Section format is invalid. +**/ +EFI_STATUS +EFIAPI +GetDecimalUintnFromDataFile ( + IN VOID *Context, + IN CHAR8 *SectionName, + IN CHAR8 *EntryName, + OUT UINTN *Data + ) +{ + CHAR8 *Value; + EFI_STATUS Status; + + if (Context == NULL || SectionName == NULL || EntryName == NULL || Data == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = GetStringFromDataFile( + Context, + SectionName, + EntryName, + &Value + ); + if (EFI_ERROR(Status)) { + return EFI_NOT_FOUND; + } + ASSERT (Value != NULL); + if (!IsValidDecimalString(Value, AsciiStrLen(Value))) { + return EFI_INVALID_PARAMETER; + } + *Data = AsciiStrDecimalToUintn(Value); + return EFI_SUCCESS; +} + +/** + Get section entry heximal UINTN value. + + @param[in] Context INI Config file context. + @param[in] SectionName Section name. + @param[in] EntryName Section entry name. + @param[out] Data Point to the got heximal UINTN value. + + @retval EFI_SUCCESS Section entry heximal UINTN value is got. + @retval EFI_NOT_FOUND Section is not found. + @retval EFI_INVALID_PARAMETER Section format is invalid. +**/ +EFI_STATUS +EFIAPI +GetHexUintnFromDataFile ( + IN VOID *Context, + IN CHAR8 *SectionName, + IN CHAR8 *EntryName, + OUT UINTN *Data + ) +{ + CHAR8 *Value; + EFI_STATUS Status; + + if (Context == NULL || SectionName == NULL || EntryName == NULL || Data == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = GetStringFromDataFile( + Context, + SectionName, + EntryName, + &Value + ); + if (EFI_ERROR(Status)) { + return EFI_NOT_FOUND; + } + ASSERT (Value != NULL); + if (!IsValidHexString(Value, AsciiStrLen(Value))) { + return EFI_INVALID_PARAMETER; + } + *Data = AsciiStrHexToUintn(Value); + return EFI_SUCCESS; +} + +/** + Get section entry heximal UINT64 value. + + @param[in] Context INI Config file context. + @param[in] SectionName Section name. + @param[in] EntryName Section entry name. + @param[out] Data Point to the got heximal UINT64 value. + + @retval EFI_SUCCESS Section entry heximal UINT64 value is got. + @retval EFI_NOT_FOUND Section is not found. + @retval EFI_INVALID_PARAMETER Section format is invalid. +**/ +EFI_STATUS +EFIAPI +GetHexUint64FromDataFile ( + IN VOID *Context, + IN CHAR8 *SectionName, + IN CHAR8 *EntryName, + OUT UINT64 *Data + ) +{ + CHAR8 *Value; + EFI_STATUS Status; + + if (Context == NULL || SectionName == NULL || EntryName == NULL || Data == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = GetStringFromDataFile( + Context, + SectionName, + EntryName, + &Value + ); + if (EFI_ERROR(Status)) { + return EFI_NOT_FOUND; + } + ASSERT (Value != NULL); + if (!IsValidHexString(Value, AsciiStrLen(Value))) { + return EFI_INVALID_PARAMETER; + } + *Data = AsciiStrHexToUint64(Value); + return EFI_SUCCESS; +} + +/** + Close an INI config file and free the context. + + @param[in] Context INI Config file context. +**/ +VOID +EFIAPI +CloseIniFile ( + IN VOID *Context + ) +{ + INI_PARSING_LIB_CONTEXT *IniContext; + + if (Context == NULL) { + return ; + } + + IniContext = Context; + FreeAllList(IniContext->SectionHead, IniContext->CommentHead); + + return; +} diff --git a/HBFA/UefiInstrumentTestPkg/Library/IniParsingLib/IniParsingLib.inf b/HBFA/UefiInstrumentTestPkg/Library/IniParsingLib/IniParsingLib.inf new file mode 100644 index 0000000..9147141 --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/IniParsingLib/IniParsingLib.inf @@ -0,0 +1,37 @@ +## @file +# INI configuration parsing library. +# +# This library parses the INI configuration file. +# +# Copyright (c) 2016, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = IniParsingLib + MODULE_UNI_FILE = IniParsingLib.uni + FILE_GUID = 6E4CD200-43E5-43CE-89E9-D715CF9526C4 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = IniParsingLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + IniParsingLib.c + +[Packages] + MdePkg/MdePkg.dec + UefiInstrumentTestPkg/UefiInstrumentTestPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + MemoryAllocationLib diff --git a/HBFA/UefiInstrumentTestPkg/Library/IniParsingLib/IniParsingLib.uni b/HBFA/UefiInstrumentTestPkg/Library/IniParsingLib/IniParsingLib.uni new file mode 100644 index 0000000..1c0f360 --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/IniParsingLib/IniParsingLib.uni @@ -0,0 +1,16 @@ +// /** @file +// INI configuration parsing library. +// +// This library parses the INI configuration file. +// +// Copyright (c) 2016, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "INI configuration parsing library." + +#string STR_MODULE_DESCRIPTION #language en-US "This library parses the INI configuration file." + diff --git a/HBFA/UefiInstrumentTestPkg/Library/InstrumentHookLibNull/InstrumentHookLibNull.c b/HBFA/UefiInstrumentTestPkg/Library/InstrumentHookLibNull/InstrumentHookLibNull.c new file mode 100644 index 0000000..aaf5d6d --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/InstrumentHookLibNull/InstrumentHookLibNull.c @@ -0,0 +1,31 @@ +/** @file + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +UINTN +EFIAPI +FunctionEnter ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + return 0; +} + +VOID +EFIAPI +FunctionExit ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN FunctionAddress, + IN UINTN CallerAddress + ) +{ + return ; +} diff --git a/HBFA/UefiInstrumentTestPkg/Library/InstrumentHookLibNull/InstrumentHookLibNull.inf b/HBFA/UefiInstrumentTestPkg/Library/InstrumentHookLibNull/InstrumentHookLibNull.inf new file mode 100644 index 0000000..24c0f6e --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/InstrumentHookLibNull/InstrumentHookLibNull.inf @@ -0,0 +1,29 @@ +## @file +# +# Copyright (c) 2017, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = InstrumentHookLibNull + FILE_GUID = B3044F07-E1C8-412B-ADD5-AD93DB330966 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = InstrumentHookLib + +[Sources] + InstrumentHookLibNull.c + +[Packages] + MdePkg/MdePkg.dec + UefiInstrumentTestPkg/UefiInstrumentTestPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + +[BuildOptions] + MSFT:*_*_*_CC_FLAGS = /Od /GL- + GCC:*_*_*_CC_FLAGS = -O0 diff --git a/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/Ia32/CygProfileEnterExit.nasm b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/Ia32/CygProfileEnterExit.nasm new file mode 100644 index 0000000..14224c8 --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/Ia32/CygProfileEnterExit.nasm @@ -0,0 +1,96 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + +extern ASM_PFX(CygProfileEnter) +extern ASM_PFX(CygProfileExit) + + SECTION .text + +; void __cyg_profile_func_enter (void *this_fn, void *call_site) +global ASM_PFX(__cyg_profile_func_enter) +ASM_PFX(__cyg_profile_func_enter): + ; prolog - begin + push ebp + mov ebp, esp + + push eax + push ecx + push edx + push ebx + mov eax, ebp + add eax, 4 ; the caller to __cyg_profile_func_enter + push eax ; original esp + mov eax, [ebp] + push eax ; original ebp + push esi + push edi + ; prolog - end + + mov eax, [ebp + 8] ; eax = func address + mov ecx, esp ; ecx = context + mov edx, [ebp + 12] ; edx = caller address + push eax + push edx + push ecx + call ASM_PFX(CygProfileEnter) + add esp, 12 + + ; epilog - begin + pop edi + pop esi + add esp, 4 ; skip ebp + add esp, 4 ; skip esp + pop ebx + pop edx + pop ecx + pop eax + mov esp, ebp + pop ebp + ; epilog - end + ret + +; void __cyg_profile_func_exit (void *this_fn, void *call_site) +global ASM_PFX(__cyg_profile_func_exit) +ASM_PFX(__cyg_profile_func_exit): + ; prolog - begin + push ebp + mov ebp, esp + + push eax + push ecx + push edx + push ebx + mov eax, ebp + add eax, 4 ; the caller to __cyg_profile_func_exit + push eax ; original esp + mov eax, [ebp] + push eax ; original ebp + push esi + push edi + ; prolog - end + + mov eax, [ebp + 8] ; eax = func address + mov ecx, esp ; ecx = context + mov edx, [ebp + 12] ; edx = caller address + push eax + push edx + push ecx + call ASM_PFX(CygProfileExit) + add esp, 12 + + ; epilog - begin + pop edi + pop esi + add esp, 4 ; skip ebp + add esp, 4 ; skip esp + pop ebx + pop edx + pop ecx + pop eax + mov esp, ebp + pop ebp + ; epilog - end + ret diff --git a/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/Ia32/CygProfileEnterExitStub.c b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/Ia32/CygProfileEnterExitStub.c new file mode 100644 index 0000000..8c3685b --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/Ia32/CygProfileEnterExitStub.c @@ -0,0 +1,39 @@ +/** @file + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +UINTN +EFIAPI +CygProfileEnter ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN CallerAddress, + IN UINTN FunctionAddress + ) +{ + EntryContext.Ia32->Esp = EntryContext.Ia32->Ebp; + EntryContext.Ia32->Esp += 4; // the caller to the caller to __cyg_profile_func_enter + + return FunctionEnter (EntryContext, FunctionAddress, CallerAddress); +} + +VOID +EFIAPI +CygProfileExit ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN CallerAddress, + IN UINTN FunctionAddress + ) +{ + ExitContext.Ia32->Esp = ExitContext.Ia32->Ebp; + ExitContext.Ia32->Esp += 4; // the caller to the caller to __cyg_profile_func_enter + + FunctionExit (ExitContext, FunctionAddress, CallerAddress); +} diff --git a/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/Ia32/FuncParam.c b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/Ia32/FuncParam.c new file mode 100644 index 0000000..3ce3b22 --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/Ia32/FuncParam.c @@ -0,0 +1,157 @@ +/** @file + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +VOID +EFIAPI +SetReturnValue ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN RetVal + ) +{ + ExitContext.Ia32->Eax = RetVal; +} + +VOID +EFIAPI +SetReturnValue64 ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINT64 RetVal + ) +{ + ExitContext.Ia32->Eax = (UINT32)RetVal; + ExitContext.Ia32->Edx = (UINT32)RShiftU64(RetVal, 32); +} + +UINTN +EFIAPI +GetReturnValue ( + IN OUT FUNC_EXIT_CONTEXT ExitContext + ) +{ + return ExitContext.Ia32->Eax; +} + +UINT64 +EFIAPI +GetReturnValue64 ( + IN OUT FUNC_EXIT_CONTEXT ExitContext + ) +{ + return (UINT64)ExitContext.Ia32->Eax + RShiftU64(ExitContext.Ia32->Edx, 32); +} + +UINTN +EFIAPI +GetParameterValue ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN Index + ) +{ + UINTN *StackPointer; + + ASSERT(EntryContext.Ia32->Esp != 0); + StackPointer = (UINTN *)(UINTN)(EntryContext.Ia32->Esp); + return *(StackPointer + Index); +} + +UINT64 +EFIAPI +GetParameterValue64 ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN Index + ) +{ + UINTN *StackPointer; + + ASSERT(EntryContext.Ia32->Esp != 0); + StackPointer = (UINTN *)(UINTN)(EntryContext.Ia32->Esp); + return *(UINT64 *)(StackPointer + Index); +} + +UINTN +EFIAPI +GetReturnParameterValue ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN Index + ) +{ + UINTN *StackPointer; + + ASSERT(ExitContext.Ia32->Esp != 0); + StackPointer = (UINTN *)(UINTN)(ExitContext.Ia32->Esp); + return *(StackPointer + Index); +} + +UINT64 +EFIAPI +GetReturnParameterValue64 ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN Index + ) +{ + UINTN *StackPointer; + + ASSERT(ExitContext.Ia32->Esp != 0); + StackPointer = (UINTN *)(UINTN)(ExitContext.Ia32->Esp); + return *(UINT64 *)(StackPointer + Index); +} + +VOID +EFIAPI +SetParameterValue ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN Index, + IN UINTN Data + ) +{ + UINTN *StackPointer; + + ASSERT(EntryContext.Ia32->Esp != 0); + StackPointer = (UINTN *)(UINTN)(EntryContext.Ia32->Esp); + *(StackPointer + Index) = Data; +} + +VOID +EFIAPI +SetParameterValue64 ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN Index, + IN UINT64 Data + ) +{ + UINTN *StackPointer; + + ASSERT(EntryContext.Ia32->Esp != 0); + StackPointer = (UINTN *)(UINTN)(EntryContext.Ia32->Esp); + *(UINT64 *)(StackPointer + Index) = Data; +} + +VOID +EFIAPI +SetSkipReturnValue ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN RetVal + ) +{ + EntryContext.Ia32->Eax = RetVal; +} + +VOID +EFIAPI +SetSkipReturnValue64 ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINT64 RetVal + ) +{ + EntryContext.Ia32->Eax = (UINT32)RetVal; + EntryContext.Ia32->Edx = (UINT32)RShiftU64(RetVal, 32); +} diff --git a/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/Ia32/FuncParamGcc.c b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/Ia32/FuncParamGcc.c new file mode 100644 index 0000000..dfe925f --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/Ia32/FuncParamGcc.c @@ -0,0 +1,156 @@ +/** @file + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +VOID +EFIAPI +SetReturnValue ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN RetVal + ) +{ + ExitContext.Ia32->Ebx = RetVal; +} + +VOID +EFIAPI +SetReturnValue64 ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINT64 RetVal + ) +{ + ExitContext.Ia32->Ebx = (UINT32)RetVal; + ExitContext.Ia32->Esi = (UINT32)RShiftU64(RetVal, 32); +} + +UINTN +EFIAPI +GetReturnValue ( + IN OUT FUNC_EXIT_CONTEXT ExitContext + ) +{ + return ExitContext.Ia32->Ebx; +} + +UINT64 +EFIAPI +GetReturnValue64 ( + IN OUT FUNC_EXIT_CONTEXT ExitContext + ) +{ + return (UINT64)ExitContext.Ia32->Ebx + RShiftU64(ExitContext.Ia32->Esi, 32); +} + +UINTN +EFIAPI +GetParameterValue ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN Index + ) +{ + UINTN *StackPointer; + + ASSERT(EntryContext.Ia32->Esp != 0); + StackPointer = (UINTN *)(UINTN)(EntryContext.Ia32->Esp); + return *(StackPointer + Index); +} + +UINT64 +EFIAPI +GetParameterValue64 ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN Index + ) +{ + UINTN *StackPointer; + + ASSERT(EntryContext.Ia32->Esp != 0); + StackPointer = (UINTN *)(UINTN)(EntryContext.Ia32->Esp); + return *(UINT64 *)(StackPointer + Index); +} + +UINTN +EFIAPI +GetReturnParameterValue ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN Index + ) +{ + UINTN *StackPointer; + + ASSERT(ExitContext.Ia32->Esp != 0); + StackPointer = (UINTN *)(UINTN)(ExitContext.Ia32->Esp); + return *(StackPointer + Index); +} + +UINT64 +EFIAPI +GetReturnParameterValue64 ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN Index + ) +{ + UINTN *StackPointer; + + ASSERT(ExitContext.Ia32->Esp != 0); + StackPointer = (UINTN *)(UINTN)(ExitContext.Ia32->Esp); + return *(UINT64 *)(StackPointer + Index); +} + +VOID +EFIAPI +SetParameterValue ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN Index, + IN UINTN Data + ) +{ + UINTN *StackPointer; + + ASSERT(EntryContext.Ia32->Esp != 0); + StackPointer = (UINTN *)(UINTN)(EntryContext.Ia32->Esp); + *(StackPointer + Index) = Data; +} + +VOID +EFIAPI +SetParameterValue64 ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN Index, + IN UINT64 Data + ) +{ + UINTN *StackPointer; + + ASSERT(EntryContext.Ia32->Esp != 0); + StackPointer = (UINTN *)(UINTN)(EntryContext.Ia32->Esp); + *(UINT64 *)(StackPointer + Index) = Data; +} + +VOID +EFIAPI +SetSkipReturnValue ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN RetVal + ) +{ + // unsupported +} + +VOID +EFIAPI +SetSkipReturnValue64 ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINT64 RetVal + ) +{ + // unsupported +} diff --git a/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/Ia32/FuncParamMsvc.c b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/Ia32/FuncParamMsvc.c new file mode 100644 index 0000000..3ce3b22 --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/Ia32/FuncParamMsvc.c @@ -0,0 +1,157 @@ +/** @file + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +VOID +EFIAPI +SetReturnValue ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN RetVal + ) +{ + ExitContext.Ia32->Eax = RetVal; +} + +VOID +EFIAPI +SetReturnValue64 ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINT64 RetVal + ) +{ + ExitContext.Ia32->Eax = (UINT32)RetVal; + ExitContext.Ia32->Edx = (UINT32)RShiftU64(RetVal, 32); +} + +UINTN +EFIAPI +GetReturnValue ( + IN OUT FUNC_EXIT_CONTEXT ExitContext + ) +{ + return ExitContext.Ia32->Eax; +} + +UINT64 +EFIAPI +GetReturnValue64 ( + IN OUT FUNC_EXIT_CONTEXT ExitContext + ) +{ + return (UINT64)ExitContext.Ia32->Eax + RShiftU64(ExitContext.Ia32->Edx, 32); +} + +UINTN +EFIAPI +GetParameterValue ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN Index + ) +{ + UINTN *StackPointer; + + ASSERT(EntryContext.Ia32->Esp != 0); + StackPointer = (UINTN *)(UINTN)(EntryContext.Ia32->Esp); + return *(StackPointer + Index); +} + +UINT64 +EFIAPI +GetParameterValue64 ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN Index + ) +{ + UINTN *StackPointer; + + ASSERT(EntryContext.Ia32->Esp != 0); + StackPointer = (UINTN *)(UINTN)(EntryContext.Ia32->Esp); + return *(UINT64 *)(StackPointer + Index); +} + +UINTN +EFIAPI +GetReturnParameterValue ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN Index + ) +{ + UINTN *StackPointer; + + ASSERT(ExitContext.Ia32->Esp != 0); + StackPointer = (UINTN *)(UINTN)(ExitContext.Ia32->Esp); + return *(StackPointer + Index); +} + +UINT64 +EFIAPI +GetReturnParameterValue64 ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN Index + ) +{ + UINTN *StackPointer; + + ASSERT(ExitContext.Ia32->Esp != 0); + StackPointer = (UINTN *)(UINTN)(ExitContext.Ia32->Esp); + return *(UINT64 *)(StackPointer + Index); +} + +VOID +EFIAPI +SetParameterValue ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN Index, + IN UINTN Data + ) +{ + UINTN *StackPointer; + + ASSERT(EntryContext.Ia32->Esp != 0); + StackPointer = (UINTN *)(UINTN)(EntryContext.Ia32->Esp); + *(StackPointer + Index) = Data; +} + +VOID +EFIAPI +SetParameterValue64 ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN Index, + IN UINT64 Data + ) +{ + UINTN *StackPointer; + + ASSERT(EntryContext.Ia32->Esp != 0); + StackPointer = (UINTN *)(UINTN)(EntryContext.Ia32->Esp); + *(UINT64 *)(StackPointer + Index) = Data; +} + +VOID +EFIAPI +SetSkipReturnValue ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN RetVal + ) +{ + EntryContext.Ia32->Eax = RetVal; +} + +VOID +EFIAPI +SetSkipReturnValue64 ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINT64 RetVal + ) +{ + EntryContext.Ia32->Eax = (UINT32)RetVal; + EntryContext.Ia32->Edx = (UINT32)RShiftU64(RetVal, 32); +} diff --git a/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/Ia32/PEnterExit.nasm b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/Ia32/PEnterExit.nasm new file mode 100644 index 0000000..94ab486 --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/Ia32/PEnterExit.nasm @@ -0,0 +1,296 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + +extern ASM_PFX(Cpenter) +extern ASM_PFX(Cpexit) + +%define PARAM_COUNT 14 + + SECTION .text + +; void __declspec(naked) _cdecl _penter( void ) +global ASM_PFX(_penter) +ASM_PFX(_penter): +;--------------- +; P1: Context +;--------------- +; P2: Ret Addr +;--------------- +; EDI | +;--------------- +; ESI | +;--------------- +; EBP | +;--------------- +; ESP | +;--------------- +; EBX | +;--------------- +; EDX | +;--------------- +; ECX | +;--------------- +; EAX | +;--------------- +; EBP <- EBP +;--------------- +; Addr in FuncB +;--------------- +; Addr in FuncA +;--------------- +; Param +;--------------- + ; prolog - begin + push ebp + mov ebp, esp + + push eax + push ecx + push edx + push ebx + mov eax, ebp + add eax, 4 ; the caller to _penter + push eax ; original esp + mov eax, [ebp] + push eax ; original ebp + push esi + push edi + ; prolog - end + + mov ecx, esp ; ecx = context + mov edx, [ebp + 4] ; edx = return address + push edx + push ecx + call ASM_PFX(Cpenter) + add esp, 8 + + ; epilog - begin + pop edi + pop esi + add esp, 4 ; skip ebp + add esp, 4 ; skip esp + pop ebx + pop edx + pop ecx + + cmp eax, 0 + jz Exit + +; skip function + +;--------------- +; EAX | +;--------------- +; EBP <- EBP | EAX +;--------------- +; Addr in FuncB | EBP <- EBP +;--------------- +; Addr in FuncA | <- ESP +;--------------- +; Param +;--------------- + mov eax, [ebp - 4 * 5] + mov esp, eax + mov eax, [ebp] + mov [esp - 4], eax + mov eax, [ebp - 4] + mov [esp - 8], eax + sub esp, 8 + mov ebp, esp + add ebp, 4 + + pop eax + mov esp, ebp + pop ebp + ; epilog - end + ret + +Exit: + push ecx + push edx + push esi + push edi + +; copy the param + +;--------------- +; EDI +;--------------- +; ESI +;--------------- +; EDX +;--------------- +; ECX +;--------------- +; EAX +;--------------- +; EBP <- EBP +;--------------- +; Addr in FuncB +;--------------- +; Addr in FuncA +;--------------- +; Param (4 * PARAM_COUNT) +;--------------- +; EDI | <- ESP +;--------------- +; ESI +;--------------- +; EDX +;--------------- +; ECX +;--------------- +; EAX +;--------------- +; EBP <- EBP +;--------------- +; Addr in FuncB +;--------------- +; Addr in FuncA +;--------------- +; Param +;--------------- + sub esp, (4 * PARAM_COUNT + 4 * 8) + mov esi, esp + mov edi, esi + add esi, (4 * PARAM_COUNT + 4 * 8) + mov ecx, (PARAM_COUNT + 8) + rep movsd + sub ebp, (4 * PARAM_COUNT + 4 * 8) + + pop edi + pop esi + pop edx + pop ecx + + pop eax + mov esp, ebp + pop ebp + ; epilog - end + ret + +; void __declspec(naked) _cdecl _pexit( void ) +global ASM_PFX(_pexit) +ASM_PFX(_pexit): +;--------------- +; EBP <- EBP +;--------------- +; Addr in FuncB +;--------------- +; Addr in FuncA +;--------------- +; Param (4 * PARAM_COUNT) +;--------------- +; EDI +;--------------- +; ESI +;--------------- +; EDX +;--------------- +; ECX +;--------------- +; EAX +;--------------- +; EBP <- EBP +;--------------- +; Addr in FuncB +;--------------- +; Addr in FuncA +;--------------- +; Param +;--------------- + ; prolog - begin + push ebp + mov ebp, esp + + push eax + push ecx + push edx + push ebx + mov eax, ebp + add eax, 4 ; the caller to _pexit + push eax ; original esp + mov eax, [ebp] + push eax ; original ebp + push esi + push edi + ; prolog - end + + mov ecx, esp ; ecx = context + mov edx, [ebp + 4 * (2 + PARAM_COUNT + 7)] ; edx = return address + push edx + push ecx + call ASM_PFX(Cpexit) + add esp, 8 + + ; epilog - begin + pop edi + pop esi + add esp, 4 ; skip ebp + add esp, 4 ; skip esp + pop ebx + pop edx + pop ecx + +;--------------- +; EDI +;--------------- +; ESI +;--------------- +; EDX +;--------------- +; ECX +;--------------- +; EAX +;--------------- +; EBP <- EBP +;--------------- +; Addr in FuncB +;--------------- +; Addr in FuncA +;--------------- +; Param (4 * PARAM_COUNT) +;--------------- +; EDI +;--------------- +; ESI +;--------------- +; EDX +;--------------- +; ECX +;--------------- +; EAX +;--------------- +; EBP <- EBP +;--------------- +; Addr in FuncB +;--------------- +; Addr in FuncA +;--------------- +; Param +;--------------- + push ecx + push edx + push esi + push edi + mov esi, esp + mov edi, esi + add edi, (4 * PARAM_COUNT + 4 * 8) + mov ecx, (7) + rep movsd + add ebp, (4 * PARAM_COUNT + 4 * 8) + add esp, (4 * PARAM_COUNT + 4 * 8) + + pop edi + pop esi + pop edx + pop ecx + + pop eax + mov esp, ebp + pop ebp + ; epilog - end + ret diff --git a/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/Ia32/PEnterExitStub.c b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/Ia32/PEnterExitStub.c new file mode 100644 index 0000000..d778b6d --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/Ia32/PEnterExitStub.c @@ -0,0 +1,61 @@ +/** @file + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +UINTN +GetFunctionAddress ( + IN UINTN ReturnAddress + ) +{ + UINTN FunctionAddress; + + FunctionAddress = (ReturnAddress - 5); + + return FunctionAddress; +} + +UINTN +EFIAPI +Cpenter ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN ReturnAddress + ) +{ + UINTN FunctionAddress; + UINTN CallerAddress; + + FunctionAddress = GetFunctionAddress (ReturnAddress); + + EntryContext.Ia32->Esp += 4; // the caller to the caller to _penter + + CallerAddress = *(UINTN *)(UINTN)(EntryContext.Ia32->Esp); + + return FunctionEnter (EntryContext, FunctionAddress, CallerAddress); +} + +VOID +EFIAPI +Cpexit ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN ReturnAddress + ) +{ + UINTN FunctionAddress; + UINTN CallerAddress; + + FunctionAddress = GetFunctionAddress (ReturnAddress); + + ExitContext.Ia32->Esp += 4; // the caller to the caller to _penter + + CallerAddress = *(UINTN *)((UINTN)ExitContext.Ia32->Esp); + + FunctionExit (ExitContext, FunctionAddress, CallerAddress); +} diff --git a/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/InstrumentLib.inf b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/InstrumentLib.inf new file mode 100644 index 0000000..ca25812 --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/InstrumentLib.inf @@ -0,0 +1,48 @@ +## @file +# +# Copyright (c) 2017, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = InstrumentLib + FILE_GUID = 06C8E8A4-C8A8-4E19-B38D-13F0E1E48470 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = NULL + +[Sources] + +[Sources.Ia32] + Ia32/FuncParamMsvc.c | MSFT + Ia32/PEnterExit.nasm | MSFT + Ia32/PEnterExitStub.c | MSFT + Ia32/FuncParamGcc.c | GCC + Ia32/CygProfileEnterExit.nasm | GCC + Ia32/CygProfileEnterExitStub.c | GCC + +[Sources.X64] + X64/FuncParamMsvc.c | MSFT + X64/PEnterExit.nasm | MSFT + X64/PEnterExitStub.c | MSFT + X64/FuncParamGcc.c | GCC + X64/CygProfileEnterExit.nasm | GCC + X64/CygProfileEnterExitStub.c | GCC + +[Packages] + MdePkg/MdePkg.dec + UefiInstrumentTestPkg/UefiInstrumentTestPkg.dec + +[LibraryClasses] + BaseLib + InstrumentHookLib + DebugLib + +[BuildOptions] + # https://msdn.microsoft.com/en-us/library/c63a9b7h.aspx + MSFT:*_*_*_CC_FLAGS = /Od /GL- + # https://gcc.gnu.org/onlinedocs/gcc-4.3.3/gcc/Code-Gen-Options.html#Code-Gen-Options + GCC:*_*_*_CC_FLAGS = -O0 + diff --git a/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/X64/CygProfileEnterExit.nasm b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/X64/CygProfileEnterExit.nasm new file mode 100644 index 0000000..0768049 --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/X64/CygProfileEnterExit.nasm @@ -0,0 +1,124 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + +extern ASM_PFX(CygProfileEnter) +extern ASM_PFX(CygProfileExit) + + SECTION .text + +; void __cyg_profile_func_enter (void *this_fn, void *call_site) +global ASM_PFX(__cyg_profile_func_enter) +ASM_PFX(__cyg_profile_func_enter): + ; prolog - begin + push rbp + mov rbp, rsp + + push rax + push rcx + push rdx + push rbx + mov rax, rbp + add rax, 8 ; the caller to __cyg_profile_func_enter + push rax ; original rsp + mov rax, [rbp] + push rax ; original rbp + push rsi + push rdi + push r8 + push r9 + push r10 + push r11 + push r12 + push r13 + push r14 + push r15 + ; prolog - end + + mov r8, rdi ; r8 = func address + mov rcx, rsp ; rcx = context + mov rdx, rsi ; rdx = caller address + sub rsp, 0x20 + call ASM_PFX(CygProfileEnter) + add rsp, 0x20 + + ; epilog - begin + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop rdi + pop rsi + add rsp, 8 ; skip rbp + add rsp, 8 ; skip rsp + pop rbx + pop rdx + pop rcx + pop rax + mov rsp, rbp + pop rbp + ; epilog - end + ret + +; void __cyg_profile_func_exit (void *this_fn, void *call_site) +global ASM_PFX(__cyg_profile_func_exit) +ASM_PFX(__cyg_profile_func_exit): + ; prolog - begin + push rbp + mov rbp, rsp + + push rax + push rcx + push rdx + push rbx + mov rax, rbp + add rax, 8 ; the caller to _penter + push rax ; original rsp + mov rax, [rbp] + push rax ; original rbp + push rsi + push rdi + push r8 + push r9 + push r10 + push r11 + push r12 + push r13 + push r14 + push r15 + ; prolog - end + + mov r8, rdi ; r8 = func address + mov rcx, rsp ; rcx = context + mov rdx, rsi ; rdx = caller address + sub rsp, 0x20 + call ASM_PFX(CygProfileExit) + add rsp, 0x20 + + ; epilog - begin + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop rdi + pop rsi + add rsp, 8 ; skip rbp + add rsp, 8 ; skip rsp + pop rbx + pop rdx + pop rcx + pop rax + mov rsp, rbp + pop rbp + ; epilog - end + ret diff --git a/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/X64/CygProfileEnterExitStub.c b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/X64/CygProfileEnterExitStub.c new file mode 100644 index 0000000..901efc3 --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/X64/CygProfileEnterExitStub.c @@ -0,0 +1,39 @@ +/** @file + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +UINTN +EFIAPI +CygProfileEnter ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN CallerAddress, + IN UINTN FunctionAddress + ) +{ + EntryContext.X64->Rsp = EntryContext.X64->Rbp; + EntryContext.X64->Rsp += 8; // the caller to the caller to __cyg_profile_func_enter + + return FunctionEnter (EntryContext, FunctionAddress, CallerAddress); +} + +VOID +EFIAPI +CygProfileExit ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN CallerAddress, + IN UINTN FunctionAddress + ) +{ + ExitContext.X64->Rsp = ExitContext.X64->Rbp; + ExitContext.X64->Rsp += 8; // the caller to the caller to __cyg_profile_func_enter + + FunctionExit (ExitContext, FunctionAddress, CallerAddress); +} diff --git a/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/X64/FuncParam.c b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/X64/FuncParam.c new file mode 100644 index 0000000..ff3e5d7 --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/X64/FuncParam.c @@ -0,0 +1,171 @@ +/** @file + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include + +/* + GCC calling convention: rdi/rsi/rdx/rcx/r8/r9 +*/ + +VOID +EFIAPI +SetReturnValue ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN RetVal + ) +{ + ExitContext.X64->Rax = RetVal; +} + +VOID +EFIAPI +SetReturnValue64 ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINT64 RetVal + ) +{ + SetReturnValue (ExitContext, RetVal); +} + +UINTN +EFIAPI +GetReturnValue ( + IN OUT FUNC_EXIT_CONTEXT ExitContext + ) +{ + return ExitContext.X64->Rax; +} + +UINT64 +EFIAPI +GetReturnValue64 ( + IN OUT FUNC_EXIT_CONTEXT ExitContext + ) +{ + return GetReturnValue (ExitContext); +} + +UINTN +EFIAPI +GetParameterValue ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN Index + ) +{ + UINTN *StackPointer; + + ASSERT(EntryContext.X64->Rsp != 0); + if (Index == 1) { + return EntryContext.X64->Rcx; + } else if (Index == 2) { + return EntryContext.X64->Rdx; + } else if (Index == 3) { + return EntryContext.X64->R8; + } else if (Index == 4) { + return EntryContext.X64->R9; + } else { + StackPointer = (UINTN *)(UINTN)(EntryContext.X64->Rsp); + return *(StackPointer + Index); + } +} + +UINT64 +EFIAPI +GetParameterValue64 ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN Index + ) +{ + return GetParameterValue (EntryContext, Index); +} + +UINTN +EFIAPI +GetReturnParameterValue ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN Index + ) +{ + UINTN *StackPointer; + + ASSERT(ExitContext.X64->Rsp != 0); + + StackPointer = (UINTN *)(UINTN)(ExitContext.X64->Rsp); + return *(StackPointer + Index); +} + +UINT64 +EFIAPI +GetReturnParameterValue64 ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN Index + ) +{ + return GetReturnParameterValue (ExitContext, Index); +} + +VOID +EFIAPI +SetParameterValue ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN Index, + IN UINTN Data + ) +{ + UINTN *StackPointer; + + ASSERT(EntryContext.X64->Rsp != 0); + if (Index == 1) { + EntryContext.X64->Rcx = Data; + } else if (Index == 2) { + EntryContext.X64->Rdx = Data; + } else if (Index == 3) { + EntryContext.X64->R8 = Data; + } else if (Index == 4) { + EntryContext.X64->R9 = Data; + } + if (EntryContext.X64->Rsp != (UINTN)-1) { + // Update both register and stack. + StackPointer = (UINTN *)(UINTN)(EntryContext.X64->Rsp); + *(StackPointer + Index) = Data; + } +} + +VOID +EFIAPI +SetParameterValue64 ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN Index, + IN UINT64 Data + ) +{ + SetParameterValue (EntryContext, Index, Data); +} + +VOID +EFIAPI +SetSkipReturnValue ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN RetVal + ) +{ + EntryContext.X64->Rax = RetVal; +} + +VOID +EFIAPI +SetSkipReturnValue64 ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINT64 RetVal + ) +{ + SetSkipReturnValue (EntryContext, RetVal); +} diff --git a/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/X64/FuncParamGcc.c b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/X64/FuncParamGcc.c new file mode 100644 index 0000000..bcd59fc --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/X64/FuncParamGcc.c @@ -0,0 +1,171 @@ +/** @file + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include + +/* + GCC calling convention: rdi/rsi/rdx/rcx/r8/r9 +*/ + +VOID +EFIAPI +SetReturnValue ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN RetVal + ) +{ + ExitContext.X64->Rbx = RetVal; +} + +VOID +EFIAPI +SetReturnValue64 ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINT64 RetVal + ) +{ + SetReturnValue (ExitContext, RetVal); +} + +UINTN +EFIAPI +GetReturnValue ( + IN OUT FUNC_EXIT_CONTEXT ExitContext + ) +{ + return ExitContext.X64->Rbx; +} + +UINT64 +EFIAPI +GetReturnValue64 ( + IN OUT FUNC_EXIT_CONTEXT ExitContext + ) +{ + return GetReturnValue (ExitContext); +} + +UINTN +EFIAPI +GetParameterValue ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN Index + ) +{ + UINTN *StackPointer; + + ASSERT(EntryContext.X64->Rsp != 0); + if (Index == 1) { + return EntryContext.X64->Rcx; + } else if (Index == 2) { + return EntryContext.X64->Rdx; + } else if (Index == 3) { + return EntryContext.X64->R8; + } else if (Index == 4) { + return EntryContext.X64->R9; + } else { + StackPointer = (UINTN *)(UINTN)(EntryContext.X64->Rsp); + return *(StackPointer + Index); + } +} + +UINT64 +EFIAPI +GetParameterValue64 ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN Index + ) +{ + return GetParameterValue (EntryContext, Index); +} + +UINTN +EFIAPI +GetReturnParameterValue ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN Index + ) +{ + UINTN *StackPointer; + + ASSERT(ExitContext.X64->Rsp != 0); + + StackPointer = (UINTN *)(UINTN)(ExitContext.X64->Rsp); + return *(StackPointer + Index); +} + +UINT64 +EFIAPI +GetReturnParameterValue64 ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN Index + ) +{ + return GetReturnParameterValue (ExitContext, Index); +} + +VOID +EFIAPI +SetParameterValue ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN Index, + IN UINTN Data + ) +{ + UINTN *StackPointer; + + ASSERT(EntryContext.X64->Rsp != 0); + if (Index == 1) { + EntryContext.X64->Rcx = Data; + } else if (Index == 2) { + EntryContext.X64->Rdx = Data; + } else if (Index == 3) { + EntryContext.X64->R8 = Data; + } else if (Index == 4) { + EntryContext.X64->R9 = Data; + } + if (EntryContext.X64->Rsp != (UINTN)-1) { + // Update both register and stack. + StackPointer = (UINTN *)(UINTN)(EntryContext.X64->Rsp); + *(StackPointer + Index) = Data; + } +} + +VOID +EFIAPI +SetParameterValue64 ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN Index, + IN UINT64 Data + ) +{ + SetParameterValue (EntryContext, Index, Data); +} + +VOID +EFIAPI +SetSkipReturnValue ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN RetVal + ) +{ + // unsupported +} + +VOID +EFIAPI +SetSkipReturnValue64 ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINT64 RetVal + ) +{ + // unsupported +} diff --git a/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/X64/FuncParamMsvc.c b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/X64/FuncParamMsvc.c new file mode 100644 index 0000000..ff3e5d7 --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/X64/FuncParamMsvc.c @@ -0,0 +1,171 @@ +/** @file + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include + +/* + GCC calling convention: rdi/rsi/rdx/rcx/r8/r9 +*/ + +VOID +EFIAPI +SetReturnValue ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN RetVal + ) +{ + ExitContext.X64->Rax = RetVal; +} + +VOID +EFIAPI +SetReturnValue64 ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINT64 RetVal + ) +{ + SetReturnValue (ExitContext, RetVal); +} + +UINTN +EFIAPI +GetReturnValue ( + IN OUT FUNC_EXIT_CONTEXT ExitContext + ) +{ + return ExitContext.X64->Rax; +} + +UINT64 +EFIAPI +GetReturnValue64 ( + IN OUT FUNC_EXIT_CONTEXT ExitContext + ) +{ + return GetReturnValue (ExitContext); +} + +UINTN +EFIAPI +GetParameterValue ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN Index + ) +{ + UINTN *StackPointer; + + ASSERT(EntryContext.X64->Rsp != 0); + if (Index == 1) { + return EntryContext.X64->Rcx; + } else if (Index == 2) { + return EntryContext.X64->Rdx; + } else if (Index == 3) { + return EntryContext.X64->R8; + } else if (Index == 4) { + return EntryContext.X64->R9; + } else { + StackPointer = (UINTN *)(UINTN)(EntryContext.X64->Rsp); + return *(StackPointer + Index); + } +} + +UINT64 +EFIAPI +GetParameterValue64 ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN Index + ) +{ + return GetParameterValue (EntryContext, Index); +} + +UINTN +EFIAPI +GetReturnParameterValue ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN Index + ) +{ + UINTN *StackPointer; + + ASSERT(ExitContext.X64->Rsp != 0); + + StackPointer = (UINTN *)(UINTN)(ExitContext.X64->Rsp); + return *(StackPointer + Index); +} + +UINT64 +EFIAPI +GetReturnParameterValue64 ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN Index + ) +{ + return GetReturnParameterValue (ExitContext, Index); +} + +VOID +EFIAPI +SetParameterValue ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN Index, + IN UINTN Data + ) +{ + UINTN *StackPointer; + + ASSERT(EntryContext.X64->Rsp != 0); + if (Index == 1) { + EntryContext.X64->Rcx = Data; + } else if (Index == 2) { + EntryContext.X64->Rdx = Data; + } else if (Index == 3) { + EntryContext.X64->R8 = Data; + } else if (Index == 4) { + EntryContext.X64->R9 = Data; + } + if (EntryContext.X64->Rsp != (UINTN)-1) { + // Update both register and stack. + StackPointer = (UINTN *)(UINTN)(EntryContext.X64->Rsp); + *(StackPointer + Index) = Data; + } +} + +VOID +EFIAPI +SetParameterValue64 ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN Index, + IN UINT64 Data + ) +{ + SetParameterValue (EntryContext, Index, Data); +} + +VOID +EFIAPI +SetSkipReturnValue ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN RetVal + ) +{ + EntryContext.X64->Rax = RetVal; +} + +VOID +EFIAPI +SetSkipReturnValue64 ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINT64 RetVal + ) +{ + SetSkipReturnValue (EntryContext, RetVal); +} diff --git a/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/X64/PEnterExit.nasm b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/X64/PEnterExit.nasm new file mode 100644 index 0000000..a6f5be4 --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/X64/PEnterExit.nasm @@ -0,0 +1,346 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + +extern ASM_PFX(Cpenter) +extern ASM_PFX(Cpexit) + +%define PARAM_COUNT 14 +%define RSVD_COUNT 16 + + SECTION .text + +; void _cdecl _penter( void ) +global ASM_PFX(_penter) +ASM_PFX(_penter): +;--------------- +; P1: Context +;--------------- +; P2: Ret Addr +;--------------- +; R8~R15 | +;--------------- +; RDI | +;--------------- +; RSI | +;--------------- +; RBP | +;--------------- +; RSP | +;--------------- +; RBX | +;--------------- +; RDX | +;--------------- +; RCX | +;--------------- +; RAX | +;--------------- +; RBP <- RBP +;--------------- +; Addr in FuncB +;--------------- +; RSVD +;--------------- +; Addr in FuncA +;--------------- +; Param +;--------------- + ; prolog - begin + push rbp + mov rbp, rsp + + push rax + push rcx + push rdx + push rbx + mov rax, rbp + add rax, 8 ; the caller to _penter + push rax ; original rsp + mov rax, [rbp] + push rax ; original rbp + push rsi + push rdi + push r8 + push r9 + push r10 + push r11 + push r12 + push r13 + push r14 + push r15 + ; prolog - end + + mov rcx, rsp ; rcx = context + mov rdx, [rbp + 8] ; rdx = return address + sub rsp, 0x20 + call ASM_PFX(Cpenter) + add rsp, 0x20 + + ; epilog - begin + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop rdi + pop rsi + add rsp, 8 ; skip rbp + add rsp, 8 ; skip rsp + pop rbx + pop rdx + pop rcx + + cmp rax, 0 + jz Exit + +; skip function + +;--------------- +; RAX | +;--------------- +; RBP <- RBP | +;--------------- +; Addr in FuncB | +;--------------- +; RAX +; RSVD RBP <- RBP +;--------------- +; Addr in FuncA | <- RSP +;--------------- +; Param +;--------------- + mov rax, [rbp - 8 * 5] + mov rsp, rax + mov rax, [rbp] + mov [rsp - 8], rax + mov rax, [rbp - 8] + mov [rsp - 0x10], rax + sub rsp, 0x10 + mov rbp, rsp + add rbp, 8 + + pop rax + mov rsp, rbp + pop rbp + ; epilog - end + ret + +Exit: + push rcx + push rdx + push rsi + push rdi + +; copy the param + +;--------------- +; RDI +;--------------- +; RSI +;--------------- +; RDX +;--------------- +; RCX +;--------------- +; RAX +;--------------- +; RBP <- RBP +;--------------- +; Addr in FuncB +;--------------- +; RSVD (8 * RSVD_COUNT) +;--------------- +; Addr in FuncA +;--------------- +; Param (8 * PARAM_COUNT) +;--------------- +; RDI | <- RSP +;--------------- +; RSI +;--------------- +; RDX +;--------------- +; RCX +;--------------- +; RAX +;--------------- +; RBP <- RBP +;--------------- +; Addr in FuncB +;--------------- +; RSVD (8 * RSVD_COUNT) +;--------------- +; Addr in FuncA +;--------------- +; Param +;--------------- + sub rsp, (8 * PARAM_COUNT + 8 * (8 + RSVD_COUNT)) + mov rsi, rsp + mov rdi, rsi + add rsi, (8 * PARAM_COUNT + 8 * (8 + RSVD_COUNT)) + mov rcx, (PARAM_COUNT + 8 + RSVD_COUNT) + rep movsq + sub rbp, (8 * PARAM_COUNT + 8 * (8 + RSVD_COUNT)) + + pop rdi + pop rsi + pop rdx + pop rcx + + pop rax + mov rsp, rbp + pop rbp + ; epilog - end + ret + +; void _cdecl _pexit( void ) +global ASM_PFX(_pexit) +ASM_PFX(_pexit): +;--------------- +; RBP <- RBP +;--------------- +; Addr in FuncB +;--------------- +; RSVD +;--------------- +; Addr in FuncA +;--------------- +; Param (8 * PARAM_COUNT) +;--------------- +; RDI +;--------------- +; RSI +;--------------- +; RDX +;--------------- +; RCX +;--------------- +; RAX +;--------------- +; RBP <- RBP +;--------------- +; Addr in FuncB +;--------------- +; RSVD +;--------------- +; Addr in FuncA +;--------------- +; Param +;--------------- + ; prolog - begin + push rbp + mov rbp, rsp + + push rax + push rcx + push rdx + push rbx + mov rax, rbp + add rax, 8 ; the caller to _pexit + push rax ; original rsp + mov rax, [rbp] + push rax ; original rbp + push rsi + push rdi + push r8 + push r9 + push r10 + push r11 + push r12 + push r13 + push r14 + push r15 + ; prolog - end + + mov rcx, rsp ; rcx = context + mov rdx, [rbp + 8 * (2 + RSVD_COUNT + PARAM_COUNT + 7)] ; rdx = return address + sub rsp, 0x20 + call ASM_PFX(Cpexit) + add rsp, 0x20 + + ; epilog - begin + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop rdi + pop rsi + add rsp, 8 ; skip rbp + add rsp, 8 ; skip rsp + pop rbx + pop rdx + pop rcx + +;--------------- +; RDI +;--------------- +; RSI +;--------------- +; RDX +;--------------- +; RCX +;--------------- +; RAX +;--------------- +; RBP <- RBP +;--------------- +; Addr in FuncB +;--------------- +; RSVD (8 * RSVD_COUNT) +;--------------- +; Addr in FuncA +;--------------- +; Param (8 * PARAM_COUNT) +;--------------- +; RDI +;--------------- +; RSI +;--------------- +; RDX +;--------------- +; RCX +;--------------- +; RAX +;--------------- +; RBP <- RBP +;--------------- +; Addr in FuncB +;--------------- +; RSVD (8 * RSVD_COUNT) +;--------------- +; Addr in FuncA +;--------------- +; Param +;--------------- + push rcx + push rdx + push rsi + push rdi + mov rsi, rsp + mov rdi, rsi + add rdi, (8 * PARAM_COUNT + 8 * (8 + RSVD_COUNT)) + mov rcx, (7) + rep movsq + add rbp, (8 * PARAM_COUNT + 8 * (8 + RSVD_COUNT)) + add rsp, (8 * PARAM_COUNT + 8 * (8 + RSVD_COUNT)) + + pop rdi + pop rsi + pop rdx + pop rcx + + pop rax + mov rsp, rbp + pop rbp + ; epilog - end + ret diff --git a/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/X64/PEnterExitStub.c b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/X64/PEnterExitStub.c new file mode 100644 index 0000000..9d9b414 --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/InstrumentLib/X64/PEnterExitStub.c @@ -0,0 +1,134 @@ +/** @file + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include + +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mMovR9Template[] = {0x4C, 0x89, 0x4C, 0x24, 0x20}; // mov qword ptr [rsp+20h],r9 +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mMovR9dTemplate[] = {0x44, 0x89, 0x4C, 0x24, 0x20}; // mov dword ptr [rsp+20h],r9d +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mMovR9wTemplate[] = {0x66, 0x44, 0x89, 0x4C, 0x24, 0x20}; // mov word ptr [rsp+20h],r9w +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mMovR9bTemplate[] = {0x44, 0x88, 0x4C, 0x24, 0x20}; // mov byte ptr [rsp+20h],r9b + +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mMovR8Template[] = {0x4C, 0x89, 0x44, 0x24, 0x18}; // mov qword ptr [rsp+18h],r8 +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mMovR8dTemplate[] = {0x44, 0x89, 0x44, 0x24, 0x18}; // mov dword ptr [rsp+18h],r8d +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mMovR8wTemplate[] = {0x66, 0x44, 0x89, 0x44, 0x24, 0x18}; // mov word ptr [rsp+18h],r8w +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mMovR8bTemplate[] = {0x44, 0x88, 0x44, 0x24, 0x18}; // mov byte ptr [rsp+18h],r8b + +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mMovRdxTemplate[] = {0x48, 0x89, 0x54, 0x24, 0x10}; // mov qword ptr [rsp+10h],rdx +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mMovEdxTemplate[] = {0x89, 0x54, 0x24, 0x10}; // mov dword ptr [rsp+10h],edx +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mMovDxTemplate[] = {0x66, 0x89, 0x54, 0x24, 0x10}; // mov word ptr [rsp+10h],dx +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mMovDlTemplate[] = {0x88, 0x54, 0x24, 0x10}; // mov byte ptr [rsp+10h],dl + +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mMovRcxTemplate[] = {0x48, 0x89, 0x4C, 0x24, 0x08}; // mov qword ptr [rsp+8],rcx +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mMovEcxTemplate[] = {0x89, 0x4C, 0x24, 0x08}; // mov dword ptr [rsp+8],ecx +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mMovCxTemplate[] = {0x66, 0x89, 0x4C, 0x24, 0x08}; // mov word ptr [rsp+8],cx +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mMovClTemplate[] = {0x88, 0x4C, 0x24, 0x08}; // mov byte ptr [rsp+8],cl + +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mSubRspTemplate[] = {0x48, 0x83, 0xEC, 0x00}; // sub rsp,28h +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mAddRspTemplate[] = {0x48, 0x83, 0xC4, 0x00}; // add rsp,28h + +typedef struct { + UINT8 *Instruction; + UINTN InstructionLength; +} INSTRUCTION_TEMPLATE; + +GLOBAL_REMOVE_IF_UNREFERENCED INSTRUCTION_TEMPLATE mInstructionTemplate[] = { + // 1st group + {mMovRcxTemplate, sizeof(mMovRcxTemplate)}, + {mMovEcxTemplate, sizeof(mMovEcxTemplate)}, + {mMovCxTemplate, sizeof(mMovCxTemplate)}, + {mMovClTemplate, sizeof(mMovClTemplate)}, + + // 2nd group + {mMovRdxTemplate, sizeof(mMovRdxTemplate)}, + {mMovEdxTemplate, sizeof(mMovEdxTemplate)}, + {mMovDxTemplate, sizeof(mMovDxTemplate)}, + {mMovDlTemplate, sizeof(mMovDlTemplate)}, + + // 3rd group + {mMovR8Template, sizeof(mMovR8Template)}, + {mMovR8dTemplate, sizeof(mMovR8dTemplate)}, + {mMovR8wTemplate, sizeof(mMovR8wTemplate)}, + {mMovR8bTemplate, sizeof(mMovR8bTemplate)}, + + // 4th group + {mMovR9Template, sizeof(mMovR9Template)}, + {mMovR9dTemplate, sizeof(mMovR9dTemplate)}, + {mMovR9wTemplate, sizeof(mMovR9wTemplate)}, + {mMovR9bTemplate, sizeof(mMovR9bTemplate)}, +}; + +UINTN +GetFunctionAddress ( + IN OUT UINTN *Rsp, + IN UINTN ReturnAddress + ) +{ + UINTN FunctionAddress; + UINTN Index; + + FunctionAddress = (ReturnAddress - 5); + if (CompareMem ( + (UINT8 *)FunctionAddress - sizeof(mSubRspTemplate), + mSubRspTemplate, + sizeof(mSubRspTemplate) - sizeof(UINT8)) == 0) { + *Rsp += *(UINT8 *)(FunctionAddress - sizeof(UINT8)); + FunctionAddress -= sizeof(mSubRspTemplate); + } + + for (Index = 0; Index < ARRAY_SIZE(mInstructionTemplate); Index++) { + if (CompareMem ( + (UINT8 *)FunctionAddress - mInstructionTemplate[Index].InstructionLength, + mInstructionTemplate[Index].Instruction, + mInstructionTemplate[Index].InstructionLength) == 0) { + FunctionAddress -= mInstructionTemplate[Index].InstructionLength; + } + } + + return FunctionAddress; +} + +UINTN +EFIAPI +Cpenter ( + IN OUT FUNC_ENTER_CONTEXT EntryContext, + IN UINTN ReturnAddress + ) +{ + UINTN FunctionAddress; + UINTN CallerAddress; + + FunctionAddress = GetFunctionAddress (&EntryContext.X64->Rsp, ReturnAddress); + + EntryContext.X64->Rsp += 8; // the caller to the caller to _penter + + CallerAddress = *(UINTN *)(UINTN)(EntryContext.X64->Rsp); + + return FunctionEnter (EntryContext, FunctionAddress, CallerAddress); +} + +VOID +EFIAPI +Cpexit ( + IN OUT FUNC_EXIT_CONTEXT ExitContext, + IN UINTN ReturnAddress + ) +{ + UINTN FunctionAddress; + UINTN CallerAddress; + + FunctionAddress = GetFunctionAddress (&ExitContext.X64->Rsp, ReturnAddress); + + ExitContext.X64->Rsp += 8; // the caller to the caller to _penter + + CallerAddress = *(UINTN *)(UINTN)(ExitContext.X64->Rsp); + + FunctionExit (ExitContext, FunctionAddress, CallerAddress); +} diff --git a/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/BaseSynchronizationLibInternals.h b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/BaseSynchronizationLibInternals.h new file mode 100644 index 0000000..804455e --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/BaseSynchronizationLibInternals.h @@ -0,0 +1,108 @@ +/** @file + Declaration of internal functions in BaseSynchronizationLib. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __BASE_SYNCHRONIZATION_LIB_INTERNALS__ +#define __BASE_SYNCHRONIZATION_LIB_INTERNALS__ + +#include +#include +#include +#include +#include + +/** + Performs an atomic increment of an 32-bit unsigned integer. + + Performs an atomic increment of the 32-bit unsigned integer specified by + Value and returns the incremented value. The increment operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + @param Value A pointer to the 32-bit value to increment. + + @return The incremented value. + +**/ +UINT32 +EFIAPI +InternalSyncIncrement ( + IN volatile UINT32 *Value + ); + + +/** + Performs an atomic decrement of an 32-bit unsigned integer. + + Performs an atomic decrement of the 32-bit unsigned integer specified by + Value and returns the decrement value. The decrement operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + @param Value A pointer to the 32-bit value to decrement. + + @return The decrement value. + +**/ +UINT32 +EFIAPI +InternalSyncDecrement ( + IN volatile UINT32 *Value + ); + + +/** + Performs an atomic compare exchange operation on a 32-bit unsigned integer. + + Performs an atomic compare exchange operation on the 32-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + @param Value A pointer to the 32-bit value for the compare exchange + operation. + @param CompareValue A 32-bit value used in compare operation. + @param ExchangeValue A 32-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT32 +EFIAPI +InternalSyncCompareExchange32 ( + IN volatile UINT32 *Value, + IN UINT32 CompareValue, + IN UINT32 ExchangeValue + ); + + +/** + Performs an atomic compare exchange operation on a 64-bit unsigned integer. + + Performs an atomic compare exchange operation on the 64-bit unsigned integer specified + by Value. If Value is equal to CompareValue, then Value is set to ExchangeValue and + CompareValue is returned. If Value is not equal to CompareValue, then Value is returned. + The compare exchange operation must be performed using MP safe mechanisms. + + @param Value A pointer to the 64-bit value for the compare exchange + operation. + @param CompareValue A 64-bit value used in compare operation. + @param ExchangeValue A 64-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT64 +EFIAPI +InternalSyncCompareExchange64 ( + IN volatile UINT64 *Value, + IN UINT64 CompareValue, + IN UINT64 ExchangeValue + ); + +#endif diff --git a/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Ia32/GccInline.c b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Ia32/GccInline.c new file mode 100644 index 0000000..5529af6 --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Ia32/GccInline.c @@ -0,0 +1,167 @@ +/** @file + GCC inline implementation of BaseSynchronizationLib processor specific functions. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + +/** + Performs an atomic increment of an 32-bit unsigned integer. + + Performs an atomic increment of the 32-bit unsigned integer specified by + Value and returns the incremented value. The increment operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + @param Value A pointer to the 32-bit value to increment. + + @return The incremented value. + +**/ +UINT32 +EFIAPI +InternalSyncIncrement ( + IN volatile UINT32 *Value + ) +{ + UINT32 Result; + + __asm__ __volatile__ ( + "lock \n\t" + "incl %2 \n\t" + "movl %2, %%eax " + : "=a" (Result), // %0 + "=m" (*Value) // %1 + : "m" (*Value) // %2 + : "memory", + "cc" + ); + + return Result; + +} + + +/** + Performs an atomic decrement of an 32-bit unsigned integer. + + Performs an atomic decrement of the 32-bit unsigned integer specified by + Value and returns the decremented value. The decrement operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + @param Value A pointer to the 32-bit value to decrement. + + @return The decremented value. + +**/ +UINT32 +EFIAPI +InternalSyncDecrement ( + IN volatile UINT32 *Value + ) +{ + UINT32 Result; + + __asm__ __volatile__ ( + "lock \n\t" + "decl %2 \n\t" + "movl %2, %%eax " + : "=a" (Result), // %0 + "=m" (*Value) // %1 + : "m" (*Value) // %2 + : "memory", + "cc" + ); + + return Result; +} + +/** + Performs an atomic compare exchange operation on a 32-bit unsigned integer. + + Performs an atomic compare exchange operation on the 32-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + + @param Value A pointer to the 32-bit value for the compare exchange + operation. + @param CompareValue 32-bit value used in compare operation. + @param ExchangeValue 32-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT32 +EFIAPI +InternalSyncCompareExchange32 ( + IN OUT volatile UINT32 *Value, + IN UINT32 CompareValue, + IN UINT32 ExchangeValue + ) +{ + + __asm__ __volatile__ ( + " \n\t" + "lock \n\t" + "cmpxchgl %1, %2 \n\t" + : "=a" (CompareValue) // %0 + : "q" (ExchangeValue), // %1 + "m" (*Value), // %2 + "0" (CompareValue) // %4 + : "memory", + "cc" + ); + + return CompareValue; +} + +/** + Performs an atomic compare exchange operation on a 64-bit unsigned integer. + + Performs an atomic compare exchange operation on the 64-bit unsigned integer specified + by Value. If Value is equal to CompareValue, then Value is set to ExchangeValue and + CompareValue is returned. If Value is not equal to CompareValue, then Value is returned. + The compare exchange operation must be performed using MP safe mechanisms. + + + @param Value A pointer to the 64-bit value for the compare exchange + operation. + @param CompareValue 64-bit value used in compare operation. + @param ExchangeValue 64-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT64 +EFIAPI +InternalSyncCompareExchange64 ( + IN OUT volatile UINT64 *Value, + IN UINT64 CompareValue, + IN UINT64 ExchangeValue + ) +{ + __asm__ __volatile__ ( + " \n\t" + "push %%ebx \n\t" + "movl %2,%%ebx \n\t" + "lock \n\t" + "cmpxchg8b (%1) \n\t" + "pop %%ebx \n\t" + : "+A" (CompareValue) // %0 + : "S" (Value), // %1 + "r" ((UINT32) ExchangeValue), // %2 + "c" ((UINT32) (ExchangeValue >> 32)) // %3 + : "memory", + "cc" + ); + + return CompareValue; +} diff --git a/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Ia32/InterlockedCompareExchange32.asm b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Ia32/InterlockedCompareExchange32.asm new file mode 100644 index 0000000..f2368ce --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Ia32/InterlockedCompareExchange32.asm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; InterlockedCompareExchange32.Asm +; +; Abstract: +; +; InterlockedCompareExchange32 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .486 + .model flat,C + .code + +;------------------------------------------------------------------------------ +; UINT32 +; EFIAPI +; InternalSyncCompareExchange32 ( +; IN volatile UINT32 *Value, +; IN UINT32 CompareValue, +; IN UINT32 ExchangeValue +; ); +;------------------------------------------------------------------------------ +InternalSyncCompareExchange32 PROC + mov ecx, [esp + 4] + mov eax, [esp + 8] + mov edx, [esp + 12] + lock cmpxchg [ecx], edx + ret +InternalSyncCompareExchange32 ENDP + + END diff --git a/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Ia32/InterlockedCompareExchange32.c b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Ia32/InterlockedCompareExchange32.c new file mode 100644 index 0000000..5b7c207 --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Ia32/InterlockedCompareExchange32.c @@ -0,0 +1,44 @@ +/** @file + InterlockedCompareExchange32 function + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Performs an atomic compare exchange operation on a 32-bit unsigned integer. + + Performs an atomic compare exchange operation on the 32-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + @param Value A pointer to the 32-bit value for the compare exchange + operation. + @param CompareValue 32-bit value used in compare operation. + @param ExchangeValue 32-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT32 +EFIAPI +InternalSyncCompareExchange32 ( + IN volatile UINT32 *Value, + IN UINT32 CompareValue, + IN UINT32 ExchangeValue + ) +{ + _asm { + mov ecx, Value + mov eax, CompareValue + mov edx, ExchangeValue + lock cmpxchg [ecx], edx + } +} + diff --git a/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Ia32/InterlockedCompareExchange64.asm b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Ia32/InterlockedCompareExchange64.asm new file mode 100644 index 0000000..e2a1b85 --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Ia32/InterlockedCompareExchange64.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; InterlockedCompareExchange64.Asm +; +; Abstract: +; +; InterlockedCompareExchange64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586P + .model flat,C + .code + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; InternalSyncCompareExchange64 ( +; IN volatile UINT64 *Value, +; IN UINT64 CompareValue, +; IN UINT64 ExchangeValue +; ); +;------------------------------------------------------------------------------ +InternalSyncCompareExchange64 PROC USES esi ebx + mov esi, [esp + 12] + mov eax, [esp + 16] + mov edx, [esp + 20] + mov ebx, [esp + 24] + mov ecx, [esp + 28] + lock cmpxchg8b qword ptr [esi] + ret +InternalSyncCompareExchange64 ENDP + + END diff --git a/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Ia32/InterlockedCompareExchange64.c b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Ia32/InterlockedCompareExchange64.c new file mode 100644 index 0000000..c9ea3ba --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Ia32/InterlockedCompareExchange64.c @@ -0,0 +1,44 @@ +/** @file + InterlockedCompareExchange64 function + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Performs an atomic compare exchange operation on a 64-bit unsigned integer. + + Performs an atomic compare exchange operation on the 64-bit unsigned integer specified + by Value. If Value is equal to CompareValue, then Value is set to ExchangeValue and + CompareValue is returned. If Value is not equal to CompareValue, then Value is returned. + The compare exchange operation must be performed using MP safe mechanisms. + + @param Value A pointer to the 64-bit value for the compare exchange + operation. + @param CompareValue A 64-bit value used in a compare operation. + @param ExchangeValue A 64-bit value used in an exchange operation. + + @return The original *Value before exchange. + +**/ +UINT64 +EFIAPI +InternalSyncCompareExchange64 ( + IN volatile UINT64 *Value, + IN UINT64 CompareValue, + IN UINT64 ExchangeValue + ) +{ + _asm { + mov esi, Value + mov eax, dword ptr [CompareValue + 0] + mov edx, dword ptr [CompareValue + 4] + mov ebx, dword ptr [ExchangeValue + 0] + mov ecx, dword ptr [ExchangeValue + 4] + lock cmpxchg8b qword ptr [esi] + } +} diff --git a/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Ia32/InterlockedDecrement.asm b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Ia32/InterlockedDecrement.asm new file mode 100644 index 0000000..15eff7d --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Ia32/InterlockedDecrement.asm @@ -0,0 +1,36 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; InterlockedDecrement.Asm +; +; Abstract: +; +; InterlockedDecrement function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386 + .model flat,C + .code + +;------------------------------------------------------------------------------ +; UINT32 +; EFIAPI +; InternalSyncDecrement ( +; IN volatile UINT32 *Value +; ); +;------------------------------------------------------------------------------ +InternalSyncDecrement PROC + mov eax, [esp + 4] + lock dec dword ptr [eax] + mov eax, [eax] + ret +InternalSyncDecrement ENDP + + END diff --git a/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Ia32/InterlockedDecrement.c b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Ia32/InterlockedDecrement.c new file mode 100644 index 0000000..916f54d --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Ia32/InterlockedDecrement.c @@ -0,0 +1,36 @@ +/** @file + InterlockedDecrement function + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Performs an atomic decrement of an 32-bit unsigned integer. + + Performs an atomic decrement of the 32-bit unsigned integer specified by + Value and returns the decrement value. The decrement operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + @param Value A pointer to the 32-bit value to decrement. + + @return The decrement value. + +**/ +UINT32 +EFIAPI +InternalSyncDecrement ( + IN volatile UINT32 *Value + ) +{ + _asm { + mov eax, Value + lock dec dword ptr [eax] + mov eax, [eax] + } +} diff --git a/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Ia32/InterlockedIncrement.asm b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Ia32/InterlockedIncrement.asm new file mode 100644 index 0000000..f17f1ae --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Ia32/InterlockedIncrement.asm @@ -0,0 +1,36 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; InterlockedIncrement.Asm +; +; Abstract: +; +; InterlockedIncrement function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386 + .model flat,C + .code + +;------------------------------------------------------------------------------ +; UINT32 +; EFIAPI +; InternalSyncIncrement ( +; IN volatile UINT32 *Value +; ); +;------------------------------------------------------------------------------ +InternalSyncIncrement PROC + mov eax, [esp + 4] + lock inc dword ptr [eax] + mov eax, [eax] + ret +InternalSyncIncrement ENDP + + END diff --git a/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Ia32/InterlockedIncrement.c b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Ia32/InterlockedIncrement.c new file mode 100644 index 0000000..ec74a29 --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Ia32/InterlockedIncrement.c @@ -0,0 +1,37 @@ +/** @file + InterLockedIncrement function + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Performs an atomic increment of an 32-bit unsigned integer. + + Performs an atomic increment of the 32-bit unsigned integer specified by + Value and returns the incremented value. The increment operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + @param Value A pointer to the 32-bit value to increment. + + @return The incremented value. + +**/ +UINT32 +EFIAPI +InternalSyncIncrement ( + IN volatile UINT32 *Value + ) +{ + _asm { + mov eax, Value + lock inc dword ptr [eax] + mov eax, [eax] + } +} + diff --git a/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/SimpleSynchronizationLib.inf b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/SimpleSynchronizationLib.inf new file mode 100644 index 0000000..06c17ee --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/SimpleSynchronizationLib.inf @@ -0,0 +1,54 @@ +## @file +# Base Synchronization Library implementation. +# It does not use Stall function. +# +# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SimpleSynchronizationLib + FILE_GUID = 787FD4EF-DAB5-49ca-BCBF-B2892C27FF7B + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = SynchronizationLib + +# +# VALID_ARCHITECTURES = IA32 X64 +# +[Sources] + BaseSynchronizationLibInternals.h + +[Sources.IA32] + Ia32/InterlockedCompareExchange64.c | MSFT + Ia32/InterlockedCompareExchange32.c | MSFT + Ia32/InterlockedDecrement.c | MSFT + Ia32/InterlockedIncrement.c | MSFT + SynchronizationMsc.c | MSFT + + Ia32/GccInline.c | GCC + SynchronizationGcc.c | GCC + +[Sources.X64] + X64/InterlockedCompareExchange64.c | MSFT + X64/InterlockedCompareExchange32.c | MSFT + + X64/InterlockedDecrement.c | MSFT + X64/InterlockedIncrement.c | MSFT + SynchronizationMsc.c | MSFT + + X64/GccInline.c | GCC + SynchronizationGcc.c | GCC + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + PcdLib + DebugLib + BaseMemoryLib diff --git a/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Synchronization.c b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Synchronization.c new file mode 100644 index 0000000..0b49a46 --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/Synchronization.c @@ -0,0 +1,326 @@ +/** @file + Implementation of synchronization functions. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseSynchronizationLibInternals.h" + +#define SPIN_LOCK_RELEASED ((UINTN) 1) +#define SPIN_LOCK_ACQUIRED ((UINTN) 2) + +/** + Retrieves the architecture specific spin lock alignment requirements for + optimal spin lock performance. + + This function retrieves the spin lock alignment requirements for optimal + performance on a given CPU architecture. The spin lock alignment must be a + power of two and is returned by this function. If there are no alignment + requirements, then 1 must be returned. The spin lock synchronization + functions must function correctly if the spin lock size and alignment values + returned by this function are not used at all. These values are hints to the + consumers of the spin lock synchronization functions to obtain optimal spin + lock performance. + + @return The architecture specific spin lock alignment. + +**/ +UINTN +EFIAPI +GetSpinLockProperties ( + VOID + ) +{ + return 32; +} + +/** + Initializes a spin lock to the released state and returns the spin lock. + + This function initializes the spin lock specified by SpinLock to the released + state, and returns SpinLock. Optimal performance can be achieved by calling + GetSpinLockProperties() to determine the size and alignment requirements for + SpinLock. + + If SpinLock is NULL, then ASSERT(). + + @param SpinLock A pointer to the spin lock to initialize to the released + state. + + @return SpinLock is in release state. + +**/ +SPIN_LOCK * +EFIAPI +InitializeSpinLock ( + OUT SPIN_LOCK *SpinLock + ) +{ + ASSERT (SpinLock != NULL); + *SpinLock = SPIN_LOCK_RELEASED; + return SpinLock; +} + +/** + Waits until a spin lock can be placed in the acquired state. + + This function checks the state of the spin lock specified by SpinLock. If + SpinLock is in the released state, then this function places SpinLock in the + acquired state and returns SpinLock. Otherwise, this function waits + indefinitely for the spin lock to be released, and then places it in the + acquired state and returns SpinLock. All state transitions of SpinLock must + be performed using MP safe mechanisms. + + If SpinLock is NULL, then ASSERT(). + If SpinLock was not initialized with InitializeSpinLock(), then ASSERT(). + If PcdSpinLockTimeout is not zero, and SpinLock is can not be acquired in + PcdSpinLockTimeout microseconds, then ASSERT(). + + @param SpinLock A pointer to the spin lock to place in the acquired state. + + @return SpinLock acquired the lock. + +**/ +SPIN_LOCK * +EFIAPI +AcquireSpinLock ( + IN OUT SPIN_LOCK *SpinLock + ) +{ + while (!AcquireSpinLockOrFail (SpinLock)) { + CpuPause (); + } + return SpinLock; +} + +/** + Attempts to place a spin lock in the acquired state. + + This function checks the state of the spin lock specified by SpinLock. If + SpinLock is in the released state, then this function places SpinLock in the + acquired state and returns TRUE. Otherwise, FALSE is returned. All state + transitions of SpinLock must be performed using MP safe mechanisms. + + If SpinLock is NULL, then ASSERT(). + If SpinLock was not initialized with InitializeSpinLock(), then ASSERT(). + + @param SpinLock A pointer to the spin lock to place in the acquired state. + + @retval TRUE SpinLock was placed in the acquired state. + @retval FALSE SpinLock could not be acquired. + +**/ +BOOLEAN +EFIAPI +AcquireSpinLockOrFail ( + IN OUT SPIN_LOCK *SpinLock + ) +{ + SPIN_LOCK LockValue; + + ASSERT (SpinLock != NULL); + + LockValue = *SpinLock; + ASSERT (SPIN_LOCK_ACQUIRED == LockValue || SPIN_LOCK_RELEASED == LockValue); + + return (BOOLEAN)( + InterlockedCompareExchangePointer ( + (VOID**)SpinLock, + (VOID*)SPIN_LOCK_RELEASED, + (VOID*)SPIN_LOCK_ACQUIRED + ) == (VOID*)SPIN_LOCK_RELEASED + ); +} + +/** + Releases a spin lock. + + This function places the spin lock specified by SpinLock in the release state + and returns SpinLock. + + If SpinLock is NULL, then ASSERT(). + If SpinLock was not initialized with InitializeSpinLock(), then ASSERT(). + + @param SpinLock A pointer to the spin lock to release. + + @return SpinLock released lock. + +**/ +SPIN_LOCK * +EFIAPI +ReleaseSpinLock ( + IN OUT SPIN_LOCK *SpinLock + ) +{ + SPIN_LOCK LockValue; + + ASSERT (SpinLock != NULL); + + LockValue = *SpinLock; + ASSERT (SPIN_LOCK_ACQUIRED == LockValue || SPIN_LOCK_RELEASED == LockValue); + + *SpinLock = SPIN_LOCK_RELEASED; + return SpinLock; +} + +/** + Performs an atomic increment of an 32-bit unsigned integer. + + Performs an atomic increment of the 32-bit unsigned integer specified by + Value and returns the incremented value. The increment operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 32-bit value to increment. + + @return The incremented value. + +**/ +UINT32 +EFIAPI +InterlockedIncrement ( + IN volatile UINT32 *Value + ) +{ + ASSERT (Value != NULL); + return InternalSyncIncrement (Value); +} + +/** + Performs an atomic decrement of an 32-bit unsigned integer. + + Performs an atomic decrement of the 32-bit unsigned integer specified by + Value and returns the decremented value. The decrement operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 32-bit value to decrement. + + @return The decremented value. + +**/ +UINT32 +EFIAPI +InterlockedDecrement ( + IN volatile UINT32 *Value + ) +{ + ASSERT (Value != NULL); + return InternalSyncDecrement (Value); +} + +/** + Performs an atomic compare exchange operation on a 32-bit unsigned integer. + + Performs an atomic compare exchange operation on the 32-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 32-bit value for the compare exchange + operation. + @param CompareValue 32-bit value used in compare operation. + @param ExchangeValue 32-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT32 +EFIAPI +InterlockedCompareExchange32 ( + IN OUT volatile UINT32 *Value, + IN UINT32 CompareValue, + IN UINT32 ExchangeValue + ) +{ + ASSERT (Value != NULL); + return InternalSyncCompareExchange32 (Value, CompareValue, ExchangeValue); +} + +/** + Performs an atomic compare exchange operation on a 64-bit unsigned integer. + + Performs an atomic compare exchange operation on the 64-bit unsigned integer specified + by Value. If Value is equal to CompareValue, then Value is set to ExchangeValue and + CompareValue is returned. If Value is not equal to CompareValue, then Value is returned. + The compare exchange operation must be performed using MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 64-bit value for the compare exchange + operation. + @param CompareValue 64-bit value used in compare operation. + @param ExchangeValue 64-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT64 +EFIAPI +InterlockedCompareExchange64 ( + IN OUT volatile UINT64 *Value, + IN UINT64 CompareValue, + IN UINT64 ExchangeValue + ) +{ + ASSERT (Value != NULL); + return InternalSyncCompareExchange64 (Value, CompareValue, ExchangeValue); +} + +/** + Performs an atomic compare exchange operation on a pointer value. + + Performs an atomic compare exchange operation on the pointer value specified + by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to + CompareValue, then Value is returned. The compare exchange operation must be + performed using MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the pointer value for the compare exchange + operation. + @param CompareValue Pointer value used in compare operation. + @param ExchangeValue Pointer value used in exchange operation. + + @return The original *Value before exchange. +**/ +VOID * +EFIAPI +InterlockedCompareExchangePointer ( + IN OUT VOID * volatile *Value, + IN VOID *CompareValue, + IN VOID *ExchangeValue + ) +{ + UINT8 SizeOfValue; + + SizeOfValue = sizeof (*Value); + + switch (SizeOfValue) { + case sizeof (UINT32): + return (VOID*)(UINTN)InterlockedCompareExchange32 ( + (volatile UINT32 *)Value, + (UINT32)(UINTN)CompareValue, + (UINT32)(UINTN)ExchangeValue + ); + case sizeof (UINT64): + return (VOID*)(UINTN)InterlockedCompareExchange64 ( + (volatile UINT64 *)Value, + (UINT64)(UINTN)CompareValue, + (UINT64)(UINTN)ExchangeValue + ); + default: + ASSERT (FALSE); + return NULL; + } +} diff --git a/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/SynchronizationGcc.c b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/SynchronizationGcc.c new file mode 100644 index 0000000..1025a7f --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/SynchronizationGcc.c @@ -0,0 +1,342 @@ +/** @file + Implementation of synchronization functions. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseSynchronizationLibInternals.h" + +// +// GCC inline assembly for Read Write Barrier +// +#define _ReadWriteBarrier() do { __asm__ __volatile__ ("": : : "memory"); } while(0) + +#define SPIN_LOCK_RELEASED ((UINTN) 1) +#define SPIN_LOCK_ACQUIRED ((UINTN) 2) + +/** + Retrieves the architecture specific spin lock alignment requirements for + optimal spin lock performance. + + This function retrieves the spin lock alignment requirements for optimal + performance on a given CPU architecture. The spin lock alignment must be a + power of two and is returned by this function. If there are no alignment + requirements, then 1 must be returned. The spin lock synchronization + functions must function correctly if the spin lock size and alignment values + returned by this function are not used at all. These values are hints to the + consumers of the spin lock synchronization functions to obtain optimal spin + lock performance. + + @return The architecture specific spin lock alignment. + +**/ +UINTN +EFIAPI +GetSpinLockProperties ( + VOID + ) +{ + return 32; +} + +/** + Initializes a spin lock to the released state and returns the spin lock. + + This function initializes the spin lock specified by SpinLock to the released + state, and returns SpinLock. Optimal performance can be achieved by calling + GetSpinLockProperties() to determine the size and alignment requirements for + SpinLock. + + If SpinLock is NULL, then ASSERT(). + + @param SpinLock A pointer to the spin lock to initialize to the released + state. + + @return SpinLock is in release state. + +**/ +SPIN_LOCK * +EFIAPI +InitializeSpinLock ( + OUT SPIN_LOCK *SpinLock + ) +{ + ASSERT (SpinLock != NULL); + + _ReadWriteBarrier(); + *SpinLock = SPIN_LOCK_RELEASED; + _ReadWriteBarrier(); + + return SpinLock; +} + +/** + Waits until a spin lock can be placed in the acquired state. + + This function checks the state of the spin lock specified by SpinLock. If + SpinLock is in the released state, then this function places SpinLock in the + acquired state and returns SpinLock. Otherwise, this function waits + indefinitely for the spin lock to be released, and then places it in the + acquired state and returns SpinLock. All state transitions of SpinLock must + be performed using MP safe mechanisms. + + If SpinLock is NULL, then ASSERT(). + If SpinLock was not initialized with InitializeSpinLock(), then ASSERT(). + If PcdSpinLockTimeout is not zero, and SpinLock is can not be acquired in + PcdSpinLockTimeout microseconds, then ASSERT(). + + @param SpinLock A pointer to the spin lock to place in the acquired state. + + @return SpinLock acquired the lock. + +**/ +SPIN_LOCK * +EFIAPI +AcquireSpinLock ( + IN OUT SPIN_LOCK *SpinLock + ) +{ + while (!AcquireSpinLockOrFail (SpinLock)) { + CpuPause (); + } + return SpinLock; +} + +/** + Attempts to place a spin lock in the acquired state. + + This function checks the state of the spin lock specified by SpinLock. If + SpinLock is in the released state, then this function places SpinLock in the + acquired state and returns TRUE. Otherwise, FALSE is returned. All state + transitions of SpinLock must be performed using MP safe mechanisms. + + If SpinLock is NULL, then ASSERT(). + If SpinLock was not initialized with InitializeSpinLock(), then ASSERT(). + + @param SpinLock A pointer to the spin lock to place in the acquired state. + + @retval TRUE SpinLock was placed in the acquired state. + @retval FALSE SpinLock could not be acquired. + +**/ +BOOLEAN +EFIAPI +AcquireSpinLockOrFail ( + IN OUT SPIN_LOCK *SpinLock + ) +{ + SPIN_LOCK LockValue; + VOID *Result; + + ASSERT (SpinLock != NULL); + + LockValue = *SpinLock; + ASSERT (LockValue == SPIN_LOCK_ACQUIRED || LockValue == SPIN_LOCK_RELEASED); + + _ReadWriteBarrier (); + Result = InterlockedCompareExchangePointer ( + (VOID**)SpinLock, + (VOID*)SPIN_LOCK_RELEASED, + (VOID*)SPIN_LOCK_ACQUIRED + ); + + _ReadWriteBarrier (); + return (BOOLEAN) (Result == (VOID*) SPIN_LOCK_RELEASED); +} + +/** + Releases a spin lock. + + This function places the spin lock specified by SpinLock in the release state + and returns SpinLock. + + If SpinLock is NULL, then ASSERT(). + If SpinLock was not initialized with InitializeSpinLock(), then ASSERT(). + + @param SpinLock A pointer to the spin lock to release. + + @return SpinLock released the lock. + +**/ +SPIN_LOCK * +EFIAPI +ReleaseSpinLock ( + IN OUT SPIN_LOCK *SpinLock + ) +{ + SPIN_LOCK LockValue; + + ASSERT (SpinLock != NULL); + + LockValue = *SpinLock; + ASSERT (LockValue == SPIN_LOCK_ACQUIRED || LockValue == SPIN_LOCK_RELEASED); + + _ReadWriteBarrier (); + *SpinLock = SPIN_LOCK_RELEASED; + _ReadWriteBarrier (); + + return SpinLock; +} + +/** + Performs an atomic increment of an 32-bit unsigned integer. + + Performs an atomic increment of the 32-bit unsigned integer specified by + Value and returns the incremented value. The increment operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 32-bit value to increment. + + @return The incremented value. + +**/ +UINT32 +EFIAPI +InterlockedIncrement ( + IN volatile UINT32 *Value + ) +{ + ASSERT (Value != NULL); + return InternalSyncIncrement (Value); +} + +/** + Performs an atomic decrement of an 32-bit unsigned integer. + + Performs an atomic decrement of the 32-bit unsigned integer specified by + Value and returns the decremented value. The decrement operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 32-bit value to decrement. + + @return The decremented value. + +**/ +UINT32 +EFIAPI +InterlockedDecrement ( + IN volatile UINT32 *Value + ) +{ + ASSERT (Value != NULL); + return InternalSyncDecrement (Value); +} + +/** + Performs an atomic compare exchange operation on a 32-bit unsigned integer. + + Performs an atomic compare exchange operation on the 32-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 32-bit value for the compare exchange + operation. + @param CompareValue A 32-bit value used in compare operation. + @param ExchangeValue A 32-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT32 +EFIAPI +InterlockedCompareExchange32 ( + IN OUT volatile UINT32 *Value, + IN UINT32 CompareValue, + IN UINT32 ExchangeValue + ) +{ + ASSERT (Value != NULL); + return InternalSyncCompareExchange32 (Value, CompareValue, ExchangeValue); +} + +/** + Performs an atomic compare exchange operation on a 64-bit unsigned integer. + + Performs an atomic compare exchange operation on the 64-bit unsigned integer specified + by Value. If Value is equal to CompareValue, then Value is set to ExchangeValue and + CompareValue is returned. If Value is not equal to CompareValue, then Value is returned. + The compare exchange operation must be performed using MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 64-bit value for the compare exchange + operation. + @param CompareValue A 64-bit value used in a compare operation. + @param ExchangeValue A 64-bit value used in an exchange operation. + + @return The original *Value before exchange. + +**/ +UINT64 +EFIAPI +InterlockedCompareExchange64 ( + IN OUT volatile UINT64 *Value, + IN UINT64 CompareValue, + IN UINT64 ExchangeValue + ) +{ + ASSERT (Value != NULL); + return InternalSyncCompareExchange64 (Value, CompareValue, ExchangeValue); +} + +/** + Performs an atomic compare exchange operation on a pointer value. + + Performs an atomic compare exchange operation on the pointer value specified + by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to + CompareValue, then Value is returned. The compare exchange operation must be + performed using MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the pointer value for the compare exchange + operation. + @param CompareValue A pointer value used in a compare operation. + @param ExchangeValue A pointer value used in an exchange operation. + + @return The original *Value before exchange. +**/ +VOID * +EFIAPI +InterlockedCompareExchangePointer ( + IN OUT VOID * volatile *Value, + IN VOID *CompareValue, + IN VOID *ExchangeValue + ) +{ + UINT8 SizeOfValue; + + SizeOfValue = sizeof (*Value); + + switch (SizeOfValue) { + case sizeof (UINT32): + return (VOID*)(UINTN)InterlockedCompareExchange32 ( + (volatile UINT32 *)Value, + (UINT32)(UINTN)CompareValue, + (UINT32)(UINTN)ExchangeValue + ); + case sizeof (UINT64): + return (VOID*)(UINTN)InterlockedCompareExchange64 ( + (volatile UINT64 *)Value, + (UINT64)(UINTN)CompareValue, + (UINT64)(UINTN)ExchangeValue + ); + default: + ASSERT (FALSE); + return NULL; + } +} diff --git a/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/SynchronizationMsc.c b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/SynchronizationMsc.c new file mode 100644 index 0000000..14834c0 --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/SynchronizationMsc.c @@ -0,0 +1,353 @@ +/** @file + Implementation of synchronization functions. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseSynchronizationLibInternals.h" + +/** + Microsoft Visual Studio 7.1 Function Prototypes for read write barrier Intrinsics. +**/ + +void _ReadWriteBarrier (void); +#pragma intrinsic(_ReadWriteBarrier) + + +#define SPIN_LOCK_RELEASED ((UINTN) 1) +#define SPIN_LOCK_ACQUIRED ((UINTN) 2) + +/** + Retrieves the architecture specific spin lock alignment requirements for + optimal spin lock performance. + + This function retrieves the spin lock alignment requirements for optimal + performance on a given CPU architecture. The spin lock alignment must be a + power of two and is returned by this function. If there are no alignment + requirements, then 1 must be returned. The spin lock synchronization + functions must function correctly if the spin lock size and alignment values + returned by this function are not used at all. These values are hints to the + consumers of the spin lock synchronization functions to obtain optimal spin + lock performance. + + @return The architecture specific spin lock alignment. + +**/ +UINTN +EFIAPI +GetSpinLockProperties ( + VOID + ) +{ + return 32; +} + +/** + Initializes a spin lock to the released state and returns the spin lock. + + This function initializes the spin lock specified by SpinLock to the released + state, and returns SpinLock. Optimal performance can be achieved by calling + GetSpinLockProperties() to determine the size and alignment requirements for + SpinLock. + + If SpinLock is NULL, then ASSERT(). + + @param SpinLock A pointer to the spin lock to initialize to the released + state. + + @return SpinLock is in release state. + +**/ +SPIN_LOCK * +EFIAPI +InitializeSpinLock ( + OUT SPIN_LOCK *SpinLock + ) +{ + ASSERT (SpinLock != NULL); + if (SpinLock == NULL) { + return NULL; + } + + _ReadWriteBarrier(); + *SpinLock = SPIN_LOCK_RELEASED; + _ReadWriteBarrier(); + + return SpinLock; +} + +/** + Waits until a spin lock can be placed in the acquired state. + + This function checks the state of the spin lock specified by SpinLock. If + SpinLock is in the released state, then this function places SpinLock in the + acquired state and returns SpinLock. Otherwise, this function waits + indefinitely for the spin lock to be released, and then places it in the + acquired state and returns SpinLock. All state transitions of SpinLock must + be performed using MP safe mechanisms. + + If SpinLock is NULL, then ASSERT(). + If SpinLock was not initialized with InitializeSpinLock(), then ASSERT(). + If PcdSpinLockTimeout is not zero, and SpinLock is can not be acquired in + PcdSpinLockTimeout microseconds, then ASSERT(). + + @param SpinLock A pointer to the spin lock to place in the acquired state. + + @return SpinLock acquired the lock. + +**/ +SPIN_LOCK * +EFIAPI +AcquireSpinLock ( + IN OUT SPIN_LOCK *SpinLock + ) +{ + while (!AcquireSpinLockOrFail (SpinLock)) { + CpuPause (); + } + return SpinLock; +} + +/** + Attempts to place a spin lock in the acquired state. + + This function checks the state of the spin lock specified by SpinLock. If + SpinLock is in the released state, then this function places SpinLock in the + acquired state and returns TRUE. Otherwise, FALSE is returned. All state + transitions of SpinLock must be performed using MP safe mechanisms. + + If SpinLock is NULL, then ASSERT(). + If SpinLock was not initialized with InitializeSpinLock(), then ASSERT(). + + @param SpinLock A pointer to the spin lock to place in the acquired state. + + @retval TRUE SpinLock was placed in the acquired state. + @retval FALSE SpinLock could not be acquired. + +**/ +BOOLEAN +EFIAPI +AcquireSpinLockOrFail ( + IN OUT SPIN_LOCK *SpinLock + ) +{ + SPIN_LOCK LockValue; + VOID *Result; + + ASSERT (SpinLock != NULL); + if (SpinLock == NULL) { + return FALSE; + } + + LockValue = *SpinLock; + ASSERT (LockValue == SPIN_LOCK_ACQUIRED || LockValue == SPIN_LOCK_RELEASED); + + _ReadWriteBarrier (); + Result = InterlockedCompareExchangePointer ( + (VOID**)SpinLock, + (VOID*)SPIN_LOCK_RELEASED, + (VOID*)SPIN_LOCK_ACQUIRED + ); + + _ReadWriteBarrier (); + return (BOOLEAN) (Result == (VOID*) SPIN_LOCK_RELEASED); +} + +/** + Releases a spin lock. + + This function places the spin lock specified by SpinLock in the release state + and returns SpinLock. + + If SpinLock is NULL, then ASSERT(). + If SpinLock was not initialized with InitializeSpinLock(), then ASSERT(). + + @param SpinLock A pointer to the spin lock to release. + + @return SpinLock released the lock. + +**/ +SPIN_LOCK * +EFIAPI +ReleaseSpinLock ( + IN OUT SPIN_LOCK *SpinLock + ) +{ + SPIN_LOCK LockValue; + + ASSERT (SpinLock != NULL); + if (SpinLock == NULL) { + return NULL; + } + + LockValue = *SpinLock; + ASSERT (LockValue == SPIN_LOCK_ACQUIRED || LockValue == SPIN_LOCK_RELEASED); + + _ReadWriteBarrier (); + *SpinLock = SPIN_LOCK_RELEASED; + _ReadWriteBarrier (); + + return SpinLock; +} + +/** + Performs an atomic increment of an 32-bit unsigned integer. + + Performs an atomic increment of the 32-bit unsigned integer specified by + Value and returns the incremented value. The increment operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 32-bit value to increment. + + @return The incremented value. + +**/ +UINT32 +EFIAPI +InterlockedIncrement ( + IN volatile UINT32 *Value + ) +{ + ASSERT (Value != NULL); + return InternalSyncIncrement (Value); +} + +/** + Performs an atomic decrement of an 32-bit unsigned integer. + + Performs an atomic decrement of the 32-bit unsigned integer specified by + Value and returns the decremented value. The decrement operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 32-bit value to decrement. + + @return The decremented value. + +**/ +UINT32 +EFIAPI +InterlockedDecrement ( + IN volatile UINT32 *Value + ) +{ + ASSERT (Value != NULL); + return InternalSyncDecrement (Value); +} + +/** + Performs an atomic compare exchange operation on a 32-bit unsigned integer. + + Performs an atomic compare exchange operation on the 32-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 32-bit value for the compare exchange + operation. + @param CompareValue A 32-bit value used in a compare operation. + @param ExchangeValue A 32-bit value used in an exchange operation. + + @return The original *Value before exchange. + +**/ +UINT32 +EFIAPI +InterlockedCompareExchange32 ( + IN OUT volatile UINT32 *Value, + IN UINT32 CompareValue, + IN UINT32 ExchangeValue + ) +{ + ASSERT (Value != NULL); + return InternalSyncCompareExchange32 (Value, CompareValue, ExchangeValue); +} + +/** + Performs an atomic compare exchange operation on a 64-bit unsigned integer. + + Performs an atomic compare exchange operation on the 64-bit unsigned integer specified + by Value. If Value is equal to CompareValue, then Value is set to ExchangeValue and + CompareValue is returned. If Value is not equal to CompareValue, then Value is returned. + The compare exchange operation must be performed using MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 64-bit value for the compare exchange + operation. + @param CompareValue A 64-bit value used in a compare operation. + @param ExchangeValue A 64-bit value used in an exchange operation. + + @return The original *Value before exchange. + +**/ +UINT64 +EFIAPI +InterlockedCompareExchange64 ( + IN OUT volatile UINT64 *Value, + IN UINT64 CompareValue, + IN UINT64 ExchangeValue + ) +{ + ASSERT (Value != NULL); + return InternalSyncCompareExchange64 (Value, CompareValue, ExchangeValue); +} + +/** + Performs an atomic compare exchange operation on a pointer value. + + Performs an atomic compare exchange operation on the pointer value specified + by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to + CompareValue, then Value is returned. The compare exchange operation must be + performed using MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the pointer value for the compare exchange + operation. + @param CompareValue A pointer value used in a compare operation. + @param ExchangeValue A pointer value used in an exchange operation. + + @return The original *Value before exchange. +**/ +VOID * +EFIAPI +InterlockedCompareExchangePointer ( + IN OUT VOID * volatile *Value, + IN VOID *CompareValue, + IN VOID *ExchangeValue + ) +{ + UINT8 SizeOfValue; + + SizeOfValue = (UINT8) sizeof (*Value); + + switch (SizeOfValue) { + case sizeof (UINT32): + return (VOID*)(UINTN)InterlockedCompareExchange32 ( + (volatile UINT32*)Value, + (UINT32)(UINTN)CompareValue, + (UINT32)(UINTN)ExchangeValue + ); + case sizeof (UINT64): + return (VOID*)(UINTN)InterlockedCompareExchange64 ( + (volatile UINT64*)Value, + (UINT64)(UINTN)CompareValue, + (UINT64)(UINTN)ExchangeValue + ); + default: + ASSERT (FALSE); + return NULL; + } +} diff --git a/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/X64/GccInline.c b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/X64/GccInline.c new file mode 100644 index 0000000..862cb47 --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/X64/GccInline.c @@ -0,0 +1,170 @@ +/** @file + GCC inline implementation of BaseSynchronizationLib processor specific functions. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + + + +/** + Performs an atomic increment of an 32-bit unsigned integer. + + Performs an atomic increment of the 32-bit unsigned integer specified by + Value and returns the incremented value. The increment operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + @param Value A pointer to the 32-bit value to increment. + + @return The incremented value. + +**/ +UINT32 +EFIAPI +InternalSyncIncrement ( + IN volatile UINT32 *Value + ) +{ + UINT32 Result; + + __asm__ __volatile__ ( + "lock \n\t" + "incl %2 \n\t" + "mov %2, %%eax " + : "=a" (Result), // %0 + "=m" (*Value) // %1 + : "m" (*Value) // %2 + : "memory", + "cc" + ); + + return Result; +} + + +/** + Performs an atomic decrement of an 32-bit unsigned integer. + + Performs an atomic decrement of the 32-bit unsigned integer specified by + Value and returns the decremented value. The decrement operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + @param Value A pointer to the 32-bit value to decrement. + + @return The decremented value. + +**/ +UINT32 +EFIAPI +InternalSyncDecrement ( + IN volatile UINT32 *Value + ) +{ + UINT32 Result; + + __asm__ __volatile__ ( + "lock \n\t" + "decl %2 \n\t" + "mov %2, %%eax " + : "=a" (Result), // %0 + "=m" (*Value) // %1 + : "m" (*Value) // %2 + : "memory", + "cc" + ); + + return Result; +} + + +/** + Performs an atomic compare exchange operation on a 32-bit unsigned integer. + + Performs an atomic compare exchange operation on the 32-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + + @param Value A pointer to the 32-bit value for the compare exchange + operation. + @param CompareValue 32-bit value used in compare operation. + @param ExchangeValue 32-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT32 +EFIAPI +InternalSyncCompareExchange32 ( + IN OUT volatile UINT32 *Value, + IN UINT32 CompareValue, + IN UINT32 ExchangeValue + ) +{ + + + __asm__ __volatile__ ( + "lock \n\t" + "cmpxchgl %3, %1 " + : "=a" (CompareValue), // %0 + "=m" (*Value) // %1 + : "a" (CompareValue), // %2 + "r" (ExchangeValue), // %3 + "m" (*Value) + : "memory", + "cc" + ); + + return CompareValue; +} + + +/** + Performs an atomic compare exchange operation on a 64-bit unsigned integer. + + Performs an atomic compare exchange operation on the 64-bit unsigned integer specified + by Value. If Value is equal to CompareValue, then Value is set to ExchangeValue and + CompareValue is returned. If Value is not equal to CompareValue, then Value is returned. + The compare exchange operation must be performed using MP safe mechanisms. + + + @param Value A pointer to the 64-bit value for the compare exchange + operation. + @param CompareValue 64-bit value used in compare operation. + @param ExchangeValue 64-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT64 +EFIAPI +InternalSyncCompareExchange64 ( + IN OUT volatile UINT64 *Value, + IN UINT64 CompareValue, + IN UINT64 ExchangeValue + ) +{ + + __asm__ __volatile__ ( + "lock \n\t" + "cmpxchgq %3, %1 " + : "=a" (CompareValue), // %0 + "=m" (*Value) // %1 + : "a" (CompareValue), // %2 + "r" (ExchangeValue), // %3 + "m" (*Value) + : "memory", + "cc" + ); + + return CompareValue; +} + + diff --git a/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/X64/InterlockedCompareExchange32.asm b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/X64/InterlockedCompareExchange32.asm new file mode 100644 index 0000000..185ae8d --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/X64/InterlockedCompareExchange32.asm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; InterlockedCompareExchange32.Asm +; +; Abstract: +; +; InterlockedCompareExchange32 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINT32 +; EFIAPI +; InternalSyncCompareExchange32 ( +; IN volatile UINT32 *Value, +; IN UINT32 CompareValue, +; IN UINT32 ExchangeValue +; ); +;------------------------------------------------------------------------------ +InternalSyncCompareExchange32 PROC + mov eax, edx + lock cmpxchg [rcx], r8d + ret +InternalSyncCompareExchange32 ENDP + + END diff --git a/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/X64/InterlockedCompareExchange32.c b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/X64/InterlockedCompareExchange32.c new file mode 100644 index 0000000..2238aa2 --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/X64/InterlockedCompareExchange32.c @@ -0,0 +1,48 @@ +/** @file + InterlockedCompareExchange32 function + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics. +**/ + +long _InterlockedCompareExchange( + long volatile * Destination, + long Exchange, + long Comperand +); + +#pragma intrinsic(_InterlockedCompareExchange) + +/** + Performs an atomic compare exchange operation on a 32-bit unsigned integer. + + Performs an atomic compare exchange operation on the 32-bit unsigned integer + specified by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue, + then Value is returned. The compare exchange operation must be performed using + MP safe mechanisms. + + @param Value A pointer to the 32-bit value for the compare exchange + operation. + @param CompareValue 32-bit value used in compare operation. + @param ExchangeValue 32-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT32 +EFIAPI +InternalSyncCompareExchange32 ( + IN volatile UINT32 *Value, + IN UINT32 CompareValue, + IN UINT32 ExchangeValue + ) +{ + return _InterlockedCompareExchange (Value, ExchangeValue, CompareValue); +} + diff --git a/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/X64/InterlockedCompareExchange64.asm b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/X64/InterlockedCompareExchange64.asm new file mode 100644 index 0000000..0658212 --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/X64/InterlockedCompareExchange64.asm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; InterlockedCompareExchange64.Asm +; +; Abstract: +; +; InterlockedCompareExchange64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; InternalSyncCompareExchange64 ( +; IN volatile UINT64 *Value, +; IN UINT64 CompareValue, +; IN UINT64 ExchangeValue +; ); +;------------------------------------------------------------------------------ +InternalSyncCompareExchange64 PROC + mov rax, rdx + lock cmpxchg [rcx], r8 + ret +InternalSyncCompareExchange64 ENDP + + END diff --git a/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/X64/InterlockedCompareExchange64.c b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/X64/InterlockedCompareExchange64.c new file mode 100644 index 0000000..5a7eac9 --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/X64/InterlockedCompareExchange64.c @@ -0,0 +1,47 @@ +/** @file + InterlockedCompareExchange64 function + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics. +**/ + +__int64 _InterlockedCompareExchange64( + __int64 volatile * Destination, + __int64 Exchange, + __int64 Comperand +); + +#pragma intrinsic(_InterlockedCompareExchange64) + +/** + Performs an atomic compare exchange operation on a 64-bit unsigned integer. + + Performs an atomic compare exchange operation on the 64-bit unsigned integer specified + by Value. If Value is equal to CompareValue, then Value is set to ExchangeValue and + CompareValue is returned. If Value is not equal to CompareValue, then Value is returned. + The compare exchange operation must be performed using MP safe mechanisms. + + @param Value A pointer to the 64-bit value for the compare exchange + operation. + @param CompareValue 64-bit value used in compare operation. + @param ExchangeValue 64-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT64 +EFIAPI +InternalSyncCompareExchange64 ( + IN volatile UINT64 *Value, + IN UINT64 CompareValue, + IN UINT64 ExchangeValue + ) +{ + return _InterlockedCompareExchange64 (Value, ExchangeValue, CompareValue); +} + diff --git a/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/X64/InterlockedDecrement.asm b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/X64/InterlockedDecrement.asm new file mode 100644 index 0000000..3f7ea3f --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/X64/InterlockedDecrement.asm @@ -0,0 +1,33 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; InterlockedDecrement.Asm +; +; Abstract: +; +; InterlockedDecrement function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINT32 +; EFIAPI +; InternalSyncDecrement ( +; IN volatile UINT32 *Value +; ); +;------------------------------------------------------------------------------ +InternalSyncDecrement PROC + lock dec dword ptr [rcx] + mov eax, [rcx] + ret +InternalSyncDecrement ENDP + + END diff --git a/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/X64/InterlockedDecrement.c b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/X64/InterlockedDecrement.c new file mode 100644 index 0000000..94d344c --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/X64/InterlockedDecrement.c @@ -0,0 +1,40 @@ +/** @file + InterlockedDecrement function + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics. +**/ + +long _InterlockedDecrement( + long * lpAddend +); + +#pragma intrinsic(_InterlockedDecrement) + +/** + Performs an atomic decrement of an 32-bit unsigned integer. + + Performs an atomic decrement of the 32-bit unsigned integer specified by + Value and returns the decrement value. The decrement operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + @param Value A pointer to the 32-bit value to decrement. + + @return The decrement value. + +**/ +UINT32 +EFIAPI +InternalSyncDecrement ( + IN volatile UINT32 *Value + ) +{ + return _InterlockedDecrement ((long *)(UINTN)(Value)); +} + diff --git a/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/X64/InterlockedIncrement.asm b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/X64/InterlockedIncrement.asm new file mode 100644 index 0000000..ed29655 --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/X64/InterlockedIncrement.asm @@ -0,0 +1,33 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; InterlockedIncrement.Asm +; +; Abstract: +; +; InterlockedIncrement function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINT32 +; EFIAPI +; InternalSyncIncrement ( +; IN volatile UINT32 *Value +; ); +;------------------------------------------------------------------------------ +InternalSyncIncrement PROC + lock inc dword ptr [rcx] + mov eax, [rcx] + ret +InternalSyncIncrement ENDP + + END diff --git a/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/X64/InterlockedIncrement.c b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/X64/InterlockedIncrement.c new file mode 100644 index 0000000..bb5c718 --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/X64/InterlockedIncrement.c @@ -0,0 +1,40 @@ +/** @file + InterLockedIncrement function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics. +**/ + +long _InterlockedIncrement( + long * lpAddend +); + +#pragma intrinsic(_InterlockedIncrement) + +/** + Performs an atomic increment of an 32-bit unsigned integer. + + Performs an atomic increment of the 32-bit unsigned integer specified by + Value and returns the incremented value. The increment operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + @param Value A pointer to the 32-bit value to increment. + + @return The incremented value. + +**/ +UINT32 +EFIAPI +InternalSyncIncrement ( + IN volatile UINT32 *Value + ) +{ + return _InterlockedIncrement ((long *)(UINTN)(Value)); +} + diff --git a/HBFA/UefiInstrumentTestPkg/UefiInstrumentTestPkg.dec b/HBFA/UefiInstrumentTestPkg/UefiInstrumentTestPkg.dec new file mode 100644 index 0000000..5251dda --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/UefiInstrumentTestPkg.dec @@ -0,0 +1,16 @@ +## @file +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = UefiInstrumentTestPkg + PACKAGE_GUID = DA14F9B4-A294-4171-91AC-C81E39D7153B + PACKAGE_VERSION = 0.11 + +[Includes] + Include \ No newline at end of file diff --git a/HBFA/UefiInstrumentTestPkg/UefiInstrumentTestPkg.dsc b/HBFA/UefiInstrumentTestPkg/UefiInstrumentTestPkg.dsc new file mode 100644 index 0000000..7dd6d99 --- /dev/null +++ b/HBFA/UefiInstrumentTestPkg/UefiInstrumentTestPkg.dsc @@ -0,0 +1,175 @@ +## @file +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + PLATFORM_NAME = UefiInstrumentTestPkg + PLATFORM_GUID = D2C24BA7-0B1A-4C06-85CD-703226264AFF + PLATFORM_VERSION = 0.11 + DSC_SPECIFICATION = 0x00010005 + OUTPUT_DIRECTORY = Build/UefiInstrumentTestPkg + SUPPORTED_ARCHITECTURES = IA32|X64 + BUILD_TARGETS = DEBUG|RELEASE|NOOPT + SKUID_IDENTIFIER = DEFAULT + +[LibraryClasses] + # + # Entry point + # + UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf + UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf + # + # Basic + # + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf + BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf + CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf + SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf + PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf + CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf + PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf + + # + # PEI + # + PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf + PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf + PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf + # + # UEFI & PI + # + UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.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 + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf + # + # Generic Modules + # + TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + # + # Misc + # + DebugLib|IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf + DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf + UefiDecompressLib|IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf + + # + # CPU + # + MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf + LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf + UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf + SmmLib|MdePkg/Library/SmmLibNull/SmmLibNull.inf + CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf + + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf + RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf + + PlatformSecureLib|SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.inf + SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf + LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf + SmmMemLib|MdePkg/Library/SmmMemLib/SmmMemLib.inf + +[LibraryClasses.common.PEIM] + ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf + HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf + MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf + +[LibraryClasses.common.PEI_CORE] + PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf + ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf + HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf + MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf + +[LibraryClasses.common.DXE_CORE] + DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf + ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf + HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf + MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf + +[LibraryClasses.common.DXE_DRIVER] + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf + +[LibraryClasses.common.UEFI_DRIVER] + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf + +[LibraryClasses.common.DXE_RUNTIME_DRIVER] + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf + +[LibraryClasses.common.SMM_CORE] + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + MemoryAllocationLib|MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.inf + SmmCorePlatformHookLib|MdeModulePkg/Library/SmmCorePlatformHookLibNull/SmmCorePlatformHookLibNull.inf + SmmServicesTableLib|MdeModulePkg/Library/PiSmmCoreSmmServicesTableLib/PiSmmCoreSmmServicesTableLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf + +[LibraryClasses.common.DXE_SMM_DRIVER] + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf + SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf + +[LibraryClasses.common.UEFI_APPLICATION] + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.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. +# +################################################################################################### + +[PcdsFixedAtBuild.common] + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x1f + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80080046 + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07 + gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask|0x1 + +[Components] + UefiInstrumentTestPkg/Library/InstrumentLib/InstrumentLib.inf + UefiInstrumentTestPkg/Library/IniParsingLib/IniParsingLib.inf + UefiInstrumentTestPkg/Library/SimpleSynchronizationLib/SimpleSynchronizationLib.inf + UefiInstrumentTestPkg/Library/InstrumentHookLibNull/InstrumentHookLibNull.inf diff --git a/HBFA/__init__.py b/HBFA/__init__.py new file mode 100755 index 0000000..e69de29 diff --git a/HBFA/tests/TestRunAFL.py b/HBFA/tests/TestRunAFL.py new file mode 100644 index 0000000..3ad92e9 --- /dev/null +++ b/HBFA/tests/TestRunAFL.py @@ -0,0 +1,266 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +import unittest +import os +import sys +import io +import contextlib +try: + from unittest import mock # python 3.3+ +except ImportError: + import mock # python 2.6-3.2 + + +class TestRunAFL(unittest.TestCase): + + # Test bad value for arch is handled (-a 'X64') + @mock.patch('UefiHostTestTools.RunAFL.Build', return_value='') + @mock.patch('UefiHostTestTools.RunAFL.RunAFL', return_value='') + @mock.patch('UefiHostTestTools.RunAFL.CheckTestEnv', return_value='') + @mock.patch('UefiHostTestTools.RunAFL.HBFA_PATH', '/root/hbfa_workspace/' + 'edk2-staging/HBFA') + @mock.patch('sys.argv', ['RunAFL.py', '-m', '/root/hbfa_workspace/edk2-' + 'staging/HBFA/UefiHostFuzzTestCasePkg/TestCase' + '/MdeModulePkg/Library/BaseBmpSupportLib/' + 'TestBmpSupportLib.inf', '-i', '/tmp/', '-o', + '/tmp/test', '-a', 'X65', '-c', 'rawcommand']) + def test_args_badarch(self, *args, **kwargs): + print("\n[+]Testing bad value for arch: -a X65") + with io.StringIO() as buffer: + with contextlib.redirect_stderr(buffer): + with self.assertRaises(SystemExit): + UefiHostTestTools.RunAFL.main() + check_string = "argument -a/--arch: invalid choice: 'X65' " + \ + "(choose from 'IA32', 'X64', 'ARM', 'AARCH64')" + self.assertIn(check_string, buffer.getvalue()) + + # Test bad value for module is handled (not in HBFA_PATH) + @mock.patch('UefiHostTestTools.RunAFL.Build', return_value='') + @mock.patch('UefiHostTestTools.RunAFL.RunAFL', return_value='') + @mock.patch('UefiHostTestTools.RunAFL.CheckTestEnv', return_value='') + @mock.patch('UefiHostTestTools.RunAFL.HBFA_PATH', + '/root/hbfa_workspace/edk2-staging/HBFA') + @mock.patch('sys.argv', ['RunAFL.py', '-m', '/tmp/TestBmpSupportLib.inf', + '-i', '/tmp/', '-o', '/tmp/test', '-a', 'X64', + '-c', 'rawcommand']) + @mock.patch('os._exit', sys.exit) + def test_args_bad_module_hbfa_path(self, *args, **kwargs): + print("\n[+]Test bad value for module is handled (not in HBFA_PATH)") + with io.StringIO() as buffer: + with contextlib.redirect_stdout(buffer): + with self.assertRaises(SystemExit): + UefiHostTestTools.RunAFL.main() + message = buffer.getvalue() + # Check against expected print string: + # ModuleFile path: /tmp/TestBmpSupportLib.inf should start + # with /root/hbfa_workspace/edk2-staging/HBFA. + check_string = b'\x4d\x6f\x64\x75\x6c\x65\x46\x69\x6c\x65\x20' \ + + b'\x70\x61\x74\x68\x3a\x20\x2f\x74\x6d\x70\x2f\x54\x65' \ + + b'\x73\x74\x42\x6d\x70\x53\x75\x70\x70\x6f\x72\x74\x4c' \ + + b'\x69\x62\x2e\x69\x6e\x66\x20\x73\x68\x6f\x75\x6c\x64' \ + + b'\x20\x73\x74\x61\x72\x74\x20\x77\x69\x74\x68\x20\x2f' \ + + b'\x72\x6f\x6f\x74\x2f\x68\x62\x66\x61\x5f\x77\x6f\x72' \ + + b'\x6b\x73\x70\x61\x63\x65\x2f\x65\x64\x6b\x32\x2d\x73' \ + + b'\x74\x61\x67\x69\x6e\x67\x2f\x48\x42\x46\x41\x2e\x0a' + check_string = check_string.decode("ascii") + self.assertEqual(message, check_string) + + # Test bad value for module is handled (no value set) + @mock.patch('UefiHostTestTools.RunAFL.Build', return_value='') + @mock.patch('UefiHostTestTools.RunAFL.RunAFL', return_value='') + @mock.patch('UefiHostTestTools.RunAFL.CheckTestEnv', return_value='') + @mock.patch('UefiHostTestTools.RunAFL.HBFA_PATH', + '/root/hbfa_workspace/edk2-staging/HBFA') + @mock.patch('sys.argv', ['RunAFL.py', '-m', '', '-i', '/tmp/', '-o', + '/tmp/test', '-a', 'X64', '-c', 'rawcommand']) + @mock.patch('os._exit', sys.exit) + def test_args_bad_module_no_value(self, *args, **kwargs): + print("\n[+]Test bad value for module is handled (no value set)") + with io.StringIO() as buffer: + with contextlib.redirect_stdout(buffer): + with self.assertRaises(SystemExit): + UefiHostTestTools.RunAFL.main() + # Check against expected print string: + # ModuleFile path: /tmp/TestBmpSupportLib.inf should be + # start with /root/hbfa_workspace/edk2-staging/HBFA + message = buffer.getvalue() + check_string = b'\x4d\x6f\x64\x75\x6c\x65\x46\x69\x6c\x65\x20' \ + + b'\x73\x68\x6f\x75\x6c\x64\x20\x62\x65\x20\x73\x65\x74' \ + + b'\x20\x6f\x6e\x63\x65\x20\x62\x79\x20\x63\x6f\x6d\x6d' \ + + b'\x61\x6e\x64\x20\x2d\x6d\x20\x4d\x4f\x44\x55\x4c\x45' \ + + b'\x46\x49\x4c\x45\x2c\x20\x2d\x2d\x6d\x6f\x64\x75\x6c' \ + + b'\x65\x3d\x4d\x4f\x44\x55\x4c\x45\x46\x49\x4c\x45' \ + + b'\x2e\x0a' + check_string = check_string.decode("ascii") + self.assertEqual(message, check_string) + + # Test bad value for module is handled (file does not exist or is not + # in relative path) + @mock.patch('UefiHostTestTools.RunAFL.Build', return_value='') + @mock.patch('UefiHostTestTools.RunAFL.RunAFL', return_value='') + @mock.patch('UefiHostTestTools.RunAFL.CheckTestEnv', return_value='') + @mock.patch('UefiHostTestTools.RunAFL.HBFA_PATH', + '/root/hbfa_workspace/edk2-staging/HBFA') + @mock.patch('sys.argv', + ['RunAFL.py', '-m', + 'root/hbfa_workspace/edk2-staging/HBFA/test/test', + '-i', '/tmp/', '-o', '/tmp/test', '-a', 'X64', + '-c', 'rawcommand']) + @mock.patch('os._exit', sys.exit) + def test_args_bad_module_bad_value(self, *args, **kwargs): + print("\n[+]Test bad value for module is handled (bad value set)") + with io.StringIO() as buffer: + with contextlib.redirect_stdout(buffer): + with self.assertRaises(SystemExit): + UefiHostTestTools.RunAFL.main() + # Check against expected print string: + # ModuleFile path: + # root/hbfa_workspace/edk2-staging/HBFA/test/test does + # not exist or is not in the relative path for HBFA + message = buffer.getvalue() + check_string = b'\x4d\x6f\x64\x75\x6c\x65\x46\x69\x6c\x65\x20' \ + + b'\x70\x61\x74\x68\x3a\x20\x72\x6f\x6f\x74\x2f\x68\x62' \ + + b'\x66\x61\x5f\x77\x6f\x72\x6b\x73\x70\x61\x63\x65\x2f' \ + + b'\x65\x64\x6b\x32\x2d\x73\x74\x61\x67\x69\x6e\x67\x2f' \ + + b'\x48\x42\x46\x41\x2f\x74\x65\x73\x74\x2f\x74\x65\x73' \ + + b'\x74\x20\x64\x6f\x65\x73\x20\x6e\x6f\x74\x20\x65\x78' \ + + b'\x69\x73\x74\x20\x6f\x72\x20\x69\x73\x20\x6e\x6f\x74' \ + + b'\x20\x69\x6e\x20\x74\x68\x65\x20\x72\x65\x6c\x61\x74' \ + + b'\x69\x76\x65\x20\x70\x61\x74\x68\x20\x66\x6f\x72\x20' \ + + b'\x48\x42\x46\x41\x0a' + check_string = check_string.decode("ascii") + self.assertEqual(message, check_string) + + # Test bad value for input seed path (no value/path) + @mock.patch('UefiHostTestTools.RunAFL.Build', return_value='') + @mock.patch('UefiHostTestTools.RunAFL.RunAFL', return_value='') + @mock.patch('UefiHostTestTools.RunAFL.CheckTestEnv', return_value='') + @mock.patch('UefiHostTestTools.RunAFL.HBFA_PATH', + '/root/hbfa_workspace/edk2-staging/HBFA') + @mock.patch('sys.argv', + ['RunAFL.py', '-m', + '/root/hbfa_workspace/edk2-staging/HBFA/' + + 'UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/' + + 'Library/BaseBmpSupportLib/TestBmpSupportLib.inf', + '-i', '', '-o', '/tmp/test', '-a', 'X64', '-c', + 'rawcommand']) + @mock.patch('os._exit', sys.exit) + def test_args_bad_input_seed_none(self, *args, **kwargs): + print("\n[+]Test bad value for input seed path is handled " + "(no value set)") + with io.StringIO() as buffer: + with contextlib.redirect_stdout(buffer): + with self.assertRaises(SystemExit): + UefiHostTestTools.RunAFL.main() + message = buffer.getvalue() + # Check against expected print string: + # InputSeed path should be set once by command -i INPUTSEED, + # --input=INPUTSEED. + check_string = b'\x49\x6e\x70\x75\x74\x53\x65\x65\x64\x20\x70' \ + + b'\x61\x74\x68\x20\x73\x68\x6f\x75\x6c\x64\x20\x62\x65' \ + + b'\x20\x73\x65\x74\x20\x6f\x6e\x63\x65\x20\x62\x79\x20' \ + + b'\x63\x6f\x6d\x6d\x61\x6e\x64\x20\x2d\x69\x20\x49\x4e' \ + + b'\x50\x55\x54\x53\x45\x45\x44\x2c\x20\x2d\x2d\x69\x6e' \ + + b'\x70\x75\x74\x3d\x49\x4e\x50\x55\x54\x53\x45\x45\x44' \ + + b'\x2e\x0a' + check_string = check_string.decode("ascii") + self.assertEqual(message, check_string) + + # Test bad value for input seed path (path does not exist) + @mock.patch('UefiHostTestTools.RunAFL.Build', return_value='') + @mock.patch('UefiHostTestTools.RunAFL.RunAFL', return_value='') + @mock.patch('UefiHostTestTools.RunAFL.CheckTestEnv', return_value='') + @mock.patch('UefiHostTestTools.RunAFL.HBFA_PATH', + '/root/hbfa_workspace/edk2-staging/HBFA') + @mock.patch('sys.argv', + ['RunAFL.py', '-m', + '/root/hbfa_workspace/edk2-staging/HBFA/' + 'UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/' + 'Library/BaseBmpSupportLib/TestBmpSupportLib.inf', + '-i', '/tmp/tmp/tmp/tmp', '-o', '/tmp/test', '-a', 'X64', + '-c', 'rawcommand']) + @mock.patch('os._exit', sys.exit) + def test_args_bad_input_seed_path(self, *args, **kwargs): + print("\n[+]Test bad value for input seed path is handled " + "(bad path, does not exist)") + with io.StringIO() as buffer: + with contextlib.redirect_stdout(buffer): + with self.assertRaises(SystemExit): + UefiHostTestTools.RunAFL.main() + message = buffer.getvalue() + # Check against expected print string: + # InputSeed path: /tmp/tmp/tmp/tmp does not exist + check_string = b'\x49\x6e\x70\x75\x74\x53\x65\x65\x64\x20\x70' \ + + b'\x61\x74\x68\x3a\x20\x2f\x74\x6d\x70\x2f\x74\x6d\x70' \ + + b'\x2f\x74\x6d\x70\x2f\x74\x6d\x70\x20\x64\x6f\x65\x73' \ + + b'\x20\x6e\x6f\x74\x20\x65\x78\x69\x73\x74\x0a' + check_string = check_string.decode("ascii") + self.assertEqual(message, check_string) + + # Test bad value for output path (no argument) + @mock.patch('UefiHostTestTools.RunAFL.Build', return_value='') + @mock.patch('UefiHostTestTools.RunAFL.RunAFL', return_value='') + @mock.patch('UefiHostTestTools.RunAFL.CheckTestEnv', return_value='') + @mock.patch('UefiHostTestTools.RunAFL.HBFA_PATH', + '/root/hbfa_workspace/edk2-staging/HBFA') + @mock.patch('sys.argv', + ['RunAFL.py', '-m', + '/root/hbfa_workspace/edk2-staging/HBFA/' + 'UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/' + 'Library/BaseBmpSupportLib/TestBmpSupportLib.inf', + '-i', '/tmp/', '-o', '', '-a', 'X64', '-c', + 'rawcommand']) + @mock.patch('os._exit', sys.exit) + def test_args_bad_output_seed_none(self, *args, **kwargs): + print("\n[+]Test bad value for output seed path is handled " + "(no argument)") + with io.StringIO() as buffer: + with contextlib.redirect_stdout(buffer): + with self.assertRaises(SystemExit): + UefiHostTestTools.RunAFL.main() + message = buffer.getvalue() + # Check against expected print string: + # OutputSeed path should be set once by command -o OUTPUT, + # --output=OUTPUT. + check_string = b'\x4f\x75\x74\x70\x75\x74\x53\x65\x65\x64\x20' \ + + b'\x70\x61\x74\x68\x20\x73\x68\x6f\x75\x6c\x64\x20\x62' \ + + b'\x65\x20\x73\x65\x74\x20\x6f\x6e\x63\x65\x20\x62\x79' \ + + b'\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x20\x2d\x6f\x20\x4f' \ + + b'\x55\x54\x50\x55\x54\x2c\x20\x2d\x2d\x6f\x75\x74\x70' \ + + b'\x75\x74\x3d\x4f\x55\x54\x50\x55\x54\x2e\x0a' + check_string = check_string.decode("ascii") + self.assertEqual(message, check_string) + + # Test bad input value for command line mode (assuming we are on Linux) + @mock.patch('UefiHostTestTools.RunAFL.Build', return_value='') + @mock.patch('UefiHostTestTools.RunAFL.RunAFL', return_value='') + @mock.patch('UefiHostTestTools.RunAFL.CheckTestEnv', return_value='') + @mock.patch('UefiHostTestTools.RunAFL.HBFA_PATH', + '/root/hbfa_workspace/edk2-staging/HBFA') + @mock.patch('sys.argv', + ['RunAFL.py', '-m', + '/root/hbfa_workspace/edk2-staging/HBFA/' + 'UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/' + 'Library/BaseBmpSupportLib/TestBmpSupportLib.inf', + '-i', '/tmp/', '-o', '/tmp/test', '-a', 'X64', + '-c', 'gnome']) + @mock.patch('UefiHostTestTools.RunAFL.SysType', 'Linux') + @mock.patch('os._exit', sys.exit) + def test_args_bad_command_mode(self, *args, **kwargs): + print("\n[+]Test bad value for command line mode") + with io.StringIO() as buffer: + with contextlib.redirect_stderr(buffer): + with self.assertRaises(SystemExit): + UefiHostTestTools.RunAFL.main() + check_string = "invalid choice: 'gnome' (choose from " + \ + "'rawcommand', 'manual')" + self.assertIn(check_string, buffer.getvalue()) + + +if __name__ == "__main__": + sys.path.append(os.path.join(os.path.dirname(__file__), '..')) + import UefiHostTestTools.RunAFL + unittest.main() diff --git a/HBFA/tests/TestRunAFLTurbo.py b/HBFA/tests/TestRunAFLTurbo.py new file mode 100644 index 0000000..b8cb9d5 --- /dev/null +++ b/HBFA/tests/TestRunAFLTurbo.py @@ -0,0 +1,270 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +import unittest +import os +import sys +import io +import contextlib +try: + from unittest import mock # python 3.3+ +except ImportError: + import mock # python 2.6-3.2 + + +class TestRunAFLTurbo(unittest.TestCase): + + # Test bad value for arch is handled (-a 'X64') + @mock.patch('UefiHostTestTools.RunAFLTurbo.Build', return_value='') + @mock.patch('UefiHostTestTools.RunAFLTurbo.RunAFLTurbo', return_value='') + @mock.patch('UefiHostTestTools.RunAFLTurbo.CheckTestEnv', return_value='') + @mock.patch('UefiHostTestTools.RunAFLTurbo.HBFA_PATH', + '/root/hbfa_workspace/edk2-staging/HBFA') + @mock.patch('sys.argv', + ['RunAFLTurbo.py', '-m', '/root/hbfa_workspace/edk2-' + 'staging/HBFA/UefiHostFuzzTestCasePkg/TestCase' + '/MdeModulePkg/Library/BaseBmpSupportLib/' + 'TestBmpSupportLib.inf', '-i', '/tmp/', '-o', + '/tmp/test', '-a', 'X65', '-c', 'rawcommand']) + def test_args_badarch(self, *args, **kwargs): + print("\n[+]Testing bad value for arch: -a X65") + with io.StringIO() as buffer: + with contextlib.redirect_stderr(buffer): + with self.assertRaises(SystemExit): + UefiHostTestTools.RunAFLTurbo.main() + check_string = "argument -a/--arch: invalid choice: 'X65' " + \ + "(choose from 'IA32', 'X64', 'ARM', 'AARCH64')" + self.assertIn(check_string, buffer.getvalue()) + + # Test bad value for module is handled (not in HBFA_PATH) + @mock.patch('UefiHostTestTools.RunAFLTurbo.Build', return_value='') + @mock.patch('UefiHostTestTools.RunAFLTurbo.RunAFLTurbo', return_value='') + @mock.patch('UefiHostTestTools.RunAFLTurbo.CheckTestEnv', return_value='') + @mock.patch('UefiHostTestTools.RunAFLTurbo.HBFA_PATH', + '/root/hbfa_workspace/edk2-staging/HBFA') + @mock.patch('sys.argv', + ['RunAFLTurbo.py', '-m', '/tmp/TestBmpSupportLib.inf', + '-i', '/tmp/', '-o', '/tmp/test', '-a', 'X64', + '-c', 'rawcommand']) + @mock.patch('os._exit', sys.exit) + def test_args_bad_module_hbfa_path(self, *args, **kwargs): + print("\n[+] Test bad value for module is handled (not in HBFA_PATH)") + with io.StringIO() as buffer: + with contextlib.redirect_stdout(buffer): + with self.assertRaises(SystemExit): + UefiHostTestTools.RunAFLTurbo.main() + message = buffer.getvalue() + # Check against expected print string: + # ModuleFile path: /tmp/TestBmpSupportLib.inf should start + # with /root/hbfa_workspace/edk2-staging/HBFA. + check_string = b'\x4d\x6f\x64\x75\x6c\x65\x46\x69\x6c\x65\x20' \ + + b'\x70\x61\x74\x68\x3a\x20\x2f\x74\x6d\x70\x2f\x54\x65' \ + + b'\x73\x74\x42\x6d\x70\x53\x75\x70\x70\x6f\x72\x74\x4c' \ + + b'\x69\x62\x2e\x69\x6e\x66\x20\x73\x68\x6f\x75\x6c\x64' \ + + b'\x20\x62\x65\x20\x73\x74\x61\x72\x74\x20\x77\x69\x74' \ + + b'\x68\x20\x2f\x72\x6f\x6f\x74\x2f\x68\x62\x66\x61\x5f' \ + + b'\x77\x6f\x72\x6b\x73\x70\x61\x63\x65\x2f\x65\x64\x6b' \ + + b'\x32\x2d\x73\x74\x61\x67\x69\x6e\x67\x2f\x48\x42\x46' \ + + b'\x41\x2e\x0a' + check_string = check_string.decode("ascii") + self.assertEqual(message, check_string) + + # Test bad value for module is handled (no value set) + @mock.patch('UefiHostTestTools.RunAFLTurbo.Build', return_value='') + @mock.patch('UefiHostTestTools.RunAFLTurbo.RunAFLTurbo', return_value='') + @mock.patch('UefiHostTestTools.RunAFLTurbo.CheckTestEnv', return_value='') + @mock.patch('UefiHostTestTools.RunAFLTurbo.HBFA_PATH', + '/root/hbfa_workspace/edk2-staging/HBFA') + @mock.patch('sys.argv', ['RunAFLTurbo.py', '-m', '', '-i', '/tmp/', '-o', + '/tmp/test', '-a', 'X64', '-c', 'rawcommand']) + @mock.patch('os._exit', sys.exit) + def test_args_bad_module_no_value(self, *args, **kwargs): + print("\n[+] Test bad value for module is handled (no value set)") + with io.StringIO() as buffer: + with contextlib.redirect_stdout(buffer): + with self.assertRaises(SystemExit): + UefiHostTestTools.RunAFLTurbo.main() + # Check against expected print string: + # ModuleFile path: /tmp/TestBmpSupportLib.inf should be + # start with /root/hbfa_workspace/edk2-staging/HBFA + message = buffer.getvalue() + check_string = b'\x4d\x6f\x64\x75\x6c\x65\x46\x69\x6c\x65\x20' \ + + b'\x73\x68\x6f\x75\x6c\x64\x20\x62\x65\x20\x73\x65\x74' \ + + b'\x20\x6f\x6e\x63\x65\x20\x62\x79\x20\x63\x6f\x6d\x6d' \ + + b'\x61\x6e\x64\x20\x2d\x6d\x20\x4d\x4f\x44\x55\x4c\x45' \ + + b'\x46\x49\x4c\x45\x2c\x20\x2d\x2d\x6d\x6f\x64\x75\x6c' \ + + b'\x65\x3d\x4d\x4f\x44\x55\x4c\x45\x46\x49\x4c\x45' \ + + b'\x2e\x0a' + check_string = check_string.decode("ascii") + self.assertEqual(message, check_string) + + # Test bad value for module is handled (file does not exist or is not + # in relative path) + @mock.patch('UefiHostTestTools.RunAFLTurbo.Build', return_value='') + @mock.patch('UefiHostTestTools.RunAFLTurbo.RunAFLTurbo', return_value='') + @mock.patch('UefiHostTestTools.RunAFLTurbo.CheckTestEnv', return_value='') + @mock.patch('UefiHostTestTools.RunAFLTurbo.HBFA_PATH', + '/root/hbfa_workspace/edk2-staging/HBFA') + @mock.patch('sys.argv', + ['RunAFLTurbo.py', '-m', + 'root/hbfa_workspace/edk2-staging/HBFA/test/test', + '-i', '/tmp/', '-o', '/tmp/test', '-a', 'X64', + '-c', 'rawcommand']) + @mock.patch('os._exit', sys.exit) + def test_args_bad_module_bad_value(self, *args, **kwargs): + print("\n+] Test bad value for module is handled (bad value set)") + with io.StringIO() as buffer: + with contextlib.redirect_stdout(buffer): + with self.assertRaises(SystemExit): + UefiHostTestTools.RunAFLTurbo.main() + # Check against expected print string: + # ModuleFile path: + # root/hbfa_workspace/edk2-staging/HBFA/test/test does + # not exist or is not in the relative path for HBFA + message = buffer.getvalue() + check_string = b'\x4d\x6f\x64\x75\x6c\x65\x46\x69\x6c\x65\x20' \ + + b'\x70\x61\x74\x68\x3a\x20\x72\x6f\x6f\x74\x2f\x68\x62' \ + + b'\x66\x61\x5f\x77\x6f\x72\x6b\x73\x70\x61\x63\x65\x2f' \ + + b'\x65\x64\x6b\x32\x2d\x73\x74\x61\x67\x69\x6e\x67\x2f' \ + + b'\x48\x42\x46\x41\x2f\x74\x65\x73\x74\x2f\x74\x65\x73' \ + + b'\x74\x20\x69\x73\x20\x6e\x6f\x20\x65\x78\x69\x74\x73' \ + + b'\x20\x6f\x72\x20\x6e\x6f\x74\x20\x74\x68\x65\x20\x72' \ + + b'\x65\x6c\x61\x74\x69\x76\x65\x20\x70\x61\x74\x68\x20' \ + + b'\x66\x6f\x72\x20\x48\x42\x46\x41\x0a' + check_string = check_string.decode("ascii") + self.assertEqual(message, check_string) + + # Test bad value for input seed path (no value/path) + @mock.patch('UefiHostTestTools.RunAFLTurbo.Build', return_value='') + @mock.patch('UefiHostTestTools.RunAFLTurbo.RunAFLTurbo', return_value='') + @mock.patch('UefiHostTestTools.RunAFLTurbo.CheckTestEnv', return_value='') + @mock.patch('UefiHostTestTools.RunAFLTurbo.HBFA_PATH', + '/root/hbfa_workspace/edk2-staging/HBFA') + @mock.patch('sys.argv', + ['RunAFLTurbo.py', '-m', + '/root/hbfa_workspace/edk2-staging/HBFA/' + + 'UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/' + + 'Library/BaseBmpSupportLib/TestBmpSupportLib.inf', + '-i', '', '-o', '/tmp/test', '-a', 'X64', '-c', + 'rawcommand']) + @mock.patch('os._exit', sys.exit) + def test_args_bad_input_seed_none(self, *args, **kwargs): + print("\n[+] Test bad value for input seed path is handled " + "(no value set)") + with io.StringIO() as buffer: + with contextlib.redirect_stdout(buffer): + with self.assertRaises(SystemExit): + UefiHostTestTools.RunAFLTurbo.main() + message = buffer.getvalue() + # Check against expected print string: + # InputSeed path should be set once by command -i INPUTSEED, + # --input=INPUTSEED. + check_string = b'\x49\x6e\x70\x75\x74\x53\x65\x65\x64\x20\x70' \ + + b'\x61\x74\x68\x20\x73\x68\x6f\x75\x6c\x64\x20\x62\x65' \ + + b'\x20\x73\x65\x74\x20\x6f\x6e\x63\x65\x20\x62\x79\x20' \ + + b'\x63\x6f\x6d\x6d\x61\x6e\x64\x20\x2d\x69\x20\x49\x4e' \ + + b'\x50\x55\x54\x53\x45\x45\x44\x2c\x20\x2d\x2d\x69\x6e' \ + + b'\x70\x75\x74\x3d\x49\x4e\x50\x55\x54\x53\x45\x45\x44' \ + + b'\x2e\x0a' + check_string = check_string.decode("ascii") + self.assertEqual(message, check_string) + + # Test bad value for input seed path (path does not exist) + @mock.patch('UefiHostTestTools.RunAFLTurbo.Build', return_value='') + @mock.patch('UefiHostTestTools.RunAFLTurbo.RunAFLTurbo', return_value='') + @mock.patch('UefiHostTestTools.RunAFLTurbo.CheckTestEnv', + return_value='') + @mock.patch('UefiHostTestTools.RunAFLTurbo.HBFA_PATH', + '/root/hbfa_workspace/edk2-staging/HBFA') + @mock.patch('sys.argv', + ['RunAFLTurbo.py', '-m', + '/root/hbfa_workspace/edk2-staging/HBFA/' + 'UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/' + 'Library/BaseBmpSupportLib/TestBmpSupportLib.inf', + '-o', '/tmp/', '-a', 'X64', + '-c', 'rawcommand', '-i', '/tmp/tmp/tmp/tmp']) + @mock.patch('os._exit', sys.exit) + def test_args_bad_input_seed_path(self, *args, **kwargs): + print("\n[+] Test bad value for input seed path is handled " + "(bad path, does not exist)") + with io.StringIO() as buffer: + with contextlib.redirect_stdout(buffer): + with self.assertRaises(SystemExit): + UefiHostTestTools.RunAFLTurbo.main() + message = buffer.getvalue() + # Check against expected print string: + # InputSeed path: /tmp/tmp/tmp/tmp does not exist + check_string = b'\x49\x6e\x70\x75\x74\x53\x65\x65\x64\x20\x70' \ + + b'\x61\x74\x68\x3a\x20\x2f\x74\x6d\x70\x2f\x74\x6d\x70' \ + + b'\x2f\x74\x6d\x70\x2f\x74\x6d\x70\x20\x69\x73\x20\x6e' \ + + b'\x6f\x20\x65\x78\x69\x73\x74\x73\x0a' + check_string = check_string.decode("ascii") + self.assertEqual(message, check_string) + + # Test bad value for output path (no argument) + @mock.patch('UefiHostTestTools.RunAFLTurbo.Build', return_value='') + @mock.patch('UefiHostTestTools.RunAFLTurbo.RunAFLTurbo', return_value='') + @mock.patch('UefiHostTestTools.RunAFLTurbo.CheckTestEnv', return_value='') + @mock.patch('UefiHostTestTools.RunAFLTurbo.HBFA_PATH', + '/root/hbfa_workspace/edk2-staging/HBFA') + @mock.patch('sys.argv', + ['RunAFLTurbo.py', '-m', + '/root/hbfa_workspace/edk2-staging/HBFA/' + 'UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/' + 'Library/BaseBmpSupportLib/TestBmpSupportLib.inf', + '-i', '/tmp/', '-o', '', '-a', 'X64', '-c', + 'rawcommand']) + @mock.patch('os._exit', sys.exit) + def test_args_bad_output_seed_none(self, *args, **kwargs): + print("\n[+]Test bad value for output seed path is handled " + "(no argument)") + with io.StringIO() as buffer: + with contextlib.redirect_stdout(buffer): + with self.assertRaises(SystemExit): + UefiHostTestTools.RunAFLTurbo.main() + message = buffer.getvalue() + # Check against expected print string: + # OutputSeed path should be set once by command -o OUTPUT, + # --output=OUTPUT. + check_string = b'\x4f\x75\x74\x70\x75\x74\x53\x65\x65\x64\x20' \ + + b'\x70\x61\x74\x68\x20\x73\x68\x6f\x75\x6c\x64\x20\x62' \ + + b'\x65\x20\x73\x65\x74\x20\x6f\x6e\x63\x65\x20\x62\x79' \ + + b'\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x20\x2d\x6f\x20\x4f' \ + + b'\x55\x54\x50\x55\x54\x2c\x20\x2d\x2d\x6f\x75\x74\x70' \ + + b'\x75\x74\x3d\x4f\x55\x54\x50\x55\x54\x2e\x0a' + check_string = check_string.decode("ascii") + self.assertEqual(message, check_string) + + # Test bad input value for command line mode (assuming we are on Linux) + @mock.patch('UefiHostTestTools.RunAFLTurbo.Build', return_value='') + @mock.patch('UefiHostTestTools.RunAFLTurbo.RunAFLTurbo', return_value='') + @mock.patch('UefiHostTestTools.RunAFLTurbo.CheckTestEnv', return_value='') + @mock.patch('UefiHostTestTools.RunAFLTurbo.HBFA_PATH', + '/root/hbfa_workspace/edk2-staging/HBFA') + @mock.patch('sys.argv', + ['RunAFLTurbo.py', '-m', + '/root/hbfa_workspace/edk2-staging/HBFA/' + 'UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/' + 'Library/BaseBmpSupportLib/TestBmpSupportLib.inf', + '-i', '/tmp/', '-o', '/tmp/test', '-a', 'X64', + '-c', 'gnome']) + @mock.patch('UefiHostTestTools.RunAFLTurbo.SysType', 'Linux') + @mock.patch('os._exit', sys.exit) + def test_args_bad_command_mode(self, *args, **kwargs): + print("\n[+]Test bad value for command line mode") + with io.StringIO() as buffer: + with contextlib.redirect_stderr(buffer): + with self.assertRaises(SystemExit): + UefiHostTestTools.RunAFLTurbo.main() + check_string = "invalid choice: 'gnome' (choose from " + \ + "'rawcommand', 'manual')" + self.assertIn(check_string, buffer.getvalue()) + print("\n[+]Testing bad value for arch: -a X65") + + +if __name__ == "__main__": + sys.path.append(os.path.join(os.path.dirname(__file__), '..')) + import UefiHostTestTools.RunAFLTurbo + unittest.main() diff --git a/HBFA/tests/TestRunKLEE.py b/HBFA/tests/TestRunKLEE.py new file mode 100644 index 0000000..aa3acf0 --- /dev/null +++ b/HBFA/tests/TestRunKLEE.py @@ -0,0 +1,188 @@ +#!/usr/bin/env python3 +import unittest +import os +import sys +import io +import contextlib +try: + from unittest import mock # python 3.3+ +except ImportError: + import mock # python 2.6-3.2 + + +class TestRunKLEE(unittest.TestCase): + + # Test bad value for arch is handled (-a 'X64') + @mock.patch('UefiHostTestTools.RunKLEE.Build', return_value='') + @mock.patch('UefiHostTestTools.RunKLEE.RunKLEE', return_value='') + @mock.patch('UefiHostTestTools.RunKLEE.CheckTestEnv', return_value='') + @mock.patch('UefiHostTestTools.RunKLEE.HBFA_PATH', + '/root/hbfa_workspace/edk2-staging/HBFA') + @mock.patch('sys.argv', + ['RunKLEE.py', '-m', '/root/hbfa_workspace/edk2-' + 'staging/HBFA/UefiHostFuzzTestCasePkg/TestCase' + '/MdeModulePkg/Library/BaseBmpSupportLib/' + 'TestBmpSupportLib.inf', '-o', + '/tmp/test', '-a', 'X65', '-c', 'rawcommand']) + def test_args_badarch(self, *args, **kwargs): + print("\n[+] Testing bad value for arch: -a X65") + with io.StringIO() as buffer: + with contextlib.redirect_stderr(buffer): + with self.assertRaises(SystemExit): + UefiHostTestTools.RunKLEE.main() + check_string = "argument -a/--arch: invalid choice: 'X65' " + \ + "(choose from 'IA32', 'X64', 'ARM', 'AARCH64')" + self.assertIn(check_string, buffer.getvalue()) + + # Test bad value for module is handled (not in HBFA_PATH) + @mock.patch('UefiHostTestTools.RunKLEE.Build', return_value='') + @mock.patch('UefiHostTestTools.RunKLEE.RunKLEE', return_value='') + @mock.patch('UefiHostTestTools.RunKLEE.CheckTestEnv', return_value='') + @mock.patch('UefiHostTestTools.RunKLEE.HBFA_PATH', + '/root/hbfa_workspace/edk2-staging/HBFA') + @mock.patch('sys.argv', + ['RunKLEE.py', '-m', '/tmp/TestBmpSupportLib.inf', + '-o', '/tmp/test', '-a', 'X64', + '-c', 'rawcommand']) + @mock.patch('os._exit', sys.exit) + def test_args_bad_module_hbfa_path(self, *args, **kwargs): + print("\n[+] Test bad value for module is handled (not in HBFA_PATH)") + with io.StringIO() as buffer: + with contextlib.redirect_stdout(buffer): + with self.assertRaises(SystemExit): + UefiHostTestTools.RunKLEE.main() + message = buffer.getvalue() + # Check against expected print string: + # ModuleFile path: /tmp/TestBmpSupportLib.inf should start + # with /root/hbfa_workspace/edk2-staging/HBFA. + check_string = b'\x4d\x6f\x64\x75\x6c\x65\x46\x69\x6c\x65\x20' \ + + b'\x70\x61\x74\x68\x3a\x20\x2f\x74\x6d\x70\x2f\x54\x65' \ + + b'\x73\x74\x42\x6d\x70\x53\x75\x70\x70\x6f\x72\x74\x4c' \ + + b'\x69\x62\x2e\x69\x6e\x66\x20\x73\x68\x6f\x75\x6c\x64' \ + + b'\x20\x62\x65\x20\x73\x74\x61\x72\x74\x20\x77\x69\x74' \ + + b'\x68\x20\x2f\x72\x6f\x6f\x74\x2f\x68\x62\x66\x61\x5f' \ + + b'\x77\x6f\x72\x6b\x73\x70\x61\x63\x65\x2f\x65\x64\x6b' \ + + b'\x32\x2d\x73\x74\x61\x67\x69\x6e\x67\x2f\x48\x42\x46' \ + + b'\x41\x2e\x0a' + check_string = "/tmp/TestBmpSupportLib.inf should start with " \ + + "/root/hbfa_workspace/edk2-staging/HBFA." + self.assertIn(check_string, message) + + # Test bad value for module is handled (no value set) + @mock.patch('UefiHostTestTools.RunKLEE.Build', return_value='') + @mock.patch('UefiHostTestTools.RunKLEE.RunKLEE', return_value='') + @mock.patch('UefiHostTestTools.RunKLEE.CheckTestEnv', return_value='') + @mock.patch('UefiHostTestTools.RunKLEE.HBFA_PATH', + '/root/hbfa_workspace/edk2-staging/HBFA') + @mock.patch('sys.argv', ['RunKLEE.py', '-m', '', '-o', + '/tmp/test', '-a', 'X64', '-c', 'rawcommand']) + @mock.patch('os._exit', sys.exit) + def test_args_bad_module_no_value(self, *args, **kwargs): + print("\n[+] Test bad value for module is handled (no value set)") + with io.StringIO() as buffer: + with contextlib.redirect_stdout(buffer): + with self.assertRaises(SystemExit): + UefiHostTestTools.RunKLEE.main() + # Check against expected print string: + # ModuleFile path: /tmp/TestBmpSupportLib.inf should be + # start with /root/hbfa_workspace/edk2-staging/HBFA + message = buffer.getvalue() + check_string = b'\x4d\x6f\x64\x75\x6c\x65\x46\x69\x6c\x65\x20' \ + + b'\x73\x68\x6f\x75\x6c\x64\x20\x62\x65\x20\x73\x65\x74' \ + + b'\x20\x6f\x6e\x63\x65\x20\x62\x79\x20\x63\x6f\x6d\x6d' \ + + b'\x61\x6e\x64\x20\x2d\x6d\x20\x4d\x4f\x44\x55\x4c\x45' \ + + b'\x46\x49\x4c\x45\x2c\x20\x2d\x2d\x6d\x6f\x64\x75\x6c' \ + + b'\x65\x3d\x4d\x4f\x44\x55\x4c\x45\x46\x49\x4c\x45' \ + + b'\x2e\x0a' + check_string = check_string.decode("ascii") + self.assertEqual(message, check_string) + + # Test bad value for module is handled (file does not exist or is not + # in relative path) + @mock.patch('UefiHostTestTools.RunKLEE.Build', return_value='') + @mock.patch('UefiHostTestTools.RunKLEE.RunKLEE', return_value='') + @mock.patch('UefiHostTestTools.RunKLEE.CheckTestEnv', return_value='') + @mock.patch('UefiHostTestTools.RunKLEE.HBFA_PATH', + '/root/hbfa_workspace/edk2-staging/HBFA') + @mock.patch('sys.argv', + ['RunKLEE.py', '-m', + 'root/hbfa_workspace/edk2-staging/HBFA/test/test', + '-o', '/tmp/test', '-a', 'X64', + '-c', 'rawcommand']) + @mock.patch('os._exit', sys.exit) + def test_args_bad_module_bad_value(self, *args, **kwargs): + print("\n[+] Test bad value for module is handled (bad value set)") + with io.StringIO() as buffer: + with contextlib.redirect_stdout(buffer): + with self.assertRaises(SystemExit): + UefiHostTestTools.RunKLEE.main() + message = buffer.getvalue() + check_string = "root/hbfa_workspace/edk2-staging/HBFA/test/test" \ + + " does not exist or is not in the relative" \ + + " path for HBFA" + self.assertIn(check_string, message) + + # Test bad value for output path (no argument) + @mock.patch('UefiHostTestTools.RunKLEE.Build', return_value='') + @mock.patch('UefiHostTestTools.RunKLEE.RunKLEE', return_value='') + @mock.patch('UefiHostTestTools.RunKLEE.CheckTestEnv', return_value='') + @mock.patch('UefiHostTestTools.RunKLEE.HBFA_PATH', + '/root/hbfa_workspace/edk2-staging/HBFA') + @mock.patch('sys.argv', + ['RunKLEE.py', '-m', + '/root/hbfa_workspace/edk2-staging/HBFA/' + 'UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/' + 'Library/BaseBmpSupportLib/TestBmpSupportLib.inf', + '-o', '', '-a', 'X64', '-c', + 'rawcommand']) + @mock.patch('os._exit', sys.exit) + def test_args_bad_output_seed_none(self, *args, **kwargs): + print("\n[+]Test bad value for output seed path is handled " + "(no argument)") + with io.StringIO() as buffer: + with contextlib.redirect_stdout(buffer): + with self.assertRaises(SystemExit): + UefiHostTestTools.RunKLEE.main() + message = buffer.getvalue() + # Check against expected print string: + # OutputSeed path should be set once by command -o OUTPUT, + # --output=OUTPUT. + check_string = b'\x4f\x75\x74\x70\x75\x74\x53\x65\x65\x64\x20' \ + + b'\x70\x61\x74\x68\x20\x73\x68\x6f\x75\x6c\x64\x20\x62' \ + + b'\x65\x20\x73\x65\x74\x20\x6f\x6e\x63\x65\x20\x62\x79' \ + + b'\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x20\x2d\x6f\x20\x4f' \ + + b'\x55\x54\x50\x55\x54\x2c\x20\x2d\x2d\x6f\x75\x74\x70' \ + + b'\x75\x74\x3d\x4f\x55\x54\x50\x55\x54\x2e\x0a' + check_string = check_string.decode("ascii") + self.assertEqual(message, check_string) + + # Test bad input value for command line mode (assuming we are on Linux) + @mock.patch('UefiHostTestTools.RunKLEE.Build', return_value='') + @mock.patch('UefiHostTestTools.RunKLEE.RunKLEE', return_value='') + @mock.patch('UefiHostTestTools.RunKLEE.CheckTestEnv', return_value='') + @mock.patch('UefiHostTestTools.RunKLEE.HBFA_PATH', + '/root/hbfa_workspace/edk2-staging/HBFA') + @mock.patch('sys.argv', + ['RunKLEE.py', '-m', + '/root/hbfa_workspace/edk2-staging/HBFA/' + 'UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/' + 'Library/BaseBmpSupportLib/TestBmpSupportLib.inf', + '-o', '/tmp/test/test/test/test', '-a', 'X64', + '-c', 'gnome']) + @mock.patch('UefiHostTestTools.RunKLEE.SysType', 'Linux') + @mock.patch('os._exit', sys.exit) + def test_args_bad_command_mode(self, *args, **kwargs): + print("\n[+]Test bad value for command line mode") + with io.StringIO() as buffer: + with contextlib.redirect_stderr(buffer): + with self.assertRaises(SystemExit): + UefiHostTestTools.RunKLEE.main() + check_string = "invalid choice: 'gnome' (choose from " + \ + "'rawcommand', 'manual')" + self.assertIn(check_string, buffer.getvalue()) + + +if __name__ == "__main__": + sys.path.append(os.path.join(os.path.dirname(__file__), '..')) + import UefiHostTestTools.RunKLEE + unittest.main() diff --git a/HBFA/tests/TestRunLibFuzzer.py b/HBFA/tests/TestRunLibFuzzer.py new file mode 100644 index 0000000..abae500 --- /dev/null +++ b/HBFA/tests/TestRunLibFuzzer.py @@ -0,0 +1,263 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +import unittest +import os +import sys +import io +import contextlib +try: + from unittest import mock # python 3.3+ +except ImportError: + import mock # python 2.6-3.2 + + +class TestRunLibFuzzer(unittest.TestCase): + + # Test bad value for arch is handled (-a 'X64') + @mock.patch('UefiHostTestTools.RunLibFuzzer.Build', return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.RunLibFuzzer', + return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.CheckTestEnv', + return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.updateBuildFlags', + return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.restoreBuildOptionFile', + return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.HBFA_PATH', + '/root/hbfa_workspace/edk2-staging/HBFA') + @mock.patch('sys.argv', ['RunLibFuzzer.py', '-m', + '/root/hbfa_workspace/edk2-' + 'staging/HBFA/UefiHostFuzzTestCasePkg/TestCase' + '/MdeModulePkg/Library/BaseBmpSupportLib/' + 'TestBmpSupportLib.inf', '-i', '/tmp/', '-o', + '/tmp/test', '-a', 'X65', '-c', 'rawcommand']) + def test_args_badarch(self, *args, **kwargs): + print("\n[+]Testing bad value for arch: -a X65") + with io.StringIO() as buffer: + with contextlib.redirect_stderr(buffer): + with self.assertRaises(SystemExit): + UefiHostTestTools.RunLibFuzzer.main() + check_string = "argument -a/--arch: invalid choice: 'X65' " + \ + "(choose from 'IA32', 'X64', 'ARM', 'AARCH64')" + self.assertIn(check_string, buffer.getvalue()) + + # Test bad value for module is handled (not in HBFA_PATH) + @mock.patch('UefiHostTestTools.RunLibFuzzer.Build', return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.RunLibFuzzer', + return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.CheckTestEnv', + return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.updateBuildFlags', + return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.restoreBuildOptionFile', + return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.HBFA_PATH', + '/root/hbfa_workspace/edk2-staging/HBFA') + @mock.patch('sys.argv', ['RunLibFuzzer.py', '-m', + '/tmp/TestBmpSupportLib.inf', '-i', '/tmp/', + '-o', '/tmp/test', '-a', 'X64', + '-c', 'rawcommand']) + @mock.patch('os._exit', sys.exit) + def test_args_bad_module_hbfa_path(self, *args, **kwargs): + print("\n[+]Test bad value for module is handled (not in HBFA_PATH)") + with io.StringIO() as buffer: + with contextlib.redirect_stdout(buffer): + with self.assertRaises(SystemExit): + UefiHostTestTools.RunLibFuzzer.main() + message = buffer.getvalue() + # Check against expected print string: + # ModuleFile path: /tmp/TestBmpSupportLib.inf should start + # with /root/hbfa_workspace/edk2-staging/HBFA. + check_string = b'\x4d\x6f\x64\x75\x6c\x65\x46\x69\x6c\x65\x20' \ + + b'\x70\x61\x74\x68\x3a\x20\x2f\x74\x6d\x70\x2f\x54\x65' \ + + b'\x73\x74\x42\x6d\x70\x53\x75\x70\x70\x6f\x72\x74\x4c' \ + + b'\x69\x62\x2e\x69\x6e\x66\x20\x73\x68\x6f\x75\x6c\x64' \ + + b'\x20\x73\x74\x61\x72\x74\x20\x77\x69\x74\x68\x20\x2f' \ + + b'\x72\x6f\x6f\x74\x2f\x68\x62\x66\x61\x5f\x77\x6f\x72' \ + + b'\x6b\x73\x70\x61\x63\x65\x2f\x65\x64\x6b\x32\x2d\x73' \ + + b'\x74\x61\x67\x69\x6e\x67\x2f\x48\x42\x46\x41\x2e\x0a' + check_string = check_string.decode("ascii") + self.assertEqual(message, check_string) + + # Test bad value for module is handled (no value set) + @mock.patch('UefiHostTestTools.RunLibFuzzer.Build', return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.RunLibFuzzer', + return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.CheckTestEnv', + return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.updateBuildFlags', + return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.restoreBuildOptionFile', + return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.HBFA_PATH', + '/root/hbfa_workspace/edk2-staging/HBFA') + @mock.patch('sys.argv', ['RunLibFuzzer.py', '-m', '', '-i', '/tmp/', '-o', + '/tmp/test', '-a', 'X64', '-c', 'rawcommand']) + @mock.patch('os._exit', sys.exit) + def test_args_bad_module_no_value(self, *args, **kwargs): + print("\n[+]Test bad value for module is handled (no value set)") + with io.StringIO() as buffer: + with contextlib.redirect_stdout(buffer): + with self.assertRaises(SystemExit): + UefiHostTestTools.RunLibFuzzer.main() + # Check against expected print string: + # ModuleFile path: /tmp/TestBmpSupportLib.inf should be + # start with /root/hbfa_workspace/edk2-staging/HBFA + message = buffer.getvalue() + check_string = b'\x4d\x6f\x64\x75\x6c\x65\x46\x69\x6c\x65\x20' \ + + b'\x73\x68\x6f\x75\x6c\x64\x20\x62\x65\x20\x73\x65\x74' \ + + b'\x20\x6f\x6e\x63\x65\x20\x62\x79\x20\x63\x6f\x6d\x6d' \ + + b'\x61\x6e\x64\x20\x2d\x6d\x20\x4d\x4f\x44\x55\x4c\x45' \ + + b'\x46\x49\x4c\x45\x2c\x20\x2d\x2d\x6d\x6f\x64\x75\x6c' \ + + b'\x65\x3d\x4d\x4f\x44\x55\x4c\x45\x46\x49\x4c\x45' \ + + b'\x2e\x0a' + check_string = check_string.decode("ascii") + self.assertEqual(message, check_string) + + # Test bad value for module is handled (file does not exist or is not + # in relative path) + @mock.patch('UefiHostTestTools.RunLibFuzzer.Build', return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.RunLibFuzzer', + return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.CheckTestEnv', + return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.updateBuildFlags', + return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.restoreBuildOptionFile', + return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.HBFA_PATH', + '/root/hbfa_workspace/edk2-staging/HBFA') + @mock.patch('sys.argv', + ['RunLibFuzzer.py', '-m', + 'root/hbfa_workspace/edk2-staging/HBFA/test/test', + '-i', '/tmp/', '-o', '/tmp/test', '-a', 'X64', + '-c', 'rawcommand']) + @mock.patch('os._exit', sys.exit) + def test_args_bad_module_bad_value(self, *args, **kwargs): + print("\n[+]Test bad value for module is handled (bad value set)") + with io.StringIO() as buffer: + with contextlib.redirect_stdout(buffer): + with self.assertRaises(SystemExit): + UefiHostTestTools.RunLibFuzzer.main() + # Check against expected print string: + # ModuleFile path: + # ModuleFile path: /tmp does not exist or is not in the + # relative path for HBFA + message = buffer.getvalue() + check_string = b'\x4d\x6f\x64\x75\x6c\x65\x46\x69\x6c\x65\x20' \ + + b'\x70\x61\x74\x68\x3a\x20\x2f\x74\x6d\x70\x20\x64\x6f' \ + + b'\x65\x73\x20\x6e\x6f\x74\x20\x65\x78\x69\x73\x74\x20' \ + + b'\x6f\x72\x20\x69\x73\x20\x6e\x6f\x74\x20\x69\x6e\x20' \ + + b'\x74\x68\x65\x20\x72\x65\x6c\x61\x74\x69\x76\x65\x20' \ + + b'\x70\x61\x74\x68\x20\x66\x6f\x72\x20\x48\x42\x46\x41' \ + + b'\x0a' + check_string = check_string.decode("ascii") + self.assertEqual(message, check_string) + + # Test bad input value for command line mode (assuming we are on Linux) + @mock.patch('UefiHostTestTools.RunLibFuzzer.Build', return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.RunLibFuzzer', + return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.CheckTestEnv', + return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.updateBuildFlags', + return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.restoreBuildOptionFile', + return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.HBFA_PATH', + '/root/hbfa_workspace/edk2-staging/HBFA') + @mock.patch('sys.argv', + ['RunLibFuzzer.py', '-m', + '/root/hbfa_workspace/edk2-staging/HBFA/' + 'UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/' + 'Library/BaseBmpSupportLib/TestBmpSupportLib.inf', + '-i', '/tmp/', '-o', '/tmp/test', '-a', 'X64', + '-c', 'gnome']) + @mock.patch('UefiHostTestTools.RunLibFuzzer.SysType', 'Linux') + @mock.patch('os._exit', sys.exit) + def test_args_bad_command_mode(self, *args, **kwargs): + print("\n[+]Test bad value for command line mode") + with io.StringIO() as buffer: + with contextlib.redirect_stderr(buffer): + with self.assertRaises(SystemExit): + UefiHostTestTools.RunLibFuzzer.main() + check_string = "argument -c/--commandline: invalid choice:" + \ + " 'gnome' (choose from 'rawcommand', 'manual')" + self.assertIn(check_string, buffer.getvalue()) + + # Test bad value for -p profraw (not True, true, T, or t) + @mock.patch('UefiHostTestTools.RunLibFuzzer.Build', return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.RunLibFuzzer', + return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.CheckTestEnv', + return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.updateBuildFlags', + return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.restoreBuildOptionFile', + return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.HBFA_PATH', + '/root/hbfa_workspace/edk2-staging/HBFA') + @mock.patch('os._exit', sys.exit) + @mock.patch('sys.argv', ['RunLibFuzzer.py', '-m', + '/root/hbfa_workspace/edk2-' + 'staging/HBFA/UefiHostFuzzTestCasePkg/TestCase' + '/MdeModulePkg/Library/BaseBmpSupportLib/' + 'TestBmpSupportLib.inf', '-i', '/tmp/', '-o', + '/tmp/test', '-a', 'X64', '-c', 'rawcommand', + '-p', 'ABCD']) + def test_args_bad_profraw(self, *args, **kwargs): + print("\n[+]Testing bad value for -p profraw (not True, true, " + "T, or t)") + with io.StringIO() as buffer: + with contextlib.redirect_stderr(buffer): + with self.assertRaises(SystemExit): + UefiHostTestTools.RunLibFuzzer.main() + check_string = "argument -p/--gen-profraw: invalid choice: " + \ + "'ABCD' (choose from 't', 'T', 'true', " + \ + "'True', 'F', 'false', 'False')" + self.assertIn(check_string, buffer.getvalue()) + + # Test bad value for -s sanitizer (give a wrong value) + @mock.patch('UefiHostTestTools.RunLibFuzzer.Build', return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.RunLibFuzzer', + return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.CheckTestEnv', + return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.updateBuildFlags', + return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.restoreBuildOptionFile', + return_value='') + @mock.patch('UefiHostTestTools.RunLibFuzzer.HBFA_PATH', + '/root/hbfa_workspace/edk2-staging/HBFA') + @mock.patch('os._exit', sys.exit) + @mock.patch('sys.argv', ['RunLibFuzzer.py', '-m', + '/root/hbfa_workspace/edk2-' + 'staging/HBFA/UefiHostFuzzTestCasePkg/TestCase' + '/MdeModulePkg/Library/BaseBmpSupportLib/' + 'TestBmpSupportLib.inf', '-i', '/tmp/', '-o', + '/tmp/test', '-a', 'X64', '-c', 'rawcommand', + '-p', 'T', '-s', 'abcd']) + def test_args_bad_sanitizer(self, *args, **kwargs): + print("\n[+]Testing bad value for -s sanitizer ('abcd')") + with io.StringIO() as buffer: + with contextlib.redirect_stdout(buffer): + with self.assertRaises(SystemExit): + UefiHostTestTools.RunLibFuzzer.main() + # Check against expected error string: + # [!] Unsupported sanitizer provided in option -s: [ abcd ] + check_string = b'\x5b\x21\x5d\x20\x55\x6e\x73\x75\x70\x70\x6f' \ + + b'\x72\x74\x65\x64\x20\x73\x61\x6e\x69\x74\x69\x7a\x65' \ + + b'\x72\x20\x70\x72\x6f\x76\x69\x64\x65\x64\x20\x69\x6e' \ + + b'\x20\x6f\x70\x74\x69\x6f\x6e\x20\x2d\x73\x3a\x20\x5b' \ + + b'\x20\x61\x62\x63\x64\x20\x5d\x0a' + check_string = check_string.decode("ascii") + self.assertIn(check_string, buffer.getvalue()) + + +if __name__ == "__main__": + sys.path.append(os.path.join(os.path.dirname(__file__), '..')) + import UefiHostTestTools.RunLibFuzzer + unittest.main() diff --git a/HBFA/tests/__init__.py b/HBFA/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..e69b085 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,23 @@ +# BSD-2-Clause Plus Patent License + +Note: This license is designed to provide: a) a simple permissive license; b) that is compatible with the GNU General Public License (GPL), version 2; and c) which also has an express patent grant included. + +Copyright (c) 2024, Intel Corporation + +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. + +Subject to the terms and conditions of this license, each copyright holder and contributor hereby grants to those receiving rights under this license a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except for failure to satisfy the conditions of this license) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer this software, where such license applies only to those patent claims, already acquired or hereafter acquired, licensable by such copyright holder or contributor that are necessarily infringed by: + +(a) their Contribution(s) (the licensed copyrights of copyright holders and non-copyrightable additions of contributors, in source or binary form) alone; or + +(b) combination of their Contribution(s) with the work of authorship to which such Contribution(s) was added by such copyright holder or contributor, if, at the time the Contribution is added, such addition causes such combination to be necessarily infringed. The patent license shall not apply to any other combinations which include the Contribution. + +Except as expressly stated above, no rights or licenses from any copyright holder or contributor is granted under this license, whether expressly, by implication, estoppel or otherwise. + +DISCLAIMER + +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 HOLDERS 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/README.md b/README.md new file mode 100644 index 0000000..ee389ac --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# Host-based Firmware Analyzer - Fuzzing Lite (HBFA-FL) + +The the Host-based Firmware Analysis - Fuzzing Lite (HBFA-FL) is based off of forking the original HBFA from the [edk2-staging repository](https://github.com/tianocore/edk2-staging/tree/HBFA). The original release of HBFA is described in the white-paper: ["Using Host-based Firmware Analysis to Improve Platform Resiliency"](https://www.intel.com/content/dam/develop/external/us/en/documents/intel-usinghbfatoimproveplatformresiliency-820238.pdf). The original release authors were Brian Richardson, Chris Wu, Jiewen Yao, and Vincent J. Zimmer. + +The goal for HBFA-FL is to update the original codebase, enhancing some features and removing/streamlining some others, with a focus on functionality for Linux environments. To that end, HBFA-FL removes much of the original HBFA code base, including support for Windows and unit-testing; we retain support for fuzzing with AFL and LibFuzzer. This repository is effectively a fork from the original version of HBFA at this commit : [ead8f4f8eefdb2eb762184e1a5809c43d6908952](https://github.com/tianocore/edk2-staging/commit/ead8f4f8eefdb2eb762184e1a5809c43d6908952) + +## Getting Started + +To get started using HBFA-FL, we recommend taking a look at the documentation, starting [here](./docs/src/SUMMARY.md). diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000..e9c0728 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1 @@ +book \ No newline at end of file diff --git a/docs/book.toml b/docs/book.toml new file mode 100644 index 0000000..7a42fb6 --- /dev/null +++ b/docs/book.toml @@ -0,0 +1,6 @@ +[book] +authors = ["el-tipton"] +language = "en" +multilingual = False +src = "src" +title = "HBFA-FL: Host-Based Firmware Analyzer - Fuzzing Lite" \ No newline at end of file diff --git a/docs/images/Step3_Select_Boot_Manager.png b/docs/images/Step3_Select_Boot_Manager.png new file mode 100644 index 0000000..0fa3378 Binary files /dev/null and b/docs/images/Step3_Select_Boot_Manager.png differ diff --git a/docs/images/Step4_Select_EFI_Shell.png b/docs/images/Step4_Select_EFI_Shell.png new file mode 100644 index 0000000..c9ff665 Binary files /dev/null and b/docs/images/Step4_Select_EFI_Shell.png differ diff --git a/docs/images/Step5_EFI_Shell_Press_Escape.png b/docs/images/Step5_EFI_Shell_Press_Escape.png new file mode 100644 index 0000000..3c3ab49 Binary files /dev/null and b/docs/images/Step5_EFI_Shell_Press_Escape.png differ diff --git a/docs/images/Ubuntu_boot_select_firmware_settings.png b/docs/images/Ubuntu_boot_select_firmware_settings.png new file mode 100644 index 0000000..6bf800b Binary files /dev/null and b/docs/images/Ubuntu_boot_select_firmware_settings.png differ diff --git a/docs/images/hbfa_covreport.png b/docs/images/hbfa_covreport.png new file mode 100644 index 0000000..f9d718b Binary files /dev/null and b/docs/images/hbfa_covreport.png differ diff --git a/docs/images/hbfa_covreport2.png b/docs/images/hbfa_covreport2.png new file mode 100644 index 0000000..4713d11 Binary files /dev/null and b/docs/images/hbfa_covreport2.png differ diff --git a/docs/images/hbfa_crash_AAA.png b/docs/images/hbfa_crash_AAA.png new file mode 100644 index 0000000..e0edc17 Binary files /dev/null and b/docs/images/hbfa_crash_AAA.png differ diff --git a/docs/images/hbfa_crashes.png b/docs/images/hbfa_crashes.png new file mode 100644 index 0000000..246c1bf Binary files /dev/null and b/docs/images/hbfa_crashes.png differ diff --git a/docs/images/hbfa_hangs.png b/docs/images/hbfa_hangs.png new file mode 100644 index 0000000..b9984b2 Binary files /dev/null and b/docs/images/hbfa_hangs.png differ diff --git a/docs/images/hbfa_helloworld_AAAAs.png b/docs/images/hbfa_helloworld_AAAAs.png new file mode 100644 index 0000000..d38ba2a Binary files /dev/null and b/docs/images/hbfa_helloworld_AAAAs.png differ diff --git a/docs/images/hbfa_helloworld_debug_Acrash1.png b/docs/images/hbfa_helloworld_debug_Acrash1.png new file mode 100644 index 0000000..37b8ace Binary files /dev/null and b/docs/images/hbfa_helloworld_debug_Acrash1.png differ diff --git a/docs/images/hbfa_helloworld_debug_Acrash2.png b/docs/images/hbfa_helloworld_debug_Acrash2.png new file mode 100644 index 0000000..59851c0 Binary files /dev/null and b/docs/images/hbfa_helloworld_debug_Acrash2.png differ diff --git a/docs/images/hbfa_helloworld_debug_Acrash3.png b/docs/images/hbfa_helloworld_debug_Acrash3.png new file mode 100644 index 0000000..bdb6b39 Binary files /dev/null and b/docs/images/hbfa_helloworld_debug_Acrash3.png differ diff --git a/docs/images/hbfa_helloworld_extended.png b/docs/images/hbfa_helloworld_extended.png new file mode 100644 index 0000000..375485c Binary files /dev/null and b/docs/images/hbfa_helloworld_extended.png differ diff --git a/docs/images/hbfa_helloworld_list.png b/docs/images/hbfa_helloworld_list.png new file mode 100644 index 0000000..ff891e6 Binary files /dev/null and b/docs/images/hbfa_helloworld_list.png differ diff --git a/docs/images/hbfa_helloworld_list2.png b/docs/images/hbfa_helloworld_list2.png new file mode 100644 index 0000000..f2dbdac Binary files /dev/null and b/docs/images/hbfa_helloworld_list2.png differ diff --git a/docs/images/hbfa_helloworld_reprocrash.png b/docs/images/hbfa_helloworld_reprocrash.png new file mode 100644 index 0000000..826e8f5 Binary files /dev/null and b/docs/images/hbfa_helloworld_reprocrash.png differ diff --git a/docs/images/hbfa_shell_helloworld.png b/docs/images/hbfa_shell_helloworld.png new file mode 100644 index 0000000..44574ec Binary files /dev/null and b/docs/images/hbfa_shell_helloworld.png differ diff --git a/docs/images/hbfa_shell_ls.png b/docs/images/hbfa_shell_ls.png new file mode 100644 index 0000000..7b85c00 Binary files /dev/null and b/docs/images/hbfa_shell_ls.png differ diff --git a/docs/images/hbfa_shell_map.png b/docs/images/hbfa_shell_map.png new file mode 100644 index 0000000..1f1ce19 Binary files /dev/null and b/docs/images/hbfa_shell_map.png differ diff --git a/docs/images/hbfa_source_UefiHostTestPkg.dsc.png b/docs/images/hbfa_source_UefiHostTestPkg.dsc.png new file mode 100644 index 0000000..cc5a454 Binary files /dev/null and b/docs/images/hbfa_source_UefiHostTestPkg.dsc.png differ diff --git a/docs/images/hbfa_source_helloworld.c.png b/docs/images/hbfa_source_helloworld.c.png new file mode 100644 index 0000000..64ecedf Binary files /dev/null and b/docs/images/hbfa_source_helloworld.c.png differ diff --git a/docs/images/hbfa_source_testhelloworld.c.png b/docs/images/hbfa_source_testhelloworld.c.png new file mode 100644 index 0000000..ca3eefc Binary files /dev/null and b/docs/images/hbfa_source_testhelloworld.c.png differ diff --git a/docs/images/hbfa_summary.png b/docs/images/hbfa_summary.png new file mode 100644 index 0000000..21851a6 Binary files /dev/null and b/docs/images/hbfa_summary.png differ diff --git a/docs/src/README.md b/docs/src/README.md new file mode 100644 index 0000000..9bd9219 --- /dev/null +++ b/docs/src/README.md @@ -0,0 +1,31 @@ +# Introduction + +The Host-based Firmware Analyzer - Fuzzing Lite (HBFA-FL) is based off of forking the original HBFA from the [edk2-staging repository](https://github.com/tianocore/edk2-staging/tree/HBFA). The original release of HBFA is described in the white-paper: ["Using Host-based Firmware Analysis to Improve Platform Resiliency"](https://www.intel.com/content/dam/develop/external/us/en/documents/intel-usinghbfatoimproveplatformresiliency-820238.pdf). The original release authors were Brian Richardson, Chris Wu, Jiewen Yao, and Vincent J. Zimmer. + +The goal for HBFA-FL is to update the original codebase, enhancing some features and removing/streamlining some others, with a focus on functionality for Linux environments. To that end, HBFA-FL removes much of the original HBFA code base, including support for Windows and unit-testing; we retain support for fuzzing with AFL and LibFuzzer. This repository is effectively a fork from the original version of HBFA at this commit : [ead8f4f8eefdb2eb762184e1a5809c43d6908952](https://github.com/tianocore/edk2-staging/commit/ead8f4f8eefdb2eb762184e1a5809c43d6908952) + +## Version + +The most recent release for HBFA-FL is version 0.11. The release is an initial release with a focus on functionality modern Linux, for AFL and LibFuzzer fuzzing support, and enabling additional sanitizers and coverage options for HBFA. + +### Supported Features + +- Command-line interfaces to support building and running of fuzzing +- Execute fuzzing harnesses from common fuzzing frameworks (e.g. AFL and LibFuzzer) +- Incorporation of Address Sanitizer (ASAN), Memory Sanitizer (MSAN), and the Undefined Behavior Sanitizer (UBSAN) +- Generating code coverage reports (GCOV/LCOV and Profraw) + +### Features Not Fully Implemented + +- Support for symbolic execution with KLEE/STP with HBFA-FL has not yet been fully updated. + +### Features Not Supported from the Original HBFA + +- Windows support has been removed +- GUI support has been removed + +## Getting Started + +To get started using HBFA-FL, we recommend taking a look at the documentation, starting [here](./SUMMARY.md). + +Return to [Summary](./SUMMARY.md) | Next [>>](./setup/README.md) diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md new file mode 100644 index 0000000..6db0893 --- /dev/null +++ b/docs/src/SUMMARY.md @@ -0,0 +1,21 @@ +# Summary + +[Introduction](README.md) + +## User Guide + +- [Setting Up](setup/README.md) + - [For Linux](setup/linux.md) +- [Getting started with fuzzing in HBFA-FL](fuzzing/README.md) + - [Where to create and save a fuzzing test case harness](harness/wheretoharness.md) + - [Creating and Compiling New Test Cases](fuzzing/building.md) + - [Fuzzing test harnesses included with HBFA-FL](harness/includedfuzzharnesses.md) + - [Fuzzing with AFL: RunAFL.py](fuzzingwithAFL.md) + - [Fuzzing with LibFuzzer: RunLibFuzzer.py](./fuzzingwithLibFuzzer.md) + - [Generating fuzzing summary and coverage data reports](./generatingCoverageReports.md) +- [Tutorials](tutorials/README.md) + - [HBFA-FL: Writing a fuzzing harness](tutorials/writingafuzzingharness.md) + +## Archived Documentation + +- [Original HBFA Documentation](archive/originalHBFA/README.md) \ No newline at end of file diff --git a/docs/src/archive/originalHBFA/Doc/User Guide - How-to-Add-New-Case.pdf b/docs/src/archive/originalHBFA/Doc/User Guide - How-to-Add-New-Case.pdf new file mode 100644 index 0000000..61b2009 Binary files /dev/null and b/docs/src/archive/originalHBFA/Doc/User Guide - How-to-Add-New-Case.pdf differ diff --git a/docs/src/archive/originalHBFA/Doc/User Guide - How-to-Run-Test-Case.pdf b/docs/src/archive/originalHBFA/Doc/User Guide - How-to-Run-Test-Case.pdf new file mode 100644 index 0000000..5443a02 Binary files /dev/null and b/docs/src/archive/originalHBFA/Doc/User Guide - How-to-Run-Test-Case.pdf differ diff --git a/docs/src/archive/originalHBFA/README.md b/docs/src/archive/originalHBFA/README.md new file mode 100644 index 0000000..edd6e87 --- /dev/null +++ b/docs/src/archive/originalHBFA/README.md @@ -0,0 +1,11 @@ +# Archive for documentation + +Several documents related to HBFA are referenced externally or archived locally in this repository in this folder. A Table of these documents is included in the following. + +| Document | Reference link | +| -------- | -------------- | +| The original HBFA release in the whitepaper | [Link](https://www.intel.com/content/dam/develop/external/us/en/documents/intel-usinghbfatoimproveplatformresiliency-820238.pdf) | +| The original HBFA 'User Guide - How-to-Add-New-Case.pdf' | [Link](./Doc/User%20Guide%20-%20How-to-Add-New-Case.pdf) | + + +Return to [Summary](../../SUMMARY.md) \ No newline at end of file diff --git a/docs/src/fuzzing/README.md b/docs/src/fuzzing/README.md new file mode 100644 index 0000000..bdd4a73 --- /dev/null +++ b/docs/src/fuzzing/README.md @@ -0,0 +1,12 @@ +# Getting started with fuzzing in HBFA-FL + +Fuzzing with AFL and LibFuzzer are supported in HBFA-FL. For a given test-harness, the source can be compiled and fuzzed with either AFL or LibFuzzer. To do this, you may directly invoke the build process from EDK-II or you may leverage the included 'RunAFL.py' and 'RunLibFuzzer.py' scripts (recommended). Additionally, several fuzzing test-harnesses are included with HBFA-FL and can be helpful for fuzzing, or as a good reference for developing other fuzzing harnesses. + +- For information on creating and building test cases, see these sections: [Where to create and save a fuzzing test case harness](../harness/wheretoharness.md) and [Creating and Compiling New Test Cases](./building.md) +- For a full-tutorial on creating fuzzing harnesses for HBFA-FL, see the tutorial [HBFA-FL: Writing a fuzzing harness](../tutorials/writingafuzzingharness.md) +- For more information on the fuzzing test-harnesses included with HBFA-FL, see this [section](../harness/includedfuzzharnesses.md) +- To get started fuzzing with AFL, see [Fuzzing with AFL](fuzzingwithAFL.md) +- To get started fuzzing with LibFuzzer, see [Fuzzing with LibFuzzer](./fuzzingwithLibFuzzer.md) +- To learn more on how to generate Fuzzing Report and Coverage data for your fuzzing, see [Generating fuzzing summary and coverage data reports](./generatingCoverageReports.md) + +[<<](../setup/linux.md) Back | Return to [Summary](../SUMMARY.md) | Next [>>](./building.md) \ No newline at end of file diff --git a/docs/src/fuzzing/building.md b/docs/src/fuzzing/building.md new file mode 100644 index 0000000..cab4f11 --- /dev/null +++ b/docs/src/fuzzing/building.md @@ -0,0 +1,32 @@ +# Creating and Compiling New Test Cases + +The original HBFA documentation provides some helpful information on how to to about adding new test cases/harnesses. For more information, see [Host-based Firmware Analyzer User Guide: How to Add New Case](https://github.com/tianocore/edk2-staging/blob/HBFA/HBFA/Doc/User%20Guide%20-%20How-to-Add-New-Case.pdf). Further, a [tutorial](../tutorials/writingafuzzingharness.md) is included in HBFA-FL, which gives details on creating a fuzzing test harness for a vulnerable (fictitious) testHelloWorld UEFI shell program. + +## Compiling Test Cases + +The recommended approach with HBFA is to use the included RunAFL.py and RunLibFuzzer.py scripts. These scripts will invoke the build commands needed (see the sections: [Using RunAFL.py to build and fuzzing a module](#b-using-runaflpy-to-build-and-fuzzing-a-module) and [Using LibFuzzer.py to build and fuzzing a module](#b-using-libfuzzerpy-to-build-and-fuzzing-a-module). However, one can directly invoke the build system in EDK-II. + +For building a test module in EDK-II, some of the important files used in the HBFA environment are described in the following. (Noting, the file paths are releative to the base of the edk2 repository.) + +| Filename | Description | +| -------- | ----------- | +| edk2/BaseTools/BinWrappers/PosixLike/build | When invoking 'build' from the CLI in HBFA, this Bash script is ran and acts as a wrapper to invoke a Python-based build script 'build.py' for the HBFA environment in this Docker image.| +| edk2/BaseTools/Source/Python/build/build.py | Primary script used to orchestrate building a platform or a module for EDK-II | + +When building a test module in HBFA, an invocation of the 'build' command may be done similar to that shown in the following. + +```console +build -p UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dsc -m UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library/BaseBmpSupportLib/TestBmpSupportLib.inf -a X64 -b DEBUG -t AFL --conf /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestPkg/Conf -t GCC5 +``` + +The 'build' script has many options and features (e.g. see the output from ```build -h```). Some useful flags used (and available in the HBFA environment are) + +| Build CLI option | Purpose | Notes/Available options | +| ---------------- | ------- | ----------------- | +| -p | To specify the platform (.dsc) file name | In this case, the platform should be the HBFA, UefiHostFuzzTestCasePkg.dsc file. | +| -m | To specify the test case the module specified by the INF file name argument | This should point to the test module file you have created and with to build/fuzz (or a pre-built test-case) | +| -a | To specify the target architecture | Per HBFA documentation, only 'X64' is supported for LibFuzzer. Use of 'IA32' is ok for AFL in HBFA. | +| -t | This is used to specify the toolchain | Note multiple targets can be specified (e.g. ```-t AFL -t GCC5```) | +| --conf | the customized Conf directory | For HBFA, this should be set as 'hbfa-fl/HBFA/UefiHostFuzzTestPkg/Conf' | + +[<<](./README.md) Back | Return to [Summary](../SUMMARY.md) | Next [>>](../harness/includedfuzzharnesses.md) \ No newline at end of file diff --git a/docs/src/fuzzing/fuzzingwithAFL.md b/docs/src/fuzzing/fuzzingwithAFL.md new file mode 100644 index 0000000..0c20c18 --- /dev/null +++ b/docs/src/fuzzing/fuzzingwithAFL.md @@ -0,0 +1,107 @@ +# Fuzzing with AFL: RunAFL.py + +To demonstrate using the RunAFL.py script for fuzzing, we'll build and fuzz the TestBmpSupportLib test-case included with HBFA-FL. First, it is important to understand some of the required arguments for the RunAFL.py script. To that end, the help contents for the script are: + +```console +# RunAFL.py -h +usage: RunAFL.py [-h] [-a {IA32,X64,ARM,AARCH64}] [-b BUILDTARGET] [-m MODULEFILE] [-i INPUTSEED] [-o OUTPUT] [-c {rawcommand,manual}] + +options: + -h, --help show this help message and exit + -a {IA32,X64,ARM,AARCH64}, --arch {IA32,X64,ARM,AARCH64} + ARCHS is one of list: IA32, X64, ARM or AARCH64, which overrides target.txt's TARGET_ARCH definition. + -b BUILDTARGET, --buildtarget BUILDTARGET + Using the TARGET to build the platform, overriding target.txt's TARGET definition. + -m MODULEFILE, --module MODULEFILE + Build the module specified by the INF file name argument. + -i INPUTSEED, --input INPUTSEED + Test input seed path. + -o OUTPUT, --output OUTPUT + Test output path for AFL. + -c {rawcommand,manual}, --commandline {rawcommand,manual} + This specifies how the fuzzer is initiated from command-line for Linux-based distributions. Specify either: 'rawcommand' or 'manual'. Using 'rawcommand' will directly initiate the AFL fuzzer + after building the test module and is recommended for automated approaches. Alternatively, 'manual' may be used to simply build the test case and print out a command that the user can run to + start the fuzzer (this will preserve the fuzzing display for AFL. +``` + +Here, we will need to reference a few files when running the script. For the TestBmpSupportLib test case, the following files should be referenced as arguments to the RunAFL.py command. **Note**, the full paths for the files should be specified. + +| File Location | Description | +| ------------- | ----------- | +| hbfa-fl/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library/BaseBmpSupportLib/TestBmpSupportLib.inf | This file is used with the '-m' option. This is the component description file for the test-case/model. This file will reference the sources, dependencies, etc. for this test-case. | +| hbfa-fl/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw | This folder is used with the '-i' option (for the input seed(s)). This directory contains several Bitmap image files (.BMP) that will serve as a fuzzing corpus. | + +Additionally, one must specify the target architecture (this example will target 'X64'), via the option '-a'. Further, the output directory for fuzzing session output should be provided via the '-o' option. If not specified, when RunAFL.py is invoked, the default assumption/value for the '--commandline' argument will be 'rawcommand', meaning the RunAFL.py script will automatically launch AFL after building the fuzzing harness. + +Putting all this together, the fuzzing test-case can be built and ran as shown: + +```console +# RunAFL.py -a X64 -m /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library/BaseBmpSupportLib/TestBmpSupportLib.inf -i /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw -o /tmp/fuzz_RunAFL_TestBmpSupportLib +Start build Test Module: +build -p UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dsc -m UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library/BaseBmpSupportLib/TestBmpSupportLib.inf -a X64 -b DEBUG -t AFL --conf /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestPkg/Conf -t GCC5 +Build Successfully !!! + +Start run AFL test: +afl-fuzz -i /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw -o /tmp/fuzz_RunAFL_TestBmpSupportLib /root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_AFL/X64/TestBmpSupportLib @@ +afl-fuzz 2.52b by + +[+] Looks like we're not running on a tty, so I'll be a bit less verbose. +... +[+] Here are some useful stats: + + + + Test case count : 8 favored, 0 variable, 10 total + + Bitmap range : 23 to 94 bits (average: 64.50 bits) + + Exec timing : 135 to 172 us (average: 147 us) + + + +[*] No -t option specified, so I'll use exec timeout of 20 ms. + +[+] All set and ready to roll! + +[*] Entering queue cycle 1. + +[*] Fuzzing test case #0 (10 total, 0 uniq crashes found)... + +[*] Fuzzing test case #1 (36 total, 0 uniq crashes found)... + +[*] Fuzzing test case #2 (37 total, 0 uniq crashes found)... +... +``` + +Here, we note your full-path to the hbfa-fl directly may differ. Alternatively, if you wish to simply build the test case and run the fuzzer later (or with other options), you can invoke the RunAFL.py script with the '--commandline' argument 'manual' as show in the following. + +```console +# RunAFL.py -a X64 -m /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library/BaseBmpSupportLib/TestBmpSupportLib.inf -i /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw -o /tmp/fuzz_RunAFL_TestBmpSupportLib --commandline manual +Start build Test Module: +build -p UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dsc -m UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library/BaseBmpSupportLib/TestBmpSupportLib.inf -a X64 -b DEBUG -t AFL --conf /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestPkg/Conf -t GCC5 +Build Successfully !!! + +Start run AFL test: +Run this command to initiate the fuzzer: afl-fuzz -i /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw -o /tmp/fuzz_RunAFL_TestBmpSupportLib /root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_AFL/X64/TestBmpSupportLib @@ +``` + +As can be seen in the output, a command is printed that can be copied and used to run the built-test case with 'afl-fuzz'. Adjust and run the command as needed to initiate a fuzzing session. E.g. for the present example, the following command will kick off the fuzzing session. + +```console +# afl-fuzz -i /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw -o /tmp/fuzz_RunAFL_TestBmpSupportLib /root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_AFL/X64/TestBmpSupportLib @@ +``` + +The fuzzing session can be terminated by pressing 'Ctrl+c'. + +### Examining the AFL output directory + +In the example provided in the prior sub-section, the fuzzing output was set to output to the directory '/tmp/fuzz_RunAFL_TestBmpSupportLib'. A file listing of this output directory is shown in the following. + +```console +[root@92fd93545422 hbfa_workspace]# ls /tmp/fuzz_RunAFL_TestBmpSupportLib +crashes fuzz_bitmap fuzzer_stats hangs plot_data queue +``` + +This is the standard output directories and files per the AFL fuzzer. For more information on the output, see [Fuzzing with afl-fuzz](https://afl-1.readthedocs.io/en/latest/fuzzing.html). Some useful folder locations include the 'crashes' directory, which will include an input file suitable for triggering any of the crashes discovered. Likewise, the queue directory will contain input files (test cases) that will reach each code path discovered. + +[<<](../harness/includedfuzzharnesses.md) Back | Return to [Summary](../SUMMARY.md) | Next [>>](./fuzzingwithLibFuzzer.md) \ No newline at end of file diff --git a/docs/src/fuzzing/fuzzingwithLibFuzzer.md b/docs/src/fuzzing/fuzzingwithLibFuzzer.md new file mode 100644 index 0000000..9c7b266 --- /dev/null +++ b/docs/src/fuzzing/fuzzingwithLibFuzzer.md @@ -0,0 +1,89 @@ +### Fuzzing with LibFuzzer: RunLibFuzzer.py + +Overall, the general approach for fuzzing with LibFuzzer is similar that that done for AFL; however, instead of RunAFL.py, we will use the RunLibFuzzer.py script in HBFA. This command offers a similar set of command-line arguments that are required; however, RunLibFuzzer.py offers a few important, additional features. Examining the '-h' (help) contents: + +```console +# RunLibFuzzer.py -h +usage: RunLibFuzzer.py [-h] [-a {IA32,X64,ARM,AARCH64}] [-b BUILDTARGET] [-m MODULEFILE] [-i INPUTSEED] [-o OUTPUT] [-s SANITIZER] [-c {rawcommand,manual}] [-p {t,T,true,True,F,false,False}] + +options: + -h, --help show this help message and exit + -a {IA32,X64,ARM,AARCH64}, --arch {IA32,X64,ARM,AARCH64} + ARCHS is one of list: IA32, X64, ARM or AARCH64, which overrides target.txt's TARGET_ARCH definition. + -b BUILDTARGET, --buildtarget BUILDTARGET + Using the TARGET to build the platform, overriding target.txt's TARGET definition. + -m MODULEFILE, --module MODULEFILE + Build the module specified by the INF file name argument. + -i INPUTSEED, --input INPUTSEED + Test input seed path. + -o OUTPUT, --output OUTPUT + Test output path for LibFuzzer. + -s SANITIZER, --sanitizer SANITIZER + A comma-separated list of sanitizers to run with LibFuzzer. E.g. '--sanitizer=address'. Included sanitizers are: (ASAN) 'address'; (MSAN) 'memory'; (UBSAN) 'undefined', 'integer', 'bounds', + 'enum', and 'function'. NOTE: 'address' and 'memory' cannot be used together. The default sanitizer is 'address'. Support for Linux only. + -c {rawcommand,manual}, --commandline {rawcommand,manual} + This specifies how the fuzzer is initiated from command-line for Linux-based distributions. Specify either: 'rawcommand', or 'manual'. Using the 'rawcommand' mode is recommended/default. The + 'manual' option will build the module and then simply print a command-line option that the end-user can subsequently use to run LibFuzzer. + -p {t,T,true,True,F,false,False}, --gen-profraw {t,T,true,True,F,false,False} + Generate 'Source Based Coverage' (Profraw) instead of the default compilation option for gcov. Support for Linux only. This setting will invoke the compilation flags '-fprofile-instr-generate + and -fcoverage-mapping' for clang and libfuzzer. +``` + +As in the prior example with AFL, we will fuzz the TestBmpSupportLib test-case. Therefore, arguments for the architecture ('-a'), the fuzzing module file ('-m'), and the fuzzing input seed ('-i') will remain the same. Likewise, we will not specify a value for the command line ('-c'), leaving it as default so the fuzzing session will be ran automatically. Also, we will specify a different location for the output directory ('-o'). Notably, there are two additional options we can consider with RunLibFuzz.py: '-s' for specifying the sanitizers to be built into our fuzzer and '-p', which is an option to use LLVM-based, 'Source Based Coverage' (Profraw format) coverage data. + +For the sanitizers ('-s') option, one can choose any combination of those listed in the help output, except the sanitizers 'address' and 'memory' cannot be used at the same time; a different build and run of the fuzzing session would be required if both are needed by the end user in their fuzzing efforts. + +Regardless of whether '-p' is specified or not, a GCC-based gov binary will be created when the RunLibFuzzer.py' script is ran; this can be later used by the 'ReportGen.py' and 'GenCodeCoverage.py' scripts for GCOV and lcovtool-based reports. When the '-p' option is included, the LibFuzzer fuzzing binary built for the test-case will be instrumented and emit Profraw ('Source-based' coverage data). This can later be used when invoking the 'GenCodeCoverage.py' command to generate llvm-tool based coverage reports. Note, you may wish to set the LLVM_PROFILE_FILE environment variable to control where the Profraw coverage data is emitted. + +In the following show an example build and run of the TestBmpSupportLib test-case using 'RunLibFuzzer.py'. Here, '-p' is used to add 'Source Based Coverage' (Profraw) and nothing is specified for the '-s' option (a default use of 'address' sanitizer is applied). + +```console +# RunLibFuzzer.py -a X64 -m /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library/BaseBmpSupportLib/TestBmpSupportLib.inf -i /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw -o /tmp/fuzz_RunLibFuzzer_TestBmpSupportLib -p true +LibFuzzer output will be generated in current directory:/tmp/fuzz_RunLibFuzzer_TestBmpSupportLib +Updating UefiHostFuzzTestBuildOption.dsc +Start build Test Module: +build -p UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dsc -m UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library/BaseBmpSupportLib/TestBmpSupportLib.inf -a X64 -b DEBUG -t LIBFUZZER --conf /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestPkg/Conf -t GCC5 +Build Successful !!! + +Start run LibFuzzer test: +/root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestBmpSupportLib /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw -rss_limit_mb=0 -artifact_prefix=/tmp/fuzz_RunLibFuzzer_TestBmpSupportLib/ +INFO: Running with entropic power schedule (0xFF, 100). + +INFO: Seed: 446151718 + +INFO: Loaded 1 modules (754 inline 8-bit counters): 754 [0x5abdc8, 0x5ac0ba), + +INFO: Loaded 1 PC tables (754 PCs): 754 [0x5797a0,0x57c6c0), + +INFO: 10 files found in /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw + +INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes +... + +``` + +For LibFuzzer, the fuzzing session will continue until either a crash is encountered or you press 'Ctrl+c'. If crashes are found, the files will be saved to the output directory specified via the '-o' option. *Importantly*, for any additional code paths discovered during the fuzzing sessions, additional seed files are added by LibFuzzer to the directory specified via the '-i' option. *Note*, if you wish to run the fuzzing session with additional parameters for LibFuzzer, take note of the following lines from the 'RunLibFuzzer.py output'; use the command printed as a starting point to add/modify to the command. + +```console +Start run LibFuzzer test: +/root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestBmpSupportLib /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw -rss_limit_mb=0 -artifact_prefix=/tmp/fuzz_RunLibFuzzer_TestBmpSupportLib/ +``` + +### Examining the LibFuzzer output directory + +If there were not any crashes discovered, the output directory will be empty as shown in the following. + +```console +# ls -l /tmp/fuzz_RunLibFuzzer_TestBmpSupportLib +total 0 +``` + +However, if there were crashes found, the input files that generated those crashes (or sanitizer detections) will be in the output directory, e.g. see the subsequent directory listing. Noting that some UBSAN detections are printed to the console output and do not terminate the fuzzing session. + +```console +# ls -l /tmp/fuzz_RunLibFuzzer_TestBmpSupportLib +total 4 +-rw-r--r-- 1 root root 62 May 21 18:35 crash-0205a0e4ec89a2fd77df87a0688599f704a5ddc2 +``` + +[<<](./fuzzingwithAFL.md) Back | Return to [Summary](../SUMMARY.md) | Next [>>](./generatingCoverageReports.md) \ No newline at end of file diff --git a/docs/src/fuzzing/generatingCoverageReports.md b/docs/src/fuzzing/generatingCoverageReports.md new file mode 100644 index 0000000..14f4edb --- /dev/null +++ b/docs/src/fuzzing/generatingCoverageReports.md @@ -0,0 +1,266 @@ +## Generating fuzzing summary and coverage data reports + +HBFA includes two scripts to assist with generating fuzzing and coverage reports: 'ReportMain.py' and 'GenCodeCoverage.py', respectively. For AFL fuzzing runs, the underlying coverage format used by HBFA is GCOV-based, and the LCOV tool is used to generate HTML reports. For LibFuzzer results, GCOV-based can be generated, or, if the '-p' option was set to 'True' for RunLibFuzzer.py, LLVM [source-based coverage](https://clang.llvm.org/docs/SourceBasedCodeCoverage.html) (Profraw-based) coverage reports can be generated. In the following, we'll step through examples for both GCOV-based- and Profraw-based- reports. + +### Generating fuzzing reports for AFL fuzzing output, GCOV-based + +We again use the TestBmpSupportLib test-case for the example. In order to generate the reports from our previous fuzzing session with RunAFL.py with the TestBmpSupportLib test-case, we should first run the 'ReportMain.py' script. To run the script, several arguments are needed; first, running the help option will show the available arguments for this command. + +```console +# ReportMain.py -h +usage: ReportMain.py [-h] [-e MODULEBIN] [-i RESULTPATH] [-r REPORTPATH] [-t TESTMETHODS] [-s SLEEPTIME] + +options: + -h, --help show this help message and exit + -e MODULEBIN, --execbinary MODULEBIN + Test module binary file name. + -i RESULTPATH, --input RESULTPATH + Test result path for test method. + -r REPORTPATH, --report REPORTPATH + Generated report path. + -t TESTMETHODS, --testmethods TESTMETHODS + Test method's name. Must be one of [afl, libfuzzer]. Will be auto detected for default. + -s SLEEPTIME, --sleep SLEEPTIME + In run time mode, # of seconds to sleep between checking for new seed files +``` + +For the test method, we will specify AFL, e.g. '-t afl'. Next, the fuzzing module binary should be specified (-e MODULEBIN). When we ran the RunAFL.py script, it also ensured that a separate build of the test case was done using GCC with GCOV coverage enabled; therefore, for the TestBmpSupportLib test-case this will be (your base directory may vary): '/root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_GCC5/X64/TestBmpSupportLib'. Further we will need to provide the directory (-i RESULTPATH) we had specified for our fuzzing output ('/tmp/fuzz_RunAFL_TestBmpSupportLib'). Lastly, we need to provide a location for the report output (-r REPORTPATH). Putting this together, we run the ReportMain.py command: + +```console +# ReportMain.py -e /root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_GCC5/X64/TestBmpSupportLib -i /tmp/fuzz_RunAFL_TestBmpSupportLib -r /tmp/TestBmpSupportLib -t afl +``` + +The report contents will be output to the directory we specified: '/tmp/TestBmpSupportLib'. For this example, the following files are created, as shown in the directory listing. + +```console +# ls /tmp/TestBmpSupportLib/DebugReport/ +GdbSummaryReport.html IndexCrashes.html IndexHangs.html +``` + +The file 'GdbSummaryReport.html' will contain an overview of the AFL fuzzing run (e.g. total case numbers, execution time). The file 'IndexCrashes.html', should contain information for detected crashes; note, if there were no crashes, then the table of cases will be empty. Example outputs for this are shown in the following. + +![](../../images/hbfa_summary.png) + +*Example GdbSummaryReport.html report with no crashes* + +![](../../images/hbfa_crashes.png) + +*Example IndexCrashes.html report with no crashes* + +![](../../images/hbfa_hangs.png) + +*Example IndexHangs.html report with no crashes* + +### Generating a Fuzzing Code Coverage Report for AFL fuzzing output, GCOV-based + +In order to generate code coverage report data, the 'GenCodeCoverage.py' script should be used. Running the help option will show the available arguments for this command: + +```console +# GenCodeCoverage.py -h +Usage: python GenCodeCoverage.py [options][argument] + +Copyright (c) 2019, Intel Corporation. All rights reserved. + +Options: + --version show program's version number and exit + -h, --help show this help message and exit + -e MODULEBIN, --execbinary=MODULEBIN + Test module binary file name. + -d SEEDPATH, --dir=SEEDPATH + Test output seed directory path. + -t TESTINIPATH, --testini=TESTINIPATH + Test ini files path for ErrorInjection, only for + ErrorInjection. + -r REPORTPATH, --report=REPORTPATH + Generated code coverage report path. +``` + +As was done when executing 'ReportMain.py', we'll again specify the '-e' option (MODULEBIN) as: '/root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_GCC5/X64/TestBmpSupportLib'. Importantly, the '-d' option for SEEDPATH will be the 'queue' directory in the AFL fuzzing output '/tmp/fuzz_RunAFL_TestBmpSupportLib/queue', as this will contain representative input files to reach all of the code paths discovered during the fuzzing session. Lastly, the '-t' option is will not be needed (for ErrorInjection), and we'll specify our report output directory for the '-r' (REPORTPATH) argument. Putting this together and running the command: + +```console +# GenCodeCoverage.py -e /root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_GCC5/X64/TestBmpSupportLib -d /tmp/fuzz_RunAFL_TestBmpSupportLib/queue -r /tmp/TestBmpSupportLib/ +Capturing coverage data from /root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_GCC5/X64 +Found gcov version: 11.3.1 +Using intermediate gcov format +Scanning /root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_GCC5/X64 for .gcda files ... +Found 15 data files in /root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_GCC5/X64 +Processing UefiHostFuzzTestPkg/Library/ToolChainHarnessLib/ToolChainHarnessLib/OUTPUT/ToolChainHarnessLib.gcda +Processing MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib/OUTPUT/SafeIntLib.gcda +Processing UefiHostTestPkg/Library/BaseLibHost/BaseLibHost/OUTPUT/SwapBytes32.gcda +Processing UefiHostTestPkg/Library/BaseLibHost/BaseLibHost/OUTPUT/RShiftU64.gcda +Processing UefiHostTestPkg/Library/BaseLibHost/BaseLibHost/OUTPUT/CpuBreakpointGcc.gcda +Processing UefiHostTestPkg/Library/BaseLibHost/BaseLibHost/OUTPUT/LShiftU64.gcda +Processing UefiHostTestPkg/Library/BaseLibHost/BaseLibHost/OUTPUT/MultS64x64.gcda +Processing UefiHostTestPkg/Library/BaseLibHost/BaseLibHost/OUTPUT/MultU64x64.gcda +Processing UefiHostTestPkg/Library/BaseLibHost/BaseLibHost/OUTPUT/SwapBytes16.gcda +Processing UefiHostTestPkg/Library/BaseLibHost/BaseLibHost/OUTPUT/Math64.gcda +Processing UefiHostTestPkg/Library/BaseMemoryLibHost/BaseMemoryLibHost/OUTPUT/BaseMemoryLibHost.gcda +Processing UefiHostTestPkg/Library/MemoryAllocationLibHost/MemoryAllocationLibHost/OUTPUT/MemoryAllocationLibHost.gcda +Processing UefiHostTestPkg/Library/DebugLibHost/DebugLibHost/OUTPUT/DebugLibHost.gcda +Processing MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib/OUTPUT/BmpSupportLib.gcda +Processing UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library/BaseBmpSupportLib/TestBmpSupportLib/OUTPUT/TestBmpSupportLib.gcda +Finished .info-file creation +Reading tracefile coverage.info +Removing /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostTestPkg/Library/BaseLibHost/CpuBreakpointGcc.c +Removing /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostTestPkg/Library/BaseLibHost/LShiftU64.c +Removing /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostTestPkg/Library/BaseLibHost/Math64.c +Removing /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostTestPkg/Library/BaseLibHost/MultS64x64.c +Removing /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostTestPkg/Library/BaseLibHost/MultU64x64.c +Removing /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostTestPkg/Library/BaseLibHost/RShiftU64.c +Removing /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostTestPkg/Library/BaseLibHost/SwapBytes16.c +Removing /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostTestPkg/Library/BaseLibHost/SwapBytes32.c +Removing /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostTestPkg/Library/BaseMemoryLibHost/BaseMemoryLibHost.c +Removing /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostTestPkg/Library/DebugLibHost/DebugLibHost.c +Removing /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostTestPkg/Library/MemoryAllocationLibHost/MemoryAllocationLibHost.c +Deleted 11 files +Writing data to coverage.info +Summary coverage rate: + lines......: 21.0% (202 of 964 lines) + functions..: 8.2% (8 of 97 functions) + branches...: no data found +Reading data file coverage.info +Found 4 entries. +Found common filename prefix "/root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library" +Writing .css and .png files. +Generating output. +Processing file BaseBmpSupportLib/TestBmpSupportLib.c +Processing file /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestPkg/Library/ToolChainHarnessLib/ToolChainHarnessLib.c +Processing file /root/hbfa_workspace/edk2/MdeModulePkg/Library/BaseBmpSupportLib/BmpSupportLib.c +Processing file /root/hbfa_workspace/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLib.c +Writing directory view page. +Overall coverage rate: + lines......: 21.0% (202 of 964 lines) + functions..: 8.2% (8 of 97 functions) +Please view code coverage report in /tmp/TestBmpSupportLib/CodeCoverageReport +``` + +The output (coverage report) is written to '/tmp/TestBmpSupportLib/CodeCoverageReport'. Examining the directory contents, one can see that an HTML-based report is generated (e.g. see index.html). + +```console +# ls /tmp/TestBmpSupportLib/CodeCoverageReport/ +BaseBmpSupportLib emerald.png glass.png index-sort-l.html root snow.png +amber.png gcov.css index-sort-f.html index.html ruby.png updown.png +``` + +An example of the coverage output is shown in the following screenshots. + +![](../../images/hbfa_covreport.png) + +*Example index.html code coverage report* + +![](../../images/hbfa_covreport2.png) + +*Example code coverage report for BmpSupportLib.c (drill down into source code view from index.html)* + +### Generating a Fuzzing and Coverage Report for LibFuzzer-base fuzzing in HBFA-FL + +Fuzzing session summary and coverage reports can be generated using 'ReportMain.py' and 'GenCodeCoverage.py' as was done in the previous cases for fuzzing with AFL; however, coverage reports can be also processed for LLVM, Profraw-based output (in addition to LCOV-based output). Noting that for the LLVM, Profraw-based output it is necessary that the 'RunLibFuzzer.py' script was ran with the '-p' option set to 'True'. (Also you may wish to set the LLVM_PROFILE_FILE environment variable to control where the Profraw coverage data is emitted). + +### Generating a Fuzzing Session Summary Report + +A summary report for the fuzzing session can be generated by using the 'ReportMain.py' script, as shown: + +```console +# ReportMain.py -e /root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestBmpSupportLib -i /tmp/fuzz_RunLibFuzzer_TestBmpSupportLib -r /tmp/TestBmpSupportLib -t libfuzzer +``` + +Note, '-i' points to the artifacts (seed) directory from running the built, LibFuzzer test-case binary and '-t' is the target type (here 'libfuzzer'). + +The report contents will be output to the directory specified (with the '-r' argument, here /tmp/TestBmpSupportLib). For this example, the following files are created (shown in a directory listing). + +```console +# ls /tmp/TestBmpSupportLib/DebugReport/ +IndexSanitizer.html SanitizerSummaryReport.html +``` + +If there are no crashes, the reports will indicate 0 crashes. In the event a sanitizer records a crash, a report may not be generated, instead a sanitizer log file may be written to the report directory, as shown in the following directory listing. + +```console +bash-5.1# ls /tmp/TestBmpSupportLib/DebugReport/ +HBFA.Sanitizer.log +``` + +### Generating a Fuzzing Code Coverage Report for output from LibFuzzer + +The GenCodeCoverage.py script is used to generate code coverage reports. Again, the HBFA-FL release can process the coverage data in two ways: + +1. The original HBFA way for LibFuzzer, using the GCC5 build target to process seed/corpus files (the original files, along with those written during the previous run of LibFuzzer), and then post processing those into a HTML-formatted report (leveraging the LCOV program) +2. The test-case is compiled such that source-based coverage data can be emitted ('PROFRAW' data is collected). When the GenCodeCoverage.py script is invoked and the target binary was built using the LIBFUZZER target, the seed/corpus files will be used, along with llvm-cov suite of tools to generate coverage report files. + +#### 1. LCOV-based coverage output + +In order to generate code coverage report data, the 'GenCodeCoverage.py' script should be used; the use will be similar as that done for the AFL version. + +```console +# GenCodeCoverage.py -e /root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_GCC5/X64/TestBmpSupportLib -d /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw -r /tmp/TestBmpSupportLib/ +Capturing coverage data from /root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_GCC5/X64 +Found gcov version: 11.3.1 +Using intermediate gcov format +Scanning /root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_GCC5/X64 for .gcda files ... +Found 15 data files in /root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_GCC5/X64 +Processing UefiHostFuzzTestPkg/Library/ToolChainHarnessLib/ToolChainHarnessLib/OUTPUT/ToolChainHarnessLib.gcda +... +Writing data to coverage.info +Summary coverage rate: + lines......: 20.4% (197 of 964 lines) + functions..: 8.2% (8 of 97 functions) + branches...: no data found +Reading data file coverage.info +Found 4 entries. +Found common filename prefix "/root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library" +Writing .css and .png files. +Generating output. +Processing file BaseBmpSupportLib/TestBmpSupportLib.c +Processing file /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestPkg/Library/ToolChainHarnessLib/ToolChainHarnessLib.c +Processing file /root/hbfa_workspace/edk2/MdeModulePkg/Library/BaseBmpSupportLib/BmpSupportLib.c +Processing file /root/hbfa_workspace/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLib.c +Writing directory view page. +Overall coverage rate: + lines......: 20.4% (197 of 964 lines) + functions..: 8.2% (8 of 97 functions) +Please view code coverage report in /tmp/TestBmpSupportLib/CodeCoverageReport +``` + +The output will be collected in the sub-directory 'CodeCoverageReport' of the report directory specified via the '-r' argument for the GenCodeCoverage.py script. An example of the output is shown in the following. + +```console +# ls /tmp/TestBmpSupportLib/CodeCoverageReport/ +BaseBmpSupportLib emerald.png glass.png index-sort-l.html root snow.png +amber.png gcov.css index-sort-f.html index.html ruby.png updown.png +``` + +When opened in a web-browser, the coverage information presented should be similar to that shown in previous examples shown for AFL code coverage output. + +#### 2. LLVM-based coverage output + +The LLVM-based (profraw data) coverage report can be produced in similar manner by running the 'GenCodeCoverage.py' script. Here, it is essential that the 'RunLibFuzzer.py' script was invoked using the '-p' option set to True, so that the proper coverage instrumentation (and emitted output) will have been generated during the fuzzing session. Assuming all of this has been done, the coverage report can be generated running the following command for our test-case. + +```console +# GenCodeCoverage.py -e /root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestBmpSupportLib -d /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw -r /tmp/TestBmpSupportLib/ +INFO: Running with entropic power schedule (0xFF, 100). +INFO: Seed: 1478178115 +INFO: Loaded 1 modules (754 inline 8-bit counters): 754 [0x4b64a8, 0x4b679a), +INFO: Loaded 1 PC tables (754 PCs): 754 [0x4993b8,0x49c2d8), +/root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestBmpSupportLib: Running 1 inputs 1 time(s) each. +Running: /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/sample.bmp +Executed /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw/sample.bmp in 0 ms +*** +*** NOTE: fuzzing was not performed, you have only +*** executed the target code on a fixed set of inputs. +*** +INFO: Running with entropic power schedule (0xFF, 100). +INFO: Seed: 1488500083 +INFO: Loaded 1 modules (754 inline 8-bit counters): 754 [0x4b64a8, 0x4b679a), +INFO: Loaded 1 PC tables (754 PCs): 754 [0x4993b8,0x49c2d8), +/root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestBmpSupportLib: Running 1 inputs 1 time(s) each. +... +``` + +The output will be collected in the sub-directory 'llvm_coverage_report' of the report directory specified via the '-r' argment for the GenCodeCoverage.py script. + +```console +# ls /tmp/TestBmpSupportLib/llvm_coverage_report/ +default.profdata filtered.txt report.html report.txt show.txt +``` + +[<<](./fuzzingwithLibFuzzer.md) Back | Return to [Summary](../SUMMARY.md) \ No newline at end of file diff --git a/docs/src/harness/README.md b/docs/src/harness/README.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/src/harness/includedfuzzharnesses.md b/docs/src/harness/includedfuzzharnesses.md new file mode 100644 index 0000000..e887c67 --- /dev/null +++ b/docs/src/harness/includedfuzzharnesses.md @@ -0,0 +1,74 @@ +# Fuzzing test harnesses included with HBFA-FL + +A number of fuzzing test harness cases are included in HBFA-FL. These, test-harnesses were included in the original [HBFA](https://github.com/tianocore/edk2-staging/tree/HBFA); however, the original HBFA includes a few additional test-cases not included here, which are described in the following [section](#test-cases-presently-not-included-in-hbfa-fl). Carefully examining all of these tests harnesses is very helpful for learning how to implement fuzzing tests harnesses in HBFA-FL. A listing of these files is presented in the following Table. + +| Fuzzing Test Case Name | File Location (based from repository root) | +| ------------------------------------- | ----------------------------- | +| TestTpm2CommandLib | HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/Tpm2CommandLib/TestTpm2CommandLib.{c,inf} | +| TestBmpSupportLib | HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library/BaseBmpSupportLib/TestBmpSupportLib.{c,inf} | +| TestPartition | HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/PartitionDxe/TestPartition.{c,inf} | +| TestUdf | HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/TestUdf.{c,inf} | +| TestUsb | HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Usb/UsbBusDxe/TestUsb.{c,inf} | +| TestPeiUsb | HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Usb/UsbBusPei/TestPeiUsb.{c,inf} | +| TestVariableSmm | HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Variable/RuntimeDxe/TestVariableSmm.{c,inf} | +| TestFmpAuthenticationLibPkcs7 | HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibPkcs7/TestFmpAuthenticationLibPkcs7.{c,inf} | +| TestFmpAuthenticationLibRsa2048Sha256 | HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibRsa2048Sha256/TestFmpAuthenticationLibRsa2048Sha256.{c,inf} | +| TestCapsulePei | HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/CapsulePei/Common/TestCapsulePei.{c,inf} | +| TestFileName | HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/TestFileName.{c,inf} | +| TestPeiGpt | HBFA/UefiHostFuzzTestCasePkg/TestCase/FatPkg/FatPei/TestPeiGpt.{c,inf} | +| TestValidateTdxCfv | HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/EmuVariableFvbRuntimeDxe/TestValidateTdxCfv.{c,inf} | +| TestTcg2MeasureGptTable | HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/DxeTpm2MeasureBootLib/TestTcg2MeasureGptTable.{c,inf} | +| TestTcg2MeasurePeImage | HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/DxeTpm2MeasureBootLib/TestTcg2MeasurePeImage.{c,inf} | +| TestVirtioPciDevice | HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioPciDeviceDxe/TestVirtioPciDevice.{c,inf} | +| TestVirtio10Blk | HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/Virtio10BlkDxe/TestVirtio10Blk.{c,inf} | +| TestVirtioBlk | HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioBlkDxe/TestVirtioBlk.{c,inf} | +| TestVirtioBlkReadWrite | HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioBlkReadWrite/TestVirtioBlkReadWrite.{c,inf} | +| TestIdentifyAtaDevice | HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/TestIdentifyAtaDevice.{c,inf} | + +Additionally, many of the test-cases make use of stub-libraries to simulate responses from function call that would interact with hardware. These libraries are included in HBFA in the relative directory: + +``` +├── HBFA + ├── UefiHostFuzzTestCasePkb + ├── TestStub + ├── DiskStubLib + ├── Tcg2StubLib + ├── Tpm2DeviceLibStub + ├── ... +``` + +## Seed files included + +HBFA-FL includes some seed corpus for the included test-cases. The relative locations are shown in the following table. + +| Case Name | Seed Location (based from repository root) | +| -------------- | ------------- | +| TestTpm2CommandLib | HBFA/UefiHostFuzzTestCasePkg/Seed/TPM/Raw +| TestBmpSupportLib | HBFA/UefiHostFuzzTestCasePkg/Seed/BMP/Raw +| TestPartition | HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/Partition +| TestUdf | HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileSystem +| TestUsb | HBFA/UefiHostFuzzTestCasePkg/Seed/USB/Raw +| TestPeiUsb | HBFA/UefiHostFuzzTestCasePkg/Seed/USB/Raw +| TestDxeCapsuleLibFmp | HBFA/UefiHostFuzzTestCasePkg/Seed/Capsule +| TestVariableSmm | HBFA/UefiHostFuzzTestCasePkg/Seed/VariableSmm/Raw +| TestFmpAuthenticationLibPkcs7 | HBFA/UefiHostFuzzTestCasePkg/Seed/Capsule +| TestFmpAuthenticationLibRsa2048Sha256 | HBFA/UefiHostFuzzTestCasePkg/Seed/Capsule +| TestCapsulePei | HBFA/UefiHostFuzzTestCasePkg/Seed/Capsule +| TestUpdateLockBoxFuzzLength | HBFA/UefiHostFuzzTestCasePkg/Seed/LockBox/Raw +| TestUpdateLockBoxFuzzOffset | HBFA/UefiHostFuzzTestCasePkg/Seed/LockBox/Raw +| TestFileName | HBFA/UefiHostFuzzTestCasePkg/Seed/UDF/Raw/FileName +| TestPeiGpt | HBFA/UefiHostFuzzTestCasePkg/Seed/Gpt/Raw + +## Test-cases presently not included in HBFA-FL + +The following fuzzing test-cases are not included in HBFA-FL; however, they are in the original HBFA. These test cases are no longer build and may be re-integrated at some future point. + +| Fuzzing Test Case Name | File Location (based from repository root of HBFA) | +| ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | +| TestDxeCapsuleLibFmp | HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library/DxeCapsuleLibFmp/TestDxeCapsuleLibFmp.{c,inf} | +| TestUpdateLockBoxFuzzLength | HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library/SmmLockBoxLib/UpdateLockBoxTestCase/TestUpdateLockBoxFuzzLength.{c,inf} | +| TestUpdateLockBoxFuzzOffset | HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library/SmmLockBoxLib/UpdateLockBoxTestCase/TestUpdateLockBoxFuzzOffset.{c,inf} | +| TestHobList | HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/Library/TdxStartupLib/TestHobList.{c,inf} | +| TestParseMmioExitInstructions | HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/Library/CcExitLib/TestParseMmioExitInstructions.{c,inf} | + +[<<](../fuzzing/building.md) Back | Return to [Summary](../SUMMARY.md) | Next [>>](../fuzzing/fuzzingwithAFL.md) \ No newline at end of file diff --git a/docs/src/harness/wheretoharness.md b/docs/src/harness/wheretoharness.md new file mode 100644 index 0000000..84fbb69 --- /dev/null +++ b/docs/src/harness/wheretoharness.md @@ -0,0 +1,22 @@ +# Where to create and save a fuzzing test case harness + +It is recommended to create fuzzing test harness cases in the file structure provided in HBFA-FL. At a minimum, the folder used for the fuzzing test cases should be located in a sub-directory under the 'HBFA' directory for use with the RunAFL.py and RunLibFuzzer.py script. For a fuzzing test harness, a minimal test case folder would consist of the test harness C-source code file (containing the fuzzing harness logic) and a module description file (the .inf file). The 'HBFA' folder shown in the file structure (tree) relative to the HBFA-FL repository root directory. + +``` +├── HBFA + ├── UefiHostFuzzTestCasePkb + ├── TestCase + ├── ... # The directories here somewhat follow the + DeviceSecurityPkg # analogous directories from the EDK2 root + FatPkg # file structure (e.g. see MdeModulePkg) + MdeModulePkg + OvmfPkg + SecurityPkg + ... + └── TestModuleFolder # This is the folder containing the new test case + └── TestXYZ.c # Test harness/logic goes in this C-source code file + └── TestXYZ.inf # The INF, module description file + +``` + +[<<](../fuzzing/README.md) Back | Return to [Summary](../SUMMARY.md) | Next [>>](../fuzzing/building.md) \ No newline at end of file diff --git a/docs/src/setup/README.md b/docs/src/setup/README.md new file mode 100644 index 0000000..54bf60b --- /dev/null +++ b/docs/src/setup/README.md @@ -0,0 +1,5 @@ +# Setting up an environment for HBFA-FL + +In order to leverage HBFA-FL, several additional software packages and tools are needed. Further, setting up a few environment variables is necessary, so that HBFA-FL can source necessary build environment parameters, EDK II source code, and invoke the various tools and fuzzing frameworks. + +[<<](../README.md) Back | Return to [Summary](../SUMMARY.md) | Next [>>](./linux.md) \ No newline at end of file diff --git a/docs/src/setup/linux.md b/docs/src/setup/linux.md new file mode 100644 index 0000000..4e1bc24 --- /dev/null +++ b/docs/src/setup/linux.md @@ -0,0 +1,198 @@ +# Setting up HBFA-FL for a Linux environment + +In order to use HBFA-FL, several dependencies should be installed. If viable, a recommended approach for setting up an environment for HBFA is to leverage the [Tianocore/containers repository](https://github.com/tianocore/containers). The Dockerfiles there for the Fedora- and Ubuntu-based images provide a good baseline for HBFA as they can provide all the necessary packages and dependencies for building in the EDK-II environment. More, specifically, the 'build' targets in those images are a great starting point. + +## Installing EDK-II + +For EDK-II, please refer to the [instructions from EDK-II](https://github.com/tianocore/tianocore.github.io/wiki/Getting-Started-with-EDK-II) for additional details on setting up the EDK-II Environment. (Note the use of the Tianocore/container Dockerfile should result in an environment suitable for setting up the EDK-II code-base and building various platforms/components.) + +For a quick-start, you can readily obtain the EDK-II source code from their [repository](https://github.com/tianocore/edk2). Following this approach, we can clone the repository to our local machine, and then build the base EDK-II tools, as shown in the following. + +```console +root@a791b2478af5:/root/hbfa_workspace# git clone https://github.com/tianocore/edk2.git --recursive +root@a791b2478af5:/root/hbfa_workspace# cd edk2 +root@a791b2478af5:/root/hbfa_workspace/edk2# make -C BaseTools +``` + +Here we note that when the 'make' command is ran for building the EDK-II base tools, a series of tests should be ran. Verify that the tests are all passing ('ok') before proceeding. Lastly, we can run the 'edk2/edksetup.sh' script, this will set several important environment variables. Depending on how you are invoking a shell instance, you may need to source this command again to set the environment variables. + +```console +root@a791b2478af5:/root/hbfa_workspace/edk2# source edksetup.sh +Using EDK2 in-source Basetools +WORKSPACE: /root/hbfa_workspace/edk2 +EDK_TOOLS_PATH: /root/hbfa_workspace/edk2/BaseTools +CONF_PATH: /root/hbfa_workspace/edk2/Conf +Copying $EDK_TOOLS_PATH/Conf/build_rule.template + to /root/hbfa_workspace/edk2/Conf/build_rule.txt +Copying $EDK_TOOLS_PATH/Conf/tools_def.template + to /root/hbfa_workspace/edk2/Conf/tools_def.txt +Copying $EDK_TOOLS_PATH/Conf/target.template + to /root/hbfa_workspace/edk2/Conf/target.txt +``` + +## Setting up HBFA-FL and the Build Environment (EDK-II with HBFA-FL) + +Next, obtain the source code for HBFA-FL (e.g. via cloning the repo with the 'git' tool, as done for edk2). Once the source code for HBFA-FL has been retrieved, you'll need to set up a few environment variables and run a Python script included in HBFA-FL to help set-up the environment. To do this, follow the steps shown: + +```console +root@a791b2478af5:~/hbfa_workspace# export WORKSPACE=~/hbfa_workspace/ +root@a791b2478af5:~/hbfa_workspace# export PACKAGES_PATH=$WORKSPACE/edk2:$WORKSPACE/hbfa-fl/HBFA/ +root@a791b2478af5:~/hbfa_workspace# python3 hbfa-fl/HBFA/UefiHostTestTools/HBFAEnvSetup.py +``` + +Noting, we are redefining the 'WORKSPACE' environment variable and defining the PACKAGES_PATH for EDK-II relative to this, which will include all code from the edk2 source and hbfa-fl source when building. Running the HBFAEnvSetup.py script, we will generate the 'build_rule.txt' and the 'tools_def.txt' configuration files under the HBFA-FL directory: ```HBFA/UefiHostFuzzTestPkg/Conf/```. These will be used by the EDK-II build system when compiling fuzzing test harnesses. + +## Installing and setting up AFL + +If you wish to fuzz with AFL, you will need to obtain, build, configure, and set-up a few environment variables. + +First, assuming the use of the original AFL-2.52b version of AFL, you can obtain the source code from http://lcamtuf.coredump.cx/afl/releases/afl-latest.tgz. Here, we'll use the ```wget``` tool to download the source, then build, and set up the appropriate environment. + +```console +root@a791b2478af5:~/hbfa_workspace# wget -q http://lcamtuf.coredump.cx/afl/releases/afl-latest.tgz +root@a791b2478af5:~/hbfa_workspace# tar xf afl-latest.tgz && rm afl-latest.tgz +root@a791b2478af5:~/hbfa_workspace# ll +total 20 +drwxr-xr-x 5 root root 4096 Dec 7 19:03 ./ +drwx------ 1 root root 4096 Dec 7 17:03 ../ +drwxr-xr-x 10 500 500 4096 Nov 5 2017 afl-2.52b/ +drwxr-xr-x 36 root root 4096 Dec 7 16:35 edk2/ +drwxrwxr-x 9 root root 4096 Dec 4 18:24 hbfa-fl/ +root@a791b2478af5:~/hbfa_workspace# export AFL_PATH=/root/hbfa_workspace/afl-2.52b +root@a791b2478af5:~/hbfa_workspace# export PATH=$PATH:$AFL_PATH +``` + +Here, we have downloaded and extracted the source code for AFL and we set the environment variable 'AFL_PATH' to point to the extracted AFL directory. We also add the AFL_PATH to the shell path. Before proceeding, we need to build the source code for AFL, as shown in the following. + +```console +root@a791b2478af5:~/hbfa_workspace/afl-2.52b# make +[*] Checking for the ability to compile x86 code... +[+] Everything seems to be working, ready to compile. +cc -O3 -funroll-loops -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -DAFL_PATH=\"/usr/local/lib/afl\" -DDOC_PATH=\"/usr/local/share/doc/afl\" -DBIN_PATH=\"/usr/local/bin\" afl-gcc.c -o afl-gcc -ldl +set -e; for i in afl-g++ afl-clang afl-clang++; do ln -sf afl-gcc $i; done +cc -O3 -funroll-loops -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -DAFL_PATH=\"/usr/local/lib/afl\" -DDOC_PATH=\"/usr/local/share/doc/afl\" -DBIN_PATH=\"/usr/local/bin\" afl-fuzz.c -o afl-fuzz -ldl +cc -O3 -funroll-loops -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -DAFL_PATH=\"/usr/local/lib/afl\" -DDOC_PATH=\"/usr/local/share/doc/afl\" -DBIN_PATH=\"/usr/local/bin\" afl-showmap.c -o afl-showmap -ldl +cc -O3 -funroll-loops -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -DAFL_PATH=\"/usr/local/lib/afl\" -DDOC_PATH=\"/usr/local/share/doc/afl\" -DBIN_PATH=\"/usr/local/bin\" afl-tmin.c -o afl-tmin -ldl +cc -O3 -funroll-loops -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -DAFL_PATH=\"/usr/local/lib/afl\" -DDOC_PATH=\"/usr/local/share/doc/afl\" -DBIN_PATH=\"/usr/local/bin\" afl-gotcpu.c -o afl-gotcpu -ldl +cc -O3 -funroll-loops -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -DAFL_PATH=\"/usr/local/lib/afl\" -DDOC_PATH=\"/usr/local/share/doc/afl\" -DBIN_PATH=\"/usr/local/bin\" afl-analyze.c -o afl-analyze -ldl +cc -O3 -funroll-loops -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -DAFL_PATH=\"/usr/local/lib/afl\" -DDOC_PATH=\"/usr/local/share/doc/afl\" -DBIN_PATH=\"/usr/local/bin\" afl-as.c -o afl-as -ldl +ln -sf afl-as as +[*] Testing the CC wrapper and instrumentation output... +unset AFL_USE_ASAN AFL_USE_MSAN; AFL_QUIET=1 AFL_INST_RATIO=100 AFL_PATH=. ./afl-gcc -O3 -funroll-loops -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -DAFL_PATH=\"/usr/local/lib/afl\" -DDOC_PATH=\"/usr/local/share/doc/afl\" -DBIN_PATH=\"/usr/local/bin\" test-instr.c -o test-instr -ldl +echo 0 | ./afl-showmap -m none -q -o .test-instr0 ./test-instr +echo 1 | ./afl-showmap -m none -q -o .test-instr1 ./test-instr +[+] All right, the instrumentation seems to be working! +[+] All done! Be sure to review README - it's pretty short and useful. +``` + +Last, you may need to adjust the core pattern and CPU scaling for the AFL fuzzer. To do so, you may run command similar to the following. Note, if you are running a container image (e.g. via Docker), you may need to run the container in privileged mode to run these commands. + +```console +# echo 'echo "core_%p_%s_%c_%d_%P_%E" > /proc/sys/kernel/core_pattern' >> /root/.bashrc +# echo 'echo "performance" | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor' >> /root/.bashrc +``` + +### Test build for the included fuzzing test-harnesses with AFL as the fuzzer + +Next, to verify the set-up, you can copy the 'build_rule.txt' and 'tools_def.txt' files generated when you ran the HBFAEnvSetup.py script into the configuration directory for EDK-II, then invoke the build command for EDK-II (where the platform provide via the '-p' option the HBFA platform UefiHostFuzzTestCasePkg.dsc). We specify the '-t' option as 'AFL' to ensure the build leverages AFL for instrumenting the binary fuzzing harnesses. Note, additional details on building and running test-cases are included in this documentation (e.g. see this [section](../fuzzing/building.md)): + +```console +root@a791b2478af5:~/hbfa_workspace# cp hbfa-fl/HBFA/UefiHostFuzzTestPkg/Conf/build_rule.txt edk2/Conf/build_rule.txt +root@a791b2478af5:~/hbfa_workspace# cp hbfa-fl/HBFA/UefiHostFuzzTestPkg/Conf/tools_def.txt edk2/Conf/tools_def.txt +root@a791b2478af5:~/hbfa_workspace# build -p hbfa-fl/HBFA/UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dsc -a X64 -t AFL +``` + +If all is set-up correctly, all of the included test-cases should build without error and can be seen in subdirectories under the 'Build' directory, e.g. see the following directory listing. + +```console +root@a791b2478af5:~/hbfa_workspace# ll Build/UefiHostFuzzTestCasePkg/DEBUG_AFL/X64/Test* +-rwxr-xr-x 1 root root 197952 Dec 7 20:07 Build/UefiHostFuzzTestCasePkg/DEBUG_AFL/X64/TestBmpSupportLib* +-rwxr-xr-x 1 root root 148848 Dec 7 20:07 Build/UefiHostFuzzTestCasePkg/DEBUG_AFL/X64/TestCapsulePei* +-rwxr-xr-x 1 root root 479448 Dec 7 20:07 Build/UefiHostFuzzTestCasePkg/DEBUG_AFL/X64/TestFileName* +-rwxr-xr-x 1 root root 96528 Dec 7 20:07 Build/UefiHostFuzzTestCasePkg/DEBUG_AFL/X64/TestFmpAuthenticationLibPkcs7* +-rwxr-xr-x 1 root root 114360 Dec 7 20:07 Build/UefiHostFuzzTestCasePkg/DEBUG_AFL/X64/TestFmpAuthenticationLibRsa2048Sha256* +-rwxr-xr-x 1 root root 383072 Dec 7 20:07 Build/UefiHostFuzzTestCasePkg/DEBUG_AFL/X64/TestIdentifyAtaDevice* +-rwxr-xr-x 1 root root 1149560 Dec 7 20:07 Build/UefiHostFuzzTestCasePkg/DEBUG_AFL/X64/TestPartition* +-rwxr-xr-x 1 root root 207256 Dec 7 20:07 Build/UefiHostFuzzTestCasePkg/DEBUG_AFL/X64/TestPeiGpt* +-rwxr-xr-x 1 root root 383688 Dec 7 20:07 Build/UefiHostFuzzTestCasePkg/DEBUG_AFL/X64/TestPeiUsb* +-rwxr-xr-x 1 root root 1164584 Dec 7 20:07 Build/UefiHostFuzzTestCasePkg/DEBUG_AFL/X64/TestTcg2MeasureGptTable* +-rwxr-xr-x 1 root root 1165784 Dec 7 20:07 Build/UefiHostFuzzTestCasePkg/DEBUG_AFL/X64/TestTcg2MeasurePeImage* +-rwxr-xr-x 1 root root 268480 Dec 7 20:07 Build/UefiHostFuzzTestCasePkg/DEBUG_AFL/X64/TestTpm2CommandLib* +-rwxr-xr-x 1 root root 1267064 Dec 7 20:07 Build/UefiHostFuzzTestCasePkg/DEBUG_AFL/X64/TestUdf* +-rwxr-xr-x 1 root root 1347160 Dec 7 20:07 Build/UefiHostFuzzTestCasePkg/DEBUG_AFL/X64/TestUsb* +-rwxr-xr-x 1 root root 2096272 Dec 7 20:07 Build/UefiHostFuzzTestCasePkg/DEBUG_AFL/X64/TestValidateTdxCfv* +-rwxr-xr-x 1 root root 1702408 Dec 7 20:07 Build/UefiHostFuzzTestCasePkg/DEBUG_AFL/X64/TestVariableSmm* +-rwxr-xr-x 1 root root 1171248 Dec 7 20:07 Build/UefiHostFuzzTestCasePkg/DEBUG_AFL/X64/TestVirtio10Blk* +-rwxr-xr-x 1 root root 1085704 Dec 7 20:07 Build/UefiHostFuzzTestCasePkg/DEBUG_AFL/X64/TestVirtioBlk* +-rwxr-xr-x 1 root root 1086016 Dec 7 20:07 Build/UefiHostFuzzTestCasePkg/DEBUG_AFL/X64/TestVirtioBlkReadWrite* +-rwxr-xr-x 1 root root 937816 Dec 7 20:07 Build/UefiHostFuzzTestCasePkg/DEBUG_AFL/X64/TestVirtioPciDevice* +``` + +## Installing and setting up LibFuzzer + +For LibFuzzer, it is assumed that a modern version of Clang/LLVM is installed on your system. For example, at the time this document was written, the Ubuntu 22.04 default package for 'clang' and 'llvm' install version 14. If you wish or need to install and build from source, see the [LLVM web-site](https://releases.llvm.org/). For fuzzing with LibFuzzer in HBFA-FL, the necessary steps for setting up the right environment includes setting a few environment variables, as shown in the following. Take care to ensure you provide the correct paths for the 'clang' and 'llvm-symbolizer' binaries. + +```console +root@a791b2478af5:~/hbfa_workspace# export CLANG_PATH=/usr/bin/ +root@a791b2478af5:~/hbfa_workspace# export ASAN_SYMBOLIZER_PATH=$CLANG/llvm-symbolizer +``` + +### Test build for the included fuzzing test-harnesses with LibFuzzer as the fuzzer + +Before attempting to build the fuzzing test-harnesses, we should re-generate the 'build_rule.txt' and 'tools_def.txt' configuration files and copy those to the EDK-II configuration directory. + +```console +root@a791b2478af5:~/hbfa_workspace# python3 hbfa-fl/HBFA/UefiHostTestTools/HBFAEnvSetup.py +root@a791b2478af5:~/hbfa_workspace# cp hbfa-fl/HBFA/UefiHostFuzzTestPkg/Conf/build_rule.txt edk2/Conf/build_rule.txt +root@a791b2478af5:~/hbfa_workspace# cp hbfa-fl/HBFA/UefiHostFuzzTestPkg/Conf/tools_def.txt edk2/Conf/tools_def.txt +``` + +Lastly, we invoke the build command, this time specifying 'LIBFUZZER' with the '-t' option for the build target. + +```console +root@a791b2478af5:~/hbfa_workspace# build -p hbfa-fl/HBFA/UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dsc -a X64 -t LIBFUZZER +``` + +As with the build for AFL, if all is set-up correctly, all of the included test-cases should build without error and can be seen in subdirectories under the 'Build' directory, e.g. see the following directory listing. + +```console +root@a791b2478af5:~/hbfa_workspace# ll Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/Test* +-rwxr-xr-x 1 root root 1887656 Dec 7 22:39 Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestBmpSupportLib* +-rwxr-xr-x 1 root root 1851200 Dec 7 22:39 Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestCapsulePei* +-rwxr-xr-x 1 root root 1981072 Dec 7 22:39 Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestFileName* +-rwxr-xr-x 1 root root 1791440 Dec 7 22:39 Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestFmpAuthenticationLibPkcs7* +-rwxr-xr-x 1 root root 1801336 Dec 7 22:39 Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestFmpAuthenticationLibRsa2048Sha256* +-rwxr-xr-x 1 root root 2013056 Dec 7 22:39 Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestIdentifyAtaDevice* +-rwxr-xr-x 1 root root 2610336 Dec 7 22:39 Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestPartition* +-rwxr-xr-x 1 root root 1880272 Dec 7 22:39 Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestPeiGpt* +-rwxr-xr-x 1 root root 2031512 Dec 7 22:39 Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestPeiUsb* +-rwxr-xr-x 1 root root 2595768 Dec 7 22:39 Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestTcg2MeasureGptTable* +-rwxr-xr-x 1 root root 2601456 Dec 7 22:39 Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestTcg2MeasurePeImage* +-rwxr-xr-x 1 root root 1945488 Dec 7 22:39 Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestTpm2CommandLib* +-rwxr-xr-x 1 root root 2643528 Dec 7 22:39 Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestUdf* +-rwxr-xr-x 1 root root 2737248 Dec 7 22:39 Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestUsb* +-rwxr-xr-x 1 root root 3115320 Dec 7 22:39 Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestValidateTdxCfv* +-rwxr-xr-x 1 root root 3024768 Dec 7 22:39 Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestVariableSmm* +-rwxr-xr-x 1 root root 2637264 Dec 7 22:39 Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestVirtio10Blk* +-rwxr-xr-x 1 root root 2535064 Dec 7 22:39 Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestVirtioBlk* +-rwxr-xr-x 1 root root 2535432 Dec 7 22:39 Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestVirtioBlkReadWrite* +-rwxr-xr-x 1 root root 2402336 Dec 7 22:39 Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestVirtioPciDevice* +``` + +## Setting up conveniences and additional path and environment variables for HBFA-FL + +A few additional items should be set-up to help improve usability of HBFA-FL. First, a few directories should be added to the system PATH, as well as a value for 'LLVM_PROFILE_FILE' should be specified if you intend to use LLVM-based coverage data with HBFA-FL. + +```console +export PATH="$PATH:$WORKSPACE/hbfa-fl/HBFA/UefiHostTestTools/" +export PATH="$PATH:$WORKSPACE/hbfa-fl/HBFA/UefiHostTestTools/Report/" +export LLVM_PROFILE_FILE="$WORKSPACE/fuzz_session.profraw" +``` + +Last, ensuring several Python scripts associated with HBFA-FL are executable is recommended for usability. The following files should be set executable(here the files are relative to the $WORKSPACE environment variable you have selected, e.g. /root/hbfa_workspace in the present example). + +- hbfa-fl/HBFA/UefiHostTestTools/Run*.py +- hbfa-fl/HBFA/UefiHostTestTools/Report/ReportMain.py +- hbfa-fl/HBFA/UefiHostTestTools/Report/GenCodeCoverage.py + +[<<](./README.md) Back | Return to [Summary](../SUMMARY.md) | Next [>>](../fuzzing/README.md) \ No newline at end of file diff --git a/docs/src/tutorials/README.md b/docs/src/tutorials/README.md new file mode 100644 index 0000000..3b9b4e2 --- /dev/null +++ b/docs/src/tutorials/README.md @@ -0,0 +1,7 @@ +# Tutorials + +Available tutorials: + +[HBFA-FL: Writing a fuzzing harness](./writingafuzzingharness.md) + +Return to [Summary](../SUMMARY.md) \ No newline at end of file diff --git a/docs/src/tutorials/writingafuzzingharness.md b/docs/src/tutorials/writingafuzzingharness.md new file mode 100644 index 0000000..9e40c0e --- /dev/null +++ b/docs/src/tutorials/writingafuzzingharness.md @@ -0,0 +1,2342 @@ +# HBFA-FL: Writing a fuzzing harness + +For this tutorial, we will be examining an example UEFI driver and how we can develop a fuzzing harness in HBFA-FL to find issues with the driver. Specifically, the fuzzing test harness for HBFA will be for fuzzing with LibFuzzer (and AFL). To do this, we will first examine an example UEFI driver, modify this driver to introduce a few vulnerabilities/issues. Following this, we will examine how to go about developing a fuzzing harness in HBFA-FL and discovering the issues. + +## Table of Contents + +- [HBFA-FL: Writing a fuzzing harness](#hbfa-fl-writing-a-fuzzing-harness) + - [Table of Contents](#table-of-contents) + - [Setting up an HBFA-FL environment for this tutorial](#setting-up-an-hbfa-fl-environment-for-this-tutorial) + - [Setting up and environment for running the HelloWorld.efi driver from an UEFI shell](#setting-up-and-environment-for-running-the-helloworldefi-driver-from-an-uefi-shell) + - [Running QEMU and accessing the UEFI shell](#running-qemu-and-accessing-the-uefi-shell) + - [Edk2 HelloWorld application example - Building the application](#edk2-helloworld-application-example---building-the-application) + - [Edk2 HelloWorld application example - Running the application (optional)](#edk2-helloworld-application-example---running-the-application-optional) + - [Extending the UEFI driver and creating a HelloWorldLib library](#extending-the-uefi-driver-and-creating-a-helloworldlib-library) + - [Files that we will be modifying or creating when extending the HelloWorld Driver](#files-that-we-will-be-modifying-or-creating-when-extending-the-helloworld-driver) + - [Files that we will be modifying or creating for HelloWorldLib Library](#files-that-we-will-be-modifying-or-creating-for-helloworldlib-library) + - [HelloWorld.c: Examining the code](#helloworldc-examining-the-code) + - [Additions to source-code](#additions-to-source-code) + - [HelloWorld.inf: Examining the source](#helloworldinf-examining-the-source) + - [HelloWorldLib: Examining the source code](#helloworldlib-examining-the-source-code) + - [HelloWorldLib.c: Examining the source code](#helloworldlibc-examining-the-source-code) + - [HelloWorldLib.inf: Examining the source code](#helloworldlibinf-examining-the-source-code) + - [HelloWorldLib.h: Examining the source code](#helloworldlibh-examining-the-source-code) + - [Updates: Adding a reference to HelloWorldLib in the platform file EmulatorPkg.dsc](#updates-adding-a-reference-to-helloworldlib-in-the-platform-file-emulatorpkgdsc) + - [Building the HelloWorld UEFI shell program](#building-the-helloworld-uefi-shell-program) + - [Verifying the bug in a UEFI shell (optional)](#verifying-the-bug-in-a-uefi-shell-optional) + - [TestHelloWorld: Creating a fuzzing test harnesses in HBFA](#testhelloworld-creating-a-fuzzing-test-harnesses-in-hbfa) + - [Where to create and save a fuzzing test case harness](#where-to-create-and-save-a-fuzzing-test-case-harness) + - [Whats needed in the fuzzing harness files (.c and .inf)?](#whats-needed-in-the-fuzzing-harness-files-c-and-inf) + - [The fuzzing harness test logic (C-source code file)](#the-fuzzing-harness-test-logic-c-source-code-file) + - [The module description file (INF file)](#the-module-description-file-inf-file) + - [Developing a fuzzing harness for HelloWorldLib](#developing-a-fuzzing-harness-for-helloworldlib) + - [Files that we will be modifying or creating when creating the fuzzing harness, TestHelloWorld](#files-that-we-will-be-modifying-or-creating-when-creating-the-fuzzing-harness-testhelloworld) + - [TestHelloWorld.c: Examining the source code](#testhelloworldc-examining-the-source-code) + - [TestHelloWorld.inf: Examining the source code](#testhelloworldinf-examining-the-source-code) + - [UefiHostTestPkg.dsc: Examining the source code](#uefihosttestpkgdsc-examining-the-source-code) + - [Building the TestHelloWorld fuzzing harness](#building-the-testhelloworld-fuzzing-harness) + - [Using the 'Build' command](#using-the-build-command) + - [Using the HBFA helper scripts](#using-the-hbfa-helper-scripts) + - [Fuzzing HelloWorldLib for vulnerabilities with LibFuzzer](#fuzzing-helloworldlib-for-vulnerabilities-with-libfuzzer) + - [Reproducing the crash](#reproducing-the-crash) + - [Debugging the crash](#debugging-the-crash) + +## Setting up an HBFA-FL environment for this tutorial + +For this tutorial is it necessary to have an environment setup for EDK2 and HBFA-FL. For this, we recommend installing HBFA-FL as described in the [HBFA-FL: A Quick Install Guide](). Optionally, you may set-up a separate environment where you can run the test/example driver (HelloWorld.efi) in an emulated UEFI shell. The set-up for these will leverage QEMU for the emulation and some details are included in the following sub-section. + +### Setting up and environment for running the HelloWorld.efi driver from an UEFI shell + +The following is an optional set-up and not required for fuzzing with HBFA. The following instructions demonstrate how to set-up the environment on an Ubuntu (22.04) desktop operating system; however, similar approaches can be used for other set-ups/configurations. Here, we will leverage the QEMU system emulator and a build Tianocore EDK2 OVMF UEFI image to provide access to a UEFI shell environment. When the HelloWorld.efi driver is built for the tutorial, the application should be copied from the HBFA build environment to a location accessible from the emulated (QEMU) UEFI shell environment. From there, you can run and interact with the driver. Further, this will provide an environment where you can confirm operation of the driver, as well as allow for you to test any modifications, etc. + +1. Assuming an Ubuntu 22.04 environment, ensure that the appropriate package is installed for Qemu (e.g. the 'qemu-kvm' package). Ensure that the 'qemu-system-x86_64' is available. +2. Next, you will need a copy of the Tianocore EDK II [OVMF](https://github.com/tianocore/tianocore.github.io/wiki/OVMF-FAQ) firmware image. The is included in EDK II and can be built within that environment. However, the package management system for most main-line Linux distributions will include a pre-built image. For Ubuntu 22.04, this package is 'ovmf'. Therefore a simple 'apt install ovmf' should complete and installation of the firmware. The installation should place a copy of the firmware at the following location: /usr/share/ovmf/OVMF.fd. +3. Last, download and have a suitable operating system ISO. Here we'll use the Ubuntu 22.04 Desktop ISO from [Ubuntu](https://ubuntu.com/download/desktop). + +#### Running QEMU and accessing the UEFI shell + +Assuming the above set-up has been completed, the following command can be used to run the emulated environment. + +```console +$ qemu-system-x86_64 -bios /usr/share/ovmf/OVMF.fd -cdrom ~/Downloads/ubuntu-22.04.2-desktop-amd64.iso -hda fat:./share,format=directory +``` + +Importantly, the OVMF.fd image is used (specified via the '-bios' parameter). Additionally, the '-cdrom' option is used to specify the location for the Ubuntu 22.04 ISO image. Last, in this example a directory 'share' located in the run directory is used. When invoked ine the manner shown, the folder will be presented to the emulated system as a FAT32-formatted disk containing the files saved in the directory. In this case, you will copy the built HelloWorld.efi binary to this location and the file will be accessible from a file system accessible in the UEFI shell. + +When the previous command is ran, you should be presented with a Tianocore splash screen followed by the GNU GRUB boot loader (as shown in the following image). From this point, we'll step a few menus and ultimately to gain access to the UEFI shell. + +
+ Example Grub Boot Loader +
Example of Grub boot loader presented from booting of Ubuntu 22.04 ISO image under QEMU.
+
+ +From the GRUB bootloader, select ``UEFI Firmware Settings``. Following this, you will be presented with the UEFI settings screen. From there you should select ``Boot Manager`` as shown in the following. + +
+ Example Grub Boot Loader +
From the 'UEFI Firmware Settings' (accessed from Grub), selecting the Boot Manager option.
+
+ +Once you have entered the ``Boot Manager``, there is an option available to select ``EFI Internal Shell`` (as shown in the following screenshot). + +
+ Boot Manager Options +
A view of the Boot Manager Menu. An interactive UEFI shell can be accessed via the 'EFI Internal Shell' option.
+
+ +Once you have selected the EFI shell, you will be presented with an interactive UEFI shell. Noting you will need to press the 'Escape' key before the timer expires. You should see a shell console similar to that shown in the following screenshot. + +
+ An interactive UEFI shell +
A view of the UEFI Interactive Shell console.
+
+ +## Edk2 HelloWorld application example - Building the application + +Included in the Edk2 distribution is a [HelloWorld](https://github.com/tianocore/edk2/tree/master/MdeModulePkg/Application/HelloWorld) example driver application. This driver is intended to act as an example UEFI shell application, which will simply print "UEFI Hello World!" to the console when ran from a UEFI shell. We'll quickly cover building this application and then look at an example of it running in a UEFI shell. + +First, the HelloWorld application can be found by examining the 'MdeModulePkg/Application/HelloWorld/' directory withing the edk2 source code. A listing of the directory from EDK II is shown in the following. + +```console +[root@12a70ad5bf59 hbfa_workspace]# ls edk2/MdeModulePkg/Application/HelloWorld/ +HelloWorld.c HelloWorld.inf HelloWorld.uni HelloWorldExtra.uni HelloWorldStr.uni +``` + +Two important files to take note of here are the ``HelloWorld.c`` and the ``HelloWorld.inf`` files. The ``HelloWorld.c`` file contains the source code and logic for the application. The ``HelloWorld.inf`` build description file is used by the EDK II build system for informing various dependencies and understanding the type of application being build. Don't worry, we'll dive into some more details on these files when we extend the functionality of this program. For now, we'll focus on simply building and verifying the program runs. Lastly, the '.uni' resource files are used as a resource for the text printed to the console + +Compiling the HelloWorld application is relatively straightforward using the EDK II build system. From the 'edk2' directory we can invoke the EDK II 'build' command as shown: + +``` +[root@00c4495bd766 edk2]# build -m MdeModulePkg/Application/HelloWorld/HelloWorld.inf -a X64 -b DEBUG -t GCC5 +``` + +Here, the '-m' option is used for build description file for the module we are building (HelloWorld.inf); '-a' is used for the architecture ('X64'); '-b' is set as 'DEBUG', so that debugging symbols will be included; and '-t' is GCC5 so that the GCC compiler will be the target compiler used for the build. Behind the scenes, the [EmulatorPkg](https://github.com/tianocore/edk2/blob/master/EmulatorPkg/Readme.md) platform is used. This is noted, as we'll need to add some updates to the platform description file when we extend the functionality of the HelloWorld application. When the build is complete, you should see a file ``HelloWorld.efi``, as shown in the following file listing from the 'Build/EmulatorX64/DEBUG_GCC5/X64/MdeModulePkg/Application/HelloWorld/HelloWorld/OUTPUT/'. Note, the 'Build' directory will be + +``` +[root@00c4495bd766 OUTPUT]# ls +AutoGen.obj HelloWorld.lib HelloWorld.txt HelloWorldhii.lib +AutoGen.obj.deps HelloWorld.map HelloWorld.uni HelloWorldhii.rc +HelloWorld.efi HelloWorld.obj HelloWorldExtra.uni object_files.lst +HelloWorld.inf HelloWorld.obj.deps HelloWorldStrDefs.hpk static_library_files.lst +``` + +### Edk2 HelloWorld application example - Running the application (optional) + +If you wish to verify that the HelloWorld.efi application is working, you can take the approach outlined in the section: [Running the QEMU and accessing the UEFI shell](#running-the-qemu-and-accessing-the-uefi-shell). Here, you need to copy the ``HelloWorld.efi`` program into the directory you wish to share as a FAT partition before starting QEMU. Once you have accessed the shell, you should see a console input similar to the following. + +
+ An interactive UEFI shell +
A view of the UEFI Interactive Shell console.
+
+ +You can list the mapped file systems by running the 'map' command as shown in the following figure. + +
+ +
Using the 'map' command to list file systems in UEFI shell.
+
+ +If you type the file system name from the mapping table (e.g. 'FS0:'), then the current working directory will be changed to that location. As shown in the following, we have switched to 'FS0:' and we list the contents of the file system with the 'ls' command. Here you can see the ``HelloWorld.efi`` application in the output. + +
+ +
Changing to 'FS0:' and using the 'ls' command to list files, showing the 'HelloWorld.efi' file.
+
+ +Last, the application can be ran by simply typing the name the application (file name) ``HelloWorld.efi``. As anticipated, the program will print the text 'UEFI Hello World!' to the console, as shown in the following figure. + +
+ +
Running the 'HelloWorld.efi' application from the UEFI shell.
+
+ +## Extending the UEFI driver and creating a HelloWorldLib library + +We will extend the UEFI driver, adding functionality to read and process arguments from the UEFI shell command-line. Importantly, the functionality we add will introduce a stack overflow vulnerability. To do this, will create a HelloWorldLib library that will process the first argument read in by the HelloWorld application. Later in this tutorial, we will develop a fuzzing harness for the HelloWorldLib library to fuzz and find this vulnerability. Firstly, a few tables are included to provide an overview of what files we'll need to modify or create when extending HelloWorld and adding our HelloWorldLib library. A relative path/location from the edk2 source code folder is provided for each file presented. + +### Files that we will be modifying or creating when extending the HelloWorld Driver + +| Filename | Description | File-Path (relative to /root/hbfa_workspace/) | +| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- | +| HelloWorld.c | The HelloWorld EFI application included with EDK2. This file is further modified to read/access arguments when invoked from the UEFI shell. Further, the file calls a function from HelloWorldLib that will process the first argument in a non-secure manner. | edk2/MdeModulePkg/Application/HelloWorld/ | +| HelloWorld.inf | The INF (build description file) for the HelloWorld application. When extending the functionality for this application (including additional libraries), the INF file must also be updated accordingly. | edk2/MdeModulePkg/Application/HelloWorld/ | + +### Files that we will be modifying or creating for HelloWorldLib Library + +| Filename | Description | File-Path (relative to /root/hbfa_workspace/) | +| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- | +| HelloWorldLib.c | The library code. Here we add a vulnerable function that processes the first argument. | edk2/MdeModulePkg/Library/HelloWorldLib/ | +| HelloWorldLib.inf | The INF (build description file) for the HelloWorldLib library. | edk2/MdeModulePkg/Library/HelloWorldLib/ | +| HelloWorldLib.h | A corresponding header file for the HelloWorldLib.c file. | edk2/MdeModulePkg/Include/Library/ | +| EmulatorPkg.dsc | This is the platform we build our test driver for. Depending on the specific platform being targeted, you will need to update the appropriate platform description file. Here the[EmulatorPkg](https://github.com/tianocore/edk2/blob/master/EmulatorPkg/Readme.md) is used. One must add a reference to the HelloWorldLib library (providing a name and a relative path to the INF file). This is required for the build system to find available libraries. | edk2/EmulatorPkg/ | + +### HelloWorld.c: Examining the code + +The modified source code for HelloWorld.c is shown in the following. Additionally, a figure is included to help highlight the areas where new code has been added. + +
+ Source-code for HelloWorld.c + +```c +/** @file + +// + This sample application bases on HelloWorld PCD setting + to print "UEFI Hello World!" to the UEFI Console. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include + +// +// String token ID of help message text. +// Shell supports to find help message in the resource section of an application image if +// .MAN file is not found. This global variable is added to make build tool recognizes +// that the help string is consumed by user and then build tool will add the string into +// the resource section. Thus the application can use '-?' option to show help message in +// Shell. +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_STRING_ID mStringHelpTokenId = STRING_TOKEN (STR_HELLO_WORLD_HELP_INFORMATION); + + +/** + The user Entry Point for Application. The user code starts with this function + as the real entry point for the application. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + UINT32 Index; + + Index = 0; + + EFI_STATUS Status; + EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters; + + Status = gBS->HandleProtocol( + ImageHandle, + &gEfiShellParametersProtocolGuid, + (VOID **) &ShellParameters + ); + + + if (Status == EFI_SUCCESS) + { + for(int i=0; iArgc; i++) + { + Print(L"Argv[%d]: %s\n", i, ShellParameters->Argv[i]); + } + + } + + +// Shell supports to find help message in the resource section of an application image if +// .MAN file is not found. This global variable is added to make build tool recognizes + + // + // Three PCD type (FeatureFlag, UINT32 and String) are used as the sample. + // + if (FeaturePcdGet (PcdHelloWorldPrintEnable)) { + for (Index = 0; Index < PcdGet32 (PcdHelloWorldPrintTimes); Index++) { + // + // Use UefiLib Print API to print string to UEFI console + // + Print ((CHAR16 *)PcdGetPtr (PcdHelloWorldPrintString)); + } + } + + + if (Status == EFI_SUCCESS) + { + // Process first argument from UEFL Shell if there is an argument + if (ShellParameters->Argc > 1) + { + ProcessArgument(ShellParameters); + } + + } + + return EFI_SUCCESS; + Print( L"S\n"); +} +``` + +
+ +#### Additions to source-code + +The updates to the source are shown in the Figure below. In the section labeled A, we can see two additional file includes have been added. The first is for our HelloWorldLib library source. We'll be calling a function from that library ('ProcessArgument()') which will be used to process the first argument provided to our application. (The call to ProcessArgument is made in the part labeled C in the Figure.). Additionally, we include the ``ShellParameters.h`` file, which will give us access to the necessary interface and structures for accessing the command-line arguments for our application. For additional information on related interfaces and structures in the UEFI shell, see the [UEFI Shell Specification](https://uefi.org/sites/default/files/resources/UEFI_Shell_2_2.pdf). + +For the section labeled B, this part defines a reference to a EFI_SHELL_PARAMETERS_PROTOCOL structure (ShellParameters), which once it is populated will contain references to the Argv array of command line arguments. To populate the ShellParameters structure, we access it via a call to ``gBS->HandleProtocol`` to ensure the Shell Parameters Protocol is supported/accessible. (For more details about UEFI Protocol Handler Services and Protocol Interface Functions, see the [UEFI specification documentation](https://uefi.org/specs/UEFI/2.10/07_Services_Boot_Services.html#protocol-handler-services) and the [UEFI Shell Specification](https://uefi.org/sites/default/files/resources/UEFI_Shell_2_2.pdf) documents). Once we have the reference to the EFI_SHELL_PARAMETERS_PROTOCOL structure, it is straightforward to access the Argc and Argv parameters. Here, we loop through the arguments and they are printed to the screen. + +Last, in the section labeled C, if the number of arguments (Argc) is greater than 1 (ensuring we have a command-line argument to process), we then call the ``ProcessArgument`` function from HelloWorldLib, passing the reference to an EFI_SHELL_PARAMETERS_PROTOCOL structure (ShellParameters). + +
+ +
Code added to HelloWorld.c (highlighted in red boxes).
+
+ +### HelloWorld.inf: Examining the source + +The modified source code for the build-description file HelloWorld.inf is shown in the following. Here, we simply need to add an entry for the HelloWorldLib in the ``[LibrariesClasses]`` section for the file. Note: if you want to learn a little more about the INF file, jump ahead to the section: [The module description file (INF file)](#the-module-description-file-inf-file) + +
+ Source-code for HelloWorld.inf + +```ini +## @file +# Sample UEFI Application Reference EDKII Module. +# +# This is a sample shell application that will print "UEFI Hello World!" to the +# UEFI Console based on PCD setting. +# +# It demos how to use EDKII PCD mechanism to make code more flexible. +# +# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = HelloWorld + MODULE_UNI_FILE = HelloWorld.uni + FILE_GUID = 6987936E-ED34-44db-AE97-1FA5E4ED2116 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain + +# +# This flag specifies whether HII resource section is generated into PE image. +# + UEFI_HII_RESOURCE_SECTION = TRUE + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + HelloWorld.c + HelloWorldStr.uni + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + PcdLib + HelloWorldLib + +[FeaturePcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdHelloWorldPrintEnable ## CONSUMES + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdHelloWorldPrintString ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdHelloWorldPrintTimes ## SOMETIMES_CONSUMES + +[UserExtensions.TianoCore."ExtraFiles"] + HelloWorldExtra.uni + +``` + +
+ +### HelloWorldLib: Examining the source code + +For the HelloWorldLib, three new files need to be created: + +1. HelloWorldLib.c +2. HelloWorldLib.inf and +3. HelloWorldLib.h. + +The source for these files is included in the following sub-sections. + +#### HelloWorldLib.c: Examining the source code + +The source code for HelloWorldLib.c is included below. Noting the code is intentionally written to be non-secure. The ``ProcessArgument`` function is intended to be exposed and called from HelloWorld.c. This function takes a reference to a EFI_SHELL_PARAMETERS_PROTOCOL struct as its argument. A character array is defined, which will be character array ``MyBuffer`` stored on the stack of fixed size. A crude implementation of a ``MyStrCpy`` is then used to copy the first argument (from the EFI_SHELL_PARAMETERS_PROTOCOL struct) into ``MyBuffer``. + +
+ Source-code for HelloWorld.c + +```c +/** @file + +// + This sample application bases on HelloWorld PCD setting + to print "UEFI Hello World!" to the UEFI Console. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include + +int GetLen(const char *s) +{ + int len = 0; + while ( 1 ) + { + if ( (s[len] == 0x0) ) { + if ( (s[len+1] == 0x0)) { + return len/2; + } + } + len = len + 2; + } +} + +/** + A dangerous copy function + +**/ +VOID MyStrCpy(char *dst, const char *src) +{ + int i = 0; + int len = GetLen(src); + Print(L"Length of string copy: %d\n", len); + while (i < 2*len) + { + *dst++ = *src++; + i++; + } +} + +/** + A vulnerable function that processes UEFI shell command-line arguments + + @param[in] MyShellParameters Shell parameters (arguments provided to HelloWorld.efi) as an EFI_SHELL_PARAMETERS_PROTOCOL structure. + +**/ +VOID ProcessArgument ( + IN EFI_SHELL_PARAMETERS_PROTOCOL *MyShellParameters + ) +{ + char MyBuffer[16]; + MyStrCpy(MyBuffer, (char *)MyShellParameters->Argv[1]); + Print(L"MyBuffer: %s\n", MyBuffer); +} + +``` + +
+ +#### HelloWorldLib.inf: Examining the source code + +The source code for HelloWorldLib.inf is included below. The file is based off of the original HelloWorld.inf. However, there are a few differences (items removed, changed, and added); the differences are described in the following table. + +| INF Section | Field | Notes | +| ------------------------------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| ``[Defines]`` | BASE_NAME | The basename is updated to HelloWorldLib. | +| ``[Defines]`` | MODULE_UNI_FILE | This is removed. | +| ``[Defines]`` | FILE_GUID | A unique value should be generated. For example, there are several[online](https://guidgenerator.com/) GUID generators that can be used. | +| ``[Defines]`` | MODULE_TYPE | This is updated to BASE (used for source code that is not tied to any specific execution environment, see this[document](https://github.com/tianocore-docs/edk2-InfSpecification/blob/master/appendix_f_module_types.md) for types | +| ``[Defines]`` | ENTRY_POINT | This is removed. | +| ``[Defines]`` | LIBRARY_CLASS | This field is added and set to the library name 'HelloWorldLib'. | +| ``[Protocols]`` | - | A protocols section with a dependence on gEfiShellParametersProtocolGuid is added. | +| ``[FeaturePcd]`` | - | This is removed. | +| ``[Pcd]`` | - | This is removed. | +| ``[UserExtensions.TianoCore."ExtraFiles"]`` | - | This is removed. | +| ``[Sources]`` | - | This is updated and the only entry is to the library source file HelloWorldLib.c. | + +
+ Source-code for HelloWorldLib.inf + +```ini +## @file +# Sample UEFI Application Reference EDKII Module. +# +# This is a sample shell application that will print "UEFI Hello World!" to the +# UEFI Console based on PCD setting. +# +# It demos how to use EDKII PCD mechanism to make code more flexible. +# +# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = HelloWorldLib + FILE_GUID = 2e20917a-a9ab-4a19-99ba-4acb72a70f22 + VERSION_STRING = 1.0 + MODULE_TYPE = BASE + LIBRARY_CLASS = HelloWorldLib + +# +# This flag specifies whether HII resource section is generated into PE image. +# + UEFI_HII_RESOURCE_SECTION = TRUE + +# +# 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 + +[Protocols] + gEfiShellParametersProtocolGuid + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + PcdLib + +[Sources] + HelloWorldLib.c + +``` + +
+ +#### HelloWorldLib.h: Examining the source code + +The source code for HelloWorldLib.h is included in the following. The file has a dependency the Protocol/ShellParameters.h file, which has includes the definition for the EFI_SHELL_PARAMETERS_PROTOCOL structure. Last, the ``ProcessArgument`` function prototype is provided as we wish to call this externally (from our HelloWorld.c application). + +
+ Source-code for HelloWorldLib.h + +```c +#ifndef __HELLOWORLD_LIB_H__ +#define __HELLOWORLD_LIB_H__ + +#include + +VOID ProcessArgument ( + IN EFI_SHELL_PARAMETERS_PROTOCOL *MyShellParameters + ); + +#endif + +``` + +
+ +### Updates: Adding a reference to HelloWorldLib in the platform file EmulatorPkg.dsc + +Lastly, since the HelloWorld application is built for the Emulator package platform, we will need to add an entry for the HelloWorldLib library in the ``[LibraryClasses]`` section of the [edk2/EmulatorPkg/EmulatorPkg.dsc](https://github.com/tianocore/edk2/blob/master/EmulatorPkg/EmulatorPkg.dsc) file. To do this, the following line should be added to the ``[LibraryClasses]`` section: + +```c +HelloWorldLib|MdeModulePkg/Library/HelloWorldLib/HelloWorldLib.inf +``` + +
+ Source-code for EmulatorPkg.dsc + +```ini +## @file +# UEFI/PI Emulation Platform with UEFI HII interface supported. +# +# The Emulation Platform can be used to debug individual modules, prior to creating +# a real platform. This also provides an example for how an DSC is created. +# +# Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2010 - 2011, Apple Inc. All rights reserved.
+# Copyright (c) Microsoft Corporation. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + PLATFORM_NAME = EmulatorPkg + PLATFORM_GUID = 05FD064D-1073-E844-936C-A0E16317107D + PLATFORM_VERSION = 0.3 + DSC_SPECIFICATION = 0x00010005 + OUTPUT_DIRECTORY = Build/Emulator$(ARCH) + + SUPPORTED_ARCHITECTURES = X64|IA32 + BUILD_TARGETS = DEBUG|RELEASE|NOOPT + SKUID_IDENTIFIER = DEFAULT + FLASH_DEFINITION = EmulatorPkg/EmulatorPkg.fdf + + + # + # Network definition + # + DEFINE NETWORK_SNP_ENABLE = FALSE + DEFINE NETWORK_IP6_ENABLE = FALSE + DEFINE NETWORK_TLS_ENABLE = FALSE + DEFINE NETWORK_HTTP_BOOT_ENABLE = FALSE + DEFINE NETWORK_HTTP_ENABLE = FALSE + DEFINE NETWORK_ISCSI_ENABLE = FALSE + DEFINE SECURE_BOOT_ENABLE = FALSE + + # + # Redfish definition + # + DEFINE REDFISH_ENABLE = FALSE + +[SkuIds] + 0|DEFAULT + +!include MdePkg/MdeLibs.dsc.inc + +[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 + SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf + PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf + FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.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 + + PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf + SmbiosLib|EmulatorPkg/Library/SmbiosLib/SmbiosLib.inf + + # + # Generic Modules + # + UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf + OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf + BootLogoLib|MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf + FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf + UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf + BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf + SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf + CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf + SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf + TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf + SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf + # + # Platform + # + PlatformBootManagerLib|EmulatorPkg/Library/PlatformBmLib/PlatformBmLib.inf + KeyMapLib|EmulatorPkg/Library/KeyMapLibNull/KeyMapLibNull.inf + !if $(REDFISH_ENABLE) == TRUE + RedfishPlatformHostInterfaceLib|EmulatorPkg/Library/RedfishPlatformHostInterfaceLib/RedfishPlatformHostInterfaceLib.inf + RedfishPlatformCredentialLib|EmulatorPkg/Library/RedfishPlatformCredentialLib/RedfishPlatformCredentialLib.inf + !endif + # + # Misc + # + DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf + PeiServicesTablePointerLib|EmulatorPkg/Library/PeiServicesTablePointerLibMagicPage/PeiServicesTablePointerLibMagicPage.inf + DebugLib|MdeModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf + LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf + CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf + TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf + VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf + VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf + VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf + VariableFlashInfoLib|MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseVariableFlashInfoLib.inf + SortLib|MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf + ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf + FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf + +!if $(SECURE_BOOT_ENABLE) == TRUE + RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf + PlatformSecureLib|SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.inf + AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf + SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf + PlatformPKProtectionLib|SecurityPkg/Library/PlatformPKProtectionLibVarPolicy/PlatformPKProtectionLibVarPolicy.inf + SecureBootVariableProvisionLib|SecurityPkg/Library/SecureBootVariableProvisionLib/SecureBootVariableProvisionLib.inf +!else + AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf +!endif + + # Adding HelloWorldLib + HelloWorldLib|MdeModulePkg/Library/HelloWorldLib/HelloWorldLib.inf + +[LibraryClasses.common.SEC] + PeiServicesLib|EmulatorPkg/Library/SecPeiServicesLib/SecPeiServicesLib.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + PeCoffGetEntryPointLib|EmulatorPkg/Library/PeiEmuPeCoffGetEntryPointLib/PeiEmuPeCoffGetEntryPointLib.inf + PeCoffExtraActionLib|EmulatorPkg/Library/PeiEmuPeCoffExtraActionLib/PeiEmuPeCoffExtraActionLib.inf + SerialPortLib|EmulatorPkg/Library/PeiEmuSerialPortLib/PeiEmuSerialPortLib.inf + PpiListLib|EmulatorPkg/Library/SecPpiListLib/SecPpiListLib.inf + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + TimerLib|EmulatorPkg/Library/PeiTimerLib/PeiTimerLib.inf + +[LibraryClasses.common.USER_DEFINED, LibraryClasses.common.BASE] + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf + MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + PpiListLib|EmulatorPkg/Library/SecPpiListLib/SecPpiListLib.inf + ThunkPpiList|EmulatorPkg/Library/ThunkPpiList/ThunkPpiList.inf + ThunkProtocolList|EmulatorPkg/Library/ThunkProtocolList/ThunkProtocolList.inf + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + PpiListLib|EmulatorPkg/Library/SecPpiListLib/SecPpiListLib.inf + PeiServicesLib|EmulatorPkg/Library/SecPeiServicesLib/SecPeiServicesLib.inf + + +[LibraryClasses.common.PEIM, LibraryClasses.common.PEI_CORE] + HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf + MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf + PeCoffGetEntryPointLib|EmulatorPkg/Library/PeiEmuPeCoffGetEntryPointLib/PeiEmuPeCoffGetEntryPointLib.inf + PeCoffExtraActionLib|EmulatorPkg/Library/PeiEmuPeCoffExtraActionLib/PeiEmuPeCoffExtraActionLib.inf + ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf + SerialPortLib|EmulatorPkg/Library/PeiEmuSerialPortLib/PeiEmuSerialPortLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf + TimerLib|EmulatorPkg/Library/PeiTimerLib/PeiTimerLib.inf + +[LibraryClasses.common.PEI_CORE] + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + +[LibraryClasses.common.PEIM] + PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf + +[LibraryClasses.common.DXE_CORE] + HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf + MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf + PeCoffExtraActionLib|EmulatorPkg/Library/DxeEmuPeCoffExtraActionLib/DxeEmuPeCoffExtraActionLib.inf + ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + TimerLib|EmulatorPkg/Library/DxeCoreTimerLib/DxeCoreTimerLib.inf + EmuThunkLib|EmulatorPkg/Library/DxeEmuLib/DxeEmuLib.inf + +[LibraryClasses.common.DXE_DRIVER, LibraryClasses.common.UEFI_DRIVER, LibraryClasses.common.UEFI_APPLICATION] +!if $(SECURE_BOOT_ENABLE) == TRUE + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf +!endif + +[LibraryClasses.common.DXE_RUNTIME_DRIVER] +!if $(SECURE_BOOT_ENABLE) == TRUE + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf +!endif + +[LibraryClasses.common.DXE_RUNTIME_DRIVER, LibraryClasses.common.UEFI_DRIVER, LibraryClasses.common.DXE_DRIVER, LibraryClasses.common.UEFI_APPLICATION] + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf + EmuThunkLib|EmulatorPkg/Library/DxeEmuLib/DxeEmuLib.inf + PeCoffExtraActionLib|EmulatorPkg/Library/DxeEmuPeCoffExtraActionLib/DxeEmuPeCoffExtraActionLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf + TimerLib|EmulatorPkg/Library/DxeTimerLib/DxeTimerLib.inf + +[PcdsFeatureFlag] + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|FALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreImageLoaderSearchTeSectionFirst|FALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplBuildPageTables|FALSE + +[PcdsFixedAtBuild] + gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy|0x00000000 + gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000040 + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x0f + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x1f + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizeNonPopulateCapsule|0x0 + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizePopulateCapsule|0x0 + gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|TRUE + + gEmulatorPkgTokenSpaceGuid.PcdEmuFirmwareFdSize|0x002a0000 + gEmulatorPkgTokenSpaceGuid.PcdEmuFirmwareBlockSize|0x10000 + gEmulatorPkgTokenSpaceGuid.PcdEmuFirmwareVolume|L"../FV/FV_RECOVERY.fd" +!if $(SECURE_BOOT_ENABLE) == TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x2800 + gEfiSecurityPkgTokenSpaceGuid.PcdUserPhysicalPresence|TRUE +!endif + + gEmulatorPkgTokenSpaceGuid.PcdEmuMemorySize|L"64!64" + + # Change PcdBootManagerMenuFile to UiApp + gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile|{ 0x21, 0xaa, 0x2c, 0x46, 0x14, 0x76, 0x03, 0x45, 0x83, 0x6e, 0x8a, 0xb6, 0xf4, 0x66, 0x23, 0x31 } + + +#define BOOT_WITH_FULL_CONFIGURATION 0x00 +#define BOOT_WITH_MINIMAL_CONFIGURATION 0x01 +#define BOOT_ASSUMING_NO_CONFIGURATION_CHANGES 0x02 +#define BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS 0x03 +#define BOOT_WITH_DEFAULT_SETTINGS 0x04 +#define BOOT_ON_S4_RESUME 0x05 +#define BOOT_ON_S5_RESUME 0x06 +#define BOOT_ON_S2_RESUME 0x10 +#define BOOT_ON_S3_RESUME 0x11 +#define BOOT_ON_FLASH_UPDATE 0x12 +#define BOOT_IN_RECOVERY_MODE 0x20 + gEmulatorPkgTokenSpaceGuid.PcdEmuBootMode|0 + + gEmulatorPkgTokenSpaceGuid.PcdEmuApCount|L"1" + + # For a CD-ROM/DVD use L"diag.dmg:RO:2048" + gEmulatorPkgTokenSpaceGuid.PcdEmuVirtualDisk|L"disk.dmg:FW" + gEmulatorPkgTokenSpaceGuid.PcdEmuGop|L"GOP Window" + gEmulatorPkgTokenSpaceGuid.PcdEmuFileSystem|L"." + gEmulatorPkgTokenSpaceGuid.PcdEmuSerialPort|L"/dev/ttyS0" + gEmulatorPkgTokenSpaceGuid.PcdEmuNetworkInterface|L"en0" + + gEmulatorPkgTokenSpaceGuid.PcdEmuCpuModel|L"Intel(R) Processor Model" + gEmulatorPkgTokenSpaceGuid.PcdEmuCpuSpeed|L"3000" + + # 0-PCANSI, 1-VT100, 2-VT00+, 3-UTF8, 4-TTYTERM + gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType|1 + +!if $(REDFISH_ENABLE) == TRUE + gEfiRedfishPkgTokenSpaceGuid.PcdRedfishRestExServiceDevicePath.DevicePathMatchMode|DEVICE_PATH_MATCH_MAC_NODE + gEfiRedfishPkgTokenSpaceGuid.PcdRedfishRestExServiceDevicePath.DevicePathNum|1 + # + # Below is the MAC address of network adapter on EDK2 Emulator platform. + # You can use ifconfig under EFI shell to get the MAC address of network adapter on EDK2 Emulator platform. + # + gEfiRedfishPkgTokenSpaceGuid.PcdRedfishRestExServiceDevicePath.DevicePath|{DEVICE_PATH("MAC(000000000000,0x1)")} + gEfiRedfishPkgTokenSpaceGuid.PcdRedfishRestExServiceAccessModeInBand|False + gEfiRedfishPkgTokenSpaceGuid.PcdRedfishDiscoverAccessModeInBand|False +!endif + +[PcdsDynamicDefault.common.DEFAULT] + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64|0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64|0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|0 + +[PcdsDynamicHii.common.DEFAULT] + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn|L"Setup"|gEmuSystemConfigGuid|0x0|80 + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow|L"Setup"|gEmuSystemConfigGuid|0x4|25 + gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|L"Timeout"|gEfiGlobalVariableGuid|0x0|10 + +[Components] +!if "IA32" in $(ARCH) || "X64" in $(ARCH) + !if "MSFT" in $(FAMILY) || $(WIN_HOST_BUILD) == TRUE + ## + # Emulator, OS WIN application + # CLANGPDB is cross OS tool chain. It depends on WIN_HOST_BUILD flag + # to build WinHost application. + ## + EmulatorPkg/Win/Host/WinHost.inf + !else + ## + # Emulator, OS POSIX application + ## + EmulatorPkg/Unix/Host/Host.inf + !endif +!endif + +!ifndef $(SKIP_MAIN_BUILD) + # + # Generic SEC + # + EmulatorPkg/Sec/Sec.inf + + ## + # PEI Phase modules + ## + MdeModulePkg/Core/Pei/PeiMain.inf + MdeModulePkg/Universal/PCD/Pei/Pcd.inf { + + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + } + MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf + MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf + + EmulatorPkg/BootModePei/BootModePei.inf + MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf + MdeModulePkg/Universal/Variable/Pei/VariablePei.inf + EmulatorPkg/AutoScanPei/AutoScanPei.inf + EmulatorPkg/FirmwareVolumePei/FirmwareVolumePei.inf + EmulatorPkg/FlashMapPei/FlashMapPei.inf + EmulatorPkg/ThunkPpiToProtocolPei/ThunkPpiToProtocolPei.inf + MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf + + ## + # DXE Phase modules + ## + MdeModulePkg/Core/Dxe/DxeMain.inf { + + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + SerialPortLib|EmulatorPkg/Library/DxeEmuStdErrSerialPortLib/DxeEmuStdErrSerialPortLib.inf + DxeEmuLib|EmulatorPkg/Library/DxeEmuLib/DxeEmuLib.inf + NULL|MdeModulePkg/Library/DxeCrc32GuidedSectionExtractLib/DxeCrc32GuidedSectionExtractLib.inf + NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf + } + MdeModulePkg/Universal/PCD/Dxe/Pcd.inf { + + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + } + + MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf + MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf { + + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + SerialPortLib|EmulatorPkg/Library/DxeEmuStdErrSerialPortLib/DxeEmuStdErrSerialPortLib.inf + } + + MdeModulePkg/Universal/Metronome/Metronome.inf + EmulatorPkg/RealTimeClockRuntimeDxe/RealTimeClock.inf + EmulatorPkg/ResetRuntimeDxe/Reset.inf + MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf + EmulatorPkg/FvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf + + MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf { + +!if $(SECURE_BOOT_ENABLE) == TRUE + NULL|SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf +!endif + } + + MdeModulePkg/Universal/EbcDxe/EbcDxe.inf + MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf + EmulatorPkg/EmuThunkDxe/EmuThunk.inf + EmulatorPkg/CpuRuntimeDxe/Cpu.inf + MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf + EmulatorPkg/PlatformSmbiosDxe/PlatformSmbiosDxe.inf + EmulatorPkg/TimerDxe/Timer.inf + +!if $(SECURE_BOOT_ENABLE) == TRUE + SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf +!endif + + MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf { + + NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf + } + MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf + MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf + MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf + MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf + MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf + MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf + MdeModulePkg/Universal/SerialDxe/SerialDxe.inf { + + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + SerialPortLib|EmulatorPkg/Library/DxeEmuSerialPortLib/DxeEmuSerialPortLib.inf + } + + MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf + MdeModulePkg/Universal/BdsDxe/BdsDxe.inf +!if "XCODE5" not in $(TOOL_CHAIN_TAG) + MdeModulePkg/Logo/LogoDxe.inf +!endif + MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.inf + MdeModulePkg/Application/UiApp/UiApp.inf { + + NULL|MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf + NULL|MdeModulePkg/Library/BootManagerUiLib/BootManagerUiLib.inf + NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerUiLib.inf + } + MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuApp.inf + + MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf + #{ + # + # NULL|EmulatorPkg/Library/DevicePathTextLib/DevicePathTextLib.inf + #} + + MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf + MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf + MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf + MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf + MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf + MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf + + EmulatorPkg/EmuBusDriverDxe/EmuBusDriverDxe.inf + EmulatorPkg/EmuGopDxe/EmuGopDxe.inf + EmulatorPkg/EmuSimpleFileSystemDxe/EmuSimpleFileSystemDxe.inf + EmulatorPkg/EmuBlockIoDxe/EmuBlockIoDxe.inf + EmulatorPkg/EmuSnpDxe/EmuSnpDxe.inf + + MdeModulePkg/Application/HelloWorld/HelloWorld.inf + + MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf + MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf + MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf + MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf + MdeModulePkg/Universal/PrintDxe/PrintDxe.inf + MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf { + + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + } + + FatPkg/EnhancedFatDxe/Fat.inf + +!if "XCODE5" not in $(TOOL_CHAIN_TAG) + ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf { + + gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE + } +!endif + ShellPkg/Application/Shell/Shell.inf { + + ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf + NULL|ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf + NULL|ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf + NULL|ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf + NULL|ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf + NULL|ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf + NULL|ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf + NULL|ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf + HandleParsingLib|ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf + OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf + SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf +# SafeBlockIoLib|ShellPkg/Library/SafeBlockIoLib/SafeBlockIoLib.inf +# SafeOpenProtocolLib|ShellPkg/Library/SafeOpenProtocolLib/SafeOpenProtocolLib.inf + BcfgCommandLib|ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + + + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0xFF + gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE + gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|8000 + } + +!endif + +!include NetworkPkg/Network.dsc.inc + +!if $(REDFISH_ENABLE) == TRUE + EmulatorPkg/Application/RedfishPlatformConfig/RedfishPlatformConfig.inf +!endif +!include RedfishPkg/Redfish.dsc.inc + +[BuildOptions] + # + # Disable deprecated APIs. + # + *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES + + MSFT:DEBUG_*_*_CC_FLAGS = /Od /Oy- + MSFT:NOOPT_*_*_CC_FLAGS = /Od /Oy- + GCC:DEBUG_CLANGPDB_*_CC_FLAGS =-O0 -Wno-unused-command-line-argument -Wno-incompatible-pointer-types -Wno-enum-conversion -Wno-incompatible-pointer-types -Wno-sometimes-uninitialized -Wno-constant-conversion -Wno-main-return-type + + MSFT:*_*_*_DLINK_FLAGS = /ALIGN:4096 /FILEALIGN:4096 /SUBSYSTEM:CONSOLE + MSFT:DEBUG_*_*_DLINK_FLAGS = /EXPORT:InitializeDriver=$(IMAGE_ENTRY_POINT) /BASE:0x10000 + MSFT:NOOPT_*_*_DLINK_FLAGS = /EXPORT:InitializeDriver=$(IMAGE_ENTRY_POINT) /BASE:0x10000 + +!if $(WIN_HOST_BUILD) == TRUE + # + # CLANGPDB tool chain depends on WIN_HOST_BUILD flag to generate the windows application. + # + GCC:*_CLANGPDB_*_DLINK_FLAGS = /ALIGN:4096 /FILEALIGN:4096 /SUBSYSTEM:CONSOLE + GCC:DEBUG_CLANGPDB_*_DLINK_FLAGS = /EXPORT:InitializeDriver=$(IMAGE_ENTRY_POINT) /BASE:0x10000 + GCC:NOOPT_CLANGPDB_*_DLINK_FLAGS = /EXPORT:InitializeDriver=$(IMAGE_ENTRY_POINT) /BASE:0x10000 +!endif + +``` + +
+ +## Building the HelloWorld UEFI shell program + +The updated/vulnerable HelloWorld application can be built in the same manner as done before, by running the following command. + +```console +[root@00c4495bd766 hbfa_workspace]# build -m MdeModulePkg/Application/HelloWorld/HelloWorld.inf -a X64 -b DEBUG -t GCC5 +``` + +#### Verifying the bug in a UEFI shell (optional) + +After building the updated/vulnerable HelloWorld application. We can again, copy the HelloWorld.efi application to a system with the QEMU emulator, and run the application from a UEFI shell (as described in the section [Running QEMU and Accessing the UEFI shell](#running-qemu-and-accessing-the-uefi-shell)). I.e. starting QEMU: + +```console +$ qemu-system-x86_64 -bios /usr/share/ovmf/OVMF.fd -cdrom ~/Downloads/ubuntu-22.04.2-desktop-amd64.iso -hda fat:./share,format=directory +``` + +As shown in the following screenshot, we can run the program, giving multiple arguments. As expected, the program outputs the arguments, as well as the length of characters copied from the first argument to ``MyBuffer``. + +
+ Running the extended HelloWorld.efi application with multiple arguments +
Example of running the extended HelloWorld.efi application with multiple arguments from the UEFI shell.
+
+ + Next, we can verify there is an issue when a large string of characters is given for the first argument. In the following screenshot, we run the application a few times with a varied length of 'A' characters for the first argument. When a large number of 'A' characters are input, the emulation freezes. + +
+ Running the extended HelloWorld.efi application with multiple arguments +
Example of running the extended HelloWorld.efi application with multiple varying length of characters for the first argument in the UEFI shell.
+
+ +## TestHelloWorld: Creating a fuzzing test harnesses in HBFA + +The [Host-based Firmware Analyzer User Guide](https://github.com/tianocore/edk2-staging/blob/HBFA/HBFA/Doc/User%20Guide%20-%20How-to-Add-New-Case.pdf) provides some recommendations for the files and folder structure used when creating a fuzzing test harness in HBFA. In this tutorial we will summarize and follow this approach. + +### Where to create and save a fuzzing test case harness + +It is recommended to create fuzzing test harness cases in the file structure provided in HBFA (although its not strictly required). Further, a minimal test case folder would consist of the test harness C-source code file (containing the fuzzing harness logic) and a module description file (the .inf file). The HBFA folder shown in the file structure (tree) relative to the repository root directory. + +``` +├── HBFA + ├── UefiHostFuzzTestCasePkb + ├── TestCase + ├── ... # The directories here somewhat follow the + DeviceSecurityPkg # analogous directories from the EDK2 root + FatPkg # file structure (e.g. see MdeModulePkg) + MdeModulePkg + OvmfPkg + SecurityPkg + ... + └── TestModuleFolder # This is the folder containing the new test case + └── TestXYZ.c # Test harness/logic goes in this C-source code file + └── TestXYZ.inf # The INF, module description file + +``` + +A number of fuzzing test harness cases are included in HBFA. Carefully examining these tests harnesses is very helpful for learning how to implement fuzzing tests harnesses in HBFA. A listing of these files is presented in the following Table. + +| Fuzzing Test Case Name | File Location (based from repository root) | +| ------------------------------------- | ----------------------------- | +| TestTpm2CommandLib | HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/Tpm2CommandLib/TestTpm2CommandLib.{c,inf} | +| TestBmpSupportLib | HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library/BaseBmpSupportLib/TestBmpSupportLib.{c,inf} | +| TestPartition | HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/PartitionDxe/TestPartition.{c,inf} | +| TestUdf | HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/TestUdf.{c,inf} | +| TestUsb | HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Usb/UsbBusDxe/TestUsb.{c,inf} | +| TestPeiUsb | HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Usb/UsbBusPei/TestPeiUsb.{c,inf} | +| TestVariableSmm | HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Variable/RuntimeDxe/TestVariableSmm.{c,inf} | +| TestFmpAuthenticationLibPkcs7 | HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibPkcs7/TestFmpAuthenticationLibPkcs7.{c,inf} | +| TestFmpAuthenticationLibRsa2048Sha256 | HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibRsa2048Sha256/TestFmpAuthenticationLibRsa2048Sha256.{c,inf} | +| TestCapsulePei | HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/CapsulePei/Common/TestCapsulePei.{c,inf} | +| TestFileName | HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/TestFileName.{c,inf} | +| TestPeiGpt | HBFA/UefiHostFuzzTestCasePkg/TestCase/FatPkg/FatPei/TestPeiGpt.{c,inf} | +| TestValidateTdxCfv | HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/EmuVariableFvbRuntimeDxe/TestValidateTdxCfv.{c,inf} | +| TestTcg2MeasureGptTable | HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/DxeTpm2MeasureBootLib/TestTcg2MeasureGptTable.{c,inf} | +| TestTcg2MeasurePeImage | HBFA/UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/DxeTpm2MeasureBootLib/TestTcg2MeasurePeImage.{c,inf} | +| TestVirtioPciDevice | HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioPciDeviceDxe/TestVirtioPciDevice.{c,inf} | +| TestVirtio10Blk | HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/Virtio10BlkDxe/TestVirtio10Blk.{c,inf} | +| TestVirtioBlk | HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioBlkDxe/TestVirtioBlk.{c,inf} | +| TestVirtioBlkReadWrite | HBFA/UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioBlkReadWrite/TestVirtioBlkReadWrite.{c,inf} | +| TestIdentifyAtaDevice | HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/TestIdentifyAtaDevice.{c,inf} | + +Additionally, many of the test-cases make use of stub-libraries to simulate responses from function call that would interact with hardware. These libraries are included in HBFA in the relative directory: + +``` +├── HBFA + ├── UefiHostFuzzTestCasePkb + ├── TestStub + ├── DiskStubLib + ├── Tcg2StubLib + ├── Tpm2DeviceLibStub + ├── ... +``` + +### Whats needed in the fuzzing harness files (.c and .inf)? + +Behind the scenes, HBFA defines an EDK2 platform "ToolChainHarnessLib" (see: [source](../../../HBFA/UefiHostFuzzTestPkg/Library/ToolChainHarnessLib/ToolChainHarnessLib.inf)) that acts as the glue to interface (pass information) between the fuzzer (e.g. AFL, LibFuzzer, KLEE) and the functions and libraries one chooses to fuzz in the harness file. The specific implementations for this can been seen this [source](../../../HBFA/UefiHostFuzzTestPkg/Library/ToolChainHarnessLib/ToolChainHarnessLib.c). Likewise, the module description file will reference the "ToolChainHarnessLib" so that everything is included in the build. + +#### The fuzzing harness test logic (C-source code file) + +For the fuzzing harness C-source code file, a few important functions should be leveraged when creating a fuzzing harness to be used with AFL or LibFuzzer. These functions are ``FixBuffer()``, ``GetMaxBufferSize()``, and ``RunTestHarness()`` (shown in the following example skeleton code). The ``RunTestHarness()`` will contain the fuzzing test logic and a test buffer (``TestBuffer``) is used to handle the fuzz data passed between the fuzzer (e.g. AFL and LibFuzzer) and the test logic for each fuzzing instance. The code/logic in ``RunTestHarness()`` is ran on each pass (fuzz/input) of the external fuzzer. The functions ``FixBuffer()`` and ``GetMaxBufferSize()`` are used when setting up/handling the test buffer. A skeleton structure for a fuzzing harness is presented in the [Host-based Firmware Analyzer User Guide](../archive/originalHBFA/Doc/User%20Guide%20-%20How-to-Add-New-Case.pdf) and is included in the following: + +```c +/* The FixBuffer function is aimed to fix some bits in the TestBuffer so +that the TestBuffer can pass basic check and touch deeper paths. It’s +optional. */ +VOID +FixBuffer ( +UINT8 *TestBuffer +) +{ } + +UINTN +EFIAPI +GetMaxBufferSize ( +VOID +) +{ +return TOTAL_SIZE; +} +VOID +EFIAPI +RunTestHarness( +IN VOID *TestBuffer, +IN UINTN TestBufferSize +) +{ +FixBuffer(TestBuffer); +// test logic that use TestBuffer as an input to try to call tested +API. +TestLogicFunc(TestBuffer, TestBufferSize); +} +``` + +Here, the ``FixBuffer()`` is considered optional can be used to adjust and set initial value/bytes for the fuzzing buffer if one needs to ensure the buffer has certain bytes set. For example, overriding some bytes from the fuzzer (e.g. AFL, Libfuzzer) to ensure some check in the code being fuzzed is passed. + +Follow this approach, we can examine an implementation in a fuzzing harness included with HBFA. [TestBmpSupportLib](../../../HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library/BaseBmpSupportLib/TestBmpSupportLib.c) is a fuzzing test harness for the [BmpSupportLib](https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Include/Library/BmpSupportLib.h) in EDK2, which is used to translate a BMP graphics image into a GOP buffer. The fuzzing harness is shown in the following: + +```c +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define TOTAL_SIZE (1 * 1024) + +VOID +FixBuffer ( + UINT8 *TestBuffer + ) +{ +} + +UINTN +EFIAPI +GetMaxBufferSize ( + VOID + ) +{ + return TOTAL_SIZE; +} + +VOID +EFIAPI +RunTestHarness( + IN VOID *TestBuffer, + IN UINTN TestBufferSize + ) +{ + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *GopBlt; + UINTN GopBltSize; + UINTN PixelHeight; + UINTN PixelWidth; + FixBuffer (TestBuffer); + GopBlt = NULL; + TranslateBmpToGopBlt( + TestBuffer, + TestBufferSize, + &GopBlt, + &GopBltSize, + &PixelHeight, + &PixelWidth + ); + if (GopBlt != NULL) + FreePool (GopBlt); +} +``` + +Here, we can see that the functions ``FixBuffer()`` and ``GetMaxBufferSize()`` remain the same as presented in the skeleton fuzzing harness example. ``FixBuffer()`` is left untouched (not used) and ``GetMaxBufferSize()`` is used to simply return the buffer maximum size (defined with he macro for TOTAL_SIZE). The bulk of the action takes place in the ``RunTestHarness()`` function. In the fuzzing harness, the appropriate variables for calling the ``TranslateBmpToGopBlt()`` function from the EDK2 [BmpSupportLib](https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Include/Library/BmpSupportLib.h) (see also [BmpSupportLib.c](https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Library/BaseBmpSupportLib/BmpSupportLib.c)). ``TestBuffer``, a pointer to the buffer containing the fuzz data, is passed into the call to ``TranslateBmpToGopBlt`` the input BMP file to convert (i.e. the argument ``*BmpImage``). Last, at the end of the code block for ``RunTestHarness()`` it is essential to clean-up and free any resources that may have been allocated. + +#### The module description file (INF file) + +The module description file is described in detail in the EDK II documentation (e.g. see [Build Description Files](https://github.com/tianocore/tianocore.github.io/wiki/Build-Description-Files#the-inf-file) and [EDK II Module Information (INF) File Specification](https://tianocore-docs.github.io/edk2-InfSpecification/draft/#edk-ii-module-information-inf-file-specification)). This file is used to describe to the build system on how to build a module (e.g. a driver, library, or application). For an example, we'll look at the INF file for the [TestBmpSupportLib](../../../HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library/BaseBmpSupportLib/TestBmpSupportLib.c) fuzzing test-case. The contents for this file ([TestBmpSupportLib.inf](../../../HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library/BaseBmpSupportLib/TestBmpSupportLib.inf)) are shown in the following. + +```ini +## @file +# Component description file for TestBmpSupportLib module. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TestBmpSupportLib + FILE_GUID = E911AB26-4741-4621-93EF-305FEA98A851 + MODULE_TYPE = USER_DEFINED + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + TestBmpSupportLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib + SafeIntLib + BmpSupportLib + ToolChainHarnessLib +``` + +The sections in this INF file are: ``[Defines]``, ``[Sources]``, ``[Packages]``, and ``[LibraryClasses]``. A description for these sections is provided in the following Table. For additional information on these and a number of other sections that can be used, see the [documentation](https://github.com/tianocore/tianocore.github.io/wiki/Build-Description-Files#the-inf-file). + +| Section | Description | +| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| ``[Defines]`` | This section should include the fields shown above in the INF file; however, there are a number of additional (optional) fields that can be defined that are listed in EDK2 documentation. Note for the present file, the ``FILE_GUID`` should be a unique GUID value; likewise, the value used for the ``BASE_NAME`` is used as a base part of the output name used in the for the final binary. | +| ``[Sources]`` | This section should list the various sources and header files used to build the module; in the case the source used for the fuzzing test harness is all in the file[TestBmpSupportLib.c](../../../HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library/BaseBmpSupportLib/TestBmpSupportLib.c). | +| ``[Packages]`` | This section should list the packages used by the module (the package description files, '.dec'). For this case, the files are[MdePkg/MdePkg.dec](https://github.com/tianocore/edk2/blob/master/MdePkg/MdePkg.dec), [MdeModulePkg/MdeModulePkg.dec](https://github.com/tianocore/edk2/blob/master/MdeModulePkg/MdeModulePkg.dec), and [UefiHostTestPkg/UefiHostTestPkg.dec](../../../HBFA/UefiHostTestPkg/UefiHostTestPkg.dec). The file ``MdeModulePkg/MdeModulePkg.dec`` should always be included as a package in this section for an EDK2 module. Further, ``MdeModulePkg/MdeModulePkg.dec`` is included because it is part of the dependencies for this specific test case (e.g. TestBmpSupportLib is a library and part of MdeModulePkg). Lastly, ``UefiHostTestPkg/UefiHostTestPkg.dec`` must be included for an HBFA fuzzing test case. | +| ``[LibraryClasses]`` | This section contains a list of the various libraries the module will use and should be linked with (or optionally required by a component), see:[EDK II Module Information (INF) File Specification](https://tianocore-docs.github.io/edk2-InfSpecification/release-1.27/2_inf_overview/212_[libraryclasses]_section.html#212-libraryclasses-section). Here, files included in the ``LibraryClasses`` section are those used included in the test harness ``TestBmpSupportLib.c``, from the Edk2 libraries. E.g. see the ``'#include , #include , ...'``. Additionally, for HBFA fuzzing test harnesses, ``ToolChainHarnessLib`` is required and included. | + +If you jumped ahead to this section from [HelloWorld.inf: Examining the source](#helloworldinf-examining-the-source) use the link to go back. + +## Developing a fuzzing harness for HelloWorldLib + +First, we'll take a look at the files we will need to create or modify to develop our fuzzing harness. Here, our fuzzing effort will focus on developing a harness to fuzz the ``ProcessArgument()`` function from HelloWorldLib. + +### Files that we will be modifying or creating when creating the fuzzing harness, TestHelloWorld + +| Filename | Description | File-Path (relative to hbfa-fl root) | +| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------- | +| TestHelloWorld.c | This is the C-source for for the fuzzing test harness. This is the focal point where the ``RunTestHarness()`` is written for the test case. | HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Application/HelloWorld/ | +| TestHelloWorld.inf | The INF (build description file) for the TestHelloWorld fuzzing harness. This should reference any libraries needed to build the TestHelloWorld.c test harness. | HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Application/HelloWorld/ | +| UefiHostTestPkg.dsc | This is the platform defined in HBFA that provides the fuzzing interface. When invoking the EDK2 build system, this should be included as the '-p' argument. A reference to the fuzzing test case INF file must be included under the '[Components]' field in this file. | HBFA/UefiHostTestPkg/ | + +### TestHelloWorld.c: Examining the source code + +The source code for TestHelloWorld.c is included below. Several key code areas from TestHelloWorld.c are highlighted in the following figure: + +
+ +
Highlighted areas from source-code for TestHelloWorld.c.
+
+ +As described from the fuzzing test harness skeleton file, the key functions that are declared in a fuzzing harness for HBFA are: + +1. FixBuffer() +2. GetMaxBufferSize() and +3. RunTestHarness() + +Here, we'll focus on the test logic we are including in the ``RunTestHarness`` function. First, as shown in the code block labeled with an A, This block of code is all about creating a reference to a EFI_SHELL_PARAMETERS_PROTOCOL struct, which will be what we will pass to the ProcessArgument function from HelloWorldLib. We allocate such a struct on the heap and refer to with the name: ShellParameters. We then assign a reference to an Argv array to the appropriate element in the ShellParameters struct. Last, we swap out the reference for the first argument from a dummy string to that of our TestBuffer fuzz data. Therefore, when the call is made to ProcessArgument, it will handle the fuzz data as the first argument. + +In the code block B, we make our call to ProcessArgument and call ``free`` to clear the memory out that we had allocated for out ShellParameters struct. Note it is critical to clean up any allocations in the ``RunTestHarness`` function, otherwise you will introduce a memory leak which get called for every fuzz sent during you fuzzing session. + +
+ Source-code for TestHelloWorld.c + +```c +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TOTAL_SIZE 64 + +VOID +FixBuffer ( + UINT8 *TestBuffer + ) +{ +} + +UINTN +EFIAPI +GetMaxBufferSize ( + VOID + ) +{ + return TOTAL_SIZE; +} + +VOID +EFIAPI +RunTestHarness( + IN VOID *TestBuffer, + IN UINTN TestBufferSize + ) +{ + FixBuffer (TestBuffer); + + // Allocate EFI_SHELL_PARAMETERS_PROTOCOL struct + EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters = malloc(sizeof(EFI_SHELL_PARAMETERS_PROTOCOL)); + // Create dummy Argv struct (CHAR16 for UEFI shell) + // The value for Argv[1] Will be swapped with a pointer to the fuzz buffer + CHAR16 *MyArgv[2] = {L"arg1", L"arg2"}; + ShellParameters->Argv = MyArgv; + // Here we swap in the 'fuzz' (TestBuffer) that is source from the fuzzer (AFL or LibFuzzer) + // with Argv[1] + ShellParameters->Argv[1] = (CHAR16 *)TestBuffer; + + // Here we call to the external function ProcessArgument from HelloWorldLib.h, passing the + // ShellParameters structure + ProcessArgument(ShellParameters); + + // Clean-up + // + free(ShellParameters); +} + +``` + +
+ +### TestHelloWorld.inf: Examining the source code + +The source code for TestHelloWorld.inf is included below. The TestHelloWorld.inf build description follows the same rules as for any other module that one would develop in EDK II. However, we note one must include the following items in their ``[Packages]`` and ``[LibraryClasses]`` sections as these are part of the platform (UefiHostTestPkg) and libraries used from HBFA to enable fuzzing. + +1. In the ``[Packages]`` section, there should be an entry for ``UefiHostTestPkg/UefiHostTestPkg.dec`` +2. In the ``[LibraryClasses]`` section, there should be an entry for ``ToolChainHarnessLib`` + +
+ Source-code for TestHelloWorld.inf + +```ini +## @file +# Component description file for TestHelloWorld module. +# + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TestHelloWorld + FILE_GUID = cc009d97-035c-430f-ac0d-c0e7451f1a12 + MODULE_TYPE = USER_DEFINED + VERSION_STRING = 1.0 + +# USER_DEFINED +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + TestHelloWorld.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiHostTestPkg/UefiHostTestPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib + ToolChainHarnessLib + UefiApplicationEntryPoint + UefiLib + PcdLib + UefiBootServicesTableLib + HelloWorldLib + +``` + +
+ +### UefiHostTestPkg.dsc: Examining the source code + +The source code for UefiHostTestPkg.dsc is included below. Further, the relevant additions are shown in the following Figure. + +
+ +
Example of references added for the TestHelloWorld fuzzing test case to UefiHostTestPkg.dsc.
+
+ +Importantly, for a fuzzing test harness in HBFA, you must ensure that there is a reference for it in the ``[Components]`` section of the UefiHostTestPkg description file. An entry for the TestHelloWorld fuzzing module can be seen in red box at the bottom of the Figure. This entry also includes a reference in the ```` field to the HelloWorldLib build description file. + +
+ Source-code for UefiHostTestPkg.dsc + +```ini +## @file UefiHostTestPkg.dsc +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + PLATFORM_NAME = UefiHostFuzzTestCasePkg + PLATFORM_GUID = 9497CEE4-EEEB-4B38-B0EF-03E01920F040 + PLATFORM_VERSION = 0.1 + DSC_SPECIFICATION = 0x00010005 + OUTPUT_DIRECTORY = Build/UefiHostFuzzTestCasePkg + SUPPORTED_ARCHITECTURES = IA32|X64 + BUILD_TARGETS = DEBUG|RELEASE|NOOPT + SKUID_IDENTIFIER = DEFAULT + + DEFINE TEST_WITH_INSTRUMENT = FALSE + +[LibraryClasses] + BaseLib|UefiHostTestPkg/Library/BaseLibHost/BaseLibHost.inf + CacheMaintenanceLib|UefiHostTestPkg/Library/BaseCacheMaintenanceLibHost/BaseCacheMaintenanceLibHost.inf + BaseMemoryLib|UefiHostTestPkg/Library/BaseMemoryLibHost/BaseMemoryLibHost.inf + MemoryAllocationLib|UefiHostTestPkg/Library/MemoryAllocationLibHost/MemoryAllocationLibHost.inf + DebugLib|UefiHostTestPkg/Library/DebugLibHost/DebugLibHost.inf + UefiBootServicesTableLib|UefiHostTestPkg/Library/UefiBootServicesTableLibHost/UefiBootServicesTableLibHost.inf + HobLib|UefiHostTestPkg/Library/HobLibHost/HobLibHost.inf + SmmMemLib|UefiHostTestPkg/Library/SmmMemLibHost/SmmMemLibHost.inf + SmmMemLibStubLib|UefiHostTestPkg/Library/SmmMemLibHost/SmmMemLibHost.inf + DevicePathLib|UefiHostTestPkg/Library/UefiDevicePathLibHost/UefiDevicePathLibHost.inf + DxeServicesTableLib|UefiHostTestPkg/Library/DxeServicesTableLibHost/DxeServicesTableLibHost.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + SmmServicesTableLib|UefiHostTestPkg/Library/SmmServicesTableLibHost/SmmServicesTableLibHost.inf + MmServicesTableLib|UefiHostTestPkg/Library/SmmServicesTableLibHost/SmmServicesTableLibHost.inf + PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf + PeiServicesTablePointerLib|UefiHostTestPkg/Library/PeiServicesTablePointerLibHost/PeiServicesTablePointerLibHost.inf + UefiDriverEntryPoint|UefiHostTestPkg/Library/UefiDriverEntryPointHost/UefiDriverEntryPointHost.inf + PeimEntryPoint|UefiHostTestPkg/Library/PeimEntryPointHost/PeimEntryPointHost.inf + ToolChainHarnessLib|UefiHostFuzzTestPkg/Library/ToolChainHarnessLib/ToolChainHarnessLib.inf + + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf + SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf + SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf + TimerLib|UefiHostTestPkg/Library/BaseTimerLibHost/BaseTimerLibHost.inf + + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + + SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf + + DiskStubLib|UefiHostFuzzTestCasePkg/TestStub/DiskStubLib/DiskStubLib.inf + Usb2HcStubLib|UefiHostFuzzTestCasePkg/TestStub/Usb2HcStubLib/Usb2HcStubLib.inf + Usb2HcPpiStubLib|UefiHostFuzzTestCasePkg/TestStub/Usb2HcPpiStubLib/Usb2HcPpiStubLib.inf + UsbIoPpiStubLib|UefiHostFuzzTestCasePkg/TestStub/UsbIoPpiStubLib/UsbIoPpiStubLib.inf + Tcg2StubLib|UefiHostFuzzTestCasePkg/TestStub/Tcg2StubLib/Tcg2StubLib.inf + # Add below libs due to Edk2 update + VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf + VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf +!if $(TEST_WITH_INSTRUMENT) + IniParsingLib|UefiInstrumentTestPkg/Library/IniParsingLib/IniParsingLib.inf + NULL|UefiInstrumentTestPkg/Library/InstrumentLib/InstrumentLib.inf + InstrumentHookLib|UefiInstrumentTestPkg/Library/InstrumentHookLibNull/InstrumentHookLibNull.inf +!endif + +!if $(TEST_WITH_KLEE) + BaseLib|UefiHostTestPkg/Library/BaseLibHost/BaseLibHostNoAsm.inf +!endif + + # Adding to support HelloWorldFuzzing + UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf + +[LibraryClasses.common.USER_DEFINED] + +[Components] +!if $(TEST_WITH_INSTRUMENT) + UefiHostFuzzTestCasePkg/TestStub/DiskStubLib/DiskStubLib.inf { + + MSFT: *_*_*_CC_FLAGS = /Gh /GH /Od /GL- + GCC:*_*_*_CC_FLAGS = -O0 -finstrument-functions + } + UefiHostTestPkg/Library/MemoryAllocationLibHost/MemoryAllocationLibHost.inf { + + MSFT: *_*_*_CC_FLAGS = /Gh /GH /Od /GL- + GCC:*_*_*_CC_FLAGS = -O0 -finstrument-functions + } + UefiHostFuzzTestPkg/Library/ToolChainHarnessLib/ToolChainHarnessLib.inf { + + MSFT: *_*_*_CC_FLAGS = "-DTEST_WITH_INSTRUMENT=TRUE" + GCC:*_*_*_CC_FLAGS = "-DTEST_WITH_INSTRUMENT=TRUE" + } +!endif + + UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/PartitionDxe/TestPartition.inf { + + NULL|MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf +!if $(TEST_WITH_INSTRUMENT) + + MSFT: *_*_*_CC_FLAGS = "-DTEST_WITH_INSTRUMENT=TRUE" + GCC:*_*_*_CC_FLAGS = "-DTEST_WITH_INSTRUMENT=TRUE" + + InstrumentHookLib|UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/PartitionDxe/InstrumentHookLibTestPartition/InstrumentHookLibTestPartition.inf +!endif + } + + UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/TestUdf.inf { + + NULL|MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf +!if $(TEST_WITH_INSTRUMENT) + + MSFT: *_*_*_CC_FLAGS = "-DTEST_WITH_INSTRUMENT=TRUE" + GCC:*_*_*_CC_FLAGS = "-DTEST_WITH_INSTRUMENT=TRUE" + + InstrumentHookLib|UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/InstrumentHookLibTestUdf/InstrumentHookLibTestUdf.inf +!endif + } + UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Disk/UdfDxe/TestFileName.inf { + + NULL|MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf + } + + UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library/BaseBmpSupportLib/TestBmpSupportLib.inf { + + BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf + } + + UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Application/HelloWorld/TestHelloWorld.inf { + + HelloWorldLib|MdeModulePkg/Library/HelloWorldLib/HelloWorldLib.inf + } + + UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library/DxeCapsuleLibFmp/TestDxeCapsuleLibFmp.inf { + + NULL|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf + FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf + UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf + SortLib|MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf + HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf + BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf + DisplayUpdateProgressLib|MdeModulePkg/Library/DisplayUpdateProgressLibGraphics/DisplayUpdateProgressLibGraphics.inf + } + UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/CapsulePei/Common/TestCapsulePei.inf { + + NULL|MdeModulePkg/Universal/CapsulePei/CapsulePei.inf + } + + UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Universal/Variable/RuntimeDxe/TestVariableSmm.inf { + + NULL|MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf + NULL|UefiHostTestPkg/Library/BaseLibNullCpuid/BaseLibNullCpuid.inf + AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf + VarCheckLib|UefiHostTestPkg/Library/VarCheckLibNull/VarCheckLibNull.inf + VariableFlashInfoLib|MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseVariableFlashInfoLib.inf + } + + UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/Tpm2CommandLib/TestTpm2CommandLib.inf { + + Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf + Tpm2DeviceLib|UefiHostFuzzTestCasePkg/TestStub/Tpm2DeviceLibStub/Tpm2DeviceLibStub.inf + Tpm2DeviceStubLib|UefiHostFuzzTestCasePkg/TestStub/Tpm2DeviceLibStub/Tpm2DeviceLibStub.inf + } + + UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Usb/UsbBusDxe/TestUsb.inf { + + NULL|MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf + } + UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Usb/UsbBusPei/TestPeiUsb.inf { + + NULL|MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf + } + + UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibPkcs7/TestFmpAuthenticationLibPkcs7.inf { + + FmpAuthenticationLib|SecurityPkg/Library/FmpAuthenticationLibPkcs7/FmpAuthenticationLibPkcs7.inf + BaseCryptLib|UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibPkcs7/CryptoLibStubPkcs7.inf + } + UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibRsa2048Sha256/TestFmpAuthenticationLibRsa2048Sha256.inf { + + FmpAuthenticationLib|SecurityPkg/Library/FmpAuthenticationLibRsa2048Sha256/FmpAuthenticationLibRsa2048Sha256.inf + BaseCryptLib|UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibRsa2048Sha256/CryptoLibStubRsa2048Sha256.inf + } + + UefiHostFuzzTestCasePkg/TestCase/FatPkg/FatPei/TestPeiGpt.inf { + + NULL|UefiHostFuzzTestCasePkg/TestCase/FatPkg/FatPei/Override/FatPei.inf +!if $(TEST_WITH_INSTRUMENT) + + MSFT: *_*_*_CC_FLAGS = "-DTEST_WITH_INSTRUMENT=TRUE" + GCC:*_*_*_CC_FLAGS = "-DTEST_WITH_INSTRUMENT=TRUE" + + InstrumentHookLib|UefiHostFuzzTestCasePkg/TestCase/FatPkg/FatPei/InstrumentHookLibTestPeiGpt/InstrumentHookLibTestPeiGpt.inf +!endif + } + + UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library/SmmLockBoxLib/UpdateLockBoxTestCase/TestUpdateLockBoxFuzzLength.inf { + + NULL|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf + } + UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Library/SmmLockBoxLib/UpdateLockBoxTestCase/TestUpdateLockBoxFuzzOffset.inf { + + NULL|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf + } + UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/TestIdentifyAtaDevice.inf{ + + NULL|UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Bus/Ata/AhciPei/Override/AhciPei.inf + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf + LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf + PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf + TdxLib|MdePkg/Library/TdxLib/TdxLib.inf + CcProbeLib|OvmfPkg/Library/CcProbeLib/DxeCcProbeLib.inf + RegisterFilterLib|MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf + } + + UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/Library/TdxStartupLib/TestHobList.inf { + + LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf + QemuFwCfgSimpleParserLib|OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFwCfgSimpleParserLib.inf + MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf + PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf + PrePiHobListPointerLib|OvmfPkg/IntelTdx/PrePiHobListPointerLibTdx/PrePiHobListPointerLibTdx.inf + PlatformInitLib|OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf + PeilessStartupLib|OvmfPkg/Library/PeilessStartupLib/PeilessStartupLib.inf + RegisterFilterLib|MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf + #UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf + #LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLibSec.inf + CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf + TdxLib|MdePkg/Library/TdxLib/TdxLib.inf + PrePiLib|EmbeddedPkg/Library/PrePiLib/PrePiLib.inf + HashLib|SecurityPkg/Library/HashLibTdx/HashLibTdx.inf + UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf + PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf + ExtractGuidedSectionLib|MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.inf + PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf + PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf + QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf + MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf + MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf + CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf + PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf + CcExitLib|OvmfPkg/Library/CcExitLib/CcExitLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf + CcExitLib|OvmfPkg/Library/CcExitLib/CcExitLib.inf + CcProbeLib|OvmfPkg/Library/CcProbeLib/DxeCcProbeLib.inf + TdxMailboxLib|OvmfPkg/Library/TdxMailboxLib/TdxMailboxLib.inf + TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf + HobLib|EmbeddedPkg/Library/PrePiHobLib/PrePiHobLib.inf + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf + } + UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/DxeTpm2MeasureBootLib/TestTcg2MeasureGptTable.inf{ + + NULL|SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf + BaseCryptLib|UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibPkcs7/CryptoLibStubPkcs7.inf + PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf + SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf + CcProbeLib|OvmfPkg/Library/CcProbeLib/DxeCcProbeLib.inf + } + + UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/DxeTpm2MeasureBootLib/TestTcg2MeasurePeImage.inf{ + + NULL|SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf + BaseCryptLib|UefiHostFuzzTestCasePkg/TestCase/SecurityPkg/Library/FmpAuthenticationLibPkcs7/CryptoLibStubPkcs7.inf + PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf + SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf + CcProbeLib|OvmfPkg/Library/CcProbeLib/DxeCcProbeLib.inf + } + UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/EmuVariableFvbRuntimeDxe/TestValidateTdxCfv.inf{ + + NULL|OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf + UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf + PlatformFvbLib|OvmfPkg/Library/EmuVariableFvbLib/EmuVariableFvbLib.inf + CcProbeLib|OvmfPkg/Library/CcProbeLib/DxeCcProbeLib.inf + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf + PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf + RegisterFilterLib|MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf + #UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf + LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf + CcExitLib|OvmfPkg/Library/CcExitLib/CcExitLib.inf + MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf + MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf + CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf + PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf + PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf + TdxLib|MdePkg/Library/TdxLib/TdxLib.inf + PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf + MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf + QemuFwCfgSimpleParserLib|OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFwCfgSimpleParserLib.inf + QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf + PlatformInitLib|OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf + } + + UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioPciDeviceDxe/TestVirtioPciDevice.inf{ + + UefiPciCapPciIoLib|OvmfPkg/Library/UefiPciCapPciIoLib/UefiPciCapPciIoLib.inf + BasePciCapLib|OvmfPkg/Library/BasePciCapLib/BasePciCapLib.inf + VirtioPciDevice10StubLib|UefiHostFuzzTestCasePkg/TestStub/VirtioPciDevice10StubLib/VirtioPciDevice10StubLib.inf + VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf + UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf + OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf + } + + UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/Virtio10BlkDxe/TestVirtio10Blk.inf{ + + NULL|OvmfPkg/VirtioBlkDxe/VirtioBlk.inf + UefiPciCapPciIoLib|OvmfPkg/Library/UefiPciCapPciIoLib/UefiPciCapPciIoLib.inf + BasePciCapLib|OvmfPkg/Library/BasePciCapLib/BasePciCapLib.inf + VirtioBlkStubLib|UefiHostFuzzTestCasePkg/TestStub/VirtioBlkStubLib/VirtioBlkStubLib.inf + VirtioPciDevice10StubLib|UefiHostFuzzTestCasePkg/TestStub/VirtioPciDevice10StubLib/VirtioPciDevice10StubLib.inf + VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf + UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf + OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf + } + + UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioBlkDxe/TestVirtioBlk.inf{ + + NULL|OvmfPkg/VirtioBlkDxe/VirtioBlk.inf + NULL|OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf + VirtioBlkStubLib|UefiHostFuzzTestCasePkg/TestStub/VirtioBlkStubLib/VirtioBlkStubLib.inf + VirtioPciDevice10StubLib|UefiHostFuzzTestCasePkg/TestStub/VirtioPciDeviceStubLib/VirtioPciDeviceStubLib.inf + VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf + UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf + OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf + } + + UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/VirtioBlkReadWrite/TestVirtioBlkReadWrite.inf{ + + NULL|OvmfPkg/VirtioBlkDxe/VirtioBlk.inf + NULL|OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf + VirtioBlkStubLib|UefiHostFuzzTestCasePkg/TestStub/VirtioBlkStubLib/VirtioBlkStubLib.inf + VirtioPciDevice10StubLib|UefiHostFuzzTestCasePkg/TestStub/VirtioPciDeviceStubLib/VirtioPciDeviceStubLib.inf + VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf + UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf + OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf + } + + UefiHostFuzzTestCasePkg/TestCase/OvmfPkg/Library/CcExitLib/TestParseMmioExitInstructions.inf{ + + CcExitLib|OvmfPkg/Library/CcExitLib/CcExitLib.inf + LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf + MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf + CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf + #UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf + RegisterFilterLib|MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf + CcProbeLib|OvmfPkg/Library/CcProbeLib/SecPeiCcProbeLib.inf + TdxLib|MdePkg/Library/TdxLib/TdxLib.inf + PlatformInitLib|OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf + } + + [PcdsDynamicDefault] + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|0 + [PcdsFixedAtBuild] + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbSize|0x002000 +!include UefiHostFuzzTestPkg/UefiHostFuzzTestBuildOption.dsc + +``` + +
+ +## Building the TestHelloWorld fuzzing harness + +Now that all of the necessary files have been created or modified, we are ready to build of fuzzing test harness. To do this, there are a couple approaches: + +1. Directly using the EDK II build command +2. Using one of the HBFA helper scripts, e.g. ``RunLibFuzzer.py`` or ``RunAFL.py`` + +### Using the 'Build' command + +For the first approach the ‘build’ command for the EDK II build system can be used directly: + +```console +build -p UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dsc -m UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Application/HelloWorld/TestHelloWorld.inf -a X64 -b DEBUG -t LIBFUZZER --conf /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestPkg/Conf +``` + +Here you must specify the platform UefiHostFuzzTestCasePkg.dsc via the `–p` flag. This must be done every time for an HBFA fuzzing harness as the is the platform that enables fuzzing. For the `–m`, module option, the TestHelloWorld.inf build description is references. For the `–a`, architecture option, we specific X64. For `–b`, DEBUG is specified so that debugging symbols are included in the build. For the build target, `-t`, we specify as LIBFUZZER. If building for AFL, this would be AFL. Last, for the `–conf`, configuration option, we specify the Configuration file included with HBFA, which if the recommended approach. + +### Using the HBFA helper scripts + +Included HBFA are several scripts that help automate building the test case and running the fuzzer. Here we are going to build and run with LibFuzzer, so we’ll use the `RunLibFuzzer.py` Python script. Several of the command-line options are the same. Here we also have a option for specifying the input seed file folder for the fuzzer, specified via the `-t` option. Likewise, we specify an output folder for any crash files, etc. from the fuzzer via the `-o` option. Behind the scenes, RunLibFuzzer.py will invoke the build system with the proper platform file. An example of the command, which will build the TestHelloWorld library and launch fuzzing is shown in the following. + +```console +RunLibFuzzer.py -a X64 -m /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Application/HelloWorld/TestHelloWorld.inf -i /tmp/helloseed/ -o /tmp/fuzz_RunLibFuzzer_TestHelloWorldLib +``` + +## Fuzzing HelloWorldLib for vulnerabilities with LibFuzzer + +If we run the TestHelloWorld fuzzing test case, as shown in the previous [section](#using-the-hbfa-helper-scripts), you should see output similar to the following. + +```console +[root@00c4495bd766 hbfa_workspace]# RunLibFuzzer.py -a X64 -m /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Application/HelloWorld/TestHelloWorld.inf -i /tmp/helloseed/ -o /tmp/fuzz_RunAFL_TestHelloWorldLib +LibFuzzer output will be generated in current directory:/tmp/fuzz_RunAFL_TestHelloWorldLib +Updating UefiHostFuzzTestBuildOption.dsc +Start build Test Module: +build -p UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dsc -m UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Application/HelloWorld/TestHelloWorld.inf -a X64 -b DEBUG -t LIBFUZZER --conf /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestPkg/Conf -t GCC5 +Build Successful !!! + +Start run LibFuzzer test: +/root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestHelloWorld /tmp/helloseed/ -rss_limit_mb=0 -artifact_prefix=/tmp/fuzz_RunAFL_TestHelloWorldLib/ +INFO: Running with entropic power schedule (0xFF, 100). + +INFO: Seed: 3584686423 + +INFO: Loaded 1 modules (3888 inline 8-bit counters): 3888 [0x5e03c0, 0x5e12f0), + +INFO: Loaded 1 PC tables (3888 PCs): 3888 [0x59fab8,0x5aedb8), + +INFO: 1 files found in /tmp/helloseed/ + +INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes + +INFO: seed corpus: files: 1 min: 5b max: 5b total: 5b rss: 30Mb + +#2 INITED cov: 108 ft: 109 corp: 1/5b exec/s: 0 rss: 31Mb + +#3 NEW cov: 108 ft: 111 corp: 2/9b lim: 5 exec/s: 0 rss: 31Mb L: 4/5 MS: 1 EraseBytes- +... +#2211 NEW cov: 113 ft: 133 corp: 15/73b lim: 15 exec/s: 0 rss: 37Mb L: 14/14 MS: 3 ChangeByte-InsertRepeatedBytes-CopyPart- + +================================================================= + +==13469==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffedc0c1df0 at pc 0x00000055a3b0 bp 0x7ffedc0c1950 sp 0x7ffedc0c1948 + +READ of size 1 at 0x7ffedc0c1df0 thread T0 + + #0 0x55a3af in BasePrintLibSPrintMarker /root/hbfa_workspace/edk2/MdePkg/Library/BasePrintLib/PrintLibInternal.c:1159:13 + + #1 0x5537cb in UnicodeVSPrint /root/hbfa_workspace/edk2/MdePkg/Library/BasePrintLib/PrintLib.c:73:10 + + #2 0x550b3c in InternalPrint /root/hbfa_workspace/edk2/MdePkg/Library/UefiLib/UefiLibPrint.c:70:12 + + #3 0x550d5e in Print /root/hbfa_workspace/edk2/MdePkg/Library/UefiLib/UefiLibPrint.c:119:12 + + #4 0x5508e1 in ProcessArgument /root/hbfa_workspace/edk2/MdeModulePkg/Library/HelloWorldLib/HelloWorldLib.c:61:5 + + #5 0x54eb7f in RunTestHarness /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Application/HelloWorld/TestHelloWorld.c:49:3 +... +Address 0x7ffedc0c1df0 is located in stack of thread T0 at offset 48 in frame + + #0 0x5506bf in ProcessArgument /root/hbfa_workspace/edk2/MdeModulePkg/Library/HelloWorldLib/HelloWorldLib.c:58 + + + + This frame has 1 object(s): + + [32, 48) 'MyBuffer' (line 59) <== Memory access at offset 48 overflows this variable +... +==13469==ABORTING + +MS: 1 CopyPart-; base unit: 05c470e2f391593e9aca50949f9528bff29413de + +0x0,0x30,0x0,0x4,0x0,0x55,0x0,0x55,0x4,0x0,0x55,0x55,0x55,0x55,0x4, + +\x000\x00\x04\x00U\x00U\x04\x00UUUU\x04 + +artifact_prefix='/tmp/fuzz_RunAFL_TestHelloWorldLib/'; Test unit written to /tmp/fuzz_RunAFL_TestHelloWorldLib/crash-64747b0e18749998ecf47ad41fd3b34439e8ce07 + +Base64: ADAABABVAFUEAFVVVVUE +``` + +
+ Expand here for full output from command: + +```console +[root@00c4495bd766 hbfa_workspace]# RunLibFuzzer.py -a X64 -m /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Application/HelloWorld/TestHelloWorld.inf -i /tmp/helloseed/ -o /tmp/fuzz_RunAFL_TestHelloWorldLib +LibFuzzer output will be generated in current directory:/tmp/fuzz_RunAFL_TestHelloWorldLib +Updating UefiHostFuzzTestBuildOption.dsc +Start build Test Module: +build -p UefiHostFuzzTestCasePkg/UefiHostFuzzTestCasePkg.dsc -m UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Application/HelloWorld/TestHelloWorld.inf -a X64 -b DEBUG -t LIBFUZZER --conf /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestPkg/Conf -t GCC5 +Build Successful !!! + +Start run LibFuzzer test: +/root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestHelloWorld /tmp/helloseed/ -rss_limit_mb=0 -artifact_prefix=/tmp/fuzz_RunAFL_TestHelloWorldLib/ +INFO: Running with entropic power schedule (0xFF, 100). + +INFO: Seed: 3584686423 + +INFO: Loaded 1 modules (3888 inline 8-bit counters): 3888 [0x5e03c0, 0x5e12f0), + +INFO: Loaded 1 PC tables (3888 PCs): 3888 [0x59fab8,0x5aedb8), + +INFO: 1 files found in /tmp/helloseed/ + +INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes + +INFO: seed corpus: files: 1 min: 5b max: 5b total: 5b rss: 30Mb + +#2 INITED cov: 108 ft: 109 corp: 1/5b exec/s: 0 rss: 31Mb + +#3 NEW cov: 108 ft: 111 corp: 2/9b lim: 5 exec/s: 0 rss: 31Mb L: 4/5 MS: 1 EraseBytes- + +#13 NEW cov: 110 ft: 113 corp: 3/13b lim: 5 exec/s: 0 rss: 31Mb L: 4/5 MS: 5 ChangeBit-ShuffleBytes-CopyPart-EraseBytes-ChangeBinInt- + +#14 NEW cov: 110 ft: 115 corp: 4/15b lim: 5 exec/s: 0 rss: 31Mb L: 2/5 MS: 1 CrossOver- + +#17 NEW cov: 110 ft: 117 corp: 5/17b lim: 5 exec/s: 0 rss: 31Mb L: 2/5 MS: 3 CopyPart-ChangeBinInt-CrossOver- + +#28 NEW cov: 113 ft: 120 corp: 6/21b lim: 5 exec/s: 0 rss: 32Mb L: 4/5 MS: 1 ChangeBinInt- + +#41 NEW cov: 113 ft: 123 corp: 7/26b lim: 5 exec/s: 0 rss: 32Mb L: 5/5 MS: 3 ChangeBit-CopyPart-InsertByte- + +#54 NEW cov: 113 ft: 124 corp: 8/30b lim: 5 exec/s: 0 rss: 32Mb L: 4/5 MS: 3 ChangeByte-ShuffleBytes-EraseBytes- + +#108 REDUCE cov: 113 ft: 124 corp: 8/29b lim: 5 exec/s: 0 rss: 32Mb L: 4/5 MS: 4 ShuffleBytes-EraseBytes-ShuffleBytes-ChangeByte- + +#156 REDUCE cov: 113 ft: 124 corp: 8/28b lim: 5 exec/s: 0 rss: 32Mb L: 3/5 MS: 3 CopyPart-ShuffleBytes-EraseBytes- + +#257 REDUCE cov: 113 ft: 124 corp: 8/27b lim: 5 exec/s: 0 rss: 32Mb L: 1/5 MS: 1 EraseBytes- + +#283 REDUCE cov: 113 ft: 124 corp: 8/26b lim: 5 exec/s: 0 rss: 32Mb L: 3/5 MS: 1 EraseBytes- + +#587 NEW cov: 113 ft: 125 corp: 9/33b lim: 7 exec/s: 0 rss: 33Mb L: 7/7 MS: 4 CMP-InsertByte-CopyPart-ChangeByte- DE: "\x00\x00"- + +#591 NEW cov: 113 ft: 126 corp: 10/40b lim: 7 exec/s: 0 rss: 33Mb L: 7/7 MS: 4 PersAutoDict-EraseBytes-ChangeByte-InsertByte- DE: "\x00\x00"- + +#607 REDUCE cov: 113 ft: 126 corp: 10/38b lim: 7 exec/s: 0 rss: 33Mb L: 5/7 MS: 1 EraseBytes- + +#748 NEW cov: 113 ft: 128 corp: 11/42b lim: 7 exec/s: 0 rss: 34Mb L: 4/7 MS: 1 ChangeBit- + +#893 REDUCE cov: 113 ft: 128 corp: 11/41b lim: 7 exec/s: 0 rss: 34Mb L: 4/7 MS: 5 InsertByte-ChangeByte-PersAutoDict-PersAutoDict-EraseBytes- DE: "\x00\x00"-"\x00\x00"- + +#1000 REDUCE cov: 113 ft: 128 corp: 11/40b lim: 7 exec/s: 0 rss: 34Mb L: 2/7 MS: 2 InsertByte-EraseBytes- + +#1089 NEW cov: 113 ft: 129 corp: 12/46b lim: 7 exec/s: 0 rss: 34Mb L: 6/7 MS: 4 PersAutoDict-ShuffleBytes-ChangeBit-ChangeBit- DE: "\x00\x00"- + +#1297 NEW cov: 113 ft: 130 corp: 13/55b lim: 9 exec/s: 0 rss: 35Mb L: 9/9 MS: 3 ChangeByte-CopyPart-InsertByte- + +#1678 NEW cov: 113 ft: 132 corp: 14/61b lim: 12 exec/s: 0 rss: 36Mb L: 6/9 MS: 1 ChangeBit- + +#1869 REDUCE cov: 113 ft: 132 corp: 14/60b lim: 12 exec/s: 0 rss: 36Mb L: 1/9 MS: 1 EraseBytes- + +#1898 REDUCE cov: 113 ft: 132 corp: 14/59b lim: 12 exec/s: 0 rss: 36Mb L: 3/9 MS: 4 ChangeASCIIInt-CopyPart-InsertRepeatedBytes-CrossOver- + +#2211 NEW cov: 113 ft: 133 corp: 15/73b lim: 15 exec/s: 0 rss: 37Mb L: 14/14 MS: 3 ChangeByte-InsertRepeatedBytes-CopyPart- + +================================================================= + +==13469==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffedc0c1df0 at pc 0x00000055a3b0 bp 0x7ffedc0c1950 sp 0x7ffedc0c1948 + +READ of size 1 at 0x7ffedc0c1df0 thread T0 + + #0 0x55a3af in BasePrintLibSPrintMarker /root/hbfa_workspace/edk2/MdePkg/Library/BasePrintLib/PrintLibInternal.c:1159:13 + + #1 0x5537cb in UnicodeVSPrint /root/hbfa_workspace/edk2/MdePkg/Library/BasePrintLib/PrintLib.c:73:10 + + #2 0x550b3c in InternalPrint /root/hbfa_workspace/edk2/MdePkg/Library/UefiLib/UefiLibPrint.c:70:12 + + #3 0x550d5e in Print /root/hbfa_workspace/edk2/MdePkg/Library/UefiLib/UefiLibPrint.c:119:12 + + #4 0x5508e1 in ProcessArgument /root/hbfa_workspace/edk2/MdeModulePkg/Library/HelloWorldLib/HelloWorldLib.c:61:5 + + #5 0x54eb7f in RunTestHarness /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestCasePkg/TestCase/MdeModulePkg/Application/HelloWorld/TestHelloWorld.c:49:3 + + #6 0x54e9d7 in LLVMFuzzerTestOneInput /root/hbfa_workspace/hbfa-fl/HBFA/UefiHostFuzzTestPkg/Library/ToolChainHarnessLib/ToolChainHarnessLib.c:138:3 + + #7 0x44dc89 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestHelloWorld+0x44dc89) + + #8 0x44e7f0 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) (/root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestHelloWorld+0x44e7f0) + + #9 0x44fa83 in fuzzer::Fuzzer::MutateAndTestOne() (/root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestHelloWorld+0x44fa83) + + #10 0x451577 in fuzzer::Fuzzer::Loop(std::vector >&) (/root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestHelloWorld+0x451577) + + #11 0x43641a in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestHelloWorld+0x43641a) + + #12 0x425a56 in main (/root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestHelloWorld+0x425a56) + + #13 0x7f77efc2feaf in __libc_start_call_main (/lib64/libc.so.6+0x3feaf) + + #14 0x7f77efc2ff5f in __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x3ff5f) + + #15 0x425aa4 in _start (/root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestHelloWorld+0x425aa4) + + + +Address 0x7ffedc0c1df0 is located in stack of thread T0 at offset 48 in frame + + #0 0x5506bf in ProcessArgument /root/hbfa_workspace/edk2/MdeModulePkg/Library/HelloWorldLib/HelloWorldLib.c:58 + + + + This frame has 1 object(s): + + [32, 48) 'MyBuffer' (line 59) <== Memory access at offset 48 overflows this variable + +HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork + + (longjmp and C++ exceptions *are* supported) + +SUMMARY: AddressSanitizer: stack-buffer-overflow /root/hbfa_workspace/edk2/MdePkg/Library/BasePrintLib/PrintLibInternal.c:1159:13 in BasePrintLibSPrintMarker + +Shadow bytes around the buggy address: + + 0x10005b810360: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + 0x10005b810370: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + 0x10005b810380: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00 00 00 f3 + + 0x10005b810390: f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00 + + 0x10005b8103a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +=>0x10005b8103b0: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00 00[f3]f3 + + 0x10005b8103c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + 0x10005b8103d0: 00 00 00 00 f1 f1 f1 f1 00 00 f3 f3 00 00 00 00 + + 0x10005b8103e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + 0x10005b8103f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + 0x10005b810400: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +Shadow byte legend (one shadow byte represents 8 application bytes): + + Addressable: 00 + + Partially addressable: 01 02 03 04 05 06 07 + + Heap left redzone: fa + + Freed heap region: fd + + Stack left redzone: f1 + + Stack mid redzone: f2 + + Stack right redzone: f3 + + Stack after return: f5 + + Stack use after scope: f8 + + Global redzone: f9 + + Global init order: f6 + + Poisoned by user: f7 + + Container overflow: fc + + Array cookie: ac + + Intra object redzone: bb + + ASan internal: fe + + Left alloca redzone: ca + + Right alloca redzone: cb + +==13469==ABORTING + +MS: 1 CopyPart-; base unit: 05c470e2f391593e9aca50949f9528bff29413de + +0x0,0x30,0x0,0x4,0x0,0x55,0x0,0x55,0x4,0x0,0x55,0x55,0x55,0x55,0x4, + +\x000\x00\x04\x00U\x00U\x04\x00UUUU\x04 + +artifact_prefix='/tmp/fuzz_RunAFL_TestHelloWorldLib/'; Test unit written to /tmp/fuzz_RunAFL_TestHelloWorldLib/crash-64747b0e18749998ecf47ad41fd3b34439e8ce07 + +Base64: ADAABABVAFUEAFVVVVUE + +``` + +
+ +As can be seen in the output, LibFuzzer goes through several iterations and eventually a stack overflow vulnerability is detected by AddressSantizer (ASAN). Looking the stack-trace, we can see the the detection/overflow occurred once we had called into the ``ProcessArgument``. Further, it indicates that the ``MyBuffer`` variable is overflowed. Last, noting the input file that caused this crash will be saved to the directory we specified for the output directory; from the output, the crash file was saved to /tmp/fuzz_RunLibFuzzer_TestHelloWorldLib. Before we proceed into debugging and verifying the issue identify by ASAN, we'll first verify that the crash is reproducible, using the crash file saved from the fuzzing run. + +### Reproducing the crash + +We will reproduce the crash by running the fuzzing test-case binary and providing the crash file as the input seed. For LibFuzzer, this is the first argument provided to the fuzzing binary. Further, we will run the binary for the fuzzer in GDB, can subsequently inspect and debug the crash.Note, you may need to install GDB. Your Linux distribution should have a package available, otherwise, see the GDB project [web-page](https://www.sourceware.org/gdb/) for information on obtaining and installing the debugger. + +Next, run GDB and provide the path to the TestHelloWorld fuzzing binary as the first argument. You should see something similar to the following: + +```console +[root@00c4495bd766 hbfa_workspace]# gdb /root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestHelloWorld +GNU gdb (GDB) Fedora 12.1-1.fc35 +Copyright (C) 2022 Free Software Foundation, Inc. +License GPLv3+: GNU GPL version 3 or later +This is free software: you are free to change and redistribute it. +There is NO WARRANTY, to the extent permitted by law. +Type "show copying" and "show warranty" for details. +This GDB was configured as "x86_64-redhat-linux-gnu". +Type "show configuration" for configuration details. +For bug reporting instructions, please see: +. +Find the GDB manual and other documentation resources online at: + . + +For help, type "help". +Type "apropos word" to search for commands related to "word"... +Reading symbols from /root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestHelloWorld... +(gdb) +``` + +Next, you can run the TestHelloWorld binary using the GDB 'run' command. The arguments provided to the 'run' command will be passed to the TestHelloWorld binary under debugging. Noting, we provide the file path to the crash file as the first argument. An additional argument is provided in the example to unlimit memory used by ASAN and may not be needed, depending on your fuzz case. + +```console +(gdb) run /tmp/fuzz_RunAFL_TestHelloWorldLib/crash-64747b0e18749998ecf47ad41fd3b34439e8ce07 -rss_limit_mb=0 +``` + +When ran, you should see the familiar output from ASAN warning/detection, as shown in the following Figure. This shows that we can at least reproduce the crash (as well as do so under a debugging environment). Next, we can take a look at debugging the crash/verifying the issue detected by ASAN. + +
+ +
Example of output from running crash case under debugger for TestHelloWorld, with important sections highlighted.
+
+ +### Debugging the crash + +In order to help make the debugging for the crash more easily viewable, instead of debugging using our crash file from above, we'll simply create a file containing 'A' characters, and use this as our crash file input. The same fundamentals apply for debugging the actual crash file; however, your crash file bytes may slightly differ and this will provide the best repeatable approach for this tutorial. To create the new crash file, you can simply run a Python command and redirect output to a new file: /tmp/crash, as shown in the following: + +```console +# python -c 'print("A"*46)' > /tmp/crash +``` + +Now when invoking the 'run' command in GDB, be sure to provide /tmp/crash as the argument, e.g.: + +```console +(gdb) run /tmp/crash +``` + +In order to verify the stack overflow, we’ll need to identify and set a few break points. Since we did compile with debugging information, we can leverage the ‘list’ command in GDB to look around the source code, as built for the harness. First, we'll look around the ``ProcessArgument`` fuction. + +
+ +
Example of output from running GDB 'list ProcessArgument' for TestHelloWorld.
+
+ +Here, as shown near the label A, we run the ‘list ProcessArgument’ to examine code near that function. As shown, we can see the ‘MyBuffer’ identified in the ASAN output. Likewise, we see a suspicious ‘MyStrCpy’ command invoked at line 60, which appears to include arguments to the function call that reference MyBuffer and the shell parameters Argv array. + +Next, we again use the 'list' command to inspect around the ``MyStrCpy`` function. + +
+ +
Example of output from running GDB 'list MyStrCpy' for TestHelloWorld.
+
+ +To that end, we’ll want to set break points around the ``MyStrCpy`` function and examine what happens to MyBuffer. Here, we end up needing to set break points at lines 41, 44, and 61 for the HelloWorldLib.c file. Line 61 corresponds to just after the return from MyStrCpy shown near the label A in the first Figure. Because of ASAN instrumentation catching the overflow and redirecting code output, we won't actually reach this point. Nonetheless we'll include. Often you want to pin your break points around where you expect to reach; a sanitizer may not be in use and you would want to see the state after return. The breakpoint at Line 41 is just before the actual copy takes place into the MyBuffer array; this point was selected as it gave the best viewpoint for the present tutorial. We also select Line 44 as this is in a loop where the actual write from source to destination for the copied bytes is taking place. We can step through the copy, byte for byte. + +The commands for setting these breakpoints are shown in the following. + +```console +(gdb) b /root/hbfa_workspace/edk2/MdeModulePkg/Library/HelloWorldLib/HelloWorldLib.c:41 +Breakpoint 1 at 0x5505ef: /root/hbfa_workspace/edk2/MdeModulePkg/Library/HelloWorldLib/HelloWorldLib.c:41. (2 locations) +(gdb) b /root/hbfa_workspace/edk2/MdeModulePkg/Library/HelloWorldLib/HelloWorldLib.c:44 +Breakpoint 2 at 0x550620: /root/hbfa_workspace/edk2/MdeModulePkg/Library/HelloWorldLib/HelloWorldLib.c:44. (2 locations) +(gdb) b /root/hbfa_workspace/edk2/MdeModulePkg/Library/HelloWorldLib/HelloWorldLib.c:61 +Breakpoint 3 at 0x5508d6: file /root/hbfa_workspace/edk2/MdeModulePkg/Library/HelloWorldLib/HelloWorldLib.c, line 61. +(gdb) i b +Num Type Disp Enb Address What +1 breakpoint keep y +1.1 y 0x00000000005505ef in MyStrCpy at /root/hbfa_workspace/edk2/MdeModulePkg/Library/HelloWorldLib/HelloWorldLib.c:41 +1.2 y 0x0000000000550833 in MyStrCpy at /root/hbfa_workspace/edk2/MdeModulePkg/Library/HelloWorldLib/HelloWorldLib.c:41 +2 breakpoint keep y +2.1 y 0x0000000000550620 in MyStrCpy at /root/hbfa_workspace/edk2/MdeModulePkg/Library/HelloWorldLib/HelloWorldLib.c:44 +2.2 y 0x0000000000550860 in MyStrCpy at /root/hbfa_workspace/edk2/MdeModulePkg/Library/HelloWorldLib/HelloWorldLib.c:44 +3 breakpoint keep y 0x00000000005508d6 in ProcessArgument + at /root/hbfa_workspace/edk2/MdeModulePkg/Library/HelloWorldLib/HelloWorldLib.c:61 +``` + +Next, we'll run the program and take a look at what is happening. + +```console +(gdb) run /tmp/crash +Starting program: /root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestHelloWorld /tmp/crash + +This GDB supports auto-downloading debuginfo from the following URLs: +https://debuginfod.fedoraproject.org/ +Enable debuginfod for this session? (y or [n]) y +Debuginfod has been enabled. +To make this setting permanent, add 'set debuginfod enabled on' to .gdbinit. +[Thread debugging using libthread_db enabled] +Using host libthread_db library "/lib64/libthread_db.so.1". +INFO: Running with entropic power schedule (0xFF, 100). +INFO: Seed: 4077516461 +INFO: Loaded 1 modules (3888 inline 8-bit counters): 3888 [0x5e03c0, 0x5e12f0), +INFO: Loaded 1 PC tables (3888 PCs): 3888 [0x59fab8,0x5aedb8), +[New Thread 0x7ffff4bf9640 (LWP 532)] +/root/hbfa_workspace/Build/UefiHostFuzzTestCasePkg/DEBUG_LIBFUZZER/X64/TestHelloWorld: Running 1 inputs 1 time(s) each. +Running: /tmp/crash + +Thread 1 "TestHelloWorld" hit Breakpoint 1, MyStrCpy (dst=0x7fffffffd320 "", src=0x606000000080 'A' , "\n") at /root/hbfa_workspace/edk2/MdeModulePkg/Library/HelloWorldLib/HelloWorldLib.c:41 +41 Print(L"Length of string copy: %d\n", len); +(gdb)``` + +Here, upon hitting the first breakpoint, we can see the memory addresses for the source (src) and destination (dst) arguments for the call into MyStrCpy. Taking a quick look at those, we see the following. + +```console +(gdb) x/16x 0x606000000080 +0x606000000080: 0x41414141 0x41414141 0x41414141 0x41414141 +0x606000000090: 0x41414141 0x41414141 0x41414141 0x41414141 +0x6060000000a0: 0x41414141 0x41414141 0x41414141 0x000a4141 +0x6060000000b0: 0x00000000 0x00000000 0x00000000 0x00000000 +(gdb) x/16x 0x7fffffffd320 +0x7fffffffd320: 0x00000000 0x00000000 0xf7fb7ce0 0x00007fff +0x7fffffffd330: 0x00000000 0x00000000 0x00000000 0x00000000 +0x7fffffffd340: 0x00000000 0x00000000 0x00000000 0x00000000 +0x7fffffffd350: 0x00000000 0x00000000 0xffffd320 0x00007fff +``` + +As expected, at the source location (corresponding to a heap address), we see a buffer of 0x41 bytes ('A' characters). Likewise, at destination address (a stack address), we see that none of the bytes have been copied to our destination address. Next, we run 'c' for continue, and hit are breapkpiont at Line 44 of HelloWorldLib.c. This is the location where the actual copy to the MyBuffer variable on the stack will occur. As shown in the screenshot below, when we first reach the breakpoint, there are Null bytes; nothing has been written. When we continue again, we hit the next pass in this loop and you can see one value 0x41 has been written to MyBuffer (note Endianess in the displayed bytes output from GDB). + +
+ +
Example of output from debugging copy of bytes in MyStrCpy when running TestHelloWorld.
+
+``` + +Next, we can keep running the 'c' (continue) command and step through the loop a few more times. As shown in the following screenshot, more bytes are written to MyBuffer. + +
+ +
Example of output from debugging copying of additional bytes in MyStrCpy when running TestHelloWorld.
+
+ +If we continue stepping, we'll eventually reach a point where the bytes have written past the 16 bytes allocated on the stack for MyBuffer and the ASAN error is caught. This is shown in the following screenshot. + +
+ +
Example of output from debugging copy of bytes in MyStrCpy and trigger an overflow detection when running TestHelloWorld.
+
+ +Thus we have verified that a buffer overflow is happening and have reached the completion of this tutorial. Thank you for taking the time to read these materials. + +Return to [Summary](../SUMMARY.md) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e69de29