1/* 2 * Copyright 2014-2021 Haiku, Inc. All rights reserved. 3 * Copyright 2013-2014, Fredrik Holmqvist, fredrik.holmqvist@gmail.com. 4 * Copyright 2014, Henry Harrington, henry.harrington@gmail.com. 5 * All rights reserved. 6 * Distributed under the terms of the MIT License. 7 */ 8 9 10#include <string.h> 11 12#include <KernelExport.h> 13 14#include <arch/cpu.h> 15#include <arch_cpu_defs.h> 16#include <kernel.h> 17 18#include <boot/kernel_args.h> 19#include <boot/platform.h> 20#include <boot/stage2.h> 21#include <boot/stdio.h> 22 23#include "arch_mmu.h" 24#include "arch_start.h" 25#include "acpi.h" 26#include "console.h" 27#include "cpu.h" 28#include "debug.h" 29#ifdef _BOOT_FDT_SUPPORT 30#include "dtb.h" 31#endif 32#include "efi_platform.h" 33#include "mmu.h" 34#include "quirks.h" 35#include "serial.h" 36#include "smp.h" 37#include "timer.h" 38 39 40extern void (*__ctor_list)(void); 41extern void (*__ctor_end)(void); 42 43 44const efi_system_table *kSystemTable; 45const efi_boot_services *kBootServices; 46const efi_runtime_services *kRuntimeServices; 47efi_handle kImage; 48 49 50static uint32 sBootOptions; 51 52extern "C" int main(stage2_args *args); 53extern "C" void _start(void); 54extern "C" void efi_enter_kernel(uint64 pml4, uint64 entry_point, uint64 stack); 55 56 57static void 58call_ctors(void) 59{ 60 void (**f)(void); 61 62 for (f = &__ctor_list; f < &__ctor_end; f++) 63 (**f)(); 64} 65 66 67extern "C" uint32 68platform_boot_options() 69{ 70 return sBootOptions; 71} 72 73 74template<class T> static void 75convert_preloaded_image(preloaded_image* _image) 76{ 77 T* image = static_cast<T*>(_image); 78 fix_address(image->next); 79 fix_address(image->name); 80 fix_address(image->debug_string_table); 81 fix_address(image->syms); 82 fix_address(image->rel); 83 fix_address(image->rela); 84 fix_address(image->pltrel); 85 fix_address(image->debug_symbols); 86} 87 88 89/*! Convert all addresses in kernel_args to virtual addresses. */ 90static void 91convert_kernel_args() 92{ 93 fix_address(gKernelArgs.boot_volume); 94 fix_address(gKernelArgs.vesa_modes); 95 fix_address(gKernelArgs.edid_info); 96 fix_address(gKernelArgs.debug_output); 97 fix_address(gKernelArgs.boot_splash); 98 99 arch_convert_kernel_args(); 100 101 if (gKernelArgs.kernel_image->elf_class == ELFCLASS64) { 102 convert_preloaded_image<preloaded_elf64_image>(gKernelArgs.kernel_image); 103 } else { 104 convert_preloaded_image<preloaded_elf32_image>(gKernelArgs.kernel_image); 105 } 106 fix_address(gKernelArgs.kernel_image); 107 108 // Iterate over the preloaded images. Must save the next address before 109 // converting, as the next pointer will be converted. 110 preloaded_image* image = gKernelArgs.preloaded_images; 111 fix_address(gKernelArgs.preloaded_images); 112 while (image != NULL) { 113 preloaded_image* next = image->next; 114 if (image->elf_class == ELFCLASS64) { 115 convert_preloaded_image<preloaded_elf64_image>(image); 116 } else { 117 convert_preloaded_image<preloaded_elf32_image>(image); 118 } 119 image = next; 120 } 121 122 // Fix driver settings files. 123 driver_settings_file* file = gKernelArgs.driver_settings; 124 fix_address(gKernelArgs.driver_settings); 125 while (file != NULL) { 126 driver_settings_file* next = file->next; 127 fix_address(file->next); 128 fix_address(file->buffer); 129 file = next; 130 } 131} 132 133 134static addr_t 135get_kernel_entry(void) 136{ 137 if (gKernelArgs.kernel_image->elf_class == ELFCLASS64) { 138 preloaded_elf64_image *image = static_cast<preloaded_elf64_image *>( 139 gKernelArgs.kernel_image.Pointer()); 140 return image->elf_header.e_entry; 141 } else if (gKernelArgs.kernel_image->elf_class == ELFCLASS32) { 142 preloaded_elf32_image *image = static_cast<preloaded_elf32_image *>( 143 gKernelArgs.kernel_image.Pointer()); 144 return image->elf_header.e_entry; 145 } 146 panic("Unknown kernel format! Not 32-bit or 64-bit!"); 147 return 0; 148} 149 150 151static void 152get_kernel_regions(addr_range& text, addr_range& data) 153{ 154 if (gKernelArgs.kernel_image->elf_class == ELFCLASS64) { 155 preloaded_elf64_image *image = static_cast<preloaded_elf64_image *>( 156 gKernelArgs.kernel_image.Pointer()); 157 text.start = image->text_region.start; 158 text.size = image->text_region.size; 159 data.start = image->data_region.start; 160 data.size = image->data_region.size; 161 return; 162 } else if (gKernelArgs.kernel_image->elf_class == ELFCLASS32) { 163 preloaded_elf32_image *image = static_cast<preloaded_elf32_image *>( 164 gKernelArgs.kernel_image.Pointer()); 165 text.start = image->text_region.start; 166 text.size = image->text_region.size; 167 data.start = image->data_region.start; 168 data.size = image->data_region.size; 169 return; 170 } 171 panic("Unknown kernel format! Not 32-bit or 64-bit!"); 172} 173 174 175extern "C" void 176platform_start_kernel(void) 177{ 178 smp_init_other_cpus(); 179#ifdef _BOOT_FDT_SUPPORT 180 dtb_set_kernel_args(); 181#endif 182 183 addr_t kernelEntry = get_kernel_entry(); 184 185 addr_range textRegion = {.start = 0, .size = 0}, dataRegion = {.start = 0, .size = 0}; 186 get_kernel_regions(textRegion, dataRegion); 187 dprintf("kernel:\n"); 188 dprintf(" text: %#" B_PRIx64 ", %#" B_PRIx64 "\n", textRegion.start, textRegion.size); 189 dprintf(" data: %#" B_PRIx64 ", %#" B_PRIx64 "\n", dataRegion.start, dataRegion.size); 190 dprintf(" entry: %#lx\n", kernelEntry); 191 192 debug_cleanup(); 193 194 arch_mmu_init(); 195 convert_kernel_args(); 196 197 // map in a kernel stack 198 void *stack_address = NULL; 199 if (platform_allocate_region(&stack_address, 200 KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE, 0, false) 201 != B_OK) { 202 panic("Unabled to allocate a stack"); 203 } 204 gKernelArgs.cpu_kstack[0].start = fix_address((addr_t)stack_address); 205 gKernelArgs.cpu_kstack[0].size = KERNEL_STACK_SIZE 206 + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE; 207 dprintf("Kernel stack at %#" B_PRIx64 "\n", gKernelArgs.cpu_kstack[0].start); 208 209 // Apply any weird EFI quirks 210 quirks_init(); 211 212 // Begin architecture-centric kernel entry. 213 arch_start_kernel(kernelEntry); 214 215 panic("Shouldn't get here!"); 216} 217 218 219extern "C" void 220platform_exit(void) 221{ 222 kRuntimeServices->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL); 223 return; 224} 225 226 227/** 228 * efi_main - The entry point for the EFI application 229 * @image: firmware-allocated handle that identifies the image 230 * @systemTable: EFI system table 231 */ 232extern "C" efi_status 233efi_main(efi_handle image, efi_system_table *systemTable) 234{ 235 stage2_args args; 236 237 memset(&args, 0, sizeof(stage2_args)); 238 239 kImage = image; 240 kSystemTable = systemTable; 241 kBootServices = systemTable->BootServices; 242 kRuntimeServices = systemTable->RuntimeServices; 243 244 call_ctors(); 245 246 console_init(); 247 serial_init(); 248 serial_enable(); 249 250 sBootOptions = console_check_boot_keys(); 251 252 // disable apm in case we ever load a 32-bit kernel... 253 gKernelArgs.platform_args.apm.version = 0; 254 255 cpu_init(); 256 acpi_init(); 257#ifdef _BOOT_FDT_SUPPORT 258 dtb_init(); 259#endif 260 timer_init(); 261 smp_init(); 262 263 main(&args); 264 265 return EFI_SUCCESS; 266} 267