[SeaBIOS] [PATCH 0/3] SeaVGABIOS serial console test

Kevin O'Connor kevin at koconnor.net
Tue Sep 5 18:31:32 CEST 2017


On Tue, Sep 05, 2017 at 10:01:41AM +0200, Gerd Hoffmann wrote:
> > Note, though, in addition to checking for broken x86emu, the
> > assembler
> > entry code would also have to check that the last mode was not set
> > via
> > a vesa call (to avoid the "skifree" bug).
> 
> Ok,  Is there some easy way to access the BDA from assembler code
> (specifically the video_mode field)?  Guess I must set a segment
> register for that.  Maybe it's easier to just place an additional flag
> in the fseg which we can easily reach via cs override ...

The flag can't be in the f-segment because it needs to be
read/writable at runtime.  I ran some tests - it looks like it is okay
to access the varlow segment - one just can't write to it.
Unfortunately, it's not enough to simply test for a legacy modeset
call (int 0x10 ah=0x00) as it looks like Vista calls that in its
emulation mode during startup.  However, it looks like it is okay if
one verifies that the legacy modeset call is for a text mode (eg, int
0x10 ax=0x0003).

I put together the patch below (based off of current seabios master).
It doesn't do anything except test that one can safely enter the C
code.  It survives winxp, winvista, winvista+skifree, and xorg on
fedora 13 (these were my typical trouble spots with vgabios testing).

-Kevin


>From ad37047c3bbd7b5d92b849acfee3844a64ac1a28 Mon Sep 17 00:00:00 2001
From: Kevin O'Connor <kevin at koconnor.net>
Date: Tue, 5 Sep 2017 11:45:08 -0400
Subject: [PATCH] sercon: Add support for hooking vga handler

Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
Signed-off-by: Kevin O'Connor <kevin at koconnor.net>
---
 Makefile         |  1 +
 src/Kconfig      |  5 +++++
 src/config.h     |  1 +
 src/optionroms.c |  6 +++++-
 src/romlayout.S  | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/sercon.c     | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/util.h       |  3 +++
 7 files changed, 124 insertions(+), 1 deletion(-)
 create mode 100644 src/sercon.c

diff --git a/Makefile b/Makefile
index 946df7e..07ac747 100644
--- a/Makefile
+++ b/Makefile
@@ -30,6 +30,7 @@ LD32BIT_FLAG:=-melf_i386
 # Source files
 SRCBOTH=misc.c stacks.c output.c string.c block.c cdrom.c disk.c mouse.c kbd.c \
     system.c serial.c clock.c resume.c pnpbios.c vgahooks.c pcibios.c apm.c \
+    sercon.c \
     hw/pci.c hw/timer.c hw/rtc.c hw/dma.c hw/pic.c hw/ps2port.c hw/serialio.c \
     hw/usb.c hw/usb-uhci.c hw/usb-ohci.c hw/usb-ehci.c \
     hw/usb-hid.c hw/usb-msc.c hw/usb-uas.c \
diff --git a/src/Kconfig b/src/Kconfig
index 77ec9c7..55a87cb 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -306,6 +306,11 @@ menu "Hardware support"
         default y
         help
             Support serial ports.  This also enables int 14 serial port calls.
+    config SERCON
+        bool "Serial console"
+        default y
+        help
+            Support redirecting vga output to the serial console.
     config LPT
         bool "Parallel port"
         default y
diff --git a/src/config.h b/src/config.h
index baca029..e56d4a7 100644
--- a/src/config.h
+++ b/src/config.h
@@ -100,6 +100,7 @@
 #define DEBUG_HDL_pmm 1
 #define DEBUG_HDL_pcibios 9
 #define DEBUG_HDL_apm 9
+#define DEBUG_HDL_sercon 9
 
 #define DEBUG_unimplemented 2
 #define DEBUG_invalid 3
