:: commit 1d45bf541e360a7a3ecc9630312cccaca94cf806

mintsuki <mintsuki@protonmail.com> — 2024-03-13 13:58

parents: f752ac31d8

protocols/limine: Add support for requests delimiter

diff --git a/PROTOCOL.md b/PROTOCOL.md
index c32d849e..9d76a29c 100644
--- a/PROTOCOL.md
+++ b/PROTOCOL.md
@@ -79,7 +79,9 @@ struct limine_example_request {
 bootloader will scan for inside the executable file to find requests. Requests
 may be located anywhere inside the executable as long as they are 8-byte
 aligned. There may only be 1 of the same request. The bootloader will refuse
-to boot an executable with multiple of the same request IDs. Alternatively, it is possible to provide a list of requests explicitly via an executable file section. See "Limine Requests Section".
+to boot an executable with multiple of the same request IDs. Alternatively,
+it is possible to provide a list of requests explicitly via an executable file section.
+See "Limine Requests Section". (Note: this is deprecated and removed in base revision 1)
 * `revision` - The revision of the request that the kernel provides. This starts at 0 and is
 bumped whenever new members or functionality are added to the request structure.
 Bootloaders process requests in a backwards compatible manner, *always*. This
@@ -109,6 +111,21 @@ revisions do.
 This is all there is to features. For a list of official Limine features, read
 the "Feature List" section below.
 
+## Requests Delimiter
+
+The bootloader can be told to stop searching for requests (including base
+revision tags) in an executable by placing a set of 2 8-byte values called the
+"requests delimiter" on an 8-byte aligned boundary.
+```c
+#define LIMINE_REQUESTS_DELIMITER \
+    uint64_t limine_requests_delimiter[2] = { 0xadc0e0531bb10d03, 0x9572709f31764c62 };
+```
+
+The requests delimiter is *a hint*. The bootloader can still search for
+requests and base revision tags past this point if it doesn't support the hint.
+When it comes to the Limine bootloader, this means versions starting from 7.1.x
+support it, while older ones do not.
+
 ## Limine Requests Section
 
 Note: *This behaviour is deprecated as of base protocol revision 1*
diff --git a/common/protos/limine.c b/common/protos/limine.c
index b8fed7f2..755a18d0 100644
--- a/common/protos/limine.c
+++ b/common/protos/limine.c
@@ -355,12 +355,19 @@ noreturn void limine_load(char *config, char *cmdline) {
 
     kaslr = kaslr && is_reloc;
 
+    LIMINE_REQUESTS_DELIMITER;
+
     // Determine base revision
-    LIMINE_BASE_REVISION(0)
+    LIMINE_BASE_REVISION(0);
     int base_revision = 0;
     for (size_t i = 0; i < ALIGN_DOWN(image_size_before_bss, 8); i += 8) {
         uint64_t *p = (void *)(uintptr_t)physical_base + i;
 
+        // Check if delimiter hit
+        if (p[0] == limine_requests_delimiter[0] && p[1] == limine_requests_delimiter[1]) {
+            break;
+        }
+
         if (p[0] == limine_base_revision[0] && p[1] == limine_base_revision[1]) {
             if (base_revision != 0) {
                 panic(true, "limine: Duplicated base revision tag");
@@ -393,6 +400,11 @@ noreturn void limine_load(char *config, char *cmdline) {
         for (size_t i = 0; i < ALIGN_DOWN(image_size_before_bss, 8); i += 8) {
             uint64_t *p = (void *)(uintptr_t)physical_base + i;
 
+            // Check if delimiter hit
+            if (p[0] == limine_requests_delimiter[0] && p[1] == limine_requests_delimiter[1]) {
+                break;
+            }
+
             if (p[0] != common_magic[0]) {
                 continue;
             }
diff --git a/limine.h b/limine.h
index 06de8179..9b427656 100644
--- a/limine.h
+++ b/limine.h
@@ -44,6 +44,9 @@ extern "C" {
 #  define LIMINE_DEPRECATED_IGNORE_END
 #endif
 
+#define LIMINE_REQUESTS_DELIMITER \
+    uint64_t limine_requests_delimiter[2] = { 0xadc0e0531bb10d03, 0x9572709f31764c62 };
+
 #define LIMINE_BASE_REVISION(N) \
     uint64_t limine_base_revision[3] = { 0xf9562b2d5c95a6c8, 0x6a7b384944536bdc, (N) };
 
diff --git a/test/limine.c b/test/limine.c
index 910d3b3c..d098a44c 100644
--- a/test/limine.c
+++ b/test/limine.c
@@ -6,38 +6,46 @@
 #include <flanterm/flanterm.h>
 #include <flanterm/backends/fb.h>
 
-LIMINE_BASE_REVISION(1)
+__attribute__((section(".limine_requests")))
+static volatile LIMINE_BASE_REVISION(1);
 
 static void limine_main(void);
 
-struct limine_entry_point_request entry_point_request = {
+__attribute__((used))
+__attribute__((section(".limine_requests")))
+static volatile struct limine_entry_point_request entry_point_request = {
     .id = LIMINE_ENTRY_POINT_REQUEST,
     .revision = 0, .response = NULL,
 
     .entry = limine_main
 };
 
-struct limine_framebuffer_request framebuffer_request = {
+__attribute__((section(".limine_requests")))
+static volatile struct limine_framebuffer_request framebuffer_request = {
     .id = LIMINE_FRAMEBUFFER_REQUEST,
     .revision = 0, .response = NULL
 };
 
-struct limine_bootloader_info_request bootloader_info_request = {
+__attribute__((section(".limine_requests")))
+static volatile struct limine_bootloader_info_request bootloader_info_request = {
     .id = LIMINE_BOOTLOADER_INFO_REQUEST,
     .revision = 0, .response = NULL
 };
 
-struct limine_hhdm_request hhdm_request = {
+__attribute__((section(".limine_requests")))
+static volatile struct limine_hhdm_request hhdm_request = {
     .id = LIMINE_HHDM_REQUEST,
     .revision = 0, .response = NULL
 };
 
-struct limine_memmap_request memmap_request = {
+__attribute__((section(".limine_requests")))
+static volatile struct limine_memmap_request memmap_request = {
     .id = LIMINE_MEMMAP_REQUEST,
     .revision = 0, .response = NULL
 };
 
-struct limine_kernel_file_request kf_request = {
+__attribute__((section(".limine_requests")))
+static volatile struct limine_kernel_file_request kf_request = {
     .id = LIMINE_KERNEL_FILE_REQUEST,
     .revision = 0, .response = NULL
 };
@@ -63,7 +71,8 @@ struct limine_internal_module *internal_modules[] = {
     &internal_module3
 };
 
-struct limine_module_request module_request = {
+__attribute__((section(".limine_requests")))
+static volatile struct limine_module_request module_request = {
     .id = LIMINE_MODULE_REQUEST,
     .revision = 1, .response = NULL,
 
@@ -71,53 +80,66 @@ struct limine_module_request module_request = {
     .internal_modules = internal_modules
 };
 
-struct limine_rsdp_request rsdp_request = {
+__attribute__((section(".limine_requests")))
+static volatile struct limine_rsdp_request rsdp_request = {
     .id = LIMINE_RSDP_REQUEST,
     .revision = 0, .response = NULL
 };
 
-struct limine_smbios_request smbios_request = {
+__attribute__((section(".limine_requests")))
+static volatile struct limine_smbios_request smbios_request = {
     .id = LIMINE_SMBIOS_REQUEST,
     .revision = 0, .response = NULL
 };
 
-struct limine_efi_system_table_request est_request = {
+__attribute__((section(".limine_requests")))
+static volatile struct limine_efi_system_table_request est_request = {
     .id = LIMINE_EFI_SYSTEM_TABLE_REQUEST,
     .revision = 0, .response = NULL
 };
 
-struct limine_efi_memmap_request efi_memmap_request = {
+__attribute__((section(".limine_requests")))
+static volatile struct limine_efi_memmap_request efi_memmap_request = {
     .id = LIMINE_EFI_MEMMAP_REQUEST,
     .revision = 0, .response = NULL
 };
 
-struct limine_boot_time_request boot_time_request = {
+__attribute__((section(".limine_requests")))
+static volatile struct limine_boot_time_request boot_time_request = {
     .id = LIMINE_BOOT_TIME_REQUEST,
     .revision = 0, .response = NULL
 };
 
-struct limine_kernel_address_request kernel_address_request = {
+__attribute__((section(".limine_requests")))
+static volatile struct limine_kernel_address_request kernel_address_request = {
     .id = LIMINE_KERNEL_ADDRESS_REQUEST,
     .revision = 0, .response = NULL
 };
 
-struct limine_smp_request _smp_request = {
+__attribute__((section(".limine_requests")))
+static volatile struct limine_smp_request _smp_request = {
     .id = LIMINE_SMP_REQUEST,
     .revision = 0, .response = NULL
 };
 
-struct limine_dtb_request _dtb_request = {
+__attribute__((section(".limine_requests")))
+static volatile struct limine_dtb_request _dtb_request = {
     .id = LIMINE_DTB_REQUEST,
     .revision = 0, .response = NULL
 };
 
-struct limine_paging_mode_request _pm_request = {
+__attribute__((section(".limine_requests")))
+static volatile struct limine_paging_mode_request _pm_request = {
     .id = LIMINE_PAGING_MODE_REQUEST,
     .revision = 0, .response = NULL,
     .mode = LIMINE_PAGING_MODE_DEFAULT,
     .flags = 0,
 };
 
+__attribute__((used))
+__attribute__((section(".limine_requests_delimiter")))
+static volatile LIMINE_REQUESTS_DELIMITER;
+
 static char *get_memmap_type(uint64_t type) {
     switch (type) {
         case LIMINE_MEMMAP_USABLE:
diff --git a/test/linker.ld b/test/linker.ld
index 676d88a3..6c4377d6 100644
--- a/test/linker.ld
+++ b/test/linker.ld
@@ -1,5 +1,7 @@
 PHDRS
 {
+    limine_requests PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */
+
     text    PT_LOAD    FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */
     rodata  PT_LOAD    FLAGS((1 << 2)) ;            /* Read only */
     data    PT_LOAD    FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */
@@ -11,6 +13,16 @@ SECTIONS
     . = 0xffffffff80000000;
     kernel_start = .;
 
+    .limine_requests : {
+        *(.limine_requests .limine_requests.*)
+    } :limine_requests
+
+    .limine_requests_delimiter : {
+        *(.limine_requests_delimiter .limine_requests_delimiter.*)
+    } :limine_requests
+
+    . += 0x1000;
+
     .text : {
         *(.text .text.*)
     } :text
tab: 248 wrap: offon