# 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.