Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ jobs:
for attempt in 1 2 3; do
apt-get -o Acquire::Check-Valid-Until=false update -qq > /tmp/apt.log 2>&1 \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y -qq git curl ca-certificates \
zstd xz-utils build-essential qemu-system-x86 >> /tmp/apt.log 2>&1 \
zstd xz-utils build-essential qemu-system-x86 ovmf-generic >> /tmp/apt.log 2>&1 \
&& break
[ "$attempt" = 3 ] && { cat /tmp/apt.log; exit 1; }
sleep 20
Expand Down
62 changes: 0 additions & 62 deletions NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,6 @@ Each section names its terms on one `SPDX-License-Identifier:` line, which
agrees with the licence column of `COMMITTED_FILES` in `src/licence.rs` for
every file both name, and that file judges what an image ships by them.

Provenance below was established by inspecting content, not by trusting
memory: `assets/` and `ovmf/` both entered in the initial squashed commit and
carry no attribution of their own. Every hash is `shasum -a 256`, taken
2026-08-08.

**If you redistribute a ToyOS image, read the DOOM1.WAD entry.** It is the one
that constrains what you may do with a build.

Expand Down Expand Up @@ -236,63 +231,6 @@ tests/iced-counter/src/bin/iced-counter.rs — iced's own counter example, MIT
`system.toml` builds ships it.


