diff options
author | H. Peter Anvin <hpa@zytor.com> | 2009-03-12 21:26:39 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2009-03-12 21:26:39 -0700 |
commit | 4171516d8fa8997db187a8d41a51344402c2dc8d (patch) | |
tree | fb2e1f310dc4bf6e9b442a09c1bc343767e8aa59 /com32 | |
parent | 14b47f77ec944c0cc8cb56d5e220ce67846dcf4d (diff) | |
parent | 7a708f025b241d8aca62014ebe7279fc605b1a46 (diff) | |
download | syslinux.git-4171516d8fa8997db187a8d41a51344402c2dc8d.tar.gz syslinux.git-4171516d8fa8997db187a8d41a51344402c2dc8d.tar.xz syslinux.git-4171516d8fa8997db187a8d41a51344402c2dc8d.zip |
Merge branch 'hdt'
Diffstat (limited to 'com32')
92 files changed, 12371 insertions, 873 deletions
diff --git a/com32/LICENCE b/com32/LICENCE index 4fd64b3c..8934e8fb 100644 --- a/com32/LICENCE +++ b/com32/LICENCE @@ -2,7 +2,7 @@ libcom32 and libutil are licensed under the MIT license: ## ----------------------------------------------------------------------- ## -## Copyright 2004-2008 H. Peter Anvin - All Rights Reserved +## Copyright 2004-2009 H. Peter Anvin - All Rights Reserved ## ## Permission is hereby granted, free of charge, to any person ## obtaining a copy of this software and associated documentation @@ -27,5 +27,5 @@ libcom32 and libutil are licensed under the MIT license: ## ## ----------------------------------------------------------------------- -The files in the samples and modules directories are mostly under the +The files in the sample, modules and libgpl directories are mostly under the GNU GPL (see the file COPYING in the directory above.) diff --git a/com32/MCONFIG b/com32/MCONFIG index 2b7e018b..d1af9455 100644 --- a/com32/MCONFIG +++ b/com32/MCONFIG @@ -23,10 +23,18 @@ GCCOPT := $(call gcc_ok,-std=gnu99,) \ com32 = $(topdir)/com32 +ifneq ($(NOGPL),1) +GPLLIB = $(com32)/gpllib/libcom32gpl.a +GPLINCLUDE = -I$(com32)/gplinclude +else +GPLLIB = +GPLINCLUDE = +endif + CFLAGS = $(GCCOPT) -W -Wall -march=i386 \ -fomit-frame-pointer -D__COM32__ \ -nostdinc -iwithprefix include \ - -I$(com32)/libutil/include -I$(com32)/include + -I$(com32)/libutil/include -I$(com32)/include $(GPLINCLUDE) SFLAGS = $(GCCOPT) -D__COM32__ -march=i386 LDFLAGS = -m elf_i386 -T $(com32)/lib/com32.ld LIBGCC := $(shell $(CC) $(GCCOPT) --print-libgcc) @@ -35,7 +43,8 @@ LNXCFLAGS = -I$(com32)/libutil/include -W -Wall -O -g -D_GNU_SOURCE LNXSFLAGS = -g LNXLDFLAGS = -g -C_LIBS = $(com32)/libutil/libutil_com.a $(com32)/lib/libcom32.a $(LIBGCC) +C_LIBS = $(com32)/libutil/libutil_com.a $(GPLLIB) \ + $(com32)/lib/libcom32.a $(LIBGCC) C_LNXLIBS = $(com32)/libutil/libutil_lnx.a .SUFFIXES: .lss .c .lo .o .elf .c32 .lnx diff --git a/com32/Makefile b/com32/Makefile index 9dee9684..64049d07 100644 --- a/com32/Makefile +++ b/com32/Makefile @@ -1,4 +1,3 @@ -SUBDIRS = lib libutil modules menu samples rosh - +SUBDIRS = lib gpllib libutil modules menu samples rosh cmenu hdt all tidy dist clean spotless install: set -e; for d in $(SUBDIRS); do $(MAKE) -C $$d $@; done diff --git a/com32/cmenu/CHANGES b/com32/cmenu/CHANGES new file mode 100644 index 00000000..cce21838 --- /dev/null +++ b/com32/cmenu/CHANGES @@ -0,0 +1,32 @@ +Changes in v1.2 +--------------- +* Allowed menu's to have names. Submenu's can be referred to by names + instead of their index in the menu system. This allows user to refer + to submenus which are not yet part of the menusystem. +* help pages can be longer than one screen +* menugen.py: Python script for converting .menu files to C source code + .menu files can be used to descibe most static uses of menu system, + including SubMenus, Checkboxes, RadioButtons, User Authentication and + Context sensitive help. You can also restrict use of certain items + to users with certain credentials. + + See MENU_FORMAT for the format of .menu files + +* display.c32: Takes the name of the text file to display and displays it + allowing user to scroll through the text. + + USAGE: display.c32 <filename> + + <filename> must be an absolute filename (including the /isolinux part) + +Changes in v1.1 +--------------- +* Additional handler type: Keys handler +* Menuitem handlers now have a return value of type t_handler_return. + For all simple cases, you just return ACTION_VALID or ACTION_INVALID + (For some types of menu items, handlers are ignored, and for + others the return value is ignored) +* add_menu takes an extra argument (to better control memory footprint) + You can just set it to -1 to choose the default value +* Now the menu system support long menu's using scroll bars. +* Support for passwords and context sensitive help is added. diff --git a/com32/cmenu/HISTORY b/com32/cmenu/HISTORY new file mode 100644 index 00000000..8e9beb3f --- /dev/null +++ b/com32/cmenu/HISTORY @@ -0,0 +1,20 @@ + +GCC & 32-bit code +----------------- +Due to the limitations of the COM file format, +(64KB limit on memory footprint) the code has been changed +so that the code compiles to a 32-bit COMBOOT program. +Since the code makes use of BIOS calls, this code cannot be +compiled into a format which can execute under Linux. As a +side effect, there is no nice way to debug this code. In order +to debug this code, you will have to run the code under syslinux. + +GCC & 16-bit code +----------------- +The code was ported to GCC by Peter Anvin. + +OpenWatcom & 16-bit code +------------------------ +Originally this code was written for the Openwatcom compiler +and generated .COM files, which could execute under DOS as well as +SYSLINUX. diff --git a/com32/cmenu/MANUAL b/com32/cmenu/MANUAL new file mode 100644 index 00000000..4e70149c --- /dev/null +++ b/com32/cmenu/MANUAL @@ -0,0 +1,348 @@ + Overview of writing code using the menu system + ---------------------------------------------- + +This file contains implementation and developer documentation. +For simple cases, you should start by using simple.c as a template. +complex.c illustrates most of the features available in the menu system. + +Menu Features currently supported are: +* menu items, +* submenus, +* disabled items, +* checkboxes, +* invisible items (useful for dynamic menus), and +* Radio menus, +* Context sensitive help +* Authenticated users + +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 +* Shortcut keys + +1. Overview +----------- + +The code usually consists of many stages. + + * Configuring the menusytem + * Installing global handlers [optional] + * Populating the menusystem + * Executing the menusystem + * Processing the result + +1.1 Configuring the menusystem +------------------------------ +This includes setting the window the menu system should use, +the choice of colors, the title of the menu etc. In most functions +calls, a value of -1 indicates that the default value be used. +For details about what the arguments are look at function +declarations in menu.h + +<code> + // Choose the default title and setup default values for all attributes.... + init_menusystem(NULL); + set_window_size(1,1,23,78); // Leave one row/col border all around + + // 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); +</code> + +1.2 Populating the menusystem +----------------------------- +This involves adding a menu to the system, and the options which +should appear in the menu. An example is given below. + +<code> + MAINMENU = add_menu(" Menu Title ",-1); + CHECKED = 1; + add_item("option1","Status 1",OPT_RUN,"kernel1 arg1=val1",0); + add_item("selfloop","Status 2",OPT_SUBMENU,NULL,MAINMENU); + add_item("othermenu","Status 3",OPT_SUBMENU,"menuname",0); + add_sep(); + add_item("checkbox,"Checkbox Info",OPT_CHECKBOX,NULL,CHECKED); + add_item("Exit ","Status String",OPT_EXITMENU,NULL,0); +</code> + +The call to add_menu has two arguments, the first being the title of +the menu and the second an upper bound on the number of items in the menu. +Putting a -1, will use the default (see MENUSIZE in menu.h). If you try +to add more items than specified, the extra items will not appear in +the menu. The accuracy of this number affects the memory required +to run the system. + +If you do not want to keep track of the return values, you can also use +the following variant of add_menu + +<code> +add_named_menu("main"," Menu Title ",-1) +</code> + +This creates a new menu as before and gives it a name "main". When using named +menus, you get an alternate way for adding submenu's. See below for details. + +The call to add_item has five arguments. +The first argument is the text which appears in the menu itself. +The second argument is the text displayed in the status line. +The third argument indicates the type of this menuitem. It is one of +the following + + * OPT_RUN : executable content + * OPT_EXITMENU : exits menu to parent + * OPT_SUBMENU : if selected, displays a submenu + * OPT_CHECKBOX : associates a boolean with this item which can be toggled + * OPT_RADIOMENU: associates this with a radio menu. + After execution, the data field of this item will point + to the option selected. + * OPT_SEP : A menu seperator (visually divide menu into parts) + * OPT_RADIOITEM: this item is one of the options in a RADIOMENU + * OPT_INACTIVE : A disabled item (user cannot select this) + * OPT_INVISIBLE: This item will not be displayed. + +The fourth argument is the value of the data field always a string. +Usually this string is just copied and nothing is done with it. Two +cases, where it is used. + +In case of a radiomenu the input string is ignored and the "data" field +points to the menuitem chosen (Dont forget to typecast this pointer to +(t_menuitem *) when reading this info). + +In case of a submenu, this string if non-trivial is interpreted as the +name of the submenu which should be linked there. This interpretation +happens when the menu is first run and not when the menu system is being +created. This allows the user to create the menusystem in an arbitrary +order. + + +The fifth argument is a number whose meaning depends on the type of the +item. For a CHECKBOX it should be 0/1 setting the initial state of the +checkbox. For a SUBMENU it should be the index of the menu which should +be displayed if this option is chosen. Incase the data field is non-trivial, +this number is ignored and computed later. For a RADIOMENU it should be the +index of the menu which contains all the options (All items in that menu +not of type RADIOITEM are ignored). For all other types, this +argument has no meaning at all. + +A call to add_sep is a convenient shorthand for calling add_item +with the type set to OPT_SEP. + +1.3 Executing the menusystem +---------------------------- +This is the simplest of all. Just call showmenus, with the index +of the main menu as its argument. It returns a pointer to the menu +item which was selected by the user. + +<code> + choice = showmenus(MAIN); // Initial menu is the one with index MAIN + // or choice = showmenus(find_menu_num("main")); // Initial menu is the one named "main" +</code> + +1.4 Processing the result +------------------------- +This pointer will either be NULL (user hit Escape) or always point +to a menuitem which can be "executed", i.e. it will be of type OPT_RUN. +Usually at this point, all we need to do is to ask syslinux to run +the command associated with this menuitem. The following code executes +the command stored in choice->data (there is no other use for the data +field, except for radiomenu's) + +<code> + if (choice) + { + if (choice->action == OPT_RUN) + { + if (syslinux) runcommand(choice->data); + else csprint(choice->data,0x07); + return 1; + } + csprint("Error in programming!",0x07); + } +</code> + +2. Advanced features +-------------------- +Everycall to add_item actually returns a pointer to the menuitem +created. This can be useful when using any of the advanced features. + +2.1 extra_data +-------------- +For example, every menuitem has an "extra_data" field (a pointer) +which the user can use to point any data he/she pleases. The menusystem +itself does not use this field in anyway. + +2.2 helpid +---------- +Every item also has a field called "helpid". It is meant to hold some +kind of identifier which can be referenced and used to generate +a context sensitive help system. This can be set after a call to +add_item as follows +<code> + add_item("selfloop","Status 2",OPT_SUBMENU,NULL,MAINMENU); + set_item_options('A',4516); +</code> + +The first is the shortcut key for this entry. You can put -1 to ensure +that the shortcut key is not reset. The second is some unsigned integer. +If this value is 0xFFFF, then the helpid is not changed. + +2.3 Installing global handlers +------------------------------ +It is possible to register handlers for the menu system. These are +user functions which are called by the menusystem in certain +situations. Usually the handlers get a pointer to the menusystem +datastructure as well as a pointer to the current item selected. +Some handlers may get additional information. Some handlers are +required to return values while others are not required to do so. + +Currently the menusystem support three types of global handlers +* timeout handler +* screen handler +* keys handler + +2.3.1 timeout handler +--------------------- +This is installed using a call to "reg_ontimeout(fn,numsteps,stepsize)" +function. fn is a pointer to a function which takes no arguments and +returns one of CODE_WAIT, CODE_ENTER, CODE_ESCAPE. This function is +called when numsteps*stepsize Centiseconds have gone by without any +user input. If the function returns CODE_WAIT then the menusystem +waits for user input (for another numsteps*stepsize Centiseconds). If +CODE_ENTER or CODE_ESCAPE is returned, then the system pretends that +the user hit ENTER or ESCAPE on the keyboard and acts accordingly. + +2.3.2 Screen handler +-------------------- +This is installed using a call to "reg_handler(HDLR_SCREEN,fn)". fn is +a pointer to a function which takes a pointer to the menusystem +datastructure and the current item selected and returns nothing. +This is called everytime a menu is drawn (i.e. everytime user changes +the current selection). This is meant for displaying any additional +information which reflects the current state of the system. + +2.3.3 Keys handler +------------------ +This is installed using a call to "reg_handler(HDLR_KEYS,fn)". fn is +a pointer to a function which takes a pointer to the menusystem +datastructure, the current item and the scan code of a key and returns +nothing. This function is called when the user presses a key which +the menusystem does not know to dealwith. In any case, when this call +returns the screen should not have changed in any way. Usually, +one can change the active page and display any output needed and +reset the active page when you return from this call. + +complex.c implements a key_handler, which implements a simple +context sensitive help system, by displaying the contents of a +file whose name is based on the helpid of the active item. + +Also, complex.c's handler allows certain users to make changes +to edit the commands associated with a menu item. + +2.4 Installing item level handlers +---------------------------------- +In addition to global handlers, one can also install handlers for each +individual item. A handler for an individual item is a function which +takes a pointer to the menusystem datastructure and a pointer to the +current item and return a structure of type t_handler_return. Currently +it has two bit fields "valid" and "refresh". + +This handler is called when the user hits "enter" on a RUN item, or +changes the status of a CHECKBOX, or called *after* a radio menu choice +has been set. In all other cases, installing a handler has no effect. + +The handler can change any of the internal datastructures it pleases. +For e.g. in a radiomenu handler, one can change the text displayed +on the menuitem depending on which choice was selected (see complex.c +for an example). The return values are ignored for RADIOMENU's. + +In case of RUN items: the return values are used as follows. If the +return value of "valid" was false, then this user choice is ignored. +This is useful if the handler has useful side effects. For e.g. +complex.c has a Login item, whose handler always return INVALID. It +sets a global variable to the name of the user logged in, and enables +some menu items, and makes some invisible items visible. + +* If the handler does not change the visibility status of any items, + the handler should set "refresh" to 0. +* If the handler changes the visibility status of items in the current + menu set "refresh" to 1. +* If you are changing the visibility status of items in menu's currently + not displayed, then you can set "refresh" to 0. +* Changing the visibility status of items in another menu + which is currently displayed, is not supported. If you do it, + the screen contents may not reflect the change until you get to the + menu which was changed. When you do get to that menu, you may notice + pieces of the old menu still on the screen. + +In case of CHECKBOXES: the return value of "valid" is ignored. Because, +the handler can change the value of checkbox if the user selected value +is not appropriate. only the value of "refresh" is honored. In this case +all the caveats in the previous paragraph apply. + +menu.h defines two instances of t_handler_return +ACTION_VALID and ACTION_INVALID for common use. These set the valid flag +to 1 and 0 respectively and the refresh flag to 0. + +3. Things to look out for +------------------------- +When you define the menu system, always declare it in the opposite +order, i.e. all lower level menu's should be defined before the higher +level menus. This is because in order to define the MAINMENU, you need +to know the index assigned to all its submenus. + +4. Additional Modules +--------------------- +You can make use of the following additional modules, in writing your +handlers. + +* Passwords +* Help + +4.1 Passwords +------------- +This module was written by Th. Gebhardt. This is basically a modification +of the DES crypt function obtained by removing the dependence of the +original crypt function on C libraries. The following functions are +defined + + init_passwords(PWDFILE) + // Read in the password database from the file + authenticate_user(user,pwd) + // Checks if user,pwd is valid + isallowed(user,perm) + // Checks if the user has a specified permission + close_passwords() + // Unloads password database from memory + + See the sample password file for more details about the file format + and the implementation of permissions. + +See complex.c for a example of how to use this. + +4.2 Help +-------- +This can be used to set up a context sensitive help system. The following +functions are defined + + init_help(HELPBASEDIR) + // Initialises the help system. All help files will be loaded + // from the directory specified. + runhelpsystem(context) + // Displays the contents of HELPBASEDIR/hlp<context>.txt + +In order to have a functioning help system, you just need to create +the hlp<NNNNN>.txt files and initialize the help system by specifying +the base directory. + +The first line of this file assumed to be the title of the help screen. +You can use ^N and ^O to change attributes absolutely and relatively, +i.e. [^O]46 (i.e. Ctrl-O followed by chars 4 and 6) will set the +attribute to 46, while [^N]08 will XOR the current attribute with +specified number, thus in this case the first [^N]08 will turn on +highlighting and the second one will turn it off. diff --git a/com32/cmenu/MENU_FORMAT b/com32/cmenu/MENU_FORMAT new file mode 100644 index 00000000..24cb02f8 --- /dev/null +++ b/com32/cmenu/MENU_FORMAT @@ -0,0 +1,262 @@ +A .menu file can be used to describe basic menu structures which can be converted +into C code which can then be compiled into a .c32 file for use with SYSLINUX. +The format of a .menu file is similar to an ini file, but with important +differences. + +Lines starting with # and ; are treated as comments. Blank lines are used to +separate the attributes of one menu item from another. Multiple blank lines are +equivalent to a single one. In other contexts Blank lines are not significant. + +Menus +----- +Each menu declaration starts with a line containing the name of menu in [ ]. +This is the "nickname" of the menu and should be different for different menus. +This is not visible to the user of the menu system. The initial menu must +be called "main" + +The menu declaration is followed by lines which set the attributes of the menu. +This is followed by a blank line and followed by declaration of menu items in +that menu. + +All lines which occur before the first menu declaration is considered as +a global declaration. + +Abstract Format +--------------- + +The overall format should look like this + +-------------------------------------------------------- +<GLOBAL SETTINGS> + +[menuname1] + +<MENU SETTINGS> + +<ITEM 1> + +... + +<ITEM N> + +[menuname2] + +<MENU SETTINGS> + +<ITEM A> + +<ITEM B> + +---------------------------------------------------------- + +GLOBAL SETTINGS +--------------- +The following global settings are now supported. Many of the keywords +accept what we call a "DOT COMMAND" as argument. Simply put they are +instructions to the menu system to perform certain actions. +The syntax and semantics of DOT COMMANDS are given later in the section +titled "DOT COMMANDS". + +videomode: (default 0xFF) [Use with care] + The textmode in which the whole menu system should operate. + Must be a number (use 0x notation for hexadecimal). + Lookup Ralph Brown Interrupt List and search for Video Mode + to find a number to put here. + + setting to 0xFF will mean, menu system will use the current + video mode. + +title: + The title of the whole menu system + +top, left, bot, right: (default 0,0,21,79) + The area of the screen used by the menu system. The remaining + part of the screen can be used by the user for anything. + +helpdir: (default /isolinux/help) + Location of the directory where help information is stored. The + help files must be called "hlpNNNNN.txt" where NNNNN is the helpid. + +pwdfile: (default /isolinux/passwd) + The name of the password file which contains user, password and permissions + See "passwd" file for details regarding format of this file + +editrow: (default 23) + the row on the screen where one can edit the command line. This must + be outside the menu area. Set this to a negative number to disable + editing the command line. In case of authenticated users, the current + user must have "editcmd" permissions to edit the command line + +pwdrow: (default 23) + The row on the screen used for user authentication. Must be outside + menu area (can be same as editrow). Set to negative to disable + user authentication + +skipif: (default 0) + The OR of the bits in the Shift-flags any of which can cause the menu system + to be skipped all together (0 means menu system always runs). It can also + be a combination of "Alt","Ctrl","Shift","Caps","Ins","Scroll". + When menu system starts it checks if any of the specified keys are On/pressed. + If true, the system exits immediately and executes the skipcmd. + + e.g. setting it to "shift-alt-caps" means menu will be skipped if alt OR shift + is pressed OR caps is on. setting to "0" means menu will always run. + +skipcmd: (default .exit) + valid terminal commands: .exit .ignore or any syslinux command + command to execute if menu system is skipped. This must be a non-trivial + syslinux command if skipcondn is not "0". ".exit" means menu system + quits back to the boot prompt. + +startfile: (default "") + if non-empty the system will display the contents of this file before launching + the menusystem. This happens only if the menusystem is not skipped. Can be used + to display licensing, usage or welcome messages. A file with given name + is expected to be found in the helpdir directory. + +exitcmd: (default .exit) + valid terminal commands: .exit .repeat or any syslinux command + The default command to execute when user quits the menu system. + +exitcmdroot: (default =exitcmd) + Same as exitcmd except applies when current user has "root" privileges. If not + specified, it is assumed to be the same as exitcmd + +timeout: (default 3000) + The amount of time (in multiple of 0.1 seconds) to wait for user keypress. If no + key pressed for specified duration then the timeoutcmd is executed. + +totaltimeout: (default 0) + The total amount of time (in multiples of 0.1 seconds) the system will wait for + user to make a decision. If no decision has been made in the specified duration + totaltimeoutcmd will be executed + + NOTE: This does not include the time spent browsing the help system or + the time taken for the user to enter his/her authentication credentials. + +timeoutcmd: (default .beep) + valid terminal commands: .wait .enter .escape or any syslinux command + command to execute when we timeout waiting for user input. The commands + .enter and .escape tell the menu system to pretend the user typed ENTER or + ESCAPE on the keyboard, while .wait tells the menusystem to wait for one + more time period + +totaltimeoutcmd: (default .wait) + choices are the same as for timeoutcmd + +MENU SETTINGS +------------- + +title: (must be specified) + Title of this menu + +row,col: [Usage not recomended] + position in screen where this menu should be placed. By default the + system will choose an appropriate location. + +ITEM ATTRIBUTES +--------------- + +item: + The string displayed to the user. Characters enclosed in < > are highlighted. + +shortcut: (default -1) valid values A-Za-z0-9 or -1 [Usage not recommended] + Sets the shortcut key for this item. If set to -1, the system scans for the first + highlighted letter in the given range and sets that as the shortcut key. + +info: (default same as data) + Additional textual information displayed in the status bar + +type: + the type of entry this item represents. This is one of the following: + + run: choosing this will run something in SYSLINUX + use data to specify the actual command to execute + exitmenu: exit to parent menu + submenu: choosing will open up submenu + use data to specify the "nickname" of the menu + which should come here + sep: Position a separator here + inactive: menu item is disabled + checkbox: this is a checkbox + use state to set initial state + invisible: User does not see this item + radioitem: One choice in a radiomenu + radiomenu: Allow user to choose one of many choices + (initial choice is always NULL) + login: Selecting this will allow user to login to system + +data: + for run items, the syslinux command to execute + for submenus and radiomenus, nickname of menu + for checkboxes, string to be added to kernel command line (if set) + for radioitems, string to be added to kernel command line (if chosen) + +ipappend: + ipappend flag to pass to PXELINUX (harmless for other variants of SYSLINUX) + See syslinux documentation for meaning of the FLAGS + +helpid: (default 65535 which is not a valid id) + associates a context for the help system. + +state: (default 0) + Initial state of a checkbox (for other items this has no meaning) + +perms: (default "") + string containing the name of the permission which user must + have to activate this item. For eg. if this item is a submenu + then user needs the permission in order to open the submenu + +argsmenu: (default "") + Name of the menu to be scanned for setting additional arguments to + pass to command line when this item is chosen for execution. Submenus + of specified menu are also scanned. Only checkboxes and radiomenu's + are scanned. Items of other type in this menu is silently ignored. + + +DOT COMMANDS +------------ +Dot commands are basically instructions to the menu system to do certain things. + +A "single command" is one of the following + +[NT] A syslinux command (any DOT command not starting with a "." is assumed to be this) +[NT] .beep [n] +[NT] .help <file> +[NT] .nop +[T] .exit or .quit (equivalent) +[T] .repeat or .wait or .ignore (all three are equivalent) + +A dot command is a sequence of "single commands" separated by a "%". When a dot command +is executed the system executes all the given "single commands" in the specified order. +All the commands marked "[T]" are terminal commands, i.e. when the system encounters +such a command it stops processing the dot command and returns the terminal command +which caused the termination to the caller (who usually interprets the command +appropriately). + +All commands marked with [NT] are non-terminal commands, i.e. once these commands are +processed the system continues to process the remaining "single commands" specified in +the "DOT COMMAND". + +Note: The case of a syslinux command is tricky. When executed, the command should never return +(if the specified kernel exists) so the fact that we consider it a [NT] should be taken with +a pinch of salt. However, if the syslinux command does return (in case of no kernel), then +remaining "single commands" are processed. In particular "ker1 arg1 % ker2 arg2 % ker3 args" +has the effect of executing the first kernel which exists + +.nop: + Does nothing. +.beep: + .beep [n] produces a beep n times. n must be between 0 and 9. If not specified n=1. + (hence .beep 0 is equivalent to .nop) +.help: + .help <file> + Displays the help file <file> which is assumed to be in the "help" directory. Its name + does not have to be in the form "hlpNNNNN.txt" (as required by the context sensitive help). + Executing this command will mean the appropriate help screen is displayed till the user hits + ESCAPE + +The meaning of the Terminal commands can vary with the context in which it is used. For example, +a ".enter" or ".escape" does not have any meaning in the "onerrorcmd" context but it has a meaning +in the "ontimeout" context. In case the user gives a Terminal command which does not make sense, it +is upto the code (in this case adv_menu.tpl) to do what it pleases. diff --git a/com32/cmenu/Makefile b/com32/cmenu/Makefile new file mode 100644 index 00000000..010fa122 --- /dev/null +++ b/com32/cmenu/Makefile @@ -0,0 +1,80 @@ +## ----------------------------------------------------------------------- +## +## Copyright 2001-2009 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., 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. +## +## ----------------------------------------------------------------------- + +## +## Makefile for the complex menu system +## + +NOGPL := 1 + +# This must be defined before MCONFIG is included +LIBS = libmenu/libmenu.a + +topdir = ../.. +include ../MCONFIG + +CFLAGS += -I./libmenu + +LIBMENU = libmenu/syslnx.o libmenu/com32io.o libmenu/tui.o \ + libmenu/menu.o libmenu/passwords.o libmenu/des.o libmenu/help.o + +CMENUS = $(patsubst %.c,%.c32,$(wildcard *.c)) +IMENUS = $(patsubst %.menu,%.c32,$(wildcard *.menu)) + +MENUS = $(CMENUS) $(IMENUS) + +.SUFFIXES: .S .c .o .elf .c32 .menu + +.PRECIOUS: %.c +%.c: %.menu adv_menu.tpl + python menugen.py --input=$< --output=$@ --template=adv_menu.tpl + +.PRECIOUS: %.o +%.o: %.S + $(CC) $(SFLAGS) -c -o $@ $< + +.PRECIOUS: %.o +%.o: %.c %.h + $(CC) $(CFLAGS) -c -o $@ $< + +.PRECIOUS: %.elf +%.elf: %.o libmenu/libmenu.a $(LIBS) + $(LD) $(LDFLAGS) -o $@ $^ + +%.c32: %.elf + $(OBJCOPY) -O binary $< $@ + +all: menus + +libmenu/libmenu.a: $(LIBMENU) + -rm -f $@ + $(AR) cq $@ $^ + $(RANLIB) $@ + +tidy dist: + rm -f *.o *.lo *.a *.lst *.elf + +libclean: + rm -f libmenu/*.o libmenu/*.a + +clean: tidy menuclean libclean + rm -f *.lss *.c32 *.com + +menuclean: + rm -f $(patsubst %.menu,%.c,$(wildcard *.menu)) + +spotless: clean libclean menuclean + rm -f *~ \#* + +menus: $(MENUS) + +install: # Don't install samples diff --git a/com32/cmenu/README b/com32/cmenu/README new file mode 100644 index 00000000..d585d2fa --- /dev/null +++ b/com32/cmenu/README @@ -0,0 +1,95 @@ + Text User Interface using comboot + --------------------------------- + +This is a menu system written by Murali Krishnan Ganapathy and ported +from OpenWatcom to gcc by HPA. It is currently being maintained by the +original author. + +To configure the menus, you need to set up a menu configuration file +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 menu configuration file; If your menu system is only going +to have entries corresponding to things which can be executed directly, +then you can create a file in ".menu" format instead of the C code. + +See MENU_FORMAT for the syntax of .menu files + +The resulting code is a 32-bit COMBOOT code, and hence can be executed +only under syslinux. You can use tools like bochs to help debug your +code. + +Menu Features currently supported are: +* menu items, +* submenus, +* disabled items, +* checkboxes, +* invisible items (useful for dynamic menus), and +* Radio menus, +* Context sensitive help +* Authenticated users +* Editing commands associated with items + +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 +* Shortcut keys + +Features +-------- +This is a general purpose menu system implemented using only BIOS calls, +so it can be executed in a COMBOOT environment as well. It is highly +customizable. Some features include: + +* Status line + Display any help information associated with each menu item. +* Window + Specify a window within which the menu system draws all its menu's. + It is upto the user to ensure that the menu's fit within the window. +* Positioning submenus + By default, each submenu is positioned just below the corresponding + entry of the parent menu. However, the user may position each menu + at a specific location of his choice. This is useful, when the menu's + have lots of options. +* Registering handlers for each menu item + This is mainly used for checkboxes and radiomenu's, where a selection may + result in disabling other menu items/checkboxes +* Global Screen Handler + This is called every time the menu is redrawn. The user can display + additional information (usually outside the window where the menu is + being displayed). See the complex.c for an example, where the global + handler is used to display the choices made so far. +* Global Keys Handler + This is called every time the user presses a key which the menu + system does not understand. This can be used to display context + sensitive help. See complex.c for how to use this hook to implement + a context sensitive help system as well as "On the fly" editing + of commands associated with menus. +* Shortcut Keys + With each item one can register a shortcut key from [A-Za-z0-9]. + Pressing a key within that range, will take you to the next item + with that shortcut key (so you can have multiple items with the + same shortcut key). The default shortcut key for each item, is + the lower case version of the first char of the item in the range + [A-Za-z0-9]. +* Escape Keys + Each item entry can have a substring enclosed in < and >. This part + is highlighted. Can be used to highlight the shortcut keys. By default + if an item has a <, then the first char inside < and > in the range + [A-Za-z0-9] is converted to lower case and set as the shortcut key. +* Ontimeout handler + The user can register an ontimeout handler, which gets called if + no key has been pressed for a user specific amount of time (default 5 min). + For an example see the complex.c file. + +Credits +------- +* The Watcom developers and Peter Anvin for figuring out an OS + independent startup code. +* Thomas for porting the crypt function and removing all C library + dependencies +* Peter Anvin for porting the code to GCC + +- Murali (gmurali+guicd@cs.uchicago.edu) diff --git a/com32/cmenu/TODO b/com32/cmenu/TODO new file mode 100644 index 00000000..d2ee82c4 --- /dev/null +++ b/com32/cmenu/TODO @@ -0,0 +1,2 @@ +* Write COMBOOT code to read .menu files and parse them directly + - take the name of menu file to parse from commandline diff --git a/com32/cmenu/adv_menu.tpl b/com32/cmenu/adv_menu.tpl new file mode 100644 index 00000000..6ce4acf8 --- /dev/null +++ b/com32/cmenu/adv_menu.tpl @@ -0,0 +1,452 @@ +All the lines in this file not in between --something BEGINS-- and --something ENDS-- +is ignored completely and will not make it into the generated C file + +This file has sections of C code each section delimited by --secname BEGINS-- +and --secname ENDS--. In the generated C code certain section may be used multiple +times. Currently the different section which must be defined are + +header, system, item, login and footer + +Any additional sections you define will be processed but will probably not make it +to the C code if you do not modify menugen.py to use it. + +header and footer go through unmolested. The remaining are % substituted using +python rules. Basically it means %(var)s gets replaced by the value of the variable +"var" which is a processed form of what is read from the .menu file + +NOTE: There is absolutely no C code in the python script, so you are free to +modify this template to suit your needs + +--header BEGINS-- +/* -*- c -*- ------------------------------------------------------------- * + * + * Copyright 2004-2006 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 NULL +#define NULL ((void *) 0) +#endif + +#include "menu.h" +#include "help.h" +#include "passwords.h" +#include "com32io.h" +#include <string.h> +#include <stdlib.h> + +#define MAX_CMD_LINE_LENGTH 514 + +typedef struct s_xtra { + long ipappend; // Stores the ipappend flag to send (useful for PXELINUX only) + char *argsmenu; // Stores the name of menu which contains options for the given RUN item + char *perms; // stores the permissions required to activate the item +} t_xtra; + +typedef t_xtra *pt_xtra; // Pointer to extra datastructure + +// Types of dot commands for which caller takes responsibility of handling +// In some case some commands may not make sense, it is up to the caller +// to handle cases which do not make sense +typedef enum {QUIT_CMD, REPEAT_CMD, ENTER_CMD, ESCAPE_CMD} t_dotcmd; + + +/*----------------- Global Variables */ + +// default user +#define GUEST_USER "guest" + +// for local commands. return value of execdotcmd +#define QUIT_CMD 0 +#define RPT_CMD 1 + +char username[12]; // Name of user currently using the system + +int PWD_ROW; // Line number where user authentication happens +int EDIT_ROW; // row where User Tab + +char loginstr[] = "<L>ogin "; +char logoutstr[30]; + +int vmode; // The video mode we want to be in +char timeoutcmd[MAX_CMD_LINE_LENGTH]; // Command to execute on timeout +char totaltimeoutcmd[MAX_CMD_LINE_LENGTH]; // Command to execute on totaltimeout + +char QUITSTR[] = ".quit"; // same as exit +char IGNORESTR[]=".ignore"; // same as repeat, wait + +/*---------------- End globals */ + +// returns pointer to first non-space char +// and advances end of str by removing trailing spaces +char * strip(char *str) +{ + char *p,*s,*e; + if (!str) return NULL; + p = str; + s = NULL; + e = NULL; + while (*p) { + if (*p != ' ') { + // mark start of string or record the last visited non-space char + if (!s) s=p; else e=p; + } + p++; + } + *(++e)='\0'; // kill string earlier + return s; +} + +// executes a list of % separated commands +// non-dot commands are assumed to be syslinux commands +// All syslinux commands are appended with the contents of kerargs +// If it fails (kernel not found) then the next one is tried in the +// list +// returns QUIT_CMD or RPT_CMD +t_dotcmd execdotcmd(const char *cmd, char *defcmd, const char *kerargs) +{ + char cmdline[MAX_CMD_LINE_LENGTH]; + char dotcmd[MAX_CMD_LINE_LENGTH]; + char *curr,*next,*p,*args; + char ctr; + + strcpy(dotcmd,cmd); + next = dotcmd; + cmdline[0] = '\0'; + while (*next) { // if something to do + curr = next; + p = strchr(next,'%'); + if (p) { + *p--='\0'; next=p+2; + while (*p == ' ') p--; + *(++p)='\0'; // remove trailing spaces + } else { + if (*defcmd) { // execute defcmd next + next=defcmd; + defcmd=NULL; // exec def cmd only once + } else next=NULL; + } + // now we just need to execute the command "curr" + curr = strip(curr); + if (curr[0] != '.') { // just run the kernel + strcpy(cmdline,curr); + if (kerargs) strcat(cmdline,kerargs); + runsyslinuximage(cmdline,0); // No IPAppend + } else { // We have a DOT command + // split command into command and args (may be empty) + args = curr; + while ( (*args != ' ') && (*args != '\0') ) args++; + if (*args) { // found a space + *args++ = '\0'; + while (*args == ' ') args++; // skip over spaces + } + if ( (strcmp(curr,".exit")==0) || + (strcmp(curr,".quit")==0) + ) + return QUIT_CMD; + if ( (strcmp(curr,".repeat")==0) || + (strcmp(curr,".ignore")==0) || + (strcmp(curr,".wait")==0) + ) + return RPT_CMD; + if (strcmp(curr,".beep")==0) { + if ((args) && ('0' <= args[0]) && (args[0] <= '9')) + ctr = args[0]-'0'; + else ctr=1; + for (;ctr>0; ctr--) beep(); + } + if (strcmp(curr,".help")==0) runhelp(args); + } + } + return RPT_CMD; // by default we do not quit +} + + +TIMEOUTCODE timeout(const char *cmd) +{ + t_dotcmd c; + c = execdotcmd(cmd,".wait",NULL); + switch(c) { + case ENTER_CMD: + return CODE_ENTER; + case ESCAPE_CMD: + return CODE_ESCAPE; + default: + return CODE_WAIT; + } +} + +TIMEOUTCODE ontimeout() +{ + return timeout(timeoutcmd); +} + +TIMEOUTCODE ontotaltimeout() +{ + return timeout(totaltimeoutcmd); +} + +void keys_handler(t_menusystem *ms, t_menuitem *mi,unsigned int scancode) +{ + char nc; + + if ( ((scancode >> 8) == 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) && + (isallowed(username,"editcmd") || isallowed(username,"root"))) { + nc = getnumcols(); + // User typed TAB and has permissions to edit command line + gotoxy(EDIT_ROW,1,ms->menupage); + csprint("Command line:",0x07); + editstring(mi->data,ACTIONLEN); + gotoxy(EDIT_ROW,1,ms->menupage); + cprint(' ',0x07,nc-1,ms->menupage); + } +} + +t_handler_return login_handler(t_menusystem *ms, t_menuitem *mi) +{ + (void)mi; // Unused + char pwd[40]; + char login[40]; + char nc; + 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); + csprint("Enter Username: ",0x07); + getstring(login, sizeof username); + gotoxy(PWD_ROW,1,ms->menupage); + cprint(' ',0x07,nc,ms->menupage); + csprint("Enter Password: ",0x07); + getpwd(pwd, sizeof pwd); + gotoxy(PWD_ROW,1,ms->menupage); + cprint(' ',0x07,nc,ms->menupage); + + if (authenticate_user(login,pwd)) + { + strcpy(username,login); + strcpy(logoutstr,"<L>ogout "); + strcat(logoutstr,username); + mi->item = logoutstr; // Change item to read "Logout" + rv.refresh = 1; // refresh the screen (as item contents changed) + } + else strcpy(username,GUEST_USER); + } + else // User needs to logout + { + strcpy(username,GUEST_USER); + strcpy(logoutstr,""); + mi->item = loginstr; + } + + return rv; +} + +t_handler_return check_perms(t_menusystem *ms, t_menuitem *mi) +{ + char *perms; + pt_xtra x; + + (void) ms; // To keep compiler happy + + x = (pt_xtra) mi->extra_data; + perms = ( x ? x->perms : NULL); + if (!perms) return ACTION_VALID; + + if (isallowed(username,"root") || isallowed(username,perms)) // If allowed + return ACTION_VALID; + else return ACTION_INVALID; +} + +// Compute the full command line to add and if non-trivial +// prepend the string prepend to final command line +// Assume cmdline points to buffer long enough to hold answer +void gencommand(pt_menuitem mi, char *cmdline) +{ + pt_xtra x; + cmdline[0] = '\0'; + strcat(cmdline,mi->data); + x = (pt_xtra) mi->extra_data; + if ( (x) && (x->argsmenu)) gen_append_line(x->argsmenu,cmdline); +} + + +// run the given command together with additional options which may need passing +void runcommand(pt_menuitem mi) +{ + char *line; + pt_xtra x; + long ipappend; + + line = (char *)malloc(sizeof(char)*MAX_CMD_LINE_LENGTH); + gencommand(mi,line); + x = (pt_xtra) mi->extra_data; + ipappend = (x ? x->ipappend : 0); + + runsyslinuximage(line,x->ipappend); + free(line); +} + +// set the extra info for the specified menu item. +void set_xtra(pt_menuitem mi, const char *argsmenu, const char *perms, unsigned int helpid, long ipappend) +{ + pt_xtra xtra; + int bad_argsmenu, bad_perms, bad_ipappend; + + mi->extra_data = NULL; // initalize + mi->helpid = helpid; // set help id + + if (mi->action != OPT_RUN) return; + + bad_argsmenu = bad_perms = bad_ipappend = 0; + if ( (argsmenu==NULL) || (strlen(argsmenu)==0)) bad_argsmenu = 1; + if ( (perms==NULL) || (strlen(perms)==0)) bad_perms = 1; + if ( ipappend==0) bad_ipappend = 1; + + if (bad_argsmenu && bad_perms && bad_ipappend) return; + + xtra = (pt_xtra) malloc(sizeof(t_xtra)); + mi->extra_data = (void *) xtra; + xtra->argsmenu = xtra->perms = NULL; + xtra->ipappend = ipappend; + if (!bad_argsmenu) { + xtra->argsmenu = (char *) malloc(sizeof(char)*(strlen(argsmenu)+1)); + strcpy(xtra->argsmenu,argsmenu); + } + if (!bad_perms) { + xtra->perms = (char *) malloc(sizeof(char)*(strlen(perms)+1)); + strcpy(xtra->perms,perms); + mi->handler = &check_perms; + } +} + +int main(void) +{ + pt_menuitem curr; + char quit; + char exitcmd[MAX_CMD_LINE_LENGTH]; + char exitcmdroot[MAX_CMD_LINE_LENGTH]; + char onerrcmd[MAX_CMD_LINE_LENGTH]; + char startfile[MAX_CMD_LINE_LENGTH]; + char *ecmd; // effective exit command or onerrorcmd + char skipbits; + char skipcmd[MAX_CMD_LINE_LENGTH]; + int timeout; // time in multiples of 0.1 seconds + int totaltimeout; // time in multiples of 0.1 seconds + t_dotcmd dotrv; // to store the return value of execdotcmd + int temp; + + strcpy(username,GUEST_USER); +--header ENDS-- +--system BEGINS-- +/* ---- Initializing menu system parameters --- */ + vmode = %(videomode)s; + skipbits = %(skipcondn)s; + PWD_ROW = %(pwdrow)s; + EDIT_ROW = %(editrow)s; + strcpy(onerrcmd,"%(onerrorcmd)s"); + strcpy(exitcmd,"%(exitcmd)s"); + strcpy(exitcmdroot,"%(exitcmdroot)s"); + // If not specified exitcmdroot = exitcmd + if (exitcmdroot[0] == '\0') strcpy(exitcmdroot,exitcmd); + // Timeout stuff + timeout = %(timeout)s; + strcpy(timeoutcmd,"%(timeoutcmd)s"); + totaltimeout = %(totaltimeout)s; + strcpy(totaltimeoutcmd,"%(totaltimeoutcmd)s"); + strcpy(startfile,"%(startfile)s"); + + init_help("%(helpdir)s"); + init_passwords("%(pwdfile)s"); + init_menusystem("%(title)s"); + set_window_size(%(top)s,%(left)s,%(bot)s,%(right)s); + + // Register the ontimeout handler, with a time out of 10 seconds + reg_ontimeout(ontimeout,timeout*10,0); + reg_ontotaltimeout(ontotaltimeout,totaltimeout*10); + + // Register menusystem handlers + reg_handler(HDLR_KEYS,&keys_handler); +/* ---- End of initialization --- */ +--system ENDS-- +--item BEGINS-- + + curr = add_item("%(item)s","%(info)s",%(type)s,"%(data)s",%(state)d); + set_xtra(curr,"%(argsmenu)s","%(perms)s",%(helpid)d,%(ipappend)d); // Set associated extra info + set_shortcut(%(shortcut)s); +--item ENDS-- +--login BEGINS-- + + curr = add_item(loginstr,"Login/Logout of authentication system",OPT_RUN,NULL,0); + curr->helpid = %(helpid)d; + curr->handler = &login_handler; +--login ENDS-- +--menu BEGINS-- + +/* ------- MENU %(name)s ----- */ + add_named_menu("%(name)s","%(title)s",-1); +--menu ENDS-- +--footer BEGINS-- +/* ------- END OF MENU declarations ----- */ + +// Check if we should skip the menu altogether + quit = 0; // Dont skip the menu + if (getshiftflags() & skipbits) { // we must skip the menu altogther and execute skipcmd + dotrv = execdotcmd(skipcmd,".beep%.exit",NULL); // Worst case we beep and exit + if (dotrv == QUIT_CMD) quit = 1; + } + +// Switch vide mode if required + if (vmode != 0xFF) setvideomode(vmode); + +// Do we have a startfile to display? + if (startfile[0] != '\0') runhelp(startfile); + +// The main loop + while (quit == 0) { // As long as quit is zero repeat + curr = showmenus(find_menu_num("main")); // Initial menu is the one called "main" + + if (curr) { + if (curr->action == OPT_RUN) { + ecmd = (char *)malloc(sizeof(char)*MAX_CMD_LINE_LENGTH); + gencommand(curr,ecmd); + temp = (curr->extra_data ? ((pt_xtra)curr->extra_data)->ipappend : 0); + runsyslinuximage(ecmd,temp); + // kernel not found so execute the appropriate dot command + dotrv = execdotcmd(onerrcmd,".quit",ecmd); // pass bad cmdline as arg + if (dotrv== QUIT_CMD) quit = 1; + free(ecmd); ecmd = NULL; + } + else csprint("Error in programming!",0x07); + } else { + // find effective exit command + ecmd = ( isallowed(username,"root") ? exitcmdroot : exitcmd); + dotrv = execdotcmd(ecmd,".repeat",NULL); + quit = (dotrv == QUIT_CMD ? 1 : 0); // should we exit now + } + } + +// Deallocate space used and quit + close_passwords(); + close_help(); + close_menusystem(); + return 0; +} + +--footer ENDS-- diff --git a/com32/cmenu/complex.c b/com32/cmenu/complex.c new file mode 100644 index 00000000..94627c4f --- /dev/null +++ b/com32/cmenu/complex.c @@ -0,0 +1,423 @@ +/* -*- 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 NULL +#define NULL ((void *) 0) +#endif + +#include "menu.h" +#include "com32io.h" +#include "help.h" +#include "passwords.h" +#include "des.h" +#include <stdlib.h> +#include <stdio.h> + +/* Global variables */ +char infoline[160]; +char buffer[80]; + +// Different network options +static char nonet[] = "<n>etwork [none]"; +static char dhcpnet[]="<n>etwork [dhcp]"; +static char statnet[]="<n>etwork [static]"; + +static char loginstr[] = "<L>ogin "; +static char logoutstr[]= "<L>ogout "; + +struct { + unsigned int baseurl : 1; // Do we need to specify by url + unsigned int mountcd : 1; // Should we mount the cd + unsigned int winrep : 1; // Want to repair windows? + unsigned int linrep : 1; // Want to repair linux? +} flags; + +// Some menu options +t_menuitem *baseurl,*mountcd,*network,*runprep,*winrep,*linrep; +t_menuitem * stat,*dhcp,*none,*prepopt,*secret; + +// all the menus we are going to declare +unsigned char TESTING,RESCUE,MAIN,PREPMENU,NETMENU,LONGMENU,SECRETMENU; + +char username[12]; // Name of user currently using the system + +/* End globals */ + +TIMEOUTCODE ontimeout() +{ + beep(); + return CODE_WAIT; +} + + +#define INFLINE 22 +#define PWDLINE 3 +#define PWDPROMPT 21 +#define PWDCOLUMN 60 +#define PWDATTR 0x74 +#define EDITPROMPT 21 + +void keys_handler(t_menusystem *ms, t_menuitem *mi,unsigned int scancode) +{ + char nc; + + if ((scancode >> 8) == F1) { // 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) && + (isallowed(username,"editcmd") || isallowed(username,"root"))) { + nc = getnumcols(); + // User typed TAB and has permissions to edit command line + gotoxy(EDITPROMPT,1,ms->menupage); + csprint("Command line:",0x07); + editstring(mi->data,ACTIONLEN); + gotoxy(EDITPROMPT,1,ms->menupage); + cprint(' ',0x07,nc-1,ms->menupage); + } +} + +t_handler_return login_handler(t_menusystem *ms, t_menuitem *mi) +{ + (void)mi; // Unused + char pwd[40]; + char login[40]; + char nc; + t_handler_return rv; + + if (mi->item == loginstr) { /* User wants to login */ + nc = getnumcols(); + gotoxy(PWDPROMPT,1,ms->menupage); + csprint("Enter Username: ",0x07); + getstring(login, sizeof username); + gotoxy(PWDPROMPT,1,ms->menupage); + cprint(' ',0x07,nc,ms->menupage); + csprint("Enter Password: ",0x07); + getpwd(pwd, sizeof pwd); + gotoxy(PWDPROMPT,1,ms->menupage); + cprint(' ',0x07,nc,ms->menupage); + + if (authenticate_user(login,pwd)) + { + strcpy(username,login); + mi->item = logoutstr; // Change item to read "Logout" + } + else strcpy(username,GUEST_USER); + } + else // User needs to logout + { + strcpy(username,GUEST_USER); + mi->item = loginstr; + } + + if (strcmp(username,GUEST_USER)==0) + { + prepopt->action = OPT_INACTIVE; + secret->action = OPT_INVISIBLE; + } + else + { + prepopt->action = OPT_SUBMENU; + prepopt->itemdata.radiomenunum = PREPMENU; + secret->action = OPT_SUBMENU; + secret->itemdata.submenunum = SECRETMENU; + } + rv.valid = 0; + rv.refresh = 1; + return rv; +} + +void msys_handler(t_menusystem *ms, t_menuitem *mi) +{ + char nc; + void *v; + nc = getnumcols(); // Get number of columns + + gotoxy(PWDLINE,PWDCOLUMN,ms->menupage); + csprint("User: ",PWDATTR); + cprint(ms->fillchar,ms->fillattr,sizeof username,ms->menupage); + gotoxy(PWDLINE,PWDCOLUMN +6,ms->menupage); + 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); + return; + } + strcpy (infoline," "); + if (flags.baseurl) strcat(infoline,"baseurl=http://192.168.11.12/gui "); + if (flags.mountcd) strcat(infoline,"mountcd=yes "); + v = (void *)network->data; + if (v!=NULL) // Some network option specified + { + strcat(infoline,"network="); + strcat(infoline,(char *)(((t_menuitem *)v)->data)); + } + if (flags.winrep) strcat(infoline,"repair=win "); + 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); + csprint("Kernel Arguments:",0x07); + gotoxy(INFLINE,17,ms->menupage); + csprint(infoline,0x07); +} + +t_handler_return network_handler(t_menusystem *ms, t_menuitem *mi) +{ + // mi=network since this is handler only for that. + (void)ms; // Unused + + if (mi->data == (void *)none) mi->item = nonet; + if (mi->data == (void *)stat) mi->item = statnet; + if (mi->data == (void *)dhcp) mi->item = dhcpnet; + return ACTION_INVALID; // VALID or INVALID does not matter +} + +t_handler_return checkbox_handler(t_menusystem *ms, t_menuitem *mi) +{ + (void)ms; /* Unused */ + + if (mi->action != OPT_CHECKBOX) return ACTION_INVALID; + + if (strcmp(mi->data,"baseurl") == 0) flags.baseurl = (mi->itemdata.checked ? 1 : 0); + 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); + 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; +} + +int main() +{ + t_menuitem * curr; + char cmd[160]; + char ip[30]; + + // Set default username as guest + strcpy(username,GUEST_USER); + + // Switch video mode here + // setvideomode(0x18); // or whatever mode you want + + // Choose the default title and setup default values for all attributes.... + init_passwords("/isolinux/password"); + init_help("/isolinux/help"); + init_menusystem(NULL); + set_window_size(1,1,20,78); // Leave some space around + + // 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); // Display status on the last line + //set_title_info (-1,-1); + //set_misc_info(-1,-1,-1,-1); + + // Register the menusystem handler + 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); + + NETMENU = add_menu(" Init Network ",-1); + none = add_item("<N>one","Dont start network",OPT_RADIOITEM,"no ",0); + dhcp = add_item("<d>hcp","Use DHCP",OPT_RADIOITEM,"dhcp ",0); + stat = add_item("<s>tatic","Use static IP I will specify later",OPT_RADIOITEM,"static ",0); + + TESTING = add_menu(" Testing ",-1); + set_menu_pos(5,55); + add_item("<M>emory Test","Perform extensive memory testing",OPT_RUN, "memtest",0); + add_item("<I>nvisible","You dont see this",OPT_INVISIBLE,"junk",0); + add_item("<E>xit this menu","Go one level up",OPT_EXITMENU,"exit",0); + + RESCUE = add_menu(" Rescue Options ",-1); + add_item("<L>inux Rescue","linresc",OPT_RUN,"linresc",0); + add_item("<D>os Rescue","dosresc",OPT_RUN,"dosresc",0); + add_item("<W>indows Rescue","winresc",OPT_RUN,"winresc",0); + add_item("<E>xit this menu","Go one level up",OPT_EXITMENU,"exit",0); + + PREPMENU = add_menu(" Prep options ",-1); + baseurl = add_item("<b>aseurl by IP?","Specify gui baseurl by IP address",OPT_CHECKBOX,"baseurl",0); + mountcd = add_item("<m>ountcd?","Mount the cdrom drive?",OPT_CHECKBOX,"mountcd",0); + network = add_item(dhcpnet,"How to initialise network device?",OPT_RADIOMENU,NULL,NETMENU); + add_sep(); + winrep = add_item("Reinstall <w>indows","Re-install the windows side of a dual boot setup",OPT_CHECKBOX,"winrepair",0); + linrep = add_item("Reinstall <l>inux","Re-install the linux side of a dual boot setup",OPT_CHECKBOX,"linrepair",0); + add_sep(); + runprep = add_item("<R>un prep now","Execute prep with the above options",OPT_RUN,"prep",0); + add_item("<E>xit this menu","Go up one level",OPT_EXITMENU,"exitmenu",0); + baseurl->handler = &checkbox_handler; + mountcd->handler = &checkbox_handler; + winrep->handler = &checkbox_handler; + linrep->handler = &checkbox_handler; + network->handler = &network_handler; + flags.baseurl = 0; + flags.mountcd = 0; + flags.winrep = 0; + flags.linrep = 0; + + SECRETMENU = add_menu(" Secret Menu ",-1); + add_item("secret 1","Secret",OPT_RUN,"A",0); + add_item("secret 2","Secret",OPT_RUN,"A",0); + + LONGMENU = add_menu(" Long Menu ",40); // Override default here + add_item("<A>a","Aa",OPT_RUN,"A",0); + add_item("<B>b","Ab",OPT_RUN,"A",0); + add_item("<C>","A",OPT_RUN,"A",0); + add_item("<D>","A",OPT_RUN,"A",0); + add_item("<E>","A",OPT_RUN,"A",0); + add_item("<F>","A",OPT_RUN,"A",0); + add_item("<G>","A",OPT_RUN,"A",0); + add_item("<H>","A",OPT_RUN,"A",0); + add_item("<I>","A",OPT_RUN,"A",0); + add_item("<J>","A",OPT_RUN,"A",0); + add_item("<K>","A",OPT_RUN,"A",0); + add_item("<L>","A",OPT_RUN,"A",0); + add_item("<J>","A",OPT_RUN,"A",0); + add_item("<K>","A",OPT_RUN,"A",0); + add_item("<L>","A",OPT_RUN,"A",0); + add_item("<M>","A",OPT_RUN,"A",0); + add_item("<N>","A",OPT_RUN,"A",0); + add_item("<O>","A",OPT_RUN,"A",0); + add_item("<P>","A",OPT_RUN,"A",0); + add_item("<Q>","A",OPT_RUN,"A",0); + add_item("<R>","A",OPT_RUN,"A",0); + add_item("<S>","A",OPT_RUN,"A",0); + add_item("<T>","A",OPT_RUN,"A",0); + add_item("<U>","A",OPT_RUN,"A",0); + add_item("<V>","A",OPT_RUN,"A",0); + add_item("<W>","A",OPT_RUN,"A",0); + add_item("<X>","A",OPT_RUN,"A",0); + add_item("<Y>","A",OPT_RUN,"A",0); + add_item("<Z>","A",OPT_RUN,"A",0); + add_item("<1>","A",OPT_RUN,"A",0); + add_item("<2>","A",OPT_RUN,"A",0); + add_item("<3>","A",OPT_RUN,"A",0); + add_item("<4>","A",OPT_RUN,"A",0); + add_item("<5>","A",OPT_RUN,"A",0); + add_item("<6>","A",OPT_RUN,"A",0); + add_item("<7>","A",OPT_RUN,"A",0); + add_item("<8>","A",OPT_RUN,"A",0); + add_item("<9>","A",OPT_RUN,"A",0); + + MAIN = add_menu(" Main Menu ",8); + curr = add_item(loginstr,"Login as a privileged user",OPT_RUN,NULL,0); + set_item_options(-1,23); + curr->handler = &login_handler; + + add_item("<P>repare","prep",OPT_RUN,"prep",0); + set_item_options(-1,24); + prepopt = add_item("<P>rep options...","Options for prep image: Requires authenticated user",OPT_INACTIVE,NULL,PREPMENU); + set_item_options(-1,25); + + add_item("<R>escue options...","Troubleshoot a system",OPT_SUBMENU,NULL,RESCUE); + set_item_options(-1,26); + add_item("<T>esting...","Options to test hardware",OPT_SUBMENU,NULL,TESTING); + set_item_options(-1,27); + add_item("<L>ong Menu...","test menu system",OPT_SUBMENU,NULL,LONGMENU); + set_item_options(-1,28); + secret = add_item("<S>ecret Menu...","Secret menu",OPT_INVISIBLE,NULL,SECRETMENU); + set_item_options(-1,29); + add_item("<E>xit to prompt", "Exit the menu system", OPT_EXITMENU, "exit", 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 + { + 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) + { + strcpy(cmd,curr->data); + if (curr == runprep) + { + strcat(cmd,infoline); + if (network->data == (void *)stat) // We want static + { + csprint("Enter IP address (last two octets only): ",0x07); + strcpy(ip, "Junk"); + editstring(ip, sizeof ip); + strcat(cmd,"ipaddr=192.168."); + strcat(cmd,ip); + } + } + if (issyslinux()) + runsyslinuxcmd(cmd); + else csprint(cmd,0x07); + return 1; // Should not happen when run from SYSLINUX + } + } + // If user quits the menu system, control comes here + // If you want to execute some specific command uncomment the next two lines + + // if (syslinux) runcommand(YOUR_COMMAND_HERE); + // else csprint(YOUR_COMMAND_HERE,0x07); + + // Deallocate space used for these data structures + close_passwords(); + close_help(); + close_menusystem(); + + // Return to prompt + return 0; +} diff --git a/com32/cmenu/display.c b/com32/cmenu/display.c new file mode 100644 index 00000000..5391d7fd --- /dev/null +++ b/com32/cmenu/display.c @@ -0,0 +1,37 @@ +/* -*- c -*- ------------------------------------------------------------- * + * + * Copyright 2004-2006 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 NULL +#define NULL ((void *) 0) +#endif + +#include "help.h" +#include "com32io.h" +#include "menu.h" +#include "tui.h" +#include <stdlib.h> +#include <com32.h> +#include <stdio.h> + + +int main(int argc, char *argv[]) +{ + if (argc < 2) { + csprint("Usage: display.c32 <textfile>\n",0x07); + exit(1); + } + + init_help(NULL); // No base dir, so all filenames must be absolute + runhelp(argv[1]); + close_help(); + return 0; +} diff --git a/com32/cmenu/libmenu/com32io.c b/com32/cmenu/libmenu/com32io.c new file mode 100644 index 00000000..31aec5df --- /dev/null +++ b/com32/cmenu/libmenu/com32io.c @@ -0,0 +1,146 @@ +/* -*- 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. + * + * ----------------------------------------------------------------------- */ + +#include <string.h> +#include <com32.h> +#include "com32io.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; + REG_BH(inreg) = page; + __intcall(0x10,&inreg,&outreg); + *row = REG_DH(outreg); + *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; + + REG_AH(inreg) = 0x86; + REG_CX(inreg) = (micro >> 16); + REG_DX(inreg) = (micro & 0xFFFF); + __intcall(0x15,&inreg,&outreg); + 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 */ + REG_AH(inreg) = 0x10; + __intcall(0x16,&inreg,&outreg); + if (scancode) *scancode = REG_AH(outreg); + return REG_AL(outreg); +} + +void getcursorshape(char *start, char *end) +{ + char page = getdisppage(); + REG_AH(inreg) = 0x03; + REG_BH(inreg) = page; + __intcall(0x10,&inreg,&outreg); + *start = REG_CH(outreg); + *end = REG_CL(outreg); +} + +void setcursorshape(char start, char end) +{ + REG_AH(inreg) = 0x01; + REG_CH(inreg) = start; + REG_CL(inreg) = 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; + REG_AL(inreg) = 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) +{ + REG_AH(inreg) = 0x08; + REG_BH(inreg) = page; + __intcall(0x16,&inreg,&outreg); + return REG_AL(outreg); +} diff --git a/com32/cmenu/libmenu/com32io.h b/com32/cmenu/libmenu/com32io.h new file mode 100644 index 00000000..78ce72fa --- /dev/null +++ b/com32/cmenu/libmenu/com32io.h @@ -0,0 +1,112 @@ +/* -*- 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 __COM32IO_H__ +#define __COM32IO_H__ + +#include <com32.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 + +void setdisppage(char num); // Set the display page to specified number + +char getdisppage(); // Get current display page + +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 + +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); // Actually numrows - 1 +} + +static inline char getnumcols(void) +{ + return readbiosb(0x44a); // Actually numcols +} + +static inline char getshiftflags(void) +{ + return readbiosb(0x417); +} + +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 +{ + return readbiosb(0x449); +} + +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/des.c b/com32/cmenu/libmenu/des.c new file mode 100644 index 00000000..47ff78c4 --- /dev/null +++ b/com32/cmenu/libmenu/des.c @@ -0,0 +1,1101 @@ +/* + * FreeSec: libcrypt for NetBSD + * + * Copyright (c) 1994 David Burren + * All rights reserved. + * + * Adapted for FreeBSD-2.0 by Geoffrey M. Rehmet + * this file should now *only* export crypt(), in order to make + * binaries of libcrypt exportable from the USA + * + * Adapted for FreeBSD-4.0 by Mark R V Murray + * this file should now *only* export crypt_des(), in order to make + * a module that can be optionally included in libcrypt. + * + * Adapted for pxelinux menu environment by Th.Gebhardt + * removed dependencies of standard C libs + * added LOWSPACE option (using common space for different arrays) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of other contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This is an original implementation of the DES and the crypt(3) interfaces + * by David Burren <davidb@werj.com.au>. + * + * An excellent reference on the underlying algorithm (and related + * algorithms) is: + * + * B. Schneier, Applied Cryptography: protocols, algorithms, + * and source code in C, John Wiley & Sons, 1994. + * + * Note that in that book's description of DES the lookups for the initial, + * pbox, and final permutations are inverted (this has been brought to the + * attention of the author). A list of errata for this book has been + * posted to the sci.crypt newsgroup by the author and is available for FTP. + * + * ARCHITECTURE ASSUMPTIONS: + * It is assumed that the 8-byte arrays passed by reference can be + * addressed as arrays of u_int32_t's (ie. the CPU is not picky about + * alignment). + */ + + +#define LOWSPACE + +#ifndef NULL +#define NULL ((void *) 0) +#endif + +typedef unsigned long my_u_int32_t; +typedef unsigned char my_u_char_t; + +/* Re-entrantify me -- all this junk needs to be in + * struct crypt_data to make this really reentrant... */ +static my_u_char_t inv_key_perm[64]; +static my_u_char_t inv_comp_perm[56]; +static my_u_char_t u_sbox[8][64]; +static my_u_char_t un_pbox[32]; +static my_u_int32_t en_keysl[16], en_keysr[16]; +static my_u_int32_t de_keysl[16], de_keysr[16]; + +#ifndef LOWSPACE +static my_u_int32_t ip_maskl[8][256], ip_maskr[8][256]; +static my_u_int32_t fp_maskl[8][256], fp_maskr[8][256]; +static my_u_int32_t key_perm_maskl[8][128], key_perm_maskr[8][128]; +static my_u_int32_t comp_maskl[8][128], comp_maskr[8][128]; +#endif + +static my_u_int32_t saltbits; +static my_u_int32_t old_salt; +static my_u_int32_t old_rawkey0, old_rawkey1; + +#ifdef LOWSPACE +static my_u_int32_t common[8][256]; +#endif + +/* Static stuff that stays resident and doesn't change after + * being initialized, and therefore doesn't need to be made + * reentrant. */ +static my_u_char_t init_perm[64], final_perm[64]; +static my_u_char_t m_sbox[4][4096]; + +#ifndef LOWSPACE +static my_u_int32_t psbox[4][256]; +#endif + +/* A pile of data */ +static const my_u_char_t ascii64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +static const my_u_char_t IP[64] = { + 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, + 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, + 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, + 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7 +}; + +static const my_u_char_t key_perm[56] = { + 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, + 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4 +}; + +static const my_u_char_t key_shifts[16] = { + 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 +}; + +static const my_u_char_t comp_perm[48] = { + 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32 +}; + +/* + * No E box is used, as it's replaced by some ANDs, shifts, and ORs. + */ + +static const my_u_char_t sbox[8][64] = { + { + 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, + 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, + 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, + 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 + }, + { + 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, + 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, + 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, + 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 + }, + { + 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, + 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, + 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, + 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 + }, + { + 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, + 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, + 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, + 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 + }, + { + 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, + 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, + 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, + 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 + }, + { + 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, + 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, + 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, + 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 + }, + { + 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, + 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, + 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, + 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 + }, + { + 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, + 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, + 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, + 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 + } +}; + +static const my_u_char_t pbox[32] = { + 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, + 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25 +}; + +static const my_u_int32_t bits32[32] = +{ + 0x80000000, 0x40000000, 0x20000000, 0x10000000, + 0x08000000, 0x04000000, 0x02000000, 0x01000000, + 0x00800000, 0x00400000, 0x00200000, 0x00100000, + 0x00080000, 0x00040000, 0x00020000, 0x00010000, + 0x00008000, 0x00004000, 0x00002000, 0x00001000, + 0x00000800, 0x00000400, 0x00000200, 0x00000100, + 0x00000080, 0x00000040, 0x00000020, 0x00000010, + 0x00000008, 0x00000004, 0x00000002, 0x00000001 +}; + +static const my_u_int32_t bits28[28] = +{ + 0x08000000, 0x04000000, 0x02000000, 0x01000000, + 0x00800000, 0x00400000, 0x00200000, 0x00100000, + 0x00080000, 0x00040000, 0x00020000, 0x00010000, + 0x00008000, 0x00004000, 0x00002000, 0x00001000, + 0x00000800, 0x00000400, 0x00000200, 0x00000100, + 0x00000080, 0x00000040, 0x00000020, 0x00000010, + 0x00000008, 0x00000004, 0x00000002, 0x00000001 +}; + +static const my_u_int32_t bits24[24] = +{ + 0x00800000, 0x00400000, 0x00200000, 0x00100000, + 0x00080000, 0x00040000, 0x00020000, 0x00010000, + 0x00008000, 0x00004000, 0x00002000, 0x00001000, + 0x00000800, 0x00000400, 0x00000200, 0x00000100, + 0x00000080, 0x00000040, 0x00000020, 0x00000010, + 0x00000008, 0x00000004, 0x00000002, 0x00000001 +}; + +static const my_u_char_t bits8[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; +// static const my_u_int32_t *bits28, *bits24; + + +static int +ascii_to_bin(char ch) +{ + if (ch > 'z') + return(0); + if (ch >= 'a') + return(ch - 'a' + 38); + if (ch > 'Z') + return(0); + if (ch >= 'A') + return(ch - 'A' + 12); + if (ch > '9') + return(0); + if (ch >= '.') + return(ch - '.'); + return(0); +} + +static void +des_init(void) +{ + +#ifdef LOWSPACE + int i, j, b; +#else + int i, j, b, k, inbit, obit; + my_u_int32_t *p, *il, *ir, *fl, *fr; +#endif + static int des_initialised = 0; + + if (des_initialised==1) + return; + + old_rawkey0 = old_rawkey1 = 0L; + saltbits = 0L; + old_salt = 0L; + // bits24 = (bits28 = bits32 + 4) + 4; + + /* + * Invert the S-boxes, reordering the input bits. + */ + for (i = 0; i < 8; i++) + for (j = 0; j < 64; j++) { + b = (j & 0x20) | ((j & 1) << 4) | ((j >> 1) & 0xf); + u_sbox[i][j] = sbox[i][b]; + } + + /* + * Convert the inverted S-boxes into 4 arrays of 8 bits. + * Each will handle 12 bits of the S-box input. + */ + for (b = 0; b < 4; b++) + for (i = 0; i < 64; i++) + for (j = 0; j < 64; j++) + m_sbox[b][(i << 6) | j] = + (my_u_char_t)((u_sbox[(b << 1)][i] << 4) | + u_sbox[(b << 1) + 1][j]); + + /* + * Set up the initial & final permutations into a useful form, and + * initialise the inverted key permutation. + */ + for (i = 0; i < 64; i++) { + init_perm[final_perm[i] = IP[i] - 1] = (my_u_char_t)i; + inv_key_perm[i] = 255; + } + + /* + * Invert the key permutation and initialise the inverted key + * compression permutation. + */ + for (i = 0; i < 56; i++) { + inv_key_perm[key_perm[i] - 1] = (my_u_char_t)i; + inv_comp_perm[i] = 255; + } + + /* + * Invert the key compression permutation. + */ + for (i = 0; i < 48; i++) { + inv_comp_perm[comp_perm[i] - 1] = (my_u_char_t)i; + } + + /* + * Set up the OR-mask arrays for the initial and final permutations, + * and for the key initial and compression permutations. + */ + +#ifndef LOWSPACE + for (k = 0; k < 8; k++) { + for (i = 0; i < 256; i++) { + *(il = &ip_maskl[k][i]) = 0L; + *(ir = &ip_maskr[k][i]) = 0L; + *(fl = &fp_maskl[k][i]) = 0L; + *(fr = &fp_maskr[k][i]) = 0L; + for (j = 0; j < 8; j++) { + inbit = 8 * k + j; + if (i & bits8[j]) { + if ((obit = init_perm[inbit]) < 32) + *il |= bits32[obit]; + else + *ir |= bits32[obit-32]; + if ((obit = final_perm[inbit]) < 32) + *fl |= bits32[obit]; + else + *fr |= bits32[obit - 32]; + } + } + } + for (i = 0; i < 128; i++) { + *(il = &key_perm_maskl[k][i]) = 0L; + *(ir = &key_perm_maskr[k][i]) = 0L; + for (j = 0; j < 7; j++) { + inbit = 8 * k + j; + if (i & bits8[j + 1]) { + if ((obit = inv_key_perm[inbit]) == 255) + continue; + if (obit < 28) + *il |= bits28[obit]; + else + *ir |= bits28[obit - 28]; + } + } + *(il = &comp_maskl[k][i]) = 0L; + *(ir = &comp_maskr[k][i]) = 0L; + for (j = 0; j < 7; j++) { + inbit = 7 * k + j; + if (i & bits8[j + 1]) { + if ((obit=inv_comp_perm[inbit]) == 255) + continue; + if (obit < 24) + *il |= bits24[obit]; + else + *ir |= bits24[obit - 24]; + } + } + } + } +#endif + + /* + * Invert the P-box permutation, and convert into OR-masks for + * handling the output of the S-box arrays setup above. + */ + for (i = 0; i < 32; i++) + un_pbox[pbox[i] - 1] = (my_u_char_t)i; + +#ifndef LOWSPACE + for (b = 0; b < 4; b++) + for (i = 0; i < 256; i++) { + *(p = &psbox[b][i]) = 0L; + for (j = 0; j < 8; j++) { + if (i & bits8[j]) + *p |= bits32[un_pbox[8 * b + j]]; + } + } +#endif + des_initialised = 1; +} + + +#ifdef LOWSPACE + +static void +setup_ip_maskl(void) +{ + int i, j, k, inbit, obit; + my_u_int32_t *il; + + for (k = 0; k < 8; k++) { + for (i = 0; i < 256; i++) { + *(il = &common[k][i]) = 0L; + for (j = 0; j < 8; j++) { + inbit = 8 * k + j; + if (i & bits8[j]) { + if ((obit = init_perm[inbit]) < 32) + *il |= bits32[obit]; + } + } + } + } +} + +static void +setup_ip_maskr(void) +{ + int i, j, k, inbit, obit; + my_u_int32_t *ir; + + for (k = 0; k < 8; k++) { + for (i = 0; i < 256; i++) { + *(ir = &common[k][i]) = 0L; + for (j = 0; j < 8; j++) { + inbit = 8 * k + j; + if (i & bits8[j]) { + if ((obit = init_perm[inbit]) >= 32) + *ir |= bits32[obit-32]; + } + } + } + } +} + +static void +setup_fp_maskl(void) +{ + int i, j, k, inbit, obit; + my_u_int32_t *fl; + + for (k = 0; k < 8; k++) { + for (i = 0; i < 256; i++) { + *(fl = &common[k][i]) = 0L; + for (j = 0; j < 8; j++) { + inbit = 8 * k + j; + if (i & bits8[j]) { + if ((obit = final_perm[inbit]) < 32) + *fl |= bits32[obit]; + } + } + } + } +} + +static void +setup_fp_maskr(void) +{ + int i, j, k, inbit, obit; + my_u_int32_t *fr; + + for (k = 0; k < 8; k++) { + for (i = 0; i < 256; i++) { + *(fr = &common[k][i]) = 0L; + for (j = 0; j < 8; j++) { + inbit = 8 * k + j; + if (i & bits8[j]) { + if ((obit = final_perm[inbit]) >= 32) + *fr |= bits32[obit - 32]; + } + } + } + } +} + +static void +setup_key_perm_maskl(void) +{ + int i, j, k, inbit, obit; + my_u_int32_t *il; + + for (k = 0; k < 8; k++) { + for (i = 0; i < 128; i++) { + *(il = &common[k][i]) = 0L; + for (j = 0; j < 7; j++) { + inbit = 8 * k + j; + if (i & bits8[j + 1]) { + if ((obit = inv_key_perm[inbit]) == 255) + continue; + if (obit < 28) + *il |= bits28[obit]; + } + } + } + } +} + +static void +setup_key_perm_maskr(void) +{ + int i, j, k, inbit, obit; + my_u_int32_t *ir; + + for (k = 0; k < 8; k++) { + for (i = 0; i < 128; i++) { + *(ir = &common[k][i]) = 0L; + for (j = 0; j < 7; j++) { + inbit = 8 * k + j; + if (i & bits8[j + 1]) { + if ((obit = inv_key_perm[inbit]) == 255) + continue; + if (obit >= 28) + *ir |= bits28[obit - 28]; + } + } + } + } +} + +static void +setup_comp_maskl(void) +{ + int i, j, k, inbit, obit; + my_u_int32_t *il; + + for (k = 0; k < 8; k++) { + for (i = 0; i < 128; i++) { + *(il = &common[k][i]) = 0L; + for (j = 0; j < 7; j++) { + inbit = 7 * k + j; + if (i & bits8[j + 1]) { + if ((obit=inv_comp_perm[inbit]) == 255) + continue; + if (obit < 24) + *il |= bits24[obit]; + } + } + } + } +} + +static void +setup_comp_maskr(void) +{ + int i, j, k, inbit, obit; + my_u_int32_t *ir; + + for (k = 0; k < 8; k++) { + for (i = 0; i < 128; i++) { + *(ir = &common[k][i]) = 0L; + for (j = 0; j < 7; j++) { + inbit = 7 * k + j; + if (i & bits8[j + 1]) { + if ((obit=inv_comp_perm[inbit]) == 255) + continue; + if (obit >= 24) + *ir |= bits24[obit - 24]; + } + } + } + } +} + +static void +setup_psbox(void) +{ + int i, j, b; + my_u_int32_t *p; + + for (b = 0; b < 4; b++) + for (i = 0; i < 256; i++) { + *(p = &common[b][i]) = 0L; + for (j = 0; j < 8; j++) { + if (i & bits8[j]) + *p |= bits32[un_pbox[8 * b + j]]; + } + } +} + +#endif + +static void +setup_salt(my_u_int32_t salt) +{ + my_u_int32_t obit, saltbit; + int i; + + if (salt == old_salt) + return; + old_salt = salt; + + saltbits = 0L; + saltbit = 1; + obit = 0x800000; + for (i = 0; i < 24; i++) { + if (salt & saltbit) + saltbits |= obit; + saltbit <<= 1; + obit >>= 1; + } +} + + +static my_u_int32_t char_to_int(const char *key) +{ + my_u_int32_t byte0,byte1,byte2,byte3; + byte0 = (my_u_int32_t) (my_u_char_t) key[0]; + byte1 = (my_u_int32_t) (my_u_char_t) key[1]; + byte2 = (my_u_int32_t) (my_u_char_t) key[2]; + byte3 = (my_u_int32_t) (my_u_char_t) key[3]; + + return byte0 << 24 | byte1 << 16 | byte2 << 8 | byte3 ; +} + + +static int +des_setkey(const char *key) +{ + my_u_int32_t k0, k1, rawkey0, rawkey1; + int shifts, round; + + des_init(); + + /* rawkey0 = ntohl(*(const my_u_int32_t *) key); + * rawkey1 = ntohl(*(const my_u_int32_t *) (key + 4)); + */ + + rawkey0 = char_to_int(key); + rawkey1 = char_to_int(key+4); + + if ((rawkey0 | rawkey1) + && rawkey0 == old_rawkey0 + && rawkey1 == old_rawkey1) { + /* + * Already setup for this key. + * This optimisation fails on a zero key (which is weak and + * has bad parity anyway) in order to simplify the starting + * conditions. + */ + return(0); + } + old_rawkey0 = rawkey0; + old_rawkey1 = rawkey1; + + /* + * Do key permutation and split into two 28-bit subkeys. + */ + +#ifdef LOWSPACE + setup_key_perm_maskl(); + k0 = common[0][rawkey0 >> 25] + | common[1][(rawkey0 >> 17) & 0x7f] + | common[2][(rawkey0 >> 9) & 0x7f] + | common[3][(rawkey0 >> 1) & 0x7f] + | common[4][rawkey1 >> 25] + | common[5][(rawkey1 >> 17) & 0x7f] + | common[6][(rawkey1 >> 9) & 0x7f] + | common[7][(rawkey1 >> 1) & 0x7f]; + setup_key_perm_maskr(); + k1 = common[0][rawkey0 >> 25] + | common[1][(rawkey0 >> 17) & 0x7f] + | common[2][(rawkey0 >> 9) & 0x7f] + | common[3][(rawkey0 >> 1) & 0x7f] + | common[4][rawkey1 >> 25] + | common[5][(rawkey1 >> 17) & 0x7f] + | common[6][(rawkey1 >> 9) & 0x7f] + | common[7][(rawkey1 >> 1) & 0x7f]; +#else + k0 = key_perm_maskl[0][rawkey0 >> 25] + | key_perm_maskl[1][(rawkey0 >> 17) & 0x7f] + | key_perm_maskl[2][(rawkey0 >> 9) & 0x7f] + | key_perm_maskl[3][(rawkey0 >> 1) & 0x7f] + | key_perm_maskl[4][rawkey1 >> 25] + | key_perm_maskl[5][(rawkey1 >> 17) & 0x7f] + | key_perm_maskl[6][(rawkey1 >> 9) & 0x7f] + | key_perm_maskl[7][(rawkey1 >> 1) & 0x7f]; + k1 = key_perm_maskr[0][rawkey0 >> 25] + | key_perm_maskr[1][(rawkey0 >> 17) & 0x7f] + | key_perm_maskr[2][(rawkey0 >> 9) & 0x7f] + | key_perm_maskr[3][(rawkey0 >> 1) & 0x7f] + | key_perm_maskr[4][rawkey1 >> 25] + | key_perm_maskr[5][(rawkey1 >> 17) & 0x7f] + | key_perm_maskr[6][(rawkey1 >> 9) & 0x7f] + | key_perm_maskr[7][(rawkey1 >> 1) & 0x7f]; +#endif + + /* + * Rotate subkeys and do compression permutation. + */ + shifts = 0; + for (round = 0; round < 16; round++) { + my_u_int32_t t0, t1; + + shifts += key_shifts[round]; + + t0 = (k0 << shifts) | (k0 >> (28 - shifts)); + t1 = (k1 << shifts) | (k1 >> (28 - shifts)); + +#ifdef LOWSPACE + setup_comp_maskl(); + de_keysl[15 - round] = + en_keysl[round] = common[0][(t0 >> 21) & 0x7f] + | common[1][(t0 >> 14) & 0x7f] + | common[2][(t0 >> 7) & 0x7f] + | common[3][t0 & 0x7f] + | common[4][(t1 >> 21) & 0x7f] + | common[5][(t1 >> 14) & 0x7f] + | common[6][(t1 >> 7) & 0x7f] + | common[7][t1 & 0x7f]; + + setup_comp_maskr(); + de_keysr[15 - round] = + en_keysr[round] = common[0][(t0 >> 21) & 0x7f] + | common[1][(t0 >> 14) & 0x7f] + | common[2][(t0 >> 7) & 0x7f] + | common[3][t0 & 0x7f] + | common[4][(t1 >> 21) & 0x7f] + | common[5][(t1 >> 14) & 0x7f] + | common[6][(t1 >> 7) & 0x7f] + | common[7][t1 & 0x7f]; +#else + de_keysl[15 - round] = + en_keysl[round] = comp_maskl[0][(t0 >> 21) & 0x7f] + | comp_maskl[1][(t0 >> 14) & 0x7f] + | comp_maskl[2][(t0 >> 7) & 0x7f] + | comp_maskl[3][t0 & 0x7f] + | comp_maskl[4][(t1 >> 21) & 0x7f] + | comp_maskl[5][(t1 >> 14) & 0x7f] + | comp_maskl[6][(t1 >> 7) & 0x7f] + | comp_maskl[7][t1 & 0x7f]; + + de_keysr[15 - round] = + en_keysr[round] = comp_maskr[0][(t0 >> 21) & 0x7f] + | comp_maskr[1][(t0 >> 14) & 0x7f] + | comp_maskr[2][(t0 >> 7) & 0x7f] + | comp_maskr[3][t0 & 0x7f] + | comp_maskr[4][(t1 >> 21) & 0x7f] + | comp_maskr[5][(t1 >> 14) & 0x7f] + | comp_maskr[6][(t1 >> 7) & 0x7f] + | comp_maskr[7][t1 & 0x7f]; +#endif + } + return(0); +} + + +static int +do_des( my_u_int32_t l_in, my_u_int32_t r_in, my_u_int32_t *l_out, my_u_int32_t *r_out, int count) +{ + /* + * l_in, r_in, l_out, and r_out are in pseudo-"big-endian" format. + */ + my_u_int32_t l, r, *kl, *kr, *kl1, *kr1; + my_u_int32_t f, r48l, r48r; + int round; + + if (count == 0) { + return(1); + } else if (count > 0) { + /* + * Encrypting + */ + kl1 = en_keysl; + kr1 = en_keysr; + } else { + /* + * Decrypting + */ + count = -count; + kl1 = de_keysl; + kr1 = de_keysr; + } + + /* + * Do initial permutation (IP). + */ + +#ifdef LOWSPACE + setup_ip_maskl(); + l = common[0][l_in >> 24] + | common[1][(l_in >> 16) & 0xff] + | common[2][(l_in >> 8) & 0xff] + | common[3][l_in & 0xff] + | common[4][r_in >> 24] + | common[5][(r_in >> 16) & 0xff] + | common[6][(r_in >> 8) & 0xff] + | common[7][r_in & 0xff]; + setup_ip_maskr(); + r = common[0][l_in >> 24] + | common[1][(l_in >> 16) & 0xff] + | common[2][(l_in >> 8) & 0xff] + | common[3][l_in & 0xff] + | common[4][r_in >> 24] + | common[5][(r_in >> 16) & 0xff] + | common[6][(r_in >> 8) & 0xff] + | common[7][r_in & 0xff]; +#else + l = ip_maskl[0][l_in >> 24] + | ip_maskl[1][(l_in >> 16) & 0xff] + | ip_maskl[2][(l_in >> 8) & 0xff] + | ip_maskl[3][l_in & 0xff] + | ip_maskl[4][r_in >> 24] + | ip_maskl[5][(r_in >> 16) & 0xff] + | ip_maskl[6][(r_in >> 8) & 0xff] + | ip_maskl[7][r_in & 0xff]; + r = ip_maskr[0][l_in >> 24] + | ip_maskr[1][(l_in >> 16) & 0xff] + | ip_maskr[2][(l_in >> 8) & 0xff] + | ip_maskr[3][l_in & 0xff] + | ip_maskr[4][r_in >> 24] + | ip_maskr[5][(r_in >> 16) & 0xff] + | ip_maskr[6][(r_in >> 8) & 0xff] + | ip_maskr[7][r_in & 0xff]; +#endif + + while (count--) { + /* + * Do each round. + */ + kl = kl1; + kr = kr1; + round = 16; + while (round--) { + /* + * Expand R to 48 bits (simulate the E-box). + */ + r48l = ((r & 0x00000001) << 23) + | ((r & 0xf8000000) >> 9) + | ((r & 0x1f800000) >> 11) + | ((r & 0x01f80000) >> 13) + | ((r & 0x001f8000) >> 15); + + r48r = ((r & 0x0001f800) << 7) + | ((r & 0x00001f80) << 5) + | ((r & 0x000001f8) << 3) + | ((r & 0x0000001f) << 1) + | ((r & 0x80000000) >> 31); + /* + * Do salting for crypt() and friends, and + * XOR with the permuted key. + */ + f = (r48l ^ r48r) & saltbits; + r48l ^= f ^ *kl++; + r48r ^= f ^ *kr++; + /* + * Do sbox lookups (which shrink it back to 32 bits) + * and do the pbox permutation at the same time. + */ + +#ifdef LOWSPACE + setup_psbox(); + f = common[0][m_sbox[0][r48l >> 12]] + | common[1][m_sbox[1][r48l & 0xfff]] + | common[2][m_sbox[2][r48r >> 12]] + | common[3][m_sbox[3][r48r & 0xfff]]; +#else + f = psbox[0][m_sbox[0][r48l >> 12]] + | psbox[1][m_sbox[1][r48l & 0xfff]] + | psbox[2][m_sbox[2][r48r >> 12]] + | psbox[3][m_sbox[3][r48r & 0xfff]]; +#endif + /* + * Now that we've permuted things, complete f(). + */ + f ^= l; + l = r; + r = f; + } + r = l; + l = f; + } + /* + * Do final permutation (inverse of IP). + */ + +#ifdef LOWSPACE + setup_fp_maskl(); + *l_out = common[0][l >> 24] + | common[1][(l >> 16) & 0xff] + | common[2][(l >> 8) & 0xff] + | common[3][l & 0xff] + | common[4][r >> 24] + | common[5][(r >> 16) & 0xff] + | common[6][(r >> 8) & 0xff] + | common[7][r & 0xff]; + setup_fp_maskr(); + *r_out = common[0][l >> 24] + | common[1][(l >> 16) & 0xff] + | common[2][(l >> 8) & 0xff] + | common[3][l & 0xff] + | common[4][r >> 24] + | common[5][(r >> 16) & 0xff] + | common[6][(r >> 8) & 0xff] + | common[7][r & 0xff]; +#else + *l_out = fp_maskl[0][l >> 24] + | fp_maskl[1][(l >> 16) & 0xff] + | fp_maskl[2][(l >> 8) & 0xff] + | fp_maskl[3][l & 0xff] + | fp_maskl[4][r >> 24] + | fp_maskl[5][(r >> 16) & 0xff] + | fp_maskl[6][(r >> 8) & 0xff] + | fp_maskl[7][r & 0xff]; + *r_out = fp_maskr[0][l >> 24] + | fp_maskr[1][(l >> 16) & 0xff] + | fp_maskr[2][(l >> 8) & 0xff] + | fp_maskr[3][l & 0xff] + | fp_maskr[4][r >> 24] + | fp_maskr[5][(r >> 16) & 0xff] + | fp_maskr[6][(r >> 8) & 0xff] + | fp_maskr[7][r & 0xff]; +#endif + return(0); +} + + +#if 0 +static int +des_cipher(const char *in, char *out, my_u_int32_t salt, int count) +{ + my_u_int32_t l_out, r_out, rawl, rawr; + int retval; + union { + my_u_int32_t *ui32; + const char *c; + } trans; + + des_init(); + + setup_salt(salt); + + trans.c = in; + rawl = ntohl(*trans.ui32++); + rawr = ntohl(*trans.ui32); + + retval = do_des(rawl, rawr, &l_out, &r_out, count); + + trans.c = out; + *trans.ui32++ = htonl(l_out); + *trans.ui32 = htonl(r_out); + return(retval); +} +#endif + + +void +setkey(const char *key) +{ + int i, j; + my_u_int32_t packed_keys[2]; + my_u_char_t *p; + + p = (my_u_char_t *) packed_keys; + + for (i = 0; i < 8; i++) { + p[i] = 0; + for (j = 0; j < 8; j++) + if (*key++ & 1) + p[i] |= bits8[j]; + } + des_setkey(p); +} + + +void +encrypt(char *block, int flag) +{ + my_u_int32_t io[2]; + my_u_char_t *p; + int i, j; + + des_init(); + + setup_salt(0L); + p = block; + for (i = 0; i < 2; i++) { + io[i] = 0L; + for (j = 0; j < 32; j++) + if (*p++ & 1) + io[i] |= bits32[j]; + } + do_des(io[0], io[1], io, io + 1, flag ? -1 : 1); + for (i = 0; i < 2; i++) + for (j = 0; j < 32; j++) + block[(i << 5) | j] = (io[i] & bits32[j]) ? 1 : 0; +} + +char *crypt(const char *key, const char *setting) +{ + my_u_int32_t count, salt, l, r0, r1, keybuf[2]; + my_u_char_t *p, *q; + static char output[21]; + + des_init(); + + /* + * Copy the key, shifting each character up by one bit + * and padding with zeros. + */ + q = (my_u_char_t *)keybuf; + while (q - (my_u_char_t *)keybuf - 8) { + *q++ = *key << 1; + if (*(q - 1)) + key++; + } + if (des_setkey((char *)keybuf)) + return(NULL); + +#if 0 + if (*setting == _PASSWORD_EFMT1) { + int i; + /* + * "new"-style: + * setting - underscore, 4 bytes of count, 4 bytes of salt + * key - unlimited characters + */ + for (i = 1, count = 0L; i < 5; i++) + count |= ascii_to_bin(setting[i]) << ((i - 1) * 6); + + for (i = 5, salt = 0L; i < 9; i++) + salt |= ascii_to_bin(setting[i]) << ((i - 5) * 6); + + while (*key) { + /* + * Encrypt the key with itself. + */ + if (des_cipher((char *)keybuf, (char *)keybuf, 0L, 1)) + return(NULL); + /* + * And XOR with the next 8 characters of the key. + */ + q = (my_u_char_t *)keybuf; + while (q - (my_u_char_t *)keybuf - 8 && *key) + *q++ ^= *key++ << 1; + + if (des_setkey((char *)keybuf)) + return(NULL); + } + strncpy(output, setting, 9); + + /* + * Double check that we weren't given a short setting. + * If we were, the above code will probably have created + * wierd values for count and salt, but we don't really care. + * Just make sure the output string doesn't have an extra + * NUL in it. + */ + output[9] = '\0'; + p = (my_u_char_t *)output + strlen(output); + } else +#endif + { + /* + * "old"-style: + * setting - 2 bytes of salt + * key - up to 8 characters + */ + count = 25; + + salt = (ascii_to_bin(setting[1]) << 6) + | ascii_to_bin(setting[0]); + + output[0] = setting[0]; + /* + * If the encrypted password that the salt was extracted from + * is only 1 character long, the salt will be corrupted. We + * need to ensure that the output string doesn't have an extra + * NUL in it! + */ + output[1] = setting[1] ? setting[1] : output[0]; + + p = (my_u_char_t *)output + 2; + } + setup_salt(salt); + /* + * Do it. + */ + if (do_des(0L, 0L, &r0, &r1, (int)count)) + return(NULL); + /* + * Now encode the result... + */ + l = (r0 >> 8); + *p++ = ascii64[(l >> 18) & 0x3f]; + *p++ = ascii64[(l >> 12) & 0x3f]; + *p++ = ascii64[(l >> 6) & 0x3f]; + *p++ = ascii64[l & 0x3f]; + + l = (r0 << 16) | ((r1 >> 16) & 0xffff); + *p++ = ascii64[(l >> 18) & 0x3f]; + *p++ = ascii64[(l >> 12) & 0x3f]; + *p++ = ascii64[(l >> 6) & 0x3f]; + *p++ = ascii64[l & 0x3f]; + + l = r1 << 2; + *p++ = ascii64[(l >> 12) & 0x3f]; + *p++ = ascii64[(l >> 6) & 0x3f]; + *p++ = ascii64[l & 0x3f]; + *p = 0; + + return(output); +} diff --git a/com32/cmenu/libmenu/des.h b/com32/cmenu/libmenu/des.h new file mode 100644 index 00000000..67fc6b70 --- /dev/null +++ b/com32/cmenu/libmenu/des.h @@ -0,0 +1,8 @@ + +#ifndef _DES_H_ +#define _DES_H_ + +// des crypt +extern char *crypt (const char *key, const char *salt); + +#endif diff --git a/com32/cmenu/libmenu/help.c b/com32/cmenu/libmenu/help.c new file mode 100644 index 00000000..31944c79 --- /dev/null +++ b/com32/cmenu/libmenu/help.c @@ -0,0 +1,200 @@ +/* -*- 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. + * + * ----------------------------------------------------------------------- */ + +#include "help.h" +#include <stdio.h> +#include "string.h" +#include "com32io.h" +#include <syslinux/loadfile.h> // to read entire file into memory + +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) +{ + int ctr; + char *p= buffer-1; + + if (count < 1) return buffer; + for (ctr=0; ctr < count; ctr++) { + p = strchr(p+1,'\n'); + if (p==NULL) return NULL; + } + return p; +} + +// return the number of lines in buffer +int countlines(char*buffer) +{ + int ans; + const char *p; + + p = buffer-1; + ans = 1; + while(p) {p = strchr(p+1,'\n'); ans++; } + return ans; +} + + +// Print numlines of text starting from buf +void printtext(char*buf, int from) +{ + char *p,*f; + char right,bot,nlines; + + // 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); + + 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 +} + +void showhelp(const char *filename) +{ + char nc,nr,ph; + char *title,*text; + union { char *buffer; void *vbuf; } buf; // This is to avoild type-punning issues + + char line[512]; + size_t size; + char scan; + int rv,numlines,curr_line; + + nc = getnumcols(); + nr = getnumrows(); + ph = nr - HELP_BOTTOM_MARGIN - HELP_BODY_ROW - 1; + cls(); + drawbox(0,0,nr,nc-1,HELPPAGE,0x07,HELPBOX); + + drawhorizline(2,0,nc-1,HELPPAGE,0x07,HELPBOX,0); // dumb==0 + 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; + } + + 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; + } + + title = buf.buffer; + text = findline(title,1); // end of first line + *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) { + printtext(text,curr_line); + gotoxy(HELP_BODY_ROW-1,nc-HELP_RIGHT_MARGIN,HELPPAGE); + if (curr_line > 0) + putch(HELP_MORE_ABOVE,0x07,HELPPAGE); + else putch(' ',0x07,HELPPAGE); + gotoxy(nr-HELP_BOTTOM_MARGIN+1,nc-HELP_RIGHT_MARGIN,HELPPAGE); + if (curr_line < numlines - ph) + putch(HELP_MORE_BELOW,0x07,HELPPAGE); + else putch(' ',0x07,HELPPAGE); + + inputc(&scan); // wait for user keypress + + switch(scan) { + case HOMEKEY: + curr_line = 0; + break; + case ENDKEY: + curr_line = numlines; + break; + case UPARROW: + curr_line--; + break; + case DNARROW: + curr_line++; + break; + case PAGEUP: + curr_line -= ph; + break; + case PAGEDN: + curr_line += ph; + break; + default: + break; + } + if (curr_line > numlines - ph) curr_line = numlines-ph; + if (curr_line < 0) curr_line = 0; + } + cls(); + return; +} + +void runhelp(const char *filename) +{ + char dp; + char fullname[HELPDIRLEN+16]; + + dp = getdisppage(); + if (dp != HELPPAGE) setdisppage(HELPPAGE); + cursoroff(); + if (helpbasedir[0] != 0) { + strcpy(fullname,helpbasedir); + strcat(fullname,"/"); + strcat(fullname,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); + runhelp(filename); +} + +void init_help(const char *helpdir) +{ + if (helpdir != NULL) + strcpy(helpbasedir,helpdir); + else helpbasedir[0] = 0; +} + +void close_help(void) +{ +} diff --git a/com32/cmenu/libmenu/help.h b/com32/cmenu/libmenu/help.h new file mode 100644 index 00000000..06832d84 --- /dev/null +++ b/com32/cmenu/libmenu/help.h @@ -0,0 +1,49 @@ +/* -*- 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 __HELP_H_ +#define __HELP_H_ + +#include "menu.h" +#include "com32io.h" +#include "tui.h" +#include <string.h> + +// How many rows for the title +#define HELP_TITLE_HEIGHT 1 +#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 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 + +// Display one screen of help information +void showhelp(const char *filename); + +// Start the help system using id helpid +void runhelpsystem(unsigned int helpid); + +// Start help system with specified file +void runhelp(const char *filename); + +// Directory where help files are located +void init_help(const char *helpdir); +// Free internal datastructures +void close_help(void); + +#endif diff --git a/com32/cmenu/libmenu/menu.c b/com32/cmenu/libmenu/menu.c new file mode 100644 index 00000000..56a7426c --- /dev/null +++ b/com32/cmenu/libmenu/menu.c @@ -0,0 +1,1300 @@ +/* -*- 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. + * + * ----------------------------------------------------------------------- */ + +#include "menu.h" +#include "com32io.h" +#include <stdlib.h> + +// Local Variables +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 "; +char ITEMLONG[] = " ITEM too long "; +char ACTIONLONG[] = " ACTION too long "; +char STATUSLONG[] = " STATUS too long "; +char EMPTYSTR[] = ""; + +/* Forward declarations */ +int calc_visible(pt_menu menu,int first); +int next_visible(pt_menu menu,int index); +int prev_visible(pt_menu menu,int index); +int next_visible_sep(pt_menu menu,int index); +int prev_visible_sep(pt_menu menu,int index); +int calc_first_early(pt_menu menu,int curr); +int calc_first_late(pt_menu menu,int curr); +int isvisible(pt_menu menu,int first, int curr); + + +/* Basic Menu routines */ + +// 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) +{ + unsigned long i; + TIMEOUTCODE c; + t_timeout_handler th; + + // Wait until keypress if no handler specified + if ((ms->ontimeout==NULL) && (ms->ontotaltimeout==NULL)) return inputc(scan); + + 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++; + } +} + +int find_shortcut(pt_menu menu,uchar shortcut, int index) +// Find the next index with specified shortcut key +{ + int ans; + pt_menuitem mi; + + // Garbage in garbage out + if ((index <0) || (index >= menu->numitems)) 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; + } + // 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; + } + 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) +{ + 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; + + numitems = calc_visible(menu,first); + if (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); + 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; + // 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); + } + 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); + } + // 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); + } + if (ms->handler) ms->handler(ms,menu->items[curr]); +} + +// 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) +{ + 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; + + 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 + 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; + // 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 + } + // 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); + } + 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); + } + // 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); + } + if (ms->handler) 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 +} + +/* 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) + // Return item chosen or NULL if ESC was hit. +{ + int curr,i,first,tmp; + uchar asc,scan; + uchar numitems; + 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); + + // 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 + { + 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); + } + 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) + /* + * cmenu + * Which menu should be currently displayed + * top,left + * What is the position of the top,left corner of the menu + * startopt + * which menu item do I start with + * menutype + * NORMALMENU or RADIOMENU + * + * Return Value: + * Returns a pointer to the final item chosen, or NULL if nothing chosen. + */ +{ + pt_menuitem opt,choice; + uchar startat,mt; + uchar row,col; + + if (cmenu == NULL) return NULL; + startover: + // Set the menu height + cmenu->menuheight = ms->maxrow - top-3; + if (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); + + if (opt == 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 + } + // 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.... + { + 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 + } + // Call recursively for submenu + // Position the submenu below the current item, + // covering half the current window (horizontally) + 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; + if (col == 0xFF) 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; + + choice = runmenusystem(row, col, + 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) // User hit Esc in submenu + { + // Startover + startopt = opt->index; + goto startover; + } + else + { + cleanupmenu(cmenu,top,left,calc_visible(cmenu,0)); + return choice; + } +} + +// Finds the indexof the menu with given name +uchar find_menu_num(const char *name) +{ + int i; + pt_menu m; + + if (name == NULL) return (uchar)(-1); + for (i=0; i < ms->nummenus; i++) + { + m = ms->menus[i]; + if ((m->name) && (strcmp(m->name,name)==0)) return i; + } + return (uchar)(-1); +} + +// Run through all items and if they are submenus +// with a non-trivial "action" and trivial submenunum +// replace submenunum with the menu with name "action" +void fix_submenus() +{ + int i,j; + pt_menu m; + pt_menuitem mi; + + 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); + } + } + } +} + +/* User Callable functions */ + +pt_menuitem showmenus(uchar startmenu) +{ + pt_menuitem rv; + uchar oldpage,tpos; + + 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); + + cursoroff(); // Doesn't seem to work? + + + // Go, main menu cannot be a radio menu + rv = runmenusystem(ms->minrow+MENUROW, ms->mincol+MENUCOL, + ms->menus[(unsigned int)startmenu], 0, NORMALMENU); + + // Hide the garbage we left on the screen + cursoron(); + if (oldpage == ms->menupage) cls(); else setdisppage(oldpage); + + // Return user choice + return rv; +} + +pt_menusystem init_menusystem(const char *title) +{ + int i; + + ms = NULL; + ms = (pt_menusystem) malloc(sizeof(t_menusystem)); + if (ms == NULL) return NULL; + ms->nummenus = 0; + // Initialise all menu pointers + for (i=0; i < MAXMENUS; i++) ms->menus[i] = NULL; + + ms->title = (char *)malloc(TITLELEN+1); + if (title == NULL) + strcpy(ms->title,TITLESTR); // Copy string + else strcpy(ms->title,title); + + // Timeout settings + ms->tm_stepsize = TIMEOUTSTEPSIZE; + ms->tm_numsteps = TIMEOUTNUMSTEPS; + + ms->normalattr[NOHLITE] = NORMALATTR; + ms->normalattr[HLITE] = NORMALHLITE; + + ms->reverseattr[NOHLITE] = REVERSEATTR; + ms->reverseattr[HLITE] = REVERSEHLITE; + + ms->inactattr[NOHLITE] = INACTATTR; + ms->inactattr[HLITE] = INACTHLITE; + + ms->revinactattr[NOHLITE] = REVINACTATTR; + ms->revinactattr[HLITE] = REVINACTHLITE; + + ms->statusattr[NOHLITE] = STATUSATTR; + ms->statusattr[HLITE] = STATUSHLITE; + + ms->statline = STATLINE; + ms->tfillchar= TFILLCHAR; + ms->titleattr= TITLEATTR; + + ms->fillchar = FILLCHAR; + ms->fillattr = FILLATTR; + ms->spacechar= SPACECHAR; + ms->shadowattr = SHADOWATTR; + + 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->tm_total_timeout = 0; + ms->tm_sofar_timeout = 0; + ms->ontotaltimeout = NULL; + + // Setup ACTION_{,IN}VALID + ACTION_VALID.valid=1; + ACTION_VALID.refresh=0; + ACTION_INVALID.valid = 0; + ACTION_INVALID.refresh = 0; + + // Figure out the size of the screen we are in now. + // By default we use the whole screen for our menu + 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; + + // 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) +{ + if (normal != 0xFF) ms->normalattr[0] = normal; + if (selected != 0xFF) ms->reverseattr[0] = selected; + if (inactivenormal != 0xFF) ms->inactattr[0] = inactivenormal; + if (inactiveselected != 0xFF) ms->revinactattr[0] = inactiveselected; +} + +void set_normal_hlite(uchar normal, uchar selected, uchar inactivenormal, uchar inactiveselected) +{ + if (normal != 0xFF) ms->normalattr[1] = normal; + if (selected != 0xFF) ms->reverseattr[1] = selected; + if (inactivenormal != 0xFF) ms->inactattr[1] = inactivenormal; + if (inactiveselected != 0xFF) ms->revinactattr[1] = inactiveselected; +} + +void set_status_info(uchar statusattr, uchar statushlite, uchar statline) +{ + if (statusattr != 0xFF) ms->statusattr[NOHLITE] = statusattr; + if (statushlite!= 0xFF) 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 +} + +void set_title_info(uchar tfillchar, uchar titleattr) +{ + if (tfillchar != 0xFF) ms->tfillchar = tfillchar; + if (titleattr != 0xFF) ms->titleattr = titleattr; +} + +void set_misc_info(uchar fillchar, uchar fillattr,uchar spacechar, uchar shadowattr) +{ + if (fillchar != 0xFF) ms->fillchar = fillchar; + if (fillattr != 0xFF) ms->fillattr = fillattr; + if (spacechar != 0xFF) 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]; +} + +void set_menu_options(uchar maxmenuheight) +{ + if (maxmenuheight != 0xFF) ms->maxmenuheight = maxmenuheight; +} + +// Set the window which menusystem should use +void set_window_size(uchar top, uchar left, uchar bot, uchar right) +{ + + uchar nr,nc; + if ((top > bot) || (left > right)) return; // Sorry no change will happen here + nr = getnumrows(); + nc = getnumcols(); + if (bot >= nr) bot = nr-1; + if (right >= nc) right = nc-1; + ms->minrow = top; + ms->mincol = left; + ms->maxrow = bot; + ms->maxcol = 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 +} + +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; + default: + ms->handler = (t_menusystem_handler) handler; + break; + } +} + +void unreg_handler(t_handler htype) +{ + switch(htype) { + case HDLR_KEYS: + ms->keys_handler = NULL; + break; + default: + ms->handler = NULL; + break; + } +} + +void reg_ontimeout(t_timeout_handler handler, unsigned int numsteps, unsigned int stepsize) +{ + ms->ontimeout = handler; + if (numsteps != 0) ms->tm_numsteps = numsteps; + if (stepsize != 0) ms->tm_stepsize = stepsize; +} + +void unreg_ontimeout() +{ + ms->ontimeout = NULL; +} + +void reg_ontotaltimeout (t_timeout_handler handler, unsigned long numcentiseconds) +{ + if (numcentiseconds != 0) { + ms->ontotaltimeout = handler; + ms->tm_total_timeout = numcentiseconds*10; // to convert to milliseconds + ms->tm_sofar_timeout = 0; + } +} + +void unreg_ontotaltimeout() +{ + ms->ontotaltimeout = NULL; +} + + +int next_visible(pt_menu menu, int index) +{ + int ans; + if (index < 0) ans = 0 ; + else if (index >= menu->numitems) ans = menu->numitems-1; + else ans = index; + while ((ans < menu->numitems-1) && + ((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 ans; + if (index < 0) ans = 0; + else if (index >= menu->numitems) ans = menu->numitems-1; + else ans = index; + while ((ans > 0) && + ((menu->items[ans]->action == OPT_INVISIBLE) || + (menu->items[ans]->action == OPT_SEP))) + ans--; + return ans; +} + +int next_visible_sep(pt_menu menu, int index) +{ + int ans; + if (index < 0) ans = 0 ; + else if (index >= menu->numitems) ans = menu->numitems-1; + else ans = index; + while ((ans < menu->numitems-1) && + (menu->items[ans]->action == OPT_INVISIBLE)) + ans++; + return ans; +} + +int prev_visible_sep(pt_menu menu, int index) // Return index of prev visible +{ + int ans; + if (index < 0) ans = 0; + else if (index >= menu->numitems) ans = menu->numitems-1; + else ans = index; + while ((ans > 0) && + (menu->items[ans]->action == OPT_INVISIBLE)) + ans--; + return ans; +} + +int calc_visible(pt_menu menu,int first) +{ + int ans,i; + + if (menu == NULL) return 0; + ans = 0; + for (i=first; i < menu->numitems; i++) + if (menu->items[i]->action != OPT_INVISIBLE) ans++; + return ans; +} + +// is curr visible if first entry is first? +int isvisible(pt_menu menu,int first, int curr) +{ + if (curr < first) return 0; + return (calc_visible(menu,first)-calc_visible(menu,curr) < menu->menuheight); +} + +// Calculate the first entry to be displayed +// so that curr is visible and make curr as late as possible +int calc_first_late(pt_menu menu,int curr) +{ + int ans,i,nv; + + nv = calc_visible(menu,0); + if (nv <= menu->menuheight) 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); + return ans; +} + +// Calculate the first entry to be displayed +// so that curr is visible and make curr as early as possible +int calc_first_early(pt_menu menu,int curr) +{ + int ans,i,nv; + + nv = calc_visible(menu,0); + if (nv <= menu->menuheight) 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 + ans = curr; + for (i=0; i < menu->menuheight - nv; i++) + ans = prev_visible_sep(menu,ans-1); + return ans; +} + +// Create a new menu and return its position +uchar add_menu(const char *title, int maxmenusize) +{ + int num,i; + pt_menu m; + + num = ms->nummenus; + if (num >= MAXMENUS) return -1; + m = NULL; + m = (pt_menu) malloc(sizeof(t_menu)); + if (m == NULL) return -1; + ms->menus[num] = m; + m->numitems = 0; + m->name = NULL; + m->row = 0xFF; + m->col = 0xFF; + if (maxmenusize < 1) + m->maxmenusize = MAXMENUSIZE; + else 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->title = (char *)malloc(MENULEN+1); + if (title) + { + if (strlen(title) > MENULEN - 2) + strcpy(m->title,TITLELONG); + else strcpy(m->title,title); + } + else 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 +{ + pt_menu m; + + m = ms->menus[ms->nummenus-1]; + if (m->name) // Free up previous name + { + free(m->name); + m -> name = NULL; + } + + if (name) + { + m->name = (char *)malloc(strlen(name)+1); + strcpy(m->name,name); + } +} + +// Create a new named menu and return its position +uchar add_named_menu(const char * name, const char *title, int maxmenusize) +{ + add_menu(title,maxmenusize); + set_menu_name(name); + return ms->nummenus - 1; +} + +void set_menu_pos(uchar row,uchar col) // Set the position of this menu. +{ + pt_menu m; + + m = ms->menus[ms->nummenus-1]; + m->row = row; + m->col = col; +} + +pt_menuitem add_sep() // Add a separator to current menu +{ + pt_menuitem mi; + pt_menu m; + + m = (ms->menus[ms->nummenus-1]); + mi = NULL; + mi = (pt_menuitem) malloc(sizeof(t_menuitem)); + if (mi == NULL) return NULL; + m->items[(unsigned int)m->numitems] = mi; + mi->handler = NULL; // No handler + mi->item = mi->status = mi->data = NULL; + mi->action = OPT_SEP; + mi->index = m->numitems++; + mi->parindex = ms->nummenus-1; + mi->shortcut = 0; + mi->helpid=0; + return mi; +} + +// Add item to the "current" menu +pt_menuitem add_item(const char *item, const char *status, t_action action, + const char *data, uchar itemdata) +{ + pt_menuitem mi; + pt_menu m; + const char *str; + 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; + m->items[(unsigned int) m->numitems] = mi; + mi->handler = NULL; // No handler + + // Allocate space to store stuff + mi->item = (char *)malloc(MENULEN+1); + mi->status = (char *)malloc(STATLEN+1); + 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); + } else strcpy(mi->item,EMPTYSTR); + + if (status) { + if (strlen(status) > STATLEN) { + strcpy(mi->status,STATUSLONG); + } else { + strcpy(mi->status,status); + } + } else 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 + // 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 ((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); + } + } else strcpy(mi->data,EMPTYSTR); + + switch (action) + { + case OPT_SUBMENU: + mi->itemdata.submenunum = itemdata; + break; + case OPT_CHECKBOX: + 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->index = m->numitems++; + mi->parindex = ms->nummenus-1; + return mi; +} + +// Set the shortcut key for the current item +void set_item_options(uchar shortcut,int helpid) +{ + pt_menuitem mi; + pt_menu m; + + m = (ms->menus[ms->nummenus-1]); + if (m->numitems <= 0) return; + mi = m->items[(unsigned int) m->numitems-1]; + + if (shortcut != 0xFF) mi->shortcut = shortcut; + if (helpid != 0xFFFF) mi->helpid = helpid; +} + +// Free internal datasutructures +void close_menusystem(void) +{ +} + +// append_line_helper(pt_menu menu,char *line) +void append_line_helper(int menunum, char *line) +{ + pt_menu menu; + 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); + } + } +} + + +// Generate string based on state of checkboxes and radioitem in given menu +// Assume line points to large enough buffer +void gen_append_line(const char *menu_name,char *line) +{ + int menunum; + + menunum = find_menu_num(menu_name); + if (menunum < 0) return; // No such menu + append_line_helper(menunum,line); +} diff --git a/com32/cmenu/libmenu/menu.h b/com32/cmenu/libmenu/menu.h new file mode 100644 index 00000000..d8db6c25 --- /dev/null +++ b/com32/cmenu/libmenu/menu.h @@ -0,0 +1,291 @@ +/* -*- 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. + * + * ----------------------------------------------------------------------- */ + +/* 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 "com32io.h" +#include "tui.h" +#include "syslnx.h" +#include "scancodes.h" +#include <string.h> + +// TIMEOUT PARAMETERS +/* If no key is pressed within TIMEOUTNUMSTEPS * TIMEOUTSTEPSIZE milliseconds + and if a timeout handler is registered, then that will be called. + The handler should either either take control from there on, or return without + producing any change in the current video settings. + + For e.g. the handler could + * Could just quit the menu program + * beep and return. + + TIMEOUTSTEPSIZE is the interval for which the program sleeps without checking for + any keystroke. So increasing this will make the response of the system slow. + Decreasing this will make a lot of interrupt calls using up your CPU. Default + value of TIMEOUTSTEPSIZE of 0.1 seconds should be right in most cases. + + TIMEOUTNUMSTEPS of 3000 corresponds to a wait time of 300 seconds or 5 minutes +*/ + +#define TIMEOUTSTEPSIZE 10 +#define TIMEOUTNUMSTEPS 30000L + +// Attributes +#define NORMALATTR 0x17 +#define NORMALHLITE 0x1F // Normal Highlight attribute +#define REVERSEATTR 0x70 +#define REVERSEHLITE 0x78 // Reverse Hightlight attribute +#define INACTATTR 0x18 +#define INACTHLITE 0x10 // Inactive Highlight attribute +#define REVINACTATTR 0x78 +#define REVINACTHLITE 0x70 // Reverse Inactive Highlight attr + +#define STATUSATTR 0x74 +#define STATUSHLITE 0x7B // Status highlight + +#define FILLCHAR 177 +#define FILLATTR 0x01 +#define SHADOWATTR 0x00 +#define SPACECHAR ' ' + +#define TFILLCHAR ' ' +#define TITLEATTR 0x70 + +#define ENABLEHLITE '<' // Char which turns on highlight +#define DISABLEHLITE '>' // Char which turns off highlight +#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 + +// Attributes of the menu system +#define MAXMENUS 100 // Maximum number of menu's allowed +#define MAXMENUSIZE 60 // Default value for max num of entries in each menu +#define MAXMENUHEIGHT 20 // Maximum number of entries displayed +#define MENUBOXTYPE BOX_SINSIN // Default box type Look at tui.h for other values + +// Upper bounds on lengths +// We copy the given string, so user can reuse the space used to store incoming arguments. +#define MENULEN 78 // Each menu entry is atmost MENULEN chars +#define STATLEN 78 // Maximum length of status string +#define TITLELEN 78 // Maximum length of title string +#define ACTIONLEN 255 // Maximum length of an action string + +// Layout of menu +#define MENUROW 3 // Row where menu is displayed (relative to window) +#define MENUCOL 4 // Col where menu is displayed (relative to window) +#define MENUPAGE 1 // show in display page 1 +#define STATLINE 24 // Line number where status line starts (relative to window) + +// Used for printing debugging messages +#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 RADIOSEL '.' // Current Radio Selection +#define RADIOUNSEL ' ' // Radio option not selected + +typedef unsigned char uchar; + +// Types of menu's +#define NORMALMENU 1 +#define RADIOMENU 2 + +typedef enum {OPT_INACTIVE, OPT_SUBMENU, OPT_RUN, OPT_EXITMENU, OPT_CHECKBOX, + OPT_RADIOMENU, OPT_SEP, OPT_INVISIBLE, + OPT_RADIOITEM} t_action; + +typedef union { + uchar submenunum; // For submenu's + uchar checked; // For check boxes + uchar radiomenunum; // Item mapping to a radio menu +} t_itemdata; + +struct s_menuitem; +struct s_menu; +struct s_menusystem; + +typedef struct { + unsigned int valid :1; // Is action valid? + unsigned int refresh:1; // Should we recompute menu stuff? + unsigned int reserved:6; // For future expansion +} t_handler_return; + +t_handler_return ACTION_VALID,ACTION_INVALID; // Specific values + +typedef t_handler_return (*t_item_handler)(struct s_menusystem *, struct s_menuitem *); +typedef void (*t_menusystem_handler)(struct s_menusystem *, struct s_menuitem *); +typedef void (*t_keys_handler)(struct s_menusystem *, struct s_menuitem *, + unsigned int scancode); + // Last parameter = HIGH BYTE = scan code , LOW BYTE = ASCII CODE + +typedef enum {HDLR_SCREEN, HDLR_KEYS } t_handler; +// Types of handlers for menu system + +// TIMEOUT is the list of possible values which can be returned by the handler +// instructing the menusystem what to do. The default is CODE_WAIT +typedef enum {CODE_WAIT, CODE_ENTER, CODE_ESCAPE } TIMEOUTCODE; +typedef TIMEOUTCODE (*t_timeout_handler)(void); + +typedef struct s_menuitem { + char *item; + char *status; + char *data; // string containing kernel to run.. but... + // for radio menu's this is a pointer to the item selected or NULL (initially) + // for submenu's this string could be name of menu + void * extra_data; // Any other data user can point to + unsigned int helpid; // Used for Context sensitive help + t_item_handler handler; // Pointer to function of type menufn + t_action action; + t_itemdata itemdata; // Data depends on action value + uchar shortcut; // one of [A-Za-z0-9] shortcut for this menu item + uchar index; // Index within the menu array + uchar parindex; // Index of the menu in which this item appears. + +} t_menuitem; + +typedef t_menuitem *pt_menuitem; // Pointer to type menuitem + +typedef struct s_menu { + pt_menuitem *items; // pointer to array of pointer to menuitems + char *title; // Title string for menu + char *name; // menu can be referred to by this string + int maxmenusize; // the size of array allocated + uchar numitems; // how many items do we actually have + uchar menuwidth; + uchar row,col; // Position where this menu should be displayed + uchar menuheight; // Maximum number of items to be displayed +} t_menu; + +typedef t_menu *pt_menu; // Pointer to type menu + +typedef struct s_menusystem { + pt_menu menus[MAXMENUS]; + char *title; + t_menusystem_handler handler; // Menu system handler + t_keys_handler keys_handler; // Handler for unknown keys + t_timeout_handler ontimeout; // Timeout handler + unsigned long tm_numsteps; + // Time to wait for key press=numsteps * stepsize milliseconds + unsigned int tm_stepsize; // Timeout step size (in milliseconds) + // Total timeout max time spent idle before we call handler + unsigned long tm_total_timeout; // (in milli seconds) + unsigned long tm_sofar_timeout; // All accumulated timeout + // total timeout handler + t_timeout_handler ontotaltimeout; // Total timeout handler + + int maxmenuheight; + uchar nummenus; + uchar normalattr[2]; // [0] is non-hlite attr, [1] is hlite attr + uchar reverseattr[2]; + uchar inactattr[2]; + uchar revinactattr[2]; + uchar statusattr[2]; + uchar fillchar; + uchar fillattr; + uchar spacechar; + uchar tfillchar; + uchar titleattr; + 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 + + // 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; + +typedef t_menusystem *pt_menusystem; // Pointer to type menusystem + +pt_menuitem showmenus(uchar startmenu); + +pt_menusystem init_menusystem(const char *title); + +void close_menusystem(); // Deallocate memory used + +void set_normal_attr(uchar normal, uchar selected, uchar inactivenormal, uchar inactiveselected); + +void set_normal_hlite(uchar normal, uchar selected, uchar inactivenormal, uchar inactiveselected); + +void set_status_info(uchar statusattr, uchar statushlite, uchar statline); + +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 + +void set_menu_options(uchar maxmenuheight); +// maximum height of a menu + +void reg_handler(t_handler htype, void * handler); // Register handler + +void unreg_handler( t_handler htype); + +void reg_ontimeout(t_timeout_handler, unsigned int numsteps, unsigned int stepsize); +// Set timeout handler, set 0 for default values. +// So stepsize=0 means numsteps is measured in centiseconds. +void unreg_ontimeout(); + +void reg_ontotaltimeout(t_timeout_handler, unsigned long numcentiseconds); +void unreg_ontotaltimeout(); + +// Find the number of the menu given the name +// Returns -1 if not found +uchar find_menu_num(const char *name); + +// Create a new menu and return its position +uchar add_menu(const char *title, int maxmenusize); + +// Create a named menu and return its position +uchar add_named_menu(const char *name, const char *title, int maxmenusize); + +void set_menu_pos(uchar row,uchar col); // Set the position of this 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); + +// Set shortcut key and help id +void set_item_options(uchar shortcut,int helpid); + +// Set the shortcut key for the current item +static inline void set_shortcut(uchar shortcut) +{ + set_item_options(shortcut,0xFFFF); +} + +// Add a separator to the "current" menu +pt_menuitem add_sep(); + +// Generate string based on state of checkboxes and radioitem in given menu +// and append string to existing contents of "line" +// line must have enough space allocated +void gen_append_line(const char *menu_name,char *line); + +#endif diff --git a/com32/cmenu/libmenu/passwords.c b/com32/cmenu/libmenu/passwords.c new file mode 100644 index 00000000..40b5c49f --- /dev/null +++ b/com32/cmenu/libmenu/passwords.c @@ -0,0 +1,140 @@ +/* -*- 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, + * Bostom MA 02111-1307, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +#include "passwords.h" +#include "des.h" +#include "string.h" +#include <stdlib.h> +#include <stdio.h> +#include "tui.h" + +#define MAX_LINE 512 +// Max line length in a pwdfile +p_pwdentry userdb[MAX_USERS]; // Array of pointers +int numusers; // Actual number of users + +// returns true or false, i.e. 1 or 0 +char authenticate_user(const char * username, const char* pwd) +{ + char salt[12]; + int i; + + for (i=0; i< numusers; i++) { + if (userdb[i] == NULL) continue; + if (strcmp(username,userdb[i]->username)==0) { + strcpy(salt, userdb[i]->pwdhash); + salt[2] = '\0'; + if (strcmp(userdb[i]->pwdhash,crypt(pwd,salt))==0) return 1; + } + } + return 0; +} + +// Does user USERNAME have permission PERM +char isallowed(const char *username, const char *perm) +{ + int i; + char *dperm; + char *tmp; + + // If no users, then everybody is allowed to do everything + if (numusers == 0) return 1; + if (strcmp(username,GUEST_USER) == 0) return 0; + dperm = (char *) malloc(strlen(perm)+3); + strcpy(dperm+1,perm); + dperm[0] = ':'; + dperm[strlen(perm)+1]=':'; + dperm[strlen(perm)+2]=0; + // Now dperm = ":perm:" + for (i=0; i < numusers; i++) { + if (strcmp(userdb[i]->username,username)==0) // Found the user + { + if (userdb[i]->perms == NULL) return 0; // No permission + tmp = strstr(userdb[i]->perms,dperm); // Search for permission + free (dperm); // Release memory + if (tmp == NULL) return 0; else return 1; + } + } + // User not found return 0 + free (dperm); + return 0; +} + +// Initialise the list of of user passwords permissions from file +void init_passwords(const char *filename) +{ + int i; + char line[MAX_LINE], *p,*user,*pwdhash,*perms; + FILE *f; + + for (i=0; i < MAX_USERS; i++) userdb[i] = NULL; + numusers = 0; + + if ( !filename ) return; // No filename specified + + f = fopen(filename,"r"); + if ( !f ) return; // File does not exist + + // Process each line + while ( fgets(line, sizeof line, f) ) { + // Replace EOLN with \0 + p = strchr(line, '\r'); + if ( p ) *p = '\0'; + p = strchr(line, '\n'); + if ( p ) *p = '\0'; + + // If comment line or empty ignore line + p = line; + while (*p==' ') p++; // skip initial spaces + if ( (*p == '#') || (*p == '\0')) continue; // Skip comment lines + + user = p; // This is where username starts + p = strchr(user,':'); + if (p == NULL) continue; // Malformed line skip + *p = '\0'; + pwdhash = p+1; + if (*pwdhash == 0) continue; // Malformed line (no password specified) + p = strchr(pwdhash,':'); + if (p == NULL) { // No perms specified + perms = NULL; + } else { + *p = '\0'; + perms = p+1; + if (*perms == 0) perms = NULL; + } + // At this point we have user,pwdhash and perms setup + userdb[numusers] = (p_pwdentry)malloc(sizeof(pwdentry)); + strcpy(userdb[numusers]->username,user); + strcpy(userdb[numusers]->pwdhash,pwdhash); + if (perms == NULL) + userdb[numusers]->perms = NULL; + else { + userdb[numusers]->perms = (char *)malloc(strlen(perms)+3); + (userdb[numusers]->perms)[0] = ':'; + strcpy(userdb[numusers]->perms + 1,perms); + (userdb[numusers]->perms)[strlen(perms)+1] = ':'; + (userdb[numusers]->perms)[strlen(perms)+2] = 0; + // Now perms field points to ":perms:" + } + numusers++; + } + fclose(f); +} + +void close_passwords() +{ + int i; + + for (i=0; i < numusers; i++) + if (userdb[i] != NULL) free(userdb[i]); + numusers = 0; +} diff --git a/com32/cmenu/libmenu/passwords.h b/com32/cmenu/libmenu/passwords.h new file mode 100644 index 00000000..00e5702d --- /dev/null +++ b/com32/cmenu/libmenu/passwords.h @@ -0,0 +1,27 @@ +#ifndef _PASSWORDS_H_ +#define _PASSWORDS_H_ + +char authenticate_user(const char * username, const char* pwd); + +char isallowed(const char *username, const char * perm); + +// Initialise the list of of user passwords permissions from file +void init_passwords(const char *filename); +// Free all space used for internal data structures +void close_passwords(); + +#define MAX_USERS 128 // Maximum number of users +#define USERNAME_LENGTH 12 // Max length of user name +#define PWDHASH_LENGTH 40 // Max lenght of pwd hash + +typedef struct { + char username[USERNAME_LENGTH+1]; + char pwdhash[PWDHASH_LENGTH+1]; + char *perms; // pointer to string containing ":" delimited permissions +} pwdentry; + +typedef pwdentry *p_pwdentry; + +#define GUEST_USER "guest" + +#endif diff --git a/com32/cmenu/libmenu/scancodes.h b/com32/cmenu/libmenu/scancodes.h new file mode 100644 index 00000000..d3f625a6 --- /dev/null +++ b/com32/cmenu/libmenu/scancodes.h @@ -0,0 +1,86 @@ +/* -*- 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/syslnx.c b/com32/cmenu/libmenu/syslnx.c new file mode 100644 index 00000000..d2b0aef4 --- /dev/null +++ b/com32/cmenu/libmenu/syslnx.c @@ -0,0 +1,88 @@ +/* -*- 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. + * + * ----------------------------------------------------------------------- */ + +#include <string.h> +#include <com32.h> +#include "syslnx.h" + +com32sys_t inreg,outreg; // Global registers for this module + +char issyslinux(void) +{ + REG_EAX(inreg) = 0x00003000; + REG_EBX(inreg) = REG_ECX(inreg) = REG_EDX(inreg) = 0xFFFFFFFF; + __intcall(0x21,&inreg,&outreg); + return (REG_EAX(outreg) == 0x59530000) && + (REG_EBX(outreg) == 0x4c530000) && + (REG_ECX(outreg) == 0x4e490000) && + (REG_EDX(outreg) == 0x58550000); +} + +void runsyslinuxcmd(const char *cmd) +{ + strcpy(__com32.cs_bounce, cmd); + REG_AX(inreg) = 0x0003; // Run command + REG_BX(inreg) = OFFS(__com32.cs_bounce); + REG_ES(inreg) = SEG(__com32.cs_bounce); + __intcall(0x22, &inreg, &outreg); +} + +void gototxtmode(void) +{ + REG_AX(inreg) = 0x0005; + __intcall(0x22,&inreg,&outreg); +} + +void syslinux_idle(void) +{ + REG_AX(inreg) = 0x0013; + __intcall(0x22,&inreg,&outreg); +} + +unsigned int getversion(char *deriv,unsigned int *numfun) +{ + REG_AX(inreg) = 0x0001; + __intcall(0x22,&inreg,&outreg); + if (deriv) *deriv= REG_DL(outreg); + if (numfun) *numfun = REG_AX(outreg); + return REG_CX(outreg); +} + +void runsyslinuximage(const char*cmd, long ipappend) +{ + unsigned int numfun = 0; + char *ptr,*cmdline; + + getversion(NULL,&numfun); + // Function 16h not supported Fall back to runcommand + if (numfun < 0x16) runsyslinuxcmd(cmd); + // Try the Run Kernel Image function + // Split command line into + strcpy(__com32.cs_bounce,cmd); + ptr = __com32.cs_bounce; + // serach for first space or end of string + while ( (*ptr) && (*ptr != ' ')) ptr++; + if (!*ptr) cmdline = ptr; // no command line + else { + *ptr++='\0'; // terminate kernal name + cmdline = ptr+1; + while (*cmdline != ' ') cmdline++; // find first non-space + } + // Now call the interrupt + REG_BX(inreg) = OFFS(cmdline); + REG_ES(inreg) = SEG(cmdline); + REG_SI(inreg) = OFFS(__com32.cs_bounce); + REG_DS(inreg) = SEG(__com32.cs_bounce); + REG_EDX(inreg) = 0; + + __intcall(0x22,&inreg,&outreg); // If successful does not return +} diff --git a/com32/cmenu/libmenu/syslnx.h b/com32/cmenu/libmenu/syslnx.h new file mode 100644 index 00000000..755b9690 --- /dev/null +++ b/com32/cmenu/libmenu/syslnx.h @@ -0,0 +1,64 @@ +/* -*- 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 __SYSLNX_H__ +#define __SYSLNX_H__ + +#include <com32.h> + +//Macros which help user not have to remember the structure of register +// Data structure + +#define REG_AH(x) ((x).eax.b[1]) +#define REG_AL(x) ((x).eax.b[0]) +#define REG_AX(x) ((x).eax.w[0]) +#define REG_EAX(x) ((x).eax.l) + +#define REG_BH(x) ((x).ebx.b[1]) +#define REG_BL(x) ((x).ebx.b[0]) +#define REG_BX(x) ((x).ebx.w[0]) +#define REG_EBX(x) ((x).ebx.l) + +#define REG_CH(x) ((x).ecx.b[1]) +#define REG_CL(x) ((x).ecx.b[0]) +#define REG_CX(x) ((x).ecx.w[0]) +#define REG_ECX(x) ((x).ecx.l) + +#define REG_DH(x) ((x).edx.b[1]) +#define REG_DL(x) ((x).edx.b[0]) +#define REG_DX(x) ((x).edx.w[0]) +#define REG_EDX(x) ((x).edx.l) + +#define REG_DS(x) ((x).ds) +#define REG_ES(x) ((x).es) +#define REG_FS(x) ((x).fs) +#define REG_GS(x) ((x).gs) + +#define REG_SI(x) ((x).esi.w[0]) +#define REG_ESI(x) ((x).esi.l) + +#define REG_DI(x) ((x).edi.w[0]) +#define REG_EDI(x) ((x).edi.l) + +char issyslinux(void); /* Check if syslinux is running */ + +void runsyslinuxcmd(const char *cmd); /* Run specified command */ + +void gototxtmode(void); /* Change mode to text mode */ + +void syslinux_idle(void); /* Call syslinux idle loop */ + +/* Run command line with ipappend, returns if kernel image not found + If syslinux version too old, then defaults to runsyslinuxcmd */ +void runsyslinuximage(const char*cmd, long ipappend); + +#endif diff --git a/com32/cmenu/libmenu/tui.c b/com32/cmenu/libmenu/tui.c new file mode 100644 index 00000000..cb8c1936 --- /dev/null +++ b/com32/cmenu/libmenu/tui.c @@ -0,0 +1,357 @@ +/* -*- c -*- ------------------------------------------------------------- * + * + * Copyright 2004-2006 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. + * + * ----------------------------------------------------------------------- */ + +#include "tui.h" +#include <string.h> +#include <com32.h> +#include <stdlib.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 +// showoldvalue <> 0 implies currentvalue displayed first +// If showoldvalue <> 0 then caller responsibility to ensure that +// str is NULL terminated. +void getuserinput(char *stra, unsigned int size, unsigned int password, + unsigned int showoldvalue) +{ + unsigned char c,scan; + 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 + getcursorshape(&start,&end); + insmode = 1; + + str = (char *)malloc(size+1); // Allocate memory to store user input + memset(str,0,size+1); // Zero it out + if (password != 0) showoldvalue = 0; // Password's never displayed + + if (showoldvalue != 0) strcpy(str,stra); // If show old value copy current value + + last = str; + while (*last) {last++;} // Find the terminating null byte + p = str+ strlen(str); + + if (insmode == 0) + setcursorshape(1,7); // Block cursor + else setcursorshape(6,7); // Normal cursor + + // Invariants: p is the current char + // col is the corresponding column on the screen + if (password == 0) // Not a password, print initial value + { + gotoxy(row,col,page); + csprint(str,GETSTRATTR); + } + while (1) { // Do forever + c = inputc(&scan); + if (c == '\r') break; // User hit Enter getout of loop + if (scan == ESCAPE) // User hit escape getout and nullify string + { *str = 0; + break; + } + fudge = 0; + // if scan code is regognized do something + // else if char code is recognized do something + // else ignore + switch(scan) { + case HOMEKEY: + p = str; + break; + case ENDKEY: + p = last; + break; + case LTARROW: + if (p > str) p--; + break; + case CTRLLT: + if (p==str) break; + if (*p == ' ') + while ((p > str) && (*p == ' ')) p--; + else { + if (*(p-1) == ' ') { + p--; + while ((p > str) && (*p == ' ')) p--; + } + } + while ((p > str) && ((*p == ' ') || (*(p-1) != ' '))) p--; + break; + case RTARROW: + if (p < last) p++; + break; + case CTRLRT: + if (*p==0) break; // At end of string + if (*p != ' ') + while ((*p!=0) && (*p != ' ')) p++; + while ((*p!=0) && ((*p == ' ') && (*(p+1) != ' '))) p++; + if (*p==' ') p++; + break; + case DELETE: + q = p; + while (*(q+1)) {*q = *(q+1); q++; } + if (last > str) last--; + fudge = 1; + break; + case 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 + q=p; + while ( q <= last ) { *(q-1)=*q; q++;} + if (last > str) last--; + if (p > str) p--; + fudge = 1; + break; + case '\x15': /* Ctrl-U: kill input */ + fudge = last-str; + while ( p > str ) *p--=0; + p = str; *p=0; last = str; + break; + default: // Handle insert and overwrite mode + if ((c >= ' ') && (c < 128) && + ((unsigned int)(p-str) < size-1) ) { + if (insmode == 0) { // Overwrite mode + if (p==last) last++; + *last = 0; + *p++ = c; + } else { // Insert mode + if (p==last) { // last char + last++; + *last=0; + *p++=c; + } else { // Non-last char + q=last++; + while (q >= p) { *q=*(q-1); q--;} + *p++=c; + } + } + } + else beep(); + } + break; + } + // Now the string has been modified, print it + if (password == 0) { + gotoxy(row,col,page); + csprint(str,GETSTRATTR); + if (fudge > 0) cprint(' ',GETSTRATTR,fudge,page); + gotoxy(row,col+(p-str),page); + } + } + *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) 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) +{ + unsigned char *box_chars; // pointer to array of box chars + unsigned char x; + + box_chars = getboxchars(bt); + // 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); + // 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); + // 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); + } +} + +void drawhorizline(char top, char left, char right, char page, char attr, + boxtype bt, char dumb) +{ + unsigned char start,end; + unsigned char *box_chars = getboxchars(bt); + if (dumb==0) { + start = left+1; + end = right-1; + } else { + start = left; + end = right; + } + gotoxy(top,start,page); + cprint(box_chars[BOX_HORIZ],attr,end-start+1,page); + 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); + } +} diff --git a/com32/cmenu/libmenu/tui.h b/com32/cmenu/libmenu/tui.h new file mode 100644 index 00000000..92f93863 --- /dev/null +++ b/com32/cmenu/libmenu/tui.h @@ -0,0 +1,88 @@ +/* -*- 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 __TUI_H__ +#define __TUI_H__ + +#include <com32.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); + +void cls(void); /* Clears the entire current screen page */ + +// Generic user input, +// password = 0 iff chars echoed on screen +// showoldvalue <> 0 iff current displayed for editing +void getuserinput(char *str, unsigned int size, + unsigned int password, unsigned int showoldvalue); + +static inline void getstring(char *str, unsigned int size) +{ + getuserinput(str,size,0,0); +} + +static inline void editstring(char *str, unsigned int size) +{ + getuserinput(str,size,0,1); +} + +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); + +// 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); + +#endif diff --git a/com32/cmenu/menugen.py b/com32/cmenu/menugen.py new file mode 100644 index 00000000..70ec1f87 --- /dev/null +++ b/com32/cmenu/menugen.py @@ -0,0 +1,307 @@ +#!/usr/bin/env python + +import sys, re, getopt + +class Menusystem: + + types = {"run" : "OPT_RUN", + "inactive" : "OPT_INACTIVE", + "checkbox" : "OPT_CHECKBOX", + "radiomenu": "OPT_RADIOMENU", + "sep" : "OPT_SEP", + "invisible": "OPT_INVISIBLE", + "radioitem": "OPT_RADIOITEM", + "exitmenu" : "OPT_EXITMENU", + "login" : "login", # special type + "submenu" : "OPT_SUBMENU"} + + entry_init = { "item" : "", + "info" : "", + "data" : "", + "ipappend" : 0, # flag to send in case of PXELINUX + "helpid" : 65535, # 0xFFFF + "shortcut":"-1", + "state" : 0, # initial state of checkboxes + "argsmenu": "", # name of menu containing arguments + "perms" : "", # permission required to execute this entry + "_updated" : None, # has this dictionary been updated + "type" : "run" } + + menu_init = { "title" : "", + "row" : "0xFF", # let system decide position + "col" : "0xFF", + "_updated" : None, + "name" : "" } + + system_init ={ "videomode" : "0xFF", + "title" : "Menu System", + "top" : "1", + "left" : "1" , + "bot" : "21", + "right":"79", + "helpdir" : "/isolinux/help", + "pwdfile" : "", + "pwdrow" : "23", + "editrow" : "23", + "skipcondn" : "0", + "skipcmd" : ".exit", + "startfile": "", + "onerrorcmd":".repeat", + "exitcmd" : ".exit", + "exitcmdroot" : "", + "timeout" : "600", + "timeoutcmd":".beep", + "totaltimeout" : "0", + "totaltimeoutcmd" : ".wait" + } + + shift_flags = { "alt" : "ALT_PRESSED", + "ctrl" : "CTRL_PRESSED", + "shift": "SHIFT_PRESSED", + "caps" : "CAPSLOCK_ON", + "num" : "NUMLOCK_ON", + "ins" : "INSERT_ON" + } + + reqd_templates = ["item","login","menu","system"] + + def __init__(self,template): + self.state = "system" + self.code_template_filename = template + self.menus = [] + self.init_entry() + self.init_menu() + self.init_system() + self.vtypes = " OR ".join(self.types.keys()) + self.vattrs = " OR ".join(filter(lambda x: x[0] != "_", self.entry.keys())) + self.mattrs = " OR ".join(filter(lambda x: x[0] != "_", self.menu.keys())) + + def init_entry(self): + self.entry = self.entry_init.copy() + + def init_menu(self): + self.menu = self.menu_init.copy() + + def init_system(self): + self.system = self.system_init.copy() + + def add_menu(self,name): + self.add_item() + self.init_menu() + self.menu["name"] = name + self.menu["_updated"] = 1 + self.menus.append( (self.menu,[]) ) + + def add_item(self): + if self.menu["_updated"]: # menu details have changed + self.menus[-1][0].update(self.menu) + self.init_menu() + if self.entry["_updated"]: + if not self.entry["info"]: + self.entry["info"] = self.entry["data"] + if not self.menus: + print "Error before line %d" % self.lineno + print "REASON: menu must be declared before a menu item is declared" + sys.exit(1) + self.menus[-1][1].append(self.entry) + self.init_entry() + + def set_item(self,name,value): + if not self.entry.has_key(name): + msg = ["Unknown attribute %s in line %d" % (name,self.lineno)] + msg.append("REASON: Attribute must be one of %s" % self.vattrs) + return "\n".join(msg) + if name=="type" and not self.types.has_key(value): + msg = [ "Unrecognized type %s in line %d" % (value,self.lineno)] + msg.append("REASON: Valid types are %s" % self.vtypes) + return "\n".join(msg) + if name=="shortcut": + if (value <> "-1") and not re.match("^[A-Za-z0-9]$",value): + msg = [ "Invalid shortcut char '%s' in line %d" % (value,self.lineno) ] + msg.append("REASON: Valid values are [A-Za-z0-9]") + return "\n".join(msg) + elif value <> "-1": value = "'%s'" % value + elif name in ["state","helpid","ipappend"]: + try: + value = int(value) + except: + return "Value of %s in line %d must be an integer" % (name,self.lineno) + self.entry[name] = value + self.entry["_updated"] = 1 + return "" + + def set_menu(self,name,value): + if not self.menu.has_key(name): + return "Error: Unknown keyword %s" % name + self.menu[name] = value + self.menu["_updated"] = 1 + return "" + + def set_system(self,name,value): + if not self.system.has_key(name): + return "Error: Unknown keyword %s" % name + if name == "skipcondn": + try: # is skipcondn a number? + a = int(value) + except: # it is a "-" delimited sequence + value = value.lower() + parts = [ self.shift_flags.get(x.strip(),None) for x in value.split("-") ] + self.system["skipcondn"] = " | ".join(filter(None, parts)) + else: + self.system[name] = value + + def set(self,name,value): + # remove quotes if given + if (value[0] == value[-1]) and (value[0] in ['"',"'"]): # remove quotes + value = value[1:-1] + if self.state == "system": + err = self.set_system(name,value) + if not err: return + if self.state == "menu": + err = self.set_menu(name,value) + # change state to entry it menu returns error + if err: + err = None + self.state = "item" + if self.state == "item": + err = self.set_item(name,value) + + if not err: return + + # all errors so return item's error message + print err + sys.exit(1) + + def print_entry(self,entry,fd): + entry["type"] = self.types[entry["type"]] + if entry["type"] == "login": #special type + fd.write(self.templates["login"] % entry) + else: + fd.write(self.templates["item"] % entry) + + def print_menu(self,menu,fd): + if menu["name"] == "main": self.foundmain = 1 + fd.write(self.templates["menu"] % menu) + if (menu["row"] != "0xFF") or (menu["col"] != "0xFF"): + fd.write(' set_menu_pos(%(row)s,%(col)s);\n' % menu) + + + def output(self,filename): + curr_template = None + contents = [] + self.templates = {} + regbeg = re.compile(r"^--(?P<name>[a-z]+) BEGINS?--\n$") + regend = re.compile(r"^--[a-z]+ ENDS?--\n$") + ifd = open(self.code_template_filename,"r") + for line in ifd.readlines(): + b = regbeg.match(line) + e = regend.match(line) + if e: # end of template + if curr_template: + self.templates[curr_template] = "".join(contents) + curr_template = None + continue + if b: + curr_template = b.group("name") + contents = [] + continue + if not curr_template: continue # lines between templates are ignored + contents.append(line) + ifd.close() + + missing = None + for x in self.reqd_templates: + if not self.templates.has_key(x): missing = x + if missing: + print "Template %s required but not defined in %s" % (missing,self.code_template_filename) + + if filename == "-": + fd = sys.stdout + else: fd = open(filename,"w") + self.foundmain = None + fd.write(self.templates["header"]) + fd.write(self.templates["system"] % self.system) + for (menu,items) in self.menus: + self.print_menu(menu,fd) + for entry in items: self.print_entry(entry,fd) + fd.write(self.templates["footer"]) + fd.close() + if not self.foundmain: + print "main menu not found" + print self.menus + sys.exit(1) + + def input(self,filename): + if filename == "-": + fd = sys.stdin + else: fd = open(filename,"r") + self.lineno = 0 + self.state = "system" + for line in fd.readlines(): + self.lineno = self.lineno + 1 + if line and line[-1] in ["\r","\n"]: line = line[:-1] + if line and line[-1] in ["\r","\n"]: line = line[:-1] + line = line.strip() + if line and line[0] in ["#",";"]: continue + + try: + # blank line -> starting a new entry + if not line: + if self.state == "item": self.add_item() + continue + + # starting a new section? + if line[0] == "[" and line[-1] == "]": + self.state = "menu" + self.add_menu(line[1:-1]) + continue + + # add property of current entry + pos = line.find("=") # find the first = in string + if pos < 0: + print "Syntax error in line %d" % self.lineno + print "REASON: non-section lines must be of the form ATTRIBUTE=VALUE" + sys.exit(1) + attr = line[:pos].strip().lower() + value = line[pos+1:].strip() + self.set(attr,value) + except: + print "Error while parsing line %d: %s" % (self.lineno,line) + raise + fd.close() + self.add_item() + +def usage(): + print sys.argv[0]," [options]" + print "--input=<file> is the name of the .menu file declaring the menu structure" + print "--output=<file> is the name of generated C source" + print "--template=<file> is the name of template to be used" + print + print "input and output default to - (stdin and stdout respectively)" + print "template defaults to adv_menu.tpl" + sys.exit(1) + +def main(): + tfile = "adv_menu.tpl" + ifile = "-" + ofile = "-" + opts,args = getopt.getopt(sys.argv[1:], "hi:o:t:",["input=","output=","template=","help"]) + if args: + print "Unknown options %s" % args + usage() + for o,a in opts: + if o in ["-i","--input"]: + ifile = a + elif o in ["-o", "--output"]: + ofile = a + elif o in ["-t","--template"]: + tfile = a + elif o in ["-h","--help"]: + usage() + + inst = Menusystem(tfile) + inst.input(ifile) + inst.output(ofile) + +if __name__ == "__main__": + main() diff --git a/com32/cmenu/password b/com32/cmenu/password new file mode 100644 index 00000000..3caffe22 --- /dev/null +++ b/com32/cmenu/password @@ -0,0 +1,18 @@ +# This file should be available as /isolinux/password +# for complex.c to use. +# +# All lines starting with # and empty lines are ignored +# +# All non-comment lines here are of the form +# USERNAME:PWDHASH:PERM1:PERM2:...: +# +# where USERNAME is maximum of 12 chars, +# PWDHASH is maximum of 40 chars (DES ENCRYPTED) +# PERM1,... are arbitrary strings +# +# The current lines correspond to +# user1:secret1, user2:secret2, user3:secret3 + +user1:LcMRo3YZGtP0c:editcmd +user2:FqewzyxP78a7A: +user3:MKjmc.IHoXBNU:root diff --git a/com32/cmenu/simple.c b/com32/cmenu/simple.c new file mode 100644 index 00000000..92e8ab12 --- /dev/null +++ b/com32/cmenu/simple.c @@ -0,0 +1,79 @@ +/* -*- 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 NULL +#define NULL ((void *) 0) +#endif + +#include "menu.h" +#include "com32io.h" +#include <string.h> + +int main(void) +{ + t_menuitem * curr; + + // Change the video mode here + // setvideomode(0) + + // Choose the default title and setup default values for all attributes.... + init_menusystem(NULL); + set_window_size(1,1,23,78); // Leave one row/col border all around + + // 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_named_menu("name"," Menu Title ",-1); + // add_item("Item string","Status String",TYPE,"any string",NUM) + // TYPE = OPT_RUN | OPT_EXITMENU | OPT_SUBMENU | OPT_CHECKBOX | OPT_INACTIVE + // "any string" useful for storing kernel names + // In case of OPT_SUBMENU, "any string" can be set to "name" of menu to be linked + // in which case value NUM is ignored + // NUM = index of submenu if OPT_SUBMENU, + // 0/1 default checked state if OPT_CHECKBOX + // unused otherwise. + + add_named_menu("testing"," Testing ",-1); + add_item("Self Loop","Go to testing",OPT_SUBMENU,"testing",0); + 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); + + add_named_menu("rescue"," Rescue Options ",-1); + 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); + + add_named_menu("main"," Main Menu ",-1); + add_item("Prepare","prep",OPT_RUN,"prep",0); + add_item("Rescue options...","Troubleshoot a system",OPT_SUBMENU,"rescue",0); + add_item("Testing...","Options to test hardware",OPT_SUBMENU,"testing",0); + add_item("Exit to prompt", "Exit the menu system", OPT_EXITMENU, "exit", 0); + + curr = showmenus(find_menu_num("main")); // Initial menu is the one called "main" + + if (curr) + { + if (curr->action == OPT_RUN) + { + if (issyslinux()) runsyslinuxcmd(curr->data); + else csprint(curr->data,0x07); + return 1; + } + csprint("Error in programming!",0x07); + } + return 0; +} diff --git a/com32/cmenu/test.menu b/com32/cmenu/test.menu new file mode 100644 index 00000000..061c548e --- /dev/null +++ b/com32/cmenu/test.menu @@ -0,0 +1,60 @@ +# choose default title +title = "A test of the test.menu file" +top = 1 +left = 1 +bot = 23 +right = 78 + +[testing] +title = " Testing " + +item="Self Loop" +info="Go to Testing" +type=submenu +data=testing + +item="Memory Test" +info="Perform extensive memory testing" +data="memtest" + +item="Exit this menu" +info="Go one level up" +type=exitmenu + +[rescue] +title = " Rescue Options " +row = 10 +col = 10 + +item="Linux Rescue" +data="linresc" + +item="Dos Rescue" +data="dosresc" + +item="Windows Rescue" +data="winresc" + +item="Exit this menu" +info="Go one level up" +type=exitmenu + +[main] +title = " Main Menu " + +item="Prepare" +data="prep" + +item="Rescue options..." +info="Troubleshoot a system" +type=submenu +data="rescue" + +item="Testing..." +info="Options to test hardware" +type=submenu +data="testing" + +item="Exit this menu" +info="Go one level up" +type=exitmenu diff --git a/com32/cmenu/test2.menu b/com32/cmenu/test2.menu new file mode 100644 index 00000000..4570dc2c --- /dev/null +++ b/com32/cmenu/test2.menu @@ -0,0 +1,142 @@ + +title=" COMBOOT Menu System " + +# location of help directory +helpdir="/isolinux/help" +pwdfile="/isolinux/password" + +# skip the menu if shift is pressed or Caps is on +# if the menu is skipped run "skipcmd" +# in our case we run the OS on the first harddisk +skipcondn=shift-caps +skipcmd="chain.c32 hd 0" + +# person with root privileges can exit menu +# others just repeat +exitcmd=".exit" +onerrorcmd=".beep 2 % % .help hlp00025.txt % .exit" + +startfile="hlp00026.txt" + +timeoutcmd=".wait" +totaltimeoutcmd="chain.c32 hd 0" + +[netmenu] +title=" Init Network " + +item="<N>one" +info="Dont start network" +type=radioitem +data="network=no" + +item="<d>hcp" +info="Use DHCP" +type=radioitem +data="network=dhcp" + +[testing] +title=" Testing " + +item="<M>emory Test" +info="Perform extensive memory testing" +data="memtest" +helpid=25 +ipappend=3 + +item="<I>nvisible" +info="You dont see this" +type=invisible + +item="<E>xit menu" +info="Go one level up" +type=exitmenu + +[rescue] +title=" Rescue Options " + +item="<L>inux Rescue" +info="Run linresc" +data="linresc" + +item="<D>os Rescue" +info="dosresc" +data="dosresc" + +item="<W>indows Rescue" +info="winresc" +data="winresc" + +item="<E>xit this menu" +info="Go one level up" +type=exitmenu + +[prep] +title=" Prep options " + +item="<b>aseurl by IP?" +info="Specify gui baseurl by IP address" +type=checkbox +data="baseurl=http://192.168.0.1" + +item="<m>ountcd?" +info="Mount the cdrom drive?" +type=checkbox +data="mountcd" + +item="Network Initialization" +info="How to initialise network device?" +type=radiomenu +data="netmenu" + +type=sep + +item="Reinstall <w>indows" +info="Re-install the windows side of a dual boot setup" +type=checkbox +data="repair=win" + +item="Reinstall <l>inux" +info="Re-install the linux side of a dual boot setup" +type=checkbox +data="repair=lin" + +type=sep + +item="<R>un prep now" +info="Execute prep with the above options" +data="prep" +argsmenu="prep" + +item="<E>xit this menu" +info="Go up one level" +type=exitmenu + +[main] + +title=" Main Menu " + +type=login + +item="<P>repare" +info="prep" +data="prep" + +item="<P>rep options..." +info="Options for prep" +type=submenu +data="prep" + +item="<R>escue options..." +info="Troubleshoot a system" +type=submenu +data="rescue" +helpid=26 + +item="<T>esting..." +info="Options to test hardware" +type=submenu +data="testing" + +item="<E>xit to prompt" +info="Exit the menu system" +type=exitmenu diff --git a/com32/gplinclude/README b/com32/gplinclude/README new file mode 100644 index 00000000..ac1bf6a8 --- /dev/null +++ b/com32/gplinclude/README @@ -0,0 +1 @@ +Put header files for LGPL or GPL library functions in this directory. diff --git a/com32/include/cpuid.h b/com32/gplinclude/cpuid.h index 050cfedb..2473b41e 100644 --- a/com32/include/cpuid.h +++ b/com32/gplinclude/cpuid.h @@ -1,27 +1,15 @@ /* ----------------------------------------------------------------------- * + * + * Copyright 2006-2009 Erwan Velu - All Rights Reserved * - * Copyright 2006 Erwan Velu - All Rights Reserved + * Portions of this file taken from the Linux kernel, + * Copyright 1991-2009 Linus Torvalds and contributors * - * 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. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston MA 02110-1301; + * incorporated herein by reference. * * ----------------------------------------------------------------------- */ @@ -168,6 +156,8 @@ struct cpuinfo_x86 { unsigned char x86_max_cores; /* cpuid returned max cores value */ unsigned char booted_cores; /* number of cores as seen by OS */ unsigned char apicid; + unsigned char x86_clflush_size; + } __attribute__((__packed__)); #endif diff --git a/com32/include/dmi/dmi.h b/com32/gplinclude/dmi/dmi.h index ceed3b4d..924ed420 100644 --- a/com32/include/dmi/dmi.h +++ b/com32/gplinclude/dmi/dmi.h @@ -12,49 +12,53 @@ #ifndef DMI_H #define DMI_H +#include <inttypes.h> +#define MAX_DMI_MEMORY_ITEMS 32 -#define u32 unsigned int -#define u16 unsigned short -#define u8 unsigned char #define PAGE_SIZE 4096 -typedef struct { - u32 l; - u32 h; -} u64; +/*typedef struct { + uint32_t l; + uint32_t h; +} uint64_t;*/ + +extern const char *out_of_spec; +extern const char *bad_index; -static const char *out_of_spec = "<OUT OF SPEC>"; -static const char *bad_index = "<BAD INDEX>"; +#define WORD(x) (uint16_t)(*(const uint16_t *)(x)) +#define DWORD(x) (uint32_t)(*(const uint32_t *)(x)) +#define QWORD(x) (*(const uint64_t *)(x)) -#define WORD(x) (u16)(*(const u16 *)(x)) -#define DWORD(x) (u32)(*(const u32 *)(x)) -#define QWORD(x) (*(const u64 *)(x)) +enum {DMI_TABLE_PRESENT = 100, ENODMITABLE}; #include "dmi_bios.h" #include "dmi_system.h" #include "dmi_base_board.h" #include "dmi_chassis.h" #include "dmi_processor.h" +#include "dmi_memory.h" +#include "dmi_battery.h" extern char display_line; #define moreprintf(...) do { display_line++; if (display_line == 24) { char tempbuf[10]; display_line=0; printf("Press enter to continue"); fgets(tempbuf, sizeof tempbuf, stdin);} printf ( __VA_ARGS__); } while (0); typedef struct { -u16 num; -u16 len; -u16 ver; -u32 base; +uint16_t num; +uint16_t len; +uint16_t ver; +uint32_t base; +uint16_t major_version; +uint16_t minor_version; } dmi_table; -static dmi_table dmitable; struct dmi_header { - u8 type; - u8 length; - u16 handle; - u8 *data; + uint8_t type; + uint8_t length; + uint16_t handle; + uint8_t *data; }; typedef struct { @@ -63,15 +67,19 @@ typedef struct { s_base_board base_board; s_chassis chassis; s_processor processor; + s_battery battery; + s_memory memory[MAX_DMI_MEMORY_ITEMS]; + int memory_count; + dmi_table dmitable; } s_dmi; -void to_dmi_header(struct dmi_header *h, u8 *data); -void dmi_bios_runtime_size(u32 code, s_dmi *dmi); -const char *dmi_string(struct dmi_header *dm, u8 s); -inline int dmi_checksum(u8 *buf); +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); void parse_dmitable(s_dmi *dmi); -void dmi_decode(struct dmi_header *h, u16 ver, s_dmi *dmi); -int dmi_interate(); +void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi *dmi); +int dmi_iterate(s_dmi *dmi); /* dmi_utils.c */ void display_bios_characteristics(s_dmi *dmi); diff --git a/com32/include/dmi/dmi_base_board.h b/com32/gplinclude/dmi/dmi_base_board.h index d6634c01..5b92b848 100644 --- a/com32/include/dmi/dmi_base_board.h +++ b/com32/gplinclude/dmi/dmi_base_board.h @@ -25,13 +25,7 @@ #define BASE_BOARD_NB_ELEMENTS 5 -static const char *base_board_features_strings[]={ - "Board is a hosting board", /* 0 */ - "Board requires at least one daughter board", - "Board is removable", - "Board is replaceable", - "Board is hot swappable" /* 4 */ -}; +extern const char *base_board_features_strings[]; /* this struct have BASE_BOARD_NB_ELEMENTS */ /* each bool is associated to the relevant message above */ @@ -52,6 +46,8 @@ char asset_tag[BASE_BOARD_ASSET_TAG_SIZE]; char location[BASE_BOARD_LOCATION_SIZE]; char type[BASE_BOARD_TYPE_SIZE]; s_base_board_features features; +/* The filled field have to be set to true when the dmitable implement that item */ +bool filled; } s_base_board; #endif diff --git a/com32/gplinclude/dmi/dmi_battery.h b/com32/gplinclude/dmi/dmi_battery.h new file mode 100644 index 00000000..72c19693 --- /dev/null +++ b/com32/gplinclude/dmi/dmi_battery.h @@ -0,0 +1,57 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Erwan Velu - 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 DMI_BATTERY_H +#define DMI_BATTERY_H + +#include <stdbool.h> +#include <inttypes.h> + +#define BATTERY_LOCATION_SIZE 255 +#define BATTERY_MANUFACTURER_SIZE 255 +#define BATTERY_MANUFACTURE_DATE_SIZE 255 +#define BATTERY_SERIAL_SIZE 255 +#define BATTERY_DEVICE_NAME_SIZE 255 +#define BATTERY_CHEMISTRY_SIZE 32 +#define BATTERY_CAPACITY_SIZE 16 +#define BATTERY_DESIGN_VOLTAGE_SIZE 16 +#define BATTERY_SBDS_SIZE 255 +#define BATTERY_MAXIMUM_ERROR_SIZE 32 +#define BATTERY_SBDS_SERIAL_SIZE 32 +#define BATTERY_SBDS_MANUFACTURE_DATE_SIZE 255 +#define BATTERY_SBDS_CHEMISTRY_SIZE 16 +#define BATTERY_OEM_INFO_SIZE 255 + +typedef struct { +char location[BATTERY_LOCATION_SIZE]; +char manufacturer[BATTERY_MANUFACTURER_SIZE]; +char manufacture_date[BATTERY_MANUFACTURE_DATE_SIZE]; +char serial[BATTERY_SERIAL_SIZE]; +char name[BATTERY_DEVICE_NAME_SIZE]; +char chemistry[BATTERY_CHEMISTRY_SIZE]; +char design_capacity[BATTERY_CAPACITY_SIZE]; +char design_voltage[BATTERY_DESIGN_VOLTAGE_SIZE]; +char sbds[BATTERY_SBDS_SIZE]; +char sbds_serial[BATTERY_SBDS_SERIAL_SIZE]; +char maximum_error[BATTERY_MAXIMUM_ERROR_SIZE]; +char sbds_manufacture_date[BATTERY_SBDS_MANUFACTURE_DATE_SIZE]; +char sbds_chemistry[BATTERY_SBDS_CHEMISTRY_SIZE]; +char oem_info[BATTERY_OEM_INFO_SIZE]; +/* The filled field have to be set to true when the dmitable implement that item */ +bool filled; +} s_battery; + +const char *dmi_battery_chemistry(uint8_t code); +void dmi_battery_capacity(uint16_t code, uint8_t multiplier,char *capacity); +void dmi_battery_voltage(uint16_t code, char *voltage); +void dmi_battery_maximum_error(uint8_t code, char *error); +#endif diff --git a/com32/include/dmi/dmi_bios.h b/com32/gplinclude/dmi/dmi_bios.h index 0241f0b2..546bbefc 100644 --- a/com32/include/dmi/dmi_bios.h +++ b/com32/gplinclude/dmi/dmi_bios.h @@ -26,37 +26,7 @@ #define BIOS_CHAR_X1_NB_ELEMENTS 8 #define BIOS_CHAR_X2_NB_ELEMENTS 3 -static const char *bios_charac_strings[]={ - "BIOS characteristics not supported", /* 3 */ - "ISA is supported", - "MCA is supported", - "EISA is supported", - "PCI is supported", - "PC Card (PCMCIA) is supported", - "PNP is supported", - "APM is supported", - "BIOS is upgradeable", - "BIOS shadowing is allowed", - "VLB is supported", - "ESCD support is available", - "Boot from CD is supported", - "Selectable boot is supported", - "BIOS ROM is socketed", - "Boot from PC Card (PCMCIA) is supported", - "EDD is supported", - "Japanese floppy for NEC 9800 1.2 MB is supported (int 13h)", - "Japanese floppy for Toshiba 1.2 MB is supported (int 13h)", - "5.25\"/360 KB floppy services are supported (int 13h)", - "5.25\"/1.2 MB floppy services are supported (int 13h)", - "3.5\"/720 KB floppy services are supported (int 13h)", - "3.5\"/2.88 MB floppy services are supported (int 13h)", - "Print screen service is supported (int 5h)", - "8042 keyboard services are supported (int 9h)", - "Serial services are supported (int 14h)", - "Printer services are supported (int 17h)", - "CGA/mono video services are supported (int 10h)", - "NEC PC-98" /* 31 */ -}; +extern const char *bios_charac_strings[]; /* this struct has BIOS_CHAR_NB_ELEMENTS */ /* each bool is associated with the relevant message above */ @@ -91,16 +61,7 @@ bool cga_mono_support; bool nec_pc_98; } __attribute__((__packed__)) s_characteristics; -static const char *bios_charac_x1_strings[]={ - "ACPI is supported", /* 0 */ - "USB legacy is supported", - "AGP is supported", - "I2O boot is supported", - "LS-120 boot is supported", - "ATAPI Zip drive boot is supported", - "IEEE 1394 boot is supported", - "Smart battery is supported" /* 7 */ -}; +extern const char *bios_charac_x1_strings[]; /* this struct has BIOS_CHAR_X1_NB_ELEMENTS */ /* each bool is associated with the relevant message above */ @@ -115,11 +76,7 @@ bool ieee_1394_boot; bool smart_battery; } __attribute__((__packed__)) s_characteristics_x1; -static const char *bios_charac_x2_strings[]={ - "BIOS boot specification is supported", /* 0 */ - "Function key-initiated network boot is supported", - "Targeted content distribution is supported" /* 2 */ -}; +extern const char *bios_charac_x2_strings[]; /* this struct has BIOS_CHAR_X2_NB_ELEMENTS */ /* each bool is associated with the relevant message above */ @@ -133,16 +90,18 @@ typedef struct { char vendor[BIOS_VENDOR_SIZE]; char version[BIOS_VERSION_SIZE]; char release_date[BIOS_RELEASE_SIZE]; -u16 address; -u16 runtime_size; +uint16_t address; +uint16_t runtime_size; char runtime_size_unit[BIOS_RUNTIME_SIZE_UNIT_SIZE]; -u16 rom_size; +uint16_t rom_size; char rom_size_unit[BIOS_ROM_UNIT_SIZE]; s_characteristics characteristics; s_characteristics_x1 characteristics_x1; s_characteristics_x2 characteristics_x2; char bios_revision [BIOS_BIOS_REVISION_SIZE]; char firmware_revision [BIOS_FIRMWARE_REVISION_SIZE]; +/* The filled field have to be set to true when the dmitable implement that item */ +bool filled; } s_bios; #endif diff --git a/com32/gplinclude/dmi/dmi_chassis.h b/com32/gplinclude/dmi/dmi_chassis.h new file mode 100644 index 00000000..96711ed4 --- /dev/null +++ b/com32/gplinclude/dmi/dmi_chassis.h @@ -0,0 +1,50 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2006 Erwan Velu - 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 DMI_CHASSIS_H +#define DMI_CHASSIS_H + +#define CHASSIS_MANUFACTURER_SIZE 32 +#define CHASSIS_TYPE_SIZE 16 +#define CHASSIS_LOCK_SIZE 16 +#define CHASSIS_VERSION_SIZE 16 +#define CHASSIS_SERIAL_SIZE 32 +#define CHASSIS_ASSET_TAG_SIZE 32 +#define CHASSIS_BOOT_UP_STATE_SIZE 32 +#define CHASSIS_POWER_SUPPLY_STATE_SIZE 32 +#define CHASSIS_THERMAL_STATE_SIZE 32 +#define CHASSIS_SECURITY_STATUS_SIZE 32 +#define CHASSIS_OEM_INFORMATION_SIZE 32 + +typedef struct { +char manufacturer[CHASSIS_MANUFACTURER_SIZE]; +char type[CHASSIS_TYPE_SIZE]; +char lock[CHASSIS_LOCK_SIZE]; +char version[CHASSIS_VERSION_SIZE]; +char serial[CHASSIS_SERIAL_SIZE]; +char asset_tag[CHASSIS_ASSET_TAG_SIZE]; +char boot_up_state[CHASSIS_BOOT_UP_STATE_SIZE]; +char power_supply_state[CHASSIS_POWER_SUPPLY_STATE_SIZE]; +char thermal_state[CHASSIS_THERMAL_STATE_SIZE]; +char security_status[CHASSIS_SECURITY_STATUS_SIZE]; +char oem_information[CHASSIS_OEM_INFORMATION_SIZE]; +uint16_t height; +uint16_t nb_power_cords; +/* The filled field have to be set to true when the dmitable implement that item */ +bool filled; +} s_chassis; + +const char *dmi_chassis_type(uint8_t code); +const char *dmi_chassis_lock(uint8_t code); +const char *dmi_chassis_state(uint8_t code); +const char *dmi_chassis_security_status(uint8_t code); +#endif diff --git a/com32/gplinclude/dmi/dmi_memory.h b/com32/gplinclude/dmi/dmi_memory.h new file mode 100644 index 00000000..2b744b5c --- /dev/null +++ b/com32/gplinclude/dmi/dmi_memory.h @@ -0,0 +1,61 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Erwan Velu - 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 DMI_MEMORY_H +#define DMI_MEMORY_H + +#define MEMORY_MANUFACTURER_SIZE 32 +#define MEMORY_ERROR_SIZE 16 +#define MEMORY_TOTAL_WIDTH_SIZE 16 +#define MEMORY_DATA_WIDTH_SIZE 16 +#define MEMORY_SIZE_SIZE 32 +#define MEMORY_FORM_FACTOR_SIZE 32 +#define MEMORY_DEVICE_SET_SIZE 32 +#define MEMORY_DEVICE_LOCATOR_SIZE 32 +#define MEMORY_BANK_LOCATOR_SIZE 32 +#define MEMORY_TYPE_SIZE 32 +#define MEMORY_TYPE_DETAIL_SIZE 16 +#define MEMORY_SPEED_SIZE 16 +#define MEMORY_SERIAL_SIZE 16 +#define MEMORY_ASSET_TAG_SIZE 16 +#define MEMORY_PART_NUMBER_SIZE 16 + +typedef struct { +char manufacturer[MEMORY_MANUFACTURER_SIZE]; +char error[MEMORY_ERROR_SIZE]; +char total_width[MEMORY_TOTAL_WIDTH_SIZE]; +char data_width[MEMORY_DATA_WIDTH_SIZE]; +char size[MEMORY_SIZE_SIZE]; +char form_factor[MEMORY_FORM_FACTOR_SIZE]; +char device_set[MEMORY_DEVICE_SET_SIZE]; +char device_locator[MEMORY_DEVICE_LOCATOR_SIZE]; +char bank_locator[MEMORY_BANK_LOCATOR_SIZE]; +char type[MEMORY_TYPE_SIZE]; +char type_detail[MEMORY_TYPE_DETAIL_SIZE]; +char speed[MEMORY_SPEED_SIZE]; +char serial[MEMORY_SERIAL_SIZE]; +char asset_tag[MEMORY_ASSET_TAG_SIZE]; +char part_number[MEMORY_PART_NUMBER_SIZE]; +/* The filled field have to be set to true when the dmitable implement that item */ +bool filled; +} s_memory; + +void dmi_memory_array_error_handle(uint16_t code,char *array); +void dmi_memory_device_width(uint16_t code, char *width); +void dmi_memory_device_size(uint16_t code, char *size); +const char *dmi_memory_device_form_factor(uint8_t code); +void dmi_memory_device_set(uint8_t code, char *set); +const char *dmi_memory_device_type(uint8_t code); +void dmi_memory_device_type_detail(uint16_t code,char *type_detail); +void dmi_memory_device_speed(uint16_t code, char *speed); + +#endif diff --git a/com32/gplinclude/dmi/dmi_processor.h b/com32/gplinclude/dmi/dmi_processor.h new file mode 100644 index 00000000..79ee43d4 --- /dev/null +++ b/com32/gplinclude/dmi/dmi_processor.h @@ -0,0 +1,111 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2006 Erwan Velu - 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 DMI_PROCESSOR_H +#define DMI_PROCESSOR_H + +#include "stdbool.h" +#include "string.h" +#define PROCESSOR_SOCKET_DESIGNATION_SIZE 32 +#define PROCESSOR_TYPE_SIZE 32 +#define PROCESSOR_FAMILY_SIZE 32 +#define PROCESSOR_MANUFACTURER_SIZE 64 +#define PROCESSOR_VERSION_SIZE 32 +#define PROCESSOR_VOLTAGE_SIZE 16 +#define PROCESSOR_STATUS_SIZE 16 +#define PROCESSOR_UPGRADE_SIZE 16 +#define PROCESSOR_CACHE_SIZE 16 +#define PROCESSOR_SERIAL_SIZE 32 +#define PROCESSOR_ASSET_TAG_SIZE 32 +#define PROCESSOR_PART_NUMBER_SIZE 32 +#define PROCESSOR_ID_SIZE 32 + +#define PROCESSOR_FLAGS_ELEMENTS 32 +/* Intel AP-485 revision 28, table 5 */ +extern const char *cpu_flags_strings[PROCESSOR_FLAGS_ELEMENTS]; + +/* this struct have PROCESSOR_FLAGS_ELEMENTS */ +/* each bool is associated to the relevant message above */ +typedef struct { +bool fpu; +bool vme; +bool de; +bool pse; +bool tsc; +bool msr; +bool pae; +bool mce; +bool cx8; +bool apic; +bool null_10; +bool sep; +bool mtrr; +bool pge; +bool mca; +bool cmov; +bool pat; +bool pse_36; +bool psn; +bool clfsh; +bool null_20; +bool ds; +bool acpi; +bool mmx; +bool fxsr; +bool sse; +bool sse2; +bool ss; +bool htt; +bool tm; +bool null_30; +bool pbe; +} __attribute__((__packed__)) s_dmi_cpu_flags; + +typedef struct { +uint8_t type; +uint8_t family; +uint8_t model; +uint8_t stepping; +uint8_t minor_stepping; +} __attribute__((__packed__)) s_signature; + +typedef struct { +char socket_designation[PROCESSOR_SOCKET_DESIGNATION_SIZE]; +char type[PROCESSOR_TYPE_SIZE]; +char family[PROCESSOR_FAMILY_SIZE]; +char manufacturer[PROCESSOR_MANUFACTURER_SIZE]; +char version[PROCESSOR_VERSION_SIZE]; +float voltage; +uint16_t external_clock; +uint16_t max_speed; +uint16_t current_speed; +char status[PROCESSOR_STATUS_SIZE]; +char upgrade[PROCESSOR_UPGRADE_SIZE]; +char cache1[PROCESSOR_CACHE_SIZE]; +char cache2[PROCESSOR_CACHE_SIZE]; +char cache3[PROCESSOR_CACHE_SIZE]; +char serial[PROCESSOR_SERIAL_SIZE]; +char asset_tag[PROCESSOR_ASSET_TAG_SIZE]; +char part_number[PROCESSOR_PART_NUMBER_SIZE]; +char id[PROCESSOR_ID_SIZE]; +s_dmi_cpu_flags cpu_flags; +s_signature signature; +/* The filled field have to be set to true when the dmitable implement that item */ +bool filled; +} s_processor; + +const char *dmi_processor_type(uint8_t code); +const char *dmi_processor_family(uint8_t code, char *manufacturer); +const char *dmi_processor_status(uint8_t code); +const char *dmi_processor_upgrade(uint8_t code); +void dmi_processor_cache(uint16_t code, const char *level, uint16_t ver, char *cache); +#endif diff --git a/com32/include/dmi/dmi_system.h b/com32/gplinclude/dmi/dmi_system.h index 27293649..5a461d5f 100644 --- a/com32/include/dmi/dmi_system.h +++ b/com32/gplinclude/dmi/dmi_system.h @@ -31,6 +31,8 @@ char uuid[SYSTEM_UUID_SIZE]; char wakeup_type[SYSTEM_WAKEUP_TYPE_SIZE]; char sku_number[SYSTEM_SKU_NUMBER_SIZE]; char family[SYSTEM_FAMILY_SIZE]; +/* The filled field have to be set to true when the dmitable implement that item */ +bool filled; } s_system; #endif diff --git a/com32/gpllib/Makefile b/com32/gpllib/Makefile new file mode 100644 index 00000000..08164c2a --- /dev/null +++ b/com32/gpllib/Makefile @@ -0,0 +1,45 @@ +# +# LGPL/GPL code library +# + +# Include configuration rules +topdir = ../.. +include ../lib/MCONFIG + +REQFLAGS += -I../gplinclude + +LIBOBJS = dmi/dmi_battery.o dmi/dmi_chassis.o dmi/dmi_memory.o \ + dmi/dmi_processor.o dmi/dmi.o dmi/dmi_bios.o dmi/dmi_base_board.o \ + cpuid.o + +BINDIR = /usr/bin +LIBDIR = /usr/lib +DATADIR = /usr/share +AUXDIR = $(DATADIR)/syslinux +INCDIR = /usr/include +COM32DIR = $(AUXDIR)/com32 + +all: libcom32gpl.a + +libcom32gpl.a : $(LIBOBJS) + rm -f $@ + $(AR) cq $@ $^ + $(RANLIB) $@ + +tidy dist clean: + find . \( -name \*.o -o -name \*.a -o -name .\*.d -o -name \*.tmp \) -print0 | \ + xargs -0r rm -f + +spotless: clean + rm -f *.a + rm -f *~ \#* */*~ */\#* + +# Mixing in the GPL include files is suboptimal, but I'm not sure +# there is a better way to do it. +install: all + mkdir -m 755 -p $(INSTALLROOT)$(COM32DIR) + install -m 644 libcom32gpl.a $(INSTALLROOT)$(COM32DIR) + mkdir -p $(INSTALLROOT)$(COM32DIR)/include/ + cp -r ../gplinclude $(INSTALLROOT)$(COM32DIR)/include/ + +-include .*.d */.*.d */*/.*.d diff --git a/com32/modules/cpuid.c b/com32/gpllib/cpuid.c index 9418a21e..ed3224d4 100644 --- a/com32/modules/cpuid.c +++ b/com32/gpllib/cpuid.c @@ -1,29 +1,20 @@ -/* ----------------------------------------------------------------------- * - * - * Copyright 2006 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. +/* + * Portions of this file taken from the Linux kernel, + * Copyright 1991-2009 Linus Torvalds and contributors * - * 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. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * ----------------------------------------------------------------------- */ + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ #include <stdio.h> #include <string.h> @@ -144,7 +135,8 @@ int get_model_name(struct cpuinfo_x86 *c) void generic_identify(struct cpuinfo_x86 *c) { - uint32_t tfms, xlvl, junk; + uint32_t tfms, xlvl; + unsigned int ebx; /* Get vendor name */ cpuid(0x00000000, @@ -157,18 +149,18 @@ void generic_identify(struct cpuinfo_x86 *c) /* Intel-defined flags: level 0x00000001 */ if ( c->cpuid_level >= 0x00000001 ) { uint32_t capability, excap; - cpuid(0x00000001, &tfms, &junk, &excap, &capability); + cpuid(0x00000001, &tfms, &ebx, &excap, &capability); c->x86_capability[0] = capability; c->x86_capability[4] = excap; c->x86 = (tfms >> 8) & 15; c->x86_model = (tfms >> 4) & 15; - if (c->x86 == 0xf) { + if (c->x86 == 0xf) c->x86 += (tfms >> 20) & 0xff; + if (c->x86 >= 0x6) c->x86_model += ((tfms >> 16) & 0xF) << 4; - } c->x86_mask = tfms & 15; - if (capability & (1<<19)) - c->x86_cache_alignment = ((junk >> 8) & 0xff) * 8; + if (cpu_has(c, X86_FEATURE_CLFLSH)) + c->x86_clflush_size = ((ebx >> 8) & 0xff) * 8; } else { /* Have CPUID level 0 only - unheard of */ c->x86 = 4; @@ -310,21 +302,22 @@ void set_generic_info(struct cpuinfo_x86 *c,s_cpu *cpu) { cpu->vendor_id=c->x86_vendor; cpu->model_id=c->x86_model; cpu->stepping=c->x86_mask; - strncpy(cpu->vendor,cpu_devs[c->x86_vendor]->c_vendor,CPU_VENDOR_SIZE); - strncpy(cpu->model,c->x86_model_id,CPU_MODEL_SIZE); + strncpy(cpu->vendor,cpu_devs[c->x86_vendor]->c_vendor,sizeof(cpu->vendor)); + strncpy(cpu->model,c->x86_model_id,sizeof(cpu->model)); } void detect_cpu(s_cpu *cpu) { struct cpuinfo_x86 c; - c.x86_cache_alignment = 32; + c.x86_clflush_size = 32; c.x86_cache_size = -1; c.x86_vendor = X86_VENDOR_UNKNOWN; c.cpuid_level = -1; /* CPUID not detected */ c.x86_model = c.x86_mask = 0; /* So far unknown... */ - c.x86_vendor_id[0] = '\0'; /* Unset */ - c.x86_model_id[0] = '\0'; /* Unset */ - memset(&c.x86_vendor_id,'\0',CPU_VENDOR_SIZE); + c.x86_max_cores = 1; + memset(&c.x86_capability, 0, sizeof(c.x86_capability)); + memset(&c.x86_vendor_id,0,sizeof(c.x86_vendor_id)); + memset(&c.x86_model_id,0,sizeof(c.x86_model_id)); if (!have_cpuid_p()) return; diff --git a/com32/modules/dmi.c b/com32/gpllib/dmi/dmi.c index 1e47c1a6..a2a08b56 100644 --- a/com32/modules/dmi.c +++ b/com32/gpllib/dmi/dmi.c @@ -30,17 +30,60 @@ #include <string.h> #include "dmi/dmi.h" +const char *out_of_spec = "<OUT OF SPEC>"; +const char *bad_index = "<BAD INDEX>"; +void dmi_bios_runtime_size(uint32_t code, s_dmi *dmi) +{ + if(code&0x000003FF) { + dmi->bios.runtime_size=code; + strcpy(dmi->bios.runtime_size_unit,"bytes"); + } else { + dmi->bios.runtime_size=code >>10; + strcpy(dmi->bios.runtime_size_unit,"KB"); + + } +} -void to_dmi_header(struct dmi_header *h, u8 *data) +void dmi_bios_characteristics(uint64_t code, s_dmi *dmi) { - h->type=data[0]; - h->length=data[1]; - h->handle=WORD(data+2); - h->data=data; + int i; + /* + * This isn't very clear what this bit is supposed to mean + */ + //if(code.l&(1<<3)) + if(code&&(1<<3)) + { + ((bool *)(& dmi->bios.characteristics))[0]=true; + return; + } + + for(i=4; i<=31; i++) + //if(code.l&(1<<i)) + if(code&(1<<i)) + ((bool *)(& dmi->bios.characteristics))[i-3]=true; +} + +void dmi_bios_characteristics_x1(uint8_t code, s_dmi *dmi) +{ + int i; + + for(i=0; i<=7; i++) + if(code&(1<<i)) + ((bool *)(& dmi->bios.characteristics_x1))[i]=true; +} + +void dmi_bios_characteristics_x2(uint8_t code, s_dmi *dmi) +{ + int i; + + for(i=0; i<=2; i++) + if(code&(1<<i)) + ((bool *)(& dmi->bios.characteristics_x2))[i]=true; } -void dmi_system_uuid(u8 *p, s_dmi *dmi) + +void dmi_system_uuid(uint8_t *p, s_dmi *dmi) { int only0xFF=1, only0x00=1; int i; @@ -67,20 +110,42 @@ void dmi_system_uuid(u8 *p, s_dmi *dmi) p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]); } -static void dmi_base_board_features(u8 code, s_dmi *dmi) +void dmi_system_wake_up_type(uint8_t code, s_dmi *dmi) +{ + /* 3.3.2.1 */ + static const char *type[]={ + "Reserved", /* 0x00 */ + "Other", + "Unknown", + "APM Timer", + "Modem Ring", + "LAN Remote", + "Power Switch", + "PCI PME#", + "AC Power Restored" /* 0x08 */ + }; + + if(code<=0x08) { + strcpy(dmi->system.wakeup_type,type[code]); + } else { + strcpy(dmi->system.wakeup_type,out_of_spec); + } +return; +} + +static void dmi_base_board_features(uint8_t code, s_dmi *dmi) { if((code&0x1F)!=0) { int i; - printf("\n"); for(i=0; i<=4; i++) if(code&(1<<i)) - ((bool *)(& dmi->base_board.features))[i]=true; + ((bool *)(& dmi->base_board.features))[i]=true; } } -static void dmi_processor_voltage(u8 code, s_dmi *dmi) +static void dmi_processor_voltage(uint8_t code, s_dmi *dmi) { /* 3.3.5.4 */ static const float voltage[]={ @@ -100,14 +165,14 @@ static void dmi_processor_voltage(u8 code, s_dmi *dmi) } } -static void dmi_processor_id(u8 type, u8 *p, const char *version, s_dmi *dmi) +static void dmi_processor_id(uint8_t type, uint8_t *p, const char *version, s_dmi *dmi) { /* * Extra flags are now returned in the ECX register when one calls * the CPUID instruction. Their meaning is explained in table 6, but * DMI doesn't support this yet. */ - u32 eax, edx; + uint32_t eax, edx; int sig=0; /* @@ -119,7 +184,7 @@ static void dmi_processor_id(u8 type, u8 *p, const char *version, s_dmi *dmi) if(type==0x05) /* 80386 */ { - u16 dx=WORD(p); + uint16_t dx=WORD(p); /* * 80386 have a different signature. */ @@ -131,7 +196,7 @@ static void dmi_processor_id(u8 type, u8 *p, const char *version, s_dmi *dmi) } if(type==0x06) /* 80486 */ { - u16 dx=WORD(p); + uint16_t dx=WORD(p); /* * Not all 80486 CPU support the CPUID instruction, we have to find * wether the one we have here does or not. Note that this trick @@ -207,77 +272,15 @@ static void dmi_processor_id(u8 type, u8 *p, const char *version, s_dmi *dmi) } -void dmi_system_wake_up_type(u8 code, s_dmi *dmi) -{ - /* 3.3.2.1 */ - static const char *type[]={ - "Reserved", /* 0x00 */ - "Other", - "Unknown", - "APM Timer", - "Modem Ring", - "LAN Remote", - "Power Switch", - "PCI PME#", - "AC Power Restored" /* 0x08 */ - }; - - if(code<=0x08) { - strcpy(dmi->system.wakeup_type,type[code]); - } else { - strcpy(dmi->system.wakeup_type,out_of_spec); - } -return; -} - -void dmi_bios_runtime_size(u32 code, s_dmi *dmi) -{ - if(code&0x000003FF) { - dmi->bios.runtime_size=code; - strcpy(dmi->bios.runtime_size_unit,"bytes"); - } else { - dmi->bios.runtime_size=code >>10; - strcpy(dmi->bios.runtime_size_unit,"KB"); - - } -} - -void dmi_bios_characteristics(u64 code, s_dmi *dmi) -{ - int i; - /* - * This isn't very clear what this bit is supposed to mean - */ - if(code.l&(1<<3)) - { - ((bool *)(& dmi->bios.characteristics))[0]=true; - return; - } - - for(i=4; i<=31; i++) - if(code.l&(1<<i)) - ((bool *)(& dmi->bios.characteristics))[i-3]=true; -} - -void dmi_bios_characteristics_x1(u8 code, s_dmi *dmi) -{ - int i; - - for(i=0; i<=7; i++) - if(code&(1<<i)) - ((bool *)(& dmi->bios.characteristics_x1))[i]=true; -} - -void dmi_bios_characteristics_x2(u8 code, s_dmi *dmi) +void to_dmi_header(struct dmi_header *h, uint8_t *data) { - int i; - - for(i=0; i<=2; i++) - if(code&(1<<i)) - ((bool *)(& dmi->bios.characteristics_x2))[i]=true; + h->type=data[0]; + h->length=data[1]; + h->handle=WORD(data+2); + h->data=data; } -const char *dmi_string(struct dmi_header *dm, u8 s) +const char *dmi_string(struct dmi_header *dm, uint8_t s) { char *bp=(char *)dm->data; size_t i, len; @@ -305,9 +308,9 @@ const char *dmi_string(struct dmi_header *dm, u8 s) return bp; } -inline int dmi_checksum(u8 *buf) +int dmi_checksum(uint8_t *buf) { - u8 sum=0; + uint8_t sum=0; int a; for(a=0; a<15; a++) @@ -315,41 +318,68 @@ inline int dmi_checksum(u8 *buf) return (sum==0); } -int dmi_interate() { - u8 buf[16]; +int dmi_iterate(s_dmi *dmi) { + uint8_t buf[16]; char *p,*q; + + /* Cleaning structures */ + memset(&dmi->base_board,0,sizeof (s_base_board)); + memset(&dmi->battery,0,sizeof (s_battery)); + memset(&dmi->bios,0,sizeof (s_bios)); + memset(&dmi->chassis,0,sizeof (s_chassis)); + for (int i=0;i<MAX_DMI_MEMORY_ITEMS;i++) + memset(&dmi->memory[i],0,sizeof (s_memory)); + memset(&dmi->processor,0,sizeof (s_processor)); + memset(&dmi->system,0,sizeof (s_system)); + + /* Until we found this elements in the dmitable, we consider them as not filled */ + dmi->base_board.filled=false; + dmi->battery.filled=false; + dmi->bios.filled=false; + dmi->chassis.filled=false; + for (int i=0;i<MAX_DMI_MEMORY_ITEMS;i++) + dmi->memory[i].filled=false; + dmi->processor.filled=false; + dmi->system.filled=false; + p=(char *)0xF0000; /* The start address to look at the dmi table */ for (q = p; q < p + 0x10000; q += 16) { memcpy(buf, q, 15); if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf)) { - dmitable.num = buf[13]<<8|buf[12]; - dmitable.len = buf[7]<<8|buf[6]; - dmitable.base = buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8]; - dmitable.ver = (buf[0x06]<<8)+buf[0x07]; + 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) - printf("DMI %d.%d present.\n",buf[14]>>4, buf[14]&0x0F); - else - printf("DMI present.\n"); + 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 1; + printf("DMI table at 0x%08X.\n",dmitable.base);*/ + return DMI_TABLE_PRESENT; } } - dmitable.base=0; - dmitable.num=0; - dmitable.ver=0; - dmitable.len=0; - return 0; + dmi->dmitable.base=0; + dmi->dmitable.num=0; + dmi->dmitable.ver=0; + dmi->dmitable.len=0; + return -ENODMITABLE; } -void dmi_decode(struct dmi_header *h, u16 ver, s_dmi *dmi) +void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi *dmi) { - u8 *data=h->data; + uint8_t *data=h->data; /* * Note: DMI types 37, 38 and 39 are untested @@ -359,6 +389,7 @@ void dmi_decode(struct dmi_header *h, u16 ver, s_dmi *dmi) case 0: /* 3.3.1 BIOS Information */ // printf("BIOS Information\n"); if(h->length<0x12) break; + dmi->bios.filled=true; strcpy(dmi->bios.vendor,dmi_string(h,data[0x04])); strcpy(dmi->bios.version,dmi_string(h,data[0x05])); strcpy(dmi->bios.release_date,dmi_string(h,data[0x08])); @@ -383,6 +414,7 @@ void dmi_decode(struct dmi_header *h, u16 ver, s_dmi *dmi) case 1: /* 3.3.2 System Information */ // printf("System Information\n"); if(h->length<0x08) break; + dmi->system.filled=true; strcpy(dmi->system.manufacturer,dmi_string(h,data[0x04])); strcpy(dmi->system.product_name,dmi_string(h,data[0x05])); strcpy(dmi->system.version,dmi_string(h,data[0x06])); @@ -398,6 +430,7 @@ void dmi_decode(struct dmi_header *h, u16 ver, s_dmi *dmi) case 2: /* 3.3.3 Base Board Information */ // printf("Base Board Information\n"); if(h->length<0x08) break; + dmi->base_board.filled=true; strcpy(dmi->base_board.manufacturer,dmi_string(h,data[0x04])); strcpy(dmi->base_board.product_name,dmi_string(h,data[0x05])); strcpy(dmi->base_board.version,dmi_string(h,data[0x06])); @@ -407,11 +440,12 @@ void dmi_decode(struct dmi_header *h, u16 ver, s_dmi *dmi) dmi_base_board_features(data[0x09], dmi); strcpy(dmi->base_board.location,dmi_string(h,data[0x0A])); strcpy(dmi->base_board.type,dmi_string(h,data[0x0D])); - if(h->length<0x0F+data[0x0E]*sizeof(u16)) break; + if(h->length<0x0F+data[0x0E]*sizeof(uint16_t)) 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])); strcpy(dmi->chassis.type,dmi_chassis_type(data[0x05]&0x7F)); strcpy(dmi->chassis.lock,dmi_chassis_lock(data[0x05]>>7)); @@ -433,10 +467,11 @@ void dmi_decode(struct dmi_header *h, u16 ver, s_dmi *dmi) 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])); strcpy(dmi->processor.type,dmi_processor_type(data[0x05])); - strcpy(dmi->processor.family,dmi_processor_family(data[0x06])); strcpy(dmi->processor.manufacturer,dmi_string(h, data[0x07])); + strcpy(dmi->processor.family,dmi_processor_family(data[0x06],dmi->processor.manufacturer)); dmi_processor_id(data[0x06], data+8, dmi_string(h, data[0x10]), dmi); strcpy(dmi->processor.version,dmi_string(h, data[0x10])); dmi_processor_voltage(data[0x11],dmi); @@ -457,18 +492,82 @@ void dmi_decode(struct dmi_header *h, u16 ver, s_dmi *dmi) strcpy(dmi->processor.asset_tag,dmi_string(h, data[0x21])); strcpy(dmi->processor.part_number,dmi_string(h, data[0x22])); break; + case 17: /* 3.3.18 Memory Device */ + if (h->length < 0x15) break; + dmi->memory_count++; + s_memory *mem = &dmi->memory[dmi->memory_count-1]; + dmi->memory[dmi->memory_count-1].filled=true; + dmi_memory_array_error_handle(WORD(data + 0x06),mem->error); + dmi_memory_device_width(WORD(data + 0x08),mem->total_width); + dmi_memory_device_width(WORD(data + 0x0A),mem->data_width); + dmi_memory_device_size(WORD(data + 0x0C),mem->size); + strcpy(mem->form_factor,dmi_memory_device_form_factor(data[0x0E])); + dmi_memory_device_set(data[0x0F],mem->device_set); + strcpy(mem->device_locator,dmi_string(h, data[0x10])); + strcpy(mem->bank_locator,dmi_string(h, data[0x11])); + strcpy(mem->type,dmi_memory_device_type(data[0x12])); + dmi_memory_device_type_detail(WORD(data + 0x13),mem->type_detail); + if (h->length < 0x17) break; + dmi_memory_device_speed(WORD(data + 0x15),mem->speed); + if (h->length < 0x1B) break; + strcpy(mem->manufacturer, dmi_string(h, data[0x17])); + strcpy(mem->serial,dmi_string(h, data[0x18])); + strcpy(mem->asset_tag,dmi_string(h, data[0x19])); + strcpy(mem->part_number,dmi_string(h, data[0x1A])); + break; + case 22: /* 3.3.23 Portable Battery */ + if (h->length < 0x10) break; + dmi->battery.filled=true; + strcpy(dmi->battery.location,dmi_string(h, data[0x04])); + strcpy(dmi->battery.manufacturer,dmi_string(h, data[0x05])); + + if (data[0x06] || h->length < 0x1A) + strcpy(dmi->battery.manufacture_date, dmi_string(h, data[0x06])); + + if (data[0x07] || h->length < 0x1A) + strcpy(dmi->battery.serial, dmi_string(h, data[0x07])); + + strcpy(dmi->battery.name,dmi_string(h, data[0x08])); + + if (data[0x09] != 0x02 || h->length < 0x1A) + strcpy(dmi->battery.chemistry,dmi_battery_chemistry(data[0x09])); + + if (h->length < 0x1A) + dmi_battery_capacity(WORD(data + 0x0A), 1,dmi->battery.design_capacity); + else + dmi_battery_capacity(WORD(data + 0x0A), data[0x15],dmi->battery.design_capacity); + dmi_battery_voltage(WORD(data + 0x0C),dmi->battery.design_voltage); + strcpy(dmi->battery.sbds,dmi_string(h, data[0x0E])); + dmi_battery_maximum_error(data[0x0F],dmi->battery.maximum_error); + if (h->length < 0x1A) break; + if (data[0x07] == 0) + sprintf(dmi->battery.sbds_serial,"%04X", WORD(data + 0x10)); + + if (data[0x06] == 0) + sprintf(dmi->battery.sbds_manufacture_date,"%u-%02u-%02u", + 1980 + (WORD(data + 0x12) >> 9), + (WORD(data + 0x12) >> 5) & 0x0F, + WORD(data + 0x12) & 0x1F); + if (data[0x09] == 0x02) + strcpy(dmi->battery.sbds_chemistry, dmi_string(h, data[0x14])); + + // sprintf(dmi->battery.oem_info,"0x%08X",DWORD(h, data+0x16)); + break; + + } } void parse_dmitable(s_dmi *dmi) { int i=0; - u8 *data = NULL; - u8 buf[dmitable.len]; + uint8_t *data = NULL; + uint8_t buf[dmi->dmitable.len]; - memcpy(buf,(int *)dmitable.base,sizeof(u8) * dmitable.len); + memcpy(buf,(int *)dmi->dmitable.base,sizeof(uint8_t) * dmi->dmitable.len); data=buf; - while(i<dmitable.num && data+4<=buf+dmitable.len) /* 4 is the length of an SMBIOS structure header */ { - u8 *next; + dmi->memory_count=0; + while(i<dmi->dmitable.num && data+4<=buf+dmi->dmitable.len) /* 4 is the length of an SMBIOS structure header */ { + uint8_t *next; struct dmi_header h; to_dmi_header(&h, data); @@ -488,16 +587,13 @@ void parse_dmitable(s_dmi *dmi) { /* loo for the next handle */ next=data+h.length; - while(next-buf+1<dmitable.len && (next[0]!=0 || next[1]!=0)) + while(next-buf+1<dmi->dmitable.len && (next[0]!=0 || next[1]!=0)) next++; next+=2; - if(next-buf<=dmitable.len) + if(next-buf<=dmi->dmitable.len) { - dmi_decode(&h, dmitable.ver,dmi); + dmi_decode(&h, dmi->dmitable.ver,dmi); } - else - printf("\t<TRUNCATED>\n"); - printf("\n"); data=next; i++; } diff --git a/com32/gpllib/dmi/dmi_base_board.c b/com32/gpllib/dmi/dmi_base_board.c new file mode 100644 index 00000000..f37feec9 --- /dev/null +++ b/com32/gpllib/dmi/dmi_base_board.c @@ -0,0 +1,38 @@ +/* ----------------------------------------------------------------------- * + * + * Pportions of this file taken from the dmidecode project + * + * Copyright (C) 2000-2002 Alan Cox <alan@redhat.com> + * Copyright (C) 2002-2008 Jean Delvare <khali@linux-fr.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For the avoidance of doubt the "preferred form" of this code is one which + * is in an open unpatent encumbered format. Where cryptographic key signing + * forms part of the process of creating an executable the information + * including keys needed to generate an equivalently functional executable + * are deemed to be part of the source code. +*/ + +#include <dmi/dmi.h> +#include <stdio.h> +const char *base_board_features_strings[]={ + "Board is a hosting board", /* 0 */ + "Board requires at least one daughter board", + "Board is removable", + "Board is replaceable", + "Board is hot swappable" /* 4 */ +}; + diff --git a/com32/gpllib/dmi/dmi_battery.c b/com32/gpllib/dmi/dmi_battery.c new file mode 100644 index 00000000..567254a8 --- /dev/null +++ b/com32/gpllib/dmi/dmi_battery.c @@ -0,0 +1,73 @@ +/* ----------------------------------------------------------------------- * + * + * Pportions of this file taken from the dmidecode project + * + * Copyright (C) 2000-2002 Alan Cox <alan@redhat.com> + * Copyright (C) 2002-2008 Jean Delvare <khali@linux-fr.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For the avoidance of doubt the "preferred form" of this code is one which + * is in an open unpatent encumbered format. Where cryptographic key signing + * forms part of the process of creating an executable the information + * including keys needed to generate an equivalently functional executable + * are deemed to be part of the source code. +*/ + +#include <dmi/dmi.h> +#include <stdio.h> +const char *dmi_battery_chemistry(uint8_t code) +{ + /* 3.3.23.1 */ + static const char *chemistry[] = { + "Other", /* 0x01 */ + "Unknown", + "Lead Acid", + "Nickel Cadmium", + "Nickel Metal Hydride", + "Lithium Ion", + "Zinc Air", + "Lithium Polymer" /* 0x08 */ + }; + + if (code >= 0x01 && code <= 0x08) + return chemistry[code - 0x01]; + return out_of_spec; +} + +void dmi_battery_capacity(uint16_t code, uint8_t multiplier,char *capacity) +{ + if (code == 0) + sprintf(capacity,"%s","Unknown"); + else + sprintf(capacity,"%u mWh", code * multiplier); +} + +void dmi_battery_voltage(uint16_t code, char *voltage) +{ + if (code == 0) + sprintf(voltage,"%s","Unknown"); + else + sprintf(voltage,"%u mV", code); +} + +void dmi_battery_maximum_error(uint8_t code, char *error) +{ + if (code == 0xFF) + sprintf(error,"%s","Unknown"); + else + sprintf(error,"%u%%", code); +} + diff --git a/com32/gpllib/dmi/dmi_bios.c b/com32/gpllib/dmi/dmi_bios.c new file mode 100644 index 00000000..9458d492 --- /dev/null +++ b/com32/gpllib/dmi/dmi_bios.c @@ -0,0 +1,80 @@ +/* ----------------------------------------------------------------------- * + * + * Pportions of this file taken from the dmidecode project + * + * Copyright (C) 2000-2002 Alan Cox <alan@redhat.com> + * Copyright (C) 2002-2008 Jean Delvare <khali@linux-fr.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For the avoidance of doubt the "preferred form" of this code is one which + * is in an open unpatent encumbered format. Where cryptographic key signing + * forms part of the process of creating an executable the information + * including keys needed to generate an equivalently functional executable + * are deemed to be part of the source code. +*/ + +#include <dmi/dmi.h> +#include <stdio.h> + +const char *bios_charac_strings[]={ + "BIOS characteristics not supported", /* 3 */ + "ISA is supported", + "MCA is supported", + "EISA is supported", + "PCI is supported", + "PC Card (PCMCIA) is supported", + "PNP is supported", + "APM is supported", + "BIOS is upgradeable", + "BIOS shadowing is allowed", + "VLB is supported", + "ESCD support is available", + "Boot from CD is supported", + "Selectable boot is supported", + "BIOS ROM is socketed", + "Boot from PC Card (PCMCIA) is supported", + "EDD is supported", + "Japanese floppy for NEC 9800 1.2 MB is supported (int 13h)", + "Japanese floppy for Toshiba 1.2 MB is supported (int 13h)", + "5.25\"/360 KB floppy services are supported (int 13h)", + "5.25\"/1.2 MB floppy services are supported (int 13h)", + "3.5\"/720 KB floppy services are supported (int 13h)", + "3.5\"/2.88 MB floppy services are supported (int 13h)", + "Print screen service is supported (int 5h)", + "8042 keyboard services are supported (int 9h)", + "Serial services are supported (int 14h)", + "Printer services are supported (int 17h)", + "CGA/mono video services are supported (int 10h)", + "NEC PC-98" /* 31 */ +}; + +const char *bios_charac_x1_strings[]={ + "ACPI is supported", /* 0 */ + "USB legacy is supported", + "AGP is supported", + "I2O boot is supported", + "LS-120 boot is supported", + "ATAPI Zip drive boot is supported", + "IEEE 1394 boot is supported", + "Smart battery is supported" /* 7 */ +}; + +const char *bios_charac_x2_strings[]={ + "BIOS boot specification is supported", /* 0 */ + "Function key-initiated network boot is supported", + "Targeted content distribution is supported" /* 2 */ +}; + diff --git a/com32/include/dmi/dmi_chassis.h b/com32/gpllib/dmi/dmi_chassis.c index 1456ede9..6150016f 100644 --- a/com32/include/dmi/dmi_chassis.h +++ b/com32/gpllib/dmi/dmi_chassis.c @@ -1,47 +1,35 @@ /* ----------------------------------------------------------------------- * * - * Copyright 2006 Erwan Velu - All Rights Reserved + * Pportions of this file taken from the dmidecode project + * + * Copyright (C) 2000-2002 Alan Cox <alan@redhat.com> + * Copyright (C) 2002-2008 Jean Delvare <khali@linux-fr.org> * * 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. + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * ----------------------------------------------------------------------- */ - -#ifndef DMI_CHASSIS_H -#define DMI_CHASSIS_H - -#define CHASSIS_MANUFACTURER_SIZE 32 -#define CHASSIS_TYPE_SIZE 16 -#define CHASSIS_LOCK_SIZE 16 -#define CHASSIS_VERSION_SIZE 16 -#define CHASSIS_SERIAL_SIZE 32 -#define CHASSIS_ASSET_TAG_SIZE 32 -#define CHASSIS_BOOT_UP_STATE_SIZE 32 -#define CHASSIS_POWER_SUPPLY_STATE_SIZE 32 -#define CHASSIS_THERMAL_STATE_SIZE 32 -#define CHASSIS_SECURITY_STATUS_SIZE 32 -#define CHASSIS_OEM_INFORMATION_SIZE 32 + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For the avoidance of doubt the "preferred form" of this code is one which + * is in an open unpatent encumbered format. Where cryptographic key signing + * forms part of the process of creating an executable the information + * including keys needed to generate an equivalently functional executable + * are deemed to be part of the source code. +*/ -typedef struct { -char manufacturer[CHASSIS_MANUFACTURER_SIZE]; -char type[CHASSIS_TYPE_SIZE]; -char lock[CHASSIS_LOCK_SIZE]; -char version[CHASSIS_VERSION_SIZE]; -char serial[CHASSIS_SERIAL_SIZE]; -char asset_tag[CHASSIS_ASSET_TAG_SIZE]; -char boot_up_state[CHASSIS_BOOT_UP_STATE_SIZE]; -char power_supply_state[CHASSIS_POWER_SUPPLY_STATE_SIZE]; -char thermal_state[CHASSIS_THERMAL_STATE_SIZE]; -char security_status[CHASSIS_SECURITY_STATUS_SIZE]; -char oem_information[CHASSIS_OEM_INFORMATION_SIZE]; -u16 height; -u16 nb_power_cords; -} s_chassis; +#include <dmi/dmi.h> +#include <stdio.h> -static const char *dmi_chassis_type(u8 code) +const char *dmi_chassis_type(uint8_t code) { /* 3.3.4.1 */ static const char *type[]={ @@ -77,7 +65,7 @@ static const char *dmi_chassis_type(u8 code) return out_of_spec; } -static const char *dmi_chassis_lock(u8 code) +const char *dmi_chassis_lock(uint8_t code) { static const char *lock[]={ "Not Present", /* 0x00 */ @@ -87,7 +75,7 @@ static const char *dmi_chassis_lock(u8 code) return lock[code]; } -static const char *dmi_chassis_state(u8 code) +const char *dmi_chassis_state(uint8_t code) { /* 3.3.4.2 */ static const char *state[]={ @@ -104,7 +92,7 @@ static const char *dmi_chassis_state(u8 code) return out_of_spec; } -static const char *dmi_chassis_security_status(u8 code) +const char *dmi_chassis_security_status(uint8_t code) { /* 3.3.4.3 */ static const char *status[]={ @@ -119,5 +107,3 @@ static const char *dmi_chassis_security_status(u8 code) return(status[code-0x01]); return out_of_spec; } - -#endif diff --git a/com32/gpllib/dmi/dmi_memory.c b/com32/gpllib/dmi/dmi_memory.c new file mode 100644 index 00000000..dc354df1 --- /dev/null +++ b/com32/gpllib/dmi/dmi_memory.c @@ -0,0 +1,172 @@ +/* ----------------------------------------------------------------------- * + * + * Pportions of this file taken from the dmidecode project + * + * Copyright (C) 2000-2002 Alan Cox <alan@redhat.com> + * Copyright (C) 2002-2008 Jean Delvare <khali@linux-fr.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For the avoidance of doubt the "preferred form" of this code is one which + * is in an open unpatent encumbered format. Where cryptographic key signing + * forms part of the process of creating an executable the information + * including keys needed to generate an equivalently functional executable + * are deemed to be part of the source code. +*/ + +#include <dmi/dmi.h> +#include <stdio.h> + +void dmi_memory_array_error_handle(uint16_t code,char *array) +{ + if (code == 0xFFFE) + sprintf(array,"%s","Not Provided"); + else if (code == 0xFFFF) + sprintf(array,"%s","No Error"); + else + sprintf(array,"0x%04X", code); +} + +void dmi_memory_device_width(uint16_t code, char *width) +{ + /* + * 3.3.18 Memory Device (Type 17) + * If no memory module is present, width may be 0 + */ + if (code == 0xFFFF || code == 0) + sprintf(width,"%s","Unknown"); + else + sprintf(width,"%u bits", code); +} + +void dmi_memory_device_size(uint16_t code, char *size) +{ + if (code == 0) + sprintf(size,"%s","Free"); + else if (code == 0xFFFF) + sprintf(size,"%s","Unknown"); + else { + if (code & 0x8000) + sprintf(size, "%u kB", code & 0x7FFF); + else + sprintf(size,"%u MB", code); + } +} + +const char *dmi_memory_device_form_factor(uint8_t code) +{ + /* 3.3.18.1 */ + static const char *form_factor[] = { + "Other", /* 0x01 */ + "Unknown", + "SIMM", + "SIP", + "Chip", + "DIP", + "ZIP", + "Proprietary Card", + "DIMM", + "TSOP", + "Row Of Chips", + "RIMM", + "SODIMM", + "SRIMM", + "FB-DIMM" /* 0x0F */ + }; + + if (code >= 0x01 && code <= 0x0F) + return form_factor[code - 0x01]; + return out_of_spec; +} + +void dmi_memory_device_set(uint8_t code, char *set) +{ + if (code == 0) + sprintf(set,"%s","None"); + else if (code == 0xFF) + sprintf(set,"%s","Unknown"); + else + sprintf(set,"%u", code); +} + +const char *dmi_memory_device_type(uint8_t code) +{ + /* 3.3.18.2 */ + static const char *type[] = { + "Other", /* 0x01 */ + "Unknown", + "DRAM", + "EDRAM", + "VRAM", + "SRAM", + "RAM", + "ROM", + "Flash", + "EEPROM", + "FEPROM", + "EPROM", + "CDRAM", + "3DRAM", + "SDRAM", + "SGRAM", + "RDRAM", + "DDR", + "DDR2", + "DDR2 FB-DIMM" /* 0x14 */ + }; + + if (code >= 0x01 && code <= 0x14) + return type[code - 0x01]; + return out_of_spec; +} + +void dmi_memory_device_type_detail(uint16_t code,char *type_detail) +{ + /* 3.3.18.3 */ + static const char *detail[] = { + "Other", /* 1 */ + "Unknown", + "Fast-paged", + "Static Column", + "Pseudo-static", + "RAMBus", + "Synchronous", + "CMOS", + "EDO", + "Window DRAM", + "Cache DRAM", + "Non-Volatile" /* 12 */ + }; + + if ((code & 0x1FFE) == 0) + sprintf(type_detail,"%s","None"); + else + { + int i; + + for (i = 1; i <= 12; i++) + if (code & (1 << i)) + sprintf(type_detail,"%s", detail[i - 1]); + } +} + +void dmi_memory_device_speed(uint16_t code, char *speed) +{ + if (code == 0) + sprintf(speed,"%s","Unknown"); + else + sprintf(speed,"%u MHz", code); +} + diff --git a/com32/gpllib/dmi/dmi_processor.c b/com32/gpllib/dmi/dmi_processor.c new file mode 100644 index 00000000..f86f0095 --- /dev/null +++ b/com32/gpllib/dmi/dmi_processor.c @@ -0,0 +1,433 @@ +/* ----------------------------------------------------------------------- * + * + * Pportions of this file taken from the dmidecode project + * + * Copyright (C) 2000-2002 Alan Cox <alan@redhat.com> + * Copyright (C) 2002-2008 Jean Delvare <khali@linux-fr.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For the avoidance of doubt the "preferred form" of this code is one which + * is in an open unpatent encumbered format. Where cryptographic key signing + * forms part of the process of creating an executable the information + * including keys needed to generate an equivalently functional executable + * are deemed to be part of the source code. +*/ + +#include <dmi/dmi.h> +#include <stdio.h> + +const char *dmi_processor_type(uint8_t code) +{ + /* 3.3.5.1 */ + static const char *type[]={ + "Other", /* 0x01 */ + "Unknown", + "Central Processor", + "Math Processor", + "DSP Processor", + "Video Processor" /* 0x06 */ + }; + + if(code>=0x01 && code<=0x06) + return type[code-0x01]; + return out_of_spec; +} + +const char *dmi_processor_family(uint8_t code, char *manufacturer) +{ + /* 3.3.5.2 */ + static const char *family[]={ + NULL, /* 0x00 */ + "Other", + "Unknown", + "8086", + "80286", + "80386", + "80486", + "8087", + "80287", + "80387", + "80487", + "Pentium", + "Pentium Pro", + "Pentium II", + "Pentium MMX", + "Celeron", + "Pentium II Xeon", + "Pentium III", + "M1", + "M2", + "Celeron M", /* 0x14 */ + "Pentium 4 HT", + NULL, + NULL, /* 0x17 */ + "Duron", + "K5", + "K6", + "K6-2", + "K6-3", + "Athlon", + "AMD2900", + "K6-2+", + "Power PC", + "Power PC 601", + "Power PC 603", + "Power PC 603+", + "Power PC 604", + "Power PC 620", + "Power PC x704", + "Power PC 750", + "Core 2 Duo", /* 0x28 */ + "Core 2 Duo Mobile", + "Core Solo Mobile", + "Atom", + NULL, + NULL, + NULL, + NULL,/* 0x2F */ + "Alpha", + "Alpha 21064", + "Alpha 21066", + "Alpha 21164", + "Alpha 21164PC", + "Alpha 21164a", + "Alpha 21264", + "Alpha 21364", + NULL, /* 0x38 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 0x3F */ + "MIPS", + "MIPS R4000", + "MIPS R4200", + "MIPS R4400", + "MIPS R4600", + "MIPS R10000", + NULL, /* 0x46 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 0x4F */ + "SPARC", + "SuperSPARC", + "MicroSPARC II", + "MicroSPARC IIep", + "UltraSPARC", + "UltraSPARC II", + "UltraSPARC IIi", + "UltraSPARC III", + "UltraSPARC IIIi", + NULL, /* 0x59 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 0x5F */ + "68040", + "68xxx", + "68000", + "68010", + "68020", + "68030", + NULL, /* 0x66 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 0x6F */ + "Hobbit", + NULL, /* 0x71 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 0x77 */ + "Crusoe TM5000", + "Crusoe TM3000", + "Efficeon TM8000", + NULL, /* 0x7B */ + NULL, + NULL, + NULL, + NULL, /* 0x7F */ + "Weitek", + NULL, /* 0x81 */ + "Itanium", + "Athlon 64", + "Opteron", + "Sempron", + "Turion 64", /* 0x86 */ + "Dual-Core Opteron", + "Atlhon 64 X2", + "Turion 64 X2", + "Quad-Core Opteron", + "Third-Generation Opteron", + "Phenom FX", + "Phenom X4", + "Phenom X2", + "Athlon X2",/* 0x8F */ + "PA-RISC", + "PA-RISC 8500", + "PA-RISC 8000", + "PA-RISC 7300LC", + "PA-RISC 7200", + "PA-RISC 7100LC", + "PA-RISC 7100", + NULL, /* 0x97 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 0x9F */ + "V30", + "Quad-Core Xeon 3200", /* 0xA1 */ + "Dual-Core Xeon 3000", + "Quad-Core Xeon 5300", + "Dual-Core Xeon 5100", + "Dual-Core Xeon 5000", + "Dual-Core Xeon LV", + "Dual-Core Xeon ULV", + "Dual-Core Xeon 7100", + "Quad-Core Xeon 5400", + "Quad-Core Xeon", /* 0xAA */ + NULL, + NULL, + NULL, + NULL, + NULL, /* 0xAF */ + "Pentium III Xeon", + "Pentium III Speedstep", + "Pentium 4", + "Xeon", + "AS400", + "Xeon MP", + "Athlon XP", + "Athlon MP", + "Itanium 2", + "Pentium M", + "Celeron D", /* 0xBA */ + "Pentium D", + "Pentium EE", + "Core Solo", /* 0xBD */ + NULL, + "Core 2 Duo", + "Core 2 Solo", + "Core 2 Extreme", + "Core 2 Quad", + "Core 2 Extreme Mobile", + "Core 2 Duo Mobile", + "Core 2 Solo Mobile", + NULL, + NULL, /* 0xC7 */ + "IBM390", + "G4", + "G5", + "ESA/390 G6", /* 0xCB */ + "z/Architectur", + NULL, + NULL, + NULL, + NULL, /*0xD0*/ + NULL, + "C7-M", + "C7-D", + "C7", + "Eden", + NULL,/*0xD6*/ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /*0xE0*/ + NULL, + NULL, + NULL, + NULL, + NULL, + "Embedded Opteron Quad-Core",/* 0xE6*/ + "Phenom Triple-Core" , + "Turion Ultra Dual-Core Mobile", + "Turion Dual-Core Mobile", + "Athlon Dual-Core", + "Sempron SI",/*0xEB*/ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 0xF9 */ + "i860", + "i960", + NULL, /* 0xFC */ + NULL, + NULL, + NULL /* 0xFF */ + /* master.mif has values beyond that, but they can't be used for DMI */ + }; + /* Special case for ambiguous value 0xBE */ + if (code == 0xBE) + { + /* Best bet based on manufacturer string */ + if (strstr(manufacturer, "Intel") != NULL + || strncasecmp(manufacturer, "Intel", 5) == 0) + return "Core 2"; + if (strstr(manufacturer, "AMD") != NULL + || strncasecmp(manufacturer, "AMD", 3) == 0) + return "K7"; + return "Core 2 or K7"; + } + + if(family[code]!=NULL) { + return family[code]; + } + return out_of_spec; +} + +const char *dmi_processor_status(uint8_t code) +{ + static const char *status[]={ + "Unknown", /* 0x00 */ + "Enabled", + "Disabled By User", + "Disabled By BIOS", + "Idle", /* 0x04 */ + "<OUT OF SPEC>", + "<OUT OF SPEC>", + "Other" /* 0x07 */ + }; + + if(code<=0x04) + return status[code]; + if(code==0x07) + return status[0x05]; + return out_of_spec; +} + +const char *dmi_processor_upgrade(uint8_t code) +{ + /* 3.3.5.5 */ + static const char *upgrade[]={ + "Other", /* 0x01 */ + "Unknown", + "Daughter Board", + "ZIF Socket", + "Replaceable Piggy Back", + "None", + "LIF Socket", + "Slot 1", + "Slot 2", + "370-pin Socket", + "Slot A", + "Slot M", + "Socket 423", + "Socket A (Socket 462)", + "Socket 478", + "Socket 754", + "Socket 940", + "Socket 939" /* 0x12 */ + "Socket mPGA604", + "Socket LGA771", + "Socket LGA775", + "Socket S1", + "Socket AM2", + "Socket F (1207)" + }; + + if(code>=0x01 && code<=0x11) + return upgrade[code-0x01]; + return out_of_spec; +} + +void dmi_processor_cache(uint16_t code, const char *level, uint16_t ver, char *cache) +{ + if(code==0xFFFF) + { + if(ver>=0x0203) + sprintf(cache,"Not Provided"); + else + sprintf(cache,"No %s Cache", level); + } + else + sprintf(cache,"0x%04X", code); +} + +/* Intel AP-485 revision 28, table 5 */ +const char *cpu_flags_strings[PROCESSOR_FLAGS_ELEMENTS]={ + "FPU (Floating-point unit on-chip)", /* 0 */ + "VME (Virtual mode extension)", + "DE (Debugging extension)", + "PSE (Page size extension)", + "TSC (Time stamp counter)", + "MSR (Model specific registers)", + "PAE (Physical address extension)", + "MCE (Machine check exception)", + "CX8 (CMPXCHG8 instruction supported)", + "APIC (On-chip APIC hardware supported)", + NULL, /* 10 */ + "SEP (Fast system call)", + "MTRR (Memory type range registers)", + "PGE (Page global enable)", + "MCA (Machine check architecture)", + "CMOV (Conditional move instruction supported)", + "PAT (Page attribute table)", + "PSE-36 (36-bit page size extension)", + "PSN (Processor serial number present and enabled)", + "CLFSH (CLFLUSH instruction supported)", + NULL, /* 20 */ + "DS (Debug store)", + "ACPI (ACPI supported)", + "MMX (MMX technology supported)", + "FXSR (Fast floating-point save and restore)", + "SSE (Streaming SIMD extensions)", + "SSE2 (Streaming SIMD extensions 2)", + "SS (Self-snoop)", + "HTT (Hyper-threading technology)", + "TM (Thermal monitor supported)", + "IA64 (IA64 capabilities)", /* 30 */ + "PBE (Pending break enabled)" /* 31 */ +}; + diff --git a/com32/hdt/Makefile b/com32/hdt/Makefile new file mode 100644 index 00000000..58715071 --- /dev/null +++ b/com32/hdt/Makefile @@ -0,0 +1,75 @@ +## ----------------------------------------------------------------------- +## +## Copyright 2001-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., 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. +## +## ----------------------------------------------------------------------- + +## +## samples for syslinux users +## + +topdir = ../.. +include $(topdir)/MCONFIG.embedded + +INCLUDES = -I$(com32)/include -I$(com32)/cmenu/libmenu -I$(com32)/gplinclude + +LIBGCC := $(shell $(CC) $(GCCOPT) --print-libgcc) +LIB = liboldcom32.a + +com32 = $(topdir)/com32 +LIBS = $(LIB) $(com32)/cmenu/libmenu/libmenu.a \ + $(com32)/gpllib/libcom32gpl.a \ + $(com32)/libutil/libutil_com.a $(com32)/lib/libcom32.a \ + $(LIBGCC) + +LDFLAGS = -m elf_i386 -T $(com32)/lib/com32.ld + +all: hdt.c32 $(LIB) + +.PRECIOUS: %.o +%.o: %.S + $(CC) $(SFLAGS) -c -o $@ $< + +.PRECIOUS: %.o +%.o: %.c + $(CC) $(CFLAGS) -std=gnu99 -D__COM32__ -c -o $@ $< + +.PRECIOUS: %.elf +%.elf: c32entry.o %.o $(LIB) + $(LD) -Ttext 0x101000 -e _start -o $@ $^ + +hdt.elf: hdt.o hdt-ata.o hdt-menu.o hdt-menu-pci.o hdt-menu-kernel.o \ + hdt-menu-disk.o hdt-menu-dmi.o hdt-menu-processor.o \ + hdt-menu-syslinux.o hdt-menu-about.o \ + hdt-cli.o hdt-common.o hdt-cli-pci.o hdt-cli-dmi.o \ + hdt-cli-cpu.o hdt-cli-pxe.o hdt-cli-kernel.o \ + hdt-cli-syslinux.o \ + hdt-menu-pxe.o hdt-menu-summary.o\ + $(LIBS) + $(LD) $(LDFLAGS) -o $@ $^ + +%.c32: %.elf + $(OBJCOPY) -O binary $< $@ + +%.com: %.asm + $(NASM) $(NASMOPT) -f bin -o $@ -l $*.lst $< + +$(LIB): + rm -f $@ + $(AR) cq $@ $^ + $(RANLIB) $@ + +tidy dist: + rm -f *.o *.a *.lst *.elf + +# Don't specify *.com since mdiskchk.com can't be built using Linux tools +clean: tidy + rm -f *.o *.c32 *.c~ *.h~ Makefile~ + +spotless: clean diff --git a/com32/hdt/hdt-ata.c b/com32/hdt/hdt-ata.c new file mode 100644 index 00000000..a5000609 --- /dev/null +++ b/com32/hdt/hdt-ata.c @@ -0,0 +1,254 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- +*/ +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <console.h> +#include "com32io.h" +#include "hdt-ata.h" + +#ifdef ATA +/** + * ata_id_string - Convert IDENTIFY DEVICE page into string + * @id: IDENTIFY DEVICE results we will examine + * @s: string into which data is output + * @ofs: offset into identify device page + * @len: length of string to return. must be an even number. + * + * The strings in the IDENTIFY DEVICE page are broken up into + * 16-bit chunks. Run through the string, and output each + * 8-bit chunk linearly, regardless of platform. + * + * LOCKING: + * caller. + */ + +void ata_id_string(const uint16_t *id, unsigned char *s, + unsigned int ofs, unsigned int len) +{ + unsigned int c; + + while (len > 0) { + c = id[ofs] >> 8; + *s = c; + s++; + + c = id[ofs] & 0xff; + *s = c; + s++; + + ofs++; + len -= 2; + } +} + +/** + * ata_id_c_string - Convert IDENTIFY DEVICE page into C string + * @id: IDENTIFY DEVICE results we will examine + * @s: string into which data is output + * @ofs: offset into identify device page + * @len: length of string to return. must be an odd number. + * + * This function is identical to ata_id_string except that it + * trims trailing spaces and terminates the resulting string with + * null. @len must be actual maximum length (even number) + 1. + * + * LOCKING: + * caller. + */ +void ata_id_c_string(const uint16_t *id, unsigned char *s, + unsigned int ofs, unsigned int len) +{ + unsigned char *p; + + //WARN_ON(!(len & 1)); + + ata_id_string(id, s, ofs, len - 1); + + p = s + strnlen(s, len - 1); + while (p > s && p[-1] == ' ') + p--; + *p = '\0'; +} +#endif + +/* + * Call int 13h, but with retry on failure. Especially floppies need this. + */ +int int13_retry(const com32sys_t *inreg, com32sys_t *outreg) +{ + int retry = 6; /* Number of retries */ + com32sys_t tmpregs; + + if ( !outreg ) outreg = &tmpregs; + + while ( retry-- ) { + __intcall(0x13, inreg, outreg); + if ( !(outreg->eflags.l & EFLAGS_CF) ) + return 0; /* CF=0, OK */ + } + + return -1; /* Error */ +} + +/* Display CPU registers for debugging purposes */ +void printregs(const com32sys_t *r) +{ + printf("eflags = %08x ds = %04x es = %04x fs = %04x gs = %04x\n" + "eax = %08x ebx = %08x ecx = %08x edx = %08x\n" + "ebp = %08x esi = %08x edi = %08x esp = %08x\n", + r->eflags.l, r->ds, r->es, r->fs, r->gs, + r->eax.l, r->ebx.l, r->ecx.l, r->edx.l, + r->ebp.l, r->esi.l, r->edi.l, r->_unused_esp.l); +} + +/* Try to get information for a given disk*/ +int get_disk_params(int disk, struct diskinfo *disk_info) +{ + static com32sys_t getparm, parm, getebios, ebios, inreg,outreg; + struct device_parameter dp; +#ifdef ATA + struct ata_identify_device aid; +#endif + + memset(&(disk_info[disk]), 0, sizeof(struct diskinfo)); + + disk_info[disk].disk = disk; + disk_info[disk].ebios = disk_info[disk].cbios = 0; + + /* Sending int 13h func 41h to query EBIOS information*/ + memset(&getebios, 0, sizeof (com32sys_t)); + memset(&ebios, 0, sizeof (com32sys_t)); + + /* Get EBIOS support */ + getebios.eax.w[0] = 0x4100; + getebios.ebx.w[0] = 0x55aa; + getebios.edx.b[0] = disk; + getebios.eflags.b[0] = 0x3; /* CF set */ + + __intcall(0x13, &getebios, &ebios); + + /* Detecting EDD support */ + if ( !(ebios.eflags.l & EFLAGS_CF) && + ebios.ebx.w[0] == 0xaa55 && + (ebios.ecx.b[0] & 1) ) { + disk_info[disk].ebios = 1; + switch(ebios.eax.b[1]) { + case 32: strlcpy(disk_info[disk].edd_version,"1.0",3); break; + case 33: strlcpy(disk_info[disk].edd_version,"1.1",3); break; + case 48: strlcpy(disk_info[disk].edd_version,"3.0",3); break; + default: strlcpy(disk_info[disk].edd_version,"0",1); break; + } + } + /* Get disk parameters -- really only useful for + hard disks, but if we have a partitioned floppy + it's actually our best chance... */ + memset(&getparm, 0, sizeof (com32sys_t)); + memset(&parm, 0, sizeof (com32sys_t)); + getparm.eax.b[1] = 0x08; + getparm.edx.b[0] = disk; + + __intcall(0x13, &getparm, &parm); + + if ( parm.eflags.l & EFLAGS_CF ) + return disk_info[disk].ebios ? 0 : -1; + + disk_info[disk].heads = parm.edx.b[1]+1; + disk_info[disk].sectors_per_track = parm.ecx.b[0] & 0x3f; + if ( disk_info[disk].sectors_per_track == 0 ) { + disk_info[disk].sectors_per_track = 1; + } else { + disk_info[disk].cbios = 1; /* Valid geometry */ + } + +/* FIXME: memset to 0 make it fails + * memset(__com32.cs_bounce, 0, sizeof(struct device_pairameter)); */ + memset(&dp, 0, sizeof(struct device_parameter)); + memset(&inreg, 0, sizeof(com32sys_t)); + + /* Requesting Extended Read Drive Parameters via int13h func 48h*/ + inreg.esi.w[0] = OFFS(__com32.cs_bounce); + inreg.ds = SEG(__com32.cs_bounce); + inreg.eax.w[0] = 0x4800; + inreg.edx.b[0] = disk; + + __intcall(0x13, &inreg, &outreg); + + /* Saving bounce buffer before anything corrupt it */ + memcpy(&dp, __com32.cs_bounce, sizeof (struct device_parameter)); + + if ( outreg.eflags.l & EFLAGS_CF) { + printf("Disk 0x%X doesn't supports EDD 3.0\n",disk); + return -1; + } + + /* Copying result to the disk_info structure + * host_bus_type, interface_type, sectors & cylinders */ + snprintf(disk_info[disk].host_bus_type,sizeof disk_info[disk].host_bus_type,"%c%c%c%c",dp.host_bus_type[0],dp.host_bus_type[1],dp.host_bus_type[2],dp.host_bus_type[3]); + snprintf(disk_info[disk].interface_type,sizeof disk_info[disk].interface_type,"%c%c%c%c%c%c%c%c",dp.interface_type[0],dp.interface_type[1],dp.interface_type[2],dp.interface_type[3],dp.interface_type[4],dp.interface_type[5],dp.interface_type[6],dp.interface_type[7]); + disk_info[disk].sectors=dp.sectors; + disk_info[disk].cylinders=dp.cylinders; + + /*FIXME: we have to find a way to grab the model & fw + * We do put dummy data until we found a solution */ + snprintf(disk_info[disk].aid.model,sizeof disk_info[disk].aid.model,"0x%X",disk); + snprintf(disk_info[disk].aid.fw_rev,sizeof disk_info[disk].aid.fw_rev,"%s","N/A"); + snprintf(disk_info[disk].aid.serial_no,sizeof disk_info[disk].aid.serial_no,"%s","N/A"); + + /* Useless stuff before I figure how to send ata packets */ +#ifdef ATA + memset(__com32.cs_bounce, 0, sizeof(struct device_parameter)); + memset(&aid, 0, sizeof(struct ata_identify_device)); + memset(&inreg, 0, sizeof inreg); + inreg.ebx.w[0] = OFFS(__com32.cs_bounce+1024); + inreg.es = SEG(__com32.cs_bounce+1024); + inreg.eax.w[0] = 0x2500; + inreg.edx.b[0] = disk; + + __intcall(0x13,&inreg, &outreg); + + memcpy(&aid, __com32.cs_bounce, sizeof (struct ata_identify_device)); + + if ( outreg.eflags.l & EFLAGS_CF) { + printf("Disk 0x%X: Failed to Identify Device\n",disk); + //FIXME + return 0; + } +// ata_id_c_string(aid, disk_info[disk].fwrev, ATA_ID_FW_REV, sizeof(disk_info[disk].fwrev)); +// ata_id_c_string(aid, disk_info[disk].model, ATA_ID_PROD, sizeof(disk_info[disk].model)); + + char buff[sizeof(struct ata_identify_device)]; + memcpy(buff,&aid, sizeof (struct ata_identify_device)); + for (int j=0;j<sizeof(struct ata_identify_device);j++) + printf ("model=|%c|\n",buff[j]); + printf ("Disk 0x%X : %s %s %s\n",disk, aid.model, aid.fw_rev,aid.serial_no); +#endif + +return 0; +} + diff --git a/com32/hdt/hdt-ata.h b/com32/hdt/hdt-ata.h new file mode 100644 index 00000000..7236c549 --- /dev/null +++ b/com32/hdt/hdt-ata.h @@ -0,0 +1,121 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- +*/ + +#ifndef DEFINE_HDT_ATA_H +#define DEFINE_HDT_ATA_H + +#include "hdt.h" +#include <com32io.h> + +struct ata_identify_device { + unsigned short words000_009[10]; + unsigned char serial_no[20]; + unsigned short words020_022[3]; + unsigned char fw_rev[8]; + unsigned char model[40]; + unsigned short words047_079[33]; + unsigned short major_rev_num; + unsigned short minor_rev_num; + unsigned short command_set_1; + unsigned short command_set_2; + unsigned short command_set_extension; + unsigned short cfs_enable_1; + unsigned short word086; + unsigned short csf_default; + unsigned short words088_255[168]; +} ATTR_PACKED; + +struct diskinfo { + int disk; + int ebios; /* EBIOS supported on this disk */ + int cbios; /* CHS geometry is valid */ + int heads; + int sectors_per_track; + int sectors; + int cylinders; + char edd_version[4]; + struct ata_identify_device aid; /* IDENTIFY xxx DEVICE data */ + char host_bus_type[5]; + char interface_type[9]; + char interface_port; +} ATTR_PACKED; + +/* + * Get a disk block and return a malloc'd buffer. + * Uses the disk number and information from disk_info. + */ +struct ebios_dapa { + uint16_t len; + uint16_t count; + uint16_t off; + uint16_t seg; + uint64_t lba; +}; + +// BYTE=8 +// WORD=16 +// DWORD=32 +// QWORD=64 +struct device_parameter { + uint16_t len; + uint16_t info; + uint32_t cylinders; + uint32_t heads; + uint32_t sectors_per_track; + uint64_t sectors; + uint16_t bytes_per_sector; + uint32_t dpte_pointer; + uint16_t device_path_information; + uint8_t device_path_lenght; + uint8_t device_path_reserved; + uint16_t device_path_reserved_2; + uint8_t host_bus_type[4]; + uint8_t interface_type[8]; + uint64_t interace_path; + uint64_t device_path[2]; + uint8_t reserved; + uint8_t cheksum; +} ATTR_PACKED; + + +/* Useless stuff until I manage how to send ata packets */ +#ifdef ATA +enum { + ATA_ID_FW_REV = 23, + ATA_ID_PROD = 27, + ATA_ID_FW_REV_LEN = 8, + ATA_ID_PROD_LEN = 40, +}; +void ata_id_c_string(const uint16_t *id, unsigned char *s, unsigned int ofs, unsigned int len); +void ata_id_string(const uint16_t *id, unsigned char *s, unsigned int ofs, unsigned int len); +int int13_retry(const com32sys_t *inreg, com32sys_t *outreg); +void printregs(const com32sys_t *r); +#endif + +int get_disk_params(int disk, struct diskinfo *disk_info); +#endif diff --git a/com32/hdt/hdt-cli-cpu.c b/com32/hdt/hdt-cli-cpu.c new file mode 100644 index 00000000..edeef24a --- /dev/null +++ b/com32/hdt/hdt-cli-cpu.c @@ -0,0 +1,151 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- +*/ + +#include "hdt-cli.h" +#include "hdt-common.h" +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> + + + +void show_cpu(struct s_hardware *hardware) { + char buffer[81]; + char buffer1[81]; + clear_screen(); + more_printf("CPU\n"); + more_printf("Vendor : %s\n",hardware->cpu.vendor); + more_printf("Model : %s\n",hardware->cpu.model); + more_printf("Vendor ID : %d\n",hardware->cpu.vendor_id); + more_printf("Family ID : %d\n",hardware->cpu.family); + more_printf("Model ID : %d\n",hardware->cpu.model_id); + more_printf("Stepping : %d\n",hardware->cpu.stepping); + more_printf("FSB : %d MHz\n",hardware->dmi.processor.external_clock); + more_printf("Cur. Speed: %d MHz\n",hardware->dmi.processor.current_speed); + more_printf("Max Speed : %d MHz\n",hardware->dmi.processor.max_speed); + more_printf("Upgrade : %s\n", hardware->dmi.processor.upgrade); + if (hardware->cpu.flags.smp) { + more_printf("SMP : yes\n"); + } else { + more_printf("SMP : no\n"); + } + if (hardware->cpu.flags.lm) { + more_printf("x86_64 : yes\n"); + } else { + more_printf("x86_64 : no\n"); + } + + memset(buffer,0,sizeof(buffer)); + memset(buffer1,0,sizeof(buffer1)); + if (hardware->cpu.flags.fpu) strcat(buffer1,"fpu "); + if (hardware->cpu.flags.vme) strcat(buffer1,"vme "); + if (hardware->cpu.flags.de) strcat(buffer1,"de "); + if (hardware->cpu.flags.pse) strcat(buffer1,"pse "); + if (hardware->cpu.flags.tsc) strcat(buffer1,"tsc "); + if (hardware->cpu.flags.msr) strcat(buffer1,"msr "); + if (hardware->cpu.flags.pae) strcat(buffer1,"pae "); +if (hardware->cpu.flags.mce) strcat(buffer1,"mce "); + if (hardware->cpu.flags.cx8) strcat(buffer1,"cx8 "); + if (hardware->cpu.flags.apic) strcat(buffer1,"apic "); + if (hardware->cpu.flags.sep) strcat(buffer1,"sep "); + if (hardware->cpu.flags.mtrr) strcat(buffer1,"mtrr "); + if (hardware->cpu.flags.pge) strcat(buffer1,"pge "); + if (hardware->cpu.flags.mca) strcat(buffer1,"mca "); + snprintf(buffer,sizeof buffer,"Flags : %s\n",buffer1); + more_printf(buffer); + + memset(buffer,0,sizeof(buffer)); + memset(buffer1,0,sizeof(buffer1)); + if (hardware->cpu.flags.cmov) strcat(buffer1,"cmov "); + if (hardware->cpu.flags.pat) strcat(buffer1,"pat "); + if (hardware->cpu.flags.pse_36) strcat(buffer1,"pse_36 "); + if (hardware->cpu.flags.psn) strcat(buffer1,"psn "); + if (hardware->cpu.flags.clflsh) strcat(buffer1,"clflsh "); + if (hardware->cpu.flags.dts) strcat(buffer1,"dts "); + if (hardware->cpu.flags.acpi) strcat(buffer1,"acpi "); + if (hardware->cpu.flags.mmx) strcat(buffer1,"mmx "); + if (hardware->cpu.flags.sse) strcat(buffer1,"sse "); + if (hardware->cpu.flags.sse2) strcat(buffer1,"sse2 "); + if (hardware->cpu.flags.ss) strcat(buffer1,"ss "); + snprintf(buffer,sizeof buffer,"Flags : %s\n",buffer1); + more_printf(buffer); + + memset(buffer,0,sizeof(buffer)); + memset(buffer1,0,sizeof(buffer1)); + if (hardware->cpu.flags.htt) strcat(buffer1,"ht "); + if (hardware->cpu.flags.acc) strcat(buffer1,"acc "); + if (hardware->cpu.flags.syscall) strcat(buffer1,"syscall "); + if (hardware->cpu.flags.mp) strcat(buffer1,"mp "); + if (hardware->cpu.flags.nx) strcat(buffer1,"nx "); + if (hardware->cpu.flags.mmxext) strcat(buffer1,"mmxext "); + if (hardware->cpu.flags.lm) strcat(buffer1,"lm "); + if (hardware->cpu.flags.nowext) strcat(buffer1,"3dnowext "); + if (hardware->cpu.flags.now) strcat(buffer1,"3dnow! "); + snprintf(buffer,sizeof buffer,"Flags : %s\n",buffer1); + more_printf(buffer); +} + +void show_cpu_help() { + more_printf("Show supports the following commands : %s\n",CLI_CPU); +} + +void cpu_show(char *item, struct s_hardware *hardware) { + if ( !strncmp(item, CLI_CPU, sizeof(CLI_CPU) - 1) ) { + show_cpu(hardware); + return; + } + show_cpu_help(); +} + +void handle_cpu_commands(char *cli_line, struct s_cli_mode *cli_mode, struct s_hardware *hardware) { + if ( !strncmp(cli_line, CLI_SHOW, sizeof(CLI_SHOW) - 1) ) { + cpu_show(strstr(cli_line,"show")+ sizeof(CLI_SHOW), hardware); + return; + } +} + +void main_show_cpu(struct s_hardware *hardware,struct s_cli_mode *cli_mode) { + cpu_detect(hardware); + detect_dmi(hardware); + more_printf("CPU\n"); + more_printf(" Manufacturer : %s \n", hardware->cpu.vendor); + more_printf(" Product : %s \n", hardware->cpu.model); + if ((hardware->cpu.flags.lm == false) && (hardware->cpu.flags.smp==false)) { + more_printf(" Features : %d MhZ : x86 32bits\n", hardware->dmi.processor.current_speed); + } else if ((hardware->cpu.flags.lm == false) && (hardware->cpu.flags.smp==true)) { + more_printf(" Features : %d MhZ : x86 32bits SMP\n", hardware->dmi.processor.current_speed); + } else if ((hardware->cpu.flags.lm == true) && (hardware->cpu.flags.smp==false)) { + more_printf(" Features : %d MhZ : x86_64 64bits\n", hardware->dmi.processor.current_speed); + } else { + more_printf(" Features : %d MhZ : x86_64 64bits SMP\n", hardware->dmi.processor.current_speed); + } + +} + + diff --git a/com32/hdt/hdt-cli-dmi.c b/com32/hdt/hdt-cli-dmi.c new file mode 100644 index 00000000..c9820657 --- /dev/null +++ b/com32/hdt/hdt-cli-dmi.c @@ -0,0 +1,360 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- +*/ + +#include "hdt-cli.h" +#include "hdt-common.h" +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> + +void show_dmi_help(struct s_hardware *hardware) { + more_printf("Show supports the following commands : \n"); + more_printf(" %s\n",CLI_SHOW_LIST); + more_printf(" <module_name>\n"); + more_printf(" -\n"); + show_dmi_modules(hardware); +} + + +void dmi_show(char *item, struct s_hardware *hardware) { + if ( !strncmp(item, CLI_DMI_BASE_BOARD, sizeof(CLI_DMI_BASE_BOARD) - 1) ) { + show_dmi_base_board(hardware); + return; + } + if ( !strncmp(item, CLI_DMI_SYSTEM, sizeof(CLI_DMI_SYSTEM) - 1) ) { + show_dmi_system(hardware); + return; + } + if ( !strncmp(item, CLI_DMI_BIOS, sizeof(CLI_DMI_BIOS) - 1) ) { + show_dmi_bios(hardware); + return; + } + if ( !strncmp(item, CLI_DMI_CHASSIS, sizeof(CLI_DMI_CHASSIS) - 1) ) { + show_dmi_chassis(hardware); + return; + } + if ( !strncmp(item, CLI_DMI_PROCESSOR, sizeof(CLI_DMI_PROCESSOR) - 1) ) { + show_dmi_cpu(hardware); + return; + } + if ( !strncmp(item, CLI_DMI_MEMORY, sizeof(CLI_DMI_MEMORY) - 1) ) { + show_dmi_memory_modules(hardware,true,true); + return; + } + if ( !strncmp(item, CLI_DMI_MEMORY_BANK, sizeof(CLI_DMI_MEMORY_BANK) - 1) ) { + show_dmi_memory_bank(hardware,item+ sizeof(CLI_DMI_MEMORY_BANK)-1); + return; + } + if ( !strncmp(item, CLI_SHOW_LIST, sizeof(CLI_SHOW_LIST) - 1) ) { + show_dmi_modules(hardware); + return; + } + if ( !strncmp(item, CLI_DMI_BATTERY, sizeof(CLI_DMI_BATTERY) - 1) ) { + show_dmi_battery(hardware); + return; + } + + show_dmi_help(hardware); +} + +void handle_dmi_commands(char *cli_line, struct s_cli_mode *cli_mode, struct s_hardware *hardware) { + if ( !strncmp(cli_line, CLI_SHOW, sizeof(CLI_SHOW) - 1) ) { + dmi_show(strstr(cli_line,"show")+ sizeof(CLI_SHOW), hardware); + return; + } +} + +void show_dmi_modules(struct s_hardware *hardware) { + char available_dmi_commands[1024]; + memset(available_dmi_commands,0,sizeof(available_dmi_commands)); + + if (hardware->dmi.base_board.filled==true) { + strncat(available_dmi_commands,CLI_DMI_BASE_BOARD,sizeof(CLI_DMI_BASE_BOARD)-1); + strncat(available_dmi_commands," ",1); + } + if (hardware->dmi.battery.filled==true) { + strncat(available_dmi_commands,CLI_DMI_BATTERY,sizeof(CLI_DMI_BATTERY)-1); + strncat(available_dmi_commands," ",1); + } + if (hardware->dmi.bios.filled==true) { + strncat(available_dmi_commands,CLI_DMI_BIOS,sizeof(CLI_DMI_BIOS)-1); + strncat(available_dmi_commands," ",1); + } + if (hardware->dmi.chassis.filled==true) { + strncat(available_dmi_commands,CLI_DMI_CHASSIS,sizeof(CLI_DMI_CHASSIS)-1); + strncat(available_dmi_commands," ",1); + } + for (int i=0;i<hardware->dmi.memory_count;i++) { + if (hardware->dmi.memory[i].filled==true) { + strncat(available_dmi_commands,CLI_DMI_MEMORY,sizeof(CLI_DMI_MEMORY)-1); + strncat(available_dmi_commands," bank<bank_number> ",19); + break; + } + } + if (hardware->dmi.processor.filled==true) { + strncat(available_dmi_commands,CLI_DMI_PROCESSOR,sizeof(CLI_DMI_PROCESSOR)-1); + strncat(available_dmi_commands," ",1); + } + if (hardware->dmi.system.filled==true) { + strncat(available_dmi_commands,CLI_DMI_SYSTEM,sizeof(CLI_DMI_SYSTEM)-1); + strncat(available_dmi_commands," ",1); + } + printf("Available DMI modules: %s\n",available_dmi_commands); +} + +void main_show_dmi(struct s_hardware *hardware,struct s_cli_mode *cli_mode) { + + detect_dmi(hardware); + + if (hardware->is_dmi_valid==false) { + printf("No valid DMI table found, exiting.\n"); + do_exit(cli_mode); + return; + } + printf("DMI Table version %d.%d found\n",hardware->dmi.dmitable.major_version,hardware->dmi.dmitable.minor_version); + + show_dmi_modules(hardware); +} + + +void show_dmi_base_board(struct s_hardware *hardware) { + if (hardware->dmi.base_board.filled==false) { + printf("Base_board module not available\n"); + return; + } + clear_screen(); + more_printf("Base board\n"); + more_printf(" Manufacturer : %s\n",hardware->dmi.base_board.manufacturer); + more_printf(" Product Name : %s\n",hardware->dmi.base_board.product_name); + more_printf(" Version : %s\n",hardware->dmi.base_board.version); + more_printf(" Serial : %s\n",hardware->dmi.base_board.serial); + more_printf(" Asset Tag : %s\n",hardware->dmi.base_board.asset_tag); + more_printf(" Location : %s\n",hardware->dmi.base_board.location); + more_printf(" Type : %s\n",hardware->dmi.base_board.type); + for (int i=0;i<BASE_BOARD_NB_ELEMENTS; i++) { + if (((bool *)(& hardware->dmi.base_board.features))[i] == true) { + more_printf(" %s\n", base_board_features_strings[i]); + } + } +} + +void show_dmi_system(struct s_hardware *hardware) { + if (hardware->dmi.system.filled==false) { + printf("System module not available\n"); + return; + } + clear_screen(); + 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); +} + +void show_dmi_bios(struct s_hardware *hardware) { + if (hardware->dmi.bios.filled==false) { + printf("Bios module not available\n"); + return; + } + clear_screen(); + more_printf("BIOS\n"); + more_printf(" Vendor : %s\n",hardware->dmi.bios.vendor); + more_printf(" Version : %s\n",hardware->dmi.bios.version); + more_printf(" Release : %s\n",hardware->dmi.bios.release_date); + more_printf(" Bios Revision : %s\n",hardware->dmi.bios.bios_revision); + more_printf(" Firmware Revision : %s\n",hardware->dmi.bios.firmware_revision); + more_printf(" Address : 0x%04X0\n",hardware->dmi.bios.address); + more_printf(" Runtime address : %u %s\n",hardware->dmi.bios.runtime_size,hardware->dmi.bios.runtime_size_unit); + more_printf(" Rom size : %u %s\n",hardware->dmi.bios.rom_size,hardware->dmi.bios.rom_size_unit); + + for (int i=0;i<BIOS_CHAR_NB_ELEMENTS; i++) { + if (((bool *)(& hardware->dmi.bios.characteristics))[i] == true) { + more_printf(" %s\n", bios_charac_strings[i]); + } + } + for (int i=0;i<BIOS_CHAR_X1_NB_ELEMENTS; i++) { + if (((bool *)(& hardware->dmi.bios.characteristics_x1))[i] == true) { + more_printf(" %s\n", bios_charac_x1_strings[i]); + } + } + + for (int i=0;i<BIOS_CHAR_X2_NB_ELEMENTS; i++) { + if (((bool *)(& hardware->dmi.bios.characteristics_x2))[i] == true) { + more_printf(" %s\n", bios_charac_x2_strings[i]); + } + } + +} + +void show_dmi_chassis(struct s_hardware *hardware) { + if (hardware->dmi.chassis.filled==false) { + printf("Chassis module not available\n"); + return; + } + clear_screen(); + more_printf("Chassis\n"); + more_printf(" Manufacturer : %s\n",hardware->dmi.chassis.manufacturer); + 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); + more_printf(" Serial : %s\n",hardware->dmi.chassis.serial); + more_printf(" Asset Tag : %s\n",hardware->dmi.chassis.asset_tag); + more_printf(" Boot up state : %s\n",hardware->dmi.chassis.boot_up_state); + more_printf(" Power supply state : %s\n",hardware->dmi.chassis.power_supply_state); + more_printf(" Thermal state : %s\n",hardware->dmi.chassis.thermal_state); + more_printf(" Security Status : %s\n",hardware->dmi.chassis.security_status); + more_printf(" OEM Information : %s\n",hardware->dmi.chassis.oem_information); + more_printf(" Height : %u\n",hardware->dmi.chassis.height); + more_printf(" NB Power Cords : %u\n",hardware->dmi.chassis.nb_power_cords); +} + +void show_dmi_battery(struct s_hardware *hardware) { + if (hardware->dmi.battery.filled==false) { + printf("Battery module not available\n"); + return; + } + clear_screen(); + more_printf("Battery \n"); + more_printf(" Vendor : %s\n",hardware->dmi.battery.manufacturer); + more_printf(" Manufacture Date : %s\n",hardware->dmi.battery.manufacture_date); + 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); + more_printf(" Design Capacity : %s\n",hardware->dmi.battery.design_capacity); + more_printf(" Design Voltage : %s\n",hardware->dmi.battery.design_voltage); + more_printf(" SBDS : %s\n",hardware->dmi.battery.sbds); + more_printf(" SBDS Manuf. Date : %s\n",hardware->dmi.battery.sbds_manufacture_date); + more_printf(" SBDS Chemistry : %s\n",hardware->dmi.battery.sbds_chemistry); + more_printf(" Maximum Error : %s\n",hardware->dmi.battery.maximum_error); + more_printf(" OEM Info : %s\n",hardware->dmi.battery.oem_info); +} + +void show_dmi_cpu(struct s_hardware *hardware) { + if (hardware->dmi.processor.filled==false) { + printf("Processor module not available\n"); + return; + } + clear_screen(); + more_printf("CPU\n"); + more_printf(" Socket Designation : %s\n",hardware->dmi.processor.socket_designation); + more_printf(" Type : %s\n",hardware->dmi.processor.type); + more_printf(" Family : %s\n",hardware->dmi.processor.family); + more_printf(" Manufacturer : %s\n",hardware->dmi.processor.manufacturer); + more_printf(" Version : %s\n",hardware->dmi.processor.version); + more_printf(" External Clock : %u\n",hardware->dmi.processor.external_clock); + more_printf(" Max Speed : %u\n",hardware->dmi.processor.max_speed); + more_printf(" Current Speed : %u\n",hardware->dmi.processor.current_speed); + more_printf(" Cpu Type : %u\n",hardware->dmi.processor.signature.type); + more_printf(" Cpu Family : %u\n",hardware->dmi.processor.signature.family); + more_printf(" Cpu Model : %u\n",hardware->dmi.processor.signature.model); + more_printf(" Cpu Stepping : %u\n",hardware->dmi.processor.signature.stepping); + more_printf(" Cpu Minor Stepping : %u\n",hardware->dmi.processor.signature.minor_stepping); +// more_printf(" Voltage : %f\n",hardware->dmi.processor.voltage); + more_printf(" Status : %s\n",hardware->dmi.processor.status); + more_printf(" Upgrade : %s\n",hardware->dmi.processor.upgrade); + more_printf(" Cache L1 Handle : %s\n",hardware->dmi.processor.cache1); + more_printf(" Cache L2 Handle : %s\n",hardware->dmi.processor.cache2); + more_printf(" Cache L3 Handle : %s\n",hardware->dmi.processor.cache3); + more_printf(" Serial : %s\n",hardware->dmi.processor.serial); + more_printf(" Part Number : %s\n",hardware->dmi.processor.part_number); + more_printf(" ID : %s\n",hardware->dmi.processor.id); + for (int i=0;i<PROCESSOR_FLAGS_ELEMENTS; i++) { + if (((bool *)(& hardware->dmi.processor.cpu_flags))[i] == true) { + more_printf(" %s\n", cpu_flags_strings[i]); + } + } + +} + +void show_dmi_memory_modules(struct s_hardware *hardware, bool clear, bool show_free_banks) { + char bank_number[10]; + char available_dmi_commands[1024]; + memset(available_dmi_commands,0,sizeof(available_dmi_commands)); + + if (hardware->dmi.memory_count <=0) { + printf("No memory module found\n"); + return; + } + + if (clear) clear_screen(); + more_printf("Memory Banks\n"); + for (int i=0;i<hardware->dmi.memory_count;i++) { + if (hardware->dmi.memory[i].filled==true) { + /* When discovering the first item, let's clear the screen */ + strncat(available_dmi_commands,CLI_DMI_MEMORY_BANK,sizeof(CLI_DMI_MEMORY_BANK)-1); + memset(bank_number,0,sizeof(bank_number)); + snprintf(bank_number,sizeof(bank_number),"%d ",i); + strncat(available_dmi_commands,bank_number,sizeof(bank_number)); + if (show_free_banks==false) { + if (strncmp(hardware->dmi.memory[i].size,"Free",4)) + printf(" bank %02d : %s %s@%s\n",i,hardware->dmi.memory[i].size, hardware->dmi.memory[i].type, hardware->dmi.memory[i].speed); + } else { + printf(" bank %02d : %s %s@%s\n",i,hardware->dmi.memory[i].size, hardware->dmi.memory[i].type, hardware->dmi.memory[i].speed); + } + } + } + //printf("Type 'show bank<bank_number>' for more details.\n"); +} + +void show_dmi_memory_bank(struct s_hardware *hardware, const char *item) { + long bank = strtol(item,(char **) NULL,10); + if (errno == ERANGE) { + 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); + return; + } + + if (hardware->dmi.memory[bank].filled==false) { + printf("Bank %d doesn't contain any information\n",bank); + return; + } + printf("Memory Bank %d\n",bank); + more_printf(" Form Factor : %s\n",hardware->dmi.memory[bank].form_factor); + more_printf(" Type : %s\n",hardware->dmi.memory[bank].type); + more_printf(" Type Detail : %s\n",hardware->dmi.memory[bank].type_detail); + 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); + more_printf(" Device Loc. : %s\n",hardware->dmi.memory[bank].device_locator); + more_printf(" Bank Locator : %s\n",hardware->dmi.memory[bank].bank_locator); + more_printf(" Total Width : %s\n",hardware->dmi.memory[bank].total_width); + more_printf(" Data Width : %s\n",hardware->dmi.memory[bank].data_width); + more_printf(" Error : %s\n",hardware->dmi.memory[bank].error); + more_printf(" Vendor : %s\n",hardware->dmi.memory[bank].manufacturer); + more_printf(" Serial : %s\n",hardware->dmi.memory[bank].serial); + more_printf(" Asset Tag : %s\n",hardware->dmi.memory[bank].asset_tag); + more_printf(" Part Number : %s\n",hardware->dmi.memory[bank].part_number); +} diff --git a/com32/hdt/hdt-cli-kernel.c b/com32/hdt/hdt-cli-kernel.c new file mode 100644 index 00000000..b5c453f1 --- /dev/null +++ b/com32/hdt/hdt-cli-kernel.c @@ -0,0 +1,147 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- +*/ + +#include "hdt-cli.h" +#include "hdt-common.h" +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> + +void main_show_kernel(struct s_hardware *hardware,struct s_cli_mode *cli_mode) { + char buffer[1024]; + struct pci_device *pci_device; + bool found=false; + char kernel_modules [LINUX_KERNEL_MODULE_SIZE*MAX_KERNEL_MODULES_PER_PCI_DEVICE]; + + memset(buffer,0,sizeof(buffer)); + + detect_pci(hardware); + more_printf("Kernel modules\n"); + +// more_printf(" PCI device no: %d \n", p->pci_device_pos); + + if (hardware->modules_pcimap_return_code == -ENOMODULESPCIMAP) { + more_printf(" modules.pcimap is missing\n"); + return; + } + + /* For every detected pci device, compute its submenu */ + for_each_pci_func(pci_device, hardware->pci_domain) { + memset(kernel_modules,0,sizeof kernel_modules); + + for (int kmod=0; kmod<pci_device->dev_info->linux_kernel_module_count;kmod++) { + if (kmod>0) { + strncat(kernel_modules," | ",3); + } + strncat(kernel_modules, pci_device->dev_info->linux_kernel_module[kmod],LINUX_KERNEL_MODULE_SIZE-1); + } + + if ((pci_device->dev_info->linux_kernel_module_count>0) && (!strstr(buffer,kernel_modules))) { + found=true; + if (pci_device->dev_info->linux_kernel_module_count>1) strncat(buffer,"(",1); + strncat(buffer, kernel_modules, sizeof(kernel_modules)); + if (pci_device->dev_info->linux_kernel_module_count>1) strncat(buffer,")",1); + strncat(buffer," # ", 3); + } + + } + if (found ==true) { + strncat(buffer,"\n",1); + more_printf(buffer); + } +} + +void show_kernel_modules(struct s_hardware *hardware) { + int i=1; + struct pci_device *pci_device; + char kernel_modules [LINUX_KERNEL_MODULE_SIZE*MAX_KERNEL_MODULES_PER_PCI_DEVICE]; + bool nopciids=false; + bool nomodulespcimap=false; + char first_line[81]; + char second_line[81]; + char modules[MAX_PCI_CLASSES][256]; + char category_name[MAX_PCI_CLASSES][256]; + + detect_pci(hardware); + memset(&modules,0,sizeof(modules)); + + if (hardware->pci_ids_return_code == -ENOPCIIDS) { + nopciids=true; + more_printf(" Missing pci.ids, we can't compute the list\n"); + return; + } + + if (hardware->modules_pcimap_return_code == -ENOMODULESPCIMAP) { + nomodulespcimap=true; + more_printf(" Missing modules.pcimap, we can't compute the list\n"); + return; + } + + clear_screen(); + + for_each_pci_func(pci_device, hardware->pci_domain) { + memset(kernel_modules,0,sizeof kernel_modules); + + for (int kmod=0; kmod<pci_device->dev_info->linux_kernel_module_count;kmod++) { + strncat(kernel_modules, pci_device->dev_info->linux_kernel_module[kmod],LINUX_KERNEL_MODULE_SIZE-1); + strncat(kernel_modules," ",1); + } + + if ((pci_device->dev_info->linux_kernel_module_count>0) && (!strstr(modules[pci_device->class[2]],kernel_modules))) { + strncat(modules[pci_device->class[2]], kernel_modules, sizeof(kernel_modules)); + snprintf(category_name[pci_device->class[2]], sizeof(category_name[pci_device->class[2]]),"%s",pci_device->dev_info->category_name); + } + } + /* print the found items */ + for (int i=0; i<MAX_PCI_CLASSES;i++) { + if (strlen(category_name[i])>1) { + more_printf("%s : %s\n",category_name[i], modules[i]); + } + } +} + +void show_kernel_help() { + more_printf("Show supports the following commands : %s\n",CLI_SHOW_LIST); +} + +void kernel_show(char *item, struct s_hardware *hardware) { + if ( !strncmp(item, CLI_SHOW_LIST, sizeof(CLI_SHOW_LIST) - 1) ) { + show_kernel_modules(hardware); + return; + } + show_kernel_help(); +} + +void handle_kernel_commands(char *cli_line, struct s_cli_mode *cli_mode, struct s_hardware *hardware) { + if ( !strncmp(cli_line, CLI_SHOW, sizeof(CLI_SHOW) - 1) ) { + kernel_show(strstr(cli_line,"show")+ sizeof(CLI_SHOW), hardware); + return; + } +} + diff --git a/com32/hdt/hdt-cli-pci.c b/com32/hdt/hdt-cli-pci.c new file mode 100644 index 00000000..554c2ce5 --- /dev/null +++ b/com32/hdt/hdt-cli-pci.c @@ -0,0 +1,241 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- +*/ + +#include "hdt-cli.h" +#include "hdt-common.h" +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +void show_pci_device(struct s_hardware *hardware, const char *item) { + int i=0; + struct pci_device *pci_device=NULL, *temp_pci_device; + long pcidev = strtol(item,(char **) NULL,10); + bool nopciids=false; + bool nomodulespcimap=false; + char kernel_modules [LINUX_KERNEL_MODULE_SIZE*MAX_KERNEL_MODULES_PER_PCI_DEVICE]; + int bus=0,slot=0,func=0; + + if (errno == ERANGE) { + 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); + return; + } + + if (hardware->pci_ids_return_code == -ENOPCIIDS) { + nopciids=true; + } + + if (hardware->modules_pcimap_return_code == -ENOMODULESPCIMAP) { + nomodulespcimap=true; + } + + for_each_pci_func(temp_pci_device, hardware->pci_domain) { + i++; + if (i==pcidev) { + bus=__pci_bus; + slot=__pci_slot; + func=__pci_func; + pci_device=temp_pci_device; + } + } + + if (pci_device == NULL) { + printf("We were enabled to find PCI device %d\n",pcidev); + return; + } + + memset(kernel_modules,0,sizeof kernel_modules); + for (int kmod=0; kmod<pci_device->dev_info->linux_kernel_module_count;kmod++) { + if (kmod>0) { + strncat(kernel_modules," | ",3); + } + strncat(kernel_modules, pci_device->dev_info->linux_kernel_module[kmod],LINUX_KERNEL_MODULE_SIZE-1); + } + if (pci_device->dev_info->linux_kernel_module_count==0) strlcpy(kernel_modules,"unknown",7); + + clear_screen(); + printf("PCI Device %d\n",pcidev); + + if (nopciids == false) { + more_printf("Vendor Name : %s\n", pci_device->dev_info->vendor_name); + more_printf("Product Name : %s\n", pci_device->dev_info->product_name); + more_printf("Class Name : %s\n", pci_device->dev_info->class_name); + } + + if (nomodulespcimap == false) { + more_printf("Kernel module : %s\n", kernel_modules); + } + + 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]); + more_printf("Revision : %02x\n",pci_device->revision); + 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) { + more_printf("Mac Address : %s\n",hardware->pxe.mac_addr); + if ((hardware->pxe.pci_device != NULL) && (hardware->pxe.pci_device == pci_device)) + more_printf("PXE : Current boot device\n",func); + } +} + +void show_pci_devices(struct s_hardware *hardware) { + int i=1; + struct pci_device *pci_device; + char kernel_modules [LINUX_KERNEL_MODULE_SIZE*MAX_KERNEL_MODULES_PER_PCI_DEVICE]; + bool nopciids=false; + bool nomodulespcimap=false; + char first_line[81]; + char second_line[81]; + + clear_screen(); + more_printf("%d PCI devices detected\n",hardware->nb_pci_devices); + + if (hardware->pci_ids_return_code == -ENOPCIIDS) { + nopciids=true; + } + + if (hardware->modules_pcimap_return_code == -ENOMODULESPCIMAP) { + nomodulespcimap=true; + } + + /* For every detected pci device, compute its submenu */ + for_each_pci_func(pci_device, hardware->pci_domain) { + memset(kernel_modules,0,sizeof kernel_modules); + for (int kmod=0; kmod<pci_device->dev_info->linux_kernel_module_count;kmod++) { + if (kmod>0) { + strncat(kernel_modules," | ",3); + } + strncat(kernel_modules, pci_device->dev_info->linux_kernel_module[kmod],LINUX_KERNEL_MODULE_SIZE-1); + } + if (pci_device->dev_info->linux_kernel_module_count==0) strlcpy(kernel_modules,"unknown",7); + + if (nopciids == false) { + snprintf(first_line,sizeof(first_line),"%02d: %s %s \n", + i,pci_device->dev_info->vendor_name, + pci_device->dev_info->product_name); + if (nomodulespcimap == false) + snprintf(second_line,sizeof(second_line)," # %-25s # Kmod: %s\n", pci_device->dev_info->class_name, kernel_modules); + else + snprintf(second_line,sizeof(second_line)," # %-25s # ID:%04x:%04x[%04x:%04x]\n", + pci_device->dev_info->class_name, + pci_device->vendor, pci_device->product, + pci_device->sub_vendor, pci_device->sub_product); + + more_printf(first_line); + more_printf(second_line); + more_printf("\n"); + } else if (nopciids == true) { + if (nomodulespcimap == true) { + more_printf("%02d: %04x:%04x [%04x:%04x] \n", + i, pci_device->vendor, pci_device->product, + pci_device->sub_vendor, pci_device->sub_product,kernel_modules); + } + else { + more_printf("%02d: %04x:%04x [%04x:%04x] Kmod:%s\n", + i, + pci_device->vendor, pci_device->product, + pci_device->sub_vendor, pci_device->sub_product,kernel_modules, + pci_device->sub_product,kernel_modules); + } + } + i++; + } + +} +void show_pci_help() { + more_printf("Show supports the following commands : \n"); + more_printf(" %s\n",CLI_SHOW_LIST); + more_printf(" %s <device_number>\n",CLI_PCI_DEVICE); +} + +void pci_show(char *item, struct s_hardware *hardware) { + if ( !strncmp(item, CLI_SHOW_LIST, sizeof(CLI_SHOW_LIST) - 1) ) { + show_pci_devices(hardware); + return; + } + if ( !strncmp(item, CLI_PCI_DEVICE, sizeof(CLI_PCI_DEVICE) - 1) ) { + show_pci_device(hardware,item+ sizeof(CLI_PCI_DEVICE)-1); + return; + } + show_pci_help(); +} + +void handle_pci_commands(char *cli_line, struct s_cli_mode *cli_mode, struct s_hardware *hardware) { + if ( !strncmp(cli_line, CLI_SHOW, sizeof(CLI_SHOW) - 1) ) { + pci_show(strstr(cli_line,"show")+ sizeof(CLI_SHOW), hardware); + return; + } +} + + +void cli_detect_pci(struct s_hardware *hardware) { + bool error=false; + if (hardware->pci_detection==false) { + detect_pci(hardware); + if (hardware->pci_ids_return_code == -ENOPCIIDS) { + more_printf("The pci.ids file is missing, device names can't be computed.\n"); + more_printf("Please put one in same dir as hdt\n"); + error=true; + } + if (hardware->modules_pcimap_return_code == -ENOMODULESPCIMAP) { + more_printf("The modules.pcimap file is missing, device names can't be computed.\n"); + more_printf("Please put one in same dir as hdt\n"); + error=true; + } + if (error == true) { + char tempbuf[10];\ + printf("Press enter to continue\n");\ + fgets(tempbuf, sizeof(tempbuf), stdin);\ + } + } +} + +void main_show_pci(struct s_hardware *hardware) { + int i=1; + char kernel_modules [LINUX_KERNEL_MODULE_SIZE*MAX_KERNEL_MODULES_PER_PCI_DEVICE]; + struct pci_device *pci_device; + bool nopciids=false; + bool nomodulespcimap=false; + char first_line[81]; + char second_line[81]; + char third_line[81]; + cli_detect_pci(hardware); + + more_printf("PCI\n"); + more_printf(" NB Devices : %d\n",hardware->nb_pci_devices); + +} diff --git a/com32/hdt/hdt-cli-pxe.c b/com32/hdt/hdt-cli-pxe.c new file mode 100644 index 00000000..2ad6981a --- /dev/null +++ b/com32/hdt/hdt-cli-pxe.c @@ -0,0 +1,90 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- +*/ + +#include "hdt-cli.h" +#include "hdt-common.h" +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <syslinux/pxe.h> +#include <syslinux/config.h> + +void main_show_pxe(struct s_hardware *hardware,struct s_cli_mode *cli_mode) { + char buffer[81]; + memset(buffer,0,sizeof(81)); + if (hardware->sv->filesystem != SYSLINUX_FS_PXELINUX) { + more_printf("You are not currently using PXELINUX\n"); + return; + } + + detect_pxe(hardware); + more_printf("PXE\n"); + if (hardware->is_pxe_valid==false) { + more_printf(" No valid PXE ROM found\n"); + return; + } + + struct s_pxe *p = &hardware->pxe; + more_printf(" PCI device no: %d \n", p->pci_device_pos); + + if (hardware->pci_ids_return_code == -ENOPCIIDS) { + snprintf(buffer,sizeof(buffer)," PCI ID : %04x:%04x[%04x:%04X] rev(%02x)\n", + p->vendor_id, p->product_id, p->subvendor_id, p->subproduct_id, + p->rev); + snprintf(buffer,sizeof(buffer)," PCI Bus pos. : %02x:%02x.%02x\n", + p->pci_bus,p->pci_dev, p->pci_func); + more_printf(buffer); + } else { + snprintf(buffer,sizeof(buffer)," Manufacturer : %s \n", p->pci_device->dev_info->vendor_name); + more_printf(buffer); + snprintf(buffer,sizeof(buffer)," Product : %s \n", p->pci_device->dev_info->product_name); + more_printf(buffer); + } + 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); +} + +void show_pxe_help() { + more_printf("Show supports the following commands : %s\n",CLI_SHOW_LIST); +} + +void pxe_show(char *item, struct s_hardware *hardware) { + if ( !strncmp(item, CLI_SHOW_LIST, sizeof(CLI_SHOW_LIST) - 1) ) { + main_show_pxe(hardware,NULL); + return; + } + show_pxe_help(); +} + +void handle_pxe_commands(char *cli_line, struct s_cli_mode *cli_mode, struct s_hardware *hardware) { + if ( !strncmp(cli_line, CLI_SHOW, sizeof(CLI_SHOW) - 1) ) { + pxe_show(strstr(cli_line,"show")+ sizeof(CLI_SHOW), hardware); + return; + } +} + diff --git a/com32/hdt/hdt-cli-syslinux.c b/com32/hdt/hdt-cli-syslinux.c new file mode 100644 index 00000000..1a0c1e0e --- /dev/null +++ b/com32/hdt/hdt-cli-syslinux.c @@ -0,0 +1,65 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- +*/ + +#include "hdt-cli.h" +#include "hdt-common.h" +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <syslinux/pxe.h> +#include <syslinux/config.h> + +void main_show_syslinux(struct s_hardware *hardware,struct s_cli_mode *cli_mode) { + 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); +} + +void show_syslinux_help() { + more_printf("Show supports the following commands : %s\n",CLI_SHOW_LIST); +} + +void syslinux_show(char *item, struct s_hardware *hardware) { + if ( !strncmp(item, CLI_SHOW_LIST, sizeof(CLI_SHOW_LIST) - 1) ) { + main_show_syslinux(hardware,NULL); + return; + } + show_syslinux_help(); +} + +void handle_syslinux_commands(char *cli_line, struct s_cli_mode *cli_mode, struct s_hardware *hardware) { + if ( !strncmp(cli_line, CLI_SHOW, sizeof(CLI_SHOW) - 1) ) { + syslinux_show(strstr(cli_line,"show")+ sizeof(CLI_SHOW), hardware); + return; + } +} + diff --git a/com32/hdt/hdt-cli.c b/com32/hdt/hdt-cli.c new file mode 100644 index 00000000..3f714858 --- /dev/null +++ b/com32/hdt/hdt-cli.c @@ -0,0 +1,254 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- +*/ + +#include "hdt-cli.h" +#include "hdt-common.h" +#include <stdlib.h> +#include <string.h> +#include <syslinux/config.h> + +void set_mode(struct s_cli_mode *cli_mode, cli_mode_t mode, struct s_hardware *hardware) { + switch (mode) { + case EXIT_MODE: + cli_mode->mode=mode; + snprintf(cli_mode->prompt, sizeof(cli_mode->prompt), "%s> ", CLI_EXIT); + break; + + case HDT_MODE: + cli_mode->mode=mode; + snprintf(cli_mode->prompt, sizeof(cli_mode->prompt), "%s> ", CLI_HDT); + break; + + case PXE_MODE: + if (hardware->sv->filesystem != SYSLINUX_FS_PXELINUX) { + more_printf("You are not currently using PXELINUX\n"); + break; + } + cli_mode->mode=mode; + snprintf(cli_mode->prompt, sizeof(cli_mode->prompt), "%s> ", CLI_PXE); + break; + + case KERNEL_MODE: + detect_pci(hardware); + cli_mode->mode=mode; + snprintf(cli_mode->prompt, sizeof(cli_mode->prompt), "%s> ", CLI_KERNEL); + break; + + case SYSLINUX_MODE: + cli_mode->mode=mode; + snprintf(cli_mode->prompt, sizeof(cli_mode->prompt), "%s> ", CLI_SYSLINUX); + break; + + case PCI_MODE: + cli_mode->mode=mode; + snprintf(cli_mode->prompt,sizeof(cli_mode->prompt),"%s> ", CLI_PCI); + if (!hardware->pci_detection) + cli_detect_pci(hardware); + break; + + case CPU_MODE: + cli_mode->mode=mode; + snprintf(cli_mode->prompt,sizeof(cli_mode->prompt),"%s> ", CLI_CPU); + if (!hardware->dmi_detection) + detect_dmi(hardware); + if (!hardware->cpu_detection) + cpu_detect(hardware); + break; + + case DMI_MODE: + detect_dmi(hardware); + if (!hardware->is_dmi_valid) { + printf("No valid DMI table found, exiting.\n"); + break; + } + cli_mode->mode=mode; + snprintf(cli_mode->prompt,sizeof(cli_mode->prompt),"%s> ",CLI_DMI); + break; + } +} + +void handle_hdt_commands(char *cli_line, struct s_cli_mode *cli_mode, struct s_hardware *hardware) { + /* hdt cli mode specific commands */ + if ( !strncmp(cli_line, CLI_SHOW, sizeof(CLI_SHOW) - 1) ) { + main_show(strstr(cli_line,"show")+ sizeof (CLI_SHOW), hardware,cli_mode); + return; + } +} + +/* Code that manage the cli mode */ +void start_cli_mode(struct s_hardware *hardware, int argc, char *argv[]) { + char cli_line[256]; + struct s_cli_mode cli_mode; + + set_mode(&cli_mode,HDT_MODE,hardware); + + printf("Entering CLI mode\n"); + + for (;;) { + memset(cli_line,0,sizeof cli_line); + printf("%s",cli_mode.prompt); + + fgets(cli_line, sizeof cli_line, stdin); + cli_line[strlen(cli_line)-1]='\0'; + /* We use sizeof BLAH - 1 to remove the last \0 */ + + if ( !strncmp(cli_line, CLI_EXIT, sizeof(CLI_EXIT) - 1) ) { + int mode=do_exit(&cli_mode); + if (mode == EXIT_MODE) + return; + set_mode(&cli_mode,mode,hardware); + continue; + } + + if ( !strncmp(cli_line, CLI_HELP, sizeof(CLI_HELP) - 1) ) { + show_cli_help(&cli_mode); + continue; + } + + if ( !strncmp(cli_line, CLI_PCI, sizeof(CLI_PCI) - 1) ) { + set_mode(&cli_mode,PCI_MODE,hardware); + continue; + } + if ( !strncmp(cli_line, CLI_CLEAR, sizeof(CLI_CLEAR) - 1) ) { + clear_screen(); + continue; + } + if ( !strncmp(cli_line, CLI_CPU, sizeof(CLI_CPU) - 1) ) { + set_mode(&cli_mode,CPU_MODE,hardware); + continue; + } + if ( !strncmp(cli_line, CLI_DMI, sizeof(CLI_DMI) - 1) ) { + set_mode(&cli_mode,DMI_MODE,hardware); + continue; + } + if ( !strncmp(cli_line, CLI_PXE, sizeof(CLI_PXE) - 1) ) { + set_mode(&cli_mode,PXE_MODE,hardware); + continue; + } + if ( !strncmp(cli_line, CLI_KERNEL, sizeof(CLI_KERNEL) - 1) ) { + set_mode(&cli_mode,KERNEL_MODE,hardware); + continue; + } + if ( !strncmp(cli_line, CLI_SYSLINUX, sizeof(CLI_SYSLINUX) - 1) ) { + set_mode(&cli_mode,SYSLINUX_MODE,hardware); + continue; + } + /* All commands before that line are common for all cli modes + * the following will be specific for every mode */ + switch(cli_mode.mode) { + case DMI_MODE: handle_dmi_commands(cli_line,&cli_mode, hardware); break; + case PCI_MODE: handle_pci_commands(cli_line,&cli_mode, hardware); break; + case HDT_MODE: handle_hdt_commands(cli_line,&cli_mode, hardware); break; + case CPU_MODE: handle_cpu_commands(cli_line,&cli_mode, hardware); break; + case PXE_MODE: handle_pxe_commands(cli_line,&cli_mode, hardware); break; + case SYSLINUX_MODE: handle_syslinux_commands(cli_line,&cli_mode, hardware); break; + case KERNEL_MODE: handle_kernel_commands(cli_line,&cli_mode, hardware); break; + case EXIT_MODE: break; /* should not happend */ + } + } +} + +int do_exit(struct s_cli_mode *cli_mode) { + switch (cli_mode->mode) { + case HDT_MODE: return EXIT_MODE; + case KERNEL_MODE: + case PXE_MODE: + case SYSLINUX_MODE: + case PCI_MODE: + case DMI_MODE: + case CPU_MODE: return HDT_MODE; + case EXIT_MODE: return EXIT_MODE; /* should not happend */ + } +return HDT_MODE; +} + +void show_cli_help(struct s_cli_mode *cli_mode) { +switch (cli_mode->mode) { + case HDT_MODE: + printf("Available commands are : %s %s %s %s %s %s %s %s %s %s\n", + CLI_CLEAR, CLI_EXIT,CLI_HELP,CLI_SHOW, CLI_PCI, + CLI_DMI, CLI_PXE, CLI_KERNEL, CLI_CPU, CLI_SYSLINUX); + break; + case SYSLINUX_MODE: + case KERNEL_MODE: + case PXE_MODE: + case CPU_MODE: + case PCI_MODE: + case DMI_MODE: + printf("Available commands are : %s %s %s %s\n", + CLI_CLEAR, CLI_EXIT, CLI_HELP, CLI_SHOW); + break; + case EXIT_MODE: /* Should not happend*/ + break; +} +} + +void main_show_summary(struct s_hardware *hardware, struct s_cli_mode *cli_mode) { + detect_pci(hardware); /* pxe is detected in the pci */ + detect_dmi(hardware); + cpu_detect(hardware); + clear_screen(); + main_show_cpu(hardware,cli_mode); + if (hardware->is_dmi_valid) { + 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(" Serial : %s\n",hardware->dmi.system.serial); + more_printf("Bios\n"); + more_printf(" Version : %s\n",hardware->dmi.bios.version); + more_printf(" Release : %s\n",hardware->dmi.bios.release_date); + show_dmi_memory_modules(hardware,false,false); + } + main_show_pci(hardware); + if (hardware->is_pxe_valid) + main_show_pxe(hardware,cli_mode); + main_show_kernel(hardware,cli_mode); +} + +void show_main_help(struct s_hardware *hardware) { + more_printf("Show supports the following commands : \n"); + more_printf(" %s\n",CLI_SUMMARY); + more_printf(" %s\n",CLI_PCI); + more_printf(" %s\n",CLI_DMI); + more_printf(" %s\n",CLI_CPU); + more_printf(" %s\n",CLI_KERNEL); + more_printf(" %s\n",CLI_SYSLINUX); + if (hardware->sv->filesystem == SYSLINUX_FS_PXELINUX) + more_printf(" %s\n",CLI_PXE); +} + +void main_show(char *item, struct s_hardware *hardware, struct s_cli_mode *cli_mode) { + if (!strncmp(item,CLI_SUMMARY, sizeof (CLI_SUMMARY))) { main_show_summary(hardware,cli_mode); return; } + if (!strncmp(item,CLI_PCI, sizeof (CLI_PCI))) { main_show_pci(hardware); return; } + if (!strncmp(item,CLI_DMI, sizeof (CLI_DMI))) { main_show_dmi(hardware,cli_mode); return; } + if (!strncmp(item,CLI_CPU, sizeof (CLI_CPU))) { main_show_cpu(hardware,cli_mode); return; } + if (!strncmp(item,CLI_PXE, sizeof (CLI_PXE))) { main_show_pxe(hardware,cli_mode); return; } + if (!strncmp(item,CLI_SYSLINUX, sizeof (CLI_SYSLINUX))) { main_show_syslinux(hardware,cli_mode); return; } + if (!strncmp(item,CLI_KERNEL, sizeof (CLI_KERNEL))) { main_show_kernel(hardware,cli_mode); return; } + show_main_help(hardware); +} diff --git a/com32/hdt/hdt-cli.h b/com32/hdt/hdt-cli.h new file mode 100644 index 00000000..92791c49 --- /dev/null +++ b/com32/hdt/hdt-cli.h @@ -0,0 +1,116 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- +*/ + +#ifndef DEFINE_HDT_CLI_H +#define DEFINE_HDT_CLI_H +#include <stdio.h> +#include "hdt-common.h" + +#define CLI_CLEAR "clear" +#define CLI_EXIT "exit" +#define CLI_HELP "help" +#define CLI_SHOW "show" +#define CLI_HDT "hdt" +#define CLI_PCI "pci" +#define CLI_PXE "pxe" +#define CLI_KERNEL "kernel" +#define CLI_SYSLINUX "syslinux" +#define CLI_SUMMARY "summary" +#define CLI_COMMANDS "commands" +#define CLI_DMI "dmi" +#define CLI_CPU "cpu" +#define CLI_SHOW_LIST "list" + +typedef enum { + EXIT_MODE, + HDT_MODE, + PCI_MODE, + DMI_MODE, + CPU_MODE, + PXE_MODE, + KERNEL_MODE, + SYSLINUX_MODE, +} cli_mode_t; + +struct s_cli_mode { + cli_mode_t mode; + char prompt[32]; +}; + + +void show_cli_help(struct s_cli_mode *cli_mode); +void start_cli_mode(struct s_hardware *hardware, int argc, char *argv[]); +void main_show(char *item, struct s_hardware *hardware, struct s_cli_mode *cli_mode); +int do_exit(struct s_cli_mode *cli_mode); + +//DMI STUFF +#define CLI_DMI_BASE_BOARD "base_board" +#define CLI_DMI_BATTERY "battery" +#define CLI_DMI_BIOS "bios" +#define CLI_DMI_CHASSIS "chassis" +#define CLI_DMI_MEMORY "memory" +#define CLI_DMI_MEMORY_BANK "bank" +#define CLI_DMI_PROCESSOR "cpu" +#define CLI_DMI_SYSTEM "system" + +void main_show_dmi(struct s_hardware *hardware,struct s_cli_mode *cli_mode); +void handle_dmi_commands(char *cli_line, struct s_cli_mode *cli_mode, struct s_hardware *hardware); +void show_dmi_base_board(struct s_hardware *hardware); +void show_dmi_system(struct s_hardware *hardware); +void show_dmi_bios(struct s_hardware *hardware); +void show_dmi_chassis(struct s_hardware *hardware); +void show_dmi_cpu(struct s_hardware *hardware); +void show_dmi_modules(struct s_hardware *hardware); +void show_dmi_memory_modules(struct s_hardware *hardware,bool clearscreen, bool show_free_banks); +void show_dmi_memory_bank(struct s_hardware *hardware, const char *item); +void show_dmi_battery(struct s_hardware *hardware); + +//PCI STUFF +#define CLI_PCI_DEVICE "device" +void main_show_pci(struct s_hardware *hardware); +void handle_pci_commands(char *cli_line, struct s_cli_mode *cli_mode, struct s_hardware *hardware); +void pci_show(char *item, struct s_hardware *hardware); +void cli_detect_pci(struct s_hardware *hardware); + +//CPU STUFF +void main_show_cpu(struct s_hardware *hardware,struct s_cli_mode *cli_mode); +void handle_cpu_commands(char *cli_line, struct s_cli_mode *cli_mode, struct s_hardware *hardware); +void cpu_show(char *item, struct s_hardware *hardware); + +//PXE STUFF +void main_show_pxe(struct s_hardware *hardware,struct s_cli_mode *cli_mode); +void handle_pxe_commands(char *cli_line, struct s_cli_mode *cli_mode, struct s_hardware *hardware); + +//KERNEL STUFF +void main_show_kernel(struct s_hardware *hardware,struct s_cli_mode *cli_mode); +void handle_kernel_commands(char *cli_line, struct s_cli_mode *cli_mode, struct s_hardware *hardware); + +//SYSLINUX STUFF +void main_show_syslinux(struct s_hardware *hardware,struct s_cli_mode *cli_mode); +void handle_syslinux_commands(char *cli_line, struct s_cli_mode *cli_mode, struct s_hardware *hardware); +#endif diff --git a/com32/hdt/hdt-common.c b/com32/hdt/hdt-common.c new file mode 100644 index 00000000..0ff7e86d --- /dev/null +++ b/com32/hdt/hdt-common.c @@ -0,0 +1,253 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- +*/ + +#include "hdt-common.h" +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include "syslinux/config.h" + +void detect_parameters(int argc, char *argv[], struct s_hardware *hardware) { + for (int i = 1; i < argc; i++) { + if (!strncmp(argv[i], "modules=", 8)) { + strncpy(hardware->modules_pcimap_path,argv[i]+8, sizeof(hardware->modules_pcimap_path)); + } else if (!strncmp(argv[i], "pciids=",7 )) { + strncpy(hardware->pciids_path,argv[i]+7, sizeof(hardware->pciids_path)); + } + } +} + +void detect_syslinux(struct s_hardware *hardware) { + hardware->sv = syslinux_version(); + switch(hardware->sv->filesystem) { + case SYSLINUX_FS_SYSLINUX: strlcpy(hardware->syslinux_fs,"SYSlinux",9); break; + case SYSLINUX_FS_PXELINUX: strlcpy(hardware->syslinux_fs,"PXElinux",9); break; + case SYSLINUX_FS_ISOLINUX: strlcpy(hardware->syslinux_fs,"ISOlinux",9); break; + case SYSLINUX_FS_EXTLINUX: strlcpy(hardware->syslinux_fs,"EXTlinux",9); break; + case SYSLINUX_FS_UNKNOWN: + default: strlcpy(hardware->syslinux_fs,"Unknown Bootloader",sizeof hardware->syslinux_fs); break; + } +} + +void init_hardware(struct s_hardware *hardware) { + hardware->pci_ids_return_code=0; + hardware->modules_pcimap_return_code=0; + hardware->cpu_detection=false; + hardware->pci_detection=false; + hardware->disk_detection=false; + hardware->dmi_detection=false; + hardware->pxe_detection=false; + hardware->nb_pci_devices=0; + hardware->is_dmi_valid=false; + hardware->is_pxe_valid=false; + hardware->pci_domain=NULL; + + /* Cleaning structures */ + memset(hardware->disk_info,0,sizeof(hardware->disk_info)); + memset(&hardware->dmi,0,sizeof(s_dmi)); + memset(&hardware->cpu,0,sizeof(s_cpu)); + memset(&hardware->pxe,0,sizeof(struct s_pxe)); + memset(hardware->syslinux_fs,0,sizeof hardware->syslinux_fs); + memset(hardware->pciids_path,0,sizeof hardware->pciids_path); + memset(hardware->modules_pcimap_path,0,sizeof hardware->modules_pcimap_path); + strcat(hardware->pciids_path,"pci.ids"); + strcat(hardware->modules_pcimap_path,"modules.pcimap"); +} + +/* Detecting if a DMI table exist + * if yes, let's parse it */ +int detect_dmi(struct s_hardware *hardware) { + if (hardware->dmi_detection == true) return -1; + hardware->dmi_detection=true; + if (dmi_iterate(&hardware->dmi) == -ENODMITABLE ) { + hardware->is_dmi_valid=false; + return -ENODMITABLE; + } + + parse_dmitable(&hardware->dmi); + hardware->is_dmi_valid=true; + return 0; +} + +/* Try to detects disk from port 0x80 to 0xff*/ +void detect_disks(struct s_hardware *hardware) { + hardware->disk_detection=true; + for (int drive = 0x80; drive < 0xff; drive++) { + if (get_disk_params(drive,hardware->disk_info) != 0) + continue; + struct diskinfo *d=&hardware->disk_info[drive]; + printf(" DISK 0x%X: %s : %s %s: sectors=%d, s/t=%d head=%d : EDD=%s\n",drive,d->aid.model,d->host_bus_type,d->interface_type, d->sectors, d->sectors_per_track,d->heads,d->edd_version); + } +} + +int detect_pxe(struct s_hardware *hardware) { + void *dhcpdata; + + size_t dhcplen; + t_PXENV_UNDI_GET_NIC_TYPE gnt; + + if (hardware->pxe_detection == true) return -1; + hardware->pxe_detection=true; + hardware->is_pxe_valid=false; + memset(&gnt,0, sizeof(t_PXENV_UNDI_GET_NIC_TYPE)); + memset(&hardware->pxe,0, sizeof(struct s_pxe)); + + /* This code can only work if pxelinux is loaded*/ + if (hardware->sv->filesystem != SYSLINUX_FS_PXELINUX) { + return -1; + } + +// printf("PXE: PXElinux detected\n"); + if (!pxe_get_cached_info(PXENV_PACKET_TYPE_DHCP_ACK, &dhcpdata, &dhcplen)) { + pxe_bootp_t *dhcp=&hardware->pxe.dhcpdata; + memcpy(&hardware->pxe.dhcpdata,dhcpdata,sizeof(hardware->pxe.dhcpdata)); + snprintf(hardware->pxe.mac_addr, sizeof(hardware->pxe.mac_addr), "%02x:%02x:%02x:%02x:%02x:%02x", + dhcp->CAddr[0],dhcp->CAddr[1],dhcp->CAddr[2],dhcp->CAddr[3],dhcp->CAddr[4],dhcp->CAddr[5]); + + /* Saving Our IP address in a easy format*/ + hardware->pxe.ip_addr[0]= hardware->pxe.dhcpdata.yip & 0xff; + hardware->pxe.ip_addr[1]= hardware->pxe.dhcpdata.yip >>8 & 0xff; + hardware->pxe.ip_addr[2]= hardware->pxe.dhcpdata.yip >>16 & 0xff; + hardware->pxe.ip_addr[3]= hardware->pxe.dhcpdata.yip >>24 & 0xff; + + if (!pxe_get_nic_type(&gnt)) { + switch(gnt.NicType) { + case PCI_NIC: + hardware->is_pxe_valid=true; + hardware->pxe.vendor_id=gnt.info.pci.Vendor_ID; + hardware->pxe.product_id=gnt.info.pci.Dev_ID; + hardware->pxe.subvendor_id=gnt.info.pci.SubVendor_ID; + hardware->pxe.subproduct_id=gnt.info.pci.SubDevice_ID, + hardware->pxe.rev=gnt.info.pci.Rev; + hardware->pxe.pci_bus= (gnt.info.pci.BusDevFunc >> 8) & 0xff; + hardware->pxe.pci_dev= (gnt.info.pci.BusDevFunc >> 3) & 0x7; + hardware->pxe.pci_func=gnt.info.pci.BusDevFunc & 0x03; + hardware->pxe.base_class=gnt.info.pci.Base_Class; + hardware->pxe.sub_class=gnt.info.pci.Sub_Class; + hardware->pxe.prog_intf=gnt.info.pci.Prog_Intf; + hardware->pxe.nictype=gnt.NicType; + break; + case CardBus_NIC: + hardware->is_pxe_valid=true; + hardware->pxe.vendor_id=gnt.info.cardbus.Vendor_ID; + hardware->pxe.product_id=gnt.info.cardbus.Dev_ID; + hardware->pxe.subvendor_id=gnt.info.cardbus.SubVendor_ID; + hardware->pxe.subproduct_id=gnt.info.cardbus.SubDevice_ID, + hardware->pxe.rev=gnt.info.cardbus.Rev; + hardware->pxe.pci_bus= (gnt.info.cardbus.BusDevFunc >> 8) & 0xff; + hardware->pxe.pci_dev= (gnt.info.cardbus.BusDevFunc >> 3) & 0x7; + hardware->pxe.pci_func=gnt.info.cardbus.BusDevFunc & 0x03; + hardware->pxe.base_class=gnt.info.cardbus.Base_Class; + hardware->pxe.sub_class=gnt.info.cardbus.Sub_Class; + hardware->pxe.prog_intf=gnt.info.cardbus.Prog_Intf; + hardware->pxe.nictype=gnt.NicType; + break; + case PnP_NIC: + default: return -1; break; + } + /* Let's try to find the associated pci device */ + detect_pci(hardware); + hardware->pxe.pci_device=NULL; + hardware->pxe.pci_device_pos=0; + struct pci_device *pci_device; + int pci_number=0; + for_each_pci_func(pci_device, hardware->pci_domain) { + pci_number++; + if ((__pci_bus == hardware->pxe.pci_bus) && + (__pci_slot == hardware->pxe.pci_dev) && + (__pci_func == hardware->pxe.pci_func) && + (pci_device->vendor == hardware->pxe.vendor_id) && + (pci_device->product == hardware->pxe.product_id)) { + hardware->pxe.pci_device=pci_device; + hardware->pxe.pci_device_pos=pci_number; + } + } + } + } + return 0; +} + +void detect_pci(struct s_hardware *hardware) { + if (hardware->pci_detection == true) return; + hardware->pci_detection=true; + + /* Scanning to detect pci buses and devices */ + hardware->pci_domain = pci_scan(); + + hardware->nb_pci_devices=0; + struct pci_device *pci_device; + for_each_pci_func(pci_device, hardware->pci_domain) { + hardware->nb_pci_devices++; + } + + printf("PCI: %d devices detected\n",hardware->nb_pci_devices); + 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"); + /* 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"); + /* Detecting which kernel module should match each device */ + hardware->modules_pcimap_return_code=get_module_name_from_pci_ids(hardware->pci_domain,hardware->modules_pcimap_path); + + /* we try to detect the pxe stuff to populate the PXE: field of pci devices */ + detect_pxe(hardware); +} + +void cpu_detect(struct s_hardware *hardware) { + if (hardware->cpu_detection == true) return; + detect_cpu(&hardware->cpu); + hardware->cpu_detection=true; +} + +/* Find the last instance of a particular command line argument + (which should include the final =; do not use for boolean arguments) */ +char *find_argument(const char **argv, const char *argument) +{ + int la = strlen(argument); + const char **arg; + char *ptr = NULL; + + for (arg = argv; *arg; arg++) { + if (!memcmp(*arg, argument, la)) + ptr = *arg + la; + } + + return ptr; +} + +void clear_screen(void) +{ + fputs("\033e\033%@\033)0\033(B\1#0\033[?25l\033[2J", stdout); + display_line_nb=0; +} + diff --git a/com32/hdt/hdt-common.h b/com32/hdt/hdt-common.h new file mode 100644 index 00000000..1b27b588 --- /dev/null +++ b/com32/hdt/hdt-common.h @@ -0,0 +1,113 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- +*/ + +#ifndef DEFINE_HDT_COMMON_H +#define DEFINE_HDT_COMMON_H +#include <stdio.h> +#include "sys/pci.h" +#include "cpuid.h" +#include "dmi/dmi.h" +#include <syslinux/pxe.h> +#include "hdt-ata.h" + +/* This two values are used for switching for the menu to the CLI mode*/ +#define HDT_SWITCH_TO_CLI "hdt_switch_to_cli" +#define HDT_RETURN_TO_CLI 100 + +extern int display_line_nb; + +#define more_printf(...) do {\ + if (display_line_nb == 23) {\ + char tempbuf[10];\ + printf("Press enter to continue\n");\ + display_line_nb=0;\ + fgets(tempbuf, sizeof(tempbuf), stdin);\ + }\ + printf ( __VA_ARGS__);\ + display_line_nb++; \ +} while (0); + + +struct s_pxe { + uint16_t vendor_id; + uint16_t product_id; + uint16_t subvendor_id; + uint16_t subproduct_id; + uint8_t rev; + uint8_t pci_bus; + uint8_t pci_dev; + uint8_t pci_func; + uint8_t base_class; + uint8_t sub_class; + uint8_t prog_intf; + uint8_t nictype; + char mac_addr[18]; /* The current mac address */ + uint8_t ip_addr[4]; + + pxe_bootp_t dhcpdata; /* The dhcp answer */ + struct pci_device *pci_device; /* The matching pci device */ + uint8_t pci_device_pos; /* It position in our pci sorted list*/ + +}; + +struct s_hardware { + s_dmi dmi; /* DMI table */ + s_cpu cpu; /* CPU information */ + struct pci_domain *pci_domain; /* PCI Devices */ + struct diskinfo disk_info[256]; /* Disk Information*/ + struct s_pxe pxe; + + int pci_ids_return_code; + int modules_pcimap_return_code; + int nb_pci_devices; + bool is_dmi_valid; + bool is_pxe_valid; + + bool dmi_detection; /* Does the dmi stuff have been already detected */ + bool pci_detection; /* Does the pci stuff have been already detected */ + bool cpu_detection; /* Does the cpu stuff have been already detected */ + bool disk_detection; /* Does the disk stuff have been already detected */ + bool pxe_detection; /* Does the pxe stuff have been already detected*/ + + char syslinux_fs[22]; + struct syslinux_version *sv; + char modules_pcimap_path[255]; + char pciids_path[255]; +}; + +char *find_argument(const char **argv, const char *argument); +int detect_dmi(struct s_hardware *hardware); +void detect_disks(struct s_hardware *hardware); +void detect_pci(struct s_hardware *hardware); +void cpu_detect(struct s_hardware *hardware); +int detect_pxe(struct s_hardware *hardware); +void init_hardware(struct s_hardware *hardware); +void clear_screen(void); +void detect_syslinux(struct s_hardware *hardware); +void detect_parameters(int argc, char *argv[], struct s_hardware *hardware); +#endif diff --git a/com32/hdt/hdt-menu-about.c b/com32/hdt/hdt-menu-about.c new file mode 100644 index 00000000..51032402 --- /dev/null +++ b/com32/hdt/hdt-menu-about.c @@ -0,0 +1,64 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- +*/ + +#include "hdt-menu.h" + +/* Computing About menu*/ +void compute_aboutmenu(struct s_my_menu *menu) { + char buffer[SUBMENULEN+1]; + char statbuffer[STATLEN+1]; + + menu->menu = add_menu(" About ",-1); + menu->items_count=0; + + set_menu_pos(SUBMENU_Y,SUBMENU_X); + + 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); + 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); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + 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++; + + printf("MENU: About menu done (%d items)\n",menu->items_count); + +} + diff --git a/com32/hdt/hdt-menu-disk.c b/com32/hdt/hdt-menu-disk.c new file mode 100644 index 00000000..9c96e787 --- /dev/null +++ b/com32/hdt/hdt-menu-disk.c @@ -0,0 +1,148 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- +*/ + +#include "hdt-menu.h" + +/* Compute the disk submenu */ +int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu,struct diskinfo *d,int disk_number) { + char buffer[MENULEN+1]; + char statbuffer[STATLEN+1]; + + /* No need to add no existing devices*/ + if (strlen(d[disk_number].aid.model)<=0) return -1; + + snprintf(buffer,sizeof buffer," Disk <%d> ",nb_sub_disk_menu); + menu[nb_sub_disk_menu].menu = add_menu(buffer,-1); + menu[nb_sub_disk_menu].items_count=0; + + snprintf(buffer,sizeof buffer,"Model : %s",d[disk_number].aid.model); + snprintf(statbuffer,sizeof statbuffer,"Model: %s",d[disk_number].aid.model); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu[nb_sub_disk_menu].items_count++; + + /* Compute device size */ + char previous_unit[3],unit[3]; //GB + int previous_size,size = d[disk_number].sectors/2; // Converting to bytes + strlcpy(unit,"KB",2); + strlcpy(previous_unit,unit,2); + previous_size=size; + if (size>1000) { + size=size/1000; + strlcpy(unit,"MB",2); + if (size>1000) { + previous_size=size; + size=size/1000; + strlcpy(previous_unit,unit,2); + strlcpy(unit,"GB",2); + if (size>1000) { + previous_size=size; + size=size/1000; + strlcpy(previous_unit,unit,2); + strlcpy(unit,"TB",2); + } + } + } + + snprintf(buffer,sizeof buffer,"Size : %d %s (%d %s)",size,unit,previous_size,previous_unit); + snprintf(statbuffer, sizeof statbuffer, "Size: %d %s (%d %s)",size,unit,previous_size,previous_unit); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu[nb_sub_disk_menu].items_count++; + + snprintf(buffer,sizeof buffer,"Firmware Rev.: %s",d[disk_number].aid.fw_rev); + snprintf(statbuffer,sizeof statbuffer,"Firmware Revision: %s",d[disk_number].aid.fw_rev); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu[nb_sub_disk_menu].items_count++; + + snprintf(buffer,sizeof buffer,"Serial Number: %s",d[disk_number].aid.serial_no); + snprintf(statbuffer,sizeof statbuffer,"Serial Number: %s",d[disk_number].aid.serial_no); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu[nb_sub_disk_menu].items_count++; + + snprintf(buffer,sizeof buffer,"Interface : %s",d[disk_number].interface_type); + snprintf(statbuffer,sizeof statbuffer,"Interface: %s",d[disk_number].interface_type); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu[nb_sub_disk_menu].items_count++; + + snprintf(buffer,sizeof buffer,"Host Bus : %s",d[disk_number].host_bus_type); + snprintf(statbuffer,sizeof statbuffer,"Host Bus Type: %s",d[disk_number].host_bus_type); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu[nb_sub_disk_menu].items_count++; + + snprintf(buffer,sizeof buffer, "Sectors : %d",d[disk_number].sectors); + snprintf(statbuffer,sizeof statbuffer, "Sectors: %d",d[disk_number].sectors); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu[nb_sub_disk_menu].items_count++; + + snprintf(buffer,sizeof buffer,"Heads : %d",d[disk_number].heads); + snprintf(statbuffer,sizeof statbuffer,"Heads: %d",d[disk_number].heads); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu[nb_sub_disk_menu].items_count++; + + snprintf(buffer, sizeof buffer,"Cylinders : %d",d[disk_number].cylinders); + snprintf(statbuffer, sizeof statbuffer,"Cylinders: %d",d[disk_number].cylinders); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu[nb_sub_disk_menu].items_count++; + + snprintf(buffer,sizeof buffer, "Sectors/Track: %d",d[disk_number].sectors_per_track); + snprintf(statbuffer,sizeof statbuffer, "Sectors per Track: %d",d[disk_number].sectors_per_track); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu[nb_sub_disk_menu].items_count++; + + snprintf(buffer,sizeof buffer,"Port : 0x%X",disk_number); + snprintf(statbuffer,sizeof statbuffer,"Port: 0x%X",disk_number); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu[nb_sub_disk_menu].items_count++; + + snprintf(buffer,sizeof buffer,"EDD Version : %s",d[disk_number].edd_version); + snprintf(statbuffer,sizeof statbuffer,"EDD Version: %s",d[disk_number].edd_version); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu[nb_sub_disk_menu].items_count++; + + return 0; +} + +/* Compute the Disk Menu*/ +void compute_disks(struct s_hdt_menu *menu, struct diskinfo *disk_info) { + char buffer[MENULEN+1]; + int nb_sub_disk_menu=0; + for (int i=0;i<0xff;i++) { + if (compute_disk_module(&(menu->disk_sub_menu),nb_sub_disk_menu,disk_info,i) == 0) + nb_sub_disk_menu++; + } + + menu->disk_menu.menu = add_menu(" Disks ",-1); + menu->disk_menu.items_count=0; + + for (int i=0;i<nb_sub_disk_menu;i++) { + snprintf(buffer,sizeof buffer," Disk <%d> ",i); + add_item(buffer,"Disk",OPT_SUBMENU,NULL,menu->disk_sub_menu[i].menu); + menu->disk_menu.items_count++; + } + printf("MENU: Disks menu done (%d items)\n",menu->disk_menu.items_count); +} + diff --git a/com32/hdt/hdt-menu-dmi.c b/com32/hdt/hdt-menu-dmi.c new file mode 100644 index 00000000..485f25ec --- /dev/null +++ b/com32/hdt/hdt-menu-dmi.c @@ -0,0 +1,383 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- +*/ + +#include "hdt-menu.h" + +/* Compute System main menu */ +void compute_system(struct s_my_menu *menu,s_dmi *dmi) { + char buffer[SUBMENULEN+1]; + char statbuffer[STATLEN+1]; + + menu->menu = add_menu(" System ",-1); + menu->items_count=0; + set_menu_pos(SUBMENU_Y,SUBMENU_X); + + snprintf(buffer,sizeof buffer,"Vendor : %s",dmi->system.manufacturer); + snprintf(statbuffer,sizeof statbuffer,"Vendor: %s",dmi->system.manufacturer); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Product : %s",dmi->system.product_name); + snprintf(statbuffer,sizeof statbuffer,"Product Name: %s",dmi->system.product_name); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Version : %s",dmi->system.version); + snprintf(statbuffer,sizeof statbuffer,"Version: %s",dmi->system.version); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Serial : %s",dmi->system.serial); + snprintf(statbuffer,sizeof statbuffer,"Serial Number: %s",dmi->system.serial); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"UUID : %s",dmi->system.uuid); + snprintf(statbuffer,sizeof statbuffer,"UUID: %s",dmi->system.uuid); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Wakeup : %s",dmi->system.wakeup_type); + snprintf(statbuffer,sizeof statbuffer,"Wakeup Type: %s",dmi->system.wakeup_type); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"SKU Number: %s",dmi->system.sku_number); + snprintf(statbuffer,sizeof statbuffer,"SKU Number: %s",dmi->system.sku_number); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Family : %s",dmi->system.family); + snprintf(statbuffer,sizeof statbuffer,"Family: %s",dmi->system.family); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + printf("MENU: System menu done (%d items)\n",menu->items_count); +} + +/* Compute Chassis menu */ +void compute_chassis(struct s_my_menu *menu,s_dmi *dmi) { + char buffer[SUBMENULEN+1]; + char statbuffer[STATLEN+1]; + menu->menu = add_menu(" Chassis ",-1); + menu->items_count=0; + set_menu_pos(SUBMENU_Y,SUBMENU_X); + + snprintf(buffer,sizeof buffer,"Vendor : %s",dmi->chassis.manufacturer); + snprintf(statbuffer,sizeof statbuffer,"Vendor: %s",dmi->chassis.manufacturer); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Type : %s",dmi->chassis.type); + snprintf(statbuffer,sizeof statbuffer,"Type: %s",dmi->chassis.type); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Version : %s",dmi->chassis.version); + snprintf(statbuffer,sizeof statbuffer,"Version: %s",dmi->chassis.version); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Serial : %s",dmi->chassis.serial); + snprintf(statbuffer,sizeof statbuffer,"Serial Number: %s",dmi->chassis.serial); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Asset Tag : %s",dmi->chassis.asset_tag); + snprintf(statbuffer,sizeof statbuffer,"Asset Tag: %s",dmi->chassis.asset_tag); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Lock : %s",dmi->chassis.lock); + snprintf(statbuffer,sizeof statbuffer,"Lock: %s",dmi->chassis.lock); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + printf("MENU: Chassis menu done (%d items)\n", menu->items_count); +} + +/* Compute BIOS menu */ +void compute_bios(struct s_my_menu *menu,s_dmi *dmi) { + char buffer[SUBMENULEN+1]; + char statbuffer[STATLEN+1]; + + menu->menu = add_menu(" BIOS ",-1); + menu->items_count=0; + set_menu_pos(SUBMENU_Y,SUBMENU_X); + + snprintf(buffer,sizeof buffer,"Vendor : %s",dmi->bios.vendor); + snprintf(statbuffer,sizeof statbuffer,"Vendor: %s",dmi->bios.vendor); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Version : %s",dmi->bios.version); + snprintf(statbuffer,sizeof statbuffer,"Version: %s",dmi->bios.version); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Release : %s",dmi->bios.release_date); + snprintf(statbuffer,sizeof statbuffer,"Release Date: %s",dmi->bios.release_date); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Bios Rev. : %s",dmi->bios.bios_revision); + snprintf(statbuffer,sizeof statbuffer,"Bios Revision: %s",dmi->bios.bios_revision); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Fw. Rev. : %s",dmi->bios.firmware_revision); + snprintf(statbuffer,sizeof statbuffer,"Firmware Revision : %s",dmi->bios.firmware_revision); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + + printf("MENU: BIOS menu done (%d items)\n",menu->items_count); +} + +/* Compute Motherboard main menu */ +void compute_motherboard(struct s_my_menu *menu,s_dmi *dmi) { + char buffer[SUBMENULEN+1]; + char statbuffer[STATLEN+1]; + + menu->menu = add_menu(" Motherboard ",-1); + menu->items_count=0; + set_menu_pos(SUBMENU_Y,SUBMENU_X); + + snprintf(buffer,sizeof buffer,"Vendor : %s",dmi->base_board.manufacturer); + snprintf(statbuffer,sizeof statbuffer,"Vendor: %s",dmi->base_board.manufacturer); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Product : %s",dmi->base_board.product_name); + snprintf(statbuffer,sizeof statbuffer,"Product Name: %s",dmi->base_board.product_name); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Version : %s",dmi->base_board.version); + snprintf(statbuffer,sizeof statbuffer,"Version: %s",dmi->base_board.version); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Serial : %s",dmi->base_board.serial); + snprintf(statbuffer,sizeof statbuffer,"Serial Number: %s",dmi->base_board.serial); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Asset Tag : %s",dmi->base_board.asset_tag); + snprintf(statbuffer,sizeof statbuffer,"Asset Tag: %s",dmi->base_board.asset_tag); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Location : %s",dmi->base_board.location); + snprintf(statbuffer,sizeof statbuffer,"Location: %s",dmi->base_board.location); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Type : %s",dmi->base_board.type); + snprintf(statbuffer,sizeof statbuffer,"Type: %s",dmi->base_board.type); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + printf("MENU: Motherboard menu done (%d items)\n",menu->items_count); +} + +/* Compute the memory submenu */ +void compute_memory_module(struct s_my_menu *menu, s_dmi *dmi, int slot_number) { + int i=slot_number; + char buffer[MENULEN+1]; + char statbuffer[STATLEN+1]; + + sprintf(buffer," Bank <%d> ",i); + menu->items_count=0; + menu->menu = add_menu(buffer,-1); + + snprintf(buffer,sizeof buffer,"Form Factor : %s",dmi->memory[i].form_factor); + snprintf(statbuffer,sizeof statbuffer,"Form Factor: %s",dmi->memory[i].form_factor); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Type : %s",dmi->memory[i].type); + snprintf(statbuffer,sizeof statbuffer,"Type: %s",dmi->memory[i].type); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Type Details : %s",dmi->memory[i].type_detail); + snprintf(statbuffer,sizeof statbuffer,"Type Details: %s",dmi->memory[i].type_detail); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Speed : %s",dmi->memory[i].speed); + snprintf(statbuffer,sizeof statbuffer,"Speed (Mhz): %s",dmi->memory[i].speed); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Size : %s",dmi->memory[i].size); + snprintf(statbuffer,sizeof statbuffer,"Size: %s",dmi->memory[i].size); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Device Set : %s",dmi->memory[i].device_set); + snprintf(statbuffer,sizeof statbuffer,"Device Set: %s",dmi->memory[i].device_set); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Device Loc. : %s",dmi->memory[i].device_locator); + snprintf(statbuffer,sizeof statbuffer,"Device Location: %s",dmi->memory[i].device_locator); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Bank Locator : %s",dmi->memory[i].bank_locator); + snprintf(statbuffer,sizeof statbuffer,"Bank Locator: %s",dmi->memory[i].bank_locator); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Total Width : %s",dmi->memory[i].total_width); + snprintf(statbuffer,sizeof statbuffer,"Total bit Width: %s",dmi->memory[i].total_width); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Data Width : %s",dmi->memory[i].data_width); + snprintf(statbuffer,sizeof statbuffer,"Data bit Width: %s",dmi->memory[i].data_width); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Error : %s",dmi->memory[i].error); + snprintf(statbuffer,sizeof statbuffer,"Error: %s",dmi->memory[i].error); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Vendor : %s",dmi->memory[i].manufacturer); + snprintf(statbuffer,sizeof statbuffer,"Vendor: %s",dmi->memory[i].manufacturer); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Serial : %s",dmi->memory[i].serial); + snprintf(statbuffer,sizeof statbuffer,"Serial: %s",dmi->memory[i].serial); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Asset Tag : %s",dmi->memory[i].asset_tag); + snprintf(statbuffer,sizeof statbuffer,"Asset Tag: %s",dmi->memory[i].asset_tag); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Part Number : %s",dmi->memory[i].part_number); + snprintf(buffer,sizeof statbuffer,"Part Number: %s",dmi->memory[i].part_number); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + +} + +/* Compute the Memory Menu*/ +void compute_memory(struct s_hdt_menu *menu, s_dmi *dmi) { + char buffer[MENULEN+1]; + for (int i=0;i<dmi->memory_count;i++) { + compute_memory_module(&(menu->memory_sub_menu[i]),dmi,i); + } + + menu->memory_menu.menu = add_menu(" Memory Banks ",-1); + menu->memory_menu.items_count=0; + + for (int i=0;i<dmi->memory_count;i++) { + snprintf(buffer,sizeof buffer," Bank <%d> ",i); + add_item(buffer,"Memory Bank",OPT_SUBMENU,NULL,menu->memory_sub_menu[i].menu); + menu->memory_menu.items_count++; + } + printf("MENU: Memory menu done (%d items)\n",menu->memory_menu.items_count); + add_item("Run Test","Run Test",OPT_RUN,"memtest",0); +} + + +/* Main Battery Menu*/ +void compute_battery(struct s_my_menu *menu, s_dmi *dmi) { + char buffer[SUBMENULEN+1]; + char statbuffer[STATLEN+1]; + menu->menu = add_menu(" Battery ",-1); + menu->items_count=0; + set_menu_pos(SUBMENU_Y,SUBMENU_X); + + snprintf(buffer, sizeof buffer,"Vendor : %s",dmi->battery.manufacturer); + snprintf(statbuffer, sizeof statbuffer,"Vendor: %s",dmi->battery.manufacturer); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer, sizeof buffer,"Manufacture Date: %s",dmi->battery.manufacture_date); + snprintf(statbuffer, sizeof statbuffer,"Manufacture Date: %s",dmi->battery.manufacture_date); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer, sizeof buffer,"Serial : %s",dmi->battery.serial); + snprintf(statbuffer, sizeof statbuffer,"Serial: %s",dmi->battery.serial); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer, sizeof buffer,"Name : %s",dmi->battery.name); + snprintf(statbuffer, sizeof statbuffer,"Name: %s",dmi->battery.name); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer, sizeof buffer,"Chemistry : %s",dmi->battery.chemistry); + snprintf(statbuffer, sizeof statbuffer,"Chemistry: %s",dmi->battery.chemistry); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer, sizeof buffer,"Design Capacity : %s",dmi->battery.design_capacity); + snprintf(statbuffer, sizeof statbuffer,"Design Capacity: %s",dmi->battery.design_capacity); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer, sizeof buffer,"Design Voltage : %s",dmi->battery.design_voltage); + snprintf(statbuffer, sizeof statbuffer,"Design Voltage : %s",dmi->battery.design_voltage); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer, sizeof buffer,"SBDS : %s",dmi->battery.sbds); + snprintf(statbuffer, sizeof statbuffer,"SBDS: %s",dmi->battery.sbds); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer, sizeof buffer,"SBDS Manuf. Date: %s",dmi->battery.sbds_manufacture_date); + snprintf(statbuffer, sizeof statbuffer,"SBDS Manufacture Date: %s",dmi->battery.sbds_manufacture_date); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer, sizeof buffer,"SBDS Chemistry : %s",dmi->battery.sbds_chemistry); + snprintf(statbuffer, sizeof statbuffer,"SBDS Chemistry : %s",dmi->battery.sbds_chemistry); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer, sizeof buffer,"Maximum Error : %s",dmi->battery.maximum_error); + snprintf(statbuffer, sizeof statbuffer,"Maximum Error (%) : %s",dmi->battery.maximum_error); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer, sizeof buffer,"OEM Info : %s",dmi->battery.oem_info); + snprintf(statbuffer, sizeof statbuffer,"OEM Info: %s",dmi->battery.oem_info); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + printf("MENU: Battery menu done (%d items)\n",menu->items_count); +} diff --git a/com32/hdt/hdt-menu-kernel.c b/com32/hdt/hdt-menu-kernel.c new file mode 100644 index 00000000..39979279 --- /dev/null +++ b/com32/hdt/hdt-menu-kernel.c @@ -0,0 +1,73 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- +*/ + +#include "hdt-menu.h" + +/* Main Kernel Menu*/ +void compute_kernel(struct s_my_menu *menu,struct s_hardware *hardware) { + char buffer[SUBMENULEN+1]; + char infobar[STATLEN+1]; + char kernel_modules [LINUX_KERNEL_MODULE_SIZE*MAX_KERNEL_MODULES_PER_PCI_DEVICE]; + struct pci_device *pci_device; + + menu->menu = add_menu(" Kernel Modules ",-1); + menu->items_count=0; + set_menu_pos(SUBMENU_Y,SUBMENU_X); + + if (hardware->modules_pcimap_return_code == -ENOMODULESPCIMAP) { + add_item("The modules.pcimap file is missing","Missing modules.pcimap file",OPT_INACTIVE,NULL,0); + add_item("Kernel modules can't be computed.","Missing modules.pcimap file",OPT_INACTIVE,NULL,0); + add_item("Please put one in same dir as hdt","Missing modules.pcimap file",OPT_INACTIVE,NULL,0); + add_item("","",OPT_SEP,"",0); + } else { + /* For every detected pci device, grab its kernel module to compute this submenu */ + for_each_pci_func(pci_device, hardware->pci_domain) { + memset(kernel_modules,0,sizeof kernel_modules); + for (int i=0; i<pci_device->dev_info->linux_kernel_module_count;i++) { + if (i>0) { + strncat(kernel_modules," | ",3); + } + strncat(kernel_modules, pci_device->dev_info->linux_kernel_module[i],LINUX_KERNEL_MODULE_SIZE-1); + } + /* No need to add unknown kernel modules*/ + if (strlen(kernel_modules)>0) { + snprintf(buffer,sizeof buffer,"%s (%s)",kernel_modules, pci_device->dev_info->class_name); + snprintf(infobar, sizeof infobar,"%04x:%04x %s : %s\n", + pci_device->vendor, pci_device->product, + pci_device->dev_info->vendor_name, + pci_device->dev_info->product_name); + + add_item(buffer,infobar,OPT_INACTIVE,NULL,0); + menu->items_count++; + } + } + } + + printf("MENU: Kernel menu done (%d items)\n",menu->items_count); +} + diff --git a/com32/hdt/hdt-menu-pci.c b/com32/hdt/hdt-menu-pci.c new file mode 100644 index 00000000..477ba4aa --- /dev/null +++ b/com32/hdt/hdt-menu-pci.c @@ -0,0 +1,125 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- +*/ + +#include "hdt-menu.h" + + +/* Dynamic submenu for the pci devices */ +void compute_pci_device(struct s_my_menu *menu,struct pci_device *pci_device,int pci_bus, int pci_slot, int pci_func) { + char buffer[56]; + char statbuffer[STATLEN]; + char kernel_modules [LINUX_KERNEL_MODULE_SIZE*MAX_KERNEL_MODULES_PER_PCI_DEVICE]; + + menu->menu = add_menu(" Details ",-1); + menu->items_count=0; + set_menu_pos(5,17); + + snprintf(buffer,sizeof buffer,"Vendor : %s",pci_device->dev_info->vendor_name); + snprintf(statbuffer,sizeof statbuffer,"Vendor Name: %s",pci_device->dev_info->vendor_name); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Product : %s",pci_device->dev_info->product_name); + snprintf(statbuffer,sizeof statbuffer,"Product Name %s",pci_device->dev_info->product_name); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Class : %s",pci_device->dev_info->class_name); + snprintf(statbuffer,sizeof statbuffer,"Class Name: %s",pci_device->dev_info->class_name); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Location: %02x:%02x.%01x",pci_bus, pci_slot, pci_func); + snprintf(statbuffer,sizeof statbuffer,"Location on the PCI Bus: %02x:%02x.%01x",pci_bus, pci_slot, pci_func); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"PCI ID : %04x:%04x[%04x:%04x]",pci_device->vendor, pci_device->product,pci_device->sub_vendor, pci_device->sub_product); + snprintf(statbuffer,sizeof statbuffer,"vendor:product[sub_vendor:sub_product] : %04x:%04x[%04x:%04x]",pci_device->vendor, pci_device->product,pci_device->sub_vendor, pci_device->sub_product); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + if (pci_device->dev_info->linux_kernel_module_count>1) { + for (int i=0; i<pci_device->dev_info->linux_kernel_module_count;i++) { + if (i>0) { + strncat(kernel_modules," | ",3); + } + strncat(kernel_modules, pci_device->dev_info->linux_kernel_module[i],LINUX_KERNEL_MODULE_SIZE-1); + } + snprintf(buffer,sizeof buffer,"Modules : %s",kernel_modules); + snprintf(statbuffer,sizeof statbuffer,"Kernel Modules: %s",kernel_modules); + } else { + snprintf(buffer,sizeof buffer,"Module : %s",pci_device->dev_info->linux_kernel_module[0]); + snprintf(statbuffer,sizeof statbuffer,"Kernel Module: %s",pci_device->dev_info->linux_kernel_module[0]); + } + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; +} + +/* Main PCI Menu*/ +int compute_PCI(struct s_hdt_menu *hdt_menu, struct s_hardware *hardware) { + int i=0; + char menuname[255][MENULEN+1]; + char infobar[255][STATLEN+1]; + struct pci_device *pci_device; + char kernel_modules [LINUX_KERNEL_MODULE_SIZE*MAX_KERNEL_MODULES_PER_PCI_DEVICE]; + + /* For every detected pci device, compute its submenu */ + for_each_pci_func(pci_device, hardware->pci_domain) { + memset(kernel_modules,0,sizeof kernel_modules); + for (int kmod=0; kmod<pci_device->dev_info->linux_kernel_module_count;kmod++) { + if (kmod>0) { + strncat(kernel_modules," | ",3); + } + strncat(kernel_modules, pci_device->dev_info->linux_kernel_module[kmod],LINUX_KERNEL_MODULE_SIZE-1); + } + if (pci_device->dev_info->linux_kernel_module_count==0) strlcpy(kernel_modules,"unknown",7); + + compute_pci_device(&(hdt_menu->pci_sub_menu[i]),pci_device,__pci_bus,__pci_slot,__pci_func); + snprintf(menuname[i],59,"%s|%s",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", + __pci_bus, __pci_slot, __pci_func,pci_device->dev_info->class_name, + pci_device->vendor, pci_device->product, + pci_device->sub_vendor, pci_device->sub_product,kernel_modules); + i++; + } + + hdt_menu->pci_menu.menu = add_menu(" PCI Devices ",-1); + hdt_menu->pci_menu.items_count=0; + if (hardware->pci_ids_return_code == -ENOPCIIDS) { + add_item("The pci.ids file is missing","Missing pci.ids file",OPT_INACTIVE,NULL,0); + add_item("PCI Device names can't be computed.","Missing pci.ids file",OPT_INACTIVE,NULL,0); + add_item("Please put one in same dir as hdt","Missing pci.ids file",OPT_INACTIVE,NULL,0); + add_item("","",OPT_SEP,"",0); + } + for (int j=0;j<i;j++) { + add_item(menuname[j],infobar[j],OPT_SUBMENU,NULL,hdt_menu->pci_sub_menu[j].menu); + hdt_menu->pci_menu.items_count++; + } + printf("MENU: PCI menu done (%d items)\n",hdt_menu->pci_menu.items_count); + return 0; +} diff --git a/com32/hdt/hdt-menu-processor.c b/com32/hdt/hdt-menu-processor.c new file mode 100644 index 00000000..d0d7dd7b --- /dev/null +++ b/com32/hdt/hdt-menu-processor.c @@ -0,0 +1,186 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- +*/ + +#include "hdt-menu.h" + +/* Compute Processor menu */ +void compute_processor(struct s_my_menu *menu,struct s_hardware *hardware) { + char buffer[SUBMENULEN+1]; + char buffer1[SUBMENULEN+1]; + char statbuffer[STATLEN+1]; + + menu->menu = add_menu(" Main Processor ",-1); + menu->items_count=0; + set_menu_pos(SUBMENU_Y,SUBMENU_X); + + snprintf(buffer,sizeof buffer,"Vendor : %s",hardware->cpu.vendor); + snprintf(statbuffer,sizeof statbuffer,"Vendor: %s",hardware->cpu.vendor); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Model : %s",hardware->cpu.model); + snprintf(statbuffer,sizeof statbuffer,"Model: %s",hardware->cpu.model); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Vendor ID : %d",hardware->cpu.vendor_id); + snprintf(statbuffer,sizeof statbuffer,"Vendor ID: %d",hardware->cpu.vendor_id); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Family ID : %d",hardware->cpu.family); + snprintf(statbuffer,sizeof statbuffer,"Family ID: %d",hardware->cpu.family); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Model ID : %d",hardware->cpu.model_id); + snprintf(statbuffer,sizeof statbuffer,"Model ID: %d",hardware->cpu.model_id); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Stepping : %d",hardware->cpu.stepping); + snprintf(statbuffer,sizeof statbuffer,"Stepping: %d",hardware->cpu.stepping); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + if (hardware->is_dmi_valid) { + snprintf(buffer,sizeof buffer,"FSB : %d",hardware->dmi.processor.external_clock); + snprintf(statbuffer,sizeof statbuffer,"Front Side Bus (MHz): %d",hardware->dmi.processor.external_clock); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Cur. Speed: %d",hardware->dmi.processor.current_speed); + snprintf(statbuffer,sizeof statbuffer,"Current Speed (MHz): %d",hardware->dmi.processor.current_speed); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Max Speed : %d",hardware->dmi.processor.max_speed); + snprintf(statbuffer,sizeof statbuffer,"Max Speed (MHz): %d",hardware->dmi.processor.max_speed); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Upgrade : %s", hardware->dmi.processor.upgrade); + snprintf(statbuffer,sizeof statbuffer,"Upgrade: %s",hardware->dmi.processor.upgrade); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + } + + if (hardware->cpu.flags.smp) { + snprintf(buffer,sizeof buffer,"SMP : Yes"); + snprintf(statbuffer,sizeof statbuffer,"SMP: Yes"); + } + else { + snprintf(buffer,sizeof buffer,"SMP : No"); + snprintf(statbuffer,sizeof statbuffer,"SMP: No"); + } + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + if (hardware->cpu.flags.lm) { + snprintf(buffer,sizeof buffer,"x86_64 : Yes"); + snprintf(statbuffer,sizeof statbuffer,"x86_64 compatible processor: Yes"); + } + else { + snprintf(buffer,sizeof buffer,"X86_64 : No"); + snprintf(statbuffer,sizeof statbuffer,"X86_64 compatible processor: No"); + } + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + buffer1[0]='\0'; + if (hardware->cpu.flags.fpu) strcat(buffer1,"fpu "); + if (hardware->cpu.flags.vme) strcat(buffer1,"vme "); + if (hardware->cpu.flags.de) strcat(buffer1,"de "); + if (hardware->cpu.flags.pse) strcat(buffer1,"pse "); + if (hardware->cpu.flags.tsc) strcat(buffer1,"tsc "); + if (hardware->cpu.flags.msr) strcat(buffer1,"msr "); + if (hardware->cpu.flags.pae) strcat(buffer1,"pae "); + snprintf(buffer,sizeof buffer,"Flags : %s",buffer1); + snprintf(statbuffer,sizeof statbuffer,"Flags: %s",buffer1); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + buffer1[0]='\0'; + if (hardware->cpu.flags.mce) strcat(buffer1,"mce "); + if (hardware->cpu.flags.cx8) strcat(buffer1,"cx8 "); + if (hardware->cpu.flags.apic) strcat(buffer1,"apic "); + if (hardware->cpu.flags.sep) strcat(buffer1,"sep "); + if (hardware->cpu.flags.mtrr) strcat(buffer1,"mtrr "); + if (hardware->cpu.flags.pge) strcat(buffer1,"pge "); + if (hardware->cpu.flags.mca) strcat(buffer1,"mca "); + snprintf(buffer,sizeof buffer,"Flags : %s",buffer1); + snprintf(statbuffer,sizeof statbuffer,"Flags: %s",buffer1); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + buffer1[0]='\0'; + if (hardware->cpu.flags.cmov) strcat(buffer1,"cmov "); + if (hardware->cpu.flags.pat) strcat(buffer1,"pat "); + if (hardware->cpu.flags.pse_36) strcat(buffer1,"pse_36 "); + if (hardware->cpu.flags.psn) strcat(buffer1,"psn "); + if (hardware->cpu.flags.clflsh) strcat(buffer1,"clflsh "); + snprintf(buffer,sizeof buffer,"Flags : %s",buffer1); + snprintf(statbuffer,sizeof statbuffer,"Flags: %s",buffer1); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + buffer1[0]='\0'; + if (hardware->cpu.flags.dts) strcat(buffer1,"dts "); + if (hardware->cpu.flags.acpi) strcat(buffer1,"acpi "); + if (hardware->cpu.flags.mmx) strcat(buffer1,"mmx "); + if (hardware->cpu.flags.sse) strcat(buffer1,"sse "); + snprintf(buffer,sizeof buffer,"Flags : %s",buffer1); + snprintf(statbuffer,sizeof statbuffer,"Flags: %s",buffer1); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + buffer1[0]='\0'; + if (hardware->cpu.flags.sse2) strcat(buffer1,"sse2 "); + if (hardware->cpu.flags.ss) strcat(buffer1,"ss "); + if (hardware->cpu.flags.htt) strcat(buffer1,"ht "); + if (hardware->cpu.flags.acc) strcat(buffer1,"acc "); + if (hardware->cpu.flags.syscall) strcat(buffer1,"syscall "); + if (hardware->cpu.flags.mp) strcat(buffer1,"mp "); + snprintf(buffer,sizeof buffer,"Flags : %s",buffer1); + snprintf(statbuffer,sizeof statbuffer,"Flags: %s",buffer1); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + buffer1[0]='\0'; + if (hardware->cpu.flags.nx) strcat(buffer1,"nx "); + if (hardware->cpu.flags.mmxext) strcat(buffer1,"mmxext "); + if (hardware->cpu.flags.lm) strcat(buffer1,"lm "); + if (hardware->cpu.flags.nowext) strcat(buffer1,"3dnowext "); + if (hardware->cpu.flags.now) strcat(buffer1,"3dnow! "); + snprintf(buffer,sizeof buffer,"Flags : %s",buffer1); + snprintf(statbuffer,sizeof statbuffer,"Flags: %s",buffer1); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + printf("MENU: Processor menu done (%d items)\n",menu->items_count); +} diff --git a/com32/hdt/hdt-menu-pxe.c b/com32/hdt/hdt-menu-pxe.c new file mode 100644 index 00000000..5ab3d8b3 --- /dev/null +++ b/com32/hdt/hdt-menu-pxe.c @@ -0,0 +1,99 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- +*/ + +#include "hdt-menu.h" + +/* Main Kernel Menu*/ +void compute_PXE(struct s_my_menu *menu,struct s_hardware *hardware) { + char buffer[SUBMENULEN+1]; + char infobar[STATLEN+1]; + + if (hardware->is_pxe_valid==false) return; + + menu->menu = add_menu(" PXE ",-1); + menu->items_count=0; + set_menu_pos(SUBMENU_Y,SUBMENU_X); + + struct s_pxe *p = &hardware->pxe; + + if (hardware->pci_ids_return_code == -ENOPCIIDS) { + snprintf(buffer,sizeof buffer, "PCI Vendor : %d",p->vendor_id); + snprintf(infobar,sizeof infobar,"PCI Vendor : %d",p->vendor_id); + add_item(buffer,infobar,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer, "PCI Product : %d",p->vendor_id); + snprintf(infobar,sizeof infobar,"PCI Product : %d",p->vendor_id); + add_item(buffer,infobar,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer, "PCI SubVendor : %d",p->subvendor_id); + snprintf(infobar,sizeof infobar,"PCI SubVendor : %d",p->subvendor_id); + add_item(buffer,infobar,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer, "PCI SubProduct : %d",p->subproduct_id); + snprintf(infobar,sizeof infobar,"PCI SubProduct : %d",p->subproduct_id); + add_item(buffer,infobar,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer, "PCI Revision : %d",p->rev); + snprintf(infobar,sizeof infobar,"PCI Revision : %d",p->rev); + add_item(buffer,infobar,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer, "PCI Bus Pos. : %02x:%02x.%02x",p->pci_bus,p->pci_dev, p->pci_func); + snprintf(infobar,sizeof infobar,"PCI Bus Pos. : %02x:%02x.%02x",p->pci_bus,p->pci_dev, p->pci_func); + add_item(buffer,infobar,OPT_INACTIVE,NULL,0); + menu->items_count++; + + } else { + + snprintf(buffer,sizeof buffer, "Manufacturer : %s", p->pci_device->dev_info->vendor_name); + snprintf(infobar,sizeof infobar,"Manufacturer : %s", p->pci_device->dev_info->vendor_name); + add_item(buffer,infobar,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer, "Product : %s", p->pci_device->dev_info->product_name); + snprintf(infobar,sizeof infobar,"Product : %s", p->pci_device->dev_info->product_name); + add_item(buffer,infobar,OPT_INACTIVE,NULL,0); + menu->items_count++; + } + + snprintf(buffer,sizeof buffer, "MAC Address : %s", p->mac_addr); + snprintf(infobar,sizeof infobar, "MAC Address : %s", p->mac_addr); + add_item(buffer,infobar,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer, "IP Address : %d.%d.%d.%d", p->ip_addr[0], p->ip_addr[1], p->ip_addr[2], p->ip_addr[3]); + snprintf(infobar,sizeof infobar, "IP Address : %d.%d.%d.%d", p->ip_addr[0], p->ip_addr[1], p->ip_addr[2], p->ip_addr[3]); + add_item(buffer,infobar,OPT_INACTIVE,NULL,0); + menu->items_count++; + + printf("MENU: PXE menu done (%d items)\n",menu->items_count); +} diff --git a/com32/hdt/hdt-menu-summary.c b/com32/hdt/hdt-menu-summary.c new file mode 100644 index 00000000..9bbefbfe --- /dev/null +++ b/com32/hdt/hdt-menu-summary.c @@ -0,0 +1,158 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- +*/ + +#include "hdt-menu.h" + +/* Computing Summary menu*/ +void compute_summarymenu(struct s_my_menu *menu, struct s_hardware *hardware) { + char buffer[SUBMENULEN+1]; + char statbuffer[STATLEN+1]; + char bank_number[10]; + + menu->menu = add_menu(" Summary ",-1); + menu->items_count=0; + + set_menu_pos(SUBMENU_Y,SUBMENU_X); + + snprintf(buffer,sizeof buffer,"CPU Vendor : %s",hardware->cpu.vendor); + snprintf(statbuffer,sizeof statbuffer,"CPU Vendor: %s",hardware->cpu.vendor); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"CPU Model : %s",hardware->cpu.model); + snprintf(statbuffer,sizeof statbuffer,"CPU Model: %s",hardware->cpu.model); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + add_item("","",OPT_SEP,"",0); + if (hardware->is_dmi_valid == true) { + + snprintf(buffer,sizeof buffer,"System Vendor : %s",hardware->dmi.system.manufacturer); + snprintf(statbuffer,sizeof statbuffer,"System Vendor: %s",hardware->dmi.system.manufacturer); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"System Product: %s",hardware->dmi.system.product_name); + snprintf(statbuffer,sizeof statbuffer,"System Product Name: %s",hardware->dmi.system.product_name); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"System Serial : %s",hardware->dmi.system.serial); + snprintf(statbuffer,sizeof statbuffer,"System Serial Number: %s",hardware->dmi.system.serial); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + add_item("","",OPT_SEP,"",0); + + snprintf(buffer,sizeof buffer,"Bios Version : %s",hardware->dmi.bios.version); + snprintf(statbuffer,sizeof statbuffer,"Bios Version: %s",hardware->dmi.bios.version); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer,"Bios Release : %s",hardware->dmi.bios.release_date); + snprintf(statbuffer,sizeof statbuffer,"Bios Release Date: %s",hardware->dmi.bios.release_date); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + add_item("","",OPT_SEP,"",0); + + for (int i=0;i<hardware->dmi.memory_count;i++) { + if (hardware->dmi.memory[i].filled==true) { + /* When discovering the first item, let's clear the screen */ + memset(bank_number,0,sizeof(bank_number)); + snprintf(bank_number,sizeof(bank_number),"%d ",i); + if (strncmp(hardware->dmi.memory[i].size,"Free",4)) { + snprintf(buffer,sizeof buffer,"Mem bank %02d : %s %s@%s", + i,hardware->dmi.memory[i].size, hardware->dmi.memory[i].type, hardware->dmi.memory[i].speed); + snprintf(statbuffer,sizeof statbuffer,"Memory bank %02d : %s %s@%s", + i,hardware->dmi.memory[i].size, hardware->dmi.memory[i].type, hardware->dmi.memory[i].speed); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + } + } + } + + add_item("","",OPT_SEP,"",0); + } + + snprintf(buffer,sizeof buffer,"Nb PCI Devices: %d",hardware->nb_pci_devices); + snprintf(statbuffer,sizeof statbuffer,"Number of PCI Devices: %d",hardware->nb_pci_devices); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + add_item("","",OPT_SEP,"",0); + + if (hardware->is_pxe_valid==true) { + struct s_pxe *p = &hardware->pxe; + + snprintf(buffer,sizeof buffer, "PXE MAC Address: %s", p->mac_addr); + snprintf(statbuffer,sizeof statbuffer, "PXE MAC Address: %s", p->mac_addr); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer,sizeof buffer, "PXE IP Address : %d.%d.%d.%d", p->ip_addr[0], p->ip_addr[1], p->ip_addr[2], p->ip_addr[3]); + snprintf(statbuffer,sizeof statbuffer, "PXE IP Address: %d.%d.%d.%d", p->ip_addr[0], p->ip_addr[1], p->ip_addr[2], p->ip_addr[3]); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + add_item("","",OPT_SEP,"",0); + } + + if (hardware->modules_pcimap_return_code != -ENOMODULESPCIMAP) { + bool kmod=false; + struct pci_device *pci_device; + char kernel_modules [LINUX_KERNEL_MODULE_SIZE*MAX_KERNEL_MODULES_PER_PCI_DEVICE]; + + /* For every detected pci device, grab its kernel module to compute this submenu */ + for_each_pci_func(pci_device, hardware->pci_domain) { + memset(kernel_modules,0,sizeof kernel_modules); + for (int i=0; i<pci_device->dev_info->linux_kernel_module_count;i++) { + if (i>0) { + strncat(kernel_modules," | ",3); + } + strncat(kernel_modules, pci_device->dev_info->linux_kernel_module[i],LINUX_KERNEL_MODULE_SIZE-1); + } + /* No need to add unknown kernel modules*/ + if (strlen(kernel_modules)>0) { + snprintf(buffer,sizeof buffer,"%s (%s)",kernel_modules, pci_device->dev_info->class_name); + snprintf(statbuffer, sizeof statbuffer,"%04x:%04x %s : %s\n", + pci_device->vendor, pci_device->product, + pci_device->dev_info->vendor_name, + pci_device->dev_info->product_name); + + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + kmod=true; + } + } + if (kmod==true) add_item("","",OPT_SEP,"",0); + } + + printf("MENU: Summary menu done (%d items)\n",menu->items_count); +} + diff --git a/com32/hdt/hdt-menu-syslinux.c b/com32/hdt/hdt-menu-syslinux.c new file mode 100644 index 00000000..d17070f8 --- /dev/null +++ b/com32/hdt/hdt-menu-syslinux.c @@ -0,0 +1,74 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- +*/ + +#include "syslinux/config.h" +#include "hdt-menu.h" + +/* Computing Syslinux menu*/ +void compute_syslinuxmenu(struct s_my_menu *menu, struct s_hardware *hardware) { + char syslinux_fs_menu[24]; + char buffer[SUBMENULEN+1]; + char statbuffer[STATLEN+1]; + + memset(syslinux_fs_menu,0,sizeof syslinux_fs_menu); + + snprintf(syslinux_fs_menu,sizeof syslinux_fs_menu," %s ",hardware->syslinux_fs); + menu->menu = add_menu(syslinux_fs_menu,-1); + menu->items_count=0; + set_menu_pos(SUBMENU_Y,SUBMENU_X); + + snprintf(buffer, sizeof buffer, "Bootloader : %s", hardware->syslinux_fs); + snprintf(statbuffer, sizeof statbuffer, "Bootloader: %s", hardware->syslinux_fs); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Version : %s", hardware->sv->version_string+2); + snprintf(statbuffer, sizeof statbuffer, "Version: %s", hardware->sv->version_string+2); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Version : %u",hardware->sv->version); + snprintf(statbuffer, sizeof statbuffer, "Version: %u",hardware->sv->version); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Max API : %u",hardware->sv->max_api); + snprintf(statbuffer, sizeof statbuffer, "Max API: %u",hardware->sv->max_api); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + add_item("","",OPT_SEP,"",0); + + snprintf(buffer, sizeof buffer, "%s", hardware->sv->copyright_string+1); + snprintf(statbuffer, sizeof statbuffer, "%s", hardware->sv->copyright_string+1); + add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0); + menu->items_count++; + + printf("MENU: Syslinux menu done (%d items)\n",menu->items_count); +} + diff --git a/com32/hdt/hdt-menu.c b/com32/hdt/hdt-menu.c new file mode 100644 index 00000000..0853f09e --- /dev/null +++ b/com32/hdt/hdt-menu.c @@ -0,0 +1,253 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- +*/ + +#include "hdt-menu.h" + + + +int start_menu_mode(struct s_hardware *hardware, char *version_string) { + struct s_hdt_menu hdt_menu; + + memset(&hdt_menu,0,sizeof (hdt_menu)); + + /* Detect every kind of hardware */ + detect_hardware(hardware); + + /* Setup the menu system*/ + setup_menu(version_string); + + /* Compute all sub menus */ + compute_submenus(&hdt_menu, hardware); + + /* Compute main menu */ + compute_main_menu(&hdt_menu,hardware); + +#ifdef WITH_MENU_DISPLAY + t_menuitem * curr; + char cmd[160]; + + 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) { + /* When want to execute something */ + if (curr->action == OPT_RUN) + { + /* Tweak, we want to switch to the cli*/ + if (! strncmp(curr->data,HDT_SWITCH_TO_CLI,sizeof(HDT_SWITCH_TO_CLI))) { + return HDT_RETURN_TO_CLI; + } + strcpy(cmd,curr->data); + + /* Use specific syslinux call if needed */ + if (issyslinux()) + runsyslinuxcmd(cmd); + else csprint(cmd,0x07); + return 1; // Should not happen when run from SYSLINUX + } + } +#endif + return 0; +} + +/* In the menu system, what to do on keyboard timeout */ +TIMEOUTCODE ontimeout() +{ + // beep(); + return CODE_WAIT; +} + +/* Keyboard handler for the menu system */ +void keys_handler(t_menusystem *ms, t_menuitem *mi,unsigned int scancode) +{ + char nc; + + if ((scancode >> 8) == F1) { // 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)) { +//(isallowed(username,"editcmd") || isallowed(username,"root"))) { + nc = getnumcols(); + // User typed TAB and has permissions to edit command line + gotoxy(EDITPROMPT,1,ms->menupage); + csprint("Command line:",0x07); + editstring(mi->data,ACTIONLEN); + gotoxy(EDITPROMPT,1,ms->menupage); + cprint(' ',0x07,nc-1,ms->menupage); + } +} + +/* Setup the Menu system*/ +void setup_menu(char *version) { + /* Creating the menu */ + init_menusystem(version); + set_window_size(0,0,24,80); + + // Register the menusystem handler + // 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); +} + +/* Compute Main' Submenus*/ +void compute_submenus(struct s_hdt_menu *hdt_menu, struct s_hardware *hardware) { + + /* Compute this menus if a DMI table exist */ + if (hardware->is_dmi_valid) { + if (hardware->dmi.base_board.filled==true) compute_motherboard(&(hdt_menu->mobo_menu),&(hardware->dmi)); + if (hardware->dmi.chassis.filled==true) compute_chassis(&(hdt_menu->chassis_menu),&(hardware->dmi)); + if (hardware->dmi.system.filled==true) compute_system(&(hdt_menu->system_menu),&(hardware->dmi)); + for (int i=0;i<hardware->dmi.memory_count;i++) { + if (hardware->dmi.memory[i].filled==true) { + compute_memory(hdt_menu,&(hardware->dmi)); + break; + } + } + if (hardware->dmi.bios.filled==true) compute_bios(&(hdt_menu->bios_menu),&(hardware->dmi)); + if (hardware->dmi.battery.filled==true) compute_battery(&(hdt_menu->battery_menu),&(hardware->dmi)); + } + + compute_processor(&(hdt_menu->cpu_menu),hardware); + compute_disks(hdt_menu,hardware->disk_info); +#ifdef WITH_PCI + compute_PCI(hdt_menu,hardware); + compute_PXE(&(hdt_menu->pxe_menu),hardware); + compute_kernel(&(hdt_menu->kernel_menu),hardware); +#endif + compute_summarymenu(&(hdt_menu->summary_menu),hardware); + compute_syslinuxmenu(&(hdt_menu->syslinux_menu),hardware); + compute_aboutmenu(&(hdt_menu->about_menu)); +} + +void compute_main_menu(struct s_hdt_menu *hdt_menu,struct s_hardware *hardware) { + char menu_item[64]; + /* Let's count the number of menu we have */ + hdt_menu->total_menu_count=0; + hdt_menu->main_menu.items_count=0; + + hdt_menu->main_menu.menu = add_menu(" Main Menu ",-1); + set_item_options(-1,24); + +#ifdef WITH_PCI + snprintf(menu_item, sizeof (menu_item), "PC<I> Devices(%2d)\n",hardware->nb_pci_devices); + add_item(menu_item,"PCI Devices Menu",OPT_SUBMENU,NULL,hdt_menu->pci_menu.menu); + hdt_menu->main_menu.items_count++; + hdt_menu->total_menu_count+=hdt_menu->pci_menu.items_count; +#endif + if (hdt_menu->disk_menu.items_count>0) { + snprintf(menu_item, sizeof (menu_item), "<D>isks (%2d)\n",hdt_menu->disk_menu.items_count); + add_item(menu_item,"Disks Menu",OPT_SUBMENU,NULL,hdt_menu->disk_menu.menu); + hdt_menu->main_menu.items_count++; + hdt_menu->total_menu_count+=hdt_menu->disk_menu.items_count; + } + + if (hdt_menu->memory_menu.items_count>0) { + snprintf(menu_item, sizeof (menu_item), "<M>emory (%2d)\n",hdt_menu->memory_menu.items_count); + add_item(menu_item,"Memory Menu",OPT_SUBMENU,NULL,hdt_menu->memory_menu.menu); + hdt_menu->main_menu.items_count++; + hdt_menu->total_menu_count+=hdt_menu->memory_menu.items_count; + } + add_item("<P>rocessor","Main Processor Menu",OPT_SUBMENU,NULL,hdt_menu->cpu_menu.menu); + hdt_menu->main_menu.items_count++; + +if (hardware->is_dmi_valid) { + if (hardware->dmi.base_board.filled==true) { + add_item("M<o>therboard","Motherboard Menu",OPT_SUBMENU,NULL,hdt_menu->mobo_menu.menu); + hdt_menu->main_menu.items_count++; + } + + if (hardware->dmi.bios.filled==true) { + add_item("<B>ios","Bios Menu",OPT_SUBMENU,NULL,hdt_menu->bios_menu.menu); + hdt_menu->main_menu.items_count++; + } + + if (hardware->dmi.chassis.filled==true) { + add_item("<C>hassis","Chassis Menu",OPT_SUBMENU,NULL,hdt_menu->chassis_menu.menu); + hdt_menu->main_menu.items_count++; + } + + if (hardware->dmi.system.filled==true) { + add_item("<S>ystem","System Menu",OPT_SUBMENU,NULL,hdt_menu->system_menu.menu); + hdt_menu->main_menu.items_count++; + } + + if (hardware->dmi.battery.filled==true) { + add_item("Ba<t>tery","Battery Menu",OPT_SUBMENU,NULL,hdt_menu->battery_menu.menu); + hdt_menu->main_menu.items_count++; + } +} + + if (hardware->is_pxe_valid == true) { + add_item("P<X>E","PXE Information Menu",OPT_SUBMENU,NULL,hdt_menu->pxe_menu.menu); + hdt_menu->main_menu.items_count++; + } + + add_item("","",OPT_SEP,"",0); +#ifdef WITH_PCI + if (hardware->modules_pcimap_return_code != -ENOMODULESPCIMAP) { + add_item("<K>ernel Modules","Kernel Modules Menu",OPT_SUBMENU,NULL,hdt_menu->kernel_menu.menu); + hdt_menu->main_menu.items_count++; + } +#endif + add_item("<S>yslinux","Syslinux Information Menu",OPT_SUBMENU,NULL,hdt_menu->syslinux_menu.menu); + hdt_menu->main_menu.items_count++; + add_item("S<u>mmary","Summary Information Menu",OPT_SUBMENU,NULL,hdt_menu->summary_menu.menu); + hdt_menu->main_menu.items_count++; + + add_item("","",OPT_SEP,"",0); + + add_item("S<w>itch to CLI","Switch to Command Line",OPT_RUN,HDT_SWITCH_TO_CLI,0); + add_item("<A>bout","About Menu",OPT_SUBMENU,NULL,hdt_menu->about_menu.menu); + hdt_menu->main_menu.items_count++; + + hdt_menu->total_menu_count+=hdt_menu->main_menu.items_count; +} + +void detect_hardware(struct s_hardware *hardware) { + printf("CPU: Detecting\n"); + cpu_detect(hardware); + + printf("DISKS: Detecting\n"); + detect_disks(hardware); + + 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); + } +#ifdef WITH_PCI + detect_pci(hardware); + printf("PCI: %d Devices Found\n",hardware->nb_pci_devices); +#endif +} diff --git a/com32/hdt/hdt-menu.h b/com32/hdt/hdt-menu.h new file mode 100644 index 00000000..db94057a --- /dev/null +++ b/com32/hdt/hdt-menu.h @@ -0,0 +1,121 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- +*/ + +#ifndef DEFINE_HDT_MENU_H +#define DEFINE_HDT_MENU_H +#include <stdio.h> +#include "menu.h" +#include "help.h" +//#include "cpuid.h" +#include "sys/pci.h" +#include "hdt-common.h" +#include "dmi/dmi.h" +#include "hdt-ata.h" + +#define EDITPROMPT 21 + +#define SUBMENULEN 46 + +#define SUBMENU_Y 3 +#define SUBMENU_X 29 + +#define MAX_PCI_SUB_MENU 128 +#define MAX_MEMORY_SUB_MENU 32 +#define MAX_DISK_SUB_MENU 32 + +struct s_my_menu { + unsigned char menu; + int items_count; +}; + +struct s_hdt_menu { + struct s_my_menu main_menu; + struct s_my_menu cpu_menu; + struct s_my_menu mobo_menu; + struct s_my_menu chassis_menu; + struct s_my_menu bios_menu; + struct s_my_menu system_menu; + struct s_my_menu pci_menu; + struct s_my_menu pci_sub_menu[MAX_PCI_SUB_MENU]; + struct s_my_menu kernel_menu; + struct s_my_menu memory_menu; + struct s_my_menu memory_sub_menu[MAX_MEMORY_SUB_MENU]; + struct s_my_menu disk_menu; + struct s_my_menu disk_sub_menu[MAX_DISK_SUB_MENU]; + struct s_my_menu battery_menu; + struct s_my_menu syslinux_menu; + struct s_my_menu about_menu; + struct s_my_menu summary_menu; + struct s_my_menu pxe_menu; + int total_menu_count; // sum of all menus we have +}; + +TIMEOUTCODE ontimeout(); +void keys_handler(t_menusystem *ms, t_menuitem *mi,unsigned int scancode); + +// PCI Stuff +void compute_pci_device(struct s_my_menu *menu,struct pci_device *pci_device,int pci_bus, int pci_slot, int pci_func); +int compute_PCI(struct s_hdt_menu *hdt_menu, struct s_hardware *hardware); + +// KERNEL Stuff +void compute_kernel(struct s_my_menu *menu,struct s_hardware *hardware); + +// Disk Stuff +int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, struct diskinfo *d,int disk_number); +void compute_disks(struct s_hdt_menu *menu, struct diskinfo *disk_info); + +// DMI Stuff +void compute_motherboard(struct s_my_menu *menu,s_dmi *dmi); +void compute_battery(struct s_my_menu *menu, s_dmi *dmi); +void compute_system(struct s_my_menu *menu,s_dmi *dmi); +void compute_chassis(struct s_my_menu *menu,s_dmi *dmi); +void compute_bios(struct s_my_menu *menu,s_dmi *dmi); +void compute_memory(struct s_hdt_menu *menu, s_dmi *dmi); +void compute_memory_module(struct s_my_menu *menu, s_dmi *dmi, int slot_number); + +// Processor Stuff +void compute_processor(struct s_my_menu *menu,struct s_hardware *hardware); + +// Syslinux stuff +void compute_syslinuxmenu(struct s_my_menu *menu,struct s_hardware *hardware); + +// About menu +void compute_aboutmenu(struct s_my_menu *menu); + +// Summary menu +void compute_summarymenu(struct s_my_menu *menu, struct s_hardware *hardware); + +//PXE menu +void compute_PXE(struct s_my_menu *menu,struct s_hardware *hardware); + +int start_menu_mode(struct s_hardware *hardware, char *version_string); +void setup_menu(char *version); +void compute_main_menu(struct s_hdt_menu *hdt_menu, struct s_hardware *hardware); +void compute_submenus(struct s_hdt_menu *hdt_menu,struct s_hardware *hardware); +void detect_hardware(struct s_hardware *hardware); +#endif diff --git a/com32/hdt/hdt.c b/com32/hdt/hdt.c new file mode 100644 index 00000000..b417d9da --- /dev/null +++ b/com32/hdt/hdt.c @@ -0,0 +1,79 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- +*/ + +/* + * hdt.c + * + * An Hardware Detection Tool + */ + +#include <stdio.h> +#include <console.h> +#include "hdt.h" +#include "hdt-menu.h" +#include "hdt-cli.h" +#include "hdt-common.h" + +int display_line_nb=0; + +int main(int argc, char *argv[]) +{ + char version_string[256]; + char *arg; + struct s_hardware hardware; + + snprintf(version_string,sizeof version_string,"%s %s by %s",PRODUCT_NAME,VERSION,AUTHOR); + + /* Cleaning structures */ + init_hardware(&hardware); + + /* Detecting parameters */ + detect_parameters(argc,argv,&hardware); + + /* Detecting Syslinux Version*/ + detect_syslinux(&hardware); + + /* Opening the syslinux console */ + openconsole(&dev_stdcon_r, &dev_ansicon_w); + + clear_screen(); + printf("%s\n",version_string); + + if ((arg = find_argument(argv+1, "nomenu"))) { + start_cli_mode(&hardware, argc, argv); + } else{ + int return_code = start_menu_mode(&hardware, version_string); + if (return_code == HDT_RETURN_TO_CLI) { + start_cli_mode(&hardware,argc,argv); + } else { + return return_code; + } + } + + return 0; +} diff --git a/com32/hdt/hdt.h b/com32/hdt/hdt.h new file mode 100644 index 00000000..b8563ab5 --- /dev/null +++ b/com32/hdt/hdt.h @@ -0,0 +1,42 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- +*/ + +#ifndef DEFINE_HDT_H +#define DEFINE_HDT_H + +#define PRODUCT_NAME "Hardware Detection Tool" +#define AUTHOR "Erwan Velu" +#define CONTACT "erwan(dot)velu(point)free(dot)fr" +#define VERSION "0.2.3" + +#define ATTR_PACKED __attribute__((packed)) + +#define WITH_PCI 1 +#define WITH_MENU_DISPLAY 1 + +#endif diff --git a/com32/include/dmi/dmi_processor.h b/com32/include/dmi/dmi_processor.h deleted file mode 100644 index 26ac97ac..00000000 --- a/com32/include/dmi/dmi_processor.h +++ /dev/null @@ -1,482 +0,0 @@ -/* ----------------------------------------------------------------------- * - * - * Copyright 2006 Erwan Velu - 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 DMI_PROCESSOR_H -#define DMI_PROCESSOR_H - -#include "stdbool.h" -#define PROCESSOR_SOCKET_DESIGNATION_SIZE 32 -#define PROCESSOR_TYPE_SIZE 32 -#define PROCESSOR_FAMILY_SIZE 32 -#define PROCESSOR_MANUFACTURER_SIZE 64 -#define PROCESSOR_VERSION_SIZE 32 -#define PROCESSOR_VOLTAGE_SIZE 16 -#define PROCESSOR_STATUS_SIZE 16 -#define PROCESSOR_UPGRADE_SIZE 16 -#define PROCESSOR_CACHE_SIZE 16 -#define PROCESSOR_SERIAL_SIZE 32 -#define PROCESSOR_ASSET_TAG_SIZE 32 -#define PROCESSOR_PART_NUMBER_SIZE 32 -#define PROCESSOR_ID_SIZE 32 - -#define PROCESSOR_FLAGS_ELEMENTS 32 -/* Intel AP-485 revision 28, table 5 */ -static const char *cpu_flags_strings[32]={ - "FPU (Floating-point unit on-chip)", /* 0 */ - "VME (Virtual mode extension)", - "DE (Debugging extension)", - "PSE (Page size extension)", - "TSC (Time stamp counter)", - "MSR (Model specific registers)", - "PAE (Physical address extension)", - "MCE (Machine check exception)", - "CX8 (CMPXCHG8 instruction supported)", - "APIC (On-chip APIC hardware supported)", - NULL, /* 10 */ - "SEP (Fast system call)", - "MTRR (Memory type range registers)", - "PGE (Page global enable)", - "MCA (Machine check architecture)", - "CMOV (Conditional move instruction supported)", - "PAT (Page attribute table)", - "PSE-36 (36-bit page size extension)", - "PSN (Processor serial number present and enabled)", - "CLFSH (CLFLUSH instruction supported)", - NULL, /* 20 */ - "DS (Debug store)", - "ACPI (ACPI supported)", - "MMX (MMX technology supported)", - "FXSR (Fast floating-point save and restore)", - "SSE (Streaming SIMD extensions)", - "SSE2 (Streaming SIMD extensions 2)", - "SS (Self-snoop)", - "HTT (Hyper-threading technology)", - "TM (Thermal monitor supported)", - NULL, /* 30 */ - "PBE (Pending break enabled)" /* 31 */ -}; - -/* this struct have PROCESSOR_FLAGS_ELEMENTS */ -/* each bool is associated to the relevant message above */ -typedef struct { -bool fpu; -bool vme; -bool de; -bool pse; -bool tsc; -bool msr; -bool pae; -bool mce; -bool cx8; -bool apic; -bool null_10; -bool sep; -bool mtrr; -bool pge; -bool mca; -bool cmov; -bool pat; -bool pse_36; -bool psn; -bool clfsh; -bool null_20; -bool ds; -bool acpi; -bool mmx; -bool fxsr; -bool sse; -bool sse2; -bool ss; -bool htt; -bool tm; -bool null_30; -bool pbe; -} __attribute__((__packed__)) s_cpu_flags; - -typedef struct { -u8 type; -u8 family; -u8 model; -u8 stepping; -u8 minor_stepping; -} __attribute__((__packed__)) s_signature; - -typedef struct { -char socket_designation[PROCESSOR_SOCKET_DESIGNATION_SIZE]; -char type[PROCESSOR_TYPE_SIZE]; -char family[PROCESSOR_FAMILY_SIZE]; -char manufacturer[PROCESSOR_MANUFACTURER_SIZE]; -char version[PROCESSOR_VERSION_SIZE]; -float voltage; -u16 external_clock; -u16 max_speed; -u16 current_speed; -char status[PROCESSOR_STATUS_SIZE]; -char upgrade[PROCESSOR_UPGRADE_SIZE]; -char cache1[PROCESSOR_CACHE_SIZE]; -char cache2[PROCESSOR_CACHE_SIZE]; -char cache3[PROCESSOR_CACHE_SIZE]; -char serial[PROCESSOR_SERIAL_SIZE]; -char asset_tag[PROCESSOR_ASSET_TAG_SIZE]; -char part_number[PROCESSOR_PART_NUMBER_SIZE]; -char id[PROCESSOR_ID_SIZE]; -s_cpu_flags cpu_flags; -s_signature signature; -} s_processor; - -static const char *dmi_processor_type(u8 code) -{ - /* 3.3.5.1 */ - static const char *type[]={ - "Other", /* 0x01 */ - "Unknown", - "Central Processor", - "Math Processor", - "DSP Processor", - "Video Processor" /* 0x06 */ - }; - - if(code>=0x01 && code<=0x06) - return type[code-0x01]; - return out_of_spec; -} - -static const char *dmi_processor_family(u8 code) -{ - /* 3.3.5.2 */ - static const char *family[]={ - NULL, /* 0x00 */ - "Other", - "Unknown", - "8086", - "80286", - "80386", - "80486", - "8087", - "80287", - "80387", - "80487", - "Pentium", - "Pentium Pro", - "Pentium II", - "Pentium MMX", - "Celeron", - "Pentium II Xeon", - "Pentium III", - "M1", - "M2", - NULL, /* 0x14 */ - NULL, - NULL, - NULL, /* 0x17 */ - "Duron", - "K5", - "K6", - "K6-2", - "K6-3", - "Athlon", - "AMD2900", - "K6-2+", - "Power PC", - "Power PC 601", - "Power PC 603", - "Power PC 603+", - "Power PC 604", - "Power PC 620", - "Power PC x704", - "Power PC 750", - NULL, /* 0x28 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL,/* 0x2F */ - "Alpha", - "Alpha 21064", - "Alpha 21066", - "Alpha 21164", - "Alpha 21164PC", - "Alpha 21164a", - "Alpha 21264", - "Alpha 21364", - NULL, /* 0x38 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 0x3F */ - "MIPS", - "MIPS R4000", - "MIPS R4200", - "MIPS R4400", - "MIPS R4600", - "MIPS R10000", - NULL, /* 0x46 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 0x4F */ - "SPARC", - "SuperSPARC", - "MicroSPARC II", - "MicroSPARC IIep", - "UltraSPARC", - "UltraSPARC II", - "UltraSPARC IIi", - "UltraSPARC III", - "UltraSPARC IIIi", - NULL, /* 0x59 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 0x5F */ - "68040", - "68xxx", - "68000", - "68010", - "68020", - "68030", - NULL, /* 0x66 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 0x6F */ - "Hobbit", - NULL, /* 0x71 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 0x77 */ - "Crusoe TM5000", - "Crusoe TM3000", - "Efficeon TM8000", - NULL, /* 0x7B */ - NULL, - NULL, - NULL, - NULL, /* 0x7F */ - "Weitek", - NULL, /* 0x81 */ - "Itanium", - "Athlon 64", - "Opteron", - "Sempron", - NULL, /* 0x86 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 0x8F */ - "PA-RISC", - "PA-RISC 8500", - "PA-RISC 8000", - "PA-RISC 7300LC", - "PA-RISC 7200", - "PA-RISC 7100LC", - "PA-RISC 7100", - NULL, /* 0x97 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 0x9F */ - "V30", - NULL, /* 0xA1 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 0xAF */ - "Pentium III Xeon", - "Pentium III Speedstep", - "Pentium 4", - "Xeon", - "AS400", - "Xeon MP", - "Athlon XP", - "Athlon MP", - "Itanium 2", - "Pentium M", - NULL, /* 0xBA */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 0xC7 */ - "IBM390", - "G4", - "G5", - NULL, /* 0xCB */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 0xF9 */ - "i860", - "i960", - NULL, /* 0xFC */ - NULL, - NULL, - NULL /* 0xFF */ - /* master.mif has values beyond that, but they can't be used for DMI */ - }; - - if(family[code]!=NULL) { - return family[code]; - } - return out_of_spec; -} - -static const char *dmi_processor_status(u8 code) -{ - static const char *status[]={ - "Unknown", /* 0x00 */ - "Enabled", - "Disabled By User", - "Disabled By BIOS", - "Idle", /* 0x04 */ - "Other" /* 0x07 */ - }; - - if(code<=0x04) - return status[code]; - if(code==0x07) - return status[0x05]; - return out_of_spec; -} -static const char *dmi_processor_upgrade(u8 code) -{ - /* 3.3.5.5 */ - static const char *upgrade[]={ - "Other", /* 0x01 */ - "Unknown", - "Daughter Board", - "ZIF Socket", - "Replaceable Piggy Back", - "None", - "LIF Socket", - "Slot 1", - "Slot 2", - "370-pin Socket", - "Slot A", - "Slot M", - "Socket 423", - "Socket A (Socket 462)", - "Socket 478", - "Socket 754", - "Socket 940", - "Socket 939" /* 0x12 */ - }; - - if(code>=0x01 && code<=0x11) - return upgrade[code-0x01]; - return out_of_spec; -} - -static void dmi_processor_cache(u16 code, const char *level, u16 ver, char *cache) -{ - if(code==0xFFFF) - { - if(ver>=0x0203) - sprintf(cache,"Not Provided"); - else - sprintf(cache,"No %s Cache", level); - } - else - sprintf(cache,"0x%04X", code); -} - - -#endif diff --git a/com32/include/string.h b/com32/include/string.h index af9792b6..c964ee3b 100644 --- a/com32/include/string.h +++ b/com32/include/string.h @@ -23,6 +23,7 @@ __extern char *strcat(char *, const char *); __extern char *strchr(const char *, int); __extern int strcmp(const char *, const char *); __extern char *strcpy(char *, const char *); +__extern char *strpcpy(char *, const char *); __extern size_t strcspn(const char *, const char *); __extern char *strdup(const char *); __extern char *strndup(const char *, size_t); diff --git a/com32/include/sys/pci.h b/com32/include/sys/pci.h index 1de095af..fad7250c 100644 --- a/com32/include/sys/pci.h +++ b/com32/include/sys/pci.h @@ -4,18 +4,32 @@ #include <inttypes.h> #include <sys/io.h> -#define MAX_PCI_FUNC 8 -#define MAX_PCI_DEVICES 32 -#define MAX_PCI_BUSES 256 +#define MAX_PCI_FUNC 8 +#define MAX_PCI_DEVICES 32 +#define MAX_PCI_BUSES 256 +#define LINUX_KERNEL_MODULE_SIZE 64 +#define PCI_VENDOR_NAME_SIZE 256 +#define PCI_PRODUCT_NAME_SIZE 256 +#define PCI_CLASS_NAME_SIZE 256 +#define MAX_KERNEL_MODULES_PER_PCI_DEVICE 10 +#define MAX_PCI_CLASSES 256 typedef uint32_t pciaddr_t; +enum { + ENOPCIIDS = 100, + ENOMODULESPCIMAP +}; + /* a structure for extended pci information */ /* XXX: use pointers for these? */ struct pci_dev_info { - char vendor_name[256]; - char product_name[256]; - char linux_kernel_module[64]; + char vendor_name[PCI_VENDOR_NAME_SIZE]; + char product_name[PCI_PRODUCT_NAME_SIZE]; + char linux_kernel_module[LINUX_KERNEL_MODULE_SIZE][MAX_KERNEL_MODULES_PER_PCI_DEVICE]; + int linux_kernel_module_count; + char class_name[PCI_CLASS_NAME_SIZE]; /* The most precise class name */ + char category_name[PCI_CLASS_NAME_SIZE]; /*The general category*/ }; /* PCI device (really, function) */ @@ -117,7 +131,8 @@ struct pci_domain *pci_scan(void); void free_pci_domain(struct pci_domain *domain); struct match * find_pci_device(const struct pci_domain *pci_domain, struct match *list); -int get_name_from_pci_ids(struct pci_domain *pci_domain); -int get_module_name_from_pci_ids(struct pci_domain *pci_domain); +int get_name_from_pci_ids(struct pci_domain *pci_domain, char *pciids_path); +int get_module_name_from_pci_ids(struct pci_domain *pci_domain, char *modules_pcimap_path); +int get_class_name_from_pci_ids(struct pci_domain *pci_domain, char *pciids_path); #endif /* _SYS_PCI_H */ diff --git a/com32/include/syslinux/pxe.h b/com32/include/syslinux/pxe.h index 7550817f..31a4041e 100644 --- a/com32/include/syslinux/pxe.h +++ b/com32/include/syslinux/pxe.h @@ -62,6 +62,38 @@ typedef struct { uint16_t seg; } segoff16_t; +typedef struct { +uint8_t opcode; +#define BOOTP_REQ 1 +#define BOOTP_REP 2 +uint8_t Hardware; +uint8_t Hardlen; +uint8_t Gatehops; +uint32_t ident; +uint16_t seconds; +uint16_t Flags; +#define BOOTP_BCAST 0x8000 +in_addr_t cip; /* Client IP address*/ +in_addr_t yip; /* You IP address*/ +in_addr_t sip; /* next server IP address*/ +in_addr_t gip; /*relay agent IP address */ +mac_addr_t CAddr; +uint8_t Sname[64]; +uint8_t bootfile[128]; +union + { + #define BOOTP_DHCPVEND 1024 + uint8_t d[BOOTP_DHCPVEND]; + struct { + uint8_t magic[4]; + #define VM_RFC1048 0x63825363L + uint32_t flags; + uint8_t pad[56]; + } v; + } vendor; +} __packed pxe_bootp_t; + + /* Function calling structures and constants */ typedef struct s_PXENV_GET_CACHED_INFO @@ -528,5 +560,6 @@ typedef struct s_PXENV_UNDI_ISR /* SYSLINUX-defined PXE utility functions */ int pxe_get_cached_info(int level, void **buf, size_t *len); +int pxe_get_nic_type(t_PXENV_UNDI_GET_NIC_TYPE *gnt); #endif /* _SYSLINUX_PXE_H */ diff --git a/com32/lib/MCONFIG b/com32/lib/MCONFIG index e40cf83c..aea0ed74 100644 --- a/com32/lib/MCONFIG +++ b/com32/lib/MCONFIG @@ -1,6 +1,5 @@ # -*- makefile -*- -topdir = ../.. include $(topdir)/MCONFIG GCCOPT := $(call gcc_ok,-std=gnu99,) \ diff --git a/com32/lib/Makefile b/com32/lib/Makefile index 0cc40617..6c137f9d 100644 --- a/com32/lib/Makefile +++ b/com32/lib/Makefile @@ -1,4 +1,10 @@ +# +# ONLY INCLUDE MIT OR 2/3-BSD-LICENSED CODE IN THIS LIBRARY +# + # Include configuration rules +NOGPL := 1 +topdir = ../.. include MCONFIG LIBOBJS = \ @@ -11,8 +17,8 @@ LIBOBJS = \ exit.o onexit.o \ perror.o printf.o puts.o qsort.o realloc.o seed48.o snprintf.o \ sprintf.o srand48.o sscanf.o stack.o strcasecmp.o strcat.o \ - strchr.o strcmp.o strcpy.o strdup.o strerror.o strlen.o \ - strnlen.o \ + strchr.o strcmp.o strcpy.o strpcpy.o strdup.o strlen.o \ + strerror.o strnlen.o \ strncasecmp.o strncat.o strncmp.o strncpy.o strndup.o \ stpcpy.o stpncpy.o \ strntoimax.o strntoumax.o strrchr.o strsep.o strspn.o strstr.o \ @@ -92,7 +98,7 @@ LIBOBJS = \ syslinux/initramfs_file.o syslinux/initramfs_loadfile.o \ syslinux/initramfs_archive.o \ \ - syslinux/pxe_get_cached.o \ + syslinux/pxe_get_cached.o syslinux/pxe_get_nic.o \ \ syslinux/adv.o syslinux/advwrite.o syslinux/getadv.o \ syslinux/setadv.o @@ -113,7 +119,7 @@ libcom32.a : $(LIBOBJS) tidy dist clean: rm -f sys/vesa/alphatbl.c - find . \( -name \*.o -o -name .\*.d -o -name \*.tmp \) -print0 | \ + find . \( -name \*.o -o -name \*.a -o -name .\*.d -o -name \*.tmp \) -print0 | \ xargs -0r rm -f spotless: clean diff --git a/com32/lib/pci/scan.c b/com32/lib/pci/scan.c index 98df0dd3..cfd9e654 100644 --- a/com32/lib/pci/scan.c +++ b/com32/lib/pci/scan.c @@ -73,7 +73,7 @@ static int hex_to_int(char *hexa) /* Try to match any pci device to the appropriate kernel module */ /* it uses the modules.pcimap from the boot device */ -int get_module_name_from_pci_ids(struct pci_domain *domain) +int get_module_name_from_pci_ids(struct pci_domain *domain, char *modules_pcimap_path) { char line[MAX_LINE]; char module_name[21]; // the module name field is 21 char long @@ -94,18 +94,21 @@ int get_module_name_from_pci_ids(struct pci_domain *domain) if (!dev->dev_info) return -1; } - strcpy(dev->dev_info->linux_kernel_module, "unknown"); + for (int i=0;i<MAX_KERNEL_MODULES_PER_PCI_DEVICE;i++) { + strlcpy(dev->dev_info->linux_kernel_module[i], "unknown",7); + } } /* Opening the modules.pcimap (of a linux kernel) from the boot device */ - f=fopen("modules.pcimap", "r"); + f=fopen(modules_pcimap_path, "r"); if (!f) - return -1; + return -ENOMODULESPCIMAP; strcpy(vendor_id,"0000"); strcpy(product_id,"0000"); strcpy(sub_product_id,"0000"); strcpy(sub_vendor_id,"0000"); + dev->dev_info->linux_kernel_module_count=0; /* for each line we found in the modules.pcimap */ while ( fgets(line, sizeof line, f) ) { @@ -134,35 +137,136 @@ int get_module_name_from_pci_ids(struct pci_domain *domain) /* Searching the next field */ result = strtok( NULL, delims ); } + int int_vendor_id=hex_to_int(vendor_id); + int int_sub_vendor_id=hex_to_int(sub_vendor_id); + int int_product_id=hex_to_int(product_id); + int int_sub_product_id=hex_to_int(sub_product_id); /* if a pci_device matches an entry, fill the linux_kernel_module with the appropriate kernel module */ for_each_pci_func(dev, domain) { - if (hex_to_int(vendor_id) == dev->vendor && - hex_to_int(product_id) == dev->product && - (hex_to_int(sub_product_id) & dev->sub_product) + if (int_vendor_id == dev->vendor && + int_product_id == dev->product && + (int_sub_product_id & dev->sub_product) == dev->sub_product && - (hex_to_int(sub_vendor_id) & dev->sub_vendor) - == dev->sub_vendor) - strcpy(dev->dev_info->linux_kernel_module, module_name); + (int_sub_vendor_id & dev->sub_vendor) + == dev->sub_vendor) { + strcpy(dev->dev_info->linux_kernel_module[dev->dev_info->linux_kernel_module_count], module_name); + dev->dev_info->linux_kernel_module_count++; + } + } + } + fclose(f); + return 0; +} + +/* Try to match any pci device to the appropriate class name */ +/* it uses the pci.ids from the boot device */ +int get_class_name_from_pci_ids(struct pci_domain *domain, char *pciids_path) +{ + char line[MAX_LINE]; + char class_name[PCI_CLASS_NAME_SIZE]; + char sub_class_name[PCI_CLASS_NAME_SIZE]; + char class_id_str[5]; + char sub_class_id_str[5]; + FILE *f; + struct pci_device *dev; + bool class_mode=false; + + /* Intializing the vendor/product name for each pci device to "unknown" */ + /* adding a dev_info member if needed */ + for_each_pci_func(dev, domain) { + /* initialize the dev_info structure if it doesn't exist yet. */ + if (! dev->dev_info) { + dev->dev_info = zalloc(sizeof *dev->dev_info); + if (!dev->dev_info) + return -1; + } + strlcpy(dev->dev_info->class_name,"unknown",7); + } + + /* Opening the pci.ids from the boot device */ + f = fopen(pciids_path,"r"); + if (!f) + return -ENOPCIIDS; + + /* for each line we found in the pci.ids */ + while ( fgets(line, sizeof line, f) ) { + /* Skipping uncessary lines */ + if ((line[0] == '#') || (line[0] == ' ') || + (line[0] == 10)) + continue; + + /* Until we found a line starting with a 'C', we are not parsing classes */ + if (line[0] == 'C') + class_mode=true; + if (class_mode == false) + continue; + strlcpy(class_name,"unknown",7); + /* If the line doesn't start with a tab, it means that's a class name */ + if (line[0] != '\t') { + + /* ignore the two first char and then copy 2 chars (class id)*/ + strlcpy(class_id_str,&line[2],2); + class_id_str[2]=0; + + /* the class name is the next field */ + strlcpy(class_name,skipspace(strstr(line," ")),PCI_CLASS_NAME_SIZE-1); + remove_eol(class_name); + + int int_class_id_str=hex_to_int(class_id_str); + /* assign the class_name to any matching pci device */ + for_each_pci_func(dev, domain) { + if (int_class_id_str == dev->class[2]) { + strlcpy(dev->dev_info->class_name,class_name,PCI_CLASS_NAME_SIZE-1); + /* This value is usually the main category*/ + strlcpy(dev->dev_info->category_name,class_name+4,PCI_CLASS_NAME_SIZE-1); + } + } + /* if we have a tab + a char, it means this is a sub class name */ + } else if ((line[0] == '\t') && (line[1] != '\t')) { + + /* the sub class name the second field */ + strlcpy(sub_class_name,skipspace(strstr(line," ")),PCI_CLASS_NAME_SIZE-1); + remove_eol(sub_class_name); + + /* the sub class id is first field */ + strlcpy(sub_class_id_str,&line[1],2); + sub_class_id_str[2]=0; + + int int_class_id_str=hex_to_int(class_id_str); + int int_sub_class_id_str=hex_to_int(sub_class_id_str); + /* assign the product_name to any matching pci device */ + for_each_pci_func(dev, domain) { + if (int_class_id_str == dev->class[2] && + int_sub_class_id_str == dev->class[1]) + strlcpy(dev->dev_info->class_name,sub_class_name,PCI_CLASS_NAME_SIZE-1); + } + } } fclose(f); return 0; } + /* Try to match any pci device to the appropriate vendor and product name */ /* it uses the pci.ids from the boot device */ -int get_name_from_pci_ids(struct pci_domain *domain) +int get_name_from_pci_ids(struct pci_domain *domain, char *pciids_path) { char line[MAX_LINE]; - char vendor[255]; + char vendor[PCI_VENDOR_NAME_SIZE]; char vendor_id[5]; - char product[255]; + char product[PCI_PRODUCT_NAME_SIZE]; char product_id[5]; char sub_product_id[5]; char sub_vendor_id[5]; FILE *f; struct pci_device *dev; + bool skip_to_next_vendor=false; + uint16_t int_vendor_id; + uint16_t int_product_id; + uint16_t int_sub_product_id; + uint16_t int_sub_vendor_id; /* Intializing the vendor/product name for each pci device to "unknown" */ /* adding a dev_info member if needed */ @@ -173,19 +277,19 @@ int get_name_from_pci_ids(struct pci_domain *domain) if (!dev->dev_info) return -1; } - strcpy(dev->dev_info->vendor_name,"unknown"); - strcpy(dev->dev_info->product_name,"unknown"); + strlcpy(dev->dev_info->vendor_name,"unknown",7); + strlcpy(dev->dev_info->product_name,"unknown",7); } /* Opening the pci.ids from the boot device */ - f = fopen("pci.ids","r"); + f = fopen(pciids_path,"r"); if (!f) - return -1; + return -ENOPCIIDS; - strcpy(vendor_id,"0000"); - strcpy(product_id,"0000"); - strcpy(sub_product_id,"0000"); - strcpy(sub_vendor_id,"0000"); + strlcpy(vendor_id,"0000",4); + strlcpy(product_id,"0000",4); + strlcpy(sub_product_id,"0000",4); + strlcpy(sub_vendor_id,"0000",4); /* for each line we found in the pci.ids */ while ( fgets(line, sizeof line, f) ) { @@ -193,6 +297,7 @@ int get_name_from_pci_ids(struct pci_domain *domain) if ((line[0] == '#') || (line[0] == ' ') || (line[0] == 'C') || (line[0] == 10)) continue; + /* If the line doesn't start with a tab, it means that's a vendor id */ if (line[0] != '\t') { @@ -201,26 +306,35 @@ int get_name_from_pci_ids(struct pci_domain *domain) /* the vendor name is the next field */ vendor_id[4]=0; - strlcpy(vendor,skipspace(strstr(line," ")),255); + strlcpy(vendor,skipspace(strstr(line," ")),PCI_VENDOR_NAME_SIZE-1); remove_eol(vendor); /* init product_id, sub_product and sub_vendor */ - strcpy(product_id,"0000"); - strcpy(sub_product_id,"0000"); - strcpy(sub_vendor_id,"0000"); + strlcpy(product_id,"0000",4); + strlcpy(sub_product_id,"0000",4); + strlcpy(sub_vendor_id,"0000",4); - /* ffff is an invalid vendor id */ - if (strstr(vendor_id,"ffff")) break; - /* assign the vendor_name to any matching pci device */ + /* Unless we found a matching device, we have to skip to the next vendor */ + skip_to_next_vendor=true; + + int_vendor_id=hex_to_int(vendor_id); + /* Iterate in all pci devices to find a matching vendor */ for_each_pci_func(dev, domain) { - if (hex_to_int(vendor_id) == dev->vendor) - strlcpy(dev->dev_info->vendor_name,vendor,255); + /* if one device that match this vendor */ + if (int_vendor_id == dev->vendor) { + /* copy the vendor name for this device */ + strlcpy(dev->dev_info->vendor_name,vendor,PCI_VENDOR_NAME_SIZE-1); + /* Some pci devices match this vendor, so we have to found them */ + skip_to_next_vendor=false; + /* Let's loop on the other devices as some may have the same vendor */ + } } - /* if we have a tab + a char, it means this is a product id */ - } else if ((line[0] == '\t') && (line[1] != '\t')) { + /* if we have a tab + a char, it means this is a product id + * but we only look at it if we own some pci devices of the current vendor*/ + } else if ((line[0] == '\t') && (line[1] != '\t') && (skip_to_next_vendor == false)) { /* the product name the second field */ - strlcpy(product,skipspace(strstr(line," ")),255); + strlcpy(product,skipspace(strstr(line," ")),PCI_PRODUCT_NAME_SIZE-1); remove_eol(product); /* the product id is first field */ @@ -228,22 +342,27 @@ int get_name_from_pci_ids(struct pci_domain *domain) product_id[4]=0; /* init sub_product and sub_vendor */ - strcpy(sub_product_id,"0000"); - strcpy(sub_vendor_id,"0000"); + strlcpy(sub_product_id,"0000",4); + strlcpy(sub_vendor_id,"0000",4); + int_vendor_id=hex_to_int(vendor_id); + int_product_id=hex_to_int(product_id); /* assign the product_name to any matching pci device */ for_each_pci_func(dev, domain) { - if (hex_to_int(vendor_id) == dev->vendor && - hex_to_int(product_id) == dev->product) - strlcpy(dev->dev_info->product_name,product,255); + if (int_vendor_id == dev->vendor && + int_product_id == dev->product) { + strlcpy(dev->dev_info->vendor_name,vendor,PCI_VENDOR_NAME_SIZE-1); + strlcpy(dev->dev_info->product_name,product,PCI_PRODUCT_NAME_SIZE-1); + } } - /* if we have two tabs, it means this is a sub product */ - } else if ((line[0] == '\t') && (line[1] == '\t')) { + /* if we have two tabs, it means this is a sub product + * but we only look at it if we own some pci devices of the current vendor*/ + } else if ((line[0] == '\t') && (line[1] == '\t') && (skip_to_next_vendor == false)) { /* the product name is last field */ - strlcpy(product,skipspace(strstr(line," ")),255); - strlcpy(product,skipspace(strstr(product," ")),255); + strlcpy(product,skipspace(strstr(line," ")),PCI_PRODUCT_NAME_SIZE-1); + strlcpy(product,skipspace(strstr(product," ")),PCI_PRODUCT_NAME_SIZE-1); remove_eol(product); /* the sub_vendor id is first field */ @@ -254,13 +373,19 @@ int get_name_from_pci_ids(struct pci_domain *domain) strlcpy(sub_product_id,&line[7],4); sub_product_id[4]=0; + int_vendor_id=hex_to_int(vendor_id); + int_sub_vendor_id=hex_to_int(sub_vendor_id); + int_product_id=hex_to_int(product_id); + int_sub_product_id=hex_to_int(sub_product_id); /* assign the product_name to any matching pci device */ for_each_pci_func(dev, domain) { - if (hex_to_int(vendor_id) == dev->vendor && - hex_to_int(product_id) == dev->product && - hex_to_int(sub_product_id) == dev->sub_product && - hex_to_int(sub_vendor_id) == dev->sub_vendor) - strlcpy(dev->dev_info->product_name,product,255); + if (int_vendor_id == dev->vendor && + int_product_id == dev->product && + int_sub_product_id == dev->sub_product && + int_sub_vendor_id == dev->sub_vendor) { + strlcpy(dev->dev_info->vendor_name,vendor,PCI_VENDOR_NAME_SIZE-1); + strlcpy(dev->dev_info->product_name,product,PCI_PRODUCT_NAME_SIZE-1); + } } } } diff --git a/com32/lib/strpcpy.c b/com32/lib/strpcpy.c new file mode 100644 index 00000000..e181e78f --- /dev/null +++ b/com32/lib/strpcpy.c @@ -0,0 +1,20 @@ +/* + * strpcpy.c + * + * strpcpy() - strcpy() which returns a pointer to the final null + */ + +#include <string.h> + +char *strpcpy(char *dst, const char *src) +{ + char *q = dst; + const char *p = src; + char ch; + + do { + *q++ = ch = *p++; + } while ( ch ); + + return q-1; +} diff --git a/com32/lib/syslinux/pxe_get_nic.c b/com32/lib/syslinux/pxe_get_nic.c new file mode 100644 index 00000000..b779542c --- /dev/null +++ b/com32/lib/syslinux/pxe_get_nic.c @@ -0,0 +1,61 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - 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. + * + * ----------------------------------------------------------------------- */ + +/* + * pxe_get_cached.c + * + * PXE call "get cached info" + */ + +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <com32.h> + +#include <syslinux/pxe.h> + +/* Returns the status code from PXE (0 on success), + or -1 on invocation failure */ +int pxe_get_nic_type(t_PXENV_UNDI_GET_NIC_TYPE *gnt) +{ + com32sys_t regs; + + memset(®s, 0, sizeof regs); + regs.eax.w[0] = 0x0009; + regs.ebx.w[0] = PXENV_UNDI_GET_NIC_TYPE; + regs.es = SEG( __com32.cs_bounce); + regs.edi.w[0] = OFFS( __com32.cs_bounce); + + __intcall(0x22, ®s, ®s); + + memcpy(gnt, __com32.cs_bounce, sizeof(t_PXENV_UNDI_GET_NIC_TYPE)); + + if (regs.eflags.l & EFLAGS_CF) + return -1; + + return gnt->Status; +} diff --git a/com32/modules/Makefile b/com32/modules/Makefile index 930e89b6..5a8a88c4 100644 --- a/com32/modules/Makefile +++ b/com32/modules/Makefile @@ -1,6 +1,6 @@ ## ----------------------------------------------------------------------- ## -## Copyright 2001-2008 H. Peter Anvin - All Rights Reserved +## Copyright 2001-2009 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 @@ -29,10 +29,14 @@ all: $(MODULES) $(TESTFILES) pcitest.elf : pcitest.o $(LIBS) $(C_LIBS) $(LD) $(LDFLAGS) -o $@ $^ -cpuidtest.elf : cpuidtest.o cpuid.o $(LIBS) $(C_LIBS) +cpuidtest.elf : cpuidtest.o $(GPLLIB) $(LIBS) $(C_LIBS) $(LD) $(LDFLAGS) -o $@ $^ -dmitest.elf : dmitest.o dmi_utils.o dmi.o $(LIBS) $(C_LIBS) +.PRECIOUS: %.o +dmitest.o: dmitest.c + $(CC) $(CFLAGS) $(GPLINCLUDE) -c -o $@ $< + +dmitest.elf : dmi_utils.o dmitest.o $(GPLLIB) $(LIBS) $(C_LIBS) $(LD) $(LDFLAGS) -o $@ $^ ethersel.elf : ethersel.o $(LIBS) $(C_LIBS) diff --git a/com32/modules/cmd.c b/com32/modules/cmd.c index f0b0a968..e1d646b5 100644 --- a/com32/modules/cmd.c +++ b/com32/modules/cmd.c @@ -18,7 +18,6 @@ #include <string.h> #include <alloca.h> -#include <console.h> #include <com32.h> int main(int argc, const char *argv[]) @@ -28,15 +27,17 @@ int main(int argc, const char *argv[]) char *tmp; int i; - openconsole(&dev_stdcon_r, &dev_stdcon_w); - for (i = 1; i < argc; i++) len += strlen(argv[i]) + 1; tmp = cmd = alloca(len); - for (i = 1; i < argc; i++) - tmp += sprintf(tmp, "%s%s", argv[i], (i == argc-1) ? "" : " "); + for (i = 1; i < argc; i++) { + tmp = strpcpy(tmp, argv[i]); + if (i != argc-1) + *tmp++ = ' '; + } + *tmp = '\0'; syslinux_run_command(cmd); } diff --git a/com32/modules/dmi_utils.c b/com32/modules/dmi_utils.c index df03ba7c..e0baa873 100644 --- a/com32/modules/dmi_utils.c +++ b/com32/modules/dmi_utils.c @@ -51,7 +51,7 @@ int i; void display_base_board_features(s_dmi *dmi) { int i; - for (i=0;i<=BASE_BOARD_NB_ELEMENTS; i++) { + for (i=0;i<BASE_BOARD_NB_ELEMENTS; i++) { if (((bool *)(& dmi->base_board.features))[i] == true) { moreprintf("\t\t%s\n", base_board_features_strings[i]); } @@ -60,7 +60,7 @@ int i; void display_processor_flags(s_dmi *dmi) { int i; - for (i=0;i<=PROCESSOR_FLAGS_ELEMENTS; i++) { + for (i=0;i<PROCESSOR_FLAGS_ELEMENTS; i++) { if (((bool *)(& dmi->processor.cpu_flags))[i] == true) { moreprintf("\t\t%s\n", cpu_flags_strings[i]); } diff --git a/com32/modules/dmitest.c b/com32/modules/dmitest.c index 64f0635d..07febc51 100644 --- a/com32/modules/dmitest.c +++ b/com32/modules/dmitest.c @@ -39,6 +39,44 @@ char display_line; +void display_memory(s_dmi *dmi) { + int i; + for (i=0;i<dmi->memory_count;i++) { + moreprintf("Memory Bank %d\n",i); + moreprintf("\tForm Factor : %s\n",dmi->memory[i].form_factor); + moreprintf("\tType : %s\n",dmi->memory[i].type); + moreprintf("\tType Detail : %s\n",dmi->memory[i].type_detail); + moreprintf("\tSpeed : %s\n",dmi->memory[i].speed); + moreprintf("\tSize : %s\n",dmi->memory[i].size); + moreprintf("\tDevice Set : %s\n",dmi->memory[i].device_set); + moreprintf("\tDevice Loc. : %s\n",dmi->memory[i].device_locator); + moreprintf("\tBank Locator : %s\n",dmi->memory[i].bank_locator); + moreprintf("\tTotal Width : %s\n",dmi->memory[i].total_width); + moreprintf("\tData Width : %s\n",dmi->memory[i].data_width); + moreprintf("\tError : %s\n",dmi->memory[i].error); + moreprintf("\tVendor : %s\n",dmi->memory[i].manufacturer); + moreprintf("\tSerial : %s\n",dmi->memory[i].serial); + moreprintf("\tAsset Tag : %s\n",dmi->memory[i].asset_tag); + moreprintf("\tPart Number : %s\n",dmi->memory[i].part_number); + } +} + +void display_battery(s_dmi *dmi) { + moreprintf("Battery\n"); + moreprintf("\tVendor : %s\n",dmi->battery.manufacturer); + moreprintf("\tManufacture Date : %s\n",dmi->battery.manufacture_date); + moreprintf("\tSerial : %s\n",dmi->battery.serial); + moreprintf("\tName : %s\n",dmi->battery.name); + moreprintf("\tChemistry : %s\n",dmi->battery.chemistry); + moreprintf("\tDesign Capacity : %s\n",dmi->battery.design_capacity); + moreprintf("\tDesign Voltage : %s\n",dmi->battery.design_voltage); + moreprintf("\tSBDS : %s\n",dmi->battery.sbds); + moreprintf("\tSBDS Manufact. Date : %s\n",dmi->battery.sbds_manufacture_date); + moreprintf("\tSBDS Chemistry : %s\n",dmi->battery.sbds_chemistry); + moreprintf("\tMaximum Error : %s\n",dmi->battery.maximum_error); + moreprintf("\tOEM Info : %s\n",dmi->battery.oem_info); +} + void display_bios(s_dmi *dmi) { moreprintf("BIOS\n"); moreprintf("\tVendor: %s\n",dmi->bios.vendor); @@ -126,15 +164,20 @@ int main(void) s_dmi dmi; openconsole(&dev_stdcon_r, &dev_stdcon_w); - if ( ! dmi_interate() ) { - printf("No DMI Structure found\n"); - return -1; + if (dmi_iterate(&dmi) == -ENODMITABLE) { + printf("No DMI Structure found\n"); + return -1; + } else { + printf("DMI %d.%d present.\n",dmi.dmitable.major_version,dmi.dmitable.minor_version); + printf("%d structures occupying %d bytes.\n",dmi.dmitable.num, dmi.dmitable.len); + printf("DMI table at 0x%08X.\n",dmi.dmitable.base); } + parse_dmitable(&dmi); for (;;) { - printf("Available commands are system, chassis, base_board, cpu, bios, all, exit\n"); + printf("Available commands are system, chassis, base_board, cpu, bios, memory, battery, all, exit\n"); printf("dmi: "); fgets(buffer, sizeof buffer, stdin); if ( !strncmp(buffer, "exit", 4) ) @@ -149,12 +192,18 @@ int main(void) display_cpu(&dmi); if ( !strncmp(buffer, "bios", 4) ) display_bios(&dmi); + if ( !strncmp(buffer, "memory", 6) ) + display_memory(&dmi); + if ( !strncmp(buffer, "battery", 7) ) + display_battery(&dmi); if ( !strncmp(buffer, "all", 3) ) { display_bios(&dmi); display_system(&dmi); display_chassis(&dmi); display_base_board(&dmi); display_cpu(&dmi); + display_memory(&dmi); + display_battery(&dmi); } } diff --git a/com32/modules/pcitest.c b/com32/modules/pcitest.c index 240f19f2..00647535 100644 --- a/com32/modules/pcitest.c +++ b/com32/modules/pcitest.c @@ -46,7 +46,7 @@ # define dprintf(...) ((void)0) #endif -char display_line; +char display_line=0; #define moreprintf(...) \ do { \ display_line++; \ @@ -61,34 +61,82 @@ char display_line; void display_pci_devices(struct pci_domain *pci_domain) { struct pci_device *pci_device; - int ndev = 0; + char kernel_modules [LINUX_KERNEL_MODULE_SIZE*MAX_KERNEL_MODULES_PER_PCI_DEVICE]; + for_each_pci_func(pci_device, pci_domain) { - printf("[%02x:%02x.%01x]: %s: %04x:%04x[%04x:%04x]) %s:%s\n", - __pci_bus, __pci_slot, __pci_func, - pci_device->dev_info->linux_kernel_module, - pci_device->vendor, pci_device->product, - pci_device->sub_vendor, pci_device->sub_product, - pci_device->dev_info->vendor_name, - pci_device->dev_info->product_name); - ndev++; + + memset(kernel_modules,0,sizeof kernel_modules); + +/* printf("PCI: found %d kernel modules for %04x:%04x[%04x:%04x]\n", + pci_device->dev_info->linux_kernel_module_count, + pci_device->vendor, pci_device->product, + pci_device->sub_vendor, pci_device->sub_product); +*/ + for (int i=0; i<pci_device->dev_info->linux_kernel_module_count;i++) { + if (i>0) { + strncat(kernel_modules," | ",3); + } + strncat(kernel_modules, pci_device->dev_info->linux_kernel_module[i],LINUX_KERNEL_MODULE_SIZE-1); + } + + moreprintf("%04x:%04x[%04x:%04x]: %s\n", + pci_device->vendor, pci_device->product, + pci_device->sub_vendor, pci_device->sub_product, + pci_device->dev_info->class_name); + + moreprintf(" Vendor Name : %s\n", pci_device->dev_info->vendor_name); + moreprintf(" Product Name : %s\n", pci_device->dev_info->product_name); + moreprintf(" PCI bus position : %02x:%02x.%01x\n", __pci_bus, __pci_slot, __pci_func); + moreprintf(" Kernel modules : %s\n\n",kernel_modules); } - printf("PCI: %d devices found\n", ndev); } int main(int argc, char *argv[]) { struct pci_domain *pci_domain; + int return_code=0; + int nb_pci_devices=0; - openconsole(&dev_null_r, &dev_stdcon_w); + openconsole(&dev_stdcon_r, &dev_stdcon_w); /* Scanning to detect pci buses and devices */ + printf("PCI: Scanning PCI BUS\n"); pci_domain = pci_scan(); + struct pci_device *pci_device; + for_each_pci_func(pci_device, pci_domain) { + nb_pci_devices++; + } + + printf("PCI: %d PCI devices found\n",nb_pci_devices); + + + printf("PCI: Looking for device name\n"); /* Assigning product & vendor name for each device*/ - get_name_from_pci_ids(pci_domain); + return_code=get_name_from_pci_ids(pci_domain,"pci.ids"); + if (return_code == -ENOPCIIDS) { + printf("PCI: ERROR !\n"); + printf("PCI: Unable to open pci.ids in the same directory as pcitest.c32.\n"); + printf("PCI: PCI Device names can't be computed.\n"); + } + + printf("PCI: Resolving class names\n"); + /* Assigning class name for each device*/ + return_code=get_class_name_from_pci_ids(pci_domain,"pci.ids"); + if (return_code == -ENOPCIIDS) { + printf("PCI: ERROR !\n"); + printf("PCI: Unable to open pci.ids in the same directory as pcitest.c32.\n"); + printf("PCI: PCI class names can't be computed.\n"); + } + printf("PCI: Looking for Kernel modules\n"); /* Detecting which kernel module should match each device */ - get_module_name_from_pci_ids(pci_domain); + return_code=get_module_name_from_pci_ids(pci_domain,"modules.pcimap"); + if (return_code == -ENOMODULESPCIMAP) { + printf("PCI: ERROR !\n"); + printf("PCI: Unable to open modules.pcimap in the same directory as pcitest.c32.\n"); + printf("PCI: Kernel Module names can't be computed.\n"); + } /* display the pci devices we found */ display_pci_devices(pci_domain); |