What is linuxboot?

LinuxBoot is a firmware for modern servers that replaces specific firmware functionality like the UEFI DXE phase with a Linux kernel and runtime.

Why?

  • Improves boot reliability by replacing lightly-tested firmware drivers with hardened Linux drivers.
  • Improves boot time by removing unnecessary code. Typically makes boot 20 times faster.
  • Allows customization of the initrd runtime to support site-specific needs (both device drivers as well as custom executables).
  • Proven approach for almost 20 years in military, consumer electronics, and supercomputing systems – wherever reliability and performance are paramount.

Hackweek goals

  • Study how linuxboot works.
  • Firmware building and running based on QEMU.
  • Try booting openSUSE via linuxboot. (optional)

Resources

Looking for hackers with the skills:

Nothing? Add some keywords!

This project is part of:

Hack Week 21

Activity

  • 7 months ago: vkarasulli joined this project.
  • 8 months ago: clin joined this project.
  • 8 months ago: dmdiss liked this project.
  • 8 months ago: fakhrylinux joined this project.
  • 8 months ago: aextecki liked this project.
  • 8 months ago: aextecki started this project.
  • 8 months ago: clin originated this project.

  • Comments

    • clin
    • clin
      7 months ago by clin | Reply

      Getting started with LinuxBoot Firmware on AArch64 Server

    • clin
      7 months ago by clin | Reply

      Problem (Solved, please see the next message): The newer kernel versions for x86_64 [v5.8 ~ v5.18] seem too big [bzImage: 8.6MB ~ 11MB] to fit into the regular max size of an OVMF FD, which is 8MB. I tried to extend the size defined in edk2/OvmfPkg/OvmfPkgX64.dsc to 16MB in order to finish the build process. [DONE]

      However, QEMU limits the size of x86_64 system FW to 8MB. [QEMU ver: 6.2.0]

      chester@linux-8mug:~/workspace/src/github/build/linuxboot/linuxboot> make run

      qemu-system-x86_64 \

      -machine q35,smm=on \

      -global ICH9-LPC.disable_s3=1 \

      -global driver=cfi.pflash01,property=secure,value=on \

      --serial stdio \

      -drive if=pflash,format=raw,unit=0,file=build/qemu/linuxboot.rom

      qemu-system-x86_64: combined size of system firmware exceeds 8388608 bytes

      make: [boards/qemu/Makefile.board:67: run] Error 1 (ignored)

      • clin
        7 months ago by clin | Reply

        edk2 patch:

        Note: The edk2 branch that LinuxBoot aligns with is UDK2018, which is relatively old. The following patch is only based on the code tree which is automatically fetched by LinuxBoot's Makefile.

        diff --git a/OvmfPkg/OvmfPkg.fdf.inc b/OvmfPkg/OvmfPkg.fdf.inc                  
        index 8d6e3c6f..77a73c31 100644                                                 
        --- a/OvmfPkg/OvmfPkg.fdf.inc                                                   
        +++ b/OvmfPkg/OvmfPkg.fdf.inc                                                   
        @@ -124,4 +124,4 @@ SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize = $(BLOCK_SIZ
         SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageFtwSpareBase = gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageFtwWorkingBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlas
         SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize = $(VARS_SPARE_SIZE)^M
         ^M                                                                             
        -DEFINE MEMFD_BASE_ADDRESS = 0x800000^M                                         
        +DEFINE MEMFD_BASE_ADDRESS = 0x1000000^M                                        
        diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc                    
        index ad2a3e39..eac09b85 100644                                                 
        --- a/OvmfPkg/OvmfPkgX64.dsc                                                    
        +++ b/OvmfPkg/OvmfPkgX64.dsc                                                    
        @@ -56,8 +56,8 @@                                                               
         !ifdef $(FD_SIZE_4MB)^M                                                        
           DEFINE FD_SIZE_IN_KB           = 4096^M                                      
         !else^M                                                                        
        -  #DEFINE FD_SIZE_IN_KB           = 16384^M                                    
        -  DEFINE FD_SIZE_IN_KB           = 8192^M                                      
        +  DEFINE FD_SIZE_IN_KB           = 16384^M                                     
        +  #DEFINE FD_SIZE_IN_KB           = 8192^M                                     
         !endif^M                                                                       
         !endif^M                                                                       
         !endif^M
        diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf                    
        index b8b7777e..def1e57a 100644                                                 
        --- a/OvmfPkg/OvmfPkgX64.fdf                                                    
        +++ b/OvmfPkg/OvmfPkgX64.fdf                                                    
        @@ -68,10 +68,10 @@ FV = SECFV                                                  
         ^M                                                                             
         [FD.MEMFD]^M                                                                   
         BaseAddress   = $(MEMFD_BASE_ADDRESS)^M                                        
        -Size          = 0xB00000^M                                                     
        +Size          = 0xFF0000^M                                                     
         ErasePolarity = 1^M                                                            
         BlockSize     = 0x10000^M                                                      
        -NumBlocks     = 0xB0^M                                                         
        +NumBlocks     = 0xFF^M                                                         
         ^M                                                                             
         0x000000|0x006000^M                                                            
         gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize^M
        @@ -89,7 +89,7 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.P
         gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize^M
         FV = PEIFV^M                                                                   
         ^M                                                                             
        -0x100000|0xA00000^M                                                            
        +0x100000|0xEF0000^M                                                            
         gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvSize^M
         FV = DXEFV^M
        

      • clin
        7 months ago by clin | Reply

        linuxboot patch

        diff --git a/boards/qemu/Makefile.board b/boards/qemu/Makefile.board                                                                                                       
        index 57784f7..77436d7 100644                                                      
        --- a/boards/qemu/Makefile.board                                                   
        +++ b/boards/qemu/Makefile.board                                                
        @@ -10,12 +10,12 @@                                                             
         # 0x084000.fv FV (DXE and PEI)                                                 
         #        0.fv PEI                                                              
         #        1.fv DXE                                                              
        -# 0x7cc000.fv SEC                                                              
        +# 0xfcc000.fv SEC                                                              
         #                                                                              
         #                                                                              
        
        -dxe-size       := 0xA00000                                                     
        -merged-size    := 0x748000                                                     
        +dxe-size       := 0xEF0000                                                     
        +merged-size    := 0xF48000                                                     
        
         fv-path := $(BUILD)/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792        
         dxe-path := $(fv-path)/1                                                       
        @@ -34,7 +34,7 @@ $(fv-path)/0.fv: $(BUILD)/$(BOARD).txt                        
         FVS := \                                                                       
                $(BUILD)/rom/0x00000000.fv \                                            
                $(BUILD)/merged.vol \                                                   
        -       $(BUILD)/rom/0x007cc000.fv \                                            
        +       $(BUILD)/rom/0x00fcc000.fv \
        
         $(BUILD)/merged.vol: \                                                         
                $(fv-path)/0.fv \                                                       
        @@ -43,7 +43,7 @@ $(BUILD)/merged.vol: \                                        
                ./bin/create-ffs \                                                      
                        --compress \                                                    
                        --type FIRMWARE_VOLUME_IMAGE \                                  
        -               $^ \                                                            
        +               $(filter-out $(BUILD)/$(BOARD).txt,$^) \                        
                | ./bin/create-fv \                                                     
                        --size $(merged-size) \                                         
                        -o $@                                                           
        @@ -65,7 +65,7 @@ boards/$(BOARD)/$(BOARD).rom: edk2/.git                       
         # We can also launch a qemu with the LinuxBoot kernel                          
         run: $(BUILD)/linuxboot.rom                                                    
                -qemu-system-x86_64 \                                                   
        -               -machine q35,smm=on  \                                          
        +               -machine q35,smm=on,max-fw-size=16777216  \                     
                        -global ICH9-LPC.disable_s3=1 \                                 
                        -global driver=cfi.pflash01,property=secure,value=on \          
                        --serial $(or $(SERIAL),stdio) \
        diff --git a/boards/qemu/image-files.txt b/boards/qemu/image-files.txt          
        index 5ae8d58..4ec4850 100644                                                   
        --- a/boards/qemu/image-files.txt                                               
        +++ b/boards/qemu/image-files.txt                                               
        @@ -6,10 +6,10 @@ d93ce3d8-a7eb-4730-8c8e-cc466a9ecc3c ReportStatusCodeRouterRuntimeDxe
         b601f8c4-43b7-4784-95b1-f4226cb40cee RuntimeDxe                                
         f80697e9-7fd6-4665-8646-88e33ef71dfc SecurityStubDxe                           
         13ac6dd0-73d0-11d4-b06b-00aa00bd6de7 EbcDxe                                    
        -245CB4DA-8E15-4A1B-87E3-9878FFA07520 Legacy8259                                
        +79ca4208-bba1-4a9a-8456-e1e66a81484e Legacy8259                                
         a19b1fe7-c1bc-49f8-875f-54a5d542443f CpuIo2Dxe                                 
         1a1e4886-9517-440e-9fde-3be44cee2136 CpuDxe                                    
        -C190FE35-44AA-41A1-8AEA-4947BC60E09D Timer                                     
        +f2765dec-6b41-11d5-8e71-00902707b35e Timer                                     
         f6697ac4-a776-4ee1-b643-1feff2b615bb IncompatiblePciDeviceSupportDxe           
         11a6edf6-a9be-426d-a6cc-b22fe51d9224 PciHotPlugInitDxe                         
         128fb770-5e79-4176-9e51-9bb268a17dd1 PciHostBridgeDxe                          
        @@ -29,7 +29,7 @@ f9d88642-0737-49bc-81b5-6889cd57d9ea SmbiosDxe                
         49970331-e3fa-4637-9abc-3b7868676970 AcpiPlatform                              
         7e374e25-8e01-4fee-87f2-390c23c606cd ACPI data                                 
         bdce85bb-fbaa-4f4e-9264-501a2c249581 S3SaveStateDxe                            
        -7C04A583-9E3E-4F1C-AD65-E05268D0B4D1 Shell                                     
        +# 7C04A583-9E3E-4F1C-AD65-E05268D0B4D1 Shell                                   
         d9dcc5df-4007-435e-9098-8970935504b2 PlatformDxe                               
         2ec9da37-ee35-4de9-86c5-6d9a81dc38a7 AmdSevDxe                                 
         8657015b-ea43-440d-949a-af3be365c0fc IoMmuDxe                                  
        diff --git a/build/.gitignore b/build/.gitignore                                
        deleted file mode 100644                                                        
        index 72e8ffc..0000000                                                          
        --- a/build/.gitignore                                                          
        +++ /dev/null                                                                   
        @@ -1 +0,0 @@                                                                   
        -*
        

      • clin
        7 months ago by clin | Reply

        Files and configs for my experiment:

        • KERNEL: vmlinuz-5.8.14-1-default [10MB] copied from my laptop kernel [OpenSUSE Tumbleweed 20211101] since it's smaller than the bzImage compiled by x86_64_defconfig [11MB].
        • INITRD: initramfs.linux_amd64.cpio.xz[3.3MB]. A smaller initramfs built by u-root.
        • BOARD: qemu [x86_64]
        • CONFIG_EFI_BDS: A downstream patch that is outdated to new kernels [~v5.x] since the related codes have been changed and moved from boot/compressed/boot.c to efistub since kernel v5.8.

      • clin
        7 months ago by clin | Reply

        u-root compiling instructions: go version >=1.17

        # git clone https://github.com/u-root/u-root

        # cd u-root/

        # go build

        # go install github.com/u-root/u-root

        # export GOPATH=$HOME/go

        # export PATH=$PATH:$GOPATH/bin

        # u-root -uroot-source github.com/u-root/u-root core

        # xz --check=crc32 -9 --lzma2=dict=1MiB \

        --stdout /tmp/initramfs.linux_amd64.cpio \

        | dd conv=sync bs=512 \

        of=/tmp/initramfs.linux_amd64.cpio.xz

    • clin
      7 months ago by clin | Reply

      The FW size limitation can be solved by adding the property "max-fw-size=16777216". For example:

      qemu-system-x86_64 \

      -machine q35,smm=on,max-fw-size=16777216 \

      -global ICH9-LPC.disable_s3=1 \

      -global driver=cfi.pflash01,property=secure,value=on \

      --serial stdio \

      -drive if=pflash,format=raw,unit=0,file=build/qemu/linuxboot.rom

      Now I can launch a QEMU instance but there's no console output. Under investigation.

    • clin
      7 months ago by clin | Reply

      If you found that LzmaCompress could not be found when the build system was compiling the edk2, it seems to be a toolchain issue but you can still compile it by your local x86-64 tool-chain, just simply cd to edk2/BaseTools and then run make.

    • clin
      7 months ago by clin | Reply

      I put all my current work here.

      Progress:

      • The simulation starts from edk2 and the boot sequence SEC->PEI->DXE looks good.
      • The BDS stage owned by LinuxBoot can be reached but the process always dies at the following assertion:

      --------

      Transfering control to BDS 7B31450

      Entry Point 7B2F280 (7B2F280)

      --------

      LinuxBoot: BDS time has arrived

      LinuxBoot: connect pci root bridges

      efivisithandles 2F707EBB

      handle_count=00000001

      PCI Bus First Scanning

      PciBus: Discovered PCI @ [00|00|00]

      PciBus: Discovered PCI @ [00|01|00]

      BAR[0]: Type = PMem32; Alignment = 0xFFFFFF; Length = 0x1000000; Offset = 0x10

      BAR[2]: Type = Mem32; Alignment = 0xFFF; Length = 0x1000; Offset = 0x18

      PciBus: Discovered PCI @ [00|02|00]

      ASSERT [PciHostBridgeDxe] /home/chester/workspace/src/github/test/linuxboot/edk2/MdePkg/Library/BasePciCf8Lib/PciCf8Lib.c(1114): ((Address) & (~0xffff0ff | (3))) == 0

    • clin
      7 months ago by clin | Reply

      TODO:

      • Solve the assertion issued by PciHostBridgeDxe.
      • run the rest of boot sequence test.
        • BDS -> 1st kernel owned by linuxboot -> mount u-root initramfs -> kexec to next-kernel or launch grub2.
      • Come up with a minimum config in order to downsize the kernel.
        • Different platforms might have different configs.

    Similar Projects

    This project is one of its kind!