75 lines · 1.4 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0 #include <stdio.h>#include <unistd.h>#include <fcntl.h>#include <sys/syscall.h>#include <sys/mount.h>#include <sys/reboot.h>#include <linux/kexec.h> /* from arch/x86/include/asm/setup.h */#define COMMAND_LINE_SIZE	2048 #define KERNEL_IMAGE "/kernel" static int mount_filesystems(void){	if (mount("debugfs", "/debugfs", "debugfs", 0, NULL) < 0)		return -1; 	return mount("proc", "/proc", "proc", 0, NULL);} static long kexec_file_load(int kernel_fd, int initrd_fd,			    unsigned long cmdline_len, const char *cmdline,			    unsigned long flags){	return syscall(__NR_kexec_file_load, kernel_fd, initrd_fd, cmdline_len,		       cmdline, flags);} static int kexec_load(void){	char cmdline[COMMAND_LINE_SIZE];	ssize_t len;	int fd, err; 	fd = open("/proc/cmdline", O_RDONLY);	if (fd < 0)		return -1; 	len = read(fd, cmdline, sizeof(cmdline));	close(fd);	if (len < 0)		return -1; 	/* replace \n with \0 */	cmdline[len - 1] = 0;	fd = open(KERNEL_IMAGE, O_RDONLY);	if (fd < 0)		return -1; 	err = kexec_file_load(fd, -1, len, cmdline, KEXEC_FILE_NO_INITRAMFS);	close(fd); 	return err ? : 0;} int main(int argc, char *argv[]){	if (mount_filesystems())		goto err_reboot; 	if (kexec_load())		goto err_reboot; 	if (reboot(RB_KEXEC))		goto err_reboot; 	return 0; err_reboot:	reboot(RB_AUTOBOOT);	return -1;}