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 24 25 #define HEAP_SIZE 65536 26 27 28 // GCC defined globals 29 extern void (*__ctor_list)(void); 30 extern void (*__ctor_end)(void); 31 32 uint32 gMachine; 33 static uint32 sBootOptions; 34 35 36 void 37 call_ctors(void) 38 { 39 void (**f)(void); 40 41 for (f = &__ctor_list; f < &__ctor_end; f++) { 42 (**f)(); 43 } 44 } 45 46 47 extern "C" void 48 platform_start_kernel(void) 49 { 50 preloaded_elf32_image* image = static_cast<preloaded_elf32_image*>( 51 gKernelArgs.kernel_image.Pointer()); 52 53 addr_t kernelEntry = image->elf_header.e_entry; 54 addr_t stackTop = gKernelArgs.cpu_kstack[0].start 55 + gKernelArgs.cpu_kstack[0].size; 56 57 printf("kernel entry at %p\n", (void*)kernelEntry); 58 printf("kernel stack top: %p\n", (void*)stackTop); 59 60 /* TODO: ? 61 mmu_init_for_kernel(); 62 smp_boot_other_cpus(); 63 */ 64 65 status_t error = arch_start_kernel(&gKernelArgs, kernelEntry, stackTop); 66 67 panic("Kernel returned! Return value: %" B_PRId32 "\n", error); 68 } 69 70 71 extern "C" void 72 platform_exit(void) 73 { 74 of_interpret("reset-all", 0, 0); 75 } 76 77 78 extern "C" uint32 79 platform_boot_options(void) 80 { 81 return sBootOptions; 82 } 83 84 85 extern "C" void 86 start(void *openFirmwareEntry) 87 { 88 char bootargs[512]; 89 90 // stage2 args - might be set via the command line one day 91 stage2_args args; 92 args.heap_size = HEAP_SIZE; 93 args.arguments = NULL; 94 95 if (of_init((intptr_t (*)(void*))openFirmwareEntry) != B_OK) 96 return; 97 98 // check for arguments 99 if (of_getprop(gChosen, "bootargs", bootargs, sizeof(bootargs)) 100 != OF_FAILED) { 101 static const char *sArgs[] = { NULL, NULL }; 102 sArgs[0] = (const char *)bootargs; 103 args.arguments = sArgs; 104 args.arguments_count = 1; 105 } 106 107 determine_machine(); 108 if (console_init() != B_OK) 109 return; 110 111 #ifdef __powerpc__ 112 if ((gMachine & MACHINE_QEMU) != 0) 113 dprintf("OpenBIOS (QEMU?) OpenFirmware machine detected\n"); 114 else if ((gMachine & MACHINE_PEGASOS) != 0) 115 dprintf("Pegasos PowerPC machine detected\n"); 116 else 117 dprintf("Apple PowerPC machine assumed\n"); 118 #endif 119 120 // Initialize and take over MMU and set the OpenFirmware callbacks - it 121 // will ask us for memory after that instead of maintaining it itself 122 // (the kernel will need to adjust the callback later on as well) 123 arch_mmu_init(); 124 125 if (boot_arch_cpu_init() != B_OK) 126 of_exit(); 127 128 // check for key presses once 129 sBootOptions = 0; 130 int key = console_check_for_key(); 131 if (key == 32) { 132 // space bar: option menu 133 sBootOptions |= BOOT_OPTION_MENU; 134 } else if (key == 27) { 135 // ESC: debug output 136 sBootOptions |= BOOT_OPTION_DEBUG_OUTPUT; 137 } 138 139 gKernelArgs.platform_args.openfirmware_entry = openFirmwareEntry; 140 141 main(&args); 142 // if everything goes fine, main() never returns 143 144 of_exit(); 145 } 146