1 /* 2 * Copyright 2003-2010, Axel Dörfler, axeld@pinc-software.de. 3 * Copyright 2008, François Revol, revol@free.fr. All rights reserved. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include <KernelExport.h> 9 #include <boot/platform.h> 10 #include <boot/heap.h> 11 #include <boot/stage2.h> 12 #include <arch/cpu.h> 13 14 #include <string.h> 15 16 #include "console.h" 17 #include "cpu.h" 18 #include "mmu.h" 19 #include "smp.h" 20 #include "traps.h" 21 #include "fdt.h" 22 #include "Htif.h" 23 #include "virtio.h" 24 #include "graphics.h" 25 26 27 // GCC defined globals 28 extern void (*__ctor_list)(void); 29 extern void (*__ctor_end)(void); 30 extern uint8 __bss_start; 31 extern uint8 _end; 32 33 extern "C" int main(stage2_args* args); 34 extern "C" void _start(int hartId, void* fdt); 35 extern "C" status_t arch_enter_kernel(uint64 satp, 36 struct kernel_args* kernelArgs, addr_t kernelEntry, addr_t kernelStackTop); 37 38 39 static uint32 sBootOptions; 40 static bool sBootOptionsValid = false; 41 42 43 static void 44 clear_bss(void) 45 { 46 memset(&__bss_start, 0, &_end - &__bss_start); 47 } 48 49 50 static void 51 call_ctors(void) 52 { 53 void (**f)(void); 54 55 for (f = &__ctor_list; f < &__ctor_end; f++) 56 (**f)(); 57 } 58 59 60 static uint32 61 check_for_boot_keys() 62 { 63 uint32 options = 0; 64 bigtime_t t0 = system_time(); 65 while (system_time() - t0 < 100000) { 66 int key = virtio_input_get_key(); 67 switch(key) { 68 case 94 /* space */: 69 options |= BOOT_OPTION_MENU; 70 break; 71 } 72 } 73 return options; 74 } 75 76 77 extern "C" uint32 78 platform_boot_options(void) 79 { 80 if (!sBootOptionsValid) { 81 sBootOptions = check_for_boot_keys(); 82 sBootOptionsValid = true; 83 /* 84 if (sBootOptions & BOOT_OPTION_DEBUG_OUTPUT) 85 serial_enable(); 86 */ 87 } 88 89 return sBootOptions; 90 } 91 92 93 static void 94 convert_preloaded_image(preloaded_elf64_image* image) 95 { 96 fix_address(image->next); 97 fix_address(image->name); 98 fix_address(image->debug_string_table); 99 fix_address(image->syms); 100 fix_address(image->rel); 101 fix_address(image->rela); 102 fix_address(image->pltrel); 103 fix_address(image->debug_symbols); 104 } 105 106 107 static void 108 convert_kernel_args() 109 { 110 if (gKernelArgs.kernel_image->elf_class != ELFCLASS64) 111 return; 112 113 fix_address(gKernelArgs.boot_volume); 114 fix_address(gKernelArgs.vesa_modes); 115 fix_address(gKernelArgs.edid_info); 116 fix_address(gKernelArgs.debug_output); 117 fix_address(gKernelArgs.boot_splash); 118 #if defined(__x86_64__) || defined(__x86__) 119 fix_address(gKernelArgs.ucode_data); 120 fix_address(gKernelArgs.arch_args.apic); 121 fix_address(gKernelArgs.arch_args.hpet); 122 #endif 123 fix_address(gKernelArgs.arch_args.fdt); 124 125 convert_preloaded_image(static_cast<preloaded_elf64_image*>( 126 gKernelArgs.kernel_image.Pointer())); 127 fix_address(gKernelArgs.kernel_image); 128 129 // Iterate over the preloaded images. Must save the next address before 130 // converting, as the next pointer will be converted. 131 preloaded_image* image = gKernelArgs.preloaded_images; 132 fix_address(gKernelArgs.preloaded_images); 133 while (image != NULL) { 134 preloaded_image* next = image->next; 135 convert_preloaded_image(static_cast<preloaded_elf64_image*>(image)); 136 image = next; 137 } 138 139 // Fix driver settings files. 140 driver_settings_file* file = gKernelArgs.driver_settings; 141 fix_address(gKernelArgs.driver_settings); 142 while (file != NULL) { 143 driver_settings_file* next = file->next; 144 fix_address(file->next); 145 fix_address(file->buffer); 146 file = next; 147 } 148 } 149 150 151 extern "C" void 152 platform_start_kernel(void) 153 { 154 static struct kernel_args* args = &gKernelArgs; 155 // platform_bootloader_address_to_kernel_address(&gKernelArgs, (addr_t*)&args); 156 157 preloaded_elf64_image* image = static_cast<preloaded_elf64_image*>( 158 gKernelArgs.kernel_image.Pointer()); 159 160 smp_init_other_cpus(); 161 //serial_cleanup(); 162 163 // Avoid interrupts from virtio devices before kernel driver takes control. 164 virtio_fini(); 165 166 // The native, non-SBI bootloader manually installs mmode hooks 167 gKernelArgs.arch_args.machine_platform = kPlatformMNative; 168 169 fdt_set_kernel_args(); 170 171 convert_kernel_args(); 172 uint64 satp; 173 mmu_init_for_kernel(satp); 174 175 smp_boot_other_cpus(satp, image->elf_header.e_entry); 176 177 dprintf("kernel entry: %lx\n", image->elf_header.e_entry); 178 dprintf("args: %lx\n", (addr_t)args); 179 180 addr_t stackTop 181 = gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size; 182 arch_enter_kernel(satp, args, image->elf_header.e_entry, stackTop); 183 184 panic("kernel returned!\n"); 185 186 } 187 188 189 extern "C" void 190 platform_exit(void) 191 { 192 HtifShutdown(); 193 } 194 195 196 extern "C" void 197 _start(int hartId, void* fdt) 198 { 199 HtifOutString("haiku_loader entry point\n"); 200 201 clear_bss(); 202 fdt_init(fdt); 203 call_ctors(); 204 205 stage2_args args; 206 args.heap_size = 0; 207 args.arguments = NULL; 208 209 traps_init(); 210 // console_init(); 211 // virtio_init(); 212 cpu_init(); 213 mmu_init(); 214 //apm_init(); 215 smp_init(); 216 217 main(&args); 218 } 219