Skip to content

real-hw-test: init - #71

Open
phip1611 wants to merge 20 commits into
rust-osdev:mainfrom
phip1611:real-hw-test
Open

real-hw-test: init#71
phip1611 wants to merge 20 commits into
rust-osdev:mainfrom
phip1611:real-hw-test

Conversation

@phip1611

Copy link
Copy Markdown
Member

Init a new crate member that builds a EFI file that can be easily booted on real hardware.

@phip1611
phip1611 force-pushed the real-hw-test branch 2 times, most recently from 1de6fe5 to 9bc95d0 Compare August 16, 2026 15:17
@phip1611
phip1611 marked this pull request as draft August 16, 2026 15:24
@phip1611 phip1611 self-assigned this Aug 18, 2026
@phip1611
phip1611 marked this pull request as ready for review August 26, 2026 08:57

@phip1611 phip1611 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Almost. Let's drop the ci feature. The crate should not know anything required for a CI run. IF this means a QEMU CI run is not feasible than drop that entirely. If it is possible, keep the QEMU CI run.

@@ -0,0 +1,31 @@
name: UEFI real-hardware test smoke test

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not like that the driver needs to know anything about the CI test. Let's strip all functionality of the testing infrastructur that depends on this.

Comment thread src/backend/mmio.rs Outdated
// register ranges whose address arithmetic would wrap.
let address = self.0.as_ptr().wrapping_add(offset as usize);
let message = "validated MMIO address offset cannot be null";
let address = NonNull::new(address).expect(message);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

embed this message without binding

Comment thread real-hw-test/.envrc
@@ -0,0 +1 @@
use flake

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

split the addition of flake.nix into a dedicated commit, and squash this change into that new commit

The dev shell supplies QEMU, OVMF, and rustup. The .envrc enables
direnv integration.
Manual hardware checks can wait forever for an operator. Disable the
UEFI image watchdog so a long session does not reset the machine.
Report firmware failures on screen.
MMIO addresses do not describe a Rust allocation, so use the wrapping
pointer primitive rather than an in-bounds pointer offset. The UART
constructor already rejects a register range that would wrap.
Mirror every test diagnostic to a dated file below
/uart_16550_test_logs while retaining UEFI console output. Keep one
flushed FAT file handle so a failed write is reported as critical and
aborts the test instead of losing failure evidence.
A real UART can still be draining the byte accepted by try_send_byte
when send_bytes is called. Retry the nonblocking API for one second
instead of treating temporary backpressure as a driver failure.

Preserve an earlier modem-signal warning if a later driver check fails.
Report the dated USB-drive log path before each normal test exit. This
keeps the result on screen when the automated checks fail as well as
when they complete successfully.
Run the unmodified interactive image headlessly under TCG. The harness
answers the operator prompts through QEMU-monitor sendkey and judges
the run by the log persisted on the boot volume plus both serial
captures. Require automatic checks for legacy COM1 and a PCI UART.
Port I/O instructions, legacy COM probing, and the PIO driver backend
exist only on x86. Compiler-enforced cfg gates keep every port-address
path out of the builds of other architectures.
Without x86 port instructions, PCI I/O space is a memory-mapped window
behind the root bridge. Firmware hides the CPU-side base inside its
protocol implementation, but AML resource templates embed plain address
space descriptors, so a strictly validated DSDT byte scan recovers the
translated window without an AML interpreter.

Firmware also leaves the decoding of endpoints it never binds disabled;
an assigned BAR of an unambiguous UART is therefore enabled explicitly.
ARCH selects the Rust target, the removable-media file name, and the
matching QEMU machine: q35 with OVMF on x86_64, virt with pflash EDK2,
ramfb, and a USB keyboard on aarch64. The dev shell switches to the full
QEMU because qemu_kvm only carries the host architecture.
The aarch64 virt machine has no 16550 except the PCI serial device, so
the run must reject the PL011 console via SPCR and drive the PCI UART
through the translated I/O window with the MMIO backend.
One USB stick can carry runs from several machines; the architecture in
the log file name and the on-screen banner keeps them apart.
'make artifacts' cross-compiles all supported architectures, and the USB
install copies every artifact under build/ to its removable-media path,
so one stick boots the test on any supported machine.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant