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 #include #include +#include // 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 __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 += \