1 /*
2 * Copyright 2014-2021 Haiku, Inc. All rights reserved.
3 * Copyright 2013-2014, Fredrik Holmqvist, fredrik.holmqvist@gmail.com.
4 * Copyright 2014, Henry Harrington, henry.harrington@gmail.com.
5 * All rights reserved.
6 * Distributed under the terms of the MIT License.
7 */
8
9
10 #include <string.h>
11
12 #include <KernelExport.h>
13
14 #include <arch/cpu.h>
15 #include <arch_cpu_defs.h>
16 #include <kernel.h>
17
18 #include <boot/kernel_args.h>
19 #include <boot/platform.h>
20 #include <boot/stage2.h>
21 #include <boot/stdio.h>
22
23 #include "arch_mmu.h"
24 #include "arch_start.h"
25 #include "acpi.h"
26 #include "console.h"
27 #include "cpu.h"
28 #include "debug.h"
29 #ifdef _BOOT_FDT_SUPPORT
30 #include "dtb.h"
31 #endif
32 #include "efi_platform.h"
33 #include "mmu.h"
34 #include "quirks.h"
35 #include "serial.h"
36 #include "smp.h"
37 #include "timer.h"
38
39
40 extern void (*__ctor_list)(void);
41 extern void (*__ctor_end)(void);
42
43
44 const efi_system_table *kSystemTable;
45 const efi_boot_services *kBootServices;
46 const efi_runtime_services *kRuntimeServices;
47 efi_handle kImage;
48
49
50 static uint32 sBootOptions;
51
52 extern "C" int main(stage2_args *args);
53 extern "C" void _start(void);
54 extern "C" void efi_enter_kernel(uint64 pml4, uint64 entry_point, uint64 stack);
55
56
57 static void
call_ctors(void)58 call_ctors(void)
59 {
60 void (**f)(void);
61
62 for (f = &__ctor_list; f < &__ctor_end; f++)
63 (**f)();
64 }
65
66
67 extern "C" uint32
platform_boot_options()68 platform_boot_options()
69 {
70 return sBootOptions;
71 }
72
73
74 template<class T> static void
convert_preloaded_image(preloaded_image * _image)75 convert_preloaded_image(preloaded_image* _image)
76 {
77 T* image = static_cast<T*>(_image);
78 fix_address(image->next);
79 fix_address(image->name);
80 fix_address(image->debug_string_table);
81 fix_address(image->syms);
82 fix_address(image->rel);
83 fix_address(image->rela);
84 fix_address(image->pltrel);
85 fix_address(image->debug_symbols);
86 }
87
88
89 /*! Convert all addresses in kernel_args to virtual addresses. */
90 static void
convert_kernel_args()91 convert_kernel_args()
92 {
93 fix_address(gKernelArgs.boot_volume);
94 fix_address(gKernelArgs.vesa_modes);
95 fix_address(gKernelArgs.edid_info);
96 fix_address(gKernelArgs.debug_output);
97 fix_address(gKernelArgs.boot_splash);
98
99 arch_convert_kernel_args();
100
101 if (gKernelArgs.kernel_image->elf_class == ELFCLASS64) {
102 convert_preloaded_image<preloaded_elf64_image>(gKernelArgs.kernel_image);
103 } else {
104 convert_preloaded_image<preloaded_elf32_image>(gKernelArgs.kernel_image);
105 }
106 fix_address(gKernelArgs.kernel_image);
107
108 // Iterate over the preloaded images. Must save the next address before
109 // converting, as the next pointer will be converted.
110 preloaded_image* image = gKernelArgs.preloaded_images;
111 fix_address(gKernelArgs.preloaded_images);
112 while (image != NULL) {
113 preloaded_image* next = image->next;
114 if (image->elf_class == ELFCLASS64) {
115 convert_preloaded_image<preloaded_elf64_image>(image);
116 } else {
117 convert_preloaded_image<preloaded_elf32_image>(image);
118 }
119 image = next;
120 }
121
122 // Fix driver settings files.
123 driver_settings_file* file = gKernelArgs.driver_settings;
124 fix_address(gKernelArgs.driver_settings);
125 while (file != NULL) {
126 driver_settings_file* next = file->next;
127 fix_address(file->next);
128 fix_address(file->buffer);
129 file = next;
130 }
131 }
132
133
134 static addr_t
get_kernel_entry(void)135 get_kernel_entry(void)
136 {
137 if (gKernelArgs.kernel_image->elf_class == ELFCLASS64) {
138 preloaded_elf64_image *image = static_cast<preloaded_elf64_image *>(
139 gKernelArgs.kernel_image.Pointer());
140 return image->elf_header.e_entry;
141 } else if (gKernelArgs.kernel_image->elf_class == ELFCLASS32) {
142 preloaded_elf32_image *image = static_cast<preloaded_elf32_image *>(
143 gKernelArgs.kernel_image.Pointer());
144 return image->elf_header.e_entry;
145 }
146 panic("Unknown kernel format! Not 32-bit or 64-bit!");
147 return 0;
148 }
149
150
151 static void
get_kernel_regions(addr_range & text,addr_range & data)152 get_kernel_regions(addr_range& text, addr_range& data)
153 {
154 if (gKernelArgs.kernel_image->elf_class == ELFCLASS64) {
155 preloaded_elf64_image *image = static_cast<preloaded_elf64_image *>(
156 gKernelArgs.kernel_image.Pointer());
157 text.start = image->text_region.start;
158 text.size = image->text_region.size;
159 data.start = image->data_region.start;
160 data.size = image->data_region.size;
161 return;
162 } else if (gKernelArgs.kernel_image->elf_class == ELFCLASS32) {
163 preloaded_elf32_image *image = static_cast<preloaded_elf32_image *>(
164 gKernelArgs.kernel_image.Pointer());
165 text.start = image->text_region.start;
166 text.size = image->text_region.size;
167 data.start = image->data_region.start;
168 data.size = image->data_region.size;
169 return;
170 }
171 panic("Unknown kernel format! Not 32-bit or 64-bit!");
172 }
173
174
175 extern "C" void
platform_start_kernel(void)176 platform_start_kernel(void)
177 {
178 smp_init_other_cpus();
179 #ifdef _BOOT_FDT_SUPPORT
180 dtb_set_kernel_args();
181 #endif
182
183 addr_t kernelEntry = get_kernel_entry();
184
185 addr_range textRegion = {.start = 0, .size = 0}, dataRegion = {.start = 0, .size = 0};
186 get_kernel_regions(textRegion, dataRegion);
187 dprintf("kernel:\n");
188 dprintf(" text: %#" B_PRIx64 ", %#" B_PRIx64 "\n", textRegion.start, textRegion.size);
189 dprintf(" data: %#" B_PRIx64 ", %#" B_PRIx64 "\n", dataRegion.start, dataRegion.size);
190 dprintf(" entry: %#lx\n", kernelEntry);
191
192 debug_cleanup();
193
194 arch_mmu_init();
195 convert_kernel_args();
196
197 // map in a kernel stack
198 void *stack_address = NULL;
199 if (platform_allocate_region(&stack_address,
200 KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE, 0, false)
201 != B_OK) {
202 panic("Unabled to allocate a stack");
203 }
204 gKernelArgs.cpu_kstack[0].start = fix_address((addr_t)stack_address);
205 gKernelArgs.cpu_kstack[0].size = KERNEL_STACK_SIZE
206 + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE;
207 dprintf("Kernel stack at %#" B_PRIx64 "\n", gKernelArgs.cpu_kstack[0].start);
208
209 // Apply any weird EFI quirks
210 quirks_init();
211
212 // Begin architecture-centric kernel entry.
213 arch_start_kernel(kernelEntry);
214
215 panic("Shouldn't get here!");
216 }
217
218
219 extern "C" void
platform_exit(void)220 platform_exit(void)
221 {
222 kRuntimeServices->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
223 return;
224 }
225
226
227 /**
228 * efi_main - The entry point for the EFI application
229 * @image: firmware-allocated handle that identifies the image
230 * @systemTable: EFI system table
231 */
232 extern "C" efi_status
efi_main(efi_handle image,efi_system_table * systemTable)233 efi_main(efi_handle image, efi_system_table *systemTable)
234 {
235 stage2_args args;
236 memset(&args, 0, sizeof(stage2_args));
237
238 kImage = image;
239 kSystemTable = systemTable;
240 kBootServices = systemTable->BootServices;
241 kRuntimeServices = systemTable->RuntimeServices;
242
243 call_ctors();
244
245 console_init();
246 serial_init();
247 serial_enable();
248
249 sBootOptions = console_check_boot_keys();
250
251 // disable apm in case we ever load a 32-bit kernel...
252 gKernelArgs.platform_args.apm.version = 0;
253
254 cpu_init();
255 acpi_init();
256 #ifdef _BOOT_FDT_SUPPORT
257 dtb_init();
258 #endif
259 timer_init();
260 smp_init();
261
262 main(&args);
263
264 return EFI_SUCCESS;
265 }
266