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
Comments
-
over 2 years 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)
-
over 2 years 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
-
over 2 years 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 := 0xF48000fv-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 FIRMWAREVOLUMEIMAGE \
- $^ \
+ $(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-x8664 \
- -machine q35,smm=on \
+ -machine q35,smm=on,max-fw-size=16777216 \
-global ICH9-LPC.disables3=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 @@
-* ``` -
over 2 years 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.
-
over 2 years 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
-
-
over 2 years 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.
-
over 2 years ago by clin | Reply
I put all my current work here.
Build folder, you can use fiano to parse
*.rom, *.vol and *.ffs
binaries
Progress:
- The simulation starts from
edk2
and the boot sequenceSEC->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
-
over 2 years 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!