From 3edbc5585266a34df2b8708b86fc95bf667c00ed Mon Sep 17 00:00:00 2001 From: hpa Date: Mon, 2 Feb 2004 08:40:14 +0000 Subject: [PATCH] Menu system from Murali --- menu/Makefile | 38 ++++++ menu/README | 31 +++++ menu/biosio.c | 204 ++++++++++++++++++++++++++++ menu/biosio.h | 54 ++++++++ menu/com16.ld | 185 +++++++++++++++++++++++++ menu/complex.c | 200 +++++++++++++++++++++++++++ menu/menu.c | 407 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ menu/menu.h | 176 ++++++++++++++++++++++++ menu/simple.c | 80 +++++++++++ menu/startup.S16 | 16 +++ menu/startup.asm | 55 ++++++++ menu/string.c | 73 ++++++++++ menu/string.h | 19 +++ menu/syslinux.c | 51 +++++++ menu/syslinux.h | 11 ++ 15 files changed, 1600 insertions(+) create mode 100644 menu/Makefile create mode 100644 menu/README create mode 100644 menu/biosio.c create mode 100644 menu/biosio.h create mode 100644 menu/com16.ld create mode 100644 menu/complex.c create mode 100644 menu/menu.c create mode 100644 menu/menu.h create mode 100644 menu/simple.c create mode 100644 menu/startup.S16 create mode 100644 menu/startup.asm create mode 100644 menu/string.c create mode 100644 menu/string.h create mode 100644 menu/syslinux.c create mode 100644 menu/syslinux.h diff --git a/menu/Makefile b/menu/Makefile new file mode 100644 index 0000000..4824f05 --- /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 0000000..5014978 --- /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 0000000..dcc806b --- /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 0000000..b090266 --- /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 .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 0000000..7310929 --- /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 0000000..04aefce --- /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 0000000..74acad0 --- /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 0000000..dc6a9de --- /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 .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 0000000..13c1480 --- /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 0000000..df82109 --- /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 0000000..074175c --- /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 0000000..9d90b5b --- /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 0000000..8aa4628 --- /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 0000000..40b357f --- /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 0000000..550c10a --- /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 -- 2.7.4