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 += \
