badappleuefi-rs/README.md

81 lines
3.6 KiB
Markdown
Raw Permalink Normal View History

2025-10-01 08:11:05 +02:00
# Bad Apple for UEFI (Rust)
Firmware payload that plays the Bad Apple animation directly from a UEFI image. The project uses the [`uefi`](https://github.com/rust-osdev/uefi-rs) crate, renders video frames through GOP, and synthesises audio via the legacy PC speaker using a 1-bit sigma-delta stream. Everything fits inside a `no_std` Rust binary and can be driven under QEMU.
## Repository layout
- `src/` modular firmware code (`app` contains assets, graphics, audio, timing, and player logic).
- `assets/` tiny demo clip/audio used as an embedded fallback.
- `tools/` helper utilities, notably `process_badapple.py` for converting the real video/audio into firmware-friendly blobs.
- `ai/state.json` persistent JSON with personas/tasks as requested.
- `flake.nix` reproducible Nix environment with Rust, ffmpeg, and QEMU.
## Building the EFI binary
1. Ensure you have a recent stable Rust toolchain with the UEFI target installed:
```bash
rustup target add aarch64-unknown-uefi
```
2. Build the binary:
```bash
cargo build --release --target aarch64-unknown-uefi
```
The resulting image will be at `target/aarch64-unknown-uefi/release/badapple-uefi.efi`.
Using Nix instead? Enter the dev shell or boot straight from the flake:
```bash
nix develop
# (rustup target add aarch64-unknown-uefi is invoked automatically in the shell)
# Build & boot in one go under QEMU (cross-emulates aarch64 firmware):
nix run .#qemu
```
## Preparing real assets
The repository embeds a tiny placeholder clip so builds work immediately. To convert the actual Bad Apple video/audio:
```bash
python3 tools/process_badapple.py \
--input /path/to/badapple.mp4 \
--output-dir build/assets \
--width 320 --height 240 --fps 30 \
--sample-rate 44100
```
Copy the generated `video.baa` and `audio.pdm` onto the EFI system partition alongside the application under `\EFI\BADAPPLE\`. The firmware attempts to load external assets first, then falls back to the embedded demo when they are missing.
### Asset format summary
- `video.baa`: magic `"BAA\0"`, header with width/height/fps/frame count, followed by 1-bit packed frames (LSB-first).
- `audio.pdm`: magic `"BAP\0"`, header with sample rate and sample count, followed by 1-bit sigma-delta stream (LSB-first).
## Running under QEMU
A minimal invocation after copying the EFI binary and assets to a FAT image might look like:
```bash
qemu-system-aarch64 \
-machine virt \
-cpu cortex-a72 \
-m 1024 \
-drive if=pflash,format=raw,readonly=on,file=/path/to/AAVMF_CODE.fd \
-drive if=pflash,format=raw,file=/path/to/AAVMF_VARS.fd \
-drive file=fat:rw:esp,format=raw \
-device virtio-gpu-pci \
-device ramfb \
-serial mon:stdio
```
Make sure the `esp` directory contains `EFI/BOOT/BOOTAA64.EFI` (your compiled binary) plus the `EFI/BADAPPLE` assets. Audio output is currently disabled on non-x86 platforms because the legacy PC speaker is unavailable; video playback continues in sync.
## Notes & limitations
- Audio playback uses the legacy PC speaker path on x86 machines; on aarch64 builds the backend is currently silent because that device is absent.
- Timing relies on TSC calibration during boot services. Firmware with non-constant TSCs may require additional guarding.
- Video rendering assumes the selected GOP mode exposes a writable framebuffer (non-BLT-only). Modes with vendor-specific bitmasks are supported via mask calculation.
## Next steps
- Replace the placeholder clip with the full Bad Apple dataset via the tooling above.
- Consider double buffering and smarter frame pacing to reduce tearing.
- Experiment with richer audio backends (e.g. direct HDA/AC97 programming) if available on your platform.