1 #include "defs.h"
2 
3 #include "xlat/kexec_load_flags.h"
4 #include "xlat/kexec_arch_values.h"
5 
6 #ifndef KEXEC_ARCH_MASK
7 # define KEXEC_ARCH_MASK 0xffff0000
8 #endif
9 #ifndef KEXEC_SEGMENT_MAX
10 # define KEXEC_SEGMENT_MAX 16
11 #endif
12 
13 static void
print_kexec_segments(struct tcb * tcp,unsigned long addr,unsigned long len)14 print_kexec_segments(struct tcb *tcp, unsigned long addr, unsigned long len)
15 {
16 #if SUPPORTED_PERSONALITIES > 1
17 	union {
18 		struct { u_int32_t buf, bufsz, mem, memsz; } seg32;
19 		struct { u_int64_t buf, bufsz, mem, memsz; } seg64;
20 	} seg;
21 # define sizeof_seg \
22 	(current_wordsize == 4 ? sizeof(seg.seg32) : sizeof(seg.seg64))
23 # define seg_buf \
24 	(current_wordsize == 4 ? (uint64_t) seg.seg32.buf : seg.seg64.buf)
25 # define seg_bufsz \
26 	(current_wordsize == 4 ? (uint64_t) seg.seg32.bufsz : seg.seg64.bufsz)
27 # define seg_mem \
28 	(current_wordsize == 4 ? (uint64_t) seg.seg32.mem : seg.seg64.mem)
29 # define seg_memsz \
30 	(current_wordsize == 4 ? (uint64_t) seg.seg32.memsz : seg.seg64.memsz)
31 #else
32 	struct {
33 		void *buf;
34 		size_t bufsz;
35 		void *mem;
36 		size_t memsz;
37 	} seg;
38 # define sizeof_seg sizeof(seg)
39 # define seg_buf seg.buf
40 # define seg_bufsz seg.bufsz
41 # define seg_mem seg.mem
42 # define seg_memsz seg.memsz
43 #endif
44 	unsigned int i, failed;
45 
46 	if (!len) {
47 		tprints("[]");
48 		return;
49 	}
50 
51 	if (len > KEXEC_SEGMENT_MAX) {
52 		tprintf("%#lx", addr);
53 		return;
54 	}
55 
56 	failed = 0;
57 	tprints("[");
58 	for (i = 0; i < len; ++i) {
59 		if (i)
60 			tprints(", ");
61 		if (umoven(tcp, addr + i * sizeof_seg, sizeof_seg, &seg) < 0) {
62 			tprints("?");
63 			failed = 1;
64 			break;
65 		}
66 		tprintf("{%#lx, %lu, %#lx, %lu}",
67 			(long) seg_buf, (unsigned long) seg_bufsz,
68 			(long) seg_mem, (unsigned long) seg_memsz);
69 	}
70 	tprints("]");
71 	if (failed)
72 		tprintf(" %#lx", addr);
73 }
74 
SYS_FUNC(kexec_load)75 SYS_FUNC(kexec_load)
76 {
77 	unsigned long n;
78 
79 	if (exiting(tcp))
80 		return 0;
81 
82 	/* entry, nr_segments */
83 	tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
84 
85 	/* segments */
86 	print_kexec_segments(tcp, tcp->u_arg[2], tcp->u_arg[1]);
87 	tprints(", ");
88 
89 	/* flags */
90 	n = tcp->u_arg[3];
91 	printxval(kexec_arch_values, n & KEXEC_ARCH_MASK, "KEXEC_ARCH_???");
92 	n &= ~KEXEC_ARCH_MASK;
93 	if (n) {
94 		tprints("|");
95 		printflags(kexec_load_flags, n, "KEXEC_???");
96 	}
97 
98 	return 0;
99 }
100