core: Reimplement lots asm code in C
authorMatt Fleming <matt.fleming@intel.com>
Tue, 18 Oct 2011 12:13:06 +0000 (13:13 +0100)
committerMatt Fleming <matt.fleming@intel.com>
Thu, 1 Dec 2011 13:14:05 +0000 (13:14 +0000)
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>
29 files changed:
com32/elflink/ldlinux/readconfig.c
core/abort.inc [deleted file]
core/cleanup.c [new file with mode: 0644]
core/cleanup.inc [deleted file]
core/comboot.inc
core/common.inc
core/conio.c [new file with mode: 0644]
core/conio.inc [deleted file]
core/diskfs.inc
core/extern.inc
core/font.c [new file with mode: 0644]
core/font.inc [deleted file]
core/graphics.c [new file with mode: 0644]
core/graphics.inc [deleted file]
core/idle.inc
core/include/bios.h [new file with mode: 0644]
core/include/core.h
core/init.c [new file with mode: 0644]
core/init.inc
core/isolinux.asm
core/plaincon.c [new file with mode: 0644]
core/plaincon.inc [deleted file]
core/pm.inc
core/pxelinux.asm
core/serirq.c [new file with mode: 0644]
core/serirq.inc [deleted file]
core/timer.inc
core/ui.inc
core/writehex.c [new file with mode: 0644]

index 5bf6f42..60448c4 100644 (file)
@@ -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 (file)
index 9b18136..0000000
+++ /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 (file)
index 0000000..7bf1df2
--- /dev/null
@@ -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 (file)
index 300584c..0000000
+++ /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
index b0e118a..880f5db 100644 (file)
@@ -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
index 0b507ce..1a6840e 100644 (file)
@@ -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 (file)
index 0000000..ddccbdb
--- /dev/null
@@ -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 (file)
index ec2aa2a..0000000
+++ /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"
index 2684328..5a029d3 100644 (file)
@@ -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
 
 ; -----------------------------------------------------------------------------
index 90599f2..dea6052 100644 (file)
        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 (file)
index 0000000..b14d3d2
--- /dev/null
@@ -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 (file)
index 9e840e4..0000000
+++ /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 (file)
index 0000000..7ca20ea
--- /dev/null
@@ -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 (file)
index a8d2851..0000000
+++ /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
index 9677c82..ad26a10 100644 (file)
@@ -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 (file)
index 0000000..3c49cf2
--- /dev/null
@@ -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 */
index 4f5f843..9fc0ce1 100644 (file)
@@ -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 (file)
index 0000000..27b9e46
--- /dev/null
@@ -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();
+}
index cce4327..83d6fd6 100644 (file)
@@ -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.
index 895468c..b0b21a3 100644 (file)
@@ -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 (file)
index 0000000..a12d551
--- /dev/null
@@ -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 (file)
index c41629d..0000000
+++ /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
index 9584cda..c6f3c52 100644 (file)
@@ -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
index 8c56022..8a95d1e 100644 (file)
@@ -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 (file)
index 0000000..767099e
--- /dev/null
@@ -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 (file)
index bd08b69..0000000
+++ /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
index b01ff91..2bf0a21 100644 (file)
@@ -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
index b4b59b8..5dfeec4 100644 (file)
@@ -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 (file)
index 0000000..fde2703
--- /dev/null
@@ -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);
+}