package/petitboot: properly shut down before kexec

It's good practice to unmount filesystems and gracefully terminate
running services before running "kexec -e". So when a boot option has
been chosen from the petitboot menu, poke init to shut the system down
and kexec the new kernel.

One benefit to us in particular is that when pb-console is killed, it
notifies the user that we're booting:

  trap 'reset; echo "SIGTERM received, booting..."; sleep 2' SIGTERM

This terminal reset is also useful, exiting the ncurses visual mode so
subsequent boot output is raw rather than being confined to the window
set up for the petitboot menu.

Currently we assume busybox init (using the bb-kexec-reboot script
included with petitboot), but do not add an accompanying entry
in the inittab to run kexec, so things aren't working.

Add a new script kexec-restart that does the right thing for all init
systems that Buildroot supports (busybox, sysv, openrc, systemd). OpenRC
and systemd have an upstream way to do a kexec-shutdown. For busybox and
sysv, we add a line to inittab that does kexec -f -e (after the shutdown
scripts have run). Finally, for other cases (where there is no
recognized init system) directly use kexec -f -e.

Signed-off-by: Reza Arbab <arbab@linux.ibm.com>
[Arnout:
 - install kexec-restart in /usr/libexec/petitboot, where it was before;
 - determine init system statically based on config instead of dynamically.
]
Signed-off-by: Arnout Vandecappelle <arnout@mind.be>
This commit is contained in:
Reza Arbab
2024-02-07 11:51:33 -06:00
committed by Arnout Vandecappelle
parent d200d8ebe2
commit c2c2f3a42c
2 changed files with 38 additions and 3 deletions

View File

@@ -0,0 +1,8 @@
#!/bin/sh
@KEXEC_COMMAND@
while :
do
sleep 1
done

View File

@@ -30,7 +30,7 @@ PETITBOOT_CONF_OPTS = \
--without-twin-x11 \
$(if $(BR2_PACKAGE_BUSYBOX),--enable-busybox,--disable-busybox) \
HOST_PROG_KEXEC=/usr/sbin/kexec \
HOST_PROG_SHUTDOWN=/usr/libexec/petitboot/bb-kexec-reboot
HOST_PROG_SHUTDOWN=/usr/libexec/petitboot/kexec-restart
# HPA and Busybox tftp are supported. HPA tftp is part of Buildroot's tftpd
# package.
@@ -55,11 +55,37 @@ else
PETITBOOT_CONF_OPTS += --without-fdt
endif
ifeq ($(BR2_INIT_BUSYBOX),y)
# inittab "restart" runlevel entry runs kexec
PETITBOOT_KEXEC_COMMAND = /bin/kill -QUIT 1
define PETITBOOT_BUSYBOX_INITTAB
grep -q kexec $(TARGET_DIR)/etc/inittab || \
printf "\nnull::restart:/usr/sbin/kexec -f -e\n" >> $(TARGET_DIR)/etc/inittab
endef
PETITBOOT_TARGET_FINALIZE_HOOKS += PETITBOOT_BUSYBOX_INITTAB
else ifeq ($(BR2_INIT_SYSV),y)
# inittab runlevel 6 entry runs kexec
PETITBOOT_KEXEC_COMMAND = /sbin/shutdown -r now
define PETITBOOT_SYSV_INITTAB
grep -q kexec $(TARGET_DIR)/etc/inittab || \
$(SED) 's~^reb0:.*~reb0:6:wait:/usr/sbin/kexec -f -e~' $(TARGET_DIR)/etc/inittab
endef
PETITBOOT_TARGET_FINALIZE_HOOKS += PETITBOOT_SYSV_INITTAB
else ifeq ($(BR2_INIT_OPENRC),y)
PETITBOOT_KEXEC_COMMAND = /sbin/openrc-shutdown --kexec now
else ifeq ($(BR2_INIT_SYSTEMD),y)
PETITBOOT_KEXEC_COMMAND = /usr/bin/systemctl kexec
else # BR2_INIT_NONE
PETITBOOT_KEXEC_COMMAND = /usr/sbin/kexec -f -e
endif
PETITBOOT_GETTY_PORT = $(patsubst %,'%',$(call qstrip,$(BR2_PACKAGE_PETITBOOT_GETTY_PORT)))
define PETITBOOT_POST_INSTALL
$(INSTALL) -D -m 0755 $(@D)/utils/bb-kexec-reboot \
$(TARGET_DIR)/usr/libexec/petitboot/bb-kexec-reboot
$(INSTALL) -D -m 0755 $(PETITBOOT_PKGDIR)/kexec-restart.in \
$(TARGET_DIR)/usr/libexec/petitboot/kexec-restart
$(SED) 's~@KEXEC_COMMAND@~$(PETITBOOT_KEXEC_COMMAND)~' \
$(TARGET_DIR)/usr/libexec/petitboot/kexec-restart
$(INSTALL) -D -m 0755 $(@D)/utils/hooks/01-create-default-dtb \
$(TARGET_DIR)/etc/petitboot/boot.d/01-create-default-dtb
$(INSTALL) -D -m 0755 $(@D)/utils/hooks/90-sort-dtb \
@@ -77,6 +103,7 @@ define PETITBOOT_POST_INSTALL
mkdir -p $(TARGET_DIR)/usr/share/udhcpc/default.script.d/
ln -sf /usr/sbin/pb-udhcpc \
$(TARGET_DIR)/usr/share/udhcpc/default.script.d/
endef
PETITBOOT_POST_INSTALL_TARGET_HOOKS += PETITBOOT_POST_INSTALL