protocols/limine: Add support for requests delimiter

This commit is contained in:
mintsuki 2024-03-13 14:58:56 +01:00
parent f752ac31d8
commit 1d45bf541e
5 changed files with 85 additions and 19 deletions

View File

@ -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*

View File

@ -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;
}

View File

@ -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) };

View File

@ -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:

View File

@ -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