[coreboot] [PATCH 1/2] libpayload, coreinfo: ACS support

Ulf Jordan jordan at chalmers.se
Sun Aug 10 16:42:57 CEST 2008


This patch adds support for handling ACS (the alternate/special graphics 
character set) both on VGA and serial console in libpayload. It also 
updates coreinfo to use the ACS_ macros for line graphics.

Build tested against svn HEAD. To actually get any output, the previously 
sent libpayload-kconfig patch, or equivalent, is needed too. Runtime 
tested with coreboot-v3 in QEMU.

/ulf
-------------- next part --------------
Add support for line drawing characters and the alternate character set.
This enables using the ACS_ curses macros with libpayload.

The translation from ACS_ macros (or characters with attribute A_ALTCHARSET)
is done using one acs map for the video console, one for serial console
(xterm/vt100/vt220), and one fallback, from which an ASCII substitute is
taken if the device specific map doesn't contain an entry (ie NUL).

coreinfo is also adapted to take advantage of the symbolic ACS_ constants.

Signed-off-by: Ulf Jordan <jordan at chalmers.se>

Index: libpayload/include/libpayload.h
===================================================================
--- libpayload/include/libpayload.h.orig	2008-08-10 15:45:28.000000000 +0200
+++ libpayload/include/libpayload.h	2008-08-10 15:47:03.000000000 +0200
@@ -110,6 +110,8 @@
 void serial_clear(void);
 void serial_start_bold(void);
 void serial_end_bold(void);
+void serial_start_altcharset(void);
+void serial_end_altcharset(void);
 void serial_set_cursor(int y, int x);
 
 /* drivers/speaker.c */
Index: libpayload/curses/tinycurses.c
===================================================================
--- libpayload/curses/tinycurses.c.orig	2008-08-10 15:45:28.000000000 +0200
+++ libpayload/curses/tinycurses.c	2008-08-10 15:47:03.000000000 +0200
@@ -2,6 +2,7 @@
  * This file is part of the libpayload project.
  *
  * Copyright (C) 2007 Uwe Hermann <uwe at hermann-uwe.de>
+ * Copyright (C) 2008 Ulf Jordan <jordan at chalmers.se>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -88,6 +89,69 @@
 SCREEN *SP;
 chtype acs_map[128];
 
+/* See terminfo(5). */
+chtype fallback_acs_map[128] =
+	{
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	'>',	'<',	'^',	'v',	' ',
+	'#',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	' ',	' ',	' ',	' ',	' ',	' ',	' ',	' ',
+	'+',	':',	' ',	' ',	' ',	' ',	'\\',   '#',
+	'#',	'#',	'+',	'+',	'+',	'+',	'+',	'~',
+	'-',	'-',	'-',	'_',	'+',	'+',	'+',	'+',
+	'|',	'<',	'>',	'*',	'!',	'f',	'o',	' ',
+	};
+
+/* See acsc of vt100. */
+chtype serial_acs_map[128] =
+	{
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	'`',	'a',	0,	0,	0,	0,	'f',	'g',
+	0,	0,	'j',	'k',	'l',	'm',	'n',	'o',
+	'p',	'q',	'r',	's',	't',	'u',	'v',	'w',
+	'x',	'y',	'z',	'{',	'|',	'}',	'~',	0,
+	};
+
+/* See acsc of linux. */
+chtype console_acs_map[128] =
+	{
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	'\020', '\021', '\030', '\031',	0,
+	'\333',	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	'\004',	'\261',	0,	0,	0,	0,	'\370',	'\361',
+	'\260',	'\316',	'\331',	'\277',	'\332',	'\300',	'\305',	'~',
+	'\304',	'\304',	'\304',	'_',	'\303', '\264', '\301',	'\302',
+	'\263',	'\363',	'\362',	'\342',	'\330',	'\234',	'\376',	0,
+	};
+
 // FIXME: Ugly (and insecure!) hack!
 char sprintf_tmp[1024];
 
