1

The manpage of reboot() says

LINUX_REBOOT_CMD_RESTART2

(0xa1b2c3d4; since Linux 2.1.30). The message "Restarting system with command '%s'" is printed, and a restart (using the command string given in arg) is performed immediately. If not preceded by a sync(2), data will be lost.

How and when exactly is the command string given in arg is executed during shutdown process?

https://unix.stackexchange.com/a/489651/674 says about LINUX_REBOOT_CMD_RESTART2

An added confusion here is caused by the fact that the reboot() system call appears to be capable of running a process to do the restart (however that works)

Is the command string given in arg run before the kernel is shutdown, so can the command do some cleanup before kernel shutdown?

Thanks.

Tim
  • 101,790

2 Answers2

2

That command is not executed during the shutdown process. It's not a shell command or such; it's a string that's supposed to be passed as callback data (via machine_restart() => do_kernel_restart()) to the restart handler registered via register_restart_handler() by some driver (watchdog, etc).

But that mechanism is not used on x86; there that "command" is completely ignored. From arch/x86/kernel/reboot.c:

void machine_restart(char *cmd)
{
        machine_ops.restart(cmd);

struct machine_ops machine_ops __ro_after_init = { ... .restart = native_machine_restart,

static void native_machine_restart(char *__unused) {

That string will be also passed to the handlers registered with register_reboot_notifier(). The only driver which is (ab)using that seems to be EFI Bootloader Control which is setting the non-volative LoaderEntryOneShot EFI variable from it, causing some bootloaders to determine which OS should be booted in next. I don't think that driver was ever used outside Android -- but in any case it looks quite clunky, as it's also detailed in an old lkml discussion concerning a previous version of that same thing.

  • Yeah, seems like I misinterpreted the meaning of that "with command" phrase in the man page. Not that the man page is too clear on what the commands could be, or what architectures even use it. Sigh. – ilkkachu Dec 20 '18 at 14:45
1

It's not executed. The command has a corresponding numerical value, which is passed to reboot mode driver to write to the reboot reason register. After rebooting the bootloader reads the reason value from the register and decides to start e.g. fastboot, recovery, etc depending on the command chosen.

E.g. phones based on Qualcomm MSM8916 SOC have Power On device, which contains such a reboot reason register. The commands (in the form mode-<command>) and corresponding reason values are described in its device tree:

pon@800 {
        compatible = "qcom,pm8916-pon";
        reg = <0x800>;
        mode-bootloader = <0x2>;
        mode-recovery = <0x1>;

Thus when reboot(2) is called with bootloader command string, the driver for Power On device writes 0x2 to the reboot reason register.

On next boot the bootloader (e.g. lk2nd) checks the reason register and boots into appropriate mode (from aboot_init() in aboot.c):

#if USE_PON_REBOOT_REG
    reboot_mode = check_hard_reboot_mode();
#else
    reboot_mode = check_reboot_mode();
#endif
    if (reboot_mode == RECOVERY_MODE)
    {
        boot_into_recovery = 1;
    }
    else if(reboot_mode == FASTBOOT_MODE)
    {
        boot_into_fastboot = true;
    }

RECOVERY_MODE and FASTBOOT_MODE are defined in lk2nd reboot.h and have the same values as in device tree above (except "fastboot" is called "bootloader" there):

#define RECOVERY_MODE     0x01
#define FASTBOOT_MODE     0x02

I don't know of utility that can reboot with the command to test this behavior, but you can do it in python with ctypes:

python -c "import ctypes; ctypes.CDLL('libc.so').syscall(142, 0xfee1dead, 0x20112000, 0xa1b2c3d4, b'bootloader')"

142 above is reboot(2) syscall number on arm64. Hex magic numbers are from man 2 reboot.

giraffes
  • 61
  • 3