1 /* 2 * Copyright 2003-2010, Axel Dörfler, axeld@pinc-software.de. 3 * Copyright 2011, Alexander von Gluck, kallisti5@unixzen.com 4 * Copyright 2019, Adrien Destugues, pulkomandy@pulkomandy.tk 5 * Distributed under the terms of the MIT License. 6 */ 7 8 9 #include "start.h" 10 11 #include <string.h> 12 13 #include <OS.h> 14 15 #include <boot/platform.h> 16 #include <boot/stage2.h> 17 #include <boot/heap.h> 18 #include <platform/openfirmware/openfirmware.h> 19 #include <platform_arch.h> 20 21 #include "console.h" 22 #include "machine.h" 23 #include "real_time_clock.h" 24 25 26 // GCC defined globals 27 extern void (*__ctor_list)(void); 28 extern void (*__ctor_end)(void); 29 30 uint32 gMachine; 31 static uint32 sBootOptions; 32 33 34 void 35 call_ctors(void) 36 { 37 void (**f)(void); 38 39 for (f = &__ctor_list; f < &__ctor_end; f++) { 40 (**f)(); 41 } 42 } 43 44 45 static addr_t 46 get_kernel_entry(void) 47 { 48 if (gKernelArgs.kernel_image->elf_class == ELFCLASS64) { 49 preloaded_elf64_image *image = static_cast<preloaded_elf64_image *>( 50 gKernelArgs.kernel_image.Pointer()); 51 return image->elf_header.e_entry; 52 } else if (gKernelArgs.kernel_image->elf_class == ELFCLASS32) { 53 preloaded_elf32_image *image = static_cast<preloaded_elf32_image *>( 54 gKernelArgs.kernel_image.Pointer()); 55 return image->elf_header.e_entry; 56 } 57 panic("Unknown kernel format! Not 32-bit or 64-bit!"); 58 return 0; 59 } 60 61 62 extern "C" void 63 platform_start_kernel(void) 64 { 65 addr_t kernelEntry = get_kernel_entry(); 66 addr_t stackTop = gKernelArgs.cpu_kstack[0].start 67 + gKernelArgs.cpu_kstack[0].size; 68 69 printf("kernel entry at %p\n", (void*)kernelEntry); 70 printf("kernel stack top: %p\n", (void*)stackTop); 71 72 /* TODO: ? 73 mmu_init_for_kernel(); 74 smp_boot_other_cpus(); 75 */ 76 77 status_t error = arch_start_kernel(&gKernelArgs, kernelEntry, stackTop); 78 79 panic("Kernel returned! Return value: %" B_PRId32 "\n", error); 80 } 81 82 83 extern "C" void 84 platform_exit(void) 85 { 86 of_interpret("reset-all", 0, 0); 87 } 88 89 90 extern "C" uint32 91 platform_boot_options(void) 92 { 93 return sBootOptions; 94 } 95 96 97 extern "C" void 98 start(void *openFirmwareEntry) 99 { 100 static char bootargs[512]; 101 102 // stage2 args - might be set via the command line one day 103 stage2_args args; 104 args.heap_size = 0; 105 args.arguments = NULL; 106 107 if (of_init((intptr_t (*)(void*))openFirmwareEntry) != B_OK) 108 return; 109 110 // check for arguments 111 if (of_getprop(gChosen, "bootargs", bootargs, sizeof(bootargs)) 112 != OF_FAILED) { 113 static const char *sArgs[] = { NULL, NULL }; 114 sArgs[0] = (const char *)bootargs; 115 args.arguments = sArgs; 116 args.arguments_count = 1; 117 } 118 119 determine_machine(); 120 if (console_init() != B_OK) 121 return; 122 123 #ifdef __powerpc__ 124 if ((gMachine & MACHINE_QEMU) != 0) 125 dprintf("OpenBIOS (QEMU?) OpenFirmware machine detected\n"); 126 else if ((gMachine & MACHINE_PEGASOS) != 0) 127 dprintf("Pegasos PowerPC machine detected\n"); 128 else 129 dprintf("Apple PowerPC machine assumed\n"); 130 #endif 131 132 // Initialize and take over MMU and set the OpenFirmware callbacks - it 133 // will ask us for memory after that instead of maintaining it itself 134 // (the kernel will need to adjust the callback later on as well) 135 arch_mmu_init(); 136 137 if (boot_arch_cpu_init() != B_OK) 138 of_exit(); 139 140 init_real_time_clock(); 141 142 // check for key presses once 143 sBootOptions = 0; 144 int key = console_check_for_key(); 145 if (key == 32) { 146 // space bar: option menu 147 sBootOptions |= BOOT_OPTION_MENU; 148 } else if (key == 27) { 149 // ESC: debug output 150 sBootOptions |= BOOT_OPTION_DEBUG_OUTPUT; 151 } 152 153 gKernelArgs.platform_args.openfirmware_entry = openFirmwareEntry; 154 155 main(&args); 156 // if everything goes fine, main() never returns 157 158 of_exit(); 159 } 160