summaryrefslogtreecommitdiffstats
path: root/qemu/roms/ipxe/src/hci/mucurses
diff options
context:
space:
mode:
authorYang Zhang <yang.z.zhang@intel.com>2015-08-28 09:58:54 +0800
committerYang Zhang <yang.z.zhang@intel.com>2015-09-01 12:44:00 +0800
commite44e3482bdb4d0ebde2d8b41830ac2cdb07948fb (patch)
tree66b09f592c55df2878107a468a91d21506104d3f /qemu/roms/ipxe/src/hci/mucurses
parent9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 (diff)
Add qemu 2.4.0
Change-Id: Ic99cbad4b61f8b127b7dc74d04576c0bcbaaf4f5 Signed-off-by: Yang Zhang <yang.z.zhang@intel.com>
Diffstat (limited to 'qemu/roms/ipxe/src/hci/mucurses')
-rw-r--r--qemu/roms/ipxe/src/hci/mucurses/alert.c18
-rw-r--r--qemu/roms/ipxe/src/hci/mucurses/ansi_screen.c102
-rw-r--r--qemu/roms/ipxe/src/hci/mucurses/clear.c100
-rw-r--r--qemu/roms/ipxe/src/hci/mucurses/colour.c66
-rw-r--r--qemu/roms/ipxe/src/hci/mucurses/cursor.h37
-rw-r--r--qemu/roms/ipxe/src/hci/mucurses/edging.c111
-rw-r--r--qemu/roms/ipxe/src/hci/mucurses/kb.c143
-rw-r--r--qemu/roms/ipxe/src/hci/mucurses/mucurses.c156
-rw-r--r--qemu/roms/ipxe/src/hci/mucurses/mucurses.h23
-rw-r--r--qemu/roms/ipxe/src/hci/mucurses/print.c86
-rw-r--r--qemu/roms/ipxe/src/hci/mucurses/print_nadv.c26
-rw-r--r--qemu/roms/ipxe/src/hci/mucurses/slk.c363
-rw-r--r--qemu/roms/ipxe/src/hci/mucurses/widgets/editbox.c103
-rw-r--r--qemu/roms/ipxe/src/hci/mucurses/winattrs.c133
-rw-r--r--qemu/roms/ipxe/src/hci/mucurses/windows.c158
-rw-r--r--qemu/roms/ipxe/src/hci/mucurses/wininit.c38
16 files changed, 1663 insertions, 0 deletions
diff --git a/qemu/roms/ipxe/src/hci/mucurses/alert.c b/qemu/roms/ipxe/src/hci/mucurses/alert.c
new file mode 100644
index 000000000..00e959a89
--- /dev/null
+++ b/qemu/roms/ipxe/src/hci/mucurses/alert.c
@@ -0,0 +1,18 @@
+#include <curses.h>
+#include <stdio.h>
+
+/** @file
+ *
+ * MuCurses alert functions
+ *
+ */
+
+/**
+ * Audible signal
+ *
+ * @ret rc return status code
+ */
+int beep ( void ) {
+ printf("\a");
+ return OK;
+}
diff --git a/qemu/roms/ipxe/src/hci/mucurses/ansi_screen.c b/qemu/roms/ipxe/src/hci/mucurses/ansi_screen.c
new file mode 100644
index 000000000..1d3143f89
--- /dev/null
+++ b/qemu/roms/ipxe/src/hci/mucurses/ansi_screen.c
@@ -0,0 +1,102 @@
+#include <stdio.h>
+#include <curses.h>
+#include <ipxe/ansicol.h>
+#include <ipxe/console.h>
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+static void ansiscr_reset(struct _curses_screen *scr) __nonnull;
+static void ansiscr_movetoyx(struct _curses_screen *scr,
+ unsigned int y, unsigned int x) __nonnull;
+static void ansiscr_putc(struct _curses_screen *scr, chtype c) __nonnull;
+
+static unsigned int saved_usage;
+
+static void ansiscr_attrs ( struct _curses_screen *scr, attr_t attrs ) {
+ int bold = ( attrs & A_BOLD );
+ attr_t cpair = PAIR_NUMBER ( attrs );
+
+ if ( scr->attrs != attrs ) {
+ scr->attrs = attrs;
+ /* Reset attributes and set/clear bold as appropriate */
+ printf ( "\033[0;%dm", ( bold ? 1 : 22 ) );
+ /* Set foreground and background colours */
+ ansicol_set_pair ( cpair );
+ }
+}
+
+static void ansiscr_reset ( struct _curses_screen *scr ) {
+ /* Reset terminal attributes and clear screen */
+ scr->attrs = 0;
+ scr->curs_x = 0;
+ scr->curs_y = 0;
+ printf ( "\0330m" );
+ ansicol_set_pair ( CPAIR_DEFAULT );
+ printf ( "\033[2J" );
+}
+
+static void ansiscr_init ( struct _curses_screen *scr ) {
+ saved_usage = console_set_usage ( CONSOLE_USAGE_TUI );
+ ansiscr_reset ( scr );
+}
+
+static void ansiscr_exit ( struct _curses_screen *scr ) {
+ ansiscr_reset ( scr );
+ console_set_usage ( saved_usage );
+}
+
+static void ansiscr_erase ( struct _curses_screen *scr, attr_t attrs ) {
+ ansiscr_attrs ( scr, attrs );
+ printf ( "\033[2J" );
+}
+
+static void ansiscr_movetoyx ( struct _curses_screen *scr,
+ unsigned int y, unsigned int x ) {
+ if ( ( x != scr->curs_x ) || ( y != scr->curs_y ) ) {
+ /* ANSI escape sequence to update cursor position */
+ printf ( "\033[%d;%dH", ( y + 1 ), ( x + 1 ) );
+ scr->curs_x = x;
+ scr->curs_y = y;
+ }
+}
+
+static void ansiscr_putc ( struct _curses_screen *scr, chtype c ) {
+ unsigned int character = ( c & A_CHARTEXT );
+ attr_t attrs = ( c & ( A_ATTRIBUTES | A_COLOR ) );
+
+ /* Update attributes if changed */
+ ansiscr_attrs ( scr, attrs );
+
+ /* Print the actual character */
+ putchar ( character );
+
+ /* Update expected cursor position */
+ if ( ++(scr->curs_x) == COLS ) {
+ scr->curs_x = 0;
+ ++scr->curs_y;
+ }
+}
+
+static int ansiscr_getc ( struct _curses_screen *scr __unused ) {
+ return getchar();
+}
+
+static bool ansiscr_peek ( struct _curses_screen *scr __unused ) {
+ return iskey();
+}
+
+static void ansiscr_cursor ( struct _curses_screen *scr __unused,
+ int visibility ) {
+ printf ( "\033[?25%c", ( visibility ? 'h' : 'l' ) );
+}
+
+SCREEN _ansi_screen = {
+ .init = ansiscr_init,
+ .exit = ansiscr_exit,
+ .erase = ansiscr_erase,
+ .movetoyx = ansiscr_movetoyx,
+ .putc = ansiscr_putc,
+ .getc = ansiscr_getc,
+ .peek = ansiscr_peek,
+ .cursor = ansiscr_cursor,
+};
diff --git a/qemu/roms/ipxe/src/hci/mucurses/clear.c b/qemu/roms/ipxe/src/hci/mucurses/clear.c
new file mode 100644
index 000000000..f5e52ca20
--- /dev/null
+++ b/qemu/roms/ipxe/src/hci/mucurses/clear.c
@@ -0,0 +1,100 @@
+#include <curses.h>
+#include "mucurses.h"
+#include "cursor.h"
+
+/** @file
+ *
+ * MuCurses clearing functions
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * Clear a window to the bottom from current cursor position
+ *
+ * @v *win subject window
+ * @ret rc return status code
+ */
+int wclrtobot ( WINDOW *win ) {
+ struct cursor_pos pos;
+
+ _store_curs_pos( win, &pos );
+ do {
+ _wputc( win, ' ', WRAP );
+ } while ( win->curs_y + win->curs_x );
+ _restore_curs_pos( win, &pos );
+
+ return OK;
+}
+
+/**
+ * Clear a window to the end of the current line
+ *
+ * @v *win subject window
+ * @ret rc return status code
+ */
+int wclrtoeol ( WINDOW *win ) {
+ struct cursor_pos pos;
+
+ _store_curs_pos( win, &pos );
+ while ( ( win->curs_y - pos.y ) == 0 ) {
+ _wputc( win, ' ', WRAP );
+ }
+ _restore_curs_pos( win, &pos );
+
+ return OK;
+}
+
+/**
+ * Delete character under the cursor in a window
+ *
+ * @v *win subject window
+ * @ret rc return status code
+ */
+int wdelch ( WINDOW *win ) {
+ _wputc( win, ' ', NOWRAP );
+ _wcursback( win );
+
+ return OK;
+}
+
+/**
+ * Delete line under a window's cursor
+ *
+ * @v *win subject window
+ * @ret rc return status code
+ */
+int wdeleteln ( WINDOW *win ) {
+ struct cursor_pos pos;
+
+ _store_curs_pos( win, &pos );
+ /* let's just set the cursor to the beginning of the line and
+ let wclrtoeol do the work :) */
+ wmove( win, win->curs_y, 0 );
+ wclrtoeol( win );
+ _restore_curs_pos( win, &pos );
+ return OK;
+}
+
+/**
+ * Completely clear a window
+ *
+ * @v *win subject window
+ * @ret rc return status code
+ */
+int werase ( WINDOW *win ) {
+ wmove( win, 0, 0 );
+ wclrtobot( win );
+ return OK;
+}
+
+/**
+ * Completely clear the screen
+ *
+ * @ret rc return status code
+ */
+int erase ( void ) {
+ stdscr->scr->erase( stdscr->scr, stdscr->attrs );
+ return OK;
+}
diff --git a/qemu/roms/ipxe/src/hci/mucurses/colour.c b/qemu/roms/ipxe/src/hci/mucurses/colour.c
new file mode 100644
index 000000000..c1359c868
--- /dev/null
+++ b/qemu/roms/ipxe/src/hci/mucurses/colour.c
@@ -0,0 +1,66 @@
+#include <curses.h>
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct colour_pair {
+ short fcol;
+ short bcol;
+};
+
+static struct colour_pair cpairs[COLOUR_PAIRS] = {
+ [0] = { COLOUR_WHITE, COLOUR_BLACK },
+};
+
+/**
+ * Identify the RGB components of a given colour value
+ *
+ * @v colour colour value
+ * @v *red address to store red component
+ * @v *green address to store green component
+ * @v *blue address to store blue component
+ * @ret rc return status code
+ */
+int colour_content ( short colour, short *red, short *green, short *blue ) {
+ *red = ( ( colour & COLOUR_RED ) ? 1 : 0 );
+ *green = ( ( colour & COLOUR_GREEN ) ? 1 : 0 );
+ *blue = ( ( colour & COLOUR_BLUE ) ? 1 : 0 );
+ return OK;
+}
+
+/**
+ * Initialise colour pair
+ *
+ * @v pair colour pair number
+ * @v fcol foreground colour
+ * @v bcol background colour
+ */
+int init_pair ( short pair, short fcol, short bcol ) {
+ struct colour_pair *cpair;
+
+ if ( ( pair < 1 ) || ( pair >= COLOUR_PAIRS ) )
+ return ERR;
+
+ cpair = &cpairs[pair];
+ cpair->fcol = fcol;
+ cpair->bcol = bcol;
+ return OK;
+}
+
+/**
+ * Get colours of colour pair
+ *
+ * @v pair colour pair number
+ * @ret fcol foreground colour
+ * @ret bcol background colour
+ */
+int pair_content ( short pair, short *fcol, short *bcol ) {
+ struct colour_pair *cpair;
+
+ if ( ( pair < 0 ) || ( pair >= COLOUR_PAIRS ) )
+ return ERR;
+
+ cpair = &cpairs[pair];
+ *fcol = cpair->fcol;
+ *bcol = cpair->bcol;
+ return OK;
+}
diff --git a/qemu/roms/ipxe/src/hci/mucurses/cursor.h b/qemu/roms/ipxe/src/hci/mucurses/cursor.h
new file mode 100644
index 000000000..16b7d27c2
--- /dev/null
+++ b/qemu/roms/ipxe/src/hci/mucurses/cursor.h
@@ -0,0 +1,37 @@
+#ifndef CURSOR_H
+#define CURSOR_H
+
+/** @file
+ *
+ * MuCurses cursor implementation specific header file
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+struct cursor_pos {
+ unsigned int y, x;
+};
+
+/**
+ * Restore cursor position from encoded backup variable
+ *
+ * @v *win window on which to operate
+ * @v *pos pointer to struct in which original cursor position is stored
+ */
+static inline void _restore_curs_pos ( WINDOW *win, struct cursor_pos *pos ) {
+ wmove ( win, pos->y, pos->x );
+}
+
+/**
+ * Store cursor position for later restoration
+ *
+ * @v *win window on which to operate
+ * @v *pos pointer to struct in which to store cursor position
+ */
+static inline void _store_curs_pos ( WINDOW *win, struct cursor_pos *pos ) {
+ pos->y = win->curs_y;
+ pos->x = win->curs_x;
+}
+
+#endif /* CURSOR_H */
diff --git a/qemu/roms/ipxe/src/hci/mucurses/edging.c b/qemu/roms/ipxe/src/hci/mucurses/edging.c
new file mode 100644
index 000000000..eccd32422
--- /dev/null
+++ b/qemu/roms/ipxe/src/hci/mucurses/edging.c
@@ -0,0 +1,111 @@
+#include <curses.h>
+#include "mucurses.h"
+#include "cursor.h"
+
+/** @file
+ *
+ * MuCurses edging functions
+ *
+ */
+
+/**
+ * Draw borders from single-byte characters and renditions around a
+ * window
+ *
+ * @v *win window to be bordered
+ * @v verch vertical chtype
+ * @v horch horizontal chtype
+ * @ret rc return status code
+ */
+int box ( WINDOW *win, chtype verch, chtype horch ) {
+ chtype corner = '+' | win->attrs; /* default corner character */
+ return wborder( win, verch, verch, horch, horch,
+ corner, corner, corner, corner );
+}
+
+/**
+ * Draw borders from single-byte characters and renditions around a
+ * window
+ *
+ * @v *win window to be bordered
+ * @v ls left side
+ * @v rs right side
+ * @v ts top
+ * @v bs bottom
+ * @v tl top left corner
+ * @v tr top right corner
+ * @v bl bottom left corner
+ * @v br bottom right corner
+ * @ret rc return status code
+ */
+int wborder ( WINDOW *win, chtype ls, chtype rs,
+ chtype ts, chtype bs, chtype tl,
+ chtype tr, chtype bl, chtype br ) {
+ struct cursor_pos pos;
+
+ _store_curs_pos( win, &pos );
+ wmove(win,0,0);
+
+ _wputch(win,tl,WRAP);
+ while ( ( win->width - 1 ) - win->curs_x ) {
+ _wputch(win,ts,WRAP);
+ }
+ _wputch(win,tr,WRAP);
+
+ while ( ( win->height - 1 ) - win->curs_y ) {
+ _wputch(win,ls,WRAP);
+ wmove(win,win->curs_y,(win->width)-1);
+ _wputch(win,rs,WRAP);
+ }
+
+ _wputch(win,bl,WRAP);
+ while ( ( win->width -1 ) - win->curs_x ) {
+ _wputch(win,bs,WRAP);
+ }
+ _wputch(win,br,NOWRAP); /* do not wrap last char to leave
+ cursor in last position */
+ _restore_curs_pos( win, &pos );
+
+ return OK;
+}
+
+/**
+ * Create a horizontal line in a window
+ *
+ * @v *win subject window
+ * @v ch rendition and character
+ * @v n max number of chars (wide) to render
+ * @ret rc return status code
+ */
+int whline ( WINDOW *win, chtype ch, int n ) {
+ struct cursor_pos pos;
+
+ _store_curs_pos ( win, &pos );
+ while ( ( win->curs_x - win->width ) && n-- ) {
+ _wputch ( win, ch, NOWRAP );
+ }
+ _restore_curs_pos ( win, &pos );
+
+ return OK;
+}
+
+/**
+ * Create a vertical line in a window
+ *
+ * @v *win subject window
+ * @v ch rendition and character
+ * @v n max number of chars (high) to render
+ * @ret rc return status code
+ */
+int wvline ( WINDOW *win, chtype ch, int n ) {
+ struct cursor_pos pos;
+
+ _store_curs_pos ( win, &pos );
+ while ( ( win->curs_y - win->height ) && n-- ) {
+ _wputch ( win, ch, NOWRAP );
+ wmove( win, ++(win->curs_y), pos.x);
+ }
+ _restore_curs_pos ( win, &pos );
+
+ return OK;
+}
diff --git a/qemu/roms/ipxe/src/hci/mucurses/kb.c b/qemu/roms/ipxe/src/hci/mucurses/kb.c
new file mode 100644
index 000000000..b38c8c146
--- /dev/null
+++ b/qemu/roms/ipxe/src/hci/mucurses/kb.c
@@ -0,0 +1,143 @@
+#include <curses.h>
+#include <stddef.h>
+#include <unistd.h>
+#include "mucurses.h"
+
+/** @file
+ *
+ * MuCurses keyboard input handling functions
+ */
+
+#define INPUT_DELAY 200 // half-blocking delay timer resolution (ms)
+#define INPUT_DELAY_TIMEOUT 1000 // half-blocking delay timeout
+
+int m_delay; /*
+ < 0 : blocking read
+ 0 : non-blocking read
+ > 0 : timed blocking read
+ */
+bool m_echo;
+bool m_cbreak;
+
+static int _wgetc ( WINDOW *win ) {
+ int timer, c;
+
+ if ( win == NULL )
+ return ERR;
+
+ timer = INPUT_DELAY_TIMEOUT;
+ while ( ! win->scr->peek( win->scr ) ) {
+ if ( m_delay == 0 ) // non-blocking read
+ return ERR;
+ if ( timer > 0 ) { // time-limited blocking read
+ if ( m_delay > 0 )
+ timer -= INPUT_DELAY;
+ mdelay( INPUT_DELAY );
+ } else { return ERR; } // non-blocking read
+ }
+
+ c = win->scr->getc( win->scr );
+
+ if ( m_echo && ( c >= 32 && c <= 126 ) ) // printable ASCII characters
+ _wputch( win, (chtype) ( c | win->attrs ), WRAP );
+
+ return c;
+}
+
+/**
+ * Pop a character from the FIFO into a window
+ *
+ * @v *win window in which to echo input
+ * @ret c char from input stream
+ */
+int wgetch ( WINDOW *win ) {
+ int c;
+
+ c = _wgetc( win );
+
+ if ( m_echo ) {
+ if ( c >= KEY_MIN ) {
+ switch(c) {
+ case KEY_LEFT :
+ case KEY_BACKSPACE :
+ _wcursback( win );
+ wdelch( win );
+ break;
+ default :
+ beep();
+ break;
+ }
+ } else {
+ _wputch( win, (chtype)( c | win->attrs ), WRAP );
+ }
+ }
+
+ return c;
+}
+
+/**
+ * Read at most n characters from the FIFO into a window
+ *
+ * @v *win window in which to echo input
+ * @v *str pointer to string in which to store result
+ * @v n maximum number of characters to read into string (inc. NUL)
+ * @ret rc return status code
+ */
+int wgetnstr ( WINDOW *win, char *str, int n ) {
+ char *_str;
+ int c;
+
+ if ( n == 0 ) {
+ *str = '\0';
+ return OK;
+ }
+
+ _str = str;
+
+ while ( ( c = _wgetc( win ) ) != ERR ) {
+ /* termination enforcement - don't let us go past the
+ end of the allocated buffer... */
+ if ( n == 0 && ( c >= 32 && c <= 126 ) ) {
+ _wcursback( win );
+ wdelch( win );
+ } else {
+ if ( c >= KEY_MIN ) {
+ switch(c) {
+ case KEY_LEFT :
+ case KEY_BACKSPACE :
+ _wcursback( win );
+ wdelch( win );
+ break;
+ case KEY_ENTER :
+ *_str = '\0';
+ return OK;
+ default :
+ beep();
+ break;
+ }
+ }
+ if ( c >= 32 && c <= 126 ) {
+ *(_str++) = c; n--;
+ }
+ }
+ }
+
+ return ERR;
+}
+
+
+/**
+ *
+ */
+int echo ( void ) {
+ m_echo = TRUE;
+ return OK;
+}
+
+/**
+ *
+ */
+int noecho ( void ) {
+ m_echo = FALSE;
+ return OK;
+}
diff --git a/qemu/roms/ipxe/src/hci/mucurses/mucurses.c b/qemu/roms/ipxe/src/hci/mucurses/mucurses.c
new file mode 100644
index 000000000..b67445baf
--- /dev/null
+++ b/qemu/roms/ipxe/src/hci/mucurses/mucurses.c
@@ -0,0 +1,156 @@
+#include <curses.h>
+#include "mucurses.h"
+
+/** @file
+ *
+ * MuCurses core functions
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+static void _wupdcurs ( WINDOW *win ) __nonnull;
+void _wputch ( WINDOW *win, chtype ch, int wrap ) __nonnull;
+void _wputc ( WINDOW *win, char c, int wrap ) __nonnull;
+void _wcursback ( WINDOW *win ) __nonnull;
+void _wputchstr ( WINDOW *win, const chtype *chstr, int wrap, int n ) __nonnull;
+void _wputstr ( WINDOW *win, const char *str, int wrap, int n ) __nonnull;
+int wmove ( WINDOW *win, int y, int x ) __nonnull;
+
+WINDOW _stdscr = {
+ .attrs = A_DEFAULT,
+ .ori_y = 0,
+ .ori_x = 0,
+ .curs_y = 0,
+ .curs_x = 0,
+ .scr = &_ansi_screen,
+};
+
+/*
+ * Primitives
+ */
+
+/**
+ * Update cursor position
+ *
+ * @v *win window in which to update position
+ */
+static void _wupdcurs ( WINDOW *win ) {
+ win->scr->movetoyx ( win->scr, win->ori_y + win->curs_y,
+ win->ori_x + win->curs_x );
+}
+
+/**
+ * Write a single character rendition to a window
+ *
+ * @v *win window in which to write
+ * @v ch character rendition to write
+ * @v wrap wrap "switch"
+ */
+void _wputch ( WINDOW *win, chtype ch, int wrap ) {
+ /* make sure we set the screen cursor to the right position
+ first! */
+ _wupdcurs(win);
+ win->scr->putc(win->scr, ch);
+ if ( ++(win->curs_x) - win->width == 0 ) {
+ if ( wrap == WRAP ) {
+ win->curs_x = 0;
+ /* specification says we should really scroll,
+ but we have no buffer to scroll with, so we
+ can only overwrite back at the beginning of
+ the window */
+ if ( ++(win->curs_y) - win->height == 0 )
+ win->curs_y = 0;
+ } else {
+ (win->curs_x)--;
+ }
+ }
+}
+
+/**
+ * Write a single character to a window
+ *
+ * @v *win window in which to write
+ * @v c character rendition to write
+ * @v wrap wrap "switch"
+ */
+void _wputc ( WINDOW *win, char c, int wrap ) {
+ _wputch ( win, ( ( ( unsigned char ) c ) | win->attrs ), wrap );
+}
+
+/**
+ * Retreat the cursor back one position (useful for a whole host of
+ * ops)
+ *
+ * @v *win window in which to retreat
+ */
+void _wcursback ( WINDOW *win ) {
+ if ( win->curs_x == 0 ) {
+ if ( win->curs_y == 0 )
+ win->curs_y = win->height - 1;
+ win->curs_x = win->width = 1;
+ } else {
+ win->curs_x--;
+ }
+
+ _wupdcurs(win);
+}
+
+/**
+ * Write a chtype string to a window
+ *
+ * @v *win window in which to write
+ * @v *chstr chtype string
+ * @v wrap wrap "switch"
+ * @v n write at most n chtypes
+ */
+void _wputchstr ( WINDOW *win, const chtype *chstr, int wrap, int n ) {
+ for ( ; *chstr && n-- ; chstr++ ) {
+ _wputch(win,*chstr,wrap);
+ }
+}
+
+/**
+ * Write a standard c-style string to a window
+ *
+ * @v *win window in which to write
+ * @v *str string
+ * @v wrap wrap "switch"
+ * @v n write at most n chars from *str
+ */
+void _wputstr ( WINDOW *win, const char *str, int wrap, int n ) {
+ for ( ; *str && n-- ; str++ ) {
+ _wputc ( win, *str, wrap );
+ }
+}
+
+/**
+ * Move a window's cursor to the specified position
+ *
+ * @v *win window to be operated on
+ * @v y Y position
+ * @v x X position
+ * @ret rc return status code
+ */
+int wmove ( WINDOW *win, int y, int x ) {
+ /* chech for out-of-bounds errors */
+ if ( ( (unsigned)y >= win->height ) ||
+ ( (unsigned)x >= win->width ) ) {
+ return ERR;
+ }
+
+ win->curs_y = y;
+ win->curs_x = x;
+ _wupdcurs(win);
+ return OK;
+}
+
+/**
+ * Set cursor visibility
+ *
+ * @v visibility cursor visibility
+ */
+int curs_set ( int visibility ) {
+ stdscr->scr->cursor ( stdscr->scr, visibility );
+ return OK;
+}
diff --git a/qemu/roms/ipxe/src/hci/mucurses/mucurses.h b/qemu/roms/ipxe/src/hci/mucurses/mucurses.h
new file mode 100644
index 000000000..7ac1086ac
--- /dev/null
+++ b/qemu/roms/ipxe/src/hci/mucurses/mucurses.h
@@ -0,0 +1,23 @@
+#ifndef _MUCURSES_H
+#define _MUCURSES_H
+
+/** @file
+ *
+ * MuCurses core implementation specific header file
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#define WRAP 0
+#define NOWRAP 1
+
+extern SCREEN _ansi_screen;
+
+extern void _wputch ( WINDOW *win, chtype ch, int wrap ) __nonnull;
+extern void _wputc ( WINDOW *win, char c, int wrap ) __nonnull;
+extern void _wputchstr ( WINDOW *win, const chtype *chstr, int wrap, int n ) __nonnull;
+extern void _wputstr ( WINDOW *win, const char *str, int wrap, int n ) __nonnull;
+extern void _wcursback ( WINDOW *win ) __nonnull;
+
+#endif /* _MUCURSES_H */
diff --git a/qemu/roms/ipxe/src/hci/mucurses/print.c b/qemu/roms/ipxe/src/hci/mucurses/print.c
new file mode 100644
index 000000000..9c682588b
--- /dev/null
+++ b/qemu/roms/ipxe/src/hci/mucurses/print.c
@@ -0,0 +1,86 @@
+#include <curses.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <ipxe/vsprintf.h>
+#include "mucurses.h"
+
+/** @file
+ *
+ * MuCurses printing functions
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * Add a single-byte character and rendition to a window and advance
+ * the cursor
+ *
+ * @v *win window to be rendered in
+ * @v ch character to be added at cursor
+ * @ret rc return status code
+ */
+int waddch ( WINDOW *win, const chtype ch ) {
+ _wputch( win, ch, WRAP );
+ return OK;
+}
+
+/**
+ * Add string of single-byte characters to a window
+ *
+ * @v *win window to be rendered in
+ * @v *str standard c-style string
+ * @v n max number of chars from string to render
+ * @ret rc return status code
+ */
+int waddnstr ( WINDOW *win, const char *str, int n ) {
+ _wputstr( win, str, WRAP, n );
+ return OK;
+}
+
+struct printw_context {
+ struct printf_context ctx;
+ WINDOW *win;
+};
+
+static void _printw_handler ( struct printf_context *ctx, unsigned int c ) {
+ struct printw_context *wctx =
+ container_of ( ctx, struct printw_context, ctx );
+
+ _wputch( wctx->win, c | wctx->win->attrs, WRAP );
+}
+
+/**
+ * Print formatted output in a window
+ *
+ * @v *win subject window
+ * @v *fmt formatted string
+ * @v varglist argument list
+ * @ret rc return status code
+ */
+int vw_printw ( WINDOW *win, const char *fmt, va_list varglist ) {
+ struct printw_context wctx;
+
+ wctx.win = win;
+ wctx.ctx.handler = _printw_handler;
+ vcprintf ( &(wctx.ctx), fmt, varglist );
+ return OK;
+}
+
+/**
+ * Print formatted output to a window
+ *
+ * @v *win subject window
+ * @v *fmt formatted string
+ * @v ... string arguments
+ * @ret rc return status code
+ */
+int wprintw ( WINDOW *win, const char *fmt, ... ) {
+ va_list args;
+ int i;
+
+ va_start ( args, fmt );
+ i = vw_printw ( win, fmt, args );
+ va_end ( args );
+ return i;
+}
diff --git a/qemu/roms/ipxe/src/hci/mucurses/print_nadv.c b/qemu/roms/ipxe/src/hci/mucurses/print_nadv.c
new file mode 100644
index 000000000..ee472e685
--- /dev/null
+++ b/qemu/roms/ipxe/src/hci/mucurses/print_nadv.c
@@ -0,0 +1,26 @@
+#include <curses.h>
+#include "mucurses.h"
+#include "cursor.h"
+
+/** @file
+ *
+ * MuCurses printing functions (no cursor advance)
+ *
+ */
+
+/**
+ * Add string of single-byte characters and renditions to a window
+ *
+ * @v *win window to be rendered in
+ * @v *chstr pointer to first chtype in "string"
+ * @v n max number of chars from chstr to render
+ * @ret rc return status code
+ */
+int waddchnstr ( WINDOW *win, const chtype *chstr, int n ) {
+ struct cursor_pos pos;
+
+ _store_curs_pos( win, &pos );
+ _wputchstr( win, chstr, NOWRAP, n );
+ _restore_curs_pos( win, &pos );
+ return OK;
+}
diff --git a/qemu/roms/ipxe/src/hci/mucurses/slk.c b/qemu/roms/ipxe/src/hci/mucurses/slk.c
new file mode 100644
index 000000000..600658e75
--- /dev/null
+++ b/qemu/roms/ipxe/src/hci/mucurses/slk.c
@@ -0,0 +1,363 @@
+#include <curses.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "mucurses.h"
+#include "cursor.h"
+
+/** @file
+ *
+ * Soft label key functions
+ */
+
+#define MIN_SPACE_SIZE 2
+
+#define SLK_MAX_LABEL_LEN 8
+
+#define SLK_MAX_NUM_LABELS 12
+
+#define SLK_MAX_NUM_SPACES 2
+
+struct _softlabel {
+ // label string
+ char label[SLK_MAX_LABEL_LEN];
+ /* Format of soft label
+ 0: left justify
+ 1: centre justify
+ 2: right justify
+ */
+ unsigned int fmt;
+};
+
+struct _softlabelkeys {
+ struct _softlabel fkeys[SLK_MAX_NUM_LABELS];
+ attr_t attrs;
+ /* Soft label layout format
+ 0: 3-2-3
+ 1: 4-4
+ 2: 4-4-4
+ 3: 4-4-4 with index line
+ */
+ unsigned int fmt;
+ unsigned int max_label_len;
+ unsigned int maj_space_len;
+ unsigned int num_labels;
+ unsigned int num_spaces;
+ unsigned int spaces[SLK_MAX_NUM_SPACES];
+ struct cursor_pos saved_cursor;
+ attr_t saved_attrs;
+ short saved_pair;
+};
+
+static struct _softlabelkeys *slks;
+
+/*
+ I either need to break the primitives here, or write a collection of
+ functions specifically for SLKs that directly access the screen
+ functions - since this technically isn't part of stdscr, I think
+ this should be ok...
+ */
+
+static void _enter_slk ( void ) {
+ _store_curs_pos ( stdscr, &slks->saved_cursor );
+ wattr_get ( stdscr, &slks->saved_attrs, &slks->saved_pair, NULL );
+ LINES++;
+ wmove ( stdscr, LINES, 0 );
+ wattrset ( stdscr, slks->attrs );
+}
+
+static void _leave_slk ( void ) {
+ LINES--;
+ wattr_set ( stdscr, slks->saved_attrs, slks->saved_pair, NULL );
+ _restore_curs_pos ( stdscr, &slks->saved_cursor );
+}
+
+static void _print_label ( struct _softlabel sl ) {
+ int space_ch;
+ char str[SLK_MAX_LABEL_LEN + 1];
+
+ assert ( slks->max_label_len <= SLK_MAX_LABEL_LEN );
+ space_ch = ' ';
+
+ // protect against gaps in the soft label keys array
+ if ( sl.label == NULL ) {
+ memset( str, space_ch, (size_t)(slks->max_label_len) );
+ } else {
+ /* we need to pad the label with varying amounts of leading
+ pad depending on the format of the label */
+ if ( sl.fmt == 1 ) {
+ memset( str, space_ch,
+ (size_t)(slks->max_label_len
+ - strlen(sl.label)) / 2 );
+ }
+ if ( sl.fmt == 2 ) {
+ memset( str, space_ch,
+ (size_t)(slks->max_label_len
+ - strlen(sl.label)) );
+ }
+ strcat(str,sl.label);
+
+ // post-padding
+ memset(str+strlen(str), space_ch,
+ (size_t)(slks->max_label_len - strlen(str)) );
+ }
+
+ // print the formatted label
+ _wputstr ( stdscr, str, NOWRAP, slks->max_label_len );
+}
+
+/**
+ * Return the attribute used for the soft function keys
+ *
+ * @ret attrs the current attributes of the soft function keys
+ */
+attr_t slk_attr ( void ) {
+ return ( slks == NULL ? 0 : slks->attrs );
+}
+
+/**
+ * Turn off soft function key attributes
+ *
+ * @v attrs attribute bit mask
+ * @ret rc return status code
+ */
+int slk_attroff ( const chtype attrs ) {
+ if ( slks == NULL )
+ return ERR;
+ slks->attrs &= ~( attrs & A_ATTRIBUTES );
+ return OK;
+}
+
+/**
+ * Turn on soft function key attributes
+ *
+ * @v attrs attribute bit mask
+ * @ret rc return status code
+ */
+int slk_attron ( const chtype attrs ) {
+ if ( slks == NULL )
+ return ERR;
+ slks->attrs |= ( attrs & A_ATTRIBUTES );
+ return OK;
+}
+
+/**
+ * Set soft function key attributes
+ *
+ * @v attrs attribute bit mask
+ * @ret rc return status code
+ */
+int slk_attrset ( const chtype attrs ) {
+ if ( slks == NULL )
+ return ERR;
+ slks->attrs = ( attrs & A_ATTRIBUTES );
+ return OK;
+}
+
+/**
+ * Turn off soft function key attributes
+ *
+ * @v attrs attribute bit mask
+ * @v *opts undefined (for future implementation)
+ * @ret rc return status code
+ */
+int slk_attr_off ( const attr_t attrs, void *opts __unused ) {
+ return slk_attroff( attrs );
+}
+
+/**
+ * Turn on soft function key attributes
+ *
+ * @v attrs attribute bit mask
+ * @v *opts undefined (for future implementation)
+ * @ret rc return status code
+ */
+int slk_attr_on ( attr_t attrs, void *opts __unused ) {
+ return slk_attron( attrs );
+}
+
+/**
+ * Set soft function key attributes
+ *
+ * @v attrs attribute bit mask
+ * @v colour_pair_number colour pair integer
+ * @v *opts undefined (for future implementation)
+ * @ret rc return status code
+ */
+int slk_attr_set ( const attr_t attrs, short colour_pair_number,
+ void *opts __unused ) {
+ if ( slks == NULL )
+ return ERR;
+
+ if ( ( unsigned short )colour_pair_number > COLORS )
+ return ERR;
+
+ slks->attrs = ( (unsigned short)colour_pair_number << CPAIR_SHIFT ) |
+ ( attrs & A_ATTRIBUTES );
+ return OK;
+}
+
+/**
+ * Clear the soft function key labels from the screen
+ *
+ * @ret rc return status code
+ */
+int slk_clear ( void ) {
+ if ( slks == NULL )
+ return ERR;
+
+ _enter_slk();
+ wclrtoeol ( stdscr );
+ _leave_slk();
+
+ return OK;
+}
+
+/**
+ * Set soft label colour pair
+ */
+int slk_colour ( short colour_pair_number ) {
+ if ( slks == NULL )
+ return ERR;
+ if ( ( unsigned short )colour_pair_number > COLORS )
+ return ERR;
+
+ slks->attrs = ( (unsigned short)colour_pair_number << CPAIR_SHIFT )
+ | ( slks->attrs & A_ATTRIBUTES );
+
+ return OK;
+}
+
+/**
+ * Initialise the soft function keys
+ *
+ * @v fmt format of keys
+ * @ret rc return status code
+ */
+int slk_init ( int fmt ) {
+ unsigned short nmaj, nmin, nblocks, available_width;
+
+ if ( (unsigned)fmt > 3 ) {
+ return ERR;
+ }
+
+ /* There seems to be no API call to free this data structure... */
+ if ( ! slks )
+ slks = calloc(1,sizeof(*slks));
+ if ( ! slks )
+ return ERR;
+
+ slks->attrs = A_DEFAULT;
+ slks->fmt = fmt;
+ switch(fmt) {
+ case 0:
+ nblocks = 8; nmaj = 2; nmin = 5;
+ slks->spaces[0] = 2; slks->spaces[1] = 4;
+ break;
+ case 1:
+ nblocks = 8; nmaj = 1; nmin = 6;
+ slks->spaces[0] = 3;
+ break;
+ case 2:
+ // same allocations as format 3
+ case 3:
+ nblocks = 12; nmaj = 2; nmin = 9;
+ slks->spaces[0] = 3; slks->spaces[1] = 7;
+ break;
+ default:
+ nblocks = 0; nmaj = 0; nmin = 0;
+ break;
+ }
+
+ // determine maximum label length and major space size
+ available_width = COLS - ( ( MIN_SPACE_SIZE * nmaj ) + nmin );
+ slks->max_label_len = available_width / nblocks;
+ slks->maj_space_len = MIN_SPACE_SIZE +
+ ( available_width % nblocks ) / nmaj;
+ slks->num_spaces = nmaj;
+ slks->num_labels = nblocks;
+
+ // strip a line from the screen
+ LINES -= 1;
+
+ return OK;
+}
+
+/**
+ * Return the label for the specified soft key
+ *
+ * @v labnum soft key identifier
+ * @ret label return label
+ */
+char* slk_label ( int labnum ) {
+ if ( slks == NULL )
+ return NULL;
+
+ return slks->fkeys[labnum].label;
+}
+
+/**
+ * Restore soft function key labels to the screen
+ *
+ * @ret rc return status code
+ */
+int slk_restore ( void ) {
+ unsigned int i, j, pos_x,
+ *next_space, *last_space;
+ chtype space_ch;
+
+ if ( slks == NULL )
+ return ERR;
+
+ pos_x = 0;
+
+ _enter_slk();
+
+ space_ch = (chtype)' ' | slks->attrs;
+ next_space = &(slks->spaces[0]);
+ last_space = &(slks->spaces[slks->num_spaces-1]);
+
+ for ( i = 0; i < slks->num_labels ; i++ ) {
+ _print_label( slks->fkeys[i] );
+ pos_x += slks->max_label_len;
+
+ if ( i == *next_space ) {
+ for ( j = 0; j < slks->maj_space_len; j++, pos_x++ )
+ _wputch ( stdscr, space_ch, NOWRAP );
+ if ( next_space < last_space )
+ next_space++;
+ } else {
+ if ( pos_x < COLS )
+ _wputch ( stdscr, space_ch, NOWRAP );
+ pos_x++;
+ }
+ }
+
+ _leave_slk();
+
+ return OK;
+}
+
+/**
+ * Configure specified soft key
+ *
+ * @v labnum soft label position to configure
+ * @v *label string to use as soft key label
+ * @v fmt justification format of label
+ * @ret rc return status code
+ */
+int slk_set ( int labnum, const char *label, int fmt ) {
+ if ( slks == NULL )
+ return ERR;
+ if ( (unsigned short)labnum >= slks->num_labels )
+ return ERR;
+ if ( (unsigned short)fmt >= 3 )
+ return ERR;
+
+ strncpy(slks->fkeys[labnum].label, label,
+ sizeof(slks->fkeys[labnum].label));
+ slks->fkeys[labnum].fmt = fmt;
+
+ return OK;
+}
diff --git a/qemu/roms/ipxe/src/hci/mucurses/widgets/editbox.c b/qemu/roms/ipxe/src/hci/mucurses/widgets/editbox.c
new file mode 100644
index 000000000..630a66e0b
--- /dev/null
+++ b/qemu/roms/ipxe/src/hci/mucurses/widgets/editbox.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * 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; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <assert.h>
+#include <ipxe/editbox.h>
+
+/** @file
+ *
+ * Editable text box widget
+ *
+ */
+
+#define EDITBOX_MIN_CHARS 3
+
+/**
+ * Initialise text box widget
+ *
+ * @v box Editable text box widget
+ * @v buf Text buffer
+ * @v len Size of text buffer
+ * @v win Containing window
+ * @v row Row
+ * @v col Starting column
+ * @v width Width
+ * @v flags Flags
+ */
+void init_editbox ( struct edit_box *box, char *buf, size_t len,
+ WINDOW *win, unsigned int row, unsigned int col,
+ unsigned int width, unsigned int flags ) {
+ memset ( box, 0, sizeof ( *box ) );
+ init_editstring ( &box->string, buf, len );
+ box->string.cursor = strlen ( buf );
+ box->win = ( win ? win : stdscr );
+ box->row = row;
+ box->col = col;
+ box->width = width;
+ box->flags = flags;
+}
+
+/**
+ * Draw text box widget
+ *
+ * @v box Editable text box widget
+ *
+ */
+void draw_editbox ( struct edit_box *box ) {
+ size_t width = box->width;
+ char buf[ width + 1 ];
+ signed int cursor_offset, underflow, overflow, first;
+ size_t len;
+
+ /* Adjust starting offset so that cursor remains within box */
+ cursor_offset = ( box->string.cursor - box->first );
+ underflow = ( EDITBOX_MIN_CHARS - cursor_offset );
+ overflow = ( cursor_offset - ( width - 1 ) );
+ first = box->first;
+ if ( underflow > 0 ) {
+ first -= underflow;
+ if ( first < 0 )
+ first = 0;
+ } else if ( overflow > 0 ) {
+ first += overflow;
+ }
+ box->first = first;
+ cursor_offset = ( box->string.cursor - first );
+
+ /* Construct underscore-padded string portion */
+ memset ( buf, '_', width );
+ buf[width] = '\0';
+ len = ( strlen ( box->string.buf ) - first );
+ if ( len > width )
+ len = width;
+ if ( box->flags & EDITBOX_STARS ) {
+ memset ( buf, '*', len );
+ } else {
+ memcpy ( buf, ( box->string.buf + first ), len );
+ }
+
+ /* Print box content and move cursor */
+ if ( ! box->win )
+ box->win = stdscr;
+ mvwprintw ( box->win, box->row, box->col, "%s", buf );
+ wmove ( box->win, box->row, ( box->col + cursor_offset ) );
+}
diff --git a/qemu/roms/ipxe/src/hci/mucurses/winattrs.c b/qemu/roms/ipxe/src/hci/mucurses/winattrs.c
new file mode 100644
index 000000000..f549d7519
--- /dev/null
+++ b/qemu/roms/ipxe/src/hci/mucurses/winattrs.c
@@ -0,0 +1,133 @@
+#include <curses.h>
+
+/** @file
+ *
+ * MuCurses window attribute functions
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * Get the background rendition attributes for a window
+ *
+ * @v *win subject window
+ * @ret ch chtype rendition representation
+ */
+inline chtype getbkgd ( WINDOW *win ) {
+ return win->attrs;
+}
+
+/**
+ * Turn off attributes in a window
+ *
+ * @v win subject window
+ * @v attrs attributes to enable
+ * @ret rc return status code
+ */
+int wattroff ( WINDOW *win, int attrs ) {
+ win->attrs &= ~attrs;
+ return OK;
+}
+
+/**
+ * Turn on attributes in a window
+ *
+ * @v win subject window
+ * @v attrs attributes to enable
+ * @ret rc return status code
+ */
+int wattron ( WINDOW *win, int attrs ) {
+ win->attrs |= attrs;
+ return OK;
+}
+
+/**
+ * Set attributes in a window
+ *
+ * @v win subject window
+ * @v attrs attributes to enable
+ * @ret rc return status code
+ */
+int wattrset ( WINDOW *win, int attrs ) {
+ win->attrs = ( attrs | ( win->attrs & A_COLOR ) );
+ return OK;
+}
+
+/**
+ * Get attributes and colour pair information
+ *
+ * @v *win window to obtain information from
+ * @v *attrs address in which to store attributes
+ * @v *pair address in which to store colour pair
+ * @v *opts undefined (for future implementation)
+ * @ret rc return status cude
+ */
+int wattr_get ( WINDOW *win, attr_t *attrs, short *pair,
+ void *opts __unused ) {
+ *attrs = win->attrs & A_ATTRIBUTES;
+ *pair = PAIR_NUMBER ( win->attrs );
+ return OK;
+}
+
+/**
+ * Turn off attributes in a window
+ *
+ * @v *win subject window
+ * @v attrs attributes to toggle
+ * @v *opts undefined (for future implementation)
+ * @ret rc return status code
+ */
+int wattr_off ( WINDOW *win, attr_t attrs,
+ void *opts __unused ) {
+ wattroff( win, attrs );
+ return OK;
+}
+
+/**
+ * Turn on attributes in a window
+ *
+ * @v *win subject window
+ * @v attrs attributes to toggle
+ * @v *opts undefined (for future implementation)
+ * @ret rc return status code
+ */
+int wattr_on ( WINDOW *win, attr_t attrs,
+ void *opts __unused ) {
+ wattron( win, attrs );
+ return OK;
+}
+
+/**
+ * Set attributes and colour pair information in a window
+ *
+ * @v *win subject window
+ * @v attrs attributes to set
+ * @v cpair colour pair to set
+ * @v *opts undefined (for future implementation)
+ * @ret rc return status code
+ */
+int wattr_set ( WINDOW *win, attr_t attrs, short cpair,
+ void *opts __unused ) {
+ wattrset( win, attrs | COLOUR_PAIR ( cpair ) );
+ return OK;
+}
+
+/**
+ * Set colour pair for a window
+ *
+ * @v *win subject window
+ * @v colour_pair_number colour pair integer
+ * @v *opts undefined (for future implementation)
+ * @ret rc return status code
+ */
+int wcolour_set ( WINDOW *win, short colour_pair_number,
+ void *opts __unused ) {
+ if ( ( unsigned short )colour_pair_number > COLOUR_PAIRS )
+ return ERR;
+
+ win->attrs = ( ( win->attrs & A_ATTRIBUTES ) |
+ COLOUR_PAIR ( colour_pair_number ) );
+ return OK;
+}
+
diff --git a/qemu/roms/ipxe/src/hci/mucurses/windows.c b/qemu/roms/ipxe/src/hci/mucurses/windows.c
new file mode 100644
index 000000000..63d0af08c
--- /dev/null
+++ b/qemu/roms/ipxe/src/hci/mucurses/windows.c
@@ -0,0 +1,158 @@
+#include <curses.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include "mucurses.h"
+
+/** @file
+ *
+ * MuCurses windows instance functions
+ *
+ */
+
+/**
+ * Delete a window
+ *
+ * @v *win pointer to window being deleted
+ * @ret rc return status code
+ */
+int delwin ( WINDOW *win ) {
+ if ( win == NULL )
+ return ERR;
+
+ /* I think we should blank the region covered by the window -
+ ncurses doesn't do this, but they have a buffer, so they
+ may just be deleting from an offscreen context whereas we
+ are guaranteed to be deleting something onscreen */
+ wmove( win, 0, 0 );
+ chtype killch = (chtype)' ';
+ do {
+ _wputch( win, killch, WRAP );
+ } while ( win->curs_x + win->curs_y );
+
+ free( win );
+
+ wmove ( stdscr, 0, 0 );
+
+ return OK;
+}
+
+/**
+ * Create a new derived window
+ *
+ * @v parent parent window
+ * @v nlines window height
+ * @v ncols window width
+ * @v begin_y window y origin (relative to parent)
+ * @v begin_x window x origin (relative to parent)
+ * @ret ptr return pointer to child window
+ */
+WINDOW *derwin ( WINDOW *parent, int nlines, int ncols,
+ int begin_y, int begin_x ) {
+ WINDOW *child;
+ if ( parent == NULL )
+ return NULL;
+ if ( ( child = malloc( sizeof( WINDOW ) ) ) == NULL )
+ return NULL;
+ if ( ( (unsigned)ncols > parent->width ) ||
+ ( (unsigned)nlines > parent->height ) )
+ return NULL;
+ child->ori_y = parent->ori_y + begin_y;
+ child->ori_x = parent->ori_x + begin_x;
+ child->height = nlines;
+ child->width = ncols;
+ child->parent = parent;
+ child->scr = parent->scr;
+ return child;
+}
+
+/**
+ * Create a duplicate of the specified window
+ *
+ * @v orig original window
+ * @ret ptr pointer to duplicate window
+ */
+WINDOW *dupwin ( WINDOW *orig ) {
+ WINDOW *copy;
+ if ( orig == NULL )
+ return NULL;
+ if ( ( copy = malloc( sizeof( WINDOW ) ) ) == NULL )
+ return NULL;
+ copy->scr = orig->scr;
+ copy->attrs = orig->attrs;
+ copy->ori_y = orig->ori_y;
+ copy->ori_x = orig->ori_x;
+ copy->curs_y = orig->curs_y;
+ copy->curs_x = orig->curs_x;
+ copy->height = orig->height;
+ copy->width = orig->width;
+ return copy;
+}
+
+/**
+ * Move window origin to specified coordinates
+ *
+ * @v *win window to move
+ * @v y Y position
+ * @v x X position
+ * @ret rc return status code
+ */
+int mvwin ( WINDOW *win, int y, int x ) {
+ if ( win == NULL )
+ return ERR;
+ if ( ( ( (unsigned)y + win->height ) > LINES ) ||
+ ( ( (unsigned)x + win->width ) > COLS ) )
+ return ERR;
+
+ win->ori_y = y;
+ win->ori_x = x;
+
+ return OK;
+}
+
+/**
+ * Create new WINDOW
+ *
+ * @v nlines number of lines
+ * @v ncols number of columns
+ * @v begin_y column origin
+ * @v begin_x line origin
+ * @ret *win return pointer to new window
+ */
+WINDOW *newwin ( int nlines, int ncols, int begin_y, int begin_x ) {
+ WINDOW *win;
+ if ( ( win = malloc( sizeof(WINDOW) ) ) == NULL )
+ return NULL;
+ if ( ( (unsigned)( begin_y + nlines ) > stdscr->height ) &&
+ ( (unsigned)( begin_x + ncols ) > stdscr->width ) )
+ return NULL;
+ win->ori_y = begin_y;
+ win->ori_x = begin_x;
+ win->height = nlines;
+ win->width = ncols;
+ win->scr = stdscr->scr;
+ win->parent = stdscr;
+ return win;
+}
+
+/**
+ * Create a new sub-window
+ *
+ * @v orig parent window
+ * @v nlines window height
+ * @v ncols window width
+ * @v begin_y window y origin (absolute)
+ * @v begin_x window x origin (absolute)
+ * @ret ptr return pointer to child window
+ */
+WINDOW *subwin ( WINDOW *parent, int nlines, int ncols,
+ int begin_y, int begin_x ) {
+ WINDOW *child;
+ if ( parent == NULL )
+ return NULL;
+ if ( ( child = malloc( sizeof( WINDOW ) ) ) == NULL )
+ return NULL;
+ child = newwin( nlines, ncols, begin_y, begin_x );
+ child->parent = parent;
+ child->scr = parent->scr;
+ return child;
+}
diff --git a/qemu/roms/ipxe/src/hci/mucurses/wininit.c b/qemu/roms/ipxe/src/hci/mucurses/wininit.c
new file mode 100644
index 000000000..b75abba44
--- /dev/null
+++ b/qemu/roms/ipxe/src/hci/mucurses/wininit.c
@@ -0,0 +1,38 @@
+#include <stddef.h>
+#include <curses.h>
+
+/** @file
+ *
+ * MuCurses initialisation functions
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * Initialise console environment
+ *
+ * @ret *win return pointer to stdscr
+ */
+WINDOW *initscr ( void ) {
+ /* determine console size */
+ /* initialise screen */
+ stdscr->scr->init( stdscr->scr );
+ stdscr->height = LINES;
+ stdscr->width = COLS;
+ move ( 0, 0 );
+ return stdscr;
+}
+
+/**
+ * Finalise console environment
+ *
+ */
+int endwin ( void ) {
+ attrset ( 0 );
+ color_set ( 0, NULL );
+ curs_set ( 1 );
+ mvprintw ( ( LINES - 1 ), 0, "\n" );
+ stdscr->scr->exit( stdscr->scr );
+ return OK;
+}