1735f1daeSFredrik Holmqvist /*
2af90bfd3SDavid Karoly * Copyright 2014-2021 Haiku, Inc. All rights reserved.
3b3215a62SHenry Harrington * Copyright 2013-2014, Fredrik Holmqvist, fredrik.holmqvist@gmail.com.
4b3215a62SHenry Harrington * Copyright 2014, Henry Harrington, henry.harrington@gmail.com.
5b3215a62SHenry Harrington * All rights reserved.
647a21c5cSAugustin Cavalier * Distributed under the terms of the MIT License.
7735f1daeSFredrik Holmqvist */
8735f1daeSFredrik Holmqvist
9735f1daeSFredrik Holmqvist
10b3215a62SHenry Harrington #include <string.h>
11b3215a62SHenry Harrington
12b3215a62SHenry Harrington #include <KernelExport.h>
13b3215a62SHenry Harrington
14b3215a62SHenry Harrington #include <arch/cpu.h>
15f1fa58bfSX512 #include <arch_cpu_defs.h>
167b4d924fSAndrej Antunovikj #include <kernel.h>
177b4d924fSAndrej Antunovikj
186e6efaecSJessica Hamilton #include <boot/kernel_args.h>
19e2e1558aSJessica Hamilton #include <boot/platform.h>
20e2e1558aSJessica Hamilton #include <boot/stage2.h>
21e2e1558aSJessica Hamilton #include <boot/stdio.h>
22735f1daeSFredrik Holmqvist
2371680f7bSAlexander von Gluck IV #include "arch_mmu.h"
2404f1baa7SAlexander von Gluck IV #include "arch_start.h"
256e6efaecSJessica Hamilton #include "acpi.h"
26735f1daeSFredrik Holmqvist #include "console.h"
27d2986cb6SAlexander von Gluck IV #include "cpu.h"
284d1c5907SAugustin Cavalier #include "debug.h"
29f1fa58bfSX512 #ifdef _BOOT_FDT_SUPPORT
30569564c0SAlexander von Gluck IV #include "dtb.h"
31f1fa58bfSX512 #endif
32735f1daeSFredrik Holmqvist #include "efi_platform.h"
33b3215a62SHenry Harrington #include "mmu.h"
34d38ba84dSAlexander von Gluck IV #include "quirks.h"
359e487d8dSFredrik Holmqvist #include "serial.h"
36a99a0c00SNick Smallbone #include "smp.h"
37b482adb1SAlexander von Gluck IV #include "timer.h"
38735f1daeSFredrik Holmqvist
39735f1daeSFredrik Holmqvist
40735f1daeSFredrik Holmqvist extern void (*__ctor_list)(void);
41735f1daeSFredrik Holmqvist extern void (*__ctor_end)(void);
42735f1daeSFredrik Holmqvist
43735f1daeSFredrik Holmqvist
44485b5cf8SAlexander von Gluck IV const efi_system_table *kSystemTable;
45485b5cf8SAlexander von Gluck IV const efi_boot_services *kBootServices;
46485b5cf8SAlexander von Gluck IV const efi_runtime_services *kRuntimeServices;
47485b5cf8SAlexander von Gluck IV efi_handle kImage;
48b3215a62SHenry Harrington
49735f1daeSFredrik Holmqvist
5096f4d68bSJessica Hamilton static uint32 sBootOptions;
51b3215a62SHenry Harrington
52b3215a62SHenry Harrington extern "C" int main(stage2_args *args);
53b3215a62SHenry Harrington extern "C" void _start(void);
54b3215a62SHenry Harrington extern "C" void efi_enter_kernel(uint64 pml4, uint64 entry_point, uint64 stack);
5596f4d68bSJessica Hamilton
56735f1daeSFredrik Holmqvist
57735f1daeSFredrik Holmqvist static void
call_ctors(void)58735f1daeSFredrik Holmqvist call_ctors(void)
59735f1daeSFredrik Holmqvist {
60735f1daeSFredrik Holmqvist void (**f)(void);
61735f1daeSFredrik Holmqvist
62735f1daeSFredrik Holmqvist for (f = &__ctor_list; f < &__ctor_end; f++)
63735f1daeSFredrik Holmqvist (**f)();
64735f1daeSFredrik Holmqvist }
65735f1daeSFredrik Holmqvist
66735f1daeSFredrik Holmqvist
67e2e1558aSJessica Hamilton extern "C" uint32
platform_boot_options()68e2e1558aSJessica Hamilton platform_boot_options()
69e2e1558aSJessica Hamilton {
7096f4d68bSJessica Hamilton return sBootOptions;
71e2e1558aSJessica Hamilton }
72e2e1558aSJessica Hamilton
73e2e1558aSJessica Hamilton
74*18e885dbSDavid Karoly template<class T> static void
convert_preloaded_image(preloaded_image * _image)75*18e885dbSDavid Karoly convert_preloaded_image(preloaded_image* _image)
76b3215a62SHenry Harrington {
77*18e885dbSDavid Karoly T* image = static_cast<T*>(_image);
78b3215a62SHenry Harrington fix_address(image->next);
79b3215a62SHenry Harrington fix_address(image->name);
80b3215a62SHenry Harrington fix_address(image->debug_string_table);
81b3215a62SHenry Harrington fix_address(image->syms);
82b3215a62SHenry Harrington fix_address(image->rel);
83b3215a62SHenry Harrington fix_address(image->rela);
84b3215a62SHenry Harrington fix_address(image->pltrel);
85b3215a62SHenry Harrington fix_address(image->debug_symbols);
86b3215a62SHenry Harrington }
87b3215a62SHenry Harrington
88b3215a62SHenry Harrington
89*18e885dbSDavid Karoly /*! Convert all addresses in kernel_args to virtual addresses. */
90b3215a62SHenry Harrington static void
convert_kernel_args()91b3215a62SHenry Harrington convert_kernel_args()
92b3215a62SHenry Harrington {
93b3215a62SHenry Harrington fix_address(gKernelArgs.boot_volume);
94b3215a62SHenry Harrington fix_address(gKernelArgs.vesa_modes);
95b3215a62SHenry Harrington fix_address(gKernelArgs.edid_info);
96b3215a62SHenry Harrington fix_address(gKernelArgs.debug_output);
97b3215a62SHenry Harrington fix_address(gKernelArgs.boot_splash);
98af90bfd3SDavid Karoly
99af90bfd3SDavid Karoly arch_convert_kernel_args();
100b3215a62SHenry Harrington
101*18e885dbSDavid Karoly if (gKernelArgs.kernel_image->elf_class == ELFCLASS64) {
102*18e885dbSDavid Karoly convert_preloaded_image<preloaded_elf64_image>(gKernelArgs.kernel_image);
103*18e885dbSDavid Karoly } else {
104*18e885dbSDavid Karoly convert_preloaded_image<preloaded_elf32_image>(gKernelArgs.kernel_image);
105*18e885dbSDavid Karoly }
106b3215a62SHenry Harrington fix_address(gKernelArgs.kernel_image);
107b3215a62SHenry Harrington
108b3215a62SHenry Harrington // Iterate over the preloaded images. Must save the next address before
109b3215a62SHenry Harrington // converting, as the next pointer will be converted.
110b3215a62SHenry Harrington preloaded_image* image = gKernelArgs.preloaded_images;
111b3215a62SHenry Harrington fix_address(gKernelArgs.preloaded_images);
112b3215a62SHenry Harrington while (image != NULL) {
113b3215a62SHenry Harrington preloaded_image* next = image->next;
114*18e885dbSDavid Karoly if (image->elf_class == ELFCLASS64) {
115*18e885dbSDavid Karoly convert_preloaded_image<preloaded_elf64_image>(image);
116*18e885dbSDavid Karoly } else {
117*18e885dbSDavid Karoly convert_preloaded_image<preloaded_elf32_image>(image);
118*18e885dbSDavid Karoly }
119b3215a62SHenry Harrington image = next;
120b3215a62SHenry Harrington }
121b3215a62SHenry Harrington
122b3215a62SHenry Harrington // Fix driver settings files.
123b3215a62SHenry Harrington driver_settings_file* file = gKernelArgs.driver_settings;
124b3215a62SHenry Harrington fix_address(gKernelArgs.driver_settings);
125b3215a62SHenry Harrington while (file != NULL) {
126b3215a62SHenry Harrington driver_settings_file* next = file->next;
127b3215a62SHenry Harrington fix_address(file->next);
128b3215a62SHenry Harrington fix_address(file->buffer);
129b3215a62SHenry Harrington file = next;
130b3215a62SHenry Harrington }
131b3215a62SHenry Harrington }
132b3215a62SHenry Harrington
133b3215a62SHenry Harrington
134312ace56SAlexander von Gluck IV static addr_t
get_kernel_entry(void)135312ace56SAlexander von Gluck IV get_kernel_entry(void)
136312ace56SAlexander von Gluck IV {
137312ace56SAlexander von Gluck IV if (gKernelArgs.kernel_image->elf_class == ELFCLASS64) {
138312ace56SAlexander von Gluck IV preloaded_elf64_image *image = static_cast<preloaded_elf64_image *>(
139312ace56SAlexander von Gluck IV gKernelArgs.kernel_image.Pointer());
140312ace56SAlexander von Gluck IV return image->elf_header.e_entry;
141312ace56SAlexander von Gluck IV } else if (gKernelArgs.kernel_image->elf_class == ELFCLASS32) {
142312ace56SAlexander von Gluck IV preloaded_elf32_image *image = static_cast<preloaded_elf32_image *>(
143312ace56SAlexander von Gluck IV gKernelArgs.kernel_image.Pointer());
144312ace56SAlexander von Gluck IV return image->elf_header.e_entry;
145312ace56SAlexander von Gluck IV }
146312ace56SAlexander von Gluck IV panic("Unknown kernel format! Not 32-bit or 64-bit!");
147312ace56SAlexander von Gluck IV return 0;
148312ace56SAlexander von Gluck IV }
149312ace56SAlexander von Gluck IV
150312ace56SAlexander von Gluck IV
151f1fa58bfSX512 static void
get_kernel_regions(addr_range & text,addr_range & data)152f1fa58bfSX512 get_kernel_regions(addr_range& text, addr_range& data)
153f1fa58bfSX512 {
154f1fa58bfSX512 if (gKernelArgs.kernel_image->elf_class == ELFCLASS64) {
155f1fa58bfSX512 preloaded_elf64_image *image = static_cast<preloaded_elf64_image *>(
156f1fa58bfSX512 gKernelArgs.kernel_image.Pointer());
157f1fa58bfSX512 text.start = image->text_region.start;
158f1fa58bfSX512 text.size = image->text_region.size;
159f1fa58bfSX512 data.start = image->data_region.start;
160f1fa58bfSX512 data.size = image->data_region.size;
161f1fa58bfSX512 return;
162f1fa58bfSX512 } else if (gKernelArgs.kernel_image->elf_class == ELFCLASS32) {
163f1fa58bfSX512 preloaded_elf32_image *image = static_cast<preloaded_elf32_image *>(
164f1fa58bfSX512 gKernelArgs.kernel_image.Pointer());
165f1fa58bfSX512 text.start = image->text_region.start;
166f1fa58bfSX512 text.size = image->text_region.size;
167f1fa58bfSX512 data.start = image->data_region.start;
168f1fa58bfSX512 data.size = image->data_region.size;
169f1fa58bfSX512 return;
170f1fa58bfSX512 }
171f1fa58bfSX512 panic("Unknown kernel format! Not 32-bit or 64-bit!");
172f1fa58bfSX512 }
173f1fa58bfSX512
174f1fa58bfSX512
175e2e1558aSJessica Hamilton extern "C" void
platform_start_kernel(void)176e2e1558aSJessica Hamilton platform_start_kernel(void)
177e2e1558aSJessica Hamilton {
178a99a0c00SNick Smallbone smp_init_other_cpus();
179f1fa58bfSX512 #ifdef _BOOT_FDT_SUPPORT
180cd9b0eedSHan Pengfei dtb_set_kernel_args();
181f1fa58bfSX512 #endif
182ec239abcSJessica Hamilton
183312ace56SAlexander von Gluck IV addr_t kernelEntry = get_kernel_entry();
184b3215a62SHenry Harrington
185f1fa58bfSX512 addr_range textRegion = {.start = 0, .size = 0}, dataRegion = {.start = 0, .size = 0};
186f1fa58bfSX512 get_kernel_regions(textRegion, dataRegion);
187f1fa58bfSX512 dprintf("kernel:\n");
188f1fa58bfSX512 dprintf(" text: %#" B_PRIx64 ", %#" B_PRIx64 "\n", textRegion.start, textRegion.size);
189f1fa58bfSX512 dprintf(" data: %#" B_PRIx64 ", %#" B_PRIx64 "\n", dataRegion.start, dataRegion.size);
190f1fa58bfSX512 dprintf(" entry: %#lx\n", kernelEntry);
191f1fa58bfSX512
1924d1c5907SAugustin Cavalier debug_cleanup();
1934d1c5907SAugustin Cavalier
1947c32619cSAlexander von Gluck IV arch_mmu_init();
195b3215a62SHenry Harrington convert_kernel_args();
196b3215a62SHenry Harrington
197b3215a62SHenry Harrington // map in a kernel stack
198b3215a62SHenry Harrington void *stack_address = NULL;
199485b5cf8SAlexander von Gluck IV if (platform_allocate_region(&stack_address,
200485b5cf8SAlexander von Gluck IV KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE, 0, false)
201485b5cf8SAlexander von Gluck IV != B_OK) {
202b3215a62SHenry Harrington panic("Unabled to allocate a stack");
203b3215a62SHenry Harrington }
20405586741SAlexander von Gluck IV gKernelArgs.cpu_kstack[0].start = fix_address((addr_t)stack_address);
205485b5cf8SAlexander von Gluck IV gKernelArgs.cpu_kstack[0].size = KERNEL_STACK_SIZE
206485b5cf8SAlexander von Gluck IV + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE;
207f1fa58bfSX512 dprintf("Kernel stack at %#" B_PRIx64 "\n", gKernelArgs.cpu_kstack[0].start);
208b3215a62SHenry Harrington
209d38ba84dSAlexander von Gluck IV // Apply any weird EFI quirks
210d38ba84dSAlexander von Gluck IV quirks_init();
211d38ba84dSAlexander von Gluck IV
21204f1baa7SAlexander von Gluck IV // Begin architecture-centric kernel entry.
21304f1baa7SAlexander von Gluck IV arch_start_kernel(kernelEntry);
214b3215a62SHenry Harrington
21504f1baa7SAlexander von Gluck IV panic("Shouldn't get here!");
216e2e1558aSJessica Hamilton }
217e2e1558aSJessica Hamilton
218e2e1558aSJessica Hamilton
219e2e1558aSJessica Hamilton extern "C" void
platform_exit(void)220e2e1558aSJessica Hamilton platform_exit(void)
221e2e1558aSJessica Hamilton {
2226df09499Sbeaglejoe kRuntimeServices->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
223e2e1558aSJessica Hamilton return;
224e2e1558aSJessica Hamilton }
225e2e1558aSJessica Hamilton
226e2e1558aSJessica Hamilton
227735f1daeSFredrik Holmqvist /**
228735f1daeSFredrik Holmqvist * efi_main - The entry point for the EFI application
229735f1daeSFredrik Holmqvist * @image: firmware-allocated handle that identifies the image
230735f1daeSFredrik Holmqvist * @systemTable: EFI system table
231735f1daeSFredrik Holmqvist */
232485b5cf8SAlexander von Gluck IV extern "C" efi_status
efi_main(efi_handle image,efi_system_table * systemTable)233485b5cf8SAlexander von Gluck IV efi_main(efi_handle image, efi_system_table *systemTable)
234735f1daeSFredrik Holmqvist {
235e2e1558aSJessica Hamilton stage2_args args;
236b3215a62SHenry Harrington memset(&args, 0, sizeof(stage2_args));
237b3215a62SHenry Harrington
238b3215a62SHenry Harrington kImage = image;
239735f1daeSFredrik Holmqvist kSystemTable = systemTable;
240735f1daeSFredrik Holmqvist kBootServices = systemTable->BootServices;
241735f1daeSFredrik Holmqvist kRuntimeServices = systemTable->RuntimeServices;
242735f1daeSFredrik Holmqvist
243735f1daeSFredrik Holmqvist call_ctors();
244735f1daeSFredrik Holmqvist
245735f1daeSFredrik Holmqvist console_init();
2469e487d8dSFredrik Holmqvist serial_init();
2479e487d8dSFredrik Holmqvist serial_enable();
248735f1daeSFredrik Holmqvist
24996f4d68bSJessica Hamilton sBootOptions = console_check_boot_keys();
25096f4d68bSJessica Hamilton
251b3215a62SHenry Harrington // disable apm in case we ever load a 32-bit kernel...
252b3215a62SHenry Harrington gKernelArgs.platform_args.apm.version = 0;
2536e6efaecSJessica Hamilton
25486b12d85SJessica Hamilton cpu_init();
25586b12d85SJessica Hamilton acpi_init();
256f1fa58bfSX512 #ifdef _BOOT_FDT_SUPPORT
257569564c0SAlexander von Gluck IV dtb_init();
258f1fa58bfSX512 #endif
259b482adb1SAlexander von Gluck IV timer_init();
26086b12d85SJessica Hamilton smp_init();
26186b12d85SJessica Hamilton
262e2e1558aSJessica Hamilton main(&args);
263735f1daeSFredrik Holmqvist
264735f1daeSFredrik Holmqvist return EFI_SUCCESS;
265735f1daeSFredrik Holmqvist }
266