xref: /haiku/src/system/boot/platform/riscv/start.cpp (revision 9e25244c5e9051f6cd333820d6332397361abd6c)
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
30 extern void (*__ctor_list)(void);
31 extern void (*__ctor_end)(void);
32 extern uint8 __bss_start;
33 extern uint8 _end;
34 
35 extern "C" int main(stage2_args* args);
36 extern "C" void _start(int hartId, void* fdt);
37 extern "C" status_t arch_enter_kernel(uint64 satp,
38 	struct kernel_args* kernelArgs, addr_t kernelEntry, addr_t kernelStackTop);
39 
40 
41 static uint32 sBootOptions;
42 static bool sBootOptionsValid = false;
43 
44 
45 static void
46 clear_bss(void)
47 {
48 	memset(&__bss_start, 0, &_end - &__bss_start);
49 }
50 
51 
52 static void
53 call_ctors(void)
54 {
55 	void (**f)(void);
56 
57 	for (f = &__ctor_list; f < &__ctor_end; f++)
58 		(**f)();
59 }
60 
61 
62 static uint32
63 check_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 
79 extern "C" uint32
80 platform_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 
95 static void
96 convert_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 
109 static void
110 convert_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 
153 extern "C" void
154 platform_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 
191 extern "C" void
192 platform_exit(void)
193 {
194 	HtifShutdown();
195 }
196 
197 
198 extern "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