From 18ec39e38ed6e8347a5028588b5b0c08aabfb735 Mon Sep 17 00:00:00 2001 From: Pepper Gray <111446242+peppergrayxyz@users.noreply.github.com> Date: Sat, 1 Nov 2025 01:44:53 +0100 Subject: [PATCH] Add basic example - showcase an OS that boots a minimal kernel using bootloader - update usage guides Signed-off-by: Pepper Gray Co-authored-by: Tom Dohrmann --- .github/workflows/ci.yml | 20 + README.md | 81 +- docs/create-disk-image.md | 95 +-- examples/basic/.cargo/config.toml | 2 + examples/basic/.gitignore | 2 + examples/basic/Cargo.lock | 1095 +++++++++++++++++++++++++ examples/basic/Cargo.toml | 15 + examples/basic/basic-os.md | 56 ++ examples/basic/build.rs | 25 + examples/basic/kernel/.gitignore | 2 + examples/basic/kernel/Cargo.toml | 9 + examples/basic/kernel/basic-kernel.md | 9 + examples/basic/kernel/src/main.rs | 48 ++ examples/basic/rust-toolchain.toml | 4 + examples/basic/src/main.rs | 69 ++ 15 files changed, 1426 insertions(+), 106 deletions(-) create mode 100644 examples/basic/.cargo/config.toml create mode 100644 examples/basic/.gitignore create mode 100644 examples/basic/Cargo.lock create mode 100644 examples/basic/Cargo.toml create mode 100644 examples/basic/basic-os.md create mode 100644 examples/basic/build.rs create mode 100644 examples/basic/kernel/.gitignore create mode 100644 examples/basic/kernel/Cargo.toml create mode 100644 examples/basic/kernel/basic-kernel.md create mode 100644 examples/basic/kernel/src/main.rs create mode 100644 examples/basic/rust-toolchain.toml create mode 100644 examples/basic/src/main.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f136dc79..dd60a085 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -85,6 +85,26 @@ jobs: if: runner.os == 'Linux' run: cargo test --no-default-features --features bios + examples: + name: Build examples + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@v3 + - uses: Swatinem/rust-cache@v2 + - uses: r7kamura/rust-problem-matchers@v1.1.0 + - name: Install QEMU (Linux) + run: sudo apt update && sudo apt install qemu-system-x86 + - name: "Build basic example" + run: cargo build + working-directory: examples/basic + - name: "Run basic example (bios)" + run: cargo run -- bios + working-directory: examples/basic + - name: "Run basic example (uefi)" + run: cargo run -- uefi + working-directory: examples/basic + fmt: name: Check Formatting runs-on: ubuntu-latest diff --git a/README.md b/README.md index e8f4ef01..b19b9104 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,19 @@ You need a nightly [Rust](https://www.rust-lang.org) compiler with the `llvm-too To use this crate, you need to adjust your kernel to be bootable first. Then you can create a bootable disk image from your compiled kernel. These steps are explained in detail below. +### Migrating from older bootloader version + If you're already using an older version of the `bootloader` crate, follow our [migration guides](docs/migration). -### Kernel +### Starting from scratch + +Our [basic example](examples/basic/basic-os.md) showcases an OS that boots a minimal kernel using `bootloader`. + +### Using an existing kernel -To make your kernel compatible with `bootloader`: +To combine your kernel with `bootloader` and create a bootable disk image, follow these steps: + +#### Make your kernel compatible with `bootloader` - Add a dependency on the `bootloader_api` crate in your kernel's `Cargo.toml`. - Your kernel binary should be `#![no_std]` and `#![no_main]`. @@ -35,34 +43,55 @@ To make your kernel compatible with `bootloader`: }; bootloader_api::entry_point!(kernel_main, config = &CONFIG); ``` -- Compile your kernel to an ELF executable by running **`cargo build --target x86_64-unknown-none`**. You might need to run `rustup target add x86_64-unknown-none` before to download precompiled versions of the `core` and `alloc` crates. +- Compile your kernel to an ELF executable by running **`cargo build --target x86_64-unknown-none`**. You might need to run `rustup target add x86_64-unknown-none` before to download precompiled versions of the `core` and `alloc` crates. You can add `x86_64-unknown-none` as default target and add it to your toolchain so that `cargo build` takes care of this. + ```toml + # .cargo/config.toml + [build] + target = "x86_64-unknown-none" + ``` + ```sh + $ cargo build + ``` - Thanks to the `entry_point` macro, the compiled executable contains a special section with metadata and the serialized config, which will enable the `bootloader` crate to load it. -### Booting - -To combine your kernel with a bootloader and create a bootable disk image, follow these steps: +#### Creating a bootable image - Move your full kernel code into a `kernel` subdirectory. -- Create a new `os` crate at the top level that defines a [workspace](https://doc.rust-lang.org/cargo/reference/workspaces.html). -- Add a `build-dependencies` on the `bootloader` crate. -- Create a [`build.rs`](https://doc.rust-lang.org/cargo/reference/build-scripts.html) build script. -- Set up an [artifact dependency](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#artifact-dependencies) to add your `kernel` crate as a `build-dependency`: - ```toml - # in Cargo.toml - [build-dependencies] - kernel = { path = "kernel", artifact = "bin", target = "x86_64-unknown-none" } - ``` - ```toml - # .cargo/config.toml - - [unstable] - # enable the unstable artifact-dependencies feature, see - # https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#artifact-dependencies - bindeps = true - ``` - Alternatively, you can use [`std::process::Command`](https://doc.rust-lang.org/stable/std/process/struct.Command.html) to invoke the build command of your kernel in the `build.rs` script. -- Obtain the path to the kernel executable. When using an artifact dependency, you can retrieve this path using `std::env::var_os("CARGO_BIN_FILE_MY_KERNEL_my-kernel")` -- Use `bootloader::UefiBoot` and/or `bootloader::BiosBoot` to create a bootable disk image with your kernel. +- Create a new `os` crate at the top level + ```sh + $ cargo init --bin + ``` +- Define a [workspace](https://doc.rust-lang.org/cargo/reference/workspaces.html) and add your kernel as a workspace member. + ```toml + # in Cargo.toml + [workspace] + resolver = "3" + members = ["kernel"] + ``` +- Enable the workspace to build your kernel: + - Set up an [artifact dependency](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#artifact-dependencies) to add your `kernel` crate as a `build-dependency`: + ```toml + # in Cargo.toml + [build-dependencies] + kernel = { path = "kernel", artifact = "bin", target = "x86_64-unknown-none" } + ``` + Enable the unstable artifact-dependencies feature: + ```toml + # .cargo/config.toml + [unstable] + bindeps = true + ``` + Experimental features are only available on the nightly channel: + ```toml + # rust-toolchain.toml + [toolchain] + channel = "nightly" + targets = ["x86_64-unknown-none"] + ``` + - Alternatively, you can use [`std::process::Command`](https://doc.rust-lang.org/stable/std/process/struct.Command.html) to invoke the build command of your kernel in the `build.rs` script. +- Create a [`build.rs`](https://doc.rust-lang.org/cargo/reference/build-scripts.html) build script in the `os` crate. See our [disk image creation template](docs/create-disk-image.md) for a more detailed example. + - Obtain the path to the kernel executable. When using an artifact dependency, you can retrieve this path using `std::env::var_os("CARGO_BIN_FILE_MY_KERNEL_my-kernel")` + - Use `bootloader::UefiBoot` and/or `bootloader::BiosBoot` to create a bootable disk image with your kernel. - Do something with the bootable disk images in your `main.rs` function. For example, run them with QEMU. See our [disk image creation template](docs/create-disk-image.md) for a more detailed example. diff --git a/docs/create-disk-image.md b/docs/create-disk-image.md index f4da7e5a..fc6ba6d1 100644 --- a/docs/create-disk-image.md +++ b/docs/create-disk-image.md @@ -5,83 +5,18 @@ The [`bootloader`](https://docs.rs/bootloader/0.11) crate provides simple functi A good way to implement this is to move your kernel into a `kernel` subdirectory. Then you can create a new `os` crate at the top level that defines a [workspace](https://doc.rust-lang.org/cargo/reference/workspaces.html). The root package has build-dependencies on the `kernel` [artifact](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#artifact-dependencies) and on the bootloader crate. This allows you to create the bootable disk image in a [cargo build script](https://doc.rust-lang.org/cargo/reference/build-scripts.html) and launch the created image in QEMU in the `main` function. -The files could look like this: - -```toml -# .cargo/config.toml - -[unstable] -# enable the unstable artifact-dependencies feature, see -# https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#artifact-dependencies -bindeps = true -``` - -```toml -# Cargo.toml - -[package] -name = "os" # or any other name -version = "0.1.0" - -[build-dependencies] -bootloader = "0.11" -test-kernel = { path = "kernel", artifact = "bin", target = "x86_64-unknown-none" } - -[dependencies] -# used for UEFI booting in QEMU -ovmf-prebuilt = "0.1.0-alpha.1" - -[workspace] -members = ["kernel"] -``` - -```rust -// build.rs - -use std::path::PathBuf; - -fn main() { - // set by cargo, build scripts should use this directory for output files - let out_dir = PathBuf::from(std::env::var_os("OUT_DIR").unwrap()); - // set by cargo's artifact dependency feature, see - // https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#artifact-dependencies - let kernel = PathBuf::from(std::env::var_os("CARGO_BIN_FILE_KERNEL_kernel").unwrap()); - - // create an UEFI disk image (optional) - let uefi_path = out_dir.join("uefi.img"); - bootloader::UefiBoot::new(&kernel).create_disk_image(&uefi_path).unwrap(); - - // create a BIOS disk image - let bios_path = out_dir.join("bios.img"); - bootloader::BiosBoot::new(&kernel).create_disk_image(&bios_path).unwrap(); - - // pass the disk image paths as env variables to the `main.rs` - println!("cargo:rustc-env=UEFI_PATH={}", uefi_path.display()); - println!("cargo:rustc-env=BIOS_PATH={}", bios_path.display()); -} -``` - -```rust -// src/main.rs - -fn main() { - // read env variables that were set in build script - let uefi_path = env!("UEFI_PATH"); - let bios_path = env!("BIOS_PATH"); - - // choose whether to start the UEFI or BIOS image - let uefi = true; - - let mut cmd = std::process::Command::new("qemu-system-x86_64"); - if uefi { - cmd.arg("-bios").arg(ovmf_prebuilt::ovmf_pure_efi()); - cmd.arg("-drive").arg(format!("format=raw,file={uefi_path}")); - } else { - cmd.arg("-drive").arg(format!("format=raw,file={bios_path}")); - } - let mut child = cmd.spawn().unwrap(); - child.wait().unwrap(); -} -``` - -Now you should be able to use `cargo build` to create a bootable disk image and `cargo run` to run in QEMU. Your kernel is automatically recompiled when it changes. For more advanced usage, you can add command-line arguments to your `main.rs` to e.g. pass additional arguments to QEMU or to copy the disk images to some path to make it easier to find them (e.g. for copying them to an thumb drive). +Our [basic example](examples/basic/basic-os.md) showcases this setup: +- [Cargo.toml](/examples/basic/Cargo.toml) + - create a workspace & add kernel as member + - add kernel as build-dependency + - add ovmf-prebuilt for UEFI booting in QEMU +- [.cargo/config.toml](/examples/basic/Cargo.toml) + - enable the unstable artifact-dependencies feature +- [rust-toolchain.toml](/examples/basic/Cargo.toml) + - change the default toolchain to nightly to use experimental features +- [build.rs](/examples/basic/build.rs) + - create bios and uefi disk image +- [src/main.rs](/examples/basic/src/main.rs]) + - launch the image using QEMU + +Now you should be able to use `cargo build` to create a bootable disk image and `cargo run bios` and `cargo run uefi` to run it in QEMU. Your kernel is automatically recompiled when it changes. For more advanced usage, you can add command-line arguments to your `main.rs` to e.g. pass additional arguments to QEMU or to copy the disk images to some path to make it easier to find them (e.g. for copying them to an thumb drive). diff --git a/examples/basic/.cargo/config.toml b/examples/basic/.cargo/config.toml new file mode 100644 index 00000000..dfa84e85 --- /dev/null +++ b/examples/basic/.cargo/config.toml @@ -0,0 +1,2 @@ +[unstable] +bindeps = true diff --git a/examples/basic/.gitignore b/examples/basic/.gitignore new file mode 100644 index 00000000..eccd7b4a --- /dev/null +++ b/examples/basic/.gitignore @@ -0,0 +1,2 @@ +/target/ +**/*.rs.bk diff --git a/examples/basic/Cargo.lock b/examples/basic/Cargo.lock new file mode 100644 index 00000000..efe2f2d2 --- /dev/null +++ b/examples/basic/Cargo.lock @@ -0,0 +1,1095 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "basic" +version = "0.1.0" +dependencies = [ + "bootloader", + "kernel", + "ovmf-prebuilt", +] + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bit_field" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bootloader" +version = "0.11.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e418d2f8952e4a6d935d23ea038daed2fe7707b0118923f91e83bf1fbe64b3" +dependencies = [ + "anyhow", + "bootloader-boot-config", + "fatfs", + "gpt", + "llvm-tools", + "mbrman", + "serde_json", + "tempfile", +] + +[[package]] +name = "bootloader-boot-config" +version = "0.11.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cfbe7f4a5d9843a9a310712e64691f3c474546f02bed7a53ed81775a681d18e" +dependencies = [ + "serde", +] + +[[package]] +name = "bootloader_api" +version = "0.11.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba1a4adcd36a49a08c4fb8c13c132fb1ea01a59681b305b46625095318328455" + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + +[[package]] +name = "cc" +version = "1.2.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37521ac7aabe3d13122dc382493e20c9416f299d2ccd5b3a5340a2570cdeb0f3" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fatfs" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05669f8e7e2d7badc545c513710f0eba09c2fbef683eb859fd79c46c355048e0" +dependencies = [ + "bitflags 1.3.2", + "byteorder", + "log", +] + +[[package]] +name = "filetime" +version = "0.2.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed" +dependencies = [ + "cfg-if", + "libc", + "libredox", + "windows-sys 0.60.2", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" + +[[package]] +name = "flate2" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "generic-array" +version = "0.14.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "gpt" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8283e7331b8c93b9756e0cfdbcfb90312852f953c6faf9bf741e684cc3b6ad69" +dependencies = [ + "bitflags 2.10.0", + "crc", + "log", + "uuid", +] + +[[package]] +name = "http" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "js-sys" +version = "0.3.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "kernel" +version = "0.1.0" +dependencies = [ + "bootloader_api", + "uart_16550", + "x86_64", +] + +[[package]] +name = "libc" +version = "0.2.177" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" + +[[package]] +name = "libredox" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" +dependencies = [ + "bitflags 2.10.0", + "libc", + "redox_syscall", +] + +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "llvm-tools" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955be5d0ca0465caf127165acb47964f911e2bc26073e865deb8be7189302faf" + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "lzma-rs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "297e814c836ae64db86b36cf2a557ba54368d03f6afcd7d947c266692f71115e" +dependencies = [ + "byteorder", + "crc", +] + +[[package]] +name = "mbrman" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1fc3bff63c208d4a14301c6cb807af2d1a0760052584ce3f9a737b55fb85498" +dependencies = [ + "bincode", + "bitvec", + "serde", + "serde-big-array", + "thiserror", +] + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "ovmf-prebuilt" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4962ad113b529120175fc669c075fa27762f91296940a94adce269b49f6fcc3b" +dependencies = [ + "log", + "lzma-rs", + "sha2", + "tar", + "ureq", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "proc-macro2" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "raw-cpuid" +version = "10.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.10.0", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.16", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustix" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +dependencies = [ + "bitflags 2.10.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls" +version = "0.23.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a9586e9ee2b4f8fab52a0048ca7334d7024eef48e2cb9407e3497bb7cab7fa7" +dependencies = [ + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94182ad936a0c91c324cd46c6511b9510ed16af436d7b5bab34beab0afd55f7a" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde-big-array" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11fc7cc2c76d73e0f27ee52abbd64eec84d46f370c88371120433196934e4b7f" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tar" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a" +dependencies = [ + "filetime", + "libc", + "xattr", +] + +[[package]] +name = "tempfile" +version = "3.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +dependencies = [ + "fastrand", + "getrandom 0.3.4", + "once_cell", + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + +[[package]] +name = "uart_16550" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94d293f51425981fdb1b766beae254dbb711a17e8c4b549dc69b9b7ee0d478d5" +dependencies = [ + "bitflags 2.10.0", + "rustversion", + "x86", +] + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "ureq" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99ba1025f18a4a3fc3e9b48c868e9beb4f24f4b4b1a325bada26bd4119f46537" +dependencies = [ + "base64", + "flate2", + "log", + "percent-encoding", + "rustls", + "rustls-pemfile", + "rustls-pki-types", + "ureq-proto", + "utf-8", + "webpki-roots", +] + +[[package]] +name = "ureq-proto" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b4531c118335662134346048ddb0e54cc86bd7e81866757873055f0e38f5d2" +dependencies = [ + "base64", + "http", + "httparse", + "log", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "uuid" +version = "1.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" +dependencies = [ + "getrandom 0.3.4", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "volatile" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "442887c63f2c839b346c192d047a7c87e73d0689c9157b00b53dcc27dd5ea793" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "webpki-roots" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b130c0d2d49f8b6889abc456e795e82525204f27c42cf767cf0d7734e089b8" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "x86" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2781db97787217ad2a2845c396a5efe286f87467a5810836db6d74926e94a385" +dependencies = [ + "bit_field", + "bitflags 1.3.2", + "raw-cpuid", +] + +[[package]] +name = "x86_64" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f042214de98141e9c8706e8192b73f56494087cc55ebec28ce10f26c5c364ae" +dependencies = [ + "bit_field", + "bitflags 2.10.0", + "rustversion", + "volatile", +] + +[[package]] +name = "xattr" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" +dependencies = [ + "libc", + "rustix", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" diff --git a/examples/basic/Cargo.toml b/examples/basic/Cargo.toml new file mode 100644 index 00000000..1bcde379 --- /dev/null +++ b/examples/basic/Cargo.toml @@ -0,0 +1,15 @@ +[workspace] +resolver = "3" +members = ["kernel"] + +[package] +name = "basic" +version = "0.1.0" +edition = "2024" + +[dependencies] +ovmf-prebuilt = "0.2.4" + +[build-dependencies] +kernel = { path = "kernel", artifact = "bin", target = "x86_64-unknown-none" } +bootloader = "0.11.12" diff --git a/examples/basic/basic-os.md b/examples/basic/basic-os.md new file mode 100644 index 00000000..c4a83ef0 --- /dev/null +++ b/examples/basic/basic-os.md @@ -0,0 +1,56 @@ +# basic-os + +A minimal os to showcase the usage of bootloader. + +## Overview + +The top level `basic` crate defines a [workspace](https://doc.rust-lang.org/cargo/reference/workspaces.html). +- The `kernel` crate is a member of that workspace + ```toml + # in Cargo.toml + [workspace] + members = ["kernel"] + ``` +- An [artifact dependency](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#artifact-dependencies) is used add the `kernel` crate as a `build-dependency`: + ```toml + # in Cargo.toml + [build-dependencies] + kernel = { path = "kernel", artifact = "bin", target = "x86_64-unknown-none" } + ``` + Enable the unstable artifact-dependencies feature: + ```toml + # .cargo/config.toml + [unstable] + bindeps = true + ``` + Experimental features are only available on the nightly channel: + ```toml + # rust-toolchain.toml + [toolchain] + channel = "nightly" + targets = ["x86_64-unknown-none"] + ``` + +The `basic` create combines the kernel with `bootloader`, creates a bootable disk image and launches them. +- A [cargo build script](https://doc.rust-lang.org/cargo/reference/build-scripts.html) is used to create a bootable disk image ([`build.rs`](build.rs)). +- `basic` launches the images in QEMU. + +See also [basic-kernel.md](kernel/basic-kernel.md) in the `kernel` subdirectory. + +## Usage + +Install dependencies: +```sh +$ sudo apt update && sudo apt install qemu-system-x86 +``` +Build: +```sh +$ cargo build +``` +Run: +```sh +$ cargo run -- bios +``` +```sh +$ cargo run -- uefi +``` diff --git a/examples/basic/build.rs b/examples/basic/build.rs new file mode 100644 index 00000000..37200d34 --- /dev/null +++ b/examples/basic/build.rs @@ -0,0 +1,25 @@ +use std::path::PathBuf; + +fn main() { + // set by cargo, build scripts should use this directory for output files + let out_dir = PathBuf::from(std::env::var_os("OUT_DIR").unwrap()); + // set by cargo's artifact dependency feature, see + // https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#artifact-dependencies + let kernel = PathBuf::from(std::env::var_os("CARGO_BIN_FILE_KERNEL_kernel").unwrap()); + + // create an UEFI disk image (optional) + let uefi_path = out_dir.join("uefi.img"); + bootloader::UefiBoot::new(&kernel) + .create_disk_image(&uefi_path) + .unwrap(); + + // create a BIOS disk image + let bios_path = out_dir.join("bios.img"); + bootloader::BiosBoot::new(&kernel) + .create_disk_image(&bios_path) + .unwrap(); + + // pass the disk image paths as env variables to the + println!("cargo:rustc-env=UEFI_PATH={}", uefi_path.display()); + println!("cargo:rustc-env=BIOS_PATH={}", bios_path.display()); +} diff --git a/examples/basic/kernel/.gitignore b/examples/basic/kernel/.gitignore new file mode 100644 index 00000000..eccd7b4a --- /dev/null +++ b/examples/basic/kernel/.gitignore @@ -0,0 +1,2 @@ +/target/ +**/*.rs.bk diff --git a/examples/basic/kernel/Cargo.toml b/examples/basic/kernel/Cargo.toml new file mode 100644 index 00000000..5672bb7a --- /dev/null +++ b/examples/basic/kernel/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "kernel" +version = "0.1.0" +edition = "2024" + +[dependencies] +bootloader_api = "0.11.12" +uart_16550 = "0.4.0" +x86_64 = "0.15.2" diff --git a/examples/basic/kernel/basic-kernel.md b/examples/basic/kernel/basic-kernel.md new file mode 100644 index 00000000..5a003ccc --- /dev/null +++ b/examples/basic/kernel/basic-kernel.md @@ -0,0 +1,9 @@ +# basic-kernel + +A minimal kernel to showcase the usage of bootloader. + +The kernel: +- Initalizes a serial port on [COM1](https://wiki.osdev.org/Serial_Ports#Port_Addresses) +- Dumps the [`boot_info`](/api/src/info.rs) it received from `bootloader` +- Prints a message +- Exits QEMU with a custom exit code via the `isa-debug-exit` device diff --git a/examples/basic/kernel/src/main.rs b/examples/basic/kernel/src/main.rs new file mode 100644 index 00000000..df1eb848 --- /dev/null +++ b/examples/basic/kernel/src/main.rs @@ -0,0 +1,48 @@ +#![no_std] // don't link the Rust standard library +#![no_main] // disable all Rust-level entry points + +use bootloader_api::{BootInfo, entry_point}; +use core::fmt::Write; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(u32)] +pub enum QemuExitCode { + Success = 0x10, + Failed = 0x11, +} + +pub fn exit_qemu(exit_code: QemuExitCode) -> ! { + use x86_64::instructions::{nop, port::Port}; + + unsafe { + let mut port = Port::new(0xf4); + port.write(exit_code as u32); + } + + loop { + nop(); + } +} + +pub fn serial() -> uart_16550::SerialPort { + let mut port = unsafe { uart_16550::SerialPort::new(0x3F8) }; + port.init(); + port +} + +entry_point!(kernel_main); + +fn kernel_main(boot_info: &'static mut BootInfo) -> ! { + let mut port = serial(); + writeln!(port, "Entered kernel with boot info: {boot_info:?}").unwrap(); + writeln!(port, "\n=(^.^)= meow\n").unwrap(); + exit_qemu(QemuExitCode::Success); +} + +/// This function is called on panic. +#[panic_handler] +#[cfg(not(test))] +fn panic(info: &core::panic::PanicInfo) -> ! { + let _ = writeln!(serial(), "PANIC: {info}"); + exit_qemu(QemuExitCode::Failed); +} diff --git a/examples/basic/rust-toolchain.toml b/examples/basic/rust-toolchain.toml new file mode 100644 index 00000000..a306d5fe --- /dev/null +++ b/examples/basic/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "nightly" +components = ["rustfmt", "clippy"] +targets = ["x86_64-unknown-none"] diff --git a/examples/basic/src/main.rs b/examples/basic/src/main.rs new file mode 100644 index 00000000..4ef3713d --- /dev/null +++ b/examples/basic/src/main.rs @@ -0,0 +1,69 @@ +use ovmf_prebuilt::{Arch, FileType, Prebuilt, Source}; +use std::env; +use std::process::{Command, exit}; + +fn main() { + // read env variables that were set in build script + let uefi_path = env!("UEFI_PATH"); + let bios_path = env!("BIOS_PATH"); + + // parse mode from CLI + let args: Vec = env::args().collect(); + let prog = &args[0]; + + // choose whether to start the UEFI or BIOS image + let uefi = match args.get(1).map(|s| s.to_lowercase()) { + Some(ref s) if s == "uefi" => true, + Some(ref s) if s == "bios" => false, + Some(ref s) if s == "-h" || s == "--help" => { + println!("Usage: {prog} [uefi|bios]"); + println!(" uefi - boot using OVMF (UEFI)"); + println!(" bios - boot using legacy BIOS"); + exit(0); + } + _ => { + eprintln!("Usage: {prog} [uefi|bios]"); + exit(1); + } + }; + + let mut cmd = Command::new("qemu-system-x86_64"); + // print serial output to the shell + cmd.arg("-serial").arg("mon:stdio"); + // don't display video output + cmd.arg("-display").arg("none"); + // enable the guest to exit qemu + cmd.arg("-device") + .arg("isa-debug-exit,iobase=0xf4,iosize=0x04"); + + if uefi { + let prebuilt = + Prebuilt::fetch(Source::LATEST, "target/ovmf").expect("failed to update prebuilt"); + + let code = prebuilt.get_file(Arch::X64, FileType::Code); + let vars = prebuilt.get_file(Arch::X64, FileType::Vars); + + cmd.arg("-drive") + .arg(format!("format=raw,file={uefi_path}")); + cmd.arg("-drive").arg(format!( + "if=pflash,format=raw,unit=0,file={},readonly=on", + code.display() + )); + // copy vars and enable rw instead of snapshot if you want to store data (e.g. enroll secure boot keys) + cmd.arg("-drive").arg(format!( + "if=pflash,format=raw,unit=1,file={},snapshot=on", + vars.display() + )); + } else { + cmd.arg("-drive") + .arg(format!("format=raw,file={bios_path}")); + } + + let mut child = cmd.spawn().expect("failed to start qemu-system-x86_64"); + let status = child.wait().expect("failed to wait on qemu"); + match status.code().unwrap_or(1) { + 0x10 => 0, // success + 0x11 => 1, // failure + _ => 2, // unknown fault + }; +}