1735f1daeSFredrik Holmqvist /* 2735f1daeSFredrik Holmqvist * Copyright 2014-2016 Haiku, Inc. All rights reserved. 3b3215a62SHenry Harrington * Copyright 2013-2014, Fredrik Holmqvist, fredrik.holmqvist@gmail.com. 4b3215a62SHenry Harrington * Copyright 2014, Henry Harrington, henry.harrington@gmail.com. 5b3215a62SHenry Harrington * All rights reserved. 647a21c5cSAugustin Cavalier * Distributed under the terms of the MIT License. 7735f1daeSFredrik Holmqvist */ 8735f1daeSFredrik Holmqvist 9735f1daeSFredrik Holmqvist 10b3215a62SHenry Harrington #include <string.h> 11b3215a62SHenry Harrington 12b3215a62SHenry Harrington #include <KernelExport.h> 13b3215a62SHenry Harrington 14b3215a62SHenry Harrington #include <arch/cpu.h> 157b4d924fSAndrej Antunovikj #include <kernel.h> 167b4d924fSAndrej Antunovikj 176e6efaecSJessica Hamilton #include <boot/kernel_args.h> 18e2e1558aSJessica Hamilton #include <boot/platform.h> 19e2e1558aSJessica Hamilton #include <boot/stage2.h> 20e2e1558aSJessica Hamilton #include <boot/stdio.h> 21735f1daeSFredrik Holmqvist 2271680f7bSAlexander von Gluck IV #include "arch_mmu.h" 2304f1baa7SAlexander von Gluck IV #include "arch_start.h" 246e6efaecSJessica Hamilton #include "acpi.h" 25735f1daeSFredrik Holmqvist #include "console.h" 26d2986cb6SAlexander von Gluck IV #include "cpu.h" 27735f1daeSFredrik Holmqvist #include "efi_platform.h" 28b3215a62SHenry Harrington #include "mmu.h" 29d38ba84dSAlexander von Gluck IV #include "quirks.h" 309e487d8dSFredrik Holmqvist #include "serial.h" 31a99a0c00SNick Smallbone #include "smp.h" 32b482adb1SAlexander von Gluck IV #include "timer.h" 33735f1daeSFredrik Holmqvist 34735f1daeSFredrik Holmqvist 35735f1daeSFredrik Holmqvist extern void (*__ctor_list)(void); 36735f1daeSFredrik Holmqvist extern void (*__ctor_end)(void); 37735f1daeSFredrik Holmqvist 38735f1daeSFredrik Holmqvist 39485b5cf8SAlexander von Gluck IV const efi_system_table *kSystemTable; 40485b5cf8SAlexander von Gluck IV const efi_boot_services *kBootServices; 41485b5cf8SAlexander von Gluck IV const efi_runtime_services *kRuntimeServices; 42485b5cf8SAlexander von Gluck IV efi_handle kImage; 43b3215a62SHenry Harrington 44735f1daeSFredrik Holmqvist 4596f4d68bSJessica Hamilton static uint32 sBootOptions; 46b3215a62SHenry Harrington 47b3215a62SHenry Harrington extern "C" int main(stage2_args *args); 48b3215a62SHenry Harrington extern "C" void _start(void); 49b3215a62SHenry Harrington extern "C" void efi_enter_kernel(uint64 pml4, uint64 entry_point, uint64 stack); 5096f4d68bSJessica Hamilton 51735f1daeSFredrik Holmqvist 52735f1daeSFredrik Holmqvist static void 53735f1daeSFredrik Holmqvist call_ctors(void) 54735f1daeSFredrik Holmqvist { 55735f1daeSFredrik Holmqvist void (**f)(void); 56735f1daeSFredrik Holmqvist 57735f1daeSFredrik Holmqvist for (f = &__ctor_list; f < &__ctor_end; f++) 58735f1daeSFredrik Holmqvist (**f)(); 59735f1daeSFredrik Holmqvist } 60735f1daeSFredrik Holmqvist 61735f1daeSFredrik Holmqvist 62e2e1558aSJessica Hamilton extern "C" uint32 63e2e1558aSJessica Hamilton platform_boot_options() 64e2e1558aSJessica Hamilton { 6596f4d68bSJessica Hamilton return sBootOptions; 66e2e1558aSJessica Hamilton } 67e2e1558aSJessica Hamilton 68e2e1558aSJessica Hamilton 69b3215a62SHenry Harrington static void 70b3215a62SHenry Harrington convert_preloaded_image(preloaded_elf64_image* image) 71b3215a62SHenry Harrington { 72b3215a62SHenry Harrington fix_address(image->next); 73b3215a62SHenry Harrington fix_address(image->name); 74b3215a62SHenry Harrington fix_address(image->debug_string_table); 75b3215a62SHenry Harrington fix_address(image->syms); 76b3215a62SHenry Harrington fix_address(image->rel); 77b3215a62SHenry Harrington fix_address(image->rela); 78b3215a62SHenry Harrington fix_address(image->pltrel); 79b3215a62SHenry Harrington fix_address(image->debug_symbols); 80b3215a62SHenry Harrington } 81b3215a62SHenry Harrington 82b3215a62SHenry Harrington 83b3215a62SHenry Harrington /*! Convert all addresses in kernel_args to 64-bit addresses. */ 84b3215a62SHenry Harrington static void 85b3215a62SHenry Harrington convert_kernel_args() 86b3215a62SHenry Harrington { 87b3215a62SHenry Harrington fix_address(gKernelArgs.boot_volume); 88b3215a62SHenry Harrington fix_address(gKernelArgs.vesa_modes); 89b3215a62SHenry Harrington fix_address(gKernelArgs.edid_info); 90b3215a62SHenry Harrington fix_address(gKernelArgs.debug_output); 91b3215a62SHenry Harrington fix_address(gKernelArgs.boot_splash); 92b482adb1SAlexander von Gluck IV #if defined(__x86_64__) || defined(__x86__) 93*11f8b65aSJérôme Duval fix_address(gKernelArgs.ucode_data); 94b3215a62SHenry Harrington fix_address(gKernelArgs.arch_args.apic); 95b3215a62SHenry Harrington fix_address(gKernelArgs.arch_args.hpet); 96b482adb1SAlexander von Gluck IV #endif 97b3215a62SHenry Harrington 98b3215a62SHenry Harrington convert_preloaded_image(static_cast<preloaded_elf64_image*>( 99b3215a62SHenry Harrington gKernelArgs.kernel_image.Pointer())); 100b3215a62SHenry Harrington fix_address(gKernelArgs.kernel_image); 101b3215a62SHenry Harrington 102b3215a62SHenry Harrington // Iterate over the preloaded images. Must save the next address before 103b3215a62SHenry Harrington // converting, as the next pointer will be converted. 104b3215a62SHenry Harrington preloaded_image* image = gKernelArgs.preloaded_images; 105b3215a62SHenry Harrington fix_address(gKernelArgs.preloaded_images); 106b3215a62SHenry Harrington while (image != NULL) { 107b3215a62SHenry Harrington preloaded_image* next = image->next; 108b3215a62SHenry Harrington convert_preloaded_image(static_cast<preloaded_elf64_image*>(image)); 109b3215a62SHenry Harrington image = next; 110b3215a62SHenry Harrington } 111b3215a62SHenry Harrington 112b3215a62SHenry Harrington // Fix driver settings files. 113b3215a62SHenry Harrington driver_settings_file* file = gKernelArgs.driver_settings; 114b3215a62SHenry Harrington fix_address(gKernelArgs.driver_settings); 115b3215a62SHenry Harrington while (file != NULL) { 116b3215a62SHenry Harrington driver_settings_file* next = file->next; 117b3215a62SHenry Harrington fix_address(file->next); 118b3215a62SHenry Harrington fix_address(file->buffer); 119b3215a62SHenry Harrington file = next; 120b3215a62SHenry Harrington } 121b3215a62SHenry Harrington } 122b3215a62SHenry Harrington 123b3215a62SHenry Harrington 124e2e1558aSJessica Hamilton extern "C" void 125e2e1558aSJessica Hamilton platform_start_kernel(void) 126e2e1558aSJessica Hamilton { 127b3215a62SHenry Harrington if (gKernelArgs.kernel_image->elf_class != ELFCLASS64) 128b3215a62SHenry Harrington panic("32-bit kernels not supported with EFI"); 129b3215a62SHenry Harrington 130a99a0c00SNick Smallbone smp_init_other_cpus(); 131ec239abcSJessica Hamilton 132b3215a62SHenry Harrington preloaded_elf64_image *image = static_cast<preloaded_elf64_image *>( 133b3215a62SHenry Harrington gKernelArgs.kernel_image.Pointer()); 134b3215a62SHenry Harrington 1357c32619cSAlexander von Gluck IV arch_mmu_init(); 136b3215a62SHenry Harrington convert_kernel_args(); 137b3215a62SHenry Harrington 138b3215a62SHenry Harrington // Save the kernel entry point address. 13904f1baa7SAlexander von Gluck IV addr_t kernelEntry = image->elf_header.e_entry; 14004f1baa7SAlexander von Gluck IV dprintf("kernel entry at %#lx\n", kernelEntry); 141b3215a62SHenry Harrington 142b3215a62SHenry Harrington // map in a kernel stack 143b3215a62SHenry Harrington void *stack_address = NULL; 144485b5cf8SAlexander von Gluck IV if (platform_allocate_region(&stack_address, 145485b5cf8SAlexander von Gluck IV KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE, 0, false) 146485b5cf8SAlexander von Gluck IV != B_OK) { 147b3215a62SHenry Harrington panic("Unabled to allocate a stack"); 148b3215a62SHenry Harrington } 149b3215a62SHenry Harrington gKernelArgs.cpu_kstack[0].start = fix_address((uint64_t)stack_address); 150485b5cf8SAlexander von Gluck IV gKernelArgs.cpu_kstack[0].size = KERNEL_STACK_SIZE 151485b5cf8SAlexander von Gluck IV + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE; 152b3215a62SHenry Harrington dprintf("Kernel stack at %#lx\n", gKernelArgs.cpu_kstack[0].start); 153b3215a62SHenry Harrington 154d38ba84dSAlexander von Gluck IV // Apply any weird EFI quirks 155d38ba84dSAlexander von Gluck IV quirks_init(); 156d38ba84dSAlexander von Gluck IV 15704f1baa7SAlexander von Gluck IV // Begin architecture-centric kernel entry. 15804f1baa7SAlexander von Gluck IV arch_start_kernel(kernelEntry); 159b3215a62SHenry Harrington 16004f1baa7SAlexander von Gluck IV panic("Shouldn't get here!"); 161e2e1558aSJessica Hamilton } 162e2e1558aSJessica Hamilton 163e2e1558aSJessica Hamilton 164e2e1558aSJessica Hamilton extern "C" void 165e2e1558aSJessica Hamilton platform_exit(void) 166e2e1558aSJessica Hamilton { 167e2e1558aSJessica Hamilton return; 168e2e1558aSJessica Hamilton } 169e2e1558aSJessica Hamilton 170e2e1558aSJessica Hamilton 171735f1daeSFredrik Holmqvist /** 172735f1daeSFredrik Holmqvist * efi_main - The entry point for the EFI application 173735f1daeSFredrik Holmqvist * @image: firmware-allocated handle that identifies the image 174735f1daeSFredrik Holmqvist * @systemTable: EFI system table 175735f1daeSFredrik Holmqvist */ 176485b5cf8SAlexander von Gluck IV extern "C" efi_status 177485b5cf8SAlexander von Gluck IV efi_main(efi_handle image, efi_system_table *systemTable) 178735f1daeSFredrik Holmqvist { 179e2e1558aSJessica Hamilton stage2_args args; 180e2e1558aSJessica Hamilton 181b3215a62SHenry Harrington memset(&args, 0, sizeof(stage2_args)); 182b3215a62SHenry Harrington 183b3215a62SHenry Harrington kImage = image; 184735f1daeSFredrik Holmqvist kSystemTable = systemTable; 185735f1daeSFredrik Holmqvist kBootServices = systemTable->BootServices; 186735f1daeSFredrik Holmqvist kRuntimeServices = systemTable->RuntimeServices; 187735f1daeSFredrik Holmqvist 188735f1daeSFredrik Holmqvist call_ctors(); 189735f1daeSFredrik Holmqvist 190735f1daeSFredrik Holmqvist console_init(); 1919e487d8dSFredrik Holmqvist serial_init(); 1929e487d8dSFredrik Holmqvist serial_enable(); 193735f1daeSFredrik Holmqvist 19496f4d68bSJessica Hamilton sBootOptions = console_check_boot_keys(); 19596f4d68bSJessica Hamilton 196b3215a62SHenry Harrington // disable apm in case we ever load a 32-bit kernel... 197b3215a62SHenry Harrington gKernelArgs.platform_args.apm.version = 0; 1986e6efaecSJessica Hamilton 19986b12d85SJessica Hamilton cpu_init(); 20086b12d85SJessica Hamilton acpi_init(); 201b482adb1SAlexander von Gluck IV timer_init(); 20286b12d85SJessica Hamilton smp_init(); 20386b12d85SJessica Hamilton 204e2e1558aSJessica Hamilton main(&args); 205735f1daeSFredrik Holmqvist 206735f1daeSFredrik Holmqvist return EFI_SUCCESS; 207735f1daeSFredrik Holmqvist } 208