[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