init.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2021, Gunnar Beutner <gbeutner@serenityos.org>
  4. * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
  5. *
  6. * SPDX-License-Identifier: BSD-2-Clause
  7. */
  8. #include <AK/Types.h>
  9. #include <Kernel/Multiboot.h>
  10. #include <Kernel/PhysicalAddress.h>
  11. #include <Kernel/Prekernel/Prekernel.h>
  12. #include <Kernel/VirtualAddress.h>
  13. #include <LibC/elf.h>
  14. #include <LibELF/Relocation.h>
  15. // Defined in the linker script
  16. extern size_t __stack_chk_guard;
  17. size_t __stack_chk_guard;
  18. extern "C" [[noreturn]] void __stack_chk_fail();
  19. extern "C" u8 start_of_prekernel_image[];
  20. extern "C" u8 end_of_prekernel_image[];
  21. extern "C" u8 gdt64ptr[];
  22. extern "C" u16 code64_sel;
  23. extern "C" u64 boot_pml4t[512];
  24. extern "C" u64 boot_pdpt[512];
  25. extern "C" u64 boot_pd0[512];
  26. extern "C" u64 boot_pd0_pts[512 * (MAX_KERNEL_SIZE >> 21 & 0x1ff)];
  27. extern "C" u64 boot_pd_kernel[512];
  28. extern "C" u64 boot_pd_kernel_pt0[512];
  29. extern "C" u64 boot_pd_kernel_image_pts[512 * (MAX_KERNEL_SIZE >> 21 & 0x1ff)];
  30. extern "C" u64 boot_pd_kernel_pt1023[512];
  31. extern "C" char const kernel_cmdline[4096];
  32. extern "C" void reload_cr3();
  33. extern "C" {
  34. multiboot_info_t* multiboot_info_ptr;
  35. }
  36. [[noreturn]] static void halt()
  37. {
  38. asm volatile("hlt");
  39. __builtin_unreachable();
  40. }
  41. void __stack_chk_fail()
  42. {
  43. halt();
  44. }
  45. void __assertion_failed(char const*, char const*, unsigned int, char const*)
  46. {
  47. halt();
  48. }
  49. namespace Kernel {
  50. // boot.S expects these functions to exactly have the following signatures.
  51. // We declare them here to ensure their signatures don't accidentally change.
  52. extern "C" [[noreturn]] void init();
  53. // SerenityOS Pre-Kernel Environment C++ entry point :^)
  54. //
  55. // This is where C++ execution begins, after boot.S transfers control here.
  56. //
  57. extern "C" [[noreturn]] void init()
  58. {
  59. if (multiboot_info_ptr->mods_count < 1)
  60. halt();
  61. multiboot_module_entry_t* kernel_module = (multiboot_module_entry_t*)(FlatPtr)multiboot_info_ptr->mods_addr;
  62. u8* kernel_image = (u8*)(FlatPtr)kernel_module->start;
  63. // copy the ELF header and program headers because we might end up overwriting them
  64. ElfW(Ehdr) kernel_elf_header = *(ElfW(Ehdr)*)kernel_image;
  65. ElfW(Phdr) kernel_program_headers[16];
  66. if (kernel_elf_header.e_phnum > array_size(kernel_program_headers))
  67. halt();
  68. __builtin_memcpy(kernel_program_headers, kernel_image + kernel_elf_header.e_phoff, sizeof(ElfW(Phdr)) * kernel_elf_header.e_phnum);
  69. FlatPtr kernel_physical_base = 0x200000;
  70. #if ARCH(I386)
  71. FlatPtr kernel_load_base = 0xc0200000;
  72. #else
  73. FlatPtr kernel_load_base = 0x2000200000;
  74. #endif
  75. FlatPtr kernel_load_end = 0;
  76. for (size_t i = 0; i < kernel_elf_header.e_phnum; i++) {
  77. auto& kernel_program_header = kernel_program_headers[i];
  78. if (kernel_program_header.p_type != PT_LOAD)
  79. continue;
  80. auto start = kernel_load_base + kernel_program_header.p_vaddr;
  81. auto end = start + kernel_program_header.p_memsz;
  82. if (start < (FlatPtr)end_of_prekernel_image)
  83. halt();
  84. if (kernel_physical_base + kernel_program_header.p_paddr < (FlatPtr)end_of_prekernel_image)
  85. halt();
  86. if (end > kernel_load_end)
  87. kernel_load_end = end;
  88. }
  89. // align to 1GB
  90. FlatPtr kernel_mapping_base = kernel_load_base & ~(FlatPtr)0x3fffffff;
  91. VERIFY(kernel_load_base % 0x1000 == 0);
  92. VERIFY(kernel_load_base >= kernel_mapping_base + 0x200000);
  93. #if ARCH(I386)
  94. int pdpt_flags = 0x1;
  95. #else
  96. int pdpt_flags = 0x3;
  97. #endif
  98. boot_pdpt[(kernel_mapping_base >> 30) & 0x1ffu] = (FlatPtr)boot_pd_kernel | pdpt_flags;
  99. boot_pd_kernel[0] = (FlatPtr)boot_pd_kernel_pt0 | 0x3;
  100. for (FlatPtr vaddr = kernel_load_base; vaddr <= kernel_load_end; vaddr += PAGE_SIZE * 512)
  101. boot_pd_kernel[(vaddr - kernel_mapping_base) >> 21] = (FlatPtr)(&boot_pd_kernel_image_pts[(vaddr - kernel_load_base) >> 12]) | 0x3;
  102. __builtin_memset(boot_pd_kernel_pt0, 0, sizeof(boot_pd_kernel_pt0));
  103. VERIFY((size_t)end_of_prekernel_image < array_size(boot_pd_kernel_pt0) * PAGE_SIZE);
  104. /* pseudo-identity map 0M - end_of_prekernel_image */
  105. for (size_t i = 0; i < (FlatPtr)end_of_prekernel_image / PAGE_SIZE; i++)
  106. boot_pd_kernel_pt0[i] = i * PAGE_SIZE | 0x3;
  107. __builtin_memset(boot_pd_kernel_image_pts, 0, sizeof(boot_pd_kernel_image_pts));
  108. for (size_t i = 0; i < kernel_elf_header.e_phnum; i++) {
  109. auto& kernel_program_header = kernel_program_headers[i];
  110. if (kernel_program_header.p_type != PT_LOAD)
  111. continue;
  112. for (FlatPtr offset = 0; offset < kernel_program_header.p_memsz; offset += PAGE_SIZE) {
  113. auto pte_index = ((kernel_load_base & 0x1fffff) + kernel_program_header.p_vaddr + offset) >> 12;
  114. boot_pd_kernel_image_pts[pte_index] = (kernel_physical_base + kernel_program_header.p_paddr + offset) | 0x3;
  115. }
  116. }
  117. boot_pd_kernel[511] = (FlatPtr)boot_pd_kernel_pt1023 | 0x3;
  118. reload_cr3();
  119. for (ssize_t i = kernel_elf_header.e_phnum - 1; i >= 0; i--) {
  120. auto& kernel_program_header = kernel_program_headers[i];
  121. if (kernel_program_header.p_type != PT_LOAD)
  122. continue;
  123. __builtin_memmove((u8*)kernel_load_base + kernel_program_header.p_vaddr, kernel_image + kernel_program_header.p_offset, kernel_program_header.p_filesz);
  124. }
  125. for (ssize_t i = kernel_elf_header.e_phnum - 1; i >= 0; i--) {
  126. auto& kernel_program_header = kernel_program_headers[i];
  127. if (kernel_program_header.p_type != PT_LOAD)
  128. continue;
  129. __builtin_memset((u8*)kernel_load_base + kernel_program_header.p_vaddr + kernel_program_header.p_filesz, 0, kernel_program_header.p_memsz - kernel_program_header.p_filesz);
  130. }
  131. multiboot_info_ptr->mods_count--;
  132. multiboot_info_ptr->mods_addr += sizeof(multiboot_module_entry_t);
  133. auto adjust_by_mapping_base = [kernel_mapping_base](auto ptr) {
  134. return (decltype(ptr))((FlatPtr)ptr + kernel_mapping_base);
  135. };
  136. BootInfo info;
  137. info.start_of_prekernel_image = (PhysicalPtr)start_of_prekernel_image;
  138. info.end_of_prekernel_image = (PhysicalPtr)end_of_prekernel_image;
  139. info.physical_to_virtual_offset = kernel_load_base - kernel_physical_base;
  140. info.kernel_mapping_base = kernel_mapping_base;
  141. info.kernel_load_base = kernel_load_base;
  142. #if ARCH(X86_64)
  143. info.gdt64ptr = (PhysicalPtr)gdt64ptr;
  144. info.code64_sel = code64_sel;
  145. info.boot_pml4t = (PhysicalPtr)boot_pml4t;
  146. #endif
  147. info.boot_pdpt = (PhysicalPtr)boot_pdpt;
  148. info.boot_pd0 = (PhysicalPtr)boot_pd0;
  149. info.boot_pd_kernel = (PhysicalPtr)boot_pd_kernel;
  150. info.boot_pd_kernel_pt1023 = (FlatPtr)adjust_by_mapping_base(boot_pd_kernel_pt1023);
  151. info.kernel_cmdline = (FlatPtr)adjust_by_mapping_base(kernel_cmdline);
  152. info.multiboot_flags = multiboot_info_ptr->flags;
  153. info.multiboot_memory_map = adjust_by_mapping_base((FlatPtr)multiboot_info_ptr->mmap_addr);
  154. info.multiboot_memory_map_count = multiboot_info_ptr->mmap_length / sizeof(multiboot_memory_map_t);
  155. info.multiboot_modules = adjust_by_mapping_base((FlatPtr)multiboot_info_ptr->mods_addr);
  156. info.multiboot_modules_count = multiboot_info_ptr->mods_count;
  157. info.multiboot_framebuffer_addr = multiboot_info_ptr->framebuffer_addr;
  158. info.multiboot_framebuffer_pitch = multiboot_info_ptr->framebuffer_pitch;
  159. info.multiboot_framebuffer_width = multiboot_info_ptr->framebuffer_width;
  160. info.multiboot_framebuffer_height = multiboot_info_ptr->framebuffer_height;
  161. info.multiboot_framebuffer_bpp = multiboot_info_ptr->framebuffer_bpp;
  162. info.multiboot_framebuffer_type = multiboot_info_ptr->framebuffer_type;
  163. asm(
  164. #if ARCH(I386)
  165. "add %0, %%esp"
  166. #else
  167. "movabs %0, %%rax\n"
  168. "add %%rax, %%rsp"
  169. #endif
  170. ::"g"(kernel_mapping_base)
  171. : "ax");
  172. // unmap the 0-1MB region
  173. for (size_t i = 0; i < 256; i++)
  174. boot_pd0_pts[i] = 0;
  175. // unmap the end_of_prekernel_image - MAX_KERNEL_SIZE region
  176. for (FlatPtr vaddr = (FlatPtr)end_of_prekernel_image; vaddr < MAX_KERNEL_SIZE; vaddr += PAGE_SIZE)
  177. boot_pd0_pts[vaddr >> 12] = 0;
  178. reload_cr3();
  179. ELF::perform_relative_relocations(kernel_load_base);
  180. void (*entry)(BootInfo const&) = (void (*)(BootInfo const&))(kernel_load_base + kernel_elf_header.e_entry);
  181. entry(*adjust_by_mapping_base(&info));
  182. __builtin_unreachable();
  183. }
  184. // Define some Itanium C++ ABI methods to stop the linker from complaining.
  185. // If we actually call these something has gone horribly wrong
  186. void* __dso_handle __attribute__((visibility("hidden")));
  187. }