ovmf/*.fd — EDK II firmware, BSD-2-Clause-Patent
------------------------------------------------

OVMF_CODE-pure-efi.fd 1,966,080 bytes
sha256 9de33971d47958f42af86584b502f83256120b2482e4f7ed14db32fd68e92922
OVMF_VARS-pure-efi.fd 131,072 bytes
sha256 c653de93db67e4f2213a35598efb379a13ef4a12c241e003699d4d7afd193635
DEBUGX64_OVMF.fd 4,194,304 bytes
sha256 800ff5af1220d1232d4da7173ccddbb74a9217600bd8935903d9d534801778b4

Copyright (c) 2019, TianoCore and contributors
Licence text: licenses/BSD-2-Clause-Patent-EDK2.txt
SPDX-License-Identifier: BSD-2-Clause-Patent

Third-party builds of Tianocore EDK II, read out of the binaries' own build
paths: the two `-pure-efi` files were built on a Jenkins worker from
`edk2-gf0064ac3af`, and `DEBUGX64_OVMF.fd` from a different tree (`/src/edk2`,
`DEBUG_GCC5`). No `LICENSE`, version record or build recipe came with them.

`OVMF_CODE`/`OVMF_VARS` are load-bearing — `src/qemu.rs:101` and
`tests/common/qemu.rs:2207` point QEMU's pflash at them, so every boot on the
dev host uses them. **`DEBUGX64_OVMF.fd` is referenced by nothing**: it is
4,194,304 bytes of firmware no code path reaches. The audit missed it, calling
all three load-bearing; whether to keep it is the owner's.

Two open questions for the owner: whether to record a real upstream and version
for these, and whether to take the firmware from QEMU's own installation
instead — which would put it inside the "comes with QEMU" allowance and delete
6,291,456 bytes from the repository.



aavmf/*.fd — EDK II firmware for QEMU `virt`, BSD-2-Clause-Patent AND Apache-2.0
------------------------------------------------------------

AAVMF_CODE.fd 67,108,864 bytes
sha256 47765fe344818cbc464b1c14ae658fb4b854f5c2ceffa982411731eb4865594d
AAVMF_VARS.fd 67,108,864 bytes
sha256 b3b855c5a80310168051164986855692d1bdb06e67619856177965cd87c6774f

Copyright (c) 2019, TianoCore and contributors
Licence text: licenses/BSD-2-Clause-Patent-EDK2.txt
Copyright 1995-2023 The OpenSSL Project Authors
Licence text: licenses/Apache-2.0-OpenSSL.txt
SPDX-License-Identifier: BSD-2-Clause-Patent AND Apache-2.0

QEMU's own prebuilt ArmVirtQemu firmware, unmodified: `edk2-aarch64-code.fd`
and `edk2-arm-vars.fd` as QEMU 11.1.1 installs them under `share/qemu/`,
whose version string reads `edk2-stable202408-prebuilt.qemu.org` (a
`DEBUG_GCC5` build of 2024-09-12). The variable store is the template: every
boot gives it a writable snapshot QEMU discards, because this `DEBUG` build
asserts on a read-only store. QEMU builds it with `NETWORK_TLS_ENABLE`
(`roms/edk2-build.config`, `[opts.common]`), and edk2-stable202408's
ArmVirtQemu links edk2's bundled OpenSSL either way (`OpensslLib` with TLS,
`OpensslLibCrypto` without): OpenSSL 3.0.9, whose `LICENSE.txt` is the
Apache-2.0 text above and which carries no `NOTICE`.

tests/fixtures/gbae-v0.2.0-* — gbae, MIT
-----------------------------------------

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ at your option.

Some of what the repository carries is not ours and is under other terms:
`userland/doom` is GPL-2.0, `assets/` holds a font, a set of icons, a wallpaper
and id Software's Doom shareware IWAD, `ovmf/` holds EDK II firmware builds,
and id Software's Doom shareware IWAD,
and `tests/testcases/` holds TinyCC's test corpus. Third-party crates keep
their own upstream licenses. **[NOTICE](NOTICE) is the list**, item by item,
with the licence texts in [licenses/](licenses).
Expand Down
Binary file removed aavmf/AAVMF_CODE.fd
Binary file not shown.
Binary file removed aavmf/AAVMF_VARS.fd
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
status: expected-red
kind: defect
opened: 2026-09-28
---

# An unreadable sector on a USB boot stick hangs the loader past the firmware watchdog

On stock edk2, a ROOT sector the USB boot stick fails with EIO stops the boot
inside the loader's read of ROOT. The read did not return in 147 s, and the 60 s
watchdog the loader arms at entry did not reset the machine.
`bootloader/src/rootimage.rs`'s `read_root` leans on that watchdog "if the
firmware honours it". This firmware did not.

Measured on the dev host with Homebrew QEMU 11.1.1's own
`edk2-x86_64-code.fd` under TCG. The stimulus is `root_chunk_refused`'s as it
stood on the Headless profile: `blkdebug` failing every `read_aio` covering
the sector seven past ROOT's middle with errno 5, under the boot image on a
`usb-storage` on `nec-usb-xhci`. The harness's deadline was lifted to 150 s,
and each 16550 line was stamped with the seconds since QEMU's spawn:

- `Firmware watchdog: 60 s, until ExitBootServices disables it` at 2.0 s;
- `Slot A: signed header … verifies under this loader's key` at 3.0 s. This
is the last byte on the 16550. The loader's next step is the chunked read
of ROOT that covers the failing sector;
- no further byte in the 147 s to the deadline, no `the read of … failed`
line, and no reset. `-no-reboot` would have turned a reset into QEMU's
exit, which the harness reports as `QEMU died before`. It reported
`Boot timed out` instead.

On the tree's former `ovmf/` image the same stimulus got further and then
also went silent. The failed read returned, and its line reached the console,
but the stick answered the loader's next write to `loader.log` with nothing,
so the read's line was the last the boot said (the ready-marker comment in
`4444076c`'s `tests/common/volumes.rs`). The stick went silent after the
EIO under both firmwares.

This measurement does not show which side does not finish: edk2's USB
mass-storage and xHCI stack, or QEMU's `usb-storage`. It also does not show
why the watchdog's timer event did not run. `usb_pcap` records only the first
data disk and not the boot stick, so no existing instrument sees the bus here.

Every measurement here is QEMU under TCG. Whether a stick with an unreadable
sector hangs the loader on a real machine is unmeasured.

`root_chunk_refused` stages the same EIO on the `InternalDisk` profile's NVMe
boot disk. `root_chunk_refused_on_a_usb_stick` is the same body on the
Headless profile's stick, and `src/redlist.rs` disables it on this file.

## Exit condition

`root_chunk_refused_on_a_usb_stick` is green on stock edk2 and its
`src/redlist.rs` row is lifted. Then this file is deleted.

## Owner

`bootloader/src/rootimage.rs`'s `read_root` and the loader's watchdog in
`bootloader/src/main.rs`; unheld.
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,18 @@ shrink-mark work and against the same tree with that kernel change reverted:
| kernel change reverted | alone | 3 | 1 fail, then 2 pass (attempt 0, 358.0 and 356.3 ms) |
| branch | full nightly tier | 3 | 2 fail, 1 pass |
| kernel change reverted | full nightly tier | 1 | pass |
| stock edk2, #572 at `9082d6b4` | alone | 5 | 2 fail (runs 1 and 3), 3 pass |
| `cd2e6307`, the committed `ovmf/` | alone | 5 | 1 fail (run 5), 4 pass |

Both arms fail and both pass, and the only same-configuration comparison with
more than one sample per side is the *alone* one, where the branch is 6 for 6
and the reverted arm failed once. So the numbers say intermittent; they do not
name a cause and they do not point at a diff.

In each of the two red runs at `9082d6b4` all 10 attempts missed, so each
failed all-or-nothing within its boot: ten `STALLED WINDOW HELD` lines about
410 ms apart, each followed by its flusher thread's exit, then the panic.

**No mechanism is established, and one plausible reading is already refuted.**
`STALLED WINDOW HELD` is not evidence that the truncate arrived after the
window: `SYS_FTRUNCATE` and `SYS_FSYNC` take the same VFS lock and the stall
Expand Down
20 changes: 0 additions & 20 deletions issues/build/no-harness-test-boots-qemus-own-edk2.md

This file was deleted.

22 changes: 0 additions & 22 deletions issues/build/ovmf-s-licence-record-names-no-openssl.md

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
status: open
kind: tooling
opened: 2026-09-28
---

# The kernel console split does not re-arm across a guest reset

`src/kernelconsole.rs`'s `KernelConsole` withholds the virtio port's bytes
until the first `[kernel ` head and passes every byte after it: `held` is
`None` from then on. A guest reset inside one QEMU process does not re-arm it.
`tests/common/update.rs`'s `Rig::boot` boots the Headless profile, whose
stdio is that port, with `takes_the_reset`, and each `reboot` resets that
machine in place. Whatever the next boot's firmware and loader write on the
port reaches every stdio reader as kernel console.

What the next boot writes there has never been captured. The first boot's
stream is measured. On QEMU 11.1.1's own edk2 it opens with
`ESC[2J ESC[01;01H ESC[=3h ESC[2J ESC[01;01H` twice, then
`BdsDxe: loading Boot0001 …`, as a failing test's console dump in the
orchestrator's #572 round-2 nightly shows. No log from #572's runs shows the
port after an in-process reset: each carries that prelude only where a stream
starts. So no signal is known to be in the stream at a reset. Re-arming on the
first boot's prelude would rest on the guess that the firmware repeats it.

Nothing reds on it. The update tests look for a needle past an offset in the
console (`owed`, `reboot_until`), and firmware lines beside the needle do not
stop it matching. Every update test passed in #572's round-2 and round-3
nightlies. If the firmware does write its handoff line there,
`Loader log: … so [kernel …` is a line `Serial::interleaved` reports as a torn
kernel line.

## Exit condition

A capture of stdio across an in-process reset on a virtio profile. If the
firmware writes on the port there, the split re-arms on a signal that capture
shows, with a host test over the captured bytes. If it writes nothing, this
file is deleted with the capture in the commit.

## Owner

`src/kernelconsole.rs` and `tests/common/qemu.rs`'s stdio reader; unheld.
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ three extents: the firmware map, every BAR firmware assigned (`taken.push` of
`memory.address()..end`), and every range a bridge forwards
(`taken.push(forwarded)`). The rule is host-tested; the two kernel pushes are
not. Deleting the BAR push still places the NIC at `0xc000200000` on QEMU's
edk2 and at `0x800200000` on `ovmf/`, because the 2 MiB alignment steps over
firmware's BARs there, and `alone_in_its_page` checks only BARs, not the ranges
bridges forward. No machine in reach puts a BAR it hands over behind a bridge.
edk2, because the 2 MiB alignment steps over firmware's BARs there, and
`alone_in_its_page` checks only BARs, not the ranges bridges forward. No
machine in reach puts a BAR it hands over behind a bridge.

Owner: orchestrator. Exit condition: a guest test goes red when either push is
deleted — a machine whose firmware places a BAR, or a bridge's forwarded range,
Expand Down
Loading
Loading