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