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