1/*
2 * Copyright 2011, Fran��ois Revol, revol@free.fr.
3 * Copyright 2003-2010, Axel D��rfler, axeld@pinc-software.de.
4 * Copyright 2011, Alexander von Gluck, kallisti5@unixzen.com
5 * Distributed under the terms of the MIT License.
6 */
7
8
9#include <string.h>
10
11#include <OS.h>
12
13#include <boot/platform.h>
14#include <boot/stage2.h>
15#include <boot/heap.h>
16#include <boot/platform/cfe/cfe.h>
17#include <platform_arch.h>
18
19#include "console.h"
20#include "real_time_clock.h"
21
22
23#define HEAP_SIZE 65536
24
25
26extern "C" uint32 _start(uint64 handle, uint64 entry, uint32 _unused,
27	uint32 signature);
28extern "C" void start(uint64 cfeHandle, uint64 cfeEntry);
29
30// GCC defined globals
31extern void (*__ctor_list)(void);
32extern void (*__ctor_end)(void);
33extern uint8 __bss_start;
34extern uint8 _end;
35
36#if 0//OF
37uint32 gMachine;
38#endif
39static uint32 sBootOptions;
40
41
42static void
43call_ctors(void)
44{
45	void (**f)(void);
46
47	for (f = &__ctor_list; f < &__ctor_end; f++) {
48		(**f)();
49	}
50}
51
52
53static void
54clear_bss(void)
55{
56	memset(&__bss_start, 0, &_end - &__bss_start);
57}
58
59
60extern "C" void
61platform_start_kernel(void)
62{
63	preloaded_elf32_image* image = static_cast<preloaded_elf32_image*>(
64		gKernelArgs.kernel_image.Pointer());
65
66	addr_t kernelEntry = image->elf_header.e_entry;
67	addr_t stackTop = gKernelArgs.cpu_kstack[0].start
68		+ gKernelArgs.cpu_kstack[0].size;
69
70	printf("kernel entry at %p\n", (void*)kernelEntry);
71	printf("kernel stack top: %p\n", (void*)stackTop);
72
73	/* TODO: ?
74	mmu_init_for_kernel();
75	smp_boot_other_cpus();
76	*/
77
78	status_t error = arch_start_kernel(&gKernelArgs, kernelEntry, stackTop);
79
80	panic("Kernel returned! Return value: %ld\n", error);
81}
82
83
84extern "C" void
85platform_exit(void)
86{
87	cfe_exit(CFE_FLG_WARMSTART, 0);
88	panic("cfe_exit() failed.");
89}
90
91
92extern "C" uint32
93platform_boot_options(void)
94{
95	return sBootOptions;
96}
97
98
99extern "C" uint32
100_start(uint64 handle, uint64 entry, uint32 _unused, uint32 signature)
101{
102
103	if (signature != CFE_EPTSEAL)
104		return 123;//XXX:something?
105
106	clear_bss();
107	call_ctors();
108		// call C++ constructors before doing anything else
109	//return 456;
110
111	start(handle, entry);
112}
113
114
115extern "C" void
116start(uint64 cfeHandle, uint64 cfeEntry)
117{
118	char bootargs[512];
119
120	// stage2 args - might be set via the command line one day
121	stage2_args args;
122	args.heap_size = HEAP_SIZE;
123	args.arguments = NULL;
124
125	cfe_init(cfeHandle, cfeEntry);
126
127	// check for arguments
128#if 0//OF
129	if (of_getprop(gChosen, "bootargs", bootargs, sizeof(bootargs))
130			!= OF_FAILED) {
131		static const char *sArgs[] = { NULL, NULL };
132		sArgs[0] = (const char *)bootargs;
133		args.arguments = sArgs;
134	}
135#endif
136
137#if 0//OF
138	determine_machine();
139#endif
140	console_init();
141
142	// XXX:FIXME: doesn't even land here.
143	dprintf("testing...\n");
144	while (true);
145
146#if 0//OF
147	if ((gMachine & MACHINE_QEMU) != 0)
148		dprintf("OpenBIOS (QEMU?) OpenFirmware machine detected\n");
149	else if ((gMachine & MACHINE_PEGASOS) != 0)
150		dprintf("Pegasos PowerPC machine detected\n");
151	else
152		dprintf("Apple PowerPC machine assumed\n");
153#endif
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		cfe_exit(CFE_FLG_WARMSTART, 1);
162
163#if 0//OF FIXME
164	if (init_real_time_clock() != B_OK)
165		cfe_exit(CFE_FLG_WARMSTART, 1);
166#endif
167
168	// check for key presses once
169	sBootOptions = 0;
170	int key = console_check_for_key();
171	if (key == 32) {
172		// space bar: option menu
173		sBootOptions |= BOOT_OPTION_MENU;
174	} else if (key == 27) {
175		// ESC: debug output
176		sBootOptions |= BOOT_OPTION_DEBUG_OUTPUT;
177	}
178
179	gKernelArgs.platform_args.cfe_entry = cfeEntry;
180
181	main(&args);
182		// if everything goes fine, main() never returns
183
184	cfe_exit(CFE_FLG_WARMSTART, 1);
185}
186