diff --git a/src/optionroms.c b/src/optionroms.c
index 65f7fe0..4f6611e 100644
--- a/src/optionroms.c
+++ b/src/optionroms.c
@@ -404,8 +404,10 @@ struct rom_header *VgaROM;
 void
 vgarom_setup(void)
 {
-    if (! CONFIG_OPTIONROMS)
+    if (! CONFIG_OPTIONROMS) {
+        sercon_setup();
         return;
+    }
 
     dprintf(1, "Scan for VGA option rom\n");
 
@@ -432,6 +434,8 @@ vgarom_setup(void)
     run_file_roms("vgaroms/", 1, NULL);
     rom_reserve(0);
 
+    sercon_setup();
+
     if (rom_get_last() == BUILD_ROM_START)
         // No VGA rom found
         return;
diff --git a/src/romlayout.S b/src/romlayout.S
index 89b3784..8ed53dc 100644
--- a/src/romlayout.S
+++ b/src/romlayout.S
@@ -414,6 +414,61 @@ __csm_return:
         popfw
         lretw
 
+// Serial console "hooked vga" entry point
+        DECLFUNC entry_sercon
+entry_sercon:
+        // Setup for chain loading to real vga handler
+        pushfw
+        pushl %cs:sercon_real_vga_handler
+
+        // Set %ds to varlow segment
+        cli
+        cld
+        pushw %ds
+        pushl %eax
+        movl $_zonelow_seg, %eax
+        movl %eax, %ds
+
+        // Test if the sercon handler can be called
+        movl %esp, %eax         // Test for broken x86emu
+        pushl $1f
+        retl
+1:      cmpl %esp, %eax
+        jne 4f
+        cmpb $0, sercon_enable  // Test that sercon is enabled
+        je 3f
+
+        // Call handle_sercon() on the extra stack
+2:      movl StackPos, %eax
+        subl $PUSHBREGS_size+8, %eax
+        SAVEBREGS_POP_DSEAX
+        movl %esp, PUSHBREGS_size(%eax)
+        movw %ss, PUSHBREGS_size+4(%eax)
+
+        movw %ds, %dx           // Setup %ss/%esp and call function
+        movw %dx, %ss
+        movl %eax, %esp
+        calll handle_sercon
+
+        movl %esp, %eax         // Restore registers and return
+        movw PUSHBREGS_size+4(%eax), %ss
+        movl PUSHBREGS_size(%eax), %esp
+        RESTOREBREGS_DSEAX
+        iretw
+
+        // sercon disabled - verify not 0x03 modeset and otherwise exit
+3:      popl %eax
+        cmpw $0x0003, %ax
+        jne 5f
+        pushl %eax
+        jmp 2b
+
+        // Running on broken x86emu - restore stack and exit
+4:      movl %eax, %esp
+        popl %eax
+5:      popw %ds
+        iretw
+
 
 /****************************************************************
  * Interrupt entry points
diff --git a/src/sercon.c b/src/sercon.c
new file mode 100644
index 0000000..7307772
--- /dev/null
+++ b/src/sercon.c
@@ -0,0 +1,54 @@
+// Serial console support
+//
+// Copyright (C) 2017  Kevin O'Connor <kevin at koconnor.net>
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "biosvar.h" // GET_IVT
+#include "bregs.h" // struct bregs
+#include "output.h" // dprintf
+#include "romfile.h" // romfile_loadint
+#include "util.h" // sercon_setup
+
+struct segoff_s sercon_real_vga_handler VARFSEG;
+u8 sercon_enable VARLOW;
+
+void
+sercon_setup(void)
+{
+    ASSERT32FLAT();
+    if (!CONFIG_SERCON || (GET_IVT(0x10).segoff != FUNC16(entry_10).segoff
+                           && !romfile_loadint("etc/sercon-hook", 0)))
+        return;
+
+    dprintf(3, "init sercon\n");
+    sercon_real_vga_handler = GET_IVT(0x10);
+    SET_IVT(0x10, FUNC16(entry_sercon));
+}
+
+static void
+sercon_1000(struct bregs *regs)
+{
+    int mode = regs->al & 0x7f;
+    SET_LOW(sercon_enable, (mode == 0x03));
+}
+
+static void
+sercon_104f(struct bregs *regs)
+{
+    // Disable sercon entry point on any vesa modeset
+    if (regs->al == 0x00)
+        SET_LOW(sercon_enable, 0);
+}
+
+void VISIBLE16
+handle_sercon(struct bregs *regs)
+{
+    if (!CONFIG_SERCON)
+        return;
+    debug_enter(regs, DEBUG_HDL_sercon);
+    switch (regs->ah) {
+    case 0x00: sercon_1000(regs); break;
+    case 0x4f: sercon_104f(regs); break;
+    }
+}
diff --git a/src/util.h b/src/util.h
index 8269057..8b747b3 100644
--- a/src/util.h
+++ b/src/util.h
@@ -229,6 +229,9 @@ void startBoot(void);
 void reloc_preinit(void *f, void *arg);
 void code_mutable_preinit(void);
 
+// sercon.c
+void sercon_setup(void);
+
 // serial.c
 void serial_setup(void);
 void lpt_setup(void);
-- 
2.9.5




More information about the SeaBIOS mailing list