xref: /linux/tools/testing/selftests/kho/init.c (revision e2683c8868d03382da7e1ce8453b543a043066d1)
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