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