1*288bf522SAndroid Build Coastguard Worker #include <errno.h>
2*288bf522SAndroid Build Coastguard Worker #include <fcntl.h>
3*288bf522SAndroid Build Coastguard Worker #include <getopt.h>
4*288bf522SAndroid Build Coastguard Worker #include <stdio.h>
5*288bf522SAndroid Build Coastguard Worker #include <stdlib.h>
6*288bf522SAndroid Build Coastguard Worker #include <string.h>
7*288bf522SAndroid Build Coastguard Worker #include <sys/mman.h>
8*288bf522SAndroid Build Coastguard Worker #include <sys/stat.h>
9*288bf522SAndroid Build Coastguard Worker #include <sys/syscall.h>
10*288bf522SAndroid Build Coastguard Worker #include <sys/types.h>
11*288bf522SAndroid Build Coastguard Worker #include <sys/wait.h>
12*288bf522SAndroid Build Coastguard Worker #include <unistd.h>
13*288bf522SAndroid Build Coastguard Worker
14*288bf522SAndroid Build Coastguard Worker #include "kexec.h"
15*288bf522SAndroid Build Coastguard Worker
16*288bf522SAndroid Build Coastguard Worker // Offsets same as in kernel asm/kexec.h
17*288bf522SAndroid Build Coastguard Worker #define KEXEC_ARM_ATAGS_OFFSET 0x1000
18*288bf522SAndroid Build Coastguard Worker #define KEXEC_ARM_ZIMAGE_OFFSET 0x8000
19*288bf522SAndroid Build Coastguard Worker
20*288bf522SAndroid Build Coastguard Worker #define MEMORY_SIZE 0x0800000
21*288bf522SAndroid Build Coastguard Worker // Physical buffer address cannot overlap with other regions
22*288bf522SAndroid Build Coastguard Worker #define START_ADDRESS 0x44000000
23*288bf522SAndroid Build Coastguard Worker
24*288bf522SAndroid Build Coastguard Worker #define ROUND_TO_PAGE(address, pagesize) (((address) + (pagesize)-1) & (~((pagesize)-1)))
25*288bf522SAndroid Build Coastguard Worker
26*288bf522SAndroid Build Coastguard Worker /*
27*288bf522SAndroid Build Coastguard Worker * Gives file position and resets current position to begining of file
28*288bf522SAndroid Build Coastguard Worker */
get_file_size(int f)29*288bf522SAndroid Build Coastguard Worker int get_file_size(int f) {
30*288bf522SAndroid Build Coastguard Worker struct stat st;
31*288bf522SAndroid Build Coastguard Worker fstat(f, &st);
32*288bf522SAndroid Build Coastguard Worker return st.st_size;
33*288bf522SAndroid Build Coastguard Worker }
34*288bf522SAndroid Build Coastguard Worker
test_kexeccall()35*288bf522SAndroid Build Coastguard Worker int test_kexeccall() {
36*288bf522SAndroid Build Coastguard Worker int rv;
37*288bf522SAndroid Build Coastguard Worker
38*288bf522SAndroid Build Coastguard Worker rv = kexec_load(0, 0, NULL, KEXEC_ARCH_DEFAULT);
39*288bf522SAndroid Build Coastguard Worker
40*288bf522SAndroid Build Coastguard Worker if (rv != 0) {
41*288bf522SAndroid Build Coastguard Worker printf("ERROR: kexec_load: %d \n", errno);
42*288bf522SAndroid Build Coastguard Worker return 1;
43*288bf522SAndroid Build Coastguard Worker }
44*288bf522SAndroid Build Coastguard Worker
45*288bf522SAndroid Build Coastguard Worker printf("Kexec test: Success \n");
46*288bf522SAndroid Build Coastguard Worker
47*288bf522SAndroid Build Coastguard Worker return 0;
48*288bf522SAndroid Build Coastguard Worker }
49*288bf522SAndroid Build Coastguard Worker
usage(void)50*288bf522SAndroid Build Coastguard Worker void usage(void) {
51*288bf522SAndroid Build Coastguard Worker fprintf(stderr,
52*288bf522SAndroid Build Coastguard Worker "usage: kexecload [ <option> ] <atags path> <kernel path>\n"
53*288bf522SAndroid Build Coastguard Worker "\n"
54*288bf522SAndroid Build Coastguard Worker "options:\n"
55*288bf522SAndroid Build Coastguard Worker " -t tests syscall\n"
56*288bf522SAndroid Build Coastguard Worker " -s <start address> specify start address of kernel\n");
57*288bf522SAndroid Build Coastguard Worker }
58*288bf522SAndroid Build Coastguard Worker
59*288bf522SAndroid Build Coastguard Worker /*
60*288bf522SAndroid Build Coastguard Worker * Loads kexec into the kernel and sets kexec on crash
61*288bf522SAndroid Build Coastguard Worker */
main(int argc,char * argv[])62*288bf522SAndroid Build Coastguard Worker int main(int argc, char* argv[]) {
63*288bf522SAndroid Build Coastguard Worker int rv;
64*288bf522SAndroid Build Coastguard Worker int atag_file, zimage_file;
65*288bf522SAndroid Build Coastguard Worker int atag_size, zimage_size;
66*288bf522SAndroid Build Coastguard Worker void* atag_buffer;
67*288bf522SAndroid Build Coastguard Worker void* zimage_buffer;
68*288bf522SAndroid Build Coastguard Worker struct kexec_segment segment[2];
69*288bf522SAndroid Build Coastguard Worker int page_size = getpagesize();
70*288bf522SAndroid Build Coastguard Worker void* start_address = (void*)START_ADDRESS;
71*288bf522SAndroid Build Coastguard Worker int c;
72*288bf522SAndroid Build Coastguard Worker
73*288bf522SAndroid Build Coastguard Worker const struct option longopts[] = {{"start_address", required_argument, 0, 's'},
74*288bf522SAndroid Build Coastguard Worker {"test", 0, 0, 't'},
75*288bf522SAndroid Build Coastguard Worker {"help", 0, 0, 'h'},
76*288bf522SAndroid Build Coastguard Worker {0, 0, 0, 0}};
77*288bf522SAndroid Build Coastguard Worker
78*288bf522SAndroid Build Coastguard Worker while (1) {
79*288bf522SAndroid Build Coastguard Worker c = getopt_long(argc, argv, "s:th", longopts, NULL);
80*288bf522SAndroid Build Coastguard Worker if (c < 0) {
81*288bf522SAndroid Build Coastguard Worker break;
82*288bf522SAndroid Build Coastguard Worker }
83*288bf522SAndroid Build Coastguard Worker /* Alphabetical cases */
84*288bf522SAndroid Build Coastguard Worker switch (c) {
85*288bf522SAndroid Build Coastguard Worker case 's':
86*288bf522SAndroid Build Coastguard Worker start_address = (void*)strtoul(optarg, 0, 16);
87*288bf522SAndroid Build Coastguard Worker break;
88*288bf522SAndroid Build Coastguard Worker case 'h':
89*288bf522SAndroid Build Coastguard Worker usage();
90*288bf522SAndroid Build Coastguard Worker return 1;
91*288bf522SAndroid Build Coastguard Worker case 't':
92*288bf522SAndroid Build Coastguard Worker test_kexeccall();
93*288bf522SAndroid Build Coastguard Worker return 1;
94*288bf522SAndroid Build Coastguard Worker case '?':
95*288bf522SAndroid Build Coastguard Worker return 1;
96*288bf522SAndroid Build Coastguard Worker default:
97*288bf522SAndroid Build Coastguard Worker abort();
98*288bf522SAndroid Build Coastguard Worker }
99*288bf522SAndroid Build Coastguard Worker }
100*288bf522SAndroid Build Coastguard Worker
101*288bf522SAndroid Build Coastguard Worker argc -= optind;
102*288bf522SAndroid Build Coastguard Worker argv += optind;
103*288bf522SAndroid Build Coastguard Worker
104*288bf522SAndroid Build Coastguard Worker if (argc < 2) {
105*288bf522SAndroid Build Coastguard Worker usage();
106*288bf522SAndroid Build Coastguard Worker return 1;
107*288bf522SAndroid Build Coastguard Worker }
108*288bf522SAndroid Build Coastguard Worker
109*288bf522SAndroid Build Coastguard Worker atag_file = open(argv[0], O_RDONLY);
110*288bf522SAndroid Build Coastguard Worker zimage_file = open(argv[1], O_RDONLY);
111*288bf522SAndroid Build Coastguard Worker
112*288bf522SAndroid Build Coastguard Worker if (atag_file < 0 || zimage_file < 0) {
113*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "Error during opening of atag file or the zImage file %s\n",
114*288bf522SAndroid Build Coastguard Worker strerror(errno));
115*288bf522SAndroid Build Coastguard Worker return 1;
116*288bf522SAndroid Build Coastguard Worker }
117*288bf522SAndroid Build Coastguard Worker
118*288bf522SAndroid Build Coastguard Worker atag_size = ROUND_TO_PAGE(get_file_size(atag_file), page_size);
119*288bf522SAndroid Build Coastguard Worker zimage_size = ROUND_TO_PAGE(get_file_size(zimage_file), page_size);
120*288bf522SAndroid Build Coastguard Worker
121*288bf522SAndroid Build Coastguard Worker if (atag_size >= KEXEC_ARM_ZIMAGE_OFFSET - KEXEC_ARM_ATAGS_OFFSET) {
122*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "Atag file is too large\n");
123*288bf522SAndroid Build Coastguard Worker return 1;
124*288bf522SAndroid Build Coastguard Worker }
125*288bf522SAndroid Build Coastguard Worker
126*288bf522SAndroid Build Coastguard Worker atag_buffer = (char*)mmap(NULL, atag_size, PROT_READ, MAP_POPULATE | MAP_PRIVATE, atag_file, 0);
127*288bf522SAndroid Build Coastguard Worker zimage_buffer =
128*288bf522SAndroid Build Coastguard Worker (char*)mmap(NULL, zimage_size, PROT_READ, MAP_POPULATE | MAP_PRIVATE, zimage_file, 0);
129*288bf522SAndroid Build Coastguard Worker
130*288bf522SAndroid Build Coastguard Worker if (atag_buffer == MAP_FAILED || zimage_buffer == MAP_FAILED) {
131*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "Unable to map files into memory");
132*288bf522SAndroid Build Coastguard Worker return 1;
133*288bf522SAndroid Build Coastguard Worker }
134*288bf522SAndroid Build Coastguard Worker
135*288bf522SAndroid Build Coastguard Worker segment[0].buf = zimage_buffer;
136*288bf522SAndroid Build Coastguard Worker segment[0].bufsz = zimage_size;
137*288bf522SAndroid Build Coastguard Worker segment[0].mem = (void*)((uintptr_t)start_address + KEXEC_ARM_ZIMAGE_OFFSET);
138*288bf522SAndroid Build Coastguard Worker segment[0].memsz = zimage_size;
139*288bf522SAndroid Build Coastguard Worker
140*288bf522SAndroid Build Coastguard Worker segment[1].buf = atag_buffer;
141*288bf522SAndroid Build Coastguard Worker segment[1].bufsz = atag_size;
142*288bf522SAndroid Build Coastguard Worker segment[1].mem = (void*)((uintptr_t)start_address + KEXEC_ARM_ATAGS_OFFSET);
143*288bf522SAndroid Build Coastguard Worker segment[1].memsz = atag_size;
144*288bf522SAndroid Build Coastguard Worker
145*288bf522SAndroid Build Coastguard Worker rv = kexec_load(((uintptr_t)start_address + KEXEC_ARM_ZIMAGE_OFFSET), 2, (void*)segment,
146*288bf522SAndroid Build Coastguard Worker KEXEC_ARCH_DEFAULT | KEXEC_ON_CRASH);
147*288bf522SAndroid Build Coastguard Worker
148*288bf522SAndroid Build Coastguard Worker if (rv != 0) {
149*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "Kexec_load returned non-zero exit code: %d with errno %d\n", rv, errno);
150*288bf522SAndroid Build Coastguard Worker return 1;
151*288bf522SAndroid Build Coastguard Worker }
152*288bf522SAndroid Build Coastguard Worker
153*288bf522SAndroid Build Coastguard Worker printf("Done! Kexec loaded\n");
154*288bf522SAndroid Build Coastguard Worker printf("New kernel should start at 0x%08x\n", START_ADDRESS + KEXEC_ARM_ZIMAGE_OFFSET);
155*288bf522SAndroid Build Coastguard Worker
156*288bf522SAndroid Build Coastguard Worker return 0;
157*288bf522SAndroid Build Coastguard Worker }
158