Git Product home page Git Product logo

phipsboot's Introduction

PhipsBoot

⚠️ Work in progress. This is more proof-of-concept than production-ready. ⚠️

Disclaimer: This project combines a lot of toolchain and binary knowledge and experience I collected and gained in recent years about legacy x86_64 boot. The main contribution IMHO is how the binary is assembled and that the thing boots with all the properties described below, but not the high-level functionality itself.

I am especially proud of the well-commented structure of the assembly files. For example the whole page-table mappings are done IMHO very nicely even though it is assembly language. Also, I think it turned out quite cool how I configured the linker script. I hope this can be a learning resource for others!

Further: This project is a solution for a niche use-case, especially in 2024.

PhipsBoot is a relocatable x86_64 bootloader written in Rust and assembly that loads a kernel into 64-bit mode. It abstracts a lot of boot-related x86_64 complexity away.

The main advantage of PhipsBoot is seen when loaded by GRUB via Multiboot2 in legacy BIOS boot systems, where it can be relocated in physical memory even though the kernel binary is a static ELF. However, PhipsBoot also supports Multiboot1 and XEN PVH entries.

About

Supported Boot Environments

PhipsBoot expects an 32-bit protected mode without paging machine state at is entry. This corresponds to the Multiboot2 i386 machine state definition.

Firmware Hand-Off by Status Comment
BIOS/UEFI Firmware Use existing projects as chainloader.
BIOS/UEFI Multiboot 1/2 Recommended (BIOS + GRUB + Multiboot 2)
* Xen PVH

Why Relying On GRUB + Multiboot2?

Effectively, in the open-source world you are limited to GRUB when you want to boot your custom kernel on legacy BIOS x86_64 systems, while keeping up a certain level of user and developer experience. By reusing all the abstracted away complexity that GRUB comes with, PhipsBoot can be much simpler and easier to program, install, adopt, and use.

Which problems does PhipsBoot solve?

It solves several problems every 64-bit kernel has to perform anyway, such as performing the transition into 64-bit long mode while also being relocatable in physical memory to never clash with firmware code, MMIO regions or otherwise reserved addresses. Kernels using this bootloader can massively simplify their build setup and boot code as much complexity is outsourced to PhipsBoot, such as several CPU state transitions and intermediate identity page mappings.

By far the biggest contribution of PhipsBoot is that it is relocatable in physical memory when it is loaded by GRUB. Here, you can read more of the overall challenges.

Related Projects & Practical Alternatives

First of all: If you are targeting UEFI and only UEFI, you need none of this! The world is much simpler there. However, for legacy BIOS, the bootloader developer and user experience is just difficult. To not be forced to use GRUB, one can also write an entire bootloader supporting legacy BIOS boot in Rust. That's awesome! However, installing legacy BIOS stage 1 bootloaders on disk is much more complicated, as one has to patch the MBR instead of just putting a file on disk. By using GRUB however, it is relatively easy to put PhipsBoot or other Multiboot payloads on disk and reference them from the GRUB config.

If you are targeting legacy x86 boot and have the freedom to choose and install your own stage 1 bootloader, you can also have a look at Limine, which is superior to GRUB and production ready. It also brings your kernel into 64-bit mode right away, making PhipsBoot obsolete.

Trivia

I'm kind of proud of the way I set up page-tables from assembly using descriptive GNU as macros! I didn't see anything like that so far. IMHO it is a great approach as low-level programming and assembly doesn't necessarily has to be ugly. 🤓

Developer Guide

  • General description about the architecture: ARCHITECTURE.md
  • Build and run test: $ make && make integration-test

Artifacts are in ./build.

User Guide

Boot PhipsBoot (for testing)

You have multiple options, for example:

  • $ cloud-hypervisor --debug-console file=log.txt --kernel ./build/phipsboot.elf64 (using Xen PVH)
  • $ qemu-system-x86_64 -kernel ./build/phipsboot.elf32 -debugcon stdio (using Multiboot 1)

Supported Kernel Payloads

Supported payloads that PhipsBoot can boot are ELF executables (static and dyn). The hand-off to the kernel follows the PhipsBoot protocol.

PhipsBoot protocol

This protocol describes the hardware state and the handover to your kernel when it is booted by PhipsBoot.

Kernel Entry

The kernel entry is taken from the ELF entry. It is invoked using the SystemV x86_64 calling convention. First argument passed to your kernel is a point to the boot information.

Machine State after hand-off

  • PhipsBoot is still mapped and occupies (at most) 2 MiB of virtual address space
  • BSP in 64-bit long mode with 4-level paging
  • APs are still asleep
  • control registers
    • %cr0: PE (0), MP (1), WP (16), PG (31)
    • %cr4: PAE (5), OSFXSR (9), OSXMMEXCPT (10)
    • %cr3: holds the physical address of the root page table
  • MSRs
    • efer: LME (8), NX (11)
  • GDT, which is living in the physical address space of PhipsBoot, is set with two selectors:
    • null selector
    • (64-bit, code segment, ring 0)-selector
  • %rsp is set to a valid 128 KiB stack
  • %rdi has pointer to boot information
  • All load segments of the kernel are loaded with their corresponding page-table rights. The NX bits are set for all non-executable LOAD segments.

Boot Information

TODO implement

Booting Your Kernel with PhipsBoot

TODO implement

You can use the following GRUB configuration:

menuentry "Kernel" {
    multiboot2 /phipsboot
    module2 /your-kernel
    boot
}

Binary Formats of PhipsBoot

The build itself produces phipsboot.elf32 and phipsboot.elf64. Both are identical except for the ELF header. You usually always want to use the .elf64 version except for when booting it via Multiboot1, where compliant bootloaders only accept 32-bit ELFs.

phipsboot's People

Contributors

phip1611 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

linecode

phipsboot's Issues

Add ELF loading

Add ELF loading.

My idea is to boot the first boot module (treat it as kernel) and pass all further modules to the kernel.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.