:: commit 5f525a10525f4311d8fc5b551ed4c988dd84fcb0

mintsuki <mintsuki@protonmail.com> — 2022-04-02 08:05

parents: c052509567

limine: Change terminal write contract

diff --git a/PROTOCOL.md b/PROTOCOL.md
index 0a79d272..ce9ed30f 100644
--- a/PROTOCOL.md
+++ b/PROTOCOL.md
@@ -322,34 +322,38 @@ struct limine_terminal_request {
 
 Response:
 ```c
+typedef void (*limine_terminal_write)(struct limine_terminal *terminal, const char *string, uint64_t length);
+
 struct limine_terminal_response {
     uint64_t revision;
     uint64_t terminal_count;
     struct limine_terminal **terminals;
+    limine_terminal_write write;
 };
 ```
 
 * `terminal_count` - How many terminals are present.
 * `terminals` - Pointer to an array of `terminal_count` pointers to
 `struct limine_terminal` structures.
+* `write` - Physical pointer to the terminal write() function.
+The function is not thread-safe, nor reentrant, per-terminal.
+This means multiple terminals may be called simultaneously, and multiple
+callbacks may be handled simultaneously.
+The `terminal` parameter points to the `struct limine_terminal` structure to
+use to output the string; the `string` parameter points to a
+string to print; the `length` paremeter contains the length, in bytes, of the
+string to print.
 
 ```c
-typedef void (*limine_terminal_write)(const char *, uint64_t);
-
 struct limine_terminal {
     uint32_t columns;
     uint32_t rows;
     struct limine_framebuffer *framebuffer;
-    limine_terminal_write write;
 };
 ```
 
 * `columns` and `rows` - Columns and rows provided by the terminal.
 * `framebuffer` - The framebuffer associated with this terminal.
-* `write` - Physical pointer to the terminal write() function.
-The function is not thread-safe, nor reentrant, per-terminal.
-This means multiple terminals may be called simultaneously, and multiple
-callbacks may be handled simultaneously.
 
 Note: Omitting this request will cause the bootloader to not initialise
 the terminal service.
@@ -373,7 +377,7 @@ void callback(struct limine_terminal *terminal, uint64_t type, uint64_t, uint64_
 ```
 
 The `terminal` argument is a pointer to the Limine terminal structure which
-has the `write()` call that caused the callback.
+represents the terminal that caused the callback.
 
 The purpose of the last 3 arguments changes depending on the `type` argument.
 
diff --git a/common/protos/limine.c b/common/protos/limine.c
index 0cd99fda..c5b6e134 100644
--- a/common/protos/limine.c
+++ b/common/protos/limine.c
@@ -108,9 +108,15 @@ static void *_get_request(uint64_t id[4]) {
 extern symbol stivale2_term_write_entry;
 extern void *stivale2_rt_stack;
 extern uint64_t stivale2_term_callback_ptr;
+extern uint64_t stivale2_term_write_ptr;
 void stivale2_term_callback(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
 #endif
 
+static void term_write_shim(uint64_t context, uint64_t buf, uint64_t count) {
+    (void)context;
+    term_write(buf, count);
+}
+
 bool limine_load(char *config, char *cmdline) {
     uint32_t eax, ebx, ecx, edx;
 
@@ -589,9 +595,10 @@ FEAT_START
         stivale2_rt_stack = ext_mem_alloc(16384) + 16384;
     }
 
-    terminal->write = (uintptr_t)(void *)stivale2_term_write_entry;
+    stivale2_term_write_ptr = (uintptr_t)term_write_shim;
+    terminal_response->write = (uintptr_t)(void *)stivale2_term_write_entry;
 #elif defined (__x86_64__)
-    terminal->write = (uintptr_t)term_write;
+    terminal_response->write = (uintptr_t)term_write_shim;
 #endif
 
     term_fb_ptr = &terminal->framebuffer;
diff --git a/common/protos/stivale2.c b/common/protos/stivale2.c
index 7fc8c3b8..26161e22 100644
--- a/common/protos/stivale2.c
+++ b/common/protos/stivale2.c
@@ -73,6 +73,7 @@
 extern symbol stivale2_term_write_entry;
 void *stivale2_rt_stack = NULL;
 uint64_t stivale2_term_callback_ptr = 0;
+uint64_t stivale2_term_write_ptr = 0;
 void stivale2_term_callback(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
 #endif
 
@@ -574,6 +575,7 @@ failed_to_load_header_section:
             stivale2_rt_stack = ext_mem_alloc(8192) + 8192;
         }
 
+        stivale2_term_write_ptr = (uintptr_t)term_write;
         tag->term_write = (uintptr_t)(void *)stivale2_term_write_entry;
 #elif defined (__x86_64__)
         tag->term_write = (uintptr_t)term_write;
diff --git a/common/protos/stivale2_rt.asm32u b/common/protos/stivale2_rt.asm32u
index a318f917..43222cfe 100644
--- a/common/protos/stivale2_rt.asm32u
+++ b/common/protos/stivale2_rt.asm32u
@@ -15,6 +15,7 @@ section .text
 extern term_write
 extern stivale2_rt_stack
 extern stivale2_term_callback_ptr
+extern stivale2_term_write_ptr
 
 global stivale2_term_callback
 stivale2_term_callback:
@@ -98,6 +99,7 @@ stivale2_term_write_entry:
     mov word [rbx + user_es wrt ..gotoff], es
     mov word [rbx + user_ss wrt ..gotoff], ss
 
+    push rdx
     push rsi
     push rdi
 
@@ -113,8 +115,8 @@ bits 32
     mov es, ax
     mov ss, ax
 
-    call term_write
-    add esp, 16
+    call [ebx + stivale2_term_write_ptr wrt ..gotoff]
+    add esp, 24
 
     push dword [ebx + user_cs wrt ..gotoff]
     call .p2
diff --git a/common/protos/stivale2_rt.asmb b/common/protos/stivale2_rt.asmb
index 3f159c53..e979e6ef 100644
--- a/common/protos/stivale2_rt.asmb
+++ b/common/protos/stivale2_rt.asmb
@@ -13,6 +13,7 @@ section .text
 extern term_write
 extern stivale2_rt_stack
 extern stivale2_term_callback_ptr
+extern stivale2_term_write_ptr
 
 global stivale2_term_callback
 stivale2_term_callback:
@@ -82,6 +83,7 @@ bits 64
     mov word [user_es], es
     mov word [user_ss], ss
 
+    push rdx
     push rsi
     push rdi
 
@@ -95,8 +97,8 @@ bits 32
     mov es, ax
     mov ss, ax
 
-    call term_write
-    add esp, 16
+    call [stivale2_term_write_ptr]
+    add esp, 24
 
     push dword [user_cs]
     push .mode64
diff --git a/limine.h b/limine.h
index 5ad7b182..8136b3da 100644
--- a/limine.h
+++ b/limine.h
@@ -171,20 +171,20 @@ struct limine_framebuffer_request {
 
 struct limine_terminal;
 
-typedef void (*limine_terminal_write)(const char *, uint64_t);
+typedef void (*limine_terminal_write)(struct limine_terminal *, const char *, uint64_t);
 typedef void (*limine_terminal_callback)(struct limine_terminal *, uint64_t, uint64_t, uint64_t, uint64_t);
 
 struct limine_terminal {
     uint32_t columns;
     uint32_t rows;
     LIMINE_PTR(struct limine_framebuffer *) framebuffer;
-    LIMINE_PTR(limine_terminal_write) write;
 };
 
 struct limine_terminal_response {
     uint64_t revision;
     uint64_t terminal_count;
     LIMINE_PTR(struct limine_terminal **) terminals;
+    LIMINE_PTR(limine_terminal_write) write;
 };
 
 struct limine_terminal_request {
diff --git a/test/limine.c b/test/limine.c
index ecdfc6a5..e809ca00 100644
--- a/test/limine.c
+++ b/test/limine.c
@@ -136,9 +136,15 @@ static void print_file(struct limine_file *file) {
 
 extern char kernel_start[];
 
+static void write_shim(const char *s, uint64_t l) {
+    struct limine_terminal *terminal = _terminal_request.response->terminals[0];
+
+    _terminal_request.response->write(terminal, s, l);
+}
+
 static void limine_main(void) {
     if (_terminal_request.response) {
-        stivale2_print = _terminal_request.response->terminals[0]->write;
+        stivale2_print = write_shim;
     }
 
     e9_printf("\nWe're alive");
@@ -329,8 +335,8 @@ FEAT_START
         e9_printf("Columns: %d", terminal->columns);
         e9_printf("Rows: %d", terminal->rows);
         e9_printf("Using framebuffer: %x", terminal->framebuffer);
-        e9_printf("Write function at: %x", terminal->write);
     }
+    e9_printf("Write function at: %x", term_response->write);
 FEAT_END
 
     for (;;);
tab: 248 wrap: offon