1 1.1 jakllsch /* $NetBSD: efi_stub.S,v 1.1.1.1 2014/04/01 16:16:07 jakllsch Exp $ */ 2 1.1 jakllsch 3 1.1 jakllsch /* 4 1.1 jakllsch * Function calling ABI conversion from Linux to EFI for x86_64 5 1.1 jakllsch * 6 1.1 jakllsch * Copyright (C) 2007 Intel Corp 7 1.1 jakllsch * Bibo Mao <bibo.mao (at) intel.com> 8 1.1 jakllsch * Huang Ying <ying.huang (at) intel.com> 9 1.1 jakllsch * Copyright (C) 2012 Felipe Contreras <felipe.contreras (at) gmail.com> 10 1.1 jakllsch */ 11 1.1 jakllsch 12 1.1 jakllsch #if !defined(HAVE_USE_MS_ABI) 13 1.1 jakllsch /* 14 1.1 jakllsch * EFI calling conventions are documented at: 15 1.1 jakllsch * http://msdn.microsoft.com/en-us/library/ms235286%28v=vs.80%29.aspx 16 1.1 jakllsch * ELF calling conventions are documented at: 17 1.1 jakllsch * http://www.x86-64.org/documentation/abi.pdf 18 1.1 jakllsch * 19 1.1 jakllsch * Basically here are the conversion rules: 20 1.1 jakllsch * a) our function pointer is in %rdi 21 1.1 jakllsch * b) rsi through r8 (elf) aka rcx through r9 (ms) require stack space 22 1.1 jakllsch * on the MS side even though it's not getting used at all. 23 1.1 jakllsch * c) 8(%rsp) is always aligned to 16 in ELF, so %rsp is shifted 8 bytes extra 24 1.1 jakllsch * d) arguments are as follows: (elf -> ms) 25 1.1 jakllsch * 1) rdi -> rcx (32 saved) 26 1.1 jakllsch * 2) rsi -> rdx (32 saved) 27 1.1 jakllsch * 3) rdx -> r8 (32 saved) 28 1.1 jakllsch * 4) rcx -> r9 (32 saved) 29 1.1 jakllsch * 5) r8 -> 32(%rsp) (32 saved) 30 1.1 jakllsch * 6) r9 -> 40(%rsp) (48 saved) 31 1.1 jakllsch * 7) 8(%rsp) -> 48(%rsp) (48 saved) 32 1.1 jakllsch * 8) 16(%rsp) -> 56(%rsp) (64 saved) 33 1.1 jakllsch * 9) 24(%rsp) -> 64(%rsp) (64 saved) 34 1.1 jakllsch * 10) 32(%rsp) -> 72(%rsp) (80 saved) 35 1.1 jakllsch * e) because the first argument we recieve in a thunker is actually the 36 1.1 jakllsch * function to be called, arguments are offset as such: 37 1.1 jakllsch * 0) rdi -> caller 38 1.1 jakllsch * 1) rsi -> rcx (32 saved) 39 1.1 jakllsch * 2) rdx -> rdx (32 saved) 40 1.1 jakllsch * 3) rcx -> r8 (32 saved) 41 1.1 jakllsch * 4) r8 -> r9 (32 saved) 42 1.1 jakllsch * 5) r9 -> 32(%rsp) (32 saved) 43 1.1 jakllsch * 6) 8(%rsp) -> 40(%rsp) (48 saved) 44 1.1 jakllsch * 7) 16(%rsp) -> 48(%rsp) (48 saved) 45 1.1 jakllsch * 8) 24(%rsp) -> 56(%rsp) (64 saved) 46 1.1 jakllsch * 9) 32(%rsp) -> 64(%rsp) (64 saved) 47 1.1 jakllsch * 10) 40(%rsp) -> 72(%rsp) (80 saved) 48 1.1 jakllsch * f) arguments need to be moved in opposite order to avoid clobbering 49 1.1 jakllsch */ 50 1.1 jakllsch 51 1.1 jakllsch #define ENTRY(name) \ 52 1.1 jakllsch .globl name; \ 53 1.1 jakllsch name: 54 1.1 jakllsch 55 1.1 jakllsch ENTRY(efi_call0) 56 1.1 jakllsch subq $40, %rsp 57 1.1 jakllsch call *%rdi 58 1.1 jakllsch addq $40, %rsp 59 1.1 jakllsch ret 60 1.1 jakllsch 61 1.1 jakllsch ENTRY(efi_call1) 62 1.1 jakllsch subq $40, %rsp 63 1.1 jakllsch mov %rsi, %rcx 64 1.1 jakllsch call *%rdi 65 1.1 jakllsch addq $40, %rsp 66 1.1 jakllsch ret 67 1.1 jakllsch 68 1.1 jakllsch ENTRY(efi_call2) 69 1.1 jakllsch subq $40, %rsp 70 1.1 jakllsch /* mov %rdx, %rdx */ 71 1.1 jakllsch mov %rsi, %rcx 72 1.1 jakllsch call *%rdi 73 1.1 jakllsch addq $40, %rsp 74 1.1 jakllsch ret 75 1.1 jakllsch 76 1.1 jakllsch ENTRY(efi_call3) 77 1.1 jakllsch subq $40, %rsp 78 1.1 jakllsch mov %rcx, %r8 79 1.1 jakllsch /* mov %rdx, %rdx */ 80 1.1 jakllsch mov %rsi, %rcx 81 1.1 jakllsch call *%rdi 82 1.1 jakllsch addq $40, %rsp 83 1.1 jakllsch ret 84 1.1 jakllsch 85 1.1 jakllsch ENTRY(efi_call4) 86 1.1 jakllsch subq $40, %rsp 87 1.1 jakllsch mov %r8, %r9 88 1.1 jakllsch mov %rcx, %r8 89 1.1 jakllsch /* mov %rdx, %rdx */ 90 1.1 jakllsch mov %rsi, %rcx 91 1.1 jakllsch call *%rdi 92 1.1 jakllsch addq $40, %rsp 93 1.1 jakllsch ret 94 1.1 jakllsch 95 1.1 jakllsch ENTRY(efi_call5) 96 1.1 jakllsch subq $40, %rsp 97 1.1 jakllsch mov %r9, 32(%rsp) 98 1.1 jakllsch mov %r8, %r9 99 1.1 jakllsch mov %rcx, %r8 100 1.1 jakllsch /* mov %rdx, %rdx */ 101 1.1 jakllsch mov %rsi, %rcx 102 1.1 jakllsch call *%rdi 103 1.1 jakllsch addq $40, %rsp 104 1.1 jakllsch ret 105 1.1 jakllsch 106 1.1 jakllsch ENTRY(efi_call6) 107 1.1 jakllsch subq $56, %rsp 108 1.1 jakllsch mov 56+8(%rsp), %rax 109 1.1 jakllsch mov %rax, 40(%rsp) 110 1.1 jakllsch mov %r9, 32(%rsp) 111 1.1 jakllsch mov %r8, %r9 112 1.1 jakllsch mov %rcx, %r8 113 1.1 jakllsch /* mov %rdx, %rdx */ 114 1.1 jakllsch mov %rsi, %rcx 115 1.1 jakllsch call *%rdi 116 1.1 jakllsch addq $56, %rsp 117 1.1 jakllsch ret 118 1.1 jakllsch 119 1.1 jakllsch ENTRY(efi_call7) 120 1.1 jakllsch subq $56, %rsp 121 1.1 jakllsch mov 56+16(%rsp), %rax 122 1.1 jakllsch mov %rax, 48(%rsp) 123 1.1 jakllsch mov 56+8(%rsp), %rax 124 1.1 jakllsch mov %rax, 40(%rsp) 125 1.1 jakllsch mov %r9, 32(%rsp) 126 1.1 jakllsch mov %r8, %r9 127 1.1 jakllsch mov %rcx, %r8 128 1.1 jakllsch /* mov %rdx, %rdx */ 129 1.1 jakllsch mov %rsi, %rcx 130 1.1 jakllsch call *%rdi 131 1.1 jakllsch addq $56, %rsp 132 1.1 jakllsch ret 133 1.1 jakllsch 134 1.1 jakllsch ENTRY(efi_call8) 135 1.1 jakllsch subq $72, %rsp 136 1.1 jakllsch mov 72+24(%rsp), %rax 137 1.1 jakllsch mov %rax, 56(%rsp) 138 1.1 jakllsch mov 72+16(%rsp), %rax 139 1.1 jakllsch mov %rax, 48(%rsp) 140 1.1 jakllsch mov 72+8(%rsp), %rax 141 1.1 jakllsch mov %rax, 40(%rsp) 142 1.1 jakllsch mov %r9, 32(%rsp) 143 1.1 jakllsch mov %r8, %r9 144 1.1 jakllsch mov %rcx, %r8 145 1.1 jakllsch /* mov %rdx, %rdx */ 146 1.1 jakllsch mov %rsi, %rcx 147 1.1 jakllsch call *%rdi 148 1.1 jakllsch addq $72, %rsp 149 1.1 jakllsch ret 150 1.1 jakllsch 151 1.1 jakllsch ENTRY(efi_call9) 152 1.1 jakllsch subq $72, %rsp 153 1.1 jakllsch mov 72+32(%rsp), %rax 154 1.1 jakllsch mov %rax, 64(%rsp) 155 1.1 jakllsch mov 72+24(%rsp), %rax 156 1.1 jakllsch mov %rax, 56(%rsp) 157 1.1 jakllsch mov 72+16(%rsp), %rax 158 1.1 jakllsch mov %rax, 48(%rsp) 159 1.1 jakllsch mov 72+8(%rsp), %rax 160 1.1 jakllsch mov %rax, 40(%rsp) 161 1.1 jakllsch mov %r9, 32(%rsp) 162 1.1 jakllsch mov %r8, %r9 163 1.1 jakllsch mov %rcx, %r8 164 1.1 jakllsch /* mov %rdx, %rdx */ 165 1.1 jakllsch mov %rsi, %rcx 166 1.1 jakllsch call *%rdi 167 1.1 jakllsch addq $72, %rsp 168 1.1 jakllsch ret 169 1.1 jakllsch 170 1.1 jakllsch ENTRY(efi_call10) 171 1.1 jakllsch subq $88, %rsp 172 1.1 jakllsch mov 88+40(%rsp), %rax 173 1.1 jakllsch mov %rax, 72(%rsp) 174 1.1 jakllsch mov 88+32(%rsp), %rax 175 1.1 jakllsch mov %rax, 64(%rsp) 176 1.1 jakllsch mov 88+24(%rsp), %rax 177 1.1 jakllsch mov %rax, 56(%rsp) 178 1.1 jakllsch mov 88+16(%rsp), %rax 179 1.1 jakllsch mov %rax, 48(%rsp) 180 1.1 jakllsch mov 88+8(%rsp), %rax 181 1.1 jakllsch mov %rax, 40(%rsp) 182 1.1 jakllsch mov %r9, 32(%rsp) 183 1.1 jakllsch mov %r8, %r9 184 1.1 jakllsch mov %rcx, %r8 185 1.1 jakllsch /* mov %rdx, %rdx */ 186 1.1 jakllsch mov %rsi, %rcx 187 1.1 jakllsch call *%rdi 188 1.1 jakllsch addq $88, %rsp 189 1.1 jakllsch ret 190 1.1 jakllsch 191 1.1 jakllsch #endif 192