1 #include <unistd.h> 2 #include <errno.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <linux/kexec.h> 6 #include <linux/reboot.h> 7 #include <sys/reboot.h> 8 #include <sys/syscall.h> 9 10 asm( 11 " .code64\n" 12 " .data\n" 13 "purgatory_start:\n" 14 15 // Trigger kexec debug exception handling 16 " int3\n" 17 18 // Set load address for next time 19 " leaq purgatory_start_b(%rip), %r11\n" 20 " movq %r11, 8(%rsp)\n" 21 22 // Back to Linux 23 " ret\n" 24 25 // Same again 26 "purgatory_start_b:\n" 27 28 // Trigger kexec debug exception handling 29 " int3\n" 30 31 // Set load address for next time 32 " leaq purgatory_start(%rip), %r11\n" 33 " movq %r11, 8(%rsp)\n" 34 35 // Back to Linux 36 " ret\n" 37 38 "purgatory_end:\n" 39 ".previous" 40 ); 41 extern char purgatory_start[], purgatory_end[]; 42 43 int main (void) 44 { 45 struct kexec_segment segment = {}; 46 int ret; 47 48 segment.buf = purgatory_start; 49 segment.bufsz = purgatory_end - purgatory_start; 50 segment.mem = (void *)0x400000; 51 segment.memsz = 0x1000; 52 ret = syscall(__NR_kexec_load, 0x400000, 1, &segment, KEXEC_PRESERVE_CONTEXT); 53 if (ret) { 54 perror("kexec_load"); 55 exit(1); 56 } 57 58 ret = syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_KEXEC); 59 if (ret) { 60 perror("kexec reboot"); 61 exit(1); 62 } 63 64 ret = syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_KEXEC); 65 if (ret) { 66 perror("kexec reboot"); 67 exit(1); 68 } 69 printf("Success\n"); 70 return 0; 71 } 72 73