1/*
2 * Copyright 2003-2010, Axel D��rfler, axeld@pinc-software.de.
3 * Copyright 2008, Fran��ois Revol, revol@free.fr. All rights reserved.
4 * Distributed under the terms of the MIT License.
5 */
6
7
8#include <KernelExport.h>
9#include <boot/platform.h>
10#include <boot/heap.h>
11#include <boot/stage2.h>
12#include <arch/cpu.h>
13
14#include <string.h>
15
16#include "console.h"
17#include "cpu.h"
18#include "mmu.h"
19#include "smp.h"
20#include "traps.h"
21#include "fdt.h"
22#include "Htif.h"
23#include "virtio.h"
24#include "graphics.h"
25
26
27#define HEAP_SIZE (1024*1024)
28
29// GCC defined globals
30extern void (*__ctor_list)(void);
31extern void (*__ctor_end)(void);
32extern uint8 __bss_start;
33extern uint8 _end;
34
35extern "C" int main(stage2_args* args);
36extern "C" void _start(int hartId, void* fdt);
37extern "C" status_t arch_enter_kernel(uint64 satp,
38	struct kernel_args* kernelArgs, addr_t kernelEntry, addr_t kernelStackTop);
39
40
41static uint32 sBootOptions;
42static bool sBootOptionsValid = false;
43
44
45static void
46clear_bss(void)
47{
48	memset(&__bss_start, 0, &_end - &__bss_start);
49}
50
51
52static void
53call_ctors(void)
54{
55	void (**f)(void);
56
57	for (f = &__ctor_list; f < &__ctor_end; f++)
58		(**f)();
59}
60
61
62static uint32
63check_for_boot_keys()
64{
65	uint32 options = 0;
66	bigtime_t t0 = system_time();
67	while (system_time() - t0 < 100000) {
68		int key = virtio_input_get_key();
69		switch(key) {
70			case 94 /* space */:
71				options |= BOOT_OPTION_MENU;
72				break;
73		}
74	}
75	return options;
76}
77
78
79extern "C" uint32
80platform_boot_options(void)
81{
82	if (!sBootOptionsValid) {
83		sBootOptions = check_for_boot_keys();
84		sBootOptionsValid = true;
85/*
86		if (sBootOptions & BOOT_OPTION_DEBUG_OUTPUT)
87			serial_enable();
88*/
89	}
90
91	return sBootOptions;
92}
93
94
95static void
96convert_preloaded_image(preloaded_elf64_image* image)
97{
98	fix_address(image->next);
99	fix_address(image->name);
100	fix_address(image->debug_string_table);
101	fix_address(image->syms);
102	fix_address(image->rel);
103	fix_address(image->rela);
104	fix_address(image->pltrel);
105	fix_address(image->debug_symbols);
106}
107
108
109static void
110convert_kernel_args()
111{
112	if (gKernelArgs.kernel_image->elf_class != ELFCLASS64)
113		return;
114
115	fix_address(gKernelArgs.boot_volume);
116	fix_address(gKernelArgs.vesa_modes);
117	fix_address(gKernelArgs.edid_info);
118	fix_address(gKernelArgs.debug_output);
119	fix_address(gKernelArgs.boot_splash);
120	#if defined(__x86_64__) || defined(__x86__)
121	fix_address(gKernelArgs.ucode_data);
122	fix_address(gKernelArgs.arch_args.apic);
123	fix_address(gKernelArgs.arch_args.hpet);
124	#endif
125	fix_address(gKernelArgs.arch_args.fdt);
126
127	convert_preloaded_image(static_cast<preloaded_elf64_image*>(
128		gKernelArgs.kernel_image.Pointer()));
129	fix_address(gKernelArgs.kernel_image);
130
131	// Iterate over the preloaded images. Must save the next address before
132	// converting, as the next pointer will be converted.
133	preloaded_image* image = gKernelArgs.preloaded_images;
134	fix_address(gKernelArgs.preloaded_images);
135	while (image != NULL) {
136		preloaded_image* next = image->next;
137		convert_preloaded_image(static_cast<preloaded_elf64_image*>(image));
138		image = next;
139	}
140
141	// Fix driver settings files.
142	driver_settings_file* file = gKernelArgs.driver_settings;
143	fix_address(gKernelArgs.driver_settings);
144	while (file != NULL) {
145		driver_settings_file* next = file->next;
146		fix_address(file->next);
147		fix_address(file->buffer);
148		file = next;
149	}
150}
151
152
153extern "C" void
154platform_start_kernel(void)
155{
156	static struct kernel_args* args = &gKernelArgs;
157	// platform_bootloader_address_to_kernel_address(&gKernelArgs, (addr_t*)&args);
158
159	preloaded_elf64_image* image = static_cast<preloaded_elf64_image*>(
160		gKernelArgs.kernel_image.Pointer());
161
162	smp_init_other_cpus();
163	//serial_cleanup();
164
165	// Avoid interrupts from virtio devices before kernel driver takes control.
166	virtio_fini();
167
168	// The native, non-SBI bootloader manually installs mmode hooks
169	gKernelArgs.arch_args.machine_platform = kPlatformMNative;
170
171	fdt_set_kernel_args();
172
173	convert_kernel_args();
174	uint64 satp;
175	mmu_init_for_kernel(satp);
176
177	smp_boot_other_cpus(satp, image->elf_header.e_entry);
178
179	dprintf("kernel entry: %lx\n", image->elf_header.e_entry);
180	dprintf("args: %lx\n", (addr_t)args);
181
182	addr_t stackTop
183		= gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size;
184	arch_enter_kernel(satp, args, image->elf_header.e_entry, stackTop);
185
186	panic("kernel returned!\n");
187
188}
189
190
191extern "C" void
192platform_exit(void)
193{
194	HtifShutdown();
195}
196
197
198extern "C" void
199_start(int hartId, void* fdt)
200{
201	HtifOutString("haiku_loader entry point\n");
202
203	clear_bss();
204	fdt_init(fdt);
205	call_ctors();
206
207	stage2_args args;
208	args.heap_size = HEAP_SIZE;
209	args.arguments = NULL;
210
211	traps_init();
212	// console_init();
213	// virtio_init();
214	cpu_init();
215	mmu_init();
216	//apm_init();
217	smp_init();
218
219	main(&args);
220}
221