:: commit 80c82d9772058e9d0dfd647331d5db5dfc05ab60

Mintsuki <mintsuki@protonmail.com> — 2025-10-25 00:31

parents: cf739c2441

protos/limine: Initial implementation of base revision 4

diff --git a/bootstrap b/bootstrap
index af8c1276..aff8e270 100755
--- a/bootstrap
+++ b/bootstrap
@@ -85,7 +85,7 @@ if ! test -f version; then
     clone_repo_commit \
         https://codeberg.org/Limine/limine-protocol.git \
         limine-protocol \
-        fedf97facd1c473ee8720f8dfd5a71d03490d928
+        cc957208629a1ee427a826915f323508fd52ee91
 
     clone_repo_commit \
         https://codeberg.org/PicoEFI/PicoEFI.git \
diff --git a/common/common.mk b/common/common.mk
index b1f55276..8c477677 100644
--- a/common/common.mk
+++ b/common/common.mk
@@ -46,7 +46,7 @@ override CPPFLAGS_FOR_TARGET := \
     $(CPPFLAGS_FOR_TARGET) \
     -DCOM_OUTPUT=$(COM_OUTPUT) \
     -DE9_OUTPUT=$(E9_OUTPUT) \
-    -DLIMINE_API_REVISION=3 \
+    -DLIMINE_API_REVISION=4 \
     -DFLANTERM_IN_FLANTERM \
     -MMD \
     -MP
diff --git a/common/lib/acpi.c b/common/lib/acpi.c
index 012f22e0..f2dee5a9 100644
--- a/common/lib/acpi.c
+++ b/common/lib/acpi.c
@@ -5,6 +5,7 @@
 #include <lib/misc.h>
 #include <lib/libc.h>
 #include <lib/print.h>
