aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Fleming <matt.fleming@intel.com>2011-10-18 13:13:06 +0100
committerMatt Fleming <matt.fleming@intel.com>2011-12-01 13:14:05 +0000
commit9f51b69d7c0500e04b3c404bb5138a9234810035 (patch)
treed566e6984457f331288f34d780f15a680334af94
parentdd5e4935f3e2f8f1940c72d9c3b39a926300c42e (diff)
downloadsyslinux-9f51b69d7c0500e04b3c404bb5138a9234810035.tar.gz
syslinux-9f51b69d7c0500e04b3c404bb5138a9234810035.tar.xz
syslinux-9f51b69d7c0500e04b3c404bb5138a9234810035.zip
core: Reimplement lots asm code in C
There is an awful lot of code currently implemented in assembly when it could just as easily be implemented in C. Having it in C makes it much easier to share code between the BIOS and forthcoming EFI firmware backend. The following code fragments have been rewritten, - timer initialisation - adjust_screen() - check_esapes() and mem_init() - conio.inc - plaincon.inc - cleanup.inc - serirq.inc - font.inc - graphics - writehex Signed-off-by: Matt Fleming <matt.fleming@intel.com>
-rw-r--r--com32/elflink/ldlinux/readconfig.c49
-rw-r--r--core/abort.inc84
-rw-r--r--core/cleanup.c46
-rw-r--r--core/cleanup.inc60
-rw-r--r--core/comboot.inc14
-rw-r--r--core/common.inc3
-rw-r--r--core/conio.c600
-rw-r--r--core/conio.inc435
-rw-r--r--core/diskfs.inc2
-rw-r--r--core/extern.inc21
-rw-r--r--core/font.c195
-rw-r--r--core/font.inc153
-rw-r--r--core/graphics.c382
-rw-r--r--core/graphics.inc353
-rw-r--r--core/idle.inc5
-rw-r--r--core/include/bios.h105
-rw-r--r--core/include/core.h2
-rw-r--r--core/init.c77
-rw-r--r--core/init.inc60
-rw-r--r--core/isolinux.asm16
-rw-r--r--core/plaincon.c32
-rw-r--r--core/plaincon.inc24
-rw-r--r--core/pm.inc3
-rw-r--r--core/pxelinux.asm17
-rw-r--r--core/serirq.c204
-rw-r--r--core/serirq.inc221
-rw-r--r--core/timer.inc3
-rw-r--r--core/ui.inc10
-rw-r--r--core/writehex.c70
29 files changed, 1803 insertions, 1443 deletions
diff --git a/com32/elflink/ldlinux/readconfig.c b/com32/elflink/ldlinux/readconfig.c
index 5bf6f42c..60448c43 100644
--- a/com32/elflink/ldlinux/readconfig.c
+++ b/com32/elflink/ldlinux/readconfig.c
@@ -721,7 +721,7 @@ extern uint8_t SerialNotice;
extern void sirq_cleanup_nowipe(void);
extern void sirq_install(void);
-extern void write_serial_str(void);
+extern void write_serial_str(char *);
static inline void io_delay(void)
{
@@ -729,9 +729,9 @@ static inline void io_delay(void)
outb(0, 0x80);
}
-extern void get_msg_file(void);
-extern void loadfont(void);
-extern void loadkeys(void);
+extern void get_msg_file(char *);
+extern void loadfont(char *);
+extern void loadkeys(char *);
extern char syslinux_banner[];
extern char copyright_str[];
@@ -1120,7 +1120,6 @@ do_include:
* display/font/kbdmap are rather similar, open a file then do sth
*/
else if (looking_at(p, "display")) {
- com32sys_t reg;
char *filename, *dst = KernelName;
size_t len = FILENAME_MAX - 1;
@@ -1130,17 +1129,9 @@ do_include:
*dst++ = *filename++;
*dst = '\0';
- memset(&reg, 0, sizeof(reg));
- reg.edi.w[0] = OFFS_WRT(KernelName, 0);
- call16(core_open, &reg, &reg);
- if (!(reg.eflags.l & EFLAGS_ZF))
- call16(get_msg_file, &reg, NULL);
- else
- printf("File not found\n");
-
+ get_msg_file(KernelName);
refstr_put(filename);
} else if (looking_at(p, "font")) {
- com32sys_t reg;
char *filename, *dst = KernelName;
size_t len = FILENAME_MAX - 1;
@@ -1150,14 +1141,7 @@ do_include:
*dst++ = *filename++;
*dst = '\0';
- memset(&reg, 0, sizeof(reg));
- reg.edi.w[0] = OFFS_WRT(KernelName, 0);
- call16(core_open, &reg, &reg);
- if (!(reg.eflags.l & EFLAGS_ZF))
- call16(loadfont, &reg, NULL);
- else
- printf("File not found\n");
-
+ loadfont(KernelName);
refstr_put(filename);
} else if (looking_at(p, "kbdmap")) {
com32sys_t reg;
@@ -1170,14 +1154,7 @@ do_include:
*dst++ = *filename++;
*dst = '\0';
- memset(&reg, 0, sizeof(reg));
- reg.edi.w[0] = OFFS_WRT(KernelName, 0);
- call16(core_open, &reg, &reg);
- if (!(reg.eflags.l & EFLAGS_ZF))
- call16(loadkeys, &reg, NULL);
- else
- printf("File not found\n");
-
+ loadkeys(KernelName);
refstr_put(filename);
}
/*
@@ -1279,8 +1256,7 @@ do_include:
/*
* Begin code to actually set up the serial port
*/
- memset(&ireg, 0, sizeof(ireg));
- call16(sirq_cleanup_nowipe, &ireg, NULL);
+ sirq_cleanup_nowipe();
outb(0x83, port + 3); /* Enable DLAB */
io_delay();
@@ -1319,17 +1295,14 @@ do_include:
/* Enable interrupts if requested */
if (FlowOutput & 0x8)
- call16(sirq_install, &ireg, NULL);
+ sirq_install();
/* Show some life */
if (SerialNotice != 0) {
SerialNotice = 0;
- ireg.esi.w[0] = syslinux_banner;
- call16(write_serial_str, &ireg, NULL);
-
- ireg.esi.w[0] = copyright_str;
- call16(write_serial_str, &ireg, NULL);
+ write_serial_str(syslinux_banner);
+ write_serial_str(copyright_str);
}
} else if (looking_at(p, "say")) {
printf("%s\n", p + 4);
diff --git a/core/abort.inc b/core/abort.inc
deleted file mode 100644
index 9b181363..00000000
--- a/core/abort.inc
+++ /dev/null
@@ -1,84 +0,0 @@
-; -----------------------------------------------------------------------
-;
-; Copyright 2005-2009 H. Peter Anvin - All Rights Reserved
-; Copyright 2009 Intel Corporation; author: H. Peter Anvin
-;
-; This program is free software; you can redistribute it and/or modify
-; it under the terms of the GNU General Public License as published by
-; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
-; Boston MA 02111-1307, USA; either version 2 of the License, or
-; (at your option) any later version; incorporated herein by reference.
-;
-; -----------------------------------------------------------------------
-
-;
-; abort.inc
-;
-; Code to terminate a kernel load
-;
-
- section .text16
-
-;
-; dot_pause: same as abort_check, except prints a dot, too
-; assumes CS == DS
-;
-dot_pause:
- push si
- mov si,dot_msg
- call writestr_qchk
- pop si
- ; fall through
-
-;
-; abort_check: let the user abort with <ESC> or <Ctrl-C>
-;
-abort_check:
- call reset_idle ; Not idle despite pollchar
- call pollchar
- jz .ret1
- pusha
- call getchar
- cmp al,27 ; <ESC>
- je .kill
- cmp al,3 ; <Ctrl-C>
- je .kill
-.ret2: popa
-.ret1: ret
-
-.kill: mov si,aborted_msg
- mov bx,enter_command
- jmp abort_load_chain
-
-;
-; abort_load: Called by various routines which wants to print a fatal
-; error message and return to the command prompt. Since this
-; may happen at just about any stage of the boot process, assume
-; our state is messed up, and just reset the segment registers
-; and the stack forcibly.
-;
-; SI = offset (in _text) of error message to print
-; BX = future entry point (abort_load_chain)
-;
-abort_load:
- mov bx,error_or_command
-abort_load_chain:
- RESET_STACK_AND_SEGS AX
- call writestr ; Expects SI -> error msg
-
- ; Return to the command prompt
- jmp bx
-
-;
-; error_or_command: Execute ONERROR if appropriate, otherwise enter_command
-;
-error_or_command:
- mov cx,[OnerrorLen]
- and cx,cx
- jnz on_error
- jmp enter_command
-
- section .data16
-aborted_msg db ' aborted.', CR, LF, 0
-
- section .text16
diff --git a/core/cleanup.c b/core/cleanup.c
new file mode 100644
index 00000000..7bf1df2e
--- /dev/null
+++ b/core/cleanup.c
@@ -0,0 +1,46 @@
+/* -----------------------------------------------------------------------
+ *
+ * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ * Boston MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * -----------------------------------------------------------------------
+ */
+#include <com32.h>
+#include <core.h>
+
+extern void timer_cleanup(void);
+extern void comboot_cleanup_api(void);
+
+/*
+ * cleanup.c
+ *
+ * Some final tidying before jumping to a kernel or bootsector
+ */
+
+/*
+ * cleanup_hardware:
+ *
+ * Shut down anything transient.
+ */
+void cleanup_hardware(void)
+{
+ /*
+ * TODO
+ *
+ * Linux wants the floppy motor shut off before starting the
+ * kernel, at least bootsect.S seems to imply so. If we don't
+ * load the floppy driver, this is *definitely* so!
+ */
+ __intcall(0x13, &zero_regs, NULL);
+
+ call16(comboot_cleanup_api, &zero_regs, NULL);
+ call16(timer_cleanup, &zero_regs, NULL);
+
+ /* If we enabled serial port interrupts, clean them up now */
+ sirq_cleanup();
+}
diff --git a/core/cleanup.inc b/core/cleanup.inc
deleted file mode 100644
index 300584c7..00000000
--- a/core/cleanup.inc
+++ /dev/null
@@ -1,60 +0,0 @@
-;; -----------------------------------------------------------------------
-;;
-;; Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
-;;
-;; This program is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
-;; Boston MA 02111-1307, USA; either version 2 of the License, or
-;; (at your option) any later version; incorporated herein by reference.
-;;
-;; -----------------------------------------------------------------------
-
-;;
-;; cleanup.inc
-;;
-;; Some final tidying before jumping to a kernel or bootsector
-;;
-
- section .text16
-;
-; cleanup_hardware:
-;
-; Shut down anything transient. *No segment assumptions*.
-; Preserves all registers.
-;
-cleanup_hardware:
- pushad
-;
-; Linux wants the floppy motor shut off before starting the kernel,
-; at least bootsect.S seems to imply so. If we don't load the floppy
-; driver, this is *definitely* so!
-;
- xor ax,ax
- xor dx,dx
- int 13h
-
-%if 0 ; This bug report has not been substantiated!
-; Vmware crashes if we scroll in the decompressor! Try to detect vmware
-; and if it is Vmware, clear the screen...
- mov eax,'VMXh'
- xor ebx, ebx
- mov ecx, 10 ; Get version
- mov dx, 'VX'
- in eax, dx
- cmp ebx, 'VMXh'
- jne .no_vmware
-
- mov ax,0x0003 ; Set mode (clear screen/home cursor)
- int 10h
-.no_vmware:
-%endif
-
- call comboot_cleanup_api
-
- call timer_cleanup
-
- popad
-
- ; If we enabled serial port interrupts, clean them up now
- jmp sirq_cleanup
diff --git a/core/comboot.inc b/core/comboot.inc
index b0e118ad..880f5db1 100644
--- a/core/comboot.inc
+++ b/core/comboot.inc
@@ -173,6 +173,7 @@ comboot_setup_api:
; Restore the original state of the COMBOOT API vectors, and free
; any low memory allocated by the comboot module.
;
+ global comboot_cleanup_api
comboot_cleanup_api:
pusha
mov si,DOSSaveVectors
@@ -238,7 +239,7 @@ comboot_int21: sti
mov es,bp
mov bp,sp ; Set up stack frame
- call adjust_screen ; The COMBOOT program might have changed the screen
+ call _adjust_screen ; The COMBOOT program might have changed the screen
mov cx,int21_count
mov si,int21_table
@@ -309,7 +310,7 @@ comboot_exit_msg:
pop bx ; Return address
RESET_STACK_AND_SEGS si ; Contains sti, cld
pm_call comboot_cleanup_lowmem
- call adjust_screen ; The COMBOOT program might have changed the screen
+ call _adjust_screen ; The COMBOOT program might have changed the screen
jcxz .nomsg
mov si,KernelName
call writestr
@@ -425,7 +426,7 @@ comboot_int22:
mov es,bp
mov bp,sp ; Set up stack frame
- call adjust_screen ; The COMBOOT program might have changed the screen
+ call _adjust_screen ; The COMBOOT program might have changed the screen
cmp ax,int22_count
jb .ok
@@ -807,7 +808,7 @@ comapi_usingvga:
mov [GXPixRows],dx
test al,08h
jnz .notext
- call adjust_screen
+ call _adjust_screen
.notext:
clc
ret
@@ -1002,6 +1003,11 @@ feature_flags_len equ ($-feature_flags)
err_notdos db ': attempted DOS system call INT ',0
err_comlarge db 'COMBOOT image too large.', CR, LF, 0
+ global VGAFontSize, UserFont
+ alignz 2
+VGAFontSize dw 16 ; Defaults to 16 byte font
+UserFont db 0 ; Using a user-specified font
+
section .bss16
alignb 4
DOSErrTramp resd 33 ; Error trampolines
diff --git a/core/common.inc b/core/common.inc
index 0b507ce7..1a6840e2 100644
--- a/core/common.inc
+++ b/core/common.inc
@@ -5,15 +5,12 @@
;
%include "getc.inc" ; getc et al
-%include "conio.inc" ; Console I/O
%include "configinit.inc" ; Initialize configuration
%include "parseconfig.inc" ; High-level config file handling
%include "parsecmd.inc" ; Low-level config file handling
%include "pm.inc" ; Protected mode
%include "bcopy32.inc" ; 32-bit bcopy
%include "loadhigh.inc" ; Load a file into high memory
-%include "font.inc" ; VGA font stuff
-%include "graphics.inc" ; VGA graphics
%include "strcpy.inc" ; strcpy()
%include "idle.inc" ; Idle handling
%include "adv.inc" ; Auxillary Data Vector
diff --git a/core/conio.c b/core/conio.c
new file mode 100644
index 00000000..ddccbdb9
--- /dev/null
+++ b/core/conio.c
@@ -0,0 +1,600 @@
+/*
+ * -----------------------------------------------------------------------
+ *
+ * Copyright 1994-2008 H. Peter Anvin - All Rights Reserved
+ * Copyright 2009 Intel Corporation; author: H. Peter Anvin
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ * Boston MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * -----------------------------------------------------------------------
+ *
+ *
+ * conio.c
+ *
+ * Console I/O code, except:
+ * writechr, writestr_early - module-dependent
+ * writestr, crlf - writestr.inc
+ * writehex* - writehex.inc
+ */
+#include <sys/io.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <fs.h>
+#include "bios.h"
+#include <com32.h>
+#include <sys/cpu.h>
+
+union screen _cursor;
+union screen _screensize;
+
+/*
+ * Serial console stuff.
+ */
+uint16_t SerialPort = 0; /* Serial port base (or 0 for no serial port) */
+uint16_t BaudDivisor = 115200/9600; /* Baud rate divisor */
+uint8_t FlowOutput = 0; /* Output to assert for serial flow */
+uint8_t FlowInput = 0; /* Input bits for serial flow */
+uint8_t FlowIgnore = 0; /* Ignore input unless these bits set */
+
+uint8_t ScrollAttribute = 0x07; /* Grey on white (normal text color) */
+uint16_t DisplayCon = 0x01; /* Display console enabled */
+static uint8_t TextAttribute; /* Text attribute for message file */
+static uint8_t DisplayMask; /* Display modes mask */
+
+/* Routine to interpret next print char */
+static void (*NextCharJump)(char);
+
+void msg_initvars(void);
+static void msg_setfg(char data);
+static void msg_putchar(char ch);
+
+uint8_t KbdMap[256]; /* Keyboard map */
+
+/*
+ * loadkeys: Load a LILO-style keymap
+ *
+ * Returns 0 on success, or -1 on error.
+ */
+int loadkeys(char *filename)
+{
+ FILE *f;
+
+ f = fopen(filename, "r");
+ if (!f)
+ return -1;
+
+ fread(KbdMap, 1, sizeof(KbdMap), f);
+
+ fclose(f);
+ return 0;
+}
+
+/*
+ *
+ * get_msg_file: Load a text file and write its contents to the screen,
+ * interpreting color codes.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+int get_msg_file(char *filename)
+{
+ FILE *f;
+ char ch;
+
+ f = fopen(filename, "r");
+ if (!f)
+ return -1;
+
+ TextAttribute = 0x7; /* Default grey on white */
+ DisplayMask = 0x7; /* Display text in all modes */
+ msg_initvars();
+
+ /*
+ * Read the text file a byte at a time and interpret that
+ * byte.
+ */
+ while ((ch = getc(f)) != EOF) {
+ /* DOS EOF? */
+ if (ch == 0x1A)
+ break;
+
+ /*
+ * 01h = text mode
+ * 02h = graphics mode
+ */
+ UsingVGA &= 0x1;
+ UsingVGA += 1;
+
+ NextCharJump(ch); /* Do what shall be done */
+ }
+
+ fclose(f);
+ return 0;
+}
+
+static inline void msg_beep(void)
+{
+ com32sys_t ireg, oreg;
+
+ ireg.eax.w[0] = 0x0E07; /* Beep */
+ ireg.ebx.w[0] = 0x0000;
+ __intcall(0x10, &ireg, &oreg);
+}
+
+/*
+ * write_serial: If serial output is enabled, write character on
+ * serial port.
+ */
+void write_serial(char data)
+{
+ if (!SerialPort)
+ return;
+
+ while (1) {
+ char ch;
+
+ ch = inb(SerialPort + 5); /* LSR */
+
+ /* Wait for space in transmit register */
+ if (!(ch & 0x20))
+ continue;
+
+ /* Wait for input flow control */
+ ch = inb(SerialPort + 6);
+ ch &= FlowInput;
+ if (ch != FlowInput)
+ continue;
+
+ break;
+ }
+
+ outb(data, SerialPort); /* Send data */
+ io_delay();
+}
+
+void pm_write_serial(com32sys_t *regs)
+{
+ write_serial(regs->eax.b[0]);
+}
+
+void pm_serialcfg(com32sys_t *regs)
+{
+ uint8_t al, ah;
+
+ regs->eax.w[0] = SerialPort;
+ regs->ecx.w[0] = BaudDivisor;
+
+ al = FlowOutput;
+ ah = FlowInput;
+
+ al |= ah;
+ ah = FlowIgnore;
+ ah >>= 4;
+
+ if (!DisplayCon)
+ ah |= 0x80;
+
+ regs->ebx.w[0] = al | (ah << 8);
+}
+
+static void write_serial_displaymask(char data)
+{
+ if (DisplayMask & 0x4)
+ write_serial(data);
+}
+
+/*
+ * write_serial_str: write_serial for strings
+ */
+void write_serial_str(char *data)
+{
+ char ch;
+
+ while ((ch = *data++))
+ write_serial(ch);
+}
+
+/*
+ * write_serial_str_displaymask: d:o, but ignore if DisplayMask & 04h == 0
+ */
+static void write_serial_str_displaymask(char *data)
+{
+ if (DisplayMask & 0x4)
+ write_serial_str(data);
+}
+
+/*
+ * pollchar: check if we have an input character pending
+ *
+ * Returns 1 if character pending.
+ */
+int pollchar(void)
+{
+ com32sys_t ireg, oreg;
+ uint8_t data = 0;
+
+ memset(&ireg, 0, sizeof(ireg));
+
+ ireg.eax.b[1] = 0x11; /* Poll keyboard */
+ __intcall(0x16, &ireg, &oreg);
+
+ if (!(oreg.eflags.l & EFLAGS_ZF))
+ return 1;
+
+ if (SerialPort) {
+ cli();
+
+ /* Already-queued input? */
+ if (SerialTail == SerialHead) {
+ /* LSR */
+ data = inb(SerialPort + 5) & 1;
+ if (data) {
+ /* MSR */
+ data = inb(SerialPort + 6);
+
+ /* Required status bits */
+ if (data) {
+ data &= FlowIgnore;
+ if (data != FlowIgnore)
+ data = 0;
+ else
+ data = 1;
+ }
+ }
+ }
+ sti();
+ }
+
+ return data;
+}
+
+int pm_pollchar(com32sys_t *regs)
+{
+ if (pollchar())
+ regs->eflags.l &= ~EFLAGS_ZF;
+ else
+ regs->eflags.l |= EFLAGS_ZF;
+}
+
+extern void do_idle(void);
+
+/*
+ * getchar: Read a character from keyboard or serial port
+ */
+char getchar(void)
+{
+ com32sys_t ireg, oreg;
+ unsigned char data;
+
+ memset(&ireg, 0, sizeof(ireg));
+ memset(&oreg, 0, sizeof(oreg));
+ while (1) {
+ call16(do_idle, &zero_regs, NULL);
+
+ ireg.eax.b[1] = 0x11; /* Poll keyboard */
+ __intcall(0x16, &ireg, &oreg);
+
+ if (oreg.eflags.l & EFLAGS_ZF) {
+ if (!SerialPort)
+ continue;
+
+ cli();
+ if (SerialTail != SerialHead) {
+ /* serial queued */
+ sti(); /* We already know we'll consume data */
+ data = *SerialTail++;
+
+ SerialTail = (unsigned char *)((unsigned long)SerialTail & (serial_buf_size - 1));
+ } else {
+ /* LSR */
+ data = inb(SerialPort + 5) & 1;
+ if (!data) {
+ sti();
+ continue;
+ }
+ data = inb(SerialPort + 6);
+ data &= FlowIgnore;
+ if (data != FlowIgnore) {
+ sti();
+ continue;
+ }
+
+ data = inb(SerialPort);
+ sti();
+ break;
+ }
+ } else {
+ /* Keyboard input? */
+ ireg.eax.b[1] = 0x10; /* Get keyboard input */
+ __intcall(0x16, &ireg, &oreg);
+
+ data = oreg.eax.b[0];
+ if (data == 0xE0)
+ data = 0;
+
+ if (data) {
+ /* Convert character sets */
+ data = KbdMap[data];
+ }
+ }
+
+ break;
+ }
+
+ reset_idle(); /* Character received */
+ return data;
+}
+
+void pm_getchar(com32sys_t *regs)
+{
+ regs->eax.b[0] = getchar();
+}
+
+static void msg_setbg(char data)
+{
+ if (unhexchar(&data) == 0) {
+ data <<= 4;
+ if (DisplayMask & UsingVGA)
+ TextAttribute = data;
+
+ NextCharJump = msg_setfg;
+ } else {
+ TextAttribute = 0x7; /* Default attribute */
+ NextCharJump = msg_putchar;
+ }
+}
+
+static void msg_setfg(char data)
+{
+ if (unhexchar(&data) == 0) {
+ if (DisplayMask & UsingVGA) {
+ /* setbg set foreground to 0 */
+ TextAttribute |= data;
+ }
+ } else
+ TextAttribute = 0x7; /* Default attribute */
+
+ NextCharJump = msg_putchar;
+}
+
+static inline void msg_ctrl_o(void)
+{
+ NextCharJump = msg_setbg;
+}
+
+static void msg_gotoxy(void)
+{
+ com32sys_t ireg, oreg;
+
+ memset(&ireg, 0, sizeof(ireg));
+
+ ireg.ebx.b[1] = *(uint8_t *)BIOS_page;
+ ireg.edx.w[0] = CursorDX;
+ ireg.eax.b[1] = 0x02; /* Set cursor position */
+
+ __intcall(0x10, &ireg, &oreg);
+}
+
+static void msg_newline(void)
+{
+ com32sys_t ireg, oreg;
+ char crlf_msg[] = { '\r', '\n', '\0' };
+
+ write_serial_str_displaymask(crlf_msg);
+
+ if (!(DisplayMask & UsingVGA))
+ return;
+
+ CursorCol = 0;
+ if ((CursorRow + 1) <= VidRows)
+ CursorRow++;
+ else {
+ ireg.ecx.w[0] = 0x0; /* Upper left hand corner */
+ ireg.edx.w[0] = ScreenSize;
+
+ CursorRow = ireg.edx.b[1]; /* New cursor at the bottom */
+
+ ireg.ebx.b[1] = ScrollAttribute;
+ ireg.eax.w[0] = 0x0601; /* Scroll up one line */
+
+ __intcall(0x10, &ireg, &oreg);
+ }
+
+ msg_gotoxy();
+}
+
+static void msg_formfeed(void)
+{
+ char crff_msg[] = { '\r', '\f', '\0' };
+
+ write_serial_str_displaymask(crff_msg);
+
+ if (DisplayMask & UsingVGA) {
+ com32sys_t ireg, oreg;
+
+ memset(&ireg, 0, sizeof(ireg));
+
+ CursorDX = 0x0; /* Upper left hand corner */
+
+ ireg.edx.w[0] = ScreenSize;
+ ireg.ebx.b[1] = TextAttribute;
+
+ ireg.eax.w[0] = 0x0600; /* Clear screen region */
+ __intcall(0x10, &ireg, &oreg);
+
+ msg_gotoxy();
+ }
+}
+
+static void msg_novga(void)
+{
+ vgaclearmode();
+ msg_initvars();
+}
+
+static void msg_viewimage(void)
+{
+ FILE *f;
+
+ *VGAFilePtr = '\0'; /* Zero-terminate filename */
+
+ mangle_name(VGAFileMBuf, VGAFileBuf);
+ f = fopen(VGAFileMBuf, "r");
+ if (!f) {
+ /* Not there */
+ NextCharJump = msg_putchar;
+ return;
+ }
+
+ vgadisplayfile(f);
+ fclose(f);
+ msg_initvars();
+}
+
+/*
+ * Getting VGA filename
+ */
+static void msg_filename(char data)
+{
+ /* <LF> = end of filename */
+ if (data == 0x0A) {
+ msg_viewimage();
+ return;
+ }
+
+ /* Ignore space/control char */
+ if (data > ' ') {
+ if ((char *)VGAFilePtr < (VGAFileBuf + sizeof(VGAFileBuf)))
+ *VGAFilePtr++ = data;
+ }
+}
+
+static void msg_vga(void)
+{
+ NextCharJump = msg_filename;
+ VGAFilePtr = (uint16_t *)VGAFileBuf;
+}
+
+static void msg_line_wrap(void)
+{
+ if (!(DisplayMask & UsingVGA))
+ return;
+
+ CursorCol = 0;
+ if ((CursorRow + 1) <= VidRows)
+ CursorRow++;
+ else {
+ com32sys_t ireg, oreg;
+
+ memset(&ireg, 0, sizeof(ireg));
+
+ ireg.ecx.w[0] = 0x0; /* Upper left hand corner */
+ ireg.edx.w[0] = ScreenSize;
+
+ CursorRow = ireg.edx.b[1]; /* New cursor at the bottom */
+
+ ireg.ebx.b[1] = ScrollAttribute;
+ ireg.eax.w[0] = 0x0601; /* Scroll up one line */
+
+ __intcall(0x10, &ireg, &oreg);
+ }
+
+ msg_gotoxy();
+}
+
+static void msg_normal(char data)
+{
+ com32sys_t ireg, oreg;
+
+ /* Write to serial port */
+ write_serial_displaymask(data);
+
+ if (!(DisplayMask & UsingVGA))
+ return; /* Not screen */
+
+ if (!(DisplayCon & 0x01))
+ return;
+
+ memset(&ireg, 0, sizeof(ireg));
+
+ ireg.ebx.b[0] = TextAttribute;
+ ireg.ebx.b[1] = *(uint8_t *)BIOS_page;
+ ireg.eax.b[0] = data;
+ ireg.eax.b[1] = 0x09; /* Write character/attribute */
+ ireg.ecx.w[0] = 1; /* One character only */
+
+ /* Write to screen */
+ __intcall(0x10, &ireg, &oreg);
+
+ if ((CursorCol + 1) <= VidCols) {
+ CursorCol++;
+ msg_gotoxy();
+ } else
+ msg_line_wrap(); /* Screen wraparound */
+}
+
+static void msg_modectl(char data)
+{
+ data &= 0x07;
+ DisplayMask = data;
+ NextCharJump = msg_putchar;
+}
+
+static void msg_putchar(char ch)
+{
+ /* 10h to 17h are mode controls */
+ if (ch >= 0x10 && ch < 0x18) {
+ msg_modectl(ch);
+ return;
+ }
+
+ switch (ch) {
+ case 0x0F: /* ^O = color code follows */
+ msg_ctrl_o();
+ break;
+ case 0x0D: /* Ignore <CR> */
+ break;
+ case 0x0A: /* <LF> = newline */
+ msg_newline();
+ break;
+ case 0x0C: /* <FF> = clear screen */
+ msg_formfeed();
+ break;
+ case 0x07: /* <BEL> = beep */
+ msg_beep();
+ break;
+ case 0x19: /* <EM> = return to text mode */
+ msg_novga();
+ break;
+ case 0x18: /* <CAN> = VGA filename follows */
+ msg_vga();
+ break;
+ default:
+ msg_normal(ch);
+ break;
+ }
+}
+
+/*
+ * Subroutine to initialize variables, also needed after loading
+ * graphics file.
+ */
+void msg_initvars(void)
+{
+ com32sys_t ireg, oreg;
+
+ ireg.eax.b[1] = 0x3; /* Read cursor position */
+ ireg.ebx.b[1] = *(uint8_t *)BIOS_page;
+ __intcall(0x10, &ireg, &oreg);
+
+ CursorDX = oreg.edx.w[0];
+
+ /* Initialize state machine */
+ NextCharJump = msg_putchar;
+}
diff --git a/core/conio.inc b/core/conio.inc
deleted file mode 100644
index ec2aa2a6..00000000
--- a/core/conio.inc
+++ /dev/null
@@ -1,435 +0,0 @@
-;; -----------------------------------------------------------------------
-;;
-;; Copyright 1994-2008 H. Peter Anvin - All Rights Reserved
-;; Copyright 2009 Intel Corporation; author: H. Peter Anvin
-;;
-;; This program is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
-;; Boston MA 02111-1307, USA; either version 2 of the License, or
-;; (at your option) any later version; incorporated herein by reference.
-;;
-;; -----------------------------------------------------------------------
-
-;;
-;; conio.inc
-;;
-;; Console I/O code, except:
-;; writechr, writestr_early - module-dependent
-;; writestr, crlf - writestr.inc
-;; writehex* - writehex.inc
-;;
-
-;
-; loadkeys: Load a LILO-style keymap; file is open on the top of the
-; getc stack.
-;
- section .text16
-
- global loadkeys
-loadkeys:
- mov cx,256
- mov di,trackbuf
- call readc
- jc .done ; EOF already?
-
- ; Make sure we are at EOF now...
- call getc
- jnc .done ; We should be at EOF now!
-
- ; It was okay, we can now move it into the KbdMap
- mov si,trackbuf
- mov di,KbdMap
- mov cx,256 >> 2
- rep movsd
-
-.done:
- call close
- ret
-
-;
-; get_msg_file: Load a text file and write its contents to the screen,
-; interpreting color codes. Call with the file already
-; on the top of the open/getc stack.
-;
-; Assumes CS == DS == ES.
-;
- global get_msg_file
-get_msg_file:
- mov byte [TextAttribute],07h ; Default grey on white
- mov byte [DisplayMask],07h ; Display text in all modes
- call msg_initvars
-
-print_msg_file:
-.getc:
- call getc
- jc .done
- cmp al,1Ah ; DOS EOF?
- je .done
- movzx cx,byte [UsingVGA]
- and cl,01h
- inc cx ; CL <- 01h = text mode,
- ; 02h = graphics mode
- call [NextCharJump] ; Do what shall be done
- jmp .getc
-.done:
- jmp close ; Tailcall!
-
-msg_putchar: ; Normal character
- cmp al,0Fh ; ^O = color code follows
- je msg_ctrl_o
- cmp al,0Dh ; Ignore <CR>
- je msg_ignore
- cmp al,0Ah ; <LF> = newline
- je msg_newline
- cmp al,0Ch ; <FF> = clear screen
- je msg_formfeed
- cmp al,07h ; <BEL> = beep
- je msg_beep
- cmp al,19h ; <EM> = return to text mode
- je msg_novga
- cmp al,18h ; <CAN> = VGA filename follows
- je msg_vga
- jnb .not_modectl
- cmp al,10h ; 10h to 17h are mode controls
- jae msg_modectl
-.not_modectl:
-
-msg_normal: call write_serial_displaymask ; Write to serial port
- test [DisplayMask],cl
- jz msg_ignore ; Not screen
- test byte [DisplayCon],01h
- jz msg_ignore
- mov bl,[TextAttribute]
- mov bh,[BIOS_page]
- mov ah,09h ; Write character/attribute
- mov cx,1 ; One character only
- int 10h ; Write to screen
- mov al,[CursorCol]
- inc ax
- cmp al,[VidCols]
- ja msg_line_wrap ; Screen wraparound
- mov [CursorCol],al
-
-msg_gotoxy: mov bh,[BIOS_page]
- mov dx,[CursorDX]
- mov ah,02h ; Set cursor position
- int 10h
-msg_ignore: ret
-
-msg_beep: mov ax,0E07h ; Beep
- xor bx,bx
- int 10h
- ret
-
-msg_ctrl_o: ; ^O = color code follows
- mov word [NextCharJump],msg_setbg
- ret
-msg_newline: ; Newline char or end of line
- mov si,crlf_msg
- call write_serial_str_displaymask
-msg_line_wrap: ; Screen wraparound
- test [DisplayMask],cl
- jz msg_ignore
- mov byte [CursorCol],0
- mov al,[CursorRow]
- inc ax
- cmp al,[VidRows]
- ja msg_scroll
- mov [CursorRow],al
- jmp short msg_gotoxy
-msg_scroll: xor cx,cx ; Upper left hand corner
- mov dx,[ScreenSize]
- mov [CursorRow],dh ; New cursor at the bottom
- mov bh,[ScrollAttribute]
- mov ax,0601h ; Scroll up one line
- int 10h
- jmp short msg_gotoxy
-msg_formfeed: ; Form feed character
- mov si,crff_msg
- call write_serial_str_displaymask
- test [DisplayMask],cl
- jz msg_ignore
- xor cx,cx
- mov [CursorDX],cx ; Upper lefthand corner
- mov dx,[ScreenSize]
- mov bh,[TextAttribute]
- mov ax,0600h ; Clear screen region
- int 10h
- jmp msg_gotoxy
-msg_setbg: ; Color background character
- call unhexchar
- jc msg_color_bad
- shl al,4
- test [DisplayMask],cl
- jz .dontset
- mov [TextAttribute],al
-.dontset:
- mov word [NextCharJump],msg_setfg
- ret
-msg_setfg: ; Color foreground character
- call unhexchar
- jc msg_color_bad
- test [DisplayMask],cl
- jz .dontset
- or [TextAttribute],al ; setbg set foreground to 0
-.dontset:
- jmp short msg_putcharnext
-msg_vga:
- mov word [NextCharJump],msg_filename
- mov di, VGAFileBuf
- jmp short msg_setvgafileptr
-
-msg_color_bad:
- mov byte [TextAttribute],07h ; Default attribute
-msg_putcharnext:
- mov word [NextCharJump],msg_putchar
- ret
-
-msg_filename: ; Getting VGA filename
- cmp al,0Ah ; <LF> = end of filename
- je msg_viewimage
- cmp al,' '
- jbe msg_ret ; Ignore space/control char
- mov di,[VGAFilePtr]
- cmp di,VGAFileBufEnd
- jnb msg_ret
- mov [di],al ; Can't use stosb (DS:)
- inc di
-msg_setvgafileptr:
- mov [VGAFilePtr],di
-msg_ret: ret
-
-msg_novga:
- call vgaclearmode
- jmp short msg_initvars
-
-msg_viewimage:
- mov si,[VGAFilePtr]
- mov byte [si],0 ; Zero-terminate filename
- mov si,VGAFileBuf
- mov di,VGAFileMBuf
- pm_call pm_mangle_name
- call core_open
- jz msg_putcharnext ; Not there
- call vgadisplayfile
- ; Fall through
-
- ; Subroutine to initialize variables, also needed
- ; after loading a graphics file
-msg_initvars:
- pusha
- mov bh,[BIOS_page]
- mov ah,03h ; Read cursor position
- int 10h
- mov [CursorDX],dx
- popa
- jmp short msg_putcharnext ; Initialize state machine
-
-msg_modectl:
- and al,07h
- mov [DisplayMask],al
- jmp short msg_putcharnext
-
-;
-; write_serial: If serial output is enabled, write character on serial port
-; write_serial_displaymask: d:o, but ignore if DisplayMask & 04h == 0
-;
-write_serial_displaymask:
- test byte [DisplayMask], 04h
- jz write_serial.end
-write_serial:
- pushfd
- pushad
- mov bx,[SerialPort]
- and bx,bx
- je .noserial
- push ax
- mov ah,[FlowInput]
-.waitspace:
- ; Wait for space in transmit register
- lea dx,[bx+5] ; DX -> LSR
- in al,dx
- test al,20h
- jz .waitspace
-
- ; Wait for input flow control
- inc dx ; DX -> MSR
- in al,dx
- and al,ah
- cmp al,ah
- jne .waitspace
-.no_flow:
-
- xchg dx,bx ; DX -> THR
- pop ax
- slow_out dx,al ; Send data
-.noserial: popad
- popfd
-.end: ret
-
-;
-; write_serial_str: write_serial for strings
-; write_serial_str_displaymask: d:o, but ignore if DisplayMask & 04h == 0
-;
-write_serial_str_displaymask:
- test byte [DisplayMask], 04h
- jz write_serial_str.end
-
- global write_serial_str
-write_serial_str:
-.loop lodsb
- and al,al
- jz .end
- call write_serial
- jmp short .loop
-.end: ret
-
-;
-; pollchar: check if we have an input character pending (ZF = 0)
-;
-pollchar:
- pushad
- mov ah,11h ; Poll keyboard
- int 16h
- jnz .done ; Keyboard response
- mov dx,[SerialPort]
- and dx,dx
- jz .done ; No serial port -> no input
- mov ax,[SerialTail] ; Already-queued input?
- cli
- cmp ax,[SerialHead]
- jne .done_sti ; If so, return ZF = 0
- add dx,5 ; DX -> LSR
- in al,dx
- test al,1 ; ZF = 0 if data pending
- jz .done_sti
- inc dx ; DX -> MSR
- mov ah,[FlowIgnore] ; Required status bits
- in al,dx
- and al,ah
- cmp al,ah
- setne al
- dec al ; Set ZF = 0 if equal
-.done_sti: sti
-.done: popad
- ret
-
-;
-; getchar: Read a character from keyboard or serial port
-;
-getchar.sti_again:
- sti
-getchar:
-.again:
- call do_idle
- mov ah,11h ; Poll keyboard
- int 16h
- jnz .kbd ; Keyboard input?
- mov bx,[SerialPort]
- and bx,bx
- jz .again
- mov ax,[SerialTail]
- cli
- cmp ax,[SerialHead]
- jne .serial_queued
- lea dx,[bx+5] ; DX -> LSR
- in al,dx
- test al,1
- jz .sti_again
- inc dx ; DX -> MSR
- mov ah,[FlowIgnore]
- in al,dx
- and al,ah
- cmp al,ah
- jne .sti_again
-.serial: xor ah,ah ; Avoid confusion
- mov dx,bx ; Data port
- in al,dx ; Read data
- sti
- jmp .done
-.serial_queued:
- sti ; We already know we'll consume data
- xchg bx,ax
- push ds
- mov ax,aux_seg + (aux.serial >> 4)
- mov ds,ax
- mov al,[bx]
- pop ds
- inc bx
- and bx,serial_buf_size-1
- mov [SerialTail],bx
- jmp .done
-
-.kbd: mov ah,10h ; Get keyboard input
- int 16h
- cmp al,0E0h
- jnz .not_ext
- xor al,al
-.not_ext:
- and al,al
- jz .func_key
- mov bx,KbdMap ; Convert character sets
- xlatb
-.func_key:
-.done:
- jmp reset_idle ; Character received
-
-%ifdef DEBUG_TRACERS
-;
-; debug hack to print a character with minimal code impact
-;
-debug_tracer: pushad
- pushfd
- mov bp,sp
- mov bx,[bp+9*4] ; Get return address
- mov al,[cs:bx] ; Get data byte
- inc word [bp+9*4] ; Return to after data byte
- call writechr
- popfd
- popad
- ret
-%endif ; DEBUG_TRACERS
-
- section .data16
-%if IS_ISOLINUX == 0 ; Defined elsewhere for ISOLINUX
-crlf_msg db CR, LF
-null_msg db 0
-%endif
-crff_msg db CR, FF, 0
-
- section .config
- ; This is a word to pc_setint16 can set it
-DisplayCon dw 01h ; Console display enabled
-
-ScrollAttribute db 07h ; Grey on white (normal text color)
-
- section .bss16
- alignb 2
-NextCharJump resw 1 ; Routine to interpret next print char
-CursorDX equ $
-CursorCol resb 1 ; Cursor column for message file
-CursorRow resb 1 ; Cursor row for message file
-ScreenSize equ $
-VidCols resb 1 ; Columns on screen-1
-VidRows resb 1 ; Rows on screen-1
-
-; Serial console stuff; don't put this in .config becasue we don't want
-; loading a new config file to undo this setting.
- section .data16
- alignz 4
- global SerialPort, BaudDivisor, FlowIgnore, FlowInput, FlowOutput
-SerialPort dw 0 ; Serial port base (or 0 for no serial port)
-BaudDivisor dw 115200/9600 ; Baud rate divisor
-FlowControl equ $
-FlowOutput db 0 ; Outputs to assert for serial flow
-FlowInput db 0 ; Input bits for serial flow
-FlowIgnore db 0 ; Ignore input unless these bits set
-FlowDummy db 0 ; Unused
-
- section .bss16
-TextAttribute resb 1 ; Text attribute for message file
-DisplayMask resb 1 ; Display modes mask
-
- section .text16
-%include "serirq.inc"
diff --git a/core/diskfs.inc b/core/diskfs.inc
index 26843281..5a029d36 100644
--- a/core/diskfs.inc
+++ b/core/diskfs.inc
@@ -115,9 +115,7 @@ kaboom2:
; -----------------------------------------------------------------------------
%include "common.inc" ; Universal modules
-%include "plaincon.inc" ; writechr
%include "writestr.inc" ; String output
-%include "writehex.inc" ; Hexadecimal output
%include "localboot.inc" ; Disk-based local boot
; -----------------------------------------------------------------------------
diff --git a/core/extern.inc b/core/extern.inc
index 90599f2f..dea60521 100644
--- a/core/extern.inc
+++ b/core/extern.inc
@@ -51,4 +51,25 @@
extern unload_pxe, reset_pxe
%endif
+ ; plaincon.c
+ extern pm_writechr
+
+ ; cleanup.c
+ extern cleanup_hardware
+
+ ; writestr.c
+ extern pm_writestr, crlf
+
+ ; writehex.c
+ extern pm_writehex2, pm_writehex4, pm_writehex8
+
+ ; graphics.c
+ extern vgaclearmode, vgashowcursor, vgahidecursor
+
+ ; conio.c
+ extern pm_pollchar, pm_write_serial, pm_serialcfg
+
+ ; font.c
+ extern pm_getchar, pm_adjust_screen, pm_usingvga, pm_userfont
+
%endif ; EXTERN_INC
diff --git a/core/font.c b/core/font.c
new file mode 100644
index 00000000..b14d3d2a
--- /dev/null
+++ b/core/font.c
@@ -0,0 +1,195 @@
+/*
+ * -----------------------------------------------------------------------
+ *
+ * Copyright 1994-2008 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ * Boston MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * -----------------------------------------------------------------------
+ *
+ *
+ * font.c
+ *
+ * VGA font handling code
+ *
+ */
+
+#include <sys/io.h>
+#include <stdio.h>
+#include <fs.h>
+#include "bios.h"
+#include "core.h"
+
+struct aux {
+ char fontbuf[8192];
+ char serial[serial_buf_size];
+};
+
+#define fontbuf offsetof(struct aux, fontbuf)
+
+extern uint16_t VGAFontSize;
+extern uint8_t UserFont;
+
+uint16_t GXPixCols = 1; /* Graphics mode pixel columns */
+uint16_t GXPixRows = 1; /* Graphics mode pixel rows */
+
+/*
+ * loadfont: Load a .psf font file and install it onto the VGA console
+ * (if we're not on a VGA screen then ignore.)
+ *
+ * The .psf font file must alredy be open and getc_file must be set.
+ */
+void loadfont(char *filename)
+{
+ uint16_t height, magic;
+ uint32_t *di, *si;
+ FILE *f;
+ char *p;
+ int i;
+
+ f = fopen(filename, "r");
+ if (!f)
+ return;
+
+ p = trackbuf;
+ /* Read header */
+ for (i = 0; i < 4; i++) {
+ char ch = getc(f);
+ if (ch == EOF)
+ return;
+ *p++ = ch;
+ }
+
+ /* Magic number */
+ magic = *(uint16_t *)trackbuf;
+ if (magic != 0x0436)
+ return;
+
+ /* File mode: font modes 0-5 supported */
+ if (*(trackbuf) > 5)
+ return;
+
+ height = *(trackbuf + 3); /* Height of font */
+
+ /* VGA minimum/maximum */
+ if (height < 2 || height > 32)
+ return;
+
+ /* Load the actual font. Bytes = font height * 256 */
+ p = trackbuf;
+ for (i = 0; i < (height << 8); i++) {
+ char ch = getc(f);
+
+ if (ch == EOF)
+ return;
+ *p++ = ch;
+ }
+
+ /* Copy to font buffer */
+ VGAFontSize = height;
+ di = (uint32_t *)MK_PTR(aux_seg, fontbuf);
+ si = (uint32_t *)trackbuf;
+ for (i = 0; i < (height << 6); i++)
+ *di++ = *si++;
+
+ UserFont = 1; /* Set font flag */
+ use_font();
+}
+
+/*
+ * use_font:
+ * This routine activates whatever font happens to be in the
+ * vgafontbuf, and updates the adjust_screen data.
+ * Must be called with CS = DS
+ */
+void use_font(void)
+{
+ com32sys_t ireg, oreg;
+ uint8_t bytes = VGAFontSize;
+
+
+ /* Nonstandard mode? */
+ if (UsingVGA & ~0x3)
+ vgaclearmode();
+
+ memset(&ireg, 0, sizeof(ireg));
+
+ ireg.es = aux_seg;
+ ireg.ebp.w[0] = fontbuf; /* ES:BP -> font */
+
+ /* Are we using a user-specified font? */
+ if (UserFont & 0x1) {
+ /* Are we in graphics mode? */
+ if (UsingVGA & 0x1) {
+ uint8_t rows;
+
+ rows = GXPixRows / bytes;
+ VidRows = rows - 1;
+
+ /* Set user character table */
+ ireg.eax.w[0] = 0x1121;
+ ireg.ebx.b[0] = 0;
+ ireg.ecx.b[0] = bytes; /* bytes/character */
+ ireg.edx.b[0] = rows;
+
+ __intcall(0x10, &ireg, &oreg);
+
+ /* 8 pixels/character */
+ VidCols = ((GXPixCols >> 3) - 1);
+
+ /* No need to call adjust_screen */
+ return;
+ } else {
+ ireg.eax.w[0] = 0x1110; /* Load into VGA RAM */
+ ireg.ebx.b[0] = 0;
+ ireg.ebx.b[1] = bytes; /* bytes/character */
+ ireg.ecx.w[0] = 256;
+ ireg.edx.w[0] = 0;
+
+ __intcall(0x10, &ireg, &oreg);
+
+ ireg.ebx.b[0] = 0;
+ ireg.eax.w[0] = 0x1103; /* Select page 0 */
+ __intcall(0x10, &ireg, NULL);
+ }
+ }
+
+ adjust_screen();
+}
+
+/*
+ * adjust_screen: Set the internal variables associated with the screen size.
+ * This is a subroutine in case we're loading a custom font.
+ */
+void adjust_screen(void)
+{
+ com32sys_t ireg, oreg;
+ volatile uint8_t *vidrows = BIOS_vidrows;
+ uint8_t rows, cols;
+
+ rows = *vidrows;
+ if (!rows) {
+ /*
+ * No vidrows in BIOS, assume 25.
+ * (Remember: vidrows == rows-1)
+ */
+ rows = 24;
+ }
+
+ VidRows = rows;
+
+ ireg.eax.b[1] = 0x0f; /* Read video state */
+ __intcall(0x10, &ireg, &oreg);
+ cols = oreg.eax.b[1];
+
+ VidCols = --cols; /* Store count-1 (same as rows) */
+}
+
+void pm_adjust_screen(com32sys_t *regs)
+{
+ adjust_screen();
+}
diff --git a/core/font.inc b/core/font.inc
deleted file mode 100644
index 9e840e4c..00000000
--- a/core/font.inc
+++ /dev/null
@@ -1,153 +0,0 @@
-;; -----------------------------------------------------------------------
-;;
-;; Copyright 1994-2008 H. Peter Anvin - All Rights Reserved
-;;
-;; This program is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
-;; Boston MA 02111-1307, USA; either version 2 of the License, or
-;; (at your option) any later version; incorporated herein by reference.
-;;
-;; -----------------------------------------------------------------------
-
-;;
-;; font.inc
-;;
-;; VGA font handling code
-;;
-
- section .text16
-
-;
-; loadfont: Load a .psf font file and install it onto the VGA console
-; (if we're not on a VGA screen then ignore.)
-; The font is on top of the getc stack.
-;
-loadfont.err: jmp close ; Tailcall the close routine
-
- global loadfont
-loadfont:
- mov di,trackbuf
- mov cx,4
- call readc ; Read header
- jc .err
-
- mov ax,[trackbuf] ; Magic number
- cmp ax,0436h
- jne .err
-
- mov al,[trackbuf+2] ; File mode
- cmp al,5 ; Font modes 0-5 supported
- ja .err
-
- xor bx,bx
- mov bh,[trackbuf+3] ; Height of font
- cmp bh,2 ; VGA minimum
- jb .err
- cmp bh,32 ; VGA maximum
- ja .err
-
- ; Load the actual font
- mov di,trackbuf
- mov cx,bx ; Bytes = font height * 256
- call readc
- jc .err
-
- call close
-
- ; Copy to font buffer
- mov si,trackbuf ; Start of font data
- mov [VGAFontSize],bh
- push es
- mov cx,aux_seg
- mov es,cx
- mov di,aux.fontbuf
- mov cx,bx
- shr cx,2
- rep movsd
- pop es
-
- mov [UserFont], byte 1 ; Set font flag
-
-;
-; use_font:
-; This routine activates whatever font happens to be in the
-; vgafontbuf, and updates the adjust_screen data.
-; Must be called with CS = DS
-;
-use_font:
- test byte [UsingVGA], ~03h ; Nonstandard mode?
- jz .modeok
- call vgaclearmode
-
-.modeok:
- test [UserFont], byte 1 ; Are we using a user-specified font?
- jz adjust_screen ; If not, just do the normal stuff
-
- push es
- mov bp,aux_seg
- mov es,bp
-
- mov bp,aux.fontbuf ; ES:BP -> font
- mov bh,[VGAFontSize]
- xor bl,bl ; Needed by both INT 10h calls
-
- test byte [UsingVGA], 01h ; Are we in graphics mode?
- jz .text
-
-.graphics:
- xor cx,cx
- mov cl,bh ; CX = bytes/character
- mov ax,[GXPixRows]
- div cl ; Compute char rows per screen
- mov dl,al
- dec ax
- mov [VidRows],al
- mov ax,1121h ; Set user character table
- int 10h
- mov ax,[GXPixCols]
- shr ax,3 ; 8 pixels/character
- dec ax
- mov [VidCols],al
- pop es
- ret ; No need to call adjust_screen
-
-.text:
- mov cx,256
- xor dx,dx
- mov ax,1110h
- int 10h ; Load into VGA RAM
- pop es
-
- xor bl,bl
- mov ax,1103h ; Select page 0
- int 10h
-
-;
-; adjust_screen: Set the internal variables associated with the screen size.
-; This is a subroutine in case we're loading a custom font.
-;
-adjust_screen:
- pusha
- mov al,[BIOS_vidrows]
- and al,al
- jnz vidrows_ok
- mov al,24 ; No vidrows in BIOS, assume 25
- ; (Remember: vidrows == rows-1)
-vidrows_ok: mov [VidRows],al
- mov ah,0fh
- int 10h ; Read video state
- dec ah ; Store count-1 (same as rows)
- mov [VidCols],ah
- popa
- ret
-
- section .data16
- alignz 2
-VGAFontSize dw 16 ; Defaults to 16 byte font
-UserFont db 0 ; Using a user-specified font
-
- section .bss16
- alignb 4
-GXPixCols resw 1 ; Graphics mode pixel columns
-GXPixRows resw 1 ; Graphics mode pixel rows
diff --git a/core/graphics.c b/core/graphics.c
new file mode 100644
index 00000000..7ca20ea1
--- /dev/null
+++ b/core/graphics.c
@@ -0,0 +1,382 @@
+/*
+ * -----------------------------------------------------------------------
+ *
+ * Copyright 1994-2008 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ * Boston MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * -----------------------------------------------------------------------
+ *
+ * -----------------------------------------------------------------------
+ * VGA splash screen code
+ * -----------------------------------------------------------------------
+ */
+
+#include <stddef.h>
+#include "core.h"
+#include <sys/io.h>
+#include "fs.h"
+#include "bios.h"
+
+uint8_t UsingVGA = 0;
+uint16_t VGAPos; /* Pointer into VGA memory */
+uint16_t *VGAFilePtr; /* Pointer into VGAFileBuf */
+
+char VGAFileBuf[VGA_FILE_BUF_SIZE]; /* Unmangled VGA image name */
+char VGAFileMBuf[FILENAME_MAX]; /* Mangled VGA image name */
+
+static uint8_t VGARowBuffer[640 + 80]; /* Decompression buffer */
+static uint8_t VGAPlaneBuffer[(640/8) * 4]; /* Plane buffers */
+
+extern uint16_t GXPixCols;
+extern uint16_t GXPixRows;
+
+/* Maps colors to consecutive DAC registers */
+static uint8_t linear_color[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 0 };
+
+static FILE *fd;
+
+typedef struct {
+ uint32_t LSSMagic; /* Magic number */
+ uint16_t GraphXSize; /* Width of splash screen file */
+ uint16_t GraphYSize; /* Height of splash screen file */
+ uint8_t GraphColorMap[3*16];
+} lssheader_t;
+
+static lssheader_t LSSHeader;
+
+#define LSSMagic LSSHeader.LSSMagic
+#define GraphXSize LSSHeader.GraphXSize
+#define GraphYSize LSSHeader.GraphYSize
+
+/*
+ * Enable VGA graphics, if possible. Return 0 on success.
+ */
+static int vgasetmode(void)
+{
+ com32sys_t ireg, oreg;
+
+ if (UsingVGA)
+ return 0; /* Nothing to do... */
+
+ memset(&ireg, 0, sizeof(ireg));
+ memset(&oreg, 0, sizeof(oreg));
+
+ if (UsingVGA & 0x4) {
+ /*
+ * We're in VESA mode, which means VGA; use VESA call
+ * to revert the mode, and then call the conventional
+ * mode-setting for good measure...
+ */
+ ireg.eax.w[0] = 0x4F02;
+ ireg.ebx.w[0] = 0x0012;
+ __intcall(0x10, &ireg, &oreg);
+ } else {
+ /* Get video card and monitor */
+ ireg.eax.w[0] = 0x1A00;
+ __intcall(0x10, &ireg, &oreg);
+ oreg.ebx.b[0] -= 7; /* BL=07h and BL=08h OK */
+
+ if (oreg.ebx.b[0] > 1)
+ return -1;
+ }
+
+ /*
+ * Set mode.
+ */
+ ireg.eax.w[0] = 0x0012; /* Set mode = 640x480 VGA 16 colors */
+ __intcall(0x10, &ireg, &oreg);
+
+ ireg.edx.w[0] = (uint16_t)linear_color;
+ ireg.eax.w[0] = 0x1002; /* Write color registers */
+ __intcall(0x10, &ireg, &oreg);
+
+ UsingVGA = 1;
+
+ /* Set GXPixCols and GXPixRows */
+ GXPixCols = 640+(480 << 16);
+
+ use_font();
+ ScrollAttribute = 0;
+
+ return 0;
+}
+
+static inline char getnybble(void)
+{
+ char data = getc(fd);
+
+ if (data & 0x10) {
+ data &= 0x0F;
+ return data;
+ }
+
+ data = getc(fd);
+ return (data & 0x0F);
+}
+
+/*
+ * rledecode:
+ * Decode a pixel row in RLE16 format.
+ *
+ * 'in': input (RLE16 encoded) buffer
+ * 'out': output (decoded) buffer
+ * 'count': pixel count
+ */
+static void rledecode(uint8_t *out, size_t count)
+{
+ uint8_t prev_pixel = 0;
+ size_t size = count;
+ uint8_t data;
+ int i;
+
+again:
+ for (i = 0; i < size; i++) {
+
+ data = getnybble();
+ if (data == prev_pixel)
+ break;
+
+ *out++ = data;
+ prev_pixel = data;
+ }
+
+ size -= i;
+ if (!size)
+ return;
+
+ /* Start of run sequence */
+ data = getnybble();
+ if (data == 0) {
+ /* long run */
+ uint8_t hi;
+
+ data = getnybble();
+ hi = getnybble();
+ hi <<= 4;
+ data |= hi;
+ data += 16;
+ }
+
+ /* dorun */
+ for (i = 0; i < data; i++)
+ *out++ = prev_pixel;
+
+ size -= i;
+ if (size)
+ goto again;
+}
+
+/*
+ * packedpixel2vga:
+ * Convert packed-pixel to VGA bitplanes
+ *
+ * 'in': packed pixel string
+ * 'out': output (four planes)
+ * 'count': pixel count (multiple of 8)
+ */
+static void packedpixel2vga(uint8_t *in, uint8_t *out, size_t count)
+{
+ uint8_t bx, al, dl;
+ int plane, pixel;
+
+ for (plane = 0; plane < 4; plane++) {
+ for (bx = 0; bx < count; bx += 8) {
+ for (pixel = 0; pixel < 8; pixel++) {
+ al = *in++;
+ al >>= plane;
+
+ /*
+ * VGA is bigendian. Sigh.
+ * Left rotate through carry
+ */
+ dl = dl << 1 | (dl >> (8 - 1));
+ }
+
+ *out++ = dl;
+ }
+ }
+}
+
+/*
+ * outputvga:
+ * Output four subsequent lines of VGA data
+ *
+ * 'in': four planes @ 640/8=80 bytes
+ * 'out': pointer into VGA memory
+ */
+static void outputvga(uint32_t *in, uint32_t *out)
+{
+ uint8_t val, *addr;
+ int i, j;
+
+ addr = (uint8_t *)0x3C4; /* VGA Sequencer Register select port */
+ val = 2; /* Sequencer mask */
+
+ /* Select the sequencer mask */
+ outb(val, (uint16_t)addr);
+
+ addr += 1; /* VGA Sequencer Register data port */
+ for (i = 1; i <= 8; i *= 2) {
+ /* Select the bit plane to write */
+ outb(i, (uint16_t)addr);
+
+ for (j = 0; j < (640 / 32); j++)
+ *(out + j) = *(in + j);
+ }
+}
+
+/*
+ * Display a graphical splash screen.
+ */
+void vgadisplayfile(FILE *_fd)
+{
+ char *p;
+ int size;
+
+ fd = _fd;
+
+ /*
+ * This is a cheap and easy way to make sure the screen is
+ * cleared in case we were in graphics mode aready.
+ */
+ vgaclearmode();
+ vgasetmode();
+
+ size = 4+2*2+16*3;
+ p = (char *)&LSSHeader;
+
+ /* Load the header */
+ while (size--)
+ *p = getc(fd);
+
+ if (*p != EOF) {
+ com32sys_t ireg, oreg;
+ uint16_t rows;
+ int i;
+
+ /* The header WILL be in the first chunk. */
+ if (LSSMagic != 0x1413f33d)
+ return;
+
+ memset(&ireg, 0, sizeof(ireg));
+
+ /* Color map offset */
+ ireg.edx.w[0] = offsetof(lssheader_t, GraphColorMap);
+
+ ireg.eax.w[0] = 0x1012; /* Set RGB registers */
+ ireg.ebx.w[0] = 0; /* First register number */
+ ireg.ecx.w[0] = 16; /* 16 registers */
+ __intcall(0x10, &ireg, &oreg);
+
+ /* Number of pixel rows */
+ rows = (GraphYSize + VGAFontSize) - 1;
+ rows = rows / VGAFontSize;
+ if (rows >= VidRows)
+ rows = VidRows - 1;
+
+ memset(&ireg, 0, sizeof(ireg));
+
+ ireg.edx.b[1] = rows;
+ ireg.eax.b[1] = 2;
+ ireg.ebx.w[0] = 0;
+
+ /* Set cursor below image */
+ __intcall(0x10, &ireg, &oreg);
+
+ rows = GraphYSize; /* Number of graphics rows */
+ VGAPos = 0;
+
+ for (i = 0; i < rows; i++) {
+ /* Pre-clear the row buffer */
+ memset(VGARowBuffer, 0, 640);
+
+ /* Decode one row */
+ rledecode(VGARowBuffer, GraphXSize);
+
+ packedpixel2vga(VGARowBuffer, VGAPlaneBuffer, 640);
+ outputvga(VGAPlaneBuffer, MK_PTR(0x0A000, VGAPos));
+ VGAPos += 640/8;
+ }
+ }
+}
+
+/*
+ * Disable VGA graphics.
+ */
+void vgaclearmode(void)
+{
+ com32sys_t ireg, oreg;
+
+ /* Already in text mode? */
+ if (!UsingVGA)
+ return;
+
+ if (UsingVGA & 0x4) {
+ /* VESA return to normal video mode */
+ memset(&ireg, 0, sizeof(ireg));
+
+ ireg.eax.w[0] = 0x4F02; /* Set SuperVGA video mode */
+ ireg.ebx.w[0] = 0x0003;
+ __intcall(0x10, &ireg, &oreg);
+ }
+
+ /* Return to normal video mode */
+ memset(&ireg, 0, sizeof(ireg));
+ ireg.eax.w[0] = 0x0003;
+ __intcall(0x10, &ireg, &oreg);
+
+ UsingVGA = 0;
+
+ ScrollAttribute = 0x7;
+ /* Restore text font/data */
+ use_font();
+}
+
+static void vgacursorcommon(char data)
+{
+ if (UsingVGA) {
+ com32sys_t ireg;
+
+ ireg.eax.b[0] = data;
+ ireg.eax.b[1] = 0x09;
+ ireg.ebx.w[0] = 0x0007;
+ ireg.ecx.w[0] = 1;
+ __intcall(0x10, &ireg, NULL);
+ }
+}
+
+void vgahidecursor(void)
+{
+ vgacursorcommon(' ');
+}
+
+void vgashowcursor(void)
+{
+ vgacursorcommon('_');
+}
+
+void pm_usingvga(com32sys_t *regs)
+{
+ if (regs->eax.w[0] > 0x0F) {
+ /* Unknown flags = failure */
+ set_flags(regs, EFLAGS_CF);
+ return;
+ }
+
+ UsingVGA = regs->eax.b[0];
+ GXPixCols = regs->ecx.w[0];
+ GXPixRows = regs->edx.w[0];
+
+ if (UsingVGA & 0x08)
+ regs->eflags.l &= ~EFLAGS_CF;
+ else {
+ adjust_screen();
+ set_flags(regs, EFLAGS_CF);
+ }
+}
diff --git a/core/graphics.inc b/core/graphics.inc
deleted file mode 100644
index a8d28515..00000000
--- a/core/graphics.inc
+++ /dev/null
@@ -1,353 +0,0 @@
-;; -----------------------------------------------------------------------
-;;
-;; Copyright 1994-2008 H. Peter Anvin - All Rights Reserved
-;;
-;; This program is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
-;; Boston MA 02111-1307, USA; either version 2 of the License, or
-;; (at your option) any later version; incorporated herein by reference.
-;;
-;; -----------------------------------------------------------------------
-
-; ----------------------------------------------------------------------------
-; VGA splash screen code
-; ----------------------------------------------------------------------------
-
-;
-; vgadisplayfile:
-; Display a graphical splash screen.
-; The file is already opened on the top of the getc stack.
-;
-; Assumes CS == DS == ES.
-;
- section .text16
-
-vgadisplayfile:
- ; This is a cheap and easy way to make sure the screen is
- ; cleared in case we were in graphics mode already
- call vgaclearmode
- call vgasetmode
- jnz .error_nz
-
-.graphalready:
- ; Load the header.
- mov cx,4+2*2+16*3
- mov di,LSSHeader
-.gethdr:
- call getc
- stosb
- loop .gethdr
- jc .error
-
- ; The header WILL be in the first chunk.
- cmp dword [LSSMagic],0x1413f33d ; Magic number
-.error_nz: jne .error
-
- mov dx,GraphColorMap ; Color map offset
- mov ax,1012h ; Set RGB registers
- xor bx,bx ; First register number
- mov cx,16 ; 16 registers
- int 10h
-
-.movecursor:
- mov ax,[GraphYSize] ; Number of pixel rows
- mov dx,[VGAFontSize]
- add ax,dx
- dec ax
- div dl
- xor dx,dx ; Set column to 0
- cmp al,[VidRows]
- jb .rowsok
- mov al,[VidRows]
- dec al
-.rowsok:
- mov dh,al
- mov ah,2
- xor bx,bx
- int 10h ; Set cursor below image
-
- mov cx,[GraphYSize] ; Number of graphics rows
- mov word [VGAPos],0
-
-.drawpixelrow:
- push cx
- mov di,VGARowBuffer
- ; Pre-clear the row buffer
- push di
- push di
- mov cx,640/4
- xor eax,eax
- rep stosd
- pop di
- mov cx,[GraphXSize]
- call rledecode ; Decode one row
- pop si
- mov di,VGAPlaneBuffer
- push di
- mov bp,640
- call packedpixel2vga
- pop si
- push es
- mov di,0A000h ; VGA segment
- mov es,di
- mov di,[VGAPos]
- call outputvga
- pop es
- add word [VGAPos],640/8
- pop cx
- loop .drawpixelrow
-
-.error:
- jmp close ; Tailcall!
-
-;
-; rledecode:
-; Decode a pixel row in RLE16 format.
-;
-; getc stack -> input
-; CX -> pixel count
-; ES:DI -> output (packed pixel)
-;
-rledecode:
- xor dx,dx ; DL = last pixel, DH = nybble buffer
-.loop:
- call .getnybble
- cmp al,dl
- je .run ; Start of run sequence
- stosb
- mov dl,al
- dec cx
- jnz .loop
-.done:
- ret
-.run:
- xor bx,bx
- call .getnybble
- or bl,al
- jz .longrun
-.dorun:
- push cx
- mov cx,bx
- mov al,dl
- rep stosb
- pop cx
- sub cx,bx
- ja .loop
- jmp short .done
-.longrun:
- call .getnybble
- mov bl,al
- call .getnybble
- shl al,4
- or bl,al
- add bx,16
- jmp short .dorun
-
-.getnybble:
- test dh,10h
- jz .low
- and dh,0Fh
- mov al,dh
- ret
-.low:
- call getc
- mov dh,al
- shr dh,4
- or dh,10h ; Nybble already read
- and al,0Fh
- ret
-
-;
-; packedpixel2vga:
-; Convert packed-pixel to VGA bitplanes
-;
-; DS:SI -> packed pixel string
-; BP -> pixel count (multiple of 8)
-; DS:DI -> output (four planes)
-;
-packedpixel2vga:
- xor cx,cx
-.planeloop:
- inc cx
- push si
- push bp
-.loop1:
- mov bx,8
-.loop2:
- lodsb
- shr al,cl
- rcl dl,1 ; VGA is bigendian. Sigh.
- dec bx
- jnz .loop2
- mov [di],dl
- inc di
- sub bp,byte 8
- ja .loop1
- pop bp
- pop si
- cmp cl,3
- jbe .planeloop
- ret
-
-;
-; outputvga:
-; Output four subsequent lines of VGA data
-;
-; DS:SI -> four planes @ 640/8=80 bytes
-; ES:DI -> pointer into VGA memory
-;
-outputvga:
- mov dx,3C4h ; VGA Sequencer Register select port
- mov al,2 ; Sequencer mask
- out dx,al ; Select the sequencer mask
- inc dx ; VGA Sequencer Register data port
- dec ax ; AL <- 1
-.loop1:
- out dx,al ; Select the bit plane to write
- push di
- mov cx,640/32
- rep movsd
- pop di
- add ax,ax
- cmp al,8
- jbe .loop1
- ret
-
-;
-; vgasetmode:
-; Enable VGA graphics, if possible; return ZF=1 on success
-; DS must be set to the base segment; ES is set to DS.
-;
-vgasetmode:
- push ds
- pop es
- mov al,[UsingVGA]
- cmp al,01h
- je .success ; Nothing to do...
- test al,04h
- jz .notvesa
- ; We're in a VESA mode, which means VGA; use VESA call
- ; to revert the mode, and then call the conventional
- ; mode-setting for good measure...
- mov ax,4F02h
- mov bx,0012h
- int 10h
- jmp .setmode
-.notvesa:
- mov ax,1A00h ; Get video card and monitor
- xor bx,bx
- int 10h
- sub bl, 7 ; BL=07h and BL=08h OK
- cmp bl, 1
- ja .error ; ZF=0
-; mov bx,TextColorReg
-; mov dx,1009h ; Read color registers
-; int 10h
-.setmode:
- mov ax,0012h ; Set mode = 640x480 VGA 16 colors
- int 10h
- mov dx,linear_color
- mov ax,1002h ; Write color registers
- int 10h
- mov [UsingVGA], byte 1
-
- ; Set GXPixCols and GXPixRows
- mov dword [GXPixCols],640+(480 << 16)
-
- call use_font ; Set graphics font/data
- mov byte [ScrollAttribute], 00h
-
-.success:
- xor ax,ax ; Set ZF
-.error:
- ret
-
-;
-; vgaclearmode:
-; Disable VGA graphics. It is not safe to assume any value
-; for DS or ES.
-;
-vgaclearmode:
- push ds
- push es
- pushad
- mov ax,cs
- mov ds,ax
- mov es,ax
- mov al,[UsingVGA]
- and al,al ; Already in text mode?
- jz .done
- test al,04h
- jz .notvesa
- mov ax,4F02h ; VESA return to normal video mode
- mov bx,0003h
- int 10h
-.notvesa:
- mov ax,0003h ; Return to normal video mode
- int 10h
-; mov dx,TextColorReg ; Restore color registers
-; mov ax,1002h
-; int 10h
- mov [UsingVGA], byte 0
-
- mov byte [ScrollAttribute], 07h
- call use_font ; Restore text font/data
-.done:
- popad
- pop es
- pop ds
- ret
-
-;
-; vgashowcursor/vgahidecursor:
-; If VGA graphics is enabled, draw a cursor/clear a cursor
-;
-vgashowcursor:
- pushad
- mov al,'_'
- jmp short vgacursorcommon
-vgahidecursor:
- pushad
- mov al,' '
-vgacursorcommon:
- cmp [UsingVGA], byte 1
- jne .done
- mov ah,09h
- mov bx,0007h
- mov cx,1
- int 10h
-.done:
- popad
- ret
-
-
- section .data16
- ; Map colors to consecutive DAC registers
-linear_color db 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0
-
- ; See comboot.doc, INT 22h AX=0017h for the semantics
- ; of this byte.
-UsingVGA db 0
-
- section .bss16
- alignb 4
-LSSHeader equ $
-LSSMagic resd 1 ; Magic number
-GraphXSize resw 1 ; Width of splash screen file
-GraphYSize resw 1 ; Height of splash screen file
-GraphColorMap resb 3*16
-VGAPos resw 1 ; Pointer into VGA memory
-VGAFilePtr resw 1 ; Pointer into VGAFileBuf
-; TextColorReg resb 17 ; VGA color registers for text mode
-%if IS_SYSLINUX
-VGAFileBuf resb FILENAME_MAX+2 ; Unmangled VGA image name
-%else
-VGAFileBuf resb FILENAME_MAX ; Unmangled VGA image name
-%endif
-VGAFileBufEnd equ $
-VGAFileMBuf resb FILENAME_MAX ; Mangled VGA image name
-
- alignb 4
-VGARowBuffer resb 640+80 ; Decompression buffer
-VGAPlaneBuffer resb (640/8)*4 ; Plane buffers
diff --git a/core/idle.inc b/core/idle.inc
index 9677c822..ad26a102 100644
--- a/core/idle.inc
+++ b/core/idle.inc
@@ -22,6 +22,7 @@ reset_idle:
sti ; Guard against BIOS/PXE brokenness...
ret
+ global do_idle
do_idle:
push eax
push ds
@@ -42,11 +43,11 @@ do_idle:
mov cx,16
.errloop:
ss lodsw
- call writehex4
+ pm_call pm_writehex4
dec cx
jz .endloop
mov al,' '
- call writechr
+ pm_call pm_writechr
jmp .errloop
.endloop:
call crlf
diff --git a/core/include/bios.h b/core/include/bios.h
new file mode 100644
index 00000000..3c49cf22
--- /dev/null
+++ b/core/include/bios.h
@@ -0,0 +1,105 @@
+/*
+ * -----------------------------------------------------------------------
+ *
+ * Copyright 1994-2008 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ * Boston MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * -----------------------------------------------------------------------
+ *
+ *
+ * bios.h
+ *
+ * Header file for the BIOS data structures etc.
+ */
+
+#ifndef _BIOS_H
+#define _BIOS_H
+
+/*
+ * Interrupt vectors
+ */
+#define BIOS_timer_hook (4 * 0x1C)
+#define fdctab (4 * 0x1E)
+#define fdctab1 fdctab
+#define fdctab2 (fdctab + 2)
+
+#define serial_base 0x0400 /* Base address for 4 serial ports */
+#define BIOS_fbm 0x0413 /* Free Base Memory (kilobytes) */
+#define BIOS_page 0x0462 /* Current video page */
+#define BIOS_timer 0x046C /* Timer ticks */
+#define BIOS_magic 0x0472 /* BIOS reset magic */
+#define BIOS_vidrows 0x0484 /* Number of screen rows */
+
+#define serial_buf_size 4096
+#define IO_DELAY_PORT 0x80 /* Invalid port (we hope!) */
+
+static inline void io_delay(void)
+{
+ outb(0x0, IO_DELAY_PORT);
+ outb(0x0, IO_DELAY_PORT);
+}
+
+/* conio.c */
+extern unsigned short SerialPort;
+extern unsigned char FlowIgnore;
+extern uint8_t ScrollAttribute;
+extern uint16_t DisplayCon;
+
+/*
+ * Sometimes we need to access screen coordinates as separate 8-bit
+ * entities and sometimes we need to use them as 16-bit entities. Using
+ * this structure allows the compiler to do it for us.
+ */
+union screen {
+ struct {
+ uint8_t col; /* Cursor column for message file */
+ uint8_t row; /* Cursor row for message file */
+ } b;
+ uint16_t dx;
+};
+extern union screen _cursor;
+extern union screen _screensize;
+
+#define CursorDX _cursor.dx
+#define CursorCol _cursor.b.col
+#define CursorRow _cursor.b.row
+
+#define ScreenSize _screensize.dx
+#define VidCols _screensize.b.col
+#define VidRows _screensize.b.row
+
+extern void write_serial(char data);
+
+/* font.c */
+extern uint16_t VGAFontSize;
+extern void use_font(void);
+extern void bios_adjust_screen(void);
+
+/* graphics.c */
+#ifdef IS_SYSLINUX
+#define VGA_FILE_BUF_SIZE (FILENAME_MAX + 2)
+#else
+#define VGA_FILE_BUF_SIZE FILENAME_MAX
+#endif
+
+extern uint8_t UsingVGA;
+extern uint16_t VGAPos;
+extern uint16_t *VGAFilePtr;
+extern char VGAFileBuf[VGA_FILE_BUF_SIZE];
+extern char VGAFileMBuf[];
+extern void vgaclearmode(void);
+extern void vgadisplayfile(FILE *fd);
+
+/* serirq.c */
+extern unsigned char *SerialHead;
+extern unsigned char *SerialTail;
+
+extern void bios_init(void);
+extern void bios_cleanup_hardware(void);
+
+#endif /* _BIOS_H */
diff --git a/core/include/core.h b/core/include/core.h
index 4f5f8433..9fc0ce1a 100644
--- a/core/include/core.h
+++ b/core/include/core.h
@@ -24,6 +24,8 @@ extern char ConfigFile[];
extern char syslinux_banner[];
extern char copyright_str[];
+extern char aux_seg[];
+
/* diskstart.inc isolinux.asm*/
extern void getlinsec(void);
diff --git a/core/init.c b/core/init.c
new file mode 100644
index 00000000..27b9e46d
--- /dev/null
+++ b/core/init.c
@@ -0,0 +1,77 @@
+#include <core.h>
+#include <com32.h>
+#include <sys/io.h>
+#include <fs.h>
+#include <bios.h>
+
+static uint16_t min_lowmem_heap = 65536;
+extern char __lowmem_heap[];
+uint8_t KbdFlags; /* Check for keyboard escapes */
+
+static inline void check_escapes(void)
+{
+ com32sys_t ireg, oreg;
+
+ ireg.eax.b[1] = 0x02; /* Check keyboard flags */
+ __intcall(0x16, &ireg, &oreg);
+
+ KbdFlags = oreg.eax.b[0];
+
+ /* Ctrl->skip 386 check */
+ if (oreg.eax.b[0] & 0x04) {
+ /*
+ * Now check that there is sufficient low (DOS) memory
+ *
+ * NOTE: Linux doesn't use all of real_mode_seg, but we use
+ * the same segment for COMBOOT images, which can use all 64K.
+ */
+ uint16_t mem;
+
+ __intcall(0x12, &ireg, &oreg);
+
+ mem = ((uint16_t)__lowmem_heap) + min_lowmem_heap + 1023;
+ mem = mem >> 10;
+
+ if (mem < oreg.eax.w[0]) {
+ char buf[256];
+
+ snprintf(buf, sizeof(buf),
+ "It appears you computer has less than "
+ "%dK of low (DOS)\nRAM. Syslinux "
+ "needs at least this amount to boot. "
+ "If you get\nthis message in error, "
+ "hold down the Ctrl key while\nbooting, "
+ "and I will take your word for it.\n",
+ mem);
+ writestr(buf);
+ kaboom();
+ }
+ }
+}
+
+extern uint32_t BIOS_timer_next;
+extern uint32_t timer_irq;
+static inline void bios_timer_init(void)
+{
+ unsigned long next;
+ uint32_t *hook = BIOS_timer_hook;
+
+ next = *hook;
+ BIOS_timer_next = next;
+ *hook = &timer_irq;
+}
+
+void init(com32sys_t *regs)
+{
+ /* Initialize timer */
+ bios_timer_init();
+
+ adjust_screen();
+ printf_init();
+
+ /* Init the memory subsystem */
+ mem_init();
+
+ /* CPU-dependent initialization and related checks. */
+ check_escapes();
+}
diff --git a/core/init.inc b/core/init.inc
index cce4327c..83d6fd68 100644
--- a/core/init.inc
+++ b/core/init.inc
@@ -28,11 +28,8 @@ common_init:
cmp eax,__pm_code_len
jne kaboom
-;
-; Initialize timer
-;
- call timer_init
-
+ extern init
+ pm_call init
;
; Initialize configuration information
;
@@ -44,63 +41,12 @@ common_init:
call comboot_setup_api
;
-; Now set up screen parameters
-;
- call adjust_screen
- pm_call printf_init
-
-;
; Inite the memmory subsystem
;
- pm_call mem_init
+; pm_call mem_init
mov eax,[HighMemSize]
mov [VKernelEnd],eax
-;
-; CPU-dependent initialization and related checks.
-;
-check_escapes:
- mov ah,02h ; Check keyboard flags
- int 16h
- mov [KbdFlags],al ; Save for boot prompt check
- test al,04h ; Ctrl->skip 386 check
- jnz skip_checks
-
-;
-; Now check that there is sufficient low (DOS) memory
-;
-; NOTE: Linux doesn't use all of real_mode_seg, but we use the same
-; segment for COMBOOT images, which can use all 64K
-;
- int 12h
- mov edx,__lowmem_heap + min_lowmem_heap + 1023
- shr edx,10
- cmp ax,dx
- jae enough_ram
- mov ax,dx
- mov si,err_noram
- mov cl,10
- div cl
- add [si+err_noram.size-err_noram+2],ah
- cbw
- div cl
- add [si+err_noram.size-err_noram],ax
- call writestr_early
- jmp kaboom
-enough_ram:
-skip_checks:
-
- section .data16
-err_noram db 'It appears your computer has less than '
-.size db '000'
- db 'K of low ("DOS")'
- db CR, LF
- db 'RAM. Syslinux needs at least this amount to boot. If you get'
- db CR, LF
- db 'this message in error, hold down the Ctrl key while'
- db CR, LF
- db 'booting, and I will take your word for it.', CR, LF, 0
-
section .text16
;
; The code to decompress the PM code and initialize other segments.
diff --git a/core/isolinux.asm b/core/isolinux.asm
index 895468ca..b0b21a3b 100644
--- a/core/isolinux.asm
+++ b/core/isolinux.asm
@@ -1169,6 +1169,22 @@ ROOT_FS_OPS:
section .text16
+%ifdef DEBUG_TRACERS
+;
+; debug hack to print a character with minimal code impact
+;
+debug_tracer: pushad
+ pushfd
+ mov bp,sp
+ mov bx,[bp+9*4] ; Get return address
+ mov al,[cs:bx] ; Get data byte
+ inc word [bp+9*4] ; Return to after data byte
+ call writechr
+ popfd
+ popad
+ ret
+%endif ; DEBUG_TRACERS
+
;
; Now we have the config file open. Parse the config file and
; run the user interface.
diff --git a/core/plaincon.c b/core/plaincon.c
new file mode 100644
index 00000000..a12d551a
--- /dev/null
+++ b/core/plaincon.c
@@ -0,0 +1,32 @@
+/*
+ * writechr: Write a single character in AL to the console without
+ * mangling any registers; handle video pages correctly.
+ */
+#include <sys/io.h>
+#include <fs.h>
+#include <com32.h>
+#include "bios.h"
+
+void writechr(char data)
+{
+ com32sys_t ireg, oreg;
+
+ write_serial(data); /* write to serial port if needed */
+
+ if (UsingVGA & 0x8)
+ vgaclearmode();
+
+ if (!(DisplayCon & 0x1))
+ return;
+
+ ireg.eax.b[0] = data;
+ ireg.eax.b[1] = 0xE;
+ ireg.ebx.b[0] = 0x07; /* attribute */
+ ireg.ebx.b[1] = *(uint8_t *)BIOS_page; /* current page */
+ __intcall(0x10, &ireg, &oreg);
+}
+
+void pm_writechr(com32sys_t *regs)
+{
+ writechr(regs->eax.b[0]);
+}
diff --git a/core/plaincon.inc b/core/plaincon.inc
deleted file mode 100644
index c41629d0..00000000
--- a/core/plaincon.inc
+++ /dev/null
@@ -1,24 +0,0 @@
-;
-; writechr: Write a single character in AL to the console without
-; mangling any registers; handle video pages correctly.
-;
- section .text16
-
-writechr:
- call write_serial ; write to serial port if needed
- pushfd
- test byte [cs:UsingVGA], 08h
- jz .videook
- call vgaclearmode
-.videook:
- test byte [cs:DisplayCon], 01h
- jz .nothing
- pushad
- mov ah,0Eh
- mov bl,07h ; attribute
- mov bh,[cs:BIOS_page] ; current page
- int 10h
- popad
-.nothing:
- popfd
- ret
diff --git a/core/pm.inc b/core/pm.inc
index 9584cda1..c6f3c52b 100644
--- a/core/pm.inc
+++ b/core/pm.inc
@@ -328,7 +328,8 @@ a20_fast:
jnz a20_dunno ; Did we get the wrong type?
mov si, err_a20
- jmp abort_load
+ pm_call pm_writestr
+ jmp kaboom
section .data16
err_a20 db CR, LF, 'A20 gate not responding!', CR, LF, 0
diff --git a/core/pxelinux.asm b/core/pxelinux.asm
index 8c560220..8a95d1e9 100644
--- a/core/pxelinux.asm
+++ b/core/pxelinux.asm
@@ -339,7 +339,7 @@ kaboom:
je .wait3
loop .wait2,ecx
mov al,'.'
- call writechr
+ pm_call pm_writechr
pop cx
loop .wait1
.keypress:
@@ -492,6 +492,18 @@ gpxe_unload:
.plain:
ret
+writestr_early:
+ pm_call pm_writestr
+ ret
+
+pollchar:
+ pm_call pm_pollchar
+ ret
+
+getchar:
+ pm_call pm_getchar
+ ret
+
section .data16
alignz 4
pxe_file_exit_hook:
@@ -507,9 +519,6 @@ pxe_file_exit_hook:
; -----------------------------------------------------------------------------
%include "common.inc" ; Universal modules
-%include "writestr.inc" ; String output
-writestr_early equ writestr
-%include "writehex.inc" ; Hexadecimal output
%include "rawcon.inc" ; Console I/O w/o using the console functions
; -----------------------------------------------------------------------------
diff --git a/core/serirq.c b/core/serirq.c
new file mode 100644
index 00000000..767099e1
--- /dev/null
+++ b/core/serirq.c
@@ -0,0 +1,204 @@
+/*
+ * -----------------------------------------------------------------------
+ *
+ * Copyright 2009 Intel Corporation; author: H. Peter Anvin
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ * Boston MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * -----------------------------------------------------------------------
+ *
+ * serirq.c
+ *
+ * Serial port IRQ code
+ *
+ * We don't know what IRQ, if any, we have, so map all of them...
+ */
+#include <sys/io.h>
+#include <string.h>
+
+#include <fs.h>
+#include "bios.h"
+
+static char serial_buf[serial_buf_size];
+
+static unsigned short SerialIRQPort; /* Serial port w IRQ service */
+unsigned char *SerialHead = serial_buf; /* Head of serial port rx buffer */
+unsigned char *SerialTail = serial_buf; /* Tail of serial port rx buffer */
+
+static unsigned char IRQMask[2]; /* PIC IRQ mask status */
+
+static unsigned int oldirq[16];
+
+typedef void (*irqhandler_t)(void);
+
+void sirq_cleanup(void);
+
+static void irq_common(unsigned short old_irq)
+{
+ unsigned char *dst;
+ irqhandler_t next;
+ char val;
+
+ dst = (unsigned char *)SerialHead;
+ next = (irqhandler_t)oldirq[old_irq];
+
+ /* LSR */
+ val = inb(SerialPort + 5);
+
+ /* Received data */
+ while (val & 1) {
+ /* RDR */
+ *dst++ = inb(SerialPort);
+ /* LSR */
+ val = inb(SerialPort + 5);
+ if ((val & FlowIgnore) == FlowIgnore) {
+ /* Wrap around if necessary */
+ dst = (unsigned char *)((unsigned long)dst & (serial_buf_size - 1));
+
+ /* Would this cause overflow? */
+ if (dst != SerialTail)
+ SerialHead = dst;
+ }
+ }
+
+ /* Chain to next handler */
+ next();
+}
+
+#define SERIAL_IRQ_HANDLER(n) \
+ static void serstub_irq##n(void) \
+ { \
+ irq_common(n); \
+ }
+
+SERIAL_IRQ_HANDLER(0);
+SERIAL_IRQ_HANDLER(1);
+SERIAL_IRQ_HANDLER(2);
+SERIAL_IRQ_HANDLER(3);
+SERIAL_IRQ_HANDLER(4);
+SERIAL_IRQ_HANDLER(5);
+SERIAL_IRQ_HANDLER(6);
+SERIAL_IRQ_HANDLER(7);
+SERIAL_IRQ_HANDLER(8);
+SERIAL_IRQ_HANDLER(9);
+SERIAL_IRQ_HANDLER(10);
+SERIAL_IRQ_HANDLER(11);
+SERIAL_IRQ_HANDLER(12);
+SERIAL_IRQ_HANDLER(13);
+SERIAL_IRQ_HANDLER(14);
+SERIAL_IRQ_HANDLER(15);
+
+static inline void save_irq_vectors(uint32_t *src, uint32_t *dst)
+{
+ int i;
+
+ for (i = 0; i < 8; i++)
+ *dst++ = *src++;
+}
+
+static inline void install_irq_vectors(uint32_t *dst, int first)
+{
+ if (first) {
+ *dst++ = (uint32_t)serstub_irq0;
+ *dst++ = (uint32_t)serstub_irq1;
+ *dst++ = (uint32_t)serstub_irq2;
+ *dst++ = (uint32_t)serstub_irq3;
+ *dst++ = (uint32_t)serstub_irq4;
+ *dst++ = (uint32_t)serstub_irq5;
+ *dst++ = (uint32_t)serstub_irq6;
+ *dst++ = (uint32_t)serstub_irq7;
+ } else {
+ *dst++ = (uint32_t)serstub_irq8;
+ *dst++ = (uint32_t)serstub_irq9;
+ *dst++ = (uint32_t)serstub_irq10;
+ *dst++ = (uint32_t)serstub_irq11;
+ *dst++ = (uint32_t)serstub_irq12;
+ *dst++ = (uint32_t)serstub_irq13;
+ *dst++ = (uint32_t)serstub_irq14;
+ *dst++ = (uint32_t)serstub_irq15;
+ }
+}
+
+void sirq_install(void)
+{
+ char val, val2;
+
+ sirq_cleanup();
+
+ save_irq_vectors((uint32_t *)(4 * 0x8), oldirq);
+ save_irq_vectors((uint32_t *)(4 * 0x70), &oldirq[8]);
+
+ install_irq_vectors((uint32_t *)(4 * 0x8), 1);
+ install_irq_vectors((uint32_t *)(4 * 0x70), 0);
+
+ SerialIRQPort = SerialPort;
+
+ /* Clear DLAB (should already be...) */
+ outb(0x3, SerialIRQPort + 5);
+ io_delay();
+
+ /* Enable receive interrupt */
+ outb(0x1, SerialIRQPort + 1);
+ io_delay();
+
+ /*
+ * Enable all the interrupt lines at the PIC. Some BIOSes only
+ * enable the timer interrupts and other interrupts actively
+ * in use by the BIOS.
+ */
+
+ /* Secondary PIC mask register */
+ val = inb(0xA1);
+ val2 = inb(0x21);
+ IRQMask[0] = val;
+ IRQMask[1] = val2;
+
+ io_delay();
+
+ /* Remove all interrupt masks */
+ outb(0x21, 0);
+ outb(0xA1, 0);
+}
+
+void sirq_cleanup_nowipe(void)
+{
+ uint32_t *dst;
+ int i;
+
+ if (!SerialIRQPort)
+ return;
+
+ /* Clear DLAB */
+ outb(0x3, SerialIRQPort + 5);
+ io_delay();
+
+ /* Clear IER */
+ outb(0x0, SerialIRQPort + 1);
+ io_delay();
+
+ /* Restore PIC masks */
+ outb(IRQMask[0], 0x21);
+ outb(IRQMask[1], 0xA1);
+
+ /* Restore the original interrupt vectors */
+ dst = (uint32_t *)(4 * 0x8);
+ for (i = 0; i < 8; i++)
+ *dst++ = oldirq[i];
+
+ dst = (uint32_t *)(4 * 0x70);
+ for (i = 8; i < 16; i++)
+ *dst++ = oldirq[i];
+
+ /* No active interrupt system */
+ SerialIRQPort = 0;
+}
+
+void sirq_cleanup(void)
+{
+ sirq_cleanup_nowipe();
+ memcpy(SerialHead, 0x0, serial_buf_size);
+}
diff --git a/core/serirq.inc b/core/serirq.inc
deleted file mode 100644
index bd08b69c..00000000
--- a/core/serirq.inc
+++ /dev/null
@@ -1,221 +0,0 @@
-;; -----------------------------------------------------------------------
-;;
-;; Copyright 2009 Intel Corporation; author: H. Peter Anvin
-;;
-;; This program is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
-;; Boston MA 02111-1307, USA; either version 2 of the License, or
-;; (at your option) any later version; incorporated herein by reference.
-;;
-;; -----------------------------------------------------------------------
-
-;;
-;; serirq.inc
-;;
-;; Serial port IRQ code
-;;
-;; We don't know what IRQ, if any, we have, so map all of them...
-;;
-
- section .text16
- bits 16
- align 8
-
- section .bss16
- alignb 8
-
-%assign n 0
-%rep 16
- section .text16
-serstub_irq %+ n :
- push dword [cs:oldirq %+ n]
- jmp short irq_common
-
- section .bss16
-oldirq %+ n resd 1
-%assign n n+1
-%endrep
-
- section .text16
-irq_common:
- pushf
- push ax
- push dx
- mov dx,[cs:SerialPort]
- add dx,5 ; DX -> LSR
- in al,dx
- test al,1 ; Received data
- jnz .data
-.done:
- pop dx
- pop ax
- popf
- retf ; Chain to next handler
-.data:
- push es
- push di
- mov ax,aux_seg + (aux.serial >> 4)
- mov es,ax
- mov di,[cs:SerialHead]
-.loop:
- mov dx,[cs:SerialPort] ; DX -> RDR
- in al,dx
- stosb
- mov ah,[cs:FlowIgnore]
- add dx,5 ; DX -> LSR
- in al,dx
- push ax
- and al,ah
- cmp al,ah
- jne .drop
- and di,serial_buf_size-1 ; Wrap around if necessary
- cmp di,[cs:SerialTail] ; Would this cause overflow?
- je .drop ; If so, just drop the data
- mov [cs:SerialHead],di
-.drop:
- pop ax
- test al,1 ; More data?
- jnz .loop
-.full:
- pop di
- pop es
- jmp .done
-
- section .bss16
-;
-; SerialIRQPort will generally track SerialPort, but will be 0 when an
-; IRQ service is not installed.
-;
-SerialIRQPort resw 1 ; Serial port w IRQ service
-SerialHead resw 1 ; Head of serial port rx buffer
-SerialTail resw 1 ; Tail of serial port rx buffer
-
- section .bss16
-IRQMask resw 1 ; PIC IRQ mask status
-
- section .text16
-
- global sirq_install
-sirq_install:
- pushad
-
- call sirq_cleanup
-
- ; Save the old interrupt vectors
- mov si,4*08h
- mov di,oldirq0
- mov cx,8
- rep movsd
- mov si,4*70h
- mov cx,8
- rep movsd
-
- ; Install new interrupt vectors
- mov di,4*08h
- mov cx,8
- mov eax,serstub_irq0
-.pic0:
- stosd
- add ax,serstub_irq1 - serstub_irq0
- loop .pic0
- mov di,4*70h
- mov cx,8
-.pic1:
- stosd
- add ax,serstub_irq1 - serstub_irq0
- loop .pic1
-
- mov bx,[SerialPort]
- mov [SerialIRQPort],bx
-
- lea dx,[bx+5] ; DX -> LCR
- mov al,03h ; Clear DLAB (should already be...)
- slow_out dx,al
-
- lea dx,[bx+1] ; DX -> IER
- mov al,1 ; Enable receive interrupt
- slow_out dx,al
-
- ;
- ; Enable all ther interupt lines at the PIC. Some BIOSes
- ; only enable the timer interrupts and other interrupts
- ; actively in use by the BIOS.
- ;
- in al,0xA1 ; Secondary PIC mask register
- mov ah,al
- in al,0x21 ; Primary PIC mask register
- mov [IRQMask],ax
-
- io_delay
-
- xor ax,ax ; Remove all interrupt masks
- out 0x21,al
- out 0xA1,al
-
- popad
- ret
-
- global sirq_cleanup_nowipe
-sirq_cleanup_nowipe:
- pushad
- push ds
- push es
- xor ax,ax
- mov ds,ax
- mov es,ax
-
- mov bx,[SerialIRQPort]
- and bx,bx
- jz .done
-
- lea dx,[bx+5] ; DX -> LCR
- mov al,03h ; Clear DLAB (should already be...)
- slow_out dx,al
-
- lea dx,[bx+1] ; DX -> IER
- xor ax,ax
- slow_out dx,al ; Clear IER
-
- ; Restore PIC masks
- mov ax,[IRQMask]
- out 0x21,al
- mov al,ah
- out 0xA1,al
-
- ; Restore the original interrupt vectors
- mov si,oldirq0
- mov di,4*08h
- mov cx,8
- rep movsd
- mov di,4*70h
- mov cx,8
- rep movsd
-
- xor ax,ax
- mov [SerialIRQPort],ax ; No active interrupt system
-
-.done:
- pop es
- pop ds
- popad
- ret
-
-sirq_cleanup:
- call sirq_cleanup_nowipe
- pushad
- push es
- ; Just in case it might contain a password, erase the
- ; serial port receive buffer...
- mov ax,aux_seg + (aux.serial >> 4)
- mov es,ax
- xor eax,eax
- mov [cs:SerialHead],eax
- mov cx,serial_buf_size >> 2
- xor di,di
- rep stosd
- pop es
- popad
- ret
-
- section .text16
diff --git a/core/timer.inc b/core/timer.inc
index b01ff917..2bf0a219 100644
--- a/core/timer.inc
+++ b/core/timer.inc
@@ -32,6 +32,7 @@ timer_init:
mov dword [BIOS_timer_hook],timer_irq
ret
+ global timer_cleanup
timer_cleanup:
; Unhook INT 1Ch
mov eax,[BIOS_timer_next]
@@ -42,11 +43,13 @@ timer_cleanup:
; The specified frequency is 14.31818 MHz/12/65536; this turns out
; to be a period of 54.92542 ms, or 0x36.ece8(187c) hexadecimal.
;
+ global timer_irq
timer_irq:
inc dword [cs:__jiffies]
add word [cs:__ms_timer_adj],0xece8
adc dword [cs:__ms_timer],0x36
jmp 0:0
+ global BIOS_timer_next
BIOS_timer_next equ $-4
section .data16
diff --git a/core/ui.inc b/core/ui.inc
index b4b59b8b..5dfeec44 100644
--- a/core/ui.inc
+++ b/core/ui.inc
@@ -731,6 +731,14 @@ CmdOptPtr resw 1 ; Pointer to first option on cmd line
KbdFlags resb 1 ; Check for keyboard escapes
FuncFlag resb 1 ; Escape sequences received from keyboard
KernelType resb 1 ; Kernel type, from vkernel, if known
+ global KernelName
+KernelName resb FILENAME_MAX ; Mangled name for kernel
+ section .config
+ global PXERetry
+PXERetry dw 0 ; Extra PXE retries
+ section .data16
+ global SerialNotice
+SerialNotice db 1 ; Only print this once
section .text16
;
@@ -753,9 +761,7 @@ KernelType resb 1 ; Kernel type, from vkernel, if known
;
; Abort loading code
;
-%include "abort.inc"
;
; Hardware cleanup common code
;
-%include "cleanup.inc"
diff --git a/core/writehex.c b/core/writehex.c
new file mode 100644
index 00000000..fde27037
--- /dev/null
+++ b/core/writehex.c
@@ -0,0 +1,70 @@
+/* -----------------------------------------------------------------------
+ *
+ * Copyright 1994-2008 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ * Boston MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * -----------------------------------------------------------------------
+ */
+#include <core.h>
+
+/*
+ * writehex.c
+ *
+ * Write hexadecimal numbers to the console
+ *
+ */
+
+static inline void __writehex(uint32_t h, int digits)
+{
+ while (digits) {
+ uint8_t shift;
+ uint8_t al;
+
+ shift = --digits;
+ al = ((h & 0x0f << shift) >> shift);
+ if (al < 10)
+ al += '0';
+ else
+ al += 'A' - 10;
+
+ writechr(al);
+ }
+}
+
+/*
+ * writehex[248]: Write a hex number in (AL, AX, EAX) to the console
+ */
+void writehex2(uint32_t h)
+{
+ __writehex(h, 2);
+}
+
+void writehex4(uint8_t h)
+{
+ __writehex(h, 4);
+}
+
+void writehex8(uint8_t h)
+{
+ __writehex(h, 8);
+}
+
+void pm_writehex2(com32sys_t *regs)
+{
+ writehex2(regs->eax.b[0]);
+}
+
+void pm_writehex4(com32sys_t *regs)
+{
+ writehex4(regs->eax.w[0]);
+}
+
+void pm_writehex8(com32sys_t *regs)
+{
+ writehex8(regs->eax.l);
+}