:: limine / common / protos / limine.c 69.5 KB raw

1
#include <stdint.h>
2
#include <stddef.h>
3
#include <stdbool.h>
4
#include <stdnoreturn.h>
5
#include <config.h>
6
#include <lib/elf.h>
7
#include <lib/misc.h>
8
#include <lib/acpi.h>
9
#include <lib/config.h>
10
#include <lib/time.h>
11
#include <lib/pe.h>
12
#include <lib/print.h>
13
#include <lib/real.h>
14
#include <lib/libc.h>
15
#include <lib/gterm.h>
16
#include <lib/fdt.h>
17
#include <libfdt.h>
18
#include <lib/uri.h>
19
#include <lib/tpm.h>
20
#include <sys/smp.h>
21
#include <sys/cpu.h>
22
#include <sys/gdt.h>
23
#include <lib/fb.h>
24
#include <lib/term.h>
25
#include <flanterm_backends/fb.h>
26
#include <sys/pic.h>
27
#include <sys/lapic.h>
28
#include <sys/iommu.h>
29
#include <sys/idt.h>
30
#include <fs/file.h>
31
#include <mm/pmm.h>
32
#include <pxe/tftp.h>
33
#include <drivers/edid.h>
34
#include <drivers/vga_textmode.h>
35
#include <lib/rand.h>
36
#define LIMINE_NO_POINTERS
37
#include <protos/limine.h>
38
#include <limine.h>
39
40
enum executable_format {
41
    EXECUTABLE_FORMAT_ELF,
42
    EXECUTABLE_FORMAT_PE,
43
};
44
45
static enum executable_format detect_kernel_format(uint8_t *kernel, size_t kernel_size) {
46
    if (elf_bits(kernel, kernel_size) != -1) {
47
        return EXECUTABLE_FORMAT_ELF;
48
    } else if (pe_bits(kernel, kernel_size) != -1) {
49
        return EXECUTABLE_FORMAT_PE;
50
    } else {
51
        panic(true, "limine: Unknown kernel executable format");
52
    }
53
}
54
55
#define SUPPORTED_BASE_REVISION 6
56
57
#define MAX_REQUESTS 128
58
59
#define MEMMAP_MAX 1024
60
61
static int paging_mode;
62
63
static uint64_t get_hhdm_span_top(int base_revision) {
64
    uint64_t ret = base_revision >= 3 ? 0 : 0x100000000;
65
    for (size_t i = 0; i < memmap_entries; i++) {
66
        if (((base_revision >= 1 && base_revision < 3) || base_revision >= 4) && (
67
            memmap[i].type == MEMMAP_RESERVED
68
         || memmap[i].type == MEMMAP_BAD_MEMORY)) {
69
            continue;
70
        }
71
72
        if (base_revision == 3 && (
73
            memmap[i].type != MEMMAP_USABLE
74
         && memmap[i].type != MEMMAP_BOOTLOADER_RECLAIMABLE
75
         && memmap[i].type != MEMMAP_KERNEL_AND_MODULES
76
         && memmap[i].type != MEMMAP_FRAMEBUFFER
77
         && memmap[i].type != MEMMAP_EFI_RECLAIMABLE)) {
78
            continue;
79
        }
80
81
        uint64_t base = memmap[i].base;
82
        uint64_t length = memmap[i].length;
83
        uint64_t top = CHECKED_ADD(base, length, continue);
84
85
        if (base_revision < 3 && base < 0x100000000) {
86
            base = 0x100000000;
87
        }
88
89
        if (base >= top) {
90
            continue;
91
        }
92
93
        uint64_t aligned_top = ALIGN_UP(top, 0x40000000, continue);
94
95
        if (aligned_top > ret) {
96
            ret = aligned_top;
97
        }
98
    }
99
100
    return ret;
101
}
102
103
#if defined (__i386__)
104
static pagemap_t build_identity_map(void) {
105
    pagemap_t pagemap = new_pagemap(paging_mode);
106
107
    map_pages(pagemap, 0, 0, VMM_FLAG_WRITE, 0x100000000);
108
109
    size_t _memmap_entries = memmap_entries;
110
    struct memmap_entry *_memmap =
111
        ext_mem_alloc_counted(_memmap_entries, sizeof(struct memmap_entry));
112
    for (size_t i = 0; i < _memmap_entries; i++) {
113
        _memmap[i] = memmap[i];
114
    }
115
116
    for (size_t i = 0; i < _memmap_entries; i++) {
117
        if (_memmap[i].type != MEMMAP_USABLE
118
         && _memmap[i].type != MEMMAP_BOOTLOADER_RECLAIMABLE
119
         && _memmap[i].type != MEMMAP_KERNEL_AND_MODULES
120
         && _memmap[i].type != MEMMAP_FRAMEBUFFER
121
         && _memmap[i].type != MEMMAP_EFI_RECLAIMABLE) {
122
            continue;
123
        }
124
125
        uint64_t base   = _memmap[i].base;
126
        uint64_t length = _memmap[i].length;
127
        uint64_t top    = CHECKED_ADD(base, length, continue);
128
129
        if (base < 0x100000000) {
130
            base = 0x100000000;
131
        }
132
133
        if (base >= top) {
134
            continue;
135
        }
136
137
        uint64_t aligned_base   = ALIGN_DOWN(base, 0x1000);
138
        uint64_t aligned_top    = ALIGN_UP(top, 0x1000, continue);
139
        uint64_t aligned_length = aligned_top - aligned_base;
140
141
        map_pages(pagemap, aligned_base, aligned_base, VMM_FLAG_WRITE, aligned_length);
142
    }
143
144
    return pagemap;
145
}
146
147
void limine_memcpy_64_asm(int paging_mode, void *pagemap, uint64_t dst, uint64_t src, size_t count);
148
149
static void limine_ensure_identity_map(pagemap_t *out) {
150
    static bool identity_map_ready = false;
151
    static pagemap_t identity_map;
152
153
    if (!identity_map_ready) {
154
        identity_map = build_identity_map();
155
        identity_map_ready = true;
156
    }
157
    *out = identity_map;
158
}
159
160
static void limine_memcpy_to_64(uint64_t dst, void *src, size_t count) {
161
    pagemap_t identity_map;
162
    limine_ensure_identity_map(&identity_map);
163
    limine_memcpy_64_asm(paging_mode, identity_map.top_level, dst, (uint64_t)(uintptr_t)src, count);
164
}
165
166
static void limine_memcpy_from_64(void *dst, uint64_t src, size_t count) {
167
    pagemap_t identity_map;
168
    limine_ensure_identity_map(&identity_map);
169
    limine_memcpy_64_asm(paging_mode, identity_map.top_level, (uint64_t)(uintptr_t)dst, src, count);
170
}
171
#endif
172
173
static pagemap_t build_pagemap(int base_revision,
174
                               bool nx, struct mem_range *ranges, size_t ranges_count,
175
                               uint64_t physical_base, uint64_t virtual_base,
176
                               uint64_t direct_map_offset) {
177
    pagemap_t pagemap = new_pagemap(paging_mode);
178
179
    if (ranges_count == 0) {
180
        panic(true, "limine: ranges_count == 0");
181
    }
182
183
    for (size_t i = 0; i < ranges_count; i++) {
184
        uint64_t virt = ranges[i].base;
185
        uint64_t phys;
186
187
        if (virt & ((uint64_t)1 << 63)) {
188
            phys = physical_base + (virt - virtual_base);
189
        } else {
190
            panic(false, "limine: Virtual address of a PHDR in lower half");
191
        }
192
193
        uint64_t pf =
194
            (ranges[i].permissions & MEM_RANGE_X ? 0 : (nx ? VMM_FLAG_NOEXEC : 0)) |
195
            (ranges[i].permissions & MEM_RANGE_W ? VMM_FLAG_WRITE : 0);
196
197
        map_pages(pagemap, virt, phys, pf, ranges[i].length);
198
    }
199
200
    // Map 0x1000->4GiB range to identity if base revision == 0
201
    if (base_revision == 0) {
202
        map_pages(pagemap, 0x1000, 0x1000, VMM_FLAG_WRITE, 0x100000000 - 0x1000);
203
    }
204
205
    // Map 0->4GiB range to HHDM if base revision < 3
206
    if (base_revision < 3) {
207
        map_pages(pagemap, direct_map_offset, 0, VMM_FLAG_WRITE, 0x100000000);
208
    }
209
210
    size_t _memmap_entries = memmap_entries;
211
    struct memmap_entry *_memmap =
212
        ext_mem_alloc_counted(_memmap_entries, sizeof(struct memmap_entry));
213
    for (size_t i = 0; i < _memmap_entries; i++)
214
        _memmap[i] = memmap[i];
215
216
    // Map all free memory regions to the higher half direct map offset.
217
    // Coalesce contiguous entries into single map_pages calls to maximise
218
    // the use of large pages (2MiB/1GiB).
219
    uint64_t pending_base = 0, pending_top = 0;
220
221
    for (size_t i = 0; i < _memmap_entries; i++) {
222
        uint64_t aligned_base = 0, aligned_top = 0;
223
224
        if (((base_revision >= 1 && base_revision < 3) || base_revision >= 4) && (
225
            _memmap[i].type == MEMMAP_RESERVED
226
         || _memmap[i].type == MEMMAP_BAD_MEMORY)) {
227
            goto flush;
228
        }
229
230
        if (base_revision == 3 && (
231
            _memmap[i].type != MEMMAP_USABLE
232
         && _memmap[i].type != MEMMAP_BOOTLOADER_RECLAIMABLE
233
         && _memmap[i].type != MEMMAP_KERNEL_AND_MODULES
234
         && _memmap[i].type != MEMMAP_FRAMEBUFFER
235
         && _memmap[i].type != MEMMAP_EFI_RECLAIMABLE)) {
236
            goto flush;
237
        }
238
239
        uint64_t base   = _memmap[i].base;
240
        uint64_t length = _memmap[i].length;
241
        uint64_t top    = CHECKED_ADD(base, length, goto flush);
242
243
        if (base_revision < 3 && base < 0x100000000) {
244
            base = 0x100000000;
245
        }
246
247
        if (base >= top) {
248
            goto flush;
249
        }
250
251
        aligned_base = ALIGN_DOWN(base, 0x1000);
252
        aligned_top  = ALIGN_UP(top, 0x1000, continue);
253
254
        if (aligned_base == pending_top && pending_top != 0) {
255
            pending_top = aligned_top;
256
            continue;
257
        }
258
259
flush:
260
        if (pending_top > pending_base) {
261
            uint64_t len = pending_top - pending_base;
262
            if (base_revision == 0) {
263
                map_pages(pagemap, pending_base, pending_base, VMM_FLAG_WRITE, len);
264
            }
265
            map_pages(pagemap, direct_map_offset + pending_base, pending_base, VMM_FLAG_WRITE, len);
266
        }
267
        pending_base = aligned_base;
268
        pending_top = aligned_top;
269
    }
270
271
    if (pending_top > pending_base) {
272
        uint64_t len = pending_top - pending_base;
273
        if (base_revision == 0) {
274
            map_pages(pagemap, pending_base, pending_base, VMM_FLAG_WRITE, len);
275
        }
276
        map_pages(pagemap, direct_map_offset + pending_base, pending_base, VMM_FLAG_WRITE, len);
277
    }
278
279
    // Map the framebuffer with appropriate permissions
280
    for (size_t i = 0; i < _memmap_entries; i++) {
281
        if (_memmap[i].type != MEMMAP_FRAMEBUFFER) {
282
            continue;
283
        }
284
285
        uint64_t base   = _memmap[i].base;
286
        uint64_t length = _memmap[i].length;
287
        uint64_t top    = CHECKED_ADD(base, length, continue);
288
289
        uint64_t aligned_base   = ALIGN_DOWN(base, 0x1000);
290
        uint64_t aligned_top    = ALIGN_UP(top, 0x1000, continue);
291
        uint64_t aligned_length = aligned_top - aligned_base;
292
293
        if (base_revision == 0) {
294
            map_pages(pagemap, aligned_base, aligned_base, VMM_FLAG_WRITE | VMM_FLAG_FB, aligned_length);
295
        }
296
        map_pages(pagemap, direct_map_offset + aligned_base, aligned_base, VMM_FLAG_WRITE | VMM_FLAG_FB, aligned_length);
297
    }
298
299
    // XXX we do this as a quick and dirty way to switch to the higher half
300
#if defined (__x86_64__) || defined (__i386__)
301
    if (base_revision >= 1) {
302
        map_pages(pagemap, 0, 0, VMM_FLAG_WRITE, 0x100000000);
303
    }
304
#endif
305
306
    return pagemap;
307
}
308
309
#if defined (__x86_64__) || defined (__i386__)
310
extern symbol limine_spinup_32;
311
#elif defined (__aarch64__)
312
313
#define LIMINE_SCTLR ((1 << 29) /* Res1 */                \
314
                    | (1 << 28) /* Res1 */                \
