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 cpu_init(); 151 acpi_init(); 152 hpet_init(); 153 smp_init(); 154 smp_init_other_cpus(); 155 156 preloaded_elf64_image *image = static_cast<preloaded_elf64_image *>( 157 gKernelArgs.kernel_image.Pointer()); 158 159 long_gdt_init(); 160 convert_kernel_args(); 161 162 // Save the kernel entry point address. 163 gLongKernelEntry = image->elf_header.e_entry; 164 dprintf("kernel entry at %#lx\n", gLongKernelEntry); 165 166 // map in a kernel stack 167 void *stack_address = NULL; 168 if (platform_allocate_region(&stack_address, KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE, 0, false) != B_OK) { 169 panic("Unabled to allocate a stack"); 170 } 171 gKernelArgs.cpu_kstack[0].start = fix_address((uint64_t)stack_address); 172 gKernelArgs.cpu_kstack[0].size = KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE; 173 dprintf("Kernel stack at %#lx\n", gKernelArgs.cpu_kstack[0].start); 174 175 // Prepare to exit EFI boot services. 176 // Read the memory map. 177 // First call is to determine the buffer size. 178 UINTN memory_map_size = 0; 179 EFI_MEMORY_DESCRIPTOR dummy; 180 EFI_MEMORY_DESCRIPTOR *memory_map; 181 UINTN map_key; 182 UINTN descriptor_size; 183 UINT32 descriptor_version; 184 if (kBootServices->GetMemoryMap(&memory_map_size, &dummy, &map_key, &descriptor_size, &descriptor_version) != EFI_BUFFER_TOO_SMALL) { 185 panic("Unable to determine size of system memory map"); 186 } 187 188 // Allocate a buffer twice as large as needed just in case it gets bigger between 189 // calls to ExitBootServices. 190 UINTN actual_memory_map_size = memory_map_size * 2; 191 memory_map = (EFI_MEMORY_DESCRIPTOR *)kernel_args_malloc(actual_memory_map_size); 192 if (memory_map == NULL) 193 panic("Unable to allocate memory map."); 194 195 // Read (and print) the memory map. 196 memory_map_size = actual_memory_map_size; 197 if (kBootServices->GetMemoryMap(&memory_map_size, memory_map, &map_key, &descriptor_size, &descriptor_version) != EFI_SUCCESS) { 198 panic("Unable to fetch system memory map."); 199 } 200 201 addr_t addr = (addr_t)memory_map; 202 dprintf("System provided memory map:\n"); 203 for (UINTN i = 0; i < memory_map_size / descriptor_size; ++i) { 204 EFI_MEMORY_DESCRIPTOR *entry = (EFI_MEMORY_DESCRIPTOR *)(addr + i * descriptor_size); 205 dprintf(" %#lx-%#lx %#lx %#x %#lx\n", 206 entry->PhysicalStart, entry->PhysicalStart + entry->NumberOfPages * 4096, 207 entry->VirtualStart, entry->Type, entry->Attribute); 208 } 209 210 // Generate page tables for use after ExitBootServices. 211 uint64_t final_pml4 = mmu_generate_post_efi_page_tables(memory_map_size, memory_map, descriptor_size, descriptor_version); 212 dprintf("Final PML4 at %#lx\n", final_pml4); 213 214 // Attempt to fetch the memory map and exit boot services. 215 // This needs to be done in a loop, as ExitBootServices can change the 216 // memory map. 217 // Even better: Only GetMemoryMap and ExitBootServices can be called after 218 // the first call to ExitBootServices, as the firmware is permitted to 219 // partially exit. This is why twice as much space was allocated for the 220 // memory map, as it's impossible to allocate more now. 221 // A changing memory map shouldn't affect the generated page tables, as 222 // they only needed to know about the maximum address, not any specific 223 // entry. 224 dprintf("Calling ExitBootServices. So long, EFI!\n"); 225 while (true) { 226 if (kBootServices->ExitBootServices(kImage, map_key) == EFI_SUCCESS) { 227 // The console was provided by boot services, disable it. 228 stdout = NULL; 229 stderr = NULL; 230 // Also switch to legacy serial output (may not work on all systems) 231 serial_switch_to_legacy(); 232 dprintf("Switched to legacy serial output\n"); 233 break; 234 } 235 236 memory_map_size = actual_memory_map_size; 237 if (kBootServices->GetMemoryMap(&memory_map_size, memory_map, &map_key, &descriptor_size, &descriptor_version) != EFI_SUCCESS) { 238 panic("Unable to fetch system memory map."); 239 } 240 } 241 242 // Update EFI, generate final kernel physical memory map, etc. 243 mmu_post_efi_setup(memory_map_size, memory_map, descriptor_size, descriptor_version); 244 245 smp_boot_other_cpus(final_pml4, (uint32_t)(uint64_t)&gLongGDTR, gLongKernelEntry); 246 247 // Enter the kernel! 248 efi_enter_kernel(final_pml4, 249 gLongKernelEntry, 250 gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size); 251 252 panic("Shouldn't get here"); 253 } 254 255 256 extern "C" void 257 platform_exit(void) 258 { 259 return; 260 } 261 262 263 /** 264 * efi_main - The entry point for the EFI application 265 * @image: firmware-allocated handle that identifies the image 266 * @systemTable: EFI system table 267 */ 268 extern "C" EFI_STATUS 269 efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systemTable) 270 { 271 stage2_args args; 272 273 memset(&args, 0, sizeof(stage2_args)); 274 275 kImage = image; 276 kSystemTable = systemTable; 277 kBootServices = systemTable->BootServices; 278 kRuntimeServices = systemTable->RuntimeServices; 279 280 call_ctors(); 281 282 console_init(); 283 serial_init(); 284 serial_enable(); 285 286 sBootOptions = console_check_boot_keys(); 287 288 // disable apm in case we ever load a 32-bit kernel... 289 gKernelArgs.platform_args.apm.version = 0; 290 291 gKernelArgs.num_cpus = 1; 292 gKernelArgs.arch_args.hpet_phys = 0; 293 gKernelArgs.arch_args.hpet = NULL; 294 295 main(&args); 296 297 return EFI_SUCCESS; 298 } 299