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