Springboard
VERSION: 3.0.1/EARLY/UNRELEASED
LICENSE: Apache-2.0
README: Where would you rather be?
INFO:
The upstream bootloader, and lib(s) source tree can be found here.
An experimental x86_64 bootloader that works on both BIOS and UEFI systems. Written in Rust and some inline assembly, buildable on all platforms without additional build-time dependencies (just some rustup components).
Trident is an operating system originally developed as part of a series on Medium and MBP2 before being co-opted into a personal research project.
The springboard bootloader project is a fork of rust-osdev/bootloader
fine-tuned to the needs of the Trident 3 project.
As of 2023.11, you will need:
- The Rust nightly as of 2023.11.12, which you may obtain through the official website: https://rust-lang.org/learn/get-started
- Docker to run the build environment: https://www.docker.com/get-started/
Extensions
You will eventually be able to develop your own extensions to Trident 3 through a proposed Extensions API.
Contributing
If you'd like to contribute to this project, please fork it and submit pull requests with your desired features.
- Fork it.
- ????? (I forgot what went here)
- Submit pull request with your feature. ("[FEATURE] describe your feature").
- Profit?
Useful Links
Requirements
You need a nightly Rust compiler with the llvm-tools-preview component, which can be installed through rustup component add llvm-tools-preview.
Usage
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.
If you're already using an older version of the springboard crate or the rust-osdev/bootloader crate, follow our migration guides.
Kernel
To make your kernel compatible with springboard:
- Add a dependency on the
springboard_apicrate in your kernel'sCargo.toml. - Your kernel binary should be
#![no_std]and#![no_main]. - Define an entry point function with the signature
fn kernel_main(boot_info: &'static mut springboard_api::BootInfo) -> !. The function name can be arbitrary.- The
boot_infoargument provides information about available memory, the framebuffer, and more. See the API docs forspringboard_apicrate for details.
- The
- Use the
entry_pointmacro to register the entry point function:springboard_api::entry_point!(kernel_main);- The macro checks the signature of your entry point function and generates a
_startentry point symbol for it. (If you use a linker script, make sure that you don't change the entry point name to something else.) - To use non-standard configuration, you can pass a second argument of type
&'static springboard_api::BootloaderConfigto theentry_pointmacro. For example, you can require a specific stack size for your kernel:const CONFIG: BootloaderConfig = ; entry_point!;
- The macro checks the signature of your entry point function and generates a
- Compile your kernel to an ELF executable by running
cargo build --target x86_64-unknown-none. You might need to runrustup target add x86_64-unknown-nonebefore to download precompiled versions of thecoreandalloccrates. - Thanks to the
entry_pointmacro, the compiled executable contains a special section with metadata and the serialized config, which will enable thespringboardcrate to load it.
Booting
To combine your kernel with a bootloader and create a bootable disk image, follow these steps:
- Move your full kernel code into a
kernelsubdirectory. - Create a new
oscrate at the top level that defines a workspace. - Add a
build-dependencieson thebootloadercrate. - Create a
build.rsbuild script. - Set up an artifact dependency to add your
kernelcrate as abuild-dependency:# in Cargo.toml [] = { = "kernel", = "bin", = "x86_64-unknown-none" }
Alternatively, you can use# .cargo/config.toml [] # enable the unstable artifact-dependencies feature, see # https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#artifact-dependencies = truestd::process::Commandto invoke the build command of your kernel in thebuild.rsscript. - 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
springboard::UefiBootand/orspringboard::BiosBootto create a bootable disk image with your kernel. - Do something with the bootable disk images in your
main.rsfunction. For example, run them with QEMU.
See our disk image creation template for a more detailed example.
Architecture
This project is split into three separate entities:
- A
springboard_apilibrary with the entry point, configuration, and boot info definitions.- Kernels should include this library as a normal cargo dependency.
- The provided
entry_pointmacro will encode the configuration settings into a separate ELF section of the compiled kernel executable.
- BIOS and UEFI binaries that contain the actual bootloader implementation.
- The implementations share a higher-level common library.
- Both implementations load the kernel at runtime from a FAT partition. This FAT partition is created
- The configuration is read from a special section of the kernel's ELF file, which is created by the
entry_pointmacro of thebootloader_apilibrary.
- A
springboardlibrary to create bootable disk images that run a given kernel. This library is the top-level crate in this project.- The library builds the BIOS and UEFI implementations in the
build.rs. - It provides functions to create FAT-formatted bootable disk images, based on the compiled BIOS and UEFI bootloaders.
- The library builds the BIOS and UEFI implementations in the
License
Licensed under Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0).
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be licensed as above, without any additional terms or conditions.