9 #include <sys/syscall.h>
10 #include <sys/types.h>
16 // Offsets same as in kernel asm/kexec.h
17 #define KEXEC_ARM_ATAGS_OFFSET 0x1000
18 #define KEXEC_ARM_ZIMAGE_OFFSET 0x8000
20 #define MEMORY_SIZE 0x0800000
21 // Physical buffer address cannot overlap with other regions
22 #define START_ADDRESS 0x44000000
24 #define ROUND_TO_PAGE(address,pagesize) ((address + pagesize - 1) & (~(pagesize - 1)))
27 * Gives file position and resets current position to begining of file
29 int get_file_size(int f)
36 int test_kexeccall() {
39 rv = kexec_load(0, 0, NULL, KEXEC_ARCH_DEFAULT);
42 printf("ERROR: kexec_load: %d \n", errno);
46 printf("Kexec test: Success \n");
54 "usage: kexecload [ <option> ] <atags path> <kernel path>\n"
58 " -s <start address> specify start address of kernel\n"
63 * Loads kexec into the kernel and sets kexec on crash
65 int main(int argc, char *argv[])
75 struct kexec_segment segment[2];
76 int page_size = getpagesize();
77 void *start_address = (void *)START_ADDRESS;
80 const struct option longopts[] = {
81 {"start_address", required_argument, 0, 's'},
89 c = getopt_long(argc, argv, "s:th", longopts, NULL);
93 /* Alphabetical cases */
96 start_address = (void *) strtoul(optarg, 0, 16);
119 atag_file = open(argv[0], O_RDONLY);
120 zimage_file = open(argv[1], O_RDONLY);
122 if (atag_file < 0 || zimage_file < 0) {
123 fprintf(stderr, "Error during opening of atag file or the zImage file %s\n", strerror(errno));
127 atag_size = ROUND_TO_PAGE(get_file_size(atag_file), page_size);
128 zimage_size = ROUND_TO_PAGE(get_file_size(zimage_file), page_size);
130 if (atag_size >= KEXEC_ARM_ZIMAGE_OFFSET - KEXEC_ARM_ATAGS_OFFSET) {
131 fprintf(stderr, "Atag file is too large\n");
135 atag_buffer = (char *) mmap(NULL, atag_size, PROT_READ, MAP_POPULATE | MAP_PRIVATE, atag_file, 0);
136 zimage_buffer = (char *) mmap(NULL, zimage_size, PROT_READ, MAP_POPULATE | MAP_PRIVATE, zimage_file, 0);
138 if(atag_buffer == MAP_FAILED || zimage_buffer == MAP_FAILED) {
139 fprintf(stderr, "Unable to map files into memory");
143 segment[0].buf = zimage_buffer;
144 segment[0].bufsz = zimage_size;
145 segment[0].mem = (void *) ((uintptr_t) start_address + KEXEC_ARM_ZIMAGE_OFFSET);
146 segment[0].memsz = zimage_size;
148 segment[1].buf = atag_buffer;
149 segment[1].bufsz = atag_size;
150 segment[1].mem = (void *) ((uintptr_t) start_address + KEXEC_ARM_ATAGS_OFFSET);
151 segment[1].memsz = atag_size;
153 rv = kexec_load(((uintptr_t) start_address + KEXEC_ARM_ZIMAGE_OFFSET),
154 2, (void *) segment, KEXEC_ARCH_DEFAULT | KEXEC_ON_CRASH);
157 fprintf(stderr, "Kexec_load returned non-zero exit code: %d with errno %d\n", rv, errno);
161 printf("Done! Kexec loaded\n");
162 printf("New kernel should start at 0x%08x\n", START_ADDRESS + KEXEC_ARM_ZIMAGE_OFFSET);