xref: /linux/tools/testing/selftests/kho/init.c (revision 0074281bb6316108e0cff094bd4db78ab3eee236)
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 
mount_filesystems(void)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 
kho_enable(void)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 
kexec_file_load(int kernel_fd,int initrd_fd,unsigned long cmdline_len,const char * cmdline,unsigned long flags)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 
kexec_load(void)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 
main(int argc,char * argv[])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