1 /* $NetBSD: efibind.h,v 1.5 2021/09/30 19:02:48 jmcneill Exp $ */ 2 3 /*++ 4 5 Copyright (c) 1998 Intel Corporation 6 7 Module Name: 8 9 efefind.h 10 11 Abstract: 12 13 EFI to compile bindings 14 15 16 17 18 Revision History 19 20 --*/ 21 #ifndef X86_64_EFI_BIND 22 #define X86_64_EFI_BIND 23 #ifndef __GNUC__ 24 #pragma pack() 25 #endif 26 27 #if defined(_MSC_VER) 28 #define HAVE_USE_MS_ABI 1 29 #elif defined(GNU_EFI_USE_MS_ABI) 30 #if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)))||(defined(__clang__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 2))) 31 #define HAVE_USE_MS_ABI 1 32 #else 33 #error Compiler is too old for GNU_EFI_USE_MS_ABI 34 #endif 35 #endif 36 37 // 38 // Basic int types of various widths 39 // 40 41 #if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L ) && !defined(__cplusplus) 42 43 // No ANSI C 1999/2000 stdint.h integer width declarations 44 45 #if defined(_MSC_EXTENSIONS) 46 47 // Use Microsoft C compiler integer width declarations 48 49 typedef unsigned __int64 uint64_t; 50 typedef __int64 int64_t; 51 typedef unsigned __int32 uint32_t; 52 typedef __int32 int32_t; 53 typedef unsigned short uint16_t; 54 typedef short int16_t; 55 typedef unsigned char uint8_t; 56 typedef char int8_t; 57 #elif defined(__GNUC__) 58 typedef int __attribute__((__mode__(__DI__))) int64_t; 59 typedef unsigned int __attribute__((__mode__(__DI__))) uint64_t; 60 typedef unsigned int uint32_t; 61 typedef int int32_t; 62 typedef unsigned short uint16_t; 63 typedef short int16_t; 64 typedef unsigned char uint8_t; 65 typedef signed char int8_t; 66 #elif defined(UNIX_LP64) 67 68 /* Use LP64 programming model from C_FLAGS for integer width declarations */ 69 70 typedef unsigned long uint64_t; 71 typedef long int64_t; 72 typedef unsigned int uint32_t; 73 typedef int int32_t; 74 typedef unsigned short uint16_t; 75 typedef short int16_t; 76 typedef unsigned char uint8_t; 77 typedef char int8_t; 78 #else 79 80 /* Assume P64 programming model from C_FLAGS for integer width declarations */ 81 82 typedef unsigned long long uint64_t __attribute__((aligned (8))); 83 typedef long long int64_t __attribute__((aligned (8))); 84 typedef unsigned int uint32_t; 85 typedef int int32_t; 86 typedef unsigned short uint16_t; 87 typedef short int16_t; 88 typedef unsigned char uint8_t; 89 typedef char int8_t; 90 #endif 91 typedef uint64_t uintptr_t; 92 typedef int64_t intptr_t; 93 #elif defined(__NetBSD__) 94 #include <sys/stdint.h> 95 #else 96 #include <stdint.h> 97 #endif 98 99 // 100 // Basic EFI types of various widths 101 // 102 103 #ifndef __WCHAR_TYPE__ 104 # define __WCHAR_TYPE__ short 105 #endif 106 107 #ifndef __ACTYPES_H__ 108 typedef uint64_t UINT64; 109 typedef int64_t INT64; 110 111 #ifndef _BASETSD_H_ 112 typedef uint32_t UINT32; 113 typedef int32_t INT32; 114 #endif 115 116 typedef uint16_t UINT16; 117 typedef int16_t INT16; 118 typedef uint8_t UINT8; 119 typedef int8_t INT8; 120 #endif /* __ACTYPES_H__ */ 121 typedef __WCHAR_TYPE__ WCHAR; 122 123 #undef VOID 124 #define VOID void 125 126 127 typedef int64_t INTN; 128 typedef uint64_t UINTN; 129 130 #ifdef EFI_NT_EMULATOR 131 #define POST_CODE(_Data) 132 #else 133 #ifdef EFI_DEBUG 134 #define POST_CODE(_Data) __asm mov eax,(_Data) __asm out 0x80,al 135 #else 136 #define POST_CODE(_Data) 137 #endif 138 #endif 139 140 #define EFIERR(a) (0x8000000000000000 | a) 141 #define EFI_ERROR_MASK 0x8000000000000000 142 #define EFIERR_OEM(a) (0xc000000000000000 | a) 143 144 145 #define BAD_POINTER 0xFBFBFBFBFBFBFBFB 146 #define MAX_ADDRESS 0xFFFFFFFFFFFFFFFF 147 148 #ifdef EFI_NT_EMULATOR 149 #define BREAKPOINT() __asm { int 3 } 150 #else 151 #define BREAKPOINT() while (TRUE); // Make it hang on Bios[Dbg]32 152 #endif 153 154 // 155 // Pointers must be aligned to these address to function 156 // 157 158 #define MIN_ALIGNMENT_SIZE 4 159 160 #define ALIGN_VARIABLE(Value ,Adjustment) \ 161 (UINTN)Adjustment = 0; \ 162 if((UINTN)Value % MIN_ALIGNMENT_SIZE) \ 163 (UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \ 164 Value = (UINTN)Value + (UINTN)Adjustment 165 166 167 // 168 // Define macros to build data structure signatures from characters. 169 // 170 171 #define EFI_SIGNATURE_16(A,B) ((A) | (B<<8)) 172 #define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16)) 173 #define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32)) 174 // 175 // To export & import functions in the EFI emulator environment 176 // 177 178 #ifdef EFI_NT_EMULATOR 179 #define EXPORTAPI __declspec( dllexport ) 180 #else 181 #define EXPORTAPI 182 #endif 183 184 185 // 186 // EFIAPI - prototype calling convention for EFI function pointers 187 // BOOTSERVICE - prototype for implementation of a boot service interface 188 // RUNTIMESERVICE - prototype for implementation of a runtime service interface 189 // RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service 190 // RUNTIME_CODE - pragma macro for declaring runtime code 191 // 192 193 #ifndef EFIAPI // Forces EFI calling conventions reguardless of compiler options 194 #ifdef _MSC_EXTENSIONS 195 #define EFIAPI __cdecl // Force C calling convention for Microsoft C compiler 196 #elif defined(HAVE_USE_MS_ABI) 197 // Force amd64/ms calling conventions. 198 #define EFIAPI __attribute__((ms_abi)) 199 #else 200 #define EFIAPI // Substitute expresion to force C calling convention 201 #endif 202 #endif 203 204 #define BOOTSERVICE 205 //#define RUNTIMESERVICE(proto,a) alloc_text("rtcode",a); proto a 206 //#define RUNTIMEFUNCTION(proto,a) alloc_text("rtcode",a); proto a 207 #define RUNTIMESERVICE 208 #define RUNTIMEFUNCTION 209 210 211 #define RUNTIME_CODE(a) alloc_text("rtcode", a) 212 #define BEGIN_RUNTIME_DATA() data_seg("rtdata") 213 #define END_RUNTIME_DATA() data_seg("") 214 215 #define VOLATILE volatile 216 217 #define MEMORY_FENCE() 218 219 #ifdef EFI_NT_EMULATOR 220 221 // 222 // To help ensure proper coding of integrated drivers, they are 223 // compiled as DLLs. In NT they require a dll init entry pointer. 224 // The macro puts a stub entry point into the DLL so it will load. 225 // 226 227 #define EFI_DRIVER_ENTRY_POINT(InitFunction) \ 228 UINTN \ 229 __stdcall \ 230 _DllMainCRTStartup ( \ 231 UINTN Inst, \ 232 UINTN reason_for_call, \ 233 VOID *rserved \ 234 ) \ 235 { \ 236 return 1; \ 237 } \ 238 \ 239 int \ 240 EXPORTAPI \ 241 __cdecl \ 242 InitializeDriver ( \ 243 void *ImageHandle, \ 244 void *SystemTable \ 245 ) \ 246 { \ 247 return InitFunction(ImageHandle, SystemTable); \ 248 } 249 250 251 #define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \ 252 (_if)->LoadInternal(type, name, NULL) 253 254 #else // EFI_NT_EMULATOR 255 256 // 257 // When build similiar to FW, then link everything together as 258 // one big module. For the MSVC toolchain, we simply tell the 259 // linker what our driver init function is using /ENTRY. 260 // 261 #if defined(_MSC_EXTENSIONS) 262 #define EFI_DRIVER_ENTRY_POINT(InitFunction) \ 263 __pragma(comment(linker, "/ENTRY:" # InitFunction)) 264 #else 265 #define EFI_DRIVER_ENTRY_POINT(InitFunction) \ 266 UINTN \ 267 InitializeDriver ( \ 268 VOID *ImageHandle, \ 269 VOID *SystemTable \ 270 ) \ 271 { \ 272 return InitFunction(ImageHandle, \ 273 SystemTable); \ 274 } \ 275 \ 276 EFI_STATUS efi_main( \ 277 EFI_HANDLE image, \ 278 EFI_SYSTEM_TABLE *systab \ 279 ) __attribute__((weak, \ 280 alias ("InitializeDriver"))); 281 #endif 282 283 #define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \ 284 (_if)->LoadInternal(type, name, entry) 285 286 #endif // EFI_NT_EMULATOR 287 288 // 289 // Some compilers don't support the forward reference construct: 290 // typedef struct XXXXX 291 // 292 // The following macro provide a workaround for such cases. 293 // 294 #ifdef NO_INTERFACE_DECL 295 #define INTERFACE_DECL(x) 296 #else 297 #if defined(__GNUC__) || defined(_MSC_EXTENSIONS) 298 #define INTERFACE_DECL(x) struct x 299 #else 300 #define INTERFACE_DECL(x) typedef struct x 301 #endif 302 #endif 303 304 /* for x86_64, EFI_FUNCTION_WRAPPER must be defined */ 305 #if defined(HAVE_USE_MS_ABI) 306 #define uefi_call_wrapper(func, va_num, ...) func(__VA_ARGS__) 307 #else 308 /* 309 Credits for macro-magic: 310 https://groups.google.com/forum/?fromgroups#!topic/comp.std.c/d-6Mj5Lko_s 311 http://efesx.com/2010/08/31/overloading-macros/ 312 */ 313 #define __VA_NARG__(...) \ 314 __VA_NARG_(_0, ## __VA_ARGS__, __RSEQ_N()) 315 #define __VA_NARG_(...) \ 316 __VA_ARG_N(__VA_ARGS__) 317 #define __VA_ARG_N( \ 318 _0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,N,...) N 319 #define __RSEQ_N() \ 320 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 321 322 #define __VA_ARG_NSUFFIX__(prefix,...) \ 323 __VA_ARG_NSUFFIX_N(prefix, __VA_NARG__(__VA_ARGS__)) 324 #define __VA_ARG_NSUFFIX_N(prefix,nargs) \ 325 __VA_ARG_NSUFFIX_N_(prefix, nargs) 326 #define __VA_ARG_NSUFFIX_N_(prefix,nargs) \ 327 prefix ## nargs 328 329 /* Prototypes of EFI cdecl -> stdcall trampolines */ 330 UINT64 efi_call0(void *func); 331 UINT64 efi_call1(void *func, UINT64 arg1); 332 UINT64 efi_call2(void *func, UINT64 arg1, UINT64 arg2); 333 UINT64 efi_call3(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3); 334 UINT64 efi_call4(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3, 335 UINT64 arg4); 336 UINT64 efi_call5(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3, 337 UINT64 arg4, UINT64 arg5); 338 UINT64 efi_call6(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3, 339 UINT64 arg4, UINT64 arg5, UINT64 arg6); 340 UINT64 efi_call7(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3, 341 UINT64 arg4, UINT64 arg5, UINT64 arg6, UINT64 arg7); 342 UINT64 efi_call8(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3, 343 UINT64 arg4, UINT64 arg5, UINT64 arg6, UINT64 arg7, 344 UINT64 arg8); 345 UINT64 efi_call9(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3, 346 UINT64 arg4, UINT64 arg5, UINT64 arg6, UINT64 arg7, 347 UINT64 arg8, UINT64 arg9); 348 UINT64 efi_call10(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3, 349 UINT64 arg4, UINT64 arg5, UINT64 arg6, UINT64 arg7, 350 UINT64 arg8, UINT64 arg9, UINT64 arg10); 351 352 /* Front-ends to efi_callX to avoid compiler warnings */ 353 #define _cast64_efi_call0(f) \ 354 efi_call0(f) 355 #define _cast64_efi_call1(f,a1) \ 356 efi_call1(f, (UINT64)(a1)) 357 #define _cast64_efi_call2(f,a1,a2) \ 358 efi_call2(f, (UINT64)(a1), (UINT64)(a2)) 359 #define _cast64_efi_call3(f,a1,a2,a3) \ 360 efi_call3(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3)) 361 #define _cast64_efi_call4(f,a1,a2,a3,a4) \ 362 efi_call4(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4)) 363 #define _cast64_efi_call5(f,a1,a2,a3,a4,a5) \ 364 efi_call5(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ 365 (UINT64)(a5)) 366 #define _cast64_efi_call6(f,a1,a2,a3,a4,a5,a6) \ 367 efi_call6(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ 368 (UINT64)(a5), (UINT64)(a6)) 369 #define _cast64_efi_call7(f,a1,a2,a3,a4,a5,a6,a7) \ 370 efi_call7(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ 371 (UINT64)(a5), (UINT64)(a6), (UINT64)(a7)) 372 #define _cast64_efi_call8(f,a1,a2,a3,a4,a5,a6,a7,a8) \ 373 efi_call8(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ 374 (UINT64)(a5), (UINT64)(a6), (UINT64)(a7), (UINT64)(a8)) 375 #define _cast64_efi_call9(f,a1,a2,a3,a4,a5,a6,a7,a8,a9) \ 376 efi_call9(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ 377 (UINT64)(a5), (UINT64)(a6), (UINT64)(a7), (UINT64)(a8), \ 378 (UINT64)(a9)) 379 #define _cast64_efi_call10(f,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) \ 380 efi_call10(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ 381 (UINT64)(a5), (UINT64)(a6), (UINT64)(a7), (UINT64)(a8), \ 382 (UINT64)(a9), (UINT64)(a10)) 383 384 /* main wrapper (va_num ignored) */ 385 #define uefi_call_wrapper(func,va_num,...) \ 386 __VA_ARG_NSUFFIX__(_cast64_efi_call, __VA_ARGS__) (func , ##__VA_ARGS__) 387 388 #endif 389 390 #if defined(HAVE_USE_MS_ABI) && !defined(_MSC_EXTENSIONS) 391 #define EFI_FUNCTION __attribute__((ms_abi)) 392 #else 393 #define EFI_FUNCTION 394 #endif 395 396 #ifdef _MSC_EXTENSIONS 397 #pragma warning ( disable : 4731 ) // Suppress warnings about modification of EBP 398 #endif 399 400 #endif 401