This guide summarizes the steps for migrating from bootloader v0.9.X to bootloader v0.11. Note that some bigger changes are required to support UEFI booting (to support the framebuffer and APIC).
- Replace the
bootloaderdependency of your kernel with a dependency on thebootloader_apicrate:-bootloader = { version = "0.9.23", features = [...]} +bootloader_api = "0.11"
- In your
main.rs, adjust the import path and change the signature of the entry point function:-use bootloader::{entry_point, BootInfo}; +use bootloader_api::{entry_point, BootInfo}; entry_point!(kernel_main); -fn kernel_main(boot_info: &'static BootInfo) -> ! { +fn kernel_main(boot_info: &'static mut BootInfo) -> ! {
- If you used optional features, such as
map_physical_memory, you can enable them again through theentry_pointmacro:See theuse bootloader_api::config::{BootloaderConfig, Mapping}; pub static BOOTLOADER_CONFIG: BootloaderConfig = { let mut config = BootloaderConfig::new_default(); config.mappings.physical_memory = Some(Mapping::Dynamic); config }; // add a `config` argument to the `entry_point` macro call entry_point!(kernel_main, config = &BOOTLOADER_CONFIG);
BootloaderConfigstruct for all configuration options. - The
v0.11version of the bootloader sets up a pixel-based framebuffer instead of using the VGA text mode. This means that you have to rewrite your screen output code. See thecommon/src/framebuffer.rsmodule for an example implementation based on thenoto-sans-mono-bitmapandlogcrates. - If you want to use UEFI booting, you cannot use the legacy PIC for interrupt handling. Instead, you have to set up the
APIC. Unfortunately, we don't have a guide for this yet, but the basic steps are:- The
boot_info.rsdp_addrfield will tell you the physical address of theRSDPstructure, which is part of theACPIstandard. Note thatACPI(Advanced Configuration and Power Interface) andAPIC(Advanced Programmable Interrupt Controller) are completely different things that just have confusingly similar acronyms. - Use the
acpicrate and itsAcpiTables::from_rsdpfunction to load the ACPI tables. Then use theplatform_infomethod and read theinterrupt_modelfield of the returnedPlatformInfo. This field gives you all the necessary information about the system's interrupt controller. - Parse and set up the local and IO APIC. We're working on a crate for that, but it's still in a very early state. We would love contributions! Alternatively, there are some other crates on crates.io that might work too.
- The
- If you reload the GDT at some point, ensure that all segment registers are written, including
ssandds. Thev0.9version of the bootloader used to initialize some of them to 0, but this is no longer the case. If you don't do this, a general protection fault might happen oniretq.
To build your kernel, run cargo build --target x86_64-unknown-none. Since the x86_64-unknown-none target is a Tier-2 target, there is no need for bootimage, cargo-xbuild, or xargo anymore. Instead, you can run rustup target add x86_64-unknown-none to download precompiled versions of the core and alloc crates. There is no need for custom JSON-based target files anymore.
The bootloader v0.11 release does not use the bootimage tool anymore. Instead, the bootloader crate provides functions to create bootable disk images from a kernel. The basic idea is to build your kernel first and then invoke a builder function that calls the disk image creation functions of the bootloader crate.
See our disk image creation template for a detailed explanation of the new build process.