summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhpa <hpa>2004-02-02 08:40:14 +0000
committerhpa <hpa>2004-02-02 08:40:14 +0000
commit3edbc5585266a34df2b8708b86fc95bf667c00ed (patch)
tree7f336b5f40ba7827035f4b06b826a61a916f01c1
parentca5d31af26694aaf4db112c2eb6c3f82a65ec672 (diff)
downloadsyslinux-3edbc5585266a34df2b8708b86fc95bf667c00ed.tar.gz
Menu system from Murali
-rw-r--r--menu/Makefile38
-rw-r--r--menu/README31
-rw-r--r--menu/biosio.c204
-rw-r--r--menu/biosio.h54
-rw-r--r--menu/com16.ld185
-rw-r--r--menu/complex.c200
-rw-r--r--menu/menu.c407
-rw-r--r--menu/menu.h176
-rw-r--r--menu/simple.c80
-rw-r--r--menu/startup.S1616
-rw-r--r--menu/startup.asm55
-rw-r--r--menu/string.c73
-rw-r--r--menu/string.h19
-rw-r--r--menu/syslinux.c51
-rw-r--r--menu/syslinux.h11
15 files changed, 1600 insertions, 0 deletions
diff --git a/menu/Makefile b/menu/Makefile
new file mode 100644
index 00000000..4824f05c
--- /dev/null
+++ b/menu/Makefile
@@ -0,0 +1,38 @@
+CC = gcc -funsigned-char -W -Wall
+CFLAGS = -march=i386 -Os
+AS = as
+LD = ld
+OBJCOPY = objcopy
+
+.SUFFIXES: .c .s .s16 .o16 .elf .com
+
+.c.s:
+ $(CC) $(CFLAGS) -S -o $@ $<
+
+.s.s16:
+ echo '.code16gcc' | cat - $< > $@
+
+.s16.o16:
+ $(AS) -o $@ $<
+
+.elf.com:
+ $(OBJCOPY) -O binary $< $@
+
+
+all : menu.com
+
+menu.elf: startup.o16 main.o16 biosio.o16 string.o16 menu.o16 syslinux.o16
+ $(LD) -T com16.ld -o $@ $^
+
+startup.s16: startup.S16
+ $(CC) $(CFLAGS) -x assembler-with-cpp -E -o $@ $<
+
+clean:
+ -rm -f *.s *.s16 *.o16 *.elf *.com
+
+spotless: clean
+ -rm -f *~ \#*
+
+distclean: spotless
+ -rm -f main.c
+
diff --git a/menu/README b/menu/README
new file mode 100644
index 00000000..50149782
--- /dev/null
+++ b/menu/README
@@ -0,0 +1,31 @@
+ Text User Interface using comboot
+ ---------------------------------
+
+This is a menu system written by Murali Krishnan Ganapathy and ported
+from OpenWatcom to gcc by HPA.
+
+To configure the menus, you need to set up main.c to have the menu
+items you desire, then build the menu system using make. You can use
+either simple.c or complex.c as a starting point for your own main.c.
+
+The resulting code runs both under DOS as well as SYSLINUX.
+Currently, menu items, submenus and checkboxes are supported.
+
+The keys used are:
+
+* Arrow Keys, PgUp, PgDn, Home, End Keys
+* Space to switch state of a checkbox
+* Enter to choose the item
+* Escape to exit from it
+
+Credits
+-------
+* The Watcom developers and Peter Anvin for figuring out the
+ startup code.
+
+- Murali
+
+P.S: I know that the choice of colors are not exactly the best
+(in fact they are horrible). If you know a better choice of colors
+I would be happy to change my defaults to your suggested ones.
+
diff --git a/menu/biosio.c b/menu/biosio.c
new file mode 100644
index 00000000..dcc806ba
--- /dev/null
+++ b/menu/biosio.c
@@ -0,0 +1,204 @@
+/* -*- c -*- ------------------------------------------------------------- *
+ *
+ * Copyright 2004 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,
+ * Bostom MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include "string.h"
+#include "biosio.h"
+
+static inline void asm_putchar(char x)
+{
+ asm volatile("int $0x21" : : "a" (x + 0x0200));
+}
+
+static inline void asm_sprint(const char *str)
+{
+ asm volatile("movb $0x09,%%ah ; int $0x21" : : "d" (str) : "eax");
+}
+
+/* BIOS Assisted output routines */
+void csprint(char *str) // Print a C str (NULL terminated)
+{
+ int o,l;
+
+ o = (long)(str) & 0xffff; // Offset of location
+ l = strlen(str);
+ str[l] = '$'; // Replace \0 with $
+ asm_sprint(str);
+ str[l] = '\0'; // Change it back.
+}
+
+void sprint(const char *str)
+{
+ asm_sprint(str);
+}
+
+
+static inline void asm_cprint(char chr, char attr, int times, char disppage)
+{
+ asm volatile("movb $0x09,%%ah ; int $0x10"
+ : "+a" (chr) : "b" (attr + (disppage << 8)), "c" (times));
+}
+
+void cprint(char chr,char attr,int times,char disppage)
+{
+ asm_cprint(chr,attr,times,disppage);
+}
+
+static inline void asm_setdisppage(char num)
+{
+ asm volatile("movb $0x05,%%ah ; int $0x10"
+ : "+a" (num));
+}
+
+void setdisppage(char num) // Set the display page to specified number
+{
+ asm_setdisppage(num);
+}
+
+
+static inline char asm_getdisppage(void)
+{
+ register char page asm("%bh");
+
+ asm("movb $0x0f,%%ah ; int $0x10" : "=r" (page) : : "eax", "ebx");
+ return page;
+}
+
+char getdisppage() // Get current display page
+{
+ return asm_getdisppage();
+}
+
+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);
+ asm_cprint(fillchar,fillattr,right-left+1,page);
+ }
+}
+
+void cls(void)
+{
+ asm_cprint(' ',0x07,25*80,getdisppage());
+}
+
+static inline void asm_gotoxy(char row,char col, char page)
+{
+ asm volatile("movb $0x02,%%ah ; "
+ "int $0x10"
+ : : "d" ((row << 8) + col), "b" (page << 8)
+ : "eax");
+}
+
+void gotoxy(char row,char col, char page)
+{
+ asm_gotoxy(row,col,page);
+}
+
+static inline void asm_getpos(char *row, char *col, char page)
+{
+ asm("movb $0x03,%%ah ; "
+ "int $0x10 ; "
+ "movb %%dh,%0 ; "
+ "movb %%dl,%1"
+ : "=m" (*row), "=m" (*col)
+ : "b" (page << 8)
+ : "eax", "ecx", "edx");
+}
+
+void getpos(char * row, char * col, char page)
+{
+ asm_getpos(row,col,page);
+}
+
+char asm_inputc(char *scancode)
+{
+ unsigned short ax;
+
+ asm volatile("movb $0x10,%%ah ; "
+ "int $0x16"
+ : "=a" (ax));
+
+ if (scancode)
+ *scancode = (ax >> 8);
+
+ return (char)ax;
+}
+
+char inputc(char * scancode)
+{
+ return asm_inputc(scancode);
+}
+
+void asm_cursorshape(char start, char end)
+{
+ asm volatile("movb $0x01,%%ah ; int $0x10"
+ : : "c" ((start << 8) + end) : "eax");
+}
+
+void cursoroff(void)
+{
+ asm_cursorshape(31,31);
+}
+
+void cursoron(void)
+{
+ asm_cursorshape(6,7);
+}
+
+char bkspstr[] = " \b$";
+char eolstr[] = "\n$";
+
+static char asm_getchar(void)
+{
+ char v;
+
+ /* Get key without echo */
+ asm("movb $0x08,%%ah ; int $0x21" : "=a" (v));
+
+ return v;
+}
+
+void getstring(char *str, unsigned int size)
+// Reads a line of input from stdin. Replace CR with NUL byte
+{
+ char c;
+ char *p = str;
+
+ while ( (c = asm_getchar()) != '\r' ) {
+ switch (c) {
+ case '\0': /* Extended char prefix */
+ asm_getchar(); /* Drop */
+ break;
+ case '\b':
+ if ( p > str ) {
+ p--;
+ sprint("\b \b$");
+ }
+ break;
+ case '\x15': /* Ctrl-U: kill input */
+ while ( p > str ) {
+ p--;
+ sprint("\b \b$");
+ }
+ break;
+ default:
+ if ( c >= ' ' && (unsigned int)(p-str) < size-1 ) {
+ *p++ = c;
+ asm_putchar(c);
+ }
+ break;
+ }
+ }
+ *p = '\0';
+}
diff --git a/menu/biosio.h b/menu/biosio.h
new file mode 100644
index 00000000..b090266a
--- /dev/null
+++ b/menu/biosio.h
@@ -0,0 +1,54 @@
+/* -*- c -*- ------------------------------------------------------------- *
+ *
+ * Copyright 2004 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,
+ * Bostom MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/* This program can be compiled for DOS with the OpenWatcom compiler
+ * (http://www.openwatcom.org/):
+ *
+ * wcl -3 -osx -mt <filename>.c
+ */
+
+#ifndef __BIOSIO_H__
+#define __BIOSIO_H__
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+/* BIOS Assisted output routines */
+
+void csprint(char *str); // Print a C str (NULL terminated)
+
+void sprint(const char *str); // Print a $ terminated string
+
+void cprint(char chr,char attr,int times,char disppage); // Print a char
+
+void setdisppage(char num); // Set the display page to specified number
+
+char getdisppage(); // Get current display page
+
+void clearwindow(char top,char left,char bot,char right, char page,char fillchar, char fillattr);
+
+void cls();
+
+void gotoxy(char row,char col, char page);
+
+void getpos(char * row, char * col, char page);
+
+char inputc(char * scancode); // Return ASCII char by val, and scancode by reference
+
+void cursoroff(void); /* Turns on cursor */
+
+void cursoron(void); /* Turns off cursor */
+
+void getstring(char *str, unsigned int size);
+
+#endif
diff --git a/menu/com16.ld b/menu/com16.ld
new file mode 100644
index 00000000..73109296
--- /dev/null
+++ b/menu/com16.ld
@@ -0,0 +1,185 @@
+/* Simple linker script to pre-link DOS .com files */
+
+OUTPUT_FORMAT("elf32-i386", "elf32-i386",
+ "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = 0x100;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .rel.dyn :
+ {
+ *(.rel.init)
+ *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)
+ *(.rel.fini)
+ *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)
+ *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)
+ *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*)
+ *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*)
+ *(.rel.ctors)
+ *(.rel.dtors)
+ *(.rel.got)
+ *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)
+ }
+ .rela.dyn :
+ {
+ *(.rela.init)
+ *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
+ *(.rela.fini)
+ *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
+ *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
+ *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
+ *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
+ *(.rela.ctors)
+ *(.rela.dtors)
+ *(.rela.got)
+ *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
+ }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init :
+ {
+ KEEP (*(.init))
+ } =0x90909090
+ .plt : { *(.plt) }
+ .text :
+ {
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ /* .gnu.warning sections are handled specially by elf32.em. */
+ *(.gnu.warning)
+ } =0x90909090
+ .fini :
+ {
+ KEEP (*(.fini))
+ } =0x90909090
+ PROVIDE (__etext = .);
+ PROVIDE (_etext = .);
+ PROVIDE (etext = .);
+ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+ .rodata1 : { *(.rodata1) }
+ .eh_frame_hdr : { *(.eh_frame_hdr) }
+ .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
+ .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table) }
+ /* For backward-compatibility with tools that don't support the
+ *_array_* sections below, our glibc's crt files contain weak
+ definitions of symbols that they reference. We don't want to use
+ them, though, unless they're strictly necessary, because they'd
+ bring us empty sections, unlike PROVIDE below, so we drop the
+ sections from the crt files here. */
+ /DISCARD/ : {
+ */crti.o(.init_array .fini_array .preinit_array)
+ */crtn.o(.init_array .fini_array .preinit_array)
+ }
+ /* Ensure the __preinit_array_start label is properly aligned. We
+ could instead move the label definition inside the section, but
+ the linker would then create the section even if it turns out to
+ be empty, which isn't pretty. */
+ . = ALIGN(32 / 8);
+ PROVIDE (__preinit_array_start = .);
+ .preinit_array : { *(.preinit_array) }
+ PROVIDE (__preinit_array_end = .);
+ PROVIDE (__init_array_start = .);
+ .init_array : { *(.init_array) }
+ PROVIDE (__init_array_end = .);
+ PROVIDE (__fini_array_start = .);
+ .fini_array : { *(.fini_array) }
+ PROVIDE (__fini_array_end = .);
+ .data :
+ {
+ *(.data .data.* .gnu.linkonce.d.*)
+ SORT(CONSTRUCTORS)
+ }
+ .data1 : { *(.data1) }
+ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+ .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }
+ .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table) }
+ .dynamic : { *(.dynamic) }
+ .ctors :
+ {
+ /* gcc uses crtbegin.o to find the start of
+ the constructors, so we make sure it is
+ first. Because this is a wildcard, it
+ doesn't matter if the user does not
+ actually link against crtbegin.o; the
+ linker won't look for a file to match a
+ wildcard. The wildcard also means that it
+ doesn't matter which directory crtbegin.o
+ is in. */
+ KEEP (*crtbegin.o(.ctors))
+ /* We don't want to include the .ctor section from
+ from the crtend.o file until after the sorted ctors.
+ The .ctor section from the crtend file contains the
+ end of ctors marker and it must be last */
+ KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+ }
+ .dtors :
+ {
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+ }
+ .jcr : { KEEP (*(.jcr)) }
+ .got : { *(.got.plt) *(.got) }
+ _edata = .;
+ PROVIDE (edata = .);
+ __bss_start = .;
+ .bss :
+ {
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(COMMON)
+ /* Align here to ensure that the .bss section occupies space up to
+ _end. Align after .bss to ensure correct alignment even if the
+ .bss section disappears because there are no input sections. */
+ . = ALIGN(32 / 8);
+ }
+ . = ALIGN(32 / 8);
+ _end = .;
+ PROVIDE (end = .);
+
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+}
diff --git a/menu/complex.c b/menu/complex.c
new file mode 100644
index 00000000..04aefce2
--- /dev/null
+++ b/menu/complex.c
@@ -0,0 +1,200 @@
+/* -*- c -*- ------------------------------------------------------------- *
+ *
+ * Copyright 2004 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,
+ * Bostom MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+#include "menu.h"
+#include "biosio.h"
+#include "string.h"
+#include "syslinux.h"
+
+/* Global variables */
+char infoline[160];
+char syslinux; // Is syslinux running?
+
+struct {
+ unsigned int baseurl : 1; // Do we need to specify by url
+ unsigned int mountcd : 1; // Should we mount the cd
+ unsigned int network : 1; // want network?
+ unsigned int dhcp : 1; // want dhcp / static ip
+ unsigned int winrep : 1; // Want to repair windows?
+ unsigned int linrep : 1; // Want to repair linux?
+} flags;
+
+t_menuitem *baseurl,*mountcd,*network,*dhcp,*runprep,*winrep,*linrep;
+// all the menus we are going to declare
+char TESTING,RESCUE,MAIN,PREP;
+
+/* End globals */
+
+void msys_handler(t_menusystem *ms, t_menuitem *mi)
+{
+ if (mi->parindex != PREP) // If we are not in the PREP MENU
+ {
+ gotoxy(21,0,ms->menupage);
+ cprint(ms->fillchar,ms->fillattr,80,ms->menupage);
+ return;
+ }
+ strcpy (infoline," ");
+ if (flags.baseurl) strcat(infoline,"baseurl=http://128.135.11.139/gui ");
+ if (flags.mountcd) strcat(infoline,"mountcd=yes ");
+ if (!flags.network)
+ strcat(infoline,"network=no ");
+ else if (!flags.dhcp) strcat(infoline,"network=static ");
+ if (flags.winrep) strcat(infoline,"repair=win ");
+ if (flags.linrep) strcat(infoline,"repair=lin ");
+ gotoxy(20,0,ms->menupage);
+ cprint(ms->spacechar,ms->statusattr,80,ms->menupage);
+ gotoxy(21,0,ms->menupage);
+ cprint(ms->spacechar,ms->statusattr,80,ms->menupage);
+ gotoxy(20,0,ms->menupage);
+ sprint("Kernel Arguments:$");
+ gotoxy(20,17,ms->menupage);
+ csprint(infoline);
+}
+
+void checkbox_handler(t_menusystem *ms, t_menuitem *mi)
+{
+ (void)ms; /* Unused */
+
+ if (mi->action != OPT_CHECKBOX) return;
+
+ if (strcmp(mi->data,"baseurl") == 0) flags.baseurl = (mi->itemdata.checked ? 1 : 0);
+ if (strcmp(mi->data,"network") == 0) {
+ if (mi->itemdata.checked)
+ {
+ flags.network = 1;
+ dhcp->action = OPT_CHECKBOX;
+ }
+ else
+ {
+ flags.network = 0;
+ dhcp->action = OPT_INACTIVE;
+ }
+ }
+ if (strcmp(mi->data,"winrepair") == 0) {
+ if (mi->itemdata.checked)
+ {
+ flags.winrep = 1;
+ linrep->action = OPT_INACTIVE;
+ }
+ else
+ {
+ flags.winrep = 0;
+ linrep->action = OPT_CHECKBOX;
+ }
+ }
+ if (strcmp(mi->data,"linrepair") == 0) {
+ if (mi->itemdata.checked)
+ {
+ flags.linrep = 1;
+ winrep->action = OPT_INACTIVE;
+ }
+ else
+ {
+ flags.winrep = 0;
+ winrep->action = OPT_CHECKBOX;
+ }
+ }
+ if (strcmp(mi->data,"mountcd") == 0) flags.mountcd = (mi->itemdata.checked ? 1 : 0);
+ if (strcmp(mi->data,"dhcp") == 0) flags.dhcp = (mi->itemdata.checked ? 1 : 0);
+}
+
+int main(void)
+{
+ t_menuitem * curr;
+ char cmdline[160];
+ char ip[30];
+
+ // Choose the default title and setup default values for all attributes....
+ init_menusystem(NULL);
+
+ // Choose the default values for all attributes and char's
+ // -1 means choose defaults (Actually the next 4 lines are not needed)
+ //set_normal_attr (-1,-1,-1,-1);
+ //set_status_info (-1,-1);
+ //set_title_info (-1,-1);
+ //set_misc_info(-1,-1,-1,-1);
+
+ reg_handler(&msys_handler);
+
+ TESTING = add_menu(" Testing ");
+ add_item("Memory Test","Perform extensive memory testing",OPT_RUN, "memtest",0);
+ add_item("Exit this menu","Go one level up",OPT_EXITMENU,"exit",0);
+
+ RESCUE = add_menu(" Rescue Options ");
+ add_item("Linux Rescue","linresc",OPT_RUN,"linresc",0);
+ add_item("Dos Rescue","dosresc",OPT_RUN,"dosresc",0);
+ add_item("Windows Rescue","winresc",OPT_RUN,"winresc",0);
+ add_item("Exit this menu","Go one level up",OPT_EXITMENU,"exit",0);
+
+ PREP = add_menu(" Prep options ");
+ baseurl = add_item("baseurl by IP?","Specify gui baseurl by IP address",OPT_CHECKBOX,"baseurl",0);
+ mountcd = add_item("mountcd?","Mount the cdrom drive?",OPT_CHECKBOX,"mountcd",0);
+ network = add_item("network?","Try to initialise network device?",OPT_CHECKBOX,"network",1);
+ dhcp = add_item("dhcp?","Use dhcp to get ipaddr?",OPT_CHECKBOX,"dhcp",1);
+ winrep = add_item("Reinstall windows","Re-install the windows side of a dual boot setup",OPT_CHECKBOX,"winrepair",0);
+ linrep = add_item("Reinstall linux","Re-install the linux side of a dual boot setup",OPT_CHECKBOX,"linrepair",0);
+ runprep = add_item("Run prep now","Execute prep with the above options",OPT_RUN,"prep",0);
+ baseurl->handler = &checkbox_handler;
+ mountcd->handler = &checkbox_handler;
+ network->handler = &checkbox_handler;
+ dhcp->handler = &checkbox_handler;
+ winrep->handler = &checkbox_handler;
+ linrep->handler = &checkbox_handler;
+ flags.baseurl = 0;
+ flags.mountcd = 0;
+ flags.network = 1;
+ flags.dhcp = 1;
+ flags.winrep = 0;
+ flags.linrep = 0;
+
+ MAIN = add_menu(" Main Menu ");
+ add_item("Prepare","prep",OPT_RUN,"prep",0);
+ add_item("Prep options...","Options for prep image",OPT_SUBMENU,NULL,PREP);
+ add_item("Rescue options...","Troubleshoot a system",OPT_SUBMENU,NULL,RESCUE);
+ add_item("Testing...","Options to test hardware",OPT_SUBMENU,NULL,TESTING);
+ add_item("Exit to prompt", "Exit the menu system", OPT_EXITMENU, "exit", 0);
+
+ syslinux = issyslinux(); // Find if syslinux is running
+ //if (syslinux) sprint("Syslinux is running!\r\n$"); else sprint("Nope its not.\r\n$");
+
+ if (syslinux) gototxtmode(); // Else assume we are running in a DOS box
+ curr = showmenus(MAIN);
+ if (curr)
+ {
+ if (curr->action == OPT_EXIT) return 0;
+ if (curr->action == OPT_RUN)
+ {
+ strcpy(cmdline,curr->data);
+ if (curr == runprep)
+ {
+ strcat(cmdline,infoline);
+ if (flags.network && !flags.dhcp) // We want static
+ {
+ sprint("Enter IP address (last two octets only): $");
+ getstring(ip, sizeof ip);
+ strcat(cmdline,"ipaddr=128.135.");
+ strcat(cmdline,ip);
+ }
+ }
+ if (syslinux)
+ runcommand(cmdline);
+ else csprint(cmdline);
+ return 1;
+ }
+ }
+ return 0;
+}
+
diff --git a/menu/menu.c b/menu/menu.c
new file mode 100644
index 00000000..74acad0e
--- /dev/null
+++ b/menu/menu.c
@@ -0,0 +1,407 @@
+/* -*- c -*- ------------------------------------------------------------- *
+ *
+ * Copyright 2004 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,
+ * Bostom MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include "biosio.h"
+#include "string.h"
+#include "menu.h"
+
+// Structures
+
+// Declare a menusystem here
+static t_menusystem menusystem;
+
+/* Basic Menu routines */
+
+void drawbox(char top, char left, char bot, char right,char attr, char page)
+{
+ char x;
+
+ // Top border
+ gotoxy(top,left,page);
+ cprint(TOPLEFT,attr,1,page);
+ gotoxy(top,left+1,page);
+ cprint(TOP,attr,right-left,page);
+ gotoxy(top,right,page);
+ cprint(TOPRIGHT,attr,1,page);
+ // Bottom border
+ gotoxy(bot,left,page);
+ cprint(BOTLEFT,attr,1,page);
+ gotoxy(bot,left+1,page);
+ cprint(BOT,attr,right-left,page);
+ gotoxy(bot,right,page);
+ cprint(BOTRIGHT,attr,1,page);
+ // Left & right borders
+ for (x=top+1; x < bot; x++)
+ {
+ gotoxy(x,left,page);
+ cprint(LEFT,attr,1,page);
+ gotoxy(x,right,page);
+ cprint(RIGHT,attr,1,page);
+ }
+}
+
+void printmenu(t_menu * menu, int curr, char top, char left)
+{
+ int x;
+ int numitems,menuwidth;
+ t_menusystem *ms;
+ char attr;
+
+ ms = & menusystem;
+ numitems = menu->numitems;
+ menuwidth = menu->menuwidth+2;
+ clearwindow(top,left-1,top+numitems+1,left+menuwidth+1,ms->menupage,ms->fillchar,ms->shadowattr);
+ drawbox(top-1,left-2,top+numitems,left+menuwidth,ms->normalattr,ms->menupage);
+ // Menu title
+ x = (menuwidth - strlen(menu->title) - 1) >> 1;
+ gotoxy(top-1,left+x,ms->menupage);
+ sprint(menu->title);
+ for (x=0; x < numitems; x++)
+ {
+ gotoxy(top+x,left-1,ms->menupage);
+ if (menu->items[x].action == OPT_INACTIVE)
+ {
+ attr = (x==curr? ms->revinactattr : ms->inactattr);
+ } else {
+ attr = (x==curr ? ms->reverseattr : ms->normalattr);
+ }
+ cprint(ms->spacechar,attr,menuwidth+1,ms->menupage);
+ gotoxy(top+x,left,ms->menupage);
+ sprint(menu->items[x].item);
+ gotoxy(top+x,left+menuwidth-1,ms->menupage); // Last char if any
+ switch (menu->items[x].action)
+ {
+ case OPT_SUBMENU:
+ cprint(SUBMENUCHAR,attr,1,ms->menupage);
+ break;
+ case OPT_CHECKBOX:
+ cprint( (menu->items[x].itemdata.checked ? CHECKED : UNCHECKED),attr,1,ms->menupage);
+ break;
+ }
+ }
+ if (menusystem.handler) menusystem.handler(&menusystem,menu->items+curr);
+}
+
+void cleanupmenu(t_menu *menu, char top,char left)
+{
+ t_menusystem *ms = &menusystem;
+ clearwindow(top,left-1,top+menu->numitems+1,left+menu->menuwidth+3,ms->menupage,ms->fillchar,ms->fillattr); // Clear the shadow
+ clearwindow(top-1,left-2,top+menu->numitems,left+menu->menuwidth+2,ms->menupage,ms->fillchar,ms->fillattr); // clear the main window
+}
+
+/* Handle one menu */
+t_menuitem * getmenuoption( t_menu *menu, char top, char left, char startopt)
+// Return item chosen or NULL if ESC was hit.
+{
+ int curr;
+ char asc,scan;
+ char numitems;
+ t_menusystem *ms;
+ t_menuitem *ci; // Current item
+
+ ms = & menusystem;
+ numitems = menu->numitems;
+ // Setup status line
+ gotoxy(ms->statline,0,ms->menupage);
+ cprint(ms->spacechar,ms->reverseattr,80,ms->menupage);
+
+ // Initialise current menu item
+ curr = startopt;
+ gotoxy(ms->statline,0,ms->menupage);
+ cprint(ms->spacechar,ms->statusattr,80,1);
+ gotoxy(ms->statline,0,ms->menupage);
+ sprint(menu->items[curr].status);
+ while (1) // Forever
+ {
+ printmenu(menu,curr,top,left);
+ ci = &(menu->items[curr]);
+ asc = inputc(&scan);
+ switch (scan)
+ {
+ case HOMEKEY:
+ curr = 0;
+ break;
+ case ENDKEY:
+ curr = numitems -1;
+ break;
+ case PAGEDN:
+ curr += 5;
+ break;
+ case PAGEUP:
+ curr -= 5;
+ break;
+ case UPARROW:
+ curr --;
+ break;
+ case DNARROW:
+ curr++;
+ break;
+ case LTARROW:
+ case ESCAPE:
+ return NULL;
+ break;
+ case ENTERA:
+ case RTARROW:
+ case ENTERB:
+ if (ci->action == OPT_INACTIVE) break;
+ if (ci->action == OPT_CHECKBOX) break;
+ if (ci->action == OPT_EXITMENU) return NULL; // As if we hit Esc
+ return ci;
+ break;
+ case SPACEKEY:
+ if (ci->action != OPT_CHECKBOX) break;
+ ci->itemdata.checked = !ci->itemdata.checked;
+ // Call handler to see it anything needs to be done
+ if (ci->handler != NULL) ci->handler(&menusystem,ci);
+ break;
+ }
+ // Adjust within range
+ if (curr < 0) curr=0;
+ if (curr >= numitems) curr = numitems -1;
+ // Update status line
+ gotoxy(ms->statline,0,ms->menupage);
+ cprint(ms->spacechar,ms->statusattr,80,ms->menupage);
+ sprint(menu->items[curr].status);
+ }
+ return NULL; // Should never come here
+}
+
+/* Handle the entire system of menu's. */
+t_menuitem * runmenusystem(char top, char left, int currmenu)
+/*
+ * currmenu
+ * Which menu should be currently displayed
+ * top,left
+ * What is the position of the top,left corner of the menu
+ *
+ * Return Value:
+ * Returns a pointer to the final item chosen, or NULL if nothing chosen.
+ */
+{
+ t_menu *cmenu;
+ t_menusystem *ms = &menusystem;
+ t_menuitem *opt,*choice;
+ int numitems;
+ char startopt;
+
+ startopt = 0;
+startover:
+ cmenu = (menusystem.menus+currmenu);
+ numitems = menusystem.menus[currmenu].numitems;
+ opt = getmenuoption(cmenu,top,left,startopt);
+ if (opt == NULL)
+ {
+ // User hit Esc
+ cleanupmenu(cmenu,top,left);
+ return NULL;
+ }
+ if (opt->action != OPT_SUBMENU) // We are done with the menu system
+ {
+ cleanupmenu(cmenu,top,left);
+ return opt; // parent cleanup other menus
+ }
+ if (opt->itemdata.submenunum >= menusystem.nummenus) // This is Bad....
+ {
+ gotoxy(12,12,ms->menupage); // Middle of screen
+ sprint("Invalid submenu requested. Ask administrator to correct this.$");
+ cleanupmenu(cmenu,top,left);
+ return NULL; // Pretend user hit esc
+ }
+ // Call recursively for submenu
+ // Position the submenu below the current item,
+ // covering half the current window (horizontally)
+ choice = runmenusystem(top+opt->index+2, left+3+(cmenu->menuwidth >> 1), opt->itemdata.submenunum);
+ if (choice==NULL) // User hit Esc in submenu
+ {
+ // Startover
+ startopt = opt->index;
+ goto startover;
+ }
+ else
+ {
+ cleanupmenu(cmenu,top,left);
+ return choice;
+ }
+}
+
+/* User Callable functions */
+
+t_menuitem * showmenus(char startmenu)
+{
+ t_menuitem *rv;
+ t_menusystem *ms;
+ char oldpage,tpos;
+
+ ms = & menusystem;
+ // Setup screen for menusystem
+ oldpage = getdisppage();
+ setdisppage(ms->menupage);
+ clearwindow(0,0,24,79,ms->menupage,ms->fillchar,ms->fillattr);
+ tpos = (80 - strlen(menusystem.title) - 1) >> 1; // To center it on line
+ gotoxy(0,0,ms->menupage);
+ cprint(ms->tfillchar,ms->titleattr,80,ms->menupage);
+ gotoxy(0,tpos,ms->menupage);
+ sprint(menusystem.title);
+
+ cursoroff(); // Doesn't seem to work?
+
+ // Go
+ rv = runmenusystem(MENUROW, MENUCOL, startmenu);
+
+ // Hide the garbage we left on the screen
+ cursoron();
+ if (oldpage == ms->menupage) cls(); else setdisppage(oldpage);
+
+ // Return user choice
+ return rv;
+}
+
+void init_menusystem(const char *title)
+{
+ menusystem.nummenus = 0;
+ if (title == NULL)
+ dstrcpy(menusystem.title,TITLESTR);
+ else dstrcpy(menusystem.title,title);
+
+ menusystem.normalattr = NORMALATTR;
+ menusystem.reverseattr= REVERSEATTR;
+ menusystem.inactattr = INACTATTR;
+ menusystem.revinactattr = REVINACTATTR;
+
+ menusystem.statusattr = STATUSATTR;
+ menusystem.statline = STATLINE;
+ menusystem.tfillchar= TFILLCHAR;
+ menusystem.titleattr= TITLEATTR;
+
+ menusystem.fillchar = FILLCHAR;
+ menusystem.fillattr = FILLATTR;
+ menusystem.spacechar= SPACECHAR;
+ menusystem.shadowattr = SHADOWATTR;
+
+ menusystem.menupage = MENUPAGE; // Usually no need to change this at all
+ menusystem.handler = NULL; // No handler function
+}
+
+void set_normal_attr(char normal, char selected, char inactivenormal, char inactiveselected)
+{
+ if (normal != 0xFF) menusystem.normalattr = normal;
+ if (selected != 0xFF) menusystem.reverseattr = selected;
+ if (inactivenormal != 0xFF) menusystem.inactattr = inactivenormal;
+ if (inactiveselected != 0xFF) menusystem.revinactattr = inactiveselected;
+}
+
+void set_status_info(char statusattr, char statline)
+{
+ if (statusattr != 0xFF) menusystem.statusattr = statusattr;
+ if (statline != 0xFF) menusystem.statline = statline;
+}
+
+void set_title_info(char tfillchar, char titleattr)
+{
+ if (tfillchar != 0xFF) menusystem.tfillchar = tfillchar;
+ if (titleattr != 0xFF) menusystem.titleattr = titleattr;
+}
+
+void set_misc_info(char fillchar, char fillattr,char spacechar, char shadowattr)
+{
+ if (fillchar != 0xFF) menusystem.fillchar = fillchar;
+ if (fillattr != 0xFF) menusystem.fillattr = fillattr;
+ if (spacechar != 0xFF) menusystem.spacechar = spacechar;
+ if (shadowattr!= 0xFF) menusystem.shadowattr= shadowattr;
+}
+
+void reg_handler( t_menusystem_handler handler)
+{
+ menusystem.handler = handler;
+}
+
+void unreg_handler()
+{
+ menusystem.handler = NULL;
+}
+
+int add_menu(const char *title) // Create a new menu and return its position
+{
+ const int num = (unsigned char)menusystem.nummenus;
+
+ if (num >= MAXMENUS) return -1;
+ menusystem.menus[num].numitems = 0;
+ menusystem.menus[num].menuwidth = 0;
+ if (title)
+ {
+ if (strlen(title) > MENULEN - 2) {
+ dstrcpy(menusystem.menus[num].title," TITLE TOO LONG ");
+ } else {
+ dstrcpy(menusystem.menus[num].title,title);
+ }
+ }
+ else
+ {
+ dstrcpy(menusystem.menus[num].title,"");
+ }
+
+ return menusystem.nummenus++;
+}
+
+t_menuitem * add_item(const char *item, const char *status, t_action action, const char *data, char itemdata) // Add item to the "current" menu
+{
+ t_menuitem *mi;
+ t_menu *m;
+
+ m = &(menusystem.menus[menusystem.nummenus-1]);
+ mi = &(m->items[m->numitems]);
+ mi->handler = NULL; // No handler
+ if (item) {
+ if (strlen(item) > MENULEN - 2) {
+ dstrcpy(mi->item,"ITEM TOO LONG");
+ } else {
+ dstrcpy(mi->item,item);
+ if (strlen(item) > m->menuwidth) m->menuwidth = strlen(item);
+ }
+ } else dstrcpy(mi->item,"");
+
+ if (status) {
+ if (strlen(status) > STATLEN - 2) {
+ dstrcpy(mi->status,"STATUS STRING TOO LONG");
+ } else {
+ dstrcpy(mi->status,status);
+ }
+ } else dstrcpy(mi->status,"");
+
+ mi->action = action;
+
+ if (data) {
+ if (strlen(data) > ACTIONLEN - 2) {
+ strcpy(mi->data,"ACTION STRING LONG");
+ } else {
+ strcpy(mi->data,data); // This is only null terminated
+ }
+ } else strcpy(mi->data,"");
+
+ switch (action)
+ {
+ case OPT_SUBMENU:
+ mi->itemdata.submenunum = itemdata;
+ break;
+ case OPT_CHECKBOX:
+ mi->itemdata.checked = itemdata;
+ break;
+ case OPT_RADIOBTN:
+ mi->itemdata.choice = itemdata;
+ break;
+ }
+ mi->index = m->numitems++;
+ mi->parindex = menusystem.nummenus-1;
+ return mi;
+}
+
+
diff --git a/menu/menu.h b/menu/menu.h
new file mode 100644
index 00000000..dc6a9de5
--- /dev/null
+++ b/menu/menu.h
@@ -0,0 +1,176 @@
+/* -*- c -*- ------------------------------------------------------------- *
+ *
+ * Copyright 2004 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,
+ * Bostom MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/* This program can be compiled for DOS with the OpenWatcom compiler
+ * (http://www.openwatcom.org/):
+ *
+ * wcl -3 -osx -mt <filename>.c
+ */
+
+#ifndef __MENU_H__
+#define __MENU_H__
+
+#include "biosio.h"
+#include "string.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 SPACEKEY 57 // Scan code for SPACE
+
+// Attributes
+#define NORMALATTR 0x70
+#define REVERSEATTR 0x87
+#define INACTATTR 0x74
+#define REVINACTATTR 0x87
+#define STATUSATTR 0xF0
+#define FILLCHAR 178
+#define FILLATTR 0x07
+#define SHADOWATTR 0x08
+#define SPACECHAR ' '
+
+#define TFILLCHAR ' '
+#define TITLEATTR 0x70
+#define TITLESTR "COMBOOT Menu System for SYSLINUX developed by Murali Krishnan Ganapathy$" // Must be $ terminated
+
+// Single line Box drawing Chars
+
+#define TOPLEFT 218
+#define BOTLEFT 192
+#define TOPRIGHT 191
+#define BOTRIGHT 217
+#define TOP 196
+#define BOT 196
+#define LEFT 179
+#define RIGHT 179
+
+
+// Double line Box Drawing Chars
+/*
+#define TOPLEFT 201
+#define BOTLEFT 200
+#define TOPRIGHT 187
+#define BOTRIGHT 188
+#define TOP 205
+#define BOT 205
+#define LEFT 186
+#define RIGHT 186
+*/
+
+// Attributes of the menu system
+#define MAXMENUS 10 // Maximum number of menu's allowed
+#define MAXMENUSIZE 10 // Maximum number of entries in each menu
+#define MENULEN 30 // Each menu entry is atmost MENULEN chars including the terminating $
+#define STATLEN 70 // Maximum length of status string
+#define ACTIONLEN 80 // Maximum length of an action string
+
+// Layout of menu
+#define MENUROW 3 // Row where menu is displayed
+#define MENUCOL 4 // Col where menu is displayed
+#define MENUPAGE 1 // show in display page 1
+#define STATLINE 23 // Line number where status line starts
+
+// Other Chars
+#define SUBMENUCHAR 175 // This is >> symbol, << is 174
+#define CHECKED 'X' // This is solid bullet
+#define UNCHECKED 250 // Light bullet
+
+typedef enum {OPT_INACTIVE, OPT_SUBMENU, OPT_RUN, OPT_EXITMENU, OPT_CHECKBOX, OPT_RADIOBTN, OPT_EXIT} t_action;
+
+typedef union {
+ char submenunum;
+ char checked; // For check boxes
+ char choice; // For Radio buttons
+} t_itemdata;
+
+struct s_menuitem;
+struct s_menu;
+struct s_menusystem;
+
+typedef void (*t_item_handler)(struct s_menusystem *, struct s_menuitem *);
+typedef void (*t_menusystem_handler)(struct s_menusystem *, struct s_menuitem *);
+
+typedef struct s_menuitem {
+ char item[MENULEN+2];
+ char status[STATLEN+2];
+ char active; // Is this item active or not
+ t_action action;
+ char data[ACTIONLEN+2];
+ t_itemdata itemdata; // Data depends on action value
+ char index; // Index within the menu array
+ char parindex; // Index of the menu in which this item appears.
+ void * extra_data; // Any other data user can point to
+ t_item_handler handler; // Pointer to function of type menufn
+} t_menuitem;
+
+typedef struct s_menu {
+ char numitems;
+ char menuwidth;
+ char title[MENULEN+2];
+ t_menuitem items[MAXMENUSIZE];
+} t_menu;
+
+typedef struct s_menusystem {
+ t_menu menus[MAXMENUS];
+ char title[80]; // Maximum title length
+ t_menusystem_handler handler; // Handler function called every time a menu is re-printed.
+ char nummenus;
+ char normalattr;
+ char reverseattr;
+ char inactattr;
+ char revinactattr;
+ char statusattr;
+ char fillchar;
+ char fillattr;
+ char spacechar;
+ char tfillchar;
+ char titleattr;
+ char shadowattr;
+ char statline;
+ char menupage;
+} t_menusystem;
+
+// User callable Functions
+
+t_menuitem * showmenus(char startmenu);
+
+void init_menusystem(const char *title);
+
+void set_normal_attr(char normal, char selected, char inactivenormal, char inactiveselected);
+
+void set_status_info(char statusattr, char statline);
+
+void set_title_info(char tfillchar, char titleattr);
+
+void set_misc_info(char fillchar, char fillattr,char spacechar, char shadowattr);
+
+void reg_handler( t_menusystem_handler handler); // Register handler
+
+void unreg_handler();
+
+// Create a new menu and return its position
+int add_menu(const char *title);
+
+// Add item to the "current" menu
+t_menuitem * add_item(const char *item, const char *status, t_action action, const char *data, char itemdata);
+
+#endif
diff --git a/menu/simple.c b/menu/simple.c
new file mode 100644
index 00000000..13c14800
--- /dev/null
+++ b/menu/simple.c
@@ -0,0 +1,80 @@
+/* -*- c -*- ------------------------------------------------------------- *
+ *
+ * Copyright 2004 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,
+ * Bostom MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+#include "menu.h"
+#include "biosio.h"
+#include "string.h"
+#include "syslinux.h"
+
+int syslinux;
+char TESTING,RESCUE,MAIN,PREP;
+
+int main(void)
+{
+ t_menuitem * curr;
+
+ // Choose the default title and setup default values for all attributes....
+ init_menusystem(NULL);
+
+ // Choose the default values for all attributes and char's
+ // -1 means choose defaults (Actually the next 4 lines are not needed)
+ //set_normal_attr (-1,-1,-1,-1);
+ //set_status_info (-1,-1);
+ //set_title_info (-1,-1);
+ //set_misc_info(-1,-1,-1,-1);
+
+ // menuindex = add_menu(" Menu Title ");
+ // add_item("Item string","Status String",TYPE,"any string",NUM)
+ // TYPE = OPT_RUN | OPT_EXITMENU | OPT_SUBMENU | OPT_CHECKBOX | OPT_INACTIVE
+ // "any string" not used by the menu system, useful for storing kernel names
+ // NUM = index of submenu if OPT_SUBMENU,
+ // 0/1 default checked state if OPT_CHECKBOX
+ // unused otherwise.
+
+ TESTING = add_menu(" Testing ");
+ add_item("Memory Test","Perform extensive memory testing",OPT_RUN, "memtest",0);
+ add_item("Exit this menu","Go one level up",OPT_EXITMENU,"exit",0);
+
+ RESCUE = add_menu(" Rescue Options ");
+ add_item("Linux Rescue","linresc",OPT_RUN,"linresc",0);
+ add_item("Dos Rescue","dosresc",OPT_RUN,"dosresc",0);
+ add_item("Windows Rescue","winresc",OPT_RUN,"winresc",0);
+ add_item("Exit this menu","Go one level up",OPT_EXITMENU,"exit",0);
+
+ MAIN = add_menu(" Main Menu ");
+ add_item("Prepare","prep",OPT_RUN,"prep",0);
+ add_item("Rescue options...","Troubleshoot a system",OPT_SUBMENU,NULL,RESCUE);
+ add_item("Testing...","Options to test hardware",OPT_SUBMENU,NULL,TESTING);
+ add_item("Exit to prompt", "Exit the menu system", OPT_EXITMENU, "exit", 0);
+
+ syslinux = issyslinux(); // Find if syslinux is running
+
+ if (syslinux) gototxtmode(); // Else assume we are running in a DOS box
+ curr = showmenus(MAIN); // Initial menu is the one with index MAIN
+ if (curr)
+ {
+ if (curr->action == OPT_EXIT) return 0;
+ if (curr->action == OPT_RUN)
+ {
+ if (syslinux) runcommand(curr->data);
+ else csprint(curr->data);
+ return 1;
+ }
+ sprint("Error in programming!$"); // Must be $ terminated
+ }
+ return 0;
+}
+
diff --git a/menu/startup.S16 b/menu/startup.S16
new file mode 100644
index 00000000..df821093
--- /dev/null
+++ b/menu/startup.S16
@@ -0,0 +1,16 @@
+ .code16gcc
+
+ .globl _start
+_start:
+ movw $__bss_start,%di
+ xorl %eax,%eax
+ movw $_end,%cx
+ subw %di,%cx
+ shrw $2,%cx
+ rep ; stosl
+
+ calll main
+ movb $0x4c,%ah
+ int $0x21
+ hlt
+
diff --git a/menu/startup.asm b/menu/startup.asm
new file mode 100644
index 00000000..074175c2
--- /dev/null
+++ b/menu/startup.asm
@@ -0,0 +1,55 @@
+ name cstart
+ assume nothing
+
+ extern _start_:proc
+
+DGROUP group _TEXT,CONST,STRINGS,_DATA,DATA,XIB,XI,XIE,YIB,YI,YIE,_BSS
+
+_TEXT segment use16 para public 'CODE'
+
+ assume cs:_TEXT
+
+ org 100h
+_cstart_ proc near
+
+ call _start_
+
+ mov ah,4Ch ; AL = exit code
+ int 21h
+
+_cstart_ endp
+
+_TEXT ends
+
+ ; Make sure we declare all the DGROUP segments...
+
+CONST segment word public 'DATA'
+CONST ends
+STRINGS segment word public 'DATA'
+STRINGS ends
+XIB segment word public 'DATA'
+XIB ends
+XI segment word public 'DATA'
+XI ends
+XIE segment word public 'DATA'
+XIE ends
+YIB segment word public 'DATA'
+YIB ends
+YI segment word public 'DATA'
+YI ends
+YIE segment word public 'DATA'
+YIE ends
+DATA segment word public 'DATA'
+DATA ends
+
+ public _small_code_
+
+_DATA segment word public 'DATA'
+_small_code_ db 0
+_DATA ends
+
+_BSS segment word public 'BSS'
+_BSS ends
+
+ end _cstart_
+
diff --git a/menu/string.c b/menu/string.c
new file mode 100644
index 00000000..9d90b5b9
--- /dev/null
+++ b/menu/string.c
@@ -0,0 +1,73 @@
+/* -*- c -*- ------------------------------------------------------------- *
+ *
+ * Copyright 2004 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,
+ * Bostom MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include "string.h"
+
+/* String routines */
+void *memset(void *buf, int chr, unsigned int len)
+{
+ asm("cld ; rep ; stosb" : "+D" (buf), "+c" (len) : "a" (chr));
+ return buf;
+}
+
+char *strcpy(char *dst, const char *src)
+{
+ char *r = dst;
+ char c;
+
+ do {
+ c = *src++;
+ *dst++ = c;
+ } while ( c );
+
+ return r;
+}
+
+char *strcat(char *dst, const char * src)
+{
+ char *r = dst;
+
+ while (*dst++); // Find end of string
+ dst--;
+ while (*src) *dst++ = *src++; // Append
+ *dst = '\0'; // Terminate string
+
+ return r;
+}
+
+void dstrcpy(char *dst, const char *src) // DOS strcpy: Make it $ terminated and null terminated
+{
+ while ( *src )
+ *dst++ = *src++;
+
+ *dst++ = '$';
+ *dst = '\0';
+}
+
+int strcmp(const char *a, const char*b)
+{
+ while (*a)
+ {
+ if (*a < *b) return -1;
+ if (*a++ > *b++) return 1;
+ }
+ if (*b) return 1; else return 0;
+}
+
+int strlen(const char *a)
+{
+ int ans = 0;
+
+ while (*a++) ans++;
+ return ans;
+}
+
diff --git a/menu/string.h b/menu/string.h
new file mode 100644
index 00000000..8aa4628e
--- /dev/null
+++ b/menu/string.h
@@ -0,0 +1,19 @@
+
+#ifndef __STRING_H__
+#define __STRING_H__
+
+/* String routines */
+
+void *memset(void *buf, int chr, unsigned int len);
+
+char *strcpy(char *dst, const char *src);
+
+void dstrcpy(char *dst, const char *src); // DOS strcpy: Make it $ terminated and null terminated
+
+char *strcat(char *dst, const char * src);
+
+int strcmp(const char *a,const char*b);
+
+int strlen(const char *a);
+
+#endif
diff --git a/menu/syslinux.c b/menu/syslinux.c
new file mode 100644
index 00000000..40b357f7
--- /dev/null
+++ b/menu/syslinux.c
@@ -0,0 +1,51 @@
+/* -*- c -*- ------------------------------------------------------------- *
+ *
+ * Copyright 2004 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,
+ * Bostom MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include "syslinux.h"
+#include "biosio.h"
+
+static inline int asm_issyslinux(void)
+{
+ unsigned long eax, ebx, ecx, edx;
+
+ asm("movb $0x30,%%ah ; int $0x21"
+ : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx));
+
+ return (eax == 0x53590000) && (ebx == 0x534c0000) &&
+ (ecx == 0x494e0000) && (edx == 0x55580000);
+}
+
+char issyslinux()
+{
+ return asm_issyslinux();
+}
+
+static inline void asm_runcommand(char *cmd)
+{
+ asm volatile("int $0x22" : : "a" (0x0003), "b" (cmd));
+}
+
+void runcommand(char *cmd)
+{
+ asm_runcommand(cmd);
+}
+
+static inline void asm_gototxtmode()
+{
+ asm volatile("int $0x22" : : "a" (0x0005));
+}
+
+void gototxtmode()
+{
+ asm_gototxtmode();
+}
+
diff --git a/menu/syslinux.h b/menu/syslinux.h
new file mode 100644
index 00000000..550c10a9
--- /dev/null
+++ b/menu/syslinux.h
@@ -0,0 +1,11 @@
+
+#ifndef _SYSLINUX_H_
+#define _SYSLINUX_H_
+
+char issyslinux(); // Check if syslinux is running
+
+void runcommand(char *cmd); // Run specified command
+
+void gototxtmode(); // Change mode to text mode
+
+#endif