1 /* 2 * Copyright 2014-2016 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 <kernel.h> 16 17 #include <boot/arch/x86/arch_cpu.h> 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 "acpi.h" 25 #include "console.h" 26 #include "efi_platform.h" 27 #include "mmu.h" 28 #include "serial.h" 29 #include "smp.h" 30 #include "timer.h" 31 32 33 extern void (*__ctor_list)(void); 34 extern void (*__ctor_end)(void); 35 36 37 const efi_system_table *kSystemTable; 38 const efi_boot_services *kBootServices; 39 const efi_runtime_services *kRuntimeServices; 40 efi_handle kImage; 41 42 43 static uint32 sBootOptions; 44 static uint64 gLongKernelEntry; 45 46 47 extern "C" int main(stage2_args *args); 48 extern "C" void _start(void); 49 extern "C" void efi_enter_kernel(uint64 pml4, uint64 entry_point, uint64 stack); 50 51 52 static void 53 call_ctors(void) 54 { 55 void (**f)(void); 56 57 for (f = &__ctor_list; f < &__ctor_end; f++) 58 (**f)(); 59 } 60 61 62 extern "C" uint32 63 platform_boot_options() 64 { 65 return sBootOptions; 66 } 67 68 69 static void 70 convert_preloaded_image(preloaded_elf64_image* image) 71 { 72 fix_address(image->next); 73 fix_address(image->name); 74 fix_address(image->debug_string_table); 75 fix_address(image->syms); 76 fix_address(image->rel); 77 fix_address(image->rela); 78 fix_address(image->pltrel); 79 fix_address(image->debug_symbols); 80 } 81 82 83 /*! Convert all addresses in kernel_args to 64-bit addresses. */ 84 static void 85 convert_kernel_args() 86 { 87 fix_address(gKernelArgs.boot_volume); 88 fix_address(gKernelArgs.vesa_modes); 89 fix_address(gKernelArgs.edid_info); 90 fix_address(gKernelArgs.debug_output); 91 fix_address(gKernelArgs.boot_splash); 92 #if defined(__x86_64__) || defined(__x86__) 93 fix_address(gKernelArgs.arch_args.apic); 94 fix_address(gKernelArgs.arch_args.hpet); 95 #endif 96 97 convert_preloaded_image(static_cast<preloaded_elf64_image*>( 98 gKernelArgs.kernel_image.Pointer())); 99 fix_address(gKernelArgs.kernel_image); 100 101 // Iterate over the preloaded images. Must save the next address before 102 // converting, as the next pointer will be converted. 103 preloaded_image* image = gKernelArgs.preloaded_images; 104 fix_address(gKernelArgs.preloaded_images); 105 while (image != NULL) { 106 preloaded_image* next = image->next; 107 convert_preloaded_image(static_cast<preloaded_elf64_image*>(image)); 108 image = next; 109 } 110 111 // Fix driver settings files. 112 driver_settings_file* file = gKernelArgs.driver_settings; 113 fix_address(gKernelArgs.driver_settings); 114 while (file != NULL) { 115 driver_settings_file* next = file->next; 116 fix_address(file->next); 117 fix_address(file->buffer); 118 file = next; 119 } 120 } 121 122 123 extern "C" void 124 platform_start_kernel(void) 125 { 126 if (gKernelArgs.kernel_image->elf_class != ELFCLASS64) 127 panic("32-bit kernels not supported with EFI"); 128 129 smp_init_other_cpus(); 130 131 preloaded_elf64_image *image = static_cast<preloaded_elf64_image *>( 132 gKernelArgs.kernel_image.Pointer()); 133 134 arch_mmu_init(); 135 convert_kernel_args(); 136 137 // Save the kernel entry point address. 138 gLongKernelEntry = image->elf_header.e_entry; 139 dprintf("kernel entry at %#lx\n", gLongKernelEntry); 140 141 // map in a kernel stack 142 void *stack_address = NULL; 143 if (platform_allocate_region(&stack_address, 144 KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE, 0, false) 145 != B_OK) { 146 panic("Unabled to allocate a stack"); 147 } 148 gKernelArgs.cpu_kstack[0].start = fix_address((uint64_t)stack_address); 149 gKernelArgs.cpu_kstack[0].size = KERNEL_STACK_SIZE 150 + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE; 151 dprintf("Kernel stack at %#lx\n", gKernelArgs.cpu_kstack[0].start); 152 153 // Prepare to exit EFI boot services. 154 // Read the memory map. 155 // First call is to determine the buffer size. 156 size_t memory_map_size = 0; 157 efi_memory_descriptor dummy; 158 efi_memory_descriptor *memory_map; 159 size_t map_key; 160 size_t descriptor_size; 161 uint32_t descriptor_version; 162 if (kBootServices->GetMemoryMap(&memory_map_size, &dummy, &map_key, 163 &descriptor_size, &descriptor_version) != EFI_BUFFER_TOO_SMALL) { 164 panic("Unable to determine size of system memory map"); 165 } 166 167 // Allocate a buffer twice as large as needed just in case it gets bigger between 168 // calls to ExitBootServices. 169 size_t actual_memory_map_size = memory_map_size * 2; 170 memory_map 171 = (efi_memory_descriptor *)kernel_args_malloc(actual_memory_map_size); 172 173 if (memory_map == NULL) 174 panic("Unable to allocate memory map."); 175 176 // Read (and print) the memory map. 177 memory_map_size = actual_memory_map_size; 178 if (kBootServices->GetMemoryMap(&memory_map_size, memory_map, &map_key, 179 &descriptor_size, &descriptor_version) != EFI_SUCCESS) { 180 panic("Unable to fetch system memory map."); 181 } 182 183 addr_t addr = (addr_t)memory_map; 184 dprintf("System provided memory map:\n"); 185 for (size_t i = 0; i < memory_map_size / descriptor_size; ++i) { 186 efi_memory_descriptor *entry 187 = (efi_memory_descriptor *)(addr + i * descriptor_size); 188 dprintf(" %#lx-%#lx %#lx %#x %#lx\n", entry->PhysicalStart, 189 entry->PhysicalStart + entry->NumberOfPages * 4096, 190 entry->VirtualStart, entry->Type, entry->Attribute); 191 } 192 193 // Generate page tables for use after ExitBootServices. 194 uint64_t final_pml4 = mmu_generate_post_efi_page_tables(memory_map_size, 195 memory_map, descriptor_size, descriptor_version); 196 dprintf("Final PML4 at %#lx\n", final_pml4); 197 198 // Attempt to fetch the memory map and exit boot services. 199 // This needs to be done in a loop, as ExitBootServices can change the 200 // memory map. 201 // Even better: Only GetMemoryMap and ExitBootServices can be called after 202 // the first call to ExitBootServices, as the firmware is permitted to 203 // partially exit. This is why twice as much space was allocated for the 204 // memory map, as it's impossible to allocate more now. 205 // A changing memory map shouldn't affect the generated page tables, as 206 // they only needed to know about the maximum address, not any specific 207 // entry. 208 dprintf("Calling ExitBootServices. So long, EFI!\n"); 209 while (true) { 210 if (kBootServices->ExitBootServices(kImage, map_key) == EFI_SUCCESS) { 211 // The console was provided by boot services, disable it. 212 stdout = NULL; 213 stderr = NULL; 214 // Also switch to legacy serial output (may not work on all systems) 215 serial_switch_to_legacy(); 216 dprintf("Switched to legacy serial output\n"); 217 break; 218 } 219 220 memory_map_size = actual_memory_map_size; 221 if (kBootServices->GetMemoryMap(&memory_map_size, memory_map, &map_key, 222 &descriptor_size, &descriptor_version) != EFI_SUCCESS) { 223 panic("Unable to fetch system memory map."); 224 } 225 } 226 227 // Update EFI, generate final kernel physical memory map, etc. 228 mmu_post_efi_setup(memory_map_size, memory_map, 229 descriptor_size, descriptor_version); 230 231 smp_boot_other_cpus(final_pml4, gLongKernelEntry); 232 233 // Enter the kernel! 234 efi_enter_kernel(final_pml4, gLongKernelEntry, 235 gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size); 236 237 panic("Shouldn't get here"); 238 } 239 240 241 extern "C" void 242 platform_exit(void) 243 { 244 return; 245 } 246 247 248 /** 249 * efi_main - The entry point for the EFI application 250 * @image: firmware-allocated handle that identifies the image 251 * @systemTable: EFI system table 252 */ 253 extern "C" efi_status 254 efi_main(efi_handle image, efi_system_table *systemTable) 255 { 256 stage2_args args; 257 258 memset(&args, 0, sizeof(stage2_args)); 259 260 kImage = image; 261 kSystemTable = systemTable; 262 kBootServices = systemTable->BootServices; 263 kRuntimeServices = systemTable->RuntimeServices; 264 265 call_ctors(); 266 267 console_init(); 268 serial_init(); 269 serial_enable(); 270 271 sBootOptions = console_check_boot_keys(); 272 273 // disable apm in case we ever load a 32-bit kernel... 274 gKernelArgs.platform_args.apm.version = 0; 275 276 gKernelArgs.num_cpus = 1; 277 #if defined(__x86_64__) || defined(__x86__) 278 gKernelArgs.arch_args.hpet_phys = 0; 279 gKernelArgs.arch_args.hpet = NULL; 280 #endif 281 282 cpu_init(); 283 acpi_init(); 284 timer_init(); 285 smp_init(); 286 287 main(&args); 288 289 return EFI_SUCCESS; 290 } 291