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