debughook.c revision 1.1 1 1.1 jmcneill /* $NetBSD: debughook.c,v 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