limine: Rework request-response system
diff --git a/common/limine.h b/common/limine.h
index d727094c..4d7f612d 100644
--- a/common/limine.h
+++ b/common/limine.h
@@ -9,58 +9,58 @@
# define LIMINE_PTR(TYPE) TYPE
#endif
-#define LIMINE_MAGIC { 0xc7b1dd30df4c8b88, 0x0a82e883a194f07b }
-
-struct limine_header {
- uint64_t magic[2];
- LIMINE_PTR(void *) entry;
- uint64_t features_count;
- LIMINE_PTR(void *) features;
-};
+#define LIMINE_COMMON_MAGIC 0xc7b1dd30df4c8b88, 0x0a82e883a194f07b
// Boot info
-#define LIMINE_BOOT_INFO_REQUEST ((LIMINE_PTR(void *)) 1 )
+#define LIMINE_BOOT_INFO_REQUEST { LIMINE_COMMON_MAGIC, 0xf55038d8e2a1202f, 0x279426fcf5f59740 }
struct limine_boot_info_response {
uint64_t flags;
LIMINE_PTR(char *) loader;
};
+struct limine_boot_info_request {
+ uint64_t id[4];
+ uint64_t flags;
+ LIMINE_PTR(struct limine_boot_info_response *) response;
+};
+
// Framebuffer
-#define LIMINE_FRAMEBUFFER_REQUEST ((LIMINE_PTR(void *)) 2 )
+#define LIMINE_FRAMEBUFFER_REQUEST { LIMINE_COMMON_MAGIC, 0xcbfe81d7dd2d1977, 0x063150319ebc9b71 }
-struct limine_framebuffer_request {
- LIMINE_PTR(void *) id;
+struct limine_framebuffer_response {
+ uint64_t flags;
+};
#define LIMINE_FRAMEBUFFER_PREFER_LFB 0
#define LIMINE_FRAMEBUFFER_PREFER_TEXT 1
#define LIMINE_FRAMEBUFFER_ENFORCE_PREFER (1 << 8)
- uint64_t flags;
- uint16_t width;
- uint16_t height;
- uint16_t bpp;
-
- uint16_t unused;
+struct limine_framebuffer_request {
+ uint64_t id[4];
+ uint64_t flags;
+ LIMINE_PTR(struct limine_framebuffer_response *) response;
};
// 5-level paging
-#define LIMINE_5_LEVEL_PAGING_REQUEST ((LIMINE_PTR(void *)) 3 )
+#define LIMINE_5_LEVEL_PAGING_REQUEST { LIMINE_COMMON_MAGIC, 0x94469551da9b3192, 0xebe5e86db7382888 }
struct limine_5_level_paging_response {
uint64_t flags;
};
-// PMRs
-
-#define LIMINE_PMR_REQUEST ((LIMINE_PTR(void *)) 4 )
+struct limine_5_level_paging_request {
+ uint64_t id[4];
+ uint64_t flags;
+ LIMINE_PTR(struct limine_5_level_paging_response *) response;
+};
// Memory map
-#define LIMINE_MEMMAP_REQUEST ((LIMINE_PTR(void *)) 5 )
+#define LIMINE_MEMMAP_REQUEST { LIMINE_COMMON_MAGIC, 0x67cf3d9d378a806f, 0xe304acdfc50c3c62 }
#define LIMINE_MEMMAP_USABLE 0
#define LIMINE_MEMMAP_RESERVED 1
@@ -84,4 +84,26 @@ struct limine_memmap_response {
LIMINE_PTR(struct limine_memmap_entry *) entries;
};
+struct limine_memmap_request {
+ uint64_t id[4];
+ uint64_t flags;
+ LIMINE_PTR(struct limine_memmap_response *) response;
+};
+
+// Entry point
+
+#define LIMINE_ENTRY_POINT_REQUEST { LIMINE_COMMON_MAGIC, 0x13d86c035a1cd3e1, 0x2b0caa89d8f3026a }
+
+struct limine_entry_point_response {
+ uint64_t flags;
+};
+
+struct limine_entry_point_request {
+ uint64_t id[4];
+ uint64_t flags;
+ LIMINE_PTR(struct limine_entry_point_response *) response;
+
+ LIMINE_PTR(void *) entry;
+};
+
#endif
diff --git a/common/protos/limine.c b/common/protos/limine.c
index 99667318..baa5e891 100644
--- a/common/protos/limine.c
+++ b/common/protos/limine.c
@@ -32,50 +32,41 @@
#include <protos/limine.h>
#include <limine.h>
-static uint64_t features_count, physical_base, virtual_base, slide, direct_map_offset;
-static uint64_t *features, *features_orig;
+#define MAX_REQUESTS 128
+
+static uint64_t physical_base, virtual_base, slide, direct_map_offset;
+static size_t requests_count;
+static void *requests[MAX_REQUESTS];
static uint64_t reported_addr(void *addr) {
return (uint64_t)(uintptr_t)addr + direct_map_offset;
}
+/*
static uintptr_t get_phys_addr(uint64_t addr) {
return physical_base + (addr - virtual_base);
}
+*/
+
+static void *_get_request(uint64_t id[4]) {
+ for (size_t i = 0; i < requests_count; i++) {
+ uint64_t *p = requests[i];
-struct feature {
- bool found;
- size_t index;
- void *request;
-};
-
-static struct feature get_feature(uint64_t id) {
- for (size_t i = 0; i < features_count; i++) {
- if (features[i] < 0xffffffff80000000 && features[i] == id) {
- return (struct feature){
- .found = true,
- .index = i,
- .request = NULL
- };
- } else {
- uint64_t *id_ptr = (void *)get_phys_addr(features[i] + slide);
- if (*id_ptr == id) {
- return (struct feature){
- .found = true,
- .index = i,
- .request = (void *)id_ptr
- };
- }
+ if (p[2] != id[2]) {
+ continue;
+ }
+ if (p[3] != id[3]) {
+ continue;
}
+
+ return p;
}
- return (struct feature){
- .found = false,
- .index = 0,
- .request = NULL
- };
+ return NULL;
}
+#define get_request(REQ) _get_request((uint64_t[4])REQ)
+
#define FEAT_START do {
#define FEAT_END } while (0);
@@ -88,8 +79,6 @@ bool limine_load(char *config, char *cmdline) {
if (kernel_path == NULL)
panic(true, "limine: KERNEL_PATH not specified");
- print("limine: Loading kernel `%s`...\n", kernel_path);
-
struct file_handle *kernel_file;
if ((kernel_file = uri_open(kernel_path)) == NULL)
panic(true, "limine: Failed to open kernel with path `%s`. Is the path correct?", kernel_path);
@@ -102,26 +91,6 @@ bool limine_load(char *config, char *cmdline) {
fclose(kernel_file);
- // Search for header
- struct limine_header *limine_header = NULL;
- uint64_t limine_magic[2] = LIMINE_MAGIC;
- for (size_t i = 0; i < kernel_file_size; i += 16) {
- if (memcmp(kernel + i, limine_magic, 16) == 0) {
- limine_header = (void *)(kernel + i);
- }
- }
-
- if (limine_header == NULL) {
- panic(true, "limine: Magic number not found");
- }
-
- printv("limine: Header found at %p\n", (size_t)limine_header - (size_t)kernel);
-
- // Check if 64 bit CPU
- if (!cpuid(0x80000001, 0, &eax, &ebx, &ecx, &edx) || !(edx & (1 << 29))) {
- panic(true, "limine: This CPU does not support 64-bit mode.");
- }
-
char *kaslr_s = config_get_value(config, 0, "KASLR");
bool kaslr = true;
if (kaslr_s != NULL && strcmp(kaslr_s, "no") == 0)
@@ -130,9 +99,11 @@ bool limine_load(char *config, char *cmdline) {
int bits = elf_bits(kernel);
if (bits == -1 || bits == 32) {
- panic(true, "limine: Kernel in unrecognised format");
+ printv("limine: Kernel in unrecognised format");
+ return false;
}
+ // ELF loading
uint64_t entry_point = 0;
struct elf_range *ranges;
uint64_t ranges_count;
@@ -141,32 +112,45 @@ bool limine_load(char *config, char *cmdline) {
MEMMAP_KERNEL_AND_MODULES, kaslr, false,
&ranges, &ranges_count,
true, &physical_base, &virtual_base)) {
- panic(true, "limine: ELF64 load failure");
+ return false;
}
- if (limine_header->entry != 0) {
- entry_point = limine_header->entry + slide;
- }
+ // Load requests
+ requests_count = 0;
+ uint64_t common_magic[2] = { LIMINE_COMMON_MAGIC };
+ for (size_t i = 0; i < ALIGN_DOWN(kernel_file_size, 8); i += 8) {
+ uint64_t *p = (void *)(uintptr_t)physical_base + i;
- printv("limine: Physical base: %X\n", physical_base);
- printv("limine: Virtual base: %X\n", virtual_base);
- printv("limine: Slide: %X\n", slide);
- printv("limine: Entry point: %X\n", entry_point);
+ if (p[0] != common_magic[0]) {
+ continue;
+ }
+ if (p[1] != common_magic[1]) {
+ continue;
+ }
- // Prepare features
+ if (requests_count == MAX_REQUESTS) {
+ panic(true, "limine: Maximum requests exceeded");
+ }
- features_count = limine_header->features_count;
- features_orig = (void *)get_phys_addr(limine_header->features + slide);
+ requests[requests_count++] = p;
+ }
- features = ext_mem_alloc(features_count * sizeof(uint64_t));
- memcpy(features, features_orig, features_count * sizeof(uint64_t));
+ if (requests_count == 0) {
+ return false;
+ }
- for (size_t i = 0; i < features_count; i++) {
- features_orig[i] = 0;
+ // Check if 64 bit CPU
+ if (!cpuid(0x80000001, 0, &eax, &ebx, &ecx, &edx) || !(edx & (1 << 29))) {
+ panic(true, "limine: This CPU does not support 64-bit mode.");
}
- printv("limine: Features count: %U\n", features_count);
- printv("limine: Features list at %X (%p)\n", limine_header->features, features_orig);
+ print("limine: Loading kernel `%s`...\n", kernel_path);
+
+ printv("limine: Physical base: %X\n", physical_base);
+ printv("limine: Virtual base: %X\n", virtual_base);
+ printv("limine: Slide: %X\n", slide);
+ printv("limine: ELF entry point: %X\n", entry_point);
+ printv("limine: Requests count: %u\n", requests_count);
// 5 level paging feature & HHDM slide
bool want_5lv;
@@ -178,8 +162,8 @@ FEAT_START
level5pg = true;
}
- struct feature lv5pg_feat = get_feature(LIMINE_5_LEVEL_PAGING_REQUEST);
- want_5lv = lv5pg_feat.found && level5pg;
+ struct limine_5_level_paging_request *lv5pg_request = get_request(LIMINE_5_LEVEL_PAGING_REQUEST);
+ want_5lv = lv5pg_request != NULL && level5pg;
direct_map_offset = want_5lv ? 0xff00000000000000 : 0xffff800000000000;
@@ -189,14 +173,31 @@ FEAT_START
if (want_5lv) {
void *lv5pg_response = ext_mem_alloc(sizeof(struct limine_5_level_paging_response));
- features_orig[lv5pg_feat.index] = reported_addr(lv5pg_response);
+ lv5pg_request->response = reported_addr(lv5pg_response);
+ }
+FEAT_END
+
+ // Entry point feature
+FEAT_START
+ struct limine_entry_point_request *entrypoint_request = get_request(LIMINE_ENTRY_POINT_REQUEST);
+ if (entrypoint_request == NULL) {
+ break;
}
+
+ entry_point = entrypoint_request->entry;
+
+ print("limine: Entry point at %X\n", entry_point);
+
+ struct limine_entry_point_response *entrypoint_response =
+ ext_mem_alloc(sizeof(struct limine_entry_point_response));
+
+ entrypoint_request->response = reported_addr(entrypoint_response);
FEAT_END
// Boot info feature
FEAT_START
- struct feature boot_info_feat = get_feature(LIMINE_BOOT_INFO_REQUEST);
- if (boot_info_feat.found == false) {
+ struct limine_boot_info_request *boot_info_request = get_request(LIMINE_BOOT_INFO_REQUEST);
+ if (boot_info_request == NULL) {
break; // next feature
}
@@ -205,7 +206,7 @@ FEAT_START
boot_info_response->loader = reported_addr("Limine " LIMINE_VERSION);
- features_orig[boot_info_feat.index] = reported_addr(boot_info_response);
+ boot_info_request->response = reported_addr(boot_info_response);
FEAT_END
// Framebuffer feature
@@ -234,17 +235,17 @@ FEAT_END
// Memmap
FEAT_START
- struct feature memmap_feat = get_feature(LIMINE_MEMMAP_REQUEST);
+ struct limine_memmap_request *memmap_request = get_request(LIMINE_MEMMAP_REQUEST);
struct limine_memmap_response *memmap_response;
- if (memmap_feat.found == true) {
+ if (memmap_request != NULL) {
memmap_response = ext_mem_alloc(sizeof(struct limine_memmap_response));
}
size_t mmap_entries;
struct e820_entry_t *mmap = get_memmap(&mmap_entries);
- if (memmap_feat.found == false) {
+ if (memmap_request == NULL) {
break; // next feature
}
@@ -281,7 +282,7 @@ FEAT_START
memmap_response->entries_count = mmap_entries;
memmap_response->entries = reported_addr(mmap);
- features_orig[memmap_feat.index] = reported_addr(memmap_response);
+ memmap_request->response = reported_addr(memmap_response);
FEAT_END
// Final wrap-up
diff --git a/test/limine.c b/test/limine.c
index 1cb37b88..dec6ed44 100644
--- a/test/limine.c
+++ b/test/limine.c
@@ -3,30 +3,33 @@
#include <limine.h>
#include <e9print.h>
+static void limine_main(void);
+
+__attribute__((used))
static struct limine_framebuffer_request framebuffer_request = {
.id = LIMINE_FRAMEBUFFER_REQUEST,
-
.flags = LIMINE_FRAMEBUFFER_PREFER_LFB | LIMINE_FRAMEBUFFER_ENFORCE_PREFER,
-
- .height = 0, .width = 0, .bpp = 0
+ .response = NULL
};
-static void *features_array[] = {
- LIMINE_BOOT_INFO_REQUEST,
- &framebuffer_request,
- LIMINE_MEMMAP_REQUEST,
- LIMINE_5_LEVEL_PAGING_REQUEST,
- LIMINE_PMR_REQUEST
+__attribute__((used))
+static struct limine_entry_point_request entry_point_request = {
+ .id = LIMINE_ENTRY_POINT_REQUEST,
+ .flags = 0, .response = NULL,
+
+ .entry = limine_main
};
-static void limine_main(void);
+__attribute__((used))
+static struct limine_boot_info_request boot_info_request = {
+ .id = LIMINE_BOOT_INFO_REQUEST,
+ .flags = 0, .response = NULL
+};
-__attribute__((used, aligned(16)))
-static struct limine_header limine_header = {
- .magic = LIMINE_MAGIC,
- .entry = limine_main,
- .features_count = sizeof(features_array) / sizeof(void *),
- .features = features_array
+__attribute__((used))
+static struct limine_memmap_request memmap_request = {
+ .id = LIMINE_MEMMAP_REQUEST,
+ .flags = 0, .response = NULL
};
static char *get_memmap_type(uint64_t type) {
@@ -59,21 +62,21 @@ static void limine_main(void) {
e9_printf("We're alive");
FEAT_START
- if (features_array[0] == NULL) {
+ if (boot_info_request.response == NULL) {
e9_printf("Boot info not passed");
break;
}
- struct limine_boot_info_response *boot_info_response = features_array[0];
+ struct limine_boot_info_response *boot_info_response = boot_info_request.response;
e9_printf("Boot info response:");
e9_printf("Bootloader name: %s", boot_info_response->loader);
FEAT_END
FEAT_START
- if (features_array[2] == NULL) {
+ if (memmap_request.response == NULL) {
e9_printf("Memory map not passed");
break;
}
- struct limine_memmap_response *memmap_response = features_array[2];
+ struct limine_memmap_response *memmap_response = memmap_request.response;
e9_printf("%d memory map entries", memmap_response->entries_count);
for (size_t i = 0; i < memmap_response->entries_count; i++) {
struct limine_memmap_entry *e = &memmap_response->entries[i];
