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 MIT License. 7 */ 8 9 10 #include <string.h> 11 12 #include <KernelExport.h> 13 14 #include <arch/cpu.h> 15 #include <kernel.h> 16 17 #include <boot/kernel_args.h> 18 #include <boot/platform.h> 19 #include <boot/stage2.h> 20 #include <boot/stdio.h> 21 22 #include "arch_mmu.h" 23 #include "arch_start.h" 24 #include "acpi.h" 25 #include "console.h" 26 #include "cpu.h" 27 #include "dtb.h" 28 #include "efi_platform.h" 29 #include "mmu.h" 30 #include "quirks.h" 31 #include "serial.h" 32 #include "smp.h" 33 #include "timer.h" 34 35 36 extern void (*__ctor_list)(void); 37 extern void (*__ctor_end)(void); 38 39 40 const efi_system_table *kSystemTable; 41 const efi_boot_services *kBootServices; 42 const efi_runtime_services *kRuntimeServices; 43 efi_handle kImage; 44 45 46 static uint32 sBootOptions; 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 convert_preloaded_image(preloaded_elf64_image* image) 72 { 73 fix_address(image->next); 74 fix_address(image->name); 75 fix_address(image->debug_string_table); 76 fix_address(image->syms); 77 fix_address(image->rel); 78 fix_address(image->rela); 79 fix_address(image->pltrel); 80 fix_address(image->debug_symbols); 81 } 82 83 84 /*! Convert all addresses in kernel_args to 64-bit addresses. */ 85 static void 86 convert_kernel_args() 87 { 88 if (gKernelArgs.kernel_image->elf_class != ELFCLASS64) 89 return; 90 91 fix_address(gKernelArgs.boot_volume); 92 fix_address(gKernelArgs.vesa_modes); 93 fix_address(gKernelArgs.edid_info); 94 fix_address(gKernelArgs.debug_output); 95 fix_address(gKernelArgs.boot_splash); 96 #if defined(__x86_64__) || defined(__x86__) 97 fix_address(gKernelArgs.ucode_data); 98 fix_address(gKernelArgs.arch_args.apic); 99 fix_address(gKernelArgs.arch_args.hpet); 100 #endif 101 102 convert_preloaded_image(static_cast<preloaded_elf64_image*>( 103 gKernelArgs.kernel_image.Pointer())); 104 fix_address(gKernelArgs.kernel_image); 105 106 // Iterate over the preloaded images. Must save the next address before 107 // converting, as the next pointer will be converted. 108 preloaded_image* image = gKernelArgs.preloaded_images; 109 fix_address(gKernelArgs.preloaded_images); 110 while (image != NULL) { 111 preloaded_image* next = image->next; 112 convert_preloaded_image(static_cast<preloaded_elf64_image*>(image)); 113 image = next; 114 } 115 116 // Fix driver settings files. 117 driver_settings_file* file = gKernelArgs.driver_settings; 118 fix_address(gKernelArgs.driver_settings); 119 while (file != NULL) { 120 driver_settings_file* next = file->next; 121 fix_address(file->next); 122 fix_address(file->buffer); 123 file = next; 124 } 125 } 126 127 128 static addr_t 129 get_kernel_entry(void) 130 { 131 if (gKernelArgs.kernel_image->elf_class == ELFCLASS64) { 132 preloaded_elf64_image *image = static_cast<preloaded_elf64_image *>( 133 gKernelArgs.kernel_image.Pointer()); 134 return image->elf_header.e_entry; 135 } else if (gKernelArgs.kernel_image->elf_class == ELFCLASS32) { 136 preloaded_elf32_image *image = static_cast<preloaded_elf32_image *>( 137 gKernelArgs.kernel_image.Pointer()); 138 return image->elf_header.e_entry; 139 } 140 panic("Unknown kernel format! Not 32-bit or 64-bit!"); 141 return 0; 142 } 143 144 145 extern "C" void 146 platform_start_kernel(void) 147 { 148 smp_init_other_cpus(); 149 150 addr_t kernelEntry = get_kernel_entry(); 151 152 arch_mmu_init(); 153 convert_kernel_args(); 154 155 // Save the kernel entry point address. 156 dprintf("kernel entry at %#lx\n", kernelEntry); 157 158 // map in a kernel stack 159 void *stack_address = NULL; 160 if (platform_allocate_region(&stack_address, 161 KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE, 0, false) 162 != B_OK) { 163 panic("Unabled to allocate a stack"); 164 } 165 gKernelArgs.cpu_kstack[0].start = fix_address((addr_t)stack_address); 166 gKernelArgs.cpu_kstack[0].size = KERNEL_STACK_SIZE 167 + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE; 168 dprintf("Kernel stack at %#lx\n", gKernelArgs.cpu_kstack[0].start); 169 170 // Apply any weird EFI quirks 171 quirks_init(); 172 173 // Begin architecture-centric kernel entry. 174 arch_start_kernel(kernelEntry); 175 176 panic("Shouldn't get here!"); 177 } 178 179 180 extern "C" void 181 platform_exit(void) 182 { 183 kRuntimeServices->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL); 184 return; 185 } 186 187 188 /** 189 * efi_main - The entry point for the EFI application 190 * @image: firmware-allocated handle that identifies the image 191 * @systemTable: EFI system table 192 */ 193 extern "C" efi_status 194 efi_main(efi_handle image, efi_system_table *systemTable) 195 { 196 stage2_args args; 197 198 memset(&args, 0, sizeof(stage2_args)); 199 200 kImage = image; 201 kSystemTable = systemTable; 202 kBootServices = systemTable->BootServices; 203 kRuntimeServices = systemTable->RuntimeServices; 204 205 call_ctors(); 206 207 console_init(); 208 serial_init(); 209 serial_enable(); 210 211 sBootOptions = console_check_boot_keys(); 212 213 // disable apm in case we ever load a 32-bit kernel... 214 gKernelArgs.platform_args.apm.version = 0; 215 216 cpu_init(); 217 acpi_init(); 218 dtb_init(); 219 timer_init(); 220 smp_init(); 221 222 main(&args); 223 224 return EFI_SUCCESS; 225 } 226