bootimage

repository·master·Indexed 21 days ago

https://github.com/rust-osdev/bootimage

A cargo subcommand and library (version 0.10.4) used to create bootable disk images from Rust-based operating system kernels. It automates the process of building a kernel and combining it with a bootloader, providing a CLI for image creation and a runner for executing kernels in QEMU. The tool requires the bootloader crate as a dependency and utilizes llvm-objcopy for binary conversion.

Tokens
6K
Snippets
21
Records
34
Agent score
74%

What's inside bootimage

  1. Run your kernel in QEMU via bootimage runner

    master

    You can automate running your kernel in QEMU by setting bootimage runner as a custom runner in your .cargo/config file.

    Once configured, you can run your kernel using cargo xrun (or your preferred cargo runner command), passing QEMU arguments after a -- separator.

    # .cargo/config
    [target.'cfg(target_os = "none")']
    runner = "bootimage runner"
    cargo xrun --target your_custom_target.json [other_args] -- [qemu args]
  2. Configure bootloader dependency

    master

    To use bootimage, you must add the bootloader crate as a dependency in your Cargo.toml.

    Version Requirements:

    • For bootimage 0.7.0 and later: Use bootloader version 0.5.1 or higher.
    • For bootimage 0.6.6 and earlier: Use earlier bootloader versions.

    If you use a custom bootloader name, you can use Cargo's dependency renaming functionality.

    # in your Cargo.toml
    
    [dependencies]
    bootloader = "0.9.8"
  3. Use bootimage runner as a Cargo target runner

    master

    You can automate the process of building and running your kernel by setting bootimage runner as the target runner in your .cargo/config file. This is typically done for bare-metal targets (e.g., target_os = "none"). When configured this way, running cargo test or cargo run will automatically invoke the bootimage runner to create a disk image and launch it in QEMU.

    [target.'cfg(target_os = "none")']
    runner = "bootimage runner"
  4. Build a bootable disk image

    master

    Build your kernel project and create a bootable disk image using the cargo bootimage command. This command invokes cargo build (forwarding all passed options) and then builds the specified bootloader together with your kernel.

    cargo bootimage --target your_custom_target.json [other_args]
  5. Configure bootimage runner behavior in Cargo.toml

    master

    The behavior of the bootimage runner subcommand can be customized by adding a [package.metadata.bootimage] table to your Cargo.toml. This allows you to define which emulator to use, pass specific arguments to the runner, and configure how test executables are handled (success codes and timeouts).

    [package.metadata.bootimage]
    # The command invoked with the created bootimage (the "{}" will be replaced with the path to the bootable disk image)
    run-command = ["qemu-system-x86_64", "-drive", "format=raw,file={}"]
    # Additional arguments passed to the run command for non-test executables
    run-args = []
    # Additional arguments passed to the run command for test executables
    test-args = []
    # An exit code that should be considered as success for test executables
    test-success-exit-code = {integer}
    # The timeout for running a test (in seconds)
    test-timeout = 300
  6. Configure cargo-bootimage in Cargo.toml

    master

    You can customize the behavior of cargo bootimage by adding a [package.metadata.bootimage] table to your Cargo.toml file.

    Currently, you can specify the cargo subcommand used to build the kernel using the build-command key. For example, if you are using cargo-xbuild instead of standard cargo, you should set this to ["xbuild"].

    [package.metadata.bootimage]
    # The cargo subcommand that will be used for building the kernel.
    # For building using the `cargo-xbuild` crate, set this to `xbuild`.
    build-command = ["build"]
  7. Configure bootimage via Cargo.toml

    master

    You can customize the behavior of bootimage by adding a [package.metadata.bootimage] table to your Cargo.toml. This allows you to define the build command, the runner command (e.g., QEMU), and specific arguments for running or testing executables.

    [package.metadata.bootimage]
    # The cargo subcommand that will be used for building the kernel.
    # For building using the `cargo-xbuild` crate, set this to `xbuild`.
    build-command = ["build"]
    
    # The command invoked with the created bootimage (the "{}" will be replaced
    # with the path to the bootable disk image)
    # Applies to `bootimage run` and `bootimage runner`
    run-command = ["qemu-system-x86_64", "-drive", "format=raw,file={}"]
    
    # Additional arguments passed to the run command for non-test executables
    # Applies to `bootimage run` and `bootimage runner`
    run-args = []
    
    # Additional arguments passed to the run command for test executables
    # Applies to `bootimage runner`
    test-args = []
    
    # An exit code that should be considered as success for test executables
    # test-success-exit-code = {integer}
    
    # The timeout for running a test through `bootimage test` or `bootimage runner` (in seconds)
    test-timeout = 300
    
    # Whether the `-no-reboot` flag should be passed to test executables
    test-no-reboot = true
  8. Use the cargo-bootimage CLI

    master

    The cargo-bootimage tool is designed to be invoked as a Cargo subcommand. You should run it using the following command structure:

    cargo bootimage

    Note that the tool expects to be called via Cargo; direct execution of the cargo-bootimage binary without the bootimage subcommand argument will result in an error.

    cargo bootimage
  9. Use the Builder API to create bootable images

    master

    The Builder struct is the primary entry point for programmatically building a kernel and combining it with a bootloader to create a bootable disk image.

    Workflow:

    1. Initialize: Create a new Builder using Builder::new(). It will attempt to find your Cargo.toml via the CARGO_MANIFEST_DIR environment variable or by searching the filesystem.
    2. Build Kernel: Use build_kernel() to execute the cargo build command for your kernel. This returns a list of paths to the resulting executable binaries.
    3. Create Bootimage: Use create_bootimage() to build the bootloader and combine it with your kernel binary into a final disk image at the specified output path.
    use bootimage::builder::Builder;
    use bootimage::config::Config;
    use std::path::PathBuf;
    
    fn main() -> Result<(), Box<dyn std::error::Error>> {
        // 1. Initialize the builder
        let mut builder = Builder::new(Some(PathBuf::from("./Cargo.toml")))?;
    
        // 2. Define configuration (Config is provided by the crate)
        let config = Config::default(); 
        let args = vec!["build".to_string()];
    
        // 3. Build the kernel
        let kernel_bins = builder.build_kernel(&args, &config, false)?;
        let kernel_bin = &kernel_bins[0];
    
        // 4. Create the bootable disk image
        builder.create_bootimage(
            builder.manifest_path(), // kernel manifest path
            kernel_bin,               // path to built kernel binary
            &PathBuf::from("bootable.bin"), // output path
            false                     // quiet mode
        )?;
    
        Ok(())
    }
  10. Configure the bootloader via Cargo.toml metadata

    master

    The bootimage builder expects specific metadata in the bootloader crate's Cargo.toml to correctly identify the target and build configuration. If you are using a custom bootloader or a specific version of the official bootloader crate, ensure the following keys are present in the [package.metadata] section:

    • bootloader.target: A string specifying the target JSON file or path used for building the bootloader.
    • bootloader.build-std: (Optional) A string specifying the component to be passed to -Zbuild-std= (e.g., core,alloc).

    Note: If you are using the official bootloader crate, you must use at least version 0.5.1 to support this metadata format.