aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhpa <hpa>2004-11-30 22:09:56 +0000
committerhpa <hpa>2004-11-30 22:09:56 +0000
commit7a8f0a4ab860f2ad0aa8255120d5d55942327d08 (patch)
tree50c64a5add7501f8a8738789a6f14a5c9a5f5737
parent65c7485dfdcbebe57194d8432439125a8c7ed797 (diff)
downloadsyslinux-2.12-pre2.tar.gz
syslinux-2.12-pre2.tar.xz
syslinux-2.12-pre2.zip
Actually working ANSI device; add demosyslinux-2.12-pre2
-rw-r--r--com32/include/console.h9
-rw-r--r--com32/include/dev.h3
-rw-r--r--com32/lib/Makefile2
-rw-r--r--com32/lib/sys/ansicon_write.c490
-rw-r--r--com32/lib/sys/ansiserial_write.c56
-rw-r--r--com32/lib/sys/serial_write.c2
-rw-r--r--com32/modules/Makefile2
-rw-r--r--com32/modules/fancyhello.c44
-rw-r--r--com32/modules/hello.c2
9 files changed, 368 insertions, 242 deletions
diff --git a/com32/include/console.h b/com32/include/console.h
index 55904277..494b0ba1 100644
--- a/com32/include/console.h
+++ b/com32/include/console.h
@@ -47,5 +47,14 @@ extern const struct output_dev dev_stdcon_w;
extern const struct input_dev dev_rawcon_r;
extern const struct output_dev dev_rawcon_w;
+/* These are output-only consoles; combine with one of the input methods */
+
+/* Serial port only */
+extern const struct output_dev dev_serial_w;
+/* ANSI console (output only; combine with one of the input methods) */
+extern const struct output_dev dev_ansicon_w;
+/* ANSI plus serial port */
+extern const struct output_dev dev_ansiserial_w;
+
#endif /* _CONSOLE_H */
diff --git a/com32/include/dev.h b/com32/include/dev.h
index a8cea76c..a5afbaf1 100644
--- a/com32/include/dev.h
+++ b/com32/include/dev.h
@@ -44,9 +44,12 @@ struct output_dev;
__extern int opendev(const struct input_dev *, const struct output_dev *, int);
/* Common generic devices */
+
+/* Null device */
extern const struct input_dev dev_null_r;
extern const struct output_dev dev_null_w;
+/* Error device */
extern const struct input_dev dev_error_r;
extern const struct output_dev dev_error_w;
diff --git a/com32/lib/Makefile b/com32/lib/Makefile
index acc385fc..9896befd 100644
--- a/com32/lib/Makefile
+++ b/com32/lib/Makefile
@@ -25,7 +25,7 @@ LIBOBJS = abort.o atexit.o atoi.o atol.o atoll.o calloc.o creat.o \
sys/rawcon_read.o sys/rawcon_write.o \
sys/err_read.o sys/err_write.o \
sys/null_read.o sys/null_write.o \
- sys/ansicon_write.o
+ sys/serial_write.o sys/ansicon_write.o sys/ansiserial_write.o
all: libcom32.a
diff --git a/com32/lib/sys/ansicon_write.c b/com32/lib/sys/ansicon_write.c
index 59eec01e..1e4e3cca 100644
--- a/com32/lib/sys/ansicon_write.c
+++ b/com32/lib/sys/ansicon_write.c
@@ -52,16 +52,14 @@ struct curxy {
uint8_t x, y;
} __attribute__((packed));
#define BIOS_CURXY ((struct curxy *)0x450) /* Array for each page */
-#define BIOS_ROWS (*(uint8_t *)0x449) /* Minus one */
+#define BIOS_ROWS (*(uint8_t *)0x484) /* Minus one; if zero use 24 (= 25 lines) */
#define BIOS_COLS (*(uint16_t *)0x44A)
#define BIOS_PAGE (*(uint8_t *)0x462)
-#define BIOS_FB (*(uint16_t *)0x44E) /* Current page fb address */
enum ansi_state {
st_init, /* Normal (no ESC seen) */
st_esc, /* ESC seen */
- st_empty, /* CSI seen, empty position */
- st_digits, /* CSI seen, digits seen in this position */
+ st_csi, /* CSI seen */
};
#define MAX_PARMS 16
@@ -89,7 +87,6 @@ static struct {
.saved_xy = { 0, 0 },
.state = st_init,
.nparms = 0,
- .parms = { 0, },
};
/* Erase a region of the screen */
@@ -113,292 +110,309 @@ static void ansicon_putchar(int ch)
const int cols = BIOS_COLS;
const int page = BIOS_PAGE;
struct curxy xy = BIOS_CURXY[page];
- int again;
- do {
- again = 0;
-
- switch ( st.state ) {
- case st_init:
- switch ( ch ) {
- case '\a':
- /* Ignore beep */
- break;
- case '\b':
- if ( xy.y > 0 ) xy.y--;
- break;
- case '\t':
- {
- int nsp = 8 - (xy.y & 7);
- while ( nsp-- )
- ansicon_putchar(' ');
- }
- return; /* Cursor already updated */
- case '\n':
- case '\v':
- case '\f':
- xy.y++;
- break;
- case '\r':
- xy.x = 0;
- break;
- case '\0':
- case 127:
- /* Ignore null or delete */
- break;
- case 27:
- st.state = st_esc;
- break;
- default:
- /* Print character */
- ireg.eax.b[1] = 0x09;
- ireg.eax.b[0] = ch;
- ireg.ebx.b[1] = page;
- ireg.ebx.b[0] = st.attr;
- ireg.ecx.w[0] = 1;
- __intcall(0x10, &ireg, NULL);
- xy.x++;
- break;
- }
+ switch ( st.state ) {
+ case st_init:
+ switch ( ch ) {
+ case '\a':
+ /* Ignore beep */
break;
-
- case st_esc:
- if ( ch == '[' ) {
- int i;
- st.state = st_empty;
- st.nparms = 0;
- for ( i = 0 ; i < MAX_PARMS ; i++ )
- st.parms[i] = 1; /* 1 is the default, not 0 */
- } else {
- st.state = st_init;
- again = 1;
+ case '\b':
+ if ( xy.x > 0 ) xy.x--;
+ break;
+ case '\t':
+ {
+ int nsp = 8 - (xy.x & 7);
+ while ( nsp-- )
+ ansicon_putchar(' ');
}
+ return; /* Cursor already updated */
+ case '\n':
+ case '\v':
+ case '\f':
+ xy.y++;
+ break;
+ case '\r':
+ xy.x = 0;
+ break;
+ case '\0':
+ case 127:
+ /* Ignore null or delete */
+ break;
+ case 27:
+ st.state = st_esc;
+ break;
+ default:
+ /* Print character */
+ ireg.eax.b[1] = 0x09;
+ ireg.eax.b[0] = ch;
+ ireg.ebx.b[1] = page;
+ ireg.ebx.b[0] = st.attr;
+ ireg.ecx.w[0] = 1;
+ __intcall(0x10, &ireg, NULL);
+ xy.x++;
break;
+ }
+ break;
- case st_empty:
- case st_digits:
- switch ( ch ) {
- case '0' ... '9':
- if ( st.state == st_empty ) {
- st.parms[st.nparms] = ch - '0';
- st.state = st_digits;
- } else {
- st.parms[st.nparms] = st.parms[st.nparms]*10 + (ch-'0');
- }
- break;
- case ';':
+ case st_esc:
+ if ( ch == '[' ) {
+ st.state = st_csi;
+ st.nparms = 0;
+ memset(st.parms, 0, sizeof st.parms);
+ } else {
+ st.state = st_init; /* Discard ESC+other symbol */
+ }
+ break;
+
+ case st_csi:
+ {
+ int p0 = st.parms[0] ? st.parms[0] : 1;
+
+ if ( ch >= '0' && ch <= '9' ) {
+ st.parms[st.nparms] = st.parms[st.nparms]*10 + (ch-'0');
+ } else if ( ch == ';' ) {
st.nparms++;
if ( st.nparms >= MAX_PARMS )
st.nparms = MAX_PARMS-1;
- st.state = st_empty;
break;
- case 'A':
- {
- int y = xy.y - st.parms[0];
- xy.y = (y < 0) ? 0 : y;
- }
- break;
- case 'B':
- {
- int y = xy.y + st.parms[0];
- xy.y = (y >= rows) ? rows-1 : y;
- }
- break;
- case 'C':
- {
- int x = xy.x + st.parms[0];
- xy.x = (x >= cols) ? cols-1 : x;
- }
- break;
- case 'D':
- {
- int x = xy.x - st.parms[0];
- xy.x = (x < 0) ? 0 : x;
- }
- break;
- case 'E':
- {
- int y = xy.y + st.parms[0];
- xy.y = (y >= rows) ? rows-1 : y;
- xy.x = 0;
- }
- break;
- case 'F':
- {
- int y = xy.y - st.parms[0];
- xy.y = (y < 0) ? 0 : y;
- xy.x = 0;
- }
- break;
- case 'H':
- case 'f':
- {
- int x = st.parms[0];
- int y = st.parms[1];
-
- xy.x = (x >= cols) ? cols-1 : x;
- xy.y = (y >= rows) ? rows-1 : y;
- }
- break;
- case 'J':
- {
- if ( st.parms[0] == 2 ) {
- ansicon_erase(0, 0, cols-1, rows-1);
- } else {
- ansicon_erase(xy.x, xy.y, cols-1, xy.y);
- if ( xy.y < rows-1 )
- ansicon_erase(0, xy.y+1, cols-1, rows-1);
+ } else {
+ switch ( ch ) {
+ case 'A':
+ {
+ int y = xy.y - p0;
+ xy.y = (y < 0) ? 0 : y;
}
- }
- break;
- case 'K':
- {
- if ( st.parms[0] == 2 )
- ansicon_erase(0, xy.y, cols-1, xy.y);
- else
- ansicon_erase(xy.x, xy.y, cols-1, xy.y);
- }
- break;
- case 'm':
- {
- static const int ansi2pc[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
+ break;
+ case 'B':
+ {
+ int y = xy.y + p0;
+ xy.y = (y >= rows) ? rows-1 : y;
+ }
+ break;
+ case 'C':
+ {
+ int x = xy.x + p0;
+ xy.x = (x >= cols) ? cols-1 : x;
+ }
+ break;
+ case 'D':
+ {
+ int x = xy.x - p0;
+ xy.x = (x < 0) ? 0 : x;
+ }
+ break;
+ case 'E':
+ {
+ int y = xy.y + p0;
+ xy.y = (y >= rows) ? rows-1 : y;
+ xy.x = 0;
+ }
+ break;
+ case 'F':
+ {
+ int y = xy.y - p0;
+ xy.y = (y < 0) ? 0 : y;
+ xy.x = 0;
+ }
+ break;
+ case 'H':
+ case 'f':
+ {
+ int x = st.parms[0] - 1;
+ int y = st.parms[1] - 1;
- int i;
- for ( i = 0 ; i < st.nparms ; i++ ) {
- int a = st.parms[i];
- switch ( a ) {
+ xy.x = (x >= cols) ? cols-1 : (x < 0) ? 0 : x;
+ xy.y = (y >= rows) ? rows-1 : (y < 0) ? 0 : y;
+ }
+ break;
+ case 'J':
+ {
+ switch ( st.parms[0] ) {
case 0:
- st.fg = 7;
- st.bg = 7;
- st.intensity = 1;
- st.underline = 0;
- st.blink = 0;
- st.reverse = 0;
+ ansicon_erase(xy.x, xy.y, cols-1, xy.y);
+ if ( xy.y < rows-1 )
+ ansicon_erase(0, xy.y+1, cols-1, rows-1);
break;
+
case 1:
- st.intensity = 2;
+ if ( xy.y > 0 )
+ ansicon_erase(0, 0, cols-1, xy.y-1);
+ if ( xy.y > 0 )
+ ansicon_erase(0, xy.y, xy.x-1, xy.y);
break;
+
case 2:
- st.intensity = 0;
- break;
- case 4:
- st.underline = 1;
- break;
- case 5:
- st.blink = 1;
- break;
- case 7:
- st.reverse = 1;
- break;
- case 21:
- case 22:
- st.intensity = 1;
- break;
- case 24:
- st.underline = 0;
+ ansicon_erase(0, 0, cols-1, rows-1);
break;
- case 25:
- st.blink = 0;
- break;
- case 27:
- st.reverse = 0;
- break;
- case 30 ... 37:
- st.fg = ansi2pc[a-30];
- break;
- case 38:
- st.fg = 7;
- st.underline = 1;
+
+ default:
+ /* Ignore */
break;
- case 39:
- st.fg = 7;
- st.underline = 0;
+ }
+ }
+ break;
+ case 'K':
+ {
+ switch ( st.parms[0] ) {
+ case 0:
+ ansicon_erase(xy.x, xy.y, cols-1, xy.y);
break;
- case 40 ... 47:
- st.bg = ansi2pc[a-40];
+
+ case 1:
+ if ( xy.x > 0 )
+ ansicon_erase(0, xy.y, xy.x-1, xy.y);
break;
- case 49:
- st.bg = 7;
+
+ case 2:
+ ansicon_erase(0, xy.y, cols-1, xy.y);
break;
+
default:
- /* Do nothing */
+ /* Ignore */
break;
}
}
-
- /* Turn into an attribute code */
+ break;
+ case 'm':
{
- int bg = st.bg;
- int fg;
-
- if ( st.underline )
- fg = 0x01;
- else if ( st.intensity == 0 )
- fg = 0x08;
- else
- fg = st.fg;
+ static const int ansi2pc[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
- if ( st.reverse ) {
- bg = fg & 0x07;
- fg &= 0x08;
- fg |= st.bg;
+ int i;
+ for ( i = 0 ; i <= st.nparms ; i++ ) {
+ int a = st.parms[i];
+ switch ( a ) {
+ case 0:
+ st.fg = 7;
+ st.bg = 0;
+ st.intensity = 1;
+ st.underline = 0;
+ st.blink = 0;
+ st.reverse = 0;
+ break;
+ case 1:
+ st.intensity = 2;
+ break;
+ case 2:
+ st.intensity = 0;
+ break;
+ case 4:
+ st.underline = 1;
+ break;
+ case 5:
+ st.blink = 1;
+ break;
+ case 7:
+ st.reverse = 1;
+ break;
+ case 21:
+ case 22:
+ st.intensity = 1;
+ break;
+ case 24:
+ st.underline = 0;
+ break;
+ case 25:
+ st.blink = 0;
+ break;
+ case 27:
+ st.reverse = 0;
+ break;
+ case 30 ... 37:
+ st.fg = ansi2pc[a-30];
+ break;
+ case 38:
+ st.fg = 7;
+ st.underline = 1;
+ break;
+ case 39:
+ st.fg = 7;
+ st.underline = 0;
+ break;
+ case 40 ... 47:
+ st.bg = ansi2pc[a-40];
+ break;
+ case 49:
+ st.bg = 7;
+ break;
+ default:
+ /* Do nothing */
+ break;
+ }
}
+
+ /* Turn into an attribute code */
+ {
+ int bg = st.bg;
+ int fg;
- if ( st.blink )
- bg ^= 0x08;
+ if ( st.underline )
+ fg = 0x01;
+ else if ( st.intensity == 0 )
+ fg = 0x08;
+ else
+ fg = st.fg;
- if ( st.intensity == 2 )
- fg ^= 0x08;
+ if ( st.reverse ) {
+ bg = fg & 0x07;
+ fg &= 0x08;
+ fg |= st.bg;
+ }
- st.attr = (bg << 4) | fg;
+ if ( st.blink )
+ bg ^= 0x08;
+
+ if ( st.intensity == 2 )
+ fg ^= 0x08;
+
+ st.attr = (bg << 4) | fg;
+ }
}
+ break;
+ case 's':
+ st.saved_xy = xy;
+ break;
+ case 'u':
+ xy = st.saved_xy;
+ break;
}
- break;
- case 's':
- st.saved_xy = xy;
- break;
- case 'u':
- xy = st.saved_xy;
- break;
+ st.state = st_init;
}
}
- } while ( again );
+ break;
+ }
/* If we fell off the end of the screen, adjust */
if ( xy.x >= cols ) {
xy.x = 0;
xy.y++;
- if ( xy.y >= rows ) {
- xy.y = 0;
- ireg.eax.w[0] = 0x0601;
- ireg.ebx.b[1] = st.attr;
- ireg.ecx.w[0] = 0;
- ireg.edx.b[1] = rows-1;
- ireg.edx.b[0] = cols-1;
- __intcall(0x10, &ireg, NULL); /* Scroll */
- }
+ }
+ while ( xy.y >= rows ) {
+ xy.y--;
+ ireg.eax.w[0] = 0x0601;
+ ireg.ebx.b[1] = st.attr;
+ ireg.ecx.w[0] = 0;
+ ireg.edx.b[1] = rows-1;
+ ireg.edx.b[0] = cols-1;
+ __intcall(0x10, &ireg, NULL); /* Scroll */
}
/* Update cursor position */
- ireg.eax.b[1] = 0x04;
- ireg.ebx.b[1] = BIOS_PAGE;
+ ireg.eax.b[1] = 0x02;
+ ireg.ebx.b[1] = page;
ireg.edx.b[1] = xy.y;
ireg.edx.b[0] = xy.x;
__intcall(0x10, &ireg, NULL);
}
-static ssize_t ansicon_write(struct file_info *fp, const void *buf, size_t count)
+ssize_t __ansicon_write(struct file_info *fp, const void *buf, size_t count)
{
- com32sys_t ireg;
- const char *bufp = buf;
+ const unsigned char *bufp = buf;
size_t n = 0;
(void)fp;
- memset(&ireg, 0, sizeof ireg);
- ireg.eax.b[1] = 0x04;
-
while ( count-- ) {
ansicon_putchar(*bufp++);
n++;
@@ -411,6 +425,6 @@ const struct output_dev dev_ansicon_w = {
.dev_magic = __DEV_MAGIC,
.flags = __DEV_TTY | __DEV_OUTPUT,
.fileflags = O_WRONLY | O_CREAT | O_TRUNC | O_APPEND,
- .write = ansicon_write,
+ .write = __ansicon_write,
.close = NULL,
};
diff --git a/com32/lib/sys/ansiserial_write.c b/com32/lib/sys/ansiserial_write.c
new file mode 100644
index 00000000..95f1c747
--- /dev/null
+++ b/com32/lib/sys/ansiserial_write.c
@@ -0,0 +1,56 @@
+#ident "$Id$"
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2004 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * ansiserial_write.c
+ *
+ * Write to both to the ANSI console and the serial port
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <com32.h>
+#include <minmax.h>
+#include "file.h"
+
+extern ssize_t __ansicon_write(struct file_info *, const void *, size_t);
+extern ssize_t __serial_write(struct file_info *, const void *, size_t);
+
+static ssize_t __ansiserial_write(struct file_info *fp, const void *buf, size_t count)
+{
+ __ansicon_write(fp, buf, count);
+ return __serial_write(fp, buf, count);
+}
+
+const struct output_dev dev_ansiserial_w = {
+ .dev_magic = __DEV_MAGIC,
+ .flags = __DEV_TTY | __DEV_OUTPUT,
+ .fileflags = O_WRONLY | O_CREAT | O_TRUNC | O_APPEND,
+ .write = __ansiserial_write,
+ .close = NULL,
+};
diff --git a/com32/lib/sys/serial_write.c b/com32/lib/sys/serial_write.c
index 27fd73ca..44f3137f 100644
--- a/com32/lib/sys/serial_write.c
+++ b/com32/lib/sys/serial_write.c
@@ -38,7 +38,7 @@
#include <minmax.h>
#include "file.h"
-static ssize_t __serial_write(struct file_info *fp, const void *buf, size_t count)
+ssize_t __serial_write(struct file_info *fp, const void *buf, size_t count)
{
com32sys_t ireg;
const char *bufp = buf;
diff --git a/com32/modules/Makefile b/com32/modules/Makefile
index af72f6bd..cfd44b43 100644
--- a/com32/modules/Makefile
+++ b/com32/modules/Makefile
@@ -35,7 +35,7 @@ LIBGCC := $(shell $(CC) --print-libgcc)
.SUFFIXES: .lss .c .o .elf .c32
-all: hello.c32
+all: hello.c32 fancyhello.c32
.PRECIOUS: %.o
%.o: %.S
diff --git a/com32/modules/fancyhello.c b/com32/modules/fancyhello.c
new file mode 100644
index 00000000..a59be43a
--- /dev/null
+++ b/com32/modules/fancyhello.c
@@ -0,0 +1,44 @@
+#ident "$Id$"
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2004 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,
+ * Bostom MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * fancyhello.c
+ *
+ * Hello, World! using libcom32 and ASI console
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <console.h>
+
+int main(void)
+{
+ char buffer[1024];
+
+ /* Write both to the ANSI console and the serial port, if configured */
+ openconsole(&dev_stdcon_r, &dev_ansiserial_w);
+
+ printf("(lifesign)\r\n(another)\r\n(another)\r\n");
+ printf("\033[1;33;44m *** \033[37mHello, World!\033[33m *** \033[0m\r\n");
+
+ for (;;) {
+ printf("\033[1;36m>\033[0m ");
+ fgets(buffer, sizeof buffer, stdin);
+ /* fgets() prints an \n for us, but not \r */
+ putchar('\r');
+ if ( !strncmp(buffer, "exit", 4) )
+ break;
+ printf("\033[1m:\033[0m %s\r", buffer);
+ }
+ return 0;
+}
diff --git a/com32/modules/hello.c b/com32/modules/hello.c
index 98964e04..7d0504bc 100644
--- a/com32/modules/hello.c
+++ b/com32/modules/hello.c
@@ -1,7 +1,7 @@
#ident "$Id$"
/* ----------------------------------------------------------------------- *
*
- * Copyright 2002 H. Peter Anvin - All Rights Reserved
+ * Copyright 2004 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