• Stars
    star
    1,368
  • Rank 34,373 (Top 0.7 %)
  • Language
    Rust
  • License
    Apache License 2.0
  • Created almost 7 years ago
  • Updated about 1 month ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

An experimental pure-Rust x86 bootloader

bootloader

Docs Build Status Join the chat at https://gitter.im/rust-osdev/bootloader

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

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 bootloader crate, follow our migration guides.

Kernel

To 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].
  • Define an entry point function with the signature fn kernel_main(boot_info: &'static mut bootloader_api::BootInfo) -> !. The function name can be arbitrary.
    • The boot_info argument provides information about available memory, the framebuffer, and more. See the API docs for bootloader_api crate for details.
  • Use the entry_point macro to register the entry point function: bootloader_api::entry_point!(kernel_main);
    • The macro checks the signature of your entry point function and generates a _start entry 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 bootloader_api::BootloaderConfig to the entry_point macro. For example, you can require a specific stack size for your kernel:
      const CONFIG: bootloader_api::BootloaderConfig = {
          let mut config = bootloader_api::BootloaderConfig::new_default();
          config.kernel_stack_size = 100 * 1024; // 100 KiB
          config
      };
      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.
  • 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:

  • Move your full kernel code into a kernel subdirectory.
  • Create a new os crate at the top level that defines a workspace.
  • Add a build-dependencies on the bootloader crate.
  • Create a build.rs build script.
  • Set up an artifact dependency to add your kernel crate as a build-dependency:
    # in Cargo.toml
    [build-dependencies]
    kernel = { path = "kernel", artifact = "bin", target = "x86_64-unknown-none" }
    # .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 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.
  • Do something with the bootable disk images in your main.rs function. 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 bootloader_api library with the entry point, configuration, and boot info definitions.
    • Kernels should include this library as a normal cargo dependency.
    • The provided entry_point macro 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_point macro of the bootloader_api library.
  • A bootloader library 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.

License

Licensed under either of

at your option.

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 dual licensed as above, without any additional terms or conditions.

More Repositories

1

uefi-rs

Rusty wrapper for the Unified Extensible Firmware Interface (UEFI). This crate makes it easy to develop Rust software that leverages safe, convenient, and performant abstractions for UEFI functionality.
Rust
1,297
star
2

x86_64

Library to program x86_64 hardware.
Rust
787
star
3

bootimage

Tool to create bootable disk images from a Rust OS kernel.
Rust
752
star
4

linked-list-allocator

Rust
220
star
5

acpi

Rust library for parsing ACPI tables and interpreting AML
Rust
200
star
6

.github

About this organization
133
star
7

homepage

CSS
119
star
8

multiboot2

Rusty wrappers for Multiboot2.
Rust
110
star
9

volatile

Rust
70
star
10

vga

Library to program vga hardware.
Rust
55
star
11

xhci

A Rust library which is useful to handle xHCI
Rust
41
star
12

spinning_top

A simple spinlock crate based on the abstractions provided by the `lock_api` crate.
Rust
36
star
13

uart_16550

Minimal support for uart_16550 serial output.
Rust
33
star
14

pci_types

Useful types for dealing with PCI
Rust
31
star
15

ovmf-prebuilt

Rust
24
star
16

apic

Rust
15
star
17

ansi_rgb

Colorful terminal text using ANSI escape sequences
Rust
14
star
18

virtio-spec-rs

Definitions from the Virtual I/O Device (VIRTIO) specification.
Rust
12
star
19

endian-num

Byte-order-aware numeric types.
Rust
11
star
20

pic8259

Rust
10
star
21

x86_64_types

Rust
7
star
22

ps2-mouse

Library to manage a PS2 mouse
Rust
7
star
23

ucs2-rs

UCS-2 conversion utilities for Rust.
Rust
6
star
24

usb

Utilities for working with USB devices
Rust
6
star
25

os_bootinfo

Rust
6
star
26

ieee1275-rs

Rudimentary ieee1275/OpenFirmware Rust environment similar to uefi-rs.
Rust
4
star
27

fuse-abi

FUSE device bindings.
Rust
3
star