@@ -213,11 +277,14 @@
 /** Note: Must _not_ be called twice! */
 WINDOW *initscr(void)
 {
-	int x, y;
+	int x, y, i;
 
 	// newterm(name, stdout, stdin);
 	// def_prog_mode();
 
+	for (i = 0; i < 128; i++)
+	  acs_map[i] = (chtype) i | A_ALTCHARSET;
+
 	if (curses_flags & F_ENABLE_SERIAL) {
 		serial_clear();
 	}
@@ -409,12 +476,12 @@
 	// NCURSES_CH_T wch;
 	// SetChar2(wch, ch);
 
-	win->_line[win->_cury].text[win->_curx].chars[0] = ch;
-
-	/* Use the window attributes - perhaps we also pull attributes from
-	   the ch itself, I don't know */
+	win->_line[win->_cury].text[win->_curx].chars[0] =
+		((ch) & (chtype)A_CHARTEXT);
 
 	win->_line[win->_cury].text[win->_curx].attr = WINDOW_ATTRS(win);
+	win->_line[win->_cury].text[win->_curx].attr |=
+		((ch) & (chtype)A_ATTRIBUTES);
 	win->_curx++;	// FIXME
 
 	// if (win && (waddch_nosync(win, wch) != ERR)) {
@@ -595,10 +662,14 @@
 {
 	// FIXME.
 	int serial_is_bold = 0;
+	int serial_is_altcharset = 0;
 
 	int x, y;
+	chtype ch;
+	int need_altcharset;
 
 	serial_end_bold();
+	serial_end_altcharset();
 
 	for (y = 0; y <= win->_maxy; y++) {
 
@@ -614,6 +685,7 @@
 				((int)color_pairs[PAIR_NUMBER(attr)]) << 8;
 
 			if (curses_flags & F_ENABLE_SERIAL) {
+				ch = win->_line[y].text[x].chars[0];
 
 				if (attr & A_BOLD) {
 					if (!serial_is_bold) {
@@ -628,10 +700,28 @@
 					}
 				}
 
-				serial_putchar(win->_line[y].text[x].chars[0]);
+				need_altcharset = 0;
+				if (attr & A_ALTCHARSET) {
+					if (serial_acs_map[ch & 0x7f]) {
+						ch = serial_acs_map[ch & 0x7f];
+						need_altcharset = 1;
+					} else
+						ch = fallback_acs_map[ch & 0x7f];
+				}
+				if (need_altcharset && !serial_is_altcharset) {
+					serial_start_altcharset();
+					serial_is_altcharset = 1;
+				}
+				if (!need_altcharset && serial_is_altcharset) {
+					serial_end_altcharset();
+					serial_is_altcharset = 0;
+				}
+
+				serial_putchar(ch);
 			}
 
 			if (curses_flags & F_ENABLE_CONSOLE) {
+				ch = win->_line[y].text[x].chars[0];
 
 				/* Handle some of the attributes. */
 				if (attr & A_BOLD)
@@ -643,6 +733,12 @@
 					c = (c >> 4) & 0xf00;
 					c |= tmp << 12;
 				}
+				if (attr & A_ALTCHARSET) {
+					if (console_acs_map[ch & 0x7f])
+						ch = console_acs_map[ch & 0x7f];
+					else
+						ch = fallback_acs_map[ch & 0x7f];
+				}
 
 				/*
 				 * FIXME: Somewhere along the line, the
@@ -650,7 +746,7 @@
 				 * For now grab just the 8 bit character,
 				 * but this will break wide characters!
 				 */
-				c |= (chtype) (win->_line[y].text[x].chars[0] & 0xff);
+				c |= (chtype) (ch & 0xff);
 				video_console_putc(win->_begy + y, win->_begx + x, c);
 			}
 		}
Index: libpayload/drivers/serial.c
===================================================================
--- libpayload/drivers/serial.c.orig	2008-08-10 15:45:28.000000000 +0200
+++ libpayload/drivers/serial.c	2008-08-10 15:47:03.000000000 +0200
@@ -2,6 +2,7 @@
  * This file is part of the libpayload project.
  *
  * Copyright (C) 2008 Advanced Micro Devices, Inc.
+ * Copyright (C) 2008 Ulf Jordan <jordan at chalmers.se>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -104,6 +105,10 @@
 #define VT100_SBOLD       "\e[1m"
 #define VT100_EBOLD       "\e[m"
 #define VT100_CURSOR_ADDR "\e[%d;%dH"
+/* The following smacs/rmacs are actually for xterm; a real vt100 has
+   enacs=\E(B\E)0, smacs=^N, rmacs=^O.  */
+#define VT100_SMACS       "\e(0"
+#define VT100_RMACS       "\e(B"
 
 static void serial_putcmd(char *str)
 {
@@ -126,6 +131,16 @@
 	serial_putcmd(VT100_EBOLD);
 }
 
+void serial_start_altcharset(void)
+{
+	serial_putcmd(VT100_SMACS);
+}
+
+void serial_end_altcharset(void)
+{
+	serial_putcmd(VT100_RMACS);
+}
+
 void serial_set_cursor(int y, int x)
 {
 	char buffer[32];
Index: coreinfo/coreinfo.c
===================================================================
--- coreinfo/coreinfo.c.orig	2008-08-10 15:45:28.000000000 +0200
+++ coreinfo/coreinfo.c	2008-08-10 15:47:03.000000000 +0200
@@ -89,7 +89,7 @@
 
 	wmove(win, 1, 1);
 	for (i = 0; i < 78; i++)
-		waddch(win, '\304');
+		waddch(win, ACS_HLINE);
 }
 
 static void print_submenu(struct coreinfo_cat *cat)
Index: coreinfo/pci_module.c
===================================================================
--- coreinfo/pci_module.c.orig	2008-08-10 15:45:28.000000000 +0200
+++ coreinfo/pci_module.c	2008-08-10 15:47:03.000000000 +0200
@@ -144,11 +144,11 @@
 
 		if (i == 0) {
 			if (item != 0)
-				mvwprintw(win, 2 + i, 19, "\30");
+				mvwaddch(win, 2 + i, 19, ACS_UARROW);
 		}
 		if (i == MENU_VISIBLE - 1) {
 			if ((item + 1) < devices_index)
-				mvwprintw(win, 2 + i, 19, "\31");
+				mvwaddch(win, 2 + i, 19, ACS_DARROW);
 		}
 	}
 
