From c0fd295cf44dd482996390f9d489787e12003c99 Mon Sep 17 00:00:00 2001 From: mintsuki Date: Thu, 8 Feb 2024 09:30:59 +0100 Subject: [PATCH] serial: Add baudrate setting for BIOS Co-authored-by: Bryce Lanham --- CONFIG.md | 1 + common/drivers/{serial.s2.c => serial.c} | 17 +++++++++++++++-- common/lib/print.s2.c | 2 +- common/linker_bios.ld.in | 1 + 4 files changed, 18 insertions(+), 3 deletions(-) rename common/drivers/{serial.s2.c => serial.c} (62%) diff --git a/CONFIG.md b/CONFIG.md index 0652673c..85675598 100644 --- a/CONFIG.md +++ b/CONFIG.md @@ -59,6 +59,7 @@ Miscellaneous: * `TIMEOUT` - Specifies the timeout in seconds before the first *entry* is automatically booted. If set to `no`, disable automatic boot. If set to `0`, boots default entry instantly (see `DEFAULT_ENTRY` key). * `QUIET` - If set to `yes`, enable quiet mode, where all screen output except panics and important warnings is suppressed. If `TIMEOUT` is not 0, the `TIMEOUT` still occurs, and pressing any key during the timeout will reveal the menu and disable quiet mode. * `SERIAL` - If set to `yes`, enable serial I/O for the bootloader. +* `SERIAL_BAUDRATE` - If `SERIAL` is set to `yes`, this specifies the baudrate to use for serial I/O. Defaults to `9600`. BIOS only, ignored with Limine UEFI. * `DEFAULT_ENTRY` - 1-based entry index of the entry which will be automatically selected at startup. If unspecified, it is `1`. * `GRAPHICS` - If set to `no`, force CGA text mode for the boot menu, else use a video mode. Ignored with Limine UEFI. * `VERBOSE` - If set to `yes`, print additional information during boot. Defaults to not verbose. diff --git a/common/drivers/serial.s2.c b/common/drivers/serial.c similarity index 62% rename from common/drivers/serial.s2.c rename to common/drivers/serial.c index f2c885f3..4038caf9 100644 --- a/common/drivers/serial.s2.c +++ b/common/drivers/serial.c @@ -6,19 +6,32 @@ #include #include #include +#include static bool serial_initialised = false; +static uint32_t serial_baudrate; static void serial_initialise(void) { - if (serial_initialised) { + if (serial_initialised || config_ready == false) { return; } + char *baudrate_s = config_get_value(NULL, 0, "SERIAL_BAUDRATE"); + if (baudrate_s == NULL) { + serial_baudrate = 9600; + } else { + serial_baudrate = strtoui(baudrate_s, NULL, 10); + } + // Init com1 outb(0x3f8 + 3, 0x00); outb(0x3f8 + 1, 0x00); outb(0x3f8 + 3, 0x80); - outb(0x3f8 + 0, 0x0c); // 9600 baud + + uint16_t divisor = (uint16_t)(115200 / serial_baudrate); + outb(0x3f8 + 0, divisor & 0xff); + outb(0x3f8 + 1, (divisor >> 8) & 0xff); + outb(0x3f8 + 1, 0x00); outb(0x3f8 + 3, 0x03); outb(0x3f8 + 2, 0xc7); diff --git a/common/lib/print.s2.c b/common/lib/print.s2.c index 45a4779f..d382c358 100644 --- a/common/lib/print.s2.c +++ b/common/lib/print.s2.c @@ -237,7 +237,7 @@ out: } #endif #if defined (BIOS) - if ((!quiet && serial) || COM_OUTPUT) { + if (stage3_loaded && ((!quiet && serial) || COM_OUTPUT)) { switch (print_buf[i]) { case '\n': serial_out('\r'); diff --git a/common/linker_bios.ld.in b/common/linker_bios.ld.in index 7a7d024f..095b075e 100644 --- a/common/linker_bios.ld.in +++ b/common/linker_bios.ld.in @@ -42,6 +42,7 @@ SECTIONS term_notready = .; terms = .; terms_i = .; + serial_out = .; stage3_addr = .; #else #ifdef LINKER_NOS2MAP