xref: /haiku/src/system/boot/platform/openfirmware/start.cpp (revision 9f739dd2e868114ce19ae73afcff07caf2ddb8b6)
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