1 /* $NetBSD: efiboot.c,v 1.24 2024/08/15 05:59:49 skrll 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 else 90 efi_bootdp = DuplicateDevicePath(efi_bootdp); 91 92 #ifdef EFIBOOT_DEBUG 93 Print(L"Loaded image : 0x%" PRIxEFIPTR "\n", efi_li); 94 Print(L"FilePath : 0x%" PRIxEFIPTR "\n", efi_li->FilePath); 95 Print(L"ImageBase : 0x%" PRIxEFIPTR "\n", efi_li->ImageBase); 96 Print(L"ImageSize : 0x%" PRIxEFISIZE "\n", efi_li->ImageSize); 97 Print(L"Image file : %s\n", DevicePathToStr(efi_li->FilePath)); 98 #endif 99 100 #ifdef EFIBOOT_ACPI 101 efi_acpi_probe(); 102 #endif 103 #ifdef EFIBOOT_FDT 104 efi_fdt_probe(); 105 #endif 106 efi_pxe_probe(); 107 efi_net_probe(); 108 efi_file_system_probe(); 109 efi_block_probe(); 110 efi_rng_probe(); 111 efi_gop_probe(); 112 113 boot(); 114 115 return EFI_SUCCESS; 116 } 117 118 void 119 efi_cleanup(void) 120 { 121 EFI_STATUS status; 122 EFI_MEMORY_DESCRIPTOR *memmap; 123 UINTN nentries, mapkey, descsize; 124 UINT32 descver; 125 126 memmap = LibMemoryMap(&nentries, &mapkey, &descsize, &descver); 127 128 status = uefi_call_wrapper(BS->ExitBootServices, 2, IH, mapkey); 129 if (EFI_ERROR(status)) { 130 printf("WARNING: ExitBootServices failed\n"); 131 return; 132 } 133 134 #ifdef EFIBOOT_RUNTIME_ADDRESS 135 efi_fdt_set_virtual_address_map(memmap, nentries, mapkey, descsize, descver); 136 #endif 137 } 138 139 void 140 efi_exit(void) 141 { 142 EFI_STATUS status; 143 144 status = uefi_call_wrapper(BS->Exit, 4, IH, EFI_ABORTED, 0, NULL); 145 if (EFI_ERROR(status)) 146 printf("WARNING: Exit failed\n"); 147 } 148 149 void 150 efi_reboot(void) 151 { 152 uefi_call_wrapper(RT->ResetSystem, 4, EfiResetCold, EFI_SUCCESS, 0, NULL); 153 154 printf("WARNING: Reset failed\n"); 155 } 156 157 void 158 efi_delay(int us) 159 { 160 EFI_STATUS status; 161 UINTN val; 162 163 if (delay_ev == 0) { 164 status = uefi_call_wrapper(BS->CreateEvent, 5, EVT_TIMER, TPL_APPLICATION, 0, 0, &delay_ev); 165 if (EFI_ERROR(status)) 166 return; 167 } 168 169 uefi_call_wrapper(BS->SetTimer, 3, delay_ev, TimerRelative, us * 10); 170 uefi_call_wrapper(BS->WaitForEvent, 3, 1, &delay_ev, &val); 171 } 172 173 void 174 efi_progress(const char *fmt, ...) 175 { 176 va_list ap; 177 178 if ((howto & AB_SILENT) != 0) 179 return; 180 181 va_start(ap, fmt); 182 vprintf(fmt, ap); 183 va_end(ap); 184 } 185