Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Practical Rust (Hypervisor) Firmware

Practical Rust (Hypervisor) Firmware

Rust Hypervisor Firmware is a small firmware written in Rust from scratch, which is dedicated to boot Linux cloud workloads on hypervisors. Since its main focus is to boot Linux, the supported guest OS is limited to the customized Ubuntu VM images and Clear Linux. In this talk, I will talk about how to boot recent versions of Windows from the firmware. In addition, I will describe how to port it to a physical machine like MinnowBoard MAX.

Akira Moroo

July 10, 2021
Tweet

More Decks by Akira Moroo

Other Decks in Technology

Transcript

  1. What’s Rust Hypervisor Firmware? • Small f irmware written from

    scratch in Rust • One of Cloud Hypervisor[1] subproject • Focuses on booting Linux cloud workloads • Ubuntu and Clear Linux • Supported VMMs: • Cloud Hypervisor and QEMU
  2. Architecture Overview • Minimal device drivers and f ilesystem support

    • VirtIO block device • FAT f ilesystem • Linux boot modes: • Native Linux loader • EFI compatible layer VirtIO Block Device FAT Filesystem EFI Compatible Layer Native Linux Loader Rust Hypervisor Firmware
  3. EFI Compatible Layer • Small subset of EFI features •

    Implemented 8 out of 39 EFI Boot Services • Enough to boot customized Ubuntu VM image • Works with typical Linux boot loaders (shim[2]+GRUB) • It was not compatible with the EFI spec. to boot: • Stock Ubuntu cloud images[3] • Other OSs?
  4. Windows Boot Stages • Windows boot process has three steps[4]:

    1. Boot Manager (bootmgfw.e f i) • Determines boot order from EFI variables/BCD 2. OS Loader (winload.e f i) • Setups Windows speci f ic pre-boot process 3. NT OS Kernel (ntoskrnl.exe) • Need to support above chain loading
  5. Changes Needed to Boot Windows EFI Variable Support EFI Device

    Path Decoder Support Chain Loading Support Fix Memory Segments Directory Support for EFI File Protocol EFI Runtime Services Support Fix EFI Memory Map Clock/Delay Support Fix PE Loader
  6. Changes Needed to Boot Windows EFI Variable Support EFI Device

    Path Decoder Support Chain Loading Support Fix Memory Segments Directory Support for EFI File Protocol EFI Runtime Services Support Fix EFI Memory Map Clock/Delay Support Fix PE Loader
  7. Boot Services and Runtime Services • Boot Services: available during

    BDS phase and TSL phase • Runtime Services: must be always available DXE Run Time (RT) Transient System Load (TSL) Boot Device Selection (BDS) EFI Runtime Services Availability EFI Boot Services Availability
  8. EFI Boot Process System Control Hand-o ff Flow • Loader

    loads and starts OS • EFI Boot Services is still available at this point DXE Run Time (RT) Transient System Load (TSL) OS Loader OS Kernel Boot Device Selection (BDS) Boot Dispatcher Boot Manager
  9. EFI Boot Process System Control Hand-o ff Flow • The

    OS requests system control hand-off to the EFI • This is done by calling gBS->ExitBootServices () DXE Run Time (RT) OS Kernel Transient System Load (TSL) OS Loader OS Kernel Boot Device Selection (BDS) Boot Dispatcher Boot Manager ExitBootServices()
  10. Paging Problem Regarding EFI Runtime Services • The OS is

    responsible to manage the system memory • It also remaps the EFI Runtime Services to the new virtual address • The EFI Runtime Services code must be relocated EFI Runtime Code mov $0x175bd0, %rax call *%rax 0x175bd0: ... ... 0x175000: EFI Runtime Code mov $0x175bd0, %rax call *%rax 0xfffc607f046ebd0: ... ... 0xfffc607f046e000: Unrecoverable Page Fault Set new page table
  11. EFI Runtime Code Relocation • The OS must call gRT-

    >SetVirtualAddressMap() • It provides the new virtual address map to the EFI Runtime Services • The EFI Runtime Services do self relocation using given map • How to implement? SetVirtualAddressMap() 0x175000 -> 0xfffc607f046e000 ... EFI Runtime Code mov $0x175bd0, %rax call *%rax 0x175bd0: ... ... 0x175000: Self Relocator Fixup
  12. EFI Runtime Services Design • Generate EFI Runtime Services as

    an independent dynamic ELF binary • The binary is embedded in the static binary using objcopy • Relocator does 1st relocation • Self-relocator does 2nd relocation Boot Services Code Relocator Self Relocator Runtime Services (Dynamic ELF) Rust Hypervisor Firmware (Static ELF)
  13. Target Windows Guest Environment • Exactly same environment supported by

    Cloud Hypervisor[5] • Recent versions of Windows: • Windows 10 20H2 and 21H1 • Windows Server 2019 • Installed 3rd-party VirtIO device drivers[6] • Enabled Emergency Management Services (EMS) [7] to use serial console • Cloud Hypervisor does not support graphics
  14. Porting to coreboot • coreboot[8]: Open source f irmware •

    coreboot ROM: • Basic system initialization + static ELF binary payload • Added coreboot table parser to provide memory map info (~170 LoC) System Initialization Code Intel FSP Rust (Hypervisor) Firmware
  15. Target Machine • MinnowBoard MAX[9] • Intel Atom (Bay Trail)

    • Easily access to SPI f lash • Pin header exposed • UART serial available x86 SBC from 2014
  16. Summary • Rust Hypervisor Firmware is a f irmware written

    in Rust • Added more compatibility to the f irmware to boot Windows • It requires sane implementation of EFI Runtime Services • Ported the f irmware to coreboot with small efforts • It now boots up on a physical machine • It still cannot boot OS due to lack of physical disk device drivers • https://github.com/cloud-hypervisor/rust-hypervisor- f irmware
  17. References • [0] https://github.com/cloud-hypervisor/rust-hypervisor- f irmware • [1] https://github.com/cloud-hypervisor/cloud-hypervisor •

    [2] https://github.com/rhboot/shim • [3] https://cloud-images.ubuntu.com • [4] https://ue f i.org/sites/default/ f iles/resources/UEFI-Plugfest-WindowsBootEnvironment.pdf • [5] https://github.com/cloud-hypervisor/cloud-hypervisor/blob/master/docs/windows.md • [6] https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.185-2/ • [7] https://docs.microsoft.com/en-us/windows-hardware/drivers/devtest/bcdedit--ems • [8] https://coreboot.org • [9] https://www.elinux.org/Minnowboard:MinnowMax
  18. Pros & Cons of Writing Firmware in Rust Rust is

    not a silver bullet • Pros: • no_std-friendly ecosystem • core crate is modular design • Clean compile-time environment • macro/const_fn • C preprocessor is hell • Strong type system • Cons: • Nightly Rust is required • Some of ABIs are unstable • Efforts needed to keep dependencies up-to-date • Cargo is so not f lexible • e.g. oreboot uses GNU Make in addition to Cargo
  19. Debugging Issues • Issue #1: WinDbg is not available in

    early boot phase • winload.e f i (2nd phase) starts WinDbg session before loading the kernel • It cannot be used for debugging bootmgfw.e f i (1st phase) • Issue #2: Dealing with KASLR • KASLR is also applied to EFI runtime services • It is hard to f ind EFI service caller from backtrace
  20. Debugging Issue #1 • Issue #1: WinDbg is not available

    in early boot phase • winload.e f i starts WinDbg session before loading the kernel • It cannot be used for debugging bootmgfw.e f i • -> Ghidra: • Microsoft Symbol Server: • Also provides bootmgfw.e f i and winload.e f i symbols • Ghidra Firmware Utilities: • Adds EFI-speci f ic types and annotates well-known GUIDs
  21. Debugging Issue #2 • Issue #2: Dealing with KASLR •

    winload.e f i loads NT OS kernel at randomized offset • It is also applied to EFI runtime services • It makes debugging EFI runtime services hard • -> Custom GDB Python script • Hooks kernel hand off and calculates KASLR offset • Set breakpoints using the offset value