xref: /haiku/src/system/boot/platform/openfirmware/start.cpp (revision 481f986b59e7782458dcc5fe98ad59a57480e5db)
1 /*
2  * Copyright 2003-2010, Axel Dörfler, axeld@pinc-software.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include <OS.h>
8 #include <boot/platform.h>
9 #include <boot/stage2.h>
10 #include <boot/heap.h>
11 #include <platform/openfirmware/openfirmware.h>
12 #include <platform_arch.h>
13 
14 #include <string.h>
15 
16 #include "console.h"
17 #include "machine.h"
18 #include "real_time_clock.h"
19 
20 
21 #define HEAP_SIZE 65536
22 
23 
24 extern "C" void _start(uint32 _unused1, uint32 _unused2,
25 	void *openFirmwareEntry);
26 extern "C" void start(void *openFirmwareEntry);
27 
28 // GCC defined globals
29 extern void (*__ctor_list)(void);
30 extern void (*__ctor_end)(void);
31 extern uint8 __bss_start;
32 extern uint8 _end;
33 
34 uint32 gMachine;
35 
36 
37 static 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 static void
49 clear_bss(void)
50 {
51 	memset(&__bss_start, 0, &_end - &__bss_start);
52 }
53 
54 
55 static void
56 determine_machine(void)
57 {
58 	gMachine = MACHINE_UNKNOWN;
59 
60 	int root = of_finddevice("/");
61 	char buffer[64];
62 	int length;
63 	if ((length = of_getprop(root, "device_type", buffer, sizeof(buffer) - 1)) == OF_FAILED)
64 		return;
65 	buffer[length] = '\0';
66 
67 	// ToDo: add more, and be as generic as possible
68 
69 	if (!strcasecmp("chrp", buffer))
70 		gMachine = MACHINE_CHRP;
71 	else if (!strcasecmp("bootrom", buffer))
72 		gMachine = MACHINE_MAC;
73 
74 	if ((length = of_getprop(root, "model", buffer, sizeof(buffer) - 1)) == OF_FAILED)
75 		return;
76 	buffer[length] = '\0';
77 
78 	if (!strcasecmp("pegasos", buffer))
79 		gMachine |= MACHINE_PEGASOS;
80 }
81 
82 
83 extern "C" void
84 platform_start_kernel(void)
85 {
86 	addr_t kernelEntry = gKernelArgs.kernel_image.elf_header.e_entry;
87 	addr_t stackTop = gKernelArgs.cpu_kstack[0].start
88 		+ gKernelArgs.cpu_kstack[0].size;
89 
90 	printf("kernel entry at %p\n", (void*)kernelEntry);
91 	printf("kernel stack top: %p\n", (void*)stackTop);
92 
93 	/* TODO: ?
94 	mmu_init_for_kernel();
95 	smp_boot_other_cpus();
96 	*/
97 
98 	status_t error = arch_start_kernel(&gKernelArgs, kernelEntry, stackTop);
99 
100 	panic("Kernel returned! Return value: %ld\n", error);
101 }
102 
103 
104 extern "C" void
105 platform_exit(void)
106 {
107 	of_interpret("reset-all", 0, 0);
108 }
109 
110 
111 extern "C" uint32
112 platform_boot_options(void)
113 {
114 	// ToDo: implement me!
115 	return 0;
116 }
117 
118 
119 extern "C" void
120 _start(uint32 _unused1, uint32 _unused3, void *openFirmwareEntry)
121 {
122 	// According to the PowerPC bindings, OpenFirmware should have created
123 	// a stack of 32kB or higher for us at this point
124 
125 	clear_bss();
126 	call_ctors();
127 		// call C++ constructors before doing anything else
128 
129 	start(openFirmwareEntry);
130 }
131 
132 
133 extern "C" void
134 start(void *openFirmwareEntry)
135 {
136 	char bootargs[512];
137 
138 	// stage2 args - might be set via the command line one day
139 	stage2_args args;
140 	args.heap_size = HEAP_SIZE;
141 	args.arguments = NULL;
142 
143 	of_init((int (*)(void*))openFirmwareEntry);
144 
145 	// check for arguments
146 	if (of_getprop(gChosen, "bootargs", bootargs, sizeof(bootargs)) != OF_FAILED) {
147 		static const char *sArgs[] = { NULL, NULL };
148 		sArgs[0] = (const char *)bootargs;
149 		args.arguments = sArgs;
150 	}
151 
152 	determine_machine();
153 	console_init();
154 
155 	// Initialize and take over MMU and set the OpenFirmware callbacks - it
156 	// will ask us for memory after that instead of maintaining it itself
157 	// (the kernel will need to adjust the callback later on as well)
158 	arch_mmu_init();
159 
160 	if (boot_arch_cpu_init() != B_OK)
161 		of_exit();
162 
163 	if (init_real_time_clock() != B_OK)
164 		of_exit();
165 
166 	gKernelArgs.platform_args.openfirmware_entry = openFirmwareEntry;
167 
168 	main(&args);
169 		// if everything goes fine, main() never returns
170 
171 	of_exit();
172 }
173