+#include <mm/pmm.h>
 
 // Following function based on https://github.com/managarm/lai/blob/master/helpers/pc-bios.c's function lai_bios_calc_checksum()
 uint8_t acpi_checksum(void *ptr, size_t size) {
@@ -238,3 +239,95 @@ void *acpi_get_table(const char *signature, int index) {
     printv("acpi: \"%s\" not found\n", signature);
     return NULL;
 }
+
+void map_single_table(uint64_t addr, uint32_t len) {
+#if defined (__i386__)
+    if (addr >= 0x100000000) {
+        print("acpi: warning: Cannot get length of ACPI table above 4GiB\n");
+        return;
+    }
+#endif
+
+    uint32_t length = len != (uint32_t)-1 ? len : *(uint32_t *)(uintptr_t)(addr + 4);
+
+    uint64_t memmap_type = pmm_check_type(addr);
+
+    if (memmap_type != MEMMAP_ACPI_RECLAIMABLE && memmap_type != MEMMAP_ACPI_NVS) {
+        memmap_alloc_range(addr, length, MEMMAP_ACPI_TABLES, 0, true, false, true);
+    }
+}
+
+
+void acpi_map_tables(void) {
+    struct rsdp *rsdp = acpi_get_rsdp();
+    if (rsdp == NULL)
+        return;
+
+    uint64_t rsdp_length;
+    if (rsdp->rev < 2) {
+        rsdp_length = 20;
+    } else {
+        rsdp_length = rsdp->length;
+    }
+
+    map_single_table((uintptr_t)rsdp, rsdp_length);
+
+    if (!(rsdp->rev >= 2 && rsdp->xsdt_addr)) {
+        goto no_xsdt;
+    }
+
+    struct rsdt *xsdt = (void *)(uintptr_t)rsdp->xsdt_addr;
+    size_t xsdt_entry_count = (xsdt->header.length - sizeof(struct sdt)) / 8;
+
+    map_single_table((uintptr_t)xsdt, (uint32_t)-1);
+
+    for (size_t i = 0; i < xsdt_entry_count; i++) {
+        struct sdt *sdt = (void *)(uintptr_t)((uint64_t *)xsdt->ptrs_start)[i];
+
+        map_single_table((uintptr_t)sdt, (uint32_t)-1);
+    }
+
+no_xsdt:;
+    struct rsdt *rsdt = (void *)(uintptr_t)rsdp->rsdt_addr;
+    size_t rsdt_entry_count = (rsdt->header.length - sizeof(struct sdt)) / 4;
+
+    map_single_table((uintptr_t)rsdt, (uint32_t)-1);
+
+    for (size_t i = 0; i < rsdt_entry_count; i++) {
+        struct sdt *sdt = (void *)(uintptr_t)((uint32_t *)rsdt->ptrs_start)[i];
+
+        map_single_table((uintptr_t)sdt, (uint32_t)-1);
+    }
+
+    uint8_t *fadt = acpi_get_table("FACP", 0);
+    if (fadt == NULL) {
+        return;
+    }
+    uint32_t fadt_length = *(uint32_t *)(fadt + 4);
+
+    // Read the single fields from the FADT without defining a struct for the whole table
+    if (fadt_length >= 132 + 8) {
+        uint64_t x_facs = *(uint64_t *)(fadt + 132);
+        if (x_facs != 0) {
+            map_single_table(x_facs, (uint32_t)-1);
+        }
+    }
+    if (fadt_length >= 140 + 8) {
+        uint64_t x_dsdt = *(uint64_t *)(fadt + 140);
+        if (x_dsdt != 0) {
+            map_single_table(x_dsdt, (uint32_t)-1);
+        }
+    }
+    if (fadt_length >= 36 + 4) {
+        uint32_t facs = *(uint32_t *)(fadt + 36);
+        if (facs != 0) {
+            map_single_table(facs, (uint32_t)-1);
+        }
+    }
+    if (fadt_length >= 40 + 4) {
+        uint32_t dsdt = *(uint32_t *)(fadt + 40);
+        if (dsdt != 0) {
+            map_single_table(dsdt, (uint32_t)-1);
+        }
+    }
+}
diff --git a/common/lib/acpi.h b/common/lib/acpi.h
index b674e78d..fac5ef24 100644
--- a/common/lib/acpi.h
+++ b/common/lib/acpi.h
@@ -182,4 +182,6 @@ void   *acpi_get_rsdp_v2(void);
 void   *acpi_get_table(const char *signature, int index);
 void    acpi_get_smbios(void **smbios32, void **smbios64);
 
+void acpi_map_tables(void);
+
 #endif
diff --git a/common/mm/pmm.h b/common/mm/pmm.h
index 830f93c4..b8768647 100644
--- a/common/mm/pmm.h
+++ b/common/mm/pmm.h
@@ -20,6 +20,7 @@ struct memmap_entry {
 #define MEMMAP_BOOTLOADER_RECLAIMABLE 0x1000
 #define MEMMAP_KERNEL_AND_MODULES     0x1001
 #define MEMMAP_FRAMEBUFFER            0x1002
+#define MEMMAP_ACPI_TABLES            0x1003
 #define MEMMAP_EFI_RECLAIMABLE        0x2000
 
 struct meminfo {
@@ -48,6 +49,7 @@ void init_memmap(void);
 struct memmap_entry *get_memmap(size_t *entries);
 struct memmap_entry *get_raw_memmap(size_t *entry_count);
 void print_memmap(struct memmap_entry *mm, size_t size);
+uint64_t pmm_check_type(uint64_t addr);
 bool memmap_alloc_range_in(struct memmap_entry *m, size_t *_count,
                            uint64_t base, uint64_t length, uint32_t type, uint32_t overlay_type, bool do_panic, bool simulation, bool new_entry);
 bool memmap_alloc_range(uint64_t base, uint64_t length, uint32_t type, uint32_t overlay_type, bool panic, bool simulation, bool new_entry);
diff --git a/common/mm/pmm.s2.c b/common/mm/pmm.s2.c
index 3bd579db..387e64c9 100644
--- a/common/mm/pmm.s2.c
+++ b/common/mm/pmm.s2.c
@@ -69,6 +69,8 @@ static const char *memmap_type(uint32_t type) {
             return "Usable RAM";
         case MEMMAP_RESERVED:
             return "Reserved";
+        case MEMMAP_ACPI_TABLES:
+            return "ACPI tables";
         case MEMMAP_ACPI_RECLAIMABLE:
             return "ACPI reclaimable";
         case MEMMAP_ACPI_NVS:
@@ -208,9 +210,10 @@ del_mm1:
         m[p] = min_e;
     }
 
-    // Merge contiguous bootloader-reclaimable and usable entries
+    // Merge contiguous bootloader-reclaimable, ACPI tables, usable entries
     for (size_t i = 0; i < count - 1; i++) {
         if (m[i].type != MEMMAP_BOOTLOADER_RECLAIMABLE
+         && m[i].type != MEMMAP_ACPI_TABLES
          && m[i].type != MEMMAP_USABLE)
             continue;
 
@@ -751,6 +754,19 @@ static bool pmm_new_entry(struct memmap_entry *m, size_t *_count,
     return true;
 }
 
+uint64_t pmm_check_type(uint64_t addr) {
+    for (size_t i = 0; i < memmap_entries; i++) {
+        uint64_t entry_base = memmap[i].base;
+        uint64_t entry_top  = memmap[i].base + memmap[i].length;
+
+        if (addr >= entry_base && addr < entry_top) {
+            return memmap[i].type;
+        }
+    }
+
+    return (uint64_t)-1;
+}
+
 bool memmap_alloc_range_in(struct memmap_entry *m, size_t *_count,
                            uint64_t base, uint64_t length, uint32_t type, uint32_t overlay_type, bool do_panic, bool simulation, bool new_entry) {
     size_t count = *_count;
diff --git a/common/protos/limine.c b/common/protos/limine.c
index b606f6ec..3dfb4c7f 100644
--- a/common/protos/limine.c
+++ b/common/protos/limine.c
@@ -50,7 +50,7 @@ static enum executable_format detect_kernel_format(uint8_t *kernel) {
     }
 }
 
-#define SUPPORTED_BASE_REVISION 3
+#define SUPPORTED_BASE_REVISION 4
 
 #define MAX_REQUESTS 128
 
@@ -61,13 +61,13 @@ static int paging_mode;
 static uint64_t get_hhdm_span_top(int base_revision) {
     uint64_t ret = base_revision >= 3 ? 0 : 0x100000000;
     for (size_t i = 0; i < memmap_entries; i++) {
-        if (base_revision >= 1 && base_revision < 3 && (
+        if (((base_revision >= 1 && base_revision < 3) || base_revision >= 4) && (
             memmap[i].type == MEMMAP_RESERVED
          || memmap[i].type == MEMMAP_BAD_MEMORY)) {
             continue;
         }
 
-        if (base_revision >= 3 && (
+        if (base_revision == 3 && (
             memmap[i].type != MEMMAP_USABLE
          && memmap[i].type != MEMMAP_BOOTLOADER_RECLAIMABLE
          && memmap[i].type != MEMMAP_KERNEL_AND_MODULES
@@ -202,13 +202,13 @@ static pagemap_t build_pagemap(int base_revision,
 
     // Map all free memory regions to the higher half direct map offset
     for (size_t i = 0; i < _memmap_entries; i++) {
-        if (base_revision >= 1 && base_revision < 3 && (
+        if (((base_revision >= 1 && base_revision < 3) || base_revision >= 4) && (
             _memmap[i].type == MEMMAP_RESERVED
          || _memmap[i].type == MEMMAP_BAD_MEMORY)) {
             continue;
         }
 
-        if (base_revision >= 3 && (
+        if (base_revision == 3 && (
             _memmap[i].type != MEMMAP_USABLE
          && _memmap[i].type != MEMMAP_BOOTLOADER_RECLAIMABLE
          && _memmap[i].type != MEMMAP_KERNEL_AND_MODULES
@@ -995,7 +995,7 @@ FEAT_START
     struct limine_rsdp_response *rsdp_response =
         ext_mem_alloc(sizeof(struct limine_rsdp_response));
 
-    rsdp_response->address = base_revision <= 2 ? reported_addr(rsdp) : (uintptr_t)rsdp;
+    rsdp_response->address = (base_revision <= 2 || base_revision >= 4) ? reported_addr(rsdp) : (uintptr_t)rsdp;
 
     rsdp_request->response = reported_addr(rsdp_response);
 FEAT_END
@@ -1446,6 +1446,11 @@ FEAT_END
         pmm_sanitise_entries(memmap, &memmap_entries, true);
     }
 
+    if (base_revision >= 4) {
+        acpi_map_tables();
+        pmm_sanitise_entries(memmap, &memmap_entries, true);
+    }
+
     pagemap_t pagemap = {0};
     pagemap = build_pagemap(base_revision, nx_available, ranges, ranges_count,
                             physical_base, virtual_base, direct_map_offset);
@@ -1577,6 +1582,9 @@ FEAT_START
             case MEMMAP_USABLE:
                 _memmap[i].type = LIMINE_MEMMAP_USABLE;
                 break;
+            case MEMMAP_ACPI_TABLES:
+                _memmap[i].type = LIMINE_MEMMAP_ACPI_TABLES;
+                break;
             case MEMMAP_ACPI_RECLAIMABLE:
                 _memmap[i].type = LIMINE_MEMMAP_ACPI_RECLAIMABLE;
                 break;
diff --git a/test/limine.c b/test/limine.c
index d8196e60..5a5b3185 100644
--- a/test/limine.c
+++ b/test/limine.c
@@ -7,7 +7,7 @@
 #include <flanterm_backends/fb.h>
 
 __attribute__((section(".limine_requests")))
-static volatile LIMINE_BASE_REVISION(3);
+static volatile LIMINE_BASE_REVISION(4);
 
 static void limine_main(void);
 
@@ -181,6 +181,8 @@ static char *get_memmap_type(uint64_t type) {
             return "Usable";
         case LIMINE_MEMMAP_RESERVED:
             return "Reserved";
+        case LIMINE_MEMMAP_ACPI_TABLES:
+            return "ACPI tables";
         case LIMINE_MEMMAP_ACPI_RECLAIMABLE:
             return "ACPI reclaimable";
         case LIMINE_MEMMAP_ACPI_NVS:
diff --git a/test/test.mk b/test/test.mk
index 75e503c6..2e02810c 100644
--- a/test/test.mk
+++ b/test/test.mk
@@ -72,7 +72,7 @@ override CFLAGS += \
     -I../flanterm/src \
     -isystem ../freestnd-c-hdrs/include \
     -D_LIMINE_PROTO \
-    -DLIMINE_API_REVISION=3
+    -DLIMINE_API_REVISION=4
 
 ifeq ($(ARCH),x86)
 override CFLAGS += \
tab: 248 wrap: offon