315
                    | (1 << 23) /* Res1 */                \
316
                    | (1 << 22) /* Res1 */                \
317
                    | (1 << 20) /* Res1 */                \
318
                    | (1 << 12) /* I-Cache */             \
319
                    | (1 << 11) /* Res1 */                \
320
                    | (1 << 8)  /* Res1 */                \
321
                    | (1 << 7)  /* Res1 */                \
322
                    | (1 << 4)  /* SP0 Alignment check */ \
323
                    | (1 << 3)  /* SP Alignment check */  \
324
                    | (1 << 2)  /* D-Cache */             \
325
                    | (1 << 0)) /* MMU */                 \
326
327
#define LIMINE_MAIR(fb) ( ((uint64_t)0b11111111 << 0) /* Normal WB RW-allocate non-transient */ \
328
                        | ((uint64_t)(fb) << 8) )     /* Framebuffer type */
329
330
#define LIMINE_TCR(tsz, pa) ( ((uint64_t)(pa) << 32)         /* Intermediate address size */  \
331
                            | ((uint64_t)2 << 30)            /* TTBR1 4K granule */           \
332
                            | ((uint64_t)3 << 28)            /* TTBR1 Inner shareable */      \
333
                            | ((uint64_t)1 << 26)            /* TTBR1 Outer WB RW-Allocate */ \
334
                            | ((uint64_t)1 << 24)            /* TTBR1 Inner WB RW-Allocate */ \
335
                            | ((uint64_t)(tsz) << 16)        /* Address bits in TTBR1 */      \
336
                                                             /* TTBR0 4K granule */           \
337
                            | ((uint64_t)3 << 12)            /* TTBR0 Inner shareable */      \
338
                            | ((uint64_t)1 << 10)            /* TTBR0 Outer WB RW-Allocate */ \
339
                            | ((uint64_t)1 << 8)             /* TTBR0 Inner WB RW-Allocate */ \
340
                            | ((uint64_t)(tsz) << 0))        /* Address bits in TTBR0 */
341
342
#elif defined (__riscv)
343
#elif defined (__loongarch64)
344
#else
345
#error Unknown architecture
346
#endif
347
348
static uint64_t physical_base, virtual_base, slide, direct_map_offset;
349
static size_t requests_count;
350
static void **requests;
351
352
static void set_paging_mode(bool randomise_hhdm_base) {
353
    direct_map_offset = paging_mode_higher_half(paging_mode);
354
    if (randomise_hhdm_base) {
355
        // A quarter of the higher half of wiggle room for KASLR, align to 1GiB steps.
356
        uint64_t mask = ((uint64_t)1 << (paging_mode_va_bits(paging_mode) - 3)) - 1;
357
        direct_map_offset += (rand64() & ~((uint64_t)0x40000000 - 1)) & mask;
358
    }
359
}
360
361
static uint64_t reported_addr(void *addr) {
362
    return (uint64_t)(uintptr_t)addr + direct_map_offset;
363
}
364
365
#if defined (__i386__)
366
static uint64_t reported_addr_64(uint64_t addr) {
367
    return addr + direct_map_offset;
368
}
369
#endif
370
371
#define get_phys_addr(addr) ({ \
372
    __auto_type get_phys_addr__addr = (addr); \
373
    uintptr_t get_phys_addr__r; \
374
    if (get_phys_addr__addr & ((uint64_t)1 << 63)) { \
375
        get_phys_addr__r = physical_base + (get_phys_addr__addr - virtual_base); \
376
    } else { \
377
        get_phys_addr__r = get_phys_addr__addr; \
378
    } \
379
    get_phys_addr__r; \
