diff --git a/.github/builder/.dockerignore b/.github/builder/.dockerignore new file mode 100644 index 00000000..1d1fe94d --- /dev/null +++ b/.github/builder/.dockerignore @@ -0,0 +1 @@ +Dockerfile \ No newline at end of file diff --git a/.github/builder/Dockerfile b/.github/builder/Dockerfile new file mode 100644 index 00000000..83e7e39d --- /dev/null +++ b/.github/builder/Dockerfile @@ -0,0 +1,17 @@ +# hadolint global ignore=DL3033,SC3044 +FROM novafacing/fedora-rustc-oldcompat:0.0.1 + +ENV PATH="${PATH}:/simics/ispm/" +ENV PATH="${PATH}:/root/.cargo/bin/" + +COPY . /tsffs/ + +WORKDIR /tsffs/ + +RUN mkdir -p /simics/ispm && \ + tar -C /simics/ispm --strip-components=1 -xvf .github/builder/rsrc/ispm.tar.gz && \ + ispm settings install-dir /simics && \ + ispm packages --install-bundle .github/builder/rsrc/simics.ispm --non-interactive --trust-insecure-packages && \ + ispm projects "$(pwd)" --create --ignore-existing-files --non-interactive && \ + bin/project-setup --force && \ + cargo -Zscript build.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 630a26df..fbb747e0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,5 +1,5 @@ --- -name: CI +name: Build And Test on: push: @@ -16,19 +16,86 @@ env: PUBLIC_SIMICS_PACKAGE_VERSION_1000: "6.0.169" MINGW_URL: "https://github.com/brechtsanders/winlibs_mingw/releases/download/13.2.0-16.0.6-11.0.0-ucrt-r1/winlibs-x86_64-posix-seh-gcc-13.2.0-llvm-16.0.6-mingw-w64ucrt-11.0.0-r1.7z" MINGW_VERSION: "13.2.0-16.0.6-11.0.0-ucrt-r1" + TSFFS_SIMICS_PKG_VERSION: "6.0.0" jobs: + build_test_artifacts: + name: Build Test Artifacts + runs-on: ubuntu-latest + steps: + - name: Add ISPM to PATH + run: | + echo "${HOME}/simics/ispm/" >> "${GITHUB_PATH}" + + - name: Install Dependencies + run: | + sudo apt-get -y update && \ + sudo apt-get -y install \ + clang libclang-dev cmake curl dosfstools g++ gcc git llvm make \ + mtools ninja-build openssl libssl-dev python3 python3-pip + + - name: Cache SIMICS Dependencies + id: cache-simics-packages + uses: actions/cache@v3 + with: + path: ~/simics + key: simics-linux-${{ env.PUBLIC_SIMICS_PACKAGE_VERSION_1000 }} + + - name: Install SIMICS (External) + if: ${{ steps.cache-simics-packages.outputs.cache-hit != 'true' }} + run: | + mkdir -p "${HOME}/simics/ispm/" && \ + curl --noproxy -L -o "${HOME}/simics/ispm.tar.gz" \ + "${{ env.PUBLIC_SIMICS_ISPM_URL }}" && \ + curl --noproxy -L -o "${HOME}/simics/simics.ispm" \ + "${{ env.PUBLIC_SIMICS_PKGS_URL }}" && \ + tar -C "${HOME}/simics/ispm" --strip-components=1 \ + -xvf "${HOME}/simics/ispm.tar.gz" + + - name: Set up SIMICS Install Directory + run: | + ispm settings install-dir "${HOME}/simics" + + - name: Install SIMICS Packages + if: ${{ steps.cache-simics-packages.outputs.cache-hit != 'true' }} + run: | + ispm packages --install-bundle "${HOME}/simics/simics.ispm" \ + --non-interactive --trust-insecure-packages + + - uses: actions/checkout@v4 + with: + lfs: true + + - name: Cache Test Artifacts + id: cache-test-artifacts + uses: actions/cache@v3 + with: + path: examples/tests + key: cache-test-artifacts-${{ hashFiles('examples/tests/**/*') }} + + - name: Build Test Artifacts + if: ${{ steps.cache-test-artifacts.outputs.cache-hit != 'true' }} + run: | + cd examples/tests/ + ./build.sh + + - name: Upload Test Artifacts + uses: actions/upload-artifact@v3 + with: + name: test-artifacts + path: examples/tests/ + build_and_test: - name: Build and Test + name: Build and Test (Linux) container: fedora:38 runs-on: ubuntu-latest + needs: build_test_artifacts steps: - name: Add ISPM to PATH run: | echo "${HOME}/simics/ispm/" >> "${GITHUB_PATH}" - name: Install Dependencies - shell: bash run: | dnf -y update && \ dnf -y install \ @@ -43,6 +110,22 @@ jobs: with: lfs: true + - name: Delete Un-Built Test Dependencies + run: | + rm -rf examples/tests/ + + - name: Download Test Dependencies + uses: actions/download-artifact@v3 + with: + name: test-artifacts + path: examples/tests/ + + - name: Take Ownership of Test Dependencies + run: | + ls -lahR examples/tests/ + chown -R "${USER}:${USER}" examples/tests/ + chmod -R 0755 examples/tests/ + - uses: dtolnay/rust-toolchain@nightly with: toolchain: nightly @@ -57,7 +140,6 @@ jobs: - name: Install SIMICS (External) if: ${{ steps.cache-simics-packages.outputs.cache-hit != 'true' }} - shell: bash run: | mkdir -p "${HOME}/simics/ispm/" && \ curl --noproxy -L -o "${HOME}/simics/ispm.tar.gz" \ @@ -84,26 +166,40 @@ jobs: bin/project-setup --force ./build.rs ispm packages \ - -i linux64/packages/simics-pkg-31337-6.0.0-linux64.ispm \ + -i linux64/packages/simics-pkg-31337-${{ env.TSFFS_SIMICS_PKG_VERSION }}-linux64.ispm \ --non-interactive --trust-insecure-packages - name: Build Project run: | SIMICS_BASE=${HOME}/simics/simics-${{ env.PUBLIC_SIMICS_PACKAGE_VERSION_1000 }} cargo build - - name: Check Project + + - name: CT39 - Clippy Check Project run: | - SIMICS_BASE=${HOME}/simics/simics-${{ env.PUBLIC_SIMICS_PACKAGE_VERSION_1000 }} cargo clippy + SIMICS_BASE=${HOME}/simics/simics-${{ env.PUBLIC_SIMICS_PACKAGE_VERSION_1000 }} cargo clippy \ + || ( echo "❗ [CT39 (1/2)] Failed clippy static analysis checks" && exit 1 ) + echo "✅ [CT39 (1/2)] Passed clippy static analysis checks" + - name: Test Project run: | - SIMICS_BASE=${HOME}/simics/simics-${{ env.PUBLIC_SIMICS_PACKAGE_VERSION_1000 }} cargo test -p command-ext -p raw-cstr -p tmp-dir -p version-tools || ( echo "❗ Tests failed" && exit 1 ) + TSFFS_TEST_CLEANUP_EACH=1 SIMICS_BASE=${HOME}/simics/simics-${{ env.PUBLIC_SIMICS_PACKAGE_VERSION_1000 }} cargo test -p command-ext -p raw-cstr -p tmp-dir -p version-tools -p tests -- --nocapture || ( echo "❗ Tests failed" && exit 1 ) echo "✅ Tests passed" + - name: Build Docs run: | SIMICS_BASE=${HOME}/simics/simics-${{ env.PUBLIC_SIMICS_PACKAGE_VERSION_1000 }} cargo doc --workspace --no-deps + - name: Test Docs run: | SIMICS_BASE=${HOME}/simics/simics-${{ env.PUBLIC_SIMICS_PACKAGE_VERSION_1000 }} cargo test --doc + - name: CT39 - MIRI Check Project + run: | + SIMICS_BASE=${HOME}/simics/simics-${{ env.PUBLIC_SIMICS_PACKAGE_VERSION_1000 }} \ + MIRIFLAGS="-Zmiri-backtrace=full -Zmiri-disable-isolation -Zmiri-panic-on-unsupported" \ + cargo miri test -p command-ext -p raw-cstr -p tmp-dir -p version-tools \ + || ( echo "❗ [CT39 (2/2)] Failed MIRI static analysis checks" && exit 1 ) + echo "✅ [CT39 (2/2)] Passed MIRI static analysis checks" + build_windows: name: Build and Test (Windows) runs-on: windows-latest @@ -175,90 +271,50 @@ jobs: ispm.exe projects $(pwd) --create --non-interactive --ignore-existing-files ./bin/project-setup.bat --mingw-dir C:\MinGW\ --ignore-existing-files --force cargo -Zscript build.rs - ispm.exe packages -i win64/packages/simics-pkg-31337-6.0.0-win64.ispm --non-interactive --trust-insecure-packages + ispm.exe packages -i win64/packages/simics-pkg-31337-${{ env.TSFFS_SIMICS_PKG_VERSION }}-win64.ispm --non-interactive --trust-insecure-packages - static_analysis: - name: Run Static Analysis - container: fedora:38 + - name: Upload Distribution Package + uses: actions/upload-artifact@v3 + with: + name: simics-pkg-31337-${{ env.TSFFS_SIMICS_PKG_VERSION }}-win64.ispm + path: win64/packages/simics-pkg-31337-${{ env.TSFFS_SIMICS_PKG_VERSION }}-win64.ispm + + build_dist: + name: Build for Distribution runs-on: ubuntu-latest steps: - - name: Add ISPM to PATH - run: | - echo "${HOME}/simics/ispm/" >> "${GITHUB_PATH}" - - - name: Install Dependencies - shell: bash - run: | - dnf -y update && \ - dnf -y install \ - alsa-lib atk clang clang-libs clang-resource-filesystem \ - clang-tools-extra cmake cups curl dosfstools g++ gcc git \ - git-lfs glibc-devel glibc-devel.i686 glibc-static \ - glibc-static.i686 gtk3 lld lld-devel lld-libs llvm llvm-libs \ - llvm-static make mesa-libgbm mtools ninja-build openssl \ - openssl-devel openssl-libs python3 python3-pip yamllint - - uses: actions/checkout@v4 with: lfs: true - - uses: dtolnay/rust-toolchain@nightly - with: - toolchain: nightly - components: rustfmt,clippy,miri - - - name: Cache SIMICS Dependencies - id: cache-simics-packages + - name: Cache Builder Dependencies + id: cache-builder-dependencies uses: actions/cache@v3 with: - path: ~/simics - key: simics-linux-${{ env.PUBLIC_SIMICS_PACKAGE_VERSION_1000 }} + path: .github/builder/rsrc + key: cache-builder-dependencies - - name: Install SIMICS (External) - if: ${{ steps.cache-simics-packages.outputs.cache-hit != 'true' }} - shell: bash + - name: Download Builder Dependencies + if: ${{ steps.cache-builder-dependencies.outputs.cache-hit != 'true' }} run: | - mkdir -p "${HOME}/simics/ispm/" && \ - curl --noproxy -L -o "${HOME}/simics/ispm.tar.gz" \ + mkdir -p .github/builder/rsrc + curl -L -o .github/builder/rsrc/ispm.tar.gz \ "${{ env.PUBLIC_SIMICS_ISPM_URL }}" && \ - curl --noproxy -L -o "${HOME}/simics/simics.ispm" \ - "${{ env.PUBLIC_SIMICS_PKGS_URL }}" && \ - tar -C "${HOME}/simics/ispm" --strip-components=1 \ - -xvf "${HOME}/simics/ispm.tar.gz" - - - name: Set up SIMICS Install Directory - run: | - ispm settings install-dir "${HOME}/simics" - - - name: Install SIMICS Packages - if: ${{ steps.cache-simics-packages.outputs.cache-hit != 'true' }} - run: | - ispm packages --install-bundle "${HOME}/simics/simics.ispm" \ - --non-interactive --trust-insecure-packages + curl -L -o .github/builder/rsrc/simics.ispm \ + "${{ env.PUBLIC_SIMICS_PKGS_URL }}" - - name: Build and Install TSFFS SIMICS Package + - name: Build Distribution Package run: | - ispm projects "$(pwd)" --create --ignore-existing-files \ - --non-interactive - bin/project-setup --force - ./build.rs - ispm packages \ - -i linux64/packages/simics-pkg-31337-6.0.0-linux64.ispm \ - --non-interactive --trust-insecure-packages + docker build -t tsffs-dist -f .github/builder/Dockerfile . + docker create --name tsffs-dist tsffs-dist bash + docker cp tsffs-dist:/tsffs/linux64/packages/simics-pkg-31337-${{ env.TSFFS_SIMICS_PKG_VERSION }}-linux64.ispm simics-pkg-31337-${{ env.TSFFS_SIMICS_PKG_VERSION }}-linux64.ispm + docker rm -f tsffs-dist - - name: CT39 - Clippy Check Project - run: | - SIMICS_BASE=${HOME}/simics/simics-${{ env.PUBLIC_SIMICS_PACKAGE_VERSION_1000 }} cargo clippy \ - || ( echo "❗ [CT39 (1/2)] Failed clippy static analysis checks" && exit 1 ) - echo "✅ [CT39 (1/2)] Passed clippy static analysis checks" - - - name: CT39 - MIRI Check Project - run: | - SIMICS_BASE=${HOME}/simics/simics-${{ env.PUBLIC_SIMICS_PACKAGE_VERSION_1000 }} \ - MIRIFLAGS="-Zmiri-backtrace=full -Zmiri-disable-isolation -Zmiri-panic-on-unsupported" \ - cargo miri test -p command-ext -p raw-cstr -p tmp-dir -p version-tools \ - || ( echo "❗ [CT39 (2/2)] Failed MIRI static analysis checks" && exit 1 ) - echo "✅ [CT39 (2/2)] Passed MIRI static analysis checks" + - name: Upload Distribution Package + uses: actions/upload-artifact@v3 + with: + name: simics-pkg-31337-${{ env.TSFFS_SIMICS_PKG_VERSION }}-linux64.ispm + path: simics-pkg-31337-${{ env.TSFFS_SIMICS_PKG_VERSION }}-linux64.ispm fuzz_tests: name: Run Fuzz Tests @@ -266,7 +322,6 @@ jobs: runs-on: ubuntu-latest steps: - name: Install Dependencies - shell: bash run: | dnf -y update && \ dnf -y install \ @@ -328,133 +383,3 @@ jobs: echo "✅ [CT632] Fuzz test completed" exit 0 - - super_lint: - name: Run Super Linter - container: github/super-linter - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - lfs: false - - name: (CT222) (E/C) - Use hadolint to evaluate Dockerfile configuration - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # Rust validation is handled by build_and_test - VALIDATE_RUST_2015: false - VALIDATE_RUST_2018: false - VALIDATE_RUST_2021: false - VALIDATE_RUST_CLIPPY: false - # We have no non-example CPP in the codebase - VALIDATE_CPP: false - VALIDATE_CLANG_FORMAT: false - VALIDATE_JSCPD: false - # This is way too pedantic - VALIDATE_NATURAL_LANGUAGE: false - # Dont flake8/mypy/pylint because our only python files attempt to import - # simics and fail - VALIDATE_PYTHON_FLAKE8: false - VALIDATE_PYTHON_MYPY: false - VALIDATE_PYTHON_PYLINT: false - run: | - /action/lib/linter.sh || ( echo "❗ [CT222] Super linter found an issue (possibly Hadolint)" && exit 1 ) - echo "✅ [CT222] Hadolint Dockerfile check passed" - - scan_containers: - runs-on: ubuntu-latest - strategy: - matrix: - dockerfile: - # NOTE: These containers exceed the GitHub size limit and must be scanned manually - # - Dockerfile - # - examples/manual-example/Dockerfile - # - modules/tsffs/tests/targets/minimal-riscv-64/Dockerfile - # - modules/tsffs/tests/targets/minimal-riscv-64-edk2/Dockerfile - - modules/tsffs/tests/targets/minimal-x86_64-breakpoint-edk2/Dockerfile - - modules/tsffs/tests/targets/minimal-x86_64-timeout/Dockerfile - - modules/tsffs/tests/targets/minimal-x86_64-edk2/Dockerfile - include: - # NOTE: These containers exceed the GitHub size limit and must be scanned manually - # - dockerfile: Dockerfile - # context: . - # - dockerfile: examples/manual-example/Dockerfile - # context: . - # - dockerfile: modules/tsffs/tests/targets/minimal-riscv-64/Dockerfile - # context: modules/tsffs/tests/targets/minimal-riscv-64/ - # - dockerfile: modules/tsffs/tests/targets/minimal-riscv-64-edk2/Dockerfile - # context: modules/tsffs/tests/targets/minimal-riscv-64-edk2/ - - dockerfile: modules/tsffs/tests/targets/minimal-x86_64-breakpoint-edk2/Dockerfile - context: modules/tsffs/tests/targets/minimal-x86_64-breakpoint-edk2/ - - dockerfile: modules/tsffs/tests/targets/minimal-x86_64-timeout/Dockerfile - context: modules/tsffs/tests/targets/minimal-x86_64-timeout/ - - dockerfile: modules/tsffs/tests/targets/minimal-x86_64-edk2/Dockerfile - context: modules/tsffs/tests/targets/minimal-x86_64-edk2/ - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - lfs: false - - - name: Build Image - run: | - docker build -t container -f ${{ matrix.dockerfile }} ${{ matrix.context }} - - - name: Run Trivy vulnerability scanner - uses: aquasecurity/trivy-action@master - with: - image-ref: container - - additional_sdl_checks: - name: Perform Additional SDL Checks - container: fedora:38 - runs-on: ubuntu-latest - steps: - - name: Install Dependencies - run: | - dnf -y update && \ - dnf -y install \ - alsa-lib atk clang clang-libs clang-resource-filesystem \ - clang-tools-extra cmake cups curl dosfstools g++ gcc git \ - git-lfs glibc-devel glibc-devel.i686 glibc-static \ - glibc-static.i686 gtk3 lld lld-devel lld-libs llvm llvm-libs \ - llvm-static make mesa-libgbm mtools ninja-build openssl \ - openssl-devel openssl-libs python3 python3-pip yamllint - - - uses: actions/checkout@v4 - with: - lfs: false - - uses: dtolnay/rust-toolchain@nightly - with: - toolchain: nightly - components: rustfmt,clippy,miri - - - name: Install Cargo Plugins - run: | - cargo install cargo-audit cargo-outdated - - name: (CT247/CT200) (N/C) - Scan 3rd-Party Components for Vulnerabilities, Verify that project is not using vulnerable 3rd party components - run: | - # shellcheck disable=SC2086,SC2143 - LATEST="$(find '.github/dependabot' -name '*.csv' -print0 \ - | xargs -r -0 ls -1 -t \ - | head -n 1)" - if ! find '.github/dependabot' -name '*.csv' -mtime -14 | grep -q '.'; then - echo "❗ [CT247/CT200] No dependabot report found from last 2 weeks. Run ./scripts/dependabot.sh." - exit 1 - fi - if tail -n+2 "${LATEST}" | grep -qv ".github/actions/toolchain"; then - cat "${LATEST}" - echo "❗ [CT247/CT200] Vulnerabilities found outside of github actions. Please remediate them." - exit 1 - fi - echo "✅ [CT247/CT200] No dependabot vulnerabilities found" - - name: (T186) (N/C) - Use recommended settings and latest patches for third party libraries and software - run: | - cargo audit - - if ! cargo outdated --exit-code 1; then - echo "❗ [T186] Out of date third party dependencies found" - exit 1 - fi - - echo "✅ [T186] No outdated or vulnerable third party dependencies found" diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 5f999e52..6bde2d33 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -1,3 +1,4 @@ +--- name: Deploy Documentation on: diff --git a/.github/workflows/scans.yml b/.github/workflows/scans.yml new file mode 100644 index 00000000..bbcd2f1d --- /dev/null +++ b/.github/workflows/scans.yml @@ -0,0 +1,143 @@ +--- +name: Scan And Validate + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + +jobs: + super_lint: + name: Run Super Linter + container: github/super-linter + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + lfs: false + + - name: (CT222) (E/C) - Use hadolint to evaluate Dockerfile configuration + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # Rust validation is handled by build_and_test + VALIDATE_RUST_2015: false + VALIDATE_RUST_2018: false + VALIDATE_RUST_2021: false + VALIDATE_RUST_CLIPPY: false + # We have no non-example CPP in the codebase + VALIDATE_CPP: false + VALIDATE_CLANG_FORMAT: false + VALIDATE_JSCPD: false + # This is way too pedantic + VALIDATE_NATURAL_LANGUAGE: false + # Dont flake8/mypy/pylint because our only python files attempt to import + # simics and fail + VALIDATE_PYTHON_FLAKE8: false + VALIDATE_PYTHON_MYPY: false + VALIDATE_PYTHON_PYLINT: false + run: | + /action/lib/linter.sh || ( echo "❗ [CT222] Super linter found an issue (possibly Hadolint)" && exit 1 ) + echo "✅ [CT222] Hadolint Dockerfile check passed" + + scan_containers: + runs-on: ubuntu-latest + strategy: + matrix: + dockerfile: + # NOTE: These containers exceed the GitHub size limit and must be scanned manually + # - Dockerfile + # - examples/manual-example/Dockerfile + # - modules/tsffs/tests/targets/minimal-riscv-64/Dockerfile + # - modules/tsffs/tests/targets/minimal-riscv-64-edk2/Dockerfile + - examples/tests/x86_64-breakpoint-uefi-edk2/Dockerfile + - examples/tests/x86_64-timeout-uefi-edk2/Dockerfile + - examples/tests/x86_64-uefi-edk2/Dockerfile + include: + # NOTE: These containers exceed the GitHub size limit and must be scanned manually + # - dockerfile: Dockerfile + # context: . + # - dockerfile: examples/manual-example/Dockerfile + # context: . + # - dockerfile: modules/tsffs/tests/targets/minimal-riscv-64/Dockerfile + # context: modules/tsffs/tests/targets/minimal-riscv-64/ + # - dockerfile: modules/tsffs/tests/targets/minimal-riscv-64-edk2/Dockerfile + # context: modules/tsffs/tests/targets/minimal-riscv-64-edk2/ + - dockerfile: examples/tests/x86_64-breakpoint-uefi-edk2/Dockerfile + context: examples/tests/x86_64-breakpoint-uefi-edk2/ + - dockerfile: examples/tests/x86_64-timeout-uefi-edk2/Dockerfile + context: examples/tests/x86_64-timeout-uefi-edk2/ + - dockerfile: examples/tests/x86_64-uefi-edk2/Dockerfile + context: examples/tests/x86_64-uefi-edk2/ + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + lfs: false + + - name: Build Image + run: | + docker build -t container -f ${{ matrix.dockerfile }} ${{ matrix.context }} + + - name: Run Trivy vulnerability scanner + uses: aquasecurity/trivy-action@master + with: + image-ref: container + + additional_sdl_checks: + name: Perform Additional SDL Checks + container: fedora:38 + runs-on: ubuntu-latest + steps: + - name: Install Dependencies + run: | + dnf -y update && \ + dnf -y install \ + g++ gcc git git-lfs glibc-devel make openssl openssl-devel openssl-libs + + - uses: actions/checkout@v4 + with: + lfs: false + + - uses: dtolnay/rust-toolchain@nightly + with: + toolchain: nightly + components: rustfmt,clippy,miri + + - name: Install Cargo Plugins + run: | + cargo install cargo-audit cargo-outdated + + - name: (CT247/CT200) (N/C) - Scan 3rd-Party Components for Vulnerabilities + run: | + # shellcheck disable=SC2086,SC2143 + LATEST="$(find '.github/dependabot' -name '*.csv' -print0 \ + | xargs -r -0 ls -1 -t \ + | head -n 1)" + + if ! find '.github/dependabot' -name '*.csv' -mtime -14 | grep -q '.'; then + echo "❗ [CT247/CT200] No dependabot report found from last 2 weeks. Run ./scripts/dependabot.sh." + exit 1 + fi + + if tail -n+2 "${LATEST}" | grep -qv ".github/actions/toolchain"; then + cat "${LATEST}" + echo "❗ [CT247/CT200] Vulnerabilities found outside of github actions. Please remediate them." + exit 1 + fi + echo "✅ [CT247/CT200] No dependabot vulnerabilities found" + + - name: (T186) (N/C) - Use recommended settings and latest patches for third party libraries and software + run: | + cargo generate-lockfile + + cargo audit + + if ! cargo outdated --exit-code 1; then + echo "❗ [T186] Out of date third party dependencies found" + exit 1 + fi + + echo "✅ [T186] No outdated or vulnerable third party dependencies found" diff --git a/Cargo.toml b/Cargo.toml index 51d22ec8..8feeb138 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,6 @@ version = "6.0.0" resolver = "2" members = [ "modules/tsffs/tests", - "modules/tsffs/tests-restricted", "modules/tsffs/src/tsffs", "modules/tsffs/src/simics/ispm-wrapper", "modules/tsffs/src/simics/simics-api-sys", @@ -43,7 +42,6 @@ members = [ ] default-members = [ "modules/tsffs/tests", - "modules/tsffs/tests-restricted", "modules/tsffs/src/tsffs", "modules/tsffs/src/simics/ispm-wrapper", "modules/tsffs/src/simics/simics-api-sys", diff --git a/config-user.mk b/config-user.mk index 0627a3fa..d4969347 100644 --- a/config-user.mk +++ b/config-user.mk @@ -14,6 +14,11 @@ USER_BUILD_ID=tsffs:1 + ifeq ($(HOST_TYPE),win64) LIBS=-lws2_32 -loleaut32 -lole32 -lbcrypt -luserenv -lntdll +endif + +ifeq ($(HOST_TYPE),linux64) + LDFLAGS=-Wl,--gc-sections endif \ No newline at end of file diff --git a/docs/src/harnessing/closed-box.md b/docs/src/harnessing/closed-box.md index b697d86d..fd5e8739 100644 --- a/docs/src/harnessing/closed-box.md +++ b/docs/src/harnessing/closed-box.md @@ -43,6 +43,13 @@ should be a processor instance, for example on the QSP platform with new testcases, and whose address space will be used for virtual address translation. +Both testcases also take a `virt: bool` as their final argument, to specify whether the +addresses passed are virtual addresses or physical addresses. If `False`, the addresses +will *not* be translated, which can allow circumventing issues where the address is +accessible, but the page table does not contain an identity mapping for it. A physical +address that is identity mapped may be passed with either a `True` or `False` value of +`virt`. + The first API takes two memory addresses, and is equivalent to the [compiled in `HARNESS_START`](compiled-in.md#using-provided-headers) macro. When called, the fuzzer will save the passed-in addresses (which may be virtual or physical), read the @@ -52,7 +59,7 @@ testcase pointer, and the size of the testcase will be written to the provided s pointer. This API is called like: ```python -tsffs.iface.tsffs.start(cpu, testcase_address, size_address) +tsffs.iface.tsffs.start(cpu, testcase_address, size_address, True) ``` The second API takes one memory address and a maximum size. Testcases will be written @@ -60,7 +67,7 @@ to the provided testcase address, and will be truncated to the provided maximum This API is called like: ```python -tsffs.iface.tsffs.start_with_maximum_size(cpu, testcase_address, maximum_size) +tsffs.iface.tsffs.start_with_maximum_size(cpu, testcase_address, maximum_size, True) ``` ## Triggering Manual Stops/Solutions diff --git a/docs/src/harnessing/manual.md b/docs/src/harnessing/manual.md index a2a0b790..b85e91aa 100644 --- a/docs/src/harnessing/manual.md +++ b/docs/src/harnessing/manual.md @@ -8,7 +8,7 @@ that is appropriate. Harnessing in this way can be done using the api. Note that the API method still takes a CPU object. When called, the initial snapshot is still captured in the same way as -with other [black box](black-box.md) harnessing methods. +with other [closed-box](closed-box.md) harnessing methods. ```python tsffs.iface.tsffs.start_without_buffer(cpu) diff --git a/modules/tsffs/tests/rsrc/minimal_boot_disk.craff b/examples/rsrc/minimal_boot_disk.craff similarity index 100% rename from modules/tsffs/tests/rsrc/minimal_boot_disk.craff rename to examples/rsrc/minimal_boot_disk.craff diff --git a/examples/tests/.gitignore b/examples/tests/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/examples/tests/README.md b/examples/tests/README.md new file mode 100644 index 00000000..7ad61b33 --- /dev/null +++ b/examples/tests/README.md @@ -0,0 +1,24 @@ +# Tests + +Examples that should be tested should be placed here. Each example should have a +`build.sh` script that generates or places all files required to run the test into the +test's directory. The `build.sh` script may accept a `SIMICS_BASE` environment +variable to locate simics-provided scripts. + +For example, [minimal-riscv-64/build.sh](minimal-riscv-64/build.sh) produces: + +- `fw_jump.elf` +- `Image` +- `rootfs.ext2` +- `test` +- `test-mod` +- `test-mod-userspace` +- `test-mod.ko` + +All of which are used by the tests that use this example. The files should be output in +the same directory structure they should be placed into the SIMICS project set up for +testing. + +Test scripts should be named following the pattern `test*.simics` and placed in the test +directory. + diff --git a/examples/tests/build.sh b/examples/tests/build.sh new file mode 100755 index 00000000..b030456f --- /dev/null +++ b/examples/tests/build.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +if [ -z "${SIMICS_BASE}" ]; then + echo "SIMICS_BASE is not set, defaulting to latest." + SIMICS_BASE="$(ispm packages --list-installed --json | jq -r '[ .installedPackages[] | select(.pkgNumber == 1000) ] | ([ .[].version ] | max_by(split(".") | map(tonumber))) as $m | first(first(.[]|select(.version == $m)).paths[0])')" + export SIMICS_BASE +fi + +if [ ! -d "${SIMICS_BASE}" ]; then + echo "SIMICS_BASE ${SIMICS_BASE} is not a directory." + exit 1 +fi + +for TARGET in *; do + if [ -d "${TARGET}" ]; then + pushd "${TARGET}" || exit 1 + ./build.sh + popd || exit 1 + fi +done diff --git a/examples/tests/riscv-64/.gitignore b/examples/tests/riscv-64/.gitignore new file mode 100644 index 00000000..fe9a8eab --- /dev/null +++ b/examples/tests/riscv-64/.gitignore @@ -0,0 +1,12 @@ +*.elf +Image +*.tar.gz +*.ext2 +test +test-mod +!test-mod/ +test-mod-userspace +test-mod.ko +*.h +*.craff +*.fs \ No newline at end of file diff --git a/modules/tsffs/tests/targets/minimal-riscv-64/Dockerfile b/examples/tests/riscv-64/Dockerfile similarity index 96% rename from modules/tsffs/tests/targets/minimal-riscv-64/Dockerfile rename to examples/tests/riscv-64/Dockerfile index e79fbfc6..f560b58e 100644 --- a/modules/tsffs/tests/targets/minimal-riscv-64/Dockerfile +++ b/examples/tests/riscv-64/Dockerfile @@ -41,5 +41,6 @@ RUN make BR2_EXTERNAL=/test/test-kernel-modules/ simics_simple_riscv_defconfig & /buildroot/output/host/bin/riscv64-buildroot-linux-gnu-gcc -o /test/usr/test /test/usr/test.c && \ /buildroot/output/host/bin/riscv64-buildroot-linux-gnu-gcc -o /test/usr/test-mod /test/usr/test-mod.c && \ /buildroot/output/host/bin/riscv64-buildroot-linux-gnu-gcc -o /test/usr/test-mod-userspace /test/usr/test-mod-userspace.c && \ + cp -a /buildroot/output/build/ /test/output/ && \ make clean diff --git a/examples/tests/riscv-64/build.sh b/examples/tests/riscv-64/build.sh new file mode 100755 index 00000000..2c11ce55 --- /dev/null +++ b/examples/tests/riscv-64/build.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +# Copyright (C) 2023 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +# Build the HelloWorld.efi module and copy it into the resource directory for the example +# this only needs to be run if you want to modify the source code for the HelloWorld.efi module, +# otherwise, the EFI is included in the source tree for ease of use + +if [ -z "${SIMICS_BASE}" ]; then + echo "SIMICS_BASE must be set" + exit 1 +fi + +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) +IMAGE_NAME="buildroot-build-tsffs-gcc-riscv64-test" +CONTAINER_UID=$(echo "${RANDOM}" | sha256sum | head -c 8) +CONTAINER_NAME="${IMAGE_NAME}-tmp-${CONTAINER_UID}" + +pushd "${SCRIPT_DIR}" || exit 1 + +cp "${SCRIPT_DIR}/../../../harness/tsffs-gcc-riscv64.h" "${SCRIPT_DIR}/tsffs-gcc-riscv64.h" +cp "${SCRIPT_DIR}/../../../harness/tsffs-gcc-riscv64.h" "${SCRIPT_DIR}/test-kernel-modules/package/kernel-modules/test-mod/tsffs-gcc-riscv64.h" +mkdir -p "${SCRIPT_DIR}/targets/risc-v-simple/images/linux/" + +if [ ! -e "${SCRIPT_DIR}/images.tar.gz" ] \ + || [ ! -e "${SCRIPT_DIR}/test" ] \ + || [ ! -e "${SCRIPT_DIR}/test-mod" ] \ + || [ ! -e "${SCRIPT_DIR}/test-mod-userspace" ] \ + || [ ! -e "${SCRIPT_DIR}/test-mod.ko" ]; then + docker build -t "${IMAGE_NAME}" -f "Dockerfile" . + docker create --name "${CONTAINER_NAME}" "${IMAGE_NAME}" + docker cp \ + "${CONTAINER_NAME}:/buildroot/images.tar.gz" \ + "${SCRIPT_DIR}/images.tar.gz" + docker cp \ + "${CONTAINER_NAME}:/test/usr/test" \ + "${SCRIPT_DIR}/test" + docker cp \ + "${CONTAINER_NAME}:/test/usr/test-mod" \ + "${SCRIPT_DIR}/test-mod" + docker cp \ + "${CONTAINER_NAME}:/test/usr/test-mod-userspace" \ + "${SCRIPT_DIR}/test-mod-userspace" + docker cp \ + "${CONTAINER_NAME}:/test/output/test-mod-1.0/test-mod.ko"\ + "${SCRIPT_DIR}/test-mod.ko" + docker rm -f "${CONTAINER_NAME}" +fi + +tar -C "${SCRIPT_DIR}/targets/risc-v-simple/images/linux/" -xvf images.tar.gz +rm images.tar.gz + +dd if=/dev/zero of=test.fs bs=1024 count=131072 +mkfs.fat test.fs +mcopy -i test.fs test-mod-userspace ::test-mod-userspace +mcopy -i test.fs test-mod ::test-mod +mcopy -i test.fs test ::test +mcopy -i test.fs test-mod.ko ::test-mod.ko +"${SIMICS_BASE}/linux64/bin/craff" -o test.fs.craff test.fs diff --git a/modules/tsffs/tests/targets/minimal-riscv-64/simics_simple_riscv_defconfig b/examples/tests/riscv-64/simics_simple_riscv_defconfig similarity index 100% rename from modules/tsffs/tests/targets/minimal-riscv-64/simics_simple_riscv_defconfig rename to examples/tests/riscv-64/simics_simple_riscv_defconfig diff --git a/examples/tests/riscv-64/test-kernel-from-userspace-magic.simics b/examples/tests/riscv-64/test-kernel-from-userspace-magic.simics new file mode 100644 index 00000000..32cb4e4b --- /dev/null +++ b/examples/tests/riscv-64/test-kernel-from-userspace-magic.simics @@ -0,0 +1,33 @@ +load-module tsffs + +@tsffs = SIM_create_object(SIM_get_class("tsffs"), "tsffs", []) +tsffs.log-level 4 +@tsffs.iface.tsffs.set_start_on_harness(True) +@tsffs.iface.tsffs.set_stop_on_harness(True) +@tsffs.iface.tsffs.set_start_magic_number(3) +@tsffs.iface.tsffs.set_stop_magic_number(4) +@tsffs.iface.tsffs.set_timeout(3.0) +@tsffs.iface.tsffs.add_exception_solution(14) +@tsffs.iface.tsffs.set_generate_random_corpus(True) +@tsffs.iface.tsffs.set_iterations(1000) +@tsffs.iface.tsffs.set_use_snapshots(True) + +load-target "risc-v-simple/linux" namespace = riscv machine:hardware:storage:disk1:image = "test.fs.craff" + +script-branch { + bp.time.wait-for seconds = 15 + board.console.con.input "mkdir /mnt/disk0\r\n" + bp.time.wait-for seconds = 1.0 + board.console.con.input "mount /dev/vdb /mnt/disk0\r\n" + bp.time.wait-for seconds = 1.0 + board.console.con.input "insmod /mnt/disk0/test-mod.ko\r\n" + bp.time.wait-for seconds = 1.0 + board.console.con.input "/mnt/disk0/test-mod-userspace\r\n" +} + +script-branch { + bp.time.wait-for seconds = 240 + quit 1 +} + +run \ No newline at end of file diff --git a/examples/tests/riscv-64/test-kernel-magic.simics b/examples/tests/riscv-64/test-kernel-magic.simics new file mode 100644 index 00000000..32cb4e4b --- /dev/null +++ b/examples/tests/riscv-64/test-kernel-magic.simics @@ -0,0 +1,33 @@ +load-module tsffs + +@tsffs = SIM_create_object(SIM_get_class("tsffs"), "tsffs", []) +tsffs.log-level 4 +@tsffs.iface.tsffs.set_start_on_harness(True) +@tsffs.iface.tsffs.set_stop_on_harness(True) +@tsffs.iface.tsffs.set_start_magic_number(3) +@tsffs.iface.tsffs.set_stop_magic_number(4) +@tsffs.iface.tsffs.set_timeout(3.0) +@tsffs.iface.tsffs.add_exception_solution(14) +@tsffs.iface.tsffs.set_generate_random_corpus(True) +@tsffs.iface.tsffs.set_iterations(1000) +@tsffs.iface.tsffs.set_use_snapshots(True) + +load-target "risc-v-simple/linux" namespace = riscv machine:hardware:storage:disk1:image = "test.fs.craff" + +script-branch { + bp.time.wait-for seconds = 15 + board.console.con.input "mkdir /mnt/disk0\r\n" + bp.time.wait-for seconds = 1.0 + board.console.con.input "mount /dev/vdb /mnt/disk0\r\n" + bp.time.wait-for seconds = 1.0 + board.console.con.input "insmod /mnt/disk0/test-mod.ko\r\n" + bp.time.wait-for seconds = 1.0 + board.console.con.input "/mnt/disk0/test-mod-userspace\r\n" +} + +script-branch { + bp.time.wait-for seconds = 240 + quit 1 +} + +run \ No newline at end of file diff --git a/modules/tsffs/tests/targets/minimal-riscv-64/test-kernel-modules/Config.in b/examples/tests/riscv-64/test-kernel-modules/Config.in similarity index 100% rename from modules/tsffs/tests/targets/minimal-riscv-64/test-kernel-modules/Config.in rename to examples/tests/riscv-64/test-kernel-modules/Config.in diff --git a/modules/tsffs/tests/targets/minimal-riscv-64/test-kernel-modules/external.desc b/examples/tests/riscv-64/test-kernel-modules/external.desc similarity index 100% rename from modules/tsffs/tests/targets/minimal-riscv-64/test-kernel-modules/external.desc rename to examples/tests/riscv-64/test-kernel-modules/external.desc diff --git a/modules/tsffs/tests/targets/minimal-riscv-64/test-kernel-modules/external.mk b/examples/tests/riscv-64/test-kernel-modules/external.mk similarity index 100% rename from modules/tsffs/tests/targets/minimal-riscv-64/test-kernel-modules/external.mk rename to examples/tests/riscv-64/test-kernel-modules/external.mk diff --git a/modules/tsffs/tests/targets/minimal-riscv-64/test-kernel-modules/package/kernel-modules/Config.in b/examples/tests/riscv-64/test-kernel-modules/package/kernel-modules/Config.in similarity index 100% rename from modules/tsffs/tests/targets/minimal-riscv-64/test-kernel-modules/package/kernel-modules/Config.in rename to examples/tests/riscv-64/test-kernel-modules/package/kernel-modules/Config.in diff --git a/modules/tsffs/tests/targets/minimal-riscv-64/test-kernel-modules/package/kernel-modules/kernel-modules.mk b/examples/tests/riscv-64/test-kernel-modules/package/kernel-modules/kernel-modules.mk similarity index 100% rename from modules/tsffs/tests/targets/minimal-riscv-64/test-kernel-modules/package/kernel-modules/kernel-modules.mk rename to examples/tests/riscv-64/test-kernel-modules/package/kernel-modules/kernel-modules.mk diff --git a/modules/tsffs/tests/targets/minimal-riscv-64/test-kernel-modules/package/kernel-modules/test-mod/Config.in b/examples/tests/riscv-64/test-kernel-modules/package/kernel-modules/test-mod/Config.in similarity index 100% rename from modules/tsffs/tests/targets/minimal-riscv-64/test-kernel-modules/package/kernel-modules/test-mod/Config.in rename to examples/tests/riscv-64/test-kernel-modules/package/kernel-modules/test-mod/Config.in diff --git a/modules/tsffs/tests/targets/minimal-riscv-64/test-kernel-modules/package/kernel-modules/test-mod/Makefile b/examples/tests/riscv-64/test-kernel-modules/package/kernel-modules/test-mod/Makefile similarity index 100% rename from modules/tsffs/tests/targets/minimal-riscv-64/test-kernel-modules/package/kernel-modules/test-mod/Makefile rename to examples/tests/riscv-64/test-kernel-modules/package/kernel-modules/test-mod/Makefile diff --git a/modules/tsffs/tests/targets/minimal-riscv-64/test-kernel-modules/package/kernel-modules/test-mod/test-mod.c b/examples/tests/riscv-64/test-kernel-modules/package/kernel-modules/test-mod/test-mod.c similarity index 100% rename from modules/tsffs/tests/targets/minimal-riscv-64/test-kernel-modules/package/kernel-modules/test-mod/test-mod.c rename to examples/tests/riscv-64/test-kernel-modules/package/kernel-modules/test-mod/test-mod.c diff --git a/modules/tsffs/tests/targets/minimal-riscv-64/test-kernel-modules/package/kernel-modules/test-mod/test-mod.mk b/examples/tests/riscv-64/test-kernel-modules/package/kernel-modules/test-mod/test-mod.mk similarity index 100% rename from modules/tsffs/tests/targets/minimal-riscv-64/test-kernel-modules/package/kernel-modules/test-mod/test-mod.mk rename to examples/tests/riscv-64/test-kernel-modules/package/kernel-modules/test-mod/test-mod.mk diff --git a/modules/tsffs/tests/targets/minimal-riscv-64/test-mod-userspace.c b/examples/tests/riscv-64/test-mod-userspace.c similarity index 100% rename from modules/tsffs/tests/targets/minimal-riscv-64/test-mod-userspace.c rename to examples/tests/riscv-64/test-mod-userspace.c diff --git a/modules/tsffs/tests/targets/minimal-riscv-64/test-mod.c b/examples/tests/riscv-64/test-mod.c similarity index 100% rename from modules/tsffs/tests/targets/minimal-riscv-64/test-mod.c rename to examples/tests/riscv-64/test-mod.c diff --git a/examples/tests/riscv-64/test-userspace-magic.simics b/examples/tests/riscv-64/test-userspace-magic.simics new file mode 100644 index 00000000..6a466fed --- /dev/null +++ b/examples/tests/riscv-64/test-userspace-magic.simics @@ -0,0 +1,30 @@ +load-module tsffs + +@tsffs = SIM_create_object(SIM_get_class("tsffs"), "tsffs", []) +tsffs.log-level 4 +@tsffs.iface.tsffs.set_start_on_harness(True) +@tsffs.iface.tsffs.set_stop_on_harness(True) +@tsffs.iface.tsffs.set_timeout(3.0) +@tsffs.iface.tsffs.add_exception_solution(14) +@tsffs.iface.tsffs.set_generate_random_corpus(True) +@tsffs.iface.tsffs.set_iterations(1000) +@tsffs.iface.tsffs.set_use_snapshots(True) + +load-target "risc-v-simple/linux" namespace = riscv machine:hardware:storage:disk1:image = "test.fs.craff" + +script-branch { + bp.time.wait-for seconds = 15 + board.console.con.input "mkdir /mnt/disk0\r\n" + bp.time.wait-for seconds = 1.0 + board.console.con.input "mount /dev/vdb /mnt/disk0\r\n" + bp.time.wait-for seconds = 1.0 + board.console.con.capture-start out.txt + board.console.con.input "/mnt/disk0/test\r\n" +} + +script-branch { + bp.time.wait-for seconds = 240 + quit 1 +} + +run \ No newline at end of file diff --git a/modules/tsffs/tests/targets/minimal-riscv-64/test.c b/examples/tests/riscv-64/test.c similarity index 100% rename from modules/tsffs/tests/targets/minimal-riscv-64/test.c rename to examples/tests/riscv-64/test.c diff --git a/examples/tests/x86-user/.gitignore b/examples/tests/x86-user/.gitignore new file mode 100644 index 00000000..82f633bb --- /dev/null +++ b/examples/tests/x86-user/.gitignore @@ -0,0 +1,5 @@ +.ninja_log +test +*.h +*.fs +*.craff \ No newline at end of file diff --git a/modules/tsffs/tests/targets/minimal-x86-user/build.ninja b/examples/tests/x86-user/build.ninja similarity index 72% rename from modules/tsffs/tests/targets/minimal-x86-user/build.ninja rename to examples/tests/x86-user/build.ninja index 52bf0e2b..a4908aeb 100644 --- a/modules/tsffs/tests/targets/minimal-x86-user/build.ninja +++ b/examples/tests/x86-user/build.ninja @@ -5,4 +5,4 @@ rule cc command = clang $cflags -o $out $in build test: cc test.c - cflags = -m32 -static -O0 -I ../../../../../harness/ + cflags = -m32 -static -O0 diff --git a/examples/tests/x86-user/build.sh b/examples/tests/x86-user/build.sh new file mode 100755 index 00000000..aa60c82e --- /dev/null +++ b/examples/tests/x86-user/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +if [ -z "${SIMICS_BASE}" ]; then + echo "SIMICS_BASE must be set" + exit 1 +fi + +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) + +cp "${SCRIPT_DIR}/../../../harness/tsffs-gcc-x86.h" "${SCRIPT_DIR}/tsffs-gcc-x86.h" +cp "${SCRIPT_DIR}/../../rsrc/minimal_boot_disk.craff" "${SCRIPT_DIR}/minimal_boot_disk.craff" + +ninja + +dd if=/dev/zero of=test.fs bs=1024 count=131072 +mkfs.fat test.fs +mcopy -i test.fs test ::test +"${SIMICS_BASE}/linux64/bin/craff" -o test.fs.craff test.fs \ No newline at end of file diff --git a/examples/tests/x86-user/test-user.py b/examples/tests/x86-user/test-user.py new file mode 100644 index 00000000..642fac62 --- /dev/null +++ b/examples/tests/x86-user/test-user.py @@ -0,0 +1,60 @@ +import cli +import simics + +simics.SIM_load_module("tsffs") + +tsffs = simics.SIM_create_object(simics.SIM_get_class("tsffs"), "tsffs", []) +simics.SIM_set_log_level(tsffs, 4) +tsffs.iface.tsffs.set_start_on_harness(True) +tsffs.iface.tsffs.set_stop_on_harness(True) +tsffs.iface.tsffs.set_timeout(3.0) +tsffs.iface.tsffs.set_generate_random_corpus(True) +tsffs.iface.tsffs.set_iterations(1000) +tsffs.iface.tsffs.set_use_snapshots(True) + +simics.SIM_load_target( + "qsp-x86/clear-linux", # Target + "qsp", # Namespace + [], # Presets + [["machine:hardware:storage:disk1:image", "test.fs.craff"]], +) + +qsp = simics.SIM_get_object("qsp") + +tsffs.iface.tsffs.add_architecture_hint(qsp.mb.cpu0.core[0][0], "i386") + + +# When we're running userspace code, we don't want to catch exeptions until +# we actually start fuzzing, including GPFs on other code. We can wait to +# enable the exception until later (we could even toggle it on and off per +# iteration) +def on_magic(o, e, r): + # Wait for magic stop -- in reality this could wait for any stop + # condition, but we make it easy on ourselves for testing purposes + if r == 1: + tsffs.iface.tsffs.add_exception_solution(13) + + +def startup_script_branch(): + cli.global_cmds.wait_for_global_time(seconds=20.0, _relative=True) + qsp.serconsole.con.iface.con_input.input_str("sudo mkdir /disk0/\n") + cli.global_cmds.wait_for_global_time(seconds=1.0, _relative=True) + qsp.serconsole.con.iface.con_input.input_str("sudo mount /dev/sdb /disk0/\n") + cli.global_cmds.wait_for_global_time(seconds=1.0, _relative=True) + qsp.serconsole.con.iface.con_input.input_str("ls /disk0\n") + cli.global_cmds.wait_for_global_time(seconds=1.0, _relative=True) + qsp.serconsole.con.iface.con_input.input_str("/disk0/test\n") + + +def exit_script_branch(): + cli.global_cmds.wait_for_global_time(seconds=240.0, _relative=True) + simics.SIM_quit(1) + + +simics.SIM_hap_add_callback("Core_Magic_Instruction", on_magic, None) +cli.sb_create(startup_script_branch) +cli.sb_create(exit_script_branch) + +simics.SIM_continue(0) +# NOTE: If running from CLI, omit this! +simics.SIM_main_loop() diff --git a/modules/tsffs/tests/targets/minimal-x86-user/test.c b/examples/tests/x86-user/test.c similarity index 100% rename from modules/tsffs/tests/targets/minimal-x86-user/test.c rename to examples/tests/x86-user/test.c diff --git a/examples/tests/x86_64-breakpoint-uefi-edk2/.gitignore b/examples/tests/x86_64-breakpoint-uefi-edk2/.gitignore new file mode 100644 index 00000000..9564f30d --- /dev/null +++ b/examples/tests/x86_64-breakpoint-uefi-edk2/.gitignore @@ -0,0 +1,2 @@ +.ninja_log +test.efi \ No newline at end of file diff --git a/modules/tsffs/tests/targets/minimal-x86_64-breakpoint-edk2/Dockerfile b/examples/tests/x86_64-breakpoint-uefi-edk2/Dockerfile similarity index 100% rename from modules/tsffs/tests/targets/minimal-x86_64-breakpoint-edk2/Dockerfile rename to examples/tests/x86_64-breakpoint-uefi-edk2/Dockerfile diff --git a/modules/tsffs/tests/targets/minimal-x86_64-breakpoint-edk2/build.ninja b/examples/tests/x86_64-breakpoint-uefi-edk2/build.ninja similarity index 100% rename from modules/tsffs/tests/targets/minimal-x86_64-breakpoint-edk2/build.ninja rename to examples/tests/x86_64-breakpoint-uefi-edk2/build.ninja diff --git a/modules/tsffs/tests/targets/minimal-x86_64-breakpoint-edk2/build.sh b/examples/tests/x86_64-breakpoint-uefi-edk2/build.sh similarity index 54% rename from modules/tsffs/tests/targets/minimal-x86_64-breakpoint-edk2/build.sh rename to examples/tests/x86_64-breakpoint-uefi-edk2/build.sh index d18932ff..e3bd18cc 100755 --- a/modules/tsffs/tests/targets/minimal-x86_64-breakpoint-edk2/build.sh +++ b/examples/tests/x86_64-breakpoint-uefi-edk2/build.sh @@ -14,11 +14,14 @@ CONTAINER_NAME="${IMAGE_NAME}-tmp-${CONTAINER_UID}" pushd "${SCRIPT_DIR}" || exit 1 -cp "${SCRIPT_DIR}/../../../../../harness/tsffs-gcc-x86_64.h" "${SCRIPT_DIR}/src/tsffs-gcc-x86_64.h" +cp "${SCRIPT_DIR}/../../../harness/tsffs-gcc-x86_64.h" "${SCRIPT_DIR}/src/tsffs-gcc-x86_64.h" +cp "${SCRIPT_DIR}/../rsrc/minimal_boot_disk.craff" "${SCRIPT_DIR}/minimal_boot_disk.craff" -docker build -t "${IMAGE_NAME}" -f "Dockerfile" . -docker create --name "${CONTAINER_NAME}" "${IMAGE_NAME}" -docker cp \ - "${CONTAINER_NAME}:/edk2/HelloWorld/Build/HelloWorld/DEBUG_GCC5/X64/HelloWorld.efi" \ - "${SCRIPT_DIR}/test.efi" -docker rm -f "${CONTAINER_NAME}" +if [ ! -e "${SCRIPT_DIR}/test.efi" ]; then + docker build -t "${IMAGE_NAME}" -f "Dockerfile" . + docker create --name "${CONTAINER_NAME}" "${IMAGE_NAME}" + docker cp \ + "${CONTAINER_NAME}:/edk2/HelloWorld/Build/HelloWorld/DEBUG_GCC5/X64/HelloWorld.efi" \ + "${SCRIPT_DIR}/test.efi" + docker rm -f "${CONTAINER_NAME}" +fi diff --git a/examples/tests/x86_64-breakpoint-uefi-edk2/src/.gitignore b/examples/tests/x86_64-breakpoint-uefi-edk2/src/.gitignore new file mode 100644 index 00000000..db4787e6 --- /dev/null +++ b/examples/tests/x86_64-breakpoint-uefi-edk2/src/.gitignore @@ -0,0 +1 @@ +*.h \ No newline at end of file diff --git a/modules/tsffs/tests/targets/minimal-x86_64-breakpoint-edk2/src/HelloWorld.c b/examples/tests/x86_64-breakpoint-uefi-edk2/src/HelloWorld.c similarity index 99% rename from modules/tsffs/tests/targets/minimal-x86_64-breakpoint-edk2/src/HelloWorld.c rename to examples/tests/x86_64-breakpoint-uefi-edk2/src/HelloWorld.c index c6a4c03a..9cd24a61 100644 --- a/modules/tsffs/tests/targets/minimal-x86_64-breakpoint-edk2/src/HelloWorld.c +++ b/examples/tests/x86_64-breakpoint-uefi-edk2/src/HelloWorld.c @@ -47,7 +47,6 @@ UefiMain(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) { SetMem((VOID *)input, input_size, 0x44); } - HARNESS_STOP(); return EFI_SUCCESS; diff --git a/modules/tsffs/tests/targets/minimal-x86_64-breakpoint-edk2/src/HelloWorld.dsc b/examples/tests/x86_64-breakpoint-uefi-edk2/src/HelloWorld.dsc similarity index 100% rename from modules/tsffs/tests/targets/minimal-x86_64-breakpoint-edk2/src/HelloWorld.dsc rename to examples/tests/x86_64-breakpoint-uefi-edk2/src/HelloWorld.dsc diff --git a/modules/tsffs/tests/targets/minimal-x86_64-breakpoint-edk2/src/HelloWorld.inf b/examples/tests/x86_64-breakpoint-uefi-edk2/src/HelloWorld.inf similarity index 100% rename from modules/tsffs/tests/targets/minimal-x86_64-breakpoint-edk2/src/HelloWorld.inf rename to examples/tests/x86_64-breakpoint-uefi-edk2/src/HelloWorld.inf diff --git a/modules/tsffs/tests/targets/minimal-riscv-64-edk2/src/HelloWorldExtra.uni b/examples/tests/x86_64-breakpoint-uefi-edk2/src/HelloWorldExtra.uni similarity index 100% rename from modules/tsffs/tests/targets/minimal-riscv-64-edk2/src/HelloWorldExtra.uni rename to examples/tests/x86_64-breakpoint-uefi-edk2/src/HelloWorldExtra.uni diff --git a/modules/tsffs/tests/targets/minimal-riscv-64-edk2/src/HelloWorldStr.uni b/examples/tests/x86_64-breakpoint-uefi-edk2/src/HelloWorldStr.uni similarity index 100% rename from modules/tsffs/tests/targets/minimal-riscv-64-edk2/src/HelloWorldStr.uni rename to examples/tests/x86_64-breakpoint-uefi-edk2/src/HelloWorldStr.uni diff --git a/modules/tsffs/tests/targets/minimal-x86_64-breakpoint-edk2/src/PlatformBuild.py b/examples/tests/x86_64-breakpoint-uefi-edk2/src/PlatformBuild.py similarity index 100% rename from modules/tsffs/tests/targets/minimal-x86_64-breakpoint-edk2/src/PlatformBuild.py rename to examples/tests/x86_64-breakpoint-uefi-edk2/src/PlatformBuild.py diff --git a/modules/tsffs/tests/targets/minimal-x86_64-breakpoint-edk2/src/tsffs-gcc-x86_64.h b/examples/tests/x86_64-breakpoint-uefi-edk2/src/tsffs-gcc-x86_64.h similarity index 100% rename from modules/tsffs/tests/targets/minimal-x86_64-breakpoint-edk2/src/tsffs-gcc-x86_64.h rename to examples/tests/x86_64-breakpoint-uefi-edk2/src/tsffs-gcc-x86_64.h diff --git a/examples/tests/x86_64-breakpoint-uefi-edk2/test-magic.simics b/examples/tests/x86_64-breakpoint-uefi-edk2/test-magic.simics new file mode 100644 index 00000000..5a79353d --- /dev/null +++ b/examples/tests/x86_64-breakpoint-uefi-edk2/test-magic.simics @@ -0,0 +1,43 @@ +load-module tsffs + +@tsffs = SIM_create_object(SIM_get_class("tsffs"), "tsffs", []) +tsffs.log-level 4 +@tsffs.iface.tsffs.set_start_on_harness(True) +@tsffs.iface.tsffs.set_stop_on_harness(True) +@tsffs.iface.tsffs.set_timeout(3.0) +@tsffs.iface.tsffs.add_exception_solution(14) +@tsffs.iface.tsffs.add_exception_solution(6) +@tsffs.iface.tsffs.set_generate_random_corpus(True) +@tsffs.iface.tsffs.set_iterations(1000) +@tsffs.iface.tsffs.set_use_snapshots(True) +@tsffs.iface.tsffs.set_all_breakpoints_are_solutions(True) + +load-target "qsp-x86/uefi-shell" namespace = qsp machine:hardware:storage:disk0:image = "minimal_boot_disk.craff" + +script-branch { + bp.time.wait-for seconds = 15 + qsp.serconsole.con.input "\n" + bp.time.wait-for seconds = .5 + qsp.serconsole.con.input "FS0:\n" + bp.time.wait-for seconds = .5 + local $manager = (start-agent-manager) + qsp.serconsole.con.input ("SimicsAgent.efi --download " + (lookup-file "%simics%/test.efi") + "\n") + bp.time.wait-for seconds = .5 + qsp.serconsole.con.input "test.efi\n" +} + +script-branch { + local $BP_BUFFER_ADDRESS = 0x4000000 + local $MAGIC_START = 1 + bp.magic.wait-for $MAGIC_START + local $ctx = (new-context) + qsp.mb.cpu0.core[0][0].set-context $ctx + $ctx.break -w $BP_BUFFER_ADDRESS 0x1000 +} + +script-branch { + bp.time.wait-for seconds = 240 + quit 1 +} + +run \ No newline at end of file diff --git a/examples/tests/x86_64-crash-uefi/.gitignore b/examples/tests/x86_64-crash-uefi/.gitignore new file mode 100644 index 00000000..12037161 --- /dev/null +++ b/examples/tests/x86_64-crash-uefi/.gitignore @@ -0,0 +1,6 @@ +test.efi +.ninja_log +test.lib +test.o +*.h +*.craff \ No newline at end of file diff --git a/modules/tsffs/tests/targets/minimal-x86_64-crash/build.ninja b/examples/tests/x86_64-crash-uefi/build.ninja similarity index 90% rename from modules/tsffs/tests/targets/minimal-x86_64-crash/build.ninja rename to examples/tests/x86_64-crash-uefi/build.ninja index a918e66e..737be7ca 100644 --- a/modules/tsffs/tests/targets/minimal-x86_64-crash/build.ninja +++ b/examples/tests/x86_64-crash-uefi/build.ninja @@ -13,5 +13,5 @@ rule copy command = cp $in $out build test.o: cc test.c - cflags = -O0 -I ../../../../../harness/ + cflags = -O0 build test.efi: link test.o diff --git a/examples/tests/x86_64-crash-uefi/build.sh b/examples/tests/x86_64-crash-uefi/build.sh new file mode 100755 index 00000000..16ae7ec0 --- /dev/null +++ b/examples/tests/x86_64-crash-uefi/build.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) + +cp "${SCRIPT_DIR}/../../../harness/tsffs-gcc-x86_64.h" "${SCRIPT_DIR}/tsffs-gcc-x86_64.h" +cp "${SCRIPT_DIR}/../../rsrc/minimal_boot_disk.craff" "${SCRIPT_DIR}/minimal_boot_disk.craff" + +ninja \ No newline at end of file diff --git a/examples/tests/x86_64-crash-uefi/test-magic.simics b/examples/tests/x86_64-crash-uefi/test-magic.simics new file mode 100644 index 00000000..0cc7faad --- /dev/null +++ b/examples/tests/x86_64-crash-uefi/test-magic.simics @@ -0,0 +1,32 @@ +load-module tsffs + +@tsffs = SIM_create_object(SIM_get_class("tsffs"), "tsffs", []) +tsffs.log-level 4 +@tsffs.iface.tsffs.set_start_on_harness(True) +@tsffs.iface.tsffs.set_stop_on_harness(True) +@tsffs.iface.tsffs.set_timeout(3.0) +@tsffs.iface.tsffs.add_exception_solution(14) +@tsffs.iface.tsffs.set_generate_random_corpus(True) +@tsffs.iface.tsffs.set_iterations(1000) +@tsffs.iface.tsffs.set_use_snapshots(True) + +load-target "qsp-x86/uefi-shell" namespace = qsp machine:hardware:storage:disk0:image = "minimal_boot_disk.craff" + +script-branch { + bp.time.wait-for seconds = 15 + qsp.serconsole.con.input "\n" + bp.time.wait-for seconds = .5 + qsp.serconsole.con.input "FS0:\n" + bp.time.wait-for seconds = .5 + local $manager = (start-agent-manager) + qsp.serconsole.con.input ("SimicsAgent.efi --download " + (lookup-file "%simics%/test.efi") + "\n") + bp.time.wait-for seconds = .5 + qsp.serconsole.con.input "test.efi\n" +} + +script-branch { + bp.time.wait-for seconds = 240 + quit 1 +} + +run \ No newline at end of file diff --git a/modules/tsffs/tests/targets/minimal-x86_64-crash/test.c b/examples/tests/x86_64-crash-uefi/test.c similarity index 100% rename from modules/tsffs/tests/targets/minimal-x86_64-crash/test.c rename to examples/tests/x86_64-crash-uefi/test.c diff --git a/examples/tests/x86_64-timeout-uefi-edk2/.gitignore b/examples/tests/x86_64-timeout-uefi-edk2/.gitignore new file mode 100644 index 00000000..23b63b94 --- /dev/null +++ b/examples/tests/x86_64-timeout-uefi-edk2/.gitignore @@ -0,0 +1,3 @@ +.ninja_log +test.efi +*.craff \ No newline at end of file diff --git a/modules/tsffs/tests/targets/minimal-x86_64-timeout/Dockerfile b/examples/tests/x86_64-timeout-uefi-edk2/Dockerfile similarity index 100% rename from modules/tsffs/tests/targets/minimal-x86_64-timeout/Dockerfile rename to examples/tests/x86_64-timeout-uefi-edk2/Dockerfile diff --git a/modules/tsffs/tests/targets/minimal-x86_64-edk2/build.ninja b/examples/tests/x86_64-timeout-uefi-edk2/build.ninja similarity index 100% rename from modules/tsffs/tests/targets/minimal-x86_64-edk2/build.ninja rename to examples/tests/x86_64-timeout-uefi-edk2/build.ninja diff --git a/modules/tsffs/tests/targets/minimal-x86_64-edk2/build.sh b/examples/tests/x86_64-timeout-uefi-edk2/build.sh similarity index 53% rename from modules/tsffs/tests/targets/minimal-x86_64-edk2/build.sh rename to examples/tests/x86_64-timeout-uefi-edk2/build.sh index c115acb6..51ad8f0b 100755 --- a/modules/tsffs/tests/targets/minimal-x86_64-edk2/build.sh +++ b/examples/tests/x86_64-timeout-uefi-edk2/build.sh @@ -14,11 +14,14 @@ CONTAINER_NAME="${IMAGE_NAME}-tmp-${CONTAINER_UID}" pushd "${SCRIPT_DIR}" || exit 1 -cp "${SCRIPT_DIR}/../../../../../harness/tsffs-gcc-x86_64.h" "${SCRIPT_DIR}/src/tsffs-gcc-x86_64.h" +cp "${SCRIPT_DIR}/../../../harness/tsffs-gcc-x86_64.h" "${SCRIPT_DIR}/src/tsffs-gcc-x86_64.h" +cp "${SCRIPT_DIR}/../../rsrc/minimal_boot_disk.craff" "${SCRIPT_DIR}/minimal_boot_disk.craff" -docker build -t "${IMAGE_NAME}" -f "Dockerfile" . -docker create --name "${CONTAINER_NAME}" "${IMAGE_NAME}" -docker cp \ - "${CONTAINER_NAME}:/edk2/HelloWorld/Build/HelloWorld/DEBUG_GCC5/X64/HelloWorld.efi" \ - "${SCRIPT_DIR}/test.efi" -docker rm -f "${CONTAINER_NAME}" +if [ ! -e "${SCRIPT_DIR}/test.efi" ]; then + docker build -t "${IMAGE_NAME}" -f "Dockerfile" . + docker create --name "${CONTAINER_NAME}" "${IMAGE_NAME}" + docker cp \ + "${CONTAINER_NAME}:/edk2/HelloWorld/Build/HelloWorld/DEBUG_GCC5/X64/HelloWorld.efi" \ + "${SCRIPT_DIR}/test.efi" + docker rm -f "${CONTAINER_NAME}" +fi \ No newline at end of file diff --git a/examples/tests/x86_64-timeout-uefi-edk2/src/.gitignore b/examples/tests/x86_64-timeout-uefi-edk2/src/.gitignore new file mode 100644 index 00000000..db4787e6 --- /dev/null +++ b/examples/tests/x86_64-timeout-uefi-edk2/src/.gitignore @@ -0,0 +1 @@ +*.h \ No newline at end of file diff --git a/modules/tsffs/tests/targets/minimal-x86_64-timeout/src/HelloWorld.c b/examples/tests/x86_64-timeout-uefi-edk2/src/HelloWorld.c similarity index 100% rename from modules/tsffs/tests/targets/minimal-x86_64-timeout/src/HelloWorld.c rename to examples/tests/x86_64-timeout-uefi-edk2/src/HelloWorld.c diff --git a/modules/tsffs/tests/targets/minimal-x86_64-edk2/src/HelloWorld.dsc b/examples/tests/x86_64-timeout-uefi-edk2/src/HelloWorld.dsc similarity index 100% rename from modules/tsffs/tests/targets/minimal-x86_64-edk2/src/HelloWorld.dsc rename to examples/tests/x86_64-timeout-uefi-edk2/src/HelloWorld.dsc diff --git a/modules/tsffs/tests/targets/minimal-x86_64-edk2/src/HelloWorld.inf b/examples/tests/x86_64-timeout-uefi-edk2/src/HelloWorld.inf similarity index 100% rename from modules/tsffs/tests/targets/minimal-x86_64-edk2/src/HelloWorld.inf rename to examples/tests/x86_64-timeout-uefi-edk2/src/HelloWorld.inf diff --git a/modules/tsffs/tests/targets/minimal-x86_64-breakpoint-edk2/src/HelloWorldExtra.uni b/examples/tests/x86_64-timeout-uefi-edk2/src/HelloWorldExtra.uni similarity index 100% rename from modules/tsffs/tests/targets/minimal-x86_64-breakpoint-edk2/src/HelloWorldExtra.uni rename to examples/tests/x86_64-timeout-uefi-edk2/src/HelloWorldExtra.uni diff --git a/modules/tsffs/tests/targets/minimal-x86_64-breakpoint-edk2/src/HelloWorldStr.uni b/examples/tests/x86_64-timeout-uefi-edk2/src/HelloWorldStr.uni similarity index 100% rename from modules/tsffs/tests/targets/minimal-x86_64-breakpoint-edk2/src/HelloWorldStr.uni rename to examples/tests/x86_64-timeout-uefi-edk2/src/HelloWorldStr.uni diff --git a/modules/tsffs/tests/targets/minimal-x86_64-edk2/src/PlatformBuild.py b/examples/tests/x86_64-timeout-uefi-edk2/src/PlatformBuild.py similarity index 100% rename from modules/tsffs/tests/targets/minimal-x86_64-edk2/src/PlatformBuild.py rename to examples/tests/x86_64-timeout-uefi-edk2/src/PlatformBuild.py diff --git a/modules/tsffs/tests/targets/minimal-x86_64-edk2/src/tsffs-gcc-x86_64.h b/examples/tests/x86_64-timeout-uefi-edk2/src/tsffs-gcc-x86_64.h similarity index 100% rename from modules/tsffs/tests/targets/minimal-x86_64-edk2/src/tsffs-gcc-x86_64.h rename to examples/tests/x86_64-timeout-uefi-edk2/src/tsffs-gcc-x86_64.h diff --git a/examples/tests/x86_64-timeout-uefi-edk2/test-magic.simics b/examples/tests/x86_64-timeout-uefi-edk2/test-magic.simics new file mode 100644 index 00000000..0f578ae6 --- /dev/null +++ b/examples/tests/x86_64-timeout-uefi-edk2/test-magic.simics @@ -0,0 +1,32 @@ +load-module tsffs + +@tsffs = SIM_create_object(SIM_get_class("tsffs"), "tsffs", []) +tsffs.log-level 4 +@tsffs.iface.tsffs.set_start_on_harness(True) +@tsffs.iface.tsffs.set_stop_on_harness(True) +@tsffs.iface.tsffs.set_timeout(3.0) +@tsffs.iface.tsffs.add_exception_solution(14) +@tsffs.iface.tsffs.set_generate_random_corpus(True) +@tsffs.iface.tsffs.set_iterations(100) +@tsffs.iface.tsffs.set_use_snapshots(True) + +load-target "qsp-x86/uefi-shell" namespace = qsp machine:hardware:storage:disk0:image = "minimal_boot_disk.craff" + +script-branch { + bp.time.wait-for seconds = 15 + qsp.serconsole.con.input "\n" + bp.time.wait-for seconds = .5 + qsp.serconsole.con.input "FS0:\n" + bp.time.wait-for seconds = .5 + local $manager = (start-agent-manager) + qsp.serconsole.con.input ("SimicsAgent.efi --download " + (lookup-file "%simics%/test.efi") + "\n") + bp.time.wait-for seconds = .5 + qsp.serconsole.con.input "test.efi\n" +} + +script-branch { + bp.time.wait-for seconds = 240 + quit 1 +} + +run \ No newline at end of file diff --git a/examples/tests/x86_64-uefi-edk2/.gitignore b/examples/tests/x86_64-uefi-edk2/.gitignore new file mode 100644 index 00000000..23b63b94 --- /dev/null +++ b/examples/tests/x86_64-uefi-edk2/.gitignore @@ -0,0 +1,3 @@ +.ninja_log +test.efi +*.craff \ No newline at end of file diff --git a/modules/tsffs/tests/targets/minimal-x86_64-edk2/Dockerfile b/examples/tests/x86_64-uefi-edk2/Dockerfile similarity index 100% rename from modules/tsffs/tests/targets/minimal-x86_64-edk2/Dockerfile rename to examples/tests/x86_64-uefi-edk2/Dockerfile diff --git a/modules/tsffs/tests/targets/minimal-x86_64-timeout/build.ninja b/examples/tests/x86_64-uefi-edk2/build.ninja similarity index 100% rename from modules/tsffs/tests/targets/minimal-x86_64-timeout/build.ninja rename to examples/tests/x86_64-uefi-edk2/build.ninja diff --git a/modules/tsffs/tests/targets/minimal-x86_64-timeout/build.sh b/examples/tests/x86_64-uefi-edk2/build.sh similarity index 53% rename from modules/tsffs/tests/targets/minimal-x86_64-timeout/build.sh rename to examples/tests/x86_64-uefi-edk2/build.sh index c115acb6..51ad8f0b 100755 --- a/modules/tsffs/tests/targets/minimal-x86_64-timeout/build.sh +++ b/examples/tests/x86_64-uefi-edk2/build.sh @@ -14,11 +14,14 @@ CONTAINER_NAME="${IMAGE_NAME}-tmp-${CONTAINER_UID}" pushd "${SCRIPT_DIR}" || exit 1 -cp "${SCRIPT_DIR}/../../../../../harness/tsffs-gcc-x86_64.h" "${SCRIPT_DIR}/src/tsffs-gcc-x86_64.h" +cp "${SCRIPT_DIR}/../../../harness/tsffs-gcc-x86_64.h" "${SCRIPT_DIR}/src/tsffs-gcc-x86_64.h" +cp "${SCRIPT_DIR}/../../rsrc/minimal_boot_disk.craff" "${SCRIPT_DIR}/minimal_boot_disk.craff" -docker build -t "${IMAGE_NAME}" -f "Dockerfile" . -docker create --name "${CONTAINER_NAME}" "${IMAGE_NAME}" -docker cp \ - "${CONTAINER_NAME}:/edk2/HelloWorld/Build/HelloWorld/DEBUG_GCC5/X64/HelloWorld.efi" \ - "${SCRIPT_DIR}/test.efi" -docker rm -f "${CONTAINER_NAME}" +if [ ! -e "${SCRIPT_DIR}/test.efi" ]; then + docker build -t "${IMAGE_NAME}" -f "Dockerfile" . + docker create --name "${CONTAINER_NAME}" "${IMAGE_NAME}" + docker cp \ + "${CONTAINER_NAME}:/edk2/HelloWorld/Build/HelloWorld/DEBUG_GCC5/X64/HelloWorld.efi" \ + "${SCRIPT_DIR}/test.efi" + docker rm -f "${CONTAINER_NAME}" +fi \ No newline at end of file diff --git a/examples/tests/x86_64-uefi-edk2/src/.gitignore b/examples/tests/x86_64-uefi-edk2/src/.gitignore new file mode 100644 index 00000000..db4787e6 --- /dev/null +++ b/examples/tests/x86_64-uefi-edk2/src/.gitignore @@ -0,0 +1 @@ +*.h \ No newline at end of file diff --git a/modules/tsffs/tests/targets/minimal-x86_64-edk2/src/HelloWorld.c b/examples/tests/x86_64-uefi-edk2/src/HelloWorld.c similarity index 100% rename from modules/tsffs/tests/targets/minimal-x86_64-edk2/src/HelloWorld.c rename to examples/tests/x86_64-uefi-edk2/src/HelloWorld.c diff --git a/modules/tsffs/tests/targets/minimal-x86_64-timeout/src/HelloWorld.dsc b/examples/tests/x86_64-uefi-edk2/src/HelloWorld.dsc similarity index 100% rename from modules/tsffs/tests/targets/minimal-x86_64-timeout/src/HelloWorld.dsc rename to examples/tests/x86_64-uefi-edk2/src/HelloWorld.dsc diff --git a/modules/tsffs/tests/targets/minimal-x86_64-timeout/src/HelloWorld.inf b/examples/tests/x86_64-uefi-edk2/src/HelloWorld.inf similarity index 100% rename from modules/tsffs/tests/targets/minimal-x86_64-timeout/src/HelloWorld.inf rename to examples/tests/x86_64-uefi-edk2/src/HelloWorld.inf diff --git a/modules/tsffs/tests/targets/minimal-x86_64-edk2/src/HelloWorldExtra.uni b/examples/tests/x86_64-uefi-edk2/src/HelloWorldExtra.uni similarity index 100% rename from modules/tsffs/tests/targets/minimal-x86_64-edk2/src/HelloWorldExtra.uni rename to examples/tests/x86_64-uefi-edk2/src/HelloWorldExtra.uni diff --git a/modules/tsffs/tests/targets/minimal-x86_64-edk2/src/HelloWorldStr.uni b/examples/tests/x86_64-uefi-edk2/src/HelloWorldStr.uni similarity index 100% rename from modules/tsffs/tests/targets/minimal-x86_64-edk2/src/HelloWorldStr.uni rename to examples/tests/x86_64-uefi-edk2/src/HelloWorldStr.uni diff --git a/modules/tsffs/tests/targets/minimal-x86_64-timeout/src/PlatformBuild.py b/examples/tests/x86_64-uefi-edk2/src/PlatformBuild.py similarity index 100% rename from modules/tsffs/tests/targets/minimal-x86_64-timeout/src/PlatformBuild.py rename to examples/tests/x86_64-uefi-edk2/src/PlatformBuild.py diff --git a/modules/tsffs/tests/targets/minimal-x86_64-timeout/src/tsffs-gcc-x86_64.h b/examples/tests/x86_64-uefi-edk2/src/tsffs-gcc-x86_64.h similarity index 100% rename from modules/tsffs/tests/targets/minimal-x86_64-timeout/src/tsffs-gcc-x86_64.h rename to examples/tests/x86_64-uefi-edk2/src/tsffs-gcc-x86_64.h diff --git a/examples/tests/x86_64-uefi-edk2/test-uefi-magic.simics b/examples/tests/x86_64-uefi-edk2/test-uefi-magic.simics new file mode 100644 index 00000000..efff5a41 --- /dev/null +++ b/examples/tests/x86_64-uefi-edk2/test-uefi-magic.simics @@ -0,0 +1,33 @@ +load-module tsffs + +@tsffs = SIM_create_object(SIM_get_class("tsffs"), "tsffs", []) +tsffs.log-level 4 +@tsffs.iface.tsffs.set_start_on_harness(True) +@tsffs.iface.tsffs.set_stop_on_harness(True) +@tsffs.iface.tsffs.set_timeout(3.0) +@tsffs.iface.tsffs.add_exception_solution(14) +@tsffs.iface.tsffs.add_exception_solution(6) +@tsffs.iface.tsffs.set_generate_random_corpus(True) +@tsffs.iface.tsffs.set_iterations(1000) +@tsffs.iface.tsffs.set_use_snapshots(True) + +load-target "qsp-x86/uefi-shell" namespace = qsp machine:hardware:storage:disk0:image = "minimal_boot_disk.craff" + +script-branch { + bp.time.wait-for seconds = 15 + qsp.serconsole.con.input "\n" + bp.time.wait-for seconds = .5 + qsp.serconsole.con.input "FS0:\n" + bp.time.wait-for seconds = .5 + local $manager = (start-agent-manager) + qsp.serconsole.con.input ("SimicsAgent.efi --download " + (lookup-file "%simics%/test.efi") + "\n") + bp.time.wait-for seconds = .5 + qsp.serconsole.con.input "test.efi\n" +} + +script-branch { + bp.time.wait-for seconds = 240 + quit 1 +} + +run \ No newline at end of file diff --git a/examples/tests/x86_64-uefi/.gitignore b/examples/tests/x86_64-uefi/.gitignore new file mode 100644 index 00000000..77bdfbae --- /dev/null +++ b/examples/tests/x86_64-uefi/.gitignore @@ -0,0 +1,6 @@ +.ninja_log +test.efi +test.lib +test.o +*.h +*.craff \ No newline at end of file diff --git a/modules/tsffs/tests/targets/minimal-x86_64/build.ninja b/examples/tests/x86_64-uefi/build.ninja similarity index 90% rename from modules/tsffs/tests/targets/minimal-x86_64/build.ninja rename to examples/tests/x86_64-uefi/build.ninja index a918e66e..7ee83ebf 100644 --- a/modules/tsffs/tests/targets/minimal-x86_64/build.ninja +++ b/examples/tests/x86_64-uefi/build.ninja @@ -13,5 +13,5 @@ rule copy command = cp $in $out build test.o: cc test.c - cflags = -O0 -I ../../../../../harness/ + cflags = -O0 build test.efi: link test.o diff --git a/examples/tests/x86_64-uefi/build.sh b/examples/tests/x86_64-uefi/build.sh new file mode 100755 index 00000000..16ae7ec0 --- /dev/null +++ b/examples/tests/x86_64-uefi/build.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) + +cp "${SCRIPT_DIR}/../../../harness/tsffs-gcc-x86_64.h" "${SCRIPT_DIR}/tsffs-gcc-x86_64.h" +cp "${SCRIPT_DIR}/../../rsrc/minimal_boot_disk.craff" "${SCRIPT_DIR}/minimal_boot_disk.craff" + +ninja \ No newline at end of file diff --git a/examples/tests/x86_64-uefi/test-magic.simics b/examples/tests/x86_64-uefi/test-magic.simics new file mode 100644 index 00000000..b120d4f8 --- /dev/null +++ b/examples/tests/x86_64-uefi/test-magic.simics @@ -0,0 +1,32 @@ +load-module tsffs + +@tsffs = SIM_create_object(SIM_get_class("tsffs"), "tsffs", []) +tsffs.log-level 1 +@tsffs.iface.tsffs.set_start_on_harness(True) +@tsffs.iface.tsffs.set_stop_on_harness(True) +@tsffs.iface.tsffs.set_timeout(3.0) +@tsffs.iface.tsffs.add_exception_solution(14) +@tsffs.iface.tsffs.set_generate_random_corpus(True) +@tsffs.iface.tsffs.set_iterations(1000) +@tsffs.iface.tsffs.set_use_snapshots(True) + +load-target "qsp-x86/uefi-shell" namespace = qsp machine:hardware:storage:disk0:image = "minimal_boot_disk.craff" + +script-branch { +bp.time.wait-for seconds = 15 +qsp.serconsole.con.input "\n" +bp.time.wait-for seconds = .5 +qsp.serconsole.con.input "FS0:\n" +bp.time.wait-for seconds = .5 +local $manager = (start-agent-manager) +qsp.serconsole.con.input ("SimicsAgent.efi --download " + (lookup-file "%simics%/test.efi") + "\n") +bp.time.wait-for seconds = .5 +qsp.serconsole.con.input "test.efi\n" +} + +script-branch { +bp.time.wait-for seconds = 240 +quit 1 +} + +run \ No newline at end of file diff --git a/examples/tests/x86_64-uefi/test-manual-max.py b/examples/tests/x86_64-uefi/test-manual-max.py new file mode 100644 index 00000000..68e42baa --- /dev/null +++ b/examples/tests/x86_64-uefi/test-manual-max.py @@ -0,0 +1,101 @@ +import cli +import simics + +simics.SIM_load_module("tsffs") + +tsffs = simics.SIM_create_object(simics.SIM_get_class("tsffs"), "tsffs", []) +simics.SIM_set_log_level(tsffs, 4) +tsffs.iface.tsffs.set_start_on_harness(False) +tsffs.iface.tsffs.set_stop_on_harness(False) +tsffs.iface.tsffs.set_timeout(3.0) +tsffs.iface.tsffs.add_exception_solution(14) +tsffs.iface.tsffs.set_generate_random_corpus(True) +tsffs.iface.tsffs.set_iterations(1000) +tsffs.iface.tsffs.set_use_snapshots(False) + +simics.SIM_load_target( + "qsp-x86/uefi-shell", # Target + "qsp", # Namespace + [], # Presets + [ # Cmdline args + ["machine:hardware:storage:disk0:image", "minimal_boot_disk.craff"], + ["machine:hardware:processor:class", "x86-goldencove-server"], + ], +) + +qsp = simics.SIM_get_object("qsp") + + +def on_magic(o, e, r): + # Wait for magic stop -- in reality this could wait for any stop + # condition, but we make it easy on ourselves for testing purposes + if r == 2: + print("Got magic stop...") + tsffs.iface.tsffs.stop() + + +def start_script_branch(): + # Wait for magic start -- in reality this could wait for any + # start condition, but we make it easy on ourselves for testing purposes + print("Waiting for magic start...") + conf.bp.magic.cli_cmds.wait_for(number=1) + print("Got magic start...") + + # In reality, you probably have a known buffer in mind to fuzz + testcase_address_regno = conf.qsp.mb.cpu0.core[0][0].iface.int_register.get_number( + "rdi" + ) + print("testcase address regno: ", testcase_address_regno) + testcase_address = conf.qsp.mb.cpu0.core[0][0].iface.int_register.read( + testcase_address_regno + ) + print("testcase address: ", testcase_address) + maximum_size = 8 + virt = False + + print( + "Starting with testcase address", + hex(testcase_address), + "maximum size", + hex(maximum_size), + "virt", + virt, + ) + + tsffs.iface.tsffs.start_with_maximum_size( + conf.qsp.mb.cpu0.core[0][0], + testcase_address, + maximum_size, + True, + ) + + +def startup_script_branch(): + cli.global_cmds.wait_for_global_time(seconds=15.0, _relative=True) + qsp.serconsole.con.iface.con_input.input_str("\n") + cli.global_cmds.wait_for_global_time(seconds=1.0, _relative=True) + qsp.serconsole.con.iface.con_input.input_str("FS0:\n") + cli.global_cmds.wait_for_global_time(seconds=1.0, _relative=True) + cli.global_cmds.start_agent_manager() + qsp.serconsole.con.iface.con_input.input_str( + "SimicsAgent.efi --download " + + simics.SIM_lookup_file("%simics%/test.efi") + + "\n" + ) + cli.global_cmds.wait_for_global_time(seconds=3.0, _relative=True) + qsp.serconsole.con.iface.con_input.input_str("test.efi\n") + + +def exit_script_branch(): + cli.global_cmds.wait_for_global_time(seconds=240.0, _relative=True) + simics.SIM_quit(1) + + +simics.SIM_hap_add_callback("Core_Magic_Instruction", on_magic, None) +cli.sb_create(start_script_branch) +cli.sb_create(startup_script_branch) +cli.sb_create(exit_script_branch) + +simics.SIM_continue(0) +# NOTE: If running from CLI, omit this! +simics.SIM_main_loop() diff --git a/examples/tests/x86_64-uefi/test-manual.py b/examples/tests/x86_64-uefi/test-manual.py new file mode 100644 index 00000000..59b36f33 --- /dev/null +++ b/examples/tests/x86_64-uefi/test-manual.py @@ -0,0 +1,104 @@ +import cli +import simics + +simics.SIM_load_module("tsffs") + +tsffs = simics.SIM_create_object(simics.SIM_get_class("tsffs"), "tsffs", []) +simics.SIM_set_log_level(tsffs, 1) +tsffs.iface.tsffs.set_start_on_harness(False) +tsffs.iface.tsffs.set_stop_on_harness(False) +tsffs.iface.tsffs.set_timeout(3.0) +tsffs.iface.tsffs.add_exception_solution(14) +tsffs.iface.tsffs.set_generate_random_corpus(True) +tsffs.iface.tsffs.set_iterations(1000) +tsffs.iface.tsffs.set_use_snapshots(False) + +simics.SIM_load_target( + "qsp-x86/uefi-shell", # Target + "qsp", # Namespace + [], # Presets + [ # Cmdline args + ["machine:hardware:storage:disk0:image", "minimal_boot_disk.craff"], + ["machine:hardware:processor:class", "x86-goldencove-server"], + ], +) + +qsp = simics.SIM_get_object("qsp") + + +def on_magic(o, e, r): + # Wait for magic stop -- in reality this could wait for any stop + # condition, but we make it easy on ourselves for testing purposes + if r == 2: + print("Got magic stop...") + tsffs.iface.tsffs.stop() + + +def start_script_branch(): + # Wait for magic start -- in reality this could wait for any + # start condition, but we make it easy on ourselves for testing purposes + print("Waiting for magic start...") + conf.bp.magic.cli_cmds.wait_for(number=1) + print("Got magic start...") + + # In reality, you probably have a known buffer in mind to fuzz + testcase_address_regno = conf.qsp.mb.cpu0.core[0][0].iface.int_register.get_number( + "rdi" + ) + print("testcase address regno: ", testcase_address_regno) + testcase_address = conf.qsp.mb.cpu0.core[0][0].iface.int_register.read( + testcase_address_regno + ) + print("testcase address: ", testcase_address) + size_regno = conf.qsp.mb.cpu0.core[0][0].iface.int_register.get_number("rsi") + print("size regno: ", size_regno) + size_address = conf.qsp.mb.cpu0.core[0][0].iface.int_register.read(size_regno) + print("size address: ", size_address) + virt = False + + print( + "Starting with testcase address", + hex(testcase_address), + "size address", + hex(size_address), + "virt", + virt, + ) + + tsffs.iface.tsffs.start( + conf.qsp.mb.cpu0.core[0][0], + testcase_address, + size_address, + True, + ) + + +def startup_script_branch(): + cli.global_cmds.wait_for_global_time(seconds=15.0, _relative=True) + qsp.serconsole.con.iface.con_input.input_str("\n") + cli.global_cmds.wait_for_global_time(seconds=1.0, _relative=True) + qsp.serconsole.con.iface.con_input.input_str("FS0:\n") + cli.global_cmds.wait_for_global_time(seconds=1.0, _relative=True) + cli.global_cmds.start_agent_manager() + qsp.serconsole.con.iface.con_input.input_str( + "SimicsAgent.efi --download " + + simics.SIM_lookup_file("%simics%/test.efi") + + "\n" + ) + cli.global_cmds.wait_for_global_time(seconds=3.0, _relative=True) + qsp.serconsole.con.iface.con_input.input_str("test.efi\n") + + +def exit_script_branch(): + cli.global_cmds.wait_for_global_time(seconds=240.0, _relative=True) + simics.SIM_quit(1) + + +simics.SIM_hap_add_callback("Core_Magic_Instruction", on_magic, None) +cli.sb_create(start_script_branch) +cli.sb_create(startup_script_branch) +cli.sb_create(exit_script_branch) + +simics.SIM_continue(0) +# NOTE: If running from CLI, omit this! +simics.SIM_main_loop() diff --git a/modules/tsffs/tests/targets/minimal-x86_64/test.c b/examples/tests/x86_64-uefi/test.c similarity index 100% rename from modules/tsffs/tests/targets/minimal-x86_64/test.c rename to examples/tests/x86_64-uefi/test.c diff --git a/modules/tsffs-interface/tsffs-interface.dml b/modules/tsffs-interface/tsffs-interface.dml index 249f2205..aca60e34 100644 --- a/modules/tsffs-interface/tsffs-interface.dml +++ b/modules/tsffs-interface/tsffs-interface.dml @@ -12,8 +12,8 @@ extern typedef struct { void (*set_start_magic_number)(conf_object_t * obj, int64 magic_number); void (*set_stop_on_harness)(conf_object_t * obj, bool stop_on_harness); void (*set_stop_magic_number)(conf_object_t * obj, int64 magic_number); - void (*start)(conf_object_t * obj, conf_object_t * cpu, generic_address_t testcase_address, generic_address_t size_address); - void (*start_with_maximum_size)(conf_object_t * obj, conf_object_t * cpu, generic_address_t testcase_address, uint32 maximum_size); + void (*start)(conf_object_t * obj, conf_object_t * cpu, generic_address_t testcase_address, generic_address_t size_address, bool virt); + void (*start_with_maximum_size)(conf_object_t * obj, conf_object_t * cpu, generic_address_t testcase_address, uint32 maximum_size, bool virt); attr_value_t (*start_without_buffer)(conf_object_t * obj, conf_object_t * cpu); void (*stop)(conf_object_t * obj); void (*solution)(conf_object_t * obj, uint64 id, char * message); diff --git a/modules/tsffs-interface/tsffs-interface.h b/modules/tsffs-interface/tsffs-interface.h index 39fc5cbd..240c7a31 100644 --- a/modules/tsffs-interface/tsffs-interface.h +++ b/modules/tsffs-interface/tsffs-interface.h @@ -16,8 +16,8 @@ SIM_INTERFACE(tsffs) { void (*set_start_magic_number)(conf_object_t * obj, int64 magic_number); void (*set_stop_on_harness)(conf_object_t * obj, bool stop_on_harness); void (*set_stop_magic_number)(conf_object_t * obj, int64 magic_number); - void (*start)(conf_object_t * obj, conf_object_t * cpu, generic_address_t testcase_address, generic_address_t size_address); - void (*start_with_maximum_size)(conf_object_t * obj, conf_object_t * cpu, generic_address_t testcase_address, uint32 maximum_size); + void (*start)(conf_object_t * obj, conf_object_t * cpu, generic_address_t testcase_address, generic_address_t size_address, bool virt); + void (*start_with_maximum_size)(conf_object_t * obj, conf_object_t * cpu, generic_address_t testcase_address, uint32 maximum_size, bool virt); attr_value_t (*start_without_buffer)(conf_object_t * obj, conf_object_t * cpu); void (*stop)(conf_object_t * obj); void (*solution)(conf_object_t * obj, uint64 id, char * message); diff --git a/modules/tsffs/src/simics/simics-api-sys/build.rs b/modules/tsffs/src/simics/simics-api-sys/build.rs index 9184e346..4870ece2 100644 --- a/modules/tsffs/src/simics/simics-api-sys/build.rs +++ b/modules/tsffs/src/simics/simics-api-sys/build.rs @@ -38,6 +38,7 @@ use std::{ collections::HashSet, env::var, ffi::OsStr, + fmt::Write, fs::{read, read_dir, write}, iter::once, path::{Path, PathBuf}, @@ -340,30 +341,34 @@ fn main() -> Result<()> { let hap_code = haps_names .iter() .zip(haps_code_indices_descriptions.iter()) - .map(|(name, (code, maybe_index, maybe_description))| { - let mut hap_name_name = name.to_ascii_uppercase(); - hap_name_name += "_HAP_NAME"; - let mut hap_callback_name = name.to_ascii_lowercase(); - hap_callback_name += "_hap_callback"; - let code = code - .replace("(*)", &format!("(*{})", hap_callback_name)) - .replace(['/', '-'], "_"); - let comment = format!( - "/**\n * Index: {}\n * Description: {}\n */", - maybe_index - .as_ref() - .unwrap_or(&"Indices not supported".to_string()), - maybe_description - .as_ref() - .unwrap_or(&"No description".to_string()) - ); - - format!( - "#define {} \"{}\"\n{}\ntypedef {}\n", - hap_name_name, name, comment, code - ) - }) - .collect::(); + .try_fold( + String::default(), + |mut s, (name, (code, maybe_index, maybe_description))| { + let mut hap_name_name = name.to_ascii_uppercase(); + hap_name_name += "_HAP_NAME"; + let mut hap_callback_name = name.to_ascii_lowercase(); + hap_callback_name += "_hap_callback"; + let code = code + .replace("(*)", &format!("(*{})", hap_callback_name)) + .replace(['/', '-'], "_"); + let comment = format!( + "/**\n * Index: {}\n * Description: {}\n */", + maybe_index + .as_ref() + .unwrap_or(&"Indices not supported".to_string()), + maybe_description + .as_ref() + .unwrap_or(&"No description".to_string()) + ); + + write!( + &mut s, + "#define {} \"{}\"\n{}\ntypedef {}\n", + hap_name_name, name, comment, code + ) + .and_then(|_| Ok(s)) + }, + )?; let simics_base_version = base_dir_path .file_name() diff --git a/modules/tsffs/src/simics/simics/build.rs b/modules/tsffs/src/simics/simics/build.rs index 3ffb368a..02b3deca 100644 --- a/modules/tsffs/src/simics/simics/build.rs +++ b/modules/tsffs/src/simics/simics/build.rs @@ -69,5 +69,11 @@ fn main() -> Result<()> { println!("cargo:rustc-cfg={CFG_SIMICS_DEPRECATED_API_SIM_LOG}"); } + if VersionConstraint::from_str(">=6.0.173")?.matches(&simics_api_version) { + // Enable the experimental snapshots api for versions over 6.0.173 (where the API first + // appears) + println!("cargo:rustc-cfg={CFG_SIMICS_EXPERIMENTAL_API_SNAPSHOTS}"); + } + Ok(()) } diff --git a/modules/tsffs/src/tsffs/src/arch/mod.rs b/modules/tsffs/src/tsffs/src/arch/mod.rs index ddcc2582..2083eaa2 100644 --- a/modules/tsffs/src/tsffs/src/arch/mod.rs +++ b/modules/tsffs/src/tsffs/src/arch/mod.rs @@ -187,45 +187,62 @@ pub trait ArchitectureOperations { .build()) } - fn get_manual_start_buffer(&mut self, buffer_address: GenericAddress) -> Result { - let physical_address_block = self - .processor_info_v2() - // NOTE: Do we need to support segmented memory via logical_to_physical? - .logical_to_physical(buffer_address, Access::Sim_Access_Read)?; + fn get_manual_start_buffer( + &mut self, + buffer_address: GenericAddress, + virt: bool, + ) -> Result { + let physical_address = if virt { + let physical_address_block = self + .processor_info_v2() + // NOTE: Do we need to support segmented memory via logical_to_physical? + .logical_to_physical(buffer_address, Access::Sim_Access_Read)?; + + if physical_address_block.valid == 0 { + bail!( + "Invalid linear address for given buffer address {:#x}", + buffer_address + ); + } - if physical_address_block.valid == 0 { - bail!( - "Invalid linear address for given buffer address {:#x}", - buffer_address - ); + physical_address_block.address } else { - Ok(StartBuffer::builder() - .physical_address(physical_address_block.address) - .virt(physical_address_block.address != buffer_address) - .build()) - } + buffer_address + }; + + Ok(StartBuffer::builder() + .physical_address(physical_address) + .virt(physical_address != buffer_address) + .build()) } /// Returns the initial start size for non-magic instructions by reading it from a given /// (possibly virtual) address - fn get_manual_start_size(&mut self, size_address: GenericAddress) -> Result { - let physical_address_block = self - .processor_info_v2() - // NOTE: Do we need to support segmented memory via logical_to_physical? - .logical_to_physical(size_address, Access::Sim_Access_Read)?; + fn get_manual_start_size( + &mut self, + size_address: GenericAddress, + virt: bool, + ) -> Result { + let physical_address = if virt { + let physical_address_block = self + .processor_info_v2() + // NOTE: Do we need to support segmented memory via logical_to_physical? + .logical_to_physical(size_address, Access::Sim_Access_Read)?; + + if physical_address_block.valid == 0 { + bail!("Invalid linear address given for start buffer : {size_address:#x}"); + } - if physical_address_block.valid == 0 { - bail!("Invalid linear address given for start buffer : {size_address:#x}"); - } + physical_address_block.address + } else { + size_address + }; let size_size = self.processor_info_v2().get_logical_address_width()? / u8::BITS as i32; - let size = read_phys_memory(self.cpu(), physical_address_block.address, size_size)?; + let size = read_phys_memory(self.cpu(), physical_address, size_size)?; Ok(StartSize::builder() - .physical_address(( - physical_address_block.address, - physical_address_block.address != size_address, - )) + .physical_address((physical_address, physical_address != size_address)) .initial_size(size) .build()) } @@ -361,19 +378,27 @@ impl ArchitectureOperations for Architecture { } } - fn get_manual_start_buffer(&mut self, buffer_address: GenericAddress) -> Result { + fn get_manual_start_buffer( + &mut self, + buffer_address: GenericAddress, + virt: bool, + ) -> Result { match self { - Architecture::X86_64(x86_64) => x86_64.get_manual_start_buffer(buffer_address), - Architecture::I386(i386) => i386.get_manual_start_buffer(buffer_address), - Architecture::RISCV(riscv) => riscv.get_manual_start_buffer(buffer_address), + Architecture::X86_64(x86_64) => x86_64.get_manual_start_buffer(buffer_address, virt), + Architecture::I386(i386) => i386.get_manual_start_buffer(buffer_address, virt), + Architecture::RISCV(riscv) => riscv.get_manual_start_buffer(buffer_address, virt), } } - fn get_manual_start_size(&mut self, size_address: GenericAddress) -> Result { + fn get_manual_start_size( + &mut self, + size_address: GenericAddress, + virt: bool, + ) -> Result { match self { - Architecture::X86_64(x86_64) => x86_64.get_manual_start_size(size_address), - Architecture::I386(i386) => i386.get_manual_start_size(size_address), - Architecture::RISCV(riscv) => riscv.get_manual_start_size(size_address), + Architecture::X86_64(x86_64) => x86_64.get_manual_start_size(size_address, virt), + Architecture::I386(i386) => i386.get_manual_start_size(size_address, virt), + Architecture::RISCV(riscv) => riscv.get_manual_start_size(size_address, virt), } } diff --git a/modules/tsffs/src/tsffs/src/arch/x86.rs b/modules/tsffs/src/tsffs/src/arch/x86.rs index 706a3fc2..ad12d899 100644 --- a/modules/tsffs/src/tsffs/src/arch/x86.rs +++ b/modules/tsffs/src/tsffs/src/arch/x86.rs @@ -344,49 +344,67 @@ impl ArchitectureOperations for X86ArchitectureOperations { .build()) } - fn get_manual_start_buffer(&mut self, buffer_address: GenericAddress) -> Result { - let physical_address_block = self - .processor_info_v2() - // NOTE: Do we need to support segmented memory via logical_to_physical? - .logical_to_physical(buffer_address, Access::Sim_Access_Read)?; - - if physical_address_block.valid == 0 { - bail!( - "Invalid linear address for given buffer address {:#x}", - buffer_address - ); + fn get_manual_start_buffer( + &mut self, + buffer_address: GenericAddress, + virt: bool, + ) -> Result { + let physical_address = if virt { + let physical_address_block = self + .processor_info_v2() + // NOTE: Do we need to support segmented memory via logical_to_physical? + .logical_to_physical(buffer_address, Access::Sim_Access_Read)?; + + if physical_address_block.valid == 0 { + bail!( + "Invalid linear address for given buffer address {:#x}", + buffer_address + ); + } + physical_address_block.address } else { - trace!( - get_object(CLASS_NAME)?, - "Got physical address {:#x} from logical address for manual start buffer", - physical_address_block.address - ); - Ok(StartBuffer::builder() - .physical_address(physical_address_block.address) - .virt(physical_address_block.address != buffer_address) - .build()) - } + buffer_address + }; + + trace!( + get_object(CLASS_NAME)?, + "Got physical address {:#x} from logical address for manual start buffer", + physical_address + ); + Ok(StartBuffer::builder() + .physical_address(physical_address) + .virt(physical_address != buffer_address) + .build()) } /// Returns the initial start size for non-magic instructions by reading it from a given /// (possibly virtual) address - fn get_manual_start_size(&mut self, size_address: GenericAddress) -> Result { - let physical_address_block = self - .processor_info_v2() - // NOTE: Do we need to support segmented memory via logical_to_physical? - .logical_to_physical(size_address, Access::Sim_Access_Read)?; - - if physical_address_block.valid == 0 { - bail!("Invalid linear address given for start buffer : {size_address:#x}"); - } + fn get_manual_start_size( + &mut self, + size_address: GenericAddress, + virt: bool, + ) -> Result { + let physical_address = if virt { + let physical_address_block = self + .processor_info_v2() + // NOTE: Do we need to support segmented memory via logical_to_physical? + .logical_to_physical(size_address, Access::Sim_Access_Read)?; + + if physical_address_block.valid == 0 { + bail!("Invalid linear address given for start buffer : {size_address:#x}"); + } + physical_address_block.address + } else { + size_address + }; trace!( get_object(CLASS_NAME)?, "Got physical address {:#x} from logical address for manual start buffer size", - physical_address_block.address + physical_address ); - let size = read_phys_memory(self.cpu(), physical_address_block.address, 4)?; + let size = read_phys_memory(self.cpu(), physical_address, 4)?; trace!( get_object(CLASS_NAME)?, @@ -394,10 +412,7 @@ impl ArchitectureOperations for X86ArchitectureOperations { ); Ok(StartSize::builder() - .physical_address(( - physical_address_block.address, - physical_address_block.address != size_address, - )) + .physical_address((physical_address, physical_address != size_address)) .initial_size(size) .build()) } diff --git a/modules/tsffs/src/tsffs/src/haps/mod.rs b/modules/tsffs/src/tsffs/src/haps/mod.rs index 94dea700..7b31dcca 100644 --- a/modules/tsffs/src/tsffs/src/haps/mod.rs +++ b/modules/tsffs/src/tsffs/src/haps/mod.rs @@ -77,7 +77,10 @@ impl Tsffs { .ok_or_else(|| anyhow!("No start processor"))?; ( if let Some(buffer) = start.buffer() { - Some(start_processor.get_manual_start_buffer(*buffer)?) + Some( + start_processor + .get_manual_start_buffer(*buffer, *start.virt())?, + ) } else { None }, @@ -85,9 +88,9 @@ impl Tsffs { ManualStartSize::MaximumSize(s) => { Some(StartSize::builder().initial_size(*s).build()) } - ManualStartSize::SizeAddress(a) => { - Some(start_processor.get_manual_start_size(*a)?) - } + ManualStartSize::SizeAddress(a) => Some( + start_processor.get_manual_start_size(*a, *start.virt())?, + ), ManualStartSize::NoSize => None, }, ) diff --git a/modules/tsffs/src/tsffs/src/interface/mod.rs b/modules/tsffs/src/tsffs/src/interface/mod.rs index 020c8c56..dfaa8279 100644 --- a/modules/tsffs/src/tsffs/src/interface/mod.rs +++ b/modules/tsffs/src/tsffs/src/interface/mod.rs @@ -154,6 +154,7 @@ impl Tsffs { cpu: *mut ConfObject, testcase_address: GenericAddress, size_address: GenericAddress, + virt: bool, ) -> Result<()> { debug!( self.as_conf_object(), @@ -165,6 +166,7 @@ impl Tsffs { .processor(cpu) .buffer(testcase_address) .size(ManualStartSize::SizeAddress(size_address)) + .virt(virt) .build(), ))?; @@ -190,6 +192,7 @@ impl Tsffs { cpu: *mut ConfObject, testcase_address: GenericAddress, maximum_size: u32, + virt: bool, ) -> Result<()> { debug!( self.as_conf_object(), @@ -201,6 +204,7 @@ impl Tsffs { .processor(cpu) .buffer(testcase_address) .size(ManualStartSize::MaximumSize(maximum_size as u64)) + .virt(virt) .build(), ))?; diff --git a/modules/tsffs/src/tsffs/src/state/mod.rs b/modules/tsffs/src/tsffs/src/state/mod.rs index 4219a385..dc33b449 100644 --- a/modules/tsffs/src/tsffs/src/state/mod.rs +++ b/modules/tsffs/src/tsffs/src/state/mod.rs @@ -28,6 +28,8 @@ pub struct ManualStart { buffer: Option, #[builder(default = ManualStartSize::NoSize)] size: ManualStartSize, + #[builder(default)] + virt: bool, } #[derive(TypedBuilder, Getters, Serialize, Deserialize, Debug, Clone)] diff --git a/modules/tsffs/tests-restricted/Cargo.toml b/modules/tsffs/tests-restricted/Cargo.toml deleted file mode 100644 index ed775706..00000000 --- a/modules/tsffs/tests-restricted/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (C) 2023 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -[package] -name = "tests-restricted" -description = "Tests for the TSFFS fuzzer" -edition = "2021" -license = "Apache 2.0" -publish = false -version = "0.1.0" - -[dev-dependencies] - -[build-dependencies] -anyhow = "1.0.75" -command-ext = { path = "../src/util/command-ext" } -simics-codegen = { path = "../src/simics/simics-codegen" } - -[dependencies] -anyhow = "1.0.75" -command-ext = { path = "../src/util/command-ext" } diff --git a/modules/tsffs/tests-restricted/SUITEINFO b/modules/tsffs/tests-restricted/SUITEINFO deleted file mode 100644 index f1d686bc..00000000 --- a/modules/tsffs/tests-restricted/SUITEINFO +++ /dev/null @@ -1,2 +0,0 @@ -timeout: 360 -tags: tsffs \ No newline at end of file diff --git a/modules/tsffs/tests-restricted/build.rs b/modules/tsffs/tests-restricted/build.rs deleted file mode 100644 index 3b8c1d93..00000000 --- a/modules/tsffs/tests-restricted/build.rs +++ /dev/null @@ -1,48 +0,0 @@ -use anyhow::{anyhow, Result}; -use command_ext::CommandExtCheck; -use simics_codegen::simics_tests; -use std::{ - env::var, - fs::{read_dir, write}, - path::PathBuf, - process::Command, -}; - -const CARGO_MANIFEST_DIR: &str = "CARGO_MANIFEST_DIR"; -const OUT_DIR_ENV: &str = "OUT_DIR"; -const TESTS_FILE: &str = "tests.rs"; - -fn main() -> Result<()> { - let out_dir = PathBuf::from( - var(OUT_DIR_ENV) - .map_err(|e| anyhow!("No environment variable {OUT_DIR_ENV} found: {e}"))?, - ); - let tests_out_file = out_dir.join(TESTS_FILE); - - let tests_tokens = simics_tests("../../../"); - write(tests_out_file, tests_tokens.to_string()) - .map_err(|e| anyhow!("Failed to write tests out file: {e}"))?; - - let manifest_dir = PathBuf::from( - var(CARGO_MANIFEST_DIR) - .map_err(|e| anyhow!("No environment variable {OUT_DIR_ENV} found: {e}"))?, - ); - - let targets_dir = manifest_dir.join("targets"); - - if targets_dir.is_dir() { - read_dir(targets_dir)? - .filter_map(|d| d.ok()) - .filter(|d| d.path().is_dir()) - .map(|d| d.path()) - .for_each(|d| { - Command::new("ninja") - .current_dir(&d) - .check() - .expect("failed to build"); - println!("cargo:rerun-if-changed={}", d.display()); - }); - } - - Ok(()) -} diff --git a/modules/tsffs/tests-restricted/src/lib.rs b/modules/tsffs/tests-restricted/src/lib.rs deleted file mode 100644 index 83b5fc68..00000000 --- a/modules/tsffs/tests-restricted/src/lib.rs +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright (C) 2023 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -include!(concat!(env!("OUT_DIR"), "/tests.rs")); diff --git a/modules/tsffs/tests/Cargo.toml b/modules/tsffs/tests/Cargo.toml index 022a4031..90116aa0 100644 --- a/modules/tsffs/tests/Cargo.toml +++ b/modules/tsffs/tests/Cargo.toml @@ -29,3 +29,4 @@ walkdir = "2.4.0" anyhow.workspace = true command-ext.workspace = true simics-codegen.workspace = true +ispm-wrapper.workspace = true \ No newline at end of file diff --git a/modules/tsffs/tests/build.rs b/modules/tsffs/tests/build.rs index 3c91f6f0..eb36f3b5 100644 --- a/modules/tsffs/tests/build.rs +++ b/modules/tsffs/tests/build.rs @@ -1,18 +1,23 @@ use anyhow::{anyhow, Result}; use command_ext::CommandExtCheck; +use ispm_wrapper::ispm::{self, GlobalOptions}; use simics_codegen::simics_tests; -use std::{ - env::var, - fs::{read_dir, write}, - path::PathBuf, - process::Command, -}; +use std::{env::var, fs::write, path::PathBuf, process::Command}; const CARGO_MANIFEST_DIR: &str = "CARGO_MANIFEST_DIR"; const OUT_DIR_ENV: &str = "OUT_DIR"; const TESTS_FILE: &str = "tests.rs"; fn main() -> Result<()> { + let packages = ispm::packages::list(&GlobalOptions::default())?; + let base = packages + .installed_packages() + .as_ref() + .ok_or_else(|| anyhow!("No installed packages"))? + .iter() + .find(|p| p.package_number() == &1000isize) + .ok_or_else(|| anyhow!("No base in installed packages"))?; + let out_dir = PathBuf::from( var(OUT_DIR_ENV) .map_err(|e| anyhow!("No environment variable {OUT_DIR_ENV} found: {e}"))?, @@ -26,21 +31,22 @@ fn main() -> Result<()> { var(CARGO_MANIFEST_DIR) .map_err(|e| anyhow!("No environment variable {OUT_DIR_ENV} found: {e}"))?, ); - let targets_dir = manifest_dir.join("targets"); - - read_dir(targets_dir)? - .filter_map(|d| d.ok()) - .filter(|d| d.path().is_dir()) - .map(|d| d.path()) - // Blocklist a few that aren't working - .filter(|d| d.ends_with("riscv-64-edk2")) - .for_each(|d| { - println!("cargo:rerun-if-changed={}", d.to_string_lossy()); - Command::new("ninja") - .current_dir(&d) - .check() - .expect("failed to build"); - }); + let targets_dir = manifest_dir.join("../../../examples/tests/"); + + println!("cargo:rerun-if-changed={}", targets_dir.display()); + + Command::new(targets_dir.join("build.sh")) + .current_dir(targets_dir) + .env( + "SIMICS_BASE", + base.paths() + .first() + .ok_or_else(|| anyhow!("No path to base package"))? + .to_string_lossy() + .to_string(), + ) + .check() + .expect("failed to build"); println!("cargo:rerun-if-changed=build.rs"); Ok(()) diff --git a/modules/tsffs/tests/s-tsffs-configure.py b/modules/tsffs/tests/s-tsffs-configure.py deleted file mode 100644 index fa8c65f7..00000000 --- a/modules/tsffs/tests/s-tsffs-configure.py +++ /dev/null @@ -1,33 +0,0 @@ -# Test that we can successfully load and configure the TSFFS module. - -import simics -import stest - -simics.SIM_load_module("tsffs") -tsffs = SIM_create_object(SIM_get_class("tsffs"), "tsffs", []) -tsffs.iface.tsffs.set_start_on_harness(True) -tsffs.iface.tsffs.set_stop_on_harness(True) -tsffs.iface.tsffs.set_use_snapshots(True) -tsffs.iface.tsffs.set_timeout(60.0) -tsffs.iface.tsffs.add_exception_solution(6) -tsffs.iface.tsffs.add_exception_solution(14) -tsffs.iface.tsffs.remove_exception_solution(6) -tsffs.iface.tsffs.set_all_exceptions_are_solutions(True) -tsffs.iface.tsffs.set_all_exceptions_are_solutions(False) -tsffs.iface.tsffs.add_breakpoint_solution(0) -tsffs.iface.tsffs.add_breakpoint_solution(1) -tsffs.iface.tsffs.remove_breakpoint_solution(0) -tsffs.iface.tsffs.set_all_breakpoints_are_solutions(True) -tsffs.iface.tsffs.set_all_breakpoints_are_solutions(False) -# tsffs.iface.tsffs.set_tracing_mode("once") -tsffs.iface.tsffs.set_cmplog_enabled(False) -# tsffs.iface.tsffs.set_corpus_directory("%simics%/corpus/") -# tsffs.iface.tsffs.set_solutions_directory("%simics%/solutions") -tsffs.iface.tsffs.set_generate_random_corpus(True) -tsffs_config = tsffs.iface.tsffs.get_configuration() -print(tsffs_config) - -# stest.expect_equal( -# tsffs_config, -# {'detector': {'all_breakpoints_are_solutions': 0 , 'all_exceptions_are_solutions': 0 , 'breakpoints': [1] , 'exceptions': [14] , 'timeout': 60.0}, 'driver': {'magic_start': 1 , 'magic_stop': 2 , 'start_on_harness': 1 , 'stop_on_harness': 1 , 'use_snapshots': 1 }, 'tracer': {'cmplog': 0 , 'coverage_mode': 'once'}}, -# ) diff --git a/modules/tsffs/tests/src/lib.rs b/modules/tsffs/tests/src/lib.rs index f228e25e..61bfbb55 100644 --- a/modules/tsffs/tests/src/lib.rs +++ b/modules/tsffs/tests/src/lib.rs @@ -17,7 +17,8 @@ use ispm_wrapper::{ }; use std::{ collections::HashSet, - fs::{copy, create_dir_all, read_dir, write}, + env::var, + fs::{copy, create_dir_all, read_dir, remove_dir_all, write}, path::{Path, PathBuf}, }; use typed_builder::TypedBuilder; @@ -52,7 +53,14 @@ where if src.is_dir() { create_dir_all(&dst)?; } else if src.is_file() { - copy(&src, &dst)?; + if let Err(e) = copy(&src, &dst) { + eprintln!( + "Warning: failed to copy file from {} to {}: {}", + src.display(), + dst.display(), + e + ); + } } } Ok(()) @@ -63,7 +71,7 @@ pub fn local_or_remote_pkg_install(mut options: InstallOptions) -> Result<()> { if Internal::is_internal()? { ispm::packages::install(&options)?; } else { - let installed = ispm::packages::list(options.global())?; + let installed = ispm::packages::list(&GlobalOptions::default())?; for package in options.packages() { let Some(installed) = installed.installed_packages() else { @@ -72,7 +80,7 @@ pub fn local_or_remote_pkg_install(mut options: InstallOptions) -> Result<()> { let Some(available) = installed.iter().find(|p| { p.package_number() == package.package_number() && p.version() == package.version() }) else { - bail!("Did not find package {package:?}"); + bail!("Did not find package {package:?} in {installed:?}"); }; let Some(path) = available.paths().first() else { bail!("No paths for available package {available:?}"); @@ -81,13 +89,30 @@ pub fn local_or_remote_pkg_install(mut options: InstallOptions) -> Result<()> { bail!("No install dir for global options {options:?}"); }; - copy_dir_contents(install_dir, path)?; + let package_install_dir = install_dir + .components() + .last() + .ok_or_else(|| { + anyhow!( + "No final component in install dir {}", + install_dir.display() + ) + })? + .as_os_str() + .to_str() + .ok_or_else(|| anyhow!("Could not convert component to string"))? + .to_string(); + + create_dir_all(&install_dir.join(&package_install_dir))?; + copy_dir_contents(path, &install_dir.join(&package_install_dir))?; } // Clear the remote packages to install, we can install local paths no problem options.packages_mut().clear(); - ispm::packages::install(&options)?; + if !options.package_paths().is_empty() { + ispm::packages::install(&options)?; + } } Ok(()) @@ -105,33 +130,33 @@ impl Architecture { Architecture::X86 => vec![ ProjectPackage::builder() .package_number(1000) - .version("latest") + .version("6.0.169") .build(), // QSP-x86 ProjectPackage::builder() .package_number(2096) - .version("latest") + .version("6.0.70") .build(), // QSP-CPU ProjectPackage::builder() .package_number(8112) - .version("latest") + .version("6.0.17") .build(), ], Architecture::Riscv => vec![ ProjectPackage::builder() .package_number(1000) - .version("latest") + .version("6.0.169") .build(), // RISC-V-CPU ProjectPackage::builder() .package_number(2050) - .version("latest") + .version("6.0.57") .build(), // RISC-V-Simple ProjectPackage::builder() .package_number(2053) - .version("latest") + .version("6.0.4") .build(), ], } @@ -157,6 +182,8 @@ pub struct TestEnvSpec { tsffs: bool, #[builder(default, setter(into))] files: Vec<(String, Vec)>, + #[builder(default, setter(into))] + directories: Vec, #[builder(default, setter(into, strip_option))] simics_home: Option, #[builder(default, setter(into, strip_option))] @@ -257,6 +284,17 @@ impl TestEnv { Ok(()) } + pub fn install_directories