@@ -160,12 +160,12 @@
 	wmove(win, 3, 25);
 
 	for (i = 0; i < 48; i++)
-		waddch(win, (i == 0) ? '\332' : '\304');
+		waddch(win, (i == 0) ? ACS_ULCORNER : ACS_HLINE);
 
 	for (i = 0; i < 4; i++) {
 		mvwprintw(win, 4 + i, 23, "%2.2X", i * 16);
 		wmove(win, 4 + i, 25);
-		waddch(win, '\263');
+		waddch(win, ACS_VLINE);
 	}
 
 	show_config_space(win, 4, 26, menu_selected);
Index: coreinfo/lar_module.c
===================================================================
--- coreinfo/lar_module.c.orig	2008-08-10 15:45:28.000000000 +0200
+++ coreinfo/lar_module.c	2008-08-10 15:47:03.000000000 +0200
@@ -66,7 +66,7 @@
 
 	/* Draw a line down the middle. */
 	for (i = 2; i < 21; i++)
-		mvwaddch(win, i, 30, '\263');
+		mvwaddch(win, i, 30, ACS_VLINE);
 
 	/* Draw the names down the left side. */
 	for (i = 0; i < lcount; i++) {
Index: coreinfo/nvram_module.c
===================================================================
--- coreinfo/nvram_module.c.orig	2008-08-10 15:45:28.000000000 +0200
+++ coreinfo/nvram_module.c	2008-08-10 15:47:03.000000000 +0200
@@ -36,9 +36,9 @@
 
 	/* Print vertical and horizontal line. */
 	for (i = 0; i < 18; i++)
-		mvwaddch(win, 3 + i, 3, '\263');
+		mvwaddch(win, 3 + i, 3, ACS_VLINE);
 	for (i = 0; i < 48; i++)
-		mvwaddch(win, 3, 3 + i, (i == 0) ? '\332' : '\304');
+		mvwaddch(win, 3, 3 + i, (i == 0) ? ACS_ULCORNER : ACS_HLINE);
 
 	/* Dump NVRAM contents. */
 	for (i = 1; i < 257; i++) {


More information about the coreboot mailing list