|
| 1 | +// UEFI Call Stub for x86_64 |
| 2 | +// |
| 3 | +// Generic stub for calling any UEFI function via the Microsoft x64 ABI. |
| 4 | +// |
| 5 | +// Go signature: func callAsm(fn uintptr, args *uintptr, nargs uintptr) Status |
| 6 | +// MS x64 entry: |
| 7 | +// RCX = fn (function pointer to call) |
| 8 | +// RDX = args (pointer to uintptr array of arguments) |
| 9 | +// R8 = nargs (number of arguments, 0-N) |
| 10 | +// |
| 11 | +// MS x64 ABI register mapping for the callee: |
| 12 | +// Args 1-4: RCX, RDX, R8, R9 |
| 13 | +// Args 5+: stack (after 32-byte shadow space) |
| 14 | +// Return: RAX |
| 15 | +// Stack: 16-byte aligned before CALL |
| 16 | +// |
| 17 | + |
| 18 | +.section .text.uefiCall,"ax" |
| 19 | +.global uefiCall |
| 20 | +uefiCall: |
| 21 | + pushq %rbp |
| 22 | + movq %rsp, %rbp |
| 23 | + pushq %rsi |
| 24 | + pushq %rdi |
| 25 | + |
| 26 | + movq %rcx, %r10 // Save fn |
| 27 | + movq %rdx, %rsi // Save args pointer |
| 28 | + movq %r8, %rdi // Save nargs |
| 29 | + |
| 30 | + // Calculate stack space: align16(32 + max(0, nargs-4) * 8) |
| 31 | + // After 3 pushes, RSP is 16-byte aligned. Subtracting an aligned |
| 32 | + // value keeps it aligned for the CALL instruction. |
| 33 | + xorq %rax, %rax |
| 34 | + cmpq $4, %rdi |
| 35 | + jle 1f |
| 36 | + movq %rdi, %rax |
| 37 | + subq $4, %rax |
| 38 | +1: |
| 39 | + shlq $3, %rax // nStackArgs * 8 |
| 40 | + addq $47, %rax // + 32 (shadow) + 15 (round-up) |
| 41 | + andq $-16, %rax // align to 16 |
| 42 | + subq %rax, %rsp |
| 43 | + |
| 44 | + // Copy stack args: args[4..nargs-1] -> RSP+32+j*8 |
| 45 | + movq %rdi, %rcx |
| 46 | + subq $4, %rcx |
| 47 | + jle 2f |
| 48 | + xorq %rax, %rax |
| 49 | +3: movq 32(%rsi,%rax,8), %r11 |
| 50 | + movq %r11, 32(%rsp,%rax,8) |
| 51 | + incq %rax |
| 52 | + cmpq %rcx, %rax |
| 53 | + jl 3b |
| 54 | +2: |
| 55 | + // Load register args |
| 56 | + xorq %rcx, %rcx |
| 57 | + xorq %rdx, %rdx |
| 58 | + xorq %r8, %r8 |
| 59 | + xorq %r9, %r9 |
| 60 | + |
| 61 | + testq %rdi, %rdi |
| 62 | + jz 4f |
| 63 | + movq 0(%rsi), %rcx // args[0] -> RCX |
| 64 | + cmpq $2, %rdi |
| 65 | + jl 4f |
| 66 | + movq 8(%rsi), %rdx // args[1] -> RDX |
| 67 | + cmpq $3, %rdi |
| 68 | + jl 4f |
| 69 | + movq 16(%rsi), %r8 // args[2] -> R8 |
| 70 | + cmpq $4, %rdi |
| 71 | + jl 4f |
| 72 | + movq 24(%rsi), %r9 // args[3] -> R9 |
| 73 | +4: |
| 74 | + callq *%r10 |
| 75 | + |
| 76 | + leaq -16(%rbp), %rsp |
| 77 | + popq %rdi |
| 78 | + popq %rsi |
| 79 | + popq %rbp |
| 80 | + retq |
0 commit comments