diff options
author | H. Peter Anvin <hpa@zytor.com> | 2009-11-05 17:52:47 -0800 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2009-11-06 15:57:15 -0800 |
commit | 8492da661cc77e26cd18e4cf307b78e50661ea29 (patch) | |
tree | d3d19f6c48eef6e6b44982f3d8b2fa993edfe16c | |
parent | ebef1cd107b7034056309bf49f92a2b9e92b9fe0 (diff) | |
parent | 259c0dca1bc6ead6003fc504e136be67a1311abb (diff) | |
download | syslinux-8492da661cc77e26cd18e4cf307b78e50661ea29.tar.gz syslinux-8492da661cc77e26cd18e4cf307b78e50661ea29.tar.xz syslinux-8492da661cc77e26cd18e4cf307b78e50661ea29.zip |
Merge branch 'master' into fsc
Conflicts:
com32/modules/Makefile
core/pxelinux.asm
core/serirq.inc
Note: hardwired options will need to be re-implemented in PXELINUX.
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
79 files changed, 3029 insertions, 1842 deletions
@@ -54,6 +54,9 @@ NM = nm RANLIB = ranlib GZIPPROG = gzip PNGTOPNM = pngtopnm +MCOPY = mcopy +MFORMAT = mformat +MKISOFS = mkisofs com32 = $(topdir)/com32 @@ -18,6 +18,13 @@ Changes in 3.83: * Simple menu: fix Ctrl-W (word erase) in command-line edit. * Simple menu: fix crash on some platforms. * Gfxboot: fixes to the configuration file parsing. + * PXELINUX: add a tool to override specific DHCP options via + values hardcoded in the pxelinux.0 file. These hardcoded + values can be either "before DHCP" (defaults if DHCP do not + provide values), or "after DHCP" (overrides DHCP). The tool + pxelinux-options can be used to set these options. This + feature does not apply to gpxelinux.0; when used with gPXE + this is better handled by modifying the embedded script. Changes in 3.82: * isohybrid: fix the -partok logic for loading from a partition. diff --git a/com32/cmenu/adv_menu.tpl b/com32/cmenu/adv_menu.tpl index 6ce4acf8..be3c558e 100644 --- a/com32/cmenu/adv_menu.tpl +++ b/com32/cmenu/adv_menu.tpl @@ -40,6 +40,7 @@ modify this template to suit your needs #include "com32io.h" #include <string.h> #include <stdlib.h> +#include <unistd.h> #define MAX_CMD_LINE_LENGTH 514 @@ -192,51 +193,61 @@ TIMEOUTCODE ontotaltimeout() return timeout(totaltimeoutcmd); } -void keys_handler(t_menusystem *ms, t_menuitem *mi,unsigned int scancode) +void keys_handler(t_menusystem * ms __attribute__ (( unused )), t_menuitem * mi, int scancode) { - char nc; + int nc, nr; - if ( ((scancode >> 8) == F1) && (mi->helpid != 0xFFFF) ) { // If scancode of F1 and non-trivial helpid + if (getscreensize(1, &nr, &nc)) { + /* Unknown screen size? */ + nc = 80; + nr = 24; + } + + if ( (scancode == KEY_F1) && (mi->helpid != 0xFFFF) ) { // If scancode of F1 and non-trivial helpid runhelpsystem(mi->helpid); } // If user hit TAB, and item is an "executable" item // and user has privileges to edit it, edit it in place. - if (((scancode & 0xFF) == 0x09) && (mi->action == OPT_RUN) && - (EDIT_ROW < getnumrows()) && (EDIT_ROW > 0) && + if ((scancode == KEY_TAB) && (mi->action == OPT_RUN) && + (EDIT_ROW < nr) && (EDIT_ROW > 0) && (isallowed(username,"editcmd") || isallowed(username,"root"))) { - nc = getnumcols(); // User typed TAB and has permissions to edit command line - gotoxy(EDIT_ROW,1,ms->menupage); + gotoxy(EDIT_ROW,1); csprint("Command line:",0x07); editstring(mi->data,ACTIONLEN); - gotoxy(EDIT_ROW,1,ms->menupage); - cprint(' ',0x07,nc-1,ms->menupage); + gotoxy(EDIT_ROW,1); + cprint(' ',0x07,nc-1); } } -t_handler_return login_handler(t_menusystem *ms, t_menuitem *mi) +t_handler_return login_handler(t_menuitem *mi) { (void)mi; // Unused char pwd[40]; char login[40]; - char nc; + int nc, nr; t_handler_return rv; rv = ACTION_INVALID; if (PWD_ROW < 0) return rv; // No need to authenticate if (mi->item == loginstr) { /* User wants to login */ - nc = getnumcols(); - gotoxy(PWD_ROW,1,ms->menupage); + if (getscreensize(1, &nr, &nc)) { + /* Unknown screen size? */ + nc = 80; + nr = 24; + } + + gotoxy(PWD_ROW,1); csprint("Enter Username: ",0x07); getstring(login, sizeof username); - gotoxy(PWD_ROW,1,ms->menupage); - cprint(' ',0x07,nc,ms->menupage); + gotoxy(PWD_ROW,1); + cprint(' ',0x07,nc); csprint("Enter Password: ",0x07); getpwd(pwd, sizeof pwd); - gotoxy(PWD_ROW,1,ms->menupage); - cprint(' ',0x07,nc,ms->menupage); + gotoxy(PWD_ROW,1); + cprint(' ',0x07,nc); if (authenticate_user(login,pwd)) { diff --git a/com32/cmenu/complex.c b/com32/cmenu/complex.c index 063125d6..1ac51997 100644 --- a/com32/cmenu/complex.c +++ b/com32/cmenu/complex.c @@ -21,6 +21,8 @@ #include "des.h" #include <stdlib.h> #include <stdio.h> +#include <unistd.h> +#include <getkey.h> /* Global variables */ char infoline[160]; @@ -65,46 +67,54 @@ TIMEOUTCODE ontimeout() #define PWDATTR 0x74 #define EDITPROMPT 21 -void keys_handler(t_menusystem * ms, t_menuitem * mi, unsigned int scancode) +void keys_handler(t_menusystem * ms __attribute__ (( unused )), t_menuitem * mi, int scancode) { - char nc; + int nc, nr; - if ((scancode >> 8) == F1) { // If scancode of F1 + if ((scancode) == KEY_F1 && mi->helpid != 0xFFFF) { // If scancode of F1 runhelpsystem(mi->helpid); } // If user hit TAB, and item is an "executable" item // and user has privileges to edit it, edit it in place. - if (((scancode & 0xFF) == 0x09) && (mi->action == OPT_RUN) && + if ((scancode == KEY_TAB) && (mi->action == OPT_RUN) && (isallowed(username, "editcmd") || isallowed(username, "root"))) { - nc = getnumcols(); + if (getscreensize(1, &nr, &nc)) { + /* Unknown screen size? */ + nc = 80; + nr = 24; + } // User typed TAB and has permissions to edit command line - gotoxy(EDITPROMPT, 1, ms->menupage); + gotoxy(EDITPROMPT, 1); csprint("Command line:", 0x07); editstring(mi->data, ACTIONLEN); - gotoxy(EDITPROMPT, 1, ms->menupage); - cprint(' ', 0x07, nc - 1, ms->menupage); + gotoxy(EDITPROMPT, 1); + clear_line(); } } -t_handler_return login_handler(t_menusystem * ms, t_menuitem * mi) +t_handler_return login_handler(t_menuitem * mi) { (void)mi; // Unused char pwd[40]; char login[40]; - char nc; + int nc, nr; t_handler_return rv; if (mi->item == loginstr) { /* User wants to login */ - nc = getnumcols(); - gotoxy(PWDPROMPT, 1, ms->menupage); + if (getscreensize(1, &nr, &nc)) { + /* Unknown screen size? */ + nc = 80; + nr = 24; + } + gotoxy(PWDPROMPT, 1); csprint("Enter Username: ", 0x07); getstring(login, sizeof username); - gotoxy(PWDPROMPT, 1, ms->menupage); - cprint(' ', 0x07, nc, ms->menupage); + gotoxy(PWDPROMPT, 1); + clear_line(); csprint("Enter Password: ", 0x07); getpwd(pwd, sizeof pwd); - gotoxy(PWDPROMPT, 1, ms->menupage); - cprint(' ', 0x07, nc, ms->menupage); + gotoxy(PWDPROMPT, 1); + clear_line(); if (authenticate_user(login, pwd)) { strcpy(username, login); @@ -133,22 +143,27 @@ t_handler_return login_handler(t_menusystem * ms, t_menuitem * mi) void msys_handler(t_menusystem * ms, t_menuitem * mi) { - char nc; + int nc, nr; void *v; - nc = getnumcols(); // Get number of columns - gotoxy(PWDLINE, PWDCOLUMN, ms->menupage); + if (getscreensize(1, &nr, &nc)) { + /* Unknown screen size? */ + nc = 80; + nr = 24; + } + gotoxy(PWDLINE, PWDCOLUMN); csprint("User: ", PWDATTR); - cprint(ms->fillchar, ms->fillattr, sizeof username, ms->menupage); - gotoxy(PWDLINE, PWDCOLUMN + 6, ms->menupage); + cprint(ms->fillchar, ms->fillattr, sizeof username); + gotoxy(PWDLINE, PWDCOLUMN + 6); csprint(username, PWDATTR); if (mi->parindex != PREPMENU) // If we are not in the PREP MENU { - gotoxy(INFLINE, 0, ms->menupage); - cprint(' ', 0x07, nc, ms->menupage); - gotoxy(INFLINE + 1, 0, ms->menupage); - cprint(' ', 0x07, nc, ms->menupage); + gotoxy(INFLINE, 0); + reset_colors(); + clear_line(); + gotoxy(INFLINE + 1, 0); + clear_line(); return; } strcpy(infoline, " "); @@ -167,13 +182,14 @@ void msys_handler(t_menusystem * ms, t_menuitem * mi) if (flags.linrep) strcat(infoline, "repair=lin "); - gotoxy(INFLINE, 0, ms->menupage); - cprint(' ', 0x07, nc, ms->menupage); - gotoxy(INFLINE + 1, 0, ms->menupage); - cprint(' ', 0x07, nc, ms->menupage); - gotoxy(INFLINE, 0, ms->menupage); + gotoxy(INFLINE, 0); + reset_colors(); + clear_line(); + gotoxy(INFLINE + 1, 0); + clear_line(); + gotoxy(INFLINE, 0); csprint("Kernel Arguments:", 0x07); - gotoxy(INFLINE, 17, ms->menupage); + gotoxy(INFLINE, 17); csprint(infoline, 0x07); } @@ -195,6 +211,8 @@ t_handler_return checkbox_handler(t_menusystem * ms, t_menuitem * mi) { (void)ms; /* Unused */ + t_handler_return rv; + if (mi->action != OPT_CHECKBOX) return ACTION_INVALID; @@ -220,26 +238,10 @@ t_handler_return checkbox_handler(t_menusystem * ms, t_menuitem * mi) } if (strcmp(mi->data, "mountcd") == 0) flags.mountcd = (mi->itemdata.checked ? 1 : 0); - return ACTION_VALID; -} -/* - Clears keyboard buffer and then - wait for stepsize*numsteps milliseconds for user to press any key - checks for keypress every stepsize milliseconds. - Returns: 1 if user pressed a key (not read from the buffer), - 0 if time elapsed -*/ -int checkkeypress(int stepsize, int numsteps) -{ - int i; - clearkbdbuf(); - for (i = 0; i < numsteps; i++) { - if (checkkbdbuf()) - return 1; - sleep(stepsize); - } - return 0; + rv.valid = 0; + rv.refresh = 1; + return rv; } int main() @@ -271,7 +273,7 @@ int main() reg_handler(HDLR_SCREEN, &msys_handler); reg_handler(HDLR_KEYS, &keys_handler); // Register the ontimeout handler, with a time out of 10 seconds - reg_ontimeout(ontimeout, 1000, 0); + reg_ontimeout(ontimeout, 10, 0); NETMENU = add_menu(" Init Network ", -1); none = add_item("<N>one", "Dont start network", OPT_RADIOITEM, "no ", 0); @@ -401,12 +403,11 @@ int main() 0); set_item_options(-1, 30); csprint("Press any key within 5 seconds to show menu...", 0x07); - if (!checkkeypress(100, 50)) // Granularity of 100 milliseconds + if (get_key(stdin, 50) == KEY_NONE) // Granularity of 100 milliseconds { csprint("Sorry! Time's up.\r\n", 0x07); return 1; - } else - clearkbdbuf(); // Just in case user pressed something important + } curr = showmenus(MAIN); if (curr) { if (curr->action == OPT_RUN) { diff --git a/com32/cmenu/libmenu/com32io.c b/com32/cmenu/libmenu/com32io.c index d99eb87f..6a27d1a1 100644 --- a/com32/cmenu/libmenu/com32io.c +++ b/com32/cmenu/libmenu/com32io.c @@ -13,35 +13,11 @@ #include <string.h> #include <com32.h> #include "com32io.h" +#include "tui.h" #include "syslnx.h" com32sys_t inreg, outreg; // Global register sets for use -/* Print character and attribute at cursor */ -void cprint(char chr, char attr, unsigned int times, char disppage) -{ - REG_AH(inreg) = 0x09; - REG_AL(inreg) = chr; - REG_BH(inreg) = disppage; - REG_BL(inreg) = attr; - REG_CX(inreg) = times; - __intcall(0x10, &inreg, &outreg); -} - -void setdisppage(char num) // Set the display page to specified number -{ - REG_AH(inreg) = 0x05; - REG_AL(inreg) = num; - __intcall(0x10, &inreg, &outreg); -} - -char getdisppage() // Get current display page -{ - REG_AH(inreg) = 0x0f; - __intcall(0x10, &inreg, &outreg); - return REG_BH(outreg); -} - void getpos(char *row, char *col, char page) { REG_AH(inreg) = 0x03; @@ -51,14 +27,6 @@ void getpos(char *row, char *col, char page) *col = REG_DL(outreg); } -void gotoxy(char row, char col, char page) -{ - REG_AH(inreg) = 0x02; - REG_BH(inreg) = page; - REG_DX(inreg) = (row << 8) + col; - __intcall(0x10, &inreg, &outreg); -} - unsigned char sleep(unsigned int msec) { unsigned long micro = 1000 * msec; @@ -70,25 +38,6 @@ unsigned char sleep(unsigned int msec) return REG_AH(outreg); } -void beep() -{ - REG_AH(inreg) = 0x0E; - REG_AL(inreg) = 0x07; - REG_BH(inreg) = 0; - __intcall(0x10, &inreg, &outreg); -} - -void scrollupwindow(char top, char left, char bot, char right, char attr, - char numlines) -{ - REG_AH(inreg) = 0x06; - REG_AL(inreg) = numlines; - REG_BH(inreg) = attr; // Attribute to write blanks lines - REG_DX(inreg) = (bot << 8) + right; // BOT RIGHT corner of window - REG_CX(inreg) = (top << 8) + left; // TOP LEFT of window - __intcall(0x10, &inreg, &outreg); -} - char inputc(char *scancode) { syslinux_idle(); /* So syslinux can perform periodic activity */ @@ -101,7 +50,7 @@ char inputc(char *scancode) void getcursorshape(char *start, char *end) { - char page = getdisppage(); + char page = 0; // XXX TODO REG_AH(inreg) = 0x03; REG_BH(inreg) = page; __intcall(0x10, &inreg, &outreg); @@ -117,13 +66,6 @@ void setcursorshape(char start, char end) __intcall(0x10, &inreg, &outreg); } -char getchar(void) -{ - REG_AH(inreg) = 0x08; - __intcall(0x21, &inreg, &outreg); - return REG_AL(outreg); -} - void setvideomode(char mode) { REG_AH(inreg) = 0x00; @@ -131,13 +73,6 @@ void setvideomode(char mode) __intcall(0x10, &inreg, &outreg); } -unsigned char checkkbdbuf() -{ - REG_AH(inreg) = 0x11; - __intcall(0x16, &inreg, &outreg); - return !(outreg.eflags.l & EFLAGS_ZF); -} - // Get char displayed at current position unsigned char getcharat(char page) { diff --git a/com32/cmenu/libmenu/com32io.h b/com32/cmenu/libmenu/com32io.h index cdaf0a84..6ff6857e 100644 --- a/com32/cmenu/libmenu/com32io.h +++ b/com32/cmenu/libmenu/com32io.h @@ -14,71 +14,41 @@ #define __COM32IO_H__ #include <com32.h> +#include <stdio.h> +#include <libansi.h> #ifndef NULL #define NULL ((void *)0) #endif -/* BIOS Assisted output routines */ - -void cswprint(const char *str, char attr, char left); -// Print a C str (NUL-terminated) respecting the left edge of window -// i.e. \n in str will move cursor to column left -// Print a C str (NUL-terminated) - -static inline void csprint(const char *str, char attr) -{ - cswprint(str, attr, 0); -} - -void cprint(char chr, char attr, unsigned int times, char disppage); // Print a char +/* Bits representing ShiftFlags, See Int16/Function 2 or Mem[0x417] to get this info */ -void setdisppage(char num); // Set the display page to specified number +#define INSERT_ON (1<<7) +#define CAPSLOCK_ON (1<<6) +#define NUMLOCK_ON (1<<5) +#define SCRLLOCK_ON (1<<4) +#define ALT_PRESSED (1<<3) +#define CTRL_PRESSED (1<<2) +// actually 1<<1 is Left Shift, 1<<0 is right shift +#define SHIFT_PRESSED (1<<1 | 1 <<0) -char getdisppage(); // Get current display page - -void gotoxy(char row, char col, char page); +/* BIOS Assisted output routines */ void getpos(char *row, char *col, char page); char inputc(char *scancode); // Return ASCII char by val, and scancode by reference -static inline void putch(char x, char attr, char page) -{ - cprint(x, attr, 1, page); -} - void setcursorshape(char start, char end); // Set cursor shape void getcursorshape(char *start, char *end); // Get shape for current page // Get char displayed at current position in specified page unsigned char getcharat(char page); -static inline void cursoroff(void) -{ /* Turns off cursor */ - setcursorshape(32, 33); -} - -static inline void cursoron(void) -{ /* Turns on cursor */ - setcursorshape(6, 7); -} - static inline unsigned char readbiosb(unsigned int ofs) { return *((unsigned char *)MK_PTR(0, ofs)); } -static inline char getnumrows() -{ - return readbiosb(0x484)+1; // Actually numrows - 1 -} - -static inline char getnumcols(void) -{ - return readbiosb(0x44a); // Actually numcols -} - static inline char getshiftflags(void) { return readbiosb(0x417); @@ -86,11 +56,6 @@ static inline char getshiftflags(void) void scrollupwindow(char top, char left, char bot, char right, char attr, char numlines); //Scroll up given window -static inline void scrollup(void) //Scroll up display screen by one line -{ - scrollupwindow(0, 0, getnumrows(), getnumcols(), 0x07, 1); -} - void setvideomode(char mode); // Set the video mode. static inline char getvideomode(void) // Get the current video mode @@ -100,14 +65,4 @@ static inline char getvideomode(void) // Get the current video mode unsigned char sleep(unsigned int msec); // Sleep for specified time -void beep(); // A Bell - -unsigned char checkkbdbuf(); // Check to see if there is kbd buffer is non-empty? - -static inline void clearkbdbuf() // Clear the kbd buffer (how many chars removed?) -{ - while (checkkbdbuf()) - inputc(NULL); -} - #endif diff --git a/com32/cmenu/libmenu/help.c b/com32/cmenu/libmenu/help.c index a635bd21..0df1e103 100644 --- a/com32/cmenu/libmenu/help.c +++ b/com32/cmenu/libmenu/help.c @@ -16,10 +16,11 @@ #include "com32io.h" #include <syslinux/loadfile.h> // to read entire file into memory +int nc, nr; // Number of columns/rows of the screen char helpbasedir[HELPDIRLEN]; // name of help directory limited to HELPDIRLEN // Find the occurence of the count'th \n in buffer (or NULL) if not found -char *findline(char *buffer, int count) +static char *findline(char *buffer, int count) { int ctr; char *p = buffer - 1; @@ -35,7 +36,7 @@ char *findline(char *buffer, int count) } // return the number of lines in buffer -int countlines(char *buffer) +static int countlines(char *buffer) { int ans; const char *p; @@ -50,34 +51,45 @@ int countlines(char *buffer) } // Print numlines of text starting from buf -void printtext(char *buf, int from) +static void printtext(char *buf, int from) { - char *p, *f; - char right, bot, nlines; + char *f, *t; + int right, nlines, i; // clear window to print - right = getnumcols() - HELP_RIGHT_MARGIN; - bot = getnumrows() - HELP_BOTTOM_MARGIN; - nlines = bot - HELP_BODY_ROW + 1; - scrollupwindow(HELP_BODY_ROW, HELP_LEFT_MARGIN, bot, right, 0x07, nlines); + right = nc - HELP_RIGHT_MARGIN; + nlines = nr - HELP_BODY_ROW - HELP_BOTTOM_MARGIN - 1; f = findline(buf, from); if (!f) return; // nothing to print if (*f == '\n') f++; // start of from+1st line - p = findline(f, nlines); - if (p && (*p == '\n')) - *p = '\0'; // change to NUL - gotoxy(HELP_BODY_ROW, HELP_LEFT_MARGIN, HELPPAGE); - cswprint(f, 0x07, HELP_LEFT_MARGIN); - if (p) - *p = '\n'; // set it back + t = f; + while (i < nlines) { + gotoxy(HELP_BODY_ROW + i, HELP_LEFT_MARGIN); + clear_end_of_line(); + putchar(SO); + gotoxy(HELP_BODY_ROW + i, nc - 1); + putch(LEFT_BORDER, 0x07); + putchar(SI); + + gotoxy(HELP_BODY_ROW + i, HELP_LEFT_MARGIN); + while (*t != '\n') { + if (*t == '\0') + return; + putchar(*t); + t++; + } + putchar('\n'); + t++; + i++; + } } void showhelp(const char *filename) { - char nc, nr, ph; + char ph; char *title, *text; union { char *buffer; @@ -86,41 +98,29 @@ void showhelp(const char *filename) char line[512]; size_t size; - char scan; + int scan; int rv, numlines, curr_line; - nc = getnumcols(); - nr = getnumrows(); - ph = nr - HELP_BOTTOM_MARGIN - HELP_BODY_ROW - 1; + if (getscreensize(1, &nr, &nc)) { + /* Unknown screen size? */ + nc = 80; + nr = 24; + } + ph = nr - HELP_BODY_ROW; cls(); - drawbox(0, 0, nr, nc - 1, HELPPAGE, 0x07, HELPBOX); - drawhorizline(2, 0, nc - 1, HELPPAGE, 0x07, HELPBOX, 0); // dumb==0 + /* Turn autowrap off, to avoid scrolling the menu */ + printf(CSI "?7l"); + if (filename == NULL) { // print file contents - gotoxy(HELP_BODY_ROW, HELP_LEFT_MARGIN, HELPPAGE); - cswprint("Filename not given", 0x07, HELP_LEFT_MARGIN); - while (1) { - inputc(&scan); - if (scan == ESCAPE) - break; - } - cls(); - return; + strcpy(line, "Filename not given"); + goto puke; } rv = loadfile(filename, (void **)&buf.vbuf, &size); // load entire file into memory if (rv < 0) { // Error reading file or no such file - sprintf(line, "Error reading file or file not found\n file=%s", - filename); - gotoxy(HELP_BODY_ROW, HELP_LEFT_MARGIN, HELPPAGE); - cswprint(line, 0x07, HELP_LEFT_MARGIN); - while (1) { - inputc(&scan); - if (scan == ESCAPE) - break; - } - cls(); - return; + sprintf(line, "Error reading file or file not found\n file=%s", filename); + goto puke; } title = buf.buffer; @@ -128,44 +128,49 @@ void showhelp(const char *filename) *text++ = '\0'; // end the title string and increment text // Now we have a file just print it. - gotoxy(1, (nc - strlen(title)) / 2, HELPPAGE); - csprint(title, 0x07); numlines = countlines(text); curr_line = 0; - scan = ESCAPE + 1; // anything except ESCAPE - - while (scan != ESCAPE) { + scan = KEY_ESC + 1; // anything except ESCAPE + + /* top, left, bottom, right, attr */ + drawbox(0, 0, nr - 1, nc - 1, 0x07); + while (scan != KEY_ESC) { + /* Title */ + gotoxy(1, (nc - strlen(title)) / 2); + fputs(title, stdout); + drawhorizline(2, HELP_LEFT_MARGIN - 1, nc - HELP_RIGHT_MARGIN, 0x07, 0); // dumb==0 + /* Text */ printtext(text, curr_line); - gotoxy(HELP_BODY_ROW - 1, nc - HELP_RIGHT_MARGIN, HELPPAGE); + gotoxy(HELP_BODY_ROW - 1, nc - HELP_RIGHT_MARGIN); if (curr_line > 0) - putch(HELP_MORE_ABOVE, 0x07, HELPPAGE); + putchar(HELP_MORE_ABOVE); else - putch(' ', 0x07, HELPPAGE); - gotoxy(nr - HELP_BOTTOM_MARGIN + 1, nc - HELP_RIGHT_MARGIN, HELPPAGE); + putchar(' '); + gotoxy(nr - HELP_BOTTOM_MARGIN - 1, nc - HELP_RIGHT_MARGIN); if (curr_line < numlines - ph) - putch(HELP_MORE_BELOW, 0x07, HELPPAGE); + putchar(HELP_MORE_BELOW); else - putch(' ', 0x07, HELPPAGE); + putchar(' '); - inputc(&scan); // wait for user keypress + scan = get_key(stdout, 0); // wait for user keypress switch (scan) { - case HOMEKEY: + case KEY_HOME: curr_line = 0; break; - case ENDKEY: + case KEY_END: curr_line = numlines; break; - case UPARROW: + case KEY_UP: curr_line--; break; - case DNARROW: + case KEY_DOWN: curr_line++; break; - case PAGEUP: + case KEY_PGUP: curr_line -= ph; break; - case PAGEDN: + case KEY_PGDN: curr_line += ph; break; default: @@ -176,18 +181,26 @@ void showhelp(const char *filename) if (curr_line < 0) curr_line = 0; } +out: cls(); return; + +puke: + gotoxy(HELP_BODY_ROW, HELP_LEFT_MARGIN); + fputs(line, stdout); + while (1) { + scan = get_key(stdin, 0); + if (scan == KEY_ESC) + break; + } + goto out; } void runhelp(const char *filename) { - char dp; char fullname[HELPDIRLEN + 16]; - dp = getdisppage(); - if (dp != HELPPAGE) - setdisppage(HELPPAGE); + cls(); cursoroff(); if (helpbasedir[0] != 0) { strcpy(fullname, helpbasedir); @@ -196,15 +209,13 @@ void runhelp(const char *filename) showhelp(fullname); } else showhelp(filename); // Assume filename is absolute - if (dp != HELPPAGE) - setdisppage(dp); } void runhelpsystem(unsigned int helpid) { char filename[15]; - sprintf(filename, "hlp%5d.txt", helpid); + sprintf(filename, "hlp%05d.txt", helpid); runhelp(filename); } diff --git a/com32/cmenu/libmenu/help.h b/com32/cmenu/libmenu/help.h index 0fff524f..de01b46e 100644 --- a/com32/cmenu/libmenu/help.h +++ b/com32/cmenu/libmenu/help.h @@ -23,14 +23,14 @@ #define HELP_BODY_ROW (HELP_TITLE_HEIGHT+3) #define HELP_LEFT_MARGIN 2 #define HELP_RIGHT_MARGIN 2 // Assume all lines dont cross this -#define HELP_BOTTOM_MARGIN 2 // Number of lines not use from bottom of screen +#define HELP_BOTTOM_MARGIN 1 // Number of lines not use from bottom of screen #define HELPBOX BOX_SINSIN #define HELPDIRLEN 64 #define HELPPAGE 2 -#define HELP_MORE_ABOVE 24 // to print when more is available above -#define HELP_MORE_BELOW 25 // same as above but for below +#define HELP_MORE_ABOVE '^' // to print when more is available above +#define HELP_MORE_BELOW 'v' // same as above but for below // Display one screen of help information void showhelp(const char *filename); diff --git a/com32/cmenu/libmenu/menu.c b/com32/cmenu/libmenu/menu.c index cfe8f39f..de4a1ee2 100644 --- a/com32/cmenu/libmenu/menu.c +++ b/com32/cmenu/libmenu/menu.c @@ -13,9 +13,10 @@ #include "menu.h" #include "com32io.h" #include <stdlib.h> +#include <console.h> // Local Variables -static pt_menusystem ms; // Pointer to the menusystem +static pt_menusystem ms; // Pointer to the menusystem char TITLESTR[] = "COMBOOT Menu System for SYSLINUX developed by Murali Krishnan Ganapathy"; char TITLELONG[] = " TITLE too long "; @@ -39,92 +40,45 @@ int isvisible(pt_menu menu, int first, int curr); // This is same as inputc except it honors the ontimeout handler // and calls it when needed. For the callee, there is no difference // as this will not return unless a key has been pressed. -char getch(char *scan) +static int getch() { - unsigned long i; - TIMEOUTCODE c; t_timeout_handler th; + int key; + unsigned long i; // Wait until keypress if no handler specified if ((ms->ontimeout == NULL) && (ms->ontotaltimeout == NULL)) - return inputc(scan); + return get_key(stdin, 0); th = ms->ontimeout; - while (1) // Forever do - { - for (i = 0; i < ms->tm_numsteps; i++) { - if (checkkbdbuf()) - return inputc(scan); - sleep(ms->tm_stepsize); - if ((ms->tm_total_timeout == 0) || (ms->ontotaltimeout == NULL)) - continue; // Dont bother with calculations if no handler - ms->tm_sofar_timeout += ms->tm_stepsize; - if (ms->tm_sofar_timeout >= ms->tm_total_timeout) { - th = ms->ontotaltimeout; - ms->tm_sofar_timeout = 0; - break; // Get out of the for loop - } - } - if (!th) - continue; // no handler dont call - c = th(); - switch (c) { - case CODE_ENTER: // Pretend user hit enter - *scan = ENTERA; - return '\015'; // \015 octal = 13 - case CODE_ESCAPE: // Pretend user hit escape - *scan = ESCAPE; - return '\033'; // \033 octal = 27 - default: - break; - } - } - return 0; -} - -/* Print a menu item */ -/* attr[0] is non-hilite attr, attr[1] is highlight attr */ -void printmenuitem(const char *str, uchar * attr) -{ - uchar page = getdisppage(); - uchar row, col; - int hlite = NOHLITE; // Initially no highlighting - - getpos(&row, &col, page); - while (*str) { - switch (*str) { - case '\b': - --col; - break; - case '\n': - ++row; - break; - case '\r': - col = 0; - break; - case BELL: // No Bell Char - break; - case ENABLEHLITE: // Switch on highlighting - hlite = HLITE; - break; - case DISABLEHLITE: // Turn off highlighting - hlite = NOHLITE; - break; - default: - putch(*str, attr[hlite], page); - ++col; - } - if (col > getnumcols()) { - ++row; - col = 0; - } - if (row > getnumrows()) { - scrollup(); - row = getnumrows(); - } - gotoxy(row, col, page); - str++; + for (;;) { + for (i = 0; i < ms->tm_numsteps; i++) { + key = get_key(stdin, ms->tm_stepsize); + if (key != KEY_NONE) + return key; + + if ((ms->tm_total_timeout == 0) || (ms->ontotaltimeout == NULL)) + continue; // Dont bother with calculations if no handler + ms->tm_sofar_timeout += ms->tm_stepsize; + if (ms->tm_sofar_timeout >= ms->tm_total_timeout) { + th = ms->ontotaltimeout; + ms->tm_sofar_timeout = 0; + break; // Get out of the for loop + } + } + if (!th) + continue; // no handler + key = th(); + switch (key) { + case CODE_ENTER: // Pretend user hit enter + return KEY_ENTER; + case CODE_ESCAPE: // Pretend user hit escape + return KEY_ESC; + default: + break; + } } + return KEY_NONE; } int find_shortcut(pt_menu menu, uchar shortcut, int index) @@ -135,481 +89,427 @@ int find_shortcut(pt_menu menu, uchar shortcut, int index) // Garbage in garbage out if ((index < 0) || (index >= menu->numitems)) - return index; + return index; ans = index + 1; // Go till end of menu while (ans < menu->numitems) { - mi = menu->items[ans]; - if ((mi->action == OPT_INVISIBLE) || (mi->action == OPT_SEP) - || (mi->shortcut != shortcut)) - ans++; - else - return ans; + mi = menu->items[ans]; + if ((mi->action == OPT_INVISIBLE) || (mi->action == OPT_SEP) + || (mi->shortcut != shortcut)) + ans++; + else + return ans; } // Start at the beginning and try again ans = 0; while (ans < index) { - mi = menu->items[ans]; - if ((mi->action == OPT_INVISIBLE) || (mi->action == OPT_SEP) - || (mi->shortcut != shortcut)) - ans++; - else - return ans; + mi = menu->items[ans]; + if ((mi->action == OPT_INVISIBLE) || (mi->action == OPT_SEP) + || (mi->shortcut != shortcut)) + ans++; + else + return ans; } - return index; // Sorry not found + return index; // Sorry not found } -// print the menu starting from FIRST -// will print a maximum of menu->menuheight items -void printmenu(pt_menu menu, int curr, uchar top, uchar left, uchar first) +/* Redraw background and title */ +static void reset_ui(void) +{ + uchar tpos; + + cls(); + clearwindow(ms->minrow, ms->mincol, ms->maxrow, ms->maxcol, + ms->fillchar, ms->fillattr); + + tpos = (ms->numcols - strlen(ms->title) - 1) >> 1; // center it on line + gotoxy(ms->minrow, ms->mincol); + cprint(ms->tfillchar, ms->titleattr, ms->numcols); + gotoxy(ms->minrow, ms->mincol + tpos); + csprint(ms->title, ms->titleattr); + + cursoroff(); +} + +/* + * Print a menu item + * + * attr[0] is non-hilite attr, attr[1] is highlight attr + */ +void printmenuitem(const char *str, uchar * attr) +{ + int hlite = NOHLITE; // Initially no highlighting + + while (*str) { + switch (*str) { + case BELL: // No Bell Char + break; + case ENABLEHLITE: // Switch on highlighting + hlite = HLITE; + break; + case DISABLEHLITE: // Turn off highlighting + hlite = NOHLITE; + break; + default: + putch(*str, attr[hlite]); + } + str++; + } +} + + +/** + * print_line - Print a whole line in a menu + * @menu: current menu to handle + * @curr: index of the current entry highlighted + * @top: top coordinate of the @menu + * @left: left coordinate of the @menu + * @x: index in the menu of curr + * @row: row currently displayed + * @radio: radio item? + **/ +static void print_line(pt_menu menu, int curr, uchar top, uchar left, + int x, int row, bool radio) { - int x, row; // x = index, row = position from top - int numitems, menuwidth; - char fchar[5], lchar[5]; // The first and last char in for each entry - const char *str; // and inbetween the item or a seperator is printed - uchar *attr; // attribute attr - char sep[MENULEN]; // and inbetween the item or a seperator is printed pt_menuitem ci; + char fchar[6], lchar[6]; // The first and last char in for each entry + const char *str; // Item string (cf printmenuitem) + char sep[MENULEN]; // Separator (OPT_SEP) + uchar *attr; // Attribute + int menuwidth = menu->menuwidth + 3; - numitems = calc_visible(menu, first); - if (numitems > menu->menuheight) - numitems = menu->menuheight; + if (row >= menu->menuheight) + return; - menuwidth = menu->menuwidth + 3; - clearwindow(top, left - 2, top + numitems + 1, left + menuwidth + 1, - ms->menupage, ms->fillchar, ms->shadowattr); - drawbox(top - 1, left - 3, top + numitems, left + menuwidth, - ms->menupage, ms->normalattr[NOHLITE], ms->menubt); - memset(sep, ms->box_horiz, menuwidth); // String containing the seperator string + ci = menu->items[x]; + + memset(sep, ms->box_horiz, menuwidth); sep[menuwidth - 1] = 0; - // Menu title - x = (menuwidth - strlen(menu->title) - 1) >> 1; - gotoxy(top - 1, left + x, ms->menupage); - printmenuitem(menu->title, ms->normalattr); - row = -1; // 1 less than inital value of x - for (x = first; x < menu->numitems; x++) { - ci = menu->items[x]; - if (ci->action == OPT_INVISIBLE) - continue; - row++; - if (row >= numitems) - break; // Already have enough number of items - // Setup the defaults now - lchar[0] = fchar[0] = ' '; - lchar[1] = fchar[1] = '\0'; // fchar and lchar are just spaces - str = ci->item; // Pointer to item string - attr = (x == curr ? ms->reverseattr : ms->normalattr); // Normal attributes - switch (ci->action) // set up attr,str,fchar,lchar for everything - { - case OPT_INACTIVE: - attr = (x == curr ? ms->revinactattr : ms->inactattr); - break; - case OPT_SUBMENU: - lchar[0] = SUBMENUCHAR; - lchar[1] = 0; - break; - case OPT_RADIOMENU: - lchar[0] = RADIOMENUCHAR; - lchar[1] = 0; - break; - case OPT_CHECKBOX: - lchar[0] = (ci->itemdata.checked ? CHECKED : UNCHECKED); - lchar[1] = 0; - break; - case OPT_SEP: - fchar[0] = '\b'; - fchar[1] = ms->box_ltrt; - fchar[2] = ms->box_horiz; - fchar[3] = ms->box_horiz; - fchar[4] = 0; - lchar[0] = ms->box_horiz; - lchar[1] = ms->box_rtlt; - lchar[2] = 0; - str = sep; - break; - case OPT_EXITMENU: - fchar[0] = EXITMENUCHAR; - fchar[1] = 0; - break; - default: // Just to keep the compiler happy - break; - } - gotoxy(top + row, left - 2, ms->menupage); - cprint(ms->spacechar, attr[NOHLITE], menuwidth + 2, ms->menupage); // Wipe area with spaces - gotoxy(top + row, left - 2, ms->menupage); - csprint(fchar, attr[NOHLITE]); // Print first part - gotoxy(top + row, left, ms->menupage); - printmenuitem(str, attr); // Print main part - gotoxy(top + row, left + menuwidth - 1, ms->menupage); // Last char if any - csprint(lchar, attr[NOHLITE]); // Print last part - } - // Check if we need to MOREABOVE and MOREBELOW to be added - // reuse x - row = 0; - x = next_visible_sep(menu, 0); // First item - if (!isvisible(menu, first, x)) // There is more above - { - row = 1; - gotoxy(top, left + menuwidth, ms->menupage); - cprint(MOREABOVE, ms->normalattr[NOHLITE], 1, ms->menupage); + + // Setup the defaults now + if (radio) { + fchar[0] = '\b'; + fchar[1] = SO; + fchar[2] = (x == curr ? RADIOSEL : RADIOUNSEL); + fchar[3] = SI; + fchar[4] = '\0'; // Unselected ( ) + lchar[0] = '\0'; // Nothing special after + attr = ms->normalattr; // Always same attribute + } else { + lchar[0] = fchar[0] = ' '; + lchar[1] = fchar[1] = '\0'; // fchar and lchar are just spaces + attr = (x == curr ? ms->reverseattr : ms->normalattr); // Normal attributes } - x = prev_visible_sep(menu, menu->numitems); // last item - if (!isvisible(menu, first, x)) // There is more above + str = ci->item; // Pointer to item string + switch (ci->action) // set up attr,str,fchar,lchar for everything { - row = 1; - gotoxy(top + numitems - 1, left + menuwidth, ms->menupage); - cprint(MOREBELOW, ms->normalattr[NOHLITE], 1, ms->menupage); - } - // Add a scroll box - x = ((numitems - 1) * curr) / (menu->numitems); - if ((x > 0) && (row == 1)) { - gotoxy(top + x, left + menuwidth, ms->menupage); - cprint(SCROLLBOX, ms->normalattr[NOHLITE], 1, ms->menupage); + case OPT_INACTIVE: + if (radio) + attr = ms->inactattr; + else + attr = (x == curr ? ms->revinactattr : ms->inactattr); + break; + case OPT_SUBMENU: + if (radio) + break; // Not supported for radio menu + lchar[0] = '>'; + lchar[1] = 0; + break; + case OPT_RADIOMENU: + if (radio) + break; // Not supported for radio menu + lchar[0] = RADIOMENUCHAR; + lchar[1] = 0; + break; + case OPT_CHECKBOX: + if (radio) + break; // Not supported for radio menu + lchar[0] = '\b'; + lchar[1] = SO; + lchar[2] = (ci->itemdata.checked ? CHECKED : UNCHECKED); + lchar[3] = SI; + lchar[4] = 0; + break; + case OPT_SEP: + fchar[0] = '\b'; + fchar[1] = SO; + fchar[2] = LEFT_MIDDLE_BORDER; + fchar[3] = MIDDLE_BORDER; + fchar[4] = MIDDLE_BORDER; + fchar[5] = 0; + memset(sep, MIDDLE_BORDER, menuwidth); + sep[menuwidth - 1] = 0; + str = sep; + lchar[0] = MIDDLE_BORDER; + lchar[1] = RIGHT_MIDDLE_BORDER; + lchar[2] = SI; + lchar[3] = 0; + break; + case OPT_EXITMENU: + if (radio) + break; // Not supported for radio menu + fchar[0] = '<'; + fchar[1] = 0; + break; + default: // Just to keep the compiler happy + break; } - if (ms->handler) - ms->handler(ms, menu->items[curr]); + + // Wipe area with spaces + gotoxy(top + row, left - 2); + cprint(ms->spacechar, attr[NOHLITE], menuwidth + 2); + + // Print first part + gotoxy(top + row, left - 2); + csprint(fchar, attr[NOHLITE]); + + // Print main part + gotoxy(top + row, left); + printmenuitem(str, attr); + + // Print last part + gotoxy(top + row, left + menuwidth - 1); + csprint(lchar, attr[NOHLITE]); } -// Difference between this and regular menu, is that only -// OPT_INVISIBLE, OPT_SEP are honoured -void printradiomenu(pt_menu menu, int curr, uchar top, uchar left, int first) +// print the menu starting from FIRST +// will print a maximum of menu->menuheight items +static void printmenu(pt_menu menu, int curr, uchar top, uchar left, uchar first, bool radio) { - int x, row; // x = index, row = position from top + int x, row; // x = index, row = position from top int numitems, menuwidth; - char fchar[5], lchar[5]; // The first and last char in for each entry - const char *str; // and inbetween the item or a seperator is printed - uchar *attr; // all in the attribute attr - char sep[MENULEN]; // and inbetween the item or a seperator is printed pt_menuitem ci; numitems = calc_visible(menu, first); if (numitems > menu->menuheight) - numitems = menu->menuheight; + numitems = menu->menuheight; menuwidth = menu->menuwidth + 3; clearwindow(top, left - 2, top + numitems + 1, left + menuwidth + 1, - ms->menupage, ms->fillchar, ms->shadowattr); + ms->fillchar, ms->shadowattr); drawbox(top - 1, left - 3, top + numitems, left + menuwidth, - ms->menupage, ms->normalattr[NOHLITE], ms->menubt); - memset(sep, ms->box_horiz, menuwidth); // String containing the seperator string - sep[menuwidth - 1] = 0; + ms->normalattr[NOHLITE]); + // Menu title x = (menuwidth - strlen(menu->title) - 1) >> 1; - gotoxy(top - 1, left + x, ms->menupage); + gotoxy(top - 1, left + x); printmenuitem(menu->title, ms->normalattr); - row = -1; // 1 less than inital value of x + + // All lines in the menu + row = -1; // 1 less than inital value of x for (x = first; x < menu->numitems; x++) { - ci = menu->items[x]; - if (ci->action == OPT_INVISIBLE) - continue; - row++; - if (row > numitems) - break; - // Setup the defaults now - fchar[0] = RADIOUNSEL; - fchar[1] = '\0'; // Unselected ( ) - lchar[0] = '\0'; // Nothing special after - str = ci->item; // Pointer to item string - attr = ms->normalattr; // Always same attribute - fchar[0] = (x == curr ? RADIOSEL : RADIOUNSEL); - switch (ci->action) // set up attr,str,fchar,lchar for everything - { - case OPT_INACTIVE: - attr = ms->inactattr; - break; - case OPT_SEP: - fchar[0] = '\b'; - fchar[1] = ms->box_ltrt; - fchar[2] = ms->box_horiz; - fchar[3] = ms->box_horiz; - fchar[4] = 0; - lchar[0] = ms->box_horiz; - lchar[1] = ms->box_rtlt; - lchar[3] = 0; - str = sep; - break; - default: // To keep the compiler happy - break; - } - gotoxy(top + row, left - 2, ms->menupage); - cprint(ms->spacechar, attr[NOHLITE], menuwidth + 2, ms->menupage); // Wipe area with spaces - gotoxy(top + row, left - 2, ms->menupage); - csprint(fchar, attr[NOHLITE]); // Print first part - gotoxy(top + row, left, ms->menupage); - printmenuitem(str, attr); // Print main part - gotoxy(top + row, left + menuwidth - 1, ms->menupage); // Last char if any - csprint(lchar, attr[NOHLITE]); // Print last part + ci = menu->items[x]; + if (ci->action == OPT_INVISIBLE) + continue; + row++; + if (row >= numitems) + break; // Already have enough number of items + print_line(menu, curr, top, left, x, row, radio); } // Check if we need to MOREABOVE and MOREBELOW to be added // reuse x row = 0; - x = next_visible_sep(menu, 0); // First item - if (!isvisible(menu, first, x)) // There is more above + x = next_visible_sep(menu, 0); // First item + if (!isvisible(menu, first, x)) // There is more above { - row = 1; - gotoxy(top, left + menuwidth, ms->menupage); - cprint(MOREABOVE, ms->normalattr[NOHLITE], 1, ms->menupage); + row = 1; + gotoxy(top, left + menuwidth); + cprint(MOREABOVE, ms->normalattr[NOHLITE], 1); } - x = prev_visible_sep(menu, menu->numitems); // last item - if (!isvisible(menu, first, x)) // There is more above + x = prev_visible_sep(menu, menu->numitems); // last item + if (!isvisible(menu, first, x)) // There is more above { - row = 1; - gotoxy(top + numitems - 1, left + menuwidth, ms->menupage); - cprint(MOREBELOW, ms->normalattr[NOHLITE], 1, ms->menupage); + row = 1; + gotoxy(top + numitems - 1, left + menuwidth); + cprint(MOREBELOW, ms->normalattr[NOHLITE], 1); } // Add a scroll box x = ((numitems - 1) * curr) / (menu->numitems); if ((x > 0) && (row == 1)) { - gotoxy(top + x, left + menuwidth, ms->menupage); - cprint(SCROLLBOX, ms->normalattr[NOHLITE], 1, ms->menupage); + gotoxy(top + x, left + menuwidth); + csprint("\016\141\017", ms->normalattr[NOHLITE]); } if (ms->handler) - ms->handler(ms, menu->items[curr]); + ms->handler(ms, menu->items[curr]); } void cleanupmenu(pt_menu menu, uchar top, uchar left, int numitems) { if (numitems > menu->menuheight) - numitems = menu->menuheight; - clearwindow(top, left - 2, top + numitems + 1, left + menu->menuwidth + 4, ms->menupage, ms->fillchar, ms->fillattr); // Clear the shadow - clearwindow(top - 1, left - 3, top + numitems, left + menu->menuwidth + 3, ms->menupage, ms->fillchar, ms->fillattr); // main window + numitems = menu->menuheight; + clearwindow(top, left - 2, top + numitems + 1, left + menu->menuwidth + 4, ms->fillchar, ms->fillattr); // Clear the shadow + clearwindow(top - 1, left - 3, top + numitems, left + menu->menuwidth + 3, ms->fillchar, ms->fillattr); // main window } -/* Handle a radio menu */ -pt_menuitem getradiooption(pt_menu menu, uchar top, uchar left, uchar startopt) - // Return item chosen or NULL if ESC was hit. -{ - int curr, i, first, tmp; - uchar asc, scan; - uchar numitems; - pt_menuitem ci; // Current item - - numitems = calc_visible(menu, 0); - // Setup status line - gotoxy(ms->minrow + ms->statline, ms->mincol, ms->menupage); - cprint(ms->spacechar, ms->statusattr[NOHLITE], ms->numcols, ms->menupage); - - // Initialise current menu item - curr = next_visible(menu, startopt); - - gotoxy(ms->minrow + ms->statline, ms->mincol, ms->menupage); - cprint(ms->spacechar, ms->statusattr[NOHLITE], ms->numcols, 1); - gotoxy(ms->minrow + ms->statline, ms->mincol, ms->menupage); - printmenuitem(menu->items[curr]->status, ms->statusattr); - first = calc_first_early(menu, curr); - while (1) // Forever - { - printradiomenu(menu, curr, top, left, first); - ci = menu->items[curr]; - - asc = getch(&scan); - switch (scan) { - case HOMEKEY: - curr = next_visible(menu, 0); - first = calc_first_early(menu, curr); - break; - case ENDKEY: - curr = prev_visible(menu, numitems - 1); - first = calc_first_late(menu, curr); - break; - case PAGEDN: - for (i = 0; i < 5; i++) - curr = next_visible(menu, curr + 1); - first = calc_first_late(menu, curr); - break; - case PAGEUP: - for (i = 0; i < 5; i++) - curr = prev_visible(menu, curr - 1); - first = calc_first_early(menu, curr); - break; - case UPARROW: - curr = prev_visible(menu, curr - 1); - if (curr < first) - first = calc_first_early(menu, curr); - break; - case DNARROW: - curr = next_visible(menu, curr + 1); - if (!isvisible(menu, first, curr)) - first = calc_first_late(menu, curr); - break; - case LTARROW: - case ESCAPE: - return NULL; - break; - case RTARROW: - case ENTERA: - case ENTERB: - if (ci->action == OPT_INACTIVE) - break; - if (ci->action == OPT_SEP) - break; - return ci; - break; - default: - // Check if this is a shortcut key - if (((asc >= 'A') && (asc <= 'Z')) || - ((asc >= 'a') && (asc <= 'z')) || - ((asc >= '0') && (asc <= '9'))) { - tmp = find_shortcut(menu, asc, curr); - if ((tmp > curr) && (!isvisible(menu, first, tmp))) - first = calc_first_late(menu, tmp); - if (tmp < curr) - first = calc_first_early(menu, tmp); - curr = tmp; - } else { - if (ms->keys_handler) // Call extra keys handler - ms->keys_handler(ms, menu->items[curr], (scan << 8) | asc); - } - break; - } - // Update status line - gotoxy(ms->minrow + ms->statline, ms->mincol, ms->menupage); - cprint(ms->spacechar, ms->statusattr[NOHLITE], ms->numcols, - ms->menupage); - printmenuitem(menu->items[curr]->status, ms->statusattr); - } - return NULL; // Should never come here -} /* Handle one menu */ -pt_menuitem getmenuoption(pt_menu menu, uchar top, uchar left, uchar startopt) +static pt_menuitem getmenuoption(pt_menu menu, uchar top, uchar left, uchar startopt, bool radio) // Return item chosen or NULL if ESC was hit. { - int curr, i, first, tmp; - uchar asc, scan; + int prev, prev_first, curr, i, first, tmp; + int asc = 0; + bool redraw = true; // Need to draw the menu the first time uchar numitems; - pt_menuitem ci; // Current item - t_handler_return hr; // Return value of handler + pt_menuitem ci; // Current item + t_handler_return hr; // Return value of handler numitems = calc_visible(menu, 0); // Setup status line - gotoxy(ms->minrow + ms->statline, ms->mincol, ms->menupage); - cprint(ms->spacechar, ms->statusattr[NOHLITE], ms->numcols, ms->menupage); + gotoxy(ms->minrow + ms->statline, ms->mincol); + cprint(ms->spacechar, ms->statusattr[NOHLITE], ms->numcols); // Initialise current menu item curr = next_visible(menu, startopt); + prev = curr; - gotoxy(ms->minrow + ms->statline, ms->mincol, ms->menupage); - cprint(ms->spacechar, ms->statusattr[NOHLITE], ms->numcols, 1); - gotoxy(ms->minrow + ms->statline, ms->mincol, ms->menupage); + gotoxy(ms->minrow + ms->statline, ms->mincol); + cprint(ms->spacechar, ms->statusattr[NOHLITE], ms->numcols); + gotoxy(ms->minrow + ms->statline, ms->mincol); printmenuitem(menu->items[curr]->status, ms->statusattr); first = calc_first_early(menu, curr); - while (1) // Forever + prev_first = first; + while (1) // Forever { - printmenu(menu, curr, top, left, first); - ci = menu->items[curr]; - asc = getch(&scan); - switch (scan) { - case HOMEKEY: - curr = next_visible(menu, 0); - first = calc_first_early(menu, curr); - break; - case ENDKEY: - curr = prev_visible(menu, numitems - 1); - first = calc_first_late(menu, curr); - break; - case PAGEDN: - for (i = 0; i < 5; i++) - curr = next_visible(menu, curr + 1); - first = calc_first_late(menu, curr); - break; - case PAGEUP: - for (i = 0; i < 5; i++) - curr = prev_visible(menu, curr - 1); - first = calc_first_early(menu, curr); - break; - case UPARROW: - curr = prev_visible(menu, curr - 1); - if (curr < first) - first = calc_first_early(menu, curr); - break; - case DNARROW: - curr = next_visible(menu, curr + 1); - if (!isvisible(menu, first, curr)) - first = calc_first_late(menu, curr); - break; - case LTARROW: - case ESCAPE: - return NULL; - break; - case RTARROW: - case ENTERA: - case ENTERB: - if (ci->action == OPT_INACTIVE) - break; - if (ci->action == OPT_CHECKBOX) - break; - if (ci->action == OPT_SEP) - break; - if (ci->action == OPT_EXITMENU) - return NULL; // As if we hit Esc - // If we are going into a radio menu, dont call handler, return ci - if (ci->action == OPT_RADIOMENU) - return ci; - if (ci->handler != NULL) // Do we have a handler - { - hr = ci->handler(ms, ci); - if (hr.refresh) // Do we need to refresh - { - // Cleanup menu using old number of items - cleanupmenu(menu, top, left, numitems); - // Recalculate the number of items - numitems = calc_visible(menu, 0); - // Reprint the menu - printmenu(menu, curr, top, left, first); - } - if (hr.valid) - return ci; - } else - return ci; - break; - case SPACEKEY: - if (ci->action != OPT_CHECKBOX) - break; - ci->itemdata.checked = !ci->itemdata.checked; - if (ci->handler != NULL) // Do we have a handler - { - hr = ci->handler(ms, ci); - if (hr.refresh) // Do we need to refresh - { - // Cleanup menu using old number of items - cleanupmenu(menu, top, left, numitems); - // Recalculate the number of items - numitems = calc_visible(menu, 0); - // Reprint the menu - printmenu(menu, curr, top, left, first); - } - } - break; - default: - // Check if this is a shortcut key - if (((asc >= 'A') && (asc <= 'Z')) || - ((asc >= 'a') && (asc <= 'z')) || - ((asc >= '0') && (asc <= '9'))) { - tmp = find_shortcut(menu, asc, curr); - if ((tmp > curr) && (!isvisible(menu, first, tmp))) - first = calc_first_late(menu, tmp); - if (tmp < curr) - first = calc_first_early(menu, tmp); - curr = tmp; - } else { - if (ms->keys_handler) // Call extra keys handler - ms->keys_handler(ms, menu->items[curr], (scan << 8) | asc); - } - break; - } - // Update status line - gotoxy(ms->minrow + ms->statline, ms->mincol, ms->menupage); - cprint(ms->spacechar, ms->statusattr[NOHLITE], ms->numcols, - ms->menupage); - printmenuitem(menu->items[curr]->status, ms->statusattr); + /* Redraw everything if: + * + we need to scroll (take care of scroll bars, ...) + * + menuoption + */ + if (prev_first != first || redraw) { + printmenu(menu, curr, top, left, first, radio); + } else { + /* Redraw only the highlighted entry */ + print_line(menu, curr, top, left, prev, prev - first, radio); + print_line(menu, curr, top, left, curr, curr - first, radio); + } + redraw = false; + prev = curr; + prev_first = first; + ci = menu->items[curr]; + asc = getch(); + switch (asc) { + case KEY_CTRL('L'): + redraw = true; + break; + case KEY_HOME: + curr = next_visible(menu, 0); + first = calc_first_early(menu, curr); + break; + case KEY_END: + curr = prev_visible(menu, numitems - 1); + first = calc_first_late(menu, curr); + break; + case KEY_PGDN: + for (i = 0; i < 5; i++) + curr = next_visible(menu, curr + 1); + first = calc_first_late(menu, curr); + break; + case KEY_PGUP: + for (i = 0; i < 5; i++) + curr = prev_visible(menu, curr - 1); + first = calc_first_early(menu, curr); + break; + case KEY_UP: + curr = prev_visible(menu, curr - 1); + if (curr < first) + first = calc_first_early(menu, curr); + break; + case KEY_DOWN: + curr = next_visible(menu, curr + 1); + if (!isvisible(menu, first, curr)) + first = calc_first_late(menu, curr); + break; + case KEY_LEFT: + case KEY_ESC: + return NULL; + break; + case KEY_RIGHT: + case KEY_ENTER: + if (ci->action == OPT_INACTIVE) + break; + if (ci->action == OPT_CHECKBOX) + break; + if (ci->action == OPT_SEP) + break; + if (ci->action == OPT_EXITMENU) + return NULL; // As if we hit Esc + // If we are going into a radio menu, dont call handler, return ci + if (ci->action == OPT_RADIOMENU) + return ci; + if (ci->handler != NULL) // Do we have a handler + { + hr = ci->handler(ms, ci); + if (hr.refresh) // Do we need to refresh + { + // Cleanup menu using old number of items + cleanupmenu(menu, top, left, numitems); + // Recalculate the number of items + numitems = calc_visible(menu, 0); + // Reprint the menu + printmenu(menu, curr, top, left, first, radio); + } + if (hr.valid) + return ci; + } else + return ci; + break; + case SPACECHAR: + if (ci->action != OPT_CHECKBOX) + break; + ci->itemdata.checked = !ci->itemdata.checked; + if (ci->handler != NULL) // Do we have a handler + { + hr = ci->handler(ms, ci); + if (hr.refresh) // Do we need to refresh + { + // Cleanup menu using old number of items + cleanupmenu(menu, top, left, numitems); + // Recalculate the number of items + numitems = calc_visible(menu, 0); + // Reprint the menu + printmenu(menu, curr, top, left, first, radio); + } + } + break; + default: + // Check if this is a shortcut key + if (((asc >= 'A') && (asc <= 'Z')) || + ((asc >= 'a') && (asc <= 'z')) || + ((asc >= '0') && (asc <= '9'))) { + tmp = find_shortcut(menu, asc, curr); + if ((tmp > curr) && (!isvisible(menu, first, tmp))) + first = calc_first_late(menu, tmp); + if (tmp < curr) + first = calc_first_early(menu, tmp); + curr = tmp; + } else { + if (ms->keys_handler) // Call extra keys handler + ms->keys_handler(ms, menu->items[curr], asc); + + /* The handler may have changed the UI, reset it on exit */ + reset_ui(); + // Cleanup menu using old number of items + cleanupmenu(menu, top, left, numitems); + // Recalculate the number of items + numitems = calc_visible(menu, 0); + // Reprint the menu + printmenu(menu, curr, top, left, first, radio); + } + break; + } + // Update status line + /* Erase the previous status */ + gotoxy(ms->minrow + ms->statline, ms->mincol); + cprint(ms->spacechar, ms->statusattr[NOHLITE], ms->numcols); + /* Print the new status */ + gotoxy(ms->minrow + ms->statline, ms->mincol); + printmenuitem(menu->items[curr]->status, ms->statusattr); } - return NULL; // Should never come here + return NULL; // Should never come here } /* Handle the entire system of menu's. */ pt_menuitem runmenusystem(uchar top, uchar left, pt_menu cmenu, uchar startopt, - uchar menutype) + uchar menutype) /* * cmenu * Which menu should be currently displayed @@ -629,36 +529,37 @@ pt_menuitem runmenusystem(uchar top, uchar left, pt_menu cmenu, uchar startopt, uchar row, col; if (cmenu == NULL) - return NULL; + return NULL; + startover: // Set the menu height cmenu->menuheight = ms->maxrow - top - 3; if (cmenu->menuheight > ms->maxmenuheight) - cmenu->menuheight = ms->maxmenuheight; + cmenu->menuheight = ms->maxmenuheight; if (menutype == NORMALMENU) - opt = getmenuoption(cmenu, top, left, startopt); - else // menutype == RADIOMENU - opt = getradiooption(cmenu, top, left, startopt); + opt = getmenuoption(cmenu, top, left, startopt, false); + else // menutype == RADIOMENU + opt = getmenuoption(cmenu, top, left, startopt, true); if (opt == NULL) { - // User hit Esc - cleanupmenu(cmenu, top, left, calc_visible(cmenu, 0)); - return NULL; + // User hit Esc + cleanupmenu(cmenu, top, left, calc_visible(cmenu, 0)); + return NULL; } // Are we done with the menu system? if ((opt->action != OPT_SUBMENU) && (opt->action != OPT_RADIOMENU)) { - cleanupmenu(cmenu, top, left, calc_visible(cmenu, 0)); - return opt; // parent cleanup other menus + cleanupmenu(cmenu, top, left, calc_visible(cmenu, 0)); + return opt; // parent cleanup other menus } // Either radiomenu or submenu // Do we have a valid menu number? The next hack uses the fact that // itemdata.submenunum = itemdata.radiomenunum (since enum data type) - if (opt->itemdata.submenunum >= ms->nummenus) // This is Bad.... + if (opt->itemdata.submenunum >= ms->nummenus) // This is Bad.... { - gotoxy(12, 12, ms->menupage); // Middle of screen - csprint("ERROR: Invalid submenu requested.", 0x07); - cleanupmenu(cmenu, top, left, calc_visible(cmenu, 0)); - return NULL; // Pretend user hit esc + gotoxy(12, 12); // Middle of screen + csprint("ERROR: Invalid submenu requested.", 0x07); + cleanupmenu(cmenu, top, left, calc_visible(cmenu, 0)); + return NULL; // Pretend user hit esc } // Call recursively for submenu // Position the submenu below the current item, @@ -666,32 +567,32 @@ startover: row = ms->menus[(unsigned int)opt->itemdata.submenunum]->row; col = ms->menus[(unsigned int)opt->itemdata.submenunum]->col; if (row == 0xFF) - row = top + opt->index + 2; + row = top + opt->index + 2; if (col == 0xFF) - col = left + 3 + (cmenu->menuwidth >> 1); + col = left + 3 + (cmenu->menuwidth >> 1); mt = (opt->action == OPT_SUBMENU ? NORMALMENU : RADIOMENU); startat = 0; if ((opt->action == OPT_RADIOMENU) && (opt->data != NULL)) - startat = ((t_menuitem *) opt->data)->index; + startat = ((t_menuitem *) opt->data)->index; choice = runmenusystem(row, col, - ms->menus[(unsigned int)opt->itemdata.submenunum], - startat, mt); + ms->menus[(unsigned int)opt->itemdata.submenunum], + startat, mt); if (opt->action == OPT_RADIOMENU) { - if (choice != NULL) - opt->data = (void *)choice; // store choice in data field - if (opt->handler != NULL) - opt->handler(ms, opt); - choice = NULL; // Pretend user hit esc + if (choice != NULL) + opt->data = (void *)choice; // store choice in data field + if (opt->handler != NULL) + opt->handler(ms, opt); + choice = NULL; // Pretend user hit esc } - if (choice == NULL) // User hit Esc in submenu + if (choice == NULL) // User hit Esc in submenu { - // Startover - startopt = opt->index; - goto startover; + // Startover + startopt = opt->index; + goto startover; } else { - cleanupmenu(cmenu, top, left, calc_visible(cmenu, 0)); - return choice; + cleanupmenu(cmenu, top, left, calc_visible(cmenu, 0)); + return choice; } } @@ -702,11 +603,11 @@ uchar find_menu_num(const char *name) pt_menu m; if (name == NULL) - return (uchar) (-1); + return (uchar) (-1); for (i = 0; i < ms->nummenus; i++) { - m = ms->menus[i]; - if ((m->name) && (strcmp(m->name, name) == 0)) - return i; + m = ms->menus[i]; + if ((m->name) && (strcmp(m->name, name) == 0)) + return i; } return (uchar) (-1); } @@ -722,16 +623,16 @@ void fix_submenus() i = 0; for (i = 0; i < ms->nummenus; i++) { - m = ms->menus[i]; - for (j = 0; j < m->numitems; j++) { - mi = m->items[j]; - // if item is a submenu and has non-empty non-trivial data string - if (mi->data && strlen(mi->data) > 0 && - ((mi->action == OPT_SUBMENU) - || (mi->action == OPT_RADIOMENU))) { - mi->itemdata.submenunum = find_menu_num(mi->data); - } - } + m = ms->menus[i]; + for (j = 0; j < m->numitems; j++) { + mi = m->items[j]; + // if item is a submenu and has non-empty non-trivial data string + if (mi->data && strlen(mi->data) > 0 && + ((mi->action == OPT_SUBMENU) + || (mi->action == OPT_RADIOMENU))) { + mi->itemdata.submenunum = find_menu_num(mi->data); + } + } } } @@ -740,34 +641,23 @@ void fix_submenus() pt_menuitem showmenus(uchar startmenu) { pt_menuitem rv; - uchar oldpage, tpos; - fix_submenus(); // Fix submenu numbers incase nick names were used + fix_submenus(); // Fix submenu numbers incase nick names were used - // Setup screen for menusystem - oldpage = getdisppage(); - setdisppage(ms->menupage); - cls(); - clearwindow(ms->minrow, ms->mincol, ms->maxrow, ms->maxcol, - ms->menupage, ms->fillchar, ms->fillattr); - tpos = (ms->numcols - strlen(ms->title) - 1) >> 1; // center it on line - gotoxy(ms->minrow, ms->mincol, ms->menupage); - cprint(ms->tfillchar, ms->titleattr, ms->numcols, ms->menupage); - gotoxy(ms->minrow, ms->mincol + tpos, ms->menupage); - csprint(ms->title, ms->titleattr); + /* Turn autowrap off, to avoid scrolling the menu */ + printf(CSI "?7l"); - cursoroff(); // Doesn't seem to work? + // Setup screen for menusystem + reset_ui(); // Go, main menu cannot be a radio menu rv = runmenusystem(ms->minrow + MENUROW, ms->mincol + MENUCOL, - ms->menus[(unsigned int)startmenu], 0, NORMALMENU); + ms->menus[(unsigned int)startmenu], 0, NORMALMENU); // Hide the garbage we left on the screen cursoron(); - if (oldpage == ms->menupage) - cls(); - else - setdisppage(oldpage); + cls(); + gotoxy(ms->minrow, ms->mincol); // Return user choice return rv; @@ -780,17 +670,17 @@ pt_menusystem init_menusystem(const char *title) ms = NULL; ms = (pt_menusystem) malloc(sizeof(t_menusystem)); if (ms == NULL) - return NULL; + return NULL; ms->nummenus = 0; // Initialise all menu pointers for (i = 0; i < MAXMENUS; i++) - ms->menus[i] = NULL; + ms->menus[i] = NULL; ms->title = (char *)malloc(TITLELEN + 1); if (title == NULL) - strcpy(ms->title, TITLESTR); // Copy string + strcpy(ms->title, TITLESTR); // Copy string else - strcpy(ms->title, title); + strcpy(ms->title, title); // Timeout settings ms->tm_stepsize = TIMEOUTSTEPSIZE; @@ -820,12 +710,12 @@ pt_menusystem init_menusystem(const char *title) ms->spacechar = SPACECHAR; ms->shadowattr = SHADOWATTR; - ms->menupage = MENUPAGE; // Usually no need to change this at all + ms->menupage = MENUPAGE; // Usually no need to change this at all // Initialise all handlers ms->handler = NULL; ms->keys_handler = NULL; - ms->ontimeout = NULL; // No timeout handler + ms->ontimeout = NULL; // No timeout handler ms->tm_total_timeout = 0; ms->tm_sofar_timeout = 0; ms->ontotaltimeout = NULL; @@ -838,110 +728,107 @@ pt_menusystem init_menusystem(const char *title) // Figure out the size of the screen we are in now. // By default we use the whole screen for our menu + if (getscreensize(1, &ms->numrows, &ms->numcols)) { + /* Unknown screen size? */ + ms->numcols = 80; + ms->numrows = 24; + } ms->minrow = ms->mincol = 0; - ms->numcols = getnumcols(); - ms->numrows = getnumrows(); ms->maxcol = ms->numcols - 1; ms->maxrow = ms->numrows - 1; // How many entries per menu can we display at a time ms->maxmenuheight = ms->maxrow - ms->minrow - 3; if (ms->maxmenuheight > MAXMENUHEIGHT) - ms->maxmenuheight = MAXMENUHEIGHT; + ms->maxmenuheight = MAXMENUHEIGHT; + + console_ansi_raw(); - // Set up the look of the box - set_box_type(MENUBOXTYPE); return ms; } void set_normal_attr(uchar normal, uchar selected, uchar inactivenormal, - uchar inactiveselected) + uchar inactiveselected) { if (normal != 0xFF) - ms->normalattr[0] = normal; + ms->normalattr[0] = normal; if (selected != 0xFF) - ms->reverseattr[0] = selected; + ms->reverseattr[0] = selected; if (inactivenormal != 0xFF) - ms->inactattr[0] = inactivenormal; + ms->inactattr[0] = inactivenormal; if (inactiveselected != 0xFF) - ms->revinactattr[0] = inactiveselected; + ms->revinactattr[0] = inactiveselected; } void set_normal_hlite(uchar normal, uchar selected, uchar inactivenormal, - uchar inactiveselected) + uchar inactiveselected) { if (normal != 0xFF) - ms->normalattr[1] = normal; + ms->normalattr[1] = normal; if (selected != 0xFF) - ms->reverseattr[1] = selected; + ms->reverseattr[1] = selected; if (inactivenormal != 0xFF) - ms->inactattr[1] = inactivenormal; + ms->inactattr[1] = inactivenormal; if (inactiveselected != 0xFF) - ms->revinactattr[1] = inactiveselected; + ms->revinactattr[1] = inactiveselected; } void set_status_info(uchar statusattr, uchar statushlite, uchar statline) { if (statusattr != 0xFF) - ms->statusattr[NOHLITE] = statusattr; + ms->statusattr[NOHLITE] = statusattr; if (statushlite != 0xFF) - ms->statusattr[HLITE] = statushlite; + ms->statusattr[HLITE] = statushlite; // statline is relative to minrow if (statline >= ms->numrows) - statline = ms->numrows - 1; - ms->statline = statline; // relative to ms->minrow, 0 based + statline = ms->numrows - 1; + ms->statline = statline; // relative to ms->minrow, 0 based } void set_title_info(uchar tfillchar, uchar titleattr) { if (tfillchar != 0xFF) - ms->tfillchar = tfillchar; + ms->tfillchar = tfillchar; if (titleattr != 0xFF) - ms->titleattr = titleattr; + ms->titleattr = titleattr; } void set_misc_info(uchar fillchar, uchar fillattr, uchar spacechar, - uchar shadowattr) + uchar shadowattr) { if (fillchar != 0xFF) - ms->fillchar = fillchar; + ms->fillchar = fillchar; if (fillattr != 0xFF) - ms->fillattr = fillattr; + ms->fillattr = fillattr; if (spacechar != 0xFF) - ms->spacechar = spacechar; + ms->spacechar = spacechar; if (shadowattr != 0xFF) - ms->shadowattr = shadowattr; -} - -void set_box_type(boxtype bt) -{ - uchar *bxc; - ms->menubt = bt; - bxc = getboxchars(bt); - ms->box_horiz = bxc[BOX_HORIZ]; // The char used to draw top line - ms->box_ltrt = bxc[BOX_LTRT]; - ms->box_rtlt = bxc[BOX_RTLT]; + ms->shadowattr = shadowattr; } void set_menu_options(uchar maxmenuheight) { if (maxmenuheight != 0xFF) - ms->maxmenuheight = maxmenuheight; + ms->maxmenuheight = maxmenuheight; } // Set the window which menusystem should use void set_window_size(uchar top, uchar left, uchar bot, uchar right) { + int nr, nc; - uchar nr, nc; if ((top > bot) || (left > right)) - return; // Sorry no change will happen here - nr = getnumrows(); - nc = getnumcols(); + return; // Sorry no change will happen here + + if (getscreensize(1, &nr, &nc)) { + /* Unknown screen size? */ + nr = 80; + nc = 24; + } if (bot >= nr) - bot = nr - 1; + bot = nr - 1; if (right >= nc) - right = nc - 1; + right = nc - 1; ms->minrow = top; ms->mincol = left; ms->maxrow = bot; @@ -949,7 +836,7 @@ void set_window_size(uchar top, uchar left, uchar bot, uchar right) ms->numcols = right - left + 1; ms->numrows = bot - top + 1; if (ms->statline >= ms->numrows) - ms->statline = ms->numrows - 1; // Clip statline if need be + ms->statline = ms->numrows - 1; // Clip statline if need be } void reg_handler(t_handler htype, void *handler) @@ -957,11 +844,11 @@ void reg_handler(t_handler htype, void *handler) // If bad value set to default screen handler switch (htype) { case HDLR_KEYS: - ms->keys_handler = (t_keys_handler) handler; - break; + ms->keys_handler = (t_keys_handler) handler; + break; default: - ms->handler = (t_menusystem_handler) handler; - break; + ms->handler = (t_menusystem_handler) handler; + break; } } @@ -969,22 +856,22 @@ void unreg_handler(t_handler htype) { switch (htype) { case HDLR_KEYS: - ms->keys_handler = NULL; - break; + ms->keys_handler = NULL; + break; default: - ms->handler = NULL; - break; + ms->handler = NULL; + break; } } void reg_ontimeout(t_timeout_handler handler, unsigned int numsteps, - unsigned int stepsize) + unsigned int stepsize) { ms->ontimeout = handler; if (numsteps != 0) - ms->tm_numsteps = numsteps; + ms->tm_numsteps = numsteps; if (stepsize != 0) - ms->tm_stepsize = stepsize; + ms->tm_stepsize = stepsize; } void unreg_ontimeout() @@ -993,12 +880,12 @@ void unreg_ontimeout() } void reg_ontotaltimeout(t_timeout_handler handler, - unsigned long numcentiseconds) + unsigned long numcentiseconds) { if (numcentiseconds != 0) { - ms->ontotaltimeout = handler; - ms->tm_total_timeout = numcentiseconds * 10; // to convert to milliseconds - ms->tm_sofar_timeout = 0; + ms->ontotaltimeout = handler; + ms->tm_total_timeout = numcentiseconds * 10; // to convert to milliseconds + ms->tm_sofar_timeout = 0; } } @@ -1011,31 +898,31 @@ int next_visible(pt_menu menu, int index) { int ans; if (index < 0) - ans = 0; + ans = 0; else if (index >= menu->numitems) - ans = menu->numitems - 1; + ans = menu->numitems - 1; else - ans = index; + ans = index; while ((ans < menu->numitems - 1) && - ((menu->items[ans]->action == OPT_INVISIBLE) || - (menu->items[ans]->action == OPT_SEP))) - ans++; + ((menu->items[ans]->action == OPT_INVISIBLE) || + (menu->items[ans]->action == OPT_SEP))) + ans++; return ans; } -int prev_visible(pt_menu menu, int index) // Return index of prev visible +int prev_visible(pt_menu menu, int index) // Return index of prev visible { int ans; if (index < 0) - ans = 0; + ans = 0; else if (index >= menu->numitems) - ans = menu->numitems - 1; + ans = menu->numitems - 1; else - ans = index; + ans = index; while ((ans > 0) && - ((menu->items[ans]->action == OPT_INVISIBLE) || - (menu->items[ans]->action == OPT_SEP))) - ans--; + ((menu->items[ans]->action == OPT_INVISIBLE) || + (menu->items[ans]->action == OPT_SEP))) + ans--; return ans; } @@ -1043,28 +930,28 @@ int next_visible_sep(pt_menu menu, int index) { int ans; if (index < 0) - ans = 0; + ans = 0; else if (index >= menu->numitems) - ans = menu->numitems - 1; + ans = menu->numitems - 1; else - ans = index; + ans = index; while ((ans < menu->numitems - 1) && - (menu->items[ans]->action == OPT_INVISIBLE)) - ans++; + (menu->items[ans]->action == OPT_INVISIBLE)) + ans++; return ans; } -int prev_visible_sep(pt_menu menu, int index) // Return index of prev visible +int prev_visible_sep(pt_menu menu, int index) // Return index of prev visible { int ans; if (index < 0) - ans = 0; + ans = 0; else if (index >= menu->numitems) - ans = menu->numitems - 1; + ans = menu->numitems - 1; else - ans = index; + ans = index; while ((ans > 0) && (menu->items[ans]->action == OPT_INVISIBLE)) - ans--; + ans--; return ans; } @@ -1073,11 +960,11 @@ int calc_visible(pt_menu menu, int first) int ans, i; if (menu == NULL) - return 0; + return 0; ans = 0; for (i = first; i < menu->numitems; i++) - if (menu->items[i]->action != OPT_INVISIBLE) - ans++; + if (menu->items[i]->action != OPT_INVISIBLE) + ans++; return ans; } @@ -1085,9 +972,9 @@ int calc_visible(pt_menu menu, int first) int isvisible(pt_menu menu, int first, int curr) { if (curr < first) - return 0; + return 0; return (calc_visible(menu, first) - calc_visible(menu, curr) < - menu->menuheight); + menu->menuheight); } // Calculate the first entry to be displayed @@ -1098,11 +985,11 @@ int calc_first_late(pt_menu menu, int curr) nv = calc_visible(menu, 0); if (nv <= menu->menuheight) - return 0; + return 0; // Start with curr and go back menu->menuheight times ans = curr + 1; for (i = 0; i < menu->menuheight; i++) - ans = prev_visible_sep(menu, ans - 1); + ans = prev_visible_sep(menu, ans - 1); return ans; } @@ -1114,13 +1001,13 @@ int calc_first_early(pt_menu menu, int curr) nv = calc_visible(menu, 0); if (nv <= menu->menuheight) - return 0; + return 0; // Start with curr and go back till >= menu->menuheight // items are visible - nv = calc_visible(menu, curr); // Already nv of them are visible + nv = calc_visible(menu, curr); // Already nv of them are visible ans = curr; for (i = 0; i < menu->menuheight - nv; i++) - ans = prev_visible_sep(menu, ans - 1); + ans = prev_visible_sep(menu, ans - 1); return ans; } @@ -1132,51 +1019,51 @@ uchar add_menu(const char *title, int maxmenusize) num = ms->nummenus; if (num >= MAXMENUS) - return -1; + return -1; m = NULL; m = (pt_menu) malloc(sizeof(t_menu)); if (m == NULL) - return -1; + return -1; ms->menus[num] = m; m->numitems = 0; m->name = NULL; m->row = 0xFF; m->col = 0xFF; if (maxmenusize < 1) - m->maxmenusize = MAXMENUSIZE; + m->maxmenusize = MAXMENUSIZE; else - m->maxmenusize = maxmenusize; + m->maxmenusize = maxmenusize; m->items = (pt_menuitem *) malloc(sizeof(pt_menuitem) * (m->maxmenusize)); for (i = 0; i < m->maxmenusize; i++) - m->items[i] = NULL; + m->items[i] = NULL; m->title = (char *)malloc(MENULEN + 1); if (title) { - if (strlen(title) > MENULEN - 2) - strcpy(m->title, TITLELONG); - else - strcpy(m->title, title); + if (strlen(title) > MENULEN - 2) + strcpy(m->title, TITLELONG); + else + strcpy(m->title, title); } else - strcpy(m->title, EMPTYSTR); + strcpy(m->title, EMPTYSTR); m->menuwidth = strlen(m->title); ms->nummenus++; return ms->nummenus - 1; } -void set_menu_name(const char *name) // Set the "name" of this menu +void set_menu_name(const char *name) // Set the "name" of this menu { pt_menu m; m = ms->menus[ms->nummenus - 1]; - if (m->name) // Free up previous name + if (m->name) // Free up previous name { - free(m->name); - m->name = NULL; + free(m->name); + m->name = NULL; } if (name) { - m->name = (char *)malloc(strlen(name) + 1); - strcpy(m->name, name); + m->name = (char *)malloc(strlen(name) + 1); + strcpy(m->name, name); } } @@ -1188,7 +1075,7 @@ uchar add_named_menu(const char *name, const char *title, int maxmenusize) return ms->nummenus - 1; } -void set_menu_pos(uchar row, uchar col) // Set the position of this menu. +void set_menu_pos(uchar row, uchar col) // Set the position of this menu. { pt_menu m; @@ -1197,7 +1084,7 @@ void set_menu_pos(uchar row, uchar col) // Set the position of this menu. m->col = col; } -pt_menuitem add_sep() // Add a separator to current menu +pt_menuitem add_sep() // Add a separator to current menu { pt_menuitem mi; pt_menu m; @@ -1206,9 +1093,9 @@ pt_menuitem add_sep() // Add a separator to current menu mi = NULL; mi = (pt_menuitem) malloc(sizeof(t_menuitem)); if (mi == NULL) - return NULL; + return NULL; m->items[(unsigned int)m->numitems] = mi; - mi->handler = NULL; // No handler + mi->handler = NULL; // No handler mi->item = mi->status = mi->data = NULL; mi->action = OPT_SEP; mi->index = m->numitems++; @@ -1220,20 +1107,20 @@ pt_menuitem add_sep() // Add a separator to current menu // Add item to the "current" menu pt_menuitem add_item(const char *item, const char *status, t_action action, - const char *data, uchar itemdata) + const char *data, uchar itemdata) { pt_menuitem mi; pt_menu m; const char *str; - uchar inhlite = 0; // Are we inside hlite area + uchar inhlite = 0; // Are we inside hlite area m = (ms->menus[ms->nummenus - 1]); mi = NULL; mi = (pt_menuitem) malloc(sizeof(t_menuitem)); if (mi == NULL) - return NULL; + return NULL; m->items[(unsigned int)m->numitems] = mi; - mi->handler = NULL; // No handler + mi->handler = NULL; // No handler // Allocate space to store stuff mi->item = (char *)malloc(MENULEN + 1); @@ -1241,74 +1128,74 @@ pt_menuitem add_item(const char *item, const char *status, t_action action, mi->data = (char *)malloc(ACTIONLEN + 1); if (item) { - if (strlen(item) > MENULEN) { - strcpy(mi->item, ITEMLONG); - } else { - strcpy(mi->item, item); - } - if (strlen(mi->item) > m->menuwidth) - m->menuwidth = strlen(mi->item); + if (strlen(item) > MENULEN) { + strcpy(mi->item, ITEMLONG); + } else { + strcpy(mi->item, item); + } + if (strlen(mi->item) > m->menuwidth) + m->menuwidth = strlen(mi->item); } else - strcpy(mi->item, EMPTYSTR); + strcpy(mi->item, EMPTYSTR); if (status) { - if (strlen(status) > STATLEN) { - strcpy(mi->status, STATUSLONG); - } else { - strcpy(mi->status, status); - } + if (strlen(status) > STATLEN) { + strcpy(mi->status, STATUSLONG); + } else { + strcpy(mi->status, status); + } } else - strcpy(mi->status, EMPTYSTR); + strcpy(mi->status, EMPTYSTR); mi->action = action; str = mi->item; mi->shortcut = 0; mi->helpid = 0xFFFF; - inhlite = 0; // We have not yet seen an ENABLEHLITE char + inhlite = 0; // We have not yet seen an ENABLEHLITE char // Find the first char in [A-Za-z0-9] after ENABLEHLITE and not arg to control char while (*str) { - if (*str == ENABLEHLITE) { - inhlite = 1; - } - if (*str == DISABLEHLITE) { - inhlite = 0; - } - if ((inhlite == 1) && - (((*str >= 'A') && (*str <= 'Z')) || - ((*str >= 'a') && (*str <= 'z')) || - ((*str >= '0') && (*str <= '9')))) { - mi->shortcut = *str; - break; - } - ++str; + if (*str == ENABLEHLITE) { + inhlite = 1; + } + if (*str == DISABLEHLITE) { + inhlite = 0; + } + if ((inhlite == 1) && + (((*str >= 'A') && (*str <= 'Z')) || + ((*str >= 'a') && (*str <= 'z')) || + ((*str >= '0') && (*str <= '9')))) { + mi->shortcut = *str; + break; + } + ++str; } - if ((mi->shortcut >= 'A') && (mi->shortcut <= 'Z')) // Make lower case - mi->shortcut = mi->shortcut - 'A' + 'a'; + if ((mi->shortcut >= 'A') && (mi->shortcut <= 'Z')) // Make lower case + mi->shortcut = mi->shortcut - 'A' + 'a'; if (data) { - if (strlen(data) > ACTIONLEN) { - strcpy(mi->data, ACTIONLONG); - } else { - strcpy(mi->data, data); - } + if (strlen(data) > ACTIONLEN) { + strcpy(mi->data, ACTIONLONG); + } else { + strcpy(mi->data, data); + } } else - strcpy(mi->data, EMPTYSTR); + strcpy(mi->data, EMPTYSTR); switch (action) { case OPT_SUBMENU: - mi->itemdata.submenunum = itemdata; - break; + mi->itemdata.submenunum = itemdata; + break; case OPT_CHECKBOX: - mi->itemdata.checked = itemdata; - break; + mi->itemdata.checked = itemdata; + break; case OPT_RADIOMENU: - mi->itemdata.radiomenunum = itemdata; - if (mi->data) - free(mi->data); - mi->data = NULL; // No selection made - break; - default: // to keep the compiler happy - break; + mi->itemdata.radiomenunum = itemdata; + if (mi->data) + free(mi->data); + mi->data = NULL; // No selection made + break; + default: // to keep the compiler happy + break; } mi->index = m->numitems++; mi->parindex = ms->nummenus - 1; @@ -1323,13 +1210,13 @@ void set_item_options(uchar shortcut, int helpid) m = (ms->menus[ms->nummenus - 1]); if (m->numitems <= 0) - return; + return; mi = m->items[(unsigned int)m->numitems - 1]; if (shortcut != 0xFF) - mi->shortcut = shortcut; + mi->shortcut = shortcut; if (helpid != 0xFFFF) - mi->helpid = helpid; + mi->helpid = helpid; } // Free internal datasutructures @@ -1344,34 +1231,32 @@ void append_line_helper(int menunum, char *line) pt_menuitem mi, ri; char *app; int ctr; - char dp; - dp = getdisppage(); menu = ms->menus[menunum]; for (ctr = 0; ctr < (int)menu->numitems; ctr++) { - mi = menu->items[ctr]; - app = NULL; //What to append - switch (mi->action) { - case OPT_CHECKBOX: - if (mi->itemdata.checked) - app = mi->data; - break; - case OPT_RADIOMENU: - if (mi->data) { // Some selection has been made - ri = (pt_menuitem) (mi->data); - app = ri->data; - } - break; - case OPT_SUBMENU: - append_line_helper(mi->itemdata.submenunum, line); - break; - default: - break; - } - if (app) { - strcat(line, " "); - strcat(line, app); - } + mi = menu->items[ctr]; + app = NULL; //What to append + switch (mi->action) { + case OPT_CHECKBOX: + if (mi->itemdata.checked) + app = mi->data; + break; + case OPT_RADIOMENU: + if (mi->data) { // Some selection has been made + ri = (pt_menuitem) (mi->data); + app = ri->data; + } + break; + case OPT_SUBMENU: + append_line_helper(mi->itemdata.submenunum, line); + break; + default: + break; + } + if (app) { + strcat(line, " "); + strcat(line, app); + } } } @@ -1383,6 +1268,6 @@ void gen_append_line(const char *menu_name, char *line) menunum = find_menu_num(menu_name); if (menunum < 0) - return; // No such menu + return; // No such menu append_line_helper(menunum, line); } diff --git a/com32/cmenu/libmenu/menu.h b/com32/cmenu/libmenu/menu.h index 68adf278..44acb122 100644 --- a/com32/cmenu/libmenu/menu.h +++ b/com32/cmenu/libmenu/menu.h @@ -22,8 +22,8 @@ #include "com32io.h" #include "tui.h" #include "syslnx.h" -#include "scancodes.h" #include <string.h> +#include <unistd.h> // TIMEOUT PARAMETERS /* If no key is pressed within TIMEOUTNUMSTEPS * TIMEOUTSTEPSIZE milliseconds @@ -59,8 +59,8 @@ #define STATUSATTR 0x74 #define STATUSHLITE 0x7B // Status highlight -#define FILLCHAR 177 -#define FILLATTR 0x01 +#define FILLCHAR ' ' +#define FILLATTR NORMALATTR #define SHADOWATTR 0x00 #define SPACECHAR ' ' @@ -72,9 +72,8 @@ #define NOHLITE 0 // The offset into attrib array for non-hilite #define HLITE 1 // The offset for Hlite attrib -#define MOREABOVE 24 // char to print when more menu items available above -#define MOREBELOW 25 // more items available below -#define SCROLLBOX 176 // Filled char to display +#define MOREABOVE '^' // char to print when more menu items available above +#define MOREBELOW 'v' // more items available below // Attributes of the menu system #define MAXMENUS 150 // Maximum number of menu's allowed @@ -99,11 +98,9 @@ #define DEBUGLINE 23 // debugging info goes here // Other Chars -#define SUBMENUCHAR 175 // This is >> symbol #define RADIOMENUCHAR '>' // > symbol for radio menu? -#define EXITMENUCHAR 174 // This is << symbol -#define CHECKED 251 // Check mark -#define UNCHECKED 250 // Light bullet +#define CHECKED '\140' // Check mark +#define UNCHECKED '\146' // Light bullet #define RADIOSEL '.' // Current Radio Selection #define RADIOUNSEL ' ' // Radio option not selected @@ -214,11 +211,10 @@ typedef struct s_menusystem { uchar shadowattr; uchar statline; uchar menupage; - uchar maxrow, minrow, numrows; // Number of rows in the window - uchar maxcol, mincol, numcols; // Number of columns in the window + int maxrow, minrow, numrows; // Number of rows in the window + int maxcol, mincol, numcols; // Number of columns in the window // Menu box look - boxtype menubt; // What type of boxes should be drawn char box_horiz, box_ltrt, box_rtlt; // Some chars of the box, for redrawing portions of the box } t_menusystem; @@ -243,7 +239,6 @@ void set_title_info(uchar tfillchar, uchar titleattr); void set_misc_info(uchar fillchar, uchar fillattr, uchar spacechar, uchar shadowattr); -void set_box_type(boxtype bt); void set_window_size(uchar top, uchar left, uchar bot, uchar right); // Set the window which menusystem should use diff --git a/com32/cmenu/libmenu/scancodes.h b/com32/cmenu/libmenu/scancodes.h deleted file mode 100644 index b70f6c67..00000000 --- a/com32/cmenu/libmenu/scancodes.h +++ /dev/null @@ -1,86 +0,0 @@ -/* -*- c -*- ------------------------------------------------------------- * - * - * Copyright 2004-2005 Murali Krishnan Ganapathy - 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. - * - * ----------------------------------------------------------------------- */ - -#ifndef __SCANCODES_H__ -#define __SCANCODES_H__ - -// Scancodes of some keys -#define ESCAPE 1 -#define ENTERA 28 -#define ENTERB 224 - -#define HOMEKEY 71 -#define UPARROW 72 -#define PAGEUP 73 -#define LTARROW 75 -#define RTARROW 77 -#define ENDKEY 79 -#define DNARROW 80 -#define PAGEDN 81 -#define INSERT 82 -#define DELETE 83 -#define SPACEKEY 57 // Scan code for SPACE - -#define CTRLLT 0x73 -#define CTRLRT 0x74 - -#define F1 0x3B -#define F2 0x3C -#define F3 0x3D -#define F4 0x3E -#define F5 0x3F -#define F6 0x40 -#define F7 0x41 -#define F8 0x42 -#define F9 0x43 -#define F10 0x44 -#define F11 0x85 -#define F12 0x86 - -#define CTRLF1 0x5E -#define CTRLF2 0x5F -#define CTRLF3 0x60 -#define CTRLF4 0x61 -#define CTRLF5 0x62 -#define CTRLF6 0x63 -#define CTRLF7 0x64 -#define CTRLF8 0x65 -#define CTRLF9 0x66 -#define CTRLF10 0x67 -#define CTRLF11 0x89 -#define CTRLF12 0x8A - -#define ALTF1 0x68 -#define ALTF2 0x69 -#define ALTF3 0x6A -#define ALTF4 0x6B -#define ALTF5 0x6C -#define ALTF6 0x6D -#define ALTF7 0x6E -#define ALTF8 0x6F -#define ALTF9 0x70 -#define ALTF10 0x71 -#define ALTF11 0x8B -#define ALTF12 0x8C - -/* Bits representing ShiftFlags, See Int16/Function 2 or Mem[0x417] to get this info */ - -#define INSERT_ON (1<<7) -#define CAPSLOCK_ON (1<<6) -#define NUMLOCK_ON (1<<5) -#define SCRLLOCK_ON (1<<4) -#define ALT_PRESSED (1<<3) -#define CTRL_PRESSED (1<<2) -// actually 1<<1 is Left Shift, 1<<0 is right shift -#define SHIFT_PRESSED (1<<1 | 1 <<0) - -#endif diff --git a/com32/cmenu/libmenu/tui.c b/com32/cmenu/libmenu/tui.c index 81e40793..dd69277a 100644 --- a/com32/cmenu/libmenu/tui.c +++ b/com32/cmenu/libmenu/tui.c @@ -14,12 +14,12 @@ #include <string.h> #include <com32.h> #include <stdlib.h> +#include "com32io.h" com32sys_t inreg, outreg; // Global register sets for use char bkspstr[] = " \b$"; char eolstr[] = "\n$"; -#define GETSTRATTR 0x07 // Reads a line of input from stdin. Replace CR with NUL byte // password <> 0 implies not echoed on screen @@ -29,18 +29,16 @@ char eolstr[] = "\n$"; void getuserinput(char *stra, unsigned int size, unsigned int password, unsigned int showoldvalue) { - unsigned char c, scan; + unsigned int c; char *p, *q; // p = current char of string, q = tmp char *last; // The current last char of string char *str; // pointer to string which is going to be allocated - char page; char row, col; char start, end; // Cursor shape char fudge; // How many chars should be removed from output char insmode; // Are we in insert or overwrite - page = getdisppage(); - getpos(&row, &col, page); // Get current position + getpos(&row, &col, 0); // Get current position getcursorshape(&start, &end); insmode = 1; @@ -67,14 +65,14 @@ void getuserinput(char *stra, unsigned int size, unsigned int password, // col is the corresponding column on the screen if (password == 0) // Not a password, print initial value { - gotoxy(row, col, page); + gotoxy(row, col); csprint(str, GETSTRATTR); } while (1) { // Do forever - c = inputc(&scan); - if (c == '\r') + c = get_key(stdin, 0); + if (c == KEY_ENTER) break; // User hit Enter getout of loop - if (scan == ESCAPE) // User hit escape getout and nullify string + if (c == KEY_ESC) // User hit escape getout and nullify string { *str = 0; break; @@ -83,18 +81,18 @@ void getuserinput(char *stra, unsigned int size, unsigned int password, // if scan code is regognized do something // else if char code is recognized do something // else ignore - switch (scan) { - case HOMEKEY: + switch (c) { + case KEY_HOME: p = str; break; - case ENDKEY: + case KEY_END: p = last; break; - case LTARROW: + case KEY_LEFT: if (p > str) p--; break; - case CTRLLT: + case KEY_CTRL(KEY_LEFT): if (p == str) break; if (*p == ' ') @@ -110,11 +108,11 @@ void getuserinput(char *stra, unsigned int size, unsigned int password, while ((p > str) && ((*p == ' ') || (*(p - 1) != ' '))) p--; break; - case RTARROW: + case KEY_RIGHT: if (p < last) p++; break; - case CTRLRT: + case KEY_CTRL(KEY_RIGHT): if (*p == 0) break; // At end of string if (*p != ' ') @@ -125,7 +123,8 @@ void getuserinput(char *stra, unsigned int size, unsigned int password, if (*p == ' ') p++; break; - case DELETE: + case KEY_DEL: + case KEY_DELETE: q = p; while (*(q + 1)) { *q = *(q + 1); @@ -135,17 +134,14 @@ void getuserinput(char *stra, unsigned int size, unsigned int password, last--; fudge = 1; break; - case INSERT: + case KEY_INSERT: insmode = 1 - insmode; // Switch mode if (insmode == 0) setcursorshape(1, 7); // Block cursor else setcursorshape(6, 7); // Normal cursor break; - - default: // Unrecognized scan code, look at the ascii value - switch (c) { - case '\b': // Move over by one + case KEY_BACKSPACE: // Move over by one q = p; while (q <= last) { *(q - 1) = *q; @@ -157,7 +153,7 @@ void getuserinput(char *stra, unsigned int size, unsigned int password, p--; fudge = 1; break; - case '\x15': /* Ctrl-U: kill input */ + case KEY_CTRL('U'): /* Ctrl-U: kill input */ fudge = last - str; while (p > str) *p-- = 0; @@ -165,7 +161,7 @@ void getuserinput(char *stra, unsigned int size, unsigned int password, *p = 0; last = str; break; - default: // Handle insert and overwrite mode + default: // Handle insert and overwrite mode if ((c >= ' ') && (c < 128) && ((unsigned int)(p - str) < size - 1)) { if (insmode == 0) { // Overwrite mode @@ -189,190 +185,59 @@ void getuserinput(char *stra, unsigned int size, unsigned int password, } } else beep(); - } break; } // Now the string has been modified, print it if (password == 0) { - gotoxy(row, col, page); + gotoxy(row, col); csprint(str, GETSTRATTR); if (fudge > 0) - cprint(' ', GETSTRATTR, fudge, page); - gotoxy(row, col + (p - str), page); + cprint(' ', GETSTRATTR, fudge); + gotoxy(row, col + (p - str)); } - } + } /* while */ *p = '\0'; if (password == 0) csprint("\r\n", GETSTRATTR); setcursorshape(start, end); // Block cursor // If user hit ESCAPE so return without any changes - if (scan != ESCAPE) + if (c != KEY_ESC) strcpy(stra, str); free(str); } -/* Print a C string (NUL-terminated) */ -void cswprint(const char *str, char attr, char left) -{ - char page = getdisppage(); - char newattr = 0, cha, chb; - char row, col; - char nr, nc; - - nr = getnumrows(); - nc = getnumcols(); - getpos(&row, &col, page); - while (*str) { - switch (*str) { - case '\b': - --col; - break; - case '\n': - ++row; - col = left; - break; - case '\r': - //col=left; - break; - case BELL: // Bell Char - beep(); - break; - case CHRELATTR: // change attribute (relatively) - case CHABSATTR: // change attribute (absolute) - cha = *(str + 1); - chb = *(str + 2); - if ((((cha >= '0') && (cha <= '9')) || ((cha >= 'A') && (cha <= 'F'))) && (((chb >= '0') && (chb <= '9')) || ((chb >= 'A') && (chb <= 'F')))) // Next two chars are legal - { - if ((cha >= 'A') && (cha <= 'F')) - cha = cha - 'A' + 10; - else - cha = cha - '0'; - if ((chb >= 'A') && (chb <= 'F')) - chb = chb - 'A' + 10; - else - chb = chb - '0'; - newattr = (cha << 4) + chb; - attr = (*str == CHABSATTR ? newattr : attr ^ newattr); - str += 2; // Will be incremented again later - } - break; - default: - putch(*str, attr, page); - ++col; - } - if (col >= nc) { - ++row; - col = left; - } - if (row > nr) { - scrollup(); - row = nr; - } - gotoxy(row, col, page); - str++; - } -} - -void clearwindow(char top, char left, char bot, char right, char page, - char fillchar, char fillattr) -{ - char x; - for (x = top; x < bot + 1; x++) { - gotoxy(x, left, page); - cprint(fillchar, fillattr, right - left + 1, page); - } -} - -void cls(void) -{ - unsigned char dp = getdisppage(); - gotoxy(0, 0, dp); - cprint(' ', GETSTRATTR, (1 + getnumrows()) * getnumcols(), dp); -} - //////////////////////////////Box Stuff -// This order of numbers must match -// the values of BOX_TOPLEFT,... in the header file - -unsigned char SINSIN_CHARS[] = { 218, 192, 191, 217, //Corners - 196, 179, // Horiz and Vertical - 195, 180, 194, 193, 197 -}; // Connectors & Middle - -unsigned char DBLDBL_CHARS[] = { 201, 200, 187, 188, // Corners - 205, 186, // Horiz and Vertical - 199, 182, 203, 202, 206 -}; // Connectors & Middle - -unsigned char SINDBL_CHARS[] = { 214, 211, 183, 189, // Corners - 196, 186, // Horiz & Vert - 199, 182, 210, 208, 215 -}; // Connectors & Middle - -unsigned char DBLSIN_CHARS[] = { 213, 212, 184, 190, // Corners - 205, 179, // Horiz & Vert - 198, 181, 209, 207, 216 -}; // Connectors & Middle - -unsigned char *getboxchars(boxtype bt) -{ - switch (bt) { - case BOX_SINSIN: - return SINSIN_CHARS; - break; - case BOX_DBLDBL: - return DBLDBL_CHARS; - break; - case BOX_SINDBL: - return SINDBL_CHARS; - break; - case BOX_DBLSIN: - return DBLSIN_CHARS; - break; - default: - return SINSIN_CHARS; - break; - } - return SINSIN_CHARS; -} - // Draw box and lines -void drawbox(char top, char left, char bot, char right, - char page, char attr, boxtype bt) +void drawbox(const char top, const char left, const char bot, + const char right, const char attr) { - unsigned char *box_chars; // pointer to array of box chars unsigned char x; - - box_chars = getboxchars(bt); + putchar(SO); // Top border - gotoxy(top, left, page); - cprint(box_chars[BOX_TOPLEFT], attr, 1, page); - gotoxy(top, left + 1, page); - cprint(box_chars[BOX_TOP], attr, right - left, page); - gotoxy(top, right, page); - cprint(box_chars[BOX_TOPRIGHT], attr, 1, page); + gotoxy(top, left); + putch(TOP_LEFT_CORNER_BORDER, attr); + cprint(TOP_BORDER, attr, right - left - 1); + putch(TOP_RIGHT_CORNER_BORDER, attr); // Bottom border - gotoxy(bot, left, page); - cprint(box_chars[BOX_BOTLEFT], attr, 1, page); - gotoxy(bot, left + 1, page); - cprint(box_chars[BOX_BOT], attr, right - left, page); - gotoxy(bot, right, page); - cprint(box_chars[BOX_BOTRIGHT], attr, 1, page); + gotoxy(bot, left); + putch(BOTTOM_LEFT_CORNER_BORDER, attr); + cprint(BOTTOM_BORDER, attr, right - left - 1); + putch(BOTTOM_RIGHT_CORNER_BORDER, attr); // Left & right borders for (x = top + 1; x < bot; x++) { - gotoxy(x, left, page); - cprint(box_chars[BOX_LEFT], attr, 1, page); - gotoxy(x, right, page); - cprint(box_chars[BOX_RIGHT], attr, 1, page); + gotoxy(x, left); + putch(LEFT_BORDER, attr); + gotoxy(x, right); + putch(RIGHT_BORDER, attr); } + putchar(SI); } -void drawhorizline(char top, char left, char right, char page, char attr, - boxtype bt, char dumb) +void drawhorizline(const char top, const char left, const char right, + const char attr, char dumb) { unsigned char start, end; - unsigned char *box_chars = getboxchars(bt); if (dumb == 0) { start = left + 1; end = right - 1; @@ -380,12 +245,14 @@ void drawhorizline(char top, char left, char right, char page, char attr, start = left; end = right; } - gotoxy(top, start, page); - cprint(box_chars[BOX_HORIZ], attr, end - start + 1, page); + gotoxy(top, start); + putchar(SO); + cprint(MIDDLE_BORDER, attr, end - start + 1); if (dumb == 0) { - gotoxy(top, left, page); - cprint(box_chars[BOX_LTRT], attr, 1, page); - gotoxy(top, right, page); - cprint(box_chars[BOX_RTLT], attr, 1, page); + gotoxy(top, left); + putch(MIDDLE_BORDER, attr); + gotoxy(top, right); + putch(MIDDLE_BORDER, attr); } + putchar(SI); } diff --git a/com32/cmenu/libmenu/tui.h b/com32/cmenu/libmenu/tui.h index 4df15327..ed554878 100644 --- a/com32/cmenu/libmenu/tui.h +++ b/com32/cmenu/libmenu/tui.h @@ -14,23 +14,32 @@ #define __TUI_H__ #include <com32.h> +#include <getkey.h> +#include <consoles.h> #include "syslnx.h" #include "com32io.h" -#include "scancodes.h" #ifndef NULL #define NULL ((void *)0) #endif -#define BELL 0x07 -// CHRELATTR = ^N, CHABSATTR = ^O -#define CHABSATTR 15 -#define CHRELATTR 14 - -void clearwindow(char top, char left, char bot, char right, - char page, char fillchar, char fillattr); +#define SO '\016' +#define SI '\017' + +#define TOP_LEFT_CORNER_BORDER '\154' +#define TOP_BORDER '\161' +#define TOP_RIGHT_CORNER_BORDER '\153' +#define BOTTOM_LEFT_CORNER_BORDER '\155' +#define BOTTOM_BORDER '\161' +#define BOTTOM_RIGHT_CORNER_BORDER '\152' +#define LEFT_BORDER '\170' +#define RIGHT_BORDER '\170' +#define LEFT_MIDDLE_BORDER '\164' +#define MIDDLE_BORDER '\161' +#define RIGHT_MIDDLE_BORDER '\165' -void cls(void); /* Clears the entire current screen page */ +#define BELL 0x07 +#define GETSTRATTR 0x07 // Generic user input, // password = 0 iff chars echoed on screen @@ -53,35 +62,14 @@ static inline void getpwd(char *str, unsigned int size) getuserinput(str, size, 1, 0); } -// Box drawing Chars offsets into array -#define BOX_TOPLEFT 0x0 -#define BOX_BOTLEFT 0x1 -#define BOX_TOPRIGHT 0x2 -#define BOX_BOTRIGHT 0x3 -#define BOX_TOP 0x4 // TOP = BOT = HORIZ -#define BOX_BOT 0x4 -#define BOX_HORIZ 0x4 -#define BOX_LEFT 0x5 -#define BOX_RIGHT 0x5 -#define BOX_VERT 0x5 // LEFT=RIGHT=VERT -#define BOX_LTRT 0x6 -#define BOX_RTLT 0x7 -#define BOX_TOPBOT 0x8 -#define BOX_BOTTOP 0x9 -#define BOX_MIDDLE 0xA - -typedef enum { BOX_SINSIN, BOX_DBLDBL, BOX_SINDBL, BOX_DBLSIN } boxtype; - -unsigned char *getboxchars(boxtype bt); - -void drawbox(char top, char left, char bot, char right, - char page, char attr, boxtype bt); +void drawbox(const char, const char, const char, const char, + const char); // Draw a horizontal line // dumb == 1, means just draw the line // dumb == 0 means check the first and last positions and depending on what is // currently on the screen make it a LTRT and/or RTLT appropriately. -void drawhorizline(char top, char left, char right, char page, char attr, - boxtype bt, char dumb); +void drawhorizline(const char, const char, const char, const char, + const char dumb); #endif diff --git a/com32/gplinclude/cpuid.h b/com32/gplinclude/cpuid.h index 95d66e99..f85e6ab3 100644 --- a/com32/gplinclude/cpuid.h +++ b/com32/gplinclude/cpuid.h @@ -65,6 +65,8 @@ typedef struct { bool nowext; /* AMD 3DNow! extensions */ bool now; /* 3DNow! */ bool smp; /* A smp configuration has been found */ + bool vmx; /* Hardware virtualization */ + bool svm; /* Secure virtual machine */ } s_cpu_flags; typedef struct { @@ -159,7 +161,6 @@ struct cpuinfo_x86 { unsigned char x86_clflush_size; } __attribute__ ((__packed__)); -#endif struct cpu_model_info { int vendor; @@ -169,10 +170,10 @@ struct cpu_model_info { /* attempt to consolidate cpu attributes */ struct cpu_dev { - char *c_vendor; + const char *c_vendor; /* some have two possibilities for cpuid string */ - char *c_ident[2]; + const char *c_ident[2]; struct cpu_model_info c_models[4]; @@ -208,3 +209,4 @@ struct intel_mp_floating { extern void get_cpu_vendor(struct cpuinfo_x86 *c); extern void detect_cpu(s_cpu * cpu); +#endif diff --git a/com32/gplinclude/disk/bootloaders.h b/com32/gplinclude/disk/bootloaders.h new file mode 100644 index 00000000..6aec9b3d --- /dev/null +++ b/com32/gplinclude/disk/bootloaders.h @@ -0,0 +1,18 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#ifndef __BOOTLOADERS_H_ +#define __BOOTLOADERS_H_ + +#include <stdint.h> +#include <disk/geom.h> +#include <disk/partition.h> + +int get_bootloader_string(const struct driveinfo *, const struct part_entry *, char*, const int); +#endif /* __BOOTLOADERS_H_ */ diff --git a/com32/gplinclude/disk/common.h b/com32/gplinclude/disk/common.h index c6df2f4e..627e94ec 100644 --- a/com32/gplinclude/disk/common.h +++ b/com32/gplinclude/disk/common.h @@ -17,10 +17,10 @@ #include <stdint.h> -#define SECTOR 512 /* bytes/sector */ +/* For PAGE_SIZE */ +#include <cpuid.h> -#undef PAGE_SIZE -#define PAGE_SIZE (1<<12) +#define SECTOR 512 /* bytes/sector */ struct ebios_dapa { uint16_t len; diff --git a/com32/gplinclude/disk/error.h b/com32/gplinclude/disk/error.h index f9e319c4..27683572 100644 --- a/com32/gplinclude/disk/error.h +++ b/com32/gplinclude/disk/error.h @@ -9,5 +9,5 @@ #ifndef _ERROR_H_ #define _ERROR_H_ -void get_error(void*); -#endif /* _UTIL_H_ */ +void get_error(const char*); +#endif /* _ERROR_H_ */ diff --git a/com32/gplinclude/disk/mbrs.h b/com32/gplinclude/disk/mbrs.h new file mode 100644 index 00000000..ad104ff7 --- /dev/null +++ b/com32/gplinclude/disk/mbrs.h @@ -0,0 +1,18 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#ifndef __MBRS_H_ +#define __MBRS_H_ + +#include <stdint.h> +#include <disk/geom.h> + +void get_mbr_string(const uint32_t, void *, const int); +uint32_t get_mbr_id(const struct driveinfo *); +#endif /* __MBRS_H_ */ diff --git a/com32/gplinclude/disk/util.h b/com32/gplinclude/disk/util.h index df2eadda..20a9428f 100644 --- a/com32/gplinclude/disk/util.h +++ b/com32/gplinclude/disk/util.h @@ -18,5 +18,4 @@ #include <com32.h> int int13_retry(const com32sys_t *inreg, com32sys_t *outreg); -void get_error(const int, char**); #endif /* _UTIL_H_ */ diff --git a/com32/gplinclude/dmi/dmi.h b/com32/gplinclude/dmi/dmi.h index def0a8ea..72bc8dc4 100644 --- a/com32/gplinclude/dmi/dmi.h +++ b/com32/gplinclude/dmi/dmi.h @@ -13,6 +13,7 @@ #ifndef DMI_H #define DMI_H #include <inttypes.h> +#define DMI_BUFFER_SIZE 16 #define MAX_DMI_MEMORY_ITEMS 32 #define MAX_DMI_CACHE_ITEMS 32 #define OEM_STRINGS_SIZE 512 @@ -86,7 +87,7 @@ typedef struct { void to_dmi_header(struct dmi_header *h, uint8_t * data); void dmi_bios_runtime_size(uint32_t code, s_dmi * dmi); const char *dmi_string(struct dmi_header *dm, uint8_t s); -int dmi_checksum(uint8_t * buf); +int dmi_checksum(uint8_t * buf, int len); void parse_dmitable(s_dmi * dmi); void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi * dmi); int dmi_iterate(s_dmi * dmi); diff --git a/com32/gpllib/cpuid.c b/com32/gpllib/cpuid.c index 6d464c7e..fb69cef6 100644 --- a/com32/gpllib/cpuid.c +++ b/com32/gpllib/cpuid.c @@ -295,6 +295,8 @@ void set_cpu_flags(struct cpuinfo_x86 *c, s_cpu * cpu) cpu->flags.nowext = cpu_has(c, X86_FEATURE_3DNOWEXT); cpu->flags.now = cpu_has(c, X86_FEATURE_3DNOW); cpu->flags.smp = find_smp_config(); + cpu->flags.vmx = cpu_has(c, X86_FEATURE_VMX); + cpu->flags.svm = cpu_has(c, X86_FEATURE_SVM); } void set_generic_info(struct cpuinfo_x86 *c, s_cpu * cpu) diff --git a/com32/gpllib/disk/ata.c b/com32/gpllib/disk/ata.c index d74dda8f..8694470d 100644 --- a/com32/gpllib/disk/ata.c +++ b/com32/gpllib/disk/ata.c @@ -1,4 +1,5 @@ #include <inttypes.h> +#include <string.h> /** * ata_id_string - Convert IDENTIFY DEVICE page into string diff --git a/com32/gpllib/disk/bootloaders.c b/com32/gpllib/disk/bootloaders.c new file mode 100644 index 00000000..4b3962ae --- /dev/null +++ b/com32/gpllib/disk/bootloaders.c @@ -0,0 +1,46 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#include <disk/bootloaders.h> +#include <disk/common.h> +#include <disk/geom.h> +#include <disk/read.h> +#include <stdlib.h> +#include <string.h> + +/** + * get_bootloader_string - return a string describing the boot code in a + * bootsector + * @d: driveinfo struct describing the drive + * @p: partition to scan (usually the active one) + * @buffer: pre-allocated buffer + * @buffer_size: @buffer size + **/ +int get_bootloader_string(const struct driveinfo *d, const struct part_entry *p, + char* buffer, const int buffer_size) +{ + char boot_sector[SECTOR * sizeof(char)]; + + if (read_sectors(d, &boot_sector, p->start_lba, 1) == -1) + return -1; + else { + if (!strncmp(boot_sector + 3, "SYSLINUX", 8)) + strncpy(buffer, "SYSLINUX", buffer_size - 1); + else if (!strncmp(boot_sector + 3, "EXTLINUX", 8)) + strncpy(buffer, "EXTLINUX", buffer_size - 1); + else if (!strncmp(boot_sector + 3, "MSWIN4.1", 8)) + strncpy(buffer, "MSWIN4.1", buffer_size - 1); + else + return -1; + /* Add more... */ + + buffer[buffer_size - 1] = '\0'; + return 0; + } +} diff --git a/com32/gpllib/disk/error.c b/com32/gpllib/disk/error.c index 1853092b..b3fb6ce1 100644 --- a/com32/gpllib/disk/error.c +++ b/com32/gpllib/disk/error.c @@ -13,7 +13,7 @@ /** * get_error - decode a disk error status - * @buffer_ptr: Preallocated buffer + * @s: Preallocated buffer * * Fill @buffer_ptr with the last errno_disk **/ diff --git a/com32/gpllib/disk/mbrs.c b/com32/gpllib/disk/mbrs.c new file mode 100644 index 00000000..0abf087a --- /dev/null +++ b/com32/gpllib/disk/mbrs.c @@ -0,0 +1,91 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#include <disk/common.h> +#include <disk/geom.h> +#include <disk/read.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +/** + * get_mbr_string - return a string describing the boot code + * @label: first four bytes of the MBR + * @buffer: pre-allocated buffer + * @buffer_size: @buffer size + **/ +void get_mbr_string(const uint32_t label, char* buffer, const int buffer_size) +{ + /* 2 bytes are usually enough to identify the MBR */ + uint16_t s_label = label >> 16; + + switch (s_label) { + case 0x0000: + case 0xfa33: + case 0xfab8: + case 0xfabe: + strncpy(buffer, "No bootloader", buffer_size - 1); break; + case 0x0ebe: strncpy(buffer, "ThinkPad", buffer_size - 1); break; + case 0x31c0: strncpy(buffer, "Acer 3", buffer_size - 1); break; + case 0x33c0: strncpy(buffer, "Windows", buffer_size - 1); break; + case 0x33ff: strncpy(buffer, "HP/Gateway", buffer_size - 1); break; + case 0xb800: strncpy(buffer, "Plop", buffer_size - 1); break; + case 0xea1e: strncpy(buffer, "Truecrypt Boot Loader", buffer_size - 1); break; + case 0xeb04: strncpy(buffer, "Solaris", buffer_size - 1); break; + case 0xeb48: strncpy(buffer, "Grub", buffer_size - 1); break; + case 0xeb63: + case 0xeb4c: strncpy(buffer, "Grub2", buffer_size - 1); break; + case 0xeb5e: + /* We need more than 2 bytes */ + if (((label >> 8) & 0xff) == 0x00) + strncpy(buffer, "fbinst", buffer_size - 1); + else if (((label >> 8) & 0xff) == 0x80) + strncpy(buffer, "Grub4Dos", buffer_size - 1); + else + strncpy(buffer, "Unknown mbr", buffer_size - 1); break; + break; + case 0xfa31: + /* We need more than 2 bytes */ + if (((label >> 8) & 0xff) == 0xc9) + strncpy(buffer, "Master Boot LoaDeR", buffer_size - 1); + else if (((label >> 8) & 0xff) == 0xc0) + strncpy(buffer, "Syslinux", buffer_size - 1); + else + strncpy(buffer, "Unknown mbr", buffer_size - 1); break; + break; + case 0xfaeb: strncpy(buffer, "Lilo", buffer_size - 1); break; + case 0xfc31: strncpy(buffer, "Testdisk", buffer_size - 1); break; + case 0xfc33: strncpy(buffer, "Gag", buffer_size - 1); break; + case 0xfceb: strncpy(buffer, "BootIT NG", buffer_size - 1); break; + default: strncpy(buffer, "Unknown mbr", buffer_size - 1); break; + } + + buffer[buffer_size - 1] = '\0'; +} + +/** + * get_mbr_id - return the first four bytes of the MBR + * @d: driveinfo struct describing the drive + **/ +uint32_t get_mbr_id(const struct driveinfo *d) +{ + char mbr[SECTOR * sizeof(char)]; + + if (read_mbr(d->disk, &mbr) == -1) + return -1; + else { + uint32_t mbr_id; + /* Reverse the opcodes */ + mbr_id = (*(uint8_t *) (mbr + 3)); + mbr_id += (*(uint8_t *) (mbr + 2) << 8); + mbr_id += (*(uint8_t *) (mbr + 1) << 16); + mbr_id += (*(uint8_t *) mbr) << 24; + return mbr_id; + } +} diff --git a/com32/gpllib/dmi/dmi.c b/com32/gpllib/dmi/dmi.c index ebf3c527..9f770376 100644 --- a/com32/gpllib/dmi/dmi.c +++ b/com32/gpllib/dmi/dmi.c @@ -406,7 +406,6 @@ static void dmi_processor_id(uint8_t type, uint8_t * p, const char *version, for (i = 0; i <= 31; i++) if (cpu_flags_strings[i] != NULL && edx & (1 << i)) ((bool *) (&dmi->processor.cpu_flags))[i] = true; - //printf("%s\t%s\n", prefix, flags[i]); } } @@ -445,20 +444,67 @@ const char *dmi_string(struct dmi_header *dm, uint8_t s) return bp; } -int dmi_checksum(uint8_t * buf) +int checksum(uint8_t * buf, int len) { uint8_t sum = 0; int a; - for (a = 0; a < 15; a++) + for (a = 0; a < len; a++) sum += buf[a]; return (sum == 0); } +static int smbios_decode(s_dmi *dmi, uint8_t *buf) +{ + + dmi->dmitable.ver = (buf[0x06] << 8) + buf[0x07]; + /* Some BIOS report weird SMBIOS version, fix that up */ + switch (dmi->dmitable.ver) { + case 0x021F: + dmi->dmitable.ver = 0x0203; + break; + case 0x0233: + dmi->dmitable.ver = 0x0206; + break; + } + dmi->dmitable.major_version=dmi->dmitable.ver >> 8; + dmi->dmitable.minor_version=dmi->dmitable.ver & 0xFF; + + return DMI_TABLE_PRESENT; +} + + +static int legacy_decode(s_dmi *dmi, uint8_t *buf) +{ + dmi->dmitable.num = buf[13] << 8 | buf[12]; + dmi->dmitable.len = buf[7] << 8 | buf[6]; + dmi->dmitable.base = + buf[11] << 24 | buf[10] << 16 | buf[9] << 8 | buf[8]; + + /* Version already found? */ + if (dmi->dmitable.ver>0) return DMI_TABLE_PRESENT; + + dmi->dmitable.ver = (buf[0x06] << 8) + buf[0x07]; + + /* + * DMI version 0.0 means that the real version is taken from + * the SMBIOS version, which we don't know at this point. + */ + if (buf[14] != 0) { + dmi->dmitable.major_version = buf[14] >> 4; + dmi->dmitable.minor_version = buf[14] & 0x0F; + } else { + dmi->dmitable.major_version = 0; + dmi->dmitable.minor_version = 0; + } + return DMI_TABLE_PRESENT; +} + + int dmi_iterate(s_dmi * dmi) { - uint8_t buf[16]; - char *p, *q; + uint8_t *p, *q; + int found = 0; /* Cleaning structures */ memset(&dmi->base_board, 0, sizeof(s_base_board)); @@ -480,34 +526,32 @@ int dmi_iterate(s_dmi * dmi) dmi->processor.filled = false; dmi->system.filled = false; - p = (char *)0xF0000; /* The start address to look at the dmi table */ + p = (uint8_t *)0xF0000; /* The start address to look at the dmi table */ + /* The anchor-string is 16-bytes aligned */ for (q = p; q < p + 0x10000; q += 16) { - memcpy(buf, q, 15); - if (memcmp(buf, "_DMI_", 5) == 0 && dmi_checksum(buf)) { - dmi->dmitable.num = buf[13] << 8 | buf[12]; - dmi->dmitable.len = buf[7] << 8 | buf[6]; - dmi->dmitable.base = - buf[11] << 24 | buf[10] << 16 | buf[9] << 8 | buf[8]; - dmi->dmitable.ver = (buf[0x06] << 8) + buf[0x07]; - - /* - * DMI version 0.0 means that the real version is taken from - * the SMBIOS version, which we don't know at this point. - */ - if (buf[14] != 0) { - dmi->dmitable.major_version = buf[14] >> 4; - dmi->dmitable.minor_version = buf[14] & 0x0F; - } else { - dmi->dmitable.major_version = 0; - dmi->dmitable.minor_version = 0; - - } -/* printf("DMI present (version %d.%d)\n", dmitable.major_version,dmitable.minor_version); - printf("%d structures occupying %d bytes.\n",dmitable.num, dmitable.len); - printf("DMI table at 0x%08X.\n",dmitable.base);*/ - return DMI_TABLE_PRESENT; - } + /* To validate the presence of SMBIOS: + * + the overall checksum must be correct + * + the intermediate anchor-string must be _DMI_ + * + the intermediate checksum must be correct + */ + if (memcmp(q, "_SM_", 4) == 0 && + checksum(q, q[0x05]) && + memcmp(q + 0x10, "_DMI_", 5)==0 && + checksum(q + 0x10, 0x0F)) { + /* Do not return, legacy_decode will need to be called + * on the intermediate structure to get the table length + * and address + */ + smbios_decode(dmi, q); + } else if (memcmp(q, "_DMI_", 5) == 0 && checksum(q, 0x0F)) { + found = 1; + legacy_decode(dmi, q); + } } + + if (found) + return DMI_TABLE_PRESENT; + dmi->dmitable.base = 0; dmi->dmitable.num = 0; dmi->dmitable.ver = 0; @@ -524,7 +568,6 @@ void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi * dmi) */ switch (h->type) { case 0: /* 3.3.1 BIOS Information */ -// printf("BIOS Information\n"); if (h->length < 0x12) break; dmi->bios.filled = true; @@ -552,7 +595,6 @@ void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi * dmi) data[0x16], data[0x17]); break; case 1: /* 3.3.2 System Information */ -// printf("System Information\n"); if (h->length < 0x08) break; dmi->system.filled = true; @@ -571,7 +613,6 @@ void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi * dmi) break; case 2: /* 3.3.3 Base Board Information */ -// printf("Base Board Information\n"); if (h->length < 0x08) break; dmi->base_board.filled = true; @@ -589,7 +630,6 @@ void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi * dmi) break; break; case 3: /* 3.3.4 Chassis Information */ -// printf("Chassis Information\n"); if(h->length<0x09) break; dmi->chassis.filled=true; strcpy(dmi->chassis.manufacturer,dmi_string(h,data[0x04])); @@ -611,7 +651,6 @@ void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi * dmi) break; case 4: /* 3.3.5 Processor Information */ -// printf("Processor Information\n"); if(h->length<0x1A) break; dmi->processor.filled=true; strcpy(dmi->processor.socket_designation,dmi_string(h, data[0x04])); @@ -628,7 +667,7 @@ void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi * dmi) strcpy(dmi->processor.status,dmi_processor_status(data[0x18]&0x07)); else sprintf(dmi->processor.status,"Unpopulated"); - sprintf(dmi->processor.upgrade,dmi_processor_upgrade(data[0x19])); + strcpy(dmi->processor.upgrade,dmi_processor_upgrade(data[0x19])); if(h->length<0x20) break; dmi_processor_cache(WORD(data+0x1A), "L1", ver,dmi->processor.cache1); dmi_processor_cache(WORD(data+0x1C), "L2", ver,dmi->processor.cache2); @@ -843,7 +882,6 @@ void parse_dmitable(s_dmi * dmi) (unsigned int)h.length); break; } -// printf("Handle 0x%04X, DMI type %d, %d bytes\n", h.handle, h.type, h.length); /* loo for the next handle */ next = data + h.length; diff --git a/com32/gpllib/dmi/dmi_memory.c b/com32/gpllib/dmi/dmi_memory.c index 588e4ad6..5c747d69 100644 --- a/com32/gpllib/dmi/dmi_memory.c +++ b/com32/gpllib/dmi/dmi_memory.c @@ -242,9 +242,9 @@ void dmi_memory_module_size(uint8_t code, char* size) } if(code&0x80) - printf(size, "%s", "(Double-bank Connection)"); + sprintf(size, "%s", "(Double-bank Connection)"); else - printf(size, "%s", "(Single-bank Connection)"); + sprintf(size, "%s", "(Single-bank Connection)"); } void dmi_memory_module_error(uint8_t code, const char *prefix, char *error) @@ -253,10 +253,10 @@ void dmi_memory_module_error(uint8_t code, const char *prefix, char *error) sprintf(error, "%s", "See Event Log\n"); else { if((code&0x03)==0) - printf(error, "%s", "OK\n"); + sprintf(error, "%s", "OK\n"); if(code&(1<<0)) - printf(error, "%sUncorrectable Errors\n", prefix); + sprintf(error, "%sUncorrectable Errors\n", prefix); if(code&(1<<1)) - printf(error, "%sCorrectable Errors\n", prefix); + sprintf(error, "%sCorrectable Errors\n", prefix); } } diff --git a/com32/hdt/Makefile b/com32/hdt/Makefile index 8f8cae21..b3eb88dc 100644 --- a/com32/hdt/Makefile +++ b/com32/hdt/Makefile @@ -27,11 +27,55 @@ TESTFILES = OBJS = $(patsubst %.c,%.o,$(wildcard *.c)) +KERNEL_VERSION ?= $(shell uname -r) +MODULES_ALIAS_FILE ?= /lib/modules/$(KERNEL_VERSION)/modules.alias +MODULES_PCIMAP_FILE ?= /lib/modules/$(KERNEL_VERSION)/modules.pcimap +ISO_DIR ?= iso +ISOLINUX_DIR ?= isolinux +FLOPPY_DIR ?= floppy +PCI_IDS_FILE ?= $(PWD)/$(FLOPPY_DIR)/pci.ids +REBOOT_COM32 ?= $(com32)/modules/reboot.c32 + all: $(MODULES) $(TESTFILES) hdt.elf : $(OBJS) $(LIBS) $(C_LIBS) $(LD) $(LDFLAGS) -o $@ $^ +hdt.img: hdt.c32 $(FLOPPY_DIR)/hdt.cfg $(FLOPPY_DIR)/mtools.conf $(topdir)/mtools/syslinux $(REBOOT_COM32) + rm -f hdt.img + MTOOLSRC=$(PWD)/$(FLOPPY_DIR)/mtools.conf $(MFORMAT) -v HDT -f 2880 -C a: + $(topdir)/mtools/syslinux hdt.img + -[ ! -f $(PCI_IDS_FILE) ] && cp /usr/share/hwdata/pci.ids $(PCI_IDS_FILE) + -[ ! -f $(PCI_IDS_FILE) ] && cp /usr/share/pci.ids $(PCI_IDS_FILE) + -[ -f $(MODULES_ALIAS_FILE) ] && MTOOLSRC=$(PWD)/$(FLOPPY_DIR)/mtools.conf $(MCOPY) $(MODULES_ALIAS_FILE) a: + -[ -f $(MODULES_PCIMAP_FILE) ] && MTOOLSRC=$(PWD)/$(FLOPPY_DIR)/mtools.conf $(MCOPY) $(MODULES_PCIMAP_FILE) a: + MTOOLSRC=$(PWD)/$(FLOPPY_DIR)/mtools.conf $(MCOPY) hdt.c32 a: + MTOOLSRC=$(PWD)/$(FLOPPY_DIR)/mtools.conf $(MCOPY) $(REBOOT_COM32) a: + @ [ -f $(PCI_IDS_FILE) ] && MTOOLSRC=$(PWD)/$(FLOPPY_DIR)/mtools.conf $(MCOPY) $(PCI_IDS_FILE) a: || printf "\nThe $(FLOPPY_DIR)/pci.ids file is missing and can be downloaded from http://pciids.sourceforge.net and put in\nthe ./com32/hdt/$(FLOPPY_DIR) directory of the extracted Syslinux source.\n\n" + MTOOLSRC=$(PWD)/$(FLOPPY_DIR)/mtools.conf $(MCOPY) $(FLOPPY_DIR)/hdt.cfg a:syslinux.cfg + +hdt.img.gz: hdt.img + rm -rf hdt.img.gz + $(GZIPPROG) -c hdt.img >hdt.img.gz + +hdt.iso: hdt.c32 $(topdir)/core/isolinux.bin $(FLOPPY_DIR)/hdt.cfg + rm -rf $(ISO_DIR) + rm -f hdt.iso + mkdir -p $(ISO_DIR)/$(ISOLINUX_DIR) + cp $(topdir)/core/isolinux.bin $(ISO_DIR)/$(ISOLINUX_DIR) + cp $(FLOPPY_DIR)/hdt.cfg $(ISO_DIR)/$(ISOLINUX_DIR)/isolinux.cfg + cp hdt.c32 $(ISO_DIR)/$(ISOLINUX_DIR) + cp $(REBOOT_COM32) $(ISO_DIR)/$(ISOLINUX_DIR) + -[ ! -f $(PCI_IDS_FILE) ] && cp /usr/share/hwdata/pci.ids $(PCI_IDS_FILE) + -[ ! -f $(PCI_IDS_FILE) ] && cp /usr/share/pci.ids $(PCI_IDS_FILE) + -[ -f $(MODULES_ALIAS_FILE) ] && cp $(MODULES_ALIAS_FILE) $(ISO_DIR)/$(ISOLINUX_DIR) + -[ -f $(MODULES_PCIMAP_FILE) ] && cp $(MODULES_PCIMAP_FILE) $(ISO_DIR)/$(ISOLINUX_DIR) + -[ ! -f $(ISO_DIR)/$(ISOLINUX_DIR)/pci.ids ] && cp $(PCI_IDS_FILE) $(ISO_DIR)/$(ISOLINUX_DIR) + -[ ! -f $(ISO_DIR)/$(ISOLINUX_DIR)/pci.ids ] && printf "\nThe $(FLOPPY_DIR)/pci.ids file is missing and can be downloaded from http://pciids.sourceforge.net and put in\nthe ./com32/hdt/$(FLOPPY_DIR) directory of the extracted Syslinux source.\n\n" + $(MKISOFS) -o hdt.iso -b $(ISOLINUX_DIR)/isolinux.bin -c $(ISOLINUX_DIR)/boot.cat \ + -no-emul-boot -boot-load-size 4 -boot-info-table \ + $(ISO_DIR) + tidy dist: rm -f *.o *.lo *.a *.lst *.elf .*.d *.tmp @@ -39,7 +83,8 @@ clean: tidy rm -f *.lnx spotless: clean - rm -f *.lss *.c32 *.com + rm -f *.lss *.c32 *.com hdt.img hdt.iso + rm -rf $(ISO_DIR) rm -f *~ \#* install: diff --git a/com32/hdt/README b/com32/hdt/README new file mode 100644 index 00000000..8e171616 --- /dev/null +++ b/com32/hdt/README @@ -0,0 +1,19 @@ +-------------- +Compiling HDT +-------------- +To build HDT, you just have to do a "make" call in this directory. + +--------------------------- +Creating a bootable floppy +-------------------------- +To build a bootable HDT floppy image, you can do a "make hdt.img" call. +This will requires the mtools (http://mtools.linux.lu) to be installed. +The script will try to pick several files from your system : +- /lib/modules/`uname -r`/modules.alias +- /lib/modules/`uname -r`/modules.pcimap +- /usr/share/pci.ids or /usr/share/hwdata/pci.ids + +This paths can be overrided with the following command line: +make MODULES_ALIAS_FILE=$(PWD)/floppy/modules.alias MODULES_PCIMAP_FILE=$(PWD)/floppy/modules.pcimap PCI_IDS_FILE=$(PWD)/floppy/pci.ids hdt.img + +If your system doesn't have pci.ids, please download it from http://pciids.sourceforge.net/ and put it into the floppy/ directory. diff --git a/com32/hdt/floppy/hdt.cfg b/com32/hdt/floppy/hdt.cfg new file mode 100644 index 00000000..8f707d0f --- /dev/null +++ b/com32/hdt/floppy/hdt.cfg @@ -0,0 +1,7 @@ +DEFAULT hdt +PROMPT 0 +SERIAL 0 + +LABEL hdt +COM32 hdt.c32 +APPEND modules_pcimap=modules.pcimap modules_alias=modules.alias pciids=pci.ids diff --git a/com32/hdt/floppy/mtools.conf b/com32/hdt/floppy/mtools.conf new file mode 100644 index 00000000..adbe2c83 --- /dev/null +++ b/com32/hdt/floppy/mtools.conf @@ -0,0 +1,2 @@ +# Floppy image for HDT +drive a: file="hdt.img" diff --git a/com32/hdt/hdt-cli-cpu.c b/com32/hdt/hdt-cli-cpu.c index f0f0a1bb..d2b5979f 100644 --- a/com32/hdt/hdt-cli-cpu.c +++ b/com32/hdt/hdt-cli-cpu.c @@ -174,6 +174,10 @@ static void show_cpu(int argc __unused, char **argv __unused, strcat(buffer1, "3dnowext "); if (hardware->cpu.flags.now) strcat(buffer1, "3dnow! "); + if (hardware->cpu.flags.svm) + strcat(buffer1, "svm "); + if (hardware->cpu.flags.vmx) + strcat(buffer1, "vmx "); if (buffer1[0]) { snprintf(buffer, sizeof buffer, "Flags : %s\n", buffer1); more_printf(buffer); diff --git a/com32/hdt/hdt-cli-disk.c b/com32/hdt/hdt-cli-disk.c index 4e2994d9..7f6b00db 100644 --- a/com32/hdt/hdt-cli-disk.c +++ b/com32/hdt/hdt-cli-disk.c @@ -31,13 +31,6 @@ #include <stdlib.h> #include <errno.h> -#include <disk/errno_disk.h> -#include <disk/geom.h> -#include <disk/read.h> -#include <disk/error.h> -#include <disk/swsusp.h> -#include <disk/msdos.h> - #include "hdt-cli.h" #include "hdt-common.h" #include "hdt-util.h" @@ -63,11 +56,14 @@ static void show_partition_information(struct driveinfo *drive_info, int nb_partitions_seen) { char size[9]; + char bootloader_name[9]; char *parttype; unsigned int start, end; int i = nb_partitions_seen; + reset_more_printf(); + start = partition_offset; end = start + ptab->length - 1; @@ -77,10 +73,10 @@ static void show_partition_information(struct driveinfo *drive_info, memset(size, 0, sizeof size); if (i == 1) - more_printf(" # B Start End Size Id Type\n"); + more_printf(" # B Start End Size Id Type\n"); get_label(ptab->ostype, &parttype); - more_printf(" %2d %s %11d %11d %s %02X %s", + more_printf("%2d %s %11d %11d %s %02X %s", i, (ptab->active_flag == 0x80) ? "x" : " ", start, end, @@ -91,6 +87,9 @@ static void show_partition_information(struct driveinfo *drive_info, if (ptab->ostype == 0x82 && swsusp_check(drive_info, ptab)) more_printf("%s", " (Swsusp sig. detected)"); + if (get_bootloader_string(drive_info, ptab, bootloader_name, 9) == 0) + more_printf("%-46s %s %s", " ", "Bootloader:", bootloader_name); + more_printf("\n"); free(parttype); @@ -99,7 +98,6 @@ static void show_partition_information(struct driveinfo *drive_info, void main_show_disk(int argc, char **argv, struct s_hardware *hardware) { - reset_more_printf(); if (!argc) { more_printf("Which disk?\n"); return; @@ -115,11 +113,16 @@ void main_show_disk(int argc, char **argv, int i = drive - 0x80; struct driveinfo *d = &hardware->disk_info[i]; char disk_size[9]; + char mbr_name[50]; detect_disks(hardware); + reset_more_printf(); + if (!hardware->disk_info[i].cbios) return; /* Invalid geometry */ + get_mbr_string(hardware->mbr_ids[i], &mbr_name, 50); + if ((int) d->edd_params.sectors > 0) sectors_to_size((int) d->edd_params.sectors, disk_size); else @@ -127,14 +130,17 @@ void main_show_disk(int argc, char **argv, more_printf("DISK 0x%X:\n" " C/H/S: %d cylinders, %d heads, %d sectors/track\n" - " EDD: Version: %X\n" + " EDD: Version: %X\n" " Size: %s, %d bytes/sector, %d sectors/track\n" - " Host bus: %s, Interface type: %s\n\n", + " Host bus: %s, Interface type: %s\n" + " MBR: %s (id 0x%X)\n\n", d->disk, d->legacy_max_cylinder + 1, d->legacy_max_head + 1, d->legacy_sectors_per_track, d->edd_version, disk_size, (int) d->edd_params.bytes_per_sector, (int) d->edd_params.sectors_per_track, - remove_spaces(d->edd_params.host_bus_type), remove_spaces(d->edd_params.interface_type)); + remove_spaces((char *) d->edd_params.host_bus_type), remove_spaces((char*) d->edd_params.interface_type), + mbr_name, hardware->mbr_ids[i]); + display_line_nb += 6; if (parse_partition_table(d, &show_partition_information)) { if (errno_disk) { @@ -145,6 +151,8 @@ void main_show_disk(int argc, char **argv, } fprintf(stderr, "\n"); } + + more_printf("\n"); } void main_show_disks(int argc __unused, char **argv __unused, @@ -153,11 +161,19 @@ void main_show_disks(int argc __unused, char **argv __unused, reset_more_printf(); detect_disks(hardware); + int first_one = 0; for (int drive = 0x80; drive < 0xff; drive++) { - char buf[5] = ""; - sprintf(buf, "0x%x", drive); - char *argv[1] = { buf }; - main_show_disk(1, argv, hardware); + if (hardware->disk_info[drive - 0x80].cbios) { + if (!first_one) { + first_one = 1; + } else { + pause_printf(); + } + char buf[5] = ""; + sprintf(buf, "0x%x", drive); + char *argv[1] = { buf }; + main_show_disk(1, argv, hardware); + } } } @@ -167,6 +183,7 @@ void disks_summary(int argc __unused, char** argv __unused, int i = -1; detect_disks(hardware); + reset_more_printf(); for (int drive = 0x80; drive < 0xff; drive++) { i++; @@ -187,8 +204,8 @@ void disks_summary(int argc __unused, char** argv __unused, more_printf(" EDD: Version: %X, size: %s\n", d->edd_version, disk_size); more_printf(" Host bus: %s, Interface type: %s\n\n", - remove_spaces(d->edd_params.host_bus_type), - remove_spaces(d->edd_params.interface_type)); + remove_spaces((char*) d->edd_params.host_bus_type), + remove_spaces((char*) d->edd_params.interface_type)); } } diff --git a/com32/hdt/hdt-cli-dmi.c b/com32/hdt/hdt-cli-dmi.c index fca94cdc..194cded3 100644 --- a/com32/hdt/hdt-cli-dmi.c +++ b/com32/hdt/hdt-cli-dmi.c @@ -38,48 +38,49 @@ static void show_dmi_modules(int argc __unused, char** argv __unused, struct s_hardware *hardware) { char available_dmi_commands[1024]; + reset_more_printf(); memset(available_dmi_commands, 0, sizeof(available_dmi_commands)); - printf("Available DMI modules on your system:\n"); + more_printf("Available DMI modules on your system:\n"); if (hardware->dmi.base_board.filled == true) - printf("\t%s\n", CLI_DMI_BASE_BOARD); + more_printf("\t%s\n", CLI_DMI_BASE_BOARD); if (hardware->dmi.battery.filled == true) - printf("\t%s\n", CLI_DMI_BATTERY); + more_printf("\t%s\n", CLI_DMI_BATTERY); if (hardware->dmi.bios.filled == true) - printf("\t%s\n", CLI_DMI_BIOS); + more_printf("\t%s\n", CLI_DMI_BIOS); if (hardware->dmi.chassis.filled == true) - printf("\t%s\n", CLI_DMI_CHASSIS); + more_printf("\t%s\n", CLI_DMI_CHASSIS); for (int i = 0; i < hardware->dmi.memory_count; i++) { if (hardware->dmi.memory[i].filled == true) { - printf("\tbank <number>\n"); + more_printf("\tbank <number>\n"); break; } } for (int i = 0; i < hardware->dmi.memory_module_count; i++) { if (hardware->dmi.memory_module[i].filled == true) { - printf("\tmodule <number>\n"); + more_printf("\tmodule <number>\n"); break; } } if (hardware->dmi.processor.filled == true) - printf("\t%s\n", CLI_DMI_PROCESSOR); + more_printf("\t%s\n", CLI_DMI_PROCESSOR); if (hardware->dmi.system.filled == true) - printf("\t%s\n", CLI_DMI_SYSTEM); + more_printf("\t%s\n", CLI_DMI_SYSTEM); if (hardware->dmi.ipmi.filled == true) - printf("\t%s\n", CLI_DMI_IPMI); + more_printf("\t%s\n", CLI_DMI_IPMI); if (hardware->dmi.cache_count) - printf("\t%s\n", CLI_DMI_CACHE); + more_printf("\t%s\n", CLI_DMI_CACHE); if (strlen(hardware->dmi.oem_strings)) more_printf("\t%s\n", CLI_DMI_OEM); if (hardware->dmi.hardware_security.filled) - printf("\t%s\n", CLI_DMI_SECURITY); + more_printf("\t%s\n", CLI_DMI_SECURITY); } static void show_dmi_base_board(int argc __unused, char** argv __unused, struct s_hardware *hardware) { if (hardware->dmi.base_board.filled == false) { - printf("base_board information not found on your system, see " + more_printf("base_board information not found on your system, see " "`show list' to see which module is available.\n"); return; } @@ -114,54 +115,55 @@ static void show_dmi_system(int argc __unused, char** argv __unused, struct s_hardware *hardware) { if (hardware->dmi.system.filled == false) { - printf("system information not found on your system, see " + more_printf("system information not found on your system, see " "`show list' to see which module is available.\n"); return; } - printf("System\n"); - printf(" Manufacturer : %s\n", hardware->dmi.system.manufacturer); - printf(" Product Name : %s\n", hardware->dmi.system.product_name); - printf(" Version : %s\n", hardware->dmi.system.version); - printf(" Serial : %s\n", hardware->dmi.system.serial); - printf(" UUID : %s\n", hardware->dmi.system.uuid); - printf(" Wakeup Type : %s\n", hardware->dmi.system.wakeup_type); - printf(" SKU Number : %s\n", hardware->dmi.system.sku_number); - printf(" Family : %s\n", hardware->dmi.system.family); + reset_more_printf(); + more_printf("System\n"); + more_printf(" Manufacturer : %s\n", hardware->dmi.system.manufacturer); + more_printf(" Product Name : %s\n", hardware->dmi.system.product_name); + more_printf(" Version : %s\n", hardware->dmi.system.version); + more_printf(" Serial : %s\n", hardware->dmi.system.serial); + more_printf(" UUID : %s\n", hardware->dmi.system.uuid); + more_printf(" Wakeup Type : %s\n", hardware->dmi.system.wakeup_type); + more_printf(" SKU Number : %s\n", hardware->dmi.system.sku_number); + more_printf(" Family : %s\n", hardware->dmi.system.family); if (strlen(hardware->dmi.system.configuration_options)) { - printf("System Configuration Options\n"); - printf("%s\n", hardware->dmi.system.configuration_options); + more_printf("System Configuration Options\n"); + more_printf("%s\n", hardware->dmi.system.configuration_options); } if (hardware->dmi.system.system_reset.filled) { - printf("System Reset\n"); - printf(" Status : %s\n", + more_printf("System Reset\n"); + more_printf(" Status : %s\n", (hardware->dmi.system.system_reset.status ? "Enabled" : "Disabled")); - printf(" Watchdog Timer : %s\n", + more_printf(" Watchdog Timer : %s\n", (hardware->dmi.system.system_reset.watchdog ? "Present" : "Not Present")); if (strlen(hardware->dmi.system.system_reset.boot_option)) - printf(" Boot Option : %s\n", hardware->dmi.system.system_reset.boot_option); + more_printf(" Boot Option : %s\n", hardware->dmi.system.system_reset.boot_option); if (strlen(hardware->dmi.system.system_reset.boot_option_on_limit)) - printf(" Boot Option On Limit : %s\n", hardware->dmi.system.system_reset.boot_option_on_limit); + more_printf(" Boot Option On Limit : %s\n", hardware->dmi.system.system_reset.boot_option_on_limit); if (strlen(hardware->dmi.system.system_reset.reset_count)) - printf(" Reset Count : %s\n", hardware->dmi.system.system_reset.reset_count); + more_printf(" Reset Count : %s\n", hardware->dmi.system.system_reset.reset_count); if (strlen(hardware->dmi.system.system_reset.reset_limit)) - printf(" Reset Limit : %s\n", hardware->dmi.system.system_reset.reset_limit); + more_printf(" Reset Limit : %s\n", hardware->dmi.system.system_reset.reset_limit); if (strlen(hardware->dmi.system.system_reset.timer_interval)) - printf(" Timer Interval : %s\n", hardware->dmi.system.system_reset.timer_interval); + more_printf(" Timer Interval : %s\n", hardware->dmi.system.system_reset.timer_interval); if (strlen(hardware->dmi.system.system_reset.timeout)) - printf(" Timeout : %s\n", hardware->dmi.system.system_reset.timeout); + more_printf(" Timeout : %s\n", hardware->dmi.system.system_reset.timeout); } - printf("System Boot Information\n"); - printf(" Status : %s\n", hardware->dmi.system.system_boot_status); + more_printf("System Boot Information\n"); + more_printf(" Status : %s\n", hardware->dmi.system.system_boot_status); } static void show_dmi_bios(int argc __unused, char** argv __unused, struct s_hardware *hardware) { if (hardware->dmi.bios.filled == false) { - printf("bios information not found on your system, see " + more_printf("bios information not found on your system, see " "`show list' to see which module is available.\n"); return; } @@ -213,28 +215,29 @@ static void show_dmi_chassis(int argc __unused, char** argv __unused, "`show list' to see which module is available.\n"); return; } - printf("Chassis\n"); - printf(" Manufacturer : %s\n", + reset_more_printf(); + more_printf("Chassis\n"); + more_printf(" Manufacturer : %s\n", hardware->dmi.chassis.manufacturer); - printf(" Type : %s\n", hardware->dmi.chassis.type); - printf(" Lock : %s\n", hardware->dmi.chassis.lock); - printf(" Version : %s\n", + more_printf(" Type : %s\n", hardware->dmi.chassis.type); + more_printf(" Lock : %s\n", hardware->dmi.chassis.lock); + more_printf(" Version : %s\n", hardware->dmi.chassis.version); - printf(" Serial : %s\n", hardware->dmi.chassis.serial); - printf(" Asset Tag : %s\n", + more_printf(" Serial : %s\n", hardware->dmi.chassis.serial); + more_printf(" Asset Tag : %s\n", del_multi_spaces(hardware->dmi.chassis.asset_tag)); - printf(" Boot up state : %s\n", + more_printf(" Boot up state : %s\n", hardware->dmi.chassis.boot_up_state); - printf(" Power supply state : %s\n", + more_printf(" Power supply state : %s\n", hardware->dmi.chassis.power_supply_state); - printf(" Thermal state : %s\n", + more_printf(" Thermal state : %s\n", hardware->dmi.chassis.thermal_state); - printf(" Security Status : %s\n", + more_printf(" Security Status : %s\n", hardware->dmi.chassis.security_status); - printf(" OEM Information : %s\n", + more_printf(" OEM Information : %s\n", hardware->dmi.chassis.oem_information); - printf(" Height : %u\n", hardware->dmi.chassis.height); - printf(" NB Power Cords : %u\n", + more_printf(" Height : %u\n", hardware->dmi.chassis.height); + more_printf(" NB Power Cords : %u\n", hardware->dmi.chassis.nb_power_cords); } @@ -245,21 +248,22 @@ static void show_dmi_ipmi(int argc __unused, char **argv __unused, more_printf("IPMI module not available\n"); return; } - printf("IPMI\n"); - printf(" Interface Type : %s\n", + reset_more_printf(); + more_printf("IPMI\n"); + more_printf(" Interface Type : %s\n", hardware->dmi.ipmi.interface_type); - printf(" Specification Ver. : %u.%u\n", + more_printf(" Specification Ver. : %u.%u\n", hardware->dmi.ipmi.major_specification_version, hardware->dmi.ipmi.minor_specification_version); - printf(" I2C Slave Address : 0x%02x\n", + more_printf(" I2C Slave Address : 0x%02x\n", hardware->dmi.ipmi.I2C_slave_address); - printf(" Nv Storage Address : %u\n", + more_printf(" Nv Storage Address : %u\n", hardware->dmi.ipmi.nv_address); uint32_t high = hardware->dmi.ipmi.base_address >> 32; uint32_t low = hardware->dmi.ipmi.base_address & 0xFFFF; - printf(" Base Address : %08X%08X\n", + more_printf(" Base Address : %08X%08X\n", high,(low & ~1)); - printf(" IRQ : %d\n", + more_printf(" IRQ : %d\n", hardware->dmi.ipmi.irq); } @@ -267,31 +271,32 @@ static void show_dmi_battery(int argc __unused, char** argv __unused, struct s_hardware *hardware) { if (hardware->dmi.battery.filled == false) { - printf("battery information not found on your system, see " + more_printf("battery information not found on your system, see " "`show list' to see which module is available.\n"); return; } - printf("Battery \n"); - printf(" Vendor : %s\n", + reset_more_printf(); + more_printf("Battery \n"); + more_printf(" Vendor : %s\n", hardware->dmi.battery.manufacturer); - printf(" Manufacture Date : %s\n", + more_printf(" Manufacture Date : %s\n", hardware->dmi.battery.manufacture_date); - printf(" Serial : %s\n", hardware->dmi.battery.serial); - printf(" Name : %s\n", hardware->dmi.battery.name); - printf(" Chemistry : %s\n", + more_printf(" Serial : %s\n", hardware->dmi.battery.serial); + more_printf(" Name : %s\n", hardware->dmi.battery.name); + more_printf(" Chemistry : %s\n", hardware->dmi.battery.chemistry); - printf(" Design Capacity : %s\n", + more_printf(" Design Capacity : %s\n", hardware->dmi.battery.design_capacity); - printf(" Design Voltage : %s\n", + more_printf(" Design Voltage : %s\n", hardware->dmi.battery.design_voltage); - printf(" SBDS : %s\n", hardware->dmi.battery.sbds); - printf(" SBDS Manuf. Date : %s\n", + more_printf(" SBDS : %s\n", hardware->dmi.battery.sbds); + more_printf(" SBDS Manuf. Date : %s\n", hardware->dmi.battery.sbds_manufacture_date); - printf(" SBDS Chemistry : %s\n", + more_printf(" SBDS Chemistry : %s\n", hardware->dmi.battery.sbds_chemistry); - printf(" Maximum Error : %s\n", + more_printf(" Maximum Error : %s\n", hardware->dmi.battery.maximum_error); - printf(" OEM Info : %s\n", + more_printf(" OEM Info : %s\n", hardware->dmi.battery.oem_info); } @@ -299,7 +304,7 @@ static void show_dmi_cpu(int argc __unused, char** argv __unused, struct s_hardware *hardware) { if (hardware->dmi.processor.filled == false) { - printf("processor information not found on your system, see " + more_printf("processor information not found on your system, see " "`show list' to see which module is available.\n"); return; } @@ -363,44 +368,45 @@ void show_dmi_memory_bank(int argc, char** argv, bank = strtol(argv[0], (char **)NULL, 10); if (errno == ERANGE || bank < 0) { - printf("This bank number is incorrect\n"); + more_printf("This bank number is incorrect\n"); return; } if ((bank >= hardware->dmi.memory_count) || (bank < 0)) { - printf("Bank %d number doesn't exists\n", bank); + more_printf("Bank %d number doesn't exist\n", bank); return; } if (hardware->dmi.memory[bank].filled == false) { - printf("Bank %d doesn't contain any information\n", bank); + more_printf("Bank %d doesn't contain any information\n", bank); return; } - printf("Memory Bank %d\n", bank); - printf(" Form Factor : %s\n", + reset_more_printf(); + more_printf("Memory Bank %d\n", bank); + more_printf(" Form Factor : %s\n", hardware->dmi.memory[bank].form_factor); - printf(" Type : %s\n", hardware->dmi.memory[bank].type); - printf(" Type Detail : %s\n", + more_printf(" Type : %s\n", hardware->dmi.memory[bank].type); + more_printf(" Type Detail : %s\n", hardware->dmi.memory[bank].type_detail); - printf(" Speed : %s\n", hardware->dmi.memory[bank].speed); - printf(" Size : %s\n", hardware->dmi.memory[bank].size); - printf(" Device Set : %s\n", + more_printf(" Speed : %s\n", hardware->dmi.memory[bank].speed); + more_printf(" Size : %s\n", hardware->dmi.memory[bank].size); + more_printf(" Device Set : %s\n", hardware->dmi.memory[bank].device_set); - printf(" Device Loc. : %s\n", + more_printf(" Device Loc. : %s\n", hardware->dmi.memory[bank].device_locator); - printf(" Bank Locator : %s\n", + more_printf(" Bank Locator : %s\n", hardware->dmi.memory[bank].bank_locator); - printf(" Total Width : %s\n", + more_printf(" Total Width : %s\n", hardware->dmi.memory[bank].total_width); - printf(" Data Width : %s\n", + more_printf(" Data Width : %s\n", hardware->dmi.memory[bank].data_width); - printf(" Error : %s\n", hardware->dmi.memory[bank].error); - printf(" Vendor : %s\n", + more_printf(" Error : %s\n", hardware->dmi.memory[bank].error); + more_printf(" Vendor : %s\n", hardware->dmi.memory[bank].manufacturer); - printf(" Serial : %s\n", hardware->dmi.memory[bank].serial); - printf(" Asset Tag : %s\n", + more_printf(" Serial : %s\n", hardware->dmi.memory[bank].serial); + more_printf(" Asset Tag : %s\n", hardware->dmi.memory[bank].asset_tag); - printf(" Part Number : %s\n", + more_printf(" Part Number : %s\n", hardware->dmi.memory[bank].part_number); } @@ -408,7 +414,7 @@ static void show_dmi_cache(int argc, char** argv, struct s_hardware *hardware) { if (!hardware->dmi.cache_count) { - printf("cache information not found on your system, see " + more_printf("cache information not found on your system, see " "`show list' to see which module is available.\n"); return; } @@ -416,7 +422,7 @@ static void show_dmi_cache(int argc, char** argv, int cache = strtol(argv[0], NULL, 10); if (argc != 1 || cache > hardware->dmi.cache_count) { - printf("show cache [0-%d]\n", hardware->dmi.cache_count-1); + more_printf("show cache [0-%d]\n", hardware->dmi.cache_count-1); return; } @@ -464,34 +470,35 @@ void show_dmi_memory_module(int argc, char** argv, module = strtol(argv[0], (char **)NULL, 10); if (errno == ERANGE || module < 0) { - printf("This module number is incorrect\n"); + more_printf("This module number is incorrect\n"); return; } if ((module >= hardware->dmi.memory_module_count) || (module < 0)) { - printf("Module number %d doesn't exist\n", module); + more_printf("Module number %d doesn't exist\n", module); return; } if (hardware->dmi.memory_module[module].filled == false) { - printf("Module %d doesn't contain any information\n", module); + more_printf("Module %d doesn't contain any information\n", module); return; } - printf("Memory Module %d\n", module); - printf(" Socket Designation : %s\n", + reset_more_printf(); + more_printf("Memory Module %d\n", module); + more_printf(" Socket Designation : %s\n", hardware->dmi.memory_module[module].socket_designation); - printf(" Bank Connections : %s\n", + more_printf(" Bank Connections : %s\n", hardware->dmi.memory_module[module].bank_connections); - printf(" Current Speed : %s\n", + more_printf(" Current Speed : %s\n", hardware->dmi.memory_module[module].speed); - printf(" Type : %s\n", + more_printf(" Type : %s\n", hardware->dmi.memory_module[module].type); - printf(" Installed Size : %s\n", + more_printf(" Installed Size : %s\n", hardware->dmi.memory_module[module].installed_size); - printf(" Enabled Size : %s\n", + more_printf(" Enabled Size : %s\n", hardware->dmi.memory_module[module].enabled_size); - printf(" Error Status : %s\n", + more_printf(" Error Status : %s\n", hardware->dmi.memory_module[module].error_status); } @@ -502,10 +509,11 @@ void main_show_dmi(int argc __unused, char **argv __unused, detect_dmi(hardware); if (hardware->is_dmi_valid == false) { - printf("No valid DMI table found, exiting.\n"); + more_printf("No valid DMI table found, exiting.\n"); return; } - printf("DMI Table version %d.%d found\n", + reset_more_printf(); + more_printf("DMI Table version %u.%u found\n", hardware->dmi.dmitable.major_version, hardware->dmi.dmitable.minor_version); @@ -536,6 +544,7 @@ void show_dmi_memory_modules(int argc __unused, char** argv __unused, return; } + reset_more_printf(); more_printf("Memory Banks\n"); for (int i = 0; i < hardware->dmi.memory_count; i++) { if (hardware->dmi.memory[i].filled == true) { diff --git a/com32/hdt/hdt-cli-hdt.c b/com32/hdt/hdt-cli-hdt.c index 5bebf584..f11cbec4 100644 --- a/com32/hdt/hdt-cli-hdt.c +++ b/com32/hdt/hdt-cli-hdt.c @@ -52,6 +52,7 @@ static void main_show_modes(int argc __unused, char** argv __unused, { int i = 0; + reset_more_printf(); printf("Available modes:\n"); while (list_modes[i]) { printf("%s ", list_modes[i]->name); @@ -70,8 +71,9 @@ static void cli_set_mode(int argc, char **argv, { cli_mode_t new_mode; + reset_more_printf(); if (argc <= 0) { - printf("Which mode?\n"); + more_printf("Which mode?\n"); return; } @@ -191,8 +193,8 @@ static void goto_menu(int argc __unused, char** argv __unused, struct s_hardware *hardware) { char version_string[256]; - snprintf(version_string, sizeof version_string, "%s %s by %s", - PRODUCT_NAME, VERSION, AUTHOR); + snprintf(version_string, sizeof version_string, "%s %s (%s)", + PRODUCT_NAME, VERSION, CODENAME); start_menu_mode(hardware, version_string); return; } @@ -206,6 +208,7 @@ void main_show_summary(int argc __unused, char **argv __unused, detect_pci(hardware); /* pxe is detected in the pci */ detect_dmi(hardware); cpu_detect(hardware); + reset_more_printf(); clear_screen(); main_show_cpu(argc, argv, hardware); if (hardware->is_dmi_valid) { @@ -236,17 +239,32 @@ void main_show_summary(int argc __unused, char **argv __unused, void main_show_hdt(int argc __unused, char **argv __unused, struct s_hardware *hardware __unused) { - printf("HDT\n"); - printf(" Product : %s\n", PRODUCT_NAME); - printf(" Version : %s\n", VERSION); - printf(" Author : %s\n", AUTHOR); - printf(" Contact : %s\n", CONTACT); + reset_more_printf(); + more_printf("HDT\n"); + more_printf(" Product : %s\n", PRODUCT_NAME); + more_printf(" Version : %s (%s)\n", VERSION, CODENAME); + more_printf(" Project Leader : %s\n", AUTHOR); + more_printf(" Contact : %s\n", CONTACT); + more_printf(" Core Developer : %s\n", CORE_DEVELOPER); char *contributors[NB_CONTRIBUTORS] = CONTRIBUTORS; for (int c = 0; c < NB_CONTRIBUTORS; c++) { - printf(" Contributor : %s\n", contributors[c]); + more_printf(" Contributor : %s\n", contributors[c]); } } +/** + * do_reboot - reboot the system + **/ +static void do_reboot(int argc __unused, char** argv __unused, + struct s_hardware *hardware) +{ + /* Use specific syslinux call if needed */ + if (issyslinux()) + return runsyslinuxcmd(hardware->reboot_label); + else + return csprint(hardware->reboot_label, 0x07); +} + /* Default hdt mode */ struct cli_callback_descr list_hdt_default_modules[] = { { @@ -266,6 +284,10 @@ struct cli_callback_descr list_hdt_default_modules[] = { .exec = goto_menu, }, { + .name = CLI_REBOOT, + .exec = do_reboot, + }, + { .name = NULL, .exec = NULL }, diff --git a/com32/hdt/hdt-cli-kernel.c b/com32/hdt/hdt-cli-kernel.c index 41c80bea..d33cdd80 100644 --- a/com32/hdt/hdt-cli-kernel.c +++ b/com32/hdt/hdt-cli-kernel.c @@ -46,6 +46,7 @@ void main_show_kernel(int argc __unused, char **argv __unused, memset(buffer, 0, sizeof(buffer)); detect_pci(hardware); + reset_more_printf(); more_printf("Kernel modules\n"); // more_printf(" PCI device no: %d \n", p->pci_device_pos); @@ -105,17 +106,18 @@ static void show_kernel_modules(int argc __unused, char **argv __unused, if (hardware->pci_ids_return_code == -ENOPCIIDS) { nopciids = true; - printf(" Missing pci.ids, we can't compute the list\n"); + more_printf(" Missing pci.ids, we can't compute the list\n"); return; } if (hardware->modules_pcimap_return_code == -ENOMODULESPCIMAP) { nomodulespcimap = true; - printf + more_printf (" Missing modules.pcimap, we can't compute the list\n"); return; } + reset_more_printf(); for_each_pci_func(pci_device, hardware->pci_domain) { memset(kernel_modules, 0, sizeof kernel_modules); @@ -140,7 +142,7 @@ static void show_kernel_modules(int argc __unused, char **argv __unused, /* Print the found items */ for (int i = 0; i < MAX_PCI_CLASSES; i++) { if (strlen(category_name[i]) > 1) { - printf("%s : %s\n", category_name[i], modules[i]); + more_printf("%s : %s\n", category_name[i], modules[i]); } } } diff --git a/com32/hdt/hdt-cli-memory.c b/com32/hdt/hdt-cli-memory.c index 89f871e1..3f8ed75a 100644 --- a/com32/hdt/hdt-cli-memory.c +++ b/com32/hdt/hdt-cli-memory.c @@ -41,8 +41,8 @@ static void show_memory_e820(int argc __unused, char **argv __unused, char type[14]; detect_memory_e820(map, E820MAX, &count); - printf("BIOS-provided physical RAM e820 map:\n"); reset_more_printf(); + more_printf("BIOS-provided physical RAM e820 map:\n"); for (int i = 0; i < count; i++) { get_type(map[i].type, type, 14); more_printf("%016llx - %016llx %016llx (%s)\n", diff --git a/com32/hdt/hdt-cli-pci.c b/com32/hdt/hdt-cli-pci.c index 2de43fe3..75e28968 100644 --- a/com32/hdt/hdt-cli-pci.c +++ b/com32/hdt/hdt-cli-pci.c @@ -37,7 +37,7 @@ void main_show_pci(int argc __unused, char **argv __unused, struct s_hardware *hardware) { cli_detect_pci(hardware); - + reset_more_printf(); more_printf("PCI\n"); more_printf(" NB Devices : %d\n", hardware->nb_pci_devices); } @@ -56,19 +56,20 @@ static void show_pci_device(int argc, char **argv, MAX_KERNEL_MODULES_PER_PCI_DEVICE]; int bus = 0, slot = 0, func = 0; + reset_more_printf(); /* Sanitize arguments */ if (argc <= 0) { - printf("show device <number>\n"); + more_printf("show device <number>\n"); return; } else pcidev = strtol(argv[0], (char **)NULL, 10); if (errno == ERANGE) { - printf("This PCI device number is incorrect\n"); + more_printf("This PCI device number is incorrect\n"); return; } if ((pcidev > hardware->nb_pci_devices) || (pcidev <= 0)) { - printf("PCI device %d doesn't exists\n", pcidev); + more_printf("PCI device %d doesn't exist\n", pcidev); return; } if (hardware->pci_ids_return_code == -ENOPCIIDS) { @@ -92,7 +93,7 @@ static void show_pci_device(int argc, char **argv, } if (pci_device == NULL) { - printf("We were enabled to find PCI device %d\n", pcidev); + more_printf("We were enabled to find PCI device %d\n", pcidev); return; } @@ -109,41 +110,41 @@ static void show_pci_device(int argc, char **argv, if (pci_device->dev_info->linux_kernel_module_count == 0) strlcpy(kernel_modules, "unknown", 7); - printf("PCI Device %d\n", pcidev); + more_printf("PCI Device %d\n", pcidev); if (nopciids == false) { - printf("Vendor Name : %s\n", + more_printf("Vendor Name : %s\n", pci_device->dev_info->vendor_name); - printf("Product Name : %s\n", + more_printf("Product Name : %s\n", pci_device->dev_info->product_name); - printf("Class Name : %s\n", + more_printf("Class Name : %s\n", pci_device->dev_info->class_name); } if (nomodulesfiles == false) { - printf("Kernel module : %s\n", kernel_modules); + more_printf("Kernel module : %s\n", kernel_modules); } - printf("Vendor ID : %04x\n", pci_device->vendor); - printf("Product ID : %04x\n", pci_device->product); - printf("SubVendor ID : %04x\n", pci_device->sub_vendor); - printf("SubProduct ID : %04x\n", pci_device->sub_product); - printf("Class ID : %02x.%02x.%02x\n", pci_device->class[2], + more_printf("Vendor ID : %04x\n", pci_device->vendor); + more_printf("Product ID : %04x\n", pci_device->product); + more_printf("SubVendor ID : %04x\n", pci_device->sub_vendor); + more_printf("SubProduct ID : %04x\n", pci_device->sub_product); + more_printf("Class ID : %02x.%02x.%02x\n", pci_device->class[2], pci_device->class[1], pci_device->class[0]); - printf("Revision : %02x\n", pci_device->revision); + more_printf("Revision : %02x\n", pci_device->revision); if ((pci_device->dev_info->irq > 0) && (pci_device->dev_info->irq < 255)) more_printf("IRQ : %0d\n", pci_device->dev_info->irq); - printf("Latency : %0d\n", pci_device->dev_info->latency); - printf("PCI Bus : %02d\n", bus); - printf("PCI Slot : %02d\n", slot); - printf("PCI Func : %02d\n", func); + more_printf("Latency : %0d\n", pci_device->dev_info->latency); + more_printf("PCI Bus : %02d\n", bus); + more_printf("PCI Slot : %02d\n", slot); + more_printf("PCI Func : %02d\n", func); if (hardware->is_pxe_valid == true) { if ((hardware->pxe.pci_device != NULL) && (hardware->pxe.pci_device == pci_device)) { - printf("Mac Address : %s\n", hardware->pxe.mac_addr); - printf("PXE : Current boot device\n"); + more_printf("Mac Address : %s\n", hardware->pxe.mac_addr); + more_printf("PXE : Current boot device\n"); } } } @@ -305,21 +306,21 @@ void cli_detect_pci(struct s_hardware *hardware) if (hardware->pci_detection == false) { detect_pci(hardware); if (hardware->pci_ids_return_code == -ENOPCIIDS) { - printf + more_printf ("The pci.ids file is missing, device names can't be computed.\n"); - printf("Please put one in same dir as hdt\n"); + more_printf("Please put one in same dir as hdt\n"); error = true; } if ((hardware->modules_pcimap_return_code == -ENOMODULESPCIMAP) && (hardware->modules_alias_return_code == -ENOMODULESALIAS)) { - printf + more_printf ("The modules.pcimap or modules.alias files are missing, device names can't be computed.\n"); - printf("Please put one of them in same dir as hdt\n"); + more_printf("Please put one of them in same dir as hdt\n"); error = true; } if (error == true) { char tempbuf[10]; - printf("Press enter to continue\n"); + more_printf("Press enter to continue\n"); fgets(tempbuf, sizeof(tempbuf), stdin); } } diff --git a/com32/hdt/hdt-cli-pxe.c b/com32/hdt/hdt-cli-pxe.c index 1d00cae5..a281d158 100644 --- a/com32/hdt/hdt-cli-pxe.c +++ b/com32/hdt/hdt-cli-pxe.c @@ -41,20 +41,21 @@ void main_show_pxe(int argc __unused, char **argv __unused, { char buffer[81]; memset(buffer, 0, sizeof(81)); + reset_more_printf(); if (hardware->sv->filesystem != SYSLINUX_FS_PXELINUX) { - printf("You are not currently using PXELINUX\n"); + more_printf("You are not currently using PXELINUX\n"); return; } detect_pxe(hardware); - printf("PXE\n"); + more_printf("PXE\n"); if (hardware->is_pxe_valid == false) { - printf(" No valid PXE ROM found\n"); + more_printf(" No valid PXE ROM found\n"); return; } struct s_pxe *p = &hardware->pxe; - printf(" PCI device no: %d \n", p->pci_device_pos); + more_printf(" PCI device no: %d \n", p->pci_device_pos); if (hardware->pci_ids_return_code == -ENOPCIIDS || (p->pci_device == NULL)) { @@ -65,16 +66,16 @@ void main_show_pxe(int argc __unused, char **argv __unused, snprintf(buffer, sizeof(buffer), " PCI Bus pos. : %02x:%02x.%02x\n", p->pci_bus, p->pci_dev, p->pci_func); - printf(buffer); + more_printf(buffer); } else { snprintf(buffer, sizeof(buffer), " Manufacturer : %s \n", p->pci_device->dev_info->vendor_name); - printf(buffer); + more_printf(buffer); snprintf(buffer, sizeof(buffer), " Product : %s \n", p->pci_device->dev_info->product_name); - printf(buffer); + more_printf(buffer); } - printf(" Addresses : %d.%d.%d.%d @ %s\n", p->ip_addr[0], + more_printf(" Addresses : %d.%d.%d.%d @ %s\n", p->ip_addr[0], p->ip_addr[1], p->ip_addr[2], p->ip_addr[3], p->mac_addr); } diff --git a/com32/hdt/hdt-cli-syslinux.c b/com32/hdt/hdt-cli-syslinux.c index 0d78bc66..160e33c4 100644 --- a/com32/hdt/hdt-cli-syslinux.c +++ b/com32/hdt/hdt-cli-syslinux.c @@ -39,12 +39,13 @@ void main_show_syslinux(int argc __unused, char **argv __unused, struct s_hardware *hardware) { - printf("SYSLINUX\n"); - printf(" Bootloader : %s\n", hardware->syslinux_fs); - printf(" Version : %s\n", hardware->sv->version_string + 2); - printf(" Version : %u\n", hardware->sv->version); - printf(" Max API : %u\n", hardware->sv->max_api); - printf(" Copyright : %s\n", hardware->sv->copyright_string + 1); + reset_more_printf(); + more_printf("SYSLINUX\n"); + more_printf(" Bootloader : %s\n", hardware->syslinux_fs); + more_printf(" Version : %s\n", hardware->sv->version_string + 2); + more_printf(" Version : %u\n", hardware->sv->version); + more_printf(" Max API : %u\n", hardware->sv->max_api); + more_printf(" Copyright : %s\n", hardware->sv->copyright_string + 1); } struct cli_module_descr syslinux_show_modules = { diff --git a/com32/hdt/hdt-cli-vesa.c b/com32/hdt/hdt-cli-vesa.c index 70d1dc61..c6eea072 100644 --- a/com32/hdt/hdt-cli-vesa.c +++ b/com32/hdt/hdt-cli-vesa.c @@ -36,33 +36,34 @@ void main_show_vesa(int argc __unused, char **argv __unused, struct s_hardware *hardware) { + reset_more_printf(); detect_vesa(hardware); if (hardware->is_vesa_valid == false) { - printf("No VESA BIOS detected\n"); + more_printf("No VESA BIOS detected\n"); return; } - printf("VESA\n"); - printf(" Vesa version : %d.%d\n", hardware->vesa.major_version, + more_printf("VESA\n"); + more_printf(" Vesa version : %d.%d\n", hardware->vesa.major_version, hardware->vesa.minor_version); - printf(" Vendor : %s\n", hardware->vesa.vendor); - printf(" Product : %s\n", hardware->vesa.product); - printf(" Product rev. : %s\n", hardware->vesa.product_revision); - printf(" Software rev.: %d\n", hardware->vesa.software_rev); - printf(" Memory (KB) : %d\n", hardware->vesa.total_memory * 64); - printf(" Modes : %d\n", hardware->vesa.vmi_count); + more_printf(" Vendor : %s\n", hardware->vesa.vendor); + more_printf(" Product : %s\n", hardware->vesa.product); + more_printf(" Product rev. : %s\n", hardware->vesa.product_revision); + more_printf(" Software rev.: %d\n", hardware->vesa.software_rev); + more_printf(" Memory (KB) : %d\n", hardware->vesa.total_memory * 64); + more_printf(" Modes : %d\n", hardware->vesa.vmi_count); } static void show_vesa_modes(int argc __unused, char **argv __unused, struct s_hardware *hardware) { detect_vesa(hardware); + reset_more_printf(); if (hardware->is_vesa_valid == false) { - printf("No VESA BIOS detected\n"); + more_printf("No VESA BIOS detected\n"); return; } - reset_more_printf(); - printf(" ResH. x ResV x Bits : vga= : Vesa Mode\n"); - printf("----------------------------------------\n"); + more_printf(" ResH. x ResV x Bits : vga= : Vesa Mode\n"); + more_printf("----------------------------------------\n"); for (int i = 0; i < hardware->vesa.vmi_count; i++) { struct vesa_mode_info *mi = &hardware->vesa.vmi[i].mi; @@ -71,7 +72,7 @@ static void show_vesa_modes(int argc __unused, char **argv __unused, * We don't need to display that ones. */ if ((mi->h_res == 0) || (mi->v_res == 0)) continue; - printf("%5u %5u %3u %3d 0x%04x\n", + more_printf("%5u %5u %3u %3d 0x%04x\n", mi->h_res, mi->v_res, mi->bpp, hardware->vesa.vmi[i].mode + 0x200, hardware->vesa.vmi[i].mode); diff --git a/com32/hdt/hdt-cli-vpd.c b/com32/hdt/hdt-cli-vpd.c index 03614d39..a445d833 100644 --- a/com32/hdt/hdt-cli-vpd.c +++ b/com32/hdt/hdt-cli-vpd.c @@ -39,11 +39,11 @@ void main_show_vpd(int argc __unused, char **argv __unused, detect_vpd(hardware); if (!hardware->is_vpd_valid) { - printf("No VPD structure detected.\n"); + more_printf("No VPD structure detected.\n"); return; } - printf("VPD present at address : 0x%s\n", hardware->vpd.base_address); + more_printf("VPD present at address : 0x%s\n", hardware->vpd.base_address); if (strlen(hardware->vpd.bios_build_id) > 0) more_printf("Bios Build ID : %s\n", hardware->vpd.bios_build_id); if (strlen(hardware->vpd.bios_release_date) > 0) diff --git a/com32/hdt/hdt-cli.c b/com32/hdt/hdt-cli.c index 0d38fb2b..060f953b 100644 --- a/com32/hdt/hdt-cli.c +++ b/com32/hdt/hdt-cli.c @@ -32,7 +32,6 @@ #include <getkey.h> #include "hdt-cli.h" #include "hdt-common.h" -#include "lib-ansi.h" struct cli_mode_descr *list_modes[] = { &hdt_mode, @@ -54,8 +53,8 @@ struct cli_mode_descr *list_modes[] = { * array of variables. There is no easy way around it besides declaring the arrays of * strings first. */ -char *exit_aliases[] = {"q", "quit"}; -char *help_aliases[] = {"h", "?"}; +const char *exit_aliases[] = {"q", "quit"}; +const char *help_aliases[] = {"h", "?"}; /* List of aliases */ struct cli_alias hdt_aliases[] = { @@ -750,6 +749,48 @@ static void reset_prompt() } } +void start_auto_mode(struct s_hardware *hardware) +{ + char *mypch; + int nb_commands=0; + char *commands[MAX_NB_AUTO_COMMANDS]; + + if (!quiet) + more_printf("\nEntering Auto mode\n"); + + /* Protecting the auto_label from the strtok modifications */ + char *temp=strdup(hardware->auto_label); + + /* Searching & saving all commands */ + mypch = strtok (temp,AUTO_SEPARATOR); + while (mypch != NULL) { + if ((strlen(remove_spaces(mypch))>0) && (remove_spaces(mypch)[0] != AUTO_SEPARATOR)) { + nb_commands++; + if ((commands[nb_commands]=malloc(AUTO_COMMAND_SIZE)) != NULL) { + sprintf(commands[nb_commands],"%s",remove_spaces(mypch)); + } else + nb_commands--; + } + mypch = strtok (NULL, AUTO_SEPARATOR); + } + + /* Executing found commands */ + for (int i=1;i<=nb_commands;i++) { + if (commands[i]) { + if (!quiet) + more_printf("%s%s\n",hdt_cli.prompt,commands[i]); + exec_command(commands[i], hardware); + free(commands[i]); + } + } + + if (!quiet) + more_printf("\nExiting Auto mode\n"); + + more_printf("\n"); +} + + /* Code that manages the cli mode */ void start_cli_mode(struct s_hardware *hardware) { @@ -773,6 +814,11 @@ void start_cli_mode(struct s_hardware *hardware) return; } + /* Start the auto mode if the command line is set*/ + if (strlen(hardware->auto_label) > 0) { + start_auto_mode(hardware); + } + printf("Entering CLI mode\n"); reset_prompt(); diff --git a/com32/hdt/hdt-cli.h b/com32/hdt/hdt-cli.h index 47137cca..3684fa40 100644 --- a/com32/hdt/hdt-cli.h +++ b/com32/hdt/hdt-cli.h @@ -48,6 +48,7 @@ #define CLI_CLEAR "clear" #define CLI_EXIT "exit" #define CLI_HELP "help" +#define CLI_REBOOT "reboot" #define CLI_SHOW "show" #define CLI_SET "set" #define CLI_MODE "mode" @@ -152,6 +153,7 @@ cli_mode_t mode_s_to_mode_t(char *name); void set_mode(cli_mode_t mode, struct s_hardware *hardware); void start_cli_mode(struct s_hardware *hardware); +void start_auto_mode(struct s_hardware *hardware); void main_show(char *item, struct s_hardware *hardware); // DMI STUFF diff --git a/com32/hdt/hdt-common.c b/com32/hdt/hdt-common.c index 80305a3e..5cfa9e87 100644 --- a/com32/hdt/hdt-common.c +++ b/com32/hdt/hdt-common.c @@ -33,8 +33,8 @@ #include "syslinux/config.h" #include "../lib/sys/vesa/vesa.h" #include "hdt-common.h" -#include "lib-ansi.h" #include <disk/util.h> +#include <disk/mbrs.h> /* ISOlinux requires a 8.3 format */ void convert_isolinux_filename(char *filename, struct s_hardware *hardware) { @@ -55,8 +55,13 @@ void convert_isolinux_filename(char *filename, struct s_hardware *hardware) { void detect_parameters(const int argc, const char *argv[], struct s_hardware *hardware) { + /* Quiet mode - make the output more quiet */ + quiet = false; + for (int i = 1; i < argc; i++) { - if (!strncmp(argv[i], "modules_pcimap=", 15)) { + if (!strncmp(argv[i], "quiet", 5)) { + quiet = true; + } else if (!strncmp(argv[i], "modules_pcimap=", 15)) { strncpy(hardware->modules_pcimap_path, argv[i] + 15, sizeof(hardware->modules_pcimap_path)); convert_isolinux_filename(hardware->modules_pcimap_path,hardware); @@ -72,6 +77,36 @@ void detect_parameters(const int argc, const char *argv[], strncpy(hardware->memtest_label, argv[i] + 8, sizeof(hardware->memtest_label)); convert_isolinux_filename(hardware->memtest_label,hardware); + } else if (!strncmp(argv[i], "reboot=", 7)) { + strncpy(hardware->reboot_label, argv[i] + 7, + sizeof(hardware->reboot_label)); + convert_isolinux_filename(hardware->reboot_label,hardware); + } else if (!strncmp(argv[i], "auto=", 5)) { + /* The auto= parameter is separated in several argv[] + * as it can contains spaces. + * We use the AUTO_DELIMITER char to define the limits + * of this parameter. + * i.e auto='show dmi; show pci' + */ + + /* Extracting the first parameter */ + strcpy(hardware->auto_label, argv[i] + 6); + strcat(hardware->auto_label," "); + char *pos; + i++; + + /* While we can't find the other AUTO_DELIMITER, let's process the argv[] */ + while(((pos=strstr(argv[i],AUTO_DELIMITER)) == NULL) && (i<argc)) { + strcat(hardware->auto_label,argv[i]); + strcat(hardware->auto_label," "); + i++; + } + + /* If we didn't reach the end of the line, let's grab the last item */ + if (i<argc) { + strcat(hardware->auto_label,argv[i]); + hardware->auto_label[strlen(hardware->auto_label)-1]=0; + } } } } @@ -133,10 +168,13 @@ void init_hardware(struct s_hardware *hardware) memset(hardware->modules_alias_path, 0, sizeof hardware->modules_alias_path); memset(hardware->memtest_label, 0, sizeof hardware->memtest_label); + memset(hardware->reboot_label, 0, sizeof hardware->reboot_label); + memset(hardware->auto_label, 0, sizeof hardware->auto_label); strcat(hardware->pciids_path, "pci.ids"); strcat(hardware->modules_pcimap_path, "modules.pcimap"); strcat(hardware->modules_alias_path, "modules.alias"); strcat(hardware->memtest_label, "memtest"); + strcat(hardware->reboot_label, "reboot.c32"); } /* @@ -269,6 +307,9 @@ void detect_disks(struct s_hardware *hardware) if (err == -1 || !hardware->disk_info[i].cbios) continue; + /* Detect MBR */ + hardware->mbr_ids[i] = get_mbr_id(&hardware->disk_info[i]); + hardware->disks_count++; } } @@ -442,19 +483,23 @@ void detect_pci(struct s_hardware *hardware) hardware->nb_pci_devices++; } - printf("PCI: %d devices detected\n", hardware->nb_pci_devices); - printf("PCI: Resolving names\n"); + if (!quiet) { + more_printf("PCI: %d devices detected\n", hardware->nb_pci_devices); + more_printf("PCI: Resolving names\n"); + } /* Assigning product & vendor name for each device */ hardware->pci_ids_return_code = get_name_from_pci_ids(hardware->pci_domain, hardware->pciids_path); - printf("PCI: Resolving class names\n"); + if (!quiet) + more_printf("PCI: Resolving class names\n"); /* Assigning class name for each device */ hardware->pci_ids_return_code = get_class_name_from_pci_ids(hardware->pci_domain, hardware->pciids_path); - printf("PCI: Resolving module names\n"); + if (!quiet) + more_printf("PCI: Resolving module names\n"); /* Detecting which kernel module should match each device using modules.pcimap*/ hardware->modules_pcimap_return_code = get_module_name_from_pcimap(hardware->pci_domain, @@ -534,6 +579,20 @@ char *remove_spaces(char *p) return p; } +/* remove trailing LF */ +char *remove_trailing_lf(char *p) +{ + char *save=p; + p+=strlen(p)-1; + while (*p && *p == 10) { + *p='\0'; + p--; + } + p=save; + + return p; +} + /* delete multiple spaces, one is enough */ char *del_multi_spaces(char *p) { /* Saving the original pointer*/ diff --git a/com32/hdt/hdt-common.h b/com32/hdt/hdt-common.h index 2b67f9ca..f178b223 100644 --- a/com32/hdt/hdt-common.h +++ b/com32/hdt/hdt-common.h @@ -32,13 +32,22 @@ #include <syslinux/pxe.h> #include "sys/pci.h" +#include <disk/bootloaders.h> +#include <disk/errno_disk.h> +#include <disk/error.h> #include <disk/geom.h> +#include <disk/mbrs.h> +#include <disk/msdos.h> +#include <disk/partition.h> +#include <disk/swsusp.h> +#include <disk/read.h> #include "cpuid.h" #include "dmi/dmi.h" #include "hdt-ata.h" #include "../lib/sys/vesa/vesa.h" #include <vpd/vpd.h> +#include <libansi.h> /* Declare a variable or data structure as unused. */ #define __unused __attribute__ (( unused )) @@ -48,16 +57,42 @@ #define HDT_RETURN_TO_CLI 100 #define MAX_VESA_MODES 255 +/* The maximum number of commands we can process */ +#define MAX_NB_AUTO_COMMANDS 255 +/* The maximum size of a command */ +#define AUTO_COMMAND_SIZE 255 +/* The char that separate two commands */ +#define AUTO_SEPARATOR ";" +/* The char that surround the list of commands */ +#define AUTO_DELIMITER "'" + +/* Defines if the cli is quiet*/ +bool quiet; + extern int display_line_nb; +extern bool disable_more_printf; +#define pause_printf() do {\ + printf("--More--");\ + get_key(stdin, 0);\ + printf("\033[2K\033[1G\033[1F\n");\ +} while (0); + +/* The brokeness of that macro is that + * it assumes that __VA_ARGS__ contains + * one \n (and only one) + */ #define more_printf(...) do {\ - if (display_line_nb == 23) {\ - printf("Press any key to continue\n");\ + if (__likely(!disable_more_printf)) {\ + if (display_line_nb == 20) {\ display_line_nb=0;\ + printf("\n--More--");\ get_key(stdin, 0);\ + printf("\033[2K\033[1G\033[1F");\ + }\ + display_line_nb++;\ }\ - printf ( __VA_ARGS__);\ - display_line_nb++; \ + printf(__VA_ARGS__);\ } while (0); /* Display CPU registers for debugging purposes */ @@ -114,6 +149,7 @@ struct s_hardware { s_vpd vpd; /* VPD information */ struct pci_domain *pci_domain; /* PCI Devices */ struct driveinfo disk_info[256]; /* Disk Information */ + uint32_t mbr_ids[256]; /* MBR ids */ int disks_count; /* Number of detected disks */ struct s_pxe pxe; struct s_vesa vesa; @@ -141,11 +177,14 @@ struct s_hardware { char modules_alias_path[255]; char pciids_path[255]; char memtest_label[255]; + char reboot_label[255]; + char auto_label[AUTO_COMMAND_SIZE]; }; void reset_more_printf(); const char *find_argument(const char **argv, const char *argument); char *remove_spaces(char *p); +char *remove_trailing_lf(char *p); char *skip_spaces(char *p); char *del_multi_spaces(char *p); int detect_dmi(struct s_hardware *hardware); diff --git a/com32/hdt/hdt-menu-about.c b/com32/hdt/hdt-menu-about.c index f19dc361..53b58f21 100644 --- a/com32/hdt/hdt-menu-about.c +++ b/com32/hdt/hdt-menu-about.c @@ -39,29 +39,34 @@ void compute_aboutmenu(struct s_my_menu *menu) set_menu_pos(SUBMENU_Y, SUBMENU_X); - snprintf(buffer, sizeof buffer, "Product : %s", PRODUCT_NAME); + snprintf(buffer, sizeof buffer, "Product : %s", PRODUCT_NAME); snprintf(statbuffer, sizeof statbuffer, "Product : %s", PRODUCT_NAME); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu->items_count++; - snprintf(buffer, sizeof buffer, "Version : %s", VERSION); - snprintf(statbuffer, sizeof statbuffer, "Version : %s", VERSION); + snprintf(buffer, sizeof buffer, "Version : %s (%s)", VERSION, CODENAME); + snprintf(statbuffer, sizeof statbuffer, "Version : %s (%s)", VERSION,CODENAME); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu->items_count++; - snprintf(buffer, sizeof buffer, "Author : %s", AUTHOR); - snprintf(statbuffer, sizeof statbuffer, "Author : %s", AUTHOR); + snprintf(buffer, sizeof buffer, "Project Leader : %s", AUTHOR); + snprintf(statbuffer, sizeof statbuffer, "Project Leader : %s", AUTHOR); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu->items_count++; - snprintf(buffer, sizeof buffer, "Contact : %s", CONTACT); + snprintf(buffer, sizeof buffer, "Contact : %s", CONTACT); snprintf(statbuffer, sizeof statbuffer, "Contact : %s", CONTACT); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu->items_count++; + snprintf(buffer, sizeof buffer, "Core Developer : %s", CORE_DEVELOPER); + snprintf(statbuffer, sizeof statbuffer, "Core Developer : %s", CORE_DEVELOPER); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + char *contributors[NB_CONTRIBUTORS] = CONTRIBUTORS; for (int c=0; c<NB_CONTRIBUTORS; c++) { - snprintf(buffer, sizeof buffer, "Contributor : %s", contributors[c]); + snprintf(buffer, sizeof buffer, "Contributor : %s", contributors[c]); snprintf(statbuffer, sizeof statbuffer, "Contributor : %s", contributors[c]); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu->items_count++; diff --git a/com32/hdt/hdt-menu-disk.c b/com32/hdt/hdt-menu-disk.c index bd33bdf3..2f3571b9 100644 --- a/com32/hdt/hdt-menu-disk.c +++ b/com32/hdt/hdt-menu-disk.c @@ -27,13 +27,6 @@ */ #include <stdlib.h> -#include <disk/errno_disk.h> -#include <disk/geom.h> -#include <disk/read.h> -#include <disk/partition.h> -#include <disk/error.h> -#include <disk/msdos.h> -#include <disk/swsusp.h> #include "hdt-menu.h" #include "hdt-util.h" @@ -81,6 +74,7 @@ static void compute_partition_information(struct driveinfo *drive_info, int nb_partitions_seen) { char size[9]; + char bootloader_name[9]; char *parttype; unsigned int start, end; char buffer[SUBMENULEN+1]; @@ -120,6 +114,14 @@ static void compute_partition_information(struct driveinfo *drive_info, parttype); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + if (get_bootloader_string(drive_info, ptab, bootloader_name, 9) == 0) { + snprintf(buffer, sizeof buffer, "Bootloader : %s", + bootloader_name); + snprintf(statbuffer, sizeof statbuffer, "Bootloader: %s", + bootloader_name); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + } + snprintf(buffer, sizeof buffer, "Bootable : %s", (ptab->active_flag == 0x80) ? "Yes" : "No"); snprintf(statbuffer, sizeof statbuffer, "Bootable: %s", @@ -157,10 +159,12 @@ static void compute_partition_information(struct driveinfo *drive_info, /* Compute the disk submenu */ static int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, - struct driveinfo *d, int disk_number) + const struct s_hardware *hardware, int disk_number) { char buffer[MENULEN + 1]; char statbuffer[STATLEN + 1]; + char mbr_name[50]; + struct driveinfo *d = (struct driveinfo*) hardware->disk_info; snprintf(buffer, sizeof buffer, " Disk <0x%X> (EDD %X)", d[disk_number].disk, d[disk_number].edd_version); @@ -181,10 +185,10 @@ static int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, menu[nb_sub_disk_menu].items_count++; snprintf(buffer, sizeof buffer, "Host Bus / Interface : %s / %s", - remove_spaces(d[disk_number].edd_params.host_bus_type), + remove_spaces((char *) d[disk_number].edd_params.host_bus_type), d[disk_number].edd_params.interface_type); snprintf(statbuffer, sizeof statbuffer, "Host Bus / Interface: %s / %s", - remove_spaces(d[disk_number].edd_params.host_bus_type), + remove_spaces((char *) d[disk_number].edd_params.host_bus_type), d[disk_number].edd_params.interface_type); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; @@ -207,6 +211,17 @@ static int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu[nb_sub_disk_menu].items_count++; + get_mbr_string(hardware->mbr_ids[disk_number], &mbr_name, 50); + + snprintf(buffer, sizeof buffer, "MBR : %s (0x%X)", + remove_spaces(mbr_name), + hardware->mbr_ids[disk_number]); + snprintf(statbuffer, sizeof statbuffer, "MBR: %s (id 0x%X)", + remove_spaces(mbr_name), + hardware->mbr_ids[disk_number]); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu[nb_sub_disk_menu].items_count++; + dn=disk_number; parse_partition_table(&d[disk_number], &show_partition_information); @@ -219,7 +234,7 @@ static int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, } /* Compute the Disks menu */ -void compute_disks(struct s_hdt_menu *menu, struct driveinfo *disk_info, struct s_hardware *hardware) +void compute_disks(struct s_hdt_menu *menu, struct s_hardware *hardware) { char buffer[MENULEN + 1]; int nb_sub_disk_menu = 0; @@ -232,8 +247,8 @@ void compute_disks(struct s_hdt_menu *menu, struct driveinfo *disk_info, struct if (!hardware->disk_info[i].cbios) continue; /* Invalid geometry */ compute_disk_module - ((struct s_my_menu*) &(menu->disk_sub_menu), nb_sub_disk_menu, disk_info, - i); + ((struct s_my_menu*) &(menu->disk_sub_menu), nb_sub_disk_menu, + hardware, i); nb_sub_disk_menu++; } diff --git a/com32/hdt/hdt-menu-kernel.c b/com32/hdt/hdt-menu-kernel.c index 7e2d6cab..81b44dbf 100644 --- a/com32/hdt/hdt-menu-kernel.c +++ b/com32/hdt/hdt-menu-kernel.c @@ -75,7 +75,7 @@ void compute_kernel(struct s_my_menu *menu, struct s_hardware *hardware) kernel_modules, pci_device->dev_info->class_name); snprintf(infobar, sizeof infobar, - "%04x:%04x %s : %s\n", + "%04x:%04x %s : %s", pci_device->vendor, pci_device->product, pci_device->dev_info->vendor_name, diff --git a/com32/hdt/hdt-menu-pci.c b/com32/hdt/hdt-menu-pci.c index 4e0d5887..d4a6b7e7 100644 --- a/com32/hdt/hdt-menu-pci.c +++ b/com32/hdt/hdt-menu-pci.c @@ -167,7 +167,7 @@ int compute_PCI(struct s_hdt_menu *hdt_menu, struct s_hardware *hardware) pci_device->dev_info->vendor_name, pci_device->dev_info->product_name); snprintf(infobar[i], STATLEN, - "%02x:%02x.%01x # %s # ID:%04x:%04x[%04x:%04x] # Kmod:%s\n", + "%02x:%02x.%01x # %s # ID:%04x:%04x[%04x:%04x] # Kmod:%s", __pci_bus, __pci_slot, __pci_func, pci_device->dev_info->class_name, pci_device->vendor, pci_device->product, pci_device->sub_vendor, diff --git a/com32/hdt/hdt-menu-processor.c b/com32/hdt/hdt-menu-processor.c index a30cf0f6..4e102cb5 100644 --- a/com32/hdt/hdt-menu-processor.c +++ b/com32/hdt/hdt-menu-processor.c @@ -231,6 +231,10 @@ void compute_processor(struct s_my_menu *menu, struct s_hardware *hardware) strcat(buffer1, "3dnowext "); if (hardware->cpu.flags.now) strcat(buffer1, "3dnow! "); + if (hardware->cpu.flags.vmx) + strcat(buffer1, "vmx "); + if (hardware->cpu.flags.svm) + strcat(buffer1, "svm "); snprintf(buffer, sizeof buffer, "Flags : %s", buffer1); snprintf(statbuffer, sizeof statbuffer, "Flags: %s", buffer1); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); diff --git a/com32/hdt/hdt-menu-summary.c b/com32/hdt/hdt-menu-summary.c index 6401221a..e8e2fc65 100644 --- a/com32/hdt/hdt-menu-summary.c +++ b/com32/hdt/hdt-menu-summary.c @@ -189,7 +189,7 @@ void compute_summarymenu(struct s_my_menu *menu, struct s_hardware *hardware) kernel_modules, pci_device->dev_info->class_name); snprintf(statbuffer, sizeof statbuffer, - "%04x:%04x %s : %s\n", + "%04x:%04x %s : %s", pci_device->vendor, pci_device->product, pci_device->dev_info->vendor_name, diff --git a/com32/hdt/hdt-menu-syslinux.c b/com32/hdt/hdt-menu-syslinux.c index 4c874d0e..758274fe 100644 --- a/com32/hdt/hdt-menu-syslinux.c +++ b/com32/hdt/hdt-menu-syslinux.c @@ -76,8 +76,9 @@ void compute_syslinuxmenu(struct s_my_menu *menu, struct s_hardware *hardware) snprintf(buffer, sizeof buffer, "%s", hardware->sv->copyright_string + 1); + /* Remove the trailing LF in the copyright string to avoid scrolling */ snprintf(statbuffer, sizeof statbuffer, "%s", - hardware->sv->copyright_string + 1); + remove_trailing_lf(hardware->sv->copyright_string + 1)); add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); menu->items_count++; diff --git a/com32/hdt/hdt-menu.c b/com32/hdt/hdt-menu.c index c37fd41b..98eb45e7 100644 --- a/com32/hdt/hdt-menu.c +++ b/com32/hdt/hdt-menu.c @@ -27,6 +27,7 @@ */ #include "hdt-menu.h" +#include <unistd.h> int start_menu_mode(struct s_hardware *hardware, char *version_string) { @@ -50,7 +51,8 @@ int start_menu_mode(struct s_hardware *hardware, char *version_string) t_menuitem *curr; char cmd[160]; - printf("Starting Menu (%d menus)\n", hdt_menu.total_menu_count); + if (!quiet) + more_printf("Starting Menu (%d menus)\n", hdt_menu.total_menu_count); curr = showmenus(hdt_menu.main_menu.menu); /* When we exit the menu, do we have something to do? */ if (curr) { @@ -84,26 +86,32 @@ TIMEOUTCODE ontimeout() } /* Keyboard handler for the menu system */ -void keys_handler(t_menusystem * ms, t_menuitem * mi, unsigned int scancode) +void keys_handler(t_menusystem * ms __attribute__ (( unused )), t_menuitem * mi, int scancode) { - char nc; + int nr, nc; - if ((scancode >> 8) == F1) { // If scancode of F1 + /* 0xFFFF is an invalid helpid */ + if (scancode == KEY_F1 && mi->helpid != 0xFFFF) { runhelpsystem(mi->helpid); } + /* * If user hit TAB, and item is an "executable" item * and user has privileges to edit it, edit it in place. */ - if (((scancode & 0xFF) == 0x09) && (mi->action == OPT_RUN)) { + if ((scancode == KEY_TAB) && (mi->action == OPT_RUN)) { //(isallowed(username,"editcmd") || isallowed(username,"root"))) { - nc = getnumcols(); + if (getscreensize(1, &nr, &nc)) { + /* Unknown screen size? */ + nc = 80; + nr = 24; + } /* User typed TAB and has permissions to edit command line */ - gotoxy(EDITPROMPT, 1, ms->menupage); + gotoxy(EDITPROMPT, 1); csprint("Command line:", 0x07); editstring(mi->data, ACTIONLEN); - gotoxy(EDITPROMPT, 1, ms->menupage); - cprint(' ', 0x07, nc - 1, ms->menupage); + gotoxy(EDITPROMPT, 1); + cprint(' ', 0x07, nc - 1); } } @@ -114,6 +122,9 @@ void setup_menu(char *version) init_menusystem(version); set_window_size(0, 0, 25, 80); + /* Do not use inactive attributes - they make little sense for HDT */ + set_normal_attr(-1, -1, 0x17, 0x1F); + /* Register the menusystem handler */ // reg_handler(HDLR_SCREEN,&msys_handler); reg_handler(HDLR_KEYS, &keys_handler); @@ -154,7 +165,7 @@ void compute_submenus(struct s_hdt_menu *hdt_menu, struct s_hardware *hardware) compute_processor(&(hdt_menu->cpu_menu), hardware); compute_vpd(&(hdt_menu->vpd_menu), hardware); - compute_disks(hdt_menu, hardware->disk_info, hardware); + compute_disks(hdt_menu, hardware); #ifdef WITH_PCI compute_PCI(hdt_menu, hardware); @@ -282,6 +293,7 @@ void compute_main_menu(struct s_hdt_menu *hdt_menu, struct s_hardware *hardware) HDT_SWITCH_TO_CLI, 0); add_item("<A>bout", "About Menu", OPT_SUBMENU, NULL, hdt_menu->about_menu.menu); + add_item("<R>eboot", "Reboot", OPT_RUN, hardware->reboot_label, 0); add_item("E<x>it","Exit", OPT_EXITMENU,NULL,0); hdt_menu->main_menu.items_count++; @@ -290,30 +302,37 @@ void compute_main_menu(struct s_hdt_menu *hdt_menu, struct s_hardware *hardware) void detect_hardware(struct s_hardware *hardware) { - printf("CPU: Detecting\n"); + if (!quiet) + more_printf("CPU: Detecting\n"); cpu_detect(hardware); - printf("DISKS: Detecting\n"); + if (!quiet) + more_printf("DISKS: Detecting\n"); detect_disks(hardware); - printf("DMI: Detecting Table\n"); + if (!quiet) + more_printf("DMI: Detecting Table\n"); if (detect_dmi(hardware) == -ENODMITABLE) { printf("DMI: ERROR ! Table not found ! \n"); printf ("DMI: Many hardware components will not be detected ! \n"); } else { - printf("DMI: Table found ! (version %d.%d)\n", - hardware->dmi.dmitable.major_version, - hardware->dmi.dmitable.minor_version); + if (!quiet) + more_printf("DMI: Table found ! (version %u.%u)\n", + hardware->dmi.dmitable.major_version, + hardware->dmi.dmitable.minor_version); } - printf("VPD: Detecting\n"); + if (!quiet) + more_printf("VPD: Detecting\n"); detect_vpd(hardware); #ifdef WITH_PCI detect_pci(hardware); - printf("PCI: %d Devices Found\n", hardware->nb_pci_devices); + if (!quiet) + more_printf("PCI: %d Devices Found\n", hardware->nb_pci_devices); #endif - printf("VESA: Detecting\n"); + if (!quiet) + more_printf("VESA: Detecting\n"); detect_vesa(hardware); } diff --git a/com32/hdt/hdt-menu.h b/com32/hdt/hdt-menu.h index 1cd2c129..8743da35 100644 --- a/com32/hdt/hdt-menu.h +++ b/com32/hdt/hdt-menu.h @@ -29,6 +29,7 @@ #ifndef DEFINE_HDT_MENU_H #define DEFINE_HDT_MENU_H #include <stdio.h> +#include <getkey.h> #include "menu.h" #include "help.h" @@ -82,7 +83,7 @@ struct s_hdt_menu { }; TIMEOUTCODE ontimeout(); -void keys_handler(t_menusystem * ms, t_menuitem * mi, unsigned int scancode); +void keys_handler(t_menusystem * ms __attribute__ (( unused )), t_menuitem * mi, int scancode); // PCI Stuff int compute_PCI(struct s_hdt_menu *hdt_menu, struct s_hardware *hardware); @@ -91,7 +92,7 @@ int compute_PCI(struct s_hdt_menu *hdt_menu, struct s_hardware *hardware); void compute_kernel(struct s_my_menu *menu, struct s_hardware *hardware); // Disk Stuff -void compute_disks(struct s_hdt_menu *menu, struct driveinfo *disk_info, struct s_hardware *hardware); +void compute_disks(struct s_hdt_menu *menu, struct s_hardware *hardware); // DMI Stuff void compute_motherboard(struct s_my_menu *menu, s_dmi * dmi); diff --git a/com32/hdt/hdt.c b/com32/hdt/hdt.c index 93c4aae2..0fe2021b 100644 --- a/com32/hdt/hdt.c +++ b/com32/hdt/hdt.c @@ -37,10 +37,10 @@ #include <consoles.h> #include "hdt.h" #include "hdt-menu.h" -#include "hdt-cli.h" #include "hdt-common.h" int display_line_nb = 0; +bool disable_more_printf = false; int main(const int argc, const char *argv[]) { @@ -48,8 +48,8 @@ int main(const int argc, const char *argv[]) const char *arg; struct s_hardware hardware; - snprintf(version_string, sizeof version_string, "%s %s by %s", - PRODUCT_NAME,VERSION,AUTHOR); + snprintf(version_string, sizeof version_string, "%s %s (%s)", + PRODUCT_NAME,VERSION, CODENAME); /* Opening the Syslinux console */ console_ansi_raw(); @@ -63,20 +63,19 @@ int main(const int argc, const char *argv[]) /* Detecting parameters */ detect_parameters(argc, argv, &hardware); - + /* Clear the screen and reset position of the cursor */ clear_screen(); - printf("%s\n", version_string); + printf("\033[1;1H"); - if ((arg = find_argument(argv + 1, "nomenu"))) - start_cli_mode(&hardware); + printf("%s\n", version_string); + if ((arg = find_argument(argv + 1, "nomenu")) || (find_argument(argv+1,"auto"))) + start_cli_mode(&hardware); else { - int return_code = start_menu_mode(&hardware, version_string); - - if (return_code == HDT_RETURN_TO_CLI) - start_cli_mode(&hardware); - else - return return_code; + int return_code = start_menu_mode(&hardware, version_string); + if (return_code == HDT_RETURN_TO_CLI) + start_cli_mode(&hardware); + else + return return_code; } - return 0; } diff --git a/com32/hdt/hdt.h b/com32/hdt/hdt.h index 04c0e664..2c2c8796 100644 --- a/com32/hdt/hdt.h +++ b/com32/hdt/hdt.h @@ -31,10 +31,12 @@ #define PRODUCT_NAME "Hardware Detection Tool" #define AUTHOR "Erwan Velu" +#define CORE_DEVELOPER "Pierre-Alexandre Meyer" #define CONTACT "hdt@zytor.com" -#define VERSION "0.3.4" +#define VERSION "0.3.5-pre3" +#define CODENAME "mojito" #define NB_CONTRIBUTORS 2 -#define CONTRIBUTORS {"Pierre-Alexandre Meyer", "Sebastien Gonzalve"} +#define CONTRIBUTORS {"Sebastien Gonzalve", "Gert Hulselmans"} #define ATTR_PACKED __attribute__((packed)) diff --git a/com32/hdt/lib-ansi.c b/com32/hdt/lib-ansi.c deleted file mode 100644 index 411dba80..00000000 --- a/com32/hdt/lib-ansi.c +++ /dev/null @@ -1,104 +0,0 @@ -/* ----------------------------------------------------------------------- * - * - * Copyright 2009 Erwan Velu - 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. - * - * ----------------------------------------------------------------------- - * Ansi Sequences can be found here : - * http://ascii-table.com/ansi-escape-sequences-vt-100.php - * http://en.wikipedia.org/wiki/ANSI_escape_code - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <stdbool.h> - -void display_cursor(bool status) -{ - if (status == true) { - fputs("\033[?25h", stdout); - } else { - fputs("\033[?25l", stdout); - } -} - -void clear_end_of_line() { - fputs("\033[0K", stdout); -} - -void move_cursor_left(int count) { - char buffer[10]; - memset(buffer,0,sizeof(buffer)); - sprintf(buffer,"\033[%dD",count); - fputs(buffer, stdout); -} - -void move_cursor_right(int count) { - char buffer[10]; - memset(buffer,0,sizeof(buffer)); - sprintf(buffer,"\033[%dC",count); - fputs(buffer, stdout); -} - -void set_cursor_blink(bool status) { - if (status == true) - fputs("\033[05m",stdout); - else - fputs("\033[0m",stdout); -} - -void clear_line() { - fputs("\033[2K", stdout); -} - -void clear_beginning_of_line() { - fputs("\033[1K", stdout); -} - -void move_cursor_to_column(int count) { - char buffer[10]; - memset(buffer,0,sizeof(buffer)); - sprintf(buffer,"\033[%dG",count); - fputs(buffer, stdout); -} - -void move_cursor_to_next_line() { - fputs("\033e", stdout); -} - -void disable_utf8() { - fputs("\033%@", stdout); -} - -void set_g1_special_char(){ - fputs("\033)0", stdout); -} - -void set_us_g0_charset() { - fputs("\033(B\1#0", stdout); -} - -void clear_entire_screen() { - fputs("\033[2J", stdout); -} diff --git a/com32/include/cpufeature.h b/com32/include/cpufeature.h index 2fd47579..036631a7 100644 --- a/com32/include/cpufeature.h +++ b/com32/include/cpufeature.h @@ -72,6 +72,7 @@ #define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */ #define X86_FEATURE_MWAIT (4*32+ 3) /* Monitor/Mwait support */ #define X86_FEATURE_DSCPL (4*32+ 4) /* CPL Qualified Debug Store */ +#define X86_FEATURE_VMX (4*32+ 5) /* Hardware virtualization */ #define X86_FEATURE_EST (4*32+ 7) /* Enhanced SpeedStep */ #define X86_FEATURE_TM2 (4*32+ 8) /* Thermal Monitor 2 */ #define X86_FEATURE_CID (4*32+10) /* Context ID */ @@ -87,6 +88,7 @@ /* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */ #define X86_FEATURE_LAHF_LM (6*32+ 0) /* LAHF/SAHF in long mode */ #define X86_FEATURE_CMP_LEGACY (6*32+ 1) /* If yes HyperThreading not valid */ +#define X86_FEATURE_SVM (6*32+ 2) /* Secure virtual machine */ #endif /* __ASM_I386_CPUFEATURE_H */ diff --git a/com32/hdt/lib-ansi.h b/com32/include/libansi.h index 0b0d0d18..d813f9fc 100644 --- a/com32/hdt/lib-ansi.h +++ b/com32/include/libansi.h @@ -28,17 +28,76 @@ #ifndef DEFINE_LIB_ANSI_H #define DEFINE_LIB_ANSI_H + +#define CSI "\e[" + void display_cursor(bool status); -void clear_end_of_line(); +void clear_end_of_line(void); void move_cursor_left(int count); void move_cursor_right(int count); -void clear_line(); -void clear_beginning_of_line(); +void clear_line(void); +void clear_beginning_of_line(void); void move_cursor_to_column(int count); -void move_cursor_to_next_line(); -void disable_utf8(); -void set_g1_special_char(); -void set_us_g0_charset(); -void clear_entire_screen(); +void move_cursor_to_next_line(void); +void disable_utf8(void); +void set_g1_special_char(void); +void set_us_g0_charset(void); +void clear_entire_screen(void); void set_cursor_blink(bool status); +void move_cursor_to_next_line(void); +void disable_utf8(void); +void set_g1_special_char(void); +void set_us_g0_charset(void); +void clear_entire_screen(void); +void clearwindow(const char top, const char left, const char bot, + const char right, const char fillchar, const char fillattr); + +static inline void beep(void) +{ + fputs("\007", stdout); +} + +void reset_colors(void); + +/* Print a string */ +void csprint(const char *, const char); + +/* Print one character, one or more times */ +void cprint(const char, const char, unsigned int); + +/* Print one character, once */ +static inline void putch(const char x, char attr) +{ + cprint(x, attr, 1); +} + +void cls(void); + +static inline void cursoroff(void) +{ + display_cursor(false); +} + +static inline void cursoron(void) +{ + display_cursor(true); +} + +static inline void scrollup(int times) +{ + if (times > 0) + printf(CSI "%dS", times); +} + +/* Scroll up display screen by one line */ +static inline void scrollup_once(void) +{ + printf(CSI "S"); +} + +static inline void gotoxy(const char row, const char col) +{ + printf(CSI "%d;%dH", row + 1, col + 1); +} + #endif diff --git a/com32/lib/Makefile b/com32/lib/Makefile index c5b19813..ecf4dfeb 100644 --- a/com32/lib/Makefile +++ b/com32/lib/Makefile @@ -54,6 +54,8 @@ LIBOBJS = \ \ sys/ansi.o \ \ + sys/libansi.o \ + \ sys/ansicon_write.o sys/ansiserial_write.o \ \ sys/vesacon_write.o sys/vesaserial_write.o \ diff --git a/com32/lib/sys/ansi.c b/com32/lib/sys/ansi.c index 7d580856..17ace1d4 100644 --- a/com32/lib/sys/ansi.c +++ b/com32/lib/sys/ansi.c @@ -36,21 +36,22 @@ #include "ansi.h" static const struct term_state default_state = { + .state = st_init, + .pvt = false, + .nparms = 0, .xy = {0, 0}, .cindex = 0, /* First color table entry */ - .vtgraphics = 0, + .vtgraphics = false, .intensity = 1, - .underline = 0, - .blink = 0, - .reverse = 0, + .underline = false, + .blink = false, + .reverse = false, .fg = 7, .bg = 0, - .autocr = 1, /* Mimic \n -> \r\n conversion by default */ + .autocr = true, /* Mimic \n -> \r\n conversion by default */ + .autowrap = true, /* Wrap lines by default */ .saved_xy = {0, 0}, - .cursor = 1, - .state = st_init, - .pvt = 0, - .nparms = 0, + .cursor = true, }; /* DEC VT graphics to codepage 437 table (characters 0x60-0x7F only) */ @@ -123,7 +124,7 @@ void __ansi_putchar(const struct term_info *ti, uint8_t ch) if (st->vtgraphics && (ch & 0xe0) == 0x60) ch = decvt_to_cp437[ch - 0x60]; - op->write_char(xy.x, xy.y, ch, st); + op->write_char(xy.x, xy.y, BIOS_PAGE, ch, st); xy.x++; } break; @@ -141,7 +142,8 @@ void __ansi_putchar(const struct term_info *ti, uint8_t ch) break; case '[': st->state = st_csi; - st->nparms = st->pvt = 0; + st->nparms = 0; + st->pvt = false; memset(st->parms, 0, sizeof st->parms); break; case 'c': @@ -170,7 +172,7 @@ void __ansi_putchar(const struct term_info *ti, uint8_t ch) st->nparms = ANSI_MAX_PARMS - 1; break; } else if (ch == '?') { - st->pvt = 1; + st->pvt = true; } else { switch (ch) { case 'A': @@ -278,22 +280,25 @@ void __ansi_putchar(const struct term_info *ti, uint8_t ch) break; case 'h': case 'l': - { - int set = (ch == 'h'); - switch (st->parms[0]) { - case 20: - st->autocr = set; - break; - case 25: - st->cursor = set; - op->showcursor(st); - break; - default: - /* Ignore */ - break; - } + { + bool set = (ch == 'h'); + switch (st->parms[0]) { + case 7: /* DECAWM */ + st->autowrap = set; + break; + case 20: /* LNM */ + st->autocr = set; + break; + case 25: /* DECTECM */ + st->cursor = set; + op->showcursor(st); + break; + default: + /* Ignore */ + break; } break; + } case 'm': { static const int ansi2pc[8] = @@ -421,8 +426,12 @@ void __ansi_putchar(const struct term_info *ti, uint8_t ch) /* If we fell off the end of the screen, adjust */ if (xy.x >= cols) { - xy.x = 0; - xy.y++; + if (st->autowrap) { + xy.x = 0; + xy.y++; + } else { + xy.x = cols - 1; + } } while (xy.y >= rows) { xy.y--; @@ -430,6 +439,6 @@ void __ansi_putchar(const struct term_info *ti, uint8_t ch) } /* Update cursor position */ - op->set_cursor(xy.x, xy.y, st->cursor); + op->set_cursor(xy.x, xy.y, BIOS_PAGE, st->cursor); st->xy = xy; } diff --git a/com32/lib/sys/ansi.h b/com32/lib/sys/ansi.h index 0d1f1025..ed4b01cb 100644 --- a/com32/lib/sys/ansi.h +++ b/com32/lib/sys/ansi.h @@ -6,9 +6,15 @@ #define COM32_LIB_SYS_ANSI_H #include <inttypes.h> +#include <stdbool.h> #define ANSI_MAX_PARMS 16 +#define BIOS_CURXY ((struct curxy *)0x450) /* Array for each page */ +#define BIOS_ROWS (*(uint8_t *)0x484) /* Minus one; if zero use 24 (= 25 lines) */ +#define BIOS_COLS (*(uint16_t *)0x44A) /* Number of columns on screen */ +#define BIOS_PAGE (*(uint8_t *)0x462) /* Current page number */ + enum ansi_state { st_init, st_esc, @@ -22,31 +28,32 @@ struct curxy { } __attribute__ ((packed)); struct term_state { - struct curxy xy; - int cindex; /* SOH color index */ - int vtgraphics; /* VT graphics on/off */ - int intensity; - int underline; - int blink; - int reverse; - int fg; - int bg; - int autocr; - struct curxy saved_xy; - int cursor; enum ansi_state state; - int pvt; /* Private code? */ int nparms; /* Number of parameters seen */ int parms[ANSI_MAX_PARMS]; + bool pvt; /* Private code? */ + struct curxy xy; + struct curxy saved_xy; + uint8_t cindex; /* SOH color index */ + uint8_t fg; + uint8_t bg; + uint8_t intensity; + bool vtgraphics; /* VT graphics on/off */ + bool underline; + bool blink; + bool reverse; + bool autocr; + bool autowrap; + bool cursor; }; struct ansi_ops { void (*erase) (const struct term_state * st, int x0, int y0, int x1, int y1); - void (*write_char) (int x, int y, uint8_t ch, const struct term_state * st); + void (*write_char) (int x, int y, int page, uint8_t ch, const struct term_state * st); void (*showcursor) (const struct term_state * st); void (*scroll_up) (const struct term_state * st); - void (*set_cursor) (int x, int y, int visible); + void (*set_cursor) (int x, int y, int page, int visible); void (*beep) (void); }; diff --git a/com32/lib/sys/ansicon_write.c b/com32/lib/sys/ansicon_write.c index 7c2754e7..8ec16b0a 100644 --- a/com32/lib/sys/ansicon_write.c +++ b/com32/lib/sys/ansicon_write.c @@ -44,10 +44,10 @@ #include "ansi.h" static void ansicon_erase(const struct term_state *, int, int, int, int); -static void ansicon_write_char(int, int, uint8_t, const struct term_state *); +static void ansicon_write_char(int, int, int, uint8_t, const struct term_state *); static void ansicon_showcursor(const struct term_state *); static void ansicon_scroll_up(const struct term_state *); -static void ansicon_set_cursor(int, int, int); +static void ansicon_set_cursor(int, int, int, int); static struct term_state ts; struct ansi_ops __ansicon_ops = { @@ -65,11 +65,6 @@ static struct term_info ti = { .op = &__ansicon_ops }; -#define BIOS_CURXY ((struct curxy *)0x450) /* Array for each page */ -#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) - /* Reference counter to the screen, to keep track of if we need reinitialization. */ static int ansicon_counter = 0; @@ -176,9 +171,8 @@ static void ansicon_showcursor(const struct term_state *st) __intcall(0x10, &ireg, NULL); } -static void ansicon_set_cursor(int x, int y, int visible) +static void ansicon_set_cursor(int x, int y, int page, int visible) { - const int page = BIOS_PAGE; struct curxy xy = BIOS_CURXY[page]; static com32sys_t ireg; @@ -193,16 +187,16 @@ static void ansicon_set_cursor(int x, int y, int visible) } } -static void ansicon_write_char(int x, int y, uint8_t ch, +static void ansicon_write_char(int x, int y, int page, uint8_t ch, const struct term_state *st) { static com32sys_t ireg; - ansicon_set_cursor(x, y, 0); + ansicon_set_cursor(x, y, 0, page); ireg.eax.b[1] = 0x09; ireg.eax.b[0] = ch; - ireg.ebx.b[1] = BIOS_PAGE; + ireg.ebx.b[1] = page; ireg.ebx.b[0] = ansicon_attribute(st); ireg.ecx.w[0] = 1; __intcall(0x10, &ireg, NULL); diff --git a/com32/lib/sys/libansi.c b/com32/lib/sys/libansi.c new file mode 100644 index 00000000..5bc0026e --- /dev/null +++ b/com32/lib/sys/libansi.c @@ -0,0 +1,237 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Erwan Velu - 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. + * + * ----------------------------------------------------------------------- + * Ansi Sequences can be found here : + * http://ascii-table.com/ansi-escape-sequences-vt-100.php + * http://en.wikipedia.org/wiki/ANSI_escape_code + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdbool.h> +#include <stdint.h> + +#include "libansi.h" + +void display_cursor(bool status) +{ + if (status == true) { + fputs(CSI "?25h", stdout); + } else { + fputs(CSI "?25l", stdout); + } +} + +void clear_end_of_line() { + fputs(CSI "0K", stdout); +} + +void move_cursor_left(int count) { + char buffer[10]; + memset(buffer,0,sizeof(buffer)); + sprintf(buffer,CSI "%dD",count); + fputs(buffer, stdout); +} + +void move_cursor_right(int count) { + char buffer[10]; + memset(buffer,0,sizeof(buffer)); + sprintf(buffer, CSI "%dC", count); + fputs(buffer, stdout); +} + +void set_cursor_blink(bool status) { + if (status == true) + fputs("\033[05m",stdout); + else + fputs("\033[0m",stdout); +} + +void clear_line() { + fputs(CSI "2K", stdout); +} + +void clear_beginning_of_line() { + fputs(CSI "1K", stdout); +} + +void move_cursor_to_column(int count) { + char buffer[10]; + memset(buffer,0,sizeof(buffer)); + sprintf(buffer, CSI "%dG", count); + fputs(buffer, stdout); +} + +void move_cursor_to_next_line() { + fputs("\033e", stdout); +} + +void disable_utf8() { + fputs("\033%@", stdout); +} + +void set_g1_special_char(){ + fputs("\033)0", stdout); +} + +void set_us_g0_charset() { + fputs("\033(B\1#0", stdout); +} + +void clear_entire_screen() { + fputs(CSI "2J", stdout); +} + +/** + * cprint_vga2ansi - given a VGA attribute, print a character + * @chr: character to print + * @attr: vga attribute + * + * Convert the VGA attribute @attr to an ANSI escape sequence and + * print it. + * For performance, SGR parameters are cached. To reset them, + * call cprint_vga2ansi('0', '0'). + **/ +static void cprint_vga2ansi(const char chr, const char attr) +{ + static const char ansi_char[8] = "04261537"; + static uint16_t last_attr = 0x300; + char buf[16], *p; + + if (chr == '0' && attr == '0') { + last_attr = 0x300; + return; + } + + if (attr != last_attr) { + bool reset = false; + p = buf; + *p++ = '\033'; + *p++ = '['; + + if (last_attr & ~attr & 0x88) { + *p++ = '0'; + *p++ = ';'; + /* Reset last_attr to unknown to handle + * background/foreground attributes correctly */ + last_attr = 0x300; + reset = true; + } + if (attr & 0x08) { + *p++ = '1'; + *p++ = ';'; + } + if (attr & 0x80) { + *p++ = '4'; + *p++ = ';'; + } + if (reset || (attr ^ last_attr) & 0x07) { + *p++ = '3'; + *p++ = ansi_char[attr & 7]; + *p++ = ';'; + } + if (reset || (attr ^ last_attr) & 0x70) { + *p++ = '4'; + *p++ = ansi_char[(attr >> 4) & 7]; + *p++ = ';'; + } + p[-1] = 'm'; /* We'll have generated at least one semicolon */ + p[0] = '\0'; + + last_attr = attr; + + fputs(buf, stdout); + } + + putchar(chr); +} + +/* + * cls - clear and initialize the entire screen + * + * Note: when initializing xterm, one has to specify that + * G1 points to the alternate character set (this is not true + * by default). Without the initial printf "\033)0", line drawing + * characters won't be displayed. + */ +void cls(void) +{ + fputs("\033e\033%@\033)0\033(B\1#0\033[?25l\033[2J", stdout); + + /* Reset SGR parameters cache */ + cprint_vga2ansi('0', '0'); +} + +void reset_colors() +{ + csprint(CSI "1D", 0x07); +} + +/** + * cprint - given a VGA attribute, print a single character at cursor + * @chr: character to print + * @attr: VGA attribute + * @times: number of times to print @chr + * + * Note: @attr is a VGA attribute. + **/ +void cprint(const char chr, const char attr, unsigned int times) +{ + while (times--) + cprint_vga2ansi(chr, attr); +} + +/** + * csprint - given a VGA attribute, print a NULL-terminated string + * @str: string to print + * @attr: VGA attribute + **/ +void csprint(const char *str, const char attr) +{ + while (*str) { + cprint(*str, attr, 1); + str++; + } +} + +/** + * clearwindow - fill a given a region on the screen + * @top, @left, @bot, @right: coordinates to fill + * @fillchar: character to use to fill the region + * @fillattr: character attribute (VGA) + **/ +void clearwindow(const char top, const char left, const char bot, + const char right, const char fillchar, const char fillattr) +{ + char x; + for (x = top; x < bot + 1; x++) { + gotoxy(x, left); + cprint(fillchar, fillattr, right - left + 1); + } +} + + diff --git a/com32/mboot/map.c b/com32/mboot/map.c index 1a788ef7..887776fe 100644 --- a/com32/mboot/map.c +++ b/com32/mboot/map.c @@ -127,7 +127,7 @@ int map_image(void *ptr, size_t len) else mbh_len = 12; - if (i + mbh_len < len) + if (i + mbh_len > len) mbh_len = 0; /* Invalid... */ else break; /* Found something... */ diff --git a/com32/modules/Makefile b/com32/modules/Makefile index 68e50571..4e262782 100644 --- a/com32/modules/Makefile +++ b/com32/modules/Makefile @@ -18,10 +18,10 @@ topdir = ../.. include ../MCONFIG -MODULES = chain.c32 config.c32 ethersel.c32 dmitest.c32 cpuidtest.c32 disk.c32 \ - pcitest.c32 elf.c32 linux.c32 reboot.c32 pmload.c32 meminfo.c32 \ - sdi.c32 sanboot.c32 ifcpu64.c32 vesainfo.c32 kbdmap.c32 cmd.c32 \ - vpdtest.c32 host.c32 dir.c32 +MODULES = chain.c32 config.c32 ethersel.c32 dmitest.c32 cpuidtest.c32 \ + disk.c32 pcitest.c32 elf.c32 linux.c32 reboot.c32 pmload.c32 \ + meminfo.c32 sdi.c32 sanboot.c32 ifcpu64.c32 vesainfo.c32 \ + kbdmap.c32 cmd.c32 vpdtest.c32 host.c32 dir.c32 gpxecmd.c32 TESTFILES = diff --git a/com32/modules/chain.c b/com32/modules/chain.c index bdeb82d5..27220143 100644 --- a/com32/modules/chain.c +++ b/com32/modules/chain.c @@ -39,6 +39,12 @@ * seg=<segment>: * loads at and jumps to <seg>:0000 instead of 0000:7C00. * + * isolinux=<loader>: + * chainload another version/build of the ISOLINUX bootloader and patch + * the loader with appropriate parameters in memory. + * This avoids the need for the -eltorito-alt-boot parameter of mkisofs, + * when you want more than one ISOLINUX per CD/DVD. + * * ntldr=<loader>: * equivalent to -seg 0x2000 -file <loader>, used with WinNT's loaders * @@ -77,6 +83,7 @@ static struct options { const char *loadfile; uint16_t keeppxe; uint16_t seg; + bool isolinux; bool swap; bool hide; } opt; @@ -446,7 +453,7 @@ static void do_boot(void *boot_sector, size_t boot_size, mmap = syslinux_memory_map(); if (!mmap) { - error("Cannot read system memory map"); + error("Cannot read system memory map\n"); return; } @@ -546,12 +553,12 @@ static void do_boot(void *boot_sector, size_t boot_size, error("Chainboot failed!\n"); return; -too_big: - error("Loader file too large"); + too_big: + error("Loader file too large\n"); return; -enomem: - error("Out of memory"); + enomem: + error("Out of memory\n"); return; } @@ -589,6 +596,47 @@ static int hide_unhide(char *mbr, int part) return 0; /* ok */ } +static uint32_t get_file_lba(const char *filename) +{ + com32sys_t inregs; + uint32_t lba; + + /* Start with clean registers */ + memset(&inregs, 0, sizeof(com32sys_t)); + + /* Put the filename in the bounce buffer */ + strlcpy(__com32.cs_bounce, filename, __com32.cs_bounce_size); + + /* Call comapi_open() which returns a structure pointer in SI + * to a structure whose first member happens to be the LBA. + */ + inregs.eax.w[0] = 0x0006; + inregs.esi.w[0] = OFFS(__com32.cs_bounce); + inregs.es = SEG(__com32.cs_bounce); + __com32.cs_intcall(0x22, &inregs, &inregs); + + if ((inregs.eflags.l & EFLAGS_CF) || inregs.esi.w[0] == 0) { + return 0; /* Filename not found */ + } + + /* Since the first member is the LBA, we simply cast */ + lba = *((uint32_t *) MK_PTR(inregs.ds, inregs.esi.w[0])); + + /* Clean the registers for the next call */ + memset(&inregs, 0, sizeof(com32sys_t)); + + /* Put the filename in the bounce buffer */ + strlcpy(__com32.cs_bounce, filename, __com32.cs_bounce_size); + + /* Call comapi_close() to free the structure */ + inregs.eax.w[0] = 0x0008; + inregs.esi.w[0] = OFFS(__com32.cs_bounce); + inregs.es = SEG(__com32.cs_bounce); + __com32.cs_intcall(0x22, &inregs, &inregs); + + return lba; +} + int main(int argc, char *argv[]) { char *mbr, *p; @@ -598,6 +646,9 @@ int main(int argc, char *argv[]) char *drivename, *partition; int hd, drive, whichpart; int i; + uint32_t file_lba = 0; + unsigned char *isolinux_bin; + uint32_t *checksum, *chkhead, *chktail; size_t boot_size = SECTOR; openconsole(&dev_null_r, &dev_stdcon_w); @@ -614,10 +665,13 @@ int main(int argc, char *argv[]) } else if (!strncmp(argv[i], "seg=", 4)) { uint32_t segval = strtoul(argv[i] + 4, NULL, 0); if (segval < 0x50 || segval > 0x9f000) { - error("Invalid segment"); + error("Invalid segment\n"); goto bail; } opt.seg = segval; + } else if (!strncmp(argv[i], "isolinux=", 9)) { + opt.loadfile = argv[i] + 9; + opt.isolinux = true; } else if (!strncmp(argv[i], "ntldr=", 6)) { opt.seg = 0x2000; /* NTLDR wants this address */ opt.loadfile = argv[i] + 6; @@ -650,7 +704,19 @@ int main(int argc, char *argv[]) } } else { error - ("Usage: chain.c32 (hd#|fd#|mbr:#|boot)[,partition] [options]\n"); + ("Usage: chain.c32 hd<disk#> [<partition>] [options]\n" + " chain.c32 fd<disk#> [options]\n" + " chain.c32 mbr:<id> [<partition>] [options]\n" + " chain.c32 boot [<partition>] [options]\n" + "Options: file=<loader> load file, instead of boot sector\n" + " isolinux=<loader> load another version of ISOLINUX\n" + " ntldr=<loader> load Windows bootloaders: NTLDR, SETUPLDR, BOOTMGR\n" + " freedos=<loader> load FreeDOS kernel.sys\n" + " msdos=<loader> load MS-DOS io.sys\n" + " pcdos=<loader> load PC-DOS ibmbio.com\n" + " seg=<segment> jump to <seg>:0000 instead of 0000:7C00\n" + " swap swap drive numbers, if bootdisk is not fd0/hd0\n" + " hide hide primary partitions, except selected partition\n"); goto bail; } } @@ -748,6 +814,64 @@ int main(int argc, char *argv[]) error("Failed to load the boot file\n"); goto bail; } + + /* Create boot info table: needed when you want to chainload + another version of ISOLINUX (or another bootlaoder that needs + the -boot-info-table switch of mkisofs) + (will only work when run from ISOLINUX) */ + if (opt.isolinux) { + const union syslinux_derivative_info *sdi; + sdi = syslinux_derivative_info(); + + if (sdi->c.filesystem == SYSLINUX_FS_ISOLINUX) { + /* Boot info table info (integers in little endian format) + + Offset Name Size Meaning + 8 bi_pvd 4 bytes LBA of primary volume descriptor + 12 bi_file 4 bytes LBA of boot file + 16 bi_length 4 bytes Boot file length in bytes + 20 bi_csum 4 bytes 32-bit checksum + 24 bi_reserved 40 bytes Reserved + + The 32-bit checksum is the sum of all the 32-bit words in the + boot file starting at byte offset 64. All linear block + addresses (LBAs) are given in CD sectors (normally 2048 bytes). + + LBA of primary volume descriptor should already be set to 16. + */ + + isolinux_bin = (unsigned char *)boot_sector; + + /* Get LBA address of bootfile */ + file_lba = get_file_lba(opt.loadfile); + + if (file_lba == 0) { + error("Failed to find LBA offset of the boot file\n"); + goto bail; + } + /* Set it */ + *((uint32_t *) & isolinux_bin[12]) = file_lba; + + /* Set boot file length */ + *((uint32_t *) & isolinux_bin[16]) = boot_size; + + /* Calculate checksum */ + checksum = (uint32_t *) & isolinux_bin[20]; + chkhead = (uint32_t *) & isolinux_bin[64]; + chktail = (uint32_t *) & isolinux_bin[boot_size - 1]; + /* Fresh checksum and clear possibly fractional uint32_t at the end */ + *checksum = *((uint32_t *) & isolinux_bin[boot_size]) = 0; + + while (chkhead <= chktail) { + *checksum += *chkhead++; + } + } else { + error + ("The isolinux= option is only valid when run from ISOLINUX\n"); + goto bail; + } + } + } else if (partinfo) { /* Actually read the boot sector */ /* Pick the first buffer that isn't already in use */ @@ -773,6 +897,6 @@ int main(int argc, char *argv[]) do_boot(boot_sector, boot_size, ®s); -bail: + bail: return 255; } diff --git a/com32/modules/cpuidtest.c b/com32/modules/cpuidtest.c index bfc1c190..b7688852 100644 --- a/com32/modules/cpuidtest.c +++ b/com32/modules/cpuidtest.c @@ -121,6 +121,10 @@ int main(void) printf("3dnowext "); if (cpu.flags.now) printf("3dnow! "); + if (cpu.flags.vmx) + printf("vmx "); + if (cpu.flags.svm) + printf("svm "); printf("\n"); printf("SMP = "); if (cpu.flags.smp) diff --git a/com32/modules/dmitest.c b/com32/modules/dmitest.c index d85b3127..212e82af 100644 --- a/com32/modules/dmitest.c +++ b/com32/modules/dmitest.c @@ -179,7 +179,7 @@ int main(void) printf("No DMI Structure found\n"); return -1; } else { - printf("DMI %d.%d present.\n", dmi.dmitable.major_version, + printf("DMI %u.%u present.\n", dmi.dmitable.major_version, dmi.dmitable.minor_version); printf("%d structures occupying %d bytes.\n", dmi.dmitable.num, dmi.dmitable.len); diff --git a/com32/modules/gpxecmd.c b/com32/modules/gpxecmd.c new file mode 100644 index 00000000..de6ffb21 --- /dev/null +++ b/com32/modules/gpxecmd.c @@ -0,0 +1,137 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 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., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * gpxecmd.c + * + * Invoke an arbitrary gPXE command, if available. + */ + +#include <alloca.h> +#include <inttypes.h> +#include <stdio.h> +#include <console.h> +#include <com32.h> +#include <stdbool.h> +#include <string.h> +#include <syslinux/config.h> + +struct segoff16 { + uint16_t offs, seg; +}; + +struct s_PXENV_FILE_CHECK_API { + uint16_t Status; + uint16_t Size; + uint32_t Magic; + uint32_t Provider; + uint32_t APIMask; + uint32_t Flags; +}; + +static bool is_gpxe(void) +{ + const struct syslinux_version *sv; + com32sys_t reg; + struct s_PXENV_FILE_CHECK_API *fca; + + sv = syslinux_version(); + if (sv->filesystem != SYSLINUX_FS_PXELINUX) + return false; /* Not PXELINUX */ + + fca = __com32.cs_bounce; + memset(fca, 0, sizeof *fca); + fca->Size = sizeof *fca; + fca->Magic = 0x91d447b2; + + memset(®, 0, sizeof reg); + reg.eax.w[0] = 0x0009; + reg.ebx.w[0] = 0x00e6; /* PXENV_FILE_API_CHECK */ + reg.edi.w[0] = OFFS(fca); + reg.es = SEG(fca); + + __intcall(0x22, ®, ®); + + if (reg.eflags.l & EFLAGS_CF) + return false; /* Cannot invoke PXE stack */ + + if (reg.eax.w[0] || fca->Status) + return false; /* PXE failure */ + + if (fca->Magic != 0xe9c17b20) + return false; /* Incorrect magic */ + + if (fca->Size < sizeof *fca) + return false; /* Short return */ + + if (!(fca->APIMask & (1 << 5))) + return false; /* No FILE EXEC */ + + return true; +} + +struct s_PXENV_FILE_EXEC { + uint16_t Status; + struct segoff16 Command; +}; + +static void gpxecmd(const char **args) +{ + char *q; + struct s_PXENV_FILE_EXEC *fx; + com32sys_t reg; + + memset(®, 0, sizeof reg); + + fx = __com32.cs_bounce; + q = (char *)(fx + 1); + + fx->Status = 1; + fx->Command.offs = OFFS(q); + fx->Command.seg = SEG(q); + + while (*args) { + q = stpcpy(q, *args); + *q++ = ' '; + args++; + } + *--q = '\0'; + + memset(®, 0, sizeof reg); + reg.eax.w[0] = 0x0009; + reg.ebx.w[0] = 0x00e5; /* PXENV_FILE_EXEC */ + reg.edi.w[0] = OFFS(fx); + reg.es = SEG(fx); + + __intcall(0x22, ®, ®); + + /* This should not return... */ +} + +int main(int argc, const char *argv[]) +{ + openconsole(&dev_null_r, &dev_stdcon_w); + + if (argc < 2) { + printf("Usage: gpxecmd command...\n"); + return 1; + } + + if (!is_gpxe()) { + printf("gpxecmd: gPXE API not detected\n"); + return 1; + } + + gpxecmd(argv + 1); + + return 0; +} diff --git a/core/localboot.inc b/core/localboot.inc index 78483463..a66cf206 100644 --- a/core/localboot.inc +++ b/core/localboot.inc @@ -31,9 +31,7 @@ local_boot: mov gs,dx mov si,localboot_msg call writestr - push ax call cleanup_hardware - pop ax cmp ax,-1 je .int18 diff --git a/core/pxelinux.asm b/core/pxelinux.asm index 93ef8b4a..e5aed7ca 100644 --- a/core/pxelinux.asm +++ b/core/pxelinux.asm @@ -122,6 +122,25 @@ MaxLMA equ 384*1024 ; bootsec equ $ _start: + jmp 0:_start1 ; Canonicalize the address and skip + ; the patch header + +; +; Patch area for adding hardwired DHCP options +; + align 4 + +hcdhcp_magic dd 0x2983c8ac ; Magic number +hcdhcp_len dd 7*4 ; Size of this structure +hcdhcp_flags dd 0 ; Reserved for the future + ; Parameters to be parsed before the ones from PXE +bdhcp_offset dd 0 ; Offset (entered by patcher) +bdhcp_len dd 0 ; Length (entered by patcher) + ; Parameters to be parsed *after* the ones from PXE +adhcp_offset dd 0 ; Offset (entered by patcher) +adhcp_len dd 0 ; Length (entered by patcher) + +_start1: pushfd ; Paranoia... in case of return to PXE pushad ; ... save as much state as possible push ds @@ -134,8 +153,6 @@ _start: mov ds,ax mov es,ax - jmp 0:_start1 ; Canonicalize address -_start1: ; That is all pushed onto the PXE stack. Save the pointer ; to it and switch to an internal stack. mov [InitStack],sp @@ -150,6 +167,54 @@ _start1: lss esp,[BaseStack] sti ; Stack set up and ready +; +; Move the hardwired DHCP options (if present) to a safe place... +; +bdhcp_copy: + mov cx,[bdhcp_len] + mov ax,trackbufsize/2 + jcxz .none + cmp cx,ax + jbe .oksize + mov cx,ax + mov [bdhcp_len],ax +.oksize: + mov eax,[bdhcp_offset] + add eax,_start + mov si,ax + and si,000Fh + shr eax,4 + push ds + mov ds,ax + mov di,trackbuf + add cx,3 + shr cx,2 + rep movsd + pop ds +.none: + +adhcp_copy: + mov cx,[adhcp_len] + mov ax,trackbufsize/2 + jcxz .none + cmp cx,ax + jbe .oksize + mov cx,ax + mov [adhcp_len],ax +.oksize: + mov eax,[adhcp_offset] + add eax,_start + mov si,ax + and si,000Fh + shr eax,4 + push ds + mov ds,ax + mov di,trackbuf+trackbufsize/2 + add cx,3 + shr cx,2 + rep movsd + pop ds +.none: ; ; Initialize screen (if we're using one) diff --git a/core/runkernel.inc b/core/runkernel.inc index 893c41c0..68ab9fac 100644 --- a/core/runkernel.inc +++ b/core/runkernel.inc @@ -461,8 +461,6 @@ run_linux_kernel: ; Set up segment registers and the Linux real-mode stack ; Note: ds == the real mode segment ; - call cleanup_hardware - cli mov ax,ds mov ss,ax diff --git a/core/serirq.inc b/core/serirq.inc index a0cf9bf6..47ccd50f 100644 --- a/core/serirq.inc +++ b/core/serirq.inc @@ -91,6 +91,9 @@ 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 sirq_install: @@ -133,6 +136,22 @@ sirq_install: 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 @@ -156,6 +175,12 @@ sirq_cleanup_nowipe: 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 @@ -165,6 +190,9 @@ sirq_cleanup_nowipe: mov cx,8 rep movsd + xor ax,ax + mov [SerialIRQPort],ax ; No active interrupt system + .done: pop es pop ds diff --git a/modules/Makefile b/modules/Makefile index 80eb995d..77020ea0 100644 --- a/modules/Makefile +++ b/modules/Makefile @@ -19,7 +19,7 @@ include $(topdir)/MCONFIG.embedded INCLUDES = -I$(com32)/include -BINS = pxechain.com gfxboot.com poweroff.com +BINS = pxechain.com gfxboot.com poweroff.com int18.com all: $(BINS) diff --git a/modules/int18.asm b/modules/int18.asm new file mode 100644 index 00000000..a13ada75 --- /dev/null +++ b/modules/int18.asm @@ -0,0 +1,16 @@ + bits 16 + org 100h +_start: + mov ax,5 + int 22h + mov ah,09h + mov dx,msg + int 21h + mov ax,000Ch + xor dx,dx + int 22h + int 18h + jmp 0F000h:0FFF0h ; INT 18h should not return... + + section .data +msg: db 'Local boot via INT 18...', 13, 10, '$' diff --git a/utils/Makefile b/utils/Makefile index 9df9595a..39adf7d3 100644 --- a/utils/Makefile +++ b/utils/Makefile @@ -21,7 +21,8 @@ CFLAGS = -W -Wall -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64 LDFLAGS = -O2 -s TARGETS = mkdiskimage isohybrid gethostip -ASIS = keytab-lilo lss16toppm md5pass ppmtolss16 sha1pass syslinux2ansi +ASIS = keytab-lilo lss16toppm md5pass ppmtolss16 sha1pass syslinux2ansi \ + pxelinux-options ISOHDPFX = ../mbr/isohdpfx.bin ../mbr/isohdpfx_f.bin ../mbr/isohdpfx_c.bin \ ../mbr/isohdppx.bin ../mbr/isohdppx_f.bin ../mbr/isohdppx_c.bin diff --git a/utils/pxelinux-options b/utils/pxelinux-options new file mode 100755 index 00000000..ab7075b5 --- /dev/null +++ b/utils/pxelinux-options @@ -0,0 +1,499 @@ +#!/usr/bin/perl +# +# Set PXELINUX hard-coded options +# + +use Socket; # For gethostbyname +use Fcntl; +use bytes; + +%option_names = ( + 6 => 'domain-name-servers', + 15 => 'domain-name', + 54 => 'next-server', + 209 => 'config-file', + 210 => 'path-prefix', + 211 => 'reboottime' + ); + +@fmt_oneip = ("ip-address", \&parse_oneip, \&show_ip); +@fmt_multiip = ("ip-address-list", \&parse_multiip, \&show_ip); +@fmt_string = ("string", \&parse_string, \&show_string); +@fmt_uint32 = ("uint32", \&parse_uint32, \&show_uint32); + +%option_format = ( + 6 => \@fmt_multiip, + 15 => \@fmt_string, + 54 => \@fmt_oneip, + 67 => \@fmt_string, + 209 => \@fmt_string, + 210 => \@fmt_string, + 211 => \@fmt_uint32 + ); + +sub parse_oneip($) +{ + my($s) = @_; + my($name,$aliases,$addrtype,$length,@addrs) = gethostbyname($s); + + return ($addrtype == AF_INET) ? $addrs[0] : undef; +} + +sub parse_multiip($) +{ + my($l) = @_; + my $s; + my @a = (); + my $addr; + my $d = ''; + + foreach $s (split(/,/, $l)) { + my($name,$aliases,$addrtype,$length,@addrs) + = gethostbyname($s); + if ($addrtype == AF_INET) { + foreach $addr (@addrs) { + $d .= $addr; + } + } + } + + return $d ne '' ? $d : undef; +} + +sub show_ip($) +{ + my($l) = @_; + + if (length($l) & 3) { + return undef; + } else { + my @h = (); + my $i; + + for ($i = 0; $i < length($l); $i += 4) { + push(@h, inet_ntoa(substr($l, $i, 4))); + } + + return join(',', @h); + } +} + +sub parse_string($) +{ + return $_[0]; +} + +sub show_string($) +{ + my($s) = @_; + my $o, $i, $c; + + $o = "\'"; + for ($i = 0; $i < length($s); $i++) { + $c = substr($s, $i, 1); + if ($c eq "\'" || $c eq '!') { + $o .= "\'\\$c\'"; + } else { + $o .= $c; + } + } + $o .= "\'"; + + return $o; +} + +sub parse_uint32($) +{ + my($s) = @_; + + if ($s =~ /^[0-9]+$/) { + return pack("N", $s); + } else { + return undef; + } +} + +sub show_uint32($) +{ + my($l) = @_; + + if (length($l) == 4) { + return unpack("N", $l); + } else { + return undef; + } +} + +sub parse_generic($) +{ + my($s) = @_; + + if ($s =~ /^[0-9a-f]{1,2}(:[0-9a-f]{1,2})*$/) { + my $h; + my @b = (); + + foreach $h (split(/\:/, $s)) { + push(@b, hex $h); + } + + return pack("C", @b); + } else { + return undef; + } +} + +sub show_generic($) +{ + my($l) = @_; + my $i; + my @h; + + for ($i = 0; $i < length($l); $i++) { + push(@h, sprintf("%02x", unpack("C", substr($l, $i, $1)))); + } + + return join(':', @h); +} + +sub parse_option($$) +{ + my($opt, $arg) = @_; + my $v; + + if (defined($option_format{$opt})) { + $v = $option_format{$opt}[1]($arg); + return $v if (defined($v)); + } + + return parse_generic($arg); +} + +sub show_option($$) +{ + my($opt, $arg) = @_; + my $v; + + if (defined($option_format{$opt})) { + $v = $option_format{$opt}[2]($arg); + return $v if (defined($v)); + } + + return show_generic($arg); +} + +sub option_number($) +{ + my($n) = @_; + + if (defined($option_rnames{$n})) { + return $option_rnames{$n}; + } elsif ($n =~ /^[0-9]+$/ && $n >= 1 && $n <= 254) { + return $n+0; + } else { + return undef; + } +} + +sub read_optsets($) +{ + my($file) = @_; + my $data, $bdata, $adata; + my $patch_start = (stat($file))[7]; + + return undef unless (seek($file, 8, SEEK_SET)); + return undef unless (read($file, $data, 7*4) == 7*4); + + my($magic, $len, $flags, $boff, $blen, $aoff, $alen) + = unpack("VVVVVVV", $data); + return undef if ($magic != 0x2983c8ac); + return undef if ($len < 7*4); + + if ($blen == 0) { + $bdata = ''; + } else { + return undef unless (seek($file, $boff, SEEK_SET)); + return undef unless (read($file, $bdata, $blen) == $blen); + $patch_start = $boff if ($boff < $patch_start); + } + + if ($alen == 0) { + $adata = ''; + } else { + return undef unless (seek($file, $aoff, SEEK_SET)); + return undef unless (read($file, $adata, $alen) == $alen); + $patch_start = $aoff if ($aoff < $patch_start); + } + + return ($patch_start, $bdata, $adata); +} + +sub write_optsets($$@) +{ + my($file, $patch_start, $bdata, $adata) = @_; + my $boff = 0; + my $aoff = 0; + + if (length($bdata) > 0) { + $bdata .= "\xff"; + $boff = $patch_start; + return undef unless (seek($file, $boff, SEEK_SET)); + return undef unless (print $file $bdata); + $patch_start += length($bdata); + } + + if (length($adata) > 0) { + $adata .= "\xff"; + $aoff = $patch_start; + return undef unless (seek($file, $aoff, SEEK_SET)); + return undef unless (print $file $adata); + $patch_start += length($adata); + } + + my $hdr = pack("VVVV", $boff, length($bdata), $aoff, length($adata)); + + return undef unless (seek($file, 8+3*4, SEEK_SET)); + return undef unless (print $file $hdr); + + truncate($file, $patch_start); + return 1; +} + +sub delete_option($$) +{ + my ($num, $block) = @_; + my $o, $l, $c, $x; + + $x = 0; + while ($x < length($block)) { + ($o, $l) = unpack("CC", substr($block, $x, 2)); + if ($o == $num) { + # Delete this option + substr($block, $x, $l+2) = ''; + } elsif ($o == 0) { + # Delete a null option + substr($block, $x, 1) = ''; + } elsif ($o == 255) { + # End marker - truncate block + $block = substr($block, 0, $x); + last; + } else { + # Skip to the next option + $x += $l+2; + } + } + + return $block; +} + +sub add_option($$$) +{ + my ($num, $data, $block) = @_; + + $block = delete_option($num, $block); + + if (length($data) == 0) { + return $block; + } elsif (length($data) > 255) { + die "$0: option $num has too much data (max 255 bytes)\n"; + } else { + return $block . pack("CC", $num, length($data)) . $data; + } +} + +sub list_options($$) +{ + my($pfx, $data) = @_; + my $x, $o, $l; + + while ($x < length($data)) { + ($o, $l) = unpack("CC", substr($data, $x, 2)); + + if ($o == 0) { + $x++; + } elsif ($o == 255) { + last; + } else { + my $odata = substr($data, $x+2, $l); + last if (length($odata) != $l); # Incomplete option + + printf "%s%-20s %s\n", $pfx, + $option_names{$o} || sprintf("%d", $o), + show_option($o, $odata); + + $x += $l+2; + } + } +} + +sub usage() +{ + my $i; + + print STDERR "Usage: $0 options pxelinux.0\n"; + print STDERR "Options:\n"; + print STDERR "--before option value -b Add an option before DHCP data\n"; + print STDERR "--after option value -a Add an option after DHCP data\n"; + print STDERR "--delete option -d Delete an option\n"; + print STDERR "--list -l List set options\n"; + print STDERR "--dry-run -n Don't modify the target file\n"; + print STDERR "--help -h Display this help text\n"; + print STDERR "\n"; + print STDERR "The following DHCP options are currently recognized:\n"; + printf STDERR "%-23s %-3s %s\n", 'Name', 'Num', 'Value Format'; + + foreach $i (sort { $a <=> $b } keys(%option_names)) { + printf STDERR "%-23s %3d %s\n", + $option_names{$i}, $i, $option_format{$i}[0]; + } +} + +%option_rnames = (); +foreach $opt (keys(%option_names)) { + $option_rnames{$option_names{$opt}} = $opt; +} + +%before = (); +%after = (); +@clear = (); +$usage = 0; +$err = 0; +$list = 0; +$no_write = 0; +undef $file; + +while (defined($opt = shift(@ARGV))) { + if ($opt !~ /^-/) { + if (defined($file)) { + $err = $usage = 1; + last; + } + $file = $opt; + } elsif ($opt eq '-b' || $opt eq '--before') { + $oname = shift(@ARGV); + $odata = shift(@ARGV); + + if (!defined($odata)) { + $err = $usage = 1; + last; + } + + $onum = option_number($oname); + if (!defined($onum)) { + print STDERR "$0: unknown option name: $oname\n"; + $err = 1; + next; + } + + $odata = parse_option($onum, $odata); + if (!defined($odata)) { + print STDERR "$0: unable to parse data for option $oname\n"; + $err = 1; + next; + } + + delete $after{$onum}; + $before{$onum} = $odata; + push(@clear, $onum); + } elsif ($opt eq '-a' || $opt eq '--after') { + $oname = shift(@ARGV); + $odata = shift(@ARGV); + + if (!defined($odata)) { + $err = $usage = 1; + last; + } + + $onum = option_number($oname); + if (!defined($onum)) { + print STDERR "$0: unknown option name: $oname\n"; + $err = 1; + next; + } + + $odata = parse_option($onum, $odata); + if (!defined($odata)) { + print STDERR "$0: unable to parse data for option $oname\n"; + $err = 1; + next; + } + + delete $before{$onum}; + $after{$onum} = $odata; + push(@clear, $onum); + } elsif ($opt eq '-d' || $opt eq '--delete') { + $oname = shift(@ARGV); + + if (!defined($oname)) { + $err = $usage = 1; + last; + } + + $onum = option_number($oname); + if (!defined($onum)) { + print STDERR "$0: unknown option name: $oname\n"; + $err = 1; + next; + } + + push(@clear, $onum); + delete $before{$onum}; + delete $after{$onum}; + } elsif ($opt eq '-n' || $opt eq '--no-write' || $opt eq '--dry-run') { + $no_write = 1; + } elsif ($opt eq '-l' || $opt eq '--list') { + $list = 1; + } elsif ($opt eq '-h' || $opt eq '--help') { + $usage = 1; + } else { + print STDERR "Invalid option: $opt\n"; + $err = $usage = 1; + } +} + +if (!defined($file) && !$usage) { + $err = $usage = 1; +} +if ($usage) { + usage(); +} +if ($err || $usage) { + exit($err); +} + +if (!scalar(@clear)) { + $no_write = 1; # No modifications requested +} + +$mode = $no_write ? '<' : '+<'; + +open(FILE, $mode, $file) + or die "$0: cannot open: $file: $!\n"; +($patch_start, @data) = read_optsets(\*FILE); +if (!defined($patch_start)) { + die "$0: $file: patch block not found or file corrupt\n"; +} + +foreach $o (@clear) { + $data[0] = delete_option($o, $data[0]); + $data[1] = delete_option($o, $data[1]); +} +foreach $o (keys(%before)) { + $data[0] = add_option($o, $before{$o}, $data[0]); +} +foreach $o (keys(%after)) { + $data[1] = add_option($o, $after{$o}, $data[1]); +} + +if ($list) { + list_options('-b ', $data[0]); + list_options('-a ', $data[1]); +} + +if (!$no_write) { + if (!write_optsets(\*FILE, $patch_start, @data)) { + die "$0: $file: failed to write options: $!\n"; + } +} + +close(FILE); +exit 0; |