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" 27*569564c0SAlexander von Gluck IV #include "dtb.h" 28735f1daeSFredrik Holmqvist #include "efi_platform.h" 29b3215a62SHenry Harrington #include "mmu.h" 30d38ba84dSAlexander von Gluck IV #include "quirks.h" 319e487d8dSFredrik Holmqvist #include "serial.h" 32a99a0c00SNick Smallbone #include "smp.h" 33b482adb1SAlexander von Gluck IV #include "timer.h" 34735f1daeSFredrik Holmqvist 35735f1daeSFredrik Holmqvist 36735f1daeSFredrik Holmqvist extern void (*__ctor_list)(void); 37735f1daeSFredrik Holmqvist extern void (*__ctor_end)(void); 38735f1daeSFredrik Holmqvist 39735f1daeSFredrik Holmqvist 40485b5cf8SAlexander von Gluck IV const efi_system_table *kSystemTable; 41485b5cf8SAlexander von Gluck IV const efi_boot_services *kBootServices; 42485b5cf8SAlexander von Gluck IV const efi_runtime_services *kRuntimeServices; 43485b5cf8SAlexander von Gluck IV efi_handle kImage; 44b3215a62SHenry Harrington 45735f1daeSFredrik Holmqvist 4696f4d68bSJessica Hamilton static uint32 sBootOptions; 47b3215a62SHenry Harrington 48b3215a62SHenry Harrington extern "C" int main(stage2_args *args); 49b3215a62SHenry Harrington extern "C" void _start(void); 50b3215a62SHenry Harrington extern "C" void efi_enter_kernel(uint64 pml4, uint64 entry_point, uint64 stack); 5196f4d68bSJessica Hamilton 52735f1daeSFredrik Holmqvist 53735f1daeSFredrik Holmqvist static void 54735f1daeSFredrik Holmqvist call_ctors(void) 55735f1daeSFredrik Holmqvist { 56735f1daeSFredrik Holmqvist void (**f)(void); 57735f1daeSFredrik Holmqvist 58735f1daeSFredrik Holmqvist for (f = &__ctor_list; f < &__ctor_end; f++) 59735f1daeSFredrik Holmqvist (**f)(); 60735f1daeSFredrik Holmqvist } 61735f1daeSFredrik Holmqvist 62735f1daeSFredrik Holmqvist 63e2e1558aSJessica Hamilton extern "C" uint32 64e2e1558aSJessica Hamilton platform_boot_options() 65e2e1558aSJessica Hamilton { 6696f4d68bSJessica Hamilton return sBootOptions; 67e2e1558aSJessica Hamilton } 68e2e1558aSJessica Hamilton 69e2e1558aSJessica Hamilton 70b3215a62SHenry Harrington static void 71b3215a62SHenry Harrington convert_preloaded_image(preloaded_elf64_image* image) 72b3215a62SHenry Harrington { 73b3215a62SHenry Harrington fix_address(image->next); 74b3215a62SHenry Harrington fix_address(image->name); 75b3215a62SHenry Harrington fix_address(image->debug_string_table); 76b3215a62SHenry Harrington fix_address(image->syms); 77b3215a62SHenry Harrington fix_address(image->rel); 78b3215a62SHenry Harrington fix_address(image->rela); 79b3215a62SHenry Harrington fix_address(image->pltrel); 80b3215a62SHenry Harrington fix_address(image->debug_symbols); 81b3215a62SHenry Harrington } 82b3215a62SHenry Harrington 83b3215a62SHenry Harrington 84b3215a62SHenry Harrington /*! Convert all addresses in kernel_args to 64-bit addresses. */ 85b3215a62SHenry Harrington static void 86b3215a62SHenry Harrington convert_kernel_args() 87b3215a62SHenry Harrington { 88312ace56SAlexander von Gluck IV if (gKernelArgs.kernel_image->elf_class != ELFCLASS64) 89312ace56SAlexander von Gluck IV return; 90312ace56SAlexander von Gluck IV 91b3215a62SHenry Harrington fix_address(gKernelArgs.boot_volume); 92b3215a62SHenry Harrington fix_address(gKernelArgs.vesa_modes); 93b3215a62SHenry Harrington fix_address(gKernelArgs.edid_info); 94b3215a62SHenry Harrington fix_address(gKernelArgs.debug_output); 95b3215a62SHenry Harrington fix_address(gKernelArgs.boot_splash); 96b482adb1SAlexander von Gluck IV #if defined(__x86_64__) || defined(__x86__) 9711f8b65aSJérôme Duval fix_address(gKernelArgs.ucode_data); 98b3215a62SHenry Harrington fix_address(gKernelArgs.arch_args.apic); 99b3215a62SHenry Harrington fix_address(gKernelArgs.arch_args.hpet); 100b482adb1SAlexander von Gluck IV #endif 101b3215a62SHenry Harrington 102b3215a62SHenry Harrington convert_preloaded_image(static_cast<preloaded_elf64_image*>( 103b3215a62SHenry Harrington gKernelArgs.kernel_image.Pointer())); 104b3215a62SHenry Harrington fix_address(gKernelArgs.kernel_image); 105b3215a62SHenry Harrington 106b3215a62SHenry Harrington // Iterate over the preloaded images. Must save the next address before 107b3215a62SHenry Harrington // converting, as the next pointer will be converted. 108b3215a62SHenry Harrington preloaded_image* image = gKernelArgs.preloaded_images; 109b3215a62SHenry Harrington fix_address(gKernelArgs.preloaded_images); 110b3215a62SHenry Harrington while (image != NULL) { 111b3215a62SHenry Harrington preloaded_image* next = image->next; 112b3215a62SHenry Harrington convert_preloaded_image(static_cast<preloaded_elf64_image*>(image)); 113b3215a62SHenry Harrington image = next; 114b3215a62SHenry Harrington } 115b3215a62SHenry Harrington 116b3215a62SHenry Harrington // Fix driver settings files. 117b3215a62SHenry Harrington driver_settings_file* file = gKernelArgs.driver_settings; 118b3215a62SHenry Harrington fix_address(gKernelArgs.driver_settings); 119b3215a62SHenry Harrington while (file != NULL) { 120b3215a62SHenry Harrington driver_settings_file* next = file->next; 121b3215a62SHenry Harrington fix_address(file->next); 122b3215a62SHenry Harrington fix_address(file->buffer); 123b3215a62SHenry Harrington file = next; 124b3215a62SHenry Harrington } 125b3215a62SHenry Harrington } 126b3215a62SHenry Harrington 127b3215a62SHenry Harrington 128312ace56SAlexander von Gluck IV static addr_t 129312ace56SAlexander von Gluck IV get_kernel_entry(void) 130312ace56SAlexander von Gluck IV { 131312ace56SAlexander von Gluck IV if (gKernelArgs.kernel_image->elf_class == ELFCLASS64) { 132312ace56SAlexander von Gluck IV preloaded_elf64_image *image = static_cast<preloaded_elf64_image *>( 133312ace56SAlexander von Gluck IV gKernelArgs.kernel_image.Pointer()); 134312ace56SAlexander von Gluck IV return image->elf_header.e_entry; 135312ace56SAlexander von Gluck IV } else if (gKernelArgs.kernel_image->elf_class == ELFCLASS32) { 136312ace56SAlexander von Gluck IV preloaded_elf32_image *image = static_cast<preloaded_elf32_image *>( 137312ace56SAlexander von Gluck IV gKernelArgs.kernel_image.Pointer()); 138312ace56SAlexander von Gluck IV return image->elf_header.e_entry; 139312ace56SAlexander von Gluck IV } 140312ace56SAlexander von Gluck IV panic("Unknown kernel format! Not 32-bit or 64-bit!"); 141312ace56SAlexander von Gluck IV return 0; 142312ace56SAlexander von Gluck IV } 143312ace56SAlexander von Gluck IV 144312ace56SAlexander von Gluck IV 145e2e1558aSJessica Hamilton extern "C" void 146e2e1558aSJessica Hamilton platform_start_kernel(void) 147e2e1558aSJessica Hamilton { 148a99a0c00SNick Smallbone smp_init_other_cpus(); 149ec239abcSJessica Hamilton 150312ace56SAlexander von Gluck IV addr_t kernelEntry = get_kernel_entry(); 151b3215a62SHenry Harrington 1527c32619cSAlexander von Gluck IV arch_mmu_init(); 153b3215a62SHenry Harrington convert_kernel_args(); 154b3215a62SHenry Harrington 155b3215a62SHenry Harrington // Save the kernel entry point address. 15604f1baa7SAlexander von Gluck IV dprintf("kernel entry at %#lx\n", kernelEntry); 157b3215a62SHenry Harrington 158b3215a62SHenry Harrington // map in a kernel stack 159b3215a62SHenry Harrington void *stack_address = NULL; 160485b5cf8SAlexander von Gluck IV if (platform_allocate_region(&stack_address, 161485b5cf8SAlexander von Gluck IV KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE, 0, false) 162485b5cf8SAlexander von Gluck IV != B_OK) { 163b3215a62SHenry Harrington panic("Unabled to allocate a stack"); 164b3215a62SHenry Harrington } 16505586741SAlexander von Gluck IV gKernelArgs.cpu_kstack[0].start = fix_address((addr_t)stack_address); 166485b5cf8SAlexander von Gluck IV gKernelArgs.cpu_kstack[0].size = KERNEL_STACK_SIZE 167485b5cf8SAlexander von Gluck IV + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE; 168b3215a62SHenry Harrington dprintf("Kernel stack at %#lx\n", gKernelArgs.cpu_kstack[0].start); 169b3215a62SHenry Harrington 170d38ba84dSAlexander von Gluck IV // Apply any weird EFI quirks 171d38ba84dSAlexander von Gluck IV quirks_init(); 172d38ba84dSAlexander von Gluck IV 17304f1baa7SAlexander von Gluck IV // Begin architecture-centric kernel entry. 17404f1baa7SAlexander von Gluck IV arch_start_kernel(kernelEntry); 175b3215a62SHenry Harrington 17604f1baa7SAlexander von Gluck IV panic("Shouldn't get here!"); 177e2e1558aSJessica Hamilton } 178e2e1558aSJessica Hamilton 179e2e1558aSJessica Hamilton 180e2e1558aSJessica Hamilton extern "C" void 181e2e1558aSJessica Hamilton platform_exit(void) 182e2e1558aSJessica Hamilton { 183e2e1558aSJessica Hamilton return; 184e2e1558aSJessica Hamilton } 185e2e1558aSJessica Hamilton 186e2e1558aSJessica Hamilton 187735f1daeSFredrik Holmqvist /** 188735f1daeSFredrik Holmqvist * efi_main - The entry point for the EFI application 189735f1daeSFredrik Holmqvist * @image: firmware-allocated handle that identifies the image 190735f1daeSFredrik Holmqvist * @systemTable: EFI system table 191735f1daeSFredrik Holmqvist */ 192485b5cf8SAlexander von Gluck IV extern "C" efi_status 193485b5cf8SAlexander von Gluck IV efi_main(efi_handle image, efi_system_table *systemTable) 194735f1daeSFredrik Holmqvist { 195e2e1558aSJessica Hamilton stage2_args args; 196e2e1558aSJessica Hamilton 197b3215a62SHenry Harrington memset(&args, 0, sizeof(stage2_args)); 198b3215a62SHenry Harrington 199b3215a62SHenry Harrington kImage = image; 200735f1daeSFredrik Holmqvist kSystemTable = systemTable; 201735f1daeSFredrik Holmqvist kBootServices = systemTable->BootServices; 202735f1daeSFredrik Holmqvist kRuntimeServices = systemTable->RuntimeServices; 203735f1daeSFredrik Holmqvist 204735f1daeSFredrik Holmqvist call_ctors(); 205735f1daeSFredrik Holmqvist 206735f1daeSFredrik Holmqvist console_init(); 2079e487d8dSFredrik Holmqvist serial_init(); 2089e487d8dSFredrik Holmqvist serial_enable(); 209735f1daeSFredrik Holmqvist 21096f4d68bSJessica Hamilton sBootOptions = console_check_boot_keys(); 21196f4d68bSJessica Hamilton 212b3215a62SHenry Harrington // disable apm in case we ever load a 32-bit kernel... 213b3215a62SHenry Harrington gKernelArgs.platform_args.apm.version = 0; 2146e6efaecSJessica Hamilton 21586b12d85SJessica Hamilton cpu_init(); 21686b12d85SJessica Hamilton acpi_init(); 217*569564c0SAlexander von Gluck IV dtb_init(); 218b482adb1SAlexander von Gluck IV timer_init(); 21986b12d85SJessica Hamilton smp_init(); 22086b12d85SJessica Hamilton 221e2e1558aSJessica Hamilton main(&args); 222735f1daeSFredrik Holmqvist 223735f1daeSFredrik Holmqvist return EFI_SUCCESS; 224735f1daeSFredrik Holmqvist } 225