1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <stdio.h> 4 #include <unistd.h> 5 #include <fcntl.h> 6 #include <sys/syscall.h> 7 #include <sys/mount.h> 8 #include <sys/reboot.h> 9 #include <linux/kexec.h> 10 11 /* from arch/x86/include/asm/setup.h */ 12 #define COMMAND_LINE_SIZE 2048 13 14 #define KERNEL_IMAGE "/kernel" 15 16 static int mount_filesystems(void) 17 { 18 if (mount("debugfs", "/debugfs", "debugfs", 0, NULL) < 0) 19 return -1; 20 21 return mount("proc", "/proc", "proc", 0, NULL); 22 } 23 24 static long kexec_file_load(int kernel_fd, int initrd_fd, 25 unsigned long cmdline_len, const char *cmdline, 26 unsigned long flags) 27 { 28 return syscall(__NR_kexec_file_load, kernel_fd, initrd_fd, cmdline_len, 29 cmdline, flags); 30 } 31 32 static int kexec_load(void) 33 { 34 char cmdline[COMMAND_LINE_SIZE]; 35 ssize_t len; 36 int fd, err; 37 38 fd = open("/proc/cmdline", O_RDONLY); 39 if (fd < 0) 40 return -1; 41 42 len = read(fd, cmdline, sizeof(cmdline)); 43 close(fd); 44 if (len < 0) 45 return -1; 46 47 /* replace \n with \0 */ 48 cmdline[len - 1] = 0; 49 fd = open(KERNEL_IMAGE, O_RDONLY); 50 if (fd < 0) 51 return -1; 52 53 err = kexec_file_load(fd, -1, len, cmdline, KEXEC_FILE_NO_INITRAMFS); 54 close(fd); 55 56 return err ? : 0; 57 } 58 59 int main(int argc, char *argv[]) 60 { 61 if (mount_filesystems()) 62 goto err_reboot; 63 64 if (kexec_load()) 65 goto err_reboot; 66 67 if (reboot(RB_KEXEC)) 68 goto err_reboot; 69 70 return 0; 71 72 err_reboot: 73 reboot(RB_AUTOBOOT); 74 return -1; 75 } 76