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