:: commit c132903b7f009ed713f51726560ab2f2ba43dcef

mintsuki <mintsuki@protonmail.com> — 2023-01-20 19:14

parents: e6cc9c9b21

term: Expose support for out-of-band output control

diff --git a/PROTOCOL.md b/PROTOCOL.md
index ab792984..1770c79d 100644
--- a/PROTOCOL.md
+++ b/PROTOCOL.md
@@ -444,10 +444,14 @@ context, and refresh the terminal fully.
 In order to achieve this, special values for the `length` argument are
 passed. These values are:
 ```c
+/* Response revision 0 */
 #define LIMINE_TERMINAL_CTX_SIZE ((uint64_t)(-1))
 #define LIMINE_TERMINAL_CTX_SAVE ((uint64_t)(-2))
 #define LIMINE_TERMINAL_CTX_RESTORE ((uint64_t)(-3))
 #define LIMINE_TERMINAL_FULL_REFRESH ((uint64_t)(-4))
+/* Response revision 1 */
+#define LIMINE_TERMINAL_OOB_OUTPUT_GET ((uint64_t)(-10))
+#define LIMINE_TERMINAL_OOB_OUTPUT_SET ((uint64_t)(-11))
 ```
 
 For `CTX_SIZE`, the `ptr` variable has to point to a location to which the
@@ -464,6 +468,25 @@ For `FULL_REFRESH`, the `ptr` variable is unused. This routine is to be used
 after control of the framebuffer is taken over and the bootloader's terminal
 has to *fully* repaint the framebuffer to avoid inconsistencies.
 
+If the response revision is equal or greater than 1
+`OOB_OUTPUT_GET` and `OOB_OUTPUT_SET` allow getting and setting the
+out-of-band terminal output settings. `ptr` points to a location to where
+the terminal will *write* or *read* a single `uint64_t` value containing the
+bits representing the settings.
+The possible settings are as follows:
+```c
+#define LIMINE_TERMINAL_OOB_OUTPUT_OCRNL (1 << 0)
+#define LIMINE_TERMINAL_OOB_OUTPUT_OFDEL (1 << 1)
+#define LIMINE_TERMINAL_OOB_OUTPUT_OFILL (1 << 2)
+#define LIMINE_TERMINAL_OOB_OUTPUT_OLCUC (1 << 3)
+#define LIMINE_TERMINAL_OOB_OUTPUT_ONLCR (1 << 4)
+#define LIMINE_TERMINAL_OOB_OUTPUT_ONLRET (1 << 5)
+#define LIMINE_TERMINAL_OOB_OUTPUT_ONOCR (1 << 6)
+#define LIMINE_TERMINAL_OOB_OUTPUT_OPOST (1 << 7)
+```
+The effect of each of these options matches the effect of the `stty(1)`
+options by the same name.
+
 #### x86_64
 
 Additionally, the kernel must ensure, when calling `write()`, that:
diff --git a/common/lib/term.c b/common/lib/term.c
index ad121e83..e0d802e5 100644
--- a/common/lib/term.c
+++ b/common/lib/term.c
@@ -351,6 +351,14 @@ static void context_restore(uint64_t buf) {
 
 void _term_write(uint64_t buf, uint64_t count) {
     switch (count) {
+        case TERM_OOB_OUTPUT_GET: {
+            memcpy32to64(buf, (uint64_t)(uintptr_t)&term->oob_output, sizeof(uint64_t));
+            return;
+        }
+        case TERM_OOB_OUTPUT_SET: {
+            memcpy32to64((uint64_t)(uintptr_t)&term->oob_output, buf, sizeof(uint64_t));
+            return;
+        }
         case TERM_CTX_SIZE: {
             uint64_t ret = context_size();
             memcpy32to64(buf, (uint64_t)(uintptr_t)&ret, sizeof(uint64_t));
diff --git a/common/lib/term.h b/common/lib/term.h
index fd8c4238..d9bc2553 100644
--- a/common/lib/term.h
+++ b/common/lib/term.h
@@ -22,6 +22,8 @@ extern struct term_context *term;
 #define TERM_CTX_SAVE ((uint64_t)(-2))
 #define TERM_CTX_RESTORE ((uint64_t)(-3))
 #define TERM_FULL_REFRESH ((uint64_t)(-4))
+#define TERM_OOB_OUTPUT_GET ((uint64_t)(-10))
+#define TERM_OOB_OUTPUT_SET ((uint64_t)(-11))
 
 inline void reset_term(void) {
     term->autoflush = true;
diff --git a/common/protos/limine.c b/common/protos/limine.c
index c81d5eb9..6aee412d 100644
--- a/common/protos/limine.c
+++ b/common/protos/limine.c
@@ -687,6 +687,8 @@ FEAT_START
     struct limine_terminal_response *terminal_response =
         ext_mem_alloc(sizeof(struct limine_terminal_response));
 
+    terminal_response->revision = 1;
+
     struct limine_terminal *terminal = ext_mem_alloc(sizeof(struct limine_terminal));
 
     quiet = false;
diff --git a/limine.h b/limine.h
index 62f78616..365de87e 100644
--- a/limine.h
+++ b/limine.h
@@ -143,7 +143,7 @@ struct limine_framebuffer {
     uint8_t unused[7];
     uint64_t edid_size;
     LIMINE_PTR(void *) edid;
-    /* Revision 1 */
+    /* Response revision 1 */
     uint64_t mode_count;
     LIMINE_PTR(struct limine_video_mode **) modes;
 };
@@ -178,6 +178,19 @@ struct limine_framebuffer_request {
 #define LIMINE_TERMINAL_CTX_RESTORE ((uint64_t)(-3))
 #define LIMINE_TERMINAL_FULL_REFRESH ((uint64_t)(-4))
 
+/* Response revision 1 */
+#define LIMINE_TERMINAL_OOB_OUTPUT_GET ((uint64_t)(-10))
+#define LIMINE_TERMINAL_OOB_OUTPUT_SET ((uint64_t)(-11))
+
+#define LIMINE_TERMINAL_OOB_OUTPUT_OCRNL (1 << 0)
+#define LIMINE_TERMINAL_OOB_OUTPUT_OFDEL (1 << 1)
+#define LIMINE_TERMINAL_OOB_OUTPUT_OFILL (1 << 2)
+#define LIMINE_TERMINAL_OOB_OUTPUT_OLCUC (1 << 3)
+#define LIMINE_TERMINAL_OOB_OUTPUT_ONLCR (1 << 4)
+#define LIMINE_TERMINAL_OOB_OUTPUT_ONLRET (1 << 5)
+#define LIMINE_TERMINAL_OOB_OUTPUT_ONOCR (1 << 6)
+#define LIMINE_TERMINAL_OOB_OUTPUT_OPOST (1 << 7)
+
 struct limine_terminal;
 
 typedef void (*limine_terminal_write)(struct limine_terminal *, const char *, uint64_t);
tab: 248 wrap: offon