HelloWorld.c (6419B)
1#include "Base.h" 2#include "ProcessorBind.h" 3#include <Uefi.h> 4#include <Library/PcdLib.h> 5#include <Library/UefiLib.h> 6#include <Library/UefiApplicationEntryPoint.h> 7 8#define INTEL_ASM(x, ...) asm volatile \ 9 (".intel_syntax noprefix;" x ";.att_syntax prefix" : __VA_ARGS__) 10 11UINT64 12gcd(UINT64 a, UINT64 b) 13{ 14 while (a != b) { 15 if (a > b) { 16 a -= b; 17 } else { 18 b -= a; 19 } 20 } 21 22 return a; 23} 24 25UINT64 26digitsum(UINT64 a) 27{ 28 UINT64 sum = 0; 29 30 while (a > 0) { 31 sum += a % 10; 32 a /= 10; 33 } 34 35 return sum; 36} 37 38void 39register_handler(UINT8 no, UINT64 offset) 40{ 41 char buf[0x10]; 42 UINT16 cs; 43 44 INTEL_ASM("movw %[cs], cs;", [cs]"=r"(cs)); 45 46 UINT64 lower = ((offset & 0xffff0000UL) << 32) 47 | (0b1ULL << 47) /* P = 1 */ 48 | (0b1110ULL << 40) /* Interrupt gate */ 49 | ((UINT64)cs << 16) /* Segment */ 50 | (offset & 0xffffUL); /* low offset */ 51 UINT64 upper = (offset >> 32) & 0xffffffff; 52 53 INTEL_ASM( 54 "sidt [rsp];" 55 "movq rax, 2[rsp];" 56 "xor ebx, ebx;" 57 "movb bl, %[no];" 58 "shl rbx, 4;" 59 "add rax, rbx;" 60 "movq [rax], %[lower];" 61 "movq 8[rax], %[upper];", 62 [buf]"+m"(buf) 63 : [lower]"r"(lower), [upper]"r"(upper), [no]"r"(no) 64 : "rax", "rbx"); 65} 66 67EFI_STATUS 68EFIAPI 69UefiMain (IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) 70{ 71 UINT64 rax, rbx, rcx, rdx, res; 72 UINT32 eax, ebx; 73 UINT16 ocs; 74 75 Print ((CHAR16 *)PcdGetPtr (PcdHelloWorldPrintString)); 76 77 // _start is already 0x1000 aligned.. 78 // INTEL_ASM(".align 0x10000;"); 79 80 *(UINT64 *)(0x4000) = 0xe6ff; // jmp rsi trampoline 81 82 INTEL_ASM("jmp after_handler;"); 83 84 INTEL_ASM( 85 "handler:" 86 "movq [0x3ff8], rax;" 87 "iretq;"); 88 89 UINT64 addr; 90 INTEL_ASM("after_handler: lea %[addr], handler[rip]", 91 [addr]"=r"(addr)); 92 93 register_handler(0x69, addr); 94 95 INTEL_ASM( 96 // Setup CS+EIP of our segment. 97 "lea rax, post%=[rip]; push rax;" 98 "xor eax, eax; movw ax, cs; movd 4[rsp], eax;" 99 // Set magic value + 1. 100 "movq rdi, 0xfef0000013ffffff;" 101 // Loop until interrupt. 102 "loop%=: jmp loop%=; nop; nop;" 103 // Switch to original segment. 104 "movw di, cs; retfd; .code64; post%=:" 105 // Save registers. 106 "movw %[ocs], di;" 107 "push rax; push rbx; push rcx; push rdx;" 108 "pop %[rdx]; pop %[rcx]; pop %[rbx]; pop %[rax];", 109 [rax]"=r"(rax), [rbx]"=r"(rbx), 110 [rcx]"=r"(rcx), [rdx]"=r"(rdx), 111 [ocs]"=r"(ocs) 112 : : "rax", "rbx", "rcx", "rdx", "rdi"); 113 114 for (int i = 0; i < 69; i++) { 115 res = gcd(rax | (rbx << 32), rcx | (rdx << 32)); 116 eax = res; 117 ebx = res >> 32; 118 119 if (i == 68) break; 120 121 INTEL_ASM( 122 // Setup CS+EIP of our segment. 123 "lea rax, post%=[rip]; push rax;" 124 "xor eax, eax; movw ax, cs; movd 4[rsp], eax;" 125 // Setup CS+EIP of other segment. 126 "lea rax, pre%=[rip]; push rax;" 127 "xor eax, eax; movw ax, %[ocs]; movd 4[rsp], eax;" 128 // Set calculation result. 129 "movd eax, %[eax]; movd ebx, %[ebx];" 130 // Switch to other segment. 131 "retfd; .code32; pre%=:" 132 // Set magic. 133 "movd ecx, 0xfefefefe;" 134 // Loop until interrupt. 135 "loop%=: jmp loop%=; nop; nop;" 136 // Switch to original segment. 137 "movw di, cs; retfd; .code64; post%=:" 138 // Save registers. 139 "movw %[ocs], di;" 140 "push rax; push rbx; push rcx; push rdx;" 141 "pop %[rdx]; pop %[rcx]; pop %[rbx]; pop %[rax];", 142 [rdx]"=r"(rdx), [rcx]"=r"(rcx), 143 [rbx]"=r"(rbx), [rax]"=r"(rax), 144 [ocs]"+r"(ocs) 145 : [eax]"r"(eax), [ebx]"r"(ebx) 146 : "rax", "rbx", "rcx", "rdx", "rdi"); 147 } 148 149 INTEL_ASM( 150 // Setup CS+IP of our segment. 151 "lea rax, post%=[rip]; movq rsi, rax; push 0x4000;" 152 "movw ax, cs; movw 2[rsp], ax;" 153 // Setup CS+EIP of other segment. 154 "lea rax, pre%=[rip]; push rax;" 155 "xor eax, eax; movw ax, %[ocs]; movd 4[rsp], eax;" 156 // Set calculation result. 157 "movd eax, %[eax]; movd ebx, %[ebx];" 158 // Switch to other segment. 159 "retfd; .code32; pre%=:" 160 // Set magic. 161 "movd ecx, 0xfefefefe;" 162 // Loop until interrupt. 163 "loop%=: jmp loop%=; .rept 256; nop; .endr;" 164 // Switch to original segment. 165 ".code16; movw di, cs; retfw; .code64; post%=:" 166 // Fixup stack misalignment. 167 "add rsp, 4;" 168 // Save registers. 169 "movw %[ocs], di;" 170 "push rax; push rbx; push rcx; push rdx;" 171 "pop %[rdx]; pop %[rcx]; pop %[rbx]; pop %[rax];", 172 [rdx]"=r"(rdx), [rcx]"=r"(rcx), 173 [rbx]"=r"(rbx), [rax]"=r"(rax), 174 [ocs]"+r"(ocs) 175 : [eax]"r"(eax), [ebx]"r"(ebx) 176 : "rax", "rbx", "rcx", "rdx", "rdi", "rsi"); 177 178 for (int i = 0; i < 420; i++) { 179 eax = digitsum((rax & 0xffff) | ((rbx & 0xffff) << 16)); 180 181 if (i == 419) break; 182 183 INTEL_ASM( 184 // Setup CS+IP of our segment. 185 "lea rax, post%=[rip]; movq rsi, rax; push 0x4000;" 186 "movw ax, cs; movw 2[rsp], ax;" 187 // Setup CS+EIP of other segment. 188 "lea rax, pre%=[rip]; and rax, 0xffff; push rax;" 189 "xor eax, eax; movw ax, %[ocs]; movd 4[rsp], eax;" 190 // Set calculation result. 191 "movd eax, %[eax];" 192 // Switch to other segment 193 "retfd; pre%=: .code16; " 194 // Set magic (movw cl, 0xfefe is not 16-bit mode compat). 195 "movb cl, 0xfe; movb ch, 0xfe;" 196 // Loop until interrupt. 197 "loop%=: jmp loop%=; nop; nop;" 198 // Switch to original segment. 199 "movw di, cs; retfw; post%=: .code64;" 200 // Fixup stack misalignment. 201 "add rsp, 4;" 202 // Save registers. 203 "movw %[ocs], di;" 204 "push rax; push rbx; push rcx; push rdx;" 205 "pop %[rdx]; pop %[rcx]; pop %[rbx]; pop %[rax];", 206 [rdx]"=r"(rdx), [rcx]"=r"(rcx), 207 [rbx]"=r"(rbx), [rax]"=r"(rax), 208 [ocs]"+r"(ocs) 209 : [eax]"r"(eax) 210 : "rax", "rbx", "rcx", "rdx", "rsi", "rdi"); 211 } 212 213 INTEL_ASM( 214 // Setup CS+EIP of other segment. 215 "lea rax, pre%=[rip]; and rax, 0xffff; push rax;" 216 "xor eax, eax; movw ax, %[ocs]; movd 4[rsp], eax;" 217 // Set calculation result. 218 "movd eax, %[eax];" 219 // Switch to other segment 220 "retfd; pre%=: .code16; " 221 // Set magic (movw cl, 0xfefe is not 16-bit mode compat). 222 "movb cl, 0xfe; movb ch, 0xfe;" 223 // Loop until interrupt. 224 "loop%=: jmp loop%=; .code64;", 225 : [eax]"r"(eax), [ocs]"r"(ocs) 226 : "rax", "rbx", "rcx", "rdx"); 227 228 INTEL_ASM( 229 // Move rdx from interrupt. 230 "movq rdx, [0x3ff8];" 231 // Set magic. 232 "mov rcx, 0x12310FFAFFFFFFFF;" 233 // Loop until interrupt. 234 "loop2%=: jmp loop2%=;" 235 // Finally, flag. 236 "mov rax, 0x420; syscall", 237 : : "rcx", "rdx"); 238 239 // Interrupt 0x69 gets called in loop after interrupt code injection. 240 241 return EFI_SUCCESS; 242}