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