1 /* $NetBSD: efiboot.c,v 1.22 2021/10/06 10:13:19 jmcneill Exp $ */ 2 3 /*- 4 * Copyright (c) 2018 Jared McNeill <jmcneill@invisible.ca> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include "efiboot.h" 30 #include "efifile.h" 31 #include "efiblock.h" 32 #include "efirng.h" 33 34 #ifdef EFIBOOT_FDT 35 #include "efifdt.h" 36 #endif 37 38 #ifdef EFIBOOT_ACPI 39 #include "efiacpi.h" 40 #endif 41 42 #include <sys/reboot.h> 43 44 EFI_HANDLE IH; 45 EFI_DEVICE_PATH *efi_bootdp; 46 EFI_LOADED_IMAGE *efi_li; 47 48 int howto = 0; 49 50 #ifdef _LP64 51 #define PRIxEFIPTR "lX" 52 #define PRIxEFISIZE "lX" 53 #else 54 #define PRIxEFIPTR "X" 55 #define PRIxEFISIZE "X" 56 #endif 57 58 static EFI_PHYSICAL_ADDRESS heap_start; 59 static UINTN heap_size = 8 * 1024 * 1024; 60 static EFI_EVENT delay_ev = 0; 61 62 EFI_STATUS EFIAPI efi_main(EFI_HANDLE, EFI_SYSTEM_TABLE *); 63 64 EFI_STATUS EFIAPI 65 efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE *systemTable) 66 { 67 EFI_STATUS status; 68 u_int sz = EFI_SIZE_TO_PAGES(heap_size); 69 70 IH = imageHandle; 71 72 InitializeLib(imageHandle, systemTable); 73 74 uefi_call_wrapper(ST->ConOut->Reset, 2, ST->ConOut, TRUE); 75 uefi_call_wrapper(ST->ConOut->SetMode, 2, ST->ConOut, 0); 76 uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, TRUE); 77 78 status = uefi_call_wrapper(BS->AllocatePages, 4, AllocateAnyPages, EfiLoaderData, sz, &heap_start); 79 if (EFI_ERROR(status)) 80 return status; 81 setheap((void *)(uintptr_t)heap_start, (void *)(uintptr_t)(heap_start + heap_size)); 82 83 status = uefi_call_wrapper(BS->HandleProtocol, 3, imageHandle, &LoadedImageProtocol, (void **)&efi_li); 84 if (EFI_ERROR(status)) 85 return status; 86 status = uefi_call_wrapper(BS->HandleProtocol, 3, efi_li->DeviceHandle, &DevicePathProtocol, (void **)&efi_bootdp); 87 if (EFI_ERROR(status)) 88 efi_bootdp = NULL; 89 90 #ifdef EFIBOOT_DEBUG 91 Print(L"Loaded image : 0x%" PRIxEFIPTR "\n", efi_li); 92 Print(L"FilePath : 0x%" PRIxEFIPTR "\n", efi_li->FilePath); 93 Print(L"ImageBase : 0x%" PRIxEFIPTR "\n", efi_li->ImageBase); 94 Print(L"ImageSize : 0x%" PRIxEFISIZE "\n", efi_li->ImageSize); 95 Print(L"Image file : %s\n", DevicePathToStr(efi_li->FilePath)); 96 #endif 97 98 #ifdef EFIBOOT_ACPI 99 efi_acpi_probe(); 100 #endif 101 #ifdef EFIBOOT_FDT 102 efi_fdt_probe(); 103 #endif 104 efi_pxe_probe(); 105 efi_net_probe(); 106 efi_file_system_probe(); 107 efi_block_probe(); 108 efi_rng_probe(); 109 efi_gop_probe(); 110 111 boot(); 112 113 return EFI_SUCCESS; 114 } 115 116 void 117 efi_cleanup(void) 118 { 119 EFI_STATUS status; 120 EFI_MEMORY_DESCRIPTOR *memmap; 121 UINTN nentries, mapkey, descsize; 122 UINT32 descver; 123 124 memmap = LibMemoryMap(&nentries, &mapkey, &descsize, &descver); 125 126 status = uefi_call_wrapper(BS->ExitBootServices, 2, IH, mapkey); 127 if (EFI_ERROR(status)) { 128 printf("WARNING: ExitBootServices failed\n"); 129 return; 130 } 131 132 #ifdef EFIBOOT_RUNTIME_ADDRESS 133 arch_set_virtual_address_map(memmap, nentries, mapkey, descsize, descver); 134 #endif 135 } 136 137 void 138 efi_exit(void) 139 { 140 EFI_STATUS status; 141 142 status = uefi_call_wrapper(BS->Exit, 4, IH, EFI_ABORTED, 0, NULL); 143 if (EFI_ERROR(status)) 144 printf("WARNING: Exit failed\n"); 145 } 146 147 void 148 efi_reboot(void) 149 { 150 uefi_call_wrapper(RT->ResetSystem, 4, EfiResetCold, EFI_SUCCESS, 0, NULL); 151 152 printf("WARNING: Reset failed\n"); 153 } 154 155 void 156 efi_delay(int us) 157 { 158 EFI_STATUS status; 159 UINTN val; 160 161 if (delay_ev == 0) { 162 status = uefi_call_wrapper(BS->CreateEvent, 5, EVT_TIMER, TPL_APPLICATION, 0, 0, &delay_ev); 163 if (EFI_ERROR(status)) 164 return; 165 } 166 167 uefi_call_wrapper(BS->SetTimer, 3, delay_ev, TimerRelative, us * 10); 168 uefi_call_wrapper(BS->WaitForEvent, 3, 1, &delay_ev, &val); 169 } 170 171 void 172 efi_progress(const char *fmt, ...) 173 { 174 va_list ap; 175 176 if ((howto & AB_SILENT) != 0) 177 return; 178 179 va_start(ap, fmt); 180 vprintf(fmt, ap); 181 va_end(ap); 182 } 183