Allows to run the serial console in parallel with a vga display.
Output will show up on both vga and serial line.
Input will be accepted from both keyboard and serial line.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
src/optionroms.c | 2 ++
src/sercon.c | 106 ++++++++++++++++++++++++++++++++++++++++++++-----------
src/romlayout.S | 46 ++++++++++++++++++++++++
3 files changed, 133 insertions(+), 21 deletions(-)
diff --git a/src/optionroms.c b/src/optionroms.c
index 8665db42e3..76a70ea686 100644
--- a/src/optionroms.c
+++ b/src/optionroms.c
@@ -442,6 +442,8 @@ vgarom_setup(void)
}
VgaROM = (void*)BUILD_ROM_START;
+ if (romfile_loadint("etc/sercon-enable", 0))
+ sercon_setup();
enable_vga_console();
}
diff --git a/src/sercon.c b/src/sercon.c
index f785aa8fd9..5699905f32 100644
--- a/src/sercon.c
+++ b/src/sercon.c
@@ -9,6 +9,7 @@
#include "stacks.h" // yield
#include "output.h" // dprintf
#include "util.h" // irqtimer_calc_ticks
+#include "string.h" // memcpy
#include "hw/serialio.h" // SEROFF_IER
#include "cp437.h"
@@ -45,6 +46,9 @@ static void cursor_pos_set(u8 row, u8 col)
****************************************************************/
VARLOW u16 sercon_port;
+VARLOW u8 sercon_split;
+VARLOW u8 sercon_enable;
+VARFSEG struct segoff_s sercon_real_vga_handler;
/*
* We have a small output buffer here, for lazy output. That allows
@@ -64,6 +68,11 @@ VARLOW u8 sercon_attr = 0x07;
static VAR16 u8 sercon_cmap[8] = { '0', '4', '2', '6', '1', '5', '3', '7' };
+static int sercon_splitmode(void)
+{
+ return GET_LOW(sercon_split);
+}
+
static void sercon_putchar(u8 chr)
{
u16 addr = GET_LOW(sercon_port);
@@ -174,6 +183,15 @@ static void sercon_print_utf8(u8 chr)
}
}
+static void sercon_cursor_pos_set(u8 row, u8 col)
+{
+ if (!sercon_splitmode()) {
+ cursor_pos_set(row, col);
+ } else {
+ /* let vgabios update cursor */
+ }
+}
+
static void sercon_lazy_cursor_sync(void)
{
u8 row = cursor_pos_row();
@@ -222,7 +240,7 @@ static void sercon_lazy_flush(void)
static void sercon_lazy_cursor_update(u8 row, u8 col)
{
- cursor_pos_set(row, col);
+ sercon_cursor_pos_set(row, col);
SET_LOW(sercon_row_last, row);
SET_LOW(sercon_col_last, col);
}
@@ -241,7 +259,7 @@ static void sercon_lazy_backspace(void)
static void sercon_lazy_cr(void)
{
- cursor_pos_set(cursor_pos_row(), 0);
+ sercon_cursor_pos_set(cursor_pos_row(), 0);
}
static void sercon_lazy_lf(void)
@@ -256,7 +274,7 @@ static void sercon_lazy_lf(void)
SET_LOW(sercon_row_last, GET_LOW(sercon_row_last) - 1);
}
}
- cursor_pos_set(row, cursor_pos_col());
+ sercon_cursor_pos_set(row, cursor_pos_col());
}
static void sercon_lazy_move_cursor(void)
@@ -268,7 +286,7 @@ static void sercon_lazy_move_cursor(void)
sercon_lazy_cr();
sercon_lazy_lf();
} else {
- cursor_pos_set(cursor_pos_row(), col);
+ sercon_cursor_pos_set(cursor_pos_row(), col);
}
}
@@ -293,23 +311,28 @@ static void sercon_1000(struct bregs *regs)
u8 mode = regs->al & 0x7f;
u8 rows, cols;
- switch (mode) {
- case 0x03:
- default:
- cols = 80;
- rows = 25;
- regs->al = 0x30;
+ if (!sercon_splitmode()) {
+ switch (mode) {
+ case 0x03:
+ default:
+ cols = 80;
+ rows = 25;
+ regs->al = 0x30;
+ }
+ cursor_pos_set(0, 0);
+ SET_BDA(video_mode, mode);
+ SET_BDA(video_cols, cols);
+ SET_BDA(video_rows, rows-1);
+ SET_BDA(cursor_type, 0x0007);
+ } else {
+ SET_LOW(sercon_enable, (mode == 0x03));
+ /* let vgabios handle mode init */
}
+
SET_LOW(sercon_col_last, 0);
SET_LOW(sercon_row_last, 0);
SET_LOW(sercon_attr_last, 0);
- cursor_pos_set(0, 0);
- SET_BDA(video_mode, mode);
- SET_BDA(video_cols, cols);
- SET_BDA(video_rows, rows-1);
- SET_BDA(cursor_type, 0x0007);
-
sercon_term_reset();
sercon_term_no_linewrap();
if (clearscreen)
@@ -326,10 +349,7 @@ static void sercon_1001(struct bregs *regs)
/* Set cursor position */
static void sercon_1002(struct bregs *regs)
{
- u8 row = regs->dh;
- u8 col = regs->dl;
-
- cursor_pos_set(row, col);
+ sercon_cursor_pos_set(regs->dh, regs->dl);
}
/* Get cursor position */
@@ -427,7 +447,13 @@ static void sercon_100f(struct bregs *regs)
/* VBE 2.0 */
static void sercon_104f(struct bregs *regs)
{
- regs->ax = 0x0100;
+ if (!sercon_splitmode()) {
+ regs->ax = 0x0100;
+ } else {
+ // Disable sercon entry point on any vesa modeset
+ if (regs->al == 0x00)
+ SET_LOW(sercon_enable, 0);
+ }
}
static void sercon_10XX(struct bregs *regs)
@@ -458,6 +484,31 @@ sercon_10(struct bregs *regs)
}
}
+void VISIBLE16
+sercon_10_splitmode(struct bregs *regs)
+{
+ if (!CONFIG_SERCON)
+ return;
+ if (!GET_LOW(sercon_port))
+ return;
+
+ switch (regs->ah) {
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x08:
+ case 0x0f:
+ /* nothing, vgabios did all work */
+ break;
+ case 0x00: sercon_1000(regs); break;
+ case 0x06: sercon_1006(regs); break;
+ case 0x09: sercon_1009(regs); break;
+ case 0x0e: sercon_100e(regs); break;
+ case 0x4f: sercon_104f(regs); break;
+ default: sercon_10XX(regs); break;
+ }
+}
+
void sercon_setup(void)
{
if (!CONFIG_SERCON)
@@ -466,6 +517,19 @@ void sercon_setup(void)
struct segoff_s seabios, vgabios;
u16 addr = PORT_SERIAL1;
+ vgabios = GET_IVT(0x10);
+ seabios = FUNC16(entry_10);
+ if (vgabios.seg != seabios.seg ||
+ vgabios.offset != seabios.offset) {
+ dprintf(1, "%s:%d: using splitmode (vgabios %04x:%04x, hook %04x:%04x)\n",
+ __func__, __LINE__,
+ vgabios.seg, vgabios.offset,
+ seabios.seg, seabios.offset);
+ sercon_real_vga_handler = vgabios;
+ SET_IVT(0x10, FUNC16(entry_sercon));
+ SET_LOW(sercon_split, 1);
+ }
+
SET_LOW(sercon_port, addr);
outb(0x03, addr + SEROFF_LCR); // 8N1
outb(0x01, addr + 0x02); // enable fifo
diff --git a/src/romlayout.S b/src/romlayout.S
index 89b3784d60..1c9d56df1b 100644
--- a/src/romlayout.S
+++ b/src/romlayout.S
@@ -414,6 +414,52 @@ __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
+
+2: popl %eax
+ popw %ds
+ pushl $sercon_10_splitmode
+#if CONFIG_ENTRY_EXTRASTACK
+ jmp irqentry_arg_extrastack
+#else
+ jmp irqentry_arg
+#endif
+
+ // 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
--
2.9.3
_______________________________________________
SeaBIOS mailing list
SeaBIOS@seabios.org
https://mail.coreboot.org/mailman/listinfo/seabios
On Fri, Sep 08, 2017 at 08:18:27AM +0200, Gerd Hoffmann wrote: > Allows to run the serial console in parallel with a vga display. > Output will show up on both vga and serial line. > Input will be accepted from both keyboard and serial line. [...] > + SET_LOW(sercon_enable, (mode == 0x03)); [...] > + // sercon disabled - verify not 0x03 modeset and otherwise exit > +3: popl %eax > + cmpw $0x0003, %ax > + jne 5f Minor note - I realized after I sent my last patch that doing: SET_LOW(sercon_enable, (mode <= 0x07)); and: cmpw $0x0007, %ax jg 5f Is more flexible and still safe. -Kevin _______________________________________________ SeaBIOS mailing list SeaBIOS@seabios.org https://mail.coreboot.org/mailman/listinfo/seabios
On Fri, 2017-09-08 at 14:53 -0400, Kevin O'Connor wrote: > On Fri, Sep 08, 2017 at 08:18:27AM +0200, Gerd Hoffmann wrote: > > Allows to run the serial console in parallel with a vga display. > > Output will show up on both vga and serial line. > > Input will be accepted from both keyboard and serial line. > > [...] > > + SET_LOW(sercon_enable, (mode == 0x03)); > > [...] > > + // sercon disabled - verify not 0x03 modeset and otherwise > > exit > > +3: popl %eax > > + cmpw $0x0003, %ax > > + jne 5f > > Minor note - I realized after I sent my last patch that doing: > > SET_LOW(sercon_enable, (mode <= 0x07)); I don't think so. 0,1,2,3,7 are text modes, but 4,5,6 not. cheers, Gerd _______________________________________________ SeaBIOS mailing list SeaBIOS@seabios.org https://mail.coreboot.org/mailman/listinfo/seabios
On Mon, Sep 11, 2017 at 12:33:24PM +0200, Gerd Hoffmann wrote: > On Fri, 2017-09-08 at 14:53 -0400, Kevin O'Connor wrote: > > On Fri, Sep 08, 2017 at 08:18:27AM +0200, Gerd Hoffmann wrote: > > > Allows to run the serial console in parallel with a vga display. > > > Output will show up on both vga and serial line. > > > Input will be accepted from both keyboard and serial line. > > > > [...] > > > + SET_LOW(sercon_enable, (mode == 0x03)); > > > > [...] > > > + // sercon disabled - verify not 0x03 modeset and otherwise > > > exit > > > +3: popl %eax > > > + cmpw $0x0003, %ax > > > + jne 5f > > > > Minor note - I realized after I sent my last patch that doing: > > > > SET_LOW(sercon_enable, (mode <= 0x07)); > > I don't think so. 0,1,2,3,7 are text modes, but 4,5,6 not. It's safe to enter the C code on 4,5,6 though. Also, I don't think it was unusual to write text while in cga mode. (CGA support isn't a priority though.) -Kevin _______________________________________________ SeaBIOS mailing list SeaBIOS@seabios.org https://mail.coreboot.org/mailman/listinfo/seabios
Hi, > > > Minor note - I realized after I sent my last patch that doing: > > > > > > SET_LOW(sercon_enable, (mode <= 0x07)); > > > > I don't think so. 0,1,2,3,7 are text modes, but 4,5,6 not. > > It's safe to enter the C code on 4,5,6 though. Also, I don't think > it > was unusual to write text while in cga mode. (CGA support isn't a > priority though.) Oh. So the char write int10h calls work in cga mode too? cheers, Gerd _______________________________________________ SeaBIOS mailing list SeaBIOS@seabios.org https://mail.coreboot.org/mailman/listinfo/seabios
On Tue, Sep 12, 2017 at 08:25:44AM +0200, Gerd Hoffmann wrote: > Hi, > > > > > Minor note - I realized after I sent my last patch that doing: > > > > > > > > SET_LOW(sercon_enable, (mode <= 0x07)); > > > > > > I don't think so. 0,1,2,3,7 are text modes, but 4,5,6 not. > > > > It's safe to enter the C code on 4,5,6 though. Also, I don't think > > it > > was unusual to write text while in cga mode. (CGA support isn't a > > priority though.) > > Oh. So the char write int10h calls work in cga mode too? Yes. On SeaVGABIOS, text writing now works in all graphic modes, though not all vgabios support that. The original bochs vgabios didn't support it in "direct" or "packed" modes, and I think it was broken for years in planar mode. So, it's rare for text writing to be seen in any mode above 7. (It's also rare for anything to go into cga mode today, but for ancient programs, it would not have been unusual to write out text in cga mode.) -Kevin _______________________________________________ SeaBIOS mailing list SeaBIOS@seabios.org https://mail.coreboot.org/mailman/listinfo/seabios
> On SeaVGABIOS, text writing now works in all graphic modes, though > not > all vgabios support that. The original bochs vgabios didn't support > it in "direct" or "packed" modes, and I think it was broken for years > in planar mode. So, it's rare for text writing to be seen in any > mode > above 7. (It's also rare for anything to go into cga mode today, but > for ancient programs, it would not have been unusual to write out > text > in cga mode.) Ah, ok. Didn't know that. So it actually makes sense to support all modes <= 7 in sercon. 4+5 are 320x200, which should be 40x25 chars, and 6 is 640x200 and therefore 80x25 chars (both using 8x8 font). I'll go add 4+5+6 and simplify the mode number checks. cheers, Gerd _______________________________________________ SeaBIOS mailing list SeaBIOS@seabios.org https://mail.coreboot.org/mailman/listinfo/seabios
© 2016 - 2025 Red Hat, Inc.