380
})
381
382
static struct limine_file get_file(struct file_handle *file, char *cmdline) {
383
    struct limine_file ret = {0};
384
385
    if (file->pxe) {
386
        ret.media_type = LIMINE_MEDIA_TYPE_TFTP;
387
388
        ret.tftp_ip = file->pxe_ip;
389
        ret.tftp_port = file->pxe_port;
390
    } else {
391
        struct volume *vol = file->vol;
392
393
        if (vol->is_optical) {
394
            ret.media_type = LIMINE_MEDIA_TYPE_OPTICAL;
395
        }
396
397
        ret.partition_index = vol->partition;
398
399
        ret.mbr_disk_id = mbr_get_id(vol->backing_dev ?: vol);
400
401
        if (vol->guid_valid) {
402
            memcpy(&ret.part_uuid, &vol->guid, sizeof(struct limine_uuid));
403
        }
404
405
        if (vol->part_guid_valid) {
406
            memcpy(&ret.gpt_part_uuid, &vol->part_guid, sizeof(struct limine_uuid));
407
        }
408
409
        struct guid gpt_disk_uuid;
410
        if (gpt_get_guid(&gpt_disk_uuid, vol->backing_dev ?: vol) == true) {
411
            memcpy(&ret.gpt_disk_uuid, &gpt_disk_uuid, sizeof(struct limine_uuid));
412
        }
413
    }
414
415
    char *path = ext_mem_alloc(file->path_len);
416
    memcpy(path, file->path, file->path_len);
417
418
    ret.path = reported_addr(path);
419
420
#if defined (__i386__)
421
    if (file->is_high_mem) {
422
        ret.address = reported_addr_64(file->load_addr_64);
423
    } else {
424
        ret.address = reported_addr(file->fd);
425
    }
426
#else
427
    ret.address = reported_addr(file->fd);
428
#endif
429
430
    ret.size = file->size;
431
432
    ret.string = reported_addr(cmdline);
433
434
    return ret;
435
}
436
437
static void *_get_request(uint64_t id[4]) {
438
    for (size_t i = 0; i < requests_count; i++) {
439
        uint64_t *p = requests[i];
440
441
        if (p[2] != id[2]) {
442
            continue;
443
        }
444
        if (p[3] != id[3]) {
445
            continue;
446
        }
447
448
        return p;
449
    }
450
451
    return NULL;
452
}
453
454
#define get_request(REQ) _get_request((uint64_t[4])REQ)
455
456
#define FEAT_START do {
457
#define FEAT_END } while (0);
458
459
noreturn void limine_load(char *config, char *cmdline) {
460
#if defined (UEFI)
461
    if (cmdline != NULL) {
462
        tpm_measure(TPM_PCR_BOOT_AUTH, TPM_EV_IPL,
463
                    cmdline, strlen(cmdline), "cmdline: ", cmdline);
464
    }
465
#endif
466
467
#if defined (__x86_64__) || defined (__i386__)
468
    uint32_t eax, ebx, ecx, edx;
469
#endif
470
471
#if defined (__aarch64__)
472
    // Booting at EL2 without VHE is not supported.
473
    if (current_el() == 2) {
474
        uint64_t mmfr1;
475
        asm volatile ("mrs %0, id_aa64mmfr1_el1" : "=r"(mmfr1));
476
        if (!((mmfr1 >> 8) & 0xF)) {
477
            panic(true, "limine: Booting at EL2 without VHE support is not supported");
478
        }
479
    }
480
#endif
481
482
    char *kernel_path = config_get_value(config, 0, "PATH");
483
    if (kernel_path == NULL) {
484
        kernel_path = config_get_value(config, 0, "KERNEL_PATH");
485
    }
486
    if (kernel_path == NULL) {
487
        panic(true, "limine: Executable path not specified");
488
    }
489
490
    print("limine: Loading executable `%#`...\n", kernel_path);
491
492
    struct file_handle *kernel_file;
493
    if ((kernel_file = uri_open(kernel_path, MEMMAP_BOOTLOADER_RECLAIMABLE, false
494
#if defined (__i386__)
495
        , NULL, NULL
496
#endif
497
    )) == NULL)
498
        panic(true, "limine: Failed to open executable with path `%#`. Is the path correct?", kernel_path);
499
500
    char *k_path_copy = ext_mem_alloc(strlen(kernel_path) + 1);
501
    strcpy(k_path_copy, kernel_path);
502
    char *k_resource = NULL, *k_root = NULL, *k_path = NULL, *k_hash = NULL;
503
    uri_resolve(k_path_copy, &k_resource, &k_root, &k_path, &k_hash);
504
    // Strip the gzip `$` marker so reuse for module paths doesn't double-prefix.
505
    if (k_resource[0] == '$') {
506
        k_resource++;
507
    }
508
    // Copy k_resource and k_root since uri_resolve returns pointers to a static
509
    // buffer that gets overwritten by subsequent uri_open/uri_resolve calls
510
    k_resource = strdup(k_resource);
511
    k_root = strdup(k_root);
512
    char *k_path_ = ext_mem_alloc(strlen(k_path) + 2);
513
    k_path_[0] = '/';
514
    strcpy(k_path_ + 1, k_path);
515
    k_path = k_path_;
516
    for (size_t i = strlen(k_path) - 1; ; i--) {
517
        if (k_path[i] == '/' || i == 1) {
518
            k_path[i] = 0;
519
            break;
520
        }
521
        k_path[i] = 0;
522
    }
523
524
    uint8_t *kernel = kernel_file->fd;
525
526
#if defined (UEFI)
527
    tpm_measure_path(TPM_PCR_BOOT_AUTH, TPM_EV_IPL, "path: ", kernel_path);
528
    tpm_measure(TPM_PCR_LOADED_IMAGES, TPM_EV_IPL,
529
                kernel, kernel_file->size, "path: ", kernel_path);
530
#endif
531
532
    char *kaslr_s = config_get_value(config, 0, "KASLR");
533
    bool kaslr = false;
534
    if (kaslr_s != NULL && strcmp(kaslr_s, "yes") == 0) {
535
        kaslr = true;
536
    }
537
538
    // ELF loading
539
    uint64_t entry_point = 0;
540
    struct mem_range *ranges;
541
    uint64_t ranges_count;
542
543
    uint64_t image_size_before_bss;
544
    bool is_reloc;
545
546
    enum executable_format kernel_format = detect_kernel_format(kernel, kernel_file->size);
547
    switch (kernel_format) {
548
        case EXECUTABLE_FORMAT_ELF:
549
            if (!elf64_load(kernel, kernel_file->size, &entry_point, &slide,
550
                            MEMMAP_KERNEL_AND_MODULES, kaslr,
551
                            &ranges, &ranges_count,
552
                            &physical_base, &virtual_base, NULL,
553
                            &image_size_before_bss,
554
                            &is_reloc)) {
555
                panic(true, "limine: ELF64 load failure");
556
            }
557
            break;
558
        case EXECUTABLE_FORMAT_PE:
559
            if (!pe64_load(kernel, kernel_file->size, &entry_point, &slide,
560
                            MEMMAP_KERNEL_AND_MODULES, kaslr,
561
                            &ranges, &ranges_count,
562
                            &physical_base, &virtual_base, NULL,
563
                            &image_size_before_bss,
564
                            &is_reloc)) {
565
                panic(true, "limine: PE64 load failure");
566
            }
567
            break;
568
    }
569
570
    kaslr = kaslr && is_reloc;
571
572
    uint64_t limine_requests_start_marker[] = LIMINE_REQUESTS_START_MARKER;
573
    uint64_t limine_requests_end_marker[] = LIMINE_REQUESTS_END_MARKER;
574
575
    // Determine base revision
576
    uint64_t limine_base_revision[] = LIMINE_BASE_REVISION(0);
577
    int base_revision = 0;
578
    bool base_revision_found = false;
579
    uint64_t *base_rev_p1_ptr = NULL;
580
    uint64_t *base_rev_p2_ptr = NULL;
581
    for (size_t i = 0; i + 32 <= image_size_before_bss; i += 8) {
582
        uint64_t *p = (void *)(uintptr_t)physical_base + i;
583
584
        // Check if start marker hit
585
        if (p[0] == limine_requests_start_marker[0] && p[1] == limine_requests_start_marker[1]
586
         && p[2] == limine_requests_start_marker[2] && p[3] == limine_requests_start_marker[3]) {
587
            base_revision = 0;
588
            base_revision_found = false;
589
            base_rev_p1_ptr = NULL;
590
            base_rev_p2_ptr = NULL;
591
            continue;
592
        }
593
594
        // Check if end marker hit
595
        if (p[0] == limine_requests_end_marker[0] && p[1] == limine_requests_end_marker[1]) {
596
            break;
597
        }
598
599
        if (p[0] == limine_base_revision[0] && p[1] == limine_base_revision[1]) {
600
            if (base_revision_found) {
601
                panic(true, "limine: Duplicated base revision tag");
602
            }
603
            base_revision_found = true;
604
            base_revision = p[2];
605
            if (p[2] <= SUPPORTED_BASE_REVISION) {
606
                // Set to 0 to mean "supported"
607
                base_rev_p2_ptr = &p[2];
608
            } else {
609
                base_revision = SUPPORTED_BASE_REVISION;
610
            }
611
            base_rev_p1_ptr = &p[1];
612
        }
613
    }
614
    if (base_rev_p1_ptr != NULL) {
615
        *base_rev_p1_ptr = base_revision;
616
    }
617
    if (base_rev_p2_ptr != NULL) {
618
        *base_rev_p2_ptr = 0;
619
    }
620
621
#if defined (__aarch64__)
622
    if (base_revision < 6) {
623
        panic(true, "limine: Base revision %u is no longer supported for aarch64 (minimum: 6)", base_revision);
624
    }
625
#endif
626
627
    // Load requests
628
    uint64_t *limine_reqs = NULL;
629
    requests = ext_mem_alloc_counted(MAX_REQUESTS, sizeof(void *));
630
    requests_count = 0;
631
    if (base_revision == 0 && kernel_format == EXECUTABLE_FORMAT_ELF && elf64_load_section(kernel, kernel_file->size, &limine_reqs, ".limine_reqs", 0, slide)) {
632
        for (size_t i = 0; ; i++) {
633
            if (i >= MAX_REQUESTS) {
634
                panic(true, "limine: Maximum requests exceeded");
635
            }
636
            if (limine_reqs[i] == 0) {
637
                break;
638
            }
639
            if (limine_reqs[i] < virtual_base
640
             || limine_reqs[i] - virtual_base >= image_size_before_bss) {
641
                panic(true, "limine: .limine_reqs entry outside kernel image");
642
            }
643
            requests[i] = (void *)(uintptr_t)((limine_reqs[i] - virtual_base) + physical_base);
644
            requests_count++;
645
        }
646
    } else {
647
        uint64_t common_magic[2] = { LIMINE_COMMON_MAGIC };
648
        for (size_t i = 0; i + 32 <= image_size_before_bss; i += 8) {
649
            uint64_t *p = (void *)(uintptr_t)physical_base + i;
650
651
            // Check if start marker hit
652
            if (p[0] == limine_requests_start_marker[0] && p[1] == limine_requests_start_marker[1]
653
             && p[2] == limine_requests_start_marker[2] && p[3] == limine_requests_start_marker[3]) {
654
                requests_count = 0;
655
                continue;
656
            }
657
658
            // Check if end marker hit
659
            if (p[0] == limine_requests_end_marker[0] && p[1] == limine_requests_end_marker[1]) {
660
                break;
661
            }
662
663
            if (p[0] != common_magic[0]) {
664
                continue;
665
            }
666
            if (p[1] != common_magic[1]) {
667
                continue;
668
            }
669
670
            if (requests_count == MAX_REQUESTS) {
671
                panic(true, "limine: Maximum requests exceeded");
672
            }
673
674
            // Check for a conflict
675
            if (_get_request(p) != NULL) {
676
                panic(true, "limine: Conflict detected for request ID %X %X", p[2], p[3]);
677
            }
678
679
            requests[requests_count++] = p;
680
        }
681
    }
682
683
#if defined (__x86_64__) || defined (__i386__)
684
    // Check if 64 bit CPU
685
    if (!cpuid(0x80000001, 0, &eax, &ebx, &ecx, &edx) || !(edx & (1 << 29))) {
686
        panic(true, "limine: This CPU does not support 64-bit mode.");
687
    }
688
#endif
689
690
    uint64_t hhdm_span_top = get_hhdm_span_top(base_revision);
691
692
#if defined (__x86_64__) || defined (__i386__)
693
    uint64_t maxphyaddr;
694
    if (!cpuid(0x80000008, 0, &eax, &ebx, &ecx, &edx)) {
695
        maxphyaddr = 36;
696
    } else {
697
        maxphyaddr = eax & 0xff;
698
    }
699
700
    if (maxphyaddr > 64) {
701
        panic(true, "limine: MAXPHYADDR > 64");
702
    }
703
    if (maxphyaddr < 64 && hhdm_span_top > (uint64_t)1 << maxphyaddr) {
704
        panic(true, "limine: Top of HHDM exceeds maximum allowable MAXPHYADDR value");
705
    }
706
#endif
707
708
    printv("limine: Physical base:   %X\n", physical_base);
709
    printv("limine: Virtual base:    %X\n", virtual_base);
710
    printv("limine: Slide:           %X\n", slide);
711
    printv("limine: ELF entry point: %X\n", entry_point);
712
    printv("limine: Base revision:   %u\n", base_revision);
713
    printv("limine: Requests count:  %U\n", (uint64_t)requests_count);
714
    printv("limine: Top of HHDM:     %X\n", hhdm_span_top);
715
716
    // Paging Mode
717
    int max_supported_paging_mode, min_supported_paging_mode;
718
719
#if defined (__x86_64__) || defined (__i386__)
720
    max_supported_paging_mode = PAGING_MODE_X86_64_4LVL;
721
    if (cpuid(0x00000007, 0, &eax, &ebx, &ecx, &edx) && (ecx & (1 << 16))) {
722
        printv("limine: CPU has 5-level paging support\n");
723
        max_supported_paging_mode = PAGING_MODE_X86_64_5LVL;
724
    }
725
    min_supported_paging_mode = PAGING_MODE_X86_64_4LVL;
726
    if (hhdm_span_top >= (uint64_t)1 << (paging_mode_va_bits(min_supported_paging_mode) - 2)) {
727
        min_supported_paging_mode = PAGING_MODE_X86_64_5LVL;
728
        if (min_supported_paging_mode > max_supported_paging_mode) {
729
            goto hhdm_fail;
730
        }
731
    }
732
    if (hhdm_span_top >= (uint64_t)1 << (paging_mode_va_bits(min_supported_paging_mode) - 2)) {
733
        goto hhdm_fail;
734
    }
735
#elif defined (__aarch64__)
736
    max_supported_paging_mode = PAGING_MODE_AARCH64_4LVL;
737
    min_supported_paging_mode = PAGING_MODE_AARCH64_4LVL;
738
    if (hhdm_span_top >= (uint64_t)1 << (paging_mode_va_bits(min_supported_paging_mode) - 2)) {
739
        goto hhdm_fail;
740
    }
741
    // TODO(qookie): aarch64 also has optional 5 level paging when using 4K pages
742
#elif defined (__riscv)
743
    max_supported_paging_mode = vmm_max_paging_mode();
744
    min_supported_paging_mode = PAGING_MODE_RISCV_SV39;
745
    if (hhdm_span_top >= (uint64_t)1 << (paging_mode_va_bits(min_supported_paging_mode) - 2)) {
746
        min_supported_paging_mode = PAGING_MODE_RISCV_SV48;
747
        if (min_supported_paging_mode > max_supported_paging_mode) {
748
            goto hhdm_fail;
749
        }
750
    }
751
    if (hhdm_span_top >= (uint64_t)1 << (paging_mode_va_bits(min_supported_paging_mode) - 2)) {
752
        min_supported_paging_mode = PAGING_MODE_RISCV_SV57;
753
        if (min_supported_paging_mode > max_supported_paging_mode) {
754
            goto hhdm_fail;
755
        }
756
    }
757
    if (hhdm_span_top >= (uint64_t)1 << (paging_mode_va_bits(min_supported_paging_mode) - 2)) {
758
        goto hhdm_fail;
759
    }
760
#elif defined (__loongarch64)
761
    max_supported_paging_mode = PAGING_MODE_LOONGARCH64_4LVL;
762
    min_supported_paging_mode = PAGING_MODE_LOONGARCH64_4LVL;
763
    if (hhdm_span_top >= (uint64_t)1 << (paging_mode_va_bits(min_supported_paging_mode) - 2)) {
764
        goto hhdm_fail;
765
    }
766
#else
767
#error Unknown architecture
768
#endif
769
770
    if (0) {
771
hhdm_fail:
772
        panic(true, "limine: Unable to allocate higher half direct map (too much memory?)");
773
    }
774
775
    char *user_paging_mode_s = config_get_value(config, 0, "PAGING_MODE");
776
777
    int user_max_paging_mode = PAGING_MODE_MAX;
778
779
    char *user_max_paging_mode_s;
780
    if (user_paging_mode_s != NULL) {
781
        user_max_paging_mode_s = user_paging_mode_s;
782
    } else {
783
        user_max_paging_mode_s = config_get_value(config, 0, "MAX_PAGING_MODE");
784
    }
785
    if (user_max_paging_mode_s != NULL) {
786
#if defined (__x86_64__) || defined (__i386__)
787
        if (strcasecmp(user_max_paging_mode_s, "4level") == 0) {
788
            user_max_paging_mode = PAGING_MODE_X86_64_4LVL;
789
        } else if (strcasecmp(user_max_paging_mode_s, "5level") == 0) {
790
            user_max_paging_mode = PAGING_MODE_X86_64_5LVL;
791
        }
792
#elif defined (__aarch64__)
793
        if (strcasecmp(user_max_paging_mode_s, "4level") == 0) {
794
            user_max_paging_mode = PAGING_MODE_AARCH64_4LVL;
795
        } else if (strcasecmp(user_max_paging_mode_s, "5level") == 0) {
796
            user_max_paging_mode = PAGING_MODE_AARCH64_5LVL;
797
        }
798
#elif defined (__riscv)
799
        if (strcasecmp(user_max_paging_mode_s, "sv39") == 0) {
800
            user_max_paging_mode = PAGING_MODE_RISCV_SV39;
801
        } else if (strcasecmp(user_max_paging_mode_s, "sv48") == 0) {
802
            user_max_paging_mode = PAGING_MODE_RISCV_SV48;
803
        } else if (strcasecmp(user_max_paging_mode_s, "sv57") == 0) {
804
            user_max_paging_mode = PAGING_MODE_RISCV_SV57;
805
        }
806
#elif defined (__loongarch64)
807
        if (strcasecmp(user_max_paging_mode_s, "4level") == 0) {
808
            user_max_paging_mode = PAGING_MODE_LOONGARCH64_4LVL;
809
        }
810
#endif
811
        else {
812
            panic(true, "limine: Invalid MAX_PAGING_MODE: `%s`", user_max_paging_mode_s);
813
        }
814
    }
815
816
    int user_min_paging_mode = PAGING_MODE_MIN;
817
818
    char *user_min_paging_mode_s;
819
    if (user_paging_mode_s != NULL) {
820
        user_min_paging_mode_s = user_paging_mode_s;
821
    } else {
822
        user_min_paging_mode_s = config_get_value(config, 0, "MIN_PAGING_MODE");
823
    }
824
    if (user_min_paging_mode_s != NULL) {
825
#if defined (__x86_64__) || defined (__i386__)
826
        if (strcasecmp(user_min_paging_mode_s, "4level") == 0) {
827
            user_min_paging_mode = PAGING_MODE_X86_64_4LVL;
828
        } else if (strcasecmp(user_min_paging_mode_s, "5level") == 0) {
829
            user_min_paging_mode = PAGING_MODE_X86_64_5LVL;
830
        }
831
#elif defined (__aarch64__)
832
        if (strcasecmp(user_min_paging_mode_s, "4level") == 0) {
833
            user_min_paging_mode = PAGING_MODE_AARCH64_4LVL;
834
        } else if (strcasecmp(user_min_paging_mode_s, "5level") == 0) {
835
            user_min_paging_mode = PAGING_MODE_AARCH64_5LVL;
836
        }
837
#elif defined (__riscv)
838
        if (strcasecmp(user_min_paging_mode_s, "sv39") == 0) {
839
            user_min_paging_mode = PAGING_MODE_RISCV_SV39;
840
        } else if (strcasecmp(user_min_paging_mode_s, "sv48") == 0) {
841
            user_min_paging_mode = PAGING_MODE_RISCV_SV48;
842
        } else if (strcasecmp(user_min_paging_mode_s, "sv57") == 0) {
843
            user_min_paging_mode = PAGING_MODE_RISCV_SV57;
844
        }
845
#elif defined (__loongarch64)
846
        if (strcasecmp(user_min_paging_mode_s, "4level") == 0) {
847
            user_min_paging_mode = PAGING_MODE_LOONGARCH64_4LVL;
848
        }
849
#endif
850
        else {
851
            panic(true, "limine: Invalid MIN_PAGING_MODE: `%s`", user_min_paging_mode_s);
852
        }
853
    }
854
855
    if (user_max_paging_mode < user_min_paging_mode) {
856
        panic(true, "limine: MAX_PAGING_MODE is lower than MIN_PAGING_MODE");
857
    }
858
859
    if (user_max_paging_mode < max_supported_paging_mode) {
860
        if (user_max_paging_mode < min_supported_paging_mode) {
861
            panic(true, "limine: User set MAX_PAGING_MODE less than minimum supported paging mode");
862
        }
863
        max_supported_paging_mode = user_max_paging_mode;
864
    }
865
    if (user_min_paging_mode > min_supported_paging_mode) {
866
        if (user_min_paging_mode > max_supported_paging_mode) {
867
            panic(true, "limine: User set MIN_PAGING_MODE greater than maximum supported paging mode");
868
        }
869
        min_supported_paging_mode = user_min_paging_mode;
870
    }
871
872
#if defined (__x86_64__) || defined (__i386__)
873
    paging_mode = PAGING_MODE_X86_64_4LVL;
874
#elif defined (__riscv)
875
    paging_mode = max_supported_paging_mode >= PAGING_MODE_RISCV_SV48 ? PAGING_MODE_RISCV_SV48 : PAGING_MODE_RISCV_SV39;
876
#elif defined (__aarch64__)
877
    paging_mode = PAGING_MODE_AARCH64_4LVL;
878
#elif defined (__loongarch64)
879
    paging_mode = PAGING_MODE_LOONGARCH64_4LVL;
880
#endif
881
882
#if defined (__riscv)
883
#define paging_mode_limine_to_vmm(x) (PAGING_MODE_RISCV_SV39 + (x))
884
#define paging_mode_vmm_to_limine(x) ((x) - PAGING_MODE_RISCV_SV39)
885
#else
886
#define paging_mode_limine_to_vmm(x) (x)
887
#define paging_mode_vmm_to_limine(x) (x)
888
#endif
889
890
    bool paging_mode_set = false;
891
    bool randomise_hhdm_base = false;
892
FEAT_START
893
    struct limine_paging_mode_request *pm_request = get_request(LIMINE_PAGING_MODE_REQUEST_ID);
894
    if (pm_request == NULL)
895
        break;
896
897
    uint64_t target_mode = pm_request->mode;
898
    paging_mode = paging_mode_limine_to_vmm(target_mode);
899
900
    int kern_min_mode = PAGING_MODE_MIN, kern_max_mode = paging_mode;
901
    if (pm_request->revision >= 1) {
902
        kern_min_mode = (int)paging_mode_limine_to_vmm(pm_request->min_mode);
903
        kern_max_mode = (int)paging_mode_limine_to_vmm(pm_request->max_mode);
904
    }
905
906
    if (paging_mode > max_supported_paging_mode) {
907
        paging_mode = max_supported_paging_mode;
908
    }
909
    if (paging_mode < min_supported_paging_mode) {
910
        paging_mode = min_supported_paging_mode;
911
    }
912
913
    if (kern_max_mode < kern_min_mode) {
914
        panic(true, "limine: Executable's paging max_mode lower than min_mode");
915
    }
916
917
    if (paging_mode > kern_max_mode) {
918
        if (kern_max_mode < min_supported_paging_mode) {
919
            panic(true, "limine: Executable's maximum supported paging mode lower than minimum allowable paging mode");
920
        }
921
        paging_mode = kern_max_mode;
922
    }
923
    if (paging_mode < kern_min_mode) {
924
        if (kern_min_mode > max_supported_paging_mode) {
925
            panic(true, "limine: Executable's minimum supported paging mode higher than maximum allowable paging mode");
926
        }
927
        paging_mode = kern_min_mode;
928
    }
929
930
    char *randomise_hhdm_base_s = config_get_value(config, 0, "RANDOMISE_HHDM_BASE");
931
    if (randomise_hhdm_base_s == NULL) {
932
        randomise_hhdm_base_s = config_get_value(config, 0, "RANDOMIZE_HHDM_BASE");
933
    }
934
    if (randomise_hhdm_base_s == NULL) {
935
        randomise_hhdm_base = kaslr;
936
    } else {
937
        randomise_hhdm_base = strcasecmp(randomise_hhdm_base_s, "yes") == 0;
938
    }
939
940
    set_paging_mode(randomise_hhdm_base);
941
    paging_mode_set = true;
942
943
    struct limine_paging_mode_response *pm_response =
944
        ext_mem_alloc(sizeof(struct limine_paging_mode_response));
945
946
    pm_response->mode = paging_mode_vmm_to_limine(paging_mode);
947
    pm_request->response = reported_addr(pm_response);
948
FEAT_END
949
950
    if (!paging_mode_set) {
951
        set_paging_mode(randomise_hhdm_base);
952
    }
953
954
#if defined (__aarch64__)
955
    uint64_t aa64mmfr0;
956
    asm volatile ("mrs %0, id_aa64mmfr0_el1" : "=r" (aa64mmfr0));
957
958
    uint64_t pa = aa64mmfr0 & 0xF;
959
960
    uint64_t tsz = 64 - (paging_mode_va_bits(paging_mode) - 1);
961
#endif
962
963
    struct limine_file *kf = ext_mem_alloc(sizeof(struct limine_file));
964
    *kf = get_file(kernel_file, cmdline);
965
    fclose(kernel_file);
966
967
    // Entry point feature
968
FEAT_START
969
    struct limine_entry_point_request *entrypoint_request = get_request(LIMINE_ENTRY_POINT_REQUEST_ID);
970
    if (entrypoint_request == NULL) {
971
        break;
972
    }
973
974
    entry_point = entrypoint_request->entry;
975
976
    printv("limine: Entry point at %X\n", entry_point);
977
978
    struct limine_entry_point_response *entrypoint_response =
979
        ext_mem_alloc(sizeof(struct limine_entry_point_response));
980
981
    entrypoint_request->response = reported_addr(entrypoint_response);
982
FEAT_END
983
984
    // x86-64 Keep IOMMU feature
985
#if defined (__x86_64__) || defined (__i386__)
986
    bool keep_iommu = false;
987
FEAT_START
988
    struct limine_x86_64_keep_iommu_request *keep_iommu_request =
989
        get_request(LIMINE_X86_64_KEEP_IOMMU_REQUEST_ID);
990
    if (keep_iommu_request == NULL) {
991
        break;
992
    }
993
994
    struct limine_x86_64_keep_iommu_response *keep_iommu_response =
995
        ext_mem_alloc(sizeof(struct limine_x86_64_keep_iommu_response));
996
997
    keep_iommu_request->response = reported_addr(keep_iommu_response);
998
    keep_iommu = true;
999
FEAT_END
1000
#endif
1001
1002
    // Bootloader info feature
1003
FEAT_START
1004
    struct limine_bootloader_info_request *bootloader_info_request = get_request(LIMINE_BOOTLOADER_INFO_REQUEST_ID);
1005
    if (bootloader_info_request == NULL) {
1006
        break; // next feature
1007
    }
1008
1009
    struct limine_bootloader_info_response *bootloader_info_response =
1010
        ext_mem_alloc(sizeof(struct limine_bootloader_info_response));
1011
1012
    bootloader_info_response->name = reported_addr("Limine");
1013
    bootloader_info_response->version = reported_addr(LIMINE_VERSION);
1014
1015
    bootloader_info_request->response = reported_addr(bootloader_info_response);
1016
FEAT_END
1017
1018
    // Executable Command Line feature
1019
FEAT_START
1020
    struct limine_executable_cmdline_request *executable_cmdline_request = get_request(LIMINE_EXECUTABLE_CMDLINE_REQUEST_ID);
1021
    if (executable_cmdline_request == NULL) {
1022
        break; // next feature
1023
    }
1024
1025
    struct limine_executable_cmdline_response *executable_cmdline_response =
1026
        ext_mem_alloc(sizeof(struct limine_executable_cmdline_response));
1027
1028
    executable_cmdline_response->cmdline = reported_addr(cmdline);
1029
1030
    executable_cmdline_request->response = reported_addr(executable_cmdline_response);
1031
FEAT_END
1032
1033
    // Firmware type feature
1034
FEAT_START
1035
    struct limine_firmware_type_request *firmware_type_request = get_request(LIMINE_FIRMWARE_TYPE_REQUEST_ID);
1036
    if (firmware_type_request == NULL) {
1037
        break; // next feature
1038
    }
1039
1040
    struct limine_firmware_type_response *firmware_type_response =
1041
        ext_mem_alloc(sizeof(struct limine_firmware_type_response));
1042
1043
    firmware_type_response->firmware_type =
1044
#if defined (UEFI)
1045
#if defined (__i386__)
1046
        LIMINE_FIRMWARE_TYPE_EFI32
1047
#else
1048
        LIMINE_FIRMWARE_TYPE_EFI64
1049
#endif
1050
#else
1051
        LIMINE_FIRMWARE_TYPE_X86BIOS
1052
#endif
1053
    ;
1054
1055
    firmware_type_request->response = reported_addr(firmware_type_response);
1056
FEAT_END
1057
1058
    // Executable address feature
1059
FEAT_START
1060
    struct limine_executable_address_request *executable_address_request = get_request(LIMINE_EXECUTABLE_ADDRESS_REQUEST_ID);
1061
    if (executable_address_request == NULL) {
1062
        break; // next feature
1063
    }
1064
1065
    struct limine_executable_address_response *executable_address_response =
1066
        ext_mem_alloc(sizeof(struct limine_executable_address_response));
1067
1068
    executable_address_response->physical_base = physical_base;
1069
    executable_address_response->virtual_base = virtual_base;
1070
1071
    executable_address_request->response = reported_addr(executable_address_response);
1072
FEAT_END
1073
1074
    // HHDM feature
1075
FEAT_START
1076
    struct limine_hhdm_request *hhdm_request = get_request(LIMINE_HHDM_REQUEST_ID);
1077
    if (hhdm_request == NULL) {
1078
        break; // next feature
1079
    }
1080
1081
    struct limine_hhdm_response *hhdm_response =
1082
        ext_mem_alloc(sizeof(struct limine_hhdm_response));
1083
1084
    hhdm_response->offset = direct_map_offset;
1085
1086
    hhdm_request->response = reported_addr(hhdm_response);
1087
FEAT_END
1088
1089
    // RSDP feature
1090
FEAT_START
1091
    struct limine_rsdp_request *rsdp_request = get_request(LIMINE_RSDP_REQUEST_ID);
1092
    if (rsdp_request == NULL) {
1093
        break; // next feature
1094
    }
1095
1096
    void *rsdp = acpi_get_rsdp();
1097
    if (rsdp == NULL) {
1098
        break;
1099
    }
1100
1101
    struct limine_rsdp_response *rsdp_response =
1102
        ext_mem_alloc(sizeof(struct limine_rsdp_response));
1103
1104
    rsdp_response->address = (base_revision <= 2 || base_revision >= 4) ? reported_addr(rsdp) : (uintptr_t)rsdp;
1105
1106
    rsdp_request->response = reported_addr(rsdp_response);
1107
FEAT_END
1108
1109
    // SMBIOS feature
1110
FEAT_START
1111
    struct limine_smbios_request *smbios_request = get_request(LIMINE_SMBIOS_REQUEST_ID);
1112
    if (smbios_request == NULL) {
1113
        break; // next feature
1114
    }
1115
1116
    void *smbios_entry_32 = NULL, *smbios_entry_64 = NULL;
1117
    acpi_get_smbios(&smbios_entry_32, &smbios_entry_64);
1118
    if (smbios_entry_32 == NULL && smbios_entry_64 == NULL) {
1119
        break;
1120
    }
1121
1122
    struct limine_smbios_response *smbios_response =
1123
        ext_mem_alloc(sizeof(struct limine_smbios_response));
1124
1125
    if (smbios_entry_32) {
1126
        smbios_response->entry_32 = (base_revision <= 2 || base_revision >= 5) ? reported_addr(smbios_entry_32) : (uintptr_t)smbios_entry_32;
1127
    }
1128
    if (smbios_entry_64) {
1129
        smbios_response->entry_64 = (base_revision <= 2 || base_revision >= 5) ? reported_addr(smbios_entry_64) : (uintptr_t)smbios_entry_64;
1130
    }
1131
1132
    smbios_request->response = reported_addr(smbios_response);
1133
FEAT_END
1134
1135
#if defined (UEFI)
1136
    // EFI system table feature
1137
FEAT_START
1138
    struct limine_efi_system_table_request *est_request = get_request(LIMINE_EFI_SYSTEM_TABLE_REQUEST_ID);
1139
    if (est_request == NULL) {
1140
        break; // next feature
1141
    }
1142
1143
    struct limine_efi_system_table_response *est_response =
1144
        ext_mem_alloc(sizeof(struct limine_efi_system_table_response));
1145
1146
    est_response->address = (base_revision <= 2 || base_revision >= 5) ? reported_addr(gST) : (uintptr_t)gST;
1147
1148
    est_request->response = reported_addr(est_response);
1149
FEAT_END
1150
#endif
1151
1152
    // Stack size
1153
    uint64_t stack_size = 65536;
1154
FEAT_START
1155
    struct limine_stack_size_request *stack_size_request = get_request(LIMINE_STACK_SIZE_REQUEST_ID);
1156
    if (stack_size_request == NULL) {
1157
        break; // next feature
1158
    }
1159
1160
    struct limine_stack_size_response *stack_size_response =
1161
        ext_mem_alloc(sizeof(struct limine_stack_size_response));
1162
1163
    if (stack_size_request->stack_size > stack_size) {
1164
        stack_size = stack_size_request->stack_size;
1165
    }
1166
1167
    stack_size_request->response = reported_addr(stack_size_response);
1168
FEAT_END
1169
1170
    // Executable file
1171
FEAT_START
1172
    struct limine_executable_file_request *executable_file_request = get_request(LIMINE_EXECUTABLE_FILE_REQUEST_ID);
1173
    if (executable_file_request == NULL) {
1174
        break; // next feature
1175
    }
1176
1177
    struct limine_executable_file_response *executable_file_response =
1178
        ext_mem_alloc(sizeof(struct limine_executable_file_response));
1179
1180
    executable_file_response->executable_file = reported_addr(kf);
1181
1182
    executable_file_request->response = reported_addr(executable_file_response);
1183
FEAT_END
1184
1185
    // Modules
1186
FEAT_START
1187
    struct limine_module_request *module_request = get_request(LIMINE_MODULE_REQUEST_ID);
1188
    if (module_request == NULL) {
1189
        break; // next feature
1190
    }
1191
1192
    size_t module_count;
1193
    for (module_count = 0; ; module_count++) {
1194
        char *module_file = config_get_value(config, module_count, "MODULE_PATH");
1195
        if (module_file == NULL)
1196
            break;
1197
    }
1198
1199
    if (module_request->revision >= 1) {
1200
        module_count += module_request->internal_module_count;
1201
    }
1202
1203
    if (module_count == 0) {
1204
        break;
1205
    }
1206
1207
    struct limine_module_response *module_response =
1208
        ext_mem_alloc(sizeof(struct limine_module_response));
1209
1210
    module_response->revision = 2;
1211
1212
    struct limine_file *modules = ext_mem_alloc_counted(module_count, sizeof(struct limine_file));
1213
1214
    size_t final_module_count = 0;
1215
    for (size_t i = 0; i < module_count; i++) {
1216
        char *module_path;
1217
        char *module_cmdline;
1218
        bool module_required = true;
1219
        bool module_path_allocated = false;
1220
1221
        if (module_request->revision >= 1 && i < module_request->internal_module_count) {
1222
            uint64_t *internal_modules = (void *)get_phys_addr(module_request->internal_modules);
1223
            struct limine_internal_module *internal_module = (void *)get_phys_addr(internal_modules[i]);
1224
1225
            module_path = (char *)get_phys_addr(internal_module->path);
1226
            module_cmdline = (char *)get_phys_addr(internal_module->string);
1227
1228
            bool module_compressed = internal_module->flags & LIMINE_INTERNAL_MODULE_COMPRESSED;
1229
            
1230
            // Validate path length to prevent buffer overflow
1231
            size_t k_resource_len = strlen(k_resource);
1232
            size_t k_root_len = strlen(k_root);
1233
            size_t module_path_len = strlen(module_path);
1234
            size_t k_path_len = strlen(k_path);
1235
            // Format: ["$"] + k_resource + "(" + k_root + "):" + k_path + "/" + module_path + null
1236
            size_t total_len = (module_compressed ? 1 : 0) + k_resource_len + 1 + k_root_len + 2 + k_path_len + 1 + module_path_len + 1;
1237
            if (total_len > 1024) {
1238
                panic(true, "limine: Internal module path too long");
1239
            }
1240
1241
            char *module_path_abs = ext_mem_alloc(1024);
1242
            char *module_path_abs_p = module_path_abs;
1243
            if (module_compressed) {
1244
                *module_path_abs_p++ = '$';
1245
            }
1246
            memcpy(module_path_abs_p, k_resource, k_resource_len);
1247
            module_path_abs_p += k_resource_len;
1248
            *module_path_abs_p++ = '(';
1249
            memcpy(module_path_abs_p, k_root, k_root_len);
1250
            module_path_abs_p += k_root_len;
1251
            memcpy(module_path_abs_p, "):", 2);
1252
            module_path_abs_p += 2;
1253
            size_t remaining_size = 1024 - (module_path_abs_p - module_path_abs);
1254
            if (!get_absolute_path(module_path_abs_p, module_path, k_path, remaining_size)) {
1255
                panic(true, "limine: Internal module path too long");
1256
            }
1257
1258
            module_path = module_path_abs;
1259
            module_path_allocated = true;
1260
1261
            module_required = internal_module->flags & LIMINE_INTERNAL_MODULE_REQUIRED;
1262
        } else {
1263
            size_t config_index = i - (module_request->revision >= 1 ? module_request->internal_module_count : 0);
1264
1265
            // Try MODULE_STRING first, then fall back to MODULE_CMDLINE
1266
            struct conf_tuple conf_tuple =
1267
                    config_get_tuple(config, config_index, "MODULE_PATH", "MODULE_STRING");
1268
1269
            module_path = conf_tuple.value1;
1270
            module_cmdline = conf_tuple.value2;
1271
1272
            if (module_cmdline == NULL) {
1273
                conf_tuple = config_get_tuple(config, config_index, "MODULE_PATH", "MODULE_CMDLINE");
1274
                module_cmdline = conf_tuple.value2;
1275
            }
1276
1277
            // Copy cmdline since conf_tuple uses static buffers
1278
            module_cmdline = module_cmdline ? strdup(module_cmdline) : "";
1279
        }
1280
1281
        print("limine: Loading module `%#`...\n", module_path);
1282
1283
        struct file_handle *f;
1284
        // On IA-32 under measured boot, refuse >4 GiB allocations: firmware's
1285
        // HashLogExtendEvent can't reach them, so we'd be unable to measure
1286
        // the module. Elsewhere, the firmware can address all of physical
1287
        // memory and high allocations remain measurable.
1288
        if ((f = uri_open(module_path, MEMMAP_KERNEL_AND_MODULES,
1289
#if defined (__i386__)
1290
            !measured_boot, limine_memcpy_to_64, limine_memcpy_from_64
1291
#else
1292
            true
1293
#endif
1294
        )) == NULL) {
1295
            if (module_required) {
1296
                panic(true, "limine: Failed to open module with path `%#`. Is the path correct?", module_path);
1297
            }
1298
            printv("limine: Warning: Non-required internal module `%#` not found\n", module_path);
1299
            if (module_path_allocated) {
1300
                pmm_free(module_path, 1024);
1301
            }
1302
            continue;
1303
        }
1304
        struct limine_file *l = &modules[final_module_count++];
1305
        *l = get_file(f, module_cmdline);
1306
1307
#if defined (UEFI)
1308
        tpm_measure_path(TPM_PCR_BOOT_AUTH, TPM_EV_IPL, "module_path: ", module_path);
1309
        tpm_measure(TPM_PCR_LOADED_IMAGES, TPM_EV_IPL,
1310
                    f->fd, f->size, "module_path: ", module_path);
1311
#endif
1312
1313
        if (module_path_allocated) {
1314
            pmm_free(module_path, 1024);
1315
        }
1316
1317
        fclose(f);
1318
    }
1319
1320
    uint64_t *modules_list = ext_mem_alloc_counted(final_module_count, sizeof(uint64_t));
1321
    for (size_t i = 0; i < final_module_count; i++) {
1322
        modules_list[i] = reported_addr(&modules[i]);
1323
    }
1324
1325
    module_response->module_count = final_module_count;
1326
    module_response->modules = reported_addr(modules_list);
1327
1328
    module_request->response = reported_addr(module_response);
1329
FEAT_END
1330
1331
    // Device tree blob feature
1332
FEAT_START
1333
    struct limine_dtb_request *dtb_request = get_request(LIMINE_DTB_REQUEST_ID);
1334
    if (dtb_request == NULL) {
1335
        break; // next feature
1336
    }
1337
1338
    void *dtb = get_device_tree_blob(config, 0, true);
1339
1340
    if (dtb) {
1341
        // Delete all /memory@... nodes.
1342
        // The executable must use the given UEFI memory map instead.
1343
        while (true) {
1344
            int offset = fdt_subnode_offset_namelen(dtb, 0, "memory@", 7);
1345
1346
            if (offset == -FDT_ERR_NOTFOUND) {
1347
                break;
1348
            }
1349
1350
            if (offset < 0) {
1351
                panic(true, "limine: failed to find node: '%s'", fdt_strerror(offset));
1352
            }
1353
1354
            int ret = fdt_del_node(dtb, offset);
1355
            if (ret < 0) {
1356
                panic(true, "limine: failed to delete memory node: '%s'", fdt_strerror(ret));
1357
            }
1358
        }
1359
1360
        struct limine_dtb_response *dtb_response =
1361
            ext_mem_alloc(sizeof(struct limine_dtb_response));
1362
        dtb_response->dtb_ptr = reported_addr(dtb);
1363
        dtb_request->response = reported_addr(dtb_response);
1364
    }
1365
FEAT_END
1366
1367
    size_t req_width = 0, req_height = 0, req_bpp = 0;
1368
1369
    char *resolution = config_get_value(config, 0, "RESOLUTION");
1370
    if (resolution != NULL) {
1371
        parse_resolution(&req_width, &req_height, &req_bpp, resolution);
1372
    }
1373
1374
    struct fb_info *fbs;
1375
    size_t fbs_count;
1376
1377
    bool preserve_screen = get_request(LIMINE_FLANTERM_FB_INIT_PARAMS_REQUEST_ID) != NULL;
1378
1379
    term_notready();
1380
1381
    fb_init(&fbs, &fbs_count, req_width, req_height, req_bpp, preserve_screen, false);
1382
    if (fbs_count == 0) {
1383
        goto no_fb;
1384
    }
1385
1386
    for (size_t i = 0; i < fbs_count; i++) {
1387
        if (!memmap_alloc_range(fbs[i].framebuffer_addr,
1388
                           (uint64_t)fbs[i].framebuffer_pitch * fbs[i].framebuffer_height,
1389
                           MEMMAP_FRAMEBUFFER, 0, false, false, true)) {
1390
            panic(true, "limine: Failed to register framebuffer in memory map");
1391
        }
1392
    }
1393
1394
    // Check for page-level overlaps between framebuffer and other memory regions.
1395
    // The framebuffer is mapped with a different caching type, so overlapping pages
1396
    // must be resolved.
1397
    for (size_t i = 0; i < memmap_entries; i++) {
1398
        if (memmap[i].type != MEMMAP_FRAMEBUFFER) {
1399
            continue;
1400
        }
1401
1402
        uint64_t fb_base = memmap[i].base;
1403
        uint64_t fb_top = CHECKED_ADD(fb_base, memmap[i].length, continue);
1404
        uint64_t fb_aligned_base = ALIGN_DOWN(fb_base, 4096);
1405
        uint64_t fb_aligned_top = ALIGN_UP(fb_top, 4096, continue);
1406
1407
        // No overshoot means no possible overlap.
1408
        if (fb_aligned_base == fb_base && fb_aligned_top == fb_top) {
1409
            continue;
1410
        }
1411
1412
        for (size_t j = 0; j < memmap_entries; j++) {
1413
            if (j == i || memmap[j].length == 0
1414
             || memmap[j].type == MEMMAP_FRAMEBUFFER) {
1415
                continue;
1416
            }
1417
1418
            uint64_t region_base = memmap[j].base;
1419
            uint64_t region_top = CHECKED_ADD(region_base, memmap[j].length, continue);
1420
1421
            // Check if this region overlaps with the framebuffer's page-aligned extent.
1422
            if (region_top <= fb_aligned_base || region_base >= fb_aligned_top) {
1423
                continue;
1424
            }
1425
1426
            // There is a page-level overlap. Only USABLE and RESERVED regions
1427
            // can be trimmed; everything else describes firmware- or
1428
            // kernel-asserted content that we must not silently shrink.
1429
            if (memmap[j].type != MEMMAP_USABLE
1430
             && memmap[j].type != MEMMAP_RESERVED) {
1431
                panic(false, "limine: Framebuffer page-level overlap with non-trimmable memory type %x", memmap[j].type);
1432
            }
1433
1434
            // Trim the region to not overlap with the framebuffer's
1435
            // page-aligned extent.
1436
            if (region_base < fb_aligned_base && region_top > fb_aligned_base) {
1437
                // Region extends before the framebuffer - trim end.
1438
                memmap[j].length = fb_aligned_base - region_base;
1439
            } else if (region_base < fb_aligned_top && region_top > fb_aligned_top) {
1440
                // Region extends after the framebuffer - trim start.
1441
                memmap[j].length = region_top - fb_aligned_top;
1442
                memmap[j].base = fb_aligned_top;
1443
            } else {
1444
                // Region is entirely within the framebuffer's page-aligned extent - zero it.
1445
                memmap[j].length = 0;
1446
            }
1447
        }
1448
    }
1449
1450
    struct limine_framebuffer *fbp = NULL;
1451
1452
    // Framebuffer feature
1453
FEAT_START
1454
    struct limine_framebuffer_request *framebuffer_request = get_request(LIMINE_FRAMEBUFFER_REQUEST_ID);
1455
    if (framebuffer_request == NULL) {
1456
        break; // next feature
1457
    }
1458
1459
    if (fbs_count == 0) {
1460
        break;
1461
    }
1462
1463
    fbp = ext_mem_alloc_counted(fbs_count, sizeof(struct limine_framebuffer));
1464
1465
    struct limine_framebuffer_response *framebuffer_response =
1466
        ext_mem_alloc(sizeof(struct limine_framebuffer_response));
1467
1468
    framebuffer_response->revision = 1;
1469
1470
    uint64_t *fb_list = ext_mem_alloc_counted(fbs_count, sizeof(uint64_t));
1471
1472
    for (size_t i = 0; i < fbs_count; i++) {
1473
        uint64_t *modes_list = ext_mem_alloc_counted(fbs[i].mode_count, sizeof(uint64_t));
1474
        for (size_t j = 0; j < fbs[i].mode_count; j++) {
1475
            fbs[i].mode_list[j].memory_model = LIMINE_FRAMEBUFFER_RGB;
1476
            modes_list[j] = reported_addr(&fbs[i].mode_list[j]);
1477
        }
1478
        fbp[i].modes = reported_addr(modes_list);
1479
        fbp[i].mode_count = fbs[i].mode_count;
1480
1481
        if (fbs[i].edid != NULL) {
1482
            fbp[i].edid_size = sizeof(struct edid_info_struct);
1483
            fbp[i].edid = reported_addr(fbs[i].edid);
1484
        }
1485
1486
        fbp[i].memory_model     = LIMINE_FRAMEBUFFER_RGB;
1487
        fbp[i].address          = reported_addr((void *)(uintptr_t)fbs[i].framebuffer_addr);
1488
        fbp[i].width            = fbs[i].framebuffer_width;
1489
        fbp[i].height           = fbs[i].framebuffer_height;
1490
        fbp[i].bpp              = fbs[i].framebuffer_bpp;
1491
        fbp[i].pitch            = fbs[i].framebuffer_pitch;
1492
        fbp[i].red_mask_size    = fbs[i].red_mask_size;
1493
        fbp[i].red_mask_shift   = fbs[i].red_mask_shift;
1494
        fbp[i].green_mask_size  = fbs[i].green_mask_size;
1495
        fbp[i].green_mask_shift = fbs[i].green_mask_shift;
1496
        fbp[i].blue_mask_size   = fbs[i].blue_mask_size;
1497
        fbp[i].blue_mask_shift  = fbs[i].blue_mask_shift;
1498
1499
        fb_list[i] = reported_addr(&fbp[i]);
1500
    }
1501
1502
    framebuffer_response->framebuffer_count = fbs_count;
1503
    framebuffer_response->framebuffers = reported_addr(fb_list);
1504
1505
    framebuffer_request->response = reported_addr(framebuffer_response);
1506
FEAT_END
1507
1508
    // Flanterm FB init params feature
1509
FEAT_START
1510
    struct limine_flanterm_fb_init_params_request *fip_request = get_request(LIMINE_FLANTERM_FB_INIT_PARAMS_REQUEST_ID);
1511
    if (fip_request == NULL) {
1512
        break;
1513
    }
1514
1515
    if (fbp == NULL || fbs_count == 0) {
1516
        break;
1517
    }
1518
1519
    struct flanterm_params *fip_raw = ext_mem_alloc_counted(fbs_count, sizeof(struct flanterm_params));
1520
    size_t fip_count = gterm_prepare_flanterm_params(fbs, fbs_count, fip_raw, fbs_count);
1521
1522
    struct limine_flanterm_fb_init_params *fip_entries =
1523
        ext_mem_alloc_counted(fbs_count, sizeof(struct limine_flanterm_fb_init_params));
1524
    uint64_t *fip_list = ext_mem_alloc_counted(fbs_count, sizeof(uint64_t));
1525
1526
    size_t fip_idx = 0;
1527
    for (size_t i = 0; i < fbs_count; i++) {
1528
        struct limine_flanterm_fb_init_params *entry = &fip_entries[i];
1529
1530
        if (fbs[i].framebuffer_bpp == 32 && fip_idx < fip_count) {
1531
            struct flanterm_params *raw = &fip_raw[fip_idx];
1532
1533
            entry->canvas = raw->canvas != NULL ? reported_addr(raw->canvas) : 0;
1534
            entry->canvas_size = raw->canvas_size;
1535
            memcpy(entry->ansi_colours, raw->ansi_colours, sizeof(raw->ansi_colours));
1536
            memcpy(entry->ansi_bright_colours, raw->ansi_bright_colours, sizeof(raw->ansi_bright_colours));
1537
            entry->default_bg = raw->default_bg;
1538
            entry->default_fg = raw->default_fg;
1539
            entry->default_bg_bright = raw->default_bg_bright;
1540
            entry->default_fg_bright = raw->default_fg_bright;
1541
            entry->font = reported_addr(raw->font);
1542
            entry->font_width = raw->font_width;
1543
            entry->font_height = raw->font_height;
1544
            entry->font_spacing = raw->font_spacing;
1545
            entry->font_scale_x = raw->font_scale_x;
1546
            entry->font_scale_y = raw->font_scale_y;
1547
            entry->margin = raw->margin;
1548
            entry->rotation = raw->rotation;
1549
1550
            fip_idx++;
1551
        }
1552
1553
        fip_list[i] = reported_addr(entry);
1554
    }
1555
1556
    struct limine_flanterm_fb_init_params_response *fip_response =
1557
        ext_mem_alloc(sizeof(struct limine_flanterm_fb_init_params_response));
1558
1559
    fip_response->entry_count = fbs_count;
1560
    fip_response->entries = reported_addr(fip_list);
1561
1562
    fip_request->response = reported_addr(fip_response);
1563
FEAT_END
1564
1565
no_fb:
1566
    // Boot time feature
1567
FEAT_START
1568
    struct limine_date_at_boot_request *date_at_boot_request = get_request(LIMINE_DATE_AT_BOOT_REQUEST_ID);
1569
    if (date_at_boot_request == NULL) {
1570
        break; // next feature
1571
    }
1572
1573
    struct limine_date_at_boot_response *date_at_boot_response =
1574
        ext_mem_alloc(sizeof(struct limine_date_at_boot_response));
1575
1576
    date_at_boot_response->timestamp = time();
1577
1578
    date_at_boot_request->response = reported_addr(date_at_boot_response);
1579
FEAT_END
1580
1581
    // Wrap-up stuff before memmap close
1582
#if defined (__x86_64__) || defined (__i386__)
1583
    struct gdtr *local_gdt = ext_mem_alloc(sizeof(struct gdtr));
1584
    local_gdt->limit = gdt.limit;
1585
    uint64_t local_gdt_base = (uint64_t)gdt.ptr;
1586
    local_gdt_base += direct_map_offset;
1587
    local_gdt->ptr = local_gdt_base;
1588
#if defined (__i386__)
1589
    local_gdt->ptr_hi = local_gdt_base >> 32;
1590
#endif
1591
#endif
1592
1593
#if defined (__aarch64__)
1594
    // Find the most restrictive caching mode from all framebuffers to use
1595
    uint64_t fb_attr = (uint64_t)-1;
1596
1597
    for (size_t i = 0; i < fbs_count; i++) {
1598
        int el = current_el();
1599
        uint64_t res;
1600
1601
        // Figure out the caching mode used for this particular framebuffer
1602
        if (el == 1) {
1603
            asm volatile (
1604
                    "at s1e1w, %1\n\t"
1605
                    "isb\n\t"
1606
                    "mrs %0, par_el1"
1607
                    : "=r"(res)
1608
                    : "r"(fbs[i].framebuffer_addr)
1609
                    : "memory");
1610
        } else if (el == 2) {
1611
            asm volatile (
1612
                    "at s1e2w, %1\n\t"
1613
                    "isb\n\t"
1614
                    "mrs %0, par_el1"
1615
                    : "=r"(res)
1616
                    : "r"(fbs[i].framebuffer_addr)
1617
                    : "memory");
1618
        } else {
1619
            panic(false, "Unexpected EL in limine_load");
1620
        }
1621
1622
        if (res & 1)
1623
            panic(false, "Address translation for framebuffer failed");
1624
1625
        uint64_t new_attr = res >> 56;
1626
1627
        // Use whatever we find first
1628
        if (fb_attr == (uint64_t)-1)
1629
            fb_attr = new_attr;
1630
        // Prefer Device memory over Normal memory
1631
        else if ((fb_attr & 0b11110000) && !(new_attr & 0b11110000))
1632
            fb_attr = new_attr;
1633
        // Prefer tighter Device memory (lower values)
1634
        else if (!(fb_attr & 0b11110000) && !(new_attr & 0b11110000) && fb_attr > new_attr)
1635
            fb_attr = new_attr;
1636
        // Use Normal non-cacheable otherwise (avoid trying to figure out how to downgrade inner vs outer).
1637
        else if ((fb_attr & 0b11110000) && (new_attr & 0b11110000))
1638
            fb_attr = 0b01000100; // Inner&outer Non-cacheable
1639
        // Otherwise do nothing (fb_attr is already more restrictive than new_attr).
1640
    }
1641
1642
    // If no framebuffers are found, just zero out the MAIR entry
1643
    if (fb_attr == (uint64_t)-1)
1644
        fb_attr = 0;
1645
#endif
1646
1647
    void *stack = ext_mem_alloc(stack_size) + stack_size;
1648
1649
    bool nx_available = true;
1650
#if defined (__x86_64__) || defined (__i386__)
1651
    // Check if we have NX
1652
    if (!cpuid(0x80000001, 0, &eax, &ebx, &ecx, &edx) || !(edx & (1 << 20))) {
1653
        nx_available = false;
1654
    }
1655
#endif
1656
1657
    // TSC Frequency
1658
FEAT_START
1659
    if (tsc_freq == 0) {
1660
        break;
1661
    }
1662
1663
    struct limine_tsc_frequency_request *tsc_freq_request = get_request(LIMINE_TSC_FREQUENCY_REQUEST_ID);
1664
    if (tsc_freq_request == NULL) {
1665
        break;
1666
    }
1667
1668
    struct limine_tsc_frequency_response *tsc_freq_response =
1669
        ext_mem_alloc(sizeof(struct limine_tsc_frequency_response));
1670
1671
    tsc_freq_response->frequency = tsc_freq;
1672
1673
    tsc_freq_request->response = reported_addr(tsc_freq_response);
1674
FEAT_END
1675
1676
    // Bootloader Performance
1677
FEAT_START
1678
    if (usec_at_bootloader_entry == 0) {
1679
        break;
1680
    }
1681
1682
    struct limine_bootloader_performance_request *perf_request = get_request(LIMINE_BOOTLOADER_PERFORMANCE_REQUEST_ID);
1683
    if (perf_request == NULL) {
1684
        break;
1685
    }
1686
1687
    struct limine_bootloader_performance_response *perf_response =
1688
        ext_mem_alloc(sizeof(struct limine_bootloader_performance_response));
1689
1690
    perf_response->reset_usec = 0;
1691
    perf_response->init_usec = usec_at_bootloader_entry;
1692
    perf_response->exec_usec = rdtsc_usec();
1693
    perf_request->response = reported_addr(perf_response);
1694
FEAT_END
1695
1696
#if defined (UEFI)
1697
    // TPM event log feature. Processed last so GetEventLog snapshots a log
1698
    // containing all of Limine's extends; later extends would land in the
1699
    // final-events table instead.
1700
FEAT_START
1701
    struct limine_tpm_event_log_request *tpm_event_log_request = get_request(LIMINE_TPM_EVENT_LOG_REQUEST_ID);
1702
    if (tpm_event_log_request == NULL) {
1703
        break; // next feature
1704
    }
1705
1706
    uint32_t tpm_event_log_format;
1707
    void *tpm_event_log_addr;
1708
    size_t tpm_event_log_size;
1709
    if (!tpm_get_event_log(&tpm_event_log_format, &tpm_event_log_addr, &tpm_event_log_size)) {
1710
        break; // no TPM or capture failed
1711
    }
1712
1713
    struct limine_tpm_event_log_response *tpm_event_log_response =
1714
        ext_mem_alloc(sizeof(struct limine_tpm_event_log_response));
1715
1716
    tpm_event_log_response->format = tpm_event_log_format;
1717
    tpm_event_log_response->size = tpm_event_log_size;
1718
    tpm_event_log_response->address = tpm_event_log_size > 0
1719
        ? reported_addr(tpm_event_log_addr) : 0;
1720
1721
    tpm_event_log_request->response = reported_addr(tpm_event_log_response);
1722
FEAT_END
1723
1724
    efi_exit_boot_services();
1725
#endif
1726
1727
    // EFI memory map
1728
#if defined (UEFI)
1729
FEAT_START
1730
    struct limine_efi_memmap_request *efi_memmap_request = get_request(LIMINE_EFI_MEMMAP_REQUEST_ID);
1731
    if (efi_memmap_request == NULL) {
1732
        break; // next feature
1733
    }
1734
1735
    struct limine_efi_memmap_response *efi_memmap_response =
1736
        ext_mem_alloc(sizeof(struct limine_efi_memmap_response));
1737
1738
    efi_memmap_response->memmap = reported_addr(efi_mmap);
1739
    efi_memmap_response->memmap_size = efi_mmap_size;
1740
    efi_memmap_response->desc_size = efi_desc_size;
1741
    efi_memmap_response->desc_version = efi_desc_ver;
1742
1743
    efi_memmap_request->response = reported_addr(efi_memmap_response);
1744
FEAT_END
1745
#endif
1746
1747
    if (base_revision < 3) {
1748
        pmm_sanitiser_keep_first_page = false;
1749
        pmm_sanitise_entries(memmap, &memmap_entries, true);
1750
    }
1751
1752
    if (base_revision >= 4) {
1753
        acpi_map_tables();
1754
        if (base_revision >= 5) {
1755
            smbios_map_tables();
1756
#if defined (UEFI)
1757
            efi_map_runtime_entries();
1758
#endif
1759
        }
1760
        pmm_sanitise_entries(memmap, &memmap_entries, true);
1761
    }
1762
1763
    pagemap_t pagemap = {0};
1764
    pagemap = build_pagemap(base_revision, nx_available, ranges, ranges_count,
1765
                            physical_base, virtual_base, direct_map_offset);
1766
1767
#if defined (__aarch64__)
1768
    // Enter at EL2 with VHE if we are at EL2 (VHE check done at function entry)
1769
    bool want_el2 = (current_el() == 2);
1770
#endif
1771
1772
    // MP
1773
FEAT_START
1774
    struct limine_mp_request *mp_request = get_request(LIMINE_MP_REQUEST_ID);
1775
    if (mp_request == NULL) {
1776
        break; // next feature
1777
    }
1778
1779
    struct limine_mp_info *mp_info;
1780
    size_t cpu_count;
1781
#if defined (__x86_64__) || defined (__i386__)
1782
    smp_configure_apic = base_revision >= 5;
1783
    uint32_t bsp_lapic_id;
1784
    mp_info = init_smp(&cpu_count, &bsp_lapic_id,
1785
                        paging_mode,
1786
                        pagemap, mp_request->flags & LIMINE_MP_REQUEST_X86_64_X2APIC, nx_available,
1787
                        direct_map_offset, true);
1788
#elif defined (__aarch64__)
1789
    uint64_t bsp_mpidr;
1790
1791
    mp_info = init_smp(config, &cpu_count, &bsp_mpidr,
1792
                        pagemap, LIMINE_MAIR(fb_attr), LIMINE_TCR(tsz, pa), LIMINE_SCTLR,
1793
                        direct_map_offset);
1794
#elif defined (__riscv)
1795
    mp_info = init_smp(&cpu_count, pagemap, direct_map_offset);
1796
#elif defined (__loongarch64)
1797
    uint32_t bsp_phys_id;
1798
    mp_info = init_smp(&cpu_count, &bsp_phys_id, pagemap, direct_map_offset);
1799
#else
1800
#error Unknown architecture
1801
#endif
1802
1803
    if (mp_info == NULL) {
1804
        break;
1805
    }
1806
1807
    for (size_t i = 0; i < cpu_count; i++) {
1808
#if defined (__x86_64__) || defined (__i386__)
1809
        if (mp_info[i].lapic_id == bsp_lapic_id) {
1810
            continue;
1811
        }
1812
#elif defined (__aarch64__)
1813
        if (mp_info[i].mpidr == bsp_mpidr) {
1814
            continue;
1815
        }
1816
#elif defined (__riscv)
1817
        if (mp_info[i].hartid == bsp_hartid) {
1818
            continue;
1819
        }
1820
#elif defined (__loongarch64)
1821
        if (mp_info[i].phys_id == bsp_phys_id) {
1822
            continue;
1823
        }
1824
#else
1825
#error Unknown architecture
1826
#endif
1827
1828
        void *cpu_stack = ext_mem_alloc(stack_size) + stack_size;
1829
        mp_info[i].reserved = reported_addr(cpu_stack);
1830
    }
1831
1832
    struct limine_mp_response *mp_response =
1833
        ext_mem_alloc(sizeof(struct limine_mp_response));
1834
1835
#if defined (__x86_64__) || defined (__i386__)
1836
    mp_response->flags |=
1837
        (mp_request->flags & LIMINE_MP_REQUEST_X86_64_X2APIC) && x2apic_check() ? LIMINE_MP_RESPONSE_X86_64_X2APIC : 0;
1838
    mp_response->bsp_lapic_id = bsp_lapic_id;
1839
#elif defined (__aarch64__)
1840
    mp_response->bsp_mpidr = bsp_mpidr;
1841
#elif defined (__riscv)
1842
    mp_response->bsp_hartid = bsp_hartid;
1843
#elif defined (__loongarch64)
1844
    mp_response->bsp_phys_id = bsp_phys_id;
1845
#else
1846
#error Unknown architecture
1847
#endif
1848
1849
    uint64_t *mp_list = ext_mem_alloc_counted(cpu_count, sizeof(uint64_t));
1850
    for (size_t i = 0; i < cpu_count; i++) {
1851
        mp_list[i] = reported_addr(&mp_info[i]);
1852
    }
1853
1854
    mp_response->cpu_count = cpu_count;
1855
    mp_response->cpus = reported_addr(mp_list);
1856
1857
    mp_request->response = reported_addr(mp_response);
1858
FEAT_END
1859
1860
#if defined (__x86_64__) || defined (__i386__)
1861
    // If there was no MP request, the kernel has no way to tell us it supports
1862
    // x2APIC. Try to disable it as a courtesy, but do not panic if we cannot
1863
    // since the kernel may be able to deal with it itself.
1864
    if (get_request(LIMINE_MP_REQUEST_ID) == NULL
1865
     && (rdmsr(0x1b) & (1 << 10))) {
1866
        if (x2apic_disable()) {
1867
            printv("limine: Firmware had x2APIC enabled, reverted to xAPIC mode\n");
1868
        } else {
1869
            printv("limine: Firmware has x2APIC enabled and it could not be disabled\n");
1870
        }
1871
    }
1872
#endif
1873
1874
#if defined(__riscv)
1875
    // RISC-V BSP Hart ID
1876
FEAT_START
1877
    struct limine_riscv_bsp_hartid_request *bsp_request = get_request(LIMINE_RISCV_BSP_HARTID_REQUEST_ID);
1878
    if (bsp_request == NULL) {
1879
        break;
1880
    }
1881
    struct limine_riscv_bsp_hartid_response *bsp_response = ext_mem_alloc(sizeof(struct limine_riscv_bsp_hartid_response));
1882
    bsp_response->bsp_hartid = bsp_hartid;
1883
    bsp_request->response = reported_addr(bsp_response);
1884
FEAT_END
1885
#endif
1886
1887
    // Memmap
1888
FEAT_START
1889
    struct limine_memmap_request *memmap_request = get_request(LIMINE_MEMMAP_REQUEST_ID);
1890
    struct limine_memmap_response *memmap_response;
1891
    struct limine_memmap_entry *_memmap;
1892
    uint64_t *memmap_list;
1893
1894
    if (memmap_request != NULL) {
1895
        memmap_response = ext_mem_alloc(sizeof(struct limine_memmap_response));
1896
        _memmap = ext_mem_alloc(sizeof(struct limine_memmap_entry) * MEMMAP_MAX);
1897
        memmap_list = ext_mem_alloc_counted(MEMMAP_MAX, sizeof(uint64_t));
1898
    }
1899
1900
    size_t mmap_entries;
1901
    struct memmap_entry *mmap = get_memmap(&mmap_entries);
1902
1903
    if (memmap_request == NULL) {
1904
        break; // next feature
1905
    }
1906
1907
    if (mmap_entries > MEMMAP_MAX) {
1908
        panic(false, "limine: Too many memmap entries");
1909
    }
1910
1911
    for (size_t i = 0; i < mmap_entries; i++) {
1912
        _memmap[i].base = mmap[i].base;
1913
        _memmap[i].length = mmap[i].length;
1914
1915
        switch (mmap[i].type) {
1916
            case MEMMAP_USABLE:
1917
                _memmap[i].type = LIMINE_MEMMAP_USABLE;
1918
                break;
1919
            case MEMMAP_RESERVED_MAPPED:
1920
                _memmap[i].type = LIMINE_MEMMAP_RESERVED_MAPPED;
1921
                break;
1922
            case MEMMAP_ACPI_RECLAIMABLE:
1923
                _memmap[i].type = LIMINE_MEMMAP_ACPI_RECLAIMABLE;
1924
                break;
1925
            case MEMMAP_ACPI_NVS:
1926
                _memmap[i].type = LIMINE_MEMMAP_ACPI_NVS;
1927
                break;
1928
            case MEMMAP_BAD_MEMORY:
1929
                _memmap[i].type = LIMINE_MEMMAP_BAD_MEMORY;
1930
                break;
1931
            case MEMMAP_BOOTLOADER_RECLAIMABLE:
1932
                _memmap[i].type = LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE;
1933
                break;
1934
            case MEMMAP_KERNEL_AND_MODULES:
1935
                _memmap[i].type = LIMINE_MEMMAP_EXECUTABLE_AND_MODULES;
1936
                break;
1937
            case MEMMAP_FRAMEBUFFER:
1938
                _memmap[i].type = LIMINE_MEMMAP_FRAMEBUFFER;
1939
                break;
1940
            default:
1941
            case MEMMAP_RESERVED:
1942
                _memmap[i].type = LIMINE_MEMMAP_RESERVED;
1943
                break;
1944
        }
1945
    }
1946
1947
    for (size_t i = 0; i < mmap_entries; i++) {
1948
        memmap_list[i] = reported_addr(&_memmap[i]);
1949
    }
1950
1951
    memmap_response->entry_count = mmap_entries;
1952
    memmap_response->entries = reported_addr(memmap_list);
1953
1954
    memmap_request->response = reported_addr(memmap_response);
1955
FEAT_END
1956
1957
#if defined (__x86_64__) || defined (__i386__)
1958
#if defined (BIOS)
1959
    // If we're going 64, we might as well call this BIOS interrupt
1960
    // to tell the BIOS that we are entering Long Mode, since it is in
1961
    // the specification.
1962
    struct rm_regs r = {0};
1963
    r.eax = 0xec00;
1964
    r.ebx = 0x02;   // Long mode only
1965
    rm_int(0x15, &r, &r);
1966
#endif
1967
1968
    if (!keep_iommu) {
1969
        iommu_disable_all();
1970
    }
1971
1972
    pic_mask_all();
1973
    io_apic_mask_all(base_revision >= 5);
1974
1975
    if (base_revision >= 5 && lapic_check()) {
1976
        lapic_configure_bsp();
1977
    }
1978
1979
    irq_flush_type = IRQ_PIC_APIC_FLUSH;
1980
1981
    uint64_t reported_stack = reported_addr(stack);
1982
1983
    common_spinup(limine_spinup_32, 11,
1984
        paging_mode, (uint32_t)(uintptr_t)pagemap.top_level,
1985
        (uint32_t)entry_point, (uint32_t)(entry_point >> 32),
1986
        (uint32_t)reported_stack, (uint32_t)(reported_stack >> 32),
1987
        (uint32_t)(uintptr_t)local_gdt, nx_available,
1988
        (uint32_t)direct_map_offset, (uint32_t)(direct_map_offset >> 32),
1989
        (uint32_t)base_revision
1990
    );
1991
#elif defined (__aarch64__)
1992
    vmm_assert_4k_pages();
1993
1994
    uint64_t reported_stack = reported_addr(stack);
1995
1996
    if (want_el2) {
1997
        enter_in_el2(entry_point, reported_stack, LIMINE_SCTLR, LIMINE_MAIR(fb_attr), LIMINE_TCR(tsz, pa),
1998
                     (uint64_t)pagemap.top_level[0],
1999
                     (uint64_t)pagemap.top_level[1],
2000
                     direct_map_offset);
2001
    } else {
2002
        enter_in_el1(entry_point, reported_stack, LIMINE_SCTLR, LIMINE_MAIR(fb_attr), LIMINE_TCR(tsz, pa),
2003
                     (uint64_t)pagemap.top_level[0],
2004
                     (uint64_t)pagemap.top_level[1],
2005
                     direct_map_offset);
2006
    }
2007
#elif defined (__riscv)
2008
    uint64_t reported_stack = reported_addr(stack);
2009
    uint64_t satp = make_satp(pagemap.paging_mode, pagemap.top_level);
2010
2011
    riscv_spinup(entry_point, reported_stack, satp, direct_map_offset);
2012
#elif defined (__loongarch64)
2013
    uint64_t reported_stack = reported_addr(stack);
2014
2015
    loongarch_spinup(entry_point, reported_stack, (uint64_t)pagemap.pgd[0], (uint64_t)pagemap.pgd[1],
2016
                     direct_map_offset);
2017
#else
2018
#error Unknown architecture
2019
#endif
2020
}
tab: 248 wrap: offon