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