(project_dir: P, directories: &Vec) -> Result<()> + where + P: AsRef, + { + for directory in directories { + copy_dir_contents(directory, &project_dir.as_ref().to_path_buf())?; + } + + Ok(()) + } + fn build(spec: &TestEnvSpec) -> Result { let test_base = PathBuf::from(&spec.cargo_target_tmpdir); let test_dir = test_base.join(&spec.name); @@ -394,6 +432,7 @@ impl TestEnv { .ok(); Self::install_files(&project_dir, &spec.files)?; + Self::install_directories(&project_dir, &spec.directories)?; Ok(Self { test_base, @@ -402,4 +441,16 @@ impl TestEnv { simics_home_dir, }) } + + pub fn cleanup(&mut self) -> Result<()> { + remove_dir_all(self.test_dir()).map_err(|e| anyhow!("Error cleaning up: {e}")) + } + + pub fn cleanup_if_env(&mut self) -> Result<()> { + if let Ok(_cleanup) = var("TSFFS_TEST_CLEANUP_EACH") { + self.cleanup()?; + } + + Ok(()) + } } diff --git a/modules/tsffs/tests/targets/.gitignore b/modules/tsffs/tests/targets/.gitignore deleted file mode 100644 index 37c5d2b9..00000000 --- a/modules/tsffs/tests/targets/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -*.efi -*.o -Image -.ninja_log -*.ext2 -*.tar.gz -*.ko -*.elf -*.lib -test* -!test.[ch] -!test-/ - -# We always copy the header from the root headers directory so it is up to date -tsffs*.h \ No newline at end of file diff --git a/modules/tsffs/tests/targets/minimal-riscv-64-edk2/Dockerfile b/modules/tsffs/tests/targets/minimal-riscv-64-edk2/Dockerfile deleted file mode 100644 index 88d9aa53..00000000 --- a/modules/tsffs/tests/targets/minimal-riscv-64-edk2/Dockerfile +++ /dev/null @@ -1,51 +0,0 @@ -# hadolint global ignore=DL3008 -FROM ghcr.io/tianocore/containers/ubuntu-22-build:a0dd931 AS riscv-gnu-toolchain-edk2 - -ENV DEBIAN_FRONTEND=noninteractive - -SHELL ["/bin/bash", "-o", "pipefail", "-c"] - -# Install riscv64-gcc -RUN apt-get -y update && \ - apt-get -y install autoconf automake autotools-dev curl python3 python3-pip \ - libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex gperf \ - libtool patchutils bc zlib1g-dev libexpat-dev ninja-build git cmake libglib2.0-dev texinfo - -WORKDIR /riscv-gnu-toolchain -# RUN ./configure --with-arch=rv32gc --with-abi=ilp32d -RUN git clone https://github.com/riscv/riscv-gnu-toolchain . && \ - ./configure --enable-multilib && \ - make && \ - make install && \ - rm -rf /riscv-gnu-toolchain - - -FROM riscv-gnu-toolchain-edk2 AS riscv-edk2 - -ENV DEBIAN_FRONTEND=noninteractive -SHELL ["/bin/bash", "-o", "pipefail", "-c"] - - -ENV GCC_RISCV64_PREFIX="riscv64-unknown-elf-" -ENV EDK2_REPO_URL "https://github.com/tianocore/edk2.git" -ENV EDK2_REPO_HASH "a671a14e63fdaa9490e5c61cf11346416f1d1463" -ENV EDK2_PATH "/edk2" - - -RUN git clone "${EDK2_REPO_URL}" "${EDK2_PATH}" && \ - git -C "${EDK2_PATH}" checkout "${EDK2_REPO_HASH}" && \ - python3 -m pip install --no-cache-dir -r "${EDK2_PATH}/pip-requirements.txt" && \ - stuart_setup -c "${EDK2_PATH}/.pytool/CISettings.py" TOOL_CHAIN_TAG=GCC && \ - stuart_update -c "${EDK2_PATH}/.pytool/CISettings.py" TOOL_CHAIN_TAG=GCC - -COPY src "${EDK2_PATH}/HelloWorld/" - -RUN stuart_setup -c "${EDK2_PATH}/HelloWorld/PlatformBuild.py" TOOL_CHAIN_TAG=GCC && \ - stuart_update -c "${EDK2_PATH}/HelloWorld/PlatformBuild.py" TOOL_CHAIN_TAG=GCC && \ - python3 "${EDK2_PATH}/BaseTools/Edk2ToolsBuild.py" -t GCC - -WORKDIR "${EDK2_PATH}" - -RUN source ${EDK2_PATH}/edksetup.sh && \ - ( build -a RISCV64 -t GCC -p HelloWorld/HelloWorld.dsc \ - || ( cat ${EDK2_PATH}/HelloWorld/Build/BUILDLOG.txt && exit 1 ) ) diff --git a/modules/tsffs/tests/targets/minimal-riscv-64-edk2/build.sh b/modules/tsffs/tests/targets/minimal-riscv-64-edk2/build.sh deleted file mode 100755 index 1193d049..00000000 --- a/modules/tsffs/tests/targets/minimal-riscv-64-edk2/build.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -# Copyright (C) 2023 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -# Build the HelloWorld.efi module and copy it into the resource directory for the example -# this only needs to be run if you want to modify the source code for the HelloWorld.efi module, -# otherwise, the EFI is included in the source tree for ease of use - -SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) -IMAGE_NAME="edk2-build-tsffs-gcc-riscv64-test" -CONTAINER_UID=$(echo "${RANDOM}" | sha256sum | head -c 8) -CONTAINER_NAME="${IMAGE_NAME}-tmp-${CONTAINER_UID}" - -pushd "${SCRIPT_DIR}" || exit 1 - -cp "${SCRIPT_DIR}/../../../../../harness/tsffs-gcc-riscv64.h" "${SCRIPT_DIR}/src/tsffs-gcc-riscv64.h" - -docker build -t "${IMAGE_NAME}" -f "Dockerfile" . -docker create --name "${CONTAINER_NAME}" "${IMAGE_NAME}" -docker cp \ - "${CONTAINER_NAME}:/edk2/HelloWorld/Build/HelloWorld/DEBUG_GCC/RISCV64/HelloWorld.efi" \ - "${SCRIPT_DIR}/test.efi" -docker rm -f "${CONTAINER_NAME}" diff --git a/modules/tsffs/tests/targets/minimal-riscv-64-edk2/src/HelloWorld.c b/modules/tsffs/tests/targets/minimal-riscv-64-edk2/src/HelloWorld.c deleted file mode 100644 index c60a93b4..00000000 --- a/modules/tsffs/tests/targets/minimal-riscv-64-edk2/src/HelloWorld.c +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (C) 2023 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -/** @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 - -#include "tsffs-gcc-riscv64.h" - -/** - 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) { - UINTN input_size = 64; - UINTN *input_size_ptr = &input_size; - UINT8 *input = (UINT8 *)AllocatePages(EFI_SIZE_TO_PAGES(input_size)); - - if (!input) { - return EFI_OUT_OF_RESOURCES; - } - - SetMem((VOID *)input, input_size, 0x44); - - HARNESS_START(input, input_size_ptr); - - switch (*input) { - case 'A': { - // Invalid opcode - __asm__(".byte 0x06"); - } - case 'B': { - // Sleep for 10 seconds, this is a "hang" - - // NOTE: gBS is the global Boot Services table - gBS->Stall(10 * 1000 * 1000); - } - case 'C': { - // This will page fault - UINT8 *ptr = (UINT8 *)0xffffffffffffffff; - *ptr = 0x00; - } - default: { - // Nothing, this is a "success" - Print(L"Working...\n"); - } - } - - HARNESS_STOP(); - - if (input) { - FreePages(input, EFI_SIZE_TO_PAGES(input_size)); - } - - return EFI_SUCCESS; -} \ No newline at end of file diff --git a/modules/tsffs/tests/targets/minimal-riscv-64-edk2/src/HelloWorld.dsc b/modules/tsffs/tests/targets/minimal-riscv-64-edk2/src/HelloWorld.dsc deleted file mode 100644 index 46419496..00000000 --- a/modules/tsffs/tests/targets/minimal-riscv-64-edk2/src/HelloWorld.dsc +++ /dev/null @@ -1,43 +0,0 @@ -[Defines] - PLATFORM_NAME = HelloWorld - PLATFORM_GUID = 0458dade-8b6e-4e45-b773-1b27cbda3e06 - PLATFORM_VERSION = 0.01 - DSC_SPECIFICATION = 0x00010006 - OUTPUT_DIRECTORY = Build/HelloWorld - SUPPORTED_ARCHITECTURES = IA32|X64|ARM|AARCH64|RISCV64 - BUILD_TARGETS = DEBUG|RELEASE|NOOPT - SKUID_IDENTIFIER = DEFAULT - DEFINE DEBUG_ENABLE_OUTPUT = FALSE # Set to TRUE to enable debug output - DEFINE DEBUG_PRINT_ERROR_LEVEL = 0x80000040 # Flags to control amount of debug output - DEFINE DEBUG_PROPERTY_MASK = 0 - -!include MdePkg/MdeLibs.dsc.inc - -[PcdsFeatureFlag] - -[PcdsFixedAtBuild] - gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|$(DEBUG_PROPERTY_MASK) - gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|$(DEBUG_PRINT_ERROR_LEVEL) - -[LibraryClasses] - UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf - UefiLib|MdePkg/Library/UefiLib/UefiLib.inf - PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf - BaseLib|MdePkg/Library/BaseLib/BaseLib.inf - BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf - PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf - MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf - UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf - DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf - UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf - - # Include the Debug Library if needed - !if $(DEBUG_ENABLE_OUTPUT) - DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf - DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf - !else ## DEBUG_ENABLE_OUTPUT - DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf - !endif ## DEBUG_ENABLE_OUTPUT - -[Components] - HelloWorld/HelloWorld.inf \ No newline at end of file diff --git a/modules/tsffs/tests/targets/minimal-riscv-64-edk2/src/HelloWorld.inf b/modules/tsffs/tests/targets/minimal-riscv-64-edk2/src/HelloWorld.inf deleted file mode 100755 index b43f119d..00000000 --- a/modules/tsffs/tests/targets/minimal-riscv-64-edk2/src/HelloWorld.inf +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (C) 2023 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -[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 - UEFI_HII_RESOURCE_SECTION = TRUE - -[Sources] - HelloWorld.c - HelloWorldStr.uni - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - -[LibraryClasses] - UefiApplicationEntryPoint - UefiLib - PcdLib - -[FeaturePcd] - gEfiMdeModulePkgTokenSpaceGuid.PcdHelloWorldPrintEnable - -[Pcd] - gEfiMdeModulePkgTokenSpaceGuid.PcdHelloWorldPrintString - gEfiMdeModulePkgTokenSpaceGuid.PcdHelloWorldPrintTimes - -[UserExtensions.TianoCore."ExtraFiles"] - HelloWorldExtra.uni \ No newline at end of file diff --git a/modules/tsffs/tests/targets/minimal-riscv-64-edk2/src/PlatformBuild.py b/modules/tsffs/tests/targets/minimal-riscv-64-edk2/src/PlatformBuild.py deleted file mode 100755 index 1aa7c19b..00000000 --- a/modules/tsffs/tests/targets/minimal-riscv-64-edk2/src/PlatformBuild.py +++ /dev/null @@ -1,112 +0,0 @@ -# Copyright (C) 2023 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -""" - -Script to build HelloWorld firmware - -See: https://www.tianocore.org/edk2-pytool-extensions/integrate/porting/ -for more info -""" - -# mypy: ignore-errors -# flake8: noqa -# pylint: disable=undefined-variable,import-error,invalid-name,too-few-public-methods - -from os.path import abspath, dirname, join -from typing import Iterable, List - -from edk2toolext.environment.uefi_build import UefiBuilder -from edk2toolext.invocables.edk2_platform_build import BuildSettingsManager -from edk2toolext.invocables.edk2_setup import RequiredSubmodule, SetupSettingsManager -from edk2toolext.invocables.edk2_update import UpdateSettingsManager -from edk2toollib.utility_functions import GetHostInfo - - -class HelloWorldSettingsManager( - UpdateSettingsManager, SetupSettingsManager, BuildSettingsManager -): - """ - Settings manager for HelloWorld EFI application build - """ - - def __init__(self) -> None: - """ - Initialize the settings manager - """ - script_path = dirname(abspath(__file__)) - - # Initialize the workspace (ws) path - self.ws = script_path - - def GetWorkspaceRoot(self) -> str: - """ - Returns the absolute path to the workspace root - """ - return self.ws - - def GetActiveScopes(self) -> List[str]: - """ - Returns scope names this settings manager will remain active for - """ - return ["HelloWorld"] - - def GetPackagesSupported(self) -> Iterable[str]: - """ - Returns paths from the edk2 repository root of edk2 packages - supported by this build - """ - return ("HelloWorld",) - - def GetRequiredSubmodules(self) -> Iterable[RequiredSubmodule]: - """ - Returns submodules required for this package. - """ - # We don't have any required submodules, so we just return an empty list. - return [] - - def GetArchitecturesSupported(self) -> Iterable[str]: - """ - Returns edk2 architectures supported by this build. - """ - return ("RISCV64",) - - def GetTargetsSupported(self) -> Iterable[str]: - """ - Returns target tags supported by this build. - """ - return ("DEBUG",) - - def GetPackagesPath(self) -> Iterable[str]: - """ - Returns the paths to the edk2 package - """ - return [abspath(join(self.GetWorkspaceRoot(), ".."))] - - -class PlatformBuilder(UefiBuilder): - """ - Platform build for HelloWorld module - """ - - def SetPlatformEnv(self) -> int: - """ - Set environment variables for the platform - """ - self.env.SetValue( - "ACTIVE_PLATFORM", - "HelloWorld/HelloWorld.dsc", - "Platform hardcoded", - ) - self.env.SetValue("PRODUCT_NAME", "HelloWorld", "Platform hardcoded") - self.env.SetValue("TARGET_ARCH", "RISCV64", "Platform hardcoded") - self.env.SetValue( - "GCC_RISCV64_PREFIX", "riscv64-unknown-elf-", "Platform hardcoded" - ) - os = GetHostInfo().os - if os.lower() == "windows": - self.env.SetValue("TOOL_CHAIN_TAG", "VS2017", "Platform Hardcoded", True) - else: - self.env.SetValue("TOOL_CHAIN_TAG", "GCC", "Platform Hardcoded", True) - - return 0 diff --git a/modules/tsffs/tests/targets/minimal-riscv-64-edk2/src/tsffs-gcc-riscv64.h b/modules/tsffs/tests/targets/minimal-riscv-64-edk2/src/tsffs-gcc-riscv64.h deleted file mode 100644 index 24243dcc..00000000 --- a/modules/tsffs/tests/targets/minimal-riscv-64-edk2/src/tsffs-gcc-riscv64.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef TSFFS_H -#define TSFFS_H - -/// TSFFS Magic Include - -// GCC EASM notes: -// - The stack pointer is required to be the same on exit to an asm block as it -// was on entry - -#define MAGIC_START (0x0001U) -#define MAGIC_STOP (0x0002U) - -#define __srai_extended(value, testcase_ptr, size_ptr) \ - __asm__ __volatile__("mv a0, %0; mv a1, %1; srai zero, zero, %2" \ - : \ - : "r"(testcase_ptr), "r"(size_ptr), "I"(value) \ - : "a0", "a1"); - -#define __srai(value) \ - __asm__ __volatile__("srai zero, zero, %0" : : "I"(value) :) - -#define __arch_harness_start(start, testcase_ptr, size_ptr) \ - do { \ - __srai_extended(start, testcase_ptr, size_ptr); \ - } while (0) - -#define __arch_harness_stop(stop) \ - do { \ - __srai(stop); \ - } while (0) - -#define HARNESS_START(testcase_ptr, size_ptr) \ - do { \ - __arch_harness_start(MAGIC_START, testcase_ptr, size_ptr); \ - } while (0) - -#define HARNESS_STOP() \ - do { \ - __arch_harness_stop(MAGIC_STOP); \ - } while (0) - -#endif // TSFFS_H \ No newline at end of file diff --git a/modules/tsffs/tests/targets/minimal-riscv-64/build.ninja b/modules/tsffs/tests/targets/minimal-riscv-64/build.ninja deleted file mode 100644 index 8e092850..00000000 --- a/modules/tsffs/tests/targets/minimal-riscv-64/build.ninja +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright (C) 2023 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -rule runbuild - command = bash build.sh - -build test: runbuild diff --git a/modules/tsffs/tests/targets/minimal-riscv-64/build.sh b/modules/tsffs/tests/targets/minimal-riscv-64/build.sh deleted file mode 100755 index 977ed5f6..00000000 --- a/modules/tsffs/tests/targets/minimal-riscv-64/build.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash - -# Copyright (C) 2023 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -# Build the HelloWorld.efi module and copy it into the resource directory for the example -# this only needs to be run if you want to modify the source code for the HelloWorld.efi module, -# otherwise, the EFI is included in the source tree for ease of use - -SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) -IMAGE_NAME="buildroot-build-tsffs-gcc-riscv64-test" -CONTAINER_UID=$(echo "${RANDOM}" | sha256sum | head -c 8) -CONTAINER_NAME="${IMAGE_NAME}-tmp-${CONTAINER_UID}" - -pushd "${SCRIPT_DIR}" || exit 1 - -cp "${SCRIPT_DIR}/../../../../../harness/tsffs-gcc-riscv64.h" "${SCRIPT_DIR}/tsffs-gcc-riscv64.h" -cp "${SCRIPT_DIR}/../../../../../harness/tsffs-gcc-riscv64.h" "${SCRIPT_DIR}/test-kernel-modules/package/kernel-modules/test-mod/tsffs-gcc-riscv64.h" - -docker build -t "${IMAGE_NAME}" -f "Dockerfile" . -docker create --name "${CONTAINER_NAME}" "${IMAGE_NAME}" -docker cp \ - "${CONTAINER_NAME}:/buildroot/images.tar.gz" \ - "${SCRIPT_DIR}/images.tar.gz" -docker cp \ - "${CONTAINER_NAME}:/test/usr/test" \ - "${SCRIPT_DIR}/test" -docker cp \ - "${CONTAINER_NAME}:/test/usr/test-mod" \ - "${SCRIPT_DIR}/test-mod" -docker cp \ - "${CONTAINER_NAME}:/test/usr/test-mod-userspace" \ - "${SCRIPT_DIR}/test-mod-userspace" -docker cp \ - "${CONTAINER_NAME}:/buildroot/output/build/test-mod-1.0/test-mod.ko" \ - "${SCRIPT_DIR}/test-mod.ko" -docker rm -f "${CONTAINER_NAME}" -tar -xvf images.tar.gz diff --git a/modules/tsffs/tests/targets/minimal-riscv-64/test-kernel-modules/package/kernel-modules/test-mod/tsffs-gcc-riscv64.h b/modules/tsffs/tests/targets/minimal-riscv-64/test-kernel-modules/package/kernel-modules/test-mod/tsffs-gcc-riscv64.h deleted file mode 100644 index 24243dcc..00000000 --- a/modules/tsffs/tests/targets/minimal-riscv-64/test-kernel-modules/package/kernel-modules/test-mod/tsffs-gcc-riscv64.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef TSFFS_H -#define TSFFS_H - -/// TSFFS Magic Include - -// GCC EASM notes: -// - The stack pointer is required to be the same on exit to an asm block as it -// was on entry - -#define MAGIC_START (0x0001U) -#define MAGIC_STOP (0x0002U) - -#define __srai_extended(value, testcase_ptr, size_ptr) \ - __asm__ __volatile__("mv a0, %0; mv a1, %1; srai zero, zero, %2" \ - : \ - : "r"(testcase_ptr), "r"(size_ptr), "I"(value) \ - : "a0", "a1"); - -#define __srai(value) \ - __asm__ __volatile__("srai zero, zero, %0" : : "I"(value) :) - -#define __arch_harness_start(start, testcase_ptr, size_ptr) \ - do { \ - __srai_extended(start, testcase_ptr, size_ptr); \ - } while (0) - -#define __arch_harness_stop(stop) \ - do { \ - __srai(stop); \ - } while (0) - -#define HARNESS_START(testcase_ptr, size_ptr) \ - do { \ - __arch_harness_start(MAGIC_START, testcase_ptr, size_ptr); \ - } while (0) - -#define HARNESS_STOP() \ - do { \ - __arch_harness_stop(MAGIC_STOP); \ - } while (0) - -#endif // TSFFS_H \ No newline at end of file diff --git a/modules/tsffs/tests/targets/minimal-riscv-64/tsffs-gcc-riscv64.h b/modules/tsffs/tests/targets/minimal-riscv-64/tsffs-gcc-riscv64.h deleted file mode 100644 index 24243dcc..00000000 --- a/modules/tsffs/tests/targets/minimal-riscv-64/tsffs-gcc-riscv64.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef TSFFS_H -#define TSFFS_H - -/// TSFFS Magic Include - -// GCC EASM notes: -// - The stack pointer is required to be the same on exit to an asm block as it -// was on entry - -#define MAGIC_START (0x0001U) -#define MAGIC_STOP (0x0002U) - -#define __srai_extended(value, testcase_ptr, size_ptr) \ - __asm__ __volatile__("mv a0, %0; mv a1, %1; srai zero, zero, %2" \ - : \ - : "r"(testcase_ptr), "r"(size_ptr), "I"(value) \ - : "a0", "a1"); - -#define __srai(value) \ - __asm__ __volatile__("srai zero, zero, %0" : : "I"(value) :) - -#define __arch_harness_start(start, testcase_ptr, size_ptr) \ - do { \ - __srai_extended(start, testcase_ptr, size_ptr); \ - } while (0) - -#define __arch_harness_stop(stop) \ - do { \ - __srai(stop); \ - } while (0) - -#define HARNESS_START(testcase_ptr, size_ptr) \ - do { \ - __arch_harness_start(MAGIC_START, testcase_ptr, size_ptr); \ - } while (0) - -#define HARNESS_STOP() \ - do { \ - __arch_harness_stop(MAGIC_STOP); \ - } while (0) - -#endif // TSFFS_H \ No newline at end of file diff --git a/modules/tsffs/tests/targets/minimal-x86_64-breakpoint-edk2/test.efi b/modules/tsffs/tests/targets/minimal-x86_64-breakpoint-edk2/test.efi deleted file mode 100644 index 172889dc..00000000 Binary files a/modules/tsffs/tests/targets/minimal-x86_64-breakpoint-edk2/test.efi and /dev/null differ diff --git a/modules/tsffs/tests/targets/minimal-x86_64-crash/test.efi b/modules/tsffs/tests/targets/minimal-x86_64-crash/test.efi deleted file mode 100755 index 3b19e367..00000000 Binary files a/modules/tsffs/tests/targets/minimal-x86_64-crash/test.efi and /dev/null differ diff --git a/modules/tsffs/tests/targets/minimal-x86_64-edk2/test.efi b/modules/tsffs/tests/targets/minimal-x86_64-edk2/test.efi deleted file mode 100644 index 522f7c85..00000000 Binary files a/modules/tsffs/tests/targets/minimal-x86_64-edk2/test.efi and /dev/null differ diff --git a/modules/tsffs/tests/targets/minimal-x86_64-timeout/src/HelloWorldExtra.uni b/modules/tsffs/tests/targets/minimal-x86_64-timeout/src/HelloWorldExtra.uni deleted file mode 100755 index efd53a36..00000000 --- a/modules/tsffs/tests/targets/minimal-x86_64-timeout/src/HelloWorldExtra.uni +++ /dev/null @@ -1,13 +0,0 @@ -// /** @file -// HelloWorld Localized Strings and Content -// -// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
-// -// SPDX-License-Identifier: BSD-2-Clause-Patent -// -// **/ - -#string STR_PROPERTIES_MODULE_NAME -#language en-US -"Hello World Application" - diff --git a/modules/tsffs/tests/targets/minimal-x86_64-timeout/src/HelloWorldStr.uni b/modules/tsffs/tests/targets/minimal-x86_64-timeout/src/HelloWorldStr.uni deleted file mode 100644 index 8bec3428..00000000 --- a/modules/tsffs/tests/targets/minimal-x86_64-timeout/src/HelloWorldStr.uni +++ /dev/null @@ -1,22 +0,0 @@ -// /** @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) 2016, Intel Corporation. All rights reserved.
-// -// SPDX-License-Identifier: BSD-2-Clause-Patent -// -// **/ - -/=# - -#langdef en-US "English" - -#string STR_HELLO_WORLD_HELP_INFORMATION #language en-US "" -".TH HelloWorld 0 "Displays a \"UEFI Hello World!\" string."\r\n" -".SH NAME\r\n" -"HelloWorld application.\r\n" \ No newline at end of file diff --git a/modules/tsffs/tests/targets/minimal-x86_64-timeout/test.efi b/modules/tsffs/tests/targets/minimal-x86_64-timeout/test.efi deleted file mode 100644 index ef9d8f91..00000000 Binary files a/modules/tsffs/tests/targets/minimal-x86_64-timeout/test.efi and /dev/null differ diff --git a/modules/tsffs/tests/targets/minimal-x86_64/test.efi b/modules/tsffs/tests/targets/minimal-x86_64/test.efi deleted file mode 100755 index e5831f07..00000000 Binary files a/modules/tsffs/tests/targets/minimal-x86_64/test.efi and /dev/null differ diff --git a/modules/tsffs/tests/tests/riscv_64.rs b/modules/tsffs/tests/tests/riscv_64.rs new file mode 100644 index 00000000..5fe4ec00 --- /dev/null +++ b/modules/tsffs/tests/tests/riscv_64.rs @@ -0,0 +1,115 @@ +// Copyright (C) 2023 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +//! Test for fuzzing a kernel module using a harnessed user-space application +//! RISC-V architecture + +use anyhow::Result; +use command_ext::CommandExtCheck; +use std::{path::PathBuf, process::Command}; +use tests::{Architecture, TestEnvSpec}; + +#[test] +#[cfg_attr(miri, ignore)] +fn test_riscv_64_kernel_from_userspace_magic() -> Result<()> { + let mut env = TestEnvSpec::builder() + .name("test_riscv_64_kernel_from_userspace_magic") + .cargo_manifest_dir(env!("CARGO_MANIFEST_DIR")) + .cargo_target_tmpdir(env!("CARGO_TARGET_TMPDIR")) + .directories([PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("..") + .join("..") + .join("..") + .join("examples") + .join("tests") + .join("riscv-64")]) + .arch(Architecture::Riscv) + .build() + .to_env()?; + + let output = Command::new("./simics") + .current_dir(env.project_dir()) + .arg("--batch-mode") + .arg("-no-gui") + .arg("--no-win") + .arg("test-kernel-from-userspace-magic.simics") + .check()?; + + let output_str = String::from_utf8_lossy(&output.stdout); + + println!("{output_str}"); + + env.cleanup_if_env()?; + + Ok(()) +} + +#[test] +#[cfg_attr(miri, ignore)] +fn test_riscv_64_kernel_magic() -> Result<()> { + let mut env = TestEnvSpec::builder() + .name("test_riscv_64_kernel_magic") + .cargo_manifest_dir(env!("CARGO_MANIFEST_DIR")) + .cargo_target_tmpdir(env!("CARGO_TARGET_TMPDIR")) + .directories([PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("..") + .join("..") + .join("..") + .join("examples") + .join("tests") + .join("riscv-64")]) + .arch(Architecture::Riscv) + .build() + .to_env()?; + + let output = Command::new("./simics") + .current_dir(env.project_dir()) + .arg("--batch-mode") + .arg("-no-gui") + .arg("--no-win") + .arg("test-kernel-magic.simics") + .check()?; + + let output_str = String::from_utf8_lossy(&output.stdout); + + println!("{output_str}"); + + env.cleanup_if_env()?; + + Ok(()) +} + +#[test] +#[cfg_attr(miri, ignore)] +fn test_riscv_64_userspace_magic() -> Result<()> { + let mut env = TestEnvSpec::builder() + .name("test_riscv_64_userspace_magic") + .cargo_manifest_dir(env!("CARGO_MANIFEST_DIR")) + .cargo_target_tmpdir(env!("CARGO_TARGET_TMPDIR")) + .directories([PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("..") + .join("..") + .join("..") + .join("examples") + .join("tests") + .join("riscv-64")]) + .arch(Architecture::Riscv) + .build() + .to_env()?; + + let output = Command::new("./simics") + .current_dir(env.project_dir()) + .arg("--batch-mode") + .arg("-no-gui") + .arg("--no-win") + .arg("test-userspace-magic.simics") + .check()?; + + let output_str = String::from_utf8_lossy(&output.stdout); + + println!("{output_str}"); + + env.cleanup_if_env()?; + + Ok(()) +} diff --git a/modules/tsffs/tests/tests/test_fuzz_gcc_riscv_64_kernel_from_userspace_magic.rs b/modules/tsffs/tests/tests/test_fuzz_gcc_riscv_64_kernel_from_userspace_magic.rs deleted file mode 100644 index 019eeac9..00000000 --- a/modules/tsffs/tests/tests/test_fuzz_gcc_riscv_64_kernel_from_userspace_magic.rs +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (C) 2023 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -//! Test for fuzzing a kernel module using a harnessed user-space application -//! RISC-V architecture - -use anyhow::Result; -use command_ext::CommandExtCheck; -use indoc::indoc; -use std::process::Command; -use tests::{Architecture, TestEnvSpec}; - -const IMAGE: &[u8] = include_bytes!("../targets/minimal-riscv-64/Image"); -const ROOTFS: &[u8] = include_bytes!("../targets/minimal-riscv-64/rootfs.ext2"); -const FW_JUMP: &[u8] = include_bytes!("../targets/minimal-riscv-64/fw_jump.elf"); -const TEST_MOD: &[u8] = include_bytes!("../targets/minimal-riscv-64/test-mod-userspace"); -const TEST_KO: &[u8] = include_bytes!("../targets/minimal-riscv-64/test-mod.ko"); - -#[test] -#[cfg_attr(miri, ignore)] -fn test_fuzz_gcc_riscv_64_kernel_from_userspace_magic() -> Result<()> { - let script = indoc! {r#" - load-module tsffs - - @tsffs = SIM_create_object(SIM_get_class("tsffs"), "tsffs", []) - tsffs.log-level 4 - @tsffs.iface.tsffs.set_start_on_harness(True) - @tsffs.iface.tsffs.set_stop_on_harness(True) - @tsffs.iface.tsffs.set_start_magic_number(3) - @tsffs.iface.tsffs.set_stop_magic_number(4) - @tsffs.iface.tsffs.set_timeout(3.0) - @tsffs.iface.tsffs.add_exception_solution(14) - @tsffs.iface.tsffs.set_generate_random_corpus(True) - @tsffs.iface.tsffs.set_iterations(1000) - @tsffs.iface.tsffs.set_use_snapshots(True) - - load-target "risc-v-simple/linux" namespace = riscv machine:hardware:storage:disk1:image = "test.fs.craff" - - script-branch { - bp.time.wait-for seconds = 15 - board.console.con.input "mkdir /mnt/disk0\r\n" - bp.time.wait-for seconds = 1.0 - board.console.con.input "mount /dev/vdb /mnt/disk0\r\n" - bp.time.wait-for seconds = 1.0 - board.console.con.input "insmod /mnt/disk0/test-mod.ko\r\n" - bp.time.wait-for seconds = 1.0 - board.console.con.input "/mnt/disk0/test-mod-userspace\r\n" - } - - script-branch { - bp.time.wait-for seconds = 240 - quit 1 - } - - run - "#}; - - let env = TestEnvSpec::builder() - .name("fuzz_gcc_riscv_64_kernel_from_user_magic") - .cargo_manifest_dir(env!("CARGO_MANIFEST_DIR")) - .cargo_target_tmpdir(env!("CARGO_TARGET_TMPDIR")) - .files([ - ("test.simics".to_string(), script.as_bytes().to_vec()), - ( - "targets/risc-v-simple/images/linux/Image".to_string(), - IMAGE.to_vec(), - ), - ( - "targets/risc-v-simple/images/linux/rootfs.ext2".to_string(), - ROOTFS.to_vec(), - ), - ( - "targets/risc-v-simple/images/linux/fw_jump.elf".to_string(), - FW_JUMP.to_vec(), - ), - ( - "targets/risc-v-simple/images/linux/test-mod-userspace".to_string(), - TEST_MOD.to_vec(), - ), - ( - "targets/risc-v-simple/images/linux/test-mod.ko".to_string(), - TEST_KO.to_vec(), - ), - ]) - .arch(Architecture::Riscv) - .build() - .to_env()?; - - let base = env.simics_base_dir()?; - let craff = base.join("linux64").join("bin").join("craff"); - - Command::new("dd") - .arg("if=/dev/zero") - .arg(format!( - "of={}", - env.project_dir().join("test.fs").display() - )) - // Create a 128MB disk - .arg("bs=1024") - .arg("count=131072") - .check()?; - Command::new("mkfs.fat") - .arg(env.project_dir().join("test.fs")) - .check()?; - Command::new("mcopy") - .arg("-i") - .arg(env.project_dir().join("test.fs")) - .arg( - env.project_dir() - .join("targets/risc-v-simple/images/linux/test-mod-userspace"), - ) - .arg("::test-mod-userspace") - .check()?; - Command::new("mcopy") - .arg("-i") - .arg(env.project_dir().join("test.fs")) - .arg( - env.project_dir() - .join("targets/risc-v-simple/images/linux/test-mod.ko"), - ) - .arg("::test-mod.ko") - .check()?; - Command::new(craff) - .arg("-o") - .arg(env.project_dir().join("test.fs.craff")) - .arg(env.project_dir().join("test.fs")) - .check()?; - - let output = Command::new("./simics") - .current_dir(env.project_dir()) - .arg("--batch-mode") - .arg("-no-gui") - .arg("--no-win") - .arg("test.simics") - .check()?; - - let _output_str = String::from_utf8_lossy(&output.stdout); - - Ok(()) -} diff --git a/modules/tsffs/tests/tests/test_fuzz_gcc_riscv_64_kernel_magic.rs b/modules/tsffs/tests/tests/test_fuzz_gcc_riscv_64_kernel_magic.rs deleted file mode 100644 index 9d580a60..00000000 --- a/modules/tsffs/tests/tests/test_fuzz_gcc_riscv_64_kernel_magic.rs +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright (C) 2023 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -//! Test for fuzzing a kernel module using a harness directly in the kernel module -//! RISC-V architecture - -use anyhow::Result; -use command_ext::CommandExtCheck; -use indoc::indoc; -use std::process::Command; -use tests::{Architecture, TestEnvSpec}; - -// const BOOT_DISK: &[u8] = include_bytes!("../rsrc/minimal_boot_disk.craff"); -const IMAGE: &[u8] = include_bytes!("../targets/minimal-riscv-64/Image"); -const ROOTFS: &[u8] = include_bytes!("../targets/minimal-riscv-64/rootfs.ext2"); -const FW_JUMP: &[u8] = include_bytes!("../targets/minimal-riscv-64/fw_jump.elf"); -const TEST_MOD: &[u8] = include_bytes!("../targets/minimal-riscv-64/test-mod"); -const TEST_KO: &[u8] = include_bytes!("../targets/minimal-riscv-64/test-mod.ko"); - -#[test] -#[cfg_attr(miri, ignore)] -fn test_fuzz_gcc_riscv_64_kernel_magic() -> Result<()> { - let script = indoc! {r#" - load-module tsffs - - @tsffs = SIM_create_object(SIM_get_class("tsffs"), "tsffs", []) - tsffs.log-level 4 - @tsffs.iface.tsffs.set_start_on_harness(True) - @tsffs.iface.tsffs.set_stop_on_harness(True) - @tsffs.iface.tsffs.set_timeout(3.0) - @tsffs.iface.tsffs.add_exception_solution(14) - @tsffs.iface.tsffs.set_generate_random_corpus(True) - @tsffs.iface.tsffs.set_iterations(1000) - @tsffs.iface.tsffs.set_use_snapshots(True) - - load-target "risc-v-simple/linux" namespace = riscv machine:hardware:storage:disk1:image = "test.fs.craff" - - script-branch { - bp.time.wait-for seconds = 15 - board.console.con.input "mkdir /mnt/disk0\r\n" - bp.time.wait-for seconds = 1.0 - board.console.con.input "mount /dev/vdb /mnt/disk0\r\n" - bp.time.wait-for seconds = 1.0 - board.console.con.input "insmod /mnt/disk0/test-mod.ko\r\n" - bp.time.wait-for seconds = 1.0 - board.console.con.input "/mnt/disk0/test-mod\r\n" - } - - script-branch { - bp.time.wait-for seconds = 240 - quit 1 - } - - run - "#}; - - let env = TestEnvSpec::builder() - .name("fuzz_gcc_riscv_64_kernel_magic") - .cargo_manifest_dir(env!("CARGO_MANIFEST_DIR")) - .cargo_target_tmpdir(env!("CARGO_TARGET_TMPDIR")) - .files([ - ("test.simics".to_string(), script.as_bytes().to_vec()), - ( - "targets/risc-v-simple/images/linux/Image".to_string(), - IMAGE.to_vec(), - ), - ( - "targets/risc-v-simple/images/linux/rootfs.ext2".to_string(), - ROOTFS.to_vec(), - ), - ( - "targets/risc-v-simple/images/linux/fw_jump.elf".to_string(), - FW_JUMP.to_vec(), - ), - ( - "targets/risc-v-simple/images/linux/test-mod".to_string(), - TEST_MOD.to_vec(), - ), - ( - "targets/risc-v-simple/images/linux/test-mod.ko".to_string(), - TEST_KO.to_vec(), - ), - ]) - .arch(Architecture::Riscv) - .build() - .to_env()?; - - let base = env.simics_base_dir()?; - let craff = base.join("linux64").join("bin").join("craff"); - - Command::new("dd") - .arg("if=/dev/zero") - .arg(format!( - "of={}", - env.project_dir().join("test.fs").display() - )) - // Create a 128MB disk - .arg("bs=1024") - .arg("count=131072") - .check()?; - Command::new("mkfs.fat") - .arg(env.project_dir().join("test.fs")) - .check()?; - Command::new("mcopy") - .arg("-i") - .arg(env.project_dir().join("test.fs")) - .arg( - env.project_dir() - .join("targets/risc-v-simple/images/linux/test-mod"), - ) - .arg("::test-mod") - .check()?; - Command::new("mcopy") - .arg("-i") - .arg(env.project_dir().join("test.fs")) - .arg( - env.project_dir() - .join("targets/risc-v-simple/images/linux/test-mod.ko"), - ) - .arg("::test-mod.ko") - .check()?; - Command::new(craff) - .arg("-o") - .arg(env.project_dir().join("test.fs.craff")) - .arg(env.project_dir().join("test.fs")) - .check()?; - - let output = Command::new("./simics") - .current_dir(env.project_dir()) - .arg("--batch-mode") - .arg("-no-gui") - .arg("--no-win") - .arg("test.simics") - .check()?; - - let _output_str = String::from_utf8_lossy(&output.stdout); - - Ok(()) -} diff --git a/modules/tsffs/tests/tests/test_fuzz_gcc_riscv_64_user_magic.rs b/modules/tsffs/tests/tests/test_fuzz_gcc_riscv_64_user_magic.rs deleted file mode 100644 index 81a2db96..00000000 --- a/modules/tsffs/tests/tests/test_fuzz_gcc_riscv_64_user_magic.rs +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright (C) 2023 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -//! Test fuzzing a user space application -//! RISC-V architecture - -use anyhow::Result; -use command_ext::CommandExtCheck; -use indoc::indoc; -use std::process::Command; -use tests::{Architecture, TestEnvSpec}; - -// const BOOT_DISK: &[u8] = include_bytes!("../rsrc/minimal_boot_disk.craff"); -const IMAGE: &[u8] = include_bytes!("../targets/minimal-riscv-64/Image"); -const ROOTFS: &[u8] = include_bytes!("../targets/minimal-riscv-64/rootfs.ext2"); -const FW_JUMP: &[u8] = include_bytes!("../targets/minimal-riscv-64/fw_jump.elf"); -const TEST: &[u8] = include_bytes!("../targets/minimal-riscv-64/test"); - -#[test] -#[cfg_attr(miri, ignore)] -fn test_fuzz_gcc_riscv_64_user_magic() -> Result<()> { - let script = indoc! {r#" - load-module tsffs - - @tsffs = SIM_create_object(SIM_get_class("tsffs"), "tsffs", []) - tsffs.log-level 4 - @tsffs.iface.tsffs.set_start_on_harness(True) - @tsffs.iface.tsffs.set_stop_on_harness(True) - @tsffs.iface.tsffs.set_timeout(3.0) - @tsffs.iface.tsffs.add_exception_solution(14) - @tsffs.iface.tsffs.set_generate_random_corpus(True) - @tsffs.iface.tsffs.set_iterations(1000) - @tsffs.iface.tsffs.set_use_snapshots(True) - - load-target "risc-v-simple/linux" namespace = riscv machine:hardware:storage:disk1:image = "test.fs.craff" - - script-branch { - bp.time.wait-for seconds = 15 - board.console.con.input "mkdir /mnt/disk0\r\n" - bp.time.wait-for seconds = 1.0 - board.console.con.input "mount /dev/vdb /mnt/disk0\r\n" - bp.time.wait-for seconds = 1.0 - board.console.con.capture-start out.txt - board.console.con.input "/mnt/disk0/test\r\n" - } - - script-branch { - bp.time.wait-for seconds = 240 - quit 1 - } - - run - "#}; - - let env = TestEnvSpec::builder() - .name("fuzz_gcc_riscv_64_user_magic") - .cargo_manifest_dir(env!("CARGO_MANIFEST_DIR")) - .cargo_target_tmpdir(env!("CARGO_TARGET_TMPDIR")) - .files([ - ("test.simics".to_string(), script.as_bytes().to_vec()), - ( - "targets/risc-v-simple/images/linux/Image".to_string(), - IMAGE.to_vec(), - ), - ( - "targets/risc-v-simple/images/linux/rootfs.ext2".to_string(), - ROOTFS.to_vec(), - ), - ( - "targets/risc-v-simple/images/linux/fw_jump.elf".to_string(), - FW_JUMP.to_vec(), - ), - ( - "targets/risc-v-simple/images/linux/test".to_string(), - TEST.to_vec(), - ), - ]) - .arch(Architecture::Riscv) - .build() - .to_env()?; - - let base = env.simics_base_dir()?; - let craff = base.join("linux64").join("bin").join("craff"); - - Command::new("dd") - .arg("if=/dev/zero") - .arg(format!( - "of={}", - env.project_dir().join("test.fs").display() - )) - // Create a 128MB disk - .arg("bs=1024") - .arg("count=131072") - .check()?; - Command::new("mkfs.fat") - .arg(env.project_dir().join("test.fs")) - .check()?; - Command::new("mcopy") - .arg("-i") - .arg(env.project_dir().join("test.fs")) - .arg( - env.project_dir() - .join("targets/risc-v-simple/images/linux/test"), - ) - .arg("::test") - .check()?; - Command::new(craff) - .arg("-o") - .arg(env.project_dir().join("test.fs.craff")) - .arg(env.project_dir().join("test.fs")) - .check()?; - - let output = Command::new("./simics") - .current_dir(env.project_dir()) - .arg("--batch-mode") - .arg("-no-gui") - .arg("--no-win") - .arg("test.simics") - .check()?; - - let _output_str = String::from_utf8_lossy(&output.stdout); - - Ok(()) -} diff --git a/modules/tsffs/tests/tests/test_fuzz_gcc_x86_64_edk2.rs b/modules/tsffs/tests/tests/test_fuzz_gcc_x86_64_edk2.rs deleted file mode 100644 index 0d052751..00000000 --- a/modules/tsffs/tests/tests/test_fuzz_gcc_x86_64_edk2.rs +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (C) 2023 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -//! Test fuzzing a UEFI firmware built with EDK2 -//! -//! X86-64 architecture - -use anyhow::Result; -use command_ext::CommandExtCheck; -use indoc::indoc; -use std::process::Command; -use tests::{Architecture, TestEnvSpec}; - -const BOOT_DISK: &[u8] = include_bytes!("../rsrc/minimal_boot_disk.craff"); -const TEST_UEFI: &[u8] = include_bytes!("../targets/minimal-x86_64-edk2/test.efi"); - -#[test] -#[cfg_attr(miri, ignore)] -fn test_fuzz_gcc_x86_64_edk2() -> Result<()> { - let script = indoc! {r#" - load-module tsffs - - @tsffs = SIM_create_object(SIM_get_class("tsffs"), "tsffs", []) - tsffs.log-level 4 - @tsffs.iface.tsffs.set_start_on_harness(True) - @tsffs.iface.tsffs.set_stop_on_harness(True) - @tsffs.iface.tsffs.set_timeout(3.0) - @tsffs.iface.tsffs.add_exception_solution(14) - @tsffs.iface.tsffs.add_exception_solution(6) - @tsffs.iface.tsffs.set_generate_random_corpus(True) - @tsffs.iface.tsffs.set_iterations(1000) - @tsffs.iface.tsffs.set_use_snapshots(True) - - load-target "qsp-x86/uefi-shell" namespace = qsp machine:hardware:storage:disk0:image = "minimal_boot_disk.craff" - - script-branch { - bp.time.wait-for seconds = 15 - qsp.serconsole.con.input "\n" - bp.time.wait-for seconds = .5 - qsp.serconsole.con.input "FS0:\n" - bp.time.wait-for seconds = .5 - local $manager = (start-agent-manager) - qsp.serconsole.con.input ("SimicsAgent.efi --download " + (lookup-file "%simics%/test.efi") + "\n") - bp.time.wait-for seconds = .5 - qsp.serconsole.con.input "test.efi\n" - } - - script-branch { - bp.time.wait-for seconds = 240 - quit 1 - } - - run - - "#}; - - let env = TestEnvSpec::builder() - .name("fuzz_gcc_x86_64-edk2") - .cargo_manifest_dir(env!("CARGO_MANIFEST_DIR")) - .cargo_target_tmpdir(env!("CARGO_TARGET_TMPDIR")) - .files(vec![ - ("test.simics".to_string(), script.as_bytes().to_vec()), - ("test.efi".to_string(), TEST_UEFI.to_vec()), - ("minimal_boot_disk.craff".to_string(), BOOT_DISK.to_vec()), - ]) - .arch(Architecture::X86) - .build() - .to_env()?; - - let output = Command::new("./simics") - .current_dir(env.project_dir()) - .arg("--batch-mode") - .arg("-no-gui") - .arg("--no-win") - .arg("test.simics") - .check()?; - - let _output_str = String::from_utf8_lossy(&output.stdout); - - Ok(()) -} diff --git a/modules/tsffs/tests/tests/test_fuzz_gcc_x86_64_edk2_breakpoint.rs b/modules/tsffs/tests/tests/test_fuzz_gcc_x86_64_edk2_breakpoint.rs deleted file mode 100644 index 03c60efa..00000000 --- a/modules/tsffs/tests/tests/test_fuzz_gcc_x86_64_edk2_breakpoint.rs +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (C) 2023 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -//! Test fuzzing a UEFI firmware built with EDK2, using a write breakpoint on a region of -//! memory as the solution condition -//! -//! X86-64 architecture - -use anyhow::Result; -use command_ext::CommandExtCheck; -use indoc::indoc; -use std::process::Command; -use tests::{Architecture, TestEnvSpec}; - -const BOOT_DISK: &[u8] = include_bytes!("../rsrc/minimal_boot_disk.craff"); -const TEST_UEFI: &[u8] = include_bytes!("../targets/minimal-x86_64-breakpoint-edk2/test.efi"); - -#[test] -#[cfg_attr(miri, ignore)] -fn test_fuzz_gcc_x86_64_edk2_breakpoint() -> Result<()> { - let script = indoc! {r#" - load-module tsffs - - @tsffs = SIM_create_object(SIM_get_class("tsffs"), "tsffs", []) - tsffs.log-level 4 - @tsffs.iface.tsffs.set_start_on_harness(True) - @tsffs.iface.tsffs.set_stop_on_harness(True) - @tsffs.iface.tsffs.set_timeout(3.0) - @tsffs.iface.tsffs.add_exception_solution(14) - @tsffs.iface.tsffs.add_exception_solution(6) - @tsffs.iface.tsffs.set_generate_random_corpus(True) - @tsffs.iface.tsffs.set_iterations(1000) - @tsffs.iface.tsffs.set_use_snapshots(True) - @tsffs.iface.tsffs.set_all_breakpoints_are_solutions(True) - - load-target "qsp-x86/uefi-shell" namespace = qsp machine:hardware:storage:disk0:image = "minimal_boot_disk.craff" - - script-branch { - bp.time.wait-for seconds = 15 - qsp.serconsole.con.input "\n" - bp.time.wait-for seconds = .5 - qsp.serconsole.con.input "FS0:\n" - bp.time.wait-for seconds = .5 - local $manager = (start-agent-manager) - qsp.serconsole.con.input ("SimicsAgent.efi --download " + (lookup-file "%simics%/test.efi") + "\n") - bp.time.wait-for seconds = .5 - qsp.serconsole.con.input "test.efi\n" - } - - script-branch { - local $BP_BUFFER_ADDRESS = 0x4000000 - local $MAGIC_START = 1 - bp.magic.wait-for $MAGIC_START - local $ctx = (new-context) - qsp.mb.cpu0.core[0][0].set-context $ctx - $ctx.break -w $BP_BUFFER_ADDRESS 0x1000 - } - - script-branch { - bp.time.wait-for seconds = 240 - quit 1 - } - - run - - "#}; - - let env = TestEnvSpec::builder() - .name("fuzz_gcc_x86_64-edk2-breakpoint") - .cargo_manifest_dir(env!("CARGO_MANIFEST_DIR")) - .cargo_target_tmpdir(env!("CARGO_TARGET_TMPDIR")) - .files(vec![ - ("test.simics".to_string(), script.as_bytes().to_vec()), - ("test.efi".to_string(), TEST_UEFI.to_vec()), - ("minimal_boot_disk.craff".to_string(), BOOT_DISK.to_vec()), - ]) - .arch(Architecture::X86) - .build() - .to_env()?; - - let output = Command::new("./simics") - .current_dir(env.project_dir()) - .arg("--batch-mode") - .arg("-no-gui") - .arg("--no-win") - .arg("test.simics") - .check()?; - - let _output_str = String::from_utf8_lossy(&output.stdout); - - Ok(()) -} diff --git a/modules/tsffs/tests/tests/test_fuzz_gcc_x86_64_magic.rs b/modules/tsffs/tests/tests/test_fuzz_gcc_x86_64_magic.rs deleted file mode 100644 index 15dd6831..00000000 --- a/modules/tsffs/tests/tests/test_fuzz_gcc_x86_64_magic.rs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (C) 2023 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -//! Test fuzzing a UEFI firmware -//! -//! X86-64 architecture - -use anyhow::Result; -use command_ext::CommandExtCheck; -use indoc::indoc; -use std::process::Command; -use tests::{Architecture, TestEnvSpec}; - -const BOOT_DISK: &[u8] = include_bytes!("../rsrc/minimal_boot_disk.craff"); -const TEST_UEFI: &[u8] = include_bytes!("../targets/minimal-x86_64/test.efi"); - -#[test] -#[cfg_attr(miri, ignore)] -fn test_fuzz_gcc_x86_64_magic() -> Result<()> { - let script = indoc! {r#" - load-module tsffs - - @tsffs = SIM_create_object(SIM_get_class("tsffs"), "tsffs", []) - tsffs.log-level 1 - @tsffs.iface.tsffs.set_start_on_harness(True) - @tsffs.iface.tsffs.set_stop_on_harness(True) - @tsffs.iface.tsffs.set_timeout(3.0) - @tsffs.iface.tsffs.add_exception_solution(14) - @tsffs.iface.tsffs.set_generate_random_corpus(True) - @tsffs.iface.tsffs.set_iterations(1000) - @tsffs.iface.tsffs.set_use_snapshots(True) - - load-target "qsp-x86/uefi-shell" namespace = qsp machine:hardware:storage:disk0:image = "minimal_boot_disk.craff" - - script-branch { - bp.time.wait-for seconds = 15 - qsp.serconsole.con.input "\n" - bp.time.wait-for seconds = .5 - qsp.serconsole.con.input "FS0:\n" - bp.time.wait-for seconds = .5 - local $manager = (start-agent-manager) - qsp.serconsole.con.input ("SimicsAgent.efi --download " + (lookup-file "%simics%/test.efi") + "\n") - bp.time.wait-for seconds = .5 - qsp.serconsole.con.input "test.efi\n" - } - - script-branch { - bp.time.wait-for seconds = 240 - quit 1 - } - - run - - "#}; - - let env = TestEnvSpec::builder() - .name("fuzz_gcc_x86_64_magic") - .cargo_manifest_dir(env!("CARGO_MANIFEST_DIR")) - .cargo_target_tmpdir(env!("CARGO_TARGET_TMPDIR")) - .files(vec![ - ("test.simics".to_string(), script.as_bytes().to_vec()), - ("test.efi".to_string(), TEST_UEFI.to_vec()), - ("minimal_boot_disk.craff".to_string(), BOOT_DISK.to_vec()), - ]) - .arch(Architecture::X86) - .build() - .to_env()?; - - let output = Command::new("./simics") - .current_dir(env.project_dir()) - .arg("--batch-mode") - .arg("-no-gui") - .arg("--no-win") - .arg("test.simics") - .check()?; - - let _output_str = String::from_utf8_lossy(&output.stdout); - - Ok(()) -} diff --git a/modules/tsffs/tests/tests/test_fuzz_gcc_x86_64_magic_crash.rs b/modules/tsffs/tests/tests/test_fuzz_gcc_x86_64_magic_crash.rs deleted file mode 100644 index 909f46e7..00000000 --- a/modules/tsffs/tests/tests/test_fuzz_gcc_x86_64_magic_crash.rs +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (C) 2023 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -//! Test fuzzing a UEFI firmware, which only crashes or doesn't - -use anyhow::Result; -use command_ext::CommandExtCheck; -use indoc::indoc; -use std::process::Command; -use tests::{Architecture, TestEnvSpec}; - -const BOOT_DISK: &[u8] = include_bytes!("../rsrc/minimal_boot_disk.craff"); -const TEST_UEFI: &[u8] = include_bytes!("../targets/minimal-x86_64-crash/test.efi"); - -#[test] -#[cfg_attr(miri, ignore)] -fn test_fuzz_gcc_x86_64_magic_crash() -> Result<()> { - let script = indoc! {r#" - load-module tsffs - - @tsffs = SIM_create_object(SIM_get_class("tsffs"), "tsffs", []) - tsffs.log-level 4 - @tsffs.iface.tsffs.set_start_on_harness(True) - @tsffs.iface.tsffs.set_stop_on_harness(True) - @tsffs.iface.tsffs.set_timeout(3.0) - @tsffs.iface.tsffs.add_exception_solution(14) - @tsffs.iface.tsffs.set_generate_random_corpus(True) - @tsffs.iface.tsffs.set_iterations(1000) - @tsffs.iface.tsffs.set_use_snapshots(True) - - load-target "qsp-x86/uefi-shell" namespace = qsp machine:hardware:storage:disk0:image = "minimal_boot_disk.craff" - - script-branch { - bp.time.wait-for seconds = 15 - qsp.serconsole.con.input "\n" - bp.time.wait-for seconds = .5 - qsp.serconsole.con.input "FS0:\n" - bp.time.wait-for seconds = .5 - local $manager = (start-agent-manager) - qsp.serconsole.con.input ("SimicsAgent.efi --download " + (lookup-file "%simics%/test.efi") + "\n") - bp.time.wait-for seconds = .5 - qsp.serconsole.con.input "test.efi\n" - } - - script-branch { - bp.time.wait-for seconds = 240 - quit 1 - } - - run - - "#}; - - let env = TestEnvSpec::builder() - .name("fuzz_gcc_x86_64_magic_crash") - .cargo_manifest_dir(env!("CARGO_MANIFEST_DIR")) - .cargo_target_tmpdir(env!("CARGO_TARGET_TMPDIR")) - .files(vec![ - ("test.simics".to_string(), script.as_bytes().to_vec()), - ("test.efi".to_string(), TEST_UEFI.to_vec()), - ("minimal_boot_disk.craff".to_string(), BOOT_DISK.to_vec()), - ]) - .arch(Architecture::X86) - .build() - .to_env()?; - - let output = Command::new("./simics") - .current_dir(env.project_dir()) - .arg("--batch-mode") - .arg("-no-gui") - .arg("--no-win") - .arg("test.simics") - .check()?; - - let _output_str = String::from_utf8_lossy(&output.stdout); - - Ok(()) -} diff --git a/modules/tsffs/tests/tests/test_fuzz_gcc_x86_64_magic_timeout.rs b/modules/tsffs/tests/tests/test_fuzz_gcc_x86_64_magic_timeout.rs deleted file mode 100644 index e7c1e86e..00000000 --- a/modules/tsffs/tests/tests/test_fuzz_gcc_x86_64_magic_timeout.rs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (C) 2023 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -//! Test fuzzing a UEFI firmware, which times out -//! -//! X86-64 architecture - -use anyhow::Result; -use command_ext::CommandExtCheck; -use indoc::indoc; -use std::process::Command; -use tests::{Architecture, TestEnvSpec}; - -const BOOT_DISK: &[u8] = include_bytes!("../rsrc/minimal_boot_disk.craff"); -const TEST_UEFI: &[u8] = include_bytes!("../targets/minimal-x86_64-timeout/test.efi"); - -#[test] -#[cfg_attr(miri, ignore)] -fn test_fuzz_gcc_x86_64_magic_timeout() -> Result<()> { - let script = indoc! {r#" - load-module tsffs - - @tsffs = SIM_create_object(SIM_get_class("tsffs"), "tsffs", []) - tsffs.log-level 4 - @tsffs.iface.tsffs.set_start_on_harness(True) - @tsffs.iface.tsffs.set_stop_on_harness(True) - @tsffs.iface.tsffs.set_timeout(3.0) - @tsffs.iface.tsffs.add_exception_solution(14) - @tsffs.iface.tsffs.set_generate_random_corpus(True) - @tsffs.iface.tsffs.set_iterations(1000) - @tsffs.iface.tsffs.set_use_snapshots(True) - - load-target "qsp-x86/uefi-shell" namespace = qsp machine:hardware:storage:disk0:image = "minimal_boot_disk.craff" - - script-branch { - bp.time.wait-for seconds = 15 - qsp.serconsole.con.input "\n" - bp.time.wait-for seconds = .5 - qsp.serconsole.con.input "FS0:\n" - bp.time.wait-for seconds = .5 - local $manager = (start-agent-manager) - qsp.serconsole.con.input ("SimicsAgent.efi --download " + (lookup-file "%simics%/test.efi") + "\n") - bp.time.wait-for seconds = .5 - qsp.serconsole.con.input "test.efi\n" - } - - script-branch { - bp.time.wait-for seconds = 240 - quit 1 - } - - run - - "#}; - - let env = TestEnvSpec::builder() - .name("fuzz_gcc_x86_64_magic_timeout") - .cargo_manifest_dir(env!("CARGO_MANIFEST_DIR")) - .cargo_target_tmpdir(env!("CARGO_TARGET_TMPDIR")) - .files(vec![ - ("test.simics".to_string(), script.as_bytes().to_vec()), - ("test.efi".to_string(), TEST_UEFI.to_vec()), - ("minimal_boot_disk.craff".to_string(), BOOT_DISK.to_vec()), - ]) - .arch(Architecture::X86) - .build() - .to_env()?; - - let output = Command::new("./simics") - .current_dir(env.project_dir()) - .arg("--batch-mode") - .arg("-no-gui") - .arg("--no-win") - .arg("test.simics") - .check()?; - - let _output_str = String::from_utf8_lossy(&output.stdout); - - Ok(()) -} diff --git a/modules/tsffs/tests/tests/test_fuzz_gcc_x86_64_manual.rs b/modules/tsffs/tests/tests/test_fuzz_gcc_x86_64_manual.rs deleted file mode 100644 index eed8657c..00000000 --- a/modules/tsffs/tests/tests/test_fuzz_gcc_x86_64_manual.rs +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright (C) 2023 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -//! Test fuzzing a UEFI firmware with manual harnessing -//! -//! X86-64 architecture - -use anyhow::Result; -use command_ext::CommandExtCheck; -use indoc::indoc; -use ispm_wrapper::data::ProjectPackage; -use std::process::Command; -use tests::{Architecture, TestEnvSpec}; - -const BOOT_DISK: &[u8] = include_bytes!("../rsrc/minimal_boot_disk.craff"); -const TEST_UEFI: &[u8] = include_bytes!("../targets/minimal-x86_64/test.efi"); - -#[test] -#[cfg_attr(miri, ignore)] -fn test_fuzz_gcc_x86_64_manual() -> Result<()> { - let script = indoc! {r#" - import simics - import cli - - simics.SIM_load_module("tsffs") - - tsffs = simics.SIM_create_object( - simics.SIM_get_class("tsffs"), - "tsffs", - [] - ) - simics.SIM_set_log_level(tsffs, 1) - tsffs.iface.tsffs.set_start_on_harness(False) - tsffs.iface.tsffs.set_stop_on_harness(False) - tsffs.iface.tsffs.set_timeout(3.0) - tsffs.iface.tsffs.add_exception_solution(14) - tsffs.iface.tsffs.set_generate_random_corpus(True) - tsffs.iface.tsffs.set_iterations(1000) - tsffs.iface.tsffs.set_use_snapshots(False) - - simics.SIM_load_target( - "qsp-x86/uefi-shell", # Target - "qsp", # Namespace - [], # Presets - [ # Cmdline args - ["machine:hardware:storage:disk0:image", "minimal_boot_disk.craff"], - ["machine:hardware:processor:class", "x86-goldencove-server"] - ] - ) - - qsp = simics.SIM_get_object("qsp") - - def on_magic(o, e, r): - # Wait for magic stop -- in reality this could wait for any stop - # condition, but we make it easy on ourselves for testing purposes - if r == 2: - print("Got magic stop...") - tsffs.iface.tsffs.stop() - - def start_script_branch(): - # Wait for magic start -- in reality this could wait for any - # start condition, but we make it easy on ourselves for testing purposes - print("Waiting for magic start...") - conf.bp.magic.cli_cmds.wait_for(number=1) - print("Got magic start...") - - # In reality, you probably have a known buffer in mind to fuzz - testcase_address_regno = conf.qsp.mb.cpu0.core[0][0].iface.int_register.get_number("rdi") - print("testcase address regno: ", testcase_address_regno) - testcase_address = conf.qsp.mb.cpu0.core[0][0].iface.int_register.read(testcase_address_regno) - print("testcase address: ", testcase_address) - size_regno = conf.qsp.mb.cpu0.core[0][0].iface.int_register.get_number("rsi") - print("size regno: ", size_regno) - size_address = conf.qsp.mb.cpu0.core[0][0].iface.int_register.read(size_regno) - print("size address: ", size_address) - virt = False - - print( - "Starting with testcase address", - hex(testcase_address), - "size address", - hex(size_address), - "virt", - virt - ) - - tsffs.iface.tsffs.start( - conf.qsp.mb.cpu0.core[0][0], - testcase_address, - size_address, - ) - - - - def startup_script_branch(): - cli.global_cmds.wait_for_global_time(seconds=15.0, _relative = True) - qsp.serconsole.con.iface.con_input.input_str("\n") - cli.global_cmds.wait_for_global_time(seconds=1.0, _relative = True) - qsp.serconsole.con.iface.con_input.input_str("FS0:\n") - cli.global_cmds.wait_for_global_time(seconds=1.0, _relative = True) - cli.global_cmds.start_agent_manager() - qsp.serconsole.con.iface.con_input.input_str( - "SimicsAgent.efi --download " + simics.SIM_lookup_file("%simics%/test.efi") + "\n" - ) - cli.global_cmds.wait_for_global_time(seconds=3.0, _relative = True) - qsp.serconsole.con.iface.con_input.input_str("test.efi\n") - - def exit_script_branch(): - cli.global_cmds.wait_for_global_time(seconds=240.0, _relative = True) - simics.SIM_quit(1) - - simics.SIM_hap_add_callback("Core_Magic_Instruction", on_magic, None) - cli.sb_create(start_script_branch) - cli.sb_create(startup_script_branch) - cli.sb_create(exit_script_branch) - - simics.SIM_continue(0) - # NOTE: If running from CLI, omit this! - simics.SIM_main_loop() - "#}; - - let env = TestEnvSpec::builder() - .name("fuzz_gcc_x86_64_manual") - .cargo_manifest_dir(env!("CARGO_MANIFEST_DIR")) - .cargo_target_tmpdir(env!("CARGO_TARGET_TMPDIR")) - .files(vec![ - ("test.py".to_string(), script.as_bytes().to_vec()), - ("test.efi".to_string(), TEST_UEFI.to_vec()), - ("minimal_boot_disk.craff".to_string(), BOOT_DISK.to_vec()), - ]) - .arch(Architecture::X86) - .extra_packages([ProjectPackage::builder() - .package_number(1030) - .version("latest") - .build()]) - .build() - .to_env()?; - - let output = Command::new("./simics") - .current_dir(env.project_dir()) - .arg("--batch-mode") - .arg("-no-gui") - .arg("--no-win") - .arg("test.py") - .check()?; - - let _output_str = String::from_utf8_lossy(&output.stdout); - - Ok(()) -} diff --git a/modules/tsffs/tests/tests/test_fuzz_gcc_x86_64_manual_max.rs b/modules/tsffs/tests/tests/test_fuzz_gcc_x86_64_manual_max.rs deleted file mode 100644 index b64e918b..00000000 --- a/modules/tsffs/tests/tests/test_fuzz_gcc_x86_64_manual_max.rs +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright (C) 2023 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -//! Test fuzzing a UEFI firmware with manual harnessing, no size write-back -//! -//! X86-64 architecture - -use anyhow::Result; -use command_ext::CommandExtCheck; -use indoc::indoc; -use ispm_wrapper::data::ProjectPackage; -use std::process::Command; -use tests::{Architecture, TestEnvSpec}; - -const BOOT_DISK: &[u8] = include_bytes!("../rsrc/minimal_boot_disk.craff"); -const TEST_UEFI: &[u8] = include_bytes!("../targets/minimal-x86_64/test.efi"); - -#[test] -#[cfg_attr(miri, ignore)] -fn test_fuzz_gcc_x86_64_manual_max() -> Result<()> { - let script = indoc! {r#" - import simics - import cli - - simics.SIM_load_module("tsffs") - - tsffs = simics.SIM_create_object( - simics.SIM_get_class("tsffs"), - "tsffs", - [] - ) - simics.SIM_set_log_level(tsffs, 4) - tsffs.iface.tsffs.set_start_on_harness(False) - tsffs.iface.tsffs.set_stop_on_harness(False) - tsffs.iface.tsffs.set_timeout(3.0) - tsffs.iface.tsffs.add_exception_solution(14) - tsffs.iface.tsffs.set_generate_random_corpus(True) - tsffs.iface.tsffs.set_iterations(1000) - tsffs.iface.tsffs.set_use_snapshots(False) - - simics.SIM_load_target( - "qsp-x86/uefi-shell", # Target - "qsp", # Namespace - [], # Presets - [ # Cmdline args - ["machine:hardware:storage:disk0:image", "minimal_boot_disk.craff"], - ["machine:hardware:processor:class", "x86-goldencove-server"] - ] - ) - - qsp = simics.SIM_get_object("qsp") - - def on_magic(o, e, r): - # Wait for magic stop -- in reality this could wait for any stop - # condition, but we make it easy on ourselves for testing purposes - if r == 2: - print("Got magic stop...") - tsffs.iface.tsffs.stop() - - def start_script_branch(): - # Wait for magic start -- in reality this could wait for any - # start condition, but we make it easy on ourselves for testing purposes - print("Waiting for magic start...") - conf.bp.magic.cli_cmds.wait_for(number=1) - print("Got magic start...") - - # In reality, you probably have a known buffer in mind to fuzz - testcase_address_regno = conf.qsp.mb.cpu0.core[0][0].iface.int_register.get_number("rdi") - print("testcase address regno: ", testcase_address_regno) - testcase_address = conf.qsp.mb.cpu0.core[0][0].iface.int_register.read(testcase_address_regno) - print("testcase address: ", testcase_address) - maximum_size = 8 - virt = False - - print( - "Starting with testcase address", - hex(testcase_address), - "maximum size", - hex(maximum_size), - "virt", - virt - ) - - tsffs.iface.tsffs.start_with_maximum_size( - conf.qsp.mb.cpu0.core[0][0], - testcase_address, - maximum_size, - ) - - - - def startup_script_branch(): - cli.global_cmds.wait_for_global_time(seconds=15.0, _relative = True) - qsp.serconsole.con.iface.con_input.input_str("\n") - cli.global_cmds.wait_for_global_time(seconds=1.0, _relative = True) - qsp.serconsole.con.iface.con_input.input_str("FS0:\n") - cli.global_cmds.wait_for_global_time(seconds=1.0, _relative = True) - cli.global_cmds.start_agent_manager() - qsp.serconsole.con.iface.con_input.input_str( - "SimicsAgent.efi --download " + simics.SIM_lookup_file("%simics%/test.efi") + "\n" - ) - cli.global_cmds.wait_for_global_time(seconds=3.0, _relative = True) - qsp.serconsole.con.iface.con_input.input_str("test.efi\n") - - def exit_script_branch(): - cli.global_cmds.wait_for_global_time(seconds=240.0, _relative = True) - simics.SIM_quit(1) - - simics.SIM_hap_add_callback("Core_Magic_Instruction", on_magic, None) - cli.sb_create(start_script_branch) - cli.sb_create(startup_script_branch) - cli.sb_create(exit_script_branch) - - simics.SIM_continue(0) - # NOTE: If running from CLI, omit this! - simics.SIM_main_loop() - "#}; - - let env = TestEnvSpec::builder() - .name("fuzz_gcc_x86_64_manual_max") - .cargo_manifest_dir(env!("CARGO_MANIFEST_DIR")) - .cargo_target_tmpdir(env!("CARGO_TARGET_TMPDIR")) - .files(vec![ - ("test.py".to_string(), script.as_bytes().to_vec()), - ("test.efi".to_string(), TEST_UEFI.to_vec()), - ("minimal_boot_disk.craff".to_string(), BOOT_DISK.to_vec()), - ]) - .arch(Architecture::X86) - .extra_packages([ProjectPackage::builder() - .package_number(1030) - .version("latest") - .build()]) - .build() - .to_env()?; - - let output = Command::new("./simics") - .current_dir(env.project_dir()) - .arg("--batch-mode") - .arg("-no-gui") - .arg("--no-win") - .arg("test.py") - .check()?; - - let _output_str = String::from_utf8_lossy(&output.stdout); - - Ok(()) -} diff --git a/modules/tsffs/tests/tests/test_fuzz_gcc_x86_user_magic.rs b/modules/tsffs/tests/tests/test_fuzz_gcc_x86_user_magic.rs deleted file mode 100644 index 6ba8de64..00000000 --- a/modules/tsffs/tests/tests/test_fuzz_gcc_x86_user_magic.rs +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (C) 2023 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -//! Test fuzzing an x86 user space application in Linux -//! -//! X86-64 architecture, hinted to x86 - -use anyhow::Result; -use command_ext::CommandExtCheck; -use indoc::indoc; -use ispm_wrapper::data::ProjectPackage; -use std::process::Command; -use tests::{Architecture, TestEnvSpec}; - -const TEST_USER: &[u8] = include_bytes!("../targets/minimal-x86-user/test"); - -#[test] -#[cfg_attr(miri, ignore)] -fn test_fuzz_gcc_x86_magic() -> Result<()> { - let script = indoc! {r#" - import simics - import cli - - simics.SIM_load_module("tsffs") - - tsffs = simics.SIM_create_object( - simics.SIM_get_class("tsffs"), - "tsffs", - [] - ) - simics.SIM_set_log_level(tsffs, 4) - tsffs.iface.tsffs.set_start_on_harness(True) - tsffs.iface.tsffs.set_stop_on_harness(True) - tsffs.iface.tsffs.set_timeout(3.0) - tsffs.iface.tsffs.set_generate_random_corpus(True) - tsffs.iface.tsffs.set_iterations(1000) - tsffs.iface.tsffs.set_use_snapshots(True) - - simics.SIM_load_target( - "qsp-x86/clear-linux", # Target - "qsp", # Namespace - [], # Presets - [["machine:hardware:storage:disk1:image", "test.fs.craff"]], - ) - - qsp = simics.SIM_get_object("qsp") - - tsffs.iface.tsffs.add_architecture_hint(qsp.mb.cpu0.core[0][0], "i386") - - # When we're running userspace code, we don't want to catch exeptions until - # we actually start fuzzing, including GPFs on other code. We can wait to - # enable the exception until later (we could even toggle it on and off per - # iteration) - def on_magic(o, e, r): - # Wait for magic stop -- in reality this could wait for any stop - # condition, but we make it easy on ourselves for testing purposes - if r == 1: - tsffs.iface.tsffs.add_exception_solution(13) - - def startup_script_branch(): - cli.global_cmds.wait_for_global_time(seconds=20.0, _relative = True) - qsp.serconsole.con.iface.con_input.input_str("sudo mkdir /disk0/\n") - cli.global_cmds.wait_for_global_time(seconds=1.0, _relative = True) - qsp.serconsole.con.iface.con_input.input_str("sudo mount /dev/sdb /disk0/\n") - cli.global_cmds.wait_for_global_time(seconds=1.0, _relative = True) - qsp.serconsole.con.iface.con_input.input_str("ls /disk0\n") - cli.global_cmds.wait_for_global_time(seconds=1.0, _relative = True) - qsp.serconsole.con.iface.con_input.input_str("/disk0/test\n") - - - def exit_script_branch(): - cli.global_cmds.wait_for_global_time(seconds=240.0, _relative = True) - simics.SIM_quit(1) - - simics.SIM_hap_add_callback("Core_Magic_Instruction", on_magic, None) - cli.sb_create(startup_script_branch) - cli.sb_create(exit_script_branch) - - simics.SIM_continue(0) - # NOTE: If running from CLI, omit this! - simics.SIM_main_loop() - "#}; - - let env = TestEnvSpec::builder() - .name("fuzz_gcc_x86_magic") - .cargo_manifest_dir(env!("CARGO_MANIFEST_DIR")) - .cargo_target_tmpdir(env!("CARGO_TARGET_TMPDIR")) - .files(vec![ - ("test.py".to_string(), script.as_bytes().to_vec()), - ("test".to_string(), TEST_USER.to_vec()), - ]) - .arch(Architecture::X86) - .extra_packages([ - ProjectPackage::builder() - .package_number(1030) - .version("latest") - .build(), - ProjectPackage::builder() - .package_number(4094) - .version("latest") - .build(), - ]) - .build() - .to_env()?; - - let base = env.simics_base_dir()?; - let craff = base.join("linux64").join("bin").join("craff"); - - Command::new("dd") - .arg("if=/dev/zero") - .arg(format!( - "of={}", - env.project_dir().join("test.fs").display() - )) - // Create a 128MB disk - .arg("bs=1024") - .arg("count=131072") - .check()?; - Command::new("mkfs.fat") - .arg(env.project_dir().join("test.fs")) - .check()?; - Command::new("mcopy") - .arg("-i") - .arg(env.project_dir().join("test.fs")) - .arg(env.project_dir().join("test")) - .arg("::test") - .check()?; - Command::new(craff) - .arg("-o") - .arg(env.project_dir().join("test.fs.craff")) - .arg(env.project_dir().join("test.fs")) - .check()?; - - let output = Command::new("./simics") - .current_dir(env.project_dir()) - .arg("--batch-mode") - .arg("-no-gui") - .arg("--no-win") - .arg("test.py") - .check()?; - - let _output_str = String::from_utf8_lossy(&output.stdout); - - Ok(()) -} diff --git a/modules/tsffs/tests/tests/x86.rs b/modules/tsffs/tests/tests/x86.rs new file mode 100644 index 00000000..fb7dc5d9 --- /dev/null +++ b/modules/tsffs/tests/tests/x86.rs @@ -0,0 +1,57 @@ +// Copyright (C) 2023 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +//! Test fuzzing an x86 user space application in Linux +//! +//! X86-64 architecture, hinted to x86 + +use anyhow::Result; +use command_ext::CommandExtCheck; +use ispm_wrapper::data::ProjectPackage; +use std::{path::PathBuf, process::Command}; +use tests::{Architecture, TestEnvSpec}; + +#[test] +#[cfg_attr(miri, ignore)] +fn test_x86_user_magic() -> Result<()> { + let mut env = TestEnvSpec::builder() + .name("x86-user") + .cargo_manifest_dir(env!("CARGO_MANIFEST_DIR")) + .cargo_target_tmpdir(env!("CARGO_TARGET_TMPDIR")) + .directories([PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("..") + .join("..") + .join("..") + .join("examples") + .join("tests") + .join("x86-user")]) + .arch(Architecture::X86) + .extra_packages([ + ProjectPackage::builder() + .package_number(1030) + .version("6.0.4") + .build(), + ProjectPackage::builder() + .package_number(4094) + .version("6.0.14") + .build(), + ]) + .build() + .to_env()?; + + let output = Command::new("./simics") + .current_dir(env.project_dir()) + .arg("--batch-mode") + .arg("-no-gui") + .arg("--no-win") + .arg("test-user.py") + .check()?; + + let output_str = String::from_utf8_lossy(&output.stdout); + + println!("{output_str}"); + + env.cleanup_if_env()?; + + Ok(()) +} diff --git a/modules/tsffs/tests/tests/x86_64.rs b/modules/tsffs/tests/tests/x86_64.rs new file mode 100644 index 00000000..2926a6c5 --- /dev/null +++ b/modules/tsffs/tests/tests/x86_64.rs @@ -0,0 +1,224 @@ +// Copyright (C) 2023 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +//! Test fuzzing a UEFI firmware built with EDK2 +//! +//! X86-64 architecture + +use anyhow::Result; +use command_ext::CommandExtCheck; +use ispm_wrapper::data::ProjectPackage; +use std::{path::PathBuf, process::Command}; +use tests::{Architecture, TestEnvSpec}; + +#[test] +#[cfg_attr(miri, ignore)] +fn test_x86_64_edk2_magic() -> Result<()> { + let mut env = TestEnvSpec::builder() + .name("test_x86_64_edk2_magic") + .cargo_manifest_dir(env!("CARGO_MANIFEST_DIR")) + .cargo_target_tmpdir(env!("CARGO_TARGET_TMPDIR")) + .directories([PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("..") + .join("..") + .join("..") + .join("examples") + .join("tests") + .join("x86_64-uefi-edk2")]) + .arch(Architecture::X86) + .build() + .to_env()?; + + let output = Command::new("./simics") + .current_dir(env.project_dir()) + .arg("--batch-mode") + .arg("-no-gui") + .arg("--no-win") + .arg("test-uefi-magic.simics") + .check()?; + + let output_str = String::from_utf8_lossy(&output.stdout); + + println!("{output_str}"); + env.cleanup_if_env()?; + + Ok(()) +} +#[test] +#[cfg_attr(miri, ignore)] +fn test_x86_64_magic_crash() -> Result<()> { + let mut env = TestEnvSpec::builder() + .name("test_x86_64_magic_crash") + .cargo_manifest_dir(env!("CARGO_MANIFEST_DIR")) + .cargo_target_tmpdir(env!("CARGO_TARGET_TMPDIR")) + .directories([PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("..") + .join("..") + .join("..") + .join("examples") + .join("tests") + .join("x86_64-crash-uefi")]) + .arch(Architecture::X86) + .build() + .to_env()?; + + let output = Command::new("./simics") + .current_dir(env.project_dir()) + .arg("--batch-mode") + .arg("-no-gui") + .arg("--no-win") + .arg("test-magic.simics") + .check()?; + + let output_str = String::from_utf8_lossy(&output.stdout); + + println!("{output_str}"); + env.cleanup_if_env()?; + + Ok(()) +} + +#[test] +#[cfg_attr(miri, ignore)] +fn test_x86_64_timeout_edk2() -> Result<()> { + let mut env = TestEnvSpec::builder() + .name("test_x86_64_timeout_edk2") + .cargo_manifest_dir(env!("CARGO_MANIFEST_DIR")) + .cargo_target_tmpdir(env!("CARGO_TARGET_TMPDIR")) + .directories([PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("..") + .join("..") + .join("..") + .join("examples") + .join("tests") + .join("x86_64-timeout-uefi-edk2")]) + .arch(Architecture::X86) + .build() + .to_env()?; + + let output = Command::new("./simics") + .current_dir(env.project_dir()) + .arg("--batch-mode") + .arg("-no-gui") + .arg("--no-win") + .arg("test-magic.simics") + .check()?; + + let output_str = String::from_utf8_lossy(&output.stdout); + + println!("{output_str}"); + env.cleanup_if_env()?; + + Ok(()) +} + +#[test] +#[cfg_attr(miri, ignore)] +fn test_x86_64_magic() -> Result<()> { + let mut env = TestEnvSpec::builder() + .name("test_x86_64_magic") + .cargo_manifest_dir(env!("CARGO_MANIFEST_DIR")) + .cargo_target_tmpdir(env!("CARGO_TARGET_TMPDIR")) + .directories([PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("..") + .join("..") + .join("..") + .join("examples") + .join("tests") + .join("x86_64-uefi")]) + .arch(Architecture::X86) + .build() + .to_env()?; + + let output = Command::new("./simics") + .current_dir(env.project_dir()) + .arg("--batch-mode") + .arg("-no-gui") + .arg("--no-win") + .arg("test-magic.simics") + .check()?; + + let output_str = String::from_utf8_lossy(&output.stdout); + + println!("{output_str}"); + env.cleanup_if_env()?; + + Ok(()) +} + +#[test] +#[cfg_attr(miri, ignore)] +fn test_x86_64_manual() -> Result<()> { + let mut env = TestEnvSpec::builder() + .name("test_x86_64_manual") + .cargo_manifest_dir(env!("CARGO_MANIFEST_DIR")) + .cargo_target_tmpdir(env!("CARGO_TARGET_TMPDIR")) + .directories([PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("..") + .join("..") + .join("..") + .join("examples") + .join("tests") + .join("x86_64-uefi")]) + .arch(Architecture::X86) + .extra_packages([ProjectPackage::builder() + .package_number(1030) + .version("6.0.4") + .build()]) + .build() + .to_env()?; + + let output = Command::new("./simics") + .current_dir(env.project_dir()) + .arg("--batch-mode") + .arg("-no-gui") + .arg("--no-win") + .arg("test-manual.py") + .check()?; + + let output_str = String::from_utf8_lossy(&output.stdout); + + println!("{output_str}"); + env.cleanup_if_env()?; + + Ok(()) +} + +#[test] +#[cfg_attr(miri, ignore)] +fn test_x86_64_manual_max() -> Result<()> { + let mut env = TestEnvSpec::builder() + .name("test_x86_64_manual_max") + .cargo_manifest_dir(env!("CARGO_MANIFEST_DIR")) + .cargo_target_tmpdir(env!("CARGO_TARGET_TMPDIR")) + .directories([PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("..") + .join("..") + .join("..") + .join("examples") + .join("tests") + .join("x86_64-uefi")]) + .arch(Architecture::X86) + .extra_packages([ProjectPackage::builder() + .package_number(1030) + .version("6.0.4") + .build()]) + .build() + .to_env()?; + + let output = Command::new("./simics") + .current_dir(env.project_dir()) + .arg("--batch-mode") + .arg("-no-gui") + .arg("--no-win") + .arg("test-manual-max.py") + .check()?; + + let output_str = String::from_utf8_lossy(&output.stdout); + + println!("{output_str}"); + + env.cleanup_if_env()?; + + Ok(()) +}