1 // SPDX-License-Identifier: GPL-2.0 2 3 #ifndef NOLIBC 4 #include <errno.h> 5 #include <stdio.h> 6 #include <unistd.h> 7 #include <fcntl.h> 8 #include <syscall.h> 9 #include <sys/mount.h> 10 #include <sys/reboot.h> 11 #endif 12 13 /* from arch/x86/include/asm/setup.h */ 14 #define COMMAND_LINE_SIZE 2048 15 16 /* from include/linux/kexex.h */ 17 #define KEXEC_FILE_NO_INITRAMFS 0x00000004 18 19 #define KHO_FINILIZE "/debugfs/kho/out/finalize" 20 #define KERNEL_IMAGE "/kernel" 21 22 static int mount_filesystems(void) 23 { 24 if (mount("debugfs", "/debugfs", "debugfs", 0, NULL) < 0) 25 return -1; 26 27 return mount("proc", "/proc", "proc", 0, NULL); 28 } 29 30 static int kho_enable(void) 31 { 32 const char enable[] = "1"; 33 int fd; 34 35 fd = open(KHO_FINILIZE, O_RDWR); 36 if (fd < 0) 37 return -1; 38 39 if (write(fd, enable, sizeof(enable)) != sizeof(enable)) 40 return 1; 41 42 close(fd); 43 return 0; 44 } 45 46 static long kexec_file_load(int kernel_fd, int initrd_fd, 47 unsigned long cmdline_len, const char *cmdline, 48 unsigned long flags) 49 { 50 return syscall(__NR_kexec_file_load, kernel_fd, initrd_fd, cmdline_len, 51 cmdline, flags); 52 } 53 54 static int kexec_load(void) 55 { 56 char cmdline[COMMAND_LINE_SIZE]; 57 ssize_t len; 58 int fd, err; 59 60 fd = open("/proc/cmdline", O_RDONLY); 61 if (fd < 0) 62 return -1; 63 64 len = read(fd, cmdline, sizeof(cmdline)); 65 close(fd); 66 if (len < 0) 67 return -1; 68 69 /* replace \n with \0 */ 70 cmdline[len - 1] = 0; 71 fd = open(KERNEL_IMAGE, O_RDONLY); 72 if (fd < 0) 73 return -1; 74 75 err = kexec_file_load(fd, -1, len, cmdline, KEXEC_FILE_NO_INITRAMFS); 76 close(fd); 77 78 return err ? : 0; 79 } 80 81 int main(int argc, char *argv[]) 82 { 83 if (mount_filesystems()) 84 goto err_reboot; 85 86 if (kho_enable()) 87 goto err_reboot; 88 89 if (kexec_load()) 90 goto err_reboot; 91 92 if (reboot(RB_KEXEC)) 93 goto err_reboot; 94 95 return 0; 96 97 err_reboot: 98 reboot(RB_AUTOBOOT); 99 return -1; 100 } 101