-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4c5c67e
commit 1a8372e
Showing
25 changed files
with
1,383 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# EDK2 SIMICS Platform BIOS Tutorial | ||
|
||
This tutorial will walk you through the entire process of creating, building, and | ||
fuzzing a platform BIOS image. You can read about what exactly a platform BIOS FD image | ||
contains | ||
[here](https://tianocore-docs.github.io/edk2-BuildSpecification/release-1.28/10_post-build_imagegen_stage_-_flash/105_create_the_fd_image_files.html#105-create-the-fd-image-files). | ||
|
||
- [Obtaining Sources](obtaining-sources.md) | ||
- [Building the BIOS](building-bios.md) | ||
- [Booting the BIOS](booting.md) | ||
- [Harnessing the BIOS Boot Logo Parser](harnessing.md) | ||
- [Configuring the Fuzzer](configuring.md) | ||
- [Running the Fuzzer](running.md) | ||
- [Optimizing the Fuzzer](optimizing.md) |
244 changes: 244 additions & 0 deletions
244
docs/src/tutorials/edk2-simics-platform-bios/booting.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,244 @@ | ||
# Booting the BIOS | ||
|
||
After building our BIOS, we want to make sure we can boot it normally before we | ||
add our fuzzing harness. This time, we'll add our harness to the boot flow, before any | ||
UEFI shell, so it is prudent to make sure everything looks OK first. | ||
|
||
Before this step, you'll need to have the TSFFS SIMICS package installed in your system | ||
by following the [setup steps](../setup/README.md) or by installing a prebuilt `ispm` | ||
package. You'll also need the SIMICS base package (1000), the QSP-x86 package (2096), | ||
and the QSP-CPU (8112) package. All three are available in the public simics release. | ||
|
||
You can check that you have the package installed by running: | ||
|
||
```sh | ||
ispm packages --list-installed | ||
``` | ||
|
||
You should see (at least, but likely more packages): | ||
|
||
```txt | ||
Installed Base Packages | ||
Package Number Name Version Installed Paths | ||
1000 Simics-Base 6.0.169 /home/rhart/simics/simics-6.0.169 | ||
Installed Addon Packages | ||
Package Number Name Version Installed Paths | ||
2096 QSP-x86 6.0.70 /home/rhart/simics/simics-qsp-x86-6.0.70 | ||
8112 QSP-CPU 6.0.17 /home/rhart/simics/simics-qsp-cpu-6.0.17 | ||
31337 TSFFS 6.0.1 /home/rhart/simics/simics-tsffs-6.0.1 | ||
``` | ||
|
||
in the list! | ||
|
||
## Create the Project | ||
|
||
We already created the `project` directory when we built our image, but we need to go | ||
ahead and initialize it and add the packages we need with `ispm`. | ||
|
||
```sh | ||
ispm projects project --create 1000-latest 2096-latest 8112-latest 31337-latest \ | ||
--ignore-existing-files | ||
``` | ||
|
||
We won't be using any custom UEFI applications, so we can skip the boot disk we used in | ||
other tutorials. We will, however, need to customize our boot script slightly. | ||
|
||
In the previous tutorials, we used the QSP-x86 package provided `qsp-x86/uefi-shell` | ||
target to boot directly to the UEFI shell without any extra steps. That target uses | ||
a script to choose the boot device for us, but because the included BIOS is both | ||
different from the one we're using and boots in release mode without debug output, we | ||
need to modify it somewhat to work with our custom BIOS. | ||
|
||
## Add SIMICS Targets | ||
|
||
A SIMICS "target" is a YAML file which declares configuration options that are | ||
ultimately passed to a script. It provides an easy way to configure and override options | ||
without digging through scripts to find the right configuration options. You can read | ||
more about targets | ||
[here](https://intel.github.io/tsffs/simics/simics-user-guide/targets.html). | ||
|
||
We'll create a new target in `project/targets/qsp-x86/qsp-uefi-custom.target.yml`: | ||
|
||
```yaml | ||
%YAML 1.2 | ||
--- | ||
description: QSP booting to EFI shell, defaults to empty disks | ||
params: | ||
machine: | ||
system_info: | ||
type: str | ||
description: A short string describing what this system is. | ||
default: "QSP x86 - UEFI Shell" | ||
hardware: | ||
import: "%simics%/targets/qsp-x86/hardware.yml" | ||
defaults: | ||
name: qsp | ||
rtc: | ||
time: auto | ||
usb_tablet: | ||
create: true | ||
firmware: | ||
bios: ^machine:software:firmware:bios | ||
lan_bios: | ||
spi_flash: ^machine:software:firmware:spi_flash | ||
uefi_device: | ||
advanced: 2 | ||
name: | ||
type: str | ||
default: simics_uefi | ||
description: | | ||
Name of a simics-uefi device added under the top component. | ||
video_mode: | ||
type: int | ||
default: 5 | ||
description: | | ||
Bochs GFX Mode to be set by UEFI BIOS during boot before OS handover. | ||
software: | ||
firmware: | ||
description: Firmware images | ||
advanced: 2 | ||
bios: | ||
type: file | ||
description: BIOS file. | ||
default: "%simics%/workspace/Build/SimicsOpenBoardPkg/BoardX58Ich10/DEBUG_GCC/FV/BOARDX58ICH10.fd" | ||
lan_bios: | ||
type: file | ||
required: false | ||
description: ROM BIOS file for the ICH10 LAN Ethernet adaptor | ||
spi_flash: | ||
type: file | ||
default: "%simics%/targets/qsp-x86/images/spi-flash.bin" | ||
description: The ICH10 SPI flash file to use. | ||
script_delay: | ||
type: int | ||
default: 1 | ||
description: Script delay multiplier during UEFI boot | ||
|
||
network: | ||
switch: | ||
import: "%simics%/targets/common/ethernet-setup.yml" | ||
service_node: | ||
import: "%simics%/targets/common/sn-setup.yml" | ||
defaults: | ||
ethernet_switch: ^network:switch:ethernet_switch:name | ||
|
||
output: | ||
system: | ||
type: str | ||
output: yes | ||
default: ^machine:hardware:output:system | ||
script: "%script%/qsp-uefi-custom.target.yml.include" | ||
... | ||
``` | ||
|
||
This target is copied more or less wholesale from the `uefi-shell.target.yml` file in | ||
your SIMICS QSP-x86 installation, but is modified to use a different default BIOS file, | ||
a different `.include` script, and uses a different path to import the top level | ||
`hardware.yml` script. | ||
|
||
We also need to provide a custom `.include` script, which is (as the name may suggest) | ||
included by the target and run on startup to configure the system. Most of this script | ||
is also copied from the `uefi-shell.target.yml.include` script with the exception of the | ||
final `script-branch`. This `script-branch` enters the BIOS boot menu and selects the | ||
UEFI shell from it after waiting for a print message that indicates the boot menu is | ||
visible. | ||
|
||
```simics | ||
run-script "%simics%/targets/qsp-x86/hardware.yml" namespace = machine:hardware | ||
local $system = (params.get machine:hardware:output:system) | ||
instantiate-components $system | ||
# Add Simics UEFI meta-data device | ||
if (params.get machine:uefi_device:name) { | ||
@name = f"{simenv.system}.{params['machine:uefi_device:name']}" | ||
@dev = SIM_create_object("simics-uefi", name, []) | ||
@getattr(conf, simenv.system).mb.nb.pci_bus.devices.append([0, 7, dev]) | ||
@dev.video_mode = params['machine:uefi_device:video_mode'] | ||
} | ||
## Name system | ||
$system->system_info = (params.get machine:system_info) | ||
## Set a time quantum that provides reasonable performance | ||
set-time-quantum cell = $system.cell seconds = 0.0001 | ||
## Set up Ethernet | ||
run-script "%simics%/targets/common/ethernet-setup.yml" namespace = network:switch | ||
if (params.get network:switch:create_network) { | ||
local $ethernet_switch = (params.get network:switch:ethernet_switch:name) | ||
connect ($ethernet_switch.get-free-connector) (params.get machine:hardware:output:eth_slot) | ||
instantiate-components (params.get network:switch:ethernet_switch:name) | ||
} | ||
run-script "%simics%/targets/common/sn-setup.yml" namespace = network:service_node | ||
local $system = (params.get machine:hardware:output:system) | ||
local $system = (params.get machine:hardware:output:system) | ||
script-branch { | ||
local $con = $system.serconsole.con | ||
# NOTE: We have to modify this from the included target because | ||
# the custom BIOS doesn't print the original message until the menu appears | ||
bp.console_string.wait-for $con "End Load Options Dumping" | ||
bp.time.wait-for seconds = 5.0 | ||
echo "Got load options dump" | ||
echo "Opening EFI shell" | ||
$con.input -e Esc | ||
bp.time.wait-for seconds = 5.0 | ||
$con.input -e Down | ||
$con.input -e Down | ||
$con.input -e Enter | ||
bp.time.wait-for seconds = 5.0 | ||
foreach $i in (range 6) { | ||
$con.input -e Down | ||
} | ||
$con.input -e Enter | ||
$con.input -e Enter | ||
} | ||
``` | ||
|
||
Save this file as `project/targets/qsp-x86/qsp-uefi-custom.target.yml.include`. | ||
|
||
## Test Booting The BIOS | ||
|
||
With our files all in place, we can create a tiny SIMICS script, and save it as | ||
`project/run.simics`: | ||
|
||
```simics | ||
load-target "qsp-x86/qsp-uefi-custom" namespace = qsp machine:hardware:firmware:bios = "%simics%/workspace/Build/SimicsOpenBoardPkg/BoardX58Ich10/DEBUG_GCC/FV/BOARDX58ICH10.fd" | ||
script-branch { | ||
local $con = qsp.serconsole.con | ||
bp.console_string.wait-for $con "Shell>" | ||
bp.time.wait-for seconds = .5 | ||
qsp.serconsole.con.input "help\n" | ||
bp.time.wait-for seconds = .5 | ||
} | ||
run | ||
``` | ||
|
||
Then run the script: | ||
|
||
```sh | ||
./simics -no-gui --no-win ./run.simics | ||
``` | ||
|
||
Somewhere in the output you should see: | ||
|
||
```txt | ||
<qsp.serconsole.con>Shell> help\r\n | ||
<qsp.serconsole.con>alias - Displays, creates, or deletes UEFI Shell aliases.\r\n | ||
<qsp.serconsole.con>attrib - Displays or modifies the attributes of files or directories.\r\n | ||
<qsp.serconsole.con>bcfg - Manages the boot and driver options that are stored in NVRAM.\r\n | ||
<qsp.serconsole.con>cd - Displays or changes the current directory.\r\n | ||
``` | ||
|
||
If you do, all is well! Notice that there is quite a bit more output due to being a | ||
debug build of the BIOS. |
74 changes: 74 additions & 0 deletions
74
docs/src/tutorials/edk2-simics-platform-bios/building-bios.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
# Building the BIOS | ||
|
||
Working from the same `Dockerfile` we obtained sources into, we'll set things up to | ||
build the BIOS image. First, we need to set up a few environment variables: | ||
|
||
```dockerfile | ||
ENV EDK_TOOLS_PATH="${PROJECT}/edk2/BaseTools/" | ||
ENV PACKAGES_PATH="${PROJECT}/edk2:${PROJECT}/edk2-platforms:${PROJECT}/edk2-non-osi" | ||
ENV WORKSPACE="${PROJECT}" | ||
``` | ||
|
||
These variables are used by EDK2 to find its own sources and binaries. | ||
|
||
Next, we'll build the *Base Tools*. You can read more about the *Base Tools* in the EDK2 | ||
[build | ||
system](https://tianocore-docs.github.io/edk2-BuildSpecification/release-1.28/4_edk_ii_build_process_overview/41_edk_ii_build_system.html#41-edk-ii-build-system) | ||
documentation. | ||
|
||
```dockerfile | ||
RUN source edk2/edksetup.sh && \ | ||
make -C edk2/BaseTools/ | ||
``` | ||
|
||
With the *Base Tools* built, we can build the BIOS. We directly follow the directions | ||
provided, and you can read more about the process, what settings are available for the | ||
BIOS (in particular, how to change the BIOS stages) [in the | ||
repo](https://github.com/tianocore/edk2-platforms/blob/f446fff05003f69a4396b2ec375301ecb5f63a2a/Platform/Intel/Readme.md). | ||
|
||
First, we'll change into the tree containing the platform code for all the Intel | ||
platforms, then use the Intel-provided build script to select our board, toolchain, | ||
and debug mode (in this case, enabled). | ||
|
||
```dockerfile | ||
WORKDIR "${PROJECT}/edk2-platforms/Platform/Intel" | ||
|
||
# Build SimicsOpenBoardPkg | ||
RUN source "${PROJECT}/edk2/edksetup.sh" && \ | ||
python build_bios.py -p BoardX58Ich10X64 -d -t GCC | ||
``` | ||
|
||
We'll use a build script to manage building the container and copying the relevant | ||
artifacts out of it. Place this script `build.sh` next to your `Dockerfile`. | ||
|
||
```sh | ||
#!/bin/bash | ||
|
||
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) | ||
IMAGE_NAME="edk2-simics-platform" | ||
DOCKERFILE="${SCRIPT_DIR}/Dockerfile" | ||
CONTAINER_UID=$(echo "${RANDOM}" | sha256sum | head -c 8) | ||
CONTAINER_NAME="${IMAGE_NAME}-tmp-${CONTAINER_UID}" | ||
|
||
mkdir -p "${SCRIPT_DIR}/project/" | ||
docker build -t "${IMAGE_NAME}" -f "${DOCKERFILE}" --build-arg "PROJECT=${SCRIPT_DIR}/project/workspace/" "${SCRIPT_DIR}" | ||
docker create --name "${CONTAINER_NAME}" "${IMAGE_NAME}" bash | ||
rm -rf "${SCRIPT_DIR}/project/workspace/" | ||
docker cp "${CONTAINER_NAME}:${SCRIPT_DIR}/project/workspace/" "${SCRIPT_DIR}/project/workspace/" | ||
docker rm -f "${CONTAINER_NAME}" | ||
``` | ||
|
||
Now run the script: | ||
|
||
```sh | ||
chmod +x build.sh | ||
./build.sh | ||
``` | ||
|
||
If all goes well, you'll have a directory | ||
`project/workspace/Build/SimicsOpenBoardPkg/BoardX58Ich10/DEBUG_GCC/FV` containing our | ||
BIOS image (`BOARDX58ICH10.fd`). | ||
|
||
```sh | ||
ls project/workspace/Build/SimicsOpenBoardPkg/BoardX58Ich10/DEBUG_GCC/FV/BOARDX58ICH10.fd | ||
``` |
Oops, something went wrong.