1 1.1 jmcneill /* $NetBSD: debughook.c,v 1.1.1.1 2018/08/16 18:17:47 jmcneill Exp $ */ 2 1.1 jmcneill 3 1.1 jmcneill #include <efi.h> 4 1.1 jmcneill #include <efilib.h> 5 1.1 jmcneill 6 1.1 jmcneill EFI_STATUS 7 1.1 jmcneill GetVariableAttr(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner, 8 1.1 jmcneill UINT32 *attributes) 9 1.1 jmcneill { 10 1.1 jmcneill EFI_STATUS efi_status; 11 1.1 jmcneill 12 1.1 jmcneill *len = 0; 13 1.1 jmcneill 14 1.1 jmcneill efi_status = uefi_call_wrapper(RT->GetVariable, 5, var, &owner, 15 1.1 jmcneill NULL, len, NULL); 16 1.1 jmcneill if (efi_status != EFI_BUFFER_TOO_SMALL) 17 1.1 jmcneill return efi_status; 18 1.1 jmcneill 19 1.1 jmcneill *data = AllocateZeroPool(*len); 20 1.1 jmcneill if (!*data) 21 1.1 jmcneill return EFI_OUT_OF_RESOURCES; 22 1.1 jmcneill 23 1.1 jmcneill efi_status = uefi_call_wrapper(RT->GetVariable, 5, var, &owner, 24 1.1 jmcneill attributes, len, *data); 25 1.1 jmcneill 26 1.1 jmcneill if (efi_status != EFI_SUCCESS) { 27 1.1 jmcneill FreePool(*data); 28 1.1 jmcneill *data = NULL; 29 1.1 jmcneill } 30 1.1 jmcneill return efi_status; 31 1.1 jmcneill } 32 1.1 jmcneill 33 1.1 jmcneill EFI_STATUS 34 1.1 jmcneill GetVariable(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner) 35 1.1 jmcneill { 36 1.1 jmcneill return GetVariableAttr(var, data, len, owner, NULL); 37 1.1 jmcneill } 38 1.1 jmcneill 39 1.1 jmcneill EFI_GUID DUMMY_GUID = 40 1.1 jmcneill {0x55aad538, 0x8f82, 0x4e2a, {0xa4,0xf0,0xbe, 0x59, 0x13, 0xb6, 0x5f, 0x1e}}; 41 1.1 jmcneill 42 1.1 jmcneill #if defined(__clang__) 43 1.1 jmcneill # define _OPTNONE __attribute__((optnone)) 44 1.1 jmcneill #else 45 1.1 jmcneill # define _OPTNONE __attribute__((__optimize__("0"))) 46 1.1 jmcneill #endif 47 1.1 jmcneill 48 1.1 jmcneill static _OPTNONE void 49 1.1 jmcneill DebugHook(void) 50 1.1 jmcneill { 51 1.1 jmcneill EFI_GUID guid = DUMMY_GUID; 52 1.1 jmcneill UINT8 *data = NULL; 53 1.1 jmcneill UINTN dataSize = 0; 54 1.1 jmcneill EFI_STATUS efi_status; 55 1.1 jmcneill register volatile unsigned long long x = 0; 56 1.1 jmcneill extern char _text, _data; 57 1.1 jmcneill 58 1.1 jmcneill if (x) 59 1.1 jmcneill return; 60 1.1 jmcneill 61 1.1 jmcneill efi_status = GetVariable(L"DUMMY_DEBUG", &data, &dataSize, guid); 62 1.1 jmcneill if (EFI_ERROR(efi_status)) { 63 1.1 jmcneill return; 64 1.1 jmcneill } 65 1.1 jmcneill 66 1.1 jmcneill Print(L"add-symbol-file /usr/lib/debug/boot/efi/debughook.debug " 67 1.1 jmcneill L"0x%08x -s .data 0x%08x\n", &_text, &_data); 68 1.1 jmcneill 69 1.1 jmcneill Print(L"Pausing for debugger attachment.\n"); 70 1.1 jmcneill Print(L"To disable this, remove the EFI variable DUMMY_DEBUG-%g .\n", 71 1.1 jmcneill &guid); 72 1.1 jmcneill x = 1; 73 1.1 jmcneill while (x++) { 74 1.1 jmcneill /* Make this so it can't /totally/ DoS us. */ 75 1.1 jmcneill #if defined(__x86_64__) || defined(__i386__) || defined(__i686__) 76 1.1 jmcneill if (x > 4294967294ULL) 77 1.1 jmcneill break; 78 1.1 jmcneill __asm__ __volatile__("pause"); 79 1.1 jmcneill #elif defined(__aarch64__) 80 1.1 jmcneill if (x > 1000) 81 1.1 jmcneill break; 82 1.1 jmcneill __asm__ __volatile__("wfi"); 83 1.1 jmcneill #else 84 1.1 jmcneill if (x > 12000) 85 1.1 jmcneill break; 86 1.1 jmcneill uefi_call_wrapper(BS->Stall, 1, 5000); 87 1.1 jmcneill #endif 88 1.1 jmcneill } 89 1.1 jmcneill x = 1; 90 1.1 jmcneill } 91 1.1 jmcneill 92 1.1 jmcneill 93 1.1 jmcneill EFI_STATUS 94 1.1 jmcneill efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) 95 1.1 jmcneill { 96 1.1 jmcneill InitializeLib(image, systab); 97 1.1 jmcneill DebugHook(); 98 1.1 jmcneill return EFI_SUCCESS; 99 1.1 jmcneill } 100