@@ -229,6 +229,12 @@ menu "Target Images"
prompt "journal size" if TARGET_ROOTFS_UBIFS
default ""
+ config SYSTEMDBOOT_IMAGES
+ bool "Build systemd-boot images (EFI x86_64 targets only)"
+ depends on TARGET_x86_64
+ depends on TARGET_ROOTFS_EXT4FS || TARGET_ROOTFS_JFFS2 || TARGET_ROOTFS_SQUASHFS || TARGET_ROOTFS_EROFS
+ select PACKAGE_systemd-boot
+
config GRUB_IMAGES
bool "Build GRUB images (Linux x86 or x86_64 host only)"
depends on TARGET_x86
@@ -251,23 +257,23 @@ menu "Target Images"
config GRUB_CONSOLE
bool "Use Console Terminal (in addition to Serial)"
- depends on GRUB_IMAGES || GRUB_EFI_IMAGES
+ depends on GRUB_IMAGES || GRUB_EFI_IMAGES || SYSTEMDBOOT_IMAGES
default y
config GRUB_BAUDRATE
int "Serial port baud rate"
- depends on GRUB_IMAGES || GRUB_EFI_IMAGES
+ depends on GRUB_IMAGES || GRUB_EFI_IMAGES || SYSTEMDBOOT_IMAGES
default 38400 if TARGET_x86_generic
default 115200
config GRUB_FLOWCONTROL
bool "Use RTE/CTS on serial console"
- depends on GRUB_IMAGES || GRUB_EFI_IMAGES
+ depends on GRUB_IMAGES || GRUB_EFI_IMAGES || SYSTEMDBOOT_IMAGES
depends on TARGET_SERIAL != ""
config GRUB_BOOTOPTS
string "Extra kernel boot options"
- depends on GRUB_IMAGES || GRUB_EFI_IMAGES
+ depends on GRUB_IMAGES || GRUB_EFI_IMAGES || SYSTEMDBOOT_IMAGES
help
If you don't know, just leave it blank.
@@ -279,8 +285,8 @@ menu "Target Images"
If you don't know, 5 seconds is a reasonable default.
config GRUB_TITLE
- string "Title for the menu entry in GRUB"
- depends on GRUB_IMAGES || GRUB_EFI_IMAGES
+ string "Title for the menu entry in GRUB and systemd-boot"
+ depends on GRUB_IMAGES || GRUB_EFI_IMAGES || SYSTEMDBOOT_IMAGES
default "OpenWrt"
help
This is the title of the GRUB menu entry.
new file mode 100644
@@ -0,0 +1,55 @@
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=systemd-boot
+PKG_VERSION:=259
+PKG_RELEASE:=1
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=https://github.com/systemd/systemd.git
+PKG_MIRROR_HASH:=1671487dc511d60d3c50070e8f5c6dec228a1d97cdedd7f5508a966bb06ba614
+PKG_SOURCE_DATE:=2025-12-17
+PKG_SOURCE_VERSION:=9ca433482f2281d71718718705ca8cd3bf562ad6
+PKG_CPE_ID:=cpe:/a:systemd_project:systemd:259:-
+
+PKG_LICENSE:=LGPL-2.1-or-later
+PKG_LICENSE_FILES:=LICENSES/README.md
+PKG_BUILD_DEPENDS:=python-pyelftools/host python-jinja2/host gperf/host
+PKG_INSTALL:=1
+
+MESON_USE_STAGING_PYTHON:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/meson.mk
+
+define Package/systemd-boot
+ SECTION:=boot
+ CATEGORY:=Boot Loaders
+ TITLE:=Simple UEFI boot manager
+ DEPENDS:=@TARGET_x86_64 +libblkid
+ URL:=https://github.com/systemd/systemd/tree/main/src/boot
+endef
+
+define Package/systemd-boot/description
+ systemd-boot Simple UEFI boot manager
+
+ systemd-boot executes EFI images. The default entry is selected by a configured
+ pattern (glob) or an on-screen menu.
+endef
+
+MESON_ARGS += \
+ -Dmode=release \
+ -Dlibc=musl \
+ -Dbootloader=enabled \
+ --auto-features=disabled
+
+define Package/systemd-boot/install
+ $(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/lib/systemd-boot
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/systemd/boot/efi/systemd-bootx64.efi $(1)/usr/lib/systemd-boot/
+endef
+
+$(eval $(call BuildPackage,systemd-boot))
@@ -125,6 +125,7 @@ platform_do_upgrade() {
mount -t $parttype -o rw,noatime "/dev/$partdev" /mnt
set -- $(dd if="/dev/$diskdev" bs=1 skip=1168 count=16 2>/dev/null | hexdump -v -e '8/1 "%02x "" "2/1 "%02x""-"6/1 "%02x"')
sed -i "s/\(PARTUUID=\)[a-f0-9-]\+/\1$4$3$2$1-$6$5-$8$7-$9/ig" /mnt/boot/grub/grub.cfg
+ sed -i "s/\(PARTUUID=\)[a-f0-9-]\+/\1$4$3$2$1-$6$5-$8$7-$9/ig" /mnt/boot/loader/entries/main.conf
umount /mnt
fi
}
@@ -52,6 +52,30 @@ define Build/combined
256
endef
+define Build/systemd-boot
+ rm -fR $@.boot
+ $(INSTALL_DIR) $@.boot/boot $@.boot/efi/boot $@.boot/loader/entries
+
+ $(CP) $(KDIR)/$(KERNEL_NAME) $@.boot/boot/vmlinuz
+ -$(CP) $(STAGING_DIR_ROOT)/boot/. $@.boot/boot/
+ $(CP) $(STAGING_DIR_ROOT)/usr/lib/systemd-boot/systemd-bootx64.efi $@.boot/efi/boot/bootx64.efi
+
+ sed \
+ -e 's#@GPT_ROOTPART@#root=$(GPT_ROOTPART) rootwait#g' \
+ -e 's#@CMDLINE@#$(BOOTOPTS) $(GRUB_CONSOLE_CMDLINE)#g' \
+ -e 's#@TITLE@#$(GRUB_TITLE)#g' \
+ ./systemdboot-entry.cfg > $@.boot/loader/entries/main.conf
+
+ $(CP) ./systemdboot-loader.conf $@.boot/loader/loader.conf
+
+ PADDING="1" SIGNATURE="$(IMG_PART_SIGNATURE)" \
+ GUID="$(IMG_PART_DISKGUID)" $(SCRIPT_DIR)/gen_image_generic.sh \
+ $@ \
+ $(CONFIG_TARGET_KERNEL_PARTSIZE) $@.boot \
+ $(CONFIG_TARGET_ROOTFS_PARTSIZE) $(IMAGE_ROOTFS) \
+ 256
+endef
+
define Build/grub-config
rm -fR $@.boot
$(INSTALL_DIR) $@.boot/boot/grub
@@ -114,14 +138,18 @@ define Device/Default
IMAGE/combined-efi.vdi := grub-config efi | combined efi | grub-install efi | qemu-image vdi
IMAGE/combined-efi.vmdk := grub-config efi | combined efi | grub-install efi | qemu-image vmdk
IMAGE/combined-efi.vhdx := grub-config efi | combined efi | grub-install efi | qemu-image vhdx -o subformat=dynamic
+ IMAGE/systemd-boot.img := systemd-boot | append-metadata
+ IMAGE/systemd-boot.img.gz := systemd-boot | gzip | append-metadata
ifeq ($(CONFIG_TARGET_IMAGES_GZIP),y)
IMAGES-y := rootfs.img.gz
IMAGES-$$(CONFIG_GRUB_IMAGES) += combined.img.gz
IMAGES-$$(CONFIG_GRUB_EFI_IMAGES) += combined-efi.img.gz
+ IMAGES-$$(CONFIG_SYSTEMDBOOT_IMAGES) += systemd-boot.img.gz
else
IMAGES-y := rootfs.img
IMAGES-$$(CONFIG_GRUB_IMAGES) += combined.img
IMAGES-$$(CONFIG_GRUB_EFI_IMAGES) += combined-efi.img
+ IMAGES-$$(CONFIG_SYSTEMDBOOT_IMAGES) += systemd-boot.img
endif
KERNEL := kernel-bin
KERNEL_INSTALL := 1
new file mode 100644
@@ -0,0 +1,4 @@
+title @TITLE@
+linux /boot/vmlinuz
+options @GPT_ROOTPART@ @CMDLINE@ noinitrd
+architecture x64
new file mode 100644
@@ -0,0 +1 @@
+timeout menu-disabled
grub2 has many features, including different implementations for loading the linux kernel. At one machine, the "linux" command cannot start OpenWrt while the "chainloader" command for the same kernel file works. Both commands use the same UEFI API, but the surrounding steps are slightly different. An UEFI native bootloader seems to be similar to "chainloader" in grub while avoiding a ton of extra features. One of those bootloaders is systemd-boot, formerly known as gummiboot. While it contains the name "systemd" and is part of the systemd codebase, the resulting efi executable can be used independent of systemd. systemd contains bootctl for managing a systemd-boot installation, but systemd-boot uses simple text configuration files so that this is not needed at all. Signed-off-by: Jonas Lochmann <openwrt@jonaslochmann.de> --- config/Config-images.in | 18 ++++-- package/boot/systemd-boot/Makefile | 55 +++++++++++++++++++ .../x86/base-files/lib/upgrade/platform.sh | 1 + target/linux/x86/image/Makefile | 28 ++++++++++ target/linux/x86/image/systemdboot-entry.cfg | 4 ++ .../linux/x86/image/systemdboot-loader.conf | 1 + 6 files changed, 101 insertions(+), 6 deletions(-) create mode 100644 package/boot/systemd-boot/Makefile create mode 100644 target/linux/x86/image/systemdboot-entry.cfg create mode 100644 target/linux/x86/image/systemdboot-loader.conf