limine: Add terminal request
diff --git a/common/limine.h b/common/limine.h
index 3c318f1c..64cc1168 100644
--- a/common/limine.h
+++ b/common/limine.h
@@ -98,6 +98,27 @@ struct limine_framebuffer_request {
LIMINE_PTR(struct limine_framebuffer_response *) response;
};
+// Terminal
+
+#define LIMINE_TERMINAL_REQUEST { LIMINE_COMMON_MAGIC, 0x0785a0aea5d0750f, 0x1c1936fee0d6cf6e }
+
+typedef void (*limine_terminal_write)(const char *, uint64_t);
+typedef void (*limine_terminal_callback)(uint64_t, uint64_t, uint64_t, uint64_t);
+
+struct limine_terminal_response {
+ uint64_t revision;
+ uint32_t columns;
+ uint32_t rows;
+ LIMINE_PTR(limine_terminal_write) write;
+};
+
+struct limine_terminal_request {
+ uint64_t id[4];
+ uint64_t revision;
+ LIMINE_PTR(struct limine_terminal_response *) response;
+ LIMINE_PTR(limine_terminal_callback) callback;
+};
+
// 5-level paging
#define LIMINE_5_LEVEL_PAGING_REQUEST { LIMINE_COMMON_MAGIC, 0x94469551da9b3192, 0xebe5e86db7382888 }
diff --git a/common/protos/limine.c b/common/protos/limine.c
index b481c7df..e3de994b 100644
--- a/common/protos/limine.c
+++ b/common/protos/limine.c
@@ -102,6 +102,13 @@ static void *_get_request(uint64_t id[4]) {
#define FEAT_START do {
#define FEAT_END } while (0);
+#if defined (__i386__)
+extern symbol stivale2_term_write_entry;
+extern void *stivale2_rt_stack;
+extern uint64_t stivale2_term_callback_ptr;
+void stivale2_term_callback(uint64_t, uint64_t, uint64_t, uint64_t);
+#endif
+
bool limine_load(char *config, char *cmdline) {
uint32_t eax, ebx, ecx, edx;
@@ -409,10 +416,6 @@ FEAT_START
module_request->response = reported_addr(module_response);
FEAT_END
- // Framebuffer feature
-FEAT_START
- term_deinit();
-
size_t req_width = 0, req_height = 0, req_bpp = 0;
char *resolution = config_get_value(config, 0, "RESOLUTION");
@@ -422,10 +425,61 @@ FEAT_START
struct fb_info fb;
+ // Terminal feature
+FEAT_START
+ struct limine_terminal_request *terminal_request = get_request(LIMINE_TERMINAL_REQUEST);
+ if (terminal_request == NULL) {
+ break; // next feature
+ }
+
+ struct limine_terminal_response *terminal_response =
+ ext_mem_alloc(sizeof(struct limine_terminal_response));
+
+ quiet = false;
+ serial = false;
+
+ term_vbe(req_width, req_height);
+
+ if (current_video_mode < 0) {
+ panic(true, "limine: Failed to initialise terminal");
+ }
+
+ fb = fbinfo;
+
+#if defined (__i386__)
+ term_callback = stivale2_term_callback;
+ stivale2_term_callback_ptr = terminal_request->callback;
+#elif defined (__x86_64__)
+ term_callback = (void *)terminal_request->callback;
+#endif
+
+#if defined (__i386__)
+ if (stivale2_rt_stack == NULL) {
+ stivale2_rt_stack = ext_mem_alloc(8192);
+ }
+
+ terminal_response->write = (uintptr_t)(void *)stivale2_term_write_entry;
+#elif defined (__x86_64__)
+ terminal_response->write = (uintptr_t)term_write;
+#endif
+
+ terminal_response->columns = term_cols;
+ terminal_response->rows = term_rows;
+
+ terminal_request->response = reported_addr(terminal_response);
+
+ goto skip_fb_init;
+FEAT_END
+
+ // Framebuffer feature
+FEAT_START
+ term_deinit();
+
if (!fb_init(&fb, req_width, req_height, req_bpp)) {
panic(true, "limine: Could not acquire framebuffer");
}
+skip_fb_init:;
struct limine_framebuffer_request *framebuffer_request = get_request(LIMINE_FRAMEBUFFER_REQUEST);
if (framebuffer_request == NULL) {
break; // next feature
@@ -614,6 +668,11 @@ FEAT_START
memmap_request->response = reported_addr(memmap_response);
FEAT_END
+ // Clear terminal for kernels that will use the stivale2 terminal
+ term_write((uint64_t)(uintptr_t)("\e[2J\e[H"), 7);
+
+ term_runtime = true;
+
stivale_spinup(64, want_5lv, &pagemap, entry_point, 0,
reported_addr(stack), true, (uintptr_t)local_gdt);
diff --git a/test/limine.c b/test/limine.c
index de430d13..99e5aa12 100644
--- a/test/limine.c
+++ b/test/limine.c
@@ -67,6 +67,11 @@ struct limine_smp_request _smp_request = {
.revision = 0, .response = NULL
};
+struct limine_terminal_request _terminal_request = {
+ .id = LIMINE_TERMINAL_REQUEST,
+ .revision = 0, .response = NULL
+};
+
static char *get_memmap_type(uint64_t type) {
switch (type) {
case LIMINE_MEMMAP_USABLE:
@@ -123,6 +128,10 @@ static void print_file_loc(struct limine_file_location *file_location) {
extern char kernel_start[];
static void limine_main(void) {
+ if (_terminal_request.response) {
+ stivale2_print = _terminal_request.response->write;
+ }
+
e9_printf("\nWe're alive");
uint64_t kernel_slide = (uint64_t)kernel_start - 0xffffffff80000000;
@@ -291,5 +300,18 @@ FEAT_START
}
FEAT_END
+FEAT_START
+ e9_printf("");
+ if (_terminal_request.response == NULL) {
+ e9_printf("Terminal not passed");
+ break;
+ }
+ struct limine_terminal_response *term_response = _terminal_request.response;
+ e9_printf("Terminal feature, revision %d", term_response->revision);
+ e9_printf("Columns: %d", term_response->columns);
+ e9_printf("Rows: %d", term_response->rows);
+ e9_printf("Write function at: %x", term_response->write);
+FEAT_END
+
for (;;);
}
