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
