xref: /aosp_15_r20/system/extras/kexec_tools/kexecload.c (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
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