MOS Source Code
Loading...
Searching...
No Matches
limine.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-3.0-or-later
2
3#define pr_fmt(fmt) "limine: " fmt
4#include "limine.hpp"
5
8#include "mos/misc/setup.hpp"
9#include "mos/mm/mm.hpp"
10#include "mos/syslog/printk.hpp"
11
12#include <algorithm>
13#include <mos/list.hpp>
14#include <mos_stdlib.hpp>
15
16#define limine_request __section(".limine.requests") __used static volatile
17
19MOS_WARNING_DISABLE("-Wextra-semi")
20MOS_WARNING_DISABLE("-Wpedantic")
21__used __section(".limine.markers.requests_start") static volatile LIMINE_REQUESTS_START_MARKER;
22__used __section(".limine.markers.requests_end") static volatile LIMINE_REQUESTS_END_MARKER;
25
27MOS_WARNING_DISABLE("-Wmissing-field-initializers")
28limine_request struct limine_bootloader_info_request bootloader_info = { .id = LIMINE_BOOTLOADER_INFO_REQUEST, .revision = 0 };
29limine_request struct limine_dtb_request dtb = { .id = LIMINE_DTB_REQUEST, .revision = 0 };
30limine_request struct limine_efi_system_table_request efi_system_table = { .id = LIMINE_EFI_SYSTEM_TABLE_REQUEST, .revision = 0 };
31limine_request struct limine_framebuffer_request framebuffer = { .id = LIMINE_FRAMEBUFFER_REQUEST, .revision = 0 };
32limine_request struct limine_hhdm_request hhdm = { .id = LIMINE_HHDM_REQUEST, .revision = 0 };
33limine_request struct limine_kernel_address_request kernel_address = { .id = LIMINE_KERNEL_ADDRESS_REQUEST, .revision = 0 };
34limine_request struct limine_kernel_file_request kernel_file = { .id = LIMINE_KERNEL_FILE_REQUEST, .revision = 0 };
35limine_request struct limine_memmap_request memmap = { .id = LIMINE_MEMMAP_REQUEST, .revision = 0 };
36limine_request struct limine_module_request module = { .id = LIMINE_MODULE_REQUEST, .revision = 0 };
37limine_request struct limine_paging_mode_request paging_mode = { .id = LIMINE_PAGING_MODE_REQUEST, .revision = 0, .mode = LIMINE_PAGING_MODE_DEFAULT };
38limine_request struct limine_rsdp_request rsdp = { .id = LIMINE_RSDP_REQUEST, .revision = 0 };
39limine_request struct limine_smp_request smp = { .id = LIMINE_SMP_REQUEST, .revision = 0, .flags = 0 };
40limine_request struct limine_stack_size_request stack_size = { .id = LIMINE_STACK_SIZE_REQUEST, .revision = 0, .stack_size = 16 MB };
42
43static void add_to_memmap(pfn_t start, size_t npages, bool reserved, u32 type, const char *typestr)
44{
45 if (start + npages < 1 MB / MOS_PAGE_SIZE)
46 type = LIMINE_MEMMAP_RESERVED, reserved = true;
47
48 if (npages == 0)
49 return;
50
51 pmm_region_t *entry = &platform_info->pmm_regions[platform_info->num_pmm_regions++];
52 entry->reserved = reserved;
53 entry->nframes = npages;
54 entry->pfn_start = start;
55 entry->type = type;
56 pr_dinfo2(limine, "%25s: " PFNADDR_RANGE " (%zu pages)", typestr, PFNADDR(entry->pfn_start, entry->pfn_start + entry->nframes), entry->nframes);
57
60 platform_info->max_pfn = std::max(platform_info->max_pfn, entry->pfn_start + entry->nframes);
61}
62
63static void ap_entry(struct limine_smp_info *info)
64{
65 u64 processor_id = info->processor_id;
66 pr_dinfo(limine, "AP started: #%llu", processor_id);
67 platform_ap_entry(info->extra_argument);
68}
69
70static void invoke_constructors(void)
71{
72 typedef void (*init_function_t)(void);
73 extern const init_function_t __init_array_start[], __init_array_end;
74
75 for (const init_function_t *func = __init_array_start; func != &__init_array_end; func++)
76 {
77 (*func)();
78 }
79}
80
81extern "C" void limine_entry(void)
82{
84 const auto hhdm_response = hhdm.response;
85 if (hhdm_response && hhdm_response->offset)
86 platform_info->direct_map_base = hhdm_response->offset; // early-populate direct_map_base for pa_va
87
88 if (platform_info->boot_console)
89 console_register(platform_info->boot_console);
90
91#if MOS_DEBUG_FEATURE(limine)
92 pr_cont("bootloader: %s, version %s", bootloader_info.response ? bootloader_info.response->name : "unknown",
93 bootloader_info.response ? bootloader_info.response->version : "unknown");
94 pr_info2("stack size: %zu KB", stack_size.stack_size / (1 KB));
95#endif
96
98 mos_panic("Unsupported Limine base revision");
99
100 if (paging_mode.response == NULL)
101 mos_panic("No paging mode found");
102
103 const auto paging_mode_response = paging_mode.response;
104 if (paging_mode_response->mode != LIMINE_PAGING_MODE_DEFAULT)
105 mos_panic("non-default paging mode not supported");
106
107 if (smp.response == NULL)
108 mos_panic("No SMP info found");
109
110 const auto smp_response = smp.response;
111 for (size_t i = 0; i < smp_response->cpu_count; i++)
112 {
113 struct limine_smp_info *info = smp_response->cpus[i];
114 if (info->processor_id == 0)
115 continue; // skip BSP
116
117 __atomic_store_n(&info->goto_address, &ap_entry, __ATOMIC_SEQ_CST);
118 }
119
120 const auto kernel_file_response = kernel_file.response;
121 if (kernel_file_response == NULL)
122 mos_panic("No kernel file found");
123
124 mos_cmdline_init(kernel_file_response->kernel_file->cmdline);
126
127 if (hhdm_response == NULL)
128 mos_panic("No HHDM found");
129
130 platform_info->direct_map_base = hhdm_response->offset;
131 pr_dinfo2(limine, "Direct map base: " PTR_FMT, platform_info->direct_map_base);
132
133 if (memmap.response == NULL)
134 mos_panic("No memory map found"); // are we able to panic at this early stage?
135
136 pfn_t last_end_pfn = 0;
137
138 const auto memmap_response = memmap.response;
139 for (size_t i = 0; i < memmap_response->entry_count; i++)
140 {
141 const struct limine_memmap_entry *entry = memmap_response->entries[i];
142
143 const pfn_t start_pfn = entry->base / MOS_PAGE_SIZE;
144 const size_t npages = entry->length / MOS_PAGE_SIZE;
145
146 // there's a gap between the last region and this one
147 // we fake a reserved region to fill the gap
148 if (last_end_pfn != start_pfn)
149 add_to_memmap(last_end_pfn, start_pfn - last_end_pfn, true, LIMINE_MEMMAP_RESERVED, "<hole>");
150 last_end_pfn = start_pfn + npages;
151
152 const char *typestr = NULL;
153 switch (entry->type)
154 {
155 case LIMINE_MEMMAP_USABLE: typestr = "usable"; break;
156 case LIMINE_MEMMAP_RESERVED: typestr = "reserved"; break;
157 case LIMINE_MEMMAP_ACPI_RECLAIMABLE: typestr = "ACPI reclaimable"; break;
158 case LIMINE_MEMMAP_ACPI_NVS: typestr = "ACPI NVS"; break;
159 case LIMINE_MEMMAP_BAD_MEMORY: typestr = "bad memory"; break;
160 case LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE: typestr = "bootloader reclaimable"; break;
161 case LIMINE_MEMMAP_KERNEL_AND_MODULES: typestr = "kernel and modules"; break;
162 case LIMINE_MEMMAP_FRAMEBUFFER: typestr = "framebuffer"; break;
163 }
164
165 add_to_memmap(start_pfn, npages, entry->type != LIMINE_MEMMAP_USABLE, entry->type, typestr);
166 }
167
168 const auto module_response = module.response;
169 if (module_response == NULL)
170 mos_panic("No modules found");
171
172 if (module_response->module_count != 1)
173 mos_panic("Expected exactly one module, got %zu", module_response->module_count);
174
175 const auto module = module_response->modules[0];
176 pr_dinfo2(limine, "initrd: %s, " PTR_RANGE, module->path, (ptr_t) module->address, (ptr_t) module->address + module->size);
177 platform_info->initrd_pfn = va_pfn(module->address);
178 platform_info->initrd_npages = ALIGN_UP_TO_PAGE(module->size) / MOS_PAGE_SIZE;
179 pr_dinfo2(limine, "initrd at " PFN_FMT ", size %zu pages", platform_info->initrd_pfn, platform_info->initrd_npages);
180
181 const auto kernel_address_response = kernel_address.response;
182 if (kernel_address.response == NULL)
183 mos_panic("No kernel address found");
184
185 platform_info->k_basepfn = kernel_address_response->physical_base / MOS_PAGE_SIZE;
186 platform_info->k_basevaddr = kernel_address_response->virtual_base;
187
188 if (rsdp.response)
189 {
190 platform_info->arch_info.rsdp_addr = (ptr_t) rsdp.response->address;
191 platform_info->arch_info.rsdp_revision = rsdp.response->revision;
192 pr_dinfo2(limine, "RSDP at " PTR_FMT ", revision %u", platform_info->arch_info.rsdp_addr, platform_info->arch_info.rsdp_revision);
193 }
194 else
195 {
196 pr_dinfo2(limine, "No RSDP found from limine");
197 }
198
199 if (dtb.response)
200 {
201#if MOS_PLATFORM_HAS_FDT
202 platform_info->arch_info.fdt = dtb.response->dtb_ptr;
203 pr_dinfo2(limine, "DTB at " PTR_FMT, (ptr_t) platform_info->arch_info.fdt);
204#endif
205 }
206 else
207 {
208 pr_dinfo2(limine, "No DTB found from limine");
209 }
210
212}
void platform_ap_entry(u64 arg)
Definition ap_entry.cpp:23
#define MOS_PAGE_SIZE
Definition autoconf.h:6
void console_register(Console *con)
Definition console.cpp:92
MOSAPI void(1, 2) fatal_abort(const char *fmt
#define va_pfn(va)
Definition mm.hpp:78
#define limine_request
Definition limine.cpp:16
static void invoke_constructors(void)
Definition limine.cpp:70
static MOS_WARNING_POP void add_to_memmap(pfn_t start, size_t npages, bool reserved, u32 type, const char *typestr)
Definition limine.cpp:43
void limine_entry(void)
Definition limine.cpp:81
static void ap_entry(struct limine_smp_info *info)
Definition limine.cpp:63
#define LIMINE_MEMMAP_RESERVED
Definition limine.hpp:386
#define LIMINE_KERNEL_ADDRESS_REQUEST
Definition limine.hpp:554
#define LIMINE_STACK_SIZE_REQUEST
Definition limine.hpp:108
#define LIMINE_BASE_REVISION_SUPPORTED
Definition limine.hpp:58
#define LIMINE_EFI_SYSTEM_TABLE_REQUEST
Definition limine.hpp:506
#define LIMINE_MEMMAP_ACPI_NVS
Definition limine.hpp:388
#define LIMINE_BOOTLOADER_INFO_REQUEST
Definition limine.hpp:92
#define LIMINE_MEMMAP_KERNEL_AND_MODULES
Definition limine.hpp:391
#define LIMINE_REQUESTS_START_MARKER
Definition limine.hpp:47
#define LIMINE_HHDM_REQUEST
Definition limine.hpp:123
#define LIMINE_DTB_REQUEST
Definition limine.hpp:570
#define LIMINE_MODULE_REQUEST
Definition limine.hpp:446
#define LIMINE_REQUESTS_END_MARKER
Definition limine.hpp:50
#define LIMINE_RSDP_REQUEST
Definition limine.hpp:475
#define LIMINE_MEMMAP_FRAMEBUFFER
Definition limine.hpp:392
#define LIMINE_BASE_REVISION(N)
Definition limine.hpp:55
#define LIMINE_SMP_REQUEST
Definition limine.hpp:307
#define LIMINE_MEMMAP_ACPI_RECLAIMABLE
Definition limine.hpp:387
#define LIMINE_KERNEL_FILE_REQUEST
Definition limine.hpp:431
#define LIMINE_MEMMAP_REQUEST
Definition limine.hpp:383
#define LIMINE_MEMMAP_USABLE
Definition limine.hpp:385
#define LIMINE_FRAMEBUFFER_REQUEST
Definition limine.hpp:138
#define LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE
Definition limine.hpp:390
#define LIMINE_MEMMAP_BAD_MEMORY
Definition limine.hpp:389
#define LIMINE_PAGING_MODE_REQUEST
Definition limine.hpp:251
void mos_cmdline_init(const char *bootloader_cmdline)
Definition cmdline.cpp:33
#define MOS_WARNING_PUSH
Definition mos_global.h:70
#define KB
Definition mos_global.h:98
#define ALIGN_UP_TO_PAGE(addr)
Definition mos_global.h:76
#define MOS_WARNING_DISABLE(text)
Definition mos_global.h:72
#define MOS_WARNING_POP
Definition mos_global.h:71
#define __used
Definition mos_global.h:34
#define __section(S)
Definition mos_global.h:32
#define MB
Definition mos_global.h:99
#define mos_panic(fmt,...)
Definition panic.hpp:51
#define NULL
Definition pb_syshdr.h:46
void mos_start_kernel(void)
Definition kmain.cpp:92
#define pr_info2(fmt,...)
Definition printk.hpp:36
#define pr_cont(fmt,...)
Definition printk.hpp:41
#define pr_dinfo(feat, fmt,...)
Definition printk.hpp:28
#define pr_dinfo2(feat, fmt,...)
Definition printk.hpp:27
mos_platform_info_t *const platform_info
void startup_invoke_early_cmdline_hooks(void)
Definition setup.cpp:56
struct limine_dtb_response * response
Definition limine.hpp:580
struct limine_hhdm_response * response
Definition limine.hpp:133
struct limine_kernel_address_response * response
Definition limine.hpp:565
struct limine_kernel_file_response * response
Definition limine.hpp:441
Definition limine.hpp:394
uint64_t type
Definition limine.hpp:397
uint64_t length
Definition limine.hpp:396
uint64_t base
Definition limine.hpp:395
struct limine_memmap_response * response
Definition limine.hpp:409
struct limine_paging_mode_response * response
Definition limine.hpp:282
struct limine_rsdp_response * response
Definition limine.hpp:485
struct limine_smp_response * response
Definition limine.hpp:377
bool reserved
Definition pmm.hpp:61
pfn_t pfn_start
Definition pmm.hpp:59
u32 type
Definition pmm.hpp:62
size_t nframes
Definition pmm.hpp:60
#define PFNADDR(pfn, end)
Definition types.h:42
unsigned int u32
Definition types.h:17
unsigned long long pfn_t
Definition types.h:37
#define PTR_RANGE
Definition types.h:32
#define PFN_FMT
Definition types.h:38
#define PTR_FMT
Definition types.h:29
unsigned long ptr_t
Definition types.h:21
#define PFNADDR_RANGE
Definition types.h:40
unsigned long long u64
Definition types.h:19