diff options
Diffstat (limited to 'contrib/syslinux-4.02/com32')
748 files changed, 148838 insertions, 0 deletions
diff --git a/contrib/syslinux-4.02/com32/LICENCE b/contrib/syslinux-4.02/com32/LICENCE new file mode 100644 index 0000000..7eec786 --- /dev/null +++ b/contrib/syslinux-4.02/com32/LICENCE @@ -0,0 +1,32 @@ +libcom32 and libutil are licensed under the MIT license: + +## ----------------------------------------------------------------------- +## +## Copyright 2004-2009 H. Peter Anvin - All Rights Reserved +## Portions Copyright 2009 Intel Corporation; author: H. Peter Anvin +## +## 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. +## +## ----------------------------------------------------------------------- + +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/contrib/syslinux-4.02/com32/MCONFIG b/contrib/syslinux-4.02/com32/MCONFIG new file mode 100644 index 0000000..a74ed32 --- /dev/null +++ b/contrib/syslinux-4.02/com32/MCONFIG @@ -0,0 +1,98 @@ +## -*- makefile -*- ------------------------------------------------------- +## +## Copyright 2008-2009 H. Peter Anvin - All Rights Reserved +## Copyright 2009 Intel Corporation; author: H. Peter Anvin +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, +## Boston MA 02110-1301, USA; either version 2 of the License, or +## (at your option) any later version; incorporated herein by reference. +## +## ----------------------------------------------------------------------- + +## +## COM32 common configurables +## + +include $(topdir)/MCONFIG + +GCCOPT := $(call gcc_ok,-std=gnu99,) +GCCOPT += $(call gcc_ok,-m32,) +GCCOPT += $(call gcc_ok,-fno-stack-protector,) +GCCOPT += $(call gcc_ok,-fwrapv,) +GCCOPT += $(call gcc_ok,-freg-struct-return,) +GCCOPT += -mregparm=3 -DREGPARM=3 -march=i386 -Os +GCCOPT += $(call gcc_ok,-fPIE,-fPIC) +GCCOPT += $(call gcc_ok,-fno-exceptions,) +GCCOPT += $(call gcc_ok,-fno-asynchronous-unwind-tables,) +GCCOPT += $(call gcc_ok,-fno-strict-aliasing,) +GCCOPT += $(call gcc_ok,-falign-functions=0,-malign-functions=0) +GCCOPT += $(call gcc_ok,-falign-jumps=0,-malign-jumps=0) +GCCOPT += $(call gcc_ok,-falign-labels=0,-malign-labels=0) +GCCOPT += $(call gcc_ok,-falign-loops=0,-malign-loops=0) +GCCOPT += $(call gcc_ok,-mpreferred-stack-boundary=2,) +GCCOPT += $(call gcc_ok,-incoming-stack-boundary=2,) + +com32 := $(topdir)/com32 +RELOCS := $(com32)/tools/relocs + +ifneq ($(NOGPL),1) +GPLLIB = $(com32)/gpllib/libcom32gpl.a +GPLINCLUDE = -I$(com32)/gplinclude +else +GPLLIB = +GPLINCLUDE = +endif + +CFLAGS = $(GCCOPT) $(GCCWARN) -march=i386 \ + -fomit-frame-pointer -D__COM32__ \ + -nostdinc -iwithprefix include \ + -I$(com32)/libutil/include -I$(com32)/include $(GPLINCLUDE) +SFLAGS = $(GCCOPT) $(GCCWARN) -march=i386 \ + -fomit-frame-pointer -D__COM32__ \ + -nostdinc -iwithprefix include \ + -I$(com32)/libutil/include -I$(com32)/include $(GPLINCLUDE) + +COM32LD = $(com32)/lib/com32.ld +LDFLAGS = -m elf_i386 --emit-relocs -T $(COM32LD) +LIBGCC := $(shell $(CC) $(GCCOPT) --print-libgcc) + +LNXCFLAGS = -I$(com32)/libutil/include $(GCCWARN) -O -g \ + -D_GNU_SOURCE -D_FORTIFY_SOURCE=0 -Wno-error +LNXSFLAGS = -g +LNXLDFLAGS = -g + +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 + +.PRECIOUS: %.o +%.o: %.S + $(CC) $(MAKEDEPS) $(SFLAGS) -c -o $@ $< + +.PRECIOUS: %.o +%.o: %.c + $(CC) $(MAKEDEPS) $(CFLAGS) -c -o $@ $< + +.PRECIOUS: %.elf +%.elf: %.o $(LIBS) $(C_LIBS) $(COM32LD) + $(LD) $(LDFLAGS) -o $@ $(filter-out $(COM32LD),$^) + +.PRECIOUS: %.lo +%.lo: %.S + $(CC) $(MAKEDEPS) $(LNXSFLAGS) -c -o $@ $< + +.PRECIOUS: %.lo +%.lo: %.c + $(CC) $(MAKEDEPS) $(LNXCFLAGS) -c -o $@ $< + +.PRECIOUS: %.lnx +%.lnx: %.lo $(LNXLIBS) $(C_LNXLIBS) + $(CC) $(LNXCFLAGS) -o $@ $^ + +%.c32: %.elf + $(OBJCOPY) -O binary $< $@ + $(RELOCS) $< >> $@ || ( rm -f $@ ; false ) diff --git a/contrib/syslinux-4.02/com32/Makefile b/contrib/syslinux-4.02/com32/Makefile new file mode 100644 index 0000000..b090c40 --- /dev/null +++ b/contrib/syslinux-4.02/com32/Makefile @@ -0,0 +1,5 @@ +SUBDIRS = tools lib gpllib libutil modules mboot menu samples rosh cmenu \ + hdt gfxboot sysdump lua/src + +all tidy dist clean spotless install: + set -e; for d in $(SUBDIRS); do $(MAKE) -C $$d $@; done diff --git a/contrib/syslinux-4.02/com32/cmenu/.gitignore b/contrib/syslinux-4.02/com32/cmenu/.gitignore new file mode 100644 index 0000000..4add14b --- /dev/null +++ b/contrib/syslinux-4.02/com32/cmenu/.gitignore @@ -0,0 +1,2 @@ +test.c +test2.c diff --git a/contrib/syslinux-4.02/com32/cmenu/CHANGES b/contrib/syslinux-4.02/com32/cmenu/CHANGES new file mode 100644 index 0000000..cce2183 --- /dev/null +++ b/contrib/syslinux-4.02/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/contrib/syslinux-4.02/com32/cmenu/HISTORY b/contrib/syslinux-4.02/com32/cmenu/HISTORY new file mode 100644 index 0000000..8e9beb3 --- /dev/null +++ b/contrib/syslinux-4.02/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/contrib/syslinux-4.02/com32/cmenu/MANUAL b/contrib/syslinux-4.02/com32/cmenu/MANUAL new file mode 100644 index 0000000..4e70149 --- /dev/null +++ b/contrib/syslinux-4.02/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/contrib/syslinux-4.02/com32/cmenu/MENU_FORMAT b/contrib/syslinux-4.02/com32/cmenu/MENU_FORMAT new file mode 100644 index 0000000..24cb02f --- /dev/null +++ b/contrib/syslinux-4.02/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/contrib/syslinux-4.02/com32/cmenu/Makefile b/contrib/syslinux-4.02/com32/cmenu/Makefile new file mode 100644 index 0000000..794af74 --- /dev/null +++ b/contrib/syslinux-4.02/com32/cmenu/Makefile @@ -0,0 +1,68 @@ +## ----------------------------------------------------------------------- +## +## Copyright 2001-2009 H. Peter Anvin - All Rights Reserved +## Copyright 2009 Intel Corporation; author: H. Peter Anvin +## +## 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 + +all: menus + +libmenu/libmenu.a: $(LIBMENU) + -rm -f $@ + $(AR) cq $@ $^ + $(RANLIB) $@ + +tidy dist: + rm -f *.o *.lo *.a *.lst *.elf .*.d */.*.d + +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 + +-include .*.d */.*.d diff --git a/contrib/syslinux-4.02/com32/cmenu/README b/contrib/syslinux-4.02/com32/cmenu/README new file mode 100644 index 0000000..d585d2f --- /dev/null +++ b/contrib/syslinux-4.02/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/contrib/syslinux-4.02/com32/cmenu/TODO b/contrib/syslinux-4.02/com32/cmenu/TODO new file mode 100644 index 0000000..d2ee82c --- /dev/null +++ b/contrib/syslinux-4.02/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/contrib/syslinux-4.02/com32/cmenu/adv_menu.tpl b/contrib/syslinux-4.02/com32/cmenu/adv_menu.tpl new file mode 100644 index 0000000..871c782 --- /dev/null +++ b/contrib/syslinux-4.02/com32/cmenu/adv_menu.tpl @@ -0,0 +1,465 @@ +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> +#include <unistd.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(void) +{ + return timeout(timeoutcmd); +} + +TIMEOUTCODE ontotaltimeout(void) +{ + return timeout(totaltimeoutcmd); +} + +void keys_handler(t_menusystem * ms __attribute__ (( unused )), t_menuitem * mi, int scancode) +{ + int nc, nr; + + if (getscreensize(1, &nr, &nc)) { + /* Unknown screen size? */ + nc = 80; + nr = 24; + } + + if ( (scancode == KEY_F1) && (mi->helpid != 0xFFFF) ) { // If scancode of F1 and non-trivial helpid + runhelpsystem(mi->helpid); + } + + // If user hit TAB, and item is an "executable" item + // and user has privileges to edit it, edit it in place. + if ((scancode == KEY_TAB) && (mi->action == OPT_RUN) && + (EDIT_ROW < nr) && (EDIT_ROW > 0) && + (isallowed(username,"editcmd") || isallowed(username,"root"))) { + // User typed TAB and has permissions to edit command line + gotoxy(EDIT_ROW,1); + csprint("Command line:",0x07); + editstring(mi->data,ACTIONLEN); + gotoxy(EDIT_ROW,1); + cprint(' ',0x07,nc-1); + } +} + +t_handler_return login_handler(t_menusystem *ms, t_menuitem *mi) +{ + (void)mi; // Unused + char pwd[40]; + char login[40]; + int nc, nr; + t_handler_return rv; + + (void)ms; + + rv = ACTION_INVALID; + if (PWD_ROW < 0) return rv; // No need to authenticate + + if (mi->item == loginstr) { /* User wants to login */ + if (getscreensize(1, &nr, &nc)) { + /* Unknown screen size? */ + nc = 80; + nr = 24; + } + + gotoxy(PWD_ROW,1); + csprint("Enter Username: ",0x07); + getstring(login, sizeof username); + gotoxy(PWD_ROW,1); + cprint(' ',0x07,nc); + csprint("Enter Password: ",0x07); + getpwd(pwd, sizeof pwd); + gotoxy(PWD_ROW,1); + cprint(' ',0x07,nc); + + 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/contrib/syslinux-4.02/com32/cmenu/complex.c b/contrib/syslinux-4.02/com32/cmenu/complex.c new file mode 100644 index 0000000..b80005d --- /dev/null +++ b/contrib/syslinux-4.02/com32/cmenu/complex.c @@ -0,0 +1,450 @@ +/* -*- 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> +#include <unistd.h> +#include <getkey.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(void) +{ + 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 __attribute__ (( unused )), t_menuitem * mi, int scancode) +{ + int nc, nr; + + if ((scancode) == KEY_F1 && mi->helpid != 0xFFFF) { // If scancode of F1 + runhelpsystem(mi->helpid); + } + // If user hit TAB, and item is an "executable" item + // and user has privileges to edit it, edit it in place. + if ((scancode == KEY_TAB) && (mi->action == OPT_RUN) && + (isallowed(username, "editcmd") || isallowed(username, "root"))) { + if (getscreensize(1, &nr, &nc)) { + /* Unknown screen size? */ + nc = 80; + nr = 24; + } + // User typed TAB and has permissions to edit command line + gotoxy(EDITPROMPT, 1); + csprint("Command line:", 0x07); + editstring(mi->data, ACTIONLEN); + gotoxy(EDITPROMPT, 1); + clear_line(); + } +} + +t_handler_return login_handler(t_menusystem * ms, t_menuitem * mi) +{ + (void)mi; // Unused + char pwd[40]; + char login[40]; + int nc, nr; + t_handler_return rv; + + (void)ms; + + if (mi->item == loginstr) { /* User wants to login */ + if (getscreensize(1, &nr, &nc)) { + /* Unknown screen size? */ + nc = 80; + nr = 24; + } + gotoxy(PWDPROMPT, 1); + csprint("Enter Username: ", 0x07); + getstring(login, sizeof username); + gotoxy(PWDPROMPT, 1); + clear_line(); + csprint("Enter Password: ", 0x07); + getpwd(pwd, sizeof pwd); + gotoxy(PWDPROMPT, 1); + clear_line(); + + 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; + rv.reserved = 0; + return rv; +} + +void msys_handler(t_menusystem * ms, t_menuitem * mi) +{ + int nc, nr; + void *v; + + if (getscreensize(1, &nr, &nc)) { + /* Unknown screen size? */ + nc = 80; + nr = 24; + } + gotoxy(PWDLINE, PWDCOLUMN); + csprint("User: ", PWDATTR); + cprint(ms->fillchar, ms->fillattr, sizeof username); + gotoxy(PWDLINE, PWDCOLUMN + 6); + csprint(username, PWDATTR); + + if (mi->parindex != PREPMENU) // If we are not in the PREP MENU + { + gotoxy(INFLINE, 0); + reset_colors(); + clear_line(); + gotoxy(INFLINE + 1, 0); + clear_line(); + 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); + reset_colors(); + clear_line(); + gotoxy(INFLINE + 1, 0); + clear_line(); + gotoxy(INFLINE, 0); + csprint("Kernel Arguments:", 0x07); + gotoxy(INFLINE, 17); + 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 */ + + t_handler_return rv; + + 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); + + rv.valid = 0; + rv.refresh = 1; + rv.reserved = 0; + return rv; +} + +int main(void) +{ + 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, 10, 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 (get_key(stdin, 50) == KEY_NONE) // Granularity of 100 milliseconds + { + csprint("Sorry! Time's up.\r\n", 0x07); + return 1; + } + 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/contrib/syslinux-4.02/com32/cmenu/display.c b/contrib/syslinux-4.02/com32/cmenu/display.c new file mode 100644 index 0000000..3acdf6a --- /dev/null +++ b/contrib/syslinux-4.02/com32/cmenu/display.c @@ -0,0 +1,36 @@ +/* -*- 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/contrib/syslinux-4.02/com32/cmenu/libmenu/com32io.c b/contrib/syslinux-4.02/com32/cmenu/libmenu/com32io.c new file mode 100644 index 0000000..8e5016b --- /dev/null +++ b/contrib/syslinux-4.02/com32/cmenu/libmenu/com32io.c @@ -0,0 +1,72 @@ +/* -*- 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 "tui.h" +#include "syslnx.h" + +com32sys_t inreg, outreg; // Global register sets for use + +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); +} + +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 = 0; // XXX TODO + 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); +} + +void setvideomode(char mode) +{ + REG_AH(inreg) = 0x00; + REG_AL(inreg) = mode; + __intcall(0x10, &inreg, &outreg); +} + +// 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/contrib/syslinux-4.02/com32/cmenu/libmenu/com32io.h b/contrib/syslinux-4.02/com32/cmenu/libmenu/com32io.h new file mode 100644 index 0000000..d9cce3d --- /dev/null +++ b/contrib/syslinux-4.02/com32/cmenu/libmenu/com32io.h @@ -0,0 +1,66 @@ +/* -*- 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> +#include <stdio.h> +#include <libansi.h> + +#ifndef NULL +#define NULL ((void *)0) +#endif + +/* 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) + +/* BIOS Assisted output routines */ + +void getpos(char *row, char *col, char page); + +char inputc(char *scancode); // Return ASCII char by val, and scancode by reference + +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 unsigned char readbiosb(unsigned int ofs) +{ + return *((unsigned char *)MK_PTR(0, ofs)); +} + +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 + +void setvideomode(char mode); // Set the video mode. + +static inline char getvideomode(void) // Get the current video mode +{ + return readbiosb(0x449); +} + +#endif diff --git a/contrib/syslinux-4.02/com32/cmenu/libmenu/des.c b/contrib/syslinux-4.02/com32/cmenu/libmenu/des.c new file mode 100644 index 0000000..37148b2 --- /dev/null +++ b/contrib/syslinux-4.02/com32/cmenu/libmenu/des.c @@ -0,0 +1,1064 @@ +/* + * 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; + char *p, packed_keys[8]; + + p = 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 = (my_u_char_t *)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/contrib/syslinux-4.02/com32/cmenu/libmenu/des.h b/contrib/syslinux-4.02/com32/cmenu/libmenu/des.h new file mode 100644 index 0000000..d820d42 --- /dev/null +++ b/contrib/syslinux-4.02/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/contrib/syslinux-4.02/com32/cmenu/libmenu/help.c b/contrib/syslinux-4.02/com32/cmenu/libmenu/help.c new file mode 100644 index 0000000..0df1e10 --- /dev/null +++ b/contrib/syslinux-4.02/com32/cmenu/libmenu/help.c @@ -0,0 +1,232 @@ +/* -*- 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 + +int nc, nr; // Number of columns/rows of the screen +char helpbasedir[HELPDIRLEN]; // name of help directory limited to HELPDIRLEN + +// Find the occurence of the count'th \n in buffer (or NULL) if not found +static 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 +static 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 +static void printtext(char *buf, int from) +{ + char *f, *t; + int right, nlines, i; + + // clear window to print + right = nc - HELP_RIGHT_MARGIN; + nlines = nr - HELP_BODY_ROW - HELP_BOTTOM_MARGIN - 1; + + f = findline(buf, from); + if (!f) + return; // nothing to print + if (*f == '\n') + f++; // start of from+1st line + t = f; + while (i < nlines) { + gotoxy(HELP_BODY_ROW + i, HELP_LEFT_MARGIN); + clear_end_of_line(); + putchar(SO); + gotoxy(HELP_BODY_ROW + i, nc - 1); + putch(LEFT_BORDER, 0x07); + putchar(SI); + + gotoxy(HELP_BODY_ROW + i, HELP_LEFT_MARGIN); + while (*t != '\n') { + if (*t == '\0') + return; + putchar(*t); + t++; + } + putchar('\n'); + t++; + i++; + } +} + +void showhelp(const char *filename) +{ + char ph; + char *title, *text; + union { + char *buffer; + void *vbuf; + } buf; // This is to avoild type-punning issues + + char line[512]; + size_t size; + int scan; + int rv, numlines, curr_line; + + if (getscreensize(1, &nr, &nc)) { + /* Unknown screen size? */ + nc = 80; + nr = 24; + } + ph = nr - HELP_BODY_ROW; + cls(); + + /* Turn autowrap off, to avoid scrolling the menu */ + printf(CSI "?7l"); + + if (filename == NULL) { // print file contents + strcpy(line, "Filename not given"); + goto puke; + } + + rv = loadfile(filename, (void **)&buf.vbuf, &size); // load entire file into memory + if (rv < 0) { // Error reading file or no such file + sprintf(line, "Error reading file or file not found\n file=%s", filename); + goto puke; + } + + 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. + numlines = countlines(text); + curr_line = 0; + scan = KEY_ESC + 1; // anything except ESCAPE + + /* top, left, bottom, right, attr */ + drawbox(0, 0, nr - 1, nc - 1, 0x07); + while (scan != KEY_ESC) { + /* Title */ + gotoxy(1, (nc - strlen(title)) / 2); + fputs(title, stdout); + drawhorizline(2, HELP_LEFT_MARGIN - 1, nc - HELP_RIGHT_MARGIN, 0x07, 0); // dumb==0 + /* Text */ + printtext(text, curr_line); + gotoxy(HELP_BODY_ROW - 1, nc - HELP_RIGHT_MARGIN); + if (curr_line > 0) + putchar(HELP_MORE_ABOVE); + else + putchar(' '); + gotoxy(nr - HELP_BOTTOM_MARGIN - 1, nc - HELP_RIGHT_MARGIN); + if (curr_line < numlines - ph) + putchar(HELP_MORE_BELOW); + else + putchar(' '); + + scan = get_key(stdout, 0); // wait for user keypress + + switch (scan) { + case KEY_HOME: + curr_line = 0; + break; + case KEY_END: + curr_line = numlines; + break; + case KEY_UP: + curr_line--; + break; + case KEY_DOWN: + curr_line++; + break; + case KEY_PGUP: + curr_line -= ph; + break; + case KEY_PGDN: + curr_line += ph; + break; + default: + break; + } + if (curr_line > numlines - ph) + curr_line = numlines - ph; + if (curr_line < 0) + curr_line = 0; + } +out: + cls(); + return; + +puke: + gotoxy(HELP_BODY_ROW, HELP_LEFT_MARGIN); + fputs(line, stdout); + while (1) { + scan = get_key(stdin, 0); + if (scan == KEY_ESC) + break; + } + goto out; +} + +void runhelp(const char *filename) +{ + char fullname[HELPDIRLEN + 16]; + + cls(); + cursoroff(); + if (helpbasedir[0] != 0) { + strcpy(fullname, helpbasedir); + strcat(fullname, "/"); + strcat(fullname, filename); + showhelp(fullname); + } else + showhelp(filename); // Assume filename is absolute +} + +void runhelpsystem(unsigned int helpid) +{ + char filename[15]; + + sprintf(filename, "hlp%05d.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/contrib/syslinux-4.02/com32/cmenu/libmenu/help.h b/contrib/syslinux-4.02/com32/cmenu/libmenu/help.h new file mode 100644 index 0000000..de01b46 --- /dev/null +++ b/contrib/syslinux-4.02/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 1 // Number of lines not use from bottom of screen + +#define HELPBOX BOX_SINSIN +#define HELPDIRLEN 64 +#define HELPPAGE 2 + +#define HELP_MORE_ABOVE '^' // to print when more is available above +#define HELP_MORE_BELOW 'v' // same as above but for below + +// Display one screen of help information +void showhelp(const char *filename); + +// 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/contrib/syslinux-4.02/com32/cmenu/libmenu/menu.c b/contrib/syslinux-4.02/com32/cmenu/libmenu/menu.c new file mode 100644 index 0000000..1375476 --- /dev/null +++ b/contrib/syslinux-4.02/com32/cmenu/libmenu/menu.c @@ -0,0 +1,1273 @@ +/* -*- 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> +#include <console.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. +static int getch(void) +{ + t_timeout_handler th; + int key; + unsigned long i; + + // Wait until keypress if no handler specified + if ((ms->ontimeout == NULL) && (ms->ontotaltimeout == NULL)) + return get_key(stdin, 0); + + th = ms->ontimeout; + for (;;) { + for (i = 0; i < ms->tm_numsteps; i++) { + key = get_key(stdin, ms->tm_stepsize); + if (key != KEY_NONE) + return key; + + if ((ms->tm_total_timeout == 0) || (ms->ontotaltimeout == NULL)) + continue; // Dont bother with calculations if no handler + ms->tm_sofar_timeout += ms->tm_stepsize; + if (ms->tm_sofar_timeout >= ms->tm_total_timeout) { + th = ms->ontotaltimeout; + ms->tm_sofar_timeout = 0; + break; // Get out of the for loop + } + } + if (!th) + continue; // no handler + key = th(); + switch (key) { + case CODE_ENTER: // Pretend user hit enter + return KEY_ENTER; + case CODE_ESCAPE: // Pretend user hit escape + return KEY_ESC; + default: + break; + } + } + return KEY_NONE; +} + +int find_shortcut(pt_menu menu, uchar shortcut, int index) +// 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 +} + +/* Redraw background and title */ +static void reset_ui(void) +{ + uchar tpos; + + cls(); + clearwindow(ms->minrow, ms->mincol, ms->maxrow, ms->maxcol, + ms->fillchar, ms->fillattr); + + tpos = (ms->numcols - strlen(ms->title) - 1) >> 1; // center it on line + gotoxy(ms->minrow, ms->mincol); + cprint(ms->tfillchar, ms->titleattr, ms->numcols); + gotoxy(ms->minrow, ms->mincol + tpos); + csprint(ms->title, ms->titleattr); + + cursoroff(); +} + +/* + * Print a menu item + * + * attr[0] is non-hilite attr, attr[1] is highlight attr + */ +void printmenuitem(const char *str, uchar * attr) +{ + int hlite = NOHLITE; // Initially no highlighting + + while (*str) { + switch (*str) { + case BELL: // No Bell Char + break; + case ENABLEHLITE: // Switch on highlighting + hlite = HLITE; + break; + case DISABLEHLITE: // Turn off highlighting + hlite = NOHLITE; + break; + default: + putch(*str, attr[hlite]); + } + str++; + } +} + + +/** + * print_line - Print a whole line in a menu + * @menu: current menu to handle + * @curr: index of the current entry highlighted + * @top: top coordinate of the @menu + * @left: left coordinate of the @menu + * @x: index in the menu of curr + * @row: row currently displayed + * @radio: radio item? + **/ +static void print_line(pt_menu menu, int curr, uchar top, uchar left, + int x, int row, bool radio) +{ + pt_menuitem ci; + char fchar[6], lchar[6]; // The first and last char in for each entry + const char *str; // Item string (cf printmenuitem) + char sep[MENULEN]; // Separator (OPT_SEP) + uchar *attr; // Attribute + int menuwidth = menu->menuwidth + 3; + + if (row >= menu->menuheight) + return; + + ci = menu->items[x]; + + memset(sep, ms->box_horiz, menuwidth); + sep[menuwidth - 1] = 0; + + // Setup the defaults now + if (radio) { + fchar[0] = '\b'; + fchar[1] = SO; + fchar[2] = (x == curr ? RADIOSEL : RADIOUNSEL); + fchar[3] = SI; + fchar[4] = '\0'; // Unselected ( ) + lchar[0] = '\0'; // Nothing special after + attr = ms->normalattr; // Always same attribute + } else { + lchar[0] = fchar[0] = ' '; + lchar[1] = fchar[1] = '\0'; // fchar and lchar are just spaces + attr = (x == curr ? ms->reverseattr : ms->normalattr); // Normal attributes + } + str = ci->item; // Pointer to item string + switch (ci->action) // set up attr,str,fchar,lchar for everything + { + case OPT_INACTIVE: + if (radio) + attr = ms->inactattr; + else + attr = (x == curr ? ms->revinactattr : ms->inactattr); + break; + case OPT_SUBMENU: + if (radio) + break; // Not supported for radio menu + lchar[0] = '>'; + lchar[1] = 0; + break; + case OPT_RADIOMENU: + if (radio) + break; // Not supported for radio menu + lchar[0] = RADIOMENUCHAR; + lchar[1] = 0; + break; + case OPT_CHECKBOX: + if (radio) + break; // Not supported for radio menu + lchar[0] = '\b'; + lchar[1] = SO; + lchar[2] = (ci->itemdata.checked ? CHECKED : UNCHECKED); + lchar[3] = SI; + lchar[4] = 0; + break; + case OPT_SEP: + fchar[0] = '\b'; + fchar[1] = SO; + fchar[2] = LEFT_MIDDLE_BORDER; + fchar[3] = MIDDLE_BORDER; + fchar[4] = MIDDLE_BORDER; + fchar[5] = 0; + memset(sep, MIDDLE_BORDER, menuwidth); + sep[menuwidth - 1] = 0; + str = sep; + lchar[0] = MIDDLE_BORDER; + lchar[1] = RIGHT_MIDDLE_BORDER; + lchar[2] = SI; + lchar[3] = 0; + break; + case OPT_EXITMENU: + if (radio) + break; // Not supported for radio menu + fchar[0] = '<'; + fchar[1] = 0; + break; + default: // Just to keep the compiler happy + break; + } + + // Wipe area with spaces + gotoxy(top + row, left - 2); + cprint(ms->spacechar, attr[NOHLITE], menuwidth + 2); + + // Print first part + gotoxy(top + row, left - 2); + csprint(fchar, attr[NOHLITE]); + + // Print main part + gotoxy(top + row, left); + printmenuitem(str, attr); + + // Print last part + gotoxy(top + row, left + menuwidth - 1); + csprint(lchar, attr[NOHLITE]); +} + +// print the menu starting from FIRST +// will print a maximum of menu->menuheight items +static void printmenu(pt_menu menu, int curr, uchar top, uchar left, uchar first, bool radio) +{ + int x, row; // x = index, row = position from top + int numitems, menuwidth; + 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->fillchar, ms->shadowattr); + drawbox(top - 1, left - 3, top + numitems, left + menuwidth, + ms->normalattr[NOHLITE]); + + // Menu title + x = (menuwidth - strlen(menu->title) - 1) >> 1; + gotoxy(top - 1, left + x); + printmenuitem(menu->title, ms->normalattr); + + // All lines in the menu + row = -1; // 1 less than inital value of x + for (x = first; x < menu->numitems; x++) { + ci = menu->items[x]; + if (ci->action == OPT_INVISIBLE) + continue; + row++; + if (row >= numitems) + break; // Already have enough number of items + print_line(menu, curr, top, left, x, row, radio); + } + // Check if we need to MOREABOVE and MOREBELOW to be added + // reuse x + row = 0; + x = next_visible_sep(menu, 0); // First item + if (!isvisible(menu, first, x)) // There is more above + { + row = 1; + gotoxy(top, left + menuwidth); + cprint(MOREABOVE, ms->normalattr[NOHLITE], 1); + } + x = prev_visible_sep(menu, menu->numitems); // last item + if (!isvisible(menu, first, x)) // There is more above + { + row = 1; + gotoxy(top + numitems - 1, left + menuwidth); + cprint(MOREBELOW, ms->normalattr[NOHLITE], 1); + } + // Add a scroll box + x = ((numitems - 1) * curr) / (menu->numitems); + if ((x > 0) && (row == 1)) { + gotoxy(top + x, left + menuwidth); + csprint("\016\141\017", ms->normalattr[NOHLITE]); + } + 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->fillchar, ms->fillattr); // Clear the shadow + clearwindow(top - 1, left - 3, top + numitems, left + menu->menuwidth + 3, ms->fillchar, ms->fillattr); // main window +} + + +/* Handle one menu */ +static pt_menuitem getmenuoption(pt_menu menu, uchar top, uchar left, uchar startopt, bool radio) + // Return item chosen or NULL if ESC was hit. +{ + int prev, prev_first, curr, i, first, tmp; + int asc = 0; + bool redraw = true; // Need to draw the menu the first time + uchar numitems; + pt_menuitem ci; // Current item + t_handler_return hr; // Return value of handler + + numitems = calc_visible(menu, 0); + // Setup status line + gotoxy(ms->minrow + ms->statline, ms->mincol); + cprint(ms->spacechar, ms->statusattr[NOHLITE], ms->numcols); + + // Initialise current menu item + curr = next_visible(menu, startopt); + prev = curr; + + gotoxy(ms->minrow + ms->statline, ms->mincol); + cprint(ms->spacechar, ms->statusattr[NOHLITE], ms->numcols); + gotoxy(ms->minrow + ms->statline, ms->mincol); + printmenuitem(menu->items[curr]->status, ms->statusattr); + first = calc_first_early(menu, curr); + prev_first = first; + while (1) // Forever + { + /* Redraw everything if: + * + we need to scroll (take care of scroll bars, ...) + * + menuoption + */ + if (prev_first != first || redraw) { + printmenu(menu, curr, top, left, first, radio); + } else { + /* Redraw only the highlighted entry */ + print_line(menu, curr, top, left, prev, prev - first, radio); + print_line(menu, curr, top, left, curr, curr - first, radio); + } + redraw = false; + prev = curr; + prev_first = first; + ci = menu->items[curr]; + asc = getch(); + switch (asc) { + case KEY_CTRL('L'): + redraw = true; + break; + case KEY_HOME: + curr = next_visible(menu, 0); + first = calc_first_early(menu, curr); + break; + case KEY_END: + curr = prev_visible(menu, numitems - 1); + first = calc_first_late(menu, curr); + break; + case KEY_PGDN: + for (i = 0; i < 5; i++) + curr = next_visible(menu, curr + 1); + first = calc_first_late(menu, curr); + break; + case KEY_PGUP: + for (i = 0; i < 5; i++) + curr = prev_visible(menu, curr - 1); + first = calc_first_early(menu, curr); + break; + case KEY_UP: + curr = prev_visible(menu, curr - 1); + if (curr < first) + first = calc_first_early(menu, curr); + break; + case KEY_DOWN: + curr = next_visible(menu, curr + 1); + if (!isvisible(menu, first, curr)) + first = calc_first_late(menu, curr); + break; + case KEY_LEFT: + case KEY_ESC: + return NULL; + break; + case KEY_RIGHT: + case KEY_ENTER: + if (ci->action == OPT_INACTIVE) + break; + if (ci->action == OPT_CHECKBOX) + break; + if (ci->action == OPT_SEP) + break; + if (ci->action == OPT_EXITMENU) + return NULL; // As if we hit Esc + // If we are going into a radio menu, dont call handler, return ci + if (ci->action == OPT_RADIOMENU) + return ci; + if (ci->handler != NULL) // Do we have a handler + { + hr = ci->handler(ms, ci); + if (hr.refresh) // Do we need to refresh + { + // Cleanup menu using old number of items + cleanupmenu(menu, top, left, numitems); + // Recalculate the number of items + numitems = calc_visible(menu, 0); + // Reprint the menu + printmenu(menu, curr, top, left, first, radio); + } + if (hr.valid) + return ci; + } else + return ci; + break; + case SPACECHAR: + if (ci->action != OPT_CHECKBOX) + break; + ci->itemdata.checked = !ci->itemdata.checked; + if (ci->handler != NULL) // Do we have a handler + { + hr = ci->handler(ms, ci); + if (hr.refresh) // Do we need to refresh + { + // Cleanup menu using old number of items + cleanupmenu(menu, top, left, numitems); + // Recalculate the number of items + numitems = calc_visible(menu, 0); + // Reprint the menu + printmenu(menu, curr, top, left, first, radio); + } + } + break; + default: + // Check if this is a shortcut key + if (((asc >= 'A') && (asc <= 'Z')) || + ((asc >= 'a') && (asc <= 'z')) || + ((asc >= '0') && (asc <= '9'))) { + tmp = find_shortcut(menu, asc, curr); + if ((tmp > curr) && (!isvisible(menu, first, tmp))) + first = calc_first_late(menu, tmp); + if (tmp < curr) + first = calc_first_early(menu, tmp); + curr = tmp; + } else { + if (ms->keys_handler) // Call extra keys handler + ms->keys_handler(ms, menu->items[curr], asc); + + /* The handler may have changed the UI, reset it on exit */ + reset_ui(); + // Cleanup menu using old number of items + cleanupmenu(menu, top, left, numitems); + // Recalculate the number of items + numitems = calc_visible(menu, 0); + // Reprint the menu + printmenu(menu, curr, top, left, first, radio); + } + break; + } + // Update status line + /* Erase the previous status */ + gotoxy(ms->minrow + ms->statline, ms->mincol); + cprint(ms->spacechar, ms->statusattr[NOHLITE], ms->numcols); + /* Print the new status */ + gotoxy(ms->minrow + ms->statline, ms->mincol); + printmenuitem(menu->items[curr]->status, ms->statusattr); + } + return NULL; // Should never come here +} + +/* 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, false); + else // menutype == RADIOMENU + opt = getmenuoption(cmenu, top, left, startopt, true); + + if (opt == NULL) { + // User hit Esc + cleanupmenu(cmenu, top, left, calc_visible(cmenu, 0)); + return NULL; + } + // 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); // 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(void) +{ + 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; + + fix_submenus(); // Fix submenu numbers incase nick names were used + + /* Turn autowrap off, to avoid scrolling the menu */ + printf(CSI "?7l"); + + // Setup screen for menusystem + reset_ui(); + + // Go, main menu cannot be a radio menu + rv = runmenusystem(ms->minrow + MENUROW, ms->mincol + MENUCOL, + ms->menus[(unsigned int)startmenu], 0, NORMALMENU); + + // Hide the garbage we left on the screen + cursoron(); + cls(); + gotoxy(ms->minrow, ms->mincol); + + // 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 + if (getscreensize(1, &ms->numrows, &ms->numcols)) { + /* Unknown screen size? */ + ms->numcols = 80; + ms->numrows = 24; + } + ms->minrow = ms->mincol = 0; + 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; + + console_ansi_raw(); + + 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_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) +{ + int nr, nc; + + if ((top > bot) || (left > right)) + return; // Sorry no change will happen here + + if (getscreensize(1, &nr, &nc)) { + /* Unknown screen size? */ + nr = 80; + nc = 24; + } + if (bot >= nr) + bot = nr - 1; + 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(void) +{ + 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(void) +{ + 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(void) // 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; + + 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/contrib/syslinux-4.02/com32/cmenu/libmenu/menu.h b/contrib/syslinux-4.02/com32/cmenu/libmenu/menu.h new file mode 100644 index 0000000..141d2ef --- /dev/null +++ b/contrib/syslinux-4.02/com32/cmenu/libmenu/menu.h @@ -0,0 +1,294 @@ +/* -*- 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 <string.h> +#include <unistd.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 ' ' +#define FILLATTR NORMALATTR +#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 '^' // char to print when more menu items available above +#define MOREBELOW 'v' // more items available below + +// Attributes of the menu system +#define MAXMENUS 250 // Maximum number of menu's allowed +#define MAXMENUSIZE 100 // 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 RADIOMENUCHAR '>' // > symbol for radio menu? +#define CHECKED '\140' // Check mark +#define UNCHECKED '\146' // 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; + int maxrow, minrow, numrows; // Number of rows in the window + int maxcol, mincol, numcols; // Number of columns in the window + + // Menu box look + 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(void); // 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_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); + +void reg_ontotaltimeout(t_timeout_handler, unsigned long numcentiseconds); +void unreg_ontotaltimeout(void); + +// 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(void); + +// 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/contrib/syslinux-4.02/com32/cmenu/libmenu/passwords.c b/contrib/syslinux-4.02/com32/cmenu/libmenu/passwords.c new file mode 100644 index 0000000..44ce461 --- /dev/null +++ b/contrib/syslinux-4.02/com32/cmenu/libmenu/passwords.c @@ -0,0 +1,159 @@ +/* -*- 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(void) +{ + int i; + + for (i = 0; i < numusers; i++) + if (userdb[i] != NULL) + free(userdb[i]); + numusers = 0; +} diff --git a/contrib/syslinux-4.02/com32/cmenu/libmenu/passwords.h b/contrib/syslinux-4.02/com32/cmenu/libmenu/passwords.h new file mode 100644 index 0000000..2e0ec27 --- /dev/null +++ b/contrib/syslinux-4.02/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(void); + +#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/contrib/syslinux-4.02/com32/cmenu/libmenu/syslnx.c b/contrib/syslinux-4.02/com32/cmenu/libmenu/syslnx.c new file mode 100644 index 0000000..53e2401 --- /dev/null +++ b/contrib/syslinux-4.02/com32/cmenu/libmenu/syslnx.c @@ -0,0 +1,95 @@ +/* -*- 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; + + (void)ipappend; // XXX: Unused?! + + 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/contrib/syslinux-4.02/com32/cmenu/libmenu/syslnx.h b/contrib/syslinux-4.02/com32/cmenu/libmenu/syslnx.h new file mode 100644 index 0000000..29649e5 --- /dev/null +++ b/contrib/syslinux-4.02/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/contrib/syslinux-4.02/com32/cmenu/libmenu/tui.c b/contrib/syslinux-4.02/com32/cmenu/libmenu/tui.c new file mode 100644 index 0000000..dd69277 --- /dev/null +++ b/contrib/syslinux-4.02/com32/cmenu/libmenu/tui.c @@ -0,0 +1,258 @@ +/* -*- 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> +#include "com32io.h" + +com32sys_t inreg, outreg; // Global register sets for use + +char bkspstr[] = " \b$"; +char eolstr[] = "\n$"; + +// 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 int c; + char *p, *q; // p = current char of string, q = tmp + char *last; // The current last char of string + char *str; // pointer to string which is going to be allocated + char 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 + + getpos(&row, &col, 0); // 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); + csprint(str, GETSTRATTR); + } + while (1) { // Do forever + c = get_key(stdin, 0); + if (c == KEY_ENTER) + break; // User hit Enter getout of loop + if (c == KEY_ESC) // 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 (c) { + case KEY_HOME: + p = str; + break; + case KEY_END: + p = last; + break; + case KEY_LEFT: + if (p > str) + p--; + break; + case KEY_CTRL(KEY_LEFT): + 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 KEY_RIGHT: + if (p < last) + p++; + break; + case KEY_CTRL(KEY_RIGHT): + 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 KEY_DEL: + case KEY_DELETE: + q = p; + while (*(q + 1)) { + *q = *(q + 1); + q++; + } + if (last > str) + last--; + fudge = 1; + break; + case KEY_INSERT: + insmode = 1 - insmode; // Switch mode + if (insmode == 0) + setcursorshape(1, 7); // Block cursor + else + setcursorshape(6, 7); // Normal cursor + break; + case KEY_BACKSPACE: // 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 KEY_CTRL('U'): /* 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); + csprint(str, GETSTRATTR); + if (fudge > 0) + cprint(' ', GETSTRATTR, fudge); + gotoxy(row, col + (p - str)); + } + } /* while */ + *p = '\0'; + if (password == 0) + csprint("\r\n", GETSTRATTR); + setcursorshape(start, end); // Block cursor + // If user hit ESCAPE so return without any changes + if (c != KEY_ESC) + strcpy(stra, str); + free(str); +} + +//////////////////////////////Box Stuff + +// Draw box and lines +void drawbox(const char top, const char left, const char bot, + const char right, const char attr) +{ + unsigned char x; + putchar(SO); + // Top border + gotoxy(top, left); + putch(TOP_LEFT_CORNER_BORDER, attr); + cprint(TOP_BORDER, attr, right - left - 1); + putch(TOP_RIGHT_CORNER_BORDER, attr); + // Bottom border + gotoxy(bot, left); + putch(BOTTOM_LEFT_CORNER_BORDER, attr); + cprint(BOTTOM_BORDER, attr, right - left - 1); + putch(BOTTOM_RIGHT_CORNER_BORDER, attr); + // Left & right borders + for (x = top + 1; x < bot; x++) { + gotoxy(x, left); + putch(LEFT_BORDER, attr); + gotoxy(x, right); + putch(RIGHT_BORDER, attr); + } + putchar(SI); +} + +void drawhorizline(const char top, const char left, const char right, + const char attr, char dumb) +{ + unsigned char start, end; + if (dumb == 0) { + start = left + 1; + end = right - 1; + } else { + start = left; + end = right; + } + gotoxy(top, start); + putchar(SO); + cprint(MIDDLE_BORDER, attr, end - start + 1); + if (dumb == 0) { + gotoxy(top, left); + putch(MIDDLE_BORDER, attr); + gotoxy(top, right); + putch(MIDDLE_BORDER, attr); + } + putchar(SI); +} diff --git a/contrib/syslinux-4.02/com32/cmenu/libmenu/tui.h b/contrib/syslinux-4.02/com32/cmenu/libmenu/tui.h new file mode 100644 index 0000000..ed55487 --- /dev/null +++ b/contrib/syslinux-4.02/com32/cmenu/libmenu/tui.h @@ -0,0 +1,75 @@ +/* -*- 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 <getkey.h> +#include <consoles.h> +#include "syslnx.h" +#include "com32io.h" + +#ifndef NULL +#define NULL ((void *)0) +#endif + +#define SO '\016' +#define SI '\017' + +#define TOP_LEFT_CORNER_BORDER '\154' +#define TOP_BORDER '\161' +#define TOP_RIGHT_CORNER_BORDER '\153' +#define BOTTOM_LEFT_CORNER_BORDER '\155' +#define BOTTOM_BORDER '\161' +#define BOTTOM_RIGHT_CORNER_BORDER '\152' +#define LEFT_BORDER '\170' +#define RIGHT_BORDER '\170' +#define LEFT_MIDDLE_BORDER '\164' +#define MIDDLE_BORDER '\161' +#define RIGHT_MIDDLE_BORDER '\165' + +#define BELL 0x07 +#define GETSTRATTR 0x07 + +// 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); +} + +void drawbox(const char, const char, const char, const char, + const char); + +// Draw a horizontal line +// dumb == 1, means just draw the line +// dumb == 0 means check the first and last positions and depending on what is +// currently on the screen make it a LTRT and/or RTLT appropriately. +void drawhorizline(const char, const char, const char, const char, + const char dumb); + +#endif diff --git a/contrib/syslinux-4.02/com32/cmenu/menugen.py b/contrib/syslinux-4.02/com32/cmenu/menugen.py new file mode 100644 index 0000000..70ec1f8 --- /dev/null +++ b/contrib/syslinux-4.02/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/contrib/syslinux-4.02/com32/cmenu/password b/contrib/syslinux-4.02/com32/cmenu/password new file mode 100644 index 0000000..3caffe2 --- /dev/null +++ b/contrib/syslinux-4.02/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/contrib/syslinux-4.02/com32/cmenu/simple.c b/contrib/syslinux-4.02/com32/cmenu/simple.c new file mode 100644 index 0000000..4f602a9 --- /dev/null +++ b/contrib/syslinux-4.02/com32/cmenu/simple.c @@ -0,0 +1,82 @@ +/* -*- 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/contrib/syslinux-4.02/com32/cmenu/test.menu b/contrib/syslinux-4.02/com32/cmenu/test.menu new file mode 100644 index 0000000..061c548 --- /dev/null +++ b/contrib/syslinux-4.02/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/contrib/syslinux-4.02/com32/cmenu/test2.menu b/contrib/syslinux-4.02/com32/cmenu/test2.menu new file mode 100644 index 0000000..4570dc2 --- /dev/null +++ b/contrib/syslinux-4.02/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/contrib/syslinux-4.02/com32/gdbstub/Makefile b/contrib/syslinux-4.02/com32/gdbstub/Makefile new file mode 100644 index 0000000..5513876 --- /dev/null +++ b/contrib/syslinux-4.02/com32/gdbstub/Makefile @@ -0,0 +1,49 @@ +## ----------------------------------------------------------------------- +## +## 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., 51 Franklin St, Fifth Floor, +## Boston MA 02110-1301, USA; either version 2 of the License, or +## (at your option) any later version; incorporated herein by reference. +## +## ----------------------------------------------------------------------- + +## +## GDB remote debugging +## + +topdir = ../.. +include ../MCONFIG + +CFLAGS += -fPIE + +LIBS = ../libutil/libutil_com.a ../lib/libcom32.a $(LIBGCC) +LNXLIBS = ../libutil/libutil_lnx.a + +MODULES = gdbstub.c32 +TESTFILES = + +OBJS = main.o int.o serial.o gdbstub.o + +all: $(MODULES) $(TESTFILES) + +gdbstub.elf : $(OBJS) $(LIBS) $(C_LIBS) + $(LD) $(LDFLAGS) -o $@ $^ + +tidy dist clean: + rm -f *.o *.lo *.a *.lst *.elf .*.d *.tmp + +clean: tidy + rm -f *.lnx + +spotless: clean + rm -f *.lss *.c32 *.com + rm -f *~ \#* + +install: + mkdir -m 755 -p $(INSTALLROOT)$(AUXDIR) + install -m 644 $(MODULES) $(INSTALLROOT)$(AUXDIR) + +-include .*.d diff --git a/contrib/syslinux-4.02/com32/gdbstub/gdbstub.c b/contrib/syslinux-4.02/com32/gdbstub/gdbstub.c new file mode 100644 index 0000000..bd19add --- /dev/null +++ b/contrib/syslinux-4.02/com32/gdbstub/gdbstub.c @@ -0,0 +1,569 @@ +/* + * Copyright (C) 2008 Stefan Hajnoczi <stefanha@gmail.com>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/** + * @file + * + * GDB stub for remote debugging + * + */ + +#include <stdlib.h> +#include <stdint.h> +#include "serial.h" + +typedef uint32_t gdbreg_t; + +enum { + POSIX_EINVAL = 0x1c, /* used to report bad arguments to GDB */ + SIZEOF_PAYLOAD = 256, /* buffer size of GDB payload data */ + DR7_CLEAR = 0x00000400, /* disable hardware breakpoints */ + DR6_CLEAR = 0xffff0ff0, /* clear breakpoint status */ +}; + +/* The register snapshot, this must be in sync with interrupt handler and the + * GDB protocol. */ +enum { + GDBMACH_EAX, + GDBMACH_ECX, + GDBMACH_EDX, + GDBMACH_EBX, + GDBMACH_ESP, + GDBMACH_EBP, + GDBMACH_ESI, + GDBMACH_EDI, + GDBMACH_EIP, + GDBMACH_EFLAGS, + GDBMACH_CS, + GDBMACH_SS, + GDBMACH_DS, + GDBMACH_ES, + GDBMACH_FS, + GDBMACH_GS, + GDBMACH_NREGS, + GDBMACH_SIZEOF_REGS = GDBMACH_NREGS * sizeof(gdbreg_t) +}; + +/* Breakpoint types */ +enum { + GDBMACH_BPMEM, + GDBMACH_BPHW, + GDBMACH_WATCH, + GDBMACH_RWATCH, + GDBMACH_AWATCH, +}; + +struct gdbstub { + int exit_handler; /* leave interrupt handler */ + + int signo; + gdbreg_t *regs; + + void (*parse) (struct gdbstub * stub, char ch); + uint8_t cksum1; + + /* Buffer for payload data when parsing a packet. Once the + * packet has been received, this buffer is used to hold + * the reply payload. */ + char buf[SIZEOF_PAYLOAD + 4]; /* $...PAYLOAD...#XX */ + char *payload; /* start of payload */ + int len; /* length of payload */ +}; + +/** Hardware breakpoint, fields stored in x86 bit pattern form */ +struct hwbp { + int type; /* type (1=write watchpoint, 3=access watchpoint) */ + unsigned long addr; /* linear address */ + size_t len; /* length (0=1-byte, 1=2-byte, 3=4-byte) */ + int enabled; +}; + +static struct hwbp hwbps[4]; +static gdbreg_t dr7 = DR7_CLEAR; + +static inline void gdbmach_set_pc(gdbreg_t * regs, gdbreg_t pc) +{ + regs[GDBMACH_EIP] = pc; +} + +static inline void gdbmach_set_single_step(gdbreg_t * regs, int step) +{ + regs[GDBMACH_EFLAGS] &= ~(1 << 8); /* Trace Flag (TF) */ + regs[GDBMACH_EFLAGS] |= (step << 8); +} + +static inline void gdbmach_breakpoint(void) +{ + __asm__ __volatile__("int $3\n"); +} + +static struct hwbp *gdbmach_find_hwbp(int type, unsigned long addr, size_t len) +{ + struct hwbp *available = NULL; + unsigned int i; + for (i = 0; i < sizeof hwbps / sizeof hwbps[0]; i++) { + if (hwbps[i].type == type && hwbps[i].addr == addr + && hwbps[i].len == len) { + return &hwbps[i]; + } + if (!hwbps[i].enabled) { + available = &hwbps[i]; + } + } + return available; +} + +static void gdbmach_commit_hwbp(struct hwbp *bp) +{ + int regnum = bp - hwbps; + + /* Set breakpoint address */ + switch (regnum) { + case 0: +__asm__ __volatile__("movl %0, %%dr0\n": :"r"(bp->addr)); + break; + case 1: +__asm__ __volatile__("movl %0, %%dr1\n": :"r"(bp->addr)); + break; + case 2: +__asm__ __volatile__("movl %0, %%dr2\n": :"r"(bp->addr)); + break; + case 3: +__asm__ __volatile__("movl %0, %%dr3\n": :"r"(bp->addr)); + break; + } + + /* Set type */ + dr7 &= ~(0x3 << (16 + 4 * regnum)); + dr7 |= bp->type << (16 + 4 * regnum); + + /* Set length */ + dr7 &= ~(0x3 << (18 + 4 * regnum)); + dr7 |= bp->len << (18 + 4 * regnum); + + /* Set/clear local enable bit */ + dr7 &= ~(0x3 << 2 * regnum); + dr7 |= bp->enabled << 2 * regnum; +} + +int gdbmach_set_breakpoint(int type, unsigned long addr, size_t len, int enable) +{ + struct hwbp *bp; + + /* Check and convert breakpoint type to x86 type */ + switch (type) { + case GDBMACH_WATCH: + type = 0x1; + break; + case GDBMACH_AWATCH: + type = 0x3; + break; + default: + return 0; /* unsupported breakpoint type */ + } + + /* Only lengths 1, 2, and 4 are supported */ + if (len != 2 && len != 4) { + len = 1; + } + len--; /* convert to x86 breakpoint length bit pattern */ + + /* Set up the breakpoint */ + bp = gdbmach_find_hwbp(type, addr, len); + if (!bp) { + return 0; /* ran out of hardware breakpoints */ + } + bp->type = type; + bp->addr = addr; + bp->len = len; + bp->enabled = enable; + gdbmach_commit_hwbp(bp); + return 1; +} + +static void gdbmach_disable_hwbps(void) +{ + /* Store and clear hardware breakpoints */ + __asm__ __volatile__("movl %0, %%dr7\n"::"r"(DR7_CLEAR)); +} + +static void gdbmach_enable_hwbps(void) +{ + /* Clear breakpoint status register */ + __asm__ __volatile__("movl %0, %%dr6\n"::"r"(DR6_CLEAR)); + + /* Restore hardware breakpoints */ + __asm__ __volatile__("movl %0, %%dr7\n"::"r"(dr7)); +} + +/* Packet parser states */ +static void gdbstub_state_new(struct gdbstub *stub, char ch); +static void gdbstub_state_data(struct gdbstub *stub, char ch); +static void gdbstub_state_cksum1(struct gdbstub *stub, char ch); +static void gdbstub_state_cksum2(struct gdbstub *stub, char ch); +static void gdbstub_state_wait_ack(struct gdbstub *stub, char ch); + +static void serial_write(void *buf, size_t len) +{ + char *p = buf; + while (len-- > 0) + serial_putc(*p++); +} + +static uint8_t gdbstub_from_hex_digit(char ch) +{ + if (ch >= '0' && ch <= '9') + return ch - '0'; + else if (ch >= 'A' && ch <= 'F') + return ch - 'A' + 0xa; + else + return (ch - 'a' + 0xa) & 0xf; +} + +static uint8_t gdbstub_to_hex_digit(uint8_t b) +{ + b &= 0xf; + return (b < 0xa ? '0' : 'a' - 0xa) + b; +} + +/* + * To make reading/writing device memory atomic, we check for + * 2- or 4-byte aligned operations and handle them specially. + */ + +static void gdbstub_from_hex_buf(char *dst, char *src, int lenbytes) +{ + if (lenbytes == 2 && ((unsigned long)dst & 0x1) == 0) { + uint16_t i = gdbstub_from_hex_digit(src[2]) << 12 | + gdbstub_from_hex_digit(src[3]) << 8 | + gdbstub_from_hex_digit(src[0]) << 4 | + gdbstub_from_hex_digit(src[1]); + *(uint16_t *) dst = i; + } else if (lenbytes == 4 && ((unsigned long)dst & 0x3) == 0) { + uint32_t i = gdbstub_from_hex_digit(src[6]) << 28 | + gdbstub_from_hex_digit(src[7]) << 24 | + gdbstub_from_hex_digit(src[4]) << 20 | + gdbstub_from_hex_digit(src[5]) << 16 | + gdbstub_from_hex_digit(src[2]) << 12 | + gdbstub_from_hex_digit(src[3]) << 8 | + gdbstub_from_hex_digit(src[0]) << 4 | + gdbstub_from_hex_digit(src[1]); + *(uint32_t *) dst = i; + } else { + while (lenbytes-- > 0) { + *dst++ = gdbstub_from_hex_digit(src[0]) << 4 | + gdbstub_from_hex_digit(src[1]); + src += 2; + } + } +} + +static void gdbstub_to_hex_buf(char *dst, char *src, int lenbytes) +{ + if (lenbytes == 2 && ((unsigned long)src & 0x1) == 0) { + uint16_t i = *(uint16_t *) src; + dst[0] = gdbstub_to_hex_digit(i >> 4); + dst[1] = gdbstub_to_hex_digit(i); + dst[2] = gdbstub_to_hex_digit(i >> 12); + dst[3] = gdbstub_to_hex_digit(i >> 8); + } else if (lenbytes == 4 && ((unsigned long)src & 0x3) == 0) { + uint32_t i = *(uint32_t *) src; + dst[0] = gdbstub_to_hex_digit(i >> 4); + dst[1] = gdbstub_to_hex_digit(i); + dst[2] = gdbstub_to_hex_digit(i >> 12); + dst[3] = gdbstub_to_hex_digit(i >> 8); + dst[4] = gdbstub_to_hex_digit(i >> 20); + dst[5] = gdbstub_to_hex_digit(i >> 16); + dst[6] = gdbstub_to_hex_digit(i >> 28); + dst[7] = gdbstub_to_hex_digit(i >> 24); + } else { + while (lenbytes-- > 0) { + *dst++ = gdbstub_to_hex_digit(*src >> 4); + *dst++ = gdbstub_to_hex_digit(*src); + src++; + } + } +} + +static uint8_t gdbstub_cksum(char *data, int len) +{ + uint8_t cksum = 0; + while (len-- > 0) { + cksum += (uint8_t) * data++; + } + return cksum; +} + +static void gdbstub_tx_packet(struct gdbstub *stub) +{ + uint8_t cksum = gdbstub_cksum(stub->payload, stub->len); + stub->buf[0] = '$'; + stub->buf[stub->len + 1] = '#'; + stub->buf[stub->len + 2] = gdbstub_to_hex_digit(cksum >> 4); + stub->buf[stub->len + 3] = gdbstub_to_hex_digit(cksum); + serial_write(stub->buf, stub->len + 4); + stub->parse = gdbstub_state_wait_ack; +} + +/* GDB commands */ +static void gdbstub_send_ok(struct gdbstub *stub) +{ + stub->payload[0] = 'O'; + stub->payload[1] = 'K'; + stub->len = 2; + gdbstub_tx_packet(stub); +} + +static void gdbstub_send_num_packet(struct gdbstub *stub, char reply, int num) +{ + stub->payload[0] = reply; + stub->payload[1] = gdbstub_to_hex_digit((char)num >> 4); + stub->payload[2] = gdbstub_to_hex_digit((char)num); + stub->len = 3; + gdbstub_tx_packet(stub); +} + +/* Format is arg1,arg2,...,argn:data where argn are hex integers and data is not an argument */ +static int gdbstub_get_packet_args(struct gdbstub *stub, unsigned long *args, + int nargs, int *stop_idx) +{ + int i; + char ch = 0; + int argc = 0; + unsigned long val = 0; + for (i = 1; i < stub->len && argc < nargs; i++) { + ch = stub->payload[i]; + if (ch == ':') { + break; + } else if (ch == ',') { + args[argc++] = val; + val = 0; + } else { + val = (val << 4) | gdbstub_from_hex_digit(ch); + } + } + if (stop_idx) { + *stop_idx = i; + } + if (argc < nargs) { + args[argc++] = val; + } + return ((i == stub->len || ch == ':') && argc == nargs); +} + +static void gdbstub_send_errno(struct gdbstub *stub, int errno) +{ + gdbstub_send_num_packet(stub, 'E', errno); +} + +static void gdbstub_report_signal(struct gdbstub *stub) +{ + gdbstub_send_num_packet(stub, 'S', stub->signo); +} + +static void gdbstub_read_regs(struct gdbstub *stub) +{ + gdbstub_to_hex_buf(stub->payload, (char *)stub->regs, GDBMACH_SIZEOF_REGS); + stub->len = GDBMACH_SIZEOF_REGS * 2; + gdbstub_tx_packet(stub); +} + +static void gdbstub_write_regs(struct gdbstub *stub) +{ + if (stub->len != 1 + GDBMACH_SIZEOF_REGS * 2) { + gdbstub_send_errno(stub, POSIX_EINVAL); + return; + } + gdbstub_from_hex_buf((char *)stub->regs, &stub->payload[1], + GDBMACH_SIZEOF_REGS); + gdbstub_send_ok(stub); +} + +static void gdbstub_read_mem(struct gdbstub *stub) +{ + unsigned long args[2]; + if (!gdbstub_get_packet_args + (stub, args, sizeof args / sizeof args[0], NULL)) { + gdbstub_send_errno(stub, POSIX_EINVAL); + return; + } + args[1] = (args[1] < SIZEOF_PAYLOAD / 2) ? args[1] : SIZEOF_PAYLOAD / 2; + gdbstub_to_hex_buf(stub->payload, (char *)args[0], args[1]); + stub->len = args[1] * 2; + gdbstub_tx_packet(stub); +} + +static void gdbstub_write_mem(struct gdbstub *stub) +{ + unsigned long args[2]; + int colon; + if (!gdbstub_get_packet_args + (stub, args, sizeof args / sizeof args[0], &colon) || colon >= stub->len + || stub->payload[colon] != ':' || (stub->len - colon - 1) % 2 != 0) { + gdbstub_send_errno(stub, POSIX_EINVAL); + return; + } + gdbstub_from_hex_buf((char *)args[0], &stub->payload[colon + 1], + (stub->len - colon - 1) / 2); + gdbstub_send_ok(stub); +} + +static void gdbstub_continue(struct gdbstub *stub, int single_step) +{ + gdbreg_t pc; + if (stub->len > 1 + && gdbstub_get_packet_args(stub, (unsigned long *)&pc, 1, NULL)) { + gdbmach_set_pc(stub->regs, pc); + } + gdbmach_set_single_step(stub->regs, single_step); + stub->exit_handler = 1; + /* Reply will be sent when we hit the next breakpoint or interrupt */ +} + +static void gdbstub_breakpoint(struct gdbstub *stub) +{ + unsigned long args[3]; + int enable = stub->payload[0] == 'Z' ? 1 : 0; + if (!gdbstub_get_packet_args + (stub, args, sizeof args / sizeof args[0], NULL)) { + gdbstub_send_errno(stub, POSIX_EINVAL); + return; + } + if (gdbmach_set_breakpoint(args[0], args[1], args[2], enable)) { + gdbstub_send_ok(stub); + } else { + /* Not supported */ + stub->len = 0; + gdbstub_tx_packet(stub); + } +} + +static void gdbstub_rx_packet(struct gdbstub *stub) +{ + switch (stub->payload[0]) { + case '?': + gdbstub_report_signal(stub); + break; + case 'g': + gdbstub_read_regs(stub); + break; + case 'G': + gdbstub_write_regs(stub); + break; + case 'm': + gdbstub_read_mem(stub); + break; + case 'M': + gdbstub_write_mem(stub); + break; + case 'c': /* Continue */ + case 'k': /* Kill */ + case 's': /* Step */ + case 'D': /* Detach */ + gdbstub_continue(stub, stub->payload[0] == 's'); + if (stub->payload[0] == 'D') { + gdbstub_send_ok(stub); + } + break; + case 'Z': /* Insert breakpoint */ + case 'z': /* Remove breakpoint */ + gdbstub_breakpoint(stub); + break; + default: + stub->len = 0; + gdbstub_tx_packet(stub); + break; + } +} + +/* GDB packet parser */ +static void gdbstub_state_new(struct gdbstub *stub, char ch) +{ + if (ch == '$') { + stub->len = 0; + stub->parse = gdbstub_state_data; + } +} + +static void gdbstub_state_data(struct gdbstub *stub, char ch) +{ + if (ch == '#') { + stub->parse = gdbstub_state_cksum1; + } else if (ch == '$') { + stub->len = 0; /* retry new packet */ + } else { + /* If the length exceeds our buffer, let the checksum fail */ + if (stub->len < SIZEOF_PAYLOAD) { + stub->payload[stub->len++] = ch; + } + } +} + +static void gdbstub_state_cksum1(struct gdbstub *stub, char ch) +{ + stub->cksum1 = gdbstub_from_hex_digit(ch) << 4; + stub->parse = gdbstub_state_cksum2; +} + +static void gdbstub_state_cksum2(struct gdbstub *stub, char ch) +{ + uint8_t their_cksum; + uint8_t our_cksum; + + stub->parse = gdbstub_state_new; + their_cksum = stub->cksum1 + gdbstub_from_hex_digit(ch); + our_cksum = gdbstub_cksum(stub->payload, stub->len); + + if (their_cksum == our_cksum) { + serial_write("+", 1); + if (stub->len > 0) { + gdbstub_rx_packet(stub); + } + } else { + serial_write("-", 1); + } +} + +static void gdbstub_state_wait_ack(struct gdbstub *stub, char ch) +{ + if (ch == '+') { + stub->parse = gdbstub_state_new; + } else { + /* This retransmit is very aggressive but necessary to keep + * in sync with GDB. */ + gdbstub_tx_packet(stub); + } +} + +void gdbstub_handler(int signo, gdbreg_t * regs) +{ + struct gdbstub stub; + + gdbmach_disable_hwbps(); + + stub.parse = gdbstub_state_new; + stub.payload = &stub.buf[1]; + stub.signo = signo; + stub.regs = regs; + stub.exit_handler = 0; + gdbstub_report_signal(&stub); + while (!stub.exit_handler) + stub.parse(&stub, serial_getc()); + + gdbmach_enable_hwbps(); +} diff --git a/contrib/syslinux-4.02/com32/gdbstub/int.S b/contrib/syslinux-4.02/com32/gdbstub/int.S new file mode 100644 index 0000000..2a1ff9d --- /dev/null +++ b/contrib/syslinux-4.02/com32/gdbstub/int.S @@ -0,0 +1,77 @@ + .section ".text","ax" + +#define SIGTRAP 5 + +#define SIZEOF_I386_REGS 32 +#define SIZEOF_I386_FLAGS 4 + +/* When invoked, the stack contains: eflags, cs, eip, signo. */ +#define IH_OFFSET_GDB_REGS ( 0 ) +#define IH_OFFSET_GDB_EIP ( IH_OFFSET_GDB_REGS + SIZEOF_I386_REGS ) +#define IH_OFFSET_GDB_EFLAGS ( IH_OFFSET_GDB_EIP + 4 ) +#define IH_OFFSET_GDB_SEG_REGS ( IH_OFFSET_GDB_EFLAGS + SIZEOF_I386_FLAGS ) +#define IH_OFFSET_GDB_END ( IH_OFFSET_GDB_SEG_REGS + 6 * 4 ) +#define IH_OFFSET_OLD_EIP ( IH_OFFSET_GDB_END ) +#define IH_OFFSET_OLD_CS ( IH_OFFSET_OLD_EIP + 4 ) +#define IH_OFFSET_OLD_EFLAGS ( IH_OFFSET_OLD_CS + 4 ) +#define IH_OFFSET_END ( IH_OFFSET_OLD_EFLAGS + 4 ) + +/* We also access the stack whilst still storing or restoring + * the register snapshot. Since ESP is in flux, we need + * special offsets. + */ +#define IH_OFFSET_FLUX_OLD_CS ( IH_OFFSET_OLD_CS - 44 ) +#define IH_OFFSET_FLUX_OLD_EFLAGS ( IH_OFFSET_OLD_EFLAGS - 40 ) +#define IH_OFFSET_FLUX_OLD_EIP ( IH_OFFSET_OLD_EIP - 36 ) +#define IH_OFFSET_FLUX_END ( IH_OFFSET_END - 20 ) + + .global int_handler +int_handler: + /* Store CPU state in GDB register snapshot */ + pushw $0 + pushw %gs + pushw $0 + pushw %fs + pushw $0 + pushw %es + pushw $0 + pushw %ds + pushw $0 + pushw %ss + pushw $0 + pushw IH_OFFSET_FLUX_OLD_CS + 2(%esp) + pushl IH_OFFSET_FLUX_OLD_EFLAGS(%esp) + pushl IH_OFFSET_FLUX_OLD_EIP(%esp) + pushl %edi + pushl %esi + pushl %ebp + leal IH_OFFSET_FLUX_END(%esp), %edi + pushl %edi /* old ESP */ + pushl %ebx + pushl %edx + pushl %ecx + pushl %eax + + /* Call GDB stub exception handler */ + movl $SIGTRAP, %eax + movl %esp, %edx + call gdbstub_handler + + /* Restore CPU state from GDB register snapshot */ + popl %eax + popl %ecx + popl %edx + popl %ebx + addl $4, %esp /* Changing ESP currently not supported */ + popl %ebp + popl %esi + popl %edi + popl IH_OFFSET_FLUX_OLD_EIP(%esp) + popl IH_OFFSET_FLUX_OLD_EFLAGS(%esp) + popl IH_OFFSET_FLUX_OLD_CS(%esp) + popl %ss + popl %ds + popl %es + popl %fs + popl %gs + iret diff --git a/contrib/syslinux-4.02/com32/gdbstub/main.c b/contrib/syslinux-4.02/com32/gdbstub/main.c new file mode 100644 index 0000000..2ff9f28 --- /dev/null +++ b/contrib/syslinux-4.02/com32/gdbstub/main.c @@ -0,0 +1,142 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <console.h> +#include <com32.h> +#include <syslinux/loadfile.h> +#include "serial.h" + +#define X86_INT_DB 1 +#define X86_INT_BP 3 +#define COM32_IDT ((void*)0x100000) +#define COM32_LOAD_ADDR ((void*)0x101000) +#define STACK_SIZE 0x1000 + +extern char _start[], _end[]; + +struct reloc_info { + void *data; + size_t len; + uint32_t old_esp; + uint32_t reloc_base; +}; + +static inline void error(const char *msg) +{ + fputs(msg, stderr); +} + +static inline uint32_t reloc_ptr(struct reloc_info *ri, void *ptr) +{ + return ri->reloc_base + (uint32_t) ((char *)ptr - _start); +} + +static void hijack_interrupt(int intn, uint32_t handler) +{ + struct { + uint32_t lo; + uint32_t hi; + } *idt = COM32_IDT; + + idt[intn].lo = (idt[intn].lo & 0xffff0000) | (handler & 0x0000ffff); + idt[intn].hi = (idt[intn].hi & 0x0000ffff) | (handler & 0xffff0000); +} + +static void shift_cmdline(struct com32_sys_args *com32) +{ + char *p; + + /* Skip leading whitespace */ + for (p = com32->cs_cmdline; *p != '\0' && *p == ' '; p++) ; + + /* Skip first word */ + for (; *p != '\0' && *p != ' '; p++) ; + + /* Skip whitespace after first word */ + for (; *p != '\0' && *p == ' '; p++) ; + + com32->cs_cmdline = p; +} + +static __noreturn reloc_entry(struct reloc_info *ri) +{ + extern char int_handler[]; + size_t stack_frame_size = sizeof(struct com32_sys_args) + 4; + struct com32_sys_args *com32; + uint32_t module_esp; + + hijack_interrupt(X86_INT_DB, reloc_ptr(ri, int_handler)); + hijack_interrupt(X86_INT_BP, reloc_ptr(ri, int_handler)); + + /* Copy module to load address */ + memcpy(COM32_LOAD_ADDR, ri->data, ri->len); + + /* Copy stack frame onto module stack */ + module_esp = (ri->reloc_base - stack_frame_size) & ~15; + memcpy((void *)module_esp, (void *)ri->old_esp, stack_frame_size); + + /* Fix up command line */ + com32 = (struct com32_sys_args *)(module_esp + 4); + shift_cmdline(com32); + + /* Set up CPU state to run module and enter GDB */ + asm volatile ("movl %0, %%esp\n\t" + "pushf\n\t" + "pushl %%cs\n\t" + "pushl %1\n\t" + "jmp *%2\n\t"::"r" (module_esp), + "c"(COM32_LOAD_ADDR), "r"(reloc_ptr(ri, int_handler)) + ); + for (;;) ; /* shut the compiler up */ +} + +static inline __noreturn reloc(void *ptr, size_t len) +{ + extern uint32_t __entry_esp; + size_t total_size = _end - _start; + __noreturn(*entry_fn) (struct reloc_info *); + struct reloc_info ri; + uint32_t esp; + char *dest; + + /* Calculate relocation address, preserve current stack */ + asm volatile ("movl %%esp, %0\n\t":"=m" (esp)); + dest = (char *)((esp - STACK_SIZE - total_size) & ~3); + + /* Calculate entry point in relocated code */ + entry_fn = (void *)(dest + ((char *)reloc_entry - _start)); + + /* Copy all sections to relocation address */ + printf("Relocating %d bytes from %p to %p\n", total_size, _start, dest); + memcpy(dest, _start, total_size); + + /* Call into relocated code */ + ri.data = ptr; + ri.len = len; + ri.old_esp = __entry_esp; + ri.reloc_base = (uint32_t) dest; + entry_fn(&ri); +} + +int main(int argc, char *argv[]) +{ + void *data; + size_t data_len; + + openconsole(&dev_null_r, &dev_stdcon_w); + + if (argc < 2) { + error("Usage: gdbstub.c32 com32_file arguments...\n"); + return 1; + } + + if (loadfile(argv[1], &data, &data_len)) { + error("Unable to load file\n"); + return 1; + } + + serial_init(); + + /* No more lib calls after this point */ + reloc(data, data_len); +} diff --git a/contrib/syslinux-4.02/com32/gdbstub/serial.c b/contrib/syslinux-4.02/com32/gdbstub/serial.c new file mode 100644 index 0000000..8c69b02 --- /dev/null +++ b/contrib/syslinux-4.02/com32/gdbstub/serial.c @@ -0,0 +1,193 @@ +/* + * The serial port interface routines implement a simple polled i/o + * interface to a standard serial port. Due to the space restrictions + * for the boot blocks, no BIOS support is used (since BIOS requires + * expensive real/protected mode switches), instead the rudimentary + * BIOS support is duplicated here. + * + * The base address and speed for the i/o port are passed from the + * Makefile in the COMCONSOLE and CONSPEED preprocessor macros. The + * line control parameters are currently hard-coded to 8 bits, no + * parity, 1 stop bit (8N1). This can be changed in init_serial(). + */ + +#include <stddef.h> +#include <sys/io.h> +#include "serial.h" + +/* Set default values if none specified */ + +#ifndef COMCONSOLE +#define COMCONSOLE 0x3f8 +#endif + +#ifndef COMSPEED +#define COMSPEED 9600 +#endif + +#ifndef COMDATA +#define COMDATA 8 +#endif + +#ifndef COMPARITY +#define COMPARITY 0 +#endif + +#ifndef COMSTOP +#define COMSTOP 1 +#endif + +#undef UART_BASE +#define UART_BASE ( COMCONSOLE ) + +#undef UART_BAUD +#define UART_BAUD ( COMSPEED ) + +#if ((115200%UART_BAUD) != 0) +#error Bad ttys0 baud rate +#endif + +#define COMBRD (115200/UART_BAUD) + +/* Line Control Settings */ +#define UART_LCS ( ( ( (COMDATA) - 5 ) << 0 ) | \ + ( ( (COMPARITY) ) << 3 ) | \ + ( ( (COMSTOP) - 1 ) << 2 ) ) + +/* Data */ +#define UART_RBR 0x00 +#define UART_TBR 0x00 + +/* Control */ +#define UART_IER 0x01 +#define UART_IIR 0x02 +#define UART_FCR 0x02 +#define UART_LCR 0x03 +#define UART_MCR 0x04 +#define UART_DLL 0x00 +#define UART_DLM 0x01 + +/* Status */ +#define UART_LSR 0x05 +#define UART_LSR_TEMPT 0x40 /* Transmitter empty */ +#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ +#define UART_LSR_BI 0x10 /* Break interrupt indicator */ +#define UART_LSR_FE 0x08 /* Frame error indicator */ +#define UART_LSR_PE 0x04 /* Parity error indicator */ +#define UART_LSR_OE 0x02 /* Overrun error indicator */ +#define UART_LSR_DR 0x01 /* Receiver data ready */ + +#define UART_MSR 0x06 +#define UART_SCR 0x07 + +#define uart_readb(addr) inb(addr) +#define uart_writeb(val,addr) outb((val),(addr)) + +/* + * void serial_putc(int ch); + * Write character `ch' to port UART_BASE. + */ +void serial_putc(int ch) +{ + int status; + for (;;) { + status = uart_readb(UART_BASE + UART_LSR); + if (status & UART_LSR_THRE) { + /* TX buffer emtpy */ + uart_writeb(ch, UART_BASE + UART_TBR); + break; + } + } +} + +/* + * int serial_getc(void); + * Read a character from port UART_BASE. + */ +int serial_getc(void) +{ + int status; + int ch; + do { + status = uart_readb(UART_BASE + UART_LSR); + } while ((status & 1) == 0); + ch = uart_readb(UART_BASE + UART_RBR); /* fetch (first) character */ + ch &= 0x7f; /* remove any parity bits we get */ + if (ch == 0x7f) { /* Make DEL... look like BS */ + ch = 0x08; + } + return ch; +} + +/* + * int serial_init(void); + * Initialize port UART_BASE to speed COMSPEED, line settings 8N1. + */ +void serial_init(void) +{ + int status; + int divisor, lcs; + + divisor = COMBRD; + lcs = UART_LCS; + +#ifdef COMPRESERVE + lcs = uart_readb(UART_BASE + UART_LCR) & 0x7f; + uart_writeb(0x80 | lcs, UART_BASE + UART_LCR); + divisor = + (uart_readb(UART_BASE + UART_DLM) << 8) | uart_readb(UART_BASE + + UART_DLL); + uart_writeb(lcs, UART_BASE + UART_LCR); +#endif + + /* Set Baud Rate Divisor to COMSPEED, and test to see if the + * serial port appears to be present. + */ + uart_writeb(0x80 | lcs, UART_BASE + UART_LCR); + uart_writeb(0xaa, UART_BASE + UART_DLL); + if (uart_readb(UART_BASE + UART_DLL) != 0xaa) { + goto out; + } + uart_writeb(0x55, UART_BASE + UART_DLL); + if (uart_readb(UART_BASE + UART_DLL) != 0x55) { + goto out; + } + uart_writeb(divisor & 0xff, UART_BASE + UART_DLL); + if (uart_readb(UART_BASE + UART_DLL) != (divisor & 0xff)) { + goto out; + } + uart_writeb(0xaa, UART_BASE + UART_DLM); + if (uart_readb(UART_BASE + UART_DLM) != 0xaa) { + goto out; + } + uart_writeb(0x55, UART_BASE + UART_DLM); + if (uart_readb(UART_BASE + UART_DLM) != 0x55) { + goto out; + } + uart_writeb((divisor >> 8) & 0xff, UART_BASE + UART_DLM); + if (uart_readb(UART_BASE + UART_DLM) != ((divisor >> 8) & 0xff)) { + goto out; + } + uart_writeb(lcs, UART_BASE + UART_LCR); + + /* disable interrupts */ + uart_writeb(0x0, UART_BASE + UART_IER); + + /* disable fifo's */ + uart_writeb(0x00, UART_BASE + UART_FCR); + + /* Set clear to send, so flow control works... */ + uart_writeb((1 << 1), UART_BASE + UART_MCR); + + /* Flush the input buffer. */ + do { + /* rx buffer reg + * throw away (unconditionally the first time) + */ + (void)uart_readb(UART_BASE + UART_RBR); + /* line status reg */ + status = uart_readb(UART_BASE + UART_LSR); + } while (status & UART_LSR_DR); +out: + return; +} diff --git a/contrib/syslinux-4.02/com32/gdbstub/serial.h b/contrib/syslinux-4.02/com32/gdbstub/serial.h new file mode 100644 index 0000000..bb27a62 --- /dev/null +++ b/contrib/syslinux-4.02/com32/gdbstub/serial.h @@ -0,0 +1,14 @@ +#ifndef _GPXE_SERIAL_H +#define _GPXE_SERIAL_H + +/** @file + * + * Serial driver functions + * + */ + +extern void serial_putc(int ch); +extern int serial_getc(void); +extern void serial_init(void); + +#endif /* _GPXE_SERIAL_H */ diff --git a/contrib/syslinux-4.02/com32/gfxboot/.gitignore b/contrib/syslinux-4.02/com32/gfxboot/.gitignore new file mode 100644 index 0000000..1944fd6 --- /dev/null +++ b/contrib/syslinux-4.02/com32/gfxboot/.gitignore @@ -0,0 +1 @@ +*.tmp diff --git a/contrib/syslinux-4.02/com32/gfxboot/Makefile b/contrib/syslinux-4.02/com32/gfxboot/Makefile new file mode 100644 index 0000000..73133e1 --- /dev/null +++ b/contrib/syslinux-4.02/com32/gfxboot/Makefile @@ -0,0 +1,44 @@ +## ----------------------------------------------------------------------- +## +## Copyright 2001-2009 H. Peter Anvin - All Rights Reserved +## Copyright 2009 Intel Corporation; author: H. Peter Anvin +## +## 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. +## +## ----------------------------------------------------------------------- + +topdir = ../.. +include ../MCONFIG + +MODULES = gfxboot.c32 + +all: $(MODULES) + +gfxboot.elf : gfxboot.o realmode_callback.o $(LIBS) $(C_LIBS) + $(LD) $(LDFLAGS) -o $@ $^ + +realmode_callback.o: realmode_callback.asm + $(NASM) -f bin -O99 -o $*.tmp -l $*.lst $< + $(OBJCOPY) -B i386 -I binary -O elf32-i386 \ + --redefine-sym _binary_$*_tmp_start=$*_start \ + --redefine-sym _binary_$*_tmp_end=$*_end \ + --strip-symbol _binary_$*_tmp_size \ + $*.tmp $@ + +tidy dist: + rm -f *.o *.lo *.a *.lst *.elf .*.d *.tmp + +clean: tidy + rm -f *.lnx + +spotless: clean + rm -f *.lss *.c32 *.com + rm -f *~ \#* + +install: + +-include .*.d diff --git a/contrib/syslinux-4.02/com32/gfxboot/gfxboot.c b/contrib/syslinux-4.02/com32/gfxboot/gfxboot.c new file mode 100644 index 0000000..dd4d641 --- /dev/null +++ b/contrib/syslinux-4.02/com32/gfxboot/gfxboot.c @@ -0,0 +1,938 @@ +/* + * + * gfxboot.c + * + * A com32 module to load gfxboot graphics. + * + * Copyright (c) 2009 Steffen Winterfeldt. + * + * 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 <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include <syslinux/loadfile.h> +#include <syslinux/config.h> +#include <syslinux/linux.h> +#include <syslinux/boot.h> +#include <console.h> +#include <com32.h> + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +#define MAX_CONFIG_LINE_LEN 2048 +#define MAX_CMDLINE_LEN 2048 + +// buffer for realmode callback +// must be at least block size; can in theory be larger than 4k, but there's +// not enough space left +#define REALMODE_BUF_SIZE 4096 + +// gfxboot working memory in MB +#define GFX_MEMORY_SIZE 7 + +// read chunk size for progress bar +#define CHUNK_SIZE (64 << 10) + +// callback function numbers +#define GFX_CB_INIT 0 +#define GFX_CB_DONE 1 +#define GFX_CB_INPUT 2 +#define GFX_CB_MENU_INIT 3 +#define GFX_CB_INFOBOX_INIT 4 +#define GFX_CB_INFOBOX_DONE 5 +#define GFX_CB_PROGRESS_INIT 6 +#define GFX_CB_PROGRESS_DONE 7 +#define GFX_CB_PROGRESS_UPDATE 8 +#define GFX_CB_PROGRESS_LIMIT 9 // unused +#define GFX_CB_PASSWORD_INIT 10 +#define GFX_CB_PASSWORD_DONE 11 + +// real mode code chunk, will be placed into bounce buffer +extern void realmode_callback_start, realmode_callback_end; + +// gets in the way +#undef linux + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// gfxboot config data (64 bytes) +typedef struct __attribute__ ((packed)) { + uint8_t bootloader; // 0: boot loader type (0: lilo, 1: syslinux, 2: grub) + uint8_t sector_shift; // 1: sector shift + uint8_t media_type; // 2: media type (0: disk, 1: floppy, 2: cdrom) + uint8_t failsafe; // 3: turn on failsafe mode (bitmask) + // 0: SHIFT pressed + // 1: skip gfxboot + // 2: skip monitor detection + uint8_t sysconfig_size; // 4: size of sysconfig data + uint8_t boot_drive; // 5: BIOS boot drive + uint16_t callback; // 6: offset to callback handler + uint16_t bootloader_seg; // 8: code/data segment used by bootloader; must follow gfx_callback + uint16_t serial_port; // 10: syslinux initialized serial port from 'serial' option + uint32_t user_info_0; // 12: data for info box + uint32_t user_info_1; // 16: data for info box + uint32_t bios_mem_size; // 20: BIOS memory size (in bytes) + uint16_t xmem_0; // 24: extended mem area 0 (start:size in MB; 12:4 bits) - obsolete + uint16_t xmem_1; // 26: extended mem area 1 - obsolete + uint16_t xmem_2; // 28: extended mem area 2 - obsolete + uint16_t xmem_3; // 30: extended mem area 3 - obsolete + uint32_t file; // 32: start of gfx file + uint32_t archive_start; // 36: start of cpio archive + uint32_t archive_end; // 40: end of cpio archive + uint32_t mem0_start; // 44: low free memory start + uint32_t mem0_end; // 48: low free memory end + uint32_t xmem_start; // 52: extended mem start + uint32_t xmem_end; // 56: extended mem end + uint16_t features; // 60: feature flags returned by GFX_CB_INIT + // 0: GFX_CB_MENU_INIT accepts 32 bit addresses + // 1: knows about xmem_start, xmem_end + uint16_t reserved_1; // 62: +} gfx_config_t; + + +// gfxboot menu description (18 bytes) +typedef struct __attribute__ ((packed)) { + uint16_t entries; + char *default_entry; + char *label_list; + uint16_t label_size; + char *arg_list; + uint16_t arg_size; +} gfx_menu_t; + + +// menu description +typedef struct menu_s { + struct menu_s *next; + char *label; // config entry name + char *menu_label; // text to show in boot menu + char *kernel; // name of program to load + char *alt_kernel; // alternative name in case user has replaced it + char *linux; // de facto an alias for 'kernel' + char *localboot; // boot from local disk + char *initrd; // initrd as separate line (instead of as part of 'append') + char *append; // kernel args + char *ipappend; // append special pxelinux args (see doc) +} menu_t; + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +gfx_config_t gfx_config; +gfx_menu_t gfx_menu; + +menu_t *menu; +menu_t *menu_default; + +struct { + uint32_t jmp_table[12]; + uint16_t code_seg; + char fname_buf[64]; +} gfx; + +void *lowmem_buf; +unsigned lowmem_buf_size; + +int timeout; + +char cmdline[MAX_CMDLINE_LEN]; + +void *save_buf; +unsigned save_buf_size; + +// progress bar is visible +unsigned progress_active; + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void show_message(char *file); +char *get_config_file_name(void); +char *skip_spaces(char *s); +char *skip_nonspaces(char *s); +void chop_line(char *s); +int read_config_file(void); +unsigned magic_ok(unsigned char *buf, unsigned *code_size); +unsigned find_file(unsigned char *buf, unsigned len, unsigned *gfx_file_start, unsigned *file_len, unsigned *code_size); +int gfx_init(char *file); +int gfx_menu_init(void); +void gfx_done(void); +int gfx_input(void); +void gfx_infobox(int type, char *str1, char *str2); +void gfx_progress_init(ssize_t kernel_size, char *label); +void gfx_progress_update(ssize_t size); +void gfx_progress_done(void); +ssize_t save_read(int fd, void *buf, size_t size); +void *load_one(char *file, ssize_t *file_size); +void boot(int index); +void boot_entry(menu_t *menu_ptr, char *arg); + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +int main(int argc, char **argv) +{ + int menu_index; + const union syslinux_derivative_info *sdi; + + openconsole(&dev_stdcon_r, &dev_stdcon_w); + + lowmem_buf = __com32.cs_bounce; + lowmem_buf_size = __com32.cs_bounce_size; + + sdi = syslinux_derivative_info(); + + gfx_config.sector_shift = sdi->disk.sector_shift; + gfx_config.boot_drive = sdi->disk.drive_number; + + if(sdi->c.filesystem == SYSLINUX_FS_PXELINUX) { + gfx_config.sector_shift = 11; + gfx_config.boot_drive = 0; + } + + gfx_config.media_type = gfx_config.boot_drive < 0x80 ? 1 : 0; + + if(sdi->c.filesystem == SYSLINUX_FS_ISOLINUX) { + gfx_config.media_type = sdi->iso.cd_mode ? 0 : 2; + } + + gfx_config.bootloader = 1; + gfx_config.sysconfig_size = sizeof gfx_config; + gfx_config.bootloader_seg = 0; // apparently not needed + + save_buf_size = lowmem_buf_size; + save_buf = malloc(save_buf_size); + + if(argc < 2) { + printf("Usage: gfxboot.c32 bootlogo_file [message_file]\n"); + if(argc > 2) show_message(argv[2]); + + return 0; + } + + if(read_config_file()) { + printf("Error reading config file\n"); + if(argc > 2) show_message(argv[2]); + + return 0; + } + + if(gfx_init(argv[1])) { + printf("Error setting up gfxboot\n"); + if(argc > 2) show_message(argv[2]); + + return 0; + } + + gfx_menu_init(); + + for(;;) { + menu_index = gfx_input(); + + // abort gfx, return to text mode prompt + if(menu_index == -1) { + gfx_done(); + break; + } + + // does not return if it succeeds + boot(menu_index); + } + + if(argc > 2) show_message(argv[2]); + + return 0; +} + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void show_message(char *file) +{ + int c; + FILE *f; + + if(!(f = fopen(file, "r"))) return; + + while((c = getc(f)) != EOF) { + if(c < ' ' && c != '\n' && c != '\t') continue; + printf("%c", c); + } + + fclose(f); +} + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +char *skip_spaces(char *s) +{ + while(*s && (*s == ' ' || *s == '\t')) s++; + + return s; +} + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +char *skip_nonspaces(char *s) +{ + while(*s && *s != ' ' && *s != '\t') s++; + + return s; +} + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void chop_line(char *s) +{ + int i = strlen(s); + + if(!i) return; + + while(--i >= 0) { + if(s[i] == ' ' || s[i] == '\t' || s[i] == '\n') { + s[i] = 0; + } + else { + break; + } + } +} + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Read and parse syslinux config file. +// +// return: +// 0: ok, 1: error +// +int read_config_file(void) +{ + FILE *f; + char *s, *t, buf[MAX_CONFIG_LINE_LEN]; + unsigned u, menu_idx = 0, label_size = 0, append_size = 0; + menu_t *menu_ptr = NULL, **menu_next = &menu; + + menu_default = calloc(1, sizeof *menu_default); + + if(!(f = fopen(syslinux_config_file(), "r"))) return 1; + + while((s = fgets(buf, sizeof buf, f))) { + chop_line(s); + s = skip_spaces(s); + if(!*s || *s == '#') continue; + t = skip_nonspaces(s); + if(*t) *t++ = 0; + t = skip_spaces(t); + + if(!strcasecmp(s, "timeout")) { + timeout = atoi(t); + continue; + } + + if(!strcasecmp(s, "default")) { + menu_default->label = strdup(t); + u = strlen(t); + if(u > label_size) label_size = u; + continue; + } + + if(!strcasecmp(s, "label")) { + menu_ptr = *menu_next = calloc(1, sizeof **menu_next); + menu_next = &menu_ptr->next; + menu_idx++; + menu_ptr->label = menu_ptr->menu_label = strdup(t); + u = strlen(t); + if(u > label_size) label_size = u; + continue; + } + + if(!strcasecmp(s, "kernel") && menu_ptr) { + menu_ptr->kernel = strdup(t); + continue; + } + + if(!strcasecmp(s, "linux") && menu_ptr) { + menu_ptr->linux = strdup(t); + continue; + } + + if(!strcasecmp(s, "localboot") && menu_ptr) { + menu_ptr->localboot = strdup(t); + continue; + } + + if(!strcasecmp(s, "initrd") && menu_ptr) { + menu_ptr->initrd = strdup(t); + continue; + } + + if(!strcasecmp(s, "append")) { + (menu_ptr ?: menu_default)->append = strdup(t); + u = strlen(t); + if(u > append_size) append_size = u; + continue; + } + + if(!strcasecmp(s, "ipappend")) { + (menu_ptr ?: menu_default)->ipappend = strdup(t); + continue; + } + + if(!strcasecmp(s, "menu") && menu_ptr) { + s = skip_spaces(t); + t = skip_nonspaces(s); + if(*t) *t++ = 0; + t = skip_spaces(t); + + if(!strcasecmp(s, "label")) { + menu_ptr->menu_label = strdup(t); + u = strlen(t); + if(u > label_size) label_size = u; + continue; + } + } + } + + fclose(f); + + // final '\0' + label_size++; + append_size++; + + // ensure we have a default entry + if(!menu_default->label) menu_default->label = menu->label; + + if(menu_default->label) { + for(menu_ptr = menu; menu_ptr; menu_ptr = menu_ptr->next) { + if(!strcmp(menu_default->label, menu_ptr->label)) { + menu_default->menu_label = menu_ptr->menu_label; + break; + } + } + } + + gfx_menu.entries = menu_idx; + gfx_menu.label_size = label_size; + gfx_menu.arg_size = append_size; + gfx_menu.default_entry = menu_default->menu_label; + gfx_menu.label_list = calloc(menu_idx, label_size); + gfx_menu.arg_list = calloc(menu_idx, append_size); + + for(u = 0, menu_ptr = menu; menu_ptr; menu_ptr = menu_ptr->next, u++) { + if(!menu_ptr->append) menu_ptr->append = menu_default->append; + if(!menu_ptr->ipappend) menu_ptr->ipappend = menu_default->ipappend; + + if(menu_ptr->menu_label) strcpy(gfx_menu.label_list + u * label_size, menu_ptr->menu_label); + if(menu_ptr->append) strcpy(gfx_menu.arg_list + u * append_size, menu_ptr->append); + } + + return 0; +} + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Check header and return code start offset. +// +unsigned magic_ok(unsigned char *buf, unsigned *code_size) +{ + if( + *(unsigned *) buf == 0x0b2d97f00 && // magic id + (buf[4] == 8) // version 8 + ) { + *code_size = *(unsigned *) (buf + 12); + return *(unsigned *) (buf + 8); + } + + return 0; +} + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Search (cpio archive) for gfx file. +// +unsigned find_file(unsigned char *buf, unsigned len, unsigned *gfx_file_start, unsigned *file_len, unsigned *code_size) +{ + unsigned i, fname_len, code_start = 0; + + *gfx_file_start = 0; + *code_size = 0; + + if((code_start = magic_ok(buf, code_size))) return code_start; + + for(i = 0; i < len;) { + if((len - i) >= 0x1a && (buf[i] + (buf[i + 1] << 8)) == 0x71c7) { + fname_len = *(unsigned short *) (buf + i + 20); + *file_len = *(unsigned short *) (buf + i + 24) + (*(unsigned short *) (buf + i + 22) << 16); + i += 26 + fname_len; + i = ((i + 1) & ~1); + if((code_start = magic_ok(buf + i, code_size))) { + *gfx_file_start = i; + return code_start; + } + i += *file_len; + i = ((i + 1) & ~1); + } + else { + break; + } + } + + return code_start; +} + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Initialize gfxboot code. +// +// return: +// 0: ok, 1: error +// +int gfx_init(char *file) +{ + size_t archive_size = 0; + void *archive; + unsigned code_start, code_size, file_start, file_len, u; + com32sys_t r; + void *lowmem = lowmem_buf; + unsigned lowmem_size = lowmem_buf_size; + + progress_active = 0; + + printf("Loading %s...\n", file); + if(loadfile(file, &archive, &archive_size)) return 1; + + if(!archive_size) return 1; + + // printf("%s: %d\n", file, archive_size); + + gfx_config.archive_start = (uint32_t) archive; + gfx_config.archive_end = gfx_config.archive_start + archive_size; + + // locate file inside cpio archive + if(!(code_start = find_file(archive, archive_size, &file_start, &file_len, &code_size))) { + printf("%s: invalid file format\n", file); + return 1; + } + +#if 0 + printf( + "code_start = 0x%x, code_size = 0x%x\n" + "archive_start = 0x%x, archive size = 0x%x\n" + "file_start = 0x%x, file_len = 0x%x\n", + code_start, code_size, + gfx_config.archive_start, archive_size, + file_start, file_len + ); +#endif + + gfx_config.file = gfx_config.archive_start + file_start; + + u = &realmode_callback_end - &realmode_callback_start; + u = (u + REALMODE_BUF_SIZE + 0xf) & ~0xf; + + if(u + code_size > lowmem_size) { + printf("bounce buffer too small: size %u, needed %u\n", lowmem_size, u + code_size); + return 1; + } + + memcpy(lowmem + REALMODE_BUF_SIZE, &realmode_callback_start, &realmode_callback_end - &realmode_callback_start); + + // fill in buffer size and location + *(uint16_t *) (lowmem + REALMODE_BUF_SIZE) = REALMODE_BUF_SIZE; + *(uint16_t *) (lowmem + REALMODE_BUF_SIZE + 2) = (uint32_t) lowmem >> 4; + + gfx_config.bootloader_seg = ((uint32_t) lowmem + REALMODE_BUF_SIZE) >> 4; + gfx_config.callback = 4; // start address + + lowmem += u; + lowmem_size -= u; + + memcpy(lowmem, archive + file_start + code_start, code_size); + + gfx_config.mem0_start = (uint32_t) lowmem + code_size; + gfx_config.mem0_end = (uint32_t) lowmem + lowmem_size; + // align a bit + gfx_config.mem0_start = (gfx_config.mem0_start + 0xf) & ~0xf; + + gfx_config.xmem_start = (uint32_t) malloc(GFX_MEMORY_SIZE << 20); + if(gfx_config.xmem_start) { + gfx_config.xmem_end = gfx_config.xmem_start + (GFX_MEMORY_SIZE << 20); + } + + // fake; not used anyway + gfx_config.bios_mem_size = 256 << 20; + + gfx.code_seg = (uint32_t) lowmem >> 4; + + for(u = 0; u < sizeof gfx.jmp_table / sizeof *gfx.jmp_table; u++) { + gfx.jmp_table[u] = (gfx.code_seg << 16) + *(uint16_t *) (lowmem + 2 * u); + } + +#if 0 + for(u = 0; u < sizeof gfx.jmp_table / sizeof *gfx.jmp_table; u++) { + printf("%d: 0x%08x\n", u, gfx.jmp_table[u]); + } +#endif + + // we are ready to start + + r.esi.l = (uint32_t) &gfx_config; + __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_INIT], &r, &r); + + if((r.eflags.l & EFLAGS_CF)) { + printf("graphics initialization failed\n"); + + return 1; + } + + if((gfx_config.features & 3) != 3) { + gfx_done(); + + printf("%s: boot graphics code too old, please use newer version\n", file); + + return 1; + } + + + return 0; +} + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +int gfx_menu_init(void) +{ + com32sys_t r; + + r.esi.l = (uint32_t) &gfx_menu; + __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_MENU_INIT], &r, &r); + + return 0; +} + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void gfx_done(void) +{ + com32sys_t r; + + gfx_progress_done(); + + __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_DONE], &r, &r); +} + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Run gfxboot main loop. +// +// return: +// boot menu index (-1: go to text mode prompt) +// +int gfx_input(void) +{ + com32sys_t r; + + r.edi.l = (uint32_t) cmdline; + r.ecx.l = sizeof cmdline; + r.eax.l = timeout * 182 / 100; + timeout = 0; // use timeout only first time + __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_INPUT], &r, &r); + if((r.eflags.l & EFLAGS_CF)) r.eax.l = 1; + + if(r.eax.l == 1) return -1; + + return r.ebx.l; +} + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void gfx_infobox(int type, char *str1, char *str2) +{ + com32sys_t r; + + r.eax.l = type; + r.esi.l = (uint32_t) str1; + r.edi.l = (uint32_t) str2; + __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_INFOBOX_INIT], &r, &r); + r.edi.l = r.eax.l = 0; + __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_INPUT], &r, &r); + __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_INFOBOX_DONE], &r, &r); +} + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void gfx_progress_init(ssize_t kernel_size, char *label) +{ + com32sys_t r; + + if(!progress_active) { + r.eax.l = kernel_size >> gfx_config.sector_shift; // in sectors + r.esi.l = (uint32_t) label; + __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_PROGRESS_INIT], &r, &r); + } + + progress_active = 1; +} + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void gfx_progress_update(ssize_t advance) +{ + com32sys_t r; + + if(progress_active) { + r.eax.l = advance >> gfx_config.sector_shift; // in sectors + __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_PROGRESS_UPDATE], &r, &r); + } +} + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void gfx_progress_done(void) +{ + com32sys_t r; + + if(progress_active) { + __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_PROGRESS_DONE], &r, &r); + } + + progress_active = 0; +} + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Like read(2) but preserve bounce buffer. +// +ssize_t save_read(int fd, void *buf, size_t size) +{ + ssize_t i; + + memcpy(save_buf, lowmem_buf, save_buf_size); + i = read(fd, buf, size); + memcpy(lowmem_buf, save_buf, save_buf_size); + + return i; +} + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Read file and update progress bar. +// +void *load_one(char *file, ssize_t *file_size) +{ + int fd; + void *buf = NULL; + char *str; + struct stat sbuf; + ssize_t size = 0, cur, i; + + *file_size = 0; + + if((fd = open(file, O_RDONLY)) == -1) { + asprintf(&str, "%s: file not found", file); + gfx_infobox(0, str, NULL); + free(str); + return buf; + } + + if(!fstat(fd, &sbuf) && S_ISREG(sbuf.st_mode)) size = sbuf.st_size; + + i = 0; + + if(size) { + buf = malloc(size); + for(i = 1, cur = 0 ; cur < size && i > 0; cur += i) { + i = save_read(fd, buf + cur, CHUNK_SIZE); + if(i == -1) break; + gfx_progress_update(i); + } + } + else { + do { + buf = realloc(buf, size + CHUNK_SIZE); + i = save_read(fd, buf + size, CHUNK_SIZE); + if(i == -1) break; + size += i; + gfx_progress_update(i); + } while(i > 0); + } + + close(fd); + + if(i == -1) { + asprintf(&str, "%s: read error @ %d", file, size); + gfx_infobox(0, str, NULL); + free(str); + free(buf); + buf = NULL; + size = 0; + } + + *file_size = size; + + return buf; +} + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Boot menu entry. +// +// cmdline can optionally start with label string. +// +void boot(int index) +{ + char *arg, *alt_kernel; + menu_t *menu_ptr; + int i, label_len; + unsigned ipapp; + const struct syslinux_ipappend_strings *ipappend; + + for(menu_ptr = menu; menu_ptr; menu_ptr = menu_ptr->next, index--) { + if(!index) break; + } + + // invalid index or menu entry + if(!menu_ptr || !menu_ptr->menu_label) return; + + arg = skip_spaces(cmdline); + label_len = strlen(menu_ptr->menu_label); + + // if it does not start with label string, assume first word is kernel name + if(strncmp(arg, menu_ptr->menu_label, label_len)) { + alt_kernel = arg; + arg = skip_nonspaces(arg); + if(*arg) *arg++ = 0; + if(*alt_kernel) menu_ptr->alt_kernel = alt_kernel; + } + else { + arg += label_len; + } + + arg = skip_spaces(arg); + + // handle IPAPPEND + if(menu_ptr->ipappend && (ipapp = atoi(menu_ptr->ipappend))) { + ipappend = syslinux_ipappend_strings(); + for(i = 0; i < ipappend->count; i++) { + if((ipapp & (1 << i)) && ipappend->ptr[i]) { + sprintf(arg + strlen(arg), " %s", ipappend->ptr[i]); + } + } + } + + boot_entry(menu_ptr, arg); + + gfx_progress_done(); +} + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Load & run kernel. +// +// Returns only on error. +// +void boot_entry(menu_t *menu_ptr, char *arg) +{ + void *kernel, *initrd_buf; + ssize_t kernel_size = 0, initrd_size = 0; + struct initramfs *initrd = NULL; + char *file, *cmd_buf; + int fd; + struct stat sbuf; + char *s, *s0, *t, *initrd_arg; + + if(!menu_ptr) return; + + if(menu_ptr->localboot) { + gfx_done(); + syslinux_local_boot(strtol(menu_ptr->localboot, NULL, 0)); + + return; + } + + file = menu_ptr->alt_kernel; + if(!file) file = menu_ptr->kernel; + if(!file) file = menu_ptr->linux; + if(!file) { + gfx_done(); + asprintf(&cmd_buf, "%s %s", menu_ptr->label, arg); + syslinux_run_command(cmd_buf); + return; + } + + // first, load kernel + + kernel_size = 0; + + if((fd = open(file, O_RDONLY)) >= 0) { + if(!fstat(fd, &sbuf) && S_ISREG(sbuf.st_mode)) kernel_size = sbuf.st_size; + close(fd); + } + + gfx_progress_init(kernel_size, file); + + kernel = load_one(file, &kernel_size); + + if(!kernel) { + return; + } + + if(kernel_size < 1024 || *(uint32_t *) (kernel + 0x202) != 0x53726448) { + // not a linux kernel + gfx_done(); + asprintf(&cmd_buf, "%s %s", menu_ptr->label, arg); + syslinux_run_command(cmd_buf); + return; + } + + // printf("kernel = %p, size = %d\n", kernel, kernel_size); + + // parse cmdline for "initrd" option + + initrd_arg = menu_ptr->initrd; + + s = s0 = strdup(arg); + + while(*s && strncmp(s, "initrd=", sizeof "initrd=" - 1)) { + s = skip_spaces(skip_nonspaces(s)); + } + + if(*s) { + s += sizeof "initrd=" - 1; + *skip_nonspaces(s) = 0; + initrd_arg = s; + } + + if(initrd_arg) { + initrd = initramfs_init(); + + while((t = strsep(&s, ","))) { + initrd_buf = load_one(t, &initrd_size); + + if(!initrd_buf) { + printf("%s: read error\n", t); + free(s0); + return; + } + + initramfs_add_data(initrd, initrd_buf, initrd_size, initrd_size, 4); + + // printf("initrd = %p, size = %d\n", initrd_buf, initrd_size); + } + } + + free(s0); + + gfx_done(); + + syslinux_boot_linux(kernel, kernel_size, initrd, arg); +} + + diff --git a/contrib/syslinux-4.02/com32/gfxboot/realmode_callback.asm b/contrib/syslinux-4.02/com32/gfxboot/realmode_callback.asm new file mode 100644 index 0000000..2ff30f2 --- /dev/null +++ b/contrib/syslinux-4.02/com32/gfxboot/realmode_callback.asm @@ -0,0 +1,190 @@ + bits 16 + + section .text + + ; must be filled in +f_buf_size dw 0 +f_buf_seg dw 0 + + +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +gfx_cb: + push cs + pop ds + + cmp al,cb_len + jae gfx_cb_80 + + movzx bx,al + add bx,bx + call word [bx+cb_table] + jmp gfx_cb_90 + +gfx_cb_80: + mov al,0ffh +gfx_cb_90: + retf + + +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; Return status info. +; +; return: +; edx filename buffer (64 bytes) +; +cb_status: + mov edx,cs + shl edx,4 + add edx,f_name + xor al,al + ret + + +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; Open file. +; +; return: +; al 0: ok, 1: file not found +; ecx file length (al = 0) +; +cb_fopen: + mov si,f_name + push ds + pop es + mov ax,6 + int 22h + xchg edx,eax + mov al,1 + jc cb_fopen_90 + cmp cx,[f_buf_size] + ja cb_fopen_90 + or cx,cx + jz cb_fopen_90 + mov [f_block_size],cx + or edx,edx + jz cb_fopen_90 + mov [f_handle],si + mov [f_size],edx + mov ecx,edx + mov ax,[f_buf_size] + cwd + div word [f_block_size] + mov [f_blocks],ax + + xor al,al +cb_fopen_90: + ret + + +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; Read next chunk. +; +; return: +; edx buffer address (linear) +; ecx data length (< 64k) +; +cb_fread: + xor ecx,ecx + mov si,[f_handle] + or si,si + jz cb_fread_80 + mov cx,[f_blocks] + mov es,[f_buf_seg] + xor bx,bx + mov ax,7 + int 22h + mov [f_handle],si + mov al,1 + jc cb_fread_90 +cb_fread_80: + xor al,al +cb_fread_90: + movzx edx,word [f_buf_seg] + shl edx,4 + ret + + +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; Return current working directory. +; +; return: +; edx filename +; +cb_getcwd: + mov ax,1fh + int 22h + mov edx,es + shl edx,4 + movzx ebx,bx + add edx,ebx + xor al,al + ret + + +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; Set current working directory. +; +cb_chdir: + mov bx,f_name + push ds + pop es + mov ax,25h + int 22h + xor al,al + ret + + +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; read sector +; +; edx sector +; +; return: +; edx buffer (linear address) +; +; Note: does not return on error! +; +cb_readsector: + xor edi,edi + xor esi,esi + mov cx,1 + mov es,[f_buf_seg] + xor bx,bx + mov ax,19h + int 22h + movzx edx,word [f_buf_seg] + shl edx,4 + xor al,al + ret + + +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; Re-read fs structures. +; +cb_mount: + mov ax,26h + int 22h + setc al + ret + + +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; + align 2, db 0 + +cb_table dw cb_status + dw cb_fopen + dw cb_fread + dw cb_getcwd + dw cb_chdir + dw cb_readsector + dw cb_mount +cb_len equ ($-cb_table)/2 + +f_handle dw 0 +f_block_size dw 0 +f_blocks dw 0 +f_size dd 0 +f_name times 64 db 0 +f_name_len equ $ - f_name + diff --git a/contrib/syslinux-4.02/com32/gplinclude/README b/contrib/syslinux-4.02/com32/gplinclude/README new file mode 100644 index 0000000..ac1bf6a --- /dev/null +++ b/contrib/syslinux-4.02/com32/gplinclude/README @@ -0,0 +1 @@ +Put header files for LGPL or GPL library functions in this directory. diff --git a/contrib/syslinux-4.02/com32/gplinclude/cpuid.h b/contrib/syslinux-4.02/com32/gplinclude/cpuid.h new file mode 100644 index 0000000..bc9df17 --- /dev/null +++ b/contrib/syslinux-4.02/com32/gplinclude/cpuid.h @@ -0,0 +1,269 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2006-2009 Erwan Velu - All Rights Reserved + * + * Portions of this file taken from the Linux kernel, + * Copyright 1991-2009 Linus Torvalds and contributors + * + * 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. + * + * ----------------------------------------------------------------------- */ + +#ifndef _CPUID_H +#define _CPUID_H + +#include <stdbool.h> +#include <stdint.h> +#include <cpufeature.h> +#include <sys/cpu.h> +#include <klibc/compiler.h> + +#define PAGE_SIZE 4096 + +#define CPU_MODEL_SIZE 48 +#define CPU_VENDOR_SIZE 48 + +typedef struct { + bool fpu; /* Onboard FPU */ + bool vme; /* Virtual Mode Extensions */ + bool de; /* Debugging Extensions */ + bool pse; /* Page Size Extensions */ + bool tsc; /* Time Stamp Counter */ + bool msr; /* Model-Specific Registers, RDMSR, WRMSR */ + bool pae; /* Physical Address Extensions */ + bool mce; /* Machine Check Architecture */ + bool cx8; /* CMPXCHG8 instruction */ + bool apic; /* Onboard APIC */ + bool sep; /* SYSENTER/SYSEXIT */ + bool mtrr; /* Memory Type Range Registers */ + bool pge; /* Page Global Enable */ + bool mca; /* Machine Check Architecture */ + bool cmov; /* CMOV instruction (FCMOVCC and FCOMI too if FPU present) */ + bool pat; /* Page Attribute Table */ + bool pse_36; /* 36-bit PSEs */ + bool psn; /* Processor serial number */ + bool clflsh; /* Supports the CLFLUSH instruction */ + bool dts; /* Debug Trace Store */ + bool acpi; /* ACPI via MSR */ + bool pbe; /* Pending Break Enable */ + bool mmx; /* Multimedia Extensions */ + bool fxsr; /* FXSAVE and FXRSTOR instructions (fast save and restore */ + /* of FPU context), and CR4.OSFXSR available */ + bool sse; /* Streaming SIMD Extensions */ + bool sse2; /* Streaming SIMD Extensions 2 */ + bool ss; /* CPU self snoop */ + bool htt; /* Hyper-Threading */ + bool acc; /* Automatic clock control */ + bool syscall; /* SYSCALL/SYSRET */ + bool mp; /* MP Capable. */ + bool nx; /* Execute Disable */ + bool mmxext; /* AMD MMX extensions */ + bool fxsr_opt; /* FXSAVE/FXRSTOR optimizations */ + bool gbpages; /* "pdpe1gb" GB pages */ + bool rdtscp; /* RDTSCP */ + bool lm; /* Long Mode (x86-64) */ + bool nowext; /* AMD 3DNow! extensions */ + bool now; /* 3DNow! */ + bool smp; /* A smp configuration has been found */ + bool pni; /* Streaming SIMD Extensions-3 */ + bool pclmulqd; /* PCLMULQDQ instruction */ + bool dtes64; /* 64-bit Debug Store */ + bool vmx; /* Hardware virtualization */ + bool smx; /* Safer Mode */ + bool est; /* Enhanced SpeedStep */ + bool tm2; /* Thermal Monitor 2 */ + bool sse3; /* Supplemental SSE-3 */ + bool cid; /* Context ID */ + bool fma; /* Fused multiply-add */ + bool cx16; /* CMPXCHG16B */ + bool xtpr; /* Send Task Priority Messages */ + bool pdcm; /* Performance Capabilities */ + bool dca; /* Direct Cache Access */ + bool xmm4_1; /* "sse4_1" SSE-4.1 */ + bool xmm4_2; /* "sse4_2" SSE-4.2 */ + bool x2apic; /* x2APIC */ + bool movbe; /* MOVBE instruction */ + bool popcnt; /* POPCNT instruction */ + bool aes; /* AES Instruction */ + bool xsave; /* XSAVE/XRSTOR/XSETBV/XGETBV */ + bool osxsave; /* XSAVE enabled in the OS */ + bool avx; /* Advanced Vector Extensions */ + bool hypervisor; /* Running on a hypervisor */ + bool ace2; /* Advanced Cryptography Engine v2 */ + bool ace2_en; /* ACE v2 enabled */ + bool phe; /* PadLock Hash Engine */ + bool phe_en; /* PadLock Hash Engine Enabled */ + bool pmm; /* PadLock Montgomery Multiplier */ + bool pmm_en; /* PadLock Montgomery Multiplier enabled */ + bool svm; /* Secure virtual machine */ + bool extapic; /* Extended APIC space */ + bool cr8_legacy; /* CR8 in 32-bit mode */ + bool abm; /* Advanced bit manipulation */ + bool sse4a; /* SSE4-A */ + bool misalignsse; /* Misaligned SSE mode */ + bool nowprefetch; /* 3DNow prefetch instructions */ + bool osvw; /* OS Visible Workaround */ + bool ibs; /* Instruction Based Sampling */ + bool sse5; /* SSE5 */ + bool skinit; /* SKINIT/STGI instructions */ + bool wdt; /* Watchdog Timer */ + bool ida; /* Intel Dynamic Acceleration */ + bool arat; /* Always Running APIC Timer */ + bool tpr_shadow; /* Intel TPR Shadow */ + bool vnmi; /* Intel Virtual NMI */ + bool flexpriority; /* Intel FlexPriority */ + bool ept; /* Intel Extended Page Table */ + bool vpid; /* Intel Virtual Processor ID */ +} s_cpu_flags; + +typedef struct { + char vendor[CPU_VENDOR_SIZE]; + uint8_t vendor_id; + uint8_t family; + char model[CPU_MODEL_SIZE]; + uint8_t model_id; + uint8_t stepping; + uint8_t num_cores; + uint16_t l1_data_cache_size; + uint16_t l1_instruction_cache_size; + uint16_t l2_cache_size; + s_cpu_flags flags; +} s_cpu; + +/**********************************************************************************/ +/**********************************************************************************/ +/* From this point this is some internal stuff mainly taken from the linux kernel */ +/**********************************************************************************/ +/**********************************************************************************/ + +/* + * EFLAGS bits + */ +#define X86_EFLAGS_CF 0x00000001 /* Carry Flag */ +#define X86_EFLAGS_PF 0x00000004 /* Parity Flag */ +#define X86_EFLAGS_AF 0x00000010 /* Auxillary carry Flag */ +#define X86_EFLAGS_ZF 0x00000040 /* Zero Flag */ +#define X86_EFLAGS_SF 0x00000080 /* Sign Flag */ +#define X86_EFLAGS_TF 0x00000100 /* Trap Flag */ +#define X86_EFLAGS_IF 0x00000200 /* Interrupt Flag */ +#define X86_EFLAGS_DF 0x00000400 /* Direction Flag */ +#define X86_EFLAGS_OF 0x00000800 /* Overflow Flag */ +#define X86_EFLAGS_IOPL 0x00003000 /* IOPL mask */ +#define X86_EFLAGS_NT 0x00004000 /* Nested Task */ +#define X86_EFLAGS_RF 0x00010000 /* Resume Flag */ +#define X86_EFLAGS_VM 0x00020000 /* Virtual Mode */ +#define X86_EFLAGS_AC 0x00040000 /* Alignment Check */ +#define X86_EFLAGS_VIF 0x00080000 /* Virtual Interrupt Flag */ +#define X86_EFLAGS_VIP 0x00100000 /* Virtual Interrupt Pending */ +#define X86_EFLAGS_ID 0x00200000 /* CPUID detection flag */ + +#define X86_VENDOR_INTEL 0 +#define X86_VENDOR_CYRIX 1 +#define X86_VENDOR_AMD 2 +#define X86_VENDOR_UMC 3 +#define X86_VENDOR_NEXGEN 4 +#define X86_VENDOR_CENTAUR 5 +#define X86_VENDOR_RISE 6 +#define X86_VENDOR_TRANSMETA 7 +#define X86_VENDOR_NSC 8 +#define X86_VENDOR_NUM 9 +#define X86_VENDOR_UNKNOWN 0xff + +static inline __purefunc bool test_bit(int nr, const uint32_t * addr) +{ + return ((1UL << (nr & 31)) & (addr[nr >> 5])) != 0; +} + +#define cpu_has(c, bit) test_bit(bit, (c)->x86_capability) + +/* + * CPU type and hardware bug flags. Kept separately for each CPU. + * Members of this structure are referenced in head.S, so think twice + * before touching them. [mj] + */ + +struct cpuinfo_x86 { + uint8_t x86; /* CPU family */ + uint8_t x86_vendor; /* CPU vendor */ + uint8_t x86_model; + uint8_t x86_mask; + char wp_works_ok; /* It doesn't on 386's */ + char hlt_works_ok; /* Problems on some 486Dx4's and old 386's */ + char hard_math; + char rfu; + int cpuid_level; /* Maximum supported CPUID level, -1=no CPUID */ + uint32_t x86_capability[NCAPINTS]; + char x86_vendor_id[16]; + char x86_model_id[64]; + uint16_t x86_l1_data_cache_size; /* in KB, if available */ + uint16_t x86_l1_instruction_cache_size; /* in KB, if available */ + uint16_t x86_l2_cache_size; /* in KB, if available */ + int x86_cache_alignment; /* in bytes */ + char fdiv_bug; + char f00f_bug; + char coma_bug; + char pad0; + int x86_power; + unsigned long loops_per_jiffy; +#ifdef CONFIG_SMP + cpumask_t llc_shared_map; /* cpus sharing the last level cache */ +#endif + unsigned char x86_num_cores; /* cpuid returned the number of cores */ + unsigned char booted_cores; /* number of cores as seen by OS */ + unsigned char apicid; + unsigned char x86_clflush_size; + +} __attribute__ ((__packed__)); + +struct cpu_model_info { + int vendor; + int family; + char *model_names[16]; +}; + +/* attempt to consolidate cpu attributes */ +struct cpu_dev { + const char *c_vendor; + + /* some have two possibilities for cpuid string */ + const char *c_ident[2]; + + struct cpu_model_info c_models[4]; + + void (*c_init) (struct cpuinfo_x86 * c); + void (*c_identify) (struct cpuinfo_x86 * c); + unsigned int (*c_size_cache) (struct cpuinfo_x86 * c, unsigned int size); +}; + +/* + * Structure definitions for SMP machines following the + * Intel Multiprocessing Specification 1.1 and 1.4. + */ + +/* + * This tag identifies where the SMP configuration + * information is. + */ + +#define SMP_MAGIC_IDENT (('_'<<24)|('P'<<16)|('M'<<8)|'_') + +struct intel_mp_floating { + char mpf_signature[4]; /* "_MP_" */ + uint32_t mpf_physptr; /* Configuration table address */ + uint8_t mpf_length; /* Our length (paragraphs) */ + uint8_t mpf_specification; /* Specification version */ + uint8_t mpf_checksum; /* Checksum (makes sum 0) */ + uint8_t mpf_feature1; /* Standard or configuration ? */ + uint8_t mpf_feature2; /* Bit7 set for IMCR|PIC */ + uint8_t mpf_feature3; /* Unused (0) */ + uint8_t mpf_feature4; /* Unused (0) */ + uint8_t mpf_feature5; /* Unused (0) */ +}; + +extern void get_cpu_vendor(struct cpuinfo_x86 *c); +extern void detect_cpu(s_cpu * cpu); +#endif diff --git a/contrib/syslinux-4.02/com32/gplinclude/disk/bootloaders.h b/contrib/syslinux-4.02/com32/gplinclude/disk/bootloaders.h new file mode 100644 index 0000000..56a0f4e --- /dev/null +++ b/contrib/syslinux-4.02/com32/gplinclude/disk/bootloaders.h @@ -0,0 +1,19 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#ifndef __BOOTLOADERS_H_ +#define __BOOTLOADERS_H_ + +#include <stdint.h> +#include <disk/geom.h> +#include <disk/partition.h> + +int get_bootloader_string(struct driveinfo *, const struct part_entry *, + char *, const int); +#endif /* __BOOTLOADERS_H_ */ diff --git a/contrib/syslinux-4.02/com32/gplinclude/disk/common.h b/contrib/syslinux-4.02/com32/gplinclude/disk/common.h new file mode 100644 index 0000000..4e415c1 --- /dev/null +++ b/contrib/syslinux-4.02/com32/gplinclude/disk/common.h @@ -0,0 +1,33 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#ifndef _COMMON_H_ +#define _COMMON_H_ + +#include <stdint.h> + +/* For PAGE_SIZE */ +#include <cpuid.h> + +#define SECTOR 512 /* bytes/sector */ + +struct ebios_dapa { + uint16_t len; + uint16_t count; + uint16_t off; + uint16_t seg; + uint64_t lba; +}; + +#endif /* _COMMON_H_ */ diff --git a/contrib/syslinux-4.02/com32/gplinclude/disk/errno_disk.h b/contrib/syslinux-4.02/com32/gplinclude/disk/errno_disk.h new file mode 100644 index 0000000..68bd89d --- /dev/null +++ b/contrib/syslinux-4.02/com32/gplinclude/disk/errno_disk.h @@ -0,0 +1,50 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#ifndef _ERRNO_DISK_H +#define _ERRNO_DISK_H + +extern int errno_disk; + +/* Prefix with ED to avoid confusion with errno */ +#define EDINV 0x01 /* Invalid function in AH or invalid parameter */ +#define EDADDR 0x02 /* Address mark not found */ +#define EDRO 0x03 /* Disk write-protected */ +#define EDNOFND 0x04 /* Sector not found/read error */ +#define EDRFAIL 0x05 /* Reset failed (hard disk) */ +#define EDCHANG 0x06 /* Disk changed (floppy) */ +#define EDFAIL 0x07 /* Drive parameter activity failed (hard disk) */ +#define EDDMA 0x08 /* DMA overrun */ +#define EDBOUND 0x09 /* Data boundary error (attempted DMA across 64K boundary or >80h sectors) */ +#define EDBADS 0x0A /* Bad sector detected (hard disk) */ +#define EDBADT 0x0B /* Bad track detected (hard disk) */ +#define EDINVM 0x0C /* Unsupported track or invalid media */ +#define EDINVS 0x0D /* Invalid number of sectors on format (PS/2 hard disk) */ +#define EDADDRM 0x0E /* Control data address mark detected (hard disk) */ +#define EDDMARG 0x0F /* DMA arbitration level out of range (hard disk) */ +#define EDCRCF 0x10 /* Uncorrectable CRC or ECC error on read */ +#define EDCRCV 0x11 /* Data ECC corrected (hard disk) */ +#define EDCTRL 0x20 /* Controller failure */ +#define EDMEDIA 0x31 /* No media in drive (IBM/MS INT 13 extensions) */ +#define EDCMOS 0x32 /* Incorrect drive type stored in CMOS (Compaq) */ +#define EDSEEKF 0x40 /* Seek failed */ +#define EDTIME 0x80 /* Timeout (not ready) */ +#define EDREADY 0xAA /* Drive not ready (hard disk) */ +#define EDNLOCK 0xB0 /* Volume not locked in drive (INT 13 extensions) */ +#define EDLOCK 0xB1 /* Volume locked in drive (INT 13 extensions) */ +#define EDREMOV 0xB2 /* Volume not removable (INT 13 extensions) */ +#define EDUSED 0xB3 /* Volume in use (INT 13 extensions) */ +#define EDCOUNT 0xB4 /* Lock count exceeded (INT 13 extensions) */ +#define EDEJF 0xB5 /* Valid eject request failed (INT 13 extensions) */ +#define EDUNKOWN 0xBB /* Undefined error (hard disk) */ +#define EDWF 0xCC /* Write fault (hard disk) */ +#define EDRF 0xE0 /* Status register error (hard disk) */ +#define EDSF 0xFF /* Sense operation failed (hard disk) */ + +#endif /* _ERRNO_DISK_H */ diff --git a/contrib/syslinux-4.02/com32/gplinclude/disk/error.h b/contrib/syslinux-4.02/com32/gplinclude/disk/error.h new file mode 100644 index 0000000..e00266f --- /dev/null +++ b/contrib/syslinux-4.02/com32/gplinclude/disk/error.h @@ -0,0 +1,13 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#ifndef _ERROR_H_ +#define _ERROR_H_ +void get_error(const char *); +#endif /* _ERROR_H_ */ diff --git a/contrib/syslinux-4.02/com32/gplinclude/disk/geom.h b/contrib/syslinux-4.02/com32/gplinclude/disk/geom.h new file mode 100644 index 0000000..359c7cf --- /dev/null +++ b/contrib/syslinux-4.02/com32/gplinclude/disk/geom.h @@ -0,0 +1,326 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * Some parts borrowed from Linux: + * + * Copyright (C) 2002, 2003, 2004 Dell Inc. + * by Matt Domsch <Matt_Domsch@dell.com> + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#ifndef _GEOM_H_ +#define _GEOM_H_ + +#include <stdint.h> + +/** + * INT 13 Extensions + * + * Note: if the size is less than 30 on call, the final DWORD will not be + * returned by a v2.x implementation; similarly for the Device Path info + **/ +struct edd_device_parameters { + uint16_t len; /* size of returned data */ + /** + * Bitfields for IBM/MS INT 13 Extensions information flags: + * Bit(s) Description (Table 00274) + * 0 DMA boundary errors handled transparently + * 1 cylinder/head/sectors-per-track information is valid + * 2 removable drive + * 3 write with verify supported + * 4 drive has change-line support (required if drive >= 80h is removable) + * 5 drive can be locked (required if drive >= 80h is removable) + * 6 CHS information set to maximum supported values, not current media + * 15-7 reserved (0) + **/ + uint16_t info; /* information flags */ + uint32_t cylinders; /* number of physical cylinders on drive */ + uint32_t heads; /* number of physical heads on drive */ + uint32_t sectors_per_track; /* number of physical sectors per track */ + uint64_t sectors; /* total number of sectors on drive */ + uint16_t bytes_per_sector; /* bytes per sector */ + /* --- v2.0+ --- */ + uint32_t dpte_pointer; /* EDD configuration parameters, FFFFh:FFFFh if not available */ + /* --- v3.0 --- */ + uint16_t device_path_information; /* signature BEDDh to indicate presence of Device Path info */ + uint8_t device_path_length; /* length of Device Path information, including signature and this byte (24h for v3.0) */ + uint8_t device_path_reserved; /* reserved (0) */ + uint16_t device_path_reserved_2; /* reserved (0) */ + uint8_t host_bus_type[4]; /* ASCIZ name of host bus ("ISA" or "PCI") */ + uint8_t interface_type[8]; /* ASCIZ name of interface type + * "ATA" + * "ATAPI" + * "SCSI" + * "USB" + * "1394" IEEE 1394 (FireWire) + * "FIBRE" Fibre Channel + */ + /** + * Format of EDD v3.0 Interface Path: + * Offset Size Description (Table 00275) + * ---ISA--- + * 00h WORD 16-bit base address + * 02h 6 BYTEs reserved (0) + * ---PCI--- + * 00h BYTE PCI bus number + * 01h BYTE PCI device number + * 02h BYTE PCI function number + * 03h 5 BYTEs reserved (0) + **/ + union { + struct { + uint16_t base_address; + uint16_t reserved1; + uint32_t reserved2; + } __attribute__ ((packed)) isa; + struct { + uint8_t bus; + uint8_t slot; + uint8_t function; + uint8_t channel; + uint32_t reserved; + } __attribute__ ((packed)) pci; + /* pcix is same as pci */ + struct { + uint64_t reserved; + } __attribute__ ((packed)) ibnd; + struct { + uint64_t reserved; + } __attribute__ ((packed)) xprs; + struct { + uint64_t reserved; + } __attribute__ ((packed)) htpt; + struct { + uint64_t reserved; + } __attribute__ ((packed)) unknown; + } interface_path; + /** + * Format of EDD v3.0 Device Path: + * Offset Size Description (Table 00276) + * ---ATA--- + * 00h BYTE flag: 00h = master, 01h = slave + * 01h 7 BYTEs reserved (0) + * ---ATAPI--- + * 00h BYTE flag: 00h = master, 01h = slave + * 01h BYTE logical unit number + * 02h 6 BYTEs reserved (0) + * ---SCSI--- + * 00h BYTE logical unit number + * 01h 7 BYTEs reserved (0) + * ---USB--- + * 00h BYTE to be determined + * 01h 7 BYTEs reserved (0) + * ---IEEE1394--- + * 00h QWORD 64-bit FireWire General Unique Identifier (GUID) + * ---FibreChannel--- + * 00h QWORD Word Wide Number (WWN) + **/ + union { + struct { + uint8_t device; + uint8_t reserved1; + uint16_t reserved2; + uint32_t reserved3; + uint64_t reserved4; + } __attribute__ ((packed)) ata; + struct { + uint8_t device; + uint8_t lun; + uint8_t reserved1; + uint8_t reserved2; + uint32_t reserved3; + uint64_t reserved4; + } __attribute__ ((packed)) atapi; + struct { + uint16_t id; + uint64_t lun; + uint16_t reserved1; + uint32_t reserved2; + } __attribute__ ((packed)) scsi; + struct { + uint64_t serial_number; + uint64_t reserved; + } __attribute__ ((packed)) usb; + struct { + uint64_t eui; + uint64_t reserved; + } __attribute__ ((packed)) i1394; + struct { + uint64_t wwid; + uint64_t lun; + } __attribute__ ((packed)) fibre; + struct { + uint64_t identity_tag; + uint64_t reserved; + } __attribute__ ((packed)) i2o; + struct { + uint32_t array_number; + uint32_t reserved1; + uint64_t reserved2; + } __attribute__ ((packed)) raid; + struct { + uint8_t device; + uint8_t reserved1; + uint16_t reserved2; + uint32_t reserved3; + uint64_t reserved4; + } __attribute__ ((packed)) sata; + struct { + uint64_t reserved1; + uint64_t reserved2; + } __attribute__ ((packed)) unknown; + } device_path; + uint8_t reserved; /* reserved (0) */ + uint8_t checksum; /* checksum of bytes 1Eh-40h (two's complement of sum, which makes + * the 8-bit sum of bytes 1Eh-41h equal 00h) */ +} __attribute__ ((packed)); + +/* + * Disk parameters + */ +struct driveinfo { + int disk; /* Disk port (0x80 - 0xff) */ + /* Legacy C/H/S */ + int cbios; /* CHS geometry is valid */ + int legacy_max_head; + int legacy_max_cylinder; + int legacy_sectors_per_track; + int legacy_max_drive; + int legacy_type; /* Drive type (AT/PS2 floppies only) */ + /* EDD support */ + int ebios; /* EBIOS supported on this disk */ + int edd_version; /* EBIOS major version */ + int edd_functionality_subset; + struct edd_device_parameters edd_params; /* EDD parameters */ +}; + +/** + * Format of Phoenix Enhanced Disk Drive Spec translated drive parameter table: + * Offset Size Description (Table 00277) + * 00h WORD number of cylinders + * 02h BYTE number of heads + * 03h BYTE A0h (signature indicating translated table) + * 04h BYTE number of physical sectors per track + * 05h WORD starting write precompensation cylinder number + * 07h BYTE reserved + * 08h BYTE control byte (see #03198 at INT 41"DISK 0") + * 09h WORD number of physical cylinders + * 0Bh BYTE number of physical heads + * 0Ch WORD cylinder number of landing zone + * 0Eh BYTE number of logical sectors per track + * 0Fh BYTE checksum + * Program: the Phoenix Enhanced Disk Drive Specification is an addition to the + * IBM/MS INT 13 extensions + * + * Format of Phoenix Enhanced Disk Drive Spec Fixed Disk Parameter Table: + * Offset Size Description (Table 00278) + * 00h WORD physical I/O port base address + * 02h WORD disk-drive control port address + * 04h BYTE drive flags (see #00279) + * 05h BYTE proprietary information + * bits 7-4 reserved (0) + * bits 3-0: Phoenix proprietary (used by BIOS) + * 06h BYTE IRQ for drive (bits 3-0; bits 7-4 reserved and must be 0) + * 07h BYTE sector count for multi-sector transfers + * 08h BYTE DMA control + * bits 7-4: DMA type (0-2) as per ATA-2 specification + * bits 3-0: DMA channel + * 09h BYTE programmed I/O control + * bits 7-4: reserved (0) + * bits 3-0: PIO type (1-4) as per ATA-2 specification + * 0Ah WORD drive options (see #00280) + * 0Ch 2 BYTEs reserved (0) + * 0Eh BYTE extension revision level (high nybble=major, low nybble=minor) + * (currently 10h for v1.0 and 11h for v1.1-3.0) + * 0Fh BYTE 2's complement checksum of bytes 00h-0Eh + * 8-bit sum of all bytes 00h-0Fh should equal 00h + * SeeAlso: #00277 + * + * Bitfields for Phoenix Enhanced Disk Drive Spec drive flags: + * Bit(s) Description (Table 00279) + * 7 reserved (1) + * 6 LBA enabled + * 5 reserved (1) + * 4 drive is slave + * 3-0 reserved (0) + * SeeAlso: #00278,#00280 + * + * Bitfields for Phoenix Enhanced Disk Drive Spec drive options: + * Bit(s) Description (Table 00280) + * 0 fast PIO enabled + * 1 fast DMA access enabled + * 2 block PIO (multi-sector transfers) enabled + * 3 CHS translation enabled + * 4 LBA translation enabled + * 5 removable media + * 6 ATAPI device (CD-ROM) + * 7 32-bit transfer mode + * ---v1.1+ --- + * 8 ATAPI device uses DRQ to signal readiness for packet command + * (must be 0 if bit 6 is 0) + * 10-9 translation type (must be 00 if bit 3 is 0) + * 00 Phoenix bit-shifting translation + * 01 LBA-assisted translation + * 10 reserved + * 11 proprietary translation + * ---v3.0--- + * 11 Ultra DMA access enabled + * 15-12 reserved + **/ + +/* + * Values for diskette drive type: + * 01h 360K + * 02h 1.2M + * 03h 720K + * 04h 1.44M + * 05h ??? + * reportedly an obscure drive type shipped on some IBM machines, + * 2.88M on some machines (at least AMI 486 BIOS) + * 06h 2.88M + * 10h ATAPI Removable Media Device + */ +enum diskette_drive_types { + DISKETTE_360K = 1, + DISKETTE_1_2M = 2, + DISKETTE_720K = 3, + DISKETTE_1_44M = 4, + DISKETTE_2_88M = 6, + DISKETTE_ATAPI = 10, +}; + +/** + * chs_to_lba - compute lba value from cylinder, head and sector number + **/ +static inline int chs_to_lba(const struct driveinfo *drive_info, + const unsigned int cylinder, + const unsigned int head, const unsigned int sector) +{ + /* Use EDD, if valid */ + if (drive_info->edd_params.sectors_per_track > 0 && + drive_info->edd_params.heads > 0) + return (sector - 1) + + (head * drive_info->edd_params.sectors_per_track) + + (cylinder * (drive_info->edd_params.heads) * + drive_info->edd_params.sectors_per_track); + else if (drive_info->cbios) + return (sector - 1) + (head * drive_info->legacy_sectors_per_track) + + (cylinder * (drive_info->legacy_max_head + 1) * + drive_info->legacy_sectors_per_track); +} + +void lba_to_chs(const struct driveinfo *drive_info, const int lba, + unsigned int *cylinder, unsigned int *head, + unsigned int *sector); +int get_drive_parameters(struct driveinfo *drive_info); + +#endif /* _GEOM_H */ diff --git a/contrib/syslinux-4.02/com32/gplinclude/disk/mbrs.h b/contrib/syslinux-4.02/com32/gplinclude/disk/mbrs.h new file mode 100644 index 0000000..ad104ff --- /dev/null +++ b/contrib/syslinux-4.02/com32/gplinclude/disk/mbrs.h @@ -0,0 +1,18 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#ifndef __MBRS_H_ +#define __MBRS_H_ + +#include <stdint.h> +#include <disk/geom.h> + +void get_mbr_string(const uint32_t, void *, const int); +uint32_t get_mbr_id(const struct driveinfo *); +#endif /* __MBRS_H_ */ diff --git a/contrib/syslinux-4.02/com32/gplinclude/disk/msdos.h b/contrib/syslinux-4.02/com32/gplinclude/disk/msdos.h new file mode 100644 index 0000000..cb39dad --- /dev/null +++ b/contrib/syslinux-4.02/com32/gplinclude/disk/msdos.h @@ -0,0 +1,19 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#ifndef _MSDOS_H_ +#define _MSDOS_H_ + +#include <disk/geom.h> +#include <disk/partition.h> + +typedef void (*p_callback) (struct driveinfo *, struct part_entry *, int, int); +int parse_partition_table(struct driveinfo *, p_callback); + +#endif /* _MSDOS_H_ */ diff --git a/contrib/syslinux-4.02/com32/gplinclude/disk/partition.h b/contrib/syslinux-4.02/com32/gplinclude/disk/partition.h new file mode 100644 index 0000000..5edf828 --- /dev/null +++ b/contrib/syslinux-4.02/com32/gplinclude/disk/partition.h @@ -0,0 +1,37 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#ifndef _PARTITION_H_ +#define _PARTITION_H_ + +#include <stdint.h> + +#define PARTITION_TABLES_OFFSET 0x1be + +/* A DOS partition table entry */ +struct part_entry { + uint8_t active_flag; /* 0x80 if "active" */ + uint8_t start_head; + uint8_t start_sect; + uint8_t start_cyl; + uint8_t ostype; + uint8_t end_head; + uint8_t end_sect; + uint8_t end_cyl; + uint32_t start_lba; + uint32_t length; +} __attribute__ ((packed)); + +void get_label(int label, char **buffer_label); +#endif /* _PARTITION_H_ */ diff --git a/contrib/syslinux-4.02/com32/gplinclude/disk/read.h b/contrib/syslinux-4.02/com32/gplinclude/disk/read.h new file mode 100644 index 0000000..08a9dd3 --- /dev/null +++ b/contrib/syslinux-4.02/com32/gplinclude/disk/read.h @@ -0,0 +1,18 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#ifndef _READ_H_ +#define _READ_H_ + +#include <disk/geom.h> + +int read_mbr(int, void *); +int dev_read(int, void *, unsigned int, int); +int read_sectors(struct driveinfo *, void *, const unsigned int, const int); +#endif /* _READ_H */ diff --git a/contrib/syslinux-4.02/com32/gplinclude/disk/swsusp.h b/contrib/syslinux-4.02/com32/gplinclude/disk/swsusp.h new file mode 100644 index 0000000..3e9acac --- /dev/null +++ b/contrib/syslinux-4.02/com32/gplinclude/disk/swsusp.h @@ -0,0 +1,19 @@ +#ifndef _SWSUSP_H_ +#define _SWSUSP_H_ + +#include <disk/geom.h> +#include <disk/common.h> +#include <disk/partition.h> + +#define SWSUSP_SIG "S1SUSPEND" + +struct swsusp_header { + char reserved[PAGE_SIZE - 20 - sizeof(unsigned long) - sizeof(int)]; + unsigned long image; + unsigned int flags; /* Flags to pass to the "boot" kernel */ + char orig_sig[10]; + char sig[10]; +} __attribute__ ((packed)); + +int swsusp_check(struct driveinfo *, struct part_entry *); +#endif /* _SWSUSP_H */ diff --git a/contrib/syslinux-4.02/com32/gplinclude/disk/util.h b/contrib/syslinux-4.02/com32/gplinclude/disk/util.h new file mode 100644 index 0000000..52f085a --- /dev/null +++ b/contrib/syslinux-4.02/com32/gplinclude/disk/util.h @@ -0,0 +1,21 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#ifndef _UTIL_H_ +#define _UTIL_H_ + +#include <com32.h> + +int int13_retry(const com32sys_t * inreg, com32sys_t * outreg); +#endif /* _UTIL_H_ */ diff --git a/contrib/syslinux-4.02/com32/gplinclude/disk/write.h b/contrib/syslinux-4.02/com32/gplinclude/disk/write.h new file mode 100644 index 0000000..89d26fc --- /dev/null +++ b/contrib/syslinux-4.02/com32/gplinclude/disk/write.h @@ -0,0 +1,26 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#ifndef _WRITE_H_ +#define _WRITE_H_ + +#include <disk/geom.h> + +int write_sectors(const struct driveinfo *, const unsigned int, + const void *, const int); +int write_verify_sector(struct driveinfo *drive_info, + const unsigned int, const void *); +int write_verify_sectors(struct driveinfo *, + const unsigned int, const void *, const int); +#endif diff --git a/contrib/syslinux-4.02/com32/gplinclude/dmi/dmi.h b/contrib/syslinux-4.02/com32/gplinclude/dmi/dmi.h new file mode 100644 index 0000000..92cd5f8 --- /dev/null +++ b/contrib/syslinux-4.02/com32/gplinclude/dmi/dmi.h @@ -0,0 +1,98 @@ +/* ----------------------------------------------------------------------- * + * + * 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_H +#define DMI_H +#include <inttypes.h> +#define MAX_DMI_MEMORY_ITEMS 32 +#define MAX_DMI_CACHE_ITEMS 32 +#define OEM_STRINGS_SIZE 512 +#define HARDWARE_SECURITY_SIZE 16 + +#define PAGE_SIZE 4096 + +extern const char *out_of_spec; +extern const char *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)) + +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" +#include "dmi_ipmi.h" +#include "dmi_cache.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 { + uint16_t num; + uint16_t len; + uint16_t ver; + uint32_t base; + uint16_t major_version; + uint16_t minor_version; +} dmi_table; + +struct dmi_header { + uint8_t type; + uint8_t length; + uint16_t handle; + uint8_t *data; +}; + +typedef struct { + s_bios bios; + s_system system; + s_base_board base_board; + s_chassis chassis; + s_processor processor; + s_battery battery; + s_memory_module memory_module[MAX_DMI_MEMORY_ITEMS]; + s_memory memory[MAX_DMI_MEMORY_ITEMS]; + s_ipmi ipmi; + s_cache cache[MAX_DMI_CACHE_ITEMS]; + int memory_module_count; + int memory_count; + int cache_count; + dmi_table dmitable; + char oem_strings[OEM_STRINGS_SIZE]; + struct { + char power_on_passwd_status[HARDWARE_SECURITY_SIZE]; + char keyboard_passwd_status[HARDWARE_SECURITY_SIZE]; + char administrator_passwd_status[HARDWARE_SECURITY_SIZE]; + char front_panel_reset_status[HARDWARE_SECURITY_SIZE]; + bool filled; + } hardware_security; +} s_dmi; + +void to_dmi_header(struct dmi_header *h, uint8_t * data); +void dmi_bios_runtime_size(uint32_t code, s_dmi * dmi); +const char *dmi_string(struct dmi_header *dm, uint8_t s); +int dmi_checksum(uint8_t * buf, int len); +void parse_dmitable(s_dmi * dmi); +void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi * dmi); +int dmi_iterate(s_dmi * dmi); + +/* dmi_utils.c */ +void display_bios_characteristics(s_dmi * dmi); +void display_base_board_features(s_dmi * dmi); +void display_processor_flags(s_dmi * dmi); +#endif diff --git a/contrib/syslinux-4.02/com32/gplinclude/dmi/dmi_base_board.h b/contrib/syslinux-4.02/com32/gplinclude/dmi/dmi_base_board.h new file mode 100644 index 0000000..3d5fb55 --- /dev/null +++ b/contrib/syslinux-4.02/com32/gplinclude/dmi/dmi_base_board.h @@ -0,0 +1,58 @@ +/* ----------------------------------------------------------------------- * + * + * 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_BASE_BOARD_H +#define DMI_BASE_BOARD_H + +#include "stdbool.h" +#define BASE_BOARD_MANUFACTURER_SIZE 32 +#define BASE_BOARD_PRODUCT_NAME_SIZE 32 +#define BASE_BOARD_VERSION_SIZE 16 +#define BASE_BOARD_SERIAL_SIZE 32 +#define BASE_BOARD_ASSET_TAG_SIZE 32 +#define BASE_BOARD_LOCATION_SIZE 32 +#define BASE_BOARD_FEATURES_SIZE 32 +#define BASE_BOARD_TYPE_SIZE 32 + +#define BASE_BOARD_NB_ELEMENTS 5 + +extern const char *base_board_features_strings[]; + +/* this struct have BASE_BOARD_NB_ELEMENTS */ +/* each bool is associated to the relevant message above */ +typedef struct { + bool hosting; + bool board_needs_daughter; + bool removable; + bool replaceable; + bool hot_swappable; +} __attribute__ ((__packed__)) s_base_board_features; + +typedef struct { + char manufacturer[BASE_BOARD_MANUFACTURER_SIZE]; + char product_name[BASE_BOARD_PRODUCT_NAME_SIZE]; + char version[BASE_BOARD_VERSION_SIZE]; + char serial[BASE_BOARD_SERIAL_SIZE]; + 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; + struct { + char type[16]; + uint8_t status; + char description[10]; + } devices_information[10]; +} s_base_board; + +#endif diff --git a/contrib/syslinux-4.02/com32/gplinclude/dmi/dmi_battery.h b/contrib/syslinux-4.02/com32/gplinclude/dmi/dmi_battery.h new file mode 100644 index 0000000..fae7acb --- /dev/null +++ b/contrib/syslinux-4.02/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/contrib/syslinux-4.02/com32/gplinclude/dmi/dmi_bios.h b/contrib/syslinux-4.02/com32/gplinclude/dmi/dmi_bios.h new file mode 100644 index 0000000..53201ac --- /dev/null +++ b/contrib/syslinux-4.02/com32/gplinclude/dmi/dmi_bios.h @@ -0,0 +1,107 @@ +/* ----------------------------------------------------------------------- * + * + * 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_BIOS_H +#define DMI_BIOS_H + +#include "stdbool.h" +#define BIOS_VENDOR_SIZE 32 +#define BIOS_VERSION_SIZE 32 +#define BIOS_RELEASE_SIZE 16 +#define BIOS_RUNTIME_SIZE_UNIT_SIZE 16 +#define BIOS_ROM_UNIT_SIZE 16 +#define BIOS_BIOS_REVISION_SIZE 16 +#define BIOS_FIRMWARE_REVISION_SIZE 16 + +#define BIOS_CHAR_NB_ELEMENTS 28 +#define BIOS_CHAR_X1_NB_ELEMENTS 8 +#define BIOS_CHAR_X2_NB_ELEMENTS 3 + +extern const char *bios_charac_strings[]; + +/* this struct has BIOS_CHAR_NB_ELEMENTS */ +/* each bool is associated with the relevant message above */ +typedef struct { + bool bios_characteristics_not_supported; + bool isa; + bool mca; + bool eisa; + bool pci; + bool pc_card; + bool pnp; + bool apm; + bool bios_upgreadable; + bool bios_shadowing; + bool vlb; + bool escd; + bool boot_from_cd; + bool selectable_boot; + bool bios_rom_socketed; + bool edd; + bool japanese_floppy_nec_9800_1_2MB; + bool japanese_floppy_toshiba_1_2MB; + bool floppy_5_25_360KB; + bool floppy_5_25_1_2MB; + bool floppy_3_5_720KB; + bool floppy_3_5_2_88MB; + bool print_screen; + bool keyboard_8042_support; + bool serial_support; + bool printer_support; + bool cga_mono_support; + bool nec_pc_98; +} __attribute__ ((__packed__)) s_characteristics; + +extern const char *bios_charac_x1_strings[]; + +/* this struct has BIOS_CHAR_X1_NB_ELEMENTS */ +/* each bool is associated with the relevant message above */ +typedef struct { + bool acpi; + bool usb_legacy; + bool agp; + bool i2o_boot; + bool ls_120_boot; + bool zip_drive_boot; + bool ieee_1394_boot; + bool smart_battery; +} __attribute__ ((__packed__)) s_characteristics_x1; + +extern const char *bios_charac_x2_strings[]; + +/* this struct has BIOS_CHAR_X2_NB_ELEMENTS */ +/* each bool is associated with the relevant message above */ +typedef struct { + bool bios_boot_specification; + bool bios_network_boot_by_keypress; + bool target_content_distribution; +} __attribute__ ((__packed__)) s_characteristics_x2; + +typedef struct { + char vendor[BIOS_VENDOR_SIZE]; + char version[BIOS_VERSION_SIZE]; + char release_date[BIOS_RELEASE_SIZE]; + uint16_t address; + uint16_t runtime_size; + char runtime_size_unit[BIOS_RUNTIME_SIZE_UNIT_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/contrib/syslinux-4.02/com32/gplinclude/dmi/dmi_cache.h b/contrib/syslinux-4.02/com32/gplinclude/dmi/dmi_cache.h new file mode 100644 index 0000000..cfd7114 --- /dev/null +++ b/contrib/syslinux-4.02/com32/gplinclude/dmi/dmi_cache.h @@ -0,0 +1,47 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer - All Rights Reserved + * + * Some part borrowed from DMI Decode: + * + * (C) 2000-2002 Alan Cox <alan@redhat.com> + * (C) 2002-2007 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. + * + * ----------------------------------------------------------------------- */ + +#ifndef DMI_CACHE_H +#define DMI_CACHE_H + +#include <stdint.h> + +#include "stdbool.h" + +typedef struct { + char socket_designation[32]; + char configuration[32]; + char mode[32]; + char location[8]; + uint16_t installed_size; + uint16_t max_size; + char supported_sram_types[32]; + char installed_sram_types[32]; + uint16_t speed; + char error_correction_type[32]; + char system_type[16]; + char associativity[32]; +} __attribute__ ((__packed__)) s_cache; + +const char *dmi_cache_mode(uint8_t code); +const char *dmi_cache_location(uint8_t code); +uint16_t dmi_cache_size(uint16_t code); +void dmi_cache_types(uint16_t code, const char *sep, char *array); +const char *dmi_cache_ec_type(uint8_t code); +const char *dmi_cache_type(uint8_t code); +const char *dmi_cache_associativity(uint8_t code); +#endif /* DMI_CACHE_H */ diff --git a/contrib/syslinux-4.02/com32/gplinclude/dmi/dmi_chassis.h b/contrib/syslinux-4.02/com32/gplinclude/dmi/dmi_chassis.h new file mode 100644 index 0000000..88433ea --- /dev/null +++ b/contrib/syslinux-4.02/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/contrib/syslinux-4.02/com32/gplinclude/dmi/dmi_ipmi.h b/contrib/syslinux-4.02/com32/gplinclude/dmi/dmi_ipmi.h new file mode 100644 index 0000000..9110ae4 --- /dev/null +++ b/contrib/syslinux-4.02/com32/gplinclude/dmi/dmi_ipmi.h @@ -0,0 +1,33 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2006-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_IPMI_H +#define DMI_IPMI_H + +#define IPMI_INTERFACE_TYPE_SIZE 32 +#define IPMI_MEMORY_MODEL_SIZE 16 + +typedef struct { + char interface_type[IPMI_INTERFACE_TYPE_SIZE]; + uint8_t major_specification_version; + uint8_t minor_specification_version; + uint8_t I2C_slave_address; + uint16_t nv_address; + uint64_t base_address; + + uint8_t irq; + bool filled; +} s_ipmi; + +void dmi_ipmi_base_address(uint8_t type, const uint8_t * p, s_ipmi * ipmi); +const char *dmi_ipmi_interface_type(uint8_t code); +#endif diff --git a/contrib/syslinux-4.02/com32/gplinclude/dmi/dmi_memory.h b/contrib/syslinux-4.02/com32/gplinclude/dmi/dmi_memory.h new file mode 100644 index 0000000..4d0ad44 --- /dev/null +++ b/contrib/syslinux-4.02/com32/gplinclude/dmi/dmi_memory.h @@ -0,0 +1,77 @@ +/* ----------------------------------------------------------------------- * + * + * 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; + +typedef struct { + char socket_designation[8]; + char bank_connections[8]; + char speed[8]; + char type[48]; + char installed_size[48]; + char enabled_size[48]; + char error_status[8]; + bool filled; +} s_memory_module; + +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, int sizeof_type_detail); +void dmi_memory_device_speed(uint16_t code, char *speed); + +void dmi_memory_module_connections(uint8_t, char *, int); +void dmi_memory_module_speed(uint8_t, char *); +void dmi_memory_module_types(uint16_t, const char *, char *, int); +void dmi_memory_module_size(uint8_t, char *, int); +void dmi_memory_module_error(uint8_t, const char *, char *); +#endif diff --git a/contrib/syslinux-4.02/com32/gplinclude/dmi/dmi_processor.h b/contrib/syslinux-4.02/com32/gplinclude/dmi/dmi_processor.h new file mode 100644 index 0000000..6107d31 --- /dev/null +++ b/contrib/syslinux-4.02/com32/gplinclude/dmi/dmi_processor.h @@ -0,0 +1,112 @@ +/* ----------------------------------------------------------------------- * + * + * 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 64 +#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]; + uint16_t voltage_mv; + 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/contrib/syslinux-4.02/com32/gplinclude/dmi/dmi_system.h b/contrib/syslinux-4.02/com32/gplinclude/dmi/dmi_system.h new file mode 100644 index 0000000..6bb053f --- /dev/null +++ b/contrib/syslinux-4.02/com32/gplinclude/dmi/dmi_system.h @@ -0,0 +1,53 @@ +/* ----------------------------------------------------------------------- * + * + * 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_SYSTEM_H +#define DMI_SYSTEM_H + +#define SYSTEM_MANUFACTURER_SIZE 32 +#define SYSTEM_PRODUCT_NAME_SIZE 32 +#define SYSTEM_VERSION_SIZE 16 +#define SYSTEM_SERIAL_SIZE 32 +#define SYSTEM_UUID_SIZE 40 +#define SYSTEM_WAKEUP_TYPE_SIZE 32 +#define SYSTEM_SKU_NUMBER_SIZE 32 +#define SYSTEM_FAMILY_SIZE 32 + +#define SYSTEM_BOOT_STATUS_SIZE 50 +#define SYSTEM_CONFIGURATION_OPTIONS_SIZE 50 + +typedef struct { + char manufacturer[SYSTEM_MANUFACTURER_SIZE]; + char product_name[SYSTEM_PRODUCT_NAME_SIZE]; + char version[SYSTEM_VERSION_SIZE]; + char serial[SYSTEM_SERIAL_SIZE]; + 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; + char system_boot_status[SYSTEM_BOOT_STATUS_SIZE]; + char configuration_options[SYSTEM_CONFIGURATION_OPTIONS_SIZE]; + struct { + bool filled; + uint8_t status; + uint8_t watchdog; + char boot_option[17]; + char boot_option_on_limit[17]; + char reset_count[8]; + char reset_limit[8]; + char timer_interval[8]; + char timeout[8]; + } system_reset; +} s_system; +#endif diff --git a/contrib/syslinux-4.02/com32/gplinclude/memory.h b/contrib/syslinux-4.02/com32/gplinclude/memory.h new file mode 100644 index 0000000..fe33c18 --- /dev/null +++ b/contrib/syslinux-4.02/com32/gplinclude/memory.h @@ -0,0 +1,53 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from meminfo.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * Some parts borrowed from Linux: + * + * Copyright (C) 1991, 1992 Linus Torvalds + * Copyright 2007 rPath, Inc. - All Rights Reserved + * Copyright 2009 Intel Corporation; author H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#ifndef _MEMORY_H_ +#define _MEMORY_H_ +#include <stdint.h> + +#define E820MAX 128 +#define E820_RAM 1 +#define E820_RESERVED 2 +#define E820_ACPI 3 /* usable as RAM once ACPI tables have been read */ +#define E820_NVS 4 + +#define RES_START 0xa0000 +#define RES_END 0x100000 + +struct e820entry { + uint64_t addr; /* start of memory segment */ + uint64_t size; /* size of memory segment */ + uint64_t type; /* type of memory segment */ +} __attribute__ ((packed)); + +const char *const e820_types[5]; + +void get_type(int, char *, int); +void detect_memory_e820(struct e820entry *desc, int size_map, int *size_found); +int detect_memory_e801(int *, int *); +int detect_memory_88(int *); + +/* The following stuff could be merge once the addr_t will be set to 64bits. + * syslinux_scan_memory can be used for that purpose */ +unsigned long memsize_e820(struct e820entry *e820, int e820_nr); +int sanitize_e820_map(struct e820entry *orig_map, struct e820entry *new_bios, + short old_nr); +unsigned long detect_memsize(void); +#endif diff --git a/contrib/syslinux-4.02/com32/gplinclude/vpd/vpd.h b/contrib/syslinux-4.02/com32/gplinclude/vpd/vpd.h new file mode 100644 index 0000000..bff77bd --- /dev/null +++ b/contrib/syslinux-4.02/com32/gplinclude/vpd/vpd.h @@ -0,0 +1,33 @@ +/* ----------------------------------------------------------------------- * + * + * 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 VPD_H +#define VPD_H +#include <inttypes.h> +#include <stdbool.h> + +enum { VPD_TABLE_PRESENT = 100, ENOVPDTABLE }; + +typedef struct { + char bios_build_id[10]; + char box_serial_number[8]; + char motherboard_serial_number[12]; + char machine_type_model[8]; + char bios_release_date[9]; + char default_flash_filename[13]; + char bios_version[255]; + char base_address[16]; + bool filled; +} s_vpd; + +int vpd_decode(s_vpd * vpd); +#endif diff --git a/contrib/syslinux-4.02/com32/gpllib/Makefile b/contrib/syslinux-4.02/com32/gpllib/Makefile new file mode 100644 index 0000000..fa866db --- /dev/null +++ b/contrib/syslinux-4.02/com32/gpllib/Makefile @@ -0,0 +1,44 @@ +# +# LGPL/GPL code library +# + +# Include configuration rules +topdir = ../.. +include ../lib/MCONFIG + +REQFLAGS += -I../gplinclude + +GPLDIRS := . disk dmi vpd +LIBOBJS := $(foreach dir,$(GPLDIRS),$(patsubst %.c,%.o,$(wildcard $(dir)/*.c))) + +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/contrib/syslinux-4.02/com32/gpllib/cpuid.c b/contrib/syslinux-4.02/com32/gpllib/cpuid.c new file mode 100644 index 0000000..2d5b5ce --- /dev/null +++ b/contrib/syslinux-4.02/com32/gpllib/cpuid.c @@ -0,0 +1,456 @@ +/* + * Portions of this file taken from the Linux kernel, + * Copyright 1991-2009 Linus Torvalds and contributors + * + * 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> +#include "cpuid.h" + +struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = { }; + +/* +* CPUID functions returning a single datum +*/ + +/* Probe for the CPUID instruction */ +static int have_cpuid_p(void) +{ + return cpu_has_eflag(X86_EFLAGS_ID); +} + +static struct cpu_dev amd_cpu_dev = { + .c_vendor = "AMD", + .c_ident = {"AuthenticAMD"} +}; + +static struct cpu_dev intel_cpu_dev = { + .c_vendor = "Intel", + .c_ident = {"GenuineIntel"} +}; + +static struct cpu_dev cyrix_cpu_dev = { + .c_vendor = "Cyrix", + .c_ident = {"CyrixInstead"} +}; + +static struct cpu_dev umc_cpu_dev = { + .c_vendor = "UMC", + .c_ident = {"UMC UMC UMC"} + +}; + +static struct cpu_dev nexgen_cpu_dev = { + .c_vendor = "Nexgen", + .c_ident = {"NexGenDriven"} +}; + +static struct cpu_dev centaur_cpu_dev = { + .c_vendor = "Centaur", + .c_ident = {"CentaurHauls"} +}; + +static struct cpu_dev rise_cpu_dev = { + .c_vendor = "Rise", + .c_ident = {"RiseRiseRise"} +}; + +static struct cpu_dev transmeta_cpu_dev = { + .c_vendor = "Transmeta", + .c_ident = {"GenuineTMx86", "TransmetaCPU"} +}; + +void init_cpu_devs(void) +{ + cpu_devs[X86_VENDOR_INTEL] = &intel_cpu_dev; + cpu_devs[X86_VENDOR_CYRIX] = &cyrix_cpu_dev; + cpu_devs[X86_VENDOR_AMD] = &amd_cpu_dev; + cpu_devs[X86_VENDOR_UMC] = &umc_cpu_dev; + cpu_devs[X86_VENDOR_NEXGEN] = &nexgen_cpu_dev; + cpu_devs[X86_VENDOR_CENTAUR] = ¢aur_cpu_dev; + cpu_devs[X86_VENDOR_RISE] = &rise_cpu_dev; + cpu_devs[X86_VENDOR_TRANSMETA] = &transmeta_cpu_dev; +} + +void get_cpu_vendor(struct cpuinfo_x86 *c) +{ + char *v = c->x86_vendor_id; + int i; + init_cpu_devs(); + for (i = 0; i < X86_VENDOR_NUM; i++) { + if (cpu_devs[i]) { + if (!strcmp(v, cpu_devs[i]->c_ident[0]) || + (cpu_devs[i]->c_ident[1] && + !strcmp(v, cpu_devs[i]->c_ident[1]))) { + c->x86_vendor = i; + return; + } + } + } + + c->x86_vendor = X86_VENDOR_UNKNOWN; +} + +int get_model_name(struct cpuinfo_x86 *c) +{ + unsigned int *v; + char *p, *q; + + if (cpuid_eax(0x80000000) < 0x80000004) + return 0; + + v = (unsigned int *)c->x86_model_id; + cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]); + cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]); + cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]); + c->x86_model_id[48] = 0; + + /* Intel chips right-justify this string for some dumb reason; + undo that brain damage */ + p = q = &c->x86_model_id[0]; + while (*p == ' ') + p++; + if (p != q) { + while (*p) + *q++ = *p++; + while (q <= &c->x86_model_id[48]) + *q++ = '\0'; /* Zero-pad the rest */ + } + + return 1; +} + +void detect_cache(uint32_t xlvl, struct cpuinfo_x86 *c) +{ + uint32_t eax, ebx, ecx, edx, l2size; + /* Detecting L1 cache */ + if (xlvl >= 0x80000005) { + cpuid(0x80000005, &eax, &ebx, &ecx, &edx); + c->x86_l1_data_cache_size = ecx >> 24; + c->x86_l1_instruction_cache_size = edx >> 24; + } + + /* Detecting L2 cache */ + c->x86_l2_cache_size = 0; + + if (xlvl < 0x80000006) /* Some chips just has a large L1. */ + return; + + cpuid(0x80000006, &eax, &ebx, &ecx, &edx); + l2size = ecx >> 16; + + /* Vendor based fixes */ + switch (c->x86_vendor) { + case X86_VENDOR_INTEL: + /* + * Intel PIII Tualatin. This comes in two flavours. + * One has 256kb of cache, the other 512. We have no way + * to determine which, so we use a boottime override + * for the 512kb model, and assume 256 otherwise. + */ + if ((c->x86 == 6) && (c->x86_model == 11) && (l2size == 0)) + l2size = 256; + break; + case X86_VENDOR_AMD: + /* AMD errata T13 (order #21922) */ + if ((c->x86 == 6)) { + if (c->x86_model == 3 && c->x86_mask == 0) /* Duron Rev A0 */ + l2size = 64; + if (c->x86_model == 4 && (c->x86_mask == 0 || c->x86_mask == 1)) /* Tbird rev A1/A2 */ + l2size = 256; + } + break; + } + c->x86_l2_cache_size = l2size; +} + +void generic_identify(struct cpuinfo_x86 *c) +{ + uint32_t tfms, xlvl; + uint32_t eax, ebx, ecx, edx; + + /* Get vendor name */ + cpuid(0x00000000, + (uint32_t *) & c->cpuid_level, + (uint32_t *) & c->x86_vendor_id[0], + (uint32_t *) & c->x86_vendor_id[8], + (uint32_t *) & c->x86_vendor_id[4]); + + get_cpu_vendor(c); + + /* Intel-defined flags: level 0x00000001 */ + if (c->cpuid_level >= 0x00000001) { + uint32_t capability, excap; + 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) + c->x86 += (tfms >> 20) & 0xff; + if (c->x86 >= 0x6) + c->x86_model += ((tfms >> 16) & 0xF) << 4; + c->x86_mask = tfms & 15; + 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; + } + + /* AMD-defined flags: level 0x80000001 */ + xlvl = cpuid_eax(0x80000000); + if ((xlvl & 0xffff0000) == 0x80000000) { + if (xlvl >= 0x80000001) { + c->x86_capability[1] = cpuid_edx(0x80000001); + c->x86_capability[6] = cpuid_ecx(0x80000001); + } + if (xlvl >= 0x80000004) + get_model_name(c); /* Default name */ + } + + /* Detecting the number of cores */ + switch (c->x86_vendor) { + case X86_VENDOR_AMD: + if (xlvl >= 0x80000008) { + c->x86_num_cores = (cpuid_ecx(0x80000008) & 0xff) + 1; + if (c->x86_num_cores & (c->x86_num_cores - 1)) + c->x86_num_cores = 1; + } + break; + case X86_VENDOR_INTEL: + if (c->cpuid_level >= 0x00000004) { + cpuid(0x4, &eax, &ebx, &ecx, &edx); + c->x86_num_cores = ((eax & 0xfc000000) >> 26) + 1; + } + break; + default: + c->x86_num_cores = 1; + break; + } + + detect_cache(xlvl, c); +} + +/* + * Checksum an MP configuration block. + */ + +static int mpf_checksum(unsigned char *mp, int len) +{ + int sum = 0; + + while (len--) + sum += *mp++; + + return sum & 0xFF; +} + +static int smp_scan_config(unsigned long base, unsigned long length) +{ + unsigned long *bp = (unsigned long *)base; + struct intel_mp_floating *mpf; + +// printf("Scan SMP from %p for %ld bytes.\n", bp,length); + if (sizeof(*mpf) != 16) { + printf("Error: MPF size\n"); + return 0; + } + + while (length > 0) { + mpf = (struct intel_mp_floating *)bp; + if ((*bp == SMP_MAGIC_IDENT) && + (mpf->mpf_length == 1) && + !mpf_checksum((unsigned char *)bp, 16) && + ((mpf->mpf_specification == 1) + || (mpf->mpf_specification == 4))) { + return 1; + } + bp += 4; + length -= 16; + } + return 0; +} + +int find_smp_config(void) +{ +// unsigned int address; + + /* + * FIXME: Linux assumes you have 640K of base ram.. + * this continues the error... + * + * 1) Scan the bottom 1K for a signature + * 2) Scan the top 1K of base RAM + * 3) Scan the 64K of bios + */ + if (smp_scan_config(0x0, 0x400) || + smp_scan_config(639 * 0x400, 0x400) || + smp_scan_config(0xF0000, 0x10000)) + return 1; + /* + * If it is an SMP machine we should know now, unless the + * configuration is in an EISA/MCA bus machine with an + * extended bios data area. + * + * there is a real-mode segmented pointer pointing to the + * 4K EBDA area at 0x40E, calculate and scan it here. + * + * NOTE! There are Linux loaders that will corrupt the EBDA + * area, and as such this kind of SMP config may be less + * trustworthy, simply because the SMP table may have been + * stomped on during early boot. These loaders are buggy and + * should be fixed. + * + * MP1.4 SPEC states to only scan first 1K of 4K EBDA. + */ + +// address = get_bios_ebda(); +// if (address) +// smp_scan_config(address, 0x400); + return 0; +} + +void set_cpu_flags(struct cpuinfo_x86 *c, s_cpu * cpu) +{ + cpu->flags.fpu = cpu_has(c, X86_FEATURE_FPU); + cpu->flags.vme = cpu_has(c, X86_FEATURE_VME); + cpu->flags.de = cpu_has(c, X86_FEATURE_DE); + cpu->flags.pse = cpu_has(c, X86_FEATURE_PSE); + cpu->flags.tsc = cpu_has(c, X86_FEATURE_TSC); + cpu->flags.msr = cpu_has(c, X86_FEATURE_MSR); + cpu->flags.pae = cpu_has(c, X86_FEATURE_PAE); + cpu->flags.mce = cpu_has(c, X86_FEATURE_MCE); + cpu->flags.cx8 = cpu_has(c, X86_FEATURE_CX8); + cpu->flags.apic = cpu_has(c, X86_FEATURE_APIC); + cpu->flags.sep = cpu_has(c, X86_FEATURE_SEP); + cpu->flags.mtrr = cpu_has(c, X86_FEATURE_MTRR); + cpu->flags.pge = cpu_has(c, X86_FEATURE_PGE); + cpu->flags.mca = cpu_has(c, X86_FEATURE_MCA); + cpu->flags.cmov = cpu_has(c, X86_FEATURE_CMOV); + cpu->flags.pat = cpu_has(c, X86_FEATURE_PAT); + cpu->flags.pse_36 = cpu_has(c, X86_FEATURE_PSE36); + cpu->flags.psn = cpu_has(c, X86_FEATURE_PN); + cpu->flags.clflsh = cpu_has(c, X86_FEATURE_CLFLSH); + cpu->flags.dts = cpu_has(c, X86_FEATURE_DTES); + cpu->flags.acpi = cpu_has(c, X86_FEATURE_ACPI); + cpu->flags.pbe = cpu_has(c, X86_FEATURE_PBE); + cpu->flags.mmx = cpu_has(c, X86_FEATURE_MMX); + cpu->flags.fxsr = cpu_has(c, X86_FEATURE_FXSR); + cpu->flags.sse = cpu_has(c, X86_FEATURE_XMM); + cpu->flags.sse2 = cpu_has(c, X86_FEATURE_XMM2); + cpu->flags.ss = cpu_has(c, X86_FEATURE_SELFSNOOP); + cpu->flags.htt = cpu_has(c, X86_FEATURE_HT); + cpu->flags.acc = cpu_has(c, X86_FEATURE_ACC); + cpu->flags.syscall = cpu_has(c, X86_FEATURE_SYSCALL); + cpu->flags.mp = cpu_has(c, X86_FEATURE_MP); + cpu->flags.nx = cpu_has(c, X86_FEATURE_NX); + cpu->flags.mmxext = cpu_has(c, X86_FEATURE_MMXEXT); + cpu->flags.fxsr_opt = cpu_has(c, X86_FEATURE_FXSR_OPT); + cpu->flags.gbpages = cpu_has(c, X86_FEATURE_GBPAGES); + cpu->flags.rdtscp = cpu_has(c, X86_FEATURE_RDTSCP); + cpu->flags.lm = cpu_has(c, X86_FEATURE_LM); + cpu->flags.nowext = cpu_has(c, X86_FEATURE_3DNOWEXT); + cpu->flags.now = cpu_has(c, X86_FEATURE_3DNOW); + cpu->flags.smp = find_smp_config(); + cpu->flags.pni = cpu_has(c, X86_FEATURE_XMM3); + cpu->flags.pclmulqd = cpu_has(c, X86_FEATURE_PCLMULQDQ); + cpu->flags.dtes64 = cpu_has(c, X86_FEATURE_DTES64); + cpu->flags.vmx = cpu_has(c, X86_FEATURE_VMX); + cpu->flags.smx = cpu_has(c, X86_FEATURE_SMX); + cpu->flags.est = cpu_has(c, X86_FEATURE_EST); + cpu->flags.tm2 = cpu_has(c, X86_FEATURE_TM2); + cpu->flags.sse3 = cpu_has(c, X86_FEATURE_SSE3); + cpu->flags.cid = cpu_has(c, X86_FEATURE_CID); + cpu->flags.fma = cpu_has(c, X86_FEATURE_FMA); + cpu->flags.cx16 = cpu_has(c, X86_FEATURE_CX16); + cpu->flags.xtpr = cpu_has(c, X86_FEATURE_XTPR); + cpu->flags.pdcm = cpu_has(c, X86_FEATURE_PDCM); + cpu->flags.dca = cpu_has(c, X86_FEATURE_DCA); + cpu->flags.xmm4_1 = cpu_has(c, X86_FEATURE_XMM4_1); + cpu->flags.xmm4_2 = cpu_has(c, X86_FEATURE_XMM4_2); + cpu->flags.x2apic = cpu_has(c, X86_FEATURE_X2APIC); + cpu->flags.movbe = cpu_has(c, X86_FEATURE_MOVBE); + cpu->flags.popcnt = cpu_has(c, X86_FEATURE_POPCNT); + cpu->flags.aes = cpu_has(c, X86_FEATURE_AES); + cpu->flags.xsave = cpu_has(c, X86_FEATURE_XSAVE); + cpu->flags.osxsave = cpu_has(c, X86_FEATURE_OSXSAVE); + cpu->flags.avx = cpu_has(c, X86_FEATURE_AVX); + cpu->flags.hypervisor = cpu_has(c, X86_FEATURE_HYPERVISOR); + cpu->flags.ace2 = cpu_has(c, X86_FEATURE_ACE2); + cpu->flags.ace2_en = cpu_has(c, X86_FEATURE_ACE2_EN); + cpu->flags.phe = cpu_has(c, X86_FEATURE_PHE); + cpu->flags.phe_en = cpu_has(c, X86_FEATURE_PHE_EN); + cpu->flags.pmm = cpu_has(c, X86_FEATURE_PMM); + cpu->flags.pmm_en = cpu_has(c, X86_FEATURE_PMM_EN); + cpu->flags.extapic = cpu_has(c, X86_FEATURE_EXTAPIC); + cpu->flags.cr8_legacy = cpu_has(c, X86_FEATURE_CR8_LEGACY); + cpu->flags.abm = cpu_has(c, X86_FEATURE_ABM); + cpu->flags.sse4a = cpu_has(c, X86_FEATURE_SSE4A); + cpu->flags.misalignsse = cpu_has(c, X86_FEATURE_MISALIGNSSE); + cpu->flags.nowprefetch = cpu_has(c, X86_FEATURE_3DNOWPREFETCH); + cpu->flags.osvw = cpu_has(c, X86_FEATURE_OSVW); + cpu->flags.ibs = cpu_has(c, X86_FEATURE_IBS); + cpu->flags.sse5 = cpu_has(c, X86_FEATURE_SSE5); + cpu->flags.skinit = cpu_has(c, X86_FEATURE_SKINIT); + cpu->flags.wdt = cpu_has(c, X86_FEATURE_WDT); + cpu->flags.ida = cpu_has(c, X86_FEATURE_IDA); + cpu->flags.arat = cpu_has(c, X86_FEATURE_ARAT); + cpu->flags.tpr_shadow = cpu_has(c, X86_FEATURE_TPR_SHADOW); + cpu->flags.vnmi = cpu_has(c, X86_FEATURE_VNMI); + cpu->flags.flexpriority = cpu_has(c, X86_FEATURE_FLEXPRIORITY); + cpu->flags.ept = cpu_has(c, X86_FEATURE_EPT); + cpu->flags.vpid = cpu_has(c, X86_FEATURE_VPID); + cpu->flags.svm = cpu_has(c, X86_FEATURE_SVM); +} + +void set_generic_info(struct cpuinfo_x86 *c, s_cpu * cpu) +{ + cpu->family = c->x86; + cpu->vendor_id = c->x86_vendor; + cpu->model_id = c->x86_model; + cpu->stepping = c->x86_mask; + strlcpy(cpu->vendor, cpu_devs[c->x86_vendor]->c_vendor, + sizeof(cpu->vendor)); + strlcpy(cpu->model, c->x86_model_id, sizeof(cpu->model)); + cpu->num_cores = c->x86_num_cores; + cpu->l1_data_cache_size = c->x86_l1_data_cache_size; + cpu->l1_instruction_cache_size = c->x86_l1_instruction_cache_size; + cpu->l2_cache_size = c->x86_l2_cache_size; +} + +void detect_cpu(s_cpu * cpu) +{ + struct cpuinfo_x86 c; + c.x86_clflush_size = 32; + c.x86_l1_data_cache_size = 0; + c.x86_l1_instruction_cache_size = 0; + c.x86_l2_cache_size = 0; + 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_num_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; + + generic_identify(&c); + set_generic_info(&c, cpu); + set_cpu_flags(&c, cpu); +} diff --git a/contrib/syslinux-4.02/com32/gpllib/disk/ata.c b/contrib/syslinux-4.02/com32/gpllib/disk/ata.c new file mode 100644 index 0000000..78f669e --- /dev/null +++ b/contrib/syslinux-4.02/com32/gpllib/disk/ata.c @@ -0,0 +1,62 @@ +#include <inttypes.h> +#include <string.h> + +/** + * 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; + + ata_id_string(id, s, ofs, len - 1); + + p = s + strnlen((const char *)s, len - 1); + while (p > s && p[-1] == ' ') + p--; + *p = '\0'; +} diff --git a/contrib/syslinux-4.02/com32/gpllib/disk/bootloaders.c b/contrib/syslinux-4.02/com32/gpllib/disk/bootloaders.c new file mode 100644 index 0000000..e034011 --- /dev/null +++ b/contrib/syslinux-4.02/com32/gpllib/disk/bootloaders.c @@ -0,0 +1,46 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#include <disk/bootloaders.h> +#include <disk/common.h> +#include <disk/geom.h> +#include <disk/read.h> +#include <stdlib.h> +#include <string.h> + +/** + * get_bootloader_string - return a string describing the boot code in a + * bootsector + * @d: driveinfo struct describing the drive + * @p: partition to scan (usually the active one) + * @buffer: pre-allocated buffer + * @buffer_size: @buffer size + **/ +int get_bootloader_string(struct driveinfo *d, const struct part_entry *p, + char *buffer, const int buffer_size) +{ + char boot_sector[SECTOR * sizeof(char)]; + + if (read_sectors(d, &boot_sector, p->start_lba, 1) == -1) + return -1; + else { + if (!strncmp(boot_sector + 3, "SYSLINUX", 8)) + strlcpy(buffer, "SYSLINUX", buffer_size - 1); + else if (!strncmp(boot_sector + 3, "EXTLINUX", 8)) + strlcpy(buffer, "EXTLINUX", buffer_size - 1); + else if (!strncmp(boot_sector + 3, "MSWIN4.1", 8)) + strlcpy(buffer, "MSWIN4.1", buffer_size - 1); + else + return -1; + /* Add more... */ + + buffer[buffer_size - 1] = '\0'; + return 0; + } +} diff --git a/contrib/syslinux-4.02/com32/gpllib/disk/errno_disk.c b/contrib/syslinux-4.02/com32/gpllib/disk/errno_disk.c new file mode 100644 index 0000000..8a68802 --- /dev/null +++ b/contrib/syslinux-4.02/com32/gpllib/disk/errno_disk.c @@ -0,0 +1,12 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#include <disk/errno_disk.h> + +int errno_disk; diff --git a/contrib/syslinux-4.02/com32/gpllib/disk/error.c b/contrib/syslinux-4.02/com32/gpllib/disk/error.c new file mode 100644 index 0000000..fe4722e --- /dev/null +++ b/contrib/syslinux-4.02/com32/gpllib/disk/error.c @@ -0,0 +1,23 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#include <stdio.h> +#include <string.h> +#include <disk/errno_disk.h> + +/** + * get_error - decode a disk error status + * @s: Preallocated buffer + * + * Fill @buffer_ptr with the last errno_disk + **/ +void get_error(const char *s) +{ + fprintf(stderr, "%s: error %d\n", s, errno_disk); +} diff --git a/contrib/syslinux-4.02/com32/gpllib/disk/geom.c b/contrib/syslinux-4.02/com32/gpllib/disk/geom.c new file mode 100644 index 0000000..9e673ed --- /dev/null +++ b/contrib/syslinux-4.02/com32/gpllib/disk/geom.c @@ -0,0 +1,271 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#include <com32.h> +#include <string.h> +#include <stdio.h> +#include <disk/geom.h> + +#include <stdio.h> + +/** + * lba_to_chs - split given lba into cylinders/heads/sectors + **/ +void lba_to_chs(const struct driveinfo *drive_info, const int lba, + unsigned int *cylinder, unsigned int *head, + unsigned int *sector) +{ + unsigned int track; + + /* Use EDD, if valid */ + if (drive_info->edd_params.sectors_per_track > 0 && + drive_info->edd_params.heads > 0) { + *cylinder = (lba % drive_info->edd_params.sectors_per_track) + 1; + track = lba / drive_info->edd_params.sectors_per_track; + *head = track % drive_info->edd_params.heads; + *sector = track / drive_info->edd_params.heads; + } else if (drive_info->cbios) { + *cylinder = (lba % drive_info->legacy_sectors_per_track) + 1; + track = lba / drive_info->legacy_sectors_per_track; + *head = track % (drive_info->legacy_max_head + 1); + *sector = track / (drive_info->legacy_max_head + 1); + } +} + +/** + * detect_extensions - detect if we can use extensions + * + * INT 13 - IBM/MS INT 13 Extensions - INSTALLATION CHECK + * AH = 41h + * BX = 55AAh + * DL = drive (80h-FFh) + * + * Return: CF set on error (extensions not supported) + * AH = 01h (invalid function) + * CF clear if successful + * BX = AA55h if installed + * AH = major version of extensions + * 01h = 1.x + * 20h = 2.0 / EDD-1.0 + * 21h = 2.1 / EDD-1.1 + * 30h = EDD-3.0 + * AL = internal use + * CX = API subset support bitmap (see #00271) + * DH = extension version (v2.0+ ??? -- not present in 1.x) + * + * Note: the Phoenix Enhanced Disk Drive Specification v1.0 uses version 2.0 of + * the INT 13 Extensions API + * + * Bitfields for IBM/MS INT 13 Extensions API support bitmap: + * Bit(s) Description (Table 00271) + * 0 extended disk access functions (AH=42h-44h,47h,48h) supported + * 1 removable drive controller functions (AH=45h,46h,48h,49h,INT 15/AH=52h) + * supported + * 2 enhanced disk drive (EDD) functions (AH=48h,AH=4Eh) supported + * extended drive parameter table is valid (see #00273,#00278) + * 3-15 reserved (0) + **/ +static int detect_extensions(struct driveinfo *drive_info) +{ + com32sys_t getebios, ebios; + + memset(&getebios, 0, sizeof getebios); + memset(&ebios, 0, sizeof ebios); + + getebios.eflags.b[0] = 0x3; /* CF set */ + getebios.ebx.w[0] = 0x55aa; + getebios.edx.b[0] = drive_info->disk; + getebios.eax.b[1] = 0x41; + + __intcall(0x13, &getebios, &ebios); + + if (!(ebios.eflags.l & EFLAGS_CF) && ebios.ebx.w[0] == 0xaa55) { + drive_info->ebios = 1; + drive_info->edd_version = ebios.eax.b[1]; + drive_info->edd_functionality_subset = ebios.ecx.w[0]; + return 0; + } else + return -1; /* Drive does not exist? */ +} + +/** + * get_drive_parameters_with_extensions - retrieve disk parameters via AH=48h + * + * INT 13 - IBM/MS INT 13 Extensions - GET DRIVE PARAMETERS + * AH = 48h + * DL = drive (80h-FFh) + * DS:SI -> buffer for drive parameters + * Return: CF clear if successful + * AH = 00h + * DS:SI buffer filled + * CF set on error + * AH = error code (see #00234) + * BUG: several different Compaq BIOSes incorrectly report high-numbered + * drives (such as 90h, B0h, D0h, and F0h) as present, giving them the + * same geometry as drive 80h; as a workaround, scan through disk + * numbers, stopping as soon as the number of valid drives encountered + * equals the value in 0040h:0075h + **/ +static int get_drive_parameters_with_extensions(struct driveinfo *drive_info) +{ + com32sys_t inreg, outreg; + struct edd_device_parameters *dp = __com32.cs_bounce; + + memset(&inreg, 0, sizeof inreg); + + /* + * The caller shall set this value to the maximum Result Buffer + * length, in bytes. If the length of this buffer is less than 30 + * bytes, this function shall not return the pointer to Drive Parameter + * Table (DPT) extension. If the buffer length is 30 or greater on + * entry, it shall be set to 30 on exit. If the buffer length is + * between 26 and 29, it shall be set to 26 on exit. + * If the buffer length is less than 26 on entry an error shall be + * returned. + */ + dp->len = sizeof(struct edd_device_parameters); + + inreg.esi.w[0] = OFFS(dp); + inreg.ds = SEG(dp); + inreg.edx.b[0] = drive_info->disk; + inreg.eax.b[1] = 0x48; + + __intcall(0x13, &inreg, &outreg); + + /* CF set on error */ + if (outreg.eflags.l & EFLAGS_CF) + return outreg.eax.b[1]; + + memcpy(&drive_info->edd_params, dp, sizeof drive_info->edd_params); + + return 0; +} + +/** + * get_drive_parameters_without_extensions - retrieve drive parameters via AH=08h + * + * INT 13 - DISK - GET DRIVE PARAMETERS (PC,XT286,CONV,PS,ESDI,SCSI) + * AH = 08h + * DL = drive (bit 7 set for hard disk) + * + * Return: CF set on error + * AH = status (07h) (see #00234) + * CF clear if successful + * AH = 00h + * AL = 00h on at least some BIOSes + * BL = drive type (AT/PS2 floppies only) (see #00242) + * CH = low eight bits of maximum cylinder number + * CL = maximum sector number (bits 5-0) + * high two bits of maximum cylinder number (bits 7-6) + * DH = maximum head number + * DL = number of drives + * ES:DI -> drive parameter table (floppies only) + * + * Notes: + * - may return successful even though specified drive is greater than the + * number of attached drives of that type (floppy/hard); check DL to + * ensure validity + * - for systems predating the IBM AT, this call is only valid for hard + * disks, as it is implemented by the hard disk BIOS rather than the + * ROM BIOS + * - Toshiba laptops with HardRAM return DL=02h when called with DL=80h, + * but fail on DL=81h. The BIOS data at 40h:75h correctly reports 01h. + * may indicate only two drives present even if more are attached; to + * ensure a correct count, one can use AH=15h to scan through possible + * drives + * - for BIOSes which reserve the last cylinder for testing purposes, the + * cylinder count is automatically decremented + * on PS/1s with IBM ROM DOS 4, nonexistent drives return CF clear, + * BX=CX=0000h, and ES:DI = 0000h:0000h + * - the PC-Tools PCFORMAT program requires that AL=00h before it will + * proceed with the formatting + * + * BUG: several different Compaq BIOSes incorrectly report high-numbered + * drives (such as 90h, B0h, D0h, and F0h) as present, giving them the + * same geometry as drive 80h; as a workaround, scan through disk + * numbers, stopping as soon as the number of valid drives encountered + * equals the value in 0040h:0075h + * + * SeeAlso: AH=06h"Adaptec",AH=13h"SyQuest",AH=48h,AH=15h,INT 1E + * SeeAlso: INT 41"HARD DISK 0" + **/ +static int get_drive_parameters_without_extensions(struct driveinfo *drive_info) +{ + com32sys_t getparm, parm; + + memset(&getparm, 0, sizeof getparm); + memset(&parm, 0, sizeof parm); + + /* Ralf Brown recommends setting ES:DI to 0:0 */ + getparm.esi.w[0] = 0; + getparm.ds = 0; + getparm.edx.b[0] = drive_info->disk; + getparm.eax.b[1] = 0x08; + + __intcall(0x13, &getparm, &parm); + + /* CF set on error */ + if (parm.eflags.l & EFLAGS_CF) + return parm.eax.b[1]; + + /* DL contains the maximum drive number (it starts at 0) */ + drive_info->legacy_max_drive = parm.edx.b[0]; + + // XXX broken + /* Drive specified greater than the bumber of attached drives */ + //if (drive_info->disk > drive_info->drives) + // return -1; + + drive_info->legacy_type = parm.ebx.b[0]; + + /* DH contains the maximum head number (it starts at 0) */ + drive_info->legacy_max_head = parm.edx.b[1]; + + /* Maximum sector number (bits 5-0) per track */ + drive_info->legacy_sectors_per_track = parm.ecx.b[0] & 0x3f; + + /* + * Maximum cylinder number: + * CH = low eight bits of maximum cylinder number + * CL = high two bits of maximum cylinder number (bits 7-6) + */ + drive_info->legacy_max_cylinder = parm.ecx.b[1] + + ((parm.ecx.b[0] & 0xc0) << 2); + + if (drive_info->legacy_sectors_per_track > 0) + drive_info->cbios = 1; /* Valid geometry */ + + return 0; +} + +/** + * get_drive_parameters - retrieve drive parameters + * @drive_info: driveinfo structure to fill + **/ +int get_drive_parameters(struct driveinfo *drive_info) +{ + int return_code; + + if (detect_extensions(drive_info)) + return -1; + + return_code = get_drive_parameters_without_extensions(drive_info); + + /* If geometry isn't valid, no need to try to get more info about the drive */ + /* Looks like in can confuse some optical drives */ + if (drive_info->ebios && drive_info->cbios) + get_drive_parameters_with_extensions(drive_info); + + return return_code; +} diff --git a/contrib/syslinux-4.02/com32/gpllib/disk/labels.c b/contrib/syslinux-4.02/com32/gpllib/disk/labels.c new file mode 100644 index 0000000..ad3d33b --- /dev/null +++ b/contrib/syslinux-4.02/com32/gpllib/disk/labels.c @@ -0,0 +1,654 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#include <stdlib.h> +#include <string.h> + +void get_label(int label, char **buffer_label) +{ + int buffer_size = (80 * sizeof(char)); + char *buffer = malloc(buffer_size); + *buffer_label = buffer; + + switch (label) { + case 0x01: + strlcpy(buffer, "DOS 12-bit fat", buffer_size); + break; + case 0x02: + strlcpy(buffer, "XENIX root", buffer_size); + break; + case 0x03: + strlcpy(buffer, "XENIX /usr", buffer_size); + break; + case 0x04: + strlcpy(buffer, "DOS 3.0+ 16-bit FAT (up to 32M)", buffer_size); + break; + case 0x05: + strlcpy(buffer, "DOS 3.3+ Extended Partition", buffer_size); + break; + case 0x06: + strlcpy(buffer, "DOS 3.31+ 16-bit FAT (over 32M)", buffer_size); + break; + case 0x07: + strlcpy(buffer, "OS/2 IFS (e.g., HPFS)", buffer_size); + break; + //case 0x07: strlcpy(buffer, "Advanced Unix", buffer_size); break; + //case 0x07: strlcpy(buffer, "Windows NT NTFS", buffer_size); break; + //case 0x07: strlcpy(buffer, "QNX2.x (pre-1988)", buffer_size); break; + case 0x08: + strlcpy(buffer, "OS/2 (v1.0-1.3 only)", buffer_size); + break; + //case 0x08: strlcpy(buffer, "AIX boot partition", buffer_size); break; + //case 0x08: strlcpy(buffer, "SplitDrive", buffer_size); break; + //case 0x08: strlcpy(buffer, "DELL partition spanning multiple drives", buffer_size); break; + //case 0x08: strlcpy(buffer, "Commodore DOS", buffer_size); break; + //case 0x08: strlcpy(buffer, "QNX 1.x and 2.x ("qny")", buffer_size); break; + case 0x09: + strlcpy(buffer, "AIX data partition", buffer_size); + break; + //case 0x09: strlcpy(buffer, "Coherent filesystem", buffer_size); break; + //case 0x09: strlcpy(buffer, "QNX 1.x and 2.x ("qnz")", buffer_size); break; + case 0x0a: + strlcpy(buffer, "OS/2 Boot Manager", buffer_size); + break; + //case 0x0a: strlcpy(buffer, "Coherent swap partition", buffer_size); break; + //case 0x0a: strlcpy(buffer, "OPUS", buffer_size); break; + case 0x0b: + strlcpy(buffer, "WIN95 OSR2 32-bit FAT", buffer_size); + break; + case 0x0c: + strlcpy(buffer, "WIN95 OSR2 32-bit FAT, LBA-mapped", buffer_size); + break; + case 0x0e: + strlcpy(buffer, "WIN95: DOS 16-bit FAT, LBA-mapped", buffer_size); + break; + case 0x0f: + strlcpy(buffer, "WIN95: Extended partition, LBA-mapped", buffer_size); + break; + case 0x10: + strlcpy(buffer, "OPUS (?)", buffer_size); + break; + case 0x11: + strlcpy(buffer, "Hidden DOS 12-bit FAT", buffer_size); + break; + case 0x12: + strlcpy(buffer, "Compaq config partition", buffer_size); + break; + case 0x14: + strlcpy(buffer, "Hidden DOS 16-bit FAT <32M", buffer_size); + break; + case 0x16: + strlcpy(buffer, "Hidden DOS 16-bit FAT >=32M", buffer_size); + break; + case 0x17: + strlcpy(buffer, "Hidden IFS (e.g., HPFS)", buffer_size); + break; + case 0x18: + strlcpy(buffer, "AST SmartSleep Partition", buffer_size); + break; + case 0x19: + strlcpy(buffer, "Unused (Claimed for Willowtech Photon COS)", + buffer_size); + break; + case 0x1b: + strlcpy(buffer, "Hidden WIN95 OSR2 32-bit FAT", buffer_size); + break; + case 0x1c: + strlcpy(buffer, "Hidden WIN95 OSR2 32-bit FAT, LBA-mapped", + buffer_size); + break; + case 0x1e: + strlcpy(buffer, "Hidden WIN95 16-bit FAT, LBA-mapped", buffer_size); + break; + case 0x20: + strlcpy(buffer, "Unused", buffer_size); + break; + case 0x21: + strlcpy(buffer, "Reserved", buffer_size); + break; + //case 0x21: strlcpy(buffer, "Unused", buffer_size); break; + case 0x22: + strlcpy(buffer, "Unused", buffer_size); + break; + case 0x23: + strlcpy(buffer, "Reserved", buffer_size); + break; + case 0x24: + strlcpy(buffer, "NEC DOS 3.x", buffer_size); + break; + case 0x26: + strlcpy(buffer, "Reserved", buffer_size); + break; + case 0x31: + strlcpy(buffer, "Reserved", buffer_size); + break; + case 0x32: + strlcpy(buffer, "NOS", buffer_size); + break; + case 0x33: + strlcpy(buffer, "Reserved", buffer_size); + break; + case 0x34: + strlcpy(buffer, "Reserved", buffer_size); + break; + case 0x35: + strlcpy(buffer, "JFS on OS/2 or eCS", buffer_size); + break; + case 0x36: + strlcpy(buffer, "Reserved", buffer_size); + break; + case 0x38: + strlcpy(buffer, "THEOS ver 3.2 2gb partition", buffer_size); + break; + case 0x39: + strlcpy(buffer, "Plan 9 partition", buffer_size); + break; + //case 0x39: strlcpy(buffer, "THEOS ver 4 spanned partition", buffer_size); break; + case 0x3a: + strlcpy(buffer, "THEOS ver 4 4gb partition", buffer_size); + break; + case 0x3b: + strlcpy(buffer, "THEOS ver 4 extended partition", buffer_size); + break; + case 0x3c: + strlcpy(buffer, "PartitionMagic recovery partition", buffer_size); + break; + case 0x3d: + strlcpy(buffer, "Hidden NetWare", buffer_size); + break; + case 0x40: + strlcpy(buffer, "Venix 80286", buffer_size); + break; + case 0x41: + strlcpy(buffer, "Linux/MINIX (sharing disk with DRDOS)", buffer_size); + break; + //case 0x41: strlcpy(buffer, "Personal RISC Boot", buffer_size); break; + //case 0x41: strlcpy(buffer, "PPC PReP (Power PC Reference Platform) Boot", buffer_size); break; + case 0x42: + strlcpy(buffer, "Linux swap (sharing disk with DRDOS)", buffer_size); + break; + //case 0x42: strlcpy(buffer, "SFS (Secure Filesystem)", buffer_size); break; + //case 0x42: strlcpy(buffer, "Windows 2000 marker", buffer_size); break; + case 0x43: + strlcpy(buffer, "Linux native (sharing disk with DRDOS)", buffer_size); + break; + case 0x44: + strlcpy(buffer, "GoBack partition", buffer_size); + break; + case 0x45: + strlcpy(buffer, "Boot-US boot manager", buffer_size); + break; + //case 0x45: strlcpy(buffer, "Priam", buffer_size); break; + //case 0x45: strlcpy(buffer, "EUMEL/Elan", buffer_size); break; + case 0x46: + strlcpy(buffer, "EUMEL/Elan", buffer_size); + break; + case 0x47: + strlcpy(buffer, "EUMEL/Elan", buffer_size); + break; + case 0x48: + strlcpy(buffer, "EUMEL/Elan", buffer_size); + break; + case 0x4a: + strlcpy(buffer, "AdaOS Aquila (Default)", buffer_size); + break; + //case 0x4a: strlcpy(buffer, "ALFS/THIN lightweight filesystem for DOS", buffer_size); break; + case 0x4c: + strlcpy(buffer, "Oberon partition", buffer_size); + break; + case 0x4d: + strlcpy(buffer, "QNX4.x", buffer_size); + break; + case 0x4e: + strlcpy(buffer, "QNX4.x 2nd part", buffer_size); + break; + case 0x4f: + strlcpy(buffer, "QNX4.x 3rd part", buffer_size); + break; + //case 0x4f: strlcpy(buffer, "Oberon partition", buffer_size); break; + case 0x50: + strlcpy(buffer, "OnTrack Disk Manager (older versions) RO", + buffer_size); + break; + //case 0x50: strlcpy(buffer, "Lynx RTOS", buffer_size); break; + //case 0x50: strlcpy(buffer, "Native Oberon (alt)", buffer_size); break; + case 0x51: + strlcpy(buffer, "OnTrack Disk Manager RW (DM6 Aux1)", buffer_size); + break; + //case 0x51: strlcpy(buffer, "Novell", buffer_size); break; + case 0x52: + strlcpy(buffer, "CP/M", buffer_size); + break; + //case 0x52: strlcpy(buffer, "Microport SysV/AT", buffer_size); break; + case 0x53: + strlcpy(buffer, "Disk Manager 6.0 Aux3", buffer_size); + break; + case 0x54: + strlcpy(buffer, "Disk Manager 6.0 Dynamic Drive Overlay", buffer_size); + break; + case 0x55: + strlcpy(buffer, "EZ-Drive", buffer_size); + break; + case 0x56: + strlcpy(buffer, "Golden Bow VFeature Partitioned Volume.", buffer_size); + break; + //case 0x56: strlcpy(buffer, "DM converted to EZ-BIOS", buffer_size); break; + case 0x57: + strlcpy(buffer, "DrivePro", buffer_size); + break; + //case 0x57: strlcpy(buffer, "VNDI Partition", buffer_size); break; + case 0x5c: + strlcpy(buffer, "Priam EDisk", buffer_size); + break; + case 0x61: + strlcpy(buffer, "SpeedStor", buffer_size); + break; + case 0x63: + strlcpy(buffer, + "Unix System V (SCO, ISC Unix, UnixWare, ...), Mach, GNU Hurd", + buffer_size); + break; + case 0x64: + strlcpy(buffer, "PC-ARMOUR protected partition", buffer_size); + break; + //case 0x64: strlcpy(buffer, "Novell Netware 286, 2.xx", buffer_size); break; + case 0x65: + strlcpy(buffer, "Novell Netware 386, 3.xx or 4.xx", buffer_size); + break; + case 0x66: + strlcpy(buffer, "Novell Netware SMS Partition", buffer_size); + break; + case 0x67: + strlcpy(buffer, "Novell", buffer_size); + break; + case 0x68: + strlcpy(buffer, "Novell", buffer_size); + break; + case 0x69: + strlcpy(buffer, "Novell Netware 5+, Novell Netware NSS Partition", + buffer_size); + break; + case 0x70: + strlcpy(buffer, "DiskSecure Multi-Boot", buffer_size); + break; + case 0x71: + strlcpy(buffer, "Reserved", buffer_size); + break; + case 0x73: + strlcpy(buffer, "Reserved", buffer_size); + break; + case 0x74: + strlcpy(buffer, "Reserved", buffer_size); + break; + //case 0x74: strlcpy(buffer, "Scramdisk partition", buffer_size); break; + case 0x75: + strlcpy(buffer, "IBM PC/IX", buffer_size); + break; + case 0x76: + strlcpy(buffer, "Reserved", buffer_size); + break; + case 0x77: + strlcpy(buffer, "M2FS/M2CS partition", buffer_size); + break; + //case 0x77: strlcpy(buffer, "VNDI Partition", buffer_size); break; + case 0x78: + strlcpy(buffer, "XOSL FS", buffer_size); + break; + case 0x7E: + strlcpy(buffer, " ", buffer_size); + break; + case 0x80: + strlcpy(buffer, "MINIX until 1.4a", buffer_size); + break; + case 0x81: + strlcpy(buffer, "MINIX since 1.4b, early Linux", buffer_size); + break; + //case 0x81: strlcpy(buffer, "Mitac disk manager", buffer_size); break; + //case 0x82: strlcpy(buffer, "Prime", buffer_size); break; + //case 0x82: strlcpy(buffer, "Solaris x86", buffer_size); break; + case 0x82: + strlcpy(buffer, "Linux swap", buffer_size); + break; + case 0x83: + strlcpy(buffer, "Linux native (usually ext2fs)", buffer_size); + break; + case 0x84: + strlcpy(buffer, "OS/2 hidden C: drive", buffer_size); + break; + //case 0x84: strlcpy(buffer, "Hibernation partition", buffer_size); break; + case 0x85: + strlcpy(buffer, "Linux extended partition", buffer_size); + break; + //case 0x86: strlcpy(buffer, "Old Linux RAID partition superblock", buffer_size); break; + case 0x86: + strlcpy(buffer, "NTFS volume set", buffer_size); + break; + case 0x87: + strlcpy(buffer, "NTFS volume set", buffer_size); + break; + case 0x8a: + strlcpy(buffer, "Linux Kernel Partition (used by AiR-BOOT)", + buffer_size); + break; + case 0x8b: + strlcpy(buffer, "Legacy Fault Tolerant FAT32 volume", buffer_size); + break; + case 0x8c: + strlcpy(buffer, + "Legacy Fault Tolerant FAT32 volume using BIOS extd INT 13h", + buffer_size); + break; + case 0x8d: + strlcpy(buffer, "Free FDISK hidden Primary DOS FAT12 partitition", + buffer_size); + break; + case 0x8e: + strlcpy(buffer, "Linux Logical Volume Manager partition", buffer_size); + break; + case 0x90: + strlcpy(buffer, "Free FDISK hidden Primary DOS FAT16 partitition", + buffer_size); + break; + case 0x91: + strlcpy(buffer, "Free FDISK hidden DOS extended partitition", + buffer_size); + break; + case 0x92: + strlcpy(buffer, "Free FDISK hidden Primary DOS large FAT16 partitition", + buffer_size); + break; + case 0x93: + strlcpy(buffer, "Hidden Linux native partition", buffer_size); + break; + //case 0x93: strlcpy(buffer, "Amoeba", buffer_size); break; + case 0x94: + strlcpy(buffer, "Amoeba bad block table", buffer_size); + break; + case 0x95: + strlcpy(buffer, "MIT EXOPC native partitions", buffer_size); + break; + case 0x97: + strlcpy(buffer, "Free FDISK hidden Primary DOS FAT32 partitition", + buffer_size); + break; + case 0x98: + strlcpy(buffer, "Free FDISK hidden Primary DOS FAT32 partitition (LBA)", + buffer_size); + break; + case 0x99: + strlcpy(buffer, "DCE376 logical drive", buffer_size); + break; + case 0x9a: + strlcpy(buffer, "Free FDISK hidden Primary DOS FAT16 partitition (LBA)", + buffer_size); + break; + case 0x9b: + strlcpy(buffer, "Free FDISK hidden DOS extended partitition (LBA)", + buffer_size); + break; + case 0x9f: + strlcpy(buffer, "BSD/OS", buffer_size); + break; + case 0xa0: + strlcpy(buffer, "Laptop hibernation partition", buffer_size); + break; + case 0xa1: + strlcpy(buffer, "Laptop hibernation partition", buffer_size); + break; + //case 0xa1: strlcpy(buffer, "HP Volume Expansion (SpeedStor variant)", buffer_size); break; + case 0xa3: + strlcpy(buffer, "Reserved", buffer_size); + break; + case 0xa4: + strlcpy(buffer, "Reserved", buffer_size); + break; + case 0xa5: + strlcpy(buffer, "BSD/386, 386BSD, NetBSD, FreeBSD", buffer_size); + break; + case 0xa6: + strlcpy(buffer, "OpenBSD", buffer_size); + break; + case 0xa7: + strlcpy(buffer, "NEXTSTEP", buffer_size); + break; + case 0xa8: + strlcpy(buffer, "Mac OS-X", buffer_size); + break; + case 0xa9: + strlcpy(buffer, "NetBSD", buffer_size); + break; + case 0xaa: + strlcpy(buffer, "Olivetti Fat 12 1.44Mb Service Partition", + buffer_size); + break; + case 0xab: + strlcpy(buffer, "Mac OS-X Boot partition", buffer_size); + break; + //case 0xab: strlcpy(buffer, "GO! partition", buffer_size); break; + case 0xae: + strlcpy(buffer, "ShagOS filesystem", buffer_size); + break; + case 0xaf: + strlcpy(buffer, "ShagOS swap partition", buffer_size); + break; + case 0xb0: + strlcpy(buffer, "BootStar Dummy", buffer_size); + break; + case 0xb1: + strlcpy(buffer, "Reserved", buffer_size); + break; + case 0xb3: + strlcpy(buffer, "Reserved", buffer_size); + break; + case 0xb4: + strlcpy(buffer, "Reserved", buffer_size); + break; + case 0xb6: + strlcpy(buffer, "Reserved", buffer_size); + break; + case 0xb7: + strlcpy(buffer, "BSDI BSD/386 filesystem", buffer_size); + break; + case 0xb8: + strlcpy(buffer, "BSDI BSD/386 swap partition", buffer_size); + break; + case 0xbb: + strlcpy(buffer, "Boot Wizard hidden", buffer_size); + break; + case 0xbe: + strlcpy(buffer, "Solaris 8 boot partition", buffer_size); + break; + case 0xc0: + strlcpy(buffer, "CTOS", buffer_size); + break; + //case 0xc0: strlcpy(buffer, "REAL/32 secure small partition", buffer_size); break; + //case 0xc0: strlcpy(buffer, "NTFT Partition", buffer_size); break; + case 0xc1: + strlcpy(buffer, "DRDOS/secured (FAT-12)", buffer_size); + break; + case 0xc2: + strlcpy(buffer, "Reserved for DR-DOS 7+", buffer_size); + break; + //case 0xc2: strlcpy(buffer, "Hidden Linux", buffer_size); break; + case 0xc3: + strlcpy(buffer, "Hidden Linux swap", buffer_size); + break; + case 0xc4: + strlcpy(buffer, "DRDOS/secured (FAT-16, < 32M)", buffer_size); + break; + case 0xc5: + strlcpy(buffer, "DRDOS/secured (extended)", buffer_size); + break; + case 0xc6: + strlcpy(buffer, "DRDOS/secured (FAT-16, >= 32M)", buffer_size); + break; + //case 0xc6: strlcpy(buffer, "Windows NT corrupted FAT16 volume/stripe set", buffer_size); break; + case 0xc7: + strlcpy(buffer, "Windows NT corrupted NTFS volume/stripe set", + buffer_size); + break; + //case 0xc7: strlcpy(buffer, "Syrinx boot", buffer_size); break; + case 0xc8: + strlcpy(buffer, "(See also ID c2.)", buffer_size); + break; + case 0xc9: + strlcpy(buffer, "(See also ID c2.)", buffer_size); + break; + case 0xca: + strlcpy(buffer, "(See also ID c2.)", buffer_size); + break; + case 0xcb: + strlcpy(buffer, "reserved for DRDOS/secured (FAT32)", buffer_size); + break; + case 0xcc: + strlcpy(buffer, "reserved for DRDOS/secured (FAT32, LBA)", buffer_size); + break; + case 0xcd: + strlcpy(buffer, "CTOS Memdump?", buffer_size); + break; + case 0xce: + strlcpy(buffer, "reserved for DRDOS/secured (FAT16, LBA)", buffer_size); + break; + case 0xd0: + strlcpy(buffer, "REAL/32 secure big partition", buffer_size); + break; + case 0xd1: + strlcpy(buffer, "Old Multiuser DOS secured FAT12", buffer_size); + break; + case 0xd4: + strlcpy(buffer, "Old Multiuser DOS secured FAT16 <32M", buffer_size); + break; + case 0xd5: + strlcpy(buffer, "Old Multiuser DOS secured extended partition", + buffer_size); + break; + case 0xd6: + strlcpy(buffer, "Old Multiuser DOS secured FAT16 >=32M", buffer_size); + break; + case 0xd8: + strlcpy(buffer, "CP/M-86", buffer_size); + break; + case 0xda: + strlcpy(buffer, "Non-FS Data", buffer_size); + break; + case 0xdb: + strlcpy(buffer, + "Digital Research CP/M, Concurrent CP/M, Concurrent DOS", + buffer_size); + break; + //case 0xdb: strlcpy(buffer, "CTOS (Convergent Technologies OS -Unisys)", buffer_size); break; + //case 0xdb: strlcpy(buffer, "KDG Telemetry SCPU boot", buffer_size); break; + case 0xdd: + strlcpy(buffer, "Hidden CTOS Memdump?", buffer_size); + break; + case 0xde: + strlcpy(buffer, "Dell PowerEdge Server utilities (FAT fs)", + buffer_size); + break; + case 0xdf: + strlcpy(buffer, "DG/UX virtual disk manager partition", buffer_size); + break; + //case 0xdf: strlcpy(buffer, "BootIt EMBRM", buffer_size); break; + case 0xe0: + strlcpy(buffer, + "Reserved by STMicroelectronics for a filesystem called ST AVFS.", + buffer_size); + break; + case 0xe1: + strlcpy(buffer, "DOS access or SpeedStor 12-bit FAT extended partition", + buffer_size); + break; + case 0xe3: + strlcpy(buffer, "DOS R/O or SpeedStor", buffer_size); + break; + case 0xe4: + strlcpy(buffer, "SpeedStor 16-bit FAT extended partition < 1024 cyl.", + buffer_size); + break; + case 0xe5: + strlcpy(buffer, + "Tandy DOS with logical sectored FAT (According to Powerquest.)", + buffer_size); + break; + //case 0xe5: strlcpy(buffer, "Reserved", buffer_size); break; + case 0xe6: + strlcpy(buffer, "Reserved", buffer_size); + break; + case 0xeb: + strlcpy(buffer, "BFS (aka BeFS)", buffer_size); + break; + case 0xed: + strlcpy(buffer, "Reserved for Matthias Paul's Sprytix", buffer_size); + break; + case 0xee: + strlcpy(buffer, + "Indication that this legacy MBR is followed by an EFI header", + buffer_size); + break; + case 0xef: + strlcpy(buffer, "Partition that contains an EFI file system", + buffer_size); + break; + case 0xf0: + strlcpy(buffer, "Linux/PA-RISC boot loader", buffer_size); + break; + case 0xf1: + strlcpy(buffer, "SpeedStor", buffer_size); + break; + case 0xf2: + strlcpy(buffer, + "DOS 3.3+ secondary partition (Powerquest writes: Unisys DOS with logical sectored FAT.)", + buffer_size); + break; + case 0xf3: + strlcpy(buffer, + "Reserved (Powerquest writes: Storage Dimensions SpeedStor.)", + buffer_size); + break; + case 0xf4: + strlcpy(buffer, "SpeedStor large partition", buffer_size); + break; + //case 0xf4: strlcpy(buffer, "Prologue single-volume partition", buffer_size); break; + case 0xf5: + strlcpy(buffer, "Prologue multi-volume partition", buffer_size); + break; + case 0xf6: + strlcpy(buffer, + "Reserved (Powerquest writes: Storage Dimensions SpeedStor. )", + buffer_size); + break; + case 0xfa: + strlcpy(buffer, "Bochs", buffer_size); + break; + case 0xfb: + strlcpy(buffer, "VMware File System partition", buffer_size); + break; + case 0xfc: + strlcpy(buffer, "VMware Swap partition", buffer_size); + break; + case 0xfd: + strlcpy(buffer, + "Linux raid partition with autodetect using persistent superblock (Powerquest writes: Reserved for FreeDOS. )", + buffer_size); + break; + case 0xfe: + strlcpy(buffer, "SpeedStor > 1024 cyl.", buffer_size); + break; + //case 0xfe: strlcpy(buffer, "LANstep", buffer_size); break; + //case 0xfe: strlcpy(buffer, "IBM PS/2 IML (Initial Microcode Load) partition, located at the end of the disk.", buffer_size); break; + //case 0xfe: strlcpy(buffer, "Windows NT Disk Administrator hidden partition", buffer_size); break; + //case 0xfe: strlcpy(buffer, "Linux Logical Volume Manager partition (old)", buffer_size); break; + case 0xff: + strlcpy(buffer, "Xenix Bad Block Table ", buffer_size); + break; + default: + strlcpy(buffer, "Unknown", buffer_size); + break; + } +} diff --git a/contrib/syslinux-4.02/com32/gpllib/disk/mbrs.c b/contrib/syslinux-4.02/com32/gpllib/disk/mbrs.c new file mode 100644 index 0000000..41bb20c --- /dev/null +++ b/contrib/syslinux-4.02/com32/gpllib/disk/mbrs.c @@ -0,0 +1,127 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#include <disk/common.h> +#include <disk/geom.h> +#include <disk/read.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +/** + * get_mbr_string - return a string describing the boot code + * @label: first four bytes of the MBR + * @buffer: pre-allocated buffer + * @buffer_size: @buffer size + **/ +void get_mbr_string(const uint32_t label, char *buffer, const int buffer_size) +{ + /* 2 bytes are usually enough to identify the MBR */ + uint16_t s_label = label >> 16; + + switch (s_label) { + case 0x0000: + case 0xfa33: + case 0xfab8: + case 0xfabe: + strlcpy(buffer, "No bootloader", buffer_size - 1); + break; + case 0x0ebe: + strlcpy(buffer, "ThinkPad", buffer_size - 1); + break; + case 0x31c0: + strlcpy(buffer, "Acer 3", buffer_size - 1); + break; + case 0x33c0: + strlcpy(buffer, "Windows", buffer_size - 1); + break; + case 0x33ff: + strlcpy(buffer, "HP/Gateway", buffer_size - 1); + break; + case 0xb800: + strlcpy(buffer, "PloP", buffer_size - 1); + break; + case 0xea05: + strlcpy(buffer, "XOSL", buffer_size - 1); + break; + case 0xea1e: + strlcpy(buffer, "Truecrypt Boot Loader", buffer_size - 1); + break; + case 0xeb04: + strlcpy(buffer, "Solaris", buffer_size - 1); + break; + case 0xeb48: + strlcpy(buffer, "Grub", buffer_size - 1); + break; + case 0xeb4c: + strlcpy(buffer, "Grub2 (v1.96)", buffer_size - 1); + break; + case 0xeb63: + strlcpy(buffer, "Grub2 (v1.97)", buffer_size - 1); + break; + case 0xeb5e: + /* We need more than 2 bytes */ + if (((label >> 8) & 0xff) == 0x00) + strlcpy(buffer, "fbinst", buffer_size - 1); + else if (((label >> 8) & 0xff) == 0x80) + strlcpy(buffer, "Grub4Dos", buffer_size - 1); + else if (((label >> 8) & 0xff) == 0x90) + strlcpy(buffer, "WEE", buffer_size - 1); + else + strlcpy(buffer, "Unknown mbr", buffer_size - 1); + break; + case 0xfa31: + /* We need more than 2 bytes */ + if (((label >> 8) & 0xff) == 0xc9) + strlcpy(buffer, "Master Boot LoaDeR", buffer_size - 1); + else if (((label >> 8) & 0xff) == 0xc0) + strlcpy(buffer, "Syslinux", buffer_size - 1); + else + strlcpy(buffer, "Unknown mbr", buffer_size - 1); + break; + case 0xfaeb: + strlcpy(buffer, "Lilo", buffer_size - 1); + break; + case 0xfc31: + strlcpy(buffer, "Testdisk", buffer_size - 1); + break; + case 0xfc33: + strlcpy(buffer, "GAG", buffer_size - 1); + break; + case 0xfceb: + strlcpy(buffer, "BootIT NG", buffer_size - 1); + break; + default: + strlcpy(buffer, "Unknown mbr", buffer_size - 1); + break; + } + + buffer[buffer_size - 1] = '\0'; +} + +/** + * get_mbr_id - return the first four bytes of the MBR + * @d: driveinfo struct describing the drive + **/ +uint32_t get_mbr_id(const struct driveinfo *d) +{ + char mbr[SECTOR * sizeof(char)]; + + if (read_mbr(d->disk, &mbr) == -1) + return -1; + else { + uint32_t mbr_id; + /* Reverse the opcodes */ + mbr_id = (*(uint8_t *) (mbr + 3)); + mbr_id += (*(uint8_t *) (mbr + 2) << 8); + mbr_id += (*(uint8_t *) (mbr + 1) << 16); + mbr_id += (*(uint8_t *) mbr) << 24; + return mbr_id; + } +} diff --git a/contrib/syslinux-4.02/com32/gpllib/disk/msdos.c b/contrib/syslinux-4.02/com32/gpllib/disk/msdos.c new file mode 100644 index 0000000..affec43 --- /dev/null +++ b/contrib/syslinux-4.02/com32/gpllib/disk/msdos.c @@ -0,0 +1,162 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#include <stdlib.h> + +#include <disk/common.h> +#include <disk/geom.h> +#include <disk/msdos.h> +#include <disk/partition.h> +#include <disk/read.h> + +static inline int is_extended_partition(struct part_entry *ptab) +{ + return (ptab->ostype == 0x05 || + ptab->ostype == 0x0f || ptab->ostype == 0x85); +} + +static inline int msdos_magic_present(const char *ptab) +{ + return (*(uint16_t *) (ptab + 0x1fe) == 0xaa55); +} + +/** + * process_extended_partition - execute a callback for each partition contained listed in an ebr + * @drive_info: driveinfo struct describing the drive + * @partition_offset: Absolute start (lba) of the extended partition + * @ebr_offset: Relative start (lba) of the current ebr processed within + * the extended partition + * @callback: Callback to execute + * @error: Buffer for I/O errors + * @nb_part_seen: Number of partitions found on the disk so far + **/ +static int process_extended_partition(struct driveinfo *drive_info, + const int partition_offset, + const int ebr_offset, + p_callback callback, int nb_part_seen) +{ + int status = 0; + /* The ebr is located at the first sector of the extended partition */ + char *ebr = malloc(SECTOR * sizeof(char)); + + if (read_sectors(drive_info, ebr, partition_offset + ebr_offset, 1) == -1) + goto abort; + + /* Check msdos magic signature */ + if (!msdos_magic_present(ebr)) + goto abort; + + struct part_entry *ptab = + (struct part_entry *)(ebr + PARTITION_TABLES_OFFSET); + + for (int i = 0; i < 4; i++) { + if (status == -1) + goto abort; + + if (!is_extended_partition(&ptab[i])) { + /* + * This EBR partition table entry points to the + * logical partition associated to that EBR + */ + int logical_partition_start = ebr_offset + ptab[i].start_lba; + + /* Last EBR in the extended partition? */ + if (!logical_partition_start) + continue; + + /* + * Check for garbage: + * 3rd and 4th entries in an EBR should be zero + * Some (malformed) partitioning software still add some + * data partitions there. + */ + if (ptab[i].start_lba <= 0 || ptab[i].length <= 0) + continue; + + nb_part_seen++; + callback(drive_info, + &ptab[i], + partition_offset + logical_partition_start, nb_part_seen); + } else + status = process_extended_partition(drive_info, + partition_offset, + ptab[i].start_lba, + callback, nb_part_seen); + } + + free(ebr); + return 0; + +abort: + free(ebr); + return -1; +} + +/** + * process_mbr - execute a callback for each partition contained in an {m,e}br + * @drive_info: driveinfo struct describing the drive + * @ptab: Pointer to the partition table + * @callback: Callback to execute + **/ +static int process_mbr(struct driveinfo *drive_info, struct part_entry *ptab, + p_callback callback) +{ + int status = 0; + + for (int i = 0; i < 4; i++) { + if (status == -1) + return -1; + + if (ptab[i].start_sect > 0) { + if (is_extended_partition(&ptab[i])) { + callback(drive_info, &ptab[i], ptab[i].start_lba, i + 1); + status = + process_extended_partition(drive_info, ptab[i].start_lba, 0, + callback, 4); + } else + callback(drive_info, &ptab[i], ptab[i].start_lba, i + 1); + } + } + + return 0; +} + +/** + * parse_partition_table - execute a callback for each partition entry + * @d: driveinfo struct describing the drive + * @callback: Callback to execute + * + * The signature of the callback should be the following: + * + * void callback(struct driveinfo *drive_info, + * struct part_entry *ptab, + * int offset_root, + * int nb_part_seen) + **/ +int parse_partition_table(struct driveinfo *d, p_callback callback) +{ + char *mbr = malloc(SECTOR * sizeof(char)); + + if (read_mbr(d->disk, mbr) == -1) + return -1; + else { + /* Check msdos magic signature */ + if (!msdos_magic_present(mbr)) + return -1; + + struct part_entry *ptab = + (struct part_entry *)(mbr + PARTITION_TABLES_OFFSET); + return process_mbr(d, ptab, callback); + } +} diff --git a/contrib/syslinux-4.02/com32/gpllib/disk/read.c b/contrib/syslinux-4.02/com32/gpllib/disk/read.c new file mode 100644 index 0000000..7a6cc43 --- /dev/null +++ b/contrib/syslinux-4.02/com32/gpllib/disk/read.c @@ -0,0 +1,135 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#include <com32.h> +#include <stdlib.h> +#include <string.h> + +#include <disk/errno_disk.h> +#include <disk/geom.h> +#include <disk/read.h> +#include <disk/util.h> +#include <disk/common.h> + +/* + * TODO: implement file descriptors to cache metadata (geometry, ...) + */ + +/** + * read_mbr - return a pointer to a malloced buffer containing the mbr + * @drive: Drive number + * @buf: Pre-allocated buffer for output + * + * Return the number of sectors read on success or -1 on failure. + * errno_disk contains the error number. + **/ +int read_mbr(int drive, void *buf) +{ + struct driveinfo drive_info; + drive_info.disk = drive; + + /* MBR: lba = 0, 1 sector */ + return read_sectors(&drive_info, buf, 0, 1); +} + +/** + * dev_read - read from a drive + * @drive: Drive number + * @buf: Pre-allocated buffer for output + * @lba: Position to start reading from + * @sectors: Number of sectors to read + * + * High-level routine to read from a hard drive. + * Return the number of sectors read on success or -1 on failure. + * errno_disk contains the error number. + **/ +int dev_read(int drive, void *buf, unsigned int lba, int sectors) +{ + struct driveinfo drive_info; + drive_info.disk = drive; + + return read_sectors(&drive_info, buf, lba, sectors); +} + +/** + * read_sectors - read several sectors from disk + * @drive_info: driveinfo struct describing the disk + * @data: Pre-allocated buffer for output + * @lba: Position to read + * @sectors: Number of sectors to read + * + * Return the number of sectors read on success or -1 on failure. + * errno_disk contains the error number. + **/ +int read_sectors(struct driveinfo *drive_info, void *data, + const unsigned int lba, const int sectors) +{ + com32sys_t inreg, outreg; + struct ebios_dapa *dapa = __com32.cs_bounce; + void *buf = (char *)__com32.cs_bounce + sectors * SECTOR; + char *bufp = data; + + if (get_drive_parameters(drive_info) == -1) + return -1; + + memset(&inreg, 0, sizeof inreg); + + if (drive_info->ebios) { + dapa->len = sizeof(*dapa); + dapa->count = sectors; + dapa->off = OFFS(buf); + dapa->seg = SEG(buf); + dapa->lba = lba; + + inreg.esi.w[0] = OFFS(dapa); + inreg.ds = SEG(dapa); + inreg.edx.b[0] = drive_info->disk; + inreg.eax.b[1] = 0x42; /* Extended read */ + } else { + unsigned int c, h, s; + + if (!drive_info->cbios) { // XXX errno + /* We failed to get the geometry */ + if (lba) + return -1; /* Can only read MBR */ + + s = 1; + h = 0; + c = 0; + } else + lba_to_chs(drive_info, lba, &s, &h, &c); + + // XXX errno + if (s > 63 || h > 256 || c > 1023) + return -1; + + inreg.eax.w[0] = 0x0201; /* Read one sector */ + inreg.ecx.b[1] = c & 0xff; + inreg.ecx.b[0] = s + (c >> 6); + inreg.edx.b[1] = h; + inreg.edx.b[0] = drive_info->disk; + inreg.ebx.w[0] = OFFS(buf); + inreg.es = SEG(buf); + } + + /* Perform the read */ + if (int13_retry(&inreg, &outreg)) { + errno_disk = outreg.eax.b[1]; + return -1; /* Give up */ + } + + memcpy(bufp, buf, sectors * SECTOR); + + return sectors; +} diff --git a/contrib/syslinux-4.02/com32/gpllib/disk/swsusp.c b/contrib/syslinux-4.02/com32/gpllib/disk/swsusp.c new file mode 100644 index 0000000..ef782fd --- /dev/null +++ b/contrib/syslinux-4.02/com32/gpllib/disk/swsusp.c @@ -0,0 +1,27 @@ +#include <stdlib.h> +#include <string.h> + +#include <disk/swsusp.h> +#include <disk/read.h> +#include <disk/geom.h> + +/** + * swsusp_check - check if a (swap) partition contains the swsusp signature + * @drive_info: driveinfo struct describing the disk containing the partition + * @ptab; Partition table of the partition + **/ +int swsusp_check(struct driveinfo *drive_info, struct part_entry *ptab) +{ + struct swsusp_header header_p; + int offset; + int found; + + /* Read first page of the swap device */ + offset = ptab->start_lba; + if (read_sectors(drive_info, &header_p, offset, PAGE_SIZE / SECTOR) == -1) { + return -1; + } else { + found = !memcmp(SWSUSP_SIG, header_p.sig, 10); + return found; + } +} diff --git a/contrib/syslinux-4.02/com32/gpllib/disk/util.c b/contrib/syslinux-4.02/com32/gpllib/disk/util.c new file mode 100644 index 0000000..59c0328 --- /dev/null +++ b/contrib/syslinux-4.02/com32/gpllib/disk/util.c @@ -0,0 +1,45 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#include <com32.h> +#include <stdlib.h> +#include <string.h> +#include <disk/geom.h> + +#define MAX_NB_RETRIES 6 + +/** + * int13_retry - int13h with error handling + * @inreg: int13h function parameters + * @outreg: output registers + * + * Call int 13h, but with retry on failure. Especially floppies need this. + **/ +int int13_retry(const com32sys_t * inreg, com32sys_t * outreg) +{ + int retry = MAX_NB_RETRIES; /* 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 */ + } + + /* If we get here: error */ + return -1; +} diff --git a/contrib/syslinux-4.02/com32/gpllib/disk/write.c b/contrib/syslinux-4.02/com32/gpllib/disk/write.c new file mode 100644 index 0000000..89e530d --- /dev/null +++ b/contrib/syslinux-4.02/com32/gpllib/disk/write.c @@ -0,0 +1,126 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from chain.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#include <com32.h> +#include <stdlib.h> +#include <string.h> + +#include <disk/common.h> +#include <disk/errno_disk.h> +#include <disk/read.h> +#include <disk/util.h> +#include <disk/write.h> + +/** + * write_sectors - write several sectors from disk + * @drive_info: driveinfo struct describing the disk + * @lba: Position to write + * @data: Buffer to write + * @size: Size of the buffer (number of sectors) + * + * Return the number of sectors write on success or -1 on failure. + * errno_disk contains the error number. + **/ +int write_sectors(const struct driveinfo *drive_info, const unsigned int lba, + const void *data, const int size) +{ + com32sys_t inreg, outreg; + struct ebios_dapa *dapa = __com32.cs_bounce; + void *buf = (char *)__com32.cs_bounce + size; + + memcpy(buf, data, size); + memset(&inreg, 0, sizeof inreg); + + if (drive_info->ebios) { + dapa->len = sizeof(*dapa); + dapa->count = size; + dapa->off = OFFS(buf); + dapa->seg = SEG(buf); + dapa->lba = lba; + + inreg.esi.w[0] = OFFS(dapa); + inreg.ds = SEG(dapa); + inreg.edx.b[0] = drive_info->disk; + inreg.eax.w[0] = 0x4300; /* Extended write */ + } else { + unsigned int c, h, s; + + if (!drive_info->cbios) { // XXX errno + /* We failed to get the geometry */ + if (lba) + return -1; /* Can only write MBR */ + + s = 1; + h = 0; + c = 0; + } else + lba_to_chs(drive_info, lba, &s, &h, &c); + + // XXX errno + if (s > 63 || h > 256 || c > 1023) + return -1; + + inreg.eax.w[0] = 0x0301; /* Write one sector */ + inreg.ecx.b[1] = c & 0xff; + inreg.ecx.b[0] = s + (c >> 6); + inreg.edx.b[1] = h; + inreg.edx.b[0] = drive_info->disk; + inreg.ebx.w[0] = OFFS(buf); + inreg.es = SEG(buf); + } + + /* Perform the write */ + if (int13_retry(&inreg, &outreg)) { + errno_disk = outreg.eax.b[1]; + return -1; /* Give up */ + } else + return size; +} + +/** + * write_verify_sectors - write several sectors from disk + * @drive_info: driveinfo struct describing the disk + * @lba: Position to write + * @data: Buffer to write + **/ +int write_verify_sector(struct driveinfo *drive_info, + const unsigned int lba, const void *data) +{ + return write_verify_sectors(drive_info, lba, data, SECTOR); +} + +/** + * write_verify_sectors - write several sectors from disk + * @drive_info: driveinfo struct describing the disk + * @lba: Position to write + * @data: Buffer to write + * @size: Size of the buffer (number of sectors) + **/ +int write_verify_sectors(struct driveinfo *drive_info, + const unsigned int lba, + const void *data, const int size) +{ + char *rb = malloc(SECTOR * size * sizeof(char)); + int status; + + if (write_sectors(drive_info, lba, data, size) == -1) + return -1; /* Write failure */ + + if (read_sectors(drive_info, rb, lba, size) == -1) + return -1; /* Readback failure */ + + status = memcmp(data, rb, SECTOR * size); + free(rb); + return status ? -1 : 0; +} diff --git a/contrib/syslinux-4.02/com32/gpllib/dmi/dmi.c b/contrib/syslinux-4.02/com32/gpllib/dmi/dmi.c new file mode 100644 index 0000000..507b11a --- /dev/null +++ b/contrib/syslinux-4.02/com32/gpllib/dmi/dmi.c @@ -0,0 +1,1004 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * 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 <stdio.h> +#include <string.h> +#include "dmi/dmi.h" + +const char *out_of_spec = "<OUT OF SPEC>"; +const char *bad_index = "<BAD INDEX>"; + +/* + * Misc. util stuff + */ + +/* + * 3.3.11 On Board Devices Information (Type 10) + */ + +static const char *dmi_on_board_devices_type(uint8_t code) +{ + /* 3.3.11.1 */ + static const char *type[] = { + "Other", /* 0x01 */ + "Unknown", + "Video", + "SCSI Controller", + "Ethernet", + "Token Ring", + "Sound", + "PATA Controller", + "SATA Controller", + "SAS Controller" /* 0x0A */ + }; + + if (code >= 0x01 && code <= 0x0A) + return type[code - 0x01]; + return out_of_spec; +} + +static void dmi_on_board_devices(struct dmi_header *h, s_dmi * dmi) +{ + uint8_t *p = h->data + 4; + uint8_t count = (h->length - 0x04) / 2; + unsigned int i; + + for (i = 0; + i < count + && i < + sizeof dmi->base_board.devices_information / + sizeof *dmi->base_board.devices_information; i++) { + strlcpy(dmi->base_board.devices_information[i].type, + dmi_on_board_devices_type(p[2 * i] & 0x7F), + sizeof dmi->base_board.devices_information[i].type); + dmi->base_board.devices_information[i].status = p[2 * i] & 0x80; + strlcpy(dmi->base_board.devices_information[i].description, + dmi_string(h, p[2 * i + 1]), + sizeof dmi->base_board.devices_information[i].description); + } +} + +/* + * 3.3.24 System Reset (Type 23) + */ + +static const char *dmi_system_reset_boot_option(uint8_t code) +{ + static const char *option[] = { + "Operating System", /* 0x1 */ + "System Utilities", + "Do Not Reboot" /* 0x3 */ + }; + + if (code >= 0x1) + return option[code - 0x1]; + return out_of_spec; +} + +static void dmi_system_reset_count(uint16_t code, char *array) +{ + if (code == 0xFFFF) + strlcpy(array, "Unknown", sizeof array); + else + snprintf(array, sizeof array, "%u", code); +} + +static void dmi_system_reset_timer(uint16_t code, char *array) +{ + if (code == 0xFFFF) + strlcpy(array, "Unknown", sizeof array); + else + snprintf(array, sizeof array, "%u min", code); +} + +/* + * 3.3.25 Hardware Security (Type 24) + */ + +static const char *dmi_hardware_security_status(uint8_t code) +{ + static const char *status[] = { + "Disabled", /* 0x00 */ + "Enabled", + "Not Implemented", + "Unknown" /* 0x03 */ + }; + + return status[code]; +} + +/* + * 3.3.12 OEM Strings (Type 11) + */ + +static void dmi_oem_strings(struct dmi_header *h, const char *prefix, + s_dmi * dmi) +{ + uint8_t *p = h->data + 4; + uint8_t count = p[0x00]; + int i; + + for (i = 1; i <= count; i++) + snprintf(dmi->oem_strings, OEM_STRINGS_SIZE, "%s %s %s\n", + dmi->oem_strings, prefix, dmi_string(h, i)); +} + +/* + * 3.3.13 System Configuration Options (Type 12) + */ +static void dmi_system_configuration_options(struct dmi_header *h, + const char *prefix, s_dmi * dmi) +{ + uint8_t *p = h->data + 4; + uint8_t count = p[0x00]; + int i; + + for (i = 1; i <= count; i++) + snprintf(dmi->system.configuration_options, + SYSTEM_CONFIGURATION_OPTIONS_SIZE, "%s %s %s\n", + dmi->system.configuration_options, prefix, dmi_string(h, i)); +} + +static void dmi_system_boot_status(uint8_t code, char *array) +{ + static const char *status[] = { + "No errors detected", /* 0 */ + "No bootable media", + "Operating system failed to load", + "Firmware-detected hardware failure", + "Operating system-detected hardware failure", + "User-requested boot", + "System security violation", + "Previously-requested image", + "System watchdog timer expired" /* 8 */ + }; + + if (code <= 8) + strlcpy(array, status[code], SYSTEM_BOOT_STATUS_SIZE); + if (code >= 128 && code <= 191) + strlcpy(array, "OEM-specific", SYSTEM_BOOT_STATUS_SIZE); + if (code >= 192) + strlcpy(array, "Product-specific", SYSTEM_BOOT_STATUS_SIZE); +} + +void dmi_bios_runtime_size(uint32_t code, s_dmi * dmi) +{ + if (code & 0x000003FF) { + dmi->bios.runtime_size = code; + strlcpy(dmi->bios.runtime_size_unit, "bytes", + sizeof(dmi->bios.runtime_size_unit)); + } else { + dmi->bios.runtime_size = code >> 10; + strlcpy(dmi->bios.runtime_size_unit, "KB", + sizeof(dmi->bios.runtime_size_unit)); + + } +} + +void dmi_bios_characteristics(uint64_t code, s_dmi * dmi) +{ + 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(uint8_t * p, s_dmi * dmi) +{ + int only0xFF = 1, only0x00 = 1; + int i; + + for (i = 0; i < 16 && (only0x00 || only0xFF); i++) { + if (p[i] != 0x00) + only0x00 = 0; + if (p[i] != 0xFF) + only0xFF = 0; + } + + if (only0xFF) { + sprintf(dmi->system.uuid, "Not Present"); + return; + } + if (only0x00) { + sprintf(dmi->system.uuid, "Not Settable"); + return; + } + + sprintf(dmi->system.uuid, + "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], + p[11], p[12], p[13], p[14], p[15]); +} + +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) { + strlcpy(dmi->system.wakeup_type, type[code], + sizeof(dmi->system.wakeup_type)); + } else { + strlcpy(dmi->system.wakeup_type, out_of_spec, + sizeof(dmi->system.wakeup_type)); + } + return; +} + +static void dmi_base_board_features(uint8_t code, s_dmi * dmi) +{ + if ((code & 0x1F) != 0) { + int i; + + for (i = 0; i <= 4; i++) + if (code & (1 << i)) + ((bool *) (&dmi->base_board.features))[i] = true; + } +} + +static void dmi_processor_voltage(uint8_t code, s_dmi * dmi) +{ + /* 3.3.5.4 */ + static const uint16_t voltage[] = { + 5000, + 3300, + 2900 + }; + int i; + + if (code & 0x80) + dmi->processor.voltage_mv = (code & 0x7f) * 100; + else { + for (i = 0; i <= 2; i++) + if (code & (1 << i)) + dmi->processor.voltage_mv = voltage[i]; + } +} + +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. + */ + uint32_t eax, edx; + int sig = 0; + + /* + * This might help learn about new processors supporting the + * CPUID instruction or another form of identification. + */ + sprintf(dmi->processor.id, "ID: %02X %02X %02X %02X %02X %02X %02X %02X\n", + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); + + if (type == 0x05) { /* 80386 */ + uint16_t dx = WORD(p); + /* + * 80386 have a different signature. + */ + dmi->processor.signature.type = (dx >> 12); + dmi->processor.signature.family = ((dx >> 8) & 0xF); + dmi->processor.signature.stepping = (dx >> 4) & 0xF; + dmi->processor.signature.minor_stepping = (dx & 0xF); + return; + } + if (type == 0x06) { /* 80486 */ + 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 + * works only because we know that 80486 must be little-endian. + */ + if ((dx & 0x0F00) == 0x0400 + && ((dx & 0x00F0) == 0x0040 || (dx & 0x00F0) >= 0x0070) + && ((dx & 0x000F) >= 0x0003)) + sig = 1; + else { + dmi->processor.signature.type = ((dx >> 12) & 0x3); + dmi->processor.signature.family = ((dx >> 8) & 0xF); + dmi->processor.signature.model = ((dx >> 4) & 0xF); + dmi->processor.signature.stepping = (dx & 0xF); + return; + } + } else if ((type >= 0x0B && type <= 0x13) /* Intel, Cyrix */ + ||(type >= 0xB0 && type <= 0xB3) /* Intel */ + ||type == 0xB5 /* Intel */ + || type == 0xB9) /* Intel */ + sig = 1; + else if ((type >= 0x18 && type <= 0x1D) /* AMD */ + ||type == 0x1F /* AMD */ + || (type >= 0xB6 && type <= 0xB7) /* AMD */ + ||(type >= 0x83 && type <= 0x85)) /* AMD */ + sig = 2; + else if (type == 0x01 || type == 0x02) { + /* + * Some X86-class CPU have family "Other" or "Unknown". In this case, + * we use the version string to determine if they are known to + * support the CPUID instruction. + */ + if (strncmp(version, "Pentium III MMX", 15) == 0) + sig = 1; + else if (strncmp(version, "AMD Athlon(TM)", 14) == 0 + || strncmp(version, "AMD Opteron(tm)", 15) == 0) + sig = 2; + else + return; + } else /* not X86-class */ + return; + + eax = DWORD(p); + edx = DWORD(p + 4); + switch (sig) { + case 1: /* Intel */ + dmi->processor.signature.type = ((eax >> 12) & 0x3); + dmi->processor.signature.family = + (((eax >> 16) & 0xFF0) + ((eax >> 8) & 0x00F)); + dmi->processor.signature.model = + (((eax >> 12) & 0xF0) + ((eax >> 4) & 0x0F)); + dmi->processor.signature.stepping = (eax & 0xF); + break; + case 2: /* AMD */ + dmi->processor.signature.family = + (((eax >> 8) & 0xF) == 0xF ? (eax >> 20) & 0xFF : (eax >> 8) & 0xF); + dmi->processor.signature.model = + (((eax >> 4) & 0xF) == 0xF ? (eax >> 16) & 0xF : (eax >> 4) & 0xF); + dmi->processor.signature.stepping = (eax & 0xF); + break; + } + + edx = DWORD(p + 4); + if ((edx & 0x3FF7FDFF) != 0) { + int i; + for (i = 0; i <= 31; i++) + if (cpu_flags_strings[i] != NULL && edx & (1 << i)) + ((bool *) (&dmi->processor.cpu_flags))[i] = true; + } +} + +void to_dmi_header(struct dmi_header *h, uint8_t * data) +{ + h->type = data[0]; + h->length = data[1]; + h->handle = WORD(data + 2); + h->data = data; +} + +const char *dmi_string(struct dmi_header *dm, uint8_t s) +{ + char *bp = (char *)dm->data; + size_t i, len; + + if (s == 0) + return "Not Specified"; + + bp += dm->length; + while (s > 1 && *bp) { + bp += strlen(bp); + bp++; + s--; + } + + if (!*bp) + return bad_index; + + /* ASCII filtering */ + len = strlen(bp); + for (i = 0; i < len; i++) + if (bp[i] < 32 || bp[i] == 127) + bp[i] = '.'; + + return bp; +} + +int checksum(uint8_t * buf, int len) +{ + uint8_t sum = 0; + int a; + + for (a = 0; a < len; a++) + sum += buf[a]; + return (sum == 0); +} + +static int smbios_decode(s_dmi * dmi, uint8_t * buf) +{ + + dmi->dmitable.ver = (buf[0x06] << 8) + buf[0x07]; + /* Some BIOS report weird SMBIOS version, fix that up */ + switch (dmi->dmitable.ver) { + case 0x021F: + dmi->dmitable.ver = 0x0203; + break; + case 0x0233: + dmi->dmitable.ver = 0x0206; + break; + } + dmi->dmitable.major_version = dmi->dmitable.ver >> 8; + dmi->dmitable.minor_version = dmi->dmitable.ver & 0xFF; + + return DMI_TABLE_PRESENT; +} + +static int legacy_decode(s_dmi * dmi, uint8_t * buf) +{ + dmi->dmitable.num = buf[13] << 8 | buf[12]; + dmi->dmitable.len = buf[7] << 8 | buf[6]; + dmi->dmitable.base = buf[11] << 24 | buf[10] << 16 | buf[9] << 8 | buf[8]; + + /* Version already found? */ + if (dmi->dmitable.ver > 0) + return DMI_TABLE_PRESENT; + + dmi->dmitable.ver = (buf[0x06] << 8) + buf[0x07]; + + /* + * DMI version 0.0 means that the real version is taken from + * the SMBIOS version, which we don't know at this point. + */ + if (buf[14] != 0) { + dmi->dmitable.major_version = buf[14] >> 4; + dmi->dmitable.minor_version = buf[14] & 0x0F; + } else { + dmi->dmitable.major_version = 0; + dmi->dmitable.minor_version = 0; + } + return DMI_TABLE_PRESENT; +} + +int dmi_iterate(s_dmi * dmi) +{ + uint8_t *p, *q; + int found = 0; + + /* Cleaning structures */ + memset(dmi, 0, sizeof(s_dmi)); + + 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 = (uint8_t *) 0xF0000; /* The start address to look at the dmi table */ + /* The anchor-string is 16-bytes aligned */ + for (q = p; q < p + 0x10000; q += 16) { + /* To validate the presence of SMBIOS: + * + the overall checksum must be correct + * + the intermediate anchor-string must be _DMI_ + * + the intermediate checksum must be correct + */ + if (memcmp(q, "_SM_", 4) == 0 && + checksum(q, q[0x05]) && + memcmp(q + 0x10, "_DMI_", 5) == 0 && checksum(q + 0x10, 0x0F)) { + /* Do not return, legacy_decode will need to be called + * on the intermediate structure to get the table length + * and address + */ + smbios_decode(dmi, q); + } else if (memcmp(q, "_DMI_", 5) == 0 && checksum(q, 0x0F)) { + found = 1; + legacy_decode(dmi, q); + } + } + + if (found) + return DMI_TABLE_PRESENT; + + dmi->dmitable.base = 0; + dmi->dmitable.num = 0; + dmi->dmitable.ver = 0; + dmi->dmitable.len = 0; + return -ENODMITABLE; +} + +void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi * dmi) +{ + uint8_t *data = h->data; + + /* + * Note: DMI types 37, 38 and 39 are untested + */ + switch (h->type) { + case 0: /* 3.3.1 BIOS Information */ + if (h->length < 0x12) + break; + dmi->bios.filled = true; + strlcpy(dmi->bios.vendor, dmi_string(h, data[0x04]), + sizeof(dmi->bios.vendor)); + strlcpy(dmi->bios.version, dmi_string(h, data[0x05]), + sizeof(dmi->bios.version)); + strlcpy(dmi->bios.release_date, dmi_string(h, data[0x08]), + sizeof(dmi->bios.release_date)); + dmi->bios.address = WORD(data + 0x06); + dmi_bios_runtime_size((0x10000 - WORD(data + 0x06)) << 4, dmi); + dmi->bios.rom_size = (data[0x09] + 1) << 6; + strlcpy(dmi->bios.rom_size_unit, "kB", sizeof(dmi->bios.rom_size_unit)); + dmi_bios_characteristics(QWORD(data + 0x0A), dmi); + + if (h->length < 0x13) + break; + dmi_bios_characteristics_x1(data[0x12], dmi); + if (h->length < 0x14) + break; + dmi_bios_characteristics_x2(data[0x13], dmi); + if (h->length < 0x18) + break; + if (data[0x14] != 0xFF && data[0x15] != 0xFF) + snprintf(dmi->bios.bios_revision, sizeof(dmi->bios.bios_revision), + "%u.%u", data[0x14], data[0x15]); + if (data[0x16] != 0xFF && data[0x17] != 0xFF) + snprintf(dmi->bios.firmware_revision, + sizeof(dmi->bios.firmware_revision), "%u.%u", data[0x16], + data[0x17]); + break; + case 1: /* 3.3.2 System Information */ + if (h->length < 0x08) + break; + dmi->system.filled = true; + strlcpy(dmi->system.manufacturer, dmi_string(h, data[0x04]), + sizeof(dmi->system.manufacturer)); + strlcpy(dmi->system.product_name, dmi_string(h, data[0x05]), + sizeof(dmi->system.product_name)); + strlcpy(dmi->system.version, dmi_string(h, data[0x06]), + sizeof(dmi->system.version)); + strlcpy(dmi->system.serial, dmi_string(h, data[0x07]), + sizeof(dmi->system.serial)); + if (h->length < 0x19) + break; + dmi_system_uuid(data + 0x08, dmi); + dmi_system_wake_up_type(data[0x18], dmi); + if (h->length < 0x1B) + break; + strlcpy(dmi->system.sku_number, dmi_string(h, data[0x19]), + sizeof(dmi->system.sku_number)); + strlcpy(dmi->system.family, dmi_string(h, data[0x1A]), + sizeof(dmi->system.family)); + break; + + case 2: /* 3.3.3 Base Board Information */ + if (h->length < 0x08) + break; + dmi->base_board.filled = true; + strlcpy(dmi->base_board.manufacturer, dmi_string(h, data[0x04]), + sizeof(dmi->base_board.manufacturer)); + strlcpy(dmi->base_board.product_name, dmi_string(h, data[0x05]), + sizeof(dmi->base_board.product_name)); + strlcpy(dmi->base_board.version, dmi_string(h, data[0x06]), + sizeof(dmi->base_board.version)); + strlcpy(dmi->base_board.serial, dmi_string(h, data[0x07]), + sizeof(dmi->base_board.serial)); + if (h->length < 0x0F) + break; + strlcpy(dmi->base_board.asset_tag, dmi_string(h, data[0x08]), + sizeof(dmi->base_board.asset_tag)); + dmi_base_board_features(data[0x09], dmi); + strlcpy(dmi->base_board.location, dmi_string(h, data[0x0A]), + sizeof(dmi->base_board.location)); + strlcpy(dmi->base_board.type, dmi_string(h, data[0x0D]), + sizeof(dmi->base_board.type)); + if (h->length < 0x0F + data[0x0E] * sizeof(uint16_t)) + break; + break; + case 3: /* 3.3.4 Chassis Information */ + if (h->length < 0x09) + break; + dmi->chassis.filled = true; + strlcpy(dmi->chassis.manufacturer, dmi_string(h, data[0x04]), + sizeof(dmi->chassis.manufacturer)); + strlcpy(dmi->chassis.type, dmi_chassis_type(data[0x05] & 0x7F), + sizeof(dmi->chassis.type)); + strlcpy(dmi->chassis.lock, dmi_chassis_lock(data[0x05] >> 7), + sizeof(dmi->chassis.lock)); + strlcpy(dmi->chassis.version, dmi_string(h, data[0x06]), + sizeof(dmi->chassis.version)); + strlcpy(dmi->chassis.serial, dmi_string(h, data[0x07]), + sizeof(dmi->chassis.serial)); + strlcpy(dmi->chassis.asset_tag, dmi_string(h, data[0x08]), + sizeof(dmi->chassis.asset_tag)); + if (h->length < 0x0D) + break; + strlcpy(dmi->chassis.boot_up_state, dmi_chassis_state(data[0x09]), + sizeof(dmi->chassis.boot_up_state)); + strlcpy(dmi->chassis.power_supply_state, + dmi_chassis_state(data[0x0A]), + sizeof(dmi->chassis.power_supply_state)); + strlcpy(dmi->chassis.thermal_state, + dmi_chassis_state(data[0x0B]), + sizeof(dmi->chassis.thermal_state)); + strlcpy(dmi->chassis.security_status, + dmi_chassis_security_status(data[0x0C]), + sizeof(dmi->chassis.security_status)); + if (h->length < 0x11) + break; + snprintf(dmi->chassis.oem_information, + sizeof(dmi->chassis.oem_information), "0x%08X", + DWORD(data + 0x0D)); + if (h->length < 0x15) + break; + dmi->chassis.height = data[0x11]; + dmi->chassis.nb_power_cords = data[0x12]; + break; + case 4: /* 3.3.5 Processor Information */ + if (h->length < 0x1A) + break; + dmi->processor.filled = true; + strlcpy(dmi->processor.socket_designation, + dmi_string(h, data[0x04]), + sizeof(dmi->processor.socket_designation)); + strlcpy(dmi->processor.type, + dmi_processor_type(data[0x05]), sizeof(dmi->processor.type)); + strlcpy(dmi->processor.manufacturer, + dmi_string(h, data[0x07]), sizeof(dmi->processor.manufacturer)); + strlcpy(dmi->processor.family, + dmi_processor_family(data[0x06], + dmi->processor.manufacturer), + sizeof(dmi->processor.family)); + dmi_processor_id(data[0x06], data + 8, dmi_string(h, data[0x10]), dmi); + strlcpy(dmi->processor.version, + dmi_string(h, data[0x10]), sizeof(dmi->processor.version)); + dmi_processor_voltage(data[0x11], dmi); + dmi->processor.external_clock = WORD(data + 0x12); + dmi->processor.max_speed = WORD(data + 0x14); + dmi->processor.current_speed = WORD(data + 0x16); + if (data[0x18] & (1 << 6)) + strlcpy(dmi->processor.status, + dmi_processor_status(data[0x18] & 0x07), + sizeof(dmi->processor.status)); + else + sprintf(dmi->processor.status, "Unpopulated"); + strlcpy(dmi->processor.upgrade, + dmi_processor_upgrade(data[0x19]), + sizeof(dmi->processor.upgrade)); + if (h->length < 0x20) + break; + dmi_processor_cache(WORD(data + 0x1A), "L1", ver, + dmi->processor.cache1); + dmi_processor_cache(WORD(data + 0x1C), "L2", ver, + dmi->processor.cache2); + dmi_processor_cache(WORD(data + 0x1E), "L3", ver, + dmi->processor.cache3); + if (h->length < 0x23) + break; + strlcpy(dmi->processor.serial, dmi_string(h, data[0x20]), + sizeof(dmi->processor.serial)); + strlcpy(dmi->processor.asset_tag, dmi_string(h, data[0x21]), + sizeof(dmi->processor.asset_tag)); + strlcpy(dmi->processor.part_number, dmi_string(h, data[0x22]), + sizeof(dmi->processor.part_number)); + break; + case 6: /* 3.3.7 Memory Module Information */ + if (h->length < 0x0C) + break; + dmi->memory_module_count++; + s_memory_module *module = + &dmi->memory_module[dmi->memory_module_count - 1]; + dmi->memory_module[dmi->memory_module_count - 1].filled = true; + strlcpy(module->socket_designation, dmi_string(h, data[0x04]), + sizeof(module->socket_designation)); + dmi_memory_module_connections(data[0x05], module->bank_connections, sizeof(module->bank_connections)); + dmi_memory_module_speed(data[0x06], module->speed); + dmi_memory_module_types(WORD(data + 0x07), " ", module->type, sizeof(module->type)); + dmi_memory_module_size(data[0x09], module->installed_size, sizeof(module->installed_size)); + dmi_memory_module_size(data[0x0A], module->enabled_size, sizeof(module->enabled_size)); + dmi_memory_module_error(data[0x0B], "\t\t", module->error_status); + break; + case 7: /* 3.3.8 Cache Information */ + if (h->length < 0x0F) + break; + dmi->cache_count++; + if (dmi->cache_count > MAX_DMI_CACHE_ITEMS) + break; + strlcpy(dmi->cache[dmi->cache_count - 1].socket_designation, + dmi_string(h, data[0x04]), + sizeof(dmi->cache[dmi->cache_count - 1].socket_designation)); + snprintf(dmi->cache[dmi->cache_count - 1].configuration, + sizeof(dmi->cache[dmi->cache_count - 1].configuration), + "%s, %s, %u", + WORD(data + 0x05) & 0x0080 ? "Enabled" : "Disabled", + WORD(data + + 0x05) & 0x0008 ? "Socketed" : "Not Socketed", + (WORD(data + 0x05) & 0x0007) + 1); + strlcpy(dmi->cache[dmi->cache_count - 1].mode, + dmi_cache_mode((WORD(data + 0x05) >> 8) & 0x0003), + sizeof(dmi->cache[dmi->cache_count - 1].mode)); + strlcpy(dmi->cache[dmi->cache_count - 1].location, + dmi_cache_location((WORD(data + 0x05) >> 5) & 0x0003), + sizeof(dmi->cache[dmi->cache_count - 1].location)); + dmi->cache[dmi->cache_count - 1].installed_size = + dmi_cache_size(WORD(data + 0x09)); + dmi->cache[dmi->cache_count - 1].max_size = + dmi_cache_size(WORD(data + 0x07)); + dmi_cache_types(WORD(data + 0x0B), " ", + dmi->cache[dmi->cache_count - 1].supported_sram_types); + dmi_cache_types(WORD(data + 0x0D), " ", + dmi->cache[dmi->cache_count - 1].installed_sram_types); + if (h->length < 0x13) + break; + dmi->cache[dmi->cache_count - 1].speed = data[0x0F]; /* ns */ + strlcpy(dmi->cache[dmi->cache_count - 1].error_correction_type, + dmi_cache_ec_type(data[0x10]), + sizeof(dmi->cache[dmi->cache_count - 1].error_correction_type)); + strlcpy(dmi->cache[dmi->cache_count - 1].system_type, + dmi_cache_type(data[0x11]), + sizeof(dmi->cache[dmi->cache_count - 1].system_type)); + strlcpy(dmi->cache[dmi->cache_count - 1].associativity, + dmi_cache_associativity(data[0x12]), + sizeof(dmi->cache[dmi->cache_count - 1].associativity)); + break; + case 10: /* 3.3.11 On Board Devices Information */ + dmi_on_board_devices(h, dmi); + break; + case 11: /* 3.3.12 OEM Strings */ + if (h->length < 0x05) + break; + dmi_oem_strings(h, "\t", dmi); + break; + case 12: /* 3.3.13 System Configuration Options */ + if (h->length < 0x05) + break; + dmi_system_configuration_options(h, "\t", dmi); + break; + case 17: /* 3.3.18 Memory Device */ + if (h->length < 0x15) + break; + dmi->memory_count++; + if (dmi->memory_count > MAX_DMI_MEMORY_ITEMS) + break; + 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); + strlcpy(mem->form_factor, + dmi_memory_device_form_factor(data[0x0E]), + sizeof(mem->form_factor)); + dmi_memory_device_set(data[0x0F], mem->device_set); + strlcpy(mem->device_locator, dmi_string(h, data[0x10]), + sizeof(mem->device_locator)); + strlcpy(mem->bank_locator, dmi_string(h, data[0x11]), + sizeof(mem->bank_locator)); + strlcpy(mem->type, dmi_memory_device_type(data[0x12]), + sizeof(mem->type)); + dmi_memory_device_type_detail(WORD(data + 0x13), mem->type_detail, sizeof(mem->type_detail)); + if (h->length < 0x17) + break; + dmi_memory_device_speed(WORD(data + 0x15), mem->speed); + if (h->length < 0x1B) + break; + strlcpy(mem->manufacturer, dmi_string(h, data[0x17]), + sizeof(mem->manufacturer)); + strlcpy(mem->serial, dmi_string(h, data[0x18]), sizeof(mem->serial)); + strlcpy(mem->asset_tag, dmi_string(h, data[0x19]), + sizeof(mem->asset_tag)); + strlcpy(mem->part_number, dmi_string(h, data[0x1A]), + sizeof(mem->part_number)); + break; + case 22: /* 3.3.23 Portable Battery */ + if (h->length < 0x10) + break; + dmi->battery.filled = true; + strlcpy(dmi->battery.location, dmi_string(h, data[0x04]), + sizeof(dmi->battery.location)); + strlcpy(dmi->battery.manufacturer, dmi_string(h, data[0x05]), + sizeof(dmi->battery.manufacturer)); + if (data[0x06] || h->length < 0x1A) + strlcpy(dmi->battery.manufacture_date, + dmi_string(h, data[0x06]), + sizeof(dmi->battery.manufacture_date)); + if (data[0x07] || h->length < 0x1A) + strlcpy(dmi->battery.serial, dmi_string(h, data[0x07]), + sizeof(dmi->battery.serial)); + strlcpy(dmi->battery.name, dmi_string(h, data[0x08]), + sizeof(dmi->battery.name)); + if (data[0x09] != 0x02 || h->length < 0x1A) + strlcpy(dmi->battery.chemistry, + dmi_battery_chemistry(data[0x09]), + sizeof(dmi->battery.chemistry)); + 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); + strlcpy(dmi->battery.sbds, dmi_string(h, data[0x0E]), + sizeof(dmi->battery.sbds)); + 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) + strlcpy(dmi->battery.sbds_chemistry, dmi_string(h, data[0x14]), + sizeof(dmi->battery.sbds_chemistry)); + // sprintf(dmi->battery.oem_info,"0x%08X",DWORD(h, data+0x16)); + break; + case 23: /* 3.3.24 System Reset */ + if (h->length < 0x0D) + break; + dmi->system.system_reset.filled = true; + dmi->system.system_reset.status = data[0x04] & (1 << 0); + dmi->system.system_reset.watchdog = data[0x04] & (1 << 5); + if (!(data[0x04] & (1 << 5))) + break; + strlcpy(dmi->system.system_reset.boot_option, + dmi_system_reset_boot_option((data[0x04] >> 1) & 0x3), + sizeof dmi->system.system_reset.boot_option); + strlcpy(dmi->system.system_reset.boot_option_on_limit, + dmi_system_reset_boot_option((data[0x04] >> 3) & 0x3), + sizeof dmi->system.system_reset.boot_option_on_limit); + dmi_system_reset_count(WORD(data + 0x05), + dmi->system.system_reset.reset_count); + dmi_system_reset_count(WORD(data + 0x07), + dmi->system.system_reset.reset_limit); + dmi_system_reset_timer(WORD(data + 0x09), + dmi->system.system_reset.timer_interval); + dmi_system_reset_timer(WORD(data + 0x0B), + dmi->system.system_reset.timeout); + break; + case 24: /* 3.3.25 Hardware Security */ + if (h->length < 0x05) + break; + dmi->hardware_security.filled = true; + strlcpy(dmi->hardware_security.power_on_passwd_status, + dmi_hardware_security_status(data[0x04] >> 6), + sizeof dmi->hardware_security.power_on_passwd_status); + strlcpy(dmi->hardware_security.keyboard_passwd_status, + dmi_hardware_security_status((data[0x04] >> 4) & 0x3), + sizeof dmi->hardware_security.keyboard_passwd_status); + strlcpy(dmi->hardware_security.administrator_passwd_status, + dmi_hardware_security_status((data[0x04] >> 2) & 0x3), + sizeof dmi->hardware_security.administrator_passwd_status); + strlcpy(dmi->hardware_security.front_panel_reset_status, + dmi_hardware_security_status(data[0x04] & 0x3), + sizeof dmi->hardware_security.front_panel_reset_status); + break; + case 32: /* 3.3.33 System Boot Information */ + if (h->length < 0x0B) + break; + dmi_system_boot_status(data[0x0A], dmi->system.system_boot_status); + case 38: /* 3.3.39 IPMI Device Information */ + if (h->length < 0x10) + break; + dmi->ipmi.filled = true; + snprintf(dmi->ipmi.interface_type, + sizeof(dmi->ipmi.interface_type), "%s", + dmi_ipmi_interface_type(data[0x04])); + dmi->ipmi.major_specification_version = data[0x05] >> 4; + dmi->ipmi.minor_specification_version = data[0x05] & 0x0F; + dmi->ipmi.I2C_slave_address = data[0x06] >> 1; + if (data[0x07] != 0xFF) + dmi->ipmi.nv_address = data[0x07]; + else + dmi->ipmi.nv_address = 0; /* Not Present */ + dmi_ipmi_base_address(data[0x04], data + 0x08, &dmi->ipmi); + if (h->length < 0x12) + break; + if (data[0x11] != 0x00) { + dmi->ipmi.irq = data[0x11]; + } + break; + } +} + +void parse_dmitable(s_dmi * dmi) +{ + int i = 0; + uint8_t *data = NULL; + uint8_t buf[dmi->dmitable.len]; + memcpy(buf, (int *)dmi->dmitable.base, sizeof(uint8_t) * dmi->dmitable.len); + data = buf; + 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); + /* + * If a short entry is found (less than 4 bytes), not only it + * is invalid, but we cannot reliably locate the next entry. + * Better stop at this point, and let the user know his/her + * table is broken. + */ + if (h.length < 4) { + printf + ("Invalid entry length (%u). DMI table is broken! Stop.\n\n", + (unsigned int)h.length); + break; + } + + /* loo for the next handle */ + next = data + h.length; + while (next - buf + 1 < dmi->dmitable.len + && (next[0] != 0 || next[1] != 0)) + next++; + next += 2; + if (next - buf <= dmi->dmitable.len) { + dmi_decode(&h, dmi->dmitable.ver, dmi); + } + data = next; + i++; + } +} diff --git a/contrib/syslinux-4.02/com32/gpllib/dmi/dmi_base_board.c b/contrib/syslinux-4.02/com32/gpllib/dmi/dmi_base_board.c new file mode 100644 index 0000000..0725321 --- /dev/null +++ b/contrib/syslinux-4.02/com32/gpllib/dmi/dmi_base_board.c @@ -0,0 +1,37 @@ +/* ----------------------------------------------------------------------- * + * + * 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/contrib/syslinux-4.02/com32/gpllib/dmi/dmi_battery.c b/contrib/syslinux-4.02/com32/gpllib/dmi/dmi_battery.c new file mode 100644 index 0000000..b0eab9b --- /dev/null +++ b/contrib/syslinux-4.02/com32/gpllib/dmi/dmi_battery.c @@ -0,0 +1,72 @@ +/* ----------------------------------------------------------------------- * + * + * 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/contrib/syslinux-4.02/com32/gpllib/dmi/dmi_bios.c b/contrib/syslinux-4.02/com32/gpllib/dmi/dmi_bios.c new file mode 100644 index 0000000..4a74800 --- /dev/null +++ b/contrib/syslinux-4.02/com32/gpllib/dmi/dmi_bios.c @@ -0,0 +1,79 @@ +/* ----------------------------------------------------------------------- * + * + * 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/contrib/syslinux-4.02/com32/gpllib/dmi/dmi_cache.c b/contrib/syslinux-4.02/com32/gpllib/dmi/dmi_cache.c new file mode 100644 index 0000000..4c3f83c --- /dev/null +++ b/contrib/syslinux-4.02/com32/gpllib/dmi/dmi_cache.c @@ -0,0 +1,134 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer - All Rights Reserved + * + * Some part borrowed from DMI Decode: + * + * (C) 2000-2002 Alan Cox <alan@redhat.com> + * (C) 2002-2007 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. + * + * ----------------------------------------------------------------------- */ + +#include <dmi/dmi.h> +#include <dmi/dmi_cache.h> +#include <stdio.h> + +/* + * 3.3.8 Cache Information (Type 7) + */ + +const char *dmi_cache_mode(uint8_t code) +{ + static const char *mode[] = { + "Write Through", /* 0x00 */ + "Write Back", + "Varies With Memory Address", + "Unknown" /* 0x03 */ + }; + + return mode[code]; +} + +const char *dmi_cache_location(uint8_t code) +{ + static const char *location[4] = { + "Internal", /* 0x00 */ + "External", + "<OUT OF SPEC", /* 0x02 */ + "Unknown" /* 0x03 */ + }; + + if (location[code] != NULL) + return location[code]; + return out_of_spec; +} + +uint16_t dmi_cache_size(uint16_t code) +{ + if (code & 0x8000) + return (code & 0x7FFF) << 6; /* KB */ + else + return code; /* KB */ +} + +void dmi_cache_types(uint16_t code, const char *sep, char *array) +{ + /* 3.3.8.2 */ + static const char *types[] = { + "Other", /* 0 */ + "Unknown", + "Non-burst", + "Burst", + "Pipeline Burst", + "Synchronous", + "Asynchronous" /* 6 */ + }; + + if ((code & 0x007F) == 0) + strcpy(array, "None"); + else { + int i; + + for (i = 0; i <= 6; i++) + if (code & (1 << i)) + sprintf(array, "%s%s", sep, types[i]); + } +} + +const char *dmi_cache_ec_type(uint8_t code) +{ + /* 3.3.8.3 */ + static const char *type[] = { + "Other", /* 0x01 */ + "Unknown", + "None", + "Parity", + "Single-bit ECC", + "Multi-bit ECC" /* 0x06 */ + }; + + if (code >= 0x01 && code <= 0x06) + return type[code - 0x01]; + return out_of_spec; +} + +const char *dmi_cache_type(uint8_t code) +{ + /* 3.3.8.4 */ + static const char *type[] = { + "Other", /* 0x01 */ + "Unknown", + "Instruction", + "Data", + "Unified" /* 0x05 */ + }; + + if (code >= 0x01 && code <= 0x05) + return type[code - 0x01]; + return out_of_spec; +} + +const char *dmi_cache_associativity(uint8_t code) +{ + /* 3.3.8.5 */ + static const char *type[] = { + "Other", /* 0x01 */ + "Unknown", + "Direct Mapped", + "2-way Set-associative", + "4-way Set-associative", + "Fully Associative", + "8-way Set-associative", + "16-way Set-associative" /* 0x08 */ + }; + + if (code >= 0x01 && code <= 0x08) + return type[code - 0x01]; + return out_of_spec; +} diff --git a/contrib/syslinux-4.02/com32/gpllib/dmi/dmi_chassis.c b/contrib/syslinux-4.02/com32/gpllib/dmi/dmi_chassis.c new file mode 100644 index 0000000..afca5c2 --- /dev/null +++ b/contrib/syslinux-4.02/com32/gpllib/dmi/dmi_chassis.c @@ -0,0 +1,113 @@ +/* ----------------------------------------------------------------------- * + * + * 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_chassis_type(uint8_t code) +{ + /* 3.3.4.1 */ + static const char *type[] = { + "Other", /* 0x01 */ + "Unknown", + "Desktop", + "Low Profile Desktop", + "Pizza Box", + "Mini Tower", + "Tower", + "Portable", + "Laptop", + "Notebook", + "Hand Held", + "Docking Station", + "All In One", + "Sub Notebook", + "Space-saving", + "Lunch Box", + "Main Server Chassis", /* master.mif says System */ + "Expansion Chassis", + "Sub Chassis", + "Bus Expansion Chassis", + "Peripheral Chassis", + "RAID Chassis", + "Rack Mount Chassis", + "Sealed-case PC", + "Multi-system", /* 0x19 */ + "CompactPCI", + "AdvancedTCA", + "Blade", + "Blade Enclosing" /* 0x1D */ + }; + + if (code >= 0x01 && code <= 0x1D) + return type[code - 0x01]; + return out_of_spec; +} + +const char *dmi_chassis_lock(uint8_t code) +{ + static const char *lock[] = { + "Not Present", /* 0x00 */ + "Present" /* 0x01 */ + }; + + return lock[code]; +} + +const char *dmi_chassis_state(uint8_t code) +{ + /* 3.3.4.2 */ + static const char *state[] = { + "Other", /* 0x01 */ + "Unknown", + "Safe", /* master.mif says OK */ + "Warning", + "Critical", + "Non-recoverable" /* 0x06 */ + }; + + if (code >= 0x01 && code <= 0x06) + return (state[code - 0x01]); + return out_of_spec; +} + +const char *dmi_chassis_security_status(uint8_t code) +{ + /* 3.3.4.3 */ + static const char *status[] = { + "Other", /* 0x01 */ + "Unknown", + "None", + "External Interface Locked Out", + "External Interface Enabled" /* 0x05 */ + }; + + if (code >= 0x01 && code <= 0x05) + return (status[code - 0x01]); + return out_of_spec; +} diff --git a/contrib/syslinux-4.02/com32/gpllib/dmi/dmi_ipmi.c b/contrib/syslinux-4.02/com32/gpllib/dmi/dmi_ipmi.c new file mode 100644 index 0000000..68a472e --- /dev/null +++ b/contrib/syslinux-4.02/com32/gpllib/dmi/dmi_ipmi.c @@ -0,0 +1,55 @@ +/* ----------------------------------------------------------------------- * + * + * Portions 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_ipmi_interface_type(uint8_t code) +{ + /* 3.3.39.1 and IPMI 2.0, appendix C1, table C1-2 */ + static const char *type[] = { + "Unknown", /* 0x00 */ + "KCS (Keyboard Control Style)", + "SMIC (Server Management Interface Chip)", + "BT (Block Transfer)", + "SSIF (SMBus System Interface)" /* 0x04 */ + }; + + if (code <= 0x04) + return type[code]; + return out_of_spec; +} + +void dmi_ipmi_base_address(uint8_t type, const uint8_t * p, s_ipmi * ipmi) +{ + if (type == 0x04) { /* SSIF */ + ipmi->base_address = (*p) >> 1; + } else { + ipmi->base_address = QWORD(p); + } +} diff --git a/contrib/syslinux-4.02/com32/gpllib/dmi/dmi_memory.c b/contrib/syslinux-4.02/com32/gpllib/dmi/dmi_memory.c new file mode 100644 index 0000000..2145829 --- /dev/null +++ b/contrib/syslinux-4.02/com32/gpllib/dmi/dmi_memory.c @@ -0,0 +1,259 @@ +/* ----------------------------------------------------------------------- * + * + * 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, int sizeof_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)) + snprintf(type_detail, sizeof_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); +} + +/* + * 3.3.7 Memory Module Information (Type 6) + */ + +void dmi_memory_module_types(uint16_t code, const char *sep, char *type, int sizeof_type) +{ + /* 3.3.7.1 */ + static const char *types[] = { + "Other", /* 0 */ + "Unknown", + "Standard", + "FPM", + "EDO", + "Parity", + "ECC", + "SIMM", + "DIMM", + "Burst EDO", + "SDRAM" /* 10 */ + }; + + if ((code & 0x07FF) == 0) + sprintf(type, "%s", "None"); + else { + int i; + + for (i = 0; i <= 10; i++) + if (code & (1 << i)) + snprintf(type, sizeof_type, "%s%s%s", type, sep, types[i]); + } +} + +void dmi_memory_module_connections(uint8_t code, char *connection, int sizeof_connection) +{ + if (code == 0xFF) + sprintf(connection, "%s", "None"); + else { + if ((code & 0xF0) != 0xF0) + sprintf(connection, "%u ", code >> 4); + if ((code & 0x0F) != 0x0F) + snprintf(connection, sizeof_connection, "%s%u", connection, code & 0x0F); + } +} + +void dmi_memory_module_speed(uint8_t code, char *speed) +{ + if (code == 0) + sprintf(speed, "%s", "Unknown"); + else + sprintf(speed, "%u ns", code); +} + +void dmi_memory_module_size(uint8_t code, char *size, int sizeof_size) +{ + /* 3.3.7.2 */ + switch (code & 0x7F) { + case 0x7D: + sprintf(size, "%s", "Not Determinable"); + break; + case 0x7E: + sprintf(size, "%s", "Disabled"); + break; + case 0x7F: + sprintf(size, "%s", "Not Installed"); + return; + default: + sprintf(size, "%u MB", 1 << (code & 0x7F)); + } + + if (code & 0x80) + snprintf(size, sizeof_size, "%s %s", size, "(Double-bank Connection)"); + else + snprintf(size, sizeof_size, "%s %s", size, "(Single-bank Connection)"); +} + +void dmi_memory_module_error(uint8_t code, const char *prefix, char *error) +{ + if (code & (1 << 2)) + sprintf(error, "%s", "See Event Log\n"); + else { + if ((code & 0x03) == 0) + sprintf(error, "%s", "OK\n"); + if (code & (1 << 0)) + sprintf(error, "%sUncorrectable Errors\n", prefix); + if (code & (1 << 1)) + sprintf(error, "%sCorrectable Errors\n", prefix); + } +} diff --git a/contrib/syslinux-4.02/com32/gpllib/dmi/dmi_processor.c b/contrib/syslinux-4.02/com32/gpllib/dmi/dmi_processor.c new file mode 100644 index 0000000..1cd9d1b --- /dev/null +++ b/contrib/syslinux-4.02/com32/gpllib/dmi/dmi_processor.c @@ -0,0 +1,429 @@ +/* ----------------------------------------------------------------------- * + * + * 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[256] = { + 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 */ + }; + /* 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 <= 0x18) + 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/contrib/syslinux-4.02/com32/gpllib/memory.c b/contrib/syslinux-4.02/com32/gpllib/memory.c new file mode 100644 index 0000000..28a95ff --- /dev/null +++ b/contrib/syslinux-4.02/com32/gpllib/memory.c @@ -0,0 +1,445 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer + * + * Some parts borrowed from meminfo.c32: + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * Some parts borrowed from Linux: + * + * Copyright (C) 1991, 1992 Linus Torvalds + * Copyright 2007 rPath, Inc. - All Rights Reserved + * Copyright 2009 Intel Corporation; author H. Peter Anvin + * + * Interrupt list from Ralf Brown (http://www.cs.cmu.edu/~ralf/files.html) + * + * This file is part of Syslinux, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +#include <stdint.h> +#include <com32.h> +#include <string.h> +#include <memory.h> + +const char *const e820_types[] = { + "usable", + "reserved", + "ACPI reclaim", + "ACPI NVS", + "unusable", +}; + +struct e820_ext_entry { + struct e820entry std; + uint32_t ext_flags; +} __attribute__ ((packed)); + +#define SMAP 0x534d4150 /* ASCII "SMAP" */ + +void get_type(int type, char *type_ptr, int type_ptr_sz) +{ + unsigned int real_type = type - 1; + if (real_type < sizeof(e820_types) / sizeof(e820_types[0])) + strlcpy(type_ptr, e820_types[real_type], type_ptr_sz); +} + +/** + *INT 15 - newer BIOSes - GET SYSTEM MEMORY MAP + * AX = E820h + * EAX = 0000E820h + * EDX = 534D4150h ('SMAP') + * EBX = continuation value or 00000000h to start at beginning of map + * ECX = size of buffer for result, in bytes (should be >= 20 bytes) + * ES:DI -> buffer for result (see #00581) + * + * Return: CF clear if successful + * EAX = 534D4150h ('SMAP') + * ES:DI buffer filled + * EBX = next offset from which to copy or 00000000h if all done + * ECX = actual length returned in bytes + * CF set on error + * AH = error code (86h) (see #00496 at INT 15/AH=80h) + * + * Notes: originally introduced with the Phoenix BIOS v4.0, this function is + * now supported by most newer BIOSes, since various versions of Windows + * call it to find out about the system memory + * a maximum of 20 bytes will be transferred at one time, even if ECX is + * higher; some BIOSes (e.g. Award Modular BIOS v4.50PG) ignore the + * value of ECX on entry, and always copy 20 bytes + * some BIOSes expect the high word of EAX to be clear on entry, i.e. + * EAX=0000E820h + * if this function is not supported, an application should fall back + * to AX=E802h, AX=E801h, and then AH=88h + * the BIOS is permitted to return a nonzero continuation value in EBX + * and indicate that the end of the list has already been reached by + * returning with CF set on the next iteration + * this function will return base memory and ISA/PCI memory contiguous + * with base memory as normal memory ranges; it will indicate + * chipset-defined address holes which are not in use and motherboard + * memory-mapped devices, and all occurrences of the system BIOS as + * reserved; standard PC address ranges will not be reported + **/ +void detect_memory_e820(struct e820entry *desc, int size_map, int *size_found) +{ + int count = 0; + static struct e820_ext_entry buf; /* static so it is zeroed */ + + com32sys_t ireg, oreg; + memset(&ireg, 0, sizeof ireg); + + ireg.eax.w[0] = 0xe820; + ireg.edx.l = SMAP; + ireg.ecx.l = sizeof(struct e820_ext_entry); + ireg.edi.w[0] = OFFS(__com32.cs_bounce); + ireg.es = SEG(__com32.cs_bounce); + + /* + * Set this here so that if the BIOS doesn't change this field + * but still doesn't change %ecx, we're still okay... + */ + memset(&buf, 0, sizeof buf); + buf.ext_flags = 1; + + do { + memcpy(__com32.cs_bounce, &buf, sizeof buf); + + /* Important: %edx and %esi are clobbered by some BIOSes, + so they must be either used for the error output + or explicitly marked clobbered. Given that, assume there + is something out there clobbering %ebp and %edi, too. */ + __intcall(0x15, &ireg, &oreg); + + /* Some BIOSes stop returning SMAP in the middle of + the search loop. We don't know exactly how the BIOS + screwed up the map at that point, we might have a + partial map, the full map, or complete garbage, so + just return failure. */ + if (oreg.eax.l != SMAP) { + count = 0; + break; + } + + if (oreg.eflags.l & EFLAGS_CF || oreg.ecx.l < 20) + break; + + memcpy(&buf, __com32.cs_bounce, sizeof buf); + + /* + * ACPI 3.0 added the extended flags support. If bit 0 + * in the extended flags is zero, we're supposed to simply + * ignore the entry -- a backwards incompatible change! + */ + if (oreg.ecx.l > 20 && !(buf.ext_flags & 1)) + continue; + + memcpy(&desc[count], &buf, sizeof buf); + count++; + + /* Set continuation value */ + ireg.ebx.l = oreg.ebx.l; + } while (ireg.ebx.l && count < size_map); + + *size_found = count; +} + +/** + * detect_memory_e801 + * + *INT 15 - Phoenix BIOS v4.0 - GET MEMORY SIZE FOR >64M CONFIGURATIONS + * AX = E801h + * + * Return: CF clear if successful + * AX = extended memory between 1M and 16M, in K (max 3C00h = 15MB) + * BX = extended memory above 16M, in 64K blocks + * CX = configured memory 1M to 16M, in K + * DX = configured memory above 16M, in 64K blocks + * CF set on error + * + * Notes: supported by the A03 level (6/14/94) and later XPS P90 BIOSes, as well + * as the Compaq Contura, 3/8/93 DESKPRO/i, and 7/26/93 LTE Lite 386 ROM + * BIOS + * supported by AMI BIOSes dated 8/23/94 or later + * on some systems, the BIOS returns AX=BX=0000h; in this case, use CX + * and DX instead of AX and BX + * this interface is used by Windows NT 3.1, OS/2 v2.11/2.20, and is + * used as a fall-back by newer versions if AX=E820h is not supported + * this function is not used by MS-DOS 6.0 HIMEM.SYS when an EISA machine + * (for example with parameter /EISA) (see also MEM F000h:FFD9h), or no + * Compaq machine was detected, or parameter /NOABOVE16 was given. + **/ +int detect_memory_e801(int *mem_size_below_16, int *mem_size_above_16) +{ + com32sys_t ireg, oreg; + memset(&ireg, 0, sizeof ireg); + + ireg.eax.w[0] = 0xe801; + + __intcall(0x15, &ireg, &oreg); + + if (oreg.eflags.l & EFLAGS_CF) + return -1; + + if (oreg.eax.w[0] > 0x3c00) + return -1; /* Bogus! */ + + /* Linux seems to use ecx and edx by default if they are defined */ + if (oreg.eax.w[0] || oreg.eax.w[0]) { + oreg.eax.w[0] = oreg.ecx.w[0]; + oreg.ebx.w[0] = oreg.edx.w[0]; + } + + *mem_size_below_16 = oreg.eax.w[0]; /* 1K blocks */ + *mem_size_above_16 = oreg.ebx.w[0]; /* 64K blocks */ + + return 0; +} + +int detect_memory_88(int *mem_size) +{ + com32sys_t ireg, oreg; + memset(&ireg, 0, sizeof ireg); + + ireg.eax.w[0] = 0x8800; + + __intcall(0x15, &ireg, &oreg); + + if (oreg.eflags.l & EFLAGS_CF) + return -1; + + *mem_size = oreg.eax.w[0]; + return 0; +} + +/* + * Sanitize the BIOS e820 map. + * + * This code come from the memtest86 project. It have been adjusted to match + * the syslinux environement. + * Some e820 responses include overlapping entries. The following + * replaces the original e820 map with a new one, removing overlaps. + * + * The following stuff could be merge once the addr_t will be set to 64bits. + * syslinux_scan_memory can be used for that purpose + */ +int sanitize_e820_map(struct e820entry *orig_map, struct e820entry *new_bios, + short old_nr) +{ + struct change_member { + struct e820entry *pbios; /* pointer to original bios entry */ + unsigned long long addr; /* address for this change point */ + }; + struct change_member change_point_list[2 * E820MAX]; + struct change_member *change_point[2 * E820MAX]; + struct e820entry *overlap_list[E820MAX]; + struct e820entry biosmap[E820MAX]; + struct change_member *change_tmp; + unsigned long current_type, last_type; + unsigned long long last_addr; + int chgidx, still_changing; + int overlap_entries; + int new_bios_entry; + int i; + + /* + Visually we're performing the following (1,2,3,4 = memory types)... + Sample memory map (w/overlaps): + ____22__________________ + ______________________4_ + ____1111________________ + _44_____________________ + 11111111________________ + ____________________33__ + ___________44___________ + __________33333_________ + ______________22________ + ___________________2222_ + _________111111111______ + _____________________11_ + _________________4______ + + Sanitized equivalent (no overlap): + 1_______________________ + _44_____________________ + ___1____________________ + ____22__________________ + ______11________________ + _________1______________ + __________3_____________ + ___________44___________ + _____________33_________ + _______________2________ + ________________1_______ + _________________4______ + ___________________2____ + ____________________33__ + ______________________4_ + */ + /* First make a copy of the map */ + for (i = 0; i < old_nr; i++) { + biosmap[i].addr = orig_map[i].addr; + biosmap[i].size = orig_map[i].size; + biosmap[i].type = orig_map[i].type; + } + + /* bail out if we find any unreasonable addresses in bios map */ + for (i = 0; i < old_nr; i++) { + if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr) + return 0; + } + + /* create pointers for initial change-point information (for sorting) */ + for (i = 0; i < 2 * old_nr; i++) + change_point[i] = &change_point_list[i]; + + /* record all known change-points (starting and ending addresses) */ + chgidx = 0; + for (i = 0; i < old_nr; i++) { + change_point[chgidx]->addr = biosmap[i].addr; + change_point[chgidx++]->pbios = &biosmap[i]; + change_point[chgidx]->addr = biosmap[i].addr + biosmap[i].size; + change_point[chgidx++]->pbios = &biosmap[i]; + } + + /* sort change-point list by memory addresses (low -> high) */ + still_changing = 1; + while (still_changing) { + still_changing = 0; + for (i = 1; i < 2 * old_nr; i++) { + /* if <current_addr> > <last_addr>, swap */ + /* or, if current=<start_addr> & last=<end_addr>, swap */ + if ((change_point[i]->addr < change_point[i - 1]->addr) || + ((change_point[i]->addr == change_point[i - 1]->addr) && + (change_point[i]->addr == change_point[i]->pbios->addr) && + (change_point[i - 1]->addr != + change_point[i - 1]->pbios->addr)) + ) { + change_tmp = change_point[i]; + change_point[i] = change_point[i - 1]; + change_point[i - 1] = change_tmp; + still_changing = 1; + } + } + } + + /* create a new bios memory map, removing overlaps */ + overlap_entries = 0; /* number of entries in the overlap table */ + new_bios_entry = 0; /* index for creating new bios map entries */ + last_type = 0; /* start with undefined memory type */ + last_addr = 0; /* start with 0 as last starting address */ + /* loop through change-points, determining affect on the new bios map */ + for (chgidx = 0; chgidx < 2 * old_nr; chgidx++) { + /* keep track of all overlapping bios entries */ + if (change_point[chgidx]->addr == change_point[chgidx]->pbios->addr) { + /* add map entry to overlap list (> 1 entry implies an overlap) */ + overlap_list[overlap_entries++] = change_point[chgidx]->pbios; + } else { + /* remove entry from list (order independent, so swap with last) */ + for (i = 0; i < overlap_entries; i++) { + if (overlap_list[i] == change_point[chgidx]->pbios) + overlap_list[i] = overlap_list[overlap_entries - 1]; + } + overlap_entries--; + } + /* if there are overlapping entries, decide which "type" to use */ + /* (larger value takes precedence -- 1=usable, 2,3,4,4+=unusable) */ + current_type = 0; + for (i = 0; i < overlap_entries; i++) + if (overlap_list[i]->type > current_type) + current_type = overlap_list[i]->type; + /* continue building up new bios map based on this information */ + if (current_type != last_type) { + if (last_type != 0) { + new_bios[new_bios_entry].size = + change_point[chgidx]->addr - last_addr; + /* move forward only if the new size was non-zero */ + if (new_bios[new_bios_entry].size != 0) + if (++new_bios_entry >= E820MAX) + break; /* no more space left for new bios entries */ + } + if (current_type != 0) { + new_bios[new_bios_entry].addr = change_point[chgidx]->addr; + new_bios[new_bios_entry].type = current_type; + last_addr = change_point[chgidx]->addr; + } + last_type = current_type; + } + } + return (new_bios_entry); +} + +/* The following stuff could be merge once the addr_t will be set to 64bits. + * syslinux_scan_memory can be used for that purpose */ +unsigned long detect_memsize(void) +{ + unsigned long memory_size = 0; + + /* Try to detect memory via e820 */ + struct e820entry map[E820MAX]; + int count = 0; + detect_memory_e820(map, E820MAX, &count); + memory_size = memsize_e820(map, count); + if (memory_size > 0) + return memory_size; + + /*e820 failed, let's try e801 */ + int mem_low, mem_high = 0; + if (!detect_memory_e801(&mem_low, &mem_high)) + return mem_low + (mem_high << 6); + + /*e801 failed, let's try e88 */ + int mem_size = 0; + if (!detect_memory_88(&mem_size)) + return mem_size; + + /* We were enable to detect any kind of memory */ + return 0; +} + +/* The following stuff could be merge once the addr_t will be set to 64bits. + * syslinux_scan_memory can be used for that purpose */ +unsigned long memsize_e820(struct e820entry *e820, int e820_nr) +{ + int i, n, nr; + unsigned long memory_size = 0; + struct e820entry nm[E820MAX]; + + /* Clean up, adjust and copy the BIOS-supplied E820-map. */ + nr = sanitize_e820_map(e820, nm, e820_nr); + + /* If there is not a good 820 map returning 0 to indicate + that we don't have any idea of the amount of ram we have */ + if (nr < 1 || nr > E820MAX) { + return 0; + } + + /* Build the memory map for testing */ + n = 0; + for (i = 0; i < nr; i++) { + if (nm[i].type == E820_RAM || nm[i].type == E820_ACPI) { + unsigned long long start; + unsigned long long end; + start = nm[i].addr; + end = start + nm[i].size; + + /* Don't ever use memory between 640 and 1024k */ + if (start > RES_START && start < RES_END) { + if (end < RES_END) { + continue; + } + start = RES_END; + } + if (end > RES_START && end < RES_END) { + end = RES_START; + } + memory_size += (end >> 12) - ((start + 4095) >> 12); + n++; + } else if (nm[i].type == E820_NVS) { + memory_size += nm[i].size >> 12; + } + } + return memory_size * 4; +} diff --git a/contrib/syslinux-4.02/com32/gpllib/vpd/vpd.c b/contrib/syslinux-4.02/com32/gpllib/vpd/vpd.c new file mode 100644 index 0000000..0e2b148 --- /dev/null +++ b/contrib/syslinux-4.02/com32/gpllib/vpd/vpd.c @@ -0,0 +1,103 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * 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 <stdio.h> +#include <string.h> +#include "vpd/vpd.h" + +int vpd_checksum(char *buf, int len) +{ + uint8_t sum = 0; + int a; + + for (a = 0; a < len; a++) + sum += buf[a]; + return (sum == 0); +} + +int vpd_decode(s_vpd * vpd) +{ + uint8_t buf[16]; + char *p, *q; + + /* Cleaning structures */ + memset(&vpd->base_address, 0, sizeof(vpd->base_address)); + memset(&vpd->bios_build_id, 0, sizeof(vpd->bios_build_id)); + memset(&vpd->box_serial_number, 0, sizeof(vpd->box_serial_number)); + memset(&vpd->motherboard_serial_number, 0, + sizeof(vpd->motherboard_serial_number)); + memset(&vpd->machine_type_model, 0, sizeof(vpd->machine_type_model)); + memset(&vpd->bios_release_date, 0, sizeof(vpd->bios_release_date)); + memset(&vpd->default_flash_filename, 0, + sizeof(vpd->default_flash_filename)); + memset(&vpd->bios_version, 0, sizeof(vpd->bios_version)); + + /* Until we found elements in the vpdtable, we consider them as not filled */ + vpd->filled = false; + + p = (char *)0xF0000; /* The start address to look at the dmi table */ + for (q = p; q < p + 0x10000; q += 4) { + memcpy(buf, q, 5); + if (memcmp(buf, "\252\125VPD", 5) == 0) { + snprintf(vpd->base_address, sizeof(vpd->base_address), "%p", q); + if (q[5] < 0x30) + return -ENOVPDTABLE; + + vpd->filled = true; + /* XSeries have longer records, exact length seems to vary. */ + if (!(q[5] >= 0x45 && vpd_checksum(q, q[5])) + /* Some Netvista seem to work with this. */ + && !(vpd_checksum(q, 0x30)) + /* The Thinkpad/Thinkcentre checksum does *not* include the first 13 bytes. */ + && !(vpd_checksum(q + 0x0D, 0x30 - 0x0D))) { + /* A few systems have a bad checksum (xSeries 325, 330, 335 + and 345 with early BIOS) but the record is otherwise + valid. */ + printf("VPD: Bad checksum!\n"); + } + + strlcpy(vpd->bios_build_id, q + 0x0D, 9); + strlcpy(vpd->box_serial_number, q + 0x16, 7); + strlcpy(vpd->motherboard_serial_number, q + 0x1D, 11); + strlcpy(vpd->machine_type_model, q + 0x28, 7); + + if (q[5] < 0x44) + return VPD_TABLE_PRESENT; + + strlcpy(vpd->bios_release_date, q + 0x30, 8); + strlcpy(vpd->default_flash_filename, q + 0x38, 12); + + if (q[5] >= 0x46 && q[0x44] != 0x00) { + strlcpy(vpd->bios_version, q + 0x44, 255); + } + + return VPD_TABLE_PRESENT; + } + } + return -ENOVPDTABLE; +} diff --git a/contrib/syslinux-4.02/com32/hdt/Makefile b/contrib/syslinux-4.02/com32/hdt/Makefile new file mode 100644 index 0000000..96af05f --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/Makefile @@ -0,0 +1,126 @@ +## ----------------------------------------------------------------------- +## +## Copyright 2001-2008 H. Peter Anvin - All Rights Reserved +## Copyright 2009 Intel Corporation; author: H. Peter Anvin +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, +## Boston MA 02110-1301, USA; either version 2 of the License, or +## (at your option) any later version; incorporated herein by reference. +## +## ----------------------------------------------------------------------- + +## +## Hardware Detection Tool +## + +topdir = ../.. +include ../MCONFIG + +LIBS = ../cmenu/libmenu/libmenu.a ../libutil/libutil_com.a \ + ../lib/libcom32.a $(LIBGCC) +CFLAGS += -I$(com32)/cmenu/libmenu + +MODULES = hdt.c32 +TESTFILES = + +OBJS = $(patsubst %.c,%.o,$(wildcard *.c)) +VERSION = $(shell $(SED) -n 's/\#define VERSION \"\(.*\)\"/\1/p' hdt.h) +CODENAME = $(shell $(SED) -n 's/\#define CODENAME \"\(.*\)\"/\1/p' hdt.h) +VERSION_C32 = $(shell echo $(VERSION) | $(SED) -e 's/-/_/g' | $(SED) -e 's/\./_/g') + +MEMTEST_URL = http://memtest.org/download/4.10/memtest86+-4.10.bin +MEMTEST = memtest.bin + +KERNEL_VERSION ?= $(shell uname -r) +MODULES_ALIAS_FILE ?= /lib/modules/$(KERNEL_VERSION)/modules.alias +GZ_MODULES_ALIAS_FILE ?= modules.alias.gz +MODULES_PCIMAP_FILE ?= /lib/modules/$(KERNEL_VERSION)/modules.pcimap +GZ_MODULES_PCIMAP_FILE ?= modules.pcimap.gz +ISO_DIR ?= iso +ISOLINUX_DIR ?= isolinux +FLOPPY_DIR ?= floppy +PCI_IDS_FILE ?= $(PWD)/$(FLOPPY_DIR)/pci.ids +GZ_PCI_IDS_FILE ?= $(PCI_IDS_FILE).gz +MENU_COM32 ?= $(com32)/menu/menu.c32 +ART_DIR ?= art/ + +all: $(MODULES) $(TESTFILES) + +hdt.elf : $(OBJS) $(LIBS) $(C_LIBS) + $(LD) $(LDFLAGS) -o $@ $^ + +memtest: + -[ ! -f $(FLOPPY_DIR)/$(MEMTEST) ] && $(WGET) $(MEMTEST_URL) -O $(FLOPPY_DIR)/$(MEMTEST) + +hdt.img: hdt.c32 $(FLOPPY_DIR)/hdt.cfg $(FLOPPY_DIR)/mtools.conf $(topdir)/mtools/syslinux $(MENU_COM32) memtest + rm -f hdt*.img + $(SED) -e 's/%VERSION%/$(VERSION)/g' $(FLOPPY_DIR)/hdt.cfg |\ + $(SED) -e 's/%CODENAME%/$(CODENAME)/g' > $(FLOPPY_DIR)/syslinux.cfg + MTOOLSRC=$(PWD)/$(FLOPPY_DIR)/mtools.conf $(MFORMAT) -v HDT_$(VERSION) -f 1440 -C a: + $(topdir)/mtools/syslinux hdt.img + -[ ! -f $(GZ_PCI_IDS_FILE) ] && cp /usr/share/hwdata/pci.ids $(PCI_IDS_FILE) && $(GZIPPROG) $(PCI_IDS_FILE) + -[ ! -f $(GZ_PCI_IDS_FILE) ] && cp /usr/share/pci.ids $(PCI_IDS_FILE) && $(GZIPPROG) $(PCI_IDS_FILE) + -[ -f $(MODULES_ALIAS_FILE) ] && cat $(MODULES_ALIAS_FILE) | $(GZIPPROG) - -f | MTOOLSRC=$(PWD)/$(FLOPPY_DIR)/mtools.conf $(MCOPY) - a:modules.alias + -[ -f $(MODULES_PCIMAP_FILE) ] && cat $(MODULES_PCIMAP_FILE) | $(GZIPPROG) - -f | MTOOLSRC=$(PWD)/$(FLOPPY_DIR)/mtools.conf $(MCOPY) - a:modules.pcimap + MTOOLSRC=$(PWD)/$(FLOPPY_DIR)/mtools.conf $(MCOPY) hdt.c32 a: + MTOOLSRC=$(PWD)/$(FLOPPY_DIR)/mtools.conf $(MCOPY) $(MENU_COM32) a: + @ [ -f $(GZ_PCI_IDS_FILE) ] && MTOOLSRC=$(PWD)/$(FLOPPY_DIR)/mtools.conf $(MCOPY) $(GZ_PCI_IDS_FILE) a:pci.ids || printf "\nThe $(GZ_PCI_IDS_FILE) file is missing and can be downloaded from http://pciids.sourceforge.net and gzipped in\nthe ./com32/hdt/$(FLOPPY_DIR) directory of the extracted Syslinux source.\n\n" + MTOOLSRC=$(PWD)/$(FLOPPY_DIR)/mtools.conf $(MCOPY) $(FLOPPY_DIR)/syslinux.cfg a: + MTOOLSRC=$(PWD)/$(FLOPPY_DIR)/mtools.conf $(MCOPY) $(FLOPPY_DIR)/$(MEMTEST) a: + MTOOLSRC=$(PWD)/$(FLOPPY_DIR)/mtools.conf $(MCOPY) $(ART_DIR)/backgnd.png a: + mv hdt.img hdt-$(VERSION).img + ln -sf hdt-$(VERSION).img hdt.img + +hdt.img.gz: hdt.img + rm -rf hdt*.img.gz + $(GZIPPROG) -c hdt-$(VERSION).img >hdt-$(VERSION).img.gz + ln -sf hdt-$(VERSION).img.gz hdt.img.gz + +hdt.iso: hdt.c32 $(topdir)/core/isolinux.bin $(FLOPPY_DIR)/hdt.cfg memtest + rm -rf $(ISO_DIR) + rm -f hdt.iso + mkdir -p $(ISO_DIR)/$(ISOLINUX_DIR) + cp $(topdir)/core/isolinux.bin $(ISO_DIR)/$(ISOLINUX_DIR) + $(SED) -e 's/%VERSION%/$(VERSION)/g' $(FLOPPY_DIR)/hdt.cfg |\ + $(SED) -e 's/%CODENAME%/$(CODENAME)/g' > $(ISO_DIR)/$(ISOLINUX_DIR)/isolinux.cfg + cp hdt.c32 $(ISO_DIR)/$(ISOLINUX_DIR) + cp $(FLOPPY_DIR)/$(MEMTEST) $(ISO_DIR)/$(ISOLINUX_DIR) + cp $(MENU_COM32) $(ISO_DIR)/$(ISOLINUX_DIR) + cp -av $(ART_DIR)/backgnd.png $(ISO_DIR)/$(ISOLINUX_DIR) + -[ ! -f $(GZ_PCI_IDS_FILE) ] && cp /usr/share/hwdata/pci.ids $(PCI_IDS_FILE) && $(GZIPPROG) $(PCI_IDS_FILE) + -[ ! -f $(GZ_PCI_IDS_FILE) ] && cp /usr/share/pci.ids $(PCI_IDS_FILE) && $(GZIPPROG) $(PCI_IDS_FILE) + -[ -f $(MODULES_ALIAS_FILE) ] && cp $(MODULES_ALIAS_FILE) $(ISO_DIR)/$(ISOLINUX_DIR)\ + && $(GZIPPROG) $(ISO_DIR)/$(ISOLINUX_DIR)/modules.alias\ + && mv $(ISO_DIR)/$(ISOLINUX_DIR)/modules.alias.gz $(ISO_DIR)/$(ISOLINUX_DIR)/modules.alias + -[ -f $(MODULES_PCIMAP_FILE) ] && cp $(MODULES_PCIMAP_FILE) $(ISO_DIR)/$(ISOLINUX_DIR)\ + && $(GZIPPROG) $(ISO_DIR)/$(ISOLINUX_DIR)/modules.pcimap\ + && mv $(ISO_DIR)/$(ISOLINUX_DIR)/modules.pcimap.gz $(ISO_DIR)/$(ISOLINUX_DIR)/modules.pcimap + -[ ! -f $(ISO_DIR)/$(ISOLINUX_DIR)/pci.ids.gz ] && cp $(GZ_PCI_IDS_FILE) $(ISO_DIR)/$(ISOLINUX_DIR)/pci.ids + -[ ! -f $(ISO_DIR)/$(ISOLINUX_DIR)/pci.ids ] && printf "\nThe $(FLOPPY_DIR)/pci.ids file is missing and can be downloaded from http://pciids.sourceforge.net and put in\nthe ./com32/hdt/$(FLOPPY_DIR) directory of the extracted Syslinux source.\n\n" + $(MKISOFS) -o hdt.iso -b $(ISOLINUX_DIR)/isolinux.bin -c $(ISOLINUX_DIR)/boot.cat \ + -no-emul-boot -boot-load-size 4 -boot-info-table \ + $(ISO_DIR) + mv hdt.iso hdt-$(VERSION).iso + ln -sf hdt-$(VERSION).iso hdt.iso + +release: spotless hdt.c32 hdt.img hdt.img.gz hdt.iso + mv hdt.c32 hdt_$(VERSION_C32).c32 + +tidy dist: + rm -f *.o *.lo *.a *.lst *.elf .*.d *.tmp + +clean: tidy + rm -f *.lnx + +spotless: clean + rm -f *.lss *.c32 *.com hdt*.img hdt*.iso hdt*.img.gz + rm -rf $(ISO_DIR) + rm -rf $(FLOPPY_DIR)/memtest + rm -rf $(FLOPPY_DIR)/pci.ids* + rm -f *~ \#* + +install: + +-include .*.d diff --git a/contrib/syslinux-4.02/com32/hdt/README b/contrib/syslinux-4.02/com32/hdt/README new file mode 100644 index 0000000..8e17161 --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/README @@ -0,0 +1,19 @@ +-------------- +Compiling HDT +-------------- +To build HDT, you just have to do a "make" call in this directory. + +--------------------------- +Creating a bootable floppy +-------------------------- +To build a bootable HDT floppy image, you can do a "make hdt.img" call. +This will requires the mtools (http://mtools.linux.lu) to be installed. +The script will try to pick several files from your system : +- /lib/modules/`uname -r`/modules.alias +- /lib/modules/`uname -r`/modules.pcimap +- /usr/share/pci.ids or /usr/share/hwdata/pci.ids + +This paths can be overrided with the following command line: +make MODULES_ALIAS_FILE=$(PWD)/floppy/modules.alias MODULES_PCIMAP_FILE=$(PWD)/floppy/modules.pcimap PCI_IDS_FILE=$(PWD)/floppy/pci.ids hdt.img + +If your system doesn't have pci.ids, please download it from http://pciids.sourceforge.net/ and put it into the floppy/ directory. diff --git a/contrib/syslinux-4.02/com32/hdt/art/backgnd.png b/contrib/syslinux-4.02/com32/hdt/art/backgnd.png Binary files differnew file mode 100644 index 0000000..a51efeb --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/art/backgnd.png diff --git a/contrib/syslinux-4.02/com32/hdt/art/hdt-black.png b/contrib/syslinux-4.02/com32/hdt/art/hdt-black.png Binary files differnew file mode 100644 index 0000000..9bfdd94 --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/art/hdt-black.png diff --git a/contrib/syslinux-4.02/com32/hdt/art/hdt.png b/contrib/syslinux-4.02/com32/hdt/art/hdt.png Binary files differnew file mode 100644 index 0000000..3dad8e7 --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/art/hdt.png diff --git a/contrib/syslinux-4.02/com32/hdt/floppy/hdt.cfg b/contrib/syslinux-4.02/com32/hdt/floppy/hdt.cfg new file mode 100644 index 0000000..1350521 --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/floppy/hdt.cfg @@ -0,0 +1,78 @@ +UI menu.c32 +DEFAULT hdt +PROMPT 0 +TIMEOUT 50 +MENU TITLE Hardware Detection Tool (HDT) version %VERSION% (%CODENAME%) +MENU MARGIN 0 +MENU ROWS 15 +MENU TABMSG +MENU TABMSGROW -3 +MENU CMDLINEROW -3 +MENU HELPMSGROW -4 +MENU HELPMSGENDROW -1 + +MENU COLOR SCREEN 37;40 +MENU COLOR BORDER 34;40 +MENU COLOR TITLE 1;33;40 +MENU COLOR SCROLLBAR 34;46 +MENU COLOR SEL 30;47 +MENU COLOR UNSEL 36;40 +MENU COLOR CMDMARK 37;40 +MENU COLOR CMDLINE 37;40 +MENU COLOR TABMSG 37;40 +MENU COLOR DISABLED 37;40 +MENU COLOR HELP 32;40 + +LABEL hdt +MENU LABEL Menu mode +MENU DEFAULT +TEXT HELP + Starts HDT using the MENU mode +ENDTEXT +COM32 hdt.c32 +APPEND modules_pcimap=modules.pcimap modules_alias=modules.alias pciids=pci.ids quiet + +LABEL cli +MENU LABEL CLI (VESA mode) +TEXT HELP + Starts HDT using the Command Line Interface (CLI) + VESA mode is enabled +ENDTEXT +COM32 hdt.c32 +APPEND modules_pcimap=modules.pcimap modules_alias=modules.alias pciids=pci.ids quiet nomenu vesa + +LABEL vesa +MENU LABEL CLI (Text mode) +TEXT HELP + Starts HDT using the Command Line Interface (CLI) + VESA mode is disabled +ENDTEXT +COM32 hdt.c32 +APPEND modules_pcimap=modules.pcimap modules_alias=modules.alias pciids=pci.ids quiet nomenu + +LABEL summary +MENU LABEL CLI (Auto summary) +TEXT HELP + Starts HDT using the Command Line Interface (CLI) and run 'show summary' + VESA mode is enabled +ENDTEXT +COM32 hdt.c32 +APPEND modules_pcimap=modules.pcimap modules_alias=modules.alias pciids=pci.ids quiet vesa nomenu auto='show summary' + +LABEL verbose +MENU LABEL CLI (Verbose) +TEXT HELP + Starts HDT using the Command Line Interface (CLI) using the verbose mode + VESA mode is enabled +ENDTEXT +COM32 hdt.c32 +APPEND modules_pcimap=modules.pcimap modules_alias=modules.alias pciids=pci.ids vesa nomenu + +MENU SEPARATOR + +LABEL memtest +MENU LABEL Memtest86+ 4.10 +TEXT HELP + Starts Memtest86+ 4.10 +ENDTEXT +LINUX memtest.bin diff --git a/contrib/syslinux-4.02/com32/hdt/floppy/mtools.conf b/contrib/syslinux-4.02/com32/hdt/floppy/mtools.conf new file mode 100644 index 0000000..adbe2c8 --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/floppy/mtools.conf @@ -0,0 +1,2 @@ +# Floppy image for HDT +drive a: file="hdt.img" diff --git a/contrib/syslinux-4.02/com32/hdt/hdt-ata.c b/contrib/syslinux-4.02/com32/hdt/hdt-ata.c new file mode 100644 index 0000000..9ba17ba --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-ata.c @@ -0,0 +1,38 @@ +/* ----------------------------------------------------------------------- * + * + * 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 <disk/geom.h> +#include <disk/util.h> + +#include "com32io.h" +#include "hdt-common.h" +#include "hdt-ata.h" diff --git a/contrib/syslinux-4.02/com32/hdt/hdt-ata.h b/contrib/syslinux-4.02/com32/hdt/hdt-ata.h new file mode 100644 index 0000000..ff35a59 --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-ata.h @@ -0,0 +1,76 @@ +/* ----------------------------------------------------------------------- * + * + * 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 <com32io.h> + +#include <disk/geom.h> +#include "hdt.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 ata_driveinfo { + struct ata_identify_device aid; /* IDENTIFY xxx DEVICE data */ + char host_bus_type[5]; + char interface_type[9]; + char interface_port; +} 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); +void printregs(const com32sys_t * r); +#endif + +#endif diff --git a/contrib/syslinux-4.02/com32/hdt/hdt-cli-cpu.c b/contrib/syslinux-4.02/com32/hdt/hdt-cli-cpu.c new file mode 100644 index 0000000..1695ccd --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-cli-cpu.c @@ -0,0 +1,227 @@ +/* ----------------------------------------------------------------------- * + * + * 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 <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> + +#include "hdt-cli.h" +#include "hdt-common.h" + +void main_show_cpu(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + char features[81]; + 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); + more_printf(" CPU Cores : %d \n", hardware->cpu.num_cores); + more_printf(" L2 Cache : %dK\n", hardware->cpu.l2_cache_size); + + memset(features, 0, sizeof(features)); + snprintf(features, sizeof(features), " Features : %d Mhz : ", + hardware->dmi.processor.current_speed); + if (hardware->cpu.flags.lm) + strcat(features, "x86_64 64bit "); + else + strcat(features, "x86 32bit "); + if (hardware->cpu.flags.smp) + strcat(features, "SMP "); + if (hardware->cpu.flags.vmx || hardware->cpu.flags.svm) + strcat(features, "HwVIRT "); + + more_printf("%s\n", features); +} + +static void show_flag(char *buffer, bool flag, char *flag_name, bool flush) +{ + char output_buffer[81]; + if ((((strlen(buffer) + strlen(flag_name)) > 66) && flag) || flush) { + snprintf(output_buffer, sizeof output_buffer, "Flags : %s\n", + buffer); + more_printf("%s", output_buffer); + memset(buffer, 0, sizeof(buffer)); + if (flush) + return; + } + if (flag) + strcat(buffer, flag_name); +} + +static void show_cpu(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + char buffer[81]; + reset_more_printf(); + more_printf("CPU\n"); + more_printf("Vendor : %s\n", hardware->cpu.vendor); + more_printf("Model : %s\n", hardware->cpu.model); + more_printf("CPU Cores : %d\n", hardware->cpu.num_cores); + more_printf("L1 Cache : %dK + %dK (I + D) \n", + hardware->cpu.l1_instruction_cache_size, + hardware->cpu.l1_data_cache_size); + more_printf("L2 Cache : %dK\n", hardware->cpu.l2_cache_size); + 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); + if (hardware->is_dmi_valid) { + 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); + more_printf("Voltage : %d.%02d\n", + hardware->dmi.processor.voltage_mv / 1000, + hardware->dmi.processor.voltage_mv - + ((hardware->dmi.processor.voltage_mv / 1000) * 1000)); + } + 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"); + } + + if (hardware->cpu.flags.vmx || hardware->cpu.flags.svm) { + more_printf("HwVirt : yes\n"); + } else { + more_printf("HwVirt : no\n"); + } + + memset(buffer, 0, sizeof(buffer)); + show_flag(buffer, hardware->cpu.flags.fpu, "fpu ", false); + show_flag(buffer, hardware->cpu.flags.vme, "vme ", false); + show_flag(buffer, hardware->cpu.flags.de, "de ", false); + show_flag(buffer, hardware->cpu.flags.pse, "pse ", false); + show_flag(buffer, hardware->cpu.flags.tsc, "tsc ", false); + show_flag(buffer, hardware->cpu.flags.msr, "msr ", false); + show_flag(buffer, hardware->cpu.flags.pae, "pae ", false); + show_flag(buffer, hardware->cpu.flags.mce, "mce ", false); + show_flag(buffer, hardware->cpu.flags.cx8, "cx8 ", false); + show_flag(buffer, hardware->cpu.flags.apic, "apic ", false); + show_flag(buffer, hardware->cpu.flags.sep, "sep ", false); + show_flag(buffer, hardware->cpu.flags.mtrr, "mtrr ", false); + show_flag(buffer, hardware->cpu.flags.pge, "pge ", false); + show_flag(buffer, hardware->cpu.flags.mca, "mca ", false); + show_flag(buffer, hardware->cpu.flags.cmov, "cmov ", false); + show_flag(buffer, hardware->cpu.flags.pat, "pat ", false); + show_flag(buffer, hardware->cpu.flags.pse_36, "pse_36 ", false); + show_flag(buffer, hardware->cpu.flags.psn, "psn ", false); + show_flag(buffer, hardware->cpu.flags.clflsh, "clflsh ", false); + show_flag(buffer, hardware->cpu.flags.dts, "dts ", false); + show_flag(buffer, hardware->cpu.flags.acpi, "acpi ", false); + show_flag(buffer, hardware->cpu.flags.mmx, "mmx ", false); + show_flag(buffer, hardware->cpu.flags.sse, "sse ", false); + show_flag(buffer, hardware->cpu.flags.sse2, "sse2 ", false); + show_flag(buffer, hardware->cpu.flags.ss, "ss ", false); + show_flag(buffer, hardware->cpu.flags.htt, "ht ", false); + show_flag(buffer, hardware->cpu.flags.acc, "acc ", false); + show_flag(buffer, hardware->cpu.flags.syscall, "syscall ", false); + show_flag(buffer, hardware->cpu.flags.mp, "mp ", false); + show_flag(buffer, hardware->cpu.flags.nx, "nx ", false); + show_flag(buffer, hardware->cpu.flags.mmxext, "mmxext ", false); + show_flag(buffer, hardware->cpu.flags.lm, "lm ", false); + show_flag(buffer, hardware->cpu.flags.nowext, "3dnowext ", false); + show_flag(buffer, hardware->cpu.flags.now, "3dnow! ", false); + show_flag(buffer, hardware->cpu.flags.svm, "svm ", false); + show_flag(buffer, hardware->cpu.flags.vmx, "vmx ", false); + show_flag(buffer, hardware->cpu.flags.pbe, "pbe ", false); + show_flag(buffer, hardware->cpu.flags.fxsr_opt, "fxsr_opt ", false); + show_flag(buffer, hardware->cpu.flags.gbpages, "gbpages ", false); + show_flag(buffer, hardware->cpu.flags.rdtscp, "rdtscp ", false); + show_flag(buffer, hardware->cpu.flags.pni, "pni ", false); + show_flag(buffer, hardware->cpu.flags.pclmulqd, "pclmulqd ", false); + show_flag(buffer, hardware->cpu.flags.dtes64, "dtes64 ", false); + show_flag(buffer, hardware->cpu.flags.smx, "smx ", false); + show_flag(buffer, hardware->cpu.flags.est, "est ", false); + show_flag(buffer, hardware->cpu.flags.tm2, "tm2 ", false); + show_flag(buffer, hardware->cpu.flags.sse3, "sse3 ", false); + show_flag(buffer, hardware->cpu.flags.fma, "fma ", false); + show_flag(buffer, hardware->cpu.flags.cx16, "cx16 ", false); + show_flag(buffer, hardware->cpu.flags.xtpr, "xtpr ", false); + show_flag(buffer, hardware->cpu.flags.pdcm, "pdcm ", false); + show_flag(buffer, hardware->cpu.flags.dca, "dca ", false); + show_flag(buffer, hardware->cpu.flags.xmm4_1, "xmm4_1 ", false); + show_flag(buffer, hardware->cpu.flags.xmm4_2, "xmm4_2 ", false); + show_flag(buffer, hardware->cpu.flags.x2apic, "x2apic ", false); + show_flag(buffer, hardware->cpu.flags.movbe, "movbe ", false); + show_flag(buffer, hardware->cpu.flags.popcnt, "popcnt ", false); + show_flag(buffer, hardware->cpu.flags.aes, "aes ", false); + show_flag(buffer, hardware->cpu.flags.xsave, "xsave ", false); + show_flag(buffer, hardware->cpu.flags.osxsave, "osxsave ", false); + show_flag(buffer, hardware->cpu.flags.avx, "avx ", false); + show_flag(buffer, hardware->cpu.flags.hypervisor, "hypervisor ", false); + show_flag(buffer, hardware->cpu.flags.ace2, "ace2 ", false); + show_flag(buffer, hardware->cpu.flags.ace2_en, "ace2_en ", false); + show_flag(buffer, hardware->cpu.flags.phe, "phe ", false); + show_flag(buffer, hardware->cpu.flags.phe_en, "phe_en ", false); + show_flag(buffer, hardware->cpu.flags.pmm, "pmm ", false); + show_flag(buffer, hardware->cpu.flags.pmm_en, "pmm_en ", false); + show_flag(buffer, hardware->cpu.flags.extapic, "extapic ", false); + show_flag(buffer, hardware->cpu.flags.cr8_legacy, "cr8_legacy ", false); + show_flag(buffer, hardware->cpu.flags.abm, "abm ", false); + show_flag(buffer, hardware->cpu.flags.sse4a, "sse4a ", false); + show_flag(buffer, hardware->cpu.flags.misalignsse, "misalignsse ", false); + show_flag(buffer, hardware->cpu.flags.nowprefetch, "3dnowprefetch ", false); + show_flag(buffer, hardware->cpu.flags.osvw, "osvw ", false); + show_flag(buffer, hardware->cpu.flags.ibs, "ibs ", false); + show_flag(buffer, hardware->cpu.flags.sse5, "sse5 ", false); + show_flag(buffer, hardware->cpu.flags.skinit, "skinit ", false); + show_flag(buffer, hardware->cpu.flags.wdt, "wdt ", false); + show_flag(buffer, hardware->cpu.flags.ida, "ida ", false); + show_flag(buffer, hardware->cpu.flags.arat, "arat ", false); + show_flag(buffer, hardware->cpu.flags.tpr_shadow, "tpr_shadow ", false); + show_flag(buffer, hardware->cpu.flags.vnmi, "vnmi ", false); + show_flag(buffer, hardware->cpu.flags.flexpriority, "flexpriority ", false); + show_flag(buffer, hardware->cpu.flags.ept, "ept ", false); + show_flag(buffer, hardware->cpu.flags.vpid, "vpid ", false); + + /* Let's flush the remaining flags */ + show_flag(buffer, false, "", true); +} + +struct cli_module_descr cpu_show_modules = { + .modules = NULL, + .default_callback = show_cpu, +}; + +struct cli_mode_descr cpu_mode = { + .mode = CPU_MODE, + .name = CLI_CPU, + .default_modules = NULL, + .show_modules = &cpu_show_modules, + .set_modules = NULL, +}; diff --git a/contrib/syslinux-4.02/com32/hdt/hdt-cli-disk.c b/contrib/syslinux-4.02/com32/hdt/hdt-cli-disk.c new file mode 100644 index 0000000..c43b7ca --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-cli-disk.c @@ -0,0 +1,253 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer - 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 <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> + +#include "hdt-cli.h" +#include "hdt-common.h" +#include "hdt-util.h" + +/** + * show_partition_information - print information about a partition + * @ptab: part_entry describing the partition + * @i: Partition number (UI purposes only) + * @ptab_root: part_entry describing the root partition (extended only) + * @drive_info: driveinfo struct describing the drive on which the partition + * is + * + * Note on offsets (from hpa, see chain.c32): + * + * To make things extra confusing: data partition offsets are relative to where + * the data partition record is stored, whereas extended partition offsets + * are relative to the beginning of the extended partition all the way back + * at the MBR... but still not absolute! + **/ +static void show_partition_information(struct driveinfo *drive_info, + struct part_entry *ptab, + int partition_offset, + int nb_partitions_seen) +{ + char size[11]; + char bootloader_name[9]; + char *parttype; + unsigned int start, end; + + int i = nb_partitions_seen; + + reset_more_printf(); + + start = partition_offset; + end = start + ptab->length - 1; + + if (ptab->length > 0) + sectors_to_size(ptab->length, size); + else + memset(size, 0, sizeof size); + + if (i == 1) + more_printf(" # B Start End Size Id Type\n"); + + get_label(ptab->ostype, &parttype); + more_printf("%2d %s %11d %11d %s %02X %s", + i, (ptab->active_flag == 0x80) ? "x" : " ", + start, end, size, ptab->ostype, parttype); + + /* Extra info */ + if (ptab->ostype == 0x82 && swsusp_check(drive_info, ptab)) + more_printf("%s", " (Swsusp sig. detected)"); + + if (get_bootloader_string(drive_info, ptab, bootloader_name, 9) == 0) + more_printf("%-46s %s %s", " ", "Bootloader:", bootloader_name); + + more_printf("\n"); + + free(parttype); +} + +void main_show_disk(int argc, char **argv, struct s_hardware *hardware) +{ + if (!argc) { + more_printf("Which disk?\n"); + return; + } + + int drive = strtol(argv[0], (char **)NULL, 16); + + if (drive < 0x80 || drive >= 0xff) { + more_printf("Invalid disk: %d.\n", drive); + return; + } + + int i = drive - 0x80; + struct driveinfo *d = &hardware->disk_info[i]; + char disk_size[11]; + char mbr_name[50]; + + detect_disks(hardware); + reset_more_printf(); + + if (!hardware->disk_info[i].cbios) { + more_printf("No disk found\n"); + return; /* Invalid geometry */ + } + + get_mbr_string(hardware->mbr_ids[i], &mbr_name, 50); + + if ((int)d->edd_params.sectors > 0) + sectors_to_size((int)d->edd_params.sectors, disk_size); + else + memset(disk_size, 0, sizeof disk_size); + + more_printf("DISK 0x%X:\n" + " C/H/S: %d cylinders, %d heads, %d sectors/track\n" + " EDD: Version: %X\n" + " Size: %s, %d bytes/sector, %d sectors/track\n" + " Host bus: %s, Interface type: %s\n" + " MBR: %s (id 0x%X)\n\n", + d->disk, + d->legacy_max_cylinder + 1, d->legacy_max_head + 1, + d->legacy_sectors_per_track, d->edd_version, disk_size, + (int)d->edd_params.bytes_per_sector, + (int)d->edd_params.sectors_per_track, + remove_spaces((char *)d->edd_params.host_bus_type), + remove_spaces((char *)d->edd_params.interface_type), mbr_name, + hardware->mbr_ids[i]); + display_line_nb += 6; + + if (parse_partition_table(d, &show_partition_information)) { + if (errno_disk) { + fprintf(stderr, "I/O error parsing disk 0x%X\n", d->disk); + get_error("parse_partition_table"); + } else { + fprintf(stderr, "Disk 0x%X: unrecognized partition layout\n", + d->disk); + } + fprintf(stderr, "\n"); + } + + more_printf("\n"); +} + +void main_show_disks(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + bool found = false; + reset_more_printf(); + detect_disks(hardware); + + int first_one = 0; + for (int drive = 0x80; drive < 0xff; drive++) { + if (hardware->disk_info[drive - 0x80].cbios) { + found = true; + if (!first_one) { + first_one = 1; + } else { + pause_printf(); + } + char buf[5] = ""; + sprintf(buf, "0x%x", drive); + char *argv[1] = { buf }; + main_show_disk(1, argv, hardware); + } + } + + if (found == false) + more_printf("No disk found\n"); +} + +void disks_summary(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + int i = -1; + bool found = false; + + detect_disks(hardware); + reset_more_printf(); + + for (int drive = 0x80; drive < 0xff; drive++) { + i++; + if (!hardware->disk_info[i].cbios) + continue; /* Invalid geometry */ + + found = true; + struct driveinfo *d = &hardware->disk_info[i]; + char disk_size[11]; + + if ((int)d->edd_params.sectors > 0) + sectors_to_size((int)d->edd_params.sectors, disk_size); + else + memset(disk_size, 0, sizeof disk_size); + + more_printf("DISK 0x%X:\n", d->disk); + more_printf(" C/H/S: %d cylinders, %d heads, %d sectors/track\n", + d->legacy_max_cylinder + 1, d->legacy_max_head + 1, + d->legacy_sectors_per_track); + more_printf(" EDD: Version: %X, size: %s\n", d->edd_version, + disk_size); + + /* Do not print Host Bus & Interface if EDD isn't 3.0 or more */ + if (d->edd_version >= 0x30) + more_printf(" Host bus: %s, Interface type: %s\n\n", + remove_spaces((char *)d->edd_params.host_bus_type), + remove_spaces((char *)d->edd_params.interface_type)); + } + + if (found == false) + more_printf("No disk found\n"); +} + +struct cli_callback_descr list_disk_show_modules[] = { + { + .name = "disks", + .exec = main_show_disks, + }, + { + .name = "disk", + .exec = main_show_disk, + }, + { + .name = NULL, + .exec = NULL, + }, +}; + +struct cli_module_descr disk_show_modules = { + .modules = list_disk_show_modules, + .default_callback = disks_summary, +}; + +struct cli_mode_descr disk_mode = { + .mode = DISK_MODE, + .name = CLI_DISK, + .default_modules = NULL, + .show_modules = &disk_show_modules, + .set_modules = NULL, +}; diff --git a/contrib/syslinux-4.02/com32/hdt/hdt-cli-dmi.c b/contrib/syslinux-4.02/com32/hdt/hdt-cli-dmi.c new file mode 100644 index 0000000..968308b --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-cli-dmi.c @@ -0,0 +1,688 @@ +/* ----------------------------------------------------------------------- * + * + * 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 <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> + +#include "hdt-cli.h" +#include "hdt-common.h" + +static void show_dmi_modules(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + char available_dmi_commands[1024]; + reset_more_printf(); + memset(available_dmi_commands, 0, sizeof(available_dmi_commands)); + + more_printf("Available DMI modules on your system:\n"); + if (hardware->dmi.base_board.filled == true) + more_printf("\t%s\n", CLI_DMI_BASE_BOARD); + if (hardware->dmi.battery.filled == true) + more_printf("\t%s\n", CLI_DMI_BATTERY); + if (hardware->dmi.bios.filled == true) + more_printf("\t%s\n", CLI_DMI_BIOS); + if (hardware->dmi.chassis.filled == true) + more_printf("\t%s\n", CLI_DMI_CHASSIS); + for (int i = 0; i < hardware->dmi.memory_count; i++) { + if (hardware->dmi.memory[i].filled == true) { + more_printf("\tbank <number>\n"); + break; + } + } + for (int i = 0; i < hardware->dmi.memory_module_count; i++) { + if (hardware->dmi.memory_module[i].filled == true) { + more_printf("\tmodule <number>\n"); + break; + } + } + if (hardware->dmi.processor.filled == true) + more_printf("\t%s\n", CLI_DMI_PROCESSOR); + if (hardware->dmi.system.filled == true) + more_printf("\t%s\n", CLI_DMI_SYSTEM); + if (hardware->dmi.ipmi.filled == true) + more_printf("\t%s\n", CLI_DMI_IPMI); + if (hardware->dmi.cache_count) + more_printf("\t%s\n", CLI_DMI_CACHE); + if (strlen(hardware->dmi.oem_strings)) + more_printf("\t%s\n", CLI_DMI_OEM); + if (hardware->dmi.hardware_security.filled) + more_printf("\t%s\n", CLI_DMI_SECURITY); +} + +static void show_dmi_base_board(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + if (hardware->dmi.base_board.filled == false) { + more_printf("base_board information not found on your system, see " + "`show list' to see which module is available.\n"); + return; + } + reset_more_printf(); + 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]); + } + } + + for (unsigned int i = 0; + i < + sizeof hardware->dmi.base_board.devices_information / + sizeof *hardware->dmi.base_board.devices_information; i++) { + if (strlen(hardware->dmi.base_board.devices_information[i].type)) { + more_printf("On Board Device #%u Information\n", i) + more_printf(" Type : %s\n", + hardware->dmi.base_board.devices_information[i]. + type); + more_printf(" Status : %s\n", + hardware->dmi.base_board.devices_information[i]. + status ? "Enabled" : "Disabled"); + more_printf(" Description : %s\n", + hardware->dmi.base_board.devices_information[i]. + description); + } + } +} + +static void show_dmi_system(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + if (hardware->dmi.system.filled == false) { + more_printf("system information not found on your system, see " + "`show list' to see which module is available.\n"); + return; + } + reset_more_printf(); + more_printf("System\n"); + more_printf(" Manufacturer : %s\n", hardware->dmi.system.manufacturer); + more_printf(" Product Name : %s\n", hardware->dmi.system.product_name); + more_printf(" Version : %s\n", hardware->dmi.system.version); + more_printf(" Serial : %s\n", hardware->dmi.system.serial); + more_printf(" UUID : %s\n", hardware->dmi.system.uuid); + more_printf(" Wakeup Type : %s\n", hardware->dmi.system.wakeup_type); + more_printf(" SKU Number : %s\n", hardware->dmi.system.sku_number); + more_printf(" Family : %s\n", hardware->dmi.system.family); + + if (strlen(hardware->dmi.system.configuration_options)) { + more_printf("System Configuration Options\n"); + more_printf("%s\n", hardware->dmi.system.configuration_options); + } + + if (hardware->dmi.system.system_reset.filled) { + more_printf("System Reset\n"); + more_printf(" Status : %s\n", + (hardware->dmi.system.system_reset. + status ? "Enabled" : "Disabled")); + more_printf(" Watchdog Timer : %s\n", + (hardware->dmi.system.system_reset. + watchdog ? "Present" : "Not Present")); + if (strlen(hardware->dmi.system.system_reset.boot_option)) + more_printf(" Boot Option : %s\n", + hardware->dmi.system.system_reset.boot_option); + if (strlen(hardware->dmi.system.system_reset.boot_option_on_limit)) + more_printf(" Boot Option On Limit : %s\n", + hardware->dmi.system.system_reset.boot_option_on_limit); + if (strlen(hardware->dmi.system.system_reset.reset_count)) + more_printf(" Reset Count : %s\n", + hardware->dmi.system.system_reset.reset_count); + if (strlen(hardware->dmi.system.system_reset.reset_limit)) + more_printf(" Reset Limit : %s\n", + hardware->dmi.system.system_reset.reset_limit); + if (strlen(hardware->dmi.system.system_reset.timer_interval)) + more_printf(" Timer Interval : %s\n", + hardware->dmi.system.system_reset.timer_interval); + if (strlen(hardware->dmi.system.system_reset.timeout)) + more_printf(" Timeout : %s\n", + hardware->dmi.system.system_reset.timeout); + } + + more_printf("System Boot Information\n"); + more_printf(" Status : %s\n", + hardware->dmi.system.system_boot_status); +} + +static void show_dmi_bios(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + if (hardware->dmi.bios.filled == false) { + more_printf("bios information not found on your system, see " + "`show list' to see which module is available.\n"); + return; + } + reset_more_printf(); + 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 Date : %s\n", hardware->dmi.bios.release_date); + more_printf(" Bios Revision : %s\n", hardware->dmi.bios.bios_revision); + if (strlen(hardware->dmi.bios.firmware_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]); + } + } + +} + +static void show_dmi_chassis(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + if (hardware->dmi.chassis.filled == false) { + more_printf("chassis information not found on your system, see " + "`show list' to see which module is available.\n"); + return; + } + reset_more_printf(); + 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", + del_multi_spaces(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); +} + +static void show_dmi_ipmi(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + if (hardware->dmi.ipmi.filled == false) { + more_printf("IPMI module not available\n"); + return; + } + reset_more_printf(); + more_printf("IPMI\n"); + more_printf(" Interface Type : %s\n", + hardware->dmi.ipmi.interface_type); + more_printf(" Specification Ver. : %u.%u\n", + hardware->dmi.ipmi.major_specification_version, + hardware->dmi.ipmi.minor_specification_version); + more_printf(" I2C Slave Address : 0x%02x\n", + hardware->dmi.ipmi.I2C_slave_address); + more_printf(" Nv Storage Address : %u\n", hardware->dmi.ipmi.nv_address); + uint32_t high = hardware->dmi.ipmi.base_address >> 32; + uint32_t low = hardware->dmi.ipmi.base_address & 0xFFFF; + more_printf(" Base Address : %08X%08X\n", high, (low & ~1)); + more_printf(" IRQ : %d\n", hardware->dmi.ipmi.irq); +} + +static void show_dmi_battery(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + if (hardware->dmi.battery.filled == false) { + more_printf("battery information not found on your system, see " + "`show list' to see which module is available.\n"); + return; + } + reset_more_printf(); + 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); +} + +static void show_dmi_cpu(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + if (hardware->dmi.processor.filled == false) { + more_printf("processor information not found on your system, see " + "`show list' to see which module is available.\n"); + return; + } + reset_more_printf(); + 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_bank(int argc, char **argv, struct s_hardware *hardware) +{ + int bank = -1; + + /* Sanitize arguments */ + if (argc > 0) + bank = strtol(argv[0], (char **)NULL, 10); + + if (errno == ERANGE || bank < 0) { + more_printf("This bank number is incorrect\n"); + return; + } + + if ((bank >= hardware->dmi.memory_count) || (bank < 0)) { + more_printf("Bank %d number doesn't exist\n", bank); + return; + } + if (hardware->dmi.memory[bank].filled == false) { + more_printf("Bank %d doesn't contain any information\n", bank); + return; + } + + reset_more_printf(); + more_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); +} + +static void show_dmi_cache(int argc, char **argv, struct s_hardware *hardware) +{ + if (!hardware->dmi.cache_count) { + more_printf("cache information not found on your system, see " + "`show list' to see which module is available.\n"); + return; + } + + int cache = strtol(argv[0], NULL, 10); + + if (argc != 1 || cache > hardware->dmi.cache_count) { + more_printf("show cache [0-%d]\n", hardware->dmi.cache_count - 1); + return; + } + + reset_more_printf(); + + more_printf("Cache Information #%d\n", cache); + more_printf(" Socket Designation : %s\n", + hardware->dmi.cache[cache].socket_designation); + more_printf(" Configuration : %s\n", + hardware->dmi.cache[cache].configuration); + more_printf(" Operational Mode : %s\n", + hardware->dmi.cache[cache].mode); + more_printf(" Location : %s\n", + hardware->dmi.cache[cache].location); + more_printf(" Installed Size : %u KB", + hardware->dmi.cache[cache].installed_size); + more_printf("\n"); + more_printf(" Maximum Size : %u KB", + hardware->dmi.cache[cache].max_size); + more_printf("\n"); + more_printf(" Supported SRAM Types : %s", + hardware->dmi.cache[cache].supported_sram_types); + more_printf("\n"); + more_printf(" Installed SRAM Type : %s", + hardware->dmi.cache[cache].installed_sram_types); + more_printf("\n"); + more_printf(" Speed : %u ns", + hardware->dmi.cache[cache].speed); + more_printf("\n"); + more_printf(" Error Correction Type : %s\n", + hardware->dmi.cache[cache].error_correction_type); + more_printf(" System Type : %s\n", + hardware->dmi.cache[cache].system_type); + more_printf(" Associativity : %s\n", + hardware->dmi.cache[cache].associativity); +} + +void show_dmi_memory_module(int argc, char **argv, struct s_hardware *hardware) +{ + int module = -1; + + /* Sanitize arguments */ + if (argc > 0) + module = strtol(argv[0], (char **)NULL, 10); + + if (errno == ERANGE || module < 0) { + more_printf("This module number is incorrect\n"); + return; + } + + if ((module >= hardware->dmi.memory_module_count) || (module < 0)) { + more_printf("Module number %d doesn't exist\n", module); + return; + } + + if (hardware->dmi.memory_module[module].filled == false) { + more_printf("Module %d doesn't contain any information\n", module); + return; + } + + reset_more_printf(); + more_printf("Memory Module %d\n", module); + more_printf(" Socket Designation : %s\n", + hardware->dmi.memory_module[module].socket_designation); + more_printf(" Bank Connections : %s\n", + hardware->dmi.memory_module[module].bank_connections); + more_printf(" Current Speed : %s\n", + hardware->dmi.memory_module[module].speed); + more_printf(" Type : %s\n", + hardware->dmi.memory_module[module].type); + more_printf(" Installed Size : %s\n", + hardware->dmi.memory_module[module].installed_size); + more_printf(" Enabled Size : %s\n", + hardware->dmi.memory_module[module].enabled_size); + more_printf(" Error Status : %s\n", + hardware->dmi.memory_module[module].error_status); +} + +void main_show_dmi(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + + detect_dmi(hardware); + + if (hardware->is_dmi_valid == false) { + more_printf("No valid DMI table found, exiting.\n"); + return; + } + reset_more_printf(); + more_printf("DMI Table version %u.%u found\n", + hardware->dmi.dmitable.major_version, + hardware->dmi.dmitable.minor_version); + + show_dmi_modules(0, NULL, hardware); +} + +void show_dmi_memory_modules(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + /* Do we have so display unpopulated banks ? */ + int show_free_banks = 1; + + /* Needed, if called by the memory mode */ + detect_dmi(hardware); + + /* Detecting installed memory */ + detect_memory(hardware); + + more_printf("Memory Size : %lu MB (%lu KB)\n", + (hardware->detected_memory_size + (1 << 9)) >> 10, + hardware->detected_memory_size); + + if ((hardware->dmi.memory_count <= 0) + && (hardware->dmi.memory_module_count <= 0)) { + more_printf("No memory bank found\n"); + return; + } + + /* Sanitize arguments */ + if (argc > 0) { + /* When we display a summary, there is no need to show the unpopulated banks + * The first argv is set to define this behavior + */ + show_free_banks = strtol(argv[0], NULL, 10); + if (errno == ERANGE || show_free_banks < 0 || show_free_banks > 1) + goto usage; + } + + reset_more_printf(); + /* If type 17 is available */ + if (hardware->dmi.memory_count > 0) { + char bank_number[255]; + more_printf("Memory Banks\n"); + for (int i = 0; i < hardware->dmi.memory_count; i++) { + if (hardware->dmi.memory[i].filled == true) { + memset(bank_number, 0, sizeof(bank_number)); + snprintf(bank_number, sizeof(bank_number), "%d ", i); + if (show_free_banks == false) { + if (strncmp(hardware->dmi.memory[i].size, "Free", 4)) + more_printf(" bank %02d : %s %s@%s\n", + i, hardware->dmi.memory[i].size, + hardware->dmi.memory[i].type, + hardware->dmi.memory[i].speed); + } else { + more_printf(" bank %02d : %s %s@%s\n", i, + hardware->dmi.memory[i].size, + hardware->dmi.memory[i].type, + hardware->dmi.memory[i].speed); + } + } + } + } else if (hardware->dmi.memory_module_count > 0) { + /* Let's use type 6 as a fallback of type 17 */ + more_printf("Memory Modules\n"); + for (int i = 0; i < hardware->dmi.memory_module_count; i++) { + if (hardware->dmi.memory_module[i].filled == true) { + more_printf(" module %02d : %s %s@%s\n", i, + hardware->dmi.memory_module[i].enabled_size, + hardware->dmi.memory_module[i].type, + hardware->dmi.memory_module[i].speed); + } + } + } + + return; + //printf("Type 'show bank<bank_number>' for more details.\n"); + +usage: + more_printf("show memory <clear screen? <show free banks?>>\n"); + return; +} + +void show_dmi_oem_strings(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + reset_more_printf(); + + if (strlen(hardware->dmi.oem_strings)) + more_printf("OEM Strings\n%s", hardware->dmi.oem_strings); +} + +void show_dmi_hardware_security(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + reset_more_printf(); + + if (!hardware->dmi.hardware_security.filled) + return; + + more_printf("Hardware Security\n"); + more_printf(" Power-On Password Status : %s\n", + hardware->dmi.hardware_security.power_on_passwd_status); + more_printf(" Keyboard Password Status : %s\n", + hardware->dmi.hardware_security.keyboard_passwd_status); + more_printf(" Administrator Password Status : %s\n", + hardware->dmi.hardware_security.administrator_passwd_status); + more_printf(" Front Panel Reset Status : %s\n", + hardware->dmi.hardware_security.front_panel_reset_status); +} + +struct cli_callback_descr list_dmi_show_modules[] = { + { + .name = CLI_DMI_BASE_BOARD, + .exec = show_dmi_base_board, + }, + { + .name = CLI_DMI_BIOS, + .exec = show_dmi_bios, + }, + { + .name = CLI_DMI_BATTERY, + .exec = show_dmi_battery, + }, + { + .name = CLI_DMI_CHASSIS, + .exec = show_dmi_chassis, + }, + { + .name = CLI_DMI_MEMORY, + .exec = show_dmi_memory_modules, + }, + { + .name = CLI_DMI_MEMORY_BANK, + .exec = show_dmi_memory_bank, + }, + { + .name = "module", + .exec = show_dmi_memory_module, + }, + { + .name = CLI_DMI_PROCESSOR, + .exec = show_dmi_cpu, + }, + { + .name = CLI_DMI_SYSTEM, + .exec = show_dmi_system, + }, + { + .name = CLI_DMI_OEM, + .exec = show_dmi_oem_strings, + }, + { + .name = CLI_DMI_SECURITY, + .exec = show_dmi_hardware_security, + }, + { + .name = CLI_DMI_IPMI, + .exec = show_dmi_ipmi, + }, + { + .name = CLI_DMI_CACHE, + .exec = show_dmi_cache, + }, + { + .name = CLI_DMI_LIST, + .exec = show_dmi_modules, + }, + { + .name = NULL, + .exec = NULL, + }, +}; + +struct cli_module_descr dmi_show_modules = { + .modules = list_dmi_show_modules, + .default_callback = main_show_dmi, +}; + +struct cli_mode_descr dmi_mode = { + .mode = DMI_MODE, + .name = CLI_DMI, + .default_modules = NULL, + .show_modules = &dmi_show_modules, + .set_modules = NULL, +}; diff --git a/contrib/syslinux-4.02/com32/hdt/hdt-cli-hdt.c b/contrib/syslinux-4.02/com32/hdt/hdt-cli-hdt.c new file mode 100644 index 0000000..f4854e3 --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-cli-hdt.c @@ -0,0 +1,375 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer - 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 <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <syslinux/config.h> +#include <syslinux/reboot.h> + +#include "hdt-menu.h" +#include "hdt-cli.h" +#include "hdt-common.h" + +/** + * cli_clear_screen - clear (erase) the entire screen + **/ +static void cli_clear_screen(int argc __unused, char **argv __unused, + struct s_hardware *hardware __unused) +{ + clear_screen(); +} + +/** + * main_show_modes - show availables modes + **/ +static void main_show_modes(int argc __unused, char **argv __unused, + struct s_hardware *hardware __unused) +{ + int i = 0; + + reset_more_printf(); + printf("Available modes:\n"); + while (list_modes[i]) { + printf("%s ", list_modes[i]->name); + i++; + } + printf("\n"); +} + +/** + * cli_set_mode - set the mode of the cli, in the cli + * + * The mode number must be supplied in argv, position 0. + **/ +static void cli_set_mode(int argc, char **argv, struct s_hardware *hardware) +{ + cli_mode_t new_mode; + + reset_more_printf(); + if (argc <= 0) { + more_printf("Which mode?\n"); + return; + } + + /* + * Note! argv[0] is a string representing the mode, we need the + * equivalent cli_mode_t to pass it to set_mode. + */ + new_mode = mode_s_to_mode_t(argv[0]); + set_mode(new_mode, hardware); +} + +/** + * do_exit - shared helper to exit a mode + **/ +static void do_exit(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + int new_mode = HDT_MODE; + + switch (hdt_cli.mode) { + case HDT_MODE: + new_mode = EXIT_MODE; + break; + default: + new_mode = HDT_MODE; + break; + } + + dprintf("CLI DEBUG: Switching from mode %d to mode %d\n", hdt_cli.mode, + new_mode); + set_mode(new_mode, hardware); +} + +/** + * show_cli_help - shared helper to show available commands + **/ +static void show_cli_help(int argc __unused, char **argv __unused, + struct s_hardware *hardware __unused) +{ + int j = 0; + struct cli_mode_descr *current_mode; + struct cli_callback_descr *associated_module = NULL; + + find_cli_mode_descr(hdt_cli.mode, ¤t_mode); + + printf("Available commands are:\n"); + + /* List first default modules of the mode */ + if (current_mode->default_modules && current_mode->default_modules->modules) { + while (current_mode->default_modules->modules[j].name) { + printf("%s ", current_mode->default_modules->modules[j].name); + j++; + } + printf("\n"); + } + + /* List secondly the show modules of the mode */ + if (current_mode->show_modules && current_mode->show_modules->modules) { + printf("\nshow commands:\n"); + j = 0; + while (current_mode->show_modules->modules[j].name) { + printf("%s ", current_mode->show_modules->modules[j].name); + j++; + } + printf("\n"); + } + + /* List thirdly the set modules of the mode */ + if (current_mode->set_modules && current_mode->set_modules->modules) { + printf("\nset commands:\n"); + j = 0; + while (current_mode->set_modules->modules[j].name) { + printf("%s ", current_mode->set_modules->modules[j].name); + j++; + } + printf("\n"); + } + + /* List finally the default modules of the hdt mode */ + if (current_mode->mode != hdt_mode.mode && + hdt_mode.default_modules && hdt_mode.default_modules->modules) { + j = 0; + while (hdt_mode.default_modules->modules[j].name) { + /* + * Any default command that is present in hdt mode but + * not in the current mode is available. A default + * command can be redefined in the current mode though. + * This next call test this use case: if it is + * overwritten, do not print it again. + */ + find_cli_callback_descr(hdt_mode.default_modules->modules[j].name, + current_mode->default_modules, + &associated_module); + if (associated_module == NULL) + printf("%s ", hdt_mode.default_modules->modules[j].name); + j++; + } + printf("\n"); + } + + printf("\n"); + main_show_modes(argc, argv, hardware); +} + +/** + * show_cli_help - shared helper to show available commands + **/ +static void goto_menu(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + char version_string[256]; + snprintf(version_string, sizeof version_string, "%s %s (%s)", + PRODUCT_NAME, VERSION, CODENAME); + start_menu_mode(hardware, version_string); + return; +} + +/** + * main_show_summary - give an overview of the system + **/ +void main_show_summary(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + detect_pci(hardware); /* pxe is detected in the pci */ + detect_dmi(hardware); + cpu_detect(hardware); + detect_memory(hardware); + reset_more_printf(); + clear_screen(); + main_show_cpu(argc, argv, hardware); + 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); + more_printf("Memory Size : %lu MB (%lu KB)\n", + (hardware->detected_memory_size + (1 << 9)) >> 10, + hardware->detected_memory_size); + } + main_show_pci(argc, argv, hardware); + + if (hardware->is_pxe_valid) + main_show_pxe(argc, argv, hardware); + + main_show_kernel(argc, argv, hardware); +} + +void main_show_hdt(int argc __unused, char **argv __unused, + struct s_hardware *hardware __unused) +{ + reset_more_printf(); + more_printf("HDT\n"); + more_printf(" Product : %s\n", PRODUCT_NAME); + more_printf(" Version : %s (%s)\n", VERSION, CODENAME); + more_printf(" Website : %s\n", WEBSITE_URL); + more_printf(" Mailing List : %s\n", CONTACT); + more_printf(" Project Leader : %s\n", AUTHOR); + more_printf(" Core Developer : %s\n", CORE_DEVELOPER); + char *contributors[NB_CONTRIBUTORS] = CONTRIBUTORS; + for (int c = 0; c < NB_CONTRIBUTORS; c++) { + more_printf(" Contributor : %s\n", contributors[c]); + } +} + +/** + * do_reboot - reboot the system + **/ +static void do_reboot(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + (void) hardware; + /* Let's call the internal rebooting call */ + syslinux_reboot(1); +} + +/* Default hdt mode */ +struct cli_callback_descr list_hdt_default_modules[] = { + { + .name = CLI_CLEAR, + .exec = cli_clear_screen, + }, + { + .name = CLI_EXIT, + .exec = do_exit, + }, + { + .name = CLI_HELP, + .exec = show_cli_help, + }, + { + .name = CLI_MENU, + .exec = goto_menu, + }, + { + .name = CLI_REBOOT, + .exec = do_reboot, + }, + { + .name = CLI_HISTORY, + .exec = print_history, + }, + { + .name = NULL, + .exec = NULL}, +}; + +struct cli_callback_descr list_hdt_show_modules[] = { + { + .name = CLI_SUMMARY, + .exec = main_show_summary, + }, + { + .name = CLI_PCI, + .exec = main_show_pci, + }, + { + .name = CLI_DMI, + .exec = main_show_dmi, + }, + { + .name = CLI_CPU, + .exec = main_show_cpu, + }, + { + .name = CLI_DISK, + .exec = disks_summary, + }, + { + .name = CLI_PXE, + .exec = main_show_pxe, + }, + { + .name = CLI_SYSLINUX, + .exec = main_show_syslinux, + }, + { + .name = CLI_KERNEL, + .exec = main_show_kernel, + }, + { + .name = CLI_VESA, + .exec = main_show_vesa, + }, + { + .name = CLI_HDT, + .exec = main_show_hdt, + }, + { + .name = CLI_VPD, + .exec = main_show_vpd, + }, + { + .name = CLI_MEMORY, + .exec = show_dmi_memory_modules, + }, + { + .name = "modes", + .exec = main_show_modes, + }, + { + .name = NULL, + .exec = NULL, + }, +}; + +struct cli_callback_descr list_hdt_set_modules[] = { + { + .name = CLI_MODE, + .exec = cli_set_mode, + }, + { + .name = NULL, + .exec = NULL, + }, +}; + +struct cli_module_descr hdt_default_modules = { + .modules = list_hdt_default_modules, +}; + +struct cli_module_descr hdt_show_modules = { + .modules = list_hdt_show_modules, + .default_callback = main_show_summary, +}; + +struct cli_module_descr hdt_set_modules = { + .modules = list_hdt_set_modules, +}; + +struct cli_mode_descr hdt_mode = { + .mode = HDT_MODE, + .name = CLI_HDT, + .default_modules = &hdt_default_modules, + .show_modules = &hdt_show_modules, + .set_modules = &hdt_set_modules, +}; diff --git a/contrib/syslinux-4.02/com32/hdt/hdt-cli-kernel.c b/contrib/syslinux-4.02/com32/hdt/hdt-cli-kernel.c new file mode 100644 index 0000000..f64771b --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-cli-kernel.c @@ -0,0 +1,155 @@ +/* ----------------------------------------------------------------------- * + * + * 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 <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> + +#include "hdt-cli.h" +#include "hdt-common.h" + +void main_show_kernel(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + char buffer[1024] = {0}; + struct pci_device *pci_device; + bool found = false; + char kernel_modules[LINUX_KERNEL_MODULE_SIZE * + MAX_KERNEL_MODULES_PER_PCI_DEVICE]; + + detect_pci(hardware); + reset_more_printf(); + more_printf("Kernel modules\n"); + +// more_printf(" PCI device no: %d \n", p->pci_device_pos); + + if ((hardware->modules_pcimap_return_code == -ENOMODULESPCIMAP) + && (hardware->modules_alias_return_code == -ENOMODULESALIAS)) { + more_printf(" modules.pcimap and modules.alias files are 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("%s", buffer); + } +} + +static void show_kernel_modules(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + 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 modules[MAX_PCI_CLASSES][256] = {{0}}; + char category_name[MAX_PCI_CLASSES][256] = {{0}}; + + detect_pci(hardware); + + 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; + } + + reset_more_printf(); + 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]); + } + } +} + +struct cli_module_descr kernel_show_modules = { + .modules = NULL, + .default_callback = show_kernel_modules, +}; + +struct cli_mode_descr kernel_mode = { + .mode = KERNEL_MODE, + .name = CLI_KERNEL, + .default_modules = NULL, + .show_modules = &kernel_show_modules, + .set_modules = NULL, +}; diff --git a/contrib/syslinux-4.02/com32/hdt/hdt-cli-memory.c b/contrib/syslinux-4.02/com32/hdt/hdt-cli-memory.c new file mode 100644 index 0000000..51d087e --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-cli-memory.c @@ -0,0 +1,134 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer - 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 <memory.h> + +#include "hdt-cli.h" +#include "hdt-common.h" + +static void show_memory_e820(int argc __unused, char **argv __unused, + struct s_hardware *hardware __unused) +{ + struct e820entry map[E820MAX]; + unsigned long memsize = 0; + int count = 0; + char type[14]; + + detect_memory_e820(map, E820MAX, &count); + memsize = memsize_e820(map, count); + reset_more_printf(); + more_printf("Detected RAM : %lu MiB (%lu KiB)\n", + (memsize + (1 << 9)) >> 10, memsize); + more_printf("BIOS-provided physical RAM e820 map:\n"); + for (int i = 0; i < count; i++) { + get_type(map[i].type, type, 14); + more_printf("%016llx - %016llx %016llx (%s)\n", + map[i].addr, map[i].size, map[i].addr + map[i].size, + remove_spaces(type)); + } + struct e820entry nm[E820MAX]; + + /* Clean up, adjust and copy the BIOS-supplied E820-map. */ + int nr = sanitize_e820_map(map, nm, count); + + more_printf("\n"); + more_printf("Sanitized e820 map:\n"); + for (int i = 0; i < nr; i++) { + get_type(nm[i].type, type, 14); + more_printf("%016llx - %016llx %016llx (%s)\n", + nm[i].addr, nm[i].size, nm[i].addr + nm[i].size, + remove_spaces(type)); + } +} + +static void show_memory_e801(int argc __unused, char **argv __unused, + struct s_hardware *hardware __unused) +{ + int mem_low, mem_high = 0; + + reset_more_printf(); + if (detect_memory_e801(&mem_low, &mem_high)) { + more_printf("e801 bogus!\n"); + } else { + more_printf("Detected RAM : %d MiB(%d KiB)\n", + (mem_low >> 10) + (mem_high >> 4), + mem_low + (mem_high << 6)); + more_printf("e801 details : %d Kb (%d MiB) - %d Kb (%d MiB)\n", mem_low, + mem_low >> 10, mem_high << 6, mem_high >> 4); + } +} + +static void show_memory_88(int argc __unused, char **argv __unused, + struct s_hardware *hardware __unused) +{ + int mem_size = 0; + + reset_more_printf(); + if (detect_memory_88(&mem_size)) { + more_printf("8800h bogus!\n"); + } else { + more_printf("8800h memory size: %d Kb (%d MiB)\n", mem_size, + mem_size >> 10); + } +} + +struct cli_callback_descr list_memory_show_modules[] = { + { + .name = "e820", + .exec = show_memory_e820, + }, + { + .name = "e801", + .exec = show_memory_e801, + }, + { + .name = "88", + .exec = show_memory_88, + }, + { + .name = CLI_DMI_MEMORY_BANK, + .exec = show_dmi_memory_bank, + }, + { + .name = NULL, + .exec = NULL, + }, +}; + +struct cli_module_descr memory_show_modules = { + .modules = list_memory_show_modules, + .default_callback = show_dmi_memory_modules, +}; + +struct cli_mode_descr memory_mode = { + .mode = MEMORY_MODE, + .name = CLI_MEMORY, + .default_modules = NULL, + .show_modules = &memory_show_modules, + .set_modules = NULL, +}; diff --git a/contrib/syslinux-4.02/com32/hdt/hdt-cli-pci.c b/contrib/syslinux-4.02/com32/hdt/hdt-cli-pci.c new file mode 100644 index 0000000..e0b7830 --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-cli-pci.c @@ -0,0 +1,318 @@ +/* ----------------------------------------------------------------------- * + * + * 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 <stdlib.h> +#include <string.h> +#include <errno.h> + +#include "hdt-cli.h" +#include "hdt-common.h" + +void main_show_pci(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + cli_detect_pci(hardware); + reset_more_printf(); + more_printf("PCI\n"); + more_printf(" NB Devices : %d\n", hardware->nb_pci_devices); +} + +static void show_pci_device(int argc, char **argv, struct s_hardware *hardware) +{ + int i = 0; + struct pci_device *pci_device = NULL, *temp_pci_device; + int pcidev = -1; + bool nopciids = false; + bool nomodulespcimap = false; + bool nomodulesalias = false; + bool nomodulesfiles = false; + char kernel_modules[LINUX_KERNEL_MODULE_SIZE * + MAX_KERNEL_MODULES_PER_PCI_DEVICE]; + int bus = 0, slot = 0, func = 0; + + reset_more_printf(); + /* Sanitize arguments */ + if (argc <= 0) { + more_printf("show device <number>\n"); + return; + } else + pcidev = strtol(argv[0], (char **)NULL, 10); + + if (errno == ERANGE) { + more_printf("This PCI device number is incorrect\n"); + return; + } + if ((pcidev > hardware->nb_pci_devices) || (pcidev <= 0)) { + more_printf("PCI device %d doesn't exist\n", pcidev); + return; + } + if (hardware->pci_ids_return_code == -ENOPCIIDS) { + nopciids = true; + } + if (hardware->modules_pcimap_return_code == -ENOMODULESPCIMAP) { + nomodulespcimap = true; + } + if (hardware->modules_alias_return_code == -ENOMODULESALIAS) { + nomodulesalias = true; + } + nomodulesfiles = nomodulespcimap && nomodulesalias; + 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) { + more_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); + + more_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 (nomodulesfiles == 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); + if ((pci_device->dev_info->irq > 0) + && (pci_device->dev_info->irq < 255)) + more_printf("IRQ : %0d\n", pci_device->dev_info->irq); + more_printf("Latency : %0d\n", pci_device->dev_info->latency); + more_printf("PCI Bus : %02d\n", bus); + more_printf("PCI Slot : %02d\n", slot); + more_printf("PCI Func : %02d\n", func); + + if (hardware->is_pxe_valid == true) { + if ((hardware->pxe.pci_device != NULL) + && (hardware->pxe.pci_device == pci_device)) { + more_printf("Mac Address : %s\n", hardware->pxe.mac_addr); + more_printf("PXE : Current boot device\n"); + } + } +} + +static void show_pci_devices(int argc __unused, char **argv __unused, + 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; + bool nomodulesalias = false; + bool nomodulesfile = false; + char first_line[81]; + char second_line[81]; + + reset_more_printf(); + 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; + } + if (hardware->modules_pcimap_return_code == -ENOMODULESALIAS) { + nomodulesalias = true; + } + + nomodulesfile = nomodulespcimap && nomodulesalias; + + /* 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 (nomodulesfile == 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("%s", first_line); + more_printf("%s", second_line); + more_printf("\n"); + } else if (nopciids == true) { + if (nomodulesfile == true) { + more_printf("%02d: %04x:%04x [%04x:%04x] \n", + i, pci_device->vendor, + pci_device->product, + pci_device->sub_vendor, pci_device->sub_product); + } 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); + } + } + i++; + } +} + +static void show_pci_irq(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + struct pci_device *pci_device; + bool nopciids = false; + + reset_more_printf(); + more_printf("%d PCI devices detected\n", hardware->nb_pci_devices); + more_printf("IRQ : product\n"); + more_printf("-------------\n"); + + if (hardware->pci_ids_return_code == -ENOPCIIDS) { + nopciids = true; + } + + /* For every detected pci device, compute its submenu */ + for_each_pci_func(pci_device, hardware->pci_domain) { + /* Only display valid IRQs */ + if ((pci_device->dev_info->irq > 0) + && (pci_device->dev_info->irq < 255)) { + if (nopciids == false) { + more_printf("%02d : %s %s \n", + pci_device->dev_info->irq, + pci_device->dev_info->vendor_name, + pci_device->dev_info->product_name); + } else { + more_printf("%02d : %04x:%04x [%04x:%04x] \n", + pci_device->dev_info->irq, + pci_device->vendor, + pci_device->product, + pci_device->sub_vendor, pci_device->sub_product); + } + } + } +} + +struct cli_callback_descr list_pci_show_modules[] = { + { + .name = CLI_IRQ, + .exec = show_pci_irq, + }, + { + .name = CLI_PCI_DEVICE, + .exec = show_pci_device, + }, + { + .name = NULL, + .exec = NULL, + }, +}; + +struct cli_module_descr pci_show_modules = { + .modules = list_pci_show_modules, + .default_callback = show_pci_devices, +}; + +struct cli_mode_descr pci_mode = { + .mode = PCI_MODE, + .name = CLI_PCI, + .default_modules = NULL, + .show_modules = &pci_show_modules, + .set_modules = NULL, +}; + +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) && + (hardware->modules_alias_return_code == -ENOMODULESALIAS)) { + more_printf + ("The modules.pcimap or modules.alias files are missing, device names can't be computed.\n"); + more_printf("Please put one of them in same dir as hdt\n"); + error = true; + } + if (error == true) { + char tempbuf[10]; + more_printf("Press enter to continue\n"); + fgets(tempbuf, sizeof(tempbuf), stdin); + } + } +} diff --git a/contrib/syslinux-4.02/com32/hdt/hdt-cli-pxe.c b/contrib/syslinux-4.02/com32/hdt/hdt-cli-pxe.c new file mode 100644 index 0000000..29e760a --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-cli-pxe.c @@ -0,0 +1,98 @@ +/* ----------------------------------------------------------------------- * + * + * 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 <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <syslinux/pxe.h> +#include <syslinux/config.h> +#include <sys/gpxe.h> + +#include "hdt-cli.h" +#include "hdt-common.h" + +void main_show_pxe(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + char buffer[81]; + memset(buffer, 0, sizeof(81)); + reset_more_printf(); + 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 || (p->pci_device == NULL)) { + 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("%s", buffer); + } else { + snprintf(buffer, sizeof(buffer), " Manufacturer : %s \n", + p->pci_device->dev_info->vendor_name); + more_printf("%s", buffer); + snprintf(buffer, sizeof(buffer), " Product : %s \n", + p->pci_device->dev_info->product_name); + more_printf("%s", 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); + + if (is_gpxe()) + more_printf(" gPXE Detected: Yes\n") + else + more_printf(" gPXE Detected: No\n"); +} + +struct cli_module_descr pxe_show_modules = { + .modules = NULL, + .default_callback = main_show_pxe, +}; + +struct cli_mode_descr pxe_mode = { + .mode = PXE_MODE, + .name = CLI_PXE, + .default_modules = NULL, + .show_modules = &pxe_show_modules, + .set_modules = NULL, +}; diff --git a/contrib/syslinux-4.02/com32/hdt/hdt-cli-syslinux.c b/contrib/syslinux-4.02/com32/hdt/hdt-cli-syslinux.c new file mode 100644 index 0000000..302ca24 --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-cli-syslinux.c @@ -0,0 +1,62 @@ +/* ----------------------------------------------------------------------- * + * + * 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 <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <syslinux/pxe.h> +#include <syslinux/config.h> + +#include "hdt-cli.h" +#include "hdt-common.h" + +void main_show_syslinux(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + reset_more_printf(); + more_printf("SYSLINUX\n"); + more_printf(" Bootloader : %s\n", hardware->syslinux_fs); + more_printf(" Version : %s\n", hardware->sv->version_string); + 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); +} + +struct cli_module_descr syslinux_show_modules = { + .modules = NULL, + .default_callback = main_show_syslinux, +}; + +struct cli_mode_descr syslinux_mode = { + .mode = SYSLINUX_MODE, + .name = CLI_SYSLINUX, + .default_modules = NULL, + .show_modules = &syslinux_show_modules, + .set_modules = NULL, +}; diff --git a/contrib/syslinux-4.02/com32/hdt/hdt-cli-vesa.c b/contrib/syslinux-4.02/com32/hdt/hdt-cli-vesa.c new file mode 100644 index 0000000..a4a80fa --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-cli-vesa.c @@ -0,0 +1,142 @@ +/* ----------------------------------------------------------------------- * + * + * 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_vesa(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + reset_more_printf(); + detect_vesa(hardware); + if (hardware->is_vesa_valid == false) { + more_printf("No VESA BIOS detected\n"); + return; + } + more_printf("VESA\n"); + more_printf(" Vesa version : %d.%d\n", hardware->vesa.major_version, + hardware->vesa.minor_version); + more_printf(" Vendor : %s\n", hardware->vesa.vendor); + more_printf(" Product : %s\n", hardware->vesa.product); + more_printf(" Product rev. : %s\n", hardware->vesa.product_revision); + more_printf(" Software rev.: %d\n", hardware->vesa.software_rev); + more_printf(" Memory (KB) : %d\n", hardware->vesa.total_memory * 64); + more_printf(" Modes : %d\n", hardware->vesa.vmi_count); +} + +static void show_vesa_modes(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + detect_vesa(hardware); + reset_more_printf(); + if (hardware->is_vesa_valid == false) { + more_printf("No VESA BIOS detected\n"); + return; + } + more_printf(" ResH. x ResV x Bits : vga= : Vesa Mode\n"); + more_printf("----------------------------------------\n"); + + for (int i = 0; i < hardware->vesa.vmi_count; i++) { + struct vesa_mode_info *mi = &hardware->vesa.vmi[i].mi; + /* + * Sometimes, vesa bios reports 0x0 modes. + * We don't need to display that ones. + */ + if ((mi->h_res == 0) || (mi->v_res == 0)) + continue; + more_printf("%5u %5u %3u %3d 0x%04x\n", + mi->h_res, mi->v_res, mi->bpp, + hardware->vesa.vmi[i].mode + 0x200, + hardware->vesa.vmi[i].mode); + } +} + +static void enable_vesa(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + vesamode = true; + max_console_lines = MAX_VESA_CLI_LINES; + init_console(hardware); +} + +static void disable_vesa(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + vesamode = false; + max_console_lines = MAX_CLI_LINES; + init_console(hardware); +} + +struct cli_callback_descr list_vesa_show_modules[] = { + { + .name = CLI_MODES, + .exec = show_vesa_modes, + }, + { + .name = NULL, + .exec = NULL, + }, +}; + +struct cli_callback_descr list_vesa_commands[] = { + { + .name = CLI_ENABLE, + .exec = enable_vesa, + }, + { + .name = CLI_DISABLE, + .exec = disable_vesa, + }, + + { + .name = NULL, + .exec = NULL, + }, +}; + +struct cli_module_descr vesa_show_modules = { + .modules = list_vesa_show_modules, + .default_callback = main_show_vesa, +}; + +struct cli_module_descr vesa_commands = { + .modules = list_vesa_commands, + .default_callback = enable_vesa, +}; + +struct cli_mode_descr vesa_mode = { + .mode = VESA_MODE, + .name = CLI_VESA, + .default_modules = &vesa_commands, + .show_modules = &vesa_show_modules, + .set_modules = NULL, +}; diff --git a/contrib/syslinux-4.02/com32/hdt/hdt-cli-vpd.c b/contrib/syslinux-4.02/com32/hdt/hdt-cli-vpd.c new file mode 100644 index 0000000..c2f1c4e --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-cli-vpd.c @@ -0,0 +1,81 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer - 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 <vpd/vpd.h> + +#include "hdt-cli.h" +#include "hdt-common.h" + +void main_show_vpd(int argc __unused, char **argv __unused, + struct s_hardware *hardware) +{ + reset_more_printf(); + detect_vpd(hardware); + + if (!hardware->is_vpd_valid) { + more_printf("No VPD structure detected.\n"); + return; + } + + more_printf("VPD present at address : %s\n", hardware->vpd.base_address); + if (strlen(hardware->vpd.bios_build_id) > 0) + more_printf("Bios Build ID : %s\n", + hardware->vpd.bios_build_id); + if (strlen(hardware->vpd.bios_release_date) > 0) + more_printf("Bios Release Date : %s\n", + hardware->vpd.bios_release_date); + if (strlen(hardware->vpd.bios_version) > 0) + more_printf("Bios Version : %s\n", + hardware->vpd.bios_version); + if (strlen(hardware->vpd.default_flash_filename) > 0) + more_printf("Default Flash Filename : %s\n", + hardware->vpd.default_flash_filename); + if (strlen(hardware->vpd.box_serial_number) > 0) + more_printf("Box Serial Number : %s\n", + hardware->vpd.box_serial_number); + if (strlen(hardware->vpd.motherboard_serial_number) > 0) + more_printf("Motherboard Serial Number : %s\n", + hardware->vpd.motherboard_serial_number); + if (strlen(hardware->vpd.machine_type_model) > 0) + more_printf("Machine Type/Model : %s\n", + hardware->vpd.machine_type_model); +} + +struct cli_module_descr vpd_show_modules = { + .modules = NULL, + .default_callback = main_show_vpd, +}; + +struct cli_mode_descr vpd_mode = { + .mode = VPD_MODE, + .name = CLI_VPD, + .default_modules = NULL, + .show_modules = &vpd_show_modules, + .set_modules = NULL, +}; diff --git a/contrib/syslinux-4.02/com32/hdt/hdt-cli.c b/contrib/syslinux-4.02/com32/hdt/hdt-cli.c new file mode 100644 index 0000000..639bcdb --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-cli.c @@ -0,0 +1,1121 @@ +/* ----------------------------------------------------------------------- * + * + * 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 <stdlib.h> +#include <string.h> +#include <syslinux/config.h> +#include <getkey.h> +#include "hdt-cli.h" +#include "hdt-common.h" + +struct cli_mode_descr *list_modes[] = { + &hdt_mode, + &dmi_mode, + &syslinux_mode, + &pxe_mode, + &kernel_mode, + &cpu_mode, + &pci_mode, + &vesa_mode, + &disk_mode, + &vpd_mode, + &memory_mode, + NULL, +}; + +/* + * .aliases = {"q", "quit"} won't work since it is an array of pointers, not an + * array of variables. There is no easy way around it besides declaring the arrays of + * strings first. + */ +const char *exit_aliases[] = { "q", "quit" }; +const char *help_aliases[] = { "h", "?" }; + +/* List of aliases */ +struct cli_alias hdt_aliases[] = { + { + .command = CLI_EXIT, + .nb_aliases = 2, + .aliases = exit_aliases, + }, + { + .command = CLI_HELP, + .nb_aliases = 2, + .aliases = help_aliases, + }, +}; + +struct cli_mode_descr *current_mode; +int autocomplete_backlog; + +struct autocomplete_list { + char autocomplete_token[MAX_LINE_SIZE]; + struct autocomplete_list *next; +}; +struct autocomplete_list *autocomplete_head = NULL; +struct autocomplete_list *autocomplete_tail = NULL; +struct autocomplete_list *autocomplete_last_seen = NULL; + +static void autocomplete_add_token_to_list(const char *token) +{ + struct autocomplete_list *new = malloc(sizeof(struct autocomplete_list)); + + strlcpy(new->autocomplete_token, token, sizeof(new->autocomplete_token)); + new->next = NULL; + autocomplete_backlog++; + + if (autocomplete_tail != NULL) + autocomplete_tail->next = new; + if (autocomplete_head == NULL) + autocomplete_head = new; + autocomplete_tail = new; +} + +static void autocomplete_destroy_list(void) +{ + struct autocomplete_list *tmp = NULL; + + while (autocomplete_head != NULL) { + tmp = autocomplete_head->next; + free(autocomplete_head); + autocomplete_head = tmp; + } + autocomplete_backlog = 0; + autocomplete_tail = NULL; + autocomplete_last_seen = NULL; +} + +/** + * set_mode - set the current mode of the cli + * @mode: mode to set + * + * Unlike cli_set_mode, this function is not used by the cli directly. + **/ +void set_mode(cli_mode_t mode, struct s_hardware *hardware) +{ + int i = 0; + + switch (mode) { + case EXIT_MODE: + hdt_cli.mode = mode; + break; + case HDT_MODE: + hdt_cli.mode = mode; + snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ", CLI_HDT); + break; + case PXE_MODE: + if (hardware->sv->filesystem != SYSLINUX_FS_PXELINUX) { + printf("You are not currently using PXELINUX\n"); + break; + } + hdt_cli.mode = mode; + snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ", CLI_PXE); + break; + case KERNEL_MODE: + detect_pci(hardware); + hdt_cli.mode = mode; + snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ", CLI_KERNEL); + break; + case SYSLINUX_MODE: + hdt_cli.mode = mode; + snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ", CLI_SYSLINUX); + break; + case VESA_MODE: + hdt_cli.mode = mode; + snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ", CLI_VESA); + break; + case PCI_MODE: + hdt_cli.mode = mode; + snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ", CLI_PCI); + if (!hardware->pci_detection) + cli_detect_pci(hardware); + break; + case CPU_MODE: + hdt_cli.mode = mode; + snprintf(hdt_cli.prompt, sizeof(hdt_cli.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; + } + hdt_cli.mode = mode; + snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ", CLI_DMI); + break; + case DISK_MODE: + detect_disks(hardware); + hdt_cli.mode = mode; + snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ", CLI_DISK); + break; + case VPD_MODE: + detect_vpd(hardware); + if (!hardware->is_vpd_valid) { + printf("No valid VPD table found, exiting.\n"); + break; + } + hdt_cli.mode = mode; + snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ", CLI_VPD); + break; + case MEMORY_MODE: + hdt_cli.mode = mode; + snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ", CLI_MEMORY); + break; + default: + /* Invalid mode */ + printf("Unknown mode, please choose among:\n"); + while (list_modes[i]) { + printf("\t%s\n", list_modes[i]->name); + i++; + } + } + + find_cli_mode_descr(hdt_cli.mode, ¤t_mode); + /* There is not cli_mode_descr struct for the exit mode */ + if (current_mode == NULL && hdt_cli.mode != EXIT_MODE) { + /* Shouldn't get here... */ + printf("!!! BUG: Mode '%d' unknown.\n", hdt_cli.mode); + } +} + +/** + * mode_s_to_mode_t - given a mode string, return the cli_mode_t representation + **/ +cli_mode_t mode_s_to_mode_t(char *name) +{ + int i = 0; + + while (list_modes[i]) { + if (!strncmp(name, list_modes[i]->name, sizeof(list_modes[i]->name))) + break; + i++; + } + + if (!list_modes[i]) + return INVALID_MODE; + else + return list_modes[i]->mode; +} + +/** + * find_cli_mode_descr - find the cli_mode_descr struct associated to a mode + * @mode: mode to look for + * @mode_found: store the mode if found, NULL otherwise + * + * Given a mode name, return a pointer to the associated cli_mode_descr + * structure. + * Note: the current mode name is stored in hdt_cli.mode. + **/ +void find_cli_mode_descr(cli_mode_t mode, struct cli_mode_descr **mode_found) +{ + int i = 0; + + while (list_modes[i] && list_modes[i]->mode != mode) + i++; + + /* Shouldn't get here... */ + if (!list_modes[i]) + *mode_found = NULL; + else + *mode_found = list_modes[i]; +} + +/** + * expand_aliases - resolve aliases mapping + * @line: command line to parse + * @command: first token in the line + * @module: second token in the line + * @argc: number of arguments + * @argv: array of arguments + * + * We maintain a small list of static alises to enhance user experience. + * Only commands can be aliased (first token). Otherwise it can become really hairy... + **/ +static void expand_aliases(char *line __unused, char **command, char **module, + int *argc, char **argv) +{ + struct cli_mode_descr *mode; + int i, j; + + find_cli_mode_descr(mode_s_to_mode_t(*command), &mode); + if (mode != NULL && *module == NULL) { + /* + * The user specified a mode instead of `set mode...', e.g. + * `dmi' instead of `set mode dmi' + */ + + /* *argv is NULL since *module is NULL */ + *argc = 1; + *argv = malloc(*argc * sizeof(char *)); + argv[0] = malloc((sizeof(*command) + 1) * sizeof(char)); + strlcpy(argv[0], *command, sizeof(*command) + 1); + dprintf("CLI DEBUG: ALIAS %s ", *command); + + strlcpy(*command, CLI_SET, sizeof(CLI_SET)); /* set */ + + *module = malloc(sizeof(CLI_MODE) * sizeof(char)); + strlcpy(*module, CLI_MODE, sizeof(CLI_MODE)); /* mode */ + + dprintf("--> %s %s %s\n", *command, *module, argv[0]); + goto out; + } + + /* Simple aliases mapping a single command to another one */ + for (i = 0; i < MAX_ALIASES; i++) { + for (j = 0; j < hdt_aliases[i].nb_aliases; j++) { + if (!strncmp(*command, hdt_aliases[i].aliases[j], + sizeof(hdt_aliases[i].aliases[j]))) { + dprintf("CLI DEBUG: ALIAS %s ", *command); + strlcpy(*command, hdt_aliases[i].command, + sizeof(hdt_aliases[i].command) + 1); + dprintf("--> %s\n", *command); + goto out; /* Don't allow chaining aliases */ + } + } + } + return; + +out: + dprintf("CLI DEBUG: New parameters:\n"); + dprintf("CLI DEBUG: command = %s\n", *command); + dprintf("CLI DEBUG: module = %s\n", *module); + dprintf("CLI DEBUG: argc = %d\n", *argc); + for (i = 0; i < *argc; i++) + dprintf("CLI DEBUG: argv[%d] = %s\n", i, argv[0]); + return; +} + +/** + * parse_command_line - low level parser for the command line + * @line: command line to parse + * @command: first token in the line + * @module: second token in the line + * @argc: number of arguments + * @argv: array of arguments + * + * The format of the command line is: + * <main command> [<module on which to operate> [<args>]] + * command is always malloc'ed (even for an empty line) + **/ +static void parse_command_line(char *line, char **command, char **module, + int *argc, char **argv) +{ + int argc_iter = 0, args_pos = 0, token_found = 0, token_len = 0; + int args_len = 0; + char *pch = NULL, *pch_next = NULL, *tmp_pch_next = NULL; + + *command = NULL; + *module = NULL; + *argc = 0; + + pch = line; + while (pch != NULL) { + pch_next = strchr(pch + 1, ' '); + tmp_pch_next = pch_next; + + /* + * Skip whitespaces if the user entered + * 'set mode foo' for 'set mode foo' + * ^ ^ + * |___|___ pch + * |___ pch_next <- wrong! + * + * We still keep the position into tmp_pch_next to compute + * the lenght of the current token. + */ + while (pch_next != NULL && !strncmp(pch_next, CLI_SPACE, 1)) + pch_next++; + + /* End of line guaranteed to be zeroed */ + if (pch_next == NULL) { + token_len = (int)(strchr(pch + 1, '\0') - pch); + args_len = token_len; + } else { + token_len = (int)(tmp_pch_next - pch); + args_len = (int)(pch_next - pch); + } + + if (token_found == 0) { + /* Main command to execute */ + *command = malloc((token_len + 1) * sizeof(char)); + strlcpy(*command, pch, token_len); + (*command)[token_len] = '\0'; + dprintf("CLI DEBUG: command = %s\n", *command); + args_pos += args_len; + } else if (token_found == 1) { + /* Module */ + *module = malloc((token_len + 1) * sizeof(char)); + strlcpy(*module, pch, token_len); + (*module)[token_len] = '\0'; + dprintf("CLI DEBUG: module = %s\n", *module); + args_pos += args_len; + } else + (*argc)++; + + token_found++; + pch = pch_next; + } + dprintf("CLI DEBUG: argc = %d\n", *argc); + + /* Skip arguments handling if none is supplied */ + if (!*argc) + return; + + /* Transform the arguments string into an array */ + *argv = malloc(*argc * sizeof(char *)); + pch = strtok(line + args_pos, CLI_SPACE); + while (pch != NULL) { + dprintf("CLI DEBUG: argv[%d] = %s\n", argc_iter, pch); + argv[argc_iter] = malloc(sizeof(pch) * sizeof(char)); + strlcpy(argv[argc_iter], pch, sizeof(pch)); + argc_iter++; + pch = strtok(NULL, CLI_SPACE); + /* + * strtok(NULL, CLI_SPACE) over a stream of spaces + * will return an empty string + */ + while (pch != NULL && !strncmp(pch, "", 1)) + pch = strtok(NULL, CLI_SPACE); + } +} + +/** + * find_cli_callback_descr - find a callback in a list of modules + * @module_name: Name of the module to find + * @modules_list: Lits of modules among which to find @module_name + * @module_found: Pointer to the matched module, NULL if not found + * + * Given a module name and a list of possible modules, find the corresponding + * module structure that matches the module name and store it in @module_found. + **/ +void find_cli_callback_descr(const char *module_name, + struct cli_module_descr *modules_list, + struct cli_callback_descr **module_found) +{ + int modules_iter = 0; + + if (modules_list == NULL) + goto not_found; + + /* Find the callback to execute */ + while (modules_list->modules[modules_iter].name && + strcmp(module_name, modules_list->modules[modules_iter].name) != 0) + modules_iter++; + + if (modules_list->modules[modules_iter].name) { + *module_found = &(modules_list->modules[modules_iter]); + dprintf("CLI DEBUG: module %s found\n", (*module_found)->name); + return; + } + +not_found: + *module_found = NULL; + return; +} + +/** + * autocomplete_command - print matching commands + * @command: Beginning of the command + * + * Given a string @command, print all availables commands starting with + * @command. Commands are found within the list of commands for the current + * mode and the hdt mode (if the current mode is not hdt). + **/ +static void autocomplete_command(char *command) +{ + int j = 0; + struct cli_callback_descr *associated_module = NULL; + + /* First take care of the two special commands: 'show' and 'set' */ + if (strncmp(CLI_SHOW, command, strlen(command)) == 0) { + printf("%s\n", CLI_SHOW); + autocomplete_add_token_to_list(CLI_SHOW); + } + if (strncmp(CLI_SET, command, strlen(command)) == 0) { + printf("%s\n", CLI_SET); + autocomplete_add_token_to_list(CLI_SET); + } + + /* + * Then, go through the modes for the special case + * '<mode>' -> 'set mode <mode>' + */ + while (list_modes[j]) { + if (strncmp(list_modes[j]->name, command, strlen(command)) == 0) { + printf("%s\n", list_modes[j]->name); + autocomplete_add_token_to_list(list_modes[j]->name); + } + j++; + } + + /* + * Let's go now through the list of default_modules for the current mode + * (single token commands for the current_mode) + */ + j = 0; + if (current_mode->default_modules && current_mode->default_modules->modules) { + while (current_mode->default_modules->modules[j].name) { + if (strncmp(current_mode->default_modules->modules[j].name, + command, strlen(command)) == 0) { + printf("%s\n", current_mode->default_modules->modules[j].name); + autocomplete_add_token_to_list(current_mode->default_modules-> + modules[j].name); + } + j++; + } + } + + /* + * Finally, if the current_mode is not hdt, list the available + * default_modules of hdt (these are always available from any mode). + */ + if (current_mode->mode == HDT_MODE) + return; + + if (!hdt_mode.default_modules || !hdt_mode.default_modules->modules) + return; + + j = 0; + while (hdt_mode.default_modules && + hdt_mode.default_modules->modules[j].name) { + /* + * Any default command that is present in hdt mode but + * not in the current mode is available. A default + * command can be redefined in the current mode though. + * This next call tests this use case: if it is + * overwritten, do not print it again. + */ + find_cli_callback_descr(hdt_mode.default_modules->modules[j].name, + current_mode->default_modules, + &associated_module); + if (associated_module == NULL && + strncmp(command, + hdt_mode.default_modules->modules[j].name, + strlen(command)) == 0) { + printf("%s\n", hdt_mode.default_modules->modules[j].name); + autocomplete_add_token_to_list(hdt_mode.default_modules->modules[j]. + name); + } + j++; + } +} + +/** + * autocomplete_module - print matching modules + * @command: Command on the command line (not NULL) + * @module: Beginning of the module + * + * Given a command @command and a string @module, print all availables modules + * starting with @module for command @command. Commands are found within the + * list of commands for the current mode and the hdt mode (if the current mode + * is not hdt). + **/ +static void autocomplete_module(char *command, char *module) +{ + int j = 0; + char autocomplete_full_line[MAX_LINE_SIZE]; + + if (strncmp(CLI_SHOW, command, strlen(command)) == 0) { + if (!current_mode->show_modules || !current_mode->show_modules->modules) + return; + + while (current_mode->show_modules->modules[j].name) { + if (strncmp(current_mode->show_modules->modules[j].name, + module, strlen(module)) == 0) { + printf("%s\n", current_mode->show_modules->modules[j].name); + sprintf(autocomplete_full_line, "%s %s", + CLI_SHOW, current_mode->show_modules->modules[j].name); + autocomplete_add_token_to_list(autocomplete_full_line); + } + j++; + } + } else if (strncmp(CLI_SET, command, strlen(command)) == 0) { + j = 0; + if (!current_mode->set_modules || !current_mode->set_modules->modules) + return; + + while (current_mode->set_modules->modules[j].name) { + if (strncmp(current_mode->set_modules->modules[j].name, + module, strlen(module)) == 0) { + printf("%s\n", current_mode->set_modules->modules[j].name); + sprintf(autocomplete_full_line, "%s %s", + CLI_SET, current_mode->set_modules->modules[j].name); + autocomplete_add_token_to_list(autocomplete_full_line); + } + j++; + } + } +} + +/** + * autocomplete - find possible matches for a command line + * @line: command line to parse + **/ +static void autocomplete(char *line) +{ + int i; + int argc = 0; + char *command = NULL, *module = NULL; + char **argv = NULL; + + parse_command_line(line, &command, &module, &argc, argv); + + /* If the user specified arguments, there is nothing we can complete */ + if (argc != 0) + goto out; + + /* No argument, (the start of) a module has been specified */ + if (module != NULL) { + autocomplete_module(command, module); + free(module); + goto out; + } + + /* No argument, no module, (the start of) a command has been specified */ + if (command != NULL) { + autocomplete_command(command); + free(command); + goto out; + } + +out: + /* Let's not forget to clean ourselves */ + for (i = 0; i < argc; i++) + free(argv[i]); + if (argc > 0) + free(argv); + return; +} + +/** + * exec_command - main logic to map the command line to callbacks + **/ +static void exec_command(char *line, struct s_hardware *hardware) +{ + int argc, i = 0; + char *command = NULL, *module = NULL; + char **argv = NULL; + struct cli_callback_descr *current_module = NULL; + + /* This will allocate memory for command and module */ + parse_command_line(line, &command, &module, &argc, argv); + + /* + * Expand shortcuts, if needed + * This will allocate memory for argc/argv + */ + expand_aliases(line, &command, &module, &argc, argv); + + if (module == NULL) { + dprintf("CLI DEBUG: single command detected\n"); + /* + * A single word was specified: look at the list of default + * commands in the current mode to see if there is a match. + * If not, it may be a generic function (exit, help, ...). These + * are stored in the list of default commands of the hdt mode. + */ + find_cli_callback_descr(command, current_mode->default_modules, + ¤t_module); + if (current_module != NULL) + current_module->exec(argc, argv, hardware); + else if (!strncmp(command, CLI_SHOW, sizeof(CLI_SHOW) - 1) && + current_mode->show_modules != NULL && + current_mode->show_modules->default_callback != NULL) + current_mode->show_modules->default_callback(argc, argv, hardware); + else if (!strncmp(command, CLI_SET, sizeof(CLI_SET) - 1) && + current_mode->set_modules != NULL && + current_mode->set_modules->default_callback != NULL) + current_mode->set_modules->default_callback(argc, argv, hardware); + else { + find_cli_callback_descr(command, hdt_mode.default_modules, + ¤t_module); + if (current_module != NULL) + current_module->exec(argc, argv, hardware); + else + printf("unknown command: '%s'\n", command); + } + } else { + /* + * A module has been specified! We now need to find the type of command. + * + * The syntax of the cli is the following: + * <type of command> <module on which to operate> <args> + * e.g. + * dmi> show system + * dmi> show bank 1 + * dmi> show memory 0 1 + * pci> show device 12 + * hdt> set mode dmi + */ + if (!strncmp(command, CLI_SHOW, sizeof(CLI_SHOW) - 1)) { + dprintf("CLI DEBUG: %s command detected\n", CLI_SHOW); + /* Look first for a 'show' callback in the current mode */ + find_cli_callback_descr(module, current_mode->show_modules, + ¤t_module); + /* Execute the callback, if found */ + if (current_module != NULL) + current_module->exec(argc, argv, hardware); + else { + /* Look now for a 'show' callback in the hdt mode */ + find_cli_callback_descr(module, hdt_mode.show_modules, + ¤t_module); + /* Execute the callback, if found */ + if (current_module != NULL) + current_module->exec(argc, argv, hardware); + else + printf("unknown module: '%s'\n", module); + } + } else if (!strncmp(command, CLI_SET, sizeof(CLI_SET) - 1)) { + dprintf("CLI DEBUG: %s command detected\n", CLI_SET); + /* Look now for a 'set' callback in the hdt mode */ + find_cli_callback_descr(module, current_mode->set_modules, + ¤t_module); + /* Execute the callback, if found */ + if (current_module != NULL) + current_module->exec(argc, argv, hardware); + else { + /* Look now for a 'set' callback in the hdt mode */ + find_cli_callback_descr(module, hdt_mode.set_modules, + ¤t_module); + /* Execute the callback, if found */ + if (current_module != NULL) + current_module->exec(argc, argv, hardware); + else + printf("unknown module: '%s'\n", module); + } + } + } + + /* Let's not forget to clean ourselves */ + if (command != NULL) + free(command); + if (module != NULL) + free(module); + for (i = 0; i < argc; i++) + free(argv[i]); + if (argc > 0) + free(argv); +} + +static void reset_prompt(void) +{ + /* No need to display the prompt if we exit */ + if (hdt_cli.mode != EXIT_MODE) { + printf("%s", hdt_cli.prompt); + /* Reset the line */ + hdt_cli.cursor_pos = 0; + } +} + +void start_auto_mode(struct s_hardware *hardware) +{ + char *mypch; + int nb_commands = 0; + char *commands[MAX_NB_AUTO_COMMANDS]; + + if (!quiet) + more_printf("\nEntering Auto mode\n"); + + /* Protecting the auto_label from the strtok modifications */ + char *temp = strdup(hardware->auto_label); + + /* Searching & saving all commands */ + mypch = strtok(temp, AUTO_SEPARATOR); + while (mypch != NULL) { + if ((strlen(remove_spaces(mypch)) > 0) && + (remove_spaces(mypch)[0] != AUTO_SEPARATOR[0])) { + nb_commands++; + if ((commands[nb_commands] = malloc(AUTO_COMMAND_SIZE)) != NULL) { + sprintf(commands[nb_commands], "%s", remove_spaces(mypch)); + } else + nb_commands--; + } + mypch = strtok(NULL, AUTO_SEPARATOR); + } + + /* Executing found commands */ + for (int i = 1; i <= nb_commands; i++) { + if (commands[i]) { + if (!quiet) + more_printf("%s%s\n", hdt_cli.prompt, commands[i]); + exec_command(commands[i], hardware); + free(commands[i]); + } + } + + if (!quiet) + more_printf("\nExiting Auto mode\n"); + + more_printf("\n"); +} + +void print_history(int argc, char **argv, struct s_hardware * hardware) +{ + (void)argc; + (void)argv; + (void)hardware; + + reset_more_printf(); + for (int i = 1; i <= MAX_HISTORY_SIZE; i++) { + if (i == hdt_cli.history_pos) { + more_printf("*%d:'%s'\n", i, hdt_cli.history[i]); + continue; + } + if (strlen(hdt_cli.history[i]) == 0) + continue; + more_printf(" %d:'%s'\n", i, hdt_cli.history[i]); + } +} + +/* Code that manages the cli mode */ +void start_cli_mode(struct s_hardware *hardware) +{ + int current_key = 0; + int future_history_pos = 1; /* position of the next position in the history */ + int current_future_history_pos = 1; /* Temp variable */ + bool display_history = true; /* Temp Variable */ + char temp_command[MAX_LINE_SIZE]; + + hdt_cli.cursor_pos = 0; + memset(hdt_cli.history, 0, sizeof(hdt_cli.history)); + hdt_cli.history_pos = 1; + hdt_cli.max_history_pos = 1; + + /* Find the mode selected */ + set_mode(HDT_MODE, hardware); + find_cli_mode_descr(hdt_cli.mode, ¤t_mode); + if (current_mode == NULL) { + /* Shouldn't get here... */ + printf("!!! BUG: Mode '%d' unknown.\n", hdt_cli.mode); + return; + } + + /* Start the auto mode if the command line is set */ + if (strlen(hardware->auto_label) > 0) { + start_auto_mode(hardware); + } + + printf("Entering CLI mode\n"); + + reset_prompt(); + + while (hdt_cli.mode != EXIT_MODE) { + + /* Display the cursor */ + display_cursor(true); + + /* Let's put the cursor blinking until we get an input */ + set_cursor_blink(true); + + /* We wait endlessly for a keyboard input */ + current_key = get_key(stdin, 0); + + /* We have to cancel the blinking mode to prevent + * input text to blink */ + set_cursor_blink(false); + + /* Reset autocomplete buffer unless TAB is pressed */ + if (current_key != KEY_TAB) + autocomplete_destroy_list(); + + switch (current_key) { + /* clear until then end of line */ + case KEY_CTRL('k'): + /* Clear the end of the line */ + clear_end_of_line(); + memset(&INPUT[hdt_cli.cursor_pos], 0, + strlen(INPUT) - hdt_cli.cursor_pos); + break; + + case KEY_CTRL('c'): + printf("\n"); + reset_prompt(); + break; + + case KEY_LEFT: + if (hdt_cli.cursor_pos > 0) { + move_cursor_left(1); + hdt_cli.cursor_pos--; + } + break; + + case KEY_RIGHT: + if (hdt_cli.cursor_pos < (int)strlen(INPUT)) { + move_cursor_right(1); + hdt_cli.cursor_pos++; + } + break; + + case KEY_CTRL('e'): + case KEY_END: + /* Calling with a 0 value will make the cursor move */ + /* So, let's move the cursor only if needed */ + if ((strlen(INPUT) - hdt_cli.cursor_pos) > 0) { + /* Return to the begining of line */ + move_cursor_right(strlen(INPUT) - hdt_cli.cursor_pos); + hdt_cli.cursor_pos = strlen(INPUT); + } + break; + + case KEY_CTRL('a'): + case KEY_HOME: + /* Calling with a 0 value will make the cursor move */ + /* So, let's move the cursor only if needed */ + if (hdt_cli.cursor_pos > 0) { + /* Return to the begining of line */ + move_cursor_left(hdt_cli.cursor_pos); + hdt_cli.cursor_pos = 0; + } + break; + + case KEY_UP: + + /* Saving future position */ + current_future_history_pos = future_history_pos; + + /* We have to compute the next position */ + if (future_history_pos == 1) { + future_history_pos = MAX_HISTORY_SIZE; + } else { + future_history_pos--; + } + + /* Does the next position is valid */ + if (strlen(hdt_cli.history[future_history_pos]) == 0) { + /* Position is invalid, restoring position */ + future_history_pos = current_future_history_pos; + break; + } + + /* Let's make that future position the one we use */ + memset(INPUT, 0, sizeof(INPUT)); + strlcpy(INPUT, hdt_cli.history[future_history_pos], sizeof(INPUT)); + + /* Clear the line */ + clear_line(); + + /* Move to the begining of line */ + move_cursor_to_column(0); + + reset_prompt(); + printf("%s", INPUT); + hdt_cli.cursor_pos = strlen(INPUT); + break; + + case KEY_DOWN: + display_history = true; + + /* Saving future position */ + current_future_history_pos = future_history_pos; + + if (future_history_pos == MAX_HISTORY_SIZE) { + future_history_pos = 1; + } else { + future_history_pos++; + } + + /* Does the next position is valid */ + if (strlen(hdt_cli.history[future_history_pos]) == 0) + display_history = false; + + /* An exception is made to reach the last empty line */ + if (future_history_pos == hdt_cli.max_history_pos) + display_history = true; + + if (display_history == false) { + /* Position is invalid, restoring position */ + future_history_pos = current_future_history_pos; + break; + } + + /* Let's make that future position the one we use */ + memset(INPUT, 0, sizeof(INPUT)); + strlcpy(INPUT, hdt_cli.history[future_history_pos], sizeof(INPUT)); + + /* Clear the line */ + clear_line(); + + /* Move to the begining of line */ + move_cursor_to_column(0); + + reset_prompt(); + printf("%s", INPUT); + hdt_cli.cursor_pos = strlen(INPUT); + break; + + case KEY_TAB: + if (autocomplete_backlog) { + clear_line(); + /* Move to the begining of line */ + move_cursor_to_column(0); + reset_prompt(); + printf("%s", autocomplete_last_seen->autocomplete_token); + strlcpy(INPUT, + autocomplete_last_seen->autocomplete_token, + sizeof(INPUT)); + hdt_cli.cursor_pos = strlen(INPUT); + + /* Cycle through the list */ + autocomplete_last_seen = autocomplete_last_seen->next; + if (autocomplete_last_seen == NULL) + autocomplete_last_seen = autocomplete_head; + } else { + printf("\n"); + autocomplete(skip_spaces(INPUT)); + autocomplete_last_seen = autocomplete_head; + + printf("%s%s", hdt_cli.prompt, INPUT); + } + break; + + case KEY_ENTER: + printf("\n"); + if (strlen(remove_spaces(INPUT)) < 1) { + reset_prompt(); + break; + } + exec_command(remove_spaces(INPUT), hardware); + hdt_cli.history_pos++; + + /* Did we reach the end of the history ?*/ + if (hdt_cli.history_pos > MAX_HISTORY_SIZE) { + /* Let's return at the beginning */ + hdt_cli.history_pos = 1; + } + + /* Does the next position is already used ? + * If yes, we are cycling in history */ + if (strlen(INPUT) > 0) { + /* Let's clean that entry */ + memset(&INPUT,0,sizeof(INPUT)); + } + + future_history_pos = hdt_cli.history_pos; + if (hdt_cli.history_pos > hdt_cli.max_history_pos) + hdt_cli.max_history_pos = hdt_cli.history_pos; + reset_prompt(); + break; + + case KEY_CTRL('d'): + case KEY_DELETE: + /* No need to delete when input is empty */ + if (strlen(INPUT) == 0) + break; + /* Don't delete when cursor is at the end of the line */ + if (hdt_cli.cursor_pos >= strlen(INPUT)) + break; + + for (int c = hdt_cli.cursor_pos; c < (int)strlen(INPUT) - 1; c++) + INPUT[c] = INPUT[c + 1]; + INPUT[strlen(INPUT) - 1] = '\0'; + + /* Clear the end of the line */ + clear_end_of_line(); + + /* Print the resulting buffer */ + printf("%s", INPUT + hdt_cli.cursor_pos); + + /* Replace the cursor at the proper place */ + if (strlen(INPUT + hdt_cli.cursor_pos) > 0) + move_cursor_left(strlen(INPUT + hdt_cli.cursor_pos)); + break; + + case KEY_DEL: + case KEY_BACKSPACE: + /* Don't delete prompt */ + if (hdt_cli.cursor_pos == 0) + break; + + for (int c = hdt_cli.cursor_pos - 1; + c < (int)strlen(INPUT) - 1; c++) + INPUT[c] = INPUT[c + 1]; + INPUT[strlen(INPUT) - 1] = '\0'; + + /* Get one char back */ + move_cursor_left(1); + + /* Clear the end of the line */ + clear_end_of_line(); + + /* Print the resulting buffer */ + printf("%s", INPUT + hdt_cli.cursor_pos - 1); + + /* Realing to a char before the place we were */ + hdt_cli.cursor_pos--; + move_cursor_to_column(strlen(hdt_cli.prompt) + hdt_cli.cursor_pos + + 1); + + break; + + case KEY_F1: + printf("\n"); + exec_command(CLI_HELP, hardware); + reset_prompt(); + break; + + default: + if ((current_key < 0x20) || (current_key > 0x7e)) + break; + /* Prevent overflow */ + if (hdt_cli.cursor_pos > MAX_LINE_SIZE - 2) + break; + /* If we aren't at the end of the input line, let's insert */ + if (hdt_cli.cursor_pos < (int)strlen(INPUT)) { + char key[2]; + int trailing_chars = strlen(INPUT) - hdt_cli.cursor_pos; + memset(temp_command, 0, sizeof(temp_command)); + strlcpy(temp_command, INPUT, hdt_cli.cursor_pos); + sprintf(key, "%c", current_key); + strncat(temp_command, key, 1); + strncat(temp_command, + INPUT + hdt_cli.cursor_pos, trailing_chars); + memset(INPUT, 0, sizeof(INPUT)); + snprintf(INPUT, sizeof(INPUT), "%s", temp_command); + + /* Clear the end of the line */ + clear_end_of_line(); + + /* Print the resulting buffer */ + printf("%s", INPUT + hdt_cli.cursor_pos); + + /* Return where we must put the new char */ + move_cursor_left(trailing_chars); + + } else { + putchar(current_key); + INPUT[hdt_cli.cursor_pos] = current_key; + } + hdt_cli.cursor_pos++; + break; + } + } +} diff --git a/contrib/syslinux-4.02/com32/hdt/hdt-cli.h b/contrib/syslinux-4.02/com32/hdt/hdt-cli.h new file mode 100644 index 0000000..98246b4 --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-cli.h @@ -0,0 +1,204 @@ +/* ----------------------------------------------------------------------- * + * + * 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 <getkey.h> +#include <dprintf.h> + +#include "hdt-common.h" + +#define MAX_LINE_SIZE 256 + +#define CLI_SPACE " " +#define CLI_LF "\n" +#define CLI_MENU "menu" +#define CLI_CLEAR "clear" +#define CLI_EXIT "exit" +#define CLI_HELP "help" +#define CLI_REBOOT "reboot" +#define CLI_SHOW "show" +#define CLI_SET "set" +#define CLI_MODE "mode" +#define CLI_HDT "hdt" +#define CLI_PCI "pci" +#define CLI_PXE "pxe" +#define CLI_KERNEL "kernel" +#define CLI_SYSLINUX "syslinux" +#define CLI_VESA "vesa" +#define CLI_SUMMARY "summary" +#define CLI_COMMANDS "commands" +#define CLI_DMI "dmi" +#define CLI_CPU "cpu" +#define CLI_DISK "disk" +#define CLI_SHOW_LIST "list" +#define CLI_IRQ "irq" +#define CLI_MODES "modes" +#define CLI_VPD "vpd" +#define CLI_MEMORY "memory" +#define CLI_ENABLE "enable" +#define CLI_DISABLE "disable" + +typedef enum { + INVALID_MODE, + EXIT_MODE, + HDT_MODE, + PCI_MODE, + DMI_MODE, + CPU_MODE, + PXE_MODE, + KERNEL_MODE, + SYSLINUX_MODE, + VESA_MODE, + DISK_MODE, + VPD_MODE, + MEMORY_MODE, +} cli_mode_t; + +#define PROMPT_SIZE 32 +#define MAX_HISTORY_SIZE 32 +#define INPUT hdt_cli.history[hdt_cli.history_pos] +struct s_cli { + cli_mode_t mode; + char prompt[PROMPT_SIZE]; + uint8_t cursor_pos; + char history[MAX_HISTORY_SIZE+1][MAX_LINE_SIZE]; + int history_pos; + int max_history_pos; +}; +struct s_cli hdt_cli; + +/* Describe a cli mode */ +struct cli_mode_descr { + const unsigned int mode; + const char *name; + /* Handle 1-token commands */ + struct cli_module_descr *default_modules; + /* Handle show <module> <args> */ + struct cli_module_descr *show_modules; + /* Handle set <module> <args> */ + struct cli_module_descr *set_modules; +}; + +/* Describe a subset of commands in a module (default, show, set, ...) */ +struct cli_module_descr { + struct cli_callback_descr *modules; + void (*default_callback) (int argc, char **argv, + struct s_hardware * hardware); +}; + +/* Describe a callback (belongs to a mode and a module) */ +struct cli_callback_descr { + const char *name; + void (*exec) (int argc, char **argv, struct s_hardware * hardware); +}; + +/* Manage aliases */ +#define MAX_ALIASES 2 +struct cli_alias { + const char *command; /* Original command */ + const int nb_aliases; /* Size of aliases array */ + const char **aliases; /* List of aliases */ +}; + +/* List of implemented modes */ +extern struct cli_mode_descr *list_modes[]; +struct cli_mode_descr hdt_mode; +struct cli_mode_descr dmi_mode; +struct cli_mode_descr syslinux_mode; +struct cli_mode_descr pxe_mode; +struct cli_mode_descr kernel_mode; +struct cli_mode_descr cpu_mode; +struct cli_mode_descr pci_mode; +struct cli_mode_descr vesa_mode; +struct cli_mode_descr disk_mode; +struct cli_mode_descr vpd_mode; +struct cli_mode_descr memory_mode; + +/* cli helpers */ +void find_cli_mode_descr(cli_mode_t mode, struct cli_mode_descr **mode_found); +void find_cli_callback_descr(const char *module_name, + struct cli_module_descr *modules_list, + struct cli_callback_descr **module_found); +cli_mode_t mode_s_to_mode_t(char *name); + +void set_mode(cli_mode_t mode, struct s_hardware *hardware); +void start_cli_mode(struct s_hardware *hardware); +void start_auto_mode(struct s_hardware *hardware); +void main_show(char *item, struct s_hardware *hardware); + +#define CLI_HISTORY "history" +void print_history(int argc, char **argv, struct s_hardware * hardware); + +// 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" +#define CLI_DMI_IPMI "ipmi" +#define CLI_DMI_CACHE "cache" +#define CLI_DMI_OEM "oem" +#define CLI_DMI_SECURITY "security" +#define CLI_DMI_LIST CLI_SHOW_LIST +void main_show_dmi(int argc, char **argv, struct s_hardware *hardware); +void show_dmi_memory_modules(int argc, char **argv, + struct s_hardware *hardware); +void show_dmi_memory_bank(int argc, char **argv, struct s_hardware *hardware); + +// PCI STUFF +#define CLI_PCI_DEVICE "device" +void main_show_pci(int argc, char **argv, struct s_hardware *hardware); +void cli_detect_pci(struct s_hardware *hardware); + +// CPU STUFF +void main_show_cpu(int argc, char **argv, struct s_hardware *hardware); + +// DISK STUFF +void disks_summary(int argc, char **argv, struct s_hardware *hardware); + +// PXE STUFF +void main_show_pxe(int argc, char **argv, struct s_hardware *hardware); + +// KERNEL STUFF +void main_show_kernel(int argc, char **argv, struct s_hardware *hardware); + +// SYSLINUX STUFF +void main_show_syslinux(int argc, char **argv, struct s_hardware *hardware); + +// VESA STUFF +void main_show_vesa(int argc, char **argv, struct s_hardware *hardware); + +// VPD STUFF +void main_show_vpd(int argc __unused, char **argv __unused, + struct s_hardware *hardware); +#endif diff --git a/contrib/syslinux-4.02/com32/hdt/hdt-common.c b/contrib/syslinux-4.02/com32/hdt/hdt-common.c new file mode 100644 index 0000000..5a187f2 --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-common.c @@ -0,0 +1,666 @@ +/* ----------------------------------------------------------------------- * + * + * 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 <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <getkey.h> +#include "syslinux/config.h" +#include "../lib/sys/vesa/vesa.h" +#include "hdt-common.h" +#include <disk/util.h> +#include <disk/mbrs.h> +#include <memory.h> + +/* ISOlinux requires a 8.3 format */ +void convert_isolinux_filename(char *filename, struct s_hardware *hardware) +{ + /* Exit if we are not running ISOLINUX */ + if (hardware->sv->filesystem != SYSLINUX_FS_ISOLINUX) + return; + /* Searching the dot */ + char *dot = strchr(filename, '.'); + /* Exiting if no dot exists in that string */ + if (dot == NULL) + return; + /* Exiting if the extension is 3 char or less */ + if (strlen(dot) <= 4) + return; + + /* We have an extension bigger than .blah + * so we have to shorten it to 3*/ + dot[4] = '\0'; +} + +void detect_parameters(const int argc, const char *argv[], + struct s_hardware *hardware) +{ + /* Quiet mode - make the output more quiet */ + quiet = false; + + /* Vesa mode isn't set until we explictly call it */ + vesamode = false; + + for (int i = 1; i < argc; i++) { + if (!strncmp(argv[i], "quiet", 5)) { + quiet = true; + } else if (!strncmp(argv[i], "modules_pcimap=", 15)) { + strlcpy(hardware->modules_pcimap_path, argv[i] + 15, + sizeof(hardware->modules_pcimap_path)); + convert_isolinux_filename(hardware->modules_pcimap_path, hardware); + } else if (!strncmp(argv[i], "pciids=", 7)) { + strlcpy(hardware->pciids_path, argv[i] + 7, + sizeof(hardware->pciids_path)); + convert_isolinux_filename(hardware->pciids_path, hardware); + } else if (!strncmp(argv[i], "modules_alias=", 14)) { + strlcpy(hardware->modules_alias_path, argv[i] + 14, + sizeof(hardware->modules_alias_path)); + convert_isolinux_filename(hardware->modules_alias_path, hardware); + } else if (!strncmp(argv[i], "memtest=", 8)) { + strlcpy(hardware->memtest_label, argv[i] + 8, + sizeof(hardware->memtest_label)); + convert_isolinux_filename(hardware->memtest_label, hardware); + } else if (!strncmp(argv[i], "vesa", 4)) { + vesamode = true; + max_console_lines = MAX_CLI_LINES; + /* If the user defines a background image */ + if (!strncmp(argv[i], "vesa=", 5)) { + strlcpy(hardware->vesa_background, argv[i] + 5, + sizeof(hardware->vesa_background)); + } + } else if (!strncmp(argv[i], "novesa", 6)) { + vesamode = false; + max_console_lines = MAX_VESA_CLI_LINES; + } else if (!strncmp(argv[i], "auto=", 5)) { + /* The auto= parameter is separated in several argv[] + * as it can contains spaces. + * We use the AUTO_DELIMITER char to define the limits + * of this parameter. + * i.e auto='show dmi; show pci' + */ + + /* Extracting the first parameter */ + strcpy(hardware->auto_label, argv[i] + 6); + strcat(hardware->auto_label, " "); + char *pos; + i++; + + /* While we can't find the other AUTO_DELIMITER, let's process the argv[] */ + while (((pos = strstr(argv[i], AUTO_DELIMITER)) == NULL) + && (i < argc)) { + strcat(hardware->auto_label, argv[i]); + strcat(hardware->auto_label, " "); + i++; + } + + /* If we didn't reach the end of the line, let's grab the last item */ + if (i < argc) { + strcat(hardware->auto_label, argv[i]); + hardware->auto_label[strlen(hardware->auto_label) - 1] = 0; + } + } + } +} + +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->modules_alias_return_code = 0; + hardware->cpu_detection = false; + hardware->pci_detection = false; + hardware->disk_detection = false; + hardware->disks_count = 0; + hardware->dmi_detection = false; + hardware->pxe_detection = false; + hardware->vesa_detection = false; + hardware->vpd_detection = false; + hardware->memory_detection = false; + hardware->nb_pci_devices = 0; + hardware->is_dmi_valid = false; + hardware->is_pxe_valid = false; + hardware->is_vpd_valid = false; + hardware->pci_domain = NULL; + hardware->detected_memory_size = 0; + + /* Cleaning structures */ + memset(hardware->disk_info, 0, sizeof(hardware->disk_info)); + memset(hardware->mbr_ids, 0, sizeof(hardware->mbr_ids)); + memset(&hardware->dmi, 0, sizeof(s_dmi)); + memset(&hardware->cpu, 0, sizeof(s_cpu)); + memset(&hardware->pxe, 0, sizeof(struct s_pxe)); + memset(&hardware->vesa, 0, sizeof(struct s_vesa)); + memset(&hardware->vpd, 0, sizeof(s_vpd)); + 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); + memset(hardware->modules_alias_path, 0, + sizeof hardware->modules_alias_path); + memset(hardware->memtest_label, 0, sizeof hardware->memtest_label); + memset(hardware->auto_label, 0, sizeof hardware->auto_label); + memset(hardware->vesa_background, 0, sizeof hardware->vesa_background); + strcat(hardware->pciids_path, "pci.ids"); + strcat(hardware->modules_pcimap_path, "modules.pcimap"); + strcat(hardware->modules_alias_path, "modules.alias"); + strcat(hardware->memtest_label, "memtest"); + strlcpy(hardware->vesa_background, CLI_DEFAULT_BACKGROUND, + sizeof(hardware->vesa_background)); +} + +/* + * 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; +} + +/** + * vpd_detection - populate the VPD structure + * + * VPD is a structure available on IBM machines. + * It is documented at: + * http://www.pc.ibm.com/qtechinfo/MIGR-45120.html + * (XXX the page seems to be gone) + **/ +int detect_vpd(struct s_hardware *hardware) +{ + if (hardware->vpd_detection) + return -1; + else + hardware->vpd_detection = true; + + if (vpd_decode(&hardware->vpd) == -ENOVPDTABLE) { + hardware->is_vpd_valid = false; + return -ENOVPDTABLE; + } else { + hardware->is_vpd_valid = true; + return 0; + } +} + +/* Detection vesa stuff*/ +int detect_vesa(struct s_hardware *hardware) +{ + static com32sys_t rm; + struct vesa_general_info *gi; + struct vesa_mode_info *mi; + uint16_t mode, *mode_ptr; + char *oem_ptr; + + if (hardware->vesa_detection == true) + return -1; + + hardware->vesa_detection = true; + hardware->is_vesa_valid = false; + + /* Allocate space in the bounce buffer for these structures */ + gi = &((struct vesa_info *)__com32.cs_bounce)->gi; + mi = &((struct vesa_info *)__com32.cs_bounce)->mi; + + gi->signature = VBE2_MAGIC; /* Get VBE2 extended data */ + rm.eax.w[0] = 0x4F00; /* Get SVGA general information */ + rm.edi.w[0] = OFFS(gi); + rm.es = SEG(gi); + __intcall(0x10, &rm, &rm); + + if (rm.eax.w[0] != 0x004F) { + return -1; + }; + + mode_ptr = GET_PTR(gi->video_mode_ptr); + oem_ptr = GET_PTR(gi->oem_vendor_name_ptr); + strlcpy(hardware->vesa.vendor, oem_ptr, sizeof(hardware->vesa.vendor)); + oem_ptr = GET_PTR(gi->oem_product_name_ptr); + strlcpy(hardware->vesa.product, oem_ptr, sizeof(hardware->vesa.product)); + oem_ptr = GET_PTR(gi->oem_product_rev_ptr); + strlcpy(hardware->vesa.product_revision, oem_ptr, + sizeof(hardware->vesa.product_revision)); + + hardware->vesa.major_version = (gi->version >> 8) & 0xff; + hardware->vesa.minor_version = gi->version & 0xff; + hardware->vesa.total_memory = gi->total_memory; + hardware->vesa.software_rev = gi->oem_software_rev; + + hardware->vesa.vmi_count = 0; + + while ((mode = *mode_ptr++) != 0xFFFF) { + + rm.eax.w[0] = 0x4F01; /* Get SVGA mode information */ + rm.ecx.w[0] = mode; + rm.edi.w[0] = OFFS(mi); + rm.es = SEG(mi); + __intcall(0x10, &rm, &rm); + + /* Must be a supported mode */ + if (rm.eax.w[0] != 0x004f) + continue; + + /* Saving detected values */ + memcpy(&hardware->vesa.vmi[hardware->vesa.vmi_count].mi, mi, + sizeof(struct vesa_mode_info)); + hardware->vesa.vmi[hardware->vesa.vmi_count].mode = mode; + + hardware->vesa.vmi_count++; + } + hardware->is_vesa_valid = true; + return 0; +} + +/* Try to detect disks from port 0x80 to 0xff */ +void detect_disks(struct s_hardware *hardware) +{ + int i = -1; + int err; + + if (hardware->disk_detection) + return; + + hardware->disk_detection = true; + for (int drive = 0x80; drive < 0xff; drive++) { + i++; + hardware->disk_info[i].disk = drive; + err = get_drive_parameters(&hardware->disk_info[i]); + + /* + * Do not print output when drive does not exist or + * doesn't support int13 (cdrom, ...) + */ + if (err == -1 || !hardware->disk_info[i].cbios) + continue; + + /* Detect MBR */ + hardware->mbr_ids[i] = get_mbr_id(&hardware->disk_info[i]); + + hardware->disks_count++; + } +} + +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); + + /* The firt pass try to find the exact pci device */ + 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; + } + } + + /* If we reach that part, it means the pci device pointed by + * the pxe rom wasn't found in our list. + * Let's try to find the device only by its pci ids. + * The pci device we'll match is maybe not exactly the good one + * as we can have the same pci id several times. + * At least, the pci id, the vendor/product will be right. + * That's clearly a workaround for some weird cases. + * This should happend very unlikely */ + hardware->pxe.pci_device = NULL; + hardware->pxe.pci_device_pos = 0; + pci_number = 0; + for_each_pci_func(pci_device, hardware->pci_domain) { + pci_number++; + if ((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; + } + } + + } + } + return 0; +} + +void detect_memory(struct s_hardware *hardware) { + if (hardware->memory_detection == false) { + hardware->memory_detection = true; + hardware->detected_memory_size = detect_memsize(); + } +} + +void detect_pci(struct s_hardware *hardware) +{ + if (hardware->pci_detection == true) + return; + hardware->pci_detection = true; + + hardware->nb_pci_devices = 0; + + /* Scanning to detect pci buses and devices */ + hardware->pci_domain = pci_scan(); + + if (!hardware->pci_domain) + return; + + /* Gathering addtional information */ + gather_additional_pci_config(hardware->pci_domain); + + struct pci_device *pci_device; + for_each_pci_func(pci_device, hardware->pci_domain) { + hardware->nb_pci_devices++; + } + + if (!quiet) { + more_printf("PCI: %d devices detected\n", hardware->nb_pci_devices); + more_printf("PCI: Resolving names\n"); + } + /* Assigning product & vendor name for each device */ + hardware->pci_ids_return_code = + get_name_from_pci_ids(hardware->pci_domain, hardware->pciids_path); + + if (!quiet) + more_printf("PCI: Resolving class names\n"); + /* Assigning class name for each device */ + hardware->pci_ids_return_code = + get_class_name_from_pci_ids(hardware->pci_domain, + hardware->pciids_path); + + if (!quiet) + more_printf("PCI: Resolving module names\n"); + /* Detecting which kernel module should match each device using modules.pcimap */ + hardware->modules_pcimap_return_code = + get_module_name_from_pcimap(hardware->pci_domain, + hardware->modules_pcimap_path); + + /* Detecting which kernel module should match each device using modules.alias */ + hardware->modules_alias_return_code = + get_module_name_from_alias(hardware->pci_domain, + hardware->modules_alias_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); + /* Old processors doesn't manage the identify commands + * Let's use the dmi value in that case */ + if (strlen(remove_spaces(hardware->cpu.model)) == 0) + strlcpy(hardware->cpu.model, hardware->dmi.processor.version, + sizeof(hardware->cpu.model)); + + /* Some CPUs like to put many spaces in the model name + * That makes some weird display in console/menu + * Let's remove that mulitple spaces */ + strlcpy(hardware->cpu.model,del_multi_spaces(hardware->cpu.model),sizeof(hardware->cpu.model)); + 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) + */ +const char *find_argument(const char **argv, const char *argument) +{ + int la = strlen(argument); + const char **arg; + const char *ptr = NULL; + + for (arg = argv; *arg; arg++) { + if (!memcmp(*arg, argument, la)) + ptr = *arg + la; + } + + return ptr; +} + +void clear_screen(void) +{ + move_cursor_to_next_line(); + disable_utf8(); + set_g1_special_char(); + set_us_g0_charset(); + display_cursor(false); + clear_entire_screen(); + gotoxy(0,0); + reset_more_printf(); +} + +/* remove begining spaces */ +char *skip_spaces(char *p) +{ + while (*p && *p <= ' ') { + p++; + } + + return p; +} + +/* remove trailing & begining spaces */ +char *remove_spaces(char *p) +{ + char *save = p; + p += strlen(p) - 1; + while (*p && *p <= ' ') { + *p = '\0'; + p--; + } + p = save; + while (*p && *p <= ' ') { + p++; + } + + return p; +} + +/* remove trailing LF */ +char *remove_trailing_lf(char *p) +{ + char *save = p; + p += strlen(p) - 1; + while (*p && *p == 10) { + *p = '\0'; + p--; + } + p = save; + + return p; +} + +/* delete multiple spaces, one is enough */ +char *del_multi_spaces(char *p) +{ + /* Saving the original pointer */ + char *save = p; + + /* Let's parse the complete string + * As we search for a double spacing + * we have to be sure then string is + * long enough to be processed */ + while (*p && *p + 1) { + + /* If we have two consecutive spaces */ + if ((*p == ' ') && (*(p + 1) == ' ')) { + + /* Let's copy to the current position + * the content from the second space*/ + strlcpy(p, p + 1, strlen(p + 1)); + + /* The string is 1 char smaller */ + *(p + strlen(p) - 1) = '\0'; + + /* Don't increment the pointer as we + * changed the content of the current position*/ + continue; + } + + /* Nothing as been found, let's see on the next char */ + p++; + } + /* Returning the original pointer */ + return save; +} + +/* Reset the more_printf counter */ +void reset_more_printf(void) +{ + display_line_nb = 0; +} + +int draw_background(const char *what) +{ + if (!what) + return vesacon_default_background(); + else + return vesacon_load_background(what); +} + +void init_console(struct s_hardware *hardware) +{ + if (vesamode) { + openconsole(&dev_rawcon_r, &dev_vesaserial_w); + draw_background(hardware->vesa_background); + } else + console_ansi_raw(); +} diff --git a/contrib/syslinux-4.02/com32/hdt/hdt-common.h b/contrib/syslinux-4.02/com32/hdt/hdt-common.h new file mode 100644 index 0000000..fd9d785 --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-common.h @@ -0,0 +1,226 @@ +/* ----------------------------------------------------------------------- * + * + * 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 <syslinux/pxe.h> +#include <console.h> +#include <consoles.h> +#include <syslinux/vesacon.h> +#include "sys/pci.h" + +#include <disk/bootloaders.h> +#include <disk/errno_disk.h> +#include <disk/error.h> +#include <disk/geom.h> +#include <disk/mbrs.h> +#include <disk/msdos.h> +#include <disk/partition.h> +#include <disk/swsusp.h> +#include <disk/read.h> + +#include "cpuid.h" +#include "dmi/dmi.h" +#include "hdt-ata.h" +#include "../lib/sys/vesa/vesa.h" +#include <vpd/vpd.h> +#include <libansi.h> + +/* Declare a variable or data structure as unused. */ +#define __unused __attribute__ (( unused )) + +/* 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 +#define MAX_VESA_MODES 255 + +/* This value is used for rebooting from the menu mode */ +#define HDT_REBOOT "hdt_reboot" + +/* The maximum number of commands we can process */ +#define MAX_NB_AUTO_COMMANDS 255 +/* The maximum size of a command */ +#define AUTO_COMMAND_SIZE 255 +/* The char that separate two commands */ +#define AUTO_SEPARATOR ";" +/* The char that surround the list of commands */ +#define AUTO_DELIMITER "'" + +/* Graphic to load in background when using the vesa mode */ +#define CLI_DEFAULT_BACKGROUND "backgnd.png" + +/* The maximum number of lines */ +#define MAX_CLI_LINES 20 +#define MAX_VESA_CLI_LINES 24 + +/* Defines if the cli is quiet*/ +bool quiet; + +/* Defines if we must use the vesa mode */ +bool vesamode; + +/* Defines the number of lines in the console + * Default is 20 for a std console */ +extern int max_console_lines; + +extern int display_line_nb; +extern bool disable_more_printf; + +#define pause_printf() do {\ + printf("--More--");\ + get_key(stdin, 0);\ + printf("\033[2K\033[1G\033[1F\n");\ +} while (0); + +/* The brokeness of that macro is that + * it assumes that __VA_ARGS__ contains + * one \n (and only one) + */ +#define more_printf(...) do {\ + if (__likely(!disable_more_printf)) {\ + if (display_line_nb == max_console_lines) {\ + display_line_nb=0;\ + printf("\n--More--");\ + get_key(stdin, 0);\ + printf("\033[2K\033[1G\033[1F");\ + }\ + display_line_nb++;\ + }\ + printf(__VA_ARGS__);\ +} while (0); + +/* Display CPU registers for debugging purposes */ +static inline 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); +} + +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_vesa_mode_info { + struct vesa_mode_info mi; + uint16_t mode; +}; + +struct s_vesa { + uint8_t major_version; + uint8_t minor_version; + struct s_vesa_mode_info vmi[MAX_VESA_MODES]; + uint8_t vmi_count; + uint16_t total_memory; + char vendor[256]; + char product[256]; + char product_revision[256]; + uint16_t software_rev; +}; + +struct s_hardware { + s_dmi dmi; /* DMI table */ + s_cpu cpu; /* CPU information */ + s_vpd vpd; /* VPD information */ + struct pci_domain *pci_domain; /* PCI Devices */ + struct driveinfo disk_info[256]; /* Disk Information */ + uint32_t mbr_ids[256]; /* MBR ids */ + int disks_count; /* Number of detected disks */ + struct s_pxe pxe; + struct s_vesa vesa; + unsigned long detected_memory_size; /* The detected memory size (in KB) */ + + int pci_ids_return_code; + int modules_pcimap_return_code; + int modules_alias_return_code; + int nb_pci_devices; + bool is_dmi_valid; + bool is_pxe_valid; + bool is_vesa_valid; + bool is_vpd_valid; + + bool dmi_detection; /* Does the dmi stuff has already been detected? */ + bool pci_detection; /* Does the pci stuff has already been detected? */ + bool cpu_detection; /* Does the cpu stuff has already been detected? */ + bool disk_detection; /* Does the disk stuff has already been detected? */ + bool pxe_detection; /* Does the pxe stuff has already been detected? */ + bool vesa_detection; /* Does the vesa sutff have been already detected? */ + bool vpd_detection; /* Does the vpd stuff has already been detected? */ + bool memory_detection; /* Does the memory size got detected ?*/ + + char syslinux_fs[22]; + const struct syslinux_version *sv; + char modules_pcimap_path[255]; + char modules_alias_path[255]; + char pciids_path[255]; + char memtest_label[255]; + char auto_label[AUTO_COMMAND_SIZE]; + char vesa_background[255]; +}; + +void reset_more_printf(void); +const char *find_argument(const char **argv, const char *argument); +char *remove_spaces(char *p); +char *remove_trailing_lf(char *p); +char *skip_spaces(char *p); +char *del_multi_spaces(char *p); +int detect_dmi(struct s_hardware *hardware); +int detect_vpd(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(const int argc, const char *argv[], + struct s_hardware *hardware); +int detect_vesa(struct s_hardware *hardware); +void detect_memory(struct s_hardware *hardware); +void init_console(struct s_hardware *hardware); +#endif diff --git a/contrib/syslinux-4.02/com32/hdt/hdt-menu-about.c b/contrib/syslinux-4.02/com32/hdt/hdt-menu-about.c new file mode 100644 index 0000000..1e8a6ff --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-menu-about.c @@ -0,0 +1,87 @@ +/* ----------------------------------------------------------------------- * + * + * 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 (%s)", VERSION, + CODENAME); + snprintf(statbuffer, sizeof statbuffer, "Version : %s (%s)", VERSION, + CODENAME); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Website : %s", WEBSITE_URL); + snprintf(statbuffer, sizeof statbuffer, "Website : %s",WEBSITE_URL); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Mailing List : %s", CONTACT); + snprintf(statbuffer, sizeof statbuffer, "Mailing List: %s", CONTACT); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + add_item("", "", OPT_SEP, "", 0); + + snprintf(buffer, sizeof buffer, "Project Leader : %s", AUTHOR); + snprintf(statbuffer, sizeof statbuffer, "Project Leader : %s", AUTHOR); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Core Developer : %s", CORE_DEVELOPER); + snprintf(statbuffer, sizeof statbuffer, "Core Developer : %s", + CORE_DEVELOPER); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + char *contributors[NB_CONTRIBUTORS] = CONTRIBUTORS; + for (int c = 0; c < NB_CONTRIBUTORS; c++) { + snprintf(buffer, sizeof buffer, "Contributor : %s", contributors[c]); + snprintf(statbuffer, sizeof statbuffer, "Contributor : %s", + contributors[c]); + 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/contrib/syslinux-4.02/com32/hdt/hdt-menu-disk.c b/contrib/syslinux-4.02/com32/hdt/hdt-menu-disk.c new file mode 100644 index 0000000..b0b4a5a --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-menu-disk.c @@ -0,0 +1,264 @@ +/* ----------------------------------------------------------------------- * + * + * 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 <stdlib.h> + +#include "hdt-menu.h" +#include "hdt-util.h" + +static int dn; + +static void show_partition_information(struct driveinfo *drive_info, + struct part_entry *ptab __unused, + int partition_offset __unused, + int nb_partitions_seen) +{ + char menu_title[MENULEN + 1]; + char menu_title_ref[MENULEN + 1]; + + if (nb_partitions_seen == 1) + add_sep(); + + memset(menu_title, 0, sizeof menu_title); + memset(menu_title_ref, 0, sizeof menu_title_ref); + snprintf(menu_title_ref, sizeof menu_title_ref, "disk_%x_part_%d", + drive_info[dn].disk, nb_partitions_seen); + snprintf(menu_title, sizeof menu_title, "Partition %d", nb_partitions_seen); + + add_item(menu_title, + "Partition information (start, end, length, type, ...)", + OPT_SUBMENU, menu_title_ref, 0); +} + +/** + * compute_partition_information - print information about a partition + * @ptab: part_entry describing the partition + * @i: Partition number (UI purposes only) + * @ptab_root: part_entry describing the root partition (extended only) + * @drive_info: driveinfo struct describing the drive on which the partition + * is + * + * Note on offsets (from hpa, see chain.c32): + * + * To make things extra confusing: data partition offsets are relative to where + * the data partition record is stored, whereas extended partition offsets + * are relative to the beginning of the extended partition all the way back + * at the MBR... but still not absolute! + **/ +static void compute_partition_information(struct driveinfo *drive_info, + struct part_entry *ptab, + int partition_offset, + int nb_partitions_seen) +{ + char size[11]; + char bootloader_name[9]; + char *parttype; + unsigned int start, end; + char buffer[SUBMENULEN + 1]; + char statbuffer[STATLEN + 1]; + char menu_title[MENULEN + 1]; + char menu_title_ref[MENULEN + 1]; + + memset(buffer, 0, sizeof buffer); + memset(statbuffer, 0, sizeof statbuffer); + memset(menu_title, 0, sizeof menu_title); + memset(menu_title_ref, 0, sizeof menu_title_ref); + snprintf(menu_title_ref, sizeof menu_title_ref, "disk_%x_part_%d", + drive_info[dn].disk, nb_partitions_seen); + snprintf(menu_title, sizeof menu_title, "Partition %d", nb_partitions_seen); + + add_named_menu(menu_title_ref, menu_title, -1); + set_menu_pos(SUBMENU_Y, SUBMENU_X); + + start = partition_offset; + end = start + ptab->length - 1; + + if (ptab->length > 0) + sectors_to_size(ptab->length, size); + else + memset(size, 0, sizeof size); + + get_label(ptab->ostype, &parttype); + + snprintf(buffer, sizeof buffer, "Size : %s", remove_spaces(size)); + snprintf(statbuffer, sizeof statbuffer, "Size : %s", remove_spaces(size)); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + + snprintf(buffer, sizeof buffer, "Type : %s", parttype); + snprintf(statbuffer, sizeof statbuffer, "Type: %s", parttype); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + + if (get_bootloader_string(drive_info, ptab, bootloader_name, 9) == 0) { + snprintf(buffer, sizeof buffer, "Bootloader : %s", bootloader_name); + snprintf(statbuffer, sizeof statbuffer, "Bootloader: %s", + bootloader_name); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + } + + snprintf(buffer, sizeof buffer, "Bootable : %s", + (ptab->active_flag == 0x80) ? "Yes" : "No"); + snprintf(statbuffer, sizeof statbuffer, "Bootable: %s", + (ptab->active_flag == 0x80) ? "Yes" : "No"); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + + snprintf(buffer, sizeof buffer, "Start : %d", start); + snprintf(statbuffer, sizeof statbuffer, "Start: %d", start); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + + snprintf(buffer, sizeof buffer, "End : %d", end); + snprintf(statbuffer, sizeof statbuffer, "End: %d", end); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + + snprintf(buffer, sizeof buffer, "Id : %X", ptab->ostype); + snprintf(statbuffer, sizeof statbuffer, "Id: %X", ptab->ostype); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + + free(parttype); + + /* Extra info */ + if (ptab->ostype == 0x82 && swsusp_check(drive_info, ptab) != -1) { + snprintf(buffer, sizeof buffer, "%s", "Swsusp sig : detected"); + snprintf(statbuffer, sizeof statbuffer, "%s", "Swsusp sig : detected"); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + } +} + +/* Compute the disk submenu */ +static int compute_disk_module(struct s_my_menu *menu, int nb_sub_disk_menu, + const struct s_hardware *hardware, + int disk_number) +{ + char buffer[MENULEN + 1]; + char statbuffer[STATLEN + 1]; + char mbr_name[50]; + struct driveinfo *d = (struct driveinfo *)hardware->disk_info; + + snprintf(buffer, sizeof buffer, " Disk <0x%X> (EDD %X)", + d[disk_number].disk, d[disk_number].edd_version); + menu[nb_sub_disk_menu].menu = add_menu(buffer, -1); + menu[nb_sub_disk_menu].items_count = 0; + + int previous_size, size; + char previous_unit[3], unit[3]; // GB + char size_iec[11]; // GiB + char size_dec[11]; // GB + sectors_to_size_dec(previous_unit, &previous_size, unit, &size, + d[disk_number].edd_params.sectors); + sectors_to_size(d[disk_number].edd_params.sectors, size_iec); + sectors_to_size_dec2(d[disk_number].edd_params.sectors, size_dec); + + snprintf(buffer, sizeof buffer, "Size : %s/%s (%d %s)", + remove_spaces(size_iec), remove_spaces(size_dec), previous_size, + previous_unit); + snprintf(statbuffer, sizeof statbuffer, "Size: %s/%s (%d %s)", + remove_spaces(size_iec), remove_spaces(size_dec), previous_size, + previous_unit); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu[nb_sub_disk_menu].items_count++; + + /* Do not print Host Bus & Interface if EDD isn't 3.0 or more */ + if (d[disk_number].edd_version >= 0x30) { + snprintf(buffer, sizeof buffer, "Host Bus/Interface: %s / %s", + remove_spaces((char *)d[disk_number].edd_params.host_bus_type), + d[disk_number].edd_params.interface_type); + snprintf(statbuffer, sizeof statbuffer, "Host Bus / Interface: %s / %s", + remove_spaces((char *)d[disk_number].edd_params.host_bus_type), + d[disk_number].edd_params.interface_type); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu[nb_sub_disk_menu].items_count++; + } + + snprintf(buffer, sizeof buffer, "C / H / S : %d / %d / %d", + d[disk_number].legacy_max_cylinder + 1, + d[disk_number].legacy_max_head + 1, + (int)d[disk_number].edd_params.sectors); + snprintf(statbuffer, sizeof statbuffer, + "Cylinders / Heads / Sectors: %d / %d / %d", + d[disk_number].legacy_max_cylinder + 1, + d[disk_number].legacy_max_head + 1, + (int)d[disk_number].edd_params.sectors); + 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].legacy_sectors_per_track); + snprintf(statbuffer, sizeof statbuffer, "Sectors per Track: %d", + d[disk_number].legacy_sectors_per_track); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu[nb_sub_disk_menu].items_count++; + + get_mbr_string(hardware->mbr_ids[disk_number], &mbr_name, 50); + + snprintf(buffer, sizeof buffer, "MBR : %s (0x%X)", + remove_spaces(mbr_name), hardware->mbr_ids[disk_number]); + snprintf(statbuffer, sizeof statbuffer, "MBR: %s (id 0x%X)", + remove_spaces(mbr_name), hardware->mbr_ids[disk_number]); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu[nb_sub_disk_menu].items_count++; + + dn = disk_number; + + parse_partition_table(&d[disk_number], &show_partition_information); + if (!parse_partition_table(&d[disk_number], &compute_partition_information)) { + get_error("parse_partition_table"); + menu[nb_sub_disk_menu].items_count++; + } + + return 0; +} + +/* Compute the Disks menu */ +void compute_disks(struct s_hdt_menu *menu, struct s_hardware *hardware) +{ + char buffer[MENULEN + 1]; + int nb_sub_disk_menu = 0; + + /* No need to compute that menu if no disks were detected */ + menu->disk_menu.items_count = 0; + if (hardware->disks_count == 0) + return; + + for (int i = 0; i < hardware->disks_count; i++) { + if (!hardware->disk_info[i].cbios) + continue; /* Invalid geometry */ + compute_disk_module + ((struct s_my_menu *)&(menu->disk_sub_menu), nb_sub_disk_menu, + hardware, i); + nb_sub_disk_menu++; + } + + menu->disk_menu.menu = add_menu(" Disks ", -1); + + for (int i = 0; i < nb_sub_disk_menu; i++) { + snprintf(buffer, sizeof buffer, " Disk <%d> ", i + 1); + 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/contrib/syslinux-4.02/com32/hdt/hdt-menu-dmi.c b/contrib/syslinux-4.02/com32/hdt/hdt-menu-dmi.c new file mode 100644 index 0000000..7a413a1 --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-menu-dmi.c @@ -0,0 +1,381 @@ +/* ----------------------------------------------------------------------- * + * + * 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", + del_multi_spaces(dmi->chassis.asset_tag)); + snprintf(statbuffer, sizeof statbuffer, "Asset Tag: %s", + del_multi_spaces(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 Main IPMI menu */ +void compute_ipmi(struct s_my_menu *menu, s_dmi * dmi) +{ + char buffer[SUBMENULEN + 1]; + char statbuffer[STATLEN + 1]; + menu->menu = add_menu(" IPMI ", -1); + menu->items_count = 0; + set_menu_pos(SUBMENU_Y, SUBMENU_X); + + snprintf(buffer, sizeof buffer, "Interface Type : %s", + dmi->ipmi.interface_type); + snprintf(statbuffer, sizeof statbuffer, "Interface Type: %s", + dmi->ipmi.interface_type); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Spec. Version : %u.%u", + dmi->ipmi.major_specification_version, + dmi->ipmi.minor_specification_version); + snprintf(statbuffer, sizeof statbuffer, "Specification Version: %u.%u", + dmi->ipmi.major_specification_version, + dmi->ipmi.minor_specification_version); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "I2C Slave @ : 0x%02x", + dmi->ipmi.I2C_slave_address); + snprintf(statbuffer, sizeof statbuffer, "I2C Slave Address: 0x%02x", + dmi->ipmi.I2C_slave_address); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "NV Storage @ : %u", + dmi->ipmi.nv_address); + snprintf(statbuffer, sizeof statbuffer, "NV Storage Address: %u", + dmi->ipmi.nv_address); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + uint32_t high = dmi->ipmi.base_address >> 32; + uint32_t low = dmi->ipmi.base_address & 0xFFFF; + + snprintf(buffer, sizeof buffer, "Base Address : %08X%08X", + high, (low & ~1)); + snprintf(statbuffer, sizeof statbuffer, "Base Address : %08X%08X", + high, (low & ~1)); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "IRQ : %d", dmi->ipmi.irq); + snprintf(statbuffer, sizeof statbuffer, "IRQ : %d", dmi->ipmi.irq); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + printf("MENU: IPMI menu done (%d items)\n", menu->items_count); +} + +/* Compute 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 (percent) : %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/contrib/syslinux-4.02/com32/hdt/hdt-menu-kernel.c b/contrib/syslinux-4.02/com32/hdt/hdt-menu-kernel.c new file mode 100644 index 0000000..98e5209 --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-menu-kernel.c @@ -0,0 +1,87 @@ +/* ----------------------------------------------------------------------- * + * + * 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) && + (hardware->modules_alias_return_code == -ENOMODULESALIAS)) { + add_item("The modules.{pcimap|alias} file is missing", + "Missing modules.{pcimap|alias} file", OPT_INACTIVE, NULL, 0); + add_item("Kernel modules can't be computed.", + "Missing modules.{pcimap|alias} file", OPT_INACTIVE, NULL, 0); + add_item("Please put one of them in same dir as hdt", + "Missing modules.{pcimap|alias} 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", + 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/contrib/syslinux-4.02/com32/hdt/hdt-menu-memory.c b/contrib/syslinux-4.02/com32/hdt/hdt-menu-memory.c new file mode 100644 index 0000000..6c82b11 --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-menu-memory.c @@ -0,0 +1,382 @@ +/* ----------------------------------------------------------------------- * + * + * 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 <memory.h> +#include "hdt-menu.h" +#define E820MAX 128 + +/* Compute the e820 submenu */ +static void compute_e820(struct s_my_menu *menu) +{ + char buffer[MENULEN + 1]; + char statbuffer[STATLEN + 1]; + + sprintf(buffer, " e820 Physical RAM map "); + menu->items_count = 0; + menu->menu = add_menu(buffer, -1); + + struct e820entry map[E820MAX]; + int count = 0; + char type[14]; + + detect_memory_e820(map, E820MAX, &count); + unsigned long memory_size = memsize_e820(map, count); + snprintf(buffer, sizeof buffer, "Detected Memory - %lu MiB (%lu KiB)", + memory_size >> 10, memory_size); + snprintf(statbuffer, sizeof statbuffer, + "Detected Memory : %lu MiB (%lu KiB)", memory_size >> 10, + memory_size); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + add_item("", "", OPT_SEP, "", 0); + + for (int j = 0; j < count; j++) { + get_type(map[j].type, type, 14); + snprintf(buffer, sizeof buffer, + "%016llx - %016llx (%s)", + map[j].addr, map[j].size, remove_spaces(type)); + snprintf(statbuffer, sizeof statbuffer, + "%016llx - %016llx (%s)", + map[j].addr, map[j].size, remove_spaces(type)); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + } +} + +/* Compute the e801 submenu */ +static void compute_e801(struct s_my_menu *menu) +{ + char buffer[MENULEN + 1]; + char statbuffer[STATLEN + 1]; + + sprintf(buffer, " e801 information "); + menu->items_count = 0; + menu->menu = add_menu(buffer, -1); + + int mem_low, mem_high = 0; + if (detect_memory_e801(&mem_low, &mem_high)) { + snprintf(buffer, sizeof buffer, "%s", "e801 output is bogus"); + snprintf(statbuffer, sizeof statbuffer, "%s", "e801 output is bogus"); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + } else { + snprintf(buffer, sizeof buffer, "Detected Memory : %d MiB (%d KiB)", + (mem_high >> 4) + (mem_low >> 10), mem_low + (mem_high << 6)); + snprintf(statbuffer, sizeof statbuffer, + "Detected Memory : %d MiB (%d KiB)", + (mem_high >> 4) + (mem_low >> 10), mem_low + (mem_high << 6)); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + + add_item("", "", OPT_SEP, "", 0); + snprintf(buffer, sizeof buffer, "Low Memory : %d KiB (%d MiB)", + mem_low, mem_low >> 10); + snprintf(statbuffer, sizeof statbuffer, "Low Memory : %d KiB (%d MiB)", + mem_low, mem_low >> 10); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + + snprintf(buffer, sizeof buffer, "High Memory : %d KiB (%d MiB)", + mem_high << 6, mem_high >> 4); + snprintf(statbuffer, sizeof statbuffer, "High Memory : %d KiB (%d MiB)", + mem_high << 6, mem_high >> 4); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + + } + menu->items_count++; +} + +/* Compute the 88 submenu */ +static void compute_88(struct s_my_menu *menu) +{ + char buffer[MENULEN + 1]; + char statbuffer[STATLEN + 1]; + + sprintf(buffer, " 88 information "); + menu->items_count = 0; + menu->menu = add_menu(buffer, -1); + + int mem_size = 0; + if (detect_memory_88(&mem_size)) { + snprintf(buffer, sizeof buffer, "%s", "88 output is bogus"); + snprintf(statbuffer, sizeof statbuffer, "%s", "88 output is bogus"); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + } else { + snprintf(buffer, sizeof buffer, "Detected Memory : %d MiB (%d KiB)", + mem_size >> 10, mem_size); + snprintf(statbuffer, sizeof statbuffer, + "Detected Memory : %d MiB (%d KiB)", mem_size >> 10, mem_size); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + } + menu->items_count++; +} + +/* Compute the Memory submenu */ +static 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(statbuffer, sizeof statbuffer, "Part Number: %s", + dmi->memory[i].part_number); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + +} + +/* Compute the Memory submenu when type 6 is used*/ +static void compute_memory_module_type6(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, "Socket Designation : %s", + dmi->memory_module[i].socket_designation); + snprintf(statbuffer, sizeof statbuffer, "Socket Designation : %s", + dmi->memory_module[i].socket_designation); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Bank Connections : %s", + dmi->memory_module[i].bank_connections); + snprintf(statbuffer, sizeof statbuffer, "Bank Connections: %s", + dmi->memory_module[i].bank_connections); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Type : %s", + dmi->memory_module[i].type); + snprintf(statbuffer, sizeof statbuffer, "Type : %s", + dmi->memory_module[i].type); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Current Speed : %s", + dmi->memory_module[i].speed); + snprintf(statbuffer, sizeof statbuffer, "Current Speed : %s", + dmi->memory_module[i].speed); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Installed Size : %s", + dmi->memory_module[i].installed_size); + snprintf(statbuffer, sizeof statbuffer, "Installed Size : %s", + dmi->memory_module[i].installed_size); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Enabled Size : %s", + dmi->memory_module[i].enabled_size); + snprintf(statbuffer, sizeof statbuffer, "Enabled Size : %s", + dmi->memory_module[i].enabled_size); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Error Status : %s", + dmi->memory_module[i].error_status); + snprintf(statbuffer, sizeof statbuffer, "Error Status : %s", + dmi->memory_module[i].error_status); + 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, + struct s_hardware *hardware) +{ + char buffer[MENULEN + 1]; + int i = 0; + int memory_count = 0; + + /* If memory type 17 is available */ + if (dmi->memory_count > 0) { + memory_count = dmi->memory_count; + for (i = 0; i < dmi->memory_count; i++) { + compute_memory_module(&(menu->memory_sub_menu[i]), dmi, i); + } + } else if (dmi->memory_module_count > 0) { + memory_count = dmi->memory_module_count; + /* Memory Type 17 isn't available, let's fallback on type 6 */ + for (i = 0; i < dmi->memory_module_count; i++) { + compute_memory_module_type6(&(menu->memory_sub_menu[i]), dmi, i); + } + } + + compute_e820(&(menu->memory_sub_menu[++i])); + compute_e801(&(menu->memory_sub_menu[++i])); + compute_88(&(menu->memory_sub_menu[++i])); + + menu->memory_menu.menu = add_menu(" Memory ", -1); + menu->memory_menu.items_count = 0; + + snprintf(buffer, sizeof(buffer), " %lu MB detected ", + (hardware->detected_memory_size + (1 << 9)) >> 10); + add_item(buffer, "Detected Memory", OPT_INACTIVE, NULL, + menu->memory_sub_menu[0].menu); + menu->memory_menu.items_count++; + + add_item("", "", OPT_SEP, "", 0); + + if (memory_count == 0) { + snprintf(buffer, sizeof buffer, " No memory bank detected "); + add_item(buffer, "Memory Bank", OPT_INACTIVE, NULL, + menu->memory_sub_menu[1].menu); + menu->memory_menu.items_count++; + } else + for (i = 0; i < 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++; + } + + add_item("", "", OPT_SEP, "", 0); + + snprintf(buffer, sizeof buffer, " e820 "); + add_item(buffer, "e820 mapping", OPT_SUBMENU, NULL, + menu->memory_sub_menu[++i].menu); + menu->memory_menu.items_count++; + + snprintf(buffer, sizeof buffer, " e801 "); + add_item(buffer, "e801 information", OPT_SUBMENU, NULL, + menu->memory_sub_menu[++i].menu); + menu->memory_menu.items_count++; + + snprintf(buffer, sizeof buffer, " 88 "); + add_item(buffer, "88 information", OPT_SUBMENU, NULL, + menu->memory_sub_menu[++i].menu); + menu->memory_menu.items_count++; + + add_item("", "", OPT_SEP, "", 0); + printf("MENU: Memory menu done (%d items)\n", + menu->memory_menu.items_count); + add_item("Run Test", "Run Test", OPT_RUN, hardware->memtest_label, 0); +} diff --git a/contrib/syslinux-4.02/com32/hdt/hdt-menu-pci.c b/contrib/syslinux-4.02/com32/hdt/hdt-menu-pci.c new file mode 100644 index 0000000..734b744 --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-menu-pci.c @@ -0,0 +1,203 @@ +/* ----------------------------------------------------------------------- * + * + * 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 pci devices */ +static void compute_pci_device(struct s_my_menu *menu, + struct pci_device *pci_device, + int pci_bus, int pci_slot, int pci_func, + struct s_hardware *hardware) +{ + 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->irq > 0) && (pci_device->dev_info->irq < 255)) { + snprintf(buffer, sizeof buffer, "IRQ : %d", + pci_device->dev_info->irq); + snprintf(statbuffer, sizeof statbuffer, "IRQ : %d", + pci_device->dev_info->irq); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + } + + snprintf(buffer, sizeof buffer, "Latency : %d", + pci_device->dev_info->latency); + snprintf(statbuffer, sizeof statbuffer, "Latency : %d", + pci_device->dev_info->latency); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + memset(kernel_modules, 0, sizeof(kernel_modules)); + + 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++; + + if (hardware->is_pxe_valid == true) { + if ((hardware->pxe.pci_device != NULL) + && (hardware->pxe.pci_device == pci_device)) { + + snprintf(buffer, sizeof buffer, "MAC Addr: %s", + hardware->pxe.mac_addr); + snprintf(statbuffer, sizeof statbuffer, "MAC Address : %s", + hardware->pxe.mac_addr); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "PXE : %s", + "Current Boot device"); + snprintf(statbuffer, sizeof statbuffer, "PXE : %s", + "Current Boot device"); + 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, hardware); + 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", + __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/contrib/syslinux-4.02/com32/hdt/hdt-menu-processor.c b/contrib/syslinux-4.02/com32/hdt/hdt-menu-processor.c new file mode 100644 index 0000000..f303eb6 --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-menu-processor.c @@ -0,0 +1,287 @@ +/* ----------------------------------------------------------------------- * + * + * 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" + +static void show_flag(struct s_my_menu *menu, char *buffer, bool flag, + char *flag_name, bool flush) +{ + char output_buffer[SUBMENULEN + 1]; + char statbuffer[SUBMENULEN + 1]; + if ((((strlen(buffer) + strlen(flag_name)) > 35) && flag) || flush) { + snprintf(output_buffer, sizeof output_buffer, "Flags : %s", buffer); + snprintf(statbuffer, sizeof statbuffer, "Flags: %s", buffer); + add_item(output_buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + memset(buffer, 0, sizeof(buffer)); + if (flush) + return; + } + if (flag) + strcat(buffer, flag_name); +} + +/* 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, "CPU Cores : %d", hardware->cpu.num_cores); + snprintf(statbuffer, sizeof statbuffer, "Number of CPU cores: %d", + hardware->cpu.num_cores); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "L1 Cache : %dK + %dK (I+D)", + hardware->cpu.l1_instruction_cache_size, + hardware->cpu.l1_data_cache_size); + snprintf(statbuffer, sizeof statbuffer, + "L1 Cache Size: %dK + %dK (Instruction + Data)", + hardware->cpu.l1_instruction_cache_size, + hardware->cpu.l1_data_cache_size); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "L2 Cache : %dK", + hardware->cpu.l2_cache_size); + snprintf(statbuffer, sizeof statbuffer, "L2 Cache Size: %dK", + hardware->cpu.l2_cache_size); + 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++; + + snprintf(buffer, sizeof buffer, "Voltage : %d.%02d", + hardware->dmi.processor.voltage_mv / 1000, + hardware->dmi.processor.voltage_mv - + ((hardware->dmi.processor.voltage_mv / 1000) * 1000)); + snprintf(statbuffer, sizeof statbuffer, "Voltage (V) : %d.%02d", + hardware->dmi.processor.voltage_mv / 1000, + hardware->dmi.processor.voltage_mv - + ((hardware->dmi.processor.voltage_mv / 1000) * 1000)); + 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++; + + if ((hardware->cpu.flags.vmx) || (hardware->cpu.flags.svm)) { + snprintf(buffer, sizeof buffer, "Hw Virt. : Yes"); + snprintf(statbuffer, sizeof statbuffer, + "Hardware Virtualisation Capable: Yes"); + } else { + snprintf(buffer, sizeof buffer, "Hw Virt. : No"); + snprintf(statbuffer, sizeof statbuffer, + "Hardware Virtualisation Capabable : No"); + } + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + memset(buffer1, 0, sizeof(buffer1)); + show_flag(menu, buffer1, hardware->cpu.flags.fpu, "fpu ", false); + show_flag(menu, buffer1, hardware->cpu.flags.vme, "vme ", false); + show_flag(menu, buffer1, hardware->cpu.flags.de, "de ", false); + show_flag(menu, buffer1, hardware->cpu.flags.pse, "pse ", false); + show_flag(menu, buffer1, hardware->cpu.flags.tsc, "tsc ", false); + show_flag(menu, buffer1, hardware->cpu.flags.msr, "msr ", false); + show_flag(menu, buffer1, hardware->cpu.flags.pae, "pae ", false); + show_flag(menu, buffer1, hardware->cpu.flags.mce, "mce ", false); + show_flag(menu, buffer1, hardware->cpu.flags.cx8, "cx8 ", false); + show_flag(menu, buffer1, hardware->cpu.flags.apic, "apic ", false); + show_flag(menu, buffer1, hardware->cpu.flags.sep, "sep ", false); + show_flag(menu, buffer1, hardware->cpu.flags.mtrr, "mtrr ", false); + show_flag(menu, buffer1, hardware->cpu.flags.pge, "pge ", false); + show_flag(menu, buffer1, hardware->cpu.flags.mca, "mca ", false); + show_flag(menu, buffer1, hardware->cpu.flags.cmov, "cmov ", false); + show_flag(menu, buffer1, hardware->cpu.flags.pat, "pat ", false); + show_flag(menu, buffer1, hardware->cpu.flags.pse_36, "pse_36 ", false); + show_flag(menu, buffer1, hardware->cpu.flags.psn, "psn ", false); + show_flag(menu, buffer1, hardware->cpu.flags.clflsh, "clflsh ", false); + show_flag(menu, buffer1, hardware->cpu.flags.dts, "dts ", false); + show_flag(menu, buffer1, hardware->cpu.flags.acpi, "acpi ", false); + show_flag(menu, buffer1, hardware->cpu.flags.mmx, "mmx ", false); + show_flag(menu, buffer1, hardware->cpu.flags.sse, "sse ", false); + show_flag(menu, buffer1, hardware->cpu.flags.sse2, "sse2 ", false); + show_flag(menu, buffer1, hardware->cpu.flags.ss, "ss ", false); + show_flag(menu, buffer1, hardware->cpu.flags.htt, "ht ", false); + show_flag(menu, buffer1, hardware->cpu.flags.acc, "acc ", false); + show_flag(menu, buffer1, hardware->cpu.flags.syscall, "syscall ", false); + show_flag(menu, buffer1, hardware->cpu.flags.mp, "mp ", false); + show_flag(menu, buffer1, hardware->cpu.flags.nx, "nx ", false); + show_flag(menu, buffer1, hardware->cpu.flags.mmxext, "mmxext ", false); + show_flag(menu, buffer1, hardware->cpu.flags.lm, "lm ", false); + show_flag(menu, buffer1, hardware->cpu.flags.nowext, "3dnowext ", false); + show_flag(menu, buffer1, hardware->cpu.flags.now, "3dnow! ", false); + show_flag(menu, buffer1, hardware->cpu.flags.svm, "svm ", false); + show_flag(menu, buffer1, hardware->cpu.flags.vmx, "vmx ", false); + show_flag(menu, buffer1, hardware->cpu.flags.pbe, "pbe ", false); + show_flag(menu, buffer1, hardware->cpu.flags.fxsr_opt, "fxsr_opt ", false); + show_flag(menu, buffer1, hardware->cpu.flags.gbpages, "gbpages ", false); + show_flag(menu, buffer1, hardware->cpu.flags.rdtscp, "rdtscp ", false); + show_flag(menu, buffer1, hardware->cpu.flags.pni, "pni ", false); + show_flag(menu, buffer1, hardware->cpu.flags.pclmulqd, "pclmulqd ", false); + show_flag(menu, buffer1, hardware->cpu.flags.dtes64, "dtes64 ", false); + show_flag(menu, buffer1, hardware->cpu.flags.smx, "smx ", false); + show_flag(menu, buffer1, hardware->cpu.flags.est, "est ", false); + show_flag(menu, buffer1, hardware->cpu.flags.tm2, "tm2 ", false); + show_flag(menu, buffer1, hardware->cpu.flags.sse3, "sse3 ", false); + show_flag(menu, buffer1, hardware->cpu.flags.fma, "fma ", false); + show_flag(menu, buffer1, hardware->cpu.flags.cx16, "cx16 ", false); + show_flag(menu, buffer1, hardware->cpu.flags.xtpr, "xtpr ", false); + show_flag(menu, buffer1, hardware->cpu.flags.pdcm, "pdcm ", false); + show_flag(menu, buffer1, hardware->cpu.flags.dca, "dca ", false); + show_flag(menu, buffer1, hardware->cpu.flags.xmm4_1, "xmm4_1 ", false); + show_flag(menu, buffer1, hardware->cpu.flags.xmm4_2, "xmm4_2 ", false); + show_flag(menu, buffer1, hardware->cpu.flags.x2apic, "x2apic ", false); + show_flag(menu, buffer1, hardware->cpu.flags.movbe, "movbe ", false); + show_flag(menu, buffer1, hardware->cpu.flags.popcnt, "popcnt ", false); + show_flag(menu, buffer1, hardware->cpu.flags.aes, "aes ", false); + show_flag(menu, buffer1, hardware->cpu.flags.xsave, "xsave ", false); + show_flag(menu, buffer1, hardware->cpu.flags.osxsave, "osxsave ", false); + show_flag(menu, buffer1, hardware->cpu.flags.avx, "avx ", false); + show_flag(menu, buffer1, hardware->cpu.flags.hypervisor, "hypervisor ", + false); + show_flag(menu, buffer1, hardware->cpu.flags.ace2, "ace2 ", false); + show_flag(menu, buffer1, hardware->cpu.flags.ace2_en, "ace2_en ", false); + show_flag(menu, buffer1, hardware->cpu.flags.phe, "phe ", false); + show_flag(menu, buffer1, hardware->cpu.flags.phe_en, "phe_en ", false); + show_flag(menu, buffer1, hardware->cpu.flags.pmm, "pmm ", false); + show_flag(menu, buffer1, hardware->cpu.flags.pmm_en, "pmm_en ", false); + show_flag(menu, buffer1, hardware->cpu.flags.extapic, "extapic ", false); + show_flag(menu, buffer1, hardware->cpu.flags.cr8_legacy, "cr8_legacy ", + false); + show_flag(menu, buffer1, hardware->cpu.flags.abm, "abm ", false); + show_flag(menu, buffer1, hardware->cpu.flags.sse4a, "sse4a ", false); + show_flag(menu, buffer1, hardware->cpu.flags.misalignsse, "misalignsse ", + false); + show_flag(menu, buffer1, hardware->cpu.flags.nowprefetch, "3dnowprefetch ", + false); + show_flag(menu, buffer1, hardware->cpu.flags.osvw, "osvw ", false); + show_flag(menu, buffer1, hardware->cpu.flags.ibs, "ibs ", false); + show_flag(menu, buffer1, hardware->cpu.flags.sse5, "sse5 ", false); + show_flag(menu, buffer1, hardware->cpu.flags.skinit, "skinit ", false); + show_flag(menu, buffer1, hardware->cpu.flags.wdt, "wdt ", false); + show_flag(menu, buffer1, hardware->cpu.flags.ida, "ida ", false); + show_flag(menu, buffer1, hardware->cpu.flags.arat, "arat ", false); + show_flag(menu, buffer1, hardware->cpu.flags.tpr_shadow, "tpr_shadow ", + false); + show_flag(menu, buffer1, hardware->cpu.flags.vnmi, "vnmi ", false); + show_flag(menu, buffer1, hardware->cpu.flags.flexpriority, "flexpriority ", + false); + show_flag(menu, buffer1, hardware->cpu.flags.ept, "ept ", false); + show_flag(menu, buffer1, hardware->cpu.flags.vpid, "vpid ", false); + + /* Let's flush the remaining flags */ + show_flag(menu, buffer1, false, "", true); + + printf("MENU: Processor menu done (%d items)\n", menu->items_count); +} diff --git a/contrib/syslinux-4.02/com32/hdt/hdt-menu-pxe.c b/contrib/syslinux-4.02/com32/hdt/hdt-menu-pxe.c new file mode 100644 index 0000000..426bfe0 --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-menu-pxe.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" +#include <sys/gpxe.h> + +/* Main Kernel menu */ +void compute_PXE(struct s_my_menu *menu, struct s_hardware *hardware) +{ + char buffer[SUBMENULEN + 1]; + char infobar[STATLEN + 1]; + char gpxe[4]; + + 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) + || (p->pci_device == NULL)) { + 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++; + + if (is_gpxe()) strcat(gpxe,"Yes"); + else strcat (gpxe,"No"); + + snprintf(buffer, sizeof buffer, "gPXE Detected: %s", gpxe); + snprintf(infobar, sizeof infobar, "gPXE Detected: %s", gpxe); + 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/contrib/syslinux-4.02/com32/hdt/hdt-menu-summary.c b/contrib/syslinux-4.02/com32/hdt/hdt-menu-summary.c new file mode 100644 index 0000000..e9d56ca --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-menu-summary.c @@ -0,0 +1,195 @@ +/* ----------------------------------------------------------------------- * + * + * 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]; + + 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++; + + char features[SUBMENULEN + 1]; + memset(features, 0, sizeof(features)); + sprintf(features, "%d cores, %dK L2 Cache", hardware->cpu.num_cores, + hardware->cpu.l2_cache_size); + if (hardware->cpu.flags.lm) + strcat(features, ", 64bit"); + else + strcat(features, ", 32bit"); + if (hardware->cpu.flags.smp) + strcat(features, ", SMP "); + if (hardware->cpu.flags.vmx || hardware->cpu.flags.svm) + strcat(features, ", HwVIRT "); + snprintf(buffer, sizeof buffer, "%s", features); + snprintf(statbuffer, sizeof statbuffer, "Features : %s", features); + 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); + + snprintf(buffer, sizeof buffer, "Memory Size : %lu MiB (%lu KiB)", + (hardware->detected_memory_size + (1 << 9)) >> 10, + hardware->detected_memory_size); + snprintf(statbuffer, sizeof statbuffer, + "Detected Memory Size: %lu MiB (%lu KiB)", + (hardware->detected_memory_size + (1 << 9)) >> 10, + hardware->detected_memory_size); + 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++; + + if (hardware->is_pxe_valid == true) { + add_item("", "", OPT_SEP, "", 0); + + 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++; + } + + if (hardware->modules_pcimap_return_code != -ENOMODULESPCIMAP) { + add_item("", "", OPT_SEP, "", 0); + + 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", + 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; + } + } + } + + printf("MENU: Summary menu done (%d items)\n", menu->items_count); +} diff --git a/contrib/syslinux-4.02/com32/hdt/hdt-menu-syslinux.c b/contrib/syslinux-4.02/com32/hdt/hdt-menu-syslinux.c new file mode 100644 index 0000000..aaddf17 --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-menu-syslinux.c @@ -0,0 +1,82 @@ +/* ----------------------------------------------------------------------- * + * + * 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); + snprintf(statbuffer, sizeof statbuffer, "Version: %s", + hardware->sv->version_string); + 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); + /* Remove the trailing LF in the copyright string to avoid scrolling */ + snprintf(statbuffer, sizeof statbuffer, "%s", + remove_trailing_lf((char *)hardware->sv->copyright_string)); + 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/contrib/syslinux-4.02/com32/hdt/hdt-menu-vesa.c b/contrib/syslinux-4.02/com32/hdt/hdt-menu-vesa.c new file mode 100644 index 0000000..0fe06ab --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-menu-vesa.c @@ -0,0 +1,129 @@ +/* ----------------------------------------------------------------------- * + * + * 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" + +/* Submenu for the vesa card */ +static void compute_vesa_card(struct s_my_menu *menu, + struct s_hardware *hardware) +{ + char buffer[SUBMENULEN + 1]; + char statbuffer[STATLEN + 1]; + + menu->menu = add_menu(" VESA Bios ", -1); + menu->items_count = 0; + set_menu_pos(SUBMENU_Y, SUBMENU_X); + + snprintf(buffer, sizeof buffer, "VESA Version: %d.%d", + hardware->vesa.major_version, hardware->vesa.minor_version); + snprintf(statbuffer, sizeof statbuffer, "Version: %d.%d", + hardware->vesa.major_version, hardware->vesa.minor_version); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Vendor : %s", hardware->vesa.vendor); + snprintf(statbuffer, sizeof statbuffer, "Vendor Name: %s", + hardware->vesa.vendor); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Product : %s", hardware->vesa.product); + snprintf(statbuffer, sizeof statbuffer, "Product Name: %s", + hardware->vesa.product); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Product Rev.: %s", + hardware->vesa.product_revision); + snprintf(statbuffer, sizeof statbuffer, "Produt Revision: %s", + hardware->vesa.product_revision); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Software Rev: %d", + hardware->vesa.software_rev); + snprintf(statbuffer, sizeof statbuffer, "Software Revision: %d", + hardware->vesa.software_rev); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + snprintf(buffer, sizeof buffer, "Memory (KB) : %d", + hardware->vesa.total_memory * 64); + snprintf(statbuffer, sizeof statbuffer, "Memory (KB): %d", + hardware->vesa.total_memory * 64); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; +} + +/* Submenu for the vesa card */ +void compute_vesa_modes(struct s_my_menu *menu, struct s_hardware *hardware) +{ + char buffer[56]; + char statbuffer[STATLEN]; + + menu->menu = add_menu(" VESA Modes ", -1); + menu->items_count = 0; + set_menu_pos(SUBMENU_Y, SUBMENU_X); + for (int i = 0; i < hardware->vesa.vmi_count; i++) { + struct vesa_mode_info *mi = &hardware->vesa.vmi[i].mi; + /* Sometimes, vesa bios reports 0x0 modes + * We don't need to display that ones */ + if ((mi->h_res == 0) || (mi->v_res == 0)) + continue; + snprintf(buffer, sizeof buffer, "%4u x %4u x %2ubits vga=%3d", + mi->h_res, mi->v_res, mi->bpp, + hardware->vesa.vmi[i].mode + 0x200); + snprintf(statbuffer, sizeof statbuffer, "%4ux%4ux%2ubits vga=%3d", + mi->h_res, mi->v_res, mi->bpp, + hardware->vesa.vmi[i].mode + 0x200); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + } +} + +/* Main VESA Menu*/ +int compute_VESA(struct s_hdt_menu *hdt_menu, struct s_hardware *hardware) +{ + char buffer[15]; + compute_vesa_card(&hdt_menu->vesa_card_menu, hardware); + compute_vesa_modes(&hdt_menu->vesa_modes_menu, hardware); + hdt_menu->vesa_menu.menu = add_menu(" VESA ", -1); + hdt_menu->vesa_menu.items_count = 0; + + add_item("VESA Bios", "VESA Bios", OPT_SUBMENU, NULL, + hdt_menu->vesa_card_menu.menu); + hdt_menu->vesa_menu.items_count++; + snprintf(buffer, sizeof buffer, "%s (%d)", "Modes", + hardware->vesa.vmi_count); + add_item(buffer, "VESA Modes", OPT_SUBMENU, NULL, + hdt_menu->vesa_modes_menu.menu); + hdt_menu->vesa_menu.items_count++; + printf("MENU: VESA menu done (%d items)\n", + hdt_menu->vesa_menu.items_count); + return 0; +} diff --git a/contrib/syslinux-4.02/com32/hdt/hdt-menu-vpd.c b/contrib/syslinux-4.02/com32/hdt/hdt-menu-vpd.c new file mode 100644 index 0000000..d77a823 --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-menu-vpd.c @@ -0,0 +1,114 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer - 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_vpd - generate vpd menu + **/ +void compute_vpd(struct s_my_menu *menu, struct s_hardware *hardware) +{ + char buffer[SUBMENULEN + 1]; + char statbuffer[STATLEN + 1]; /* Status bar */ + + menu->menu = add_menu(" VPD ", -1); + menu->items_count = 0; + set_menu_pos(SUBMENU_Y, SUBMENU_X); + + snprintf(buffer, sizeof buffer, "Address : %s", + hardware->vpd.base_address); + snprintf(statbuffer, sizeof statbuffer, "Address: %s", + hardware->cpu.vendor); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + + if (strlen(hardware->vpd.bios_build_id) > 0) { + snprintf(buffer, sizeof buffer, "Bios Build ID : %s", + hardware->vpd.bios_build_id); + snprintf(statbuffer, sizeof statbuffer, "Bios Build ID: %s", + hardware->vpd.bios_build_id); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + } + + if (strlen(hardware->vpd.bios_release_date) > 0) { + snprintf(buffer, sizeof buffer, "Bios Release Date : %s", + hardware->vpd.bios_release_date); + snprintf(statbuffer, sizeof statbuffer, "Bios Release Date: %s", + hardware->vpd.bios_release_date); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + } + + if (strlen(hardware->vpd.bios_version) > 0) { + snprintf(buffer, sizeof buffer, "Bios Version : %s", + hardware->vpd.bios_version); + snprintf(statbuffer, sizeof statbuffer, "Bios Version: %s", + hardware->vpd.bios_version); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + } + + if (strlen(hardware->vpd.default_flash_filename) > 0) { + snprintf(buffer, sizeof buffer, "Default Flash Filename : %s", + hardware->vpd.default_flash_filename); + snprintf(statbuffer, sizeof statbuffer, "Default Flash Filename: %s", + hardware->vpd.default_flash_filename); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + } + + if (strlen(hardware->vpd.box_serial_number) > 0) { + snprintf(buffer, sizeof buffer, "Box Serial Number : %s", + hardware->vpd.box_serial_number); + snprintf(statbuffer, sizeof statbuffer, "Box Serial Number: %s", + hardware->vpd.box_serial_number); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + } + + if (strlen(hardware->vpd.motherboard_serial_number) > 0) { + snprintf(buffer, sizeof buffer, "Motherboard Serial Number: %s", + hardware->vpd.motherboard_serial_number); + snprintf(statbuffer, sizeof statbuffer, "Motherboard Serial Number: %s", + hardware->vpd.motherboard_serial_number); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + } + + if (strlen(hardware->vpd.machine_type_model) > 0) { + snprintf(buffer, sizeof buffer, "Machine Type/Model : %s", + hardware->vpd.machine_type_model); + snprintf(statbuffer, sizeof statbuffer, "Machine Type/Model: %s", + hardware->vpd.machine_type_model); + add_item(buffer, statbuffer, OPT_INACTIVE, NULL, 0); + menu->items_count++; + } + + printf("MENU: VPD menu done (%d items)\n", menu->items_count); +} diff --git a/contrib/syslinux-4.02/com32/hdt/hdt-menu.c b/contrib/syslinux-4.02/com32/hdt/hdt-menu.c new file mode 100644 index 0000000..219f698 --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-menu.c @@ -0,0 +1,337 @@ +/* ----------------------------------------------------------------------- * + * + * 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 <unistd.h> +#include <memory.h> +#include <syslinux/reboot.h> +#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 submenus */ + compute_submenus(&hdt_menu, hardware); + + /* Compute the main menu */ + compute_main_menu(&hdt_menu, hardware); + +#ifdef WITH_MENU_DISPLAY + t_menuitem *curr; + char cmd[160]; + + if (!quiet) + more_printf("Starting Menu (%d menus)\n", hdt_menu.total_menu_count); + curr = showmenus(hdt_menu.main_menu.menu); + /* When we exit the menu, do we have something to do? */ + if (curr) { + /* 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; + } + if (!strncmp + (curr->data, HDT_REBOOT, sizeof(HDT_REBOOT))) { + syslinux_reboot(1); + } + 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(void) +{ + // beep(); + return CODE_WAIT; +} + +/* Keyboard handler for the menu system */ +void keys_handler(t_menusystem * ms + __attribute__ ((unused)), t_menuitem * mi, int scancode) +{ + int nr, nc; + + /* 0xFFFF is an invalid helpid */ + if (scancode == KEY_F1 && mi->helpid != 0xFFFF) { + runhelpsystem(mi->helpid); + } + + /* + * If user hit TAB, and item is an "executable" item + * and user has privileges to edit it, edit it in place. + */ + if ((scancode == KEY_TAB) && (mi->action == OPT_RUN)) { +//(isallowed(username,"editcmd") || isallowed(username,"root"))) { + if (getscreensize(1, &nr, &nc)) { + /* Unknown screen size? */ + nc = 80; + nr = 24; + } + /* User typed TAB and has permissions to edit command line */ + gotoxy(EDITPROMPT, 1); + csprint("Command line:", 0x07); + editstring(mi->data, ACTIONLEN); + gotoxy(EDITPROMPT, 1); + cprint(' ', 0x07, nc - 1); + } +} + +/* Setup the Menu system */ +void setup_menu(char *version) +{ + /* Creating the menu */ + init_menusystem(version); + set_window_size(0, 0, 25, 80); + + /* Do not use inactive attributes - they make little sense for HDT */ + set_normal_attr(-1, -1, 0x17, 0x1F); + + /* Register the menusystem handler */ + // reg_handler(HDLR_SCREEN,&msys_handler); + reg_handler(HDLR_KEYS, &keys_handler); + + /* 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 menu if a DMI table exists */ + if (hardware->is_dmi_valid) { + if (hardware->dmi.ipmi.filled == true) + compute_ipmi(&hdt_menu->ipmi_menu, &hardware->dmi); + 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)); + compute_memory(hdt_menu, &(hardware->dmi), hardware); + 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_vpd(&(hdt_menu->vpd_menu), hardware); + compute_disks(hdt_menu, hardware); + +#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_VESA(hdt_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 menus 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; + } + + snprintf(menu_item, sizeof(menu_item), "<M>emory\n"); + 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->dmi.ipmi.filled == true) { + add_item("I<P>MI", "IPMI Menu", OPT_SUBMENU, NULL, + hdt_menu->ipmi_menu.menu); + hdt_menu->main_menu.items_count++; + } + } + + if (hardware->is_vpd_valid == true) { + add_item("<V>PD", "VPD Information Menu", OPT_SUBMENU, NULL, + hdt_menu->vpd_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++; + } + + if (hardware->is_vesa_valid == true) { + add_item("<V>ESA", "VESA Information Menu", OPT_SUBMENU, NULL, + hdt_menu->vesa_menu.menu); + hdt_menu->main_menu.items_count++; + } + + add_item("", "", OPT_SEP, "", 0); +#ifdef WITH_PCI + if ((hardware->modules_pcimap_return_code != -ENOMODULESPCIMAP) || + (hardware->modules_alias_return_code != -ENOMODULESALIAS)) { + 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<y>slinux", "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); + add_item("<R>eboot", "Reboot", OPT_RUN, HDT_REBOOT, 0); + add_item("E<x>it", "Exit", OPT_EXITMENU, NULL, 0); + hdt_menu->main_menu.items_count++; + + hdt_menu->total_menu_count += hdt_menu->main_menu.items_count; +} + +void detect_hardware(struct s_hardware *hardware) +{ + if (!quiet) + more_printf("MEMORY: Detecting\n"); + detect_memory(hardware); + + if (!quiet) + more_printf("DMI: Detecting Table\n"); + if (detect_dmi(hardware) == -ENODMITABLE) { + printf("DMI: ERROR ! Table not found ! \n"); + printf("DMI: Many hardware components will not be detected ! \n"); + } else { + if (!quiet) + more_printf("DMI: Table found ! (version %u.%u)\n", + hardware->dmi.dmitable.major_version, + hardware->dmi.dmitable.minor_version); + } + + if (!quiet) + more_printf("CPU: Detecting\n"); + cpu_detect(hardware); + + if (!quiet) + more_printf("DISKS: Detecting\n"); + detect_disks(hardware); + + if (!quiet) + more_printf("VPD: Detecting\n"); + detect_vpd(hardware); + +#ifdef WITH_PCI + detect_pci(hardware); + if (!quiet) + more_printf("PCI: %d Devices Found\n", hardware->nb_pci_devices); +#endif + if (!quiet) + more_printf("VESA: Detecting\n"); + detect_vesa(hardware); +} diff --git a/contrib/syslinux-4.02/com32/hdt/hdt-menu.h b/contrib/syslinux-4.02/com32/hdt/hdt-menu.h new file mode 100644 index 0000000..c8c9124 --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-menu.h @@ -0,0 +1,135 @@ +/* ----------------------------------------------------------------------- * + * + * 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 <getkey.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 ipmi_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; + struct s_my_menu vesa_menu; + struct s_my_menu vesa_card_menu; + struct s_my_menu vesa_modes_menu; + struct s_my_menu vpd_menu; + int total_menu_count; // Sum of all menus we have +}; + +TIMEOUTCODE ontimeout(void); +void keys_handler(t_menusystem * ms + __attribute__ ((unused)), t_menuitem * mi, int scancode); + +// PCI Stuff +int compute_PCI(struct s_hdt_menu *hdt_menu, struct s_hardware *hardware); + +// KERNEL Stuff +void compute_kernel(struct s_my_menu *menu, struct s_hardware *hardware); + +// Disk Stuff +void compute_disks(struct s_hdt_menu *menu, struct s_hardware *hardware); + +// DMI Stuff +void compute_motherboard(struct s_my_menu *menu, s_dmi * dmi); +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, + struct s_hardware *hardware); +void compute_ipmi(struct s_my_menu *menu, s_dmi * dmi); + +// VPD Stuff +void compute_vpd(struct s_my_menu *menu, struct s_hardware *hardware); + +// 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); + +//VESA menu +int compute_VESA(struct s_hdt_menu *hdt_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/contrib/syslinux-4.02/com32/hdt/hdt-util.c b/contrib/syslinux-4.02/com32/hdt/hdt-util.c new file mode 100644 index 0000000..3b41a91 --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-util.c @@ -0,0 +1,93 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer - 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 <stdio.h> +#include <string.h> + +/* Computing div(x,y) */ +#define sub(val) (((val%1024)*100)>>10) +#define sub_dec(val) (((val%1000)*100)/1000) + +void sectors_to_size(int sectors, char *buffer) +{ + int b = (sectors / 2); + int mib = b >> 10; + int gib = mib >> 10; + int tib = gib >> 10; + + if (tib > 0) + sprintf(buffer, "%3d.%02d TiB", tib,sub(gib)); + else if (gib > 0) + sprintf(buffer, "%3d.%02d GiB", gib,sub(mib)); + else if (mib > 0) + sprintf(buffer, "%3d.%02d MiB", mib,sub(b)); + else + sprintf(buffer, "%d B", b); +} + +void sectors_to_size_dec(char *previous_unit, int *previous_size, char *unit, + int *size, int sectors) +{ + *size = 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); + } + } + } +} + +void sectors_to_size_dec2(int sectors, char *buffer) +{ + int b = (sectors / 2); + int mib = b / 1000; + int gib = mib / 1000; + int tib = gib / 1000; + + if (tib > 0) + sprintf(buffer, "%3d.%02d TB", tib,sub_dec(gib)); + else if (gib > 0) + sprintf(buffer, "%3d.%02d GB", gib,sub_dec(mib)); + else if (mib > 0) + sprintf(buffer, "%3d.%02d MB", mib,sub_dec(b)); + else + sprintf(buffer, "%d B", b); +} diff --git a/contrib/syslinux-4.02/com32/hdt/hdt-util.h b/contrib/syslinux-4.02/com32/hdt/hdt-util.h new file mode 100644 index 0000000..9e3769e --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt-util.h @@ -0,0 +1,34 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer - 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_UTIL_H +#define DEFINE_HDT_UTIL_H +void sectors_to_size(int, char *); +void sectors_to_size_dec(char *, int *, char *, int *, int); +void sectors_to_size_dec2(int sectors, char *buffer); +#endif diff --git a/contrib/syslinux-4.02/com32/hdt/hdt.c b/contrib/syslinux-4.02/com32/hdt/hdt.c new file mode 100644 index 0000000..1a438a3 --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt.c @@ -0,0 +1,86 @@ +/* ----------------------------------------------------------------------- * + * + * 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 "hdt.h" +#include "hdt-cli.h" +#include "hdt-menu.h" +#include "hdt-common.h" + +int display_line_nb = 0; +bool disable_more_printf = false; + +/* Defines the number of lines in the console + * Default is 20 for a std console */ +int max_console_lines = MAX_CLI_LINES; + +int main(const int argc, const char *argv[]) +{ + char version_string[256]; + const char *arg; + struct s_hardware hardware; + + snprintf(version_string, sizeof version_string, "%s %s (%s)", + PRODUCT_NAME, VERSION, CODENAME); + + /* Cleaning structures */ + init_hardware(&hardware); + + /* Detecting Syslinux version */ + detect_syslinux(&hardware); + + /* Detecting parameters */ + detect_parameters(argc, argv, &hardware); + + /* Opening the Syslinux console */ + init_console(&hardware); + + /* Clear the screen and reset position of the cursor */ + clear_screen(); + printf("\033[1;1H"); + + printf("%s\n", version_string); + + if ((arg = find_argument(argv + 1, "nomenu")) + || (find_argument(argv + 1, "auto"))) + start_cli_mode(&hardware); + else { + int return_code = start_menu_mode(&hardware, version_string); + if (return_code == HDT_RETURN_TO_CLI) + start_cli_mode(&hardware); + else + return return_code; + } + return 0; +} diff --git a/contrib/syslinux-4.02/com32/hdt/hdt.h b/contrib/syslinux-4.02/com32/hdt/hdt.h new file mode 100644 index 0000000..0c7535d --- /dev/null +++ b/contrib/syslinux-4.02/com32/hdt/hdt.h @@ -0,0 +1,47 @@ +/* ----------------------------------------------------------------------- * + * + * 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 CORE_DEVELOPER "Pierre-Alexandre Meyer" +#define CONTACT "hdt@zytor.com" +#define VERSION "0.3.6.1" +#define CODENAME "cachaca" +#define NB_CONTRIBUTORS 3 +#define CONTRIBUTORS {"Sebastien Gonzalve (Patches)", "Gert Hulselmans (Tests)", "Alexander Andino (Design)"} +#define WEBSITE_URL "http://hdt-project.org" + +#define ATTR_PACKED __attribute__((packed)) + +#define WITH_PCI 1 +#define WITH_MENU_DISPLAY 1 + +#endif diff --git a/contrib/syslinux-4.02/com32/include/alloca.h b/contrib/syslinux-4.02/com32/include/alloca.h new file mode 100644 index 0000000..8c4067f --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/alloca.h @@ -0,0 +1,12 @@ +/* + * alloca.h + * + * Just call the builtin alloca() function + */ + +#ifndef _ALLOCA_H +#define _ALLOCA_H + +#define alloca(size) __builtin_alloca(size) + +#endif /* _ALLOCA_H */ diff --git a/contrib/syslinux-4.02/com32/include/assert.h b/contrib/syslinux-4.02/com32/include/assert.h new file mode 100644 index 0000000..b303bb9 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/assert.h @@ -0,0 +1,7 @@ +#ifndef _ASSERT_H +#define _ASSERT_H + +/* Assert not currently supported */ +#define assert(X) ((void)0) + +#endif /* _ASSERT_H */ diff --git a/contrib/syslinux-4.02/com32/include/bitsize/limits.h b/contrib/syslinux-4.02/com32/include/bitsize/limits.h new file mode 100644 index 0000000..f90e524 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/bitsize/limits.h @@ -0,0 +1,14 @@ +/* + * bits32/limits.h + */ + +#ifndef _BITSIZE_LIMITS_H +#define _BITSIZE_LIMITS_H + +#define LONG_BIT 32 + +#define LONG_MIN (-2147483647L-1) +#define LONG_MAX 2147483647L +#define ULONG_MAX 4294967295UL + +#endif /* _BITSIZE_LIMITS_H */ diff --git a/contrib/syslinux-4.02/com32/include/bitsize/stddef.h b/contrib/syslinux-4.02/com32/include/bitsize/stddef.h new file mode 100644 index 0000000..caa5e72 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/bitsize/stddef.h @@ -0,0 +1,18 @@ +/* + * bits32/stddef.h + */ + +#ifndef _BITSIZE_STDDEF_H +#define _BITSIZE_STDDEF_H + +#define _SIZE_T +#if defined(__s390__) || defined(__hppa__) || defined(__cris__) +typedef unsigned long size_t; +#else +typedef unsigned int size_t; +#endif + +#define _PTRDIFF_T +typedef signed int ptrdiff_t; + +#endif /* _BITSIZE_STDDEF_H */ diff --git a/contrib/syslinux-4.02/com32/include/bitsize/stdint.h b/contrib/syslinux-4.02/com32/include/bitsize/stdint.h new file mode 100644 index 0000000..8cbfc5d --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/bitsize/stdint.h @@ -0,0 +1,34 @@ +/* + * bits32/stdint.h + */ + +#ifndef _BITSIZE_STDINT_H +#define _BITSIZE_STDINT_H + +typedef signed char int8_t; +typedef short int int16_t; +typedef int int32_t; +typedef long long int int64_t; + +typedef unsigned char uint8_t; +typedef unsigned short int uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long int uint64_t; + +typedef int int_fast16_t; +typedef int int_fast32_t; + +typedef unsigned int uint_fast16_t; +typedef unsigned int uint_fast32_t; + +typedef int intptr_t; +typedef unsigned int uintptr_t; + +#define __INT64_C(c) c ## LL +#define __UINT64_C(c) c ## ULL + +#define __PRI64_RANK "ll" +#define __PRIFAST_RANK "" +#define __PRIPTR_RANK "" + +#endif /* _BITSIZE_STDINT_H */ diff --git a/contrib/syslinux-4.02/com32/include/bitsize/stdintconst.h b/contrib/syslinux-4.02/com32/include/bitsize/stdintconst.h new file mode 100644 index 0000000..8157dd0 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/bitsize/stdintconst.h @@ -0,0 +1,18 @@ +/* + * bits32/stdintconst.h + */ + +#ifndef _BITSIZE_STDINTCONST_H +#define _BITSIZE_STDINTCONST_H + +#define INT_FAST16_C(c) INT32_C(c) +#define INT_FAST32_C(c) INT32_C(c) + +#define UINT_FAST16_C(c) UINT32_C(c) +#define UINT_FAST32_C(c) UINT32_C(c) + +#define INTPTR_C(c) INT32_C(c) +#define UINTPTR_C(c) UINT32_C(c) +#define PTRDIFF_C(c) INT32_C(c) + +#endif /* _BITSIZE_STDINTCONST_H */ diff --git a/contrib/syslinux-4.02/com32/include/bitsize/stdintlimits.h b/contrib/syslinux-4.02/com32/include/bitsize/stdintlimits.h new file mode 100644 index 0000000..b44fe01 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/bitsize/stdintlimits.h @@ -0,0 +1,22 @@ +/* + * bits32/stdintlimits.h + */ + +#ifndef _BITSIZE_STDINTLIMITS_H +#define _BITSIZE_STDINTLIMITS_H + +#define INT_FAST16_MIN INT32_MIN +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST16_MAX INT32_MAX +#define INT_FAST32_MAX INT32_MAX +#define UINT_FAST16_MAX UINT32_MAX +#define UINT_FAST32_MAX UINT32_MAX + +#define INTPTR_MIN INT32_MIN +#define INTPTR_MAX INT32_MAX +#define UINTPTR_MAX UINT32_MAX + +#define PTRDIFF_MIN INT32_MIN +#define PTRDIFF_MAX INT32_MAX + +#endif /* _BITSIZE_STDINTLIMITS_H */ diff --git a/contrib/syslinux-4.02/com32/include/colortbl.h b/contrib/syslinux-4.02/com32/include/colortbl.h new file mode 100644 index 0000000..e9f0a12 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/colortbl.h @@ -0,0 +1,53 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2006-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. + * + * ----------------------------------------------------------------------- */ + +#ifndef _COLORTBL_H +#define _COLORTBL_H + +/* Attribute/color table used by ansicon and vesacon to abstract + out the color selection. */ + +/* Note: vesacon relies on the encoding of these numbers */ +enum color_table_shadow { + SHADOW_NONE = 0, + SHADOW_ALL = 1, + SHADOW_NORMAL = 2, + SHADOW_REVERSE = 3, +}; + +struct color_table { + const char *name; /* Attribute name (used for customization) */ + const char *ansi; /* ANSI attribute */ + unsigned int argb_fg; /* ARGB for foreground */ + unsigned int argb_bg; /* ARGB for background */ + enum color_table_shadow shadow; /* Shadow mode */ +}; + +extern struct color_table *console_color_table; +extern int console_color_table_size; + +#endif /* _COLORTBL_H */ diff --git a/contrib/syslinux-4.02/com32/include/com32.h b/contrib/syslinux-4.02/com32/include/com32.h new file mode 100644 index 0000000..6b14208 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/com32.h @@ -0,0 +1,197 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2002-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * com32.h + * + * Common declarations for com32 programs. + */ + +#ifndef _COM32_H +#define _COM32_H + +#include <stdint.h> +#include <stdbool.h> +#include <stddef.h> +#include <klibc/compiler.h> /* For __cdecl */ + +/* + * This structure defines the register frame used by the + * system call interface. + * + * The syscall interface is: + * + * __intcall(interrupt_#, source_regs, return_regs) + * __farcall(seg, offs, source_regs, return_regs) + */ +typedef union { + uint32_t l; + uint16_t w[2]; + uint8_t b[4]; +} reg32_t; + +typedef struct { + uint16_t gs; /* Offset 0 */ + uint16_t fs; /* Offset 2 */ + uint16_t es; /* Offset 4 */ + uint16_t ds; /* Offset 6 */ + + reg32_t edi; /* Offset 8 */ + reg32_t esi; /* Offset 12 */ + reg32_t ebp; /* Offset 16 */ + reg32_t _unused_esp; /* Offset 20 */ + reg32_t ebx; /* Offset 24 */ + reg32_t edx; /* Offset 28 */ + reg32_t ecx; /* Offset 32 */ + reg32_t eax; /* Offset 36 */ + + reg32_t eflags; /* Offset 40 */ +} com32sys_t; + +/* EFLAGS definitions */ +#define EFLAGS_CF 0x00000001 +#define EFLAGS_PF 0x00000004 +#define EFLAGS_AF 0x00000010 +#define EFLAGS_ZF 0x00000040 +#define EFLAGS_SF 0x00000080 +#define EFLAGS_TF 0x00000100 +#define EFLAGS_IF 0x00000200 +#define EFLAGS_DF 0x00000400 +#define EFLAGS_OF 0x00000800 +#define EFLAGS_IOPL 0x00003000 +#define EFLAGS_NT 0x00004000 +#define EFLAGS_RF 0x00010000 +#define EFLAGS_VM 0x00020000 +#define EFLAGS_AC 0x00040000 +#define EFLAGS_VIF 0x00080000 +#define EFLAGS_VIP 0x00100000 +#define EFLAGS_ID 0x00200000 + +struct com32_pmapi; + +extern struct com32_sys_args { + uint32_t cs_sysargs; + char *cs_cmdline; + void __cdecl (*cs_intcall)(uint8_t, const com32sys_t *, com32sys_t *); + void *cs_bounce; + uint32_t cs_bounce_size; + void __cdecl (*cs_farcall)(uint32_t, const com32sys_t *, com32sys_t *); + int __cdecl (*cs_cfarcall)(uint32_t, const void *, uint32_t); + uint32_t cs_memsize; + const char *cs_name; + const struct com32_pmapi *cs_pm; +} __com32; + +/* + * System call wrapper functions + */ +void __intcall(uint8_t __i, const com32sys_t * __sr, com32sys_t * __dr); +void __farcall(uint16_t __cs, uint16_t __ip, + const com32sys_t * __sr, com32sys_t * __dr); +int __cfarcall(uint16_t __cs, uint16_t __ip, + const void *__stack, uint32_t __stack_size); +extern const com32sys_t __com32_zero_regs; + +/* + * Lowmem allocation functions + */ +void *lmalloc(size_t); +void *lzalloc(size_t); +void lfree(void *); +char *lstrdup(const char *); + +/* + * These functions convert between linear pointers in the range + * 0..0xFFFFF and real-mode style SEG:OFFS pointers. Note that a + * 32-bit linear pointer is not compatible with a SEG:OFFS pointer + * stored in two consecutive 16-bit words. + * + * Use OFFS_WRT() if you want to compute an offset relative to a + * specific segment. OFFS_VALID() will return whether or not the + * pointer is actually reachable from the target segment. + */ +static inline uint16_t SEG(const volatile void *__p) +{ + return (uint16_t) (((uintptr_t) __p) >> 4); +} + +static inline uint16_t OFFS(const volatile void *__p) +{ + /* The double cast here is to shut up gcc */ + return (uint16_t) (uintptr_t) __p & 0x000F; +} + +static inline uint16_t OFFS_WRT(const volatile void *__p, uint16_t __seg) +{ + return (uint16_t) ((uintptr_t) __p - ((uintptr_t) __seg << 4)); +} + +#define OFFS_VALID(p,s) _OFFS_VALID((p), sizeof *(p), (s)) + +static inline bool _OFFS_VALID(const volatile void *__p, size_t __s, + uint16_t __seg) +{ + uintptr_t __segstart = (uintptr_t)__seg << 4; + uintptr_t __offs = (uintptr_t)__p - __segstart; + + return __offs <= 0x10000-__s; +} + +static inline void *MK_PTR(uint16_t __seg, uint16_t __offs) +{ + return (void *)((__seg << 4) + __offs); +} + +/* Some tools to handle 16:16 far pointers in memory */ + +struct __far_ptr { + union { + uint32_t ptr; + struct { + uint16_t offs, seg; + }; + }; +} __attribute__ ((packed)); + +typedef struct __far_ptr far_ptr_t; + +static inline void *GET_PTR(far_ptr_t __fptr) +{ + return MK_PTR(__fptr.seg, __fptr.offs); +} + +static inline far_ptr_t FAR_PTR(void *__ptr) +{ + far_ptr_t __fptr; + + __fptr.offs = OFFS(__ptr); + __fptr.seg = SEG(__ptr); + return __fptr; +} + +#endif /* _COM32_H */ diff --git a/contrib/syslinux-4.02/com32/include/console.h b/contrib/syslinux-4.02/com32/include/console.h new file mode 100644 index 0000000..74e68f1 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/console.h @@ -0,0 +1,63 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * console.h + * + * Alternative consoles + */ + +#ifndef _CONSOLE_H +#define _CONSOLE_H + +#include <klibc/extern.h> +#include <dev.h> + +__extern int openconsole(const struct input_dev *, const struct output_dev *); + +/* Standard line-oriented console */ +extern const struct input_dev dev_stdcon_r; +extern const struct output_dev dev_stdcon_w; +/* Raw character-oriented console */ +extern const struct input_dev dev_rawcon_r; +extern const struct output_dev dev_rawcon_w; + +/* These are output-only consoles; combine with one of the input methods */ + +/* Serial port only */ +extern const struct output_dev dev_serial_w; +/* ANSI console (output only; combine with one of the input methods) */ +extern const struct output_dev dev_ansicon_w; +/* ANSI plus serial port */ +extern const struct output_dev dev_ansiserial_w; + +/* VESA graphics console (output only) */ +extern const struct output_dev dev_vesacon_w; +/* VESA plus serial port */ +extern const struct output_dev dev_vesaserial_w; + +#endif /* _CONSOLE_H */ diff --git a/contrib/syslinux-4.02/com32/include/cpufeature.h b/contrib/syslinux-4.02/com32/include/cpufeature.h new file mode 100644 index 0000000..df9dd3d --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/cpufeature.h @@ -0,0 +1,152 @@ +/* + * cpufeature.h + * + * Defines x86 CPU feature bits + */ + +#ifndef __ASM_I386_CPUFEATURE_H +#define __ASM_I386_CPUFEATURE_H + +#define NCAPINTS 7 /* N 32-bit words worth of info */ + +/* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */ +#define X86_FEATURE_FPU (0*32+ 0) /* Onboard FPU */ +#define X86_FEATURE_VME (0*32+ 1) /* Virtual Mode Extensions */ +#define X86_FEATURE_DE (0*32+ 2) /* Debugging Extensions */ +#define X86_FEATURE_PSE (0*32+ 3) /* Page Size Extensions */ +#define X86_FEATURE_TSC (0*32+ 4) /* Time Stamp Counter */ +#define X86_FEATURE_MSR (0*32+ 5) /* Model-Specific Registers, RDMSR, WRMSR */ +#define X86_FEATURE_PAE (0*32+ 6) /* Physical Address Extensions */ +#define X86_FEATURE_MCE (0*32+ 7) /* Machine Check Architecture */ +#define X86_FEATURE_CX8 (0*32+ 8) /* CMPXCHG8 instruction */ +#define X86_FEATURE_APIC (0*32+ 9) /* Onboard APIC */ +#define X86_FEATURE_SEP (0*32+11) /* SYSENTER/SYSEXIT */ +#define X86_FEATURE_MTRR (0*32+12) /* Memory Type Range Registers */ +#define X86_FEATURE_PGE (0*32+13) /* Page Global Enable */ +#define X86_FEATURE_MCA (0*32+14) /* Machine Check Architecture */ +#define X86_FEATURE_CMOV (0*32+15) /* CMOV instruction (FCMOVCC and FCOMI too if FPU present) */ +#define X86_FEATURE_PAT (0*32+16) /* Page Attribute Table */ +#define X86_FEATURE_PSE36 (0*32+17) /* 36-bit PSEs */ +#define X86_FEATURE_PN (0*32+18) /* Processor serial number */ +#define X86_FEATURE_CLFLSH (0*32+19) /* Supports the CLFLUSH instruction */ +#define X86_FEATURE_DTES (0*32+21) /* Debug Trace Store */ +#define X86_FEATURE_ACPI (0*32+22) /* ACPI via MSR */ +#define X86_FEATURE_MMX (0*32+23) /* Multimedia Extensions */ +#define X86_FEATURE_FXSR (0*32+24) /* FXSAVE and FXRSTOR instructions (fast save and restore */ + /* of FPU context), and CR4.OSFXSR available */ +#define X86_FEATURE_XMM (0*32+25) /* Streaming SIMD Extensions */ +#define X86_FEATURE_XMM2 (0*32+26) /* Streaming SIMD Extensions-2 */ +#define X86_FEATURE_SELFSNOOP (0*32+27) /* CPU self snoop */ +#define X86_FEATURE_HT (0*32+28) /* Hyper-Threading */ +#define X86_FEATURE_ACC (0*32+29) /* Automatic clock control */ +#define X86_FEATURE_IA64 (0*32+30) /* IA-64 processor */ +#define X86_FEATURE_PBE (0*32+31) /* Pending Break Enable */ + +/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */ +/* Don't duplicate feature flags which are redundant with Intel! */ +#define X86_FEATURE_SYSCALL (1*32+11) /* SYSCALL/SYSRET */ +#define X86_FEATURE_MP (1*32+19) /* MP Capable. */ +#define X86_FEATURE_NX (1*32+20) /* Execute Disable */ +#define X86_FEATURE_MMXEXT (1*32+22) /* AMD MMX extensions */ +#define X86_FEATURE_FXSR_OPT (1*32+25) /* FXSAVE/FXRSTOR optimizations */ +#define X86_FEATURE_GBPAGES (1*32+26) /* "pdpe1gb" GB pages */ +#define X86_FEATURE_RDTSCP (1*32+27) /* RDTSCP */ +#define X86_FEATURE_LM (1*32+29) /* Long Mode (x86-64) */ +#define X86_FEATURE_3DNOWEXT (1*32+30) /* AMD 3DNow! extensions */ +#define X86_FEATURE_3DNOW (1*32+31) /* 3DNow! */ + +/* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */ +#define X86_FEATURE_RECOVERY (2*32+ 0) /* CPU in recovery mode */ +#define X86_FEATURE_LONGRUN (2*32+ 1) /* Longrun power control */ +#define X86_FEATURE_LRTI (2*32+ 3) /* LongRun table interface */ + +/* Other features, Linux-defined mapping, word 3 */ +/* This range is used for feature bits which conflict or are synthesized */ +#define X86_FEATURE_CXMMX (3*32+ 0) /* Cyrix MMX extensions */ +#define X86_FEATURE_K6_MTRR (3*32+ 1) /* AMD K6 nonstandard MTRRs */ +#define X86_FEATURE_CYRIX_ARR (3*32+ 2) /* Cyrix ARRs (= MTRRs) */ +#define X86_FEATURE_CENTAUR_MCR (3*32+ 3) /* Centaur MCRs (= MTRRs) */ +/* cpu types for specific tunings: */ +#define X86_FEATURE_K8 (3*32+ 4) /* Opteron, Athlon64 */ +#define X86_FEATURE_K7 (3*32+ 5) /* Athlon */ +#define X86_FEATURE_P3 (3*32+ 6) /* P3 */ +#define X86_FEATURE_P4 (3*32+ 7) /* P4 */ + +/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ +#define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */ +#define X86_FEATURE_PCLMULQDQ (4*32+ 1) /* PCLMULQDQ instruction */ +#define X86_FEATURE_DTES64 (4*32+ 2) /* 64-bit Debug Store */ +#define X86_FEATURE_MWAIT (4*32+ 3) /* Monitor/Mwait support */ +#define X86_FEATURE_DSCPL (4*32+ 4) /* CPL Qualified Debug Store */ +#define X86_FEATURE_VMX (4*32+ 5) /* Hardware virtualization */ +#define X86_FEATURE_SMX (4*32+ 6) /* Safer mode */ +#define X86_FEATURE_EST (4*32+ 7) /* Enhanced SpeedStep */ +#define X86_FEATURE_TM2 (4*32+ 8) /* Thermal Monitor 2 */ +#define X86_FEATURE_SSE3 (4*32+ 9) /* Supplemental SSE-3 */ +#define X86_FEATURE_CID (4*32+10) /* Context ID */ +#define X86_FEATURE_FMA (4*32+12) /* Fused multiply-add */ +#define X86_FEATURE_CX16 (4*32+13) /* CMPXCHG16B */ +#define X86_FEATURE_XTPR (4*32+14) /* Send Task Priority Messages */ +#define X86_FEATURE_PDCM (4*32+15) /* Performance Capabilities */ +#define X86_FEATURE_DCA (4*32+18) /* Direct Cache Access */ +#define X86_FEATURE_XMM4_1 (4*32+19) /* "sse4_1" SSE-4.1 */ +#define X86_FEATURE_XMM4_2 (4*32+20) /* "sse4_2" SSE-4.2 */ +#define X86_FEATURE_X2APIC (4*32+21) /* x2APIC */ +#define X86_FEATURE_MOVBE (4*32+22) /* MOVBE instruction */ +#define X86_FEATURE_POPCNT (4*32+23) /* POPCNT instruction */ +#define X86_FEATURE_AES (4*32+25) /* AES instructions */ +#define X86_FEATURE_XSAVE (4*32+26) /* XSAVE/XRSTOR/XSETBV/XGETBV */ +#define X86_FEATURE_OSXSAVE (4*32+27) /* "" XSAVE enabled in the OS */ +#define X86_FEATURE_AVX (4*32+28) /* Advanced Vector Extensions */ +#define X86_FEATURE_HYPERVISOR (4*32+31) /* Running on a hypervisor */ + +/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */ +#define X86_FEATURE_XSTORE (5*32+ 2) /* on-CPU RNG present (xstore insn) */ +#define X86_FEATURE_XSTORE_EN (5*32+ 3) /* on-CPU RNG enabled */ +#define X86_FEATURE_XCRYPT (5*32+ 6) /* on-CPU crypto (xcrypt insn) */ +#define X86_FEATURE_XCRYPT_EN (5*32+ 7) /* on-CPU crypto enabled */ +#define X86_FEATURE_ACE2 (5*32+ 8) /* Advanced Cryptography Engine v2 */ +#define X86_FEATURE_ACE2_EN (5*32+ 9) /* ACE v2 enabled */ +#define X86_FEATURE_PHE (5*32+10) /* PadLock Hash Engine */ +#define X86_FEATURE_PHE_EN (5*32+11) /* PHE enabled */ +#define X86_FEATURE_PMM (5*32+12) /* PadLock Montgomery Multiplier */ +#define X86_FEATURE_PMM_EN (5*32+13) /* PMM enabled */ + +/* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */ +#define X86_FEATURE_LAHF_LM (6*32+ 0) /* LAHF/SAHF in long mode */ +#define X86_FEATURE_CMP_LEGACY (6*32+ 1) /* If yes HyperThreading not valid */ +#define X86_FEATURE_SVM (6*32+ 2) /* Secure virtual machine */ +#define X86_FEATURE_EXTAPIC (6*32+ 3) /* Extended APIC space */ +#define X86_FEATURE_CR8_LEGACY (6*32+ 4) /* CR8 in 32-bit mode */ +#define X86_FEATURE_ABM (6*32+ 5) /* Advanced bit manipulation */ +#define X86_FEATURE_SSE4A (6*32+ 6) /* SSE-4A */ +#define X86_FEATURE_MISALIGNSSE (6*32+ 7) /* Misaligned SSE mode */ +#define X86_FEATURE_3DNOWPREFETCH (6*32+ 8) /* 3DNow prefetch instructions */ +#define X86_FEATURE_OSVW (6*32+ 9) /* OS Visible Workaround */ +#define X86_FEATURE_IBS (6*32+10) /* Instruction Based Sampling */ +#define X86_FEATURE_SSE5 (6*32+11) /* SSE-5 */ +#define X86_FEATURE_SKINIT (6*32+12) /* SKINIT/STGI instructions */ +#define X86_FEATURE_WDT (6*32+13) /* Watchdog timer */ + +/* + * * Auxiliary flags: Linux defined - For features scattered in various + * * CPUID levels like 0x6, 0xA etc + * */ +#define X86_FEATURE_IDA (7*32+ 0) /* Intel Dynamic Acceleration */ +#define X86_FEATURE_ARAT (7*32+ 1) /* Always Running APIC Timer */ + +/* Virtualization flags: Linux defined */ +#define X86_FEATURE_TPR_SHADOW (8*32+ 0) /* Intel TPR Shadow */ +#define X86_FEATURE_VNMI (8*32+ 1) /* Intel Virtual NMI */ +#define X86_FEATURE_FLEXPRIORITY (8*32+ 2) /* Intel FlexPriority */ +#define X86_FEATURE_EPT (8*32+ 3) /* Intel Extended Page Table */ +#define X86_FEATURE_VPID (8*32+ 4) /* Intel Virtual Processor ID */ + +#endif /* __ASM_I386_CPUFEATURE_H */ + +/* + * Local Variables: + * mode:c + * comment-column:42 + * End: + */ diff --git a/contrib/syslinux-4.02/com32/include/ctype.h b/contrib/syslinux-4.02/com32/include/ctype.h new file mode 100644 index 0000000..28fae9f --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/ctype.h @@ -0,0 +1,117 @@ +/* + * ctype.h + * + * This assumes ISO 8859-1, being a reasonable superset of ASCII. + */ + +#ifndef _CTYPE_H +#define _CTYPE_H + +#ifndef __CTYPE_NO_INLINE +# define __ctype_inline static __inline__ +#else +# define __ctype_inline +#endif + +/* + * This relies on the following definitions: + * + * cntrl = !print + * alpha = upper|lower + * graph = punct|alpha|digit + * blank = '\t' || ' ' (per POSIX requirement) + */ +enum { + __ctype_upper = (1 << 0), + __ctype_lower = (1 << 1), + __ctype_digit = (1 << 2), + __ctype_xdigit = (1 << 3), + __ctype_space = (1 << 4), + __ctype_print = (1 << 5), + __ctype_punct = (1 << 6), + __ctype_cntrl = (1 << 7), +}; + +extern const unsigned char __ctypes[]; + +__ctype_inline int isalnum(int __c) +{ + return __ctypes[__c + 1] & (__ctype_upper | __ctype_lower | __ctype_digit); +} + +__ctype_inline int isalpha(int __c) +{ + return __ctypes[__c + 1] & (__ctype_upper | __ctype_lower); +} + +__ctype_inline int isascii(int __c) +{ + return !(__c & ~0x7f); +} + +__ctype_inline int isblank(int __c) +{ + return (__c == '\t') || (__c == ' '); +} + +__ctype_inline int iscntrl(int __c) +{ + return __ctypes[__c + 1] & __ctype_cntrl; +} + +__ctype_inline int isdigit(int __c) +{ + return ((unsigned)__c - '0') <= 9; +} + +__ctype_inline int isgraph(int __c) +{ + return __ctypes[__c + 1] & + (__ctype_upper | __ctype_lower | __ctype_digit | __ctype_punct); +} + +__ctype_inline int islower(int __c) +{ + return __ctypes[__c + 1] & __ctype_lower; +} + +__ctype_inline int isprint(int __c) +{ + return __ctypes[__c + 1] & __ctype_print; +} + +__ctype_inline int ispunct(int __c) +{ + return __ctypes[__c + 1] & __ctype_punct; +} + +__ctype_inline int isspace(int __c) +{ + return __ctypes[__c + 1] & __ctype_space; +} + +__ctype_inline int isupper(int __c) +{ + return __ctypes[__c + 1] & __ctype_upper; +} + +__ctype_inline int isxdigit(int __c) +{ + return __ctypes[__c + 1] & __ctype_xdigit; +} + +/* Note: this is decimal, not hex, to avoid accidental promotion to unsigned */ +#define _toupper(__c) ((__c) & ~32) +#define _tolower(__c) ((__c) | 32) + +__ctype_inline int toupper(int __c) +{ + return islower(__c) ? _toupper(__c) : __c; +} + +__ctype_inline int tolower(int __c) +{ + return isupper(__c) ? _tolower(__c) : __c; +} + +#endif /* _CTYPE_H */ diff --git a/contrib/syslinux-4.02/com32/include/dev.h b/contrib/syslinux-4.02/com32/include/dev.h new file mode 100644 index 0000000..70b3165 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/dev.h @@ -0,0 +1,56 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * console.h + * + * Alternative consoles + */ + +#ifndef _DEV_H +#define _DEV_H + +#include <klibc/extern.h> +#include <stdint.h> + +struct input_dev; +struct output_dev; + +__extern int opendev(const struct input_dev *, const struct output_dev *, int); +__extern int openmem(const void *, size_t, int); + +/* Common generic devices */ + +/* Null device */ +extern const struct input_dev dev_null_r; +extern const struct output_dev dev_null_w; + +/* Error device */ +extern const struct input_dev dev_error_r; +extern const struct output_dev dev_error_w; + +#endif /* _DEV_H */ diff --git a/contrib/syslinux-4.02/com32/include/dirent.h b/contrib/syslinux-4.02/com32/include/dirent.h new file mode 100644 index 0000000..c4aca4f --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/dirent.h @@ -0,0 +1,20 @@ +/* + * dirent.h + */ + +#ifndef _DIRENT_H +#define _DIRENT_H + +#include <klibc/extern.h> +#include <klibc/compiler.h> +#include <stddef.h> +#include <sys/types.h> + +#include <sys/dirent.h> + +__extern DIR *opendir(const char *); +__extern struct dirent *readdir(DIR *); +__extern int closedir(DIR *); +__extern DIR *fdopendir(int); + +#endif /* Not _DIRENT_H */ diff --git a/contrib/syslinux-4.02/com32/include/dprintf.h b/contrib/syslinux-4.02/com32/include/dprintf.h new file mode 100644 index 0000000..30a21ad --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/dprintf.h @@ -0,0 +1,22 @@ +/* + * dprintf.h + */ + +#ifndef _DPRINTF_H +#define _DPRINTF_H + +#ifdef DEBUG + +#include <stdio.h> + +void dprintf(const char *, ...); +void vdprintf(const char *, va_list); + +#else + +#define dprintf(fmt, ...) ((void)(0)) +#define vdprintf(fmt, ap) ((void)(0)) + +#endif /* DEBUG */ + +#endif /* _DPRINTF_H */ diff --git a/contrib/syslinux-4.02/com32/include/elf.h b/contrib/syslinux-4.02/com32/include/elf.h new file mode 100644 index 0000000..970753d --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/elf.h @@ -0,0 +1,11 @@ +/* + * elf.h + */ + +#ifndef _ELF_H +#define _ELF_H + +#include <sys/elf32.h> +#include <sys/elf64.h> + +#endif /* _ELF_H */ diff --git a/contrib/syslinux-4.02/com32/include/endian.h b/contrib/syslinux-4.02/com32/include/endian.h new file mode 100644 index 0000000..e65b1b9 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/endian.h @@ -0,0 +1,15 @@ +/* + * endian.h + */ + +#ifndef _ENDIAN_H +#define _ENDIAN_H + +#include <klibc/endian.h> + +#define LITTLE_ENDIAN __LITTLE_ENDIAN +#define BIG_ENDIAN __BIG_ENDIAN +#define PDP_ENDIAN __PDP_ENDIAN +#define BYTE_ORDER __BYTE_ORDER + +#endif /* _ENDIAN_H */ diff --git a/contrib/syslinux-4.02/com32/include/errno.h b/contrib/syslinux-4.02/com32/include/errno.h new file mode 100644 index 0000000..36690bf --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/errno.h @@ -0,0 +1,134 @@ +#ifndef _ERRNO_H +#define _ERRNO_H + +extern int errno; + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Arg list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ + +#define EDEADLOCK EDEADLK + +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ + +#endif /* _ERRNO_H */ diff --git a/contrib/syslinux-4.02/com32/include/fcntl.h b/contrib/syslinux-4.02/com32/include/fcntl.h new file mode 100644 index 0000000..b691b5c --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/fcntl.h @@ -0,0 +1,24 @@ +/* + * fcntl.h + */ + +#ifndef _FCNTL_H +#define _FCNTL_H + +#include <klibc/extern.h> +#include <klibc/compiler.h> +#include <sys/types.h> + +/* None of these are actually supported, although O_RDONLY works */ +/* Note this is different from the classical Unix way of doing it */ +#define O_RDONLY 1 +#define O_WRONLY 2 +#define O_RDWR 3 +#define O_CREAT 0100 +#define O_EXCL 0200 +#define O_TRUNC 01000 +#define O_APPEND 02000 + +__extern int open(const char *, int, ...); + +#endif /* _FCNTL_H */ diff --git a/contrib/syslinux-4.02/com32/include/getopt.h b/contrib/syslinux-4.02/com32/include/getopt.h new file mode 100644 index 0000000..71c41cd --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/getopt.h @@ -0,0 +1,22 @@ +#ifndef _GETOPT_H +#define _GETOPT_H + +#include <klibc/extern.h> + +struct option { + const char *name; + int has_arg; + int *flag; + int val; +}; + +enum { + no_argument = 0, + required_argument = 1, + optional_argument = 2, +}; + +__extern int getopt_long(int, char *const *, const char *, + const struct option *, int *); + +#endif /* _GETOPT_H */ diff --git a/contrib/syslinux-4.02/com32/include/ilog2.h b/contrib/syslinux-4.02/com32/include/ilog2.h new file mode 100644 index 0000000..91a5057 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/ilog2.h @@ -0,0 +1,48 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2010 Intel Corporation; author: H. Peter Anvin + * + * 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 _ILOG2_H +#define _ILOG2_H + +/* + * Computes floor(log2(x)) -- undefined for x = 0. + */ + +#include <klibc/compiler.h> +#include <stdint.h> + +static inline __constfunc uint32_t ilog2(uint32_t __v) +{ +# if __GNUC__ >= 4 + return __builtin_clz(__v) ^ 31; +# else + asm("bsrl %1,%0" : "=r" (__v) : "rm" (__v)); + return __v; +# endif +} + +#endif /* _ILOG2_H */ diff --git a/contrib/syslinux-4.02/com32/include/inttypes.h b/contrib/syslinux-4.02/com32/include/inttypes.h new file mode 100644 index 0000000..b863126 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/inttypes.h @@ -0,0 +1,226 @@ +/* + * inttypes.h + */ + +#ifndef _INTTYPES_H +#define _INTTYPES_H + +#include <klibc/extern.h> +#include <stdint.h> +#include <stddef.h> + +static __inline__ intmax_t imaxabs(intmax_t __n) +{ + return (__n < (intmax_t) 0) ? -__n : __n; +} + +__extern intmax_t strtoimax(const char *, char **, int); +__extern uintmax_t strtoumax(const char *, char **, int); + +/* extensions */ +__extern intmax_t strntoimax(const char *, char **, int, size_t); +__extern uintmax_t strntoumax(const char *, char **, int, size_t); + +#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) + +#define PRId8 "d" +#define PRId16 "d" +#define PRId32 "d" +#define PRId64 __PRI64_RANK "d" + +#define PRIdLEAST8 "d" +#define PRIdLEAST16 "d" +#define PRIdLEAST32 "d" +#define PRIdLEAST64 __PRI64_RANK "d" + +#define PRIdFAST8 "d" +#define PRIdFAST16 __PRIFAST_RANK "d" +#define PRIdFAST32 __PRIFAST_RANK "d" +#define PRIdFAST64 __PRI64_RANK "d" + +#define PRIdMAX __PRI64_RANK "d" +#define PRIdPTR __PRIPTR_RANK "d" + +#define PRIi8 "i" +#define PRIi16 "i" +#define PRIi32 "i" +#define PRIi64 __PRI64_RANK "i" + +#define PRIiLEAST8 "i" +#define PRIiLEAST16 "i" +#define PRIiLEAST32 "i" +#define PRIiLEAST64 __PRI64_RANK "i" + +#define PRIiFAST8 "i" +#define PRIiFAST16 __PRIFAST_RANK "i" +#define PRIiFAST32 __PRIFAST_RANK "i" +#define PRIiFAST64 __PRI64_RANK "i" + +#define PRIiMAX __PRI64_RANK "i" +#define PRIiPTR __PRIPTR_RANK "i" + +#define PRIo8 "o" +#define PRIo16 "o" +#define PRIo32 "o" +#define PRIo64 __PRI64_RANK "o" + +#define PRIoLEAST8 "o" +#define PRIoLEAST16 "o" +#define PRIoLEAST32 "o" +#define PRIoLEAST64 __PRI64_RANK "o" + +#define PRIoFAST8 "o" +#define PRIoFAST16 __PRIFAST_RANK "o" +#define PRIoFAST32 __PRIFAST_RANK "o" +#define PRIoFAST64 __PRI64_RANK "o" + +#define PRIoMAX __PRI64_RANK "o" +#define PRIoPTR __PRIPTR_RANK "o" + +#define PRIu8 "u" +#define PRIu16 "u" +#define PRIu32 "u" +#define PRIu64 __PRI64_RANK "u" + +#define PRIuLEAST8 "u" +#define PRIuLEAST16 "u" +#define PRIuLEAST32 "u" +#define PRIuLEAST64 __PRI64_RANK "u" + +#define PRIuFAST8 "u" +#define PRIuFAST16 __PRIFAST_RANK "u" +#define PRIuFAST32 __PRIFAST_RANK "u" +#define PRIuFAST64 __PRI64_RANK "u" + +#define PRIuMAX __PRI64_RANK "u" +#define PRIuPTR __PRIPTR_RANK "u" + +#define PRIx8 "x" +#define PRIx16 "x" +#define PRIx32 "x" +#define PRIx64 __PRI64_RANK "x" + +#define PRIxLEAST8 "x" +#define PRIxLEAST16 "x" +#define PRIxLEAST32 "x" +#define PRIxLEAST64 __PRI64_RANK "x" + +#define PRIxFAST8 "x" +#define PRIxFAST16 __PRIFAST_RANK "x" +#define PRIxFAST32 __PRIFAST_RANK "x" +#define PRIxFAST64 __PRI64_RANK "x" + +#define PRIxMAX __PRI64_RANK "x" +#define PRIxPTR __PRIPTR_RANK "x" + +#define PRIX8 "X" +#define PRIX16 "X" +#define PRIX32 "X" +#define PRIX64 __PRI64_RANK "X" + +#define PRIXLEAST8 "X" +#define PRIXLEAST16 "X" +#define PRIXLEAST32 "X" +#define PRIXLEAST64 __PRI64_RANK "X" + +#define PRIXFAST8 "X" +#define PRIXFAST16 __PRIFAST_RANK "X" +#define PRIXFAST32 __PRIFAST_RANK "X" +#define PRIXFAST64 __PRI64_RANK "X" + +#define PRIXMAX __PRI64_RANK "X" +#define PRIXPTR __PRIPTR_RANK "X" + +#define SCNd8 "hhd" +#define SCNd16 "hd" +#define SCNd32 "d" +#define SCNd64 __PRI64_RANK "d" + +#define SCNdLEAST8 "hhd" +#define SCNdLEAST16 "hd" +#define SCNdLEAST32 "d" +#define SCNdLEAST64 __PRI64_RANK "d" + +#define SCNdFAST8 "hhd" +#define SCNdFAST16 __PRIFAST_RANK "d" +#define SCNdFAST32 __PRIFAST_RANK "d" +#define SCNdFAST64 __PRI64_RANK "d" + +#define SCNdMAX __PRI64_RANK "d" +#define SCNdPTR __PRIPTR_RANK "d" + +#define SCNi8 "hhi" +#define SCNi16 "hi" +#define SCNi32 "i" +#define SCNi64 __PRI64_RANK "i" + +#define SCNiLEAST8 "hhi" +#define SCNiLEAST16 "hi" +#define SCNiLEAST32 "i" +#define SCNiLEAST64 __PRI64_RANK "i" + +#define SCNiFAST8 "hhi" +#define SCNiFAST16 __PRIFAST_RANK "i" +#define SCNiFAST32 __PRIFAST_RANK "i" +#define SCNiFAST64 __PRI64_RANK "i" + +#define SCNiMAX __PRI64_RANK "i" +#define SCNiPTR __PRIPTR_RANK "i" + +#define SCNo8 "hho" +#define SCNo16 "ho" +#define SCNo32 "o" +#define SCNo64 __PRI64_RANK "o" + +#define SCNoLEAST8 "hho" +#define SCNoLEAST16 "ho" +#define SCNoLEAST32 "o" +#define SCNoLEAST64 __PRI64_RANK "o" + +#define SCNoFAST8 "hho" +#define SCNoFAST16 __PRIFAST_RANK "o" +#define SCNoFAST32 __PRIFAST_RANK "o" +#define SCNoFAST64 __PRI64_RANK "o" + +#define SCNoMAX __PRI64_RANK "o" +#define SCNoPTR __PRIPTR_RANK "o" + +#define SCNu8 "hhu" +#define SCNu16 "hu" +#define SCNu32 "u" +#define SCNu64 __PRI64_RANK "u" + +#define SCNuLEAST8 "hhu" +#define SCNuLEAST16 "hu" +#define SCNuLEAST32 "u" +#define SCNuLEAST64 __PRI64_RANK "u" + +#define SCNuFAST8 "hhu" +#define SCNuFAST16 __PRIFAST_RANK "u" +#define SCNuFAST32 __PRIFAST_RANK "u" +#define SCNuFAST64 __PRI64_RANK "u" + +#define SCNuMAX __PRI64_RANK "u" +#define SCNuPTR __PRIPTR_RANK "u" + +#define SCNx8 "hhx" +#define SCNx16 "hx" +#define SCNx32 "x" +#define SCNx64 __PRI64_RANK "x" + +#define SCNxLEAST8 "hhx" +#define SCNxLEAST16 "hx" +#define SCNxLEAST32 "x" +#define SCNxLEAST64 __PRI64_RANK "x" + +#define SCNxFAST8 "hhx" +#define SCNxFAST16 __PRIFAST_RANK "x" +#define SCNxFAST32 __PRIFAST_RANK "x" +#define SCNxFAST64 __PRI64_RANK "x" + +#define SCNxMAX __PRI64_RANK "x" +#define SCNxPTR __PRIPTR_RANK "x" + +#endif + +#endif /* _INTTYPES_H */ diff --git a/contrib/syslinux-4.02/com32/include/klibc/archsetjmp.h b/contrib/syslinux-4.02/com32/include/klibc/archsetjmp.h new file mode 100644 index 0000000..a0def6a --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/klibc/archsetjmp.h @@ -0,0 +1,19 @@ +/* + * arch/i386/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + unsigned int __ebx; + unsigned int __esp; + unsigned int __ebp; + unsigned int __esi; + unsigned int __edi; + unsigned int __eip; +}; + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _SETJMP_H */ diff --git a/contrib/syslinux-4.02/com32/include/klibc/compiler.h b/contrib/syslinux-4.02/com32/include/klibc/compiler.h new file mode 100644 index 0000000..5ac2118 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/klibc/compiler.h @@ -0,0 +1,129 @@ +/* + * klibc/compiler.h + * + * Various compiler features + */ + +#ifndef _KLIBC_COMPILER_H +#define _KLIBC_COMPILER_H + +#define __user + +/* Specific calling conventions */ +/* __cdecl is used when we want varadic and non-varadic functions to have + the same binary calling convention. */ +#ifdef __i386__ +# ifdef __GNUC__ +# define __cdecl __attribute__((cdecl,regparm(0))) +# else + /* Most other C compilers have __cdecl as a keyword */ +# endif +#else +# define __cdecl /* Meaningless on non-i386 */ +#endif + +/* How to declare a function that *must* be inlined */ +#ifdef __GNUC__ +# if __GNUC_MAJOR__ >= 3 +# define __must_inline static __inline__ __attribute__((always_inline)) +# else +# define __must_inline extern __inline__ +# endif +#else +# define __must_inline inline /* Just hope this works... */ +#endif + +/* How to declare a function that does not return */ +#ifdef __GNUC__ +# define __noreturn void __attribute__((noreturn)) +#else +# define __noreturn void +#endif + +/* "const" function: + + Many functions do not examine any values except their arguments, + and have no effects except the return value. Basically this is + just slightly more strict class than the `pure' attribute above, + since function is not allowed to read global memory. + + Note that a function that has pointer arguments and examines the + data pointed to must _not_ be declared `const'. Likewise, a + function that calls a non-`const' function usually must not be + `const'. It does not make sense for a `const' function to return + `void'. +*/ +#ifdef __GNUC__ +# define __constfunc __attribute__((const)) +#else +# define __constfunc +#endif +#undef __attribute_const__ +#define __attribute_const__ __constfunc + +/* "pure" function: + + Many functions have no effects except the return value and their + return value depends only on the parameters and/or global + variables. Such a function can be subject to common subexpression + elimination and loop optimization just as an arithmetic operator + would be. These functions should be declared with the attribute + `pure'. +*/ +#ifdef __GNUC__ +# define __purefunc __attribute__((pure)) +#else +# define __purefunc +#endif +#undef __attribute_pure__ +#define __attribute_pure__ __purefunc + +/* Format attribute */ +#ifdef __GNUC__ +# define __formatfunc(t,f,a) __attribute__((format(t,f,a))) +#else +# define __formatfunc(t,f,a) +#endif + +/* malloc() function (returns unaliased pointer) */ +#if defined(__GNUC__) && (__GNUC_MAJOR__ >= 3) +# define __mallocfunc __attribute__((malloc)) +#else +# define __mallocfunc +#endif + +/* likely/unlikely */ +#if defined(__GNUC__) && (__GNUC_MAJOR__ > 2 || (__GNUC_MAJOR__ == 2 && __GNUC_MINOR__ >= 95)) +# define __likely(x) __builtin_expect(!!(x), 1) +# define __unlikely(x) __builtin_expect(!!(x), 0) +#else +# define __likely(x) (!!(x)) +# define __unlikely(x) (!!(x)) +#endif + +/* Possibly unused function */ +#ifdef __GNUC__ +# define __unusedfunc __attribute__((unused)) +#else +# define __unusedfunc +#endif + +/* Constructors and destructors */ +#define __constructor __attribute__((constructor)) +#define __destructor __attribute__((destructor)) + +/* Packed structures */ +#define __packed __attribute__((packed)) + +/* Weak symbols */ +#define __weak __attribute__((weak)) + +/* Alignment */ +#define __aligned(x) __attribute__((aligned(x))) +#define __alignas(x) __attribute__((aligned(__alignof__(x)))) + +/* Handling of common (affect constructors/destructors) */ +#define __common __attribute__((common)) +#define __nocommon __attribute__((nocommon)) + +#endif diff --git a/contrib/syslinux-4.02/com32/include/klibc/diverr.h b/contrib/syslinux-4.02/com32/include/klibc/diverr.h new file mode 100644 index 0000000..106f062 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/klibc/diverr.h @@ -0,0 +1,4 @@ +static inline void __divide_error(void) +{ + asm volatile ("int $0"); /* Divide by zero */ +} diff --git a/contrib/syslinux-4.02/com32/include/klibc/endian.h b/contrib/syslinux-4.02/com32/include/klibc/endian.h new file mode 100644 index 0000000..9466421 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/klibc/endian.h @@ -0,0 +1,38 @@ +/* + * klibc/endian.h + * + * Like <endian.h>, but export only double-underscore symbols + */ + +#ifndef _KLIBC_ENDIAN_H +#define _KLIBC_ENDIAN_H + +#define __LITTLE_ENDIAN /* we're on i386, littleendian */ + +/* Linux' asm/byteorder.h defines either __LITTLE_ENDIAN or + __BIG_ENDIAN, but the glibc/BSD-ish macros expect both to be + defined with __BYTE_ORDER defining which is actually used... */ + +#if defined(__LITTLE_ENDIAN) +# undef __LITTLE_ENDIAN +# define __LITTLE_ENDIAN 1234 +# define __BIG_ENDIAN 4321 +# define __PDP_ENDIAN 3412 +# define __BYTE_ORDER __LITTLE_ENDIAN +#elif defined(__BIG_ENDIAN) +# undef __BIG_ENDIAN +# define __LITTLE_ENDIAN 1234 +# define __BIG_ENDIAN 4321 +# define __PDP_ENDIAN 3412 +# define __BYTE_ORDER __BIG_ENDIAN +#elif defined(__PDP_ENDIAN) +# undef __PDP_ENDIAN +# define __LITTLE_ENDIAN 1234 +# define __BIG_ENDIAN 4321 +# define __PDP_ENDIAN 3412 +# define __BYTE_ORDER __PDP_ENDIAN +#else +# error "Unknown byte order!" +#endif + +#endif /* _KLIBC_ENDIAN_H */ diff --git a/contrib/syslinux-4.02/com32/include/klibc/extern.h b/contrib/syslinux-4.02/com32/include/klibc/extern.h new file mode 100644 index 0000000..f9c3467 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/klibc/extern.h @@ -0,0 +1,14 @@ +/* + * klibc/extern.h + */ + +#ifndef _KLIBC_EXTERN_H +#define _KLIBC_EXTERN_H + +#ifdef __cplusplus +#define __extern extern "C" +#else +#define __extern extern +#endif + +#endif /* _KLIBC_EXTERN_H */ diff --git a/contrib/syslinux-4.02/com32/include/klibc/sysconfig.h b/contrib/syslinux-4.02/com32/include/klibc/sysconfig.h new file mode 100644 index 0000000..efaaaf5 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/klibc/sysconfig.h @@ -0,0 +1,34 @@ +/* + * klibc/sysconfig.h + * + * Allows for definitions of some things which may be system-dependent + */ + +#ifndef _KLIBC_SYSCONFIG_H +#define _KLIBC_SYSCONFIG_H + +/* + * Define this to obtain memory using sbrk() instead + * of mmap(). This should make it friendlier on + * non-MMU architectures. This should become a + * per-architecture configurable. + */ +#define MALLOC_USING_SBRK + +/* + * This is the minimum chunk size we will ask the kernel for using + * malloc(); this should be a multiple of the page size on all + * architectures. + */ +#define MALLOC_CHUNK_SIZE 4096 +#define MALLOC_CHUNK_MASK (MALLOC_CHUNK_SIZE-1) + +/* + * This is the minimum alignment for the memory returned by sbrk(). + * It must be a power of 2. If MALLOC_USING_SBRK is defined it should + * be no smaller than the size of struct arena_header in malloc.h (4 + * pointers.) + */ +#define SBRK_ALIGNMENT 32 + +#endif /* _KLIBC_SYSCONFIG_H */ diff --git a/contrib/syslinux-4.02/com32/include/libansi.h b/contrib/syslinux-4.02/com32/include/libansi.h new file mode 100644 index 0000000..d813f9f --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/libansi.h @@ -0,0 +1,103 @@ +/* ----------------------------------------------------------------------- * + * + * 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_LIB_ANSI_H +#define DEFINE_LIB_ANSI_H + +#define CSI "\e[" + +void display_cursor(bool status); +void clear_end_of_line(void); +void move_cursor_left(int count); +void move_cursor_right(int count); +void clear_line(void); +void clear_beginning_of_line(void); +void move_cursor_to_column(int count); +void move_cursor_to_next_line(void); +void disable_utf8(void); +void set_g1_special_char(void); +void set_us_g0_charset(void); +void clear_entire_screen(void); +void set_cursor_blink(bool status); +void move_cursor_to_next_line(void); +void disable_utf8(void); +void set_g1_special_char(void); +void set_us_g0_charset(void); +void clear_entire_screen(void); +void clearwindow(const char top, const char left, const char bot, + const char right, const char fillchar, const char fillattr); + +static inline void beep(void) +{ + fputs("\007", stdout); +} + +void reset_colors(void); + +/* Print a string */ +void csprint(const char *, const char); + +/* Print one character, one or more times */ +void cprint(const char, const char, unsigned int); + +/* Print one character, once */ +static inline void putch(const char x, char attr) +{ + cprint(x, attr, 1); +} + +void cls(void); + +static inline void cursoroff(void) +{ + display_cursor(false); +} + +static inline void cursoron(void) +{ + display_cursor(true); +} + +static inline void scrollup(int times) +{ + if (times > 0) + printf(CSI "%dS", times); +} + +/* Scroll up display screen by one line */ +static inline void scrollup_once(void) +{ + printf(CSI "S"); +} + +static inline void gotoxy(const char row, const char col) +{ + printf(CSI "%d;%dH", row + 1, col + 1); +} + +#endif diff --git a/contrib/syslinux-4.02/com32/include/limits.h b/contrib/syslinux-4.02/com32/include/limits.h new file mode 100644 index 0000000..64ef974 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/limits.h @@ -0,0 +1,39 @@ +/* + * limits.h + */ + +#ifndef _LIMITS_H +#define _LIMITS_H + +#define CHAR_BIT 8 +#define SHRT_BIT 16 +#define INT_BIT 32 +#define LONGLONG_BIT 64 + +#define SCHAR_MIN (-128) +#define SCHAR_MAX 127 +#define UCHAR_MAX 255 + +#ifdef __CHAR_UNSIGNED__ +# define CHAR_MIN 0 +# define CHAR_MAX UCHAR_MAX +#else +# define CHAR_MIN SCHAR_MIN +# define CHAR_MAX SCHAR_MAX +#endif + +#define SHRT_MIN (-32768) +#define SHRT_MAX 32767 +#define USHRT_MAX 65535 + +#define INT_MIN (-2147483647-1) +#define INT_MAX 2147483647 +#define UINT_MAX 4294967295U + +#define LONGLONG_MIN (-9223372036854775807LL-1) +#define LONGLONG_MAX 9223372036854775807LL +#define ULONGLONG_MAX 18446744073709551615ULL + +#include <bitsize/limits.h> + +#endif /* _LIMITS_H */ diff --git a/contrib/syslinux-4.02/com32/include/math.h b/contrib/syslinux-4.02/com32/include/math.h new file mode 100644 index 0000000..e3d248f --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/math.h @@ -0,0 +1,15 @@ +#ifndef _MATH_H +#define _MATH_H + +#ifndef __DBL_MIN_EXP__ +# define __DBL_MIN_EXP__ (-1021) +#endif +#ifndef __DBL_MAX_EXP__ +# define __DBL_MAX_EXP__ 1024 +#endif + +double pow(double, double); +double fabs(double); +double strtod(const char *, char **); + +#endif /* _MATH_H */ diff --git a/contrib/syslinux-4.02/com32/include/minmax.h b/contrib/syslinux-4.02/com32/include/minmax.h new file mode 100644 index 0000000..eb6e39a --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/minmax.h @@ -0,0 +1,42 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +#ifndef _MINMAX_H +#define _MINMAX_H + +/* + * minmax.h: Type-independent safe min/max macros + */ + +#define min(x,y) ({ __typeof(x) xx = (x); \ + __typeof(y) yy = (y); \ + xx < yy ? xx : yy; }) +#define max(x,y) ({ __typeof(x) xx = (x); \ + __typeof(y) yy = (y); \ + xx > yy ? xx : yy; }) + +#endif /* _MINMAX_H */ diff --git a/contrib/syslinux-4.02/com32/include/netinet/in.h b/contrib/syslinux-4.02/com32/include/netinet/in.h new file mode 100644 index 0000000..ccf0475 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/netinet/in.h @@ -0,0 +1,56 @@ +#ifndef _NETINET_IN_H +#define _NETINET_IN_H + +/* COM32 will be running on an i386 platform */ + +#include <stdint.h> +#include <klibc/compiler.h> + +#define __htons_macro(v) ((uint16_t) \ + (((uint16_t)(v) << 8) | \ + ((uint16_t)(v) >> 8))) + +static inline __constfunc uint16_t __htons(uint16_t v) +{ + return __htons_macro(v); +} + +#define htons(x) (__builtin_constant_p(x) ? __htons_macro(x) : __htons(x)) +#define ntohs(x) htons(x) + +#define __htonl_macro(v) ((uint32_t) \ + ((((uint32_t)(v) & 0x000000ff) << 24) | \ + (((uint32_t)(v) & 0x0000ff00) << 8) | \ + (((uint32_t)(v) & 0x00ff0000) >> 8) | \ + (((uint32_t)(v) & 0xff000000) >> 24))) + +static inline __constfunc uint32_t __htonl(uint32_t v) +{ + asm("xchgb %h0,%b0 ; roll $16,%0 ; xchgb %h0,%b0" + : "+q" (v)); + return v; +} + +#define htonl(x) (__builtin_constant_p(x) ? __htonl_macro(x) : __htonl(x)) +#define ntohl(x) htonl(x) + +#define __htonq_macro(v) ((uint64_t) \ + (((uint64_t)__htonl_macro((uint32_t)(v)) << 32) | \ + (__htonl_macro((uint32_t)((uint64_t)(v) >> 32))))) + +static inline __constfunc uint64_t __htonq(uint64_t v) +{ + return ((uint64_t)__htonl(v) << 32) | __htonl(v >> 32); +} + +#define htonq(x) (__builtin_constant_p(x) ? __htonq_macro(x) : __htonq(x)) +#define ntohq(x) htonq(x) + +typedef uint32_t in_addr_t; +typedef uint16_t in_port_t; + +struct in_addr { + in_addr_t s_addr; +}; + +#endif /* _NETINET_IN_H */ diff --git a/contrib/syslinux-4.02/com32/include/png.h b/contrib/syslinux-4.02/com32/include/png.h new file mode 100644 index 0000000..cc1915d --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/png.h @@ -0,0 +1,3788 @@ +/* png.h - header file for PNG reference library + * + * libpng version 1.2.44 - June 26, 2010 + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license (See LICENSE, below) + * + * Authors and maintainers: + * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat + * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger + * libpng versions 0.97, January 1998, through 1.2.44 - June 26, 2010: Glenn + * See also "Contributing Authors", below. + * + * Note about libpng version numbers: + * + * Due to various miscommunications, unforeseen code incompatibilities + * and occasional factors outside the authors' control, version numbering + * on the library has not always been consistent and straightforward. + * The following table summarizes matters since version 0.89c, which was + * the first widely used release: + * + * source png.h png.h shared-lib + * version string int version + * ------- ------ ----- ---------- + * 0.89c "1.0 beta 3" 0.89 89 1.0.89 + * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] + * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] + * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] + * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] + * 0.97c 0.97 97 2.0.97 + * 0.98 0.98 98 2.0.98 + * 0.99 0.99 98 2.0.99 + * 0.99a-m 0.99 99 2.0.99 + * 1.00 1.00 100 2.1.0 [100 should be 10000] + * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] + * 1.0.1 png.h string is 10001 2.1.0 + * 1.0.1a-e identical to the 10002 from here on, the shared library + * 1.0.2 source version) 10002 is 2.V where V is the source code + * 1.0.2a-b 10003 version, except as noted. + * 1.0.3 10003 + * 1.0.3a-d 10004 + * 1.0.4 10004 + * 1.0.4a-f 10005 + * 1.0.5 (+ 2 patches) 10005 + * 1.0.5a-d 10006 + * 1.0.5e-r 10100 (not source compatible) + * 1.0.5s-v 10006 (not binary compatible) + * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) + * 1.0.6d-f 10007 (still binary incompatible) + * 1.0.6g 10007 + * 1.0.6h 10007 10.6h (testing xy.z so-numbering) + * 1.0.6i 10007 10.6i + * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) + * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) + * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) + * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) + * 1.0.7 1 10007 (still compatible) + * 1.0.8beta1-4 1 10008 2.1.0.8beta1-4 + * 1.0.8rc1 1 10008 2.1.0.8rc1 + * 1.0.8 1 10008 2.1.0.8 + * 1.0.9beta1-6 1 10009 2.1.0.9beta1-6 + * 1.0.9rc1 1 10009 2.1.0.9rc1 + * 1.0.9beta7-10 1 10009 2.1.0.9beta7-10 + * 1.0.9rc2 1 10009 2.1.0.9rc2 + * 1.0.9 1 10009 2.1.0.9 + * 1.0.10beta1 1 10010 2.1.0.10beta1 + * 1.0.10rc1 1 10010 2.1.0.10rc1 + * 1.0.10 1 10010 2.1.0.10 + * 1.0.11beta1-3 1 10011 2.1.0.11beta1-3 + * 1.0.11rc1 1 10011 2.1.0.11rc1 + * 1.0.11 1 10011 2.1.0.11 + * 1.0.12beta1-2 2 10012 2.1.0.12beta1-2 + * 1.0.12rc1 2 10012 2.1.0.12rc1 + * 1.0.12 2 10012 2.1.0.12 + * 1.1.0a-f - 10100 2.1.1.0a-f (branch abandoned) + * 1.2.0beta1-2 2 10200 2.1.2.0beta1-2 + * 1.2.0beta3-5 3 10200 3.1.2.0beta3-5 + * 1.2.0rc1 3 10200 3.1.2.0rc1 + * 1.2.0 3 10200 3.1.2.0 + * 1.2.1beta1-4 3 10201 3.1.2.1beta1-4 + * 1.2.1rc1-2 3 10201 3.1.2.1rc1-2 + * 1.2.1 3 10201 3.1.2.1 + * 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6 + * 1.0.13beta1 10 10013 10.so.0.1.0.13beta1 + * 1.0.13rc1 10 10013 10.so.0.1.0.13rc1 + * 1.2.2rc1 12 10202 12.so.0.1.2.2rc1 + * 1.0.13 10 10013 10.so.0.1.0.13 + * 1.2.2 12 10202 12.so.0.1.2.2 + * 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6 + * 1.2.3 12 10203 12.so.0.1.2.3 + * 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3 + * 1.0.14rc1 13 10014 10.so.0.1.0.14rc1 + * 1.2.4rc1 13 10204 12.so.0.1.2.4rc1 + * 1.0.14 10 10014 10.so.0.1.0.14 + * 1.2.4 13 10204 12.so.0.1.2.4 + * 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2 + * 1.0.15rc1-3 10 10015 10.so.0.1.0.15rc1-3 + * 1.2.5rc1-3 13 10205 12.so.0.1.2.5rc1-3 + * 1.0.15 10 10015 10.so.0.1.0.15 + * 1.2.5 13 10205 12.so.0.1.2.5 + * 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4 + * 1.0.16 10 10016 10.so.0.1.0.16 + * 1.2.6 13 10206 12.so.0.1.2.6 + * 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2 + * 1.0.17rc1 10 10017 10.so.0.1.0.17rc1 + * 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 + * 1.0.17 10 10017 10.so.0.1.0.17 + * 1.2.7 13 10207 12.so.0.1.2.7 + * 1.2.8beta1-5 13 10208 12.so.0.1.2.8beta1-5 + * 1.0.18rc1-5 10 10018 10.so.0.1.0.18rc1-5 + * 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5 + * 1.0.18 10 10018 10.so.0.1.0.18 + * 1.2.8 13 10208 12.so.0.1.2.8 + * 1.2.9beta1-3 13 10209 12.so.0.1.2.9beta1-3 + * 1.2.9beta4-11 13 10209 12.so.0.9[.0] + * 1.2.9rc1 13 10209 12.so.0.9[.0] + * 1.2.9 13 10209 12.so.0.9[.0] + * 1.2.10beta1-8 13 10210 12.so.0.10[.0] + * 1.2.10rc1-3 13 10210 12.so.0.10[.0] + * 1.2.10 13 10210 12.so.0.10[.0] + * 1.2.11beta1-4 13 10211 12.so.0.11[.0] + * 1.0.19rc1-5 10 10019 10.so.0.19[.0] + * 1.2.11rc1-5 13 10211 12.so.0.11[.0] + * 1.0.19 10 10019 10.so.0.19[.0] + * 1.2.11 13 10211 12.so.0.11[.0] + * 1.0.20 10 10020 10.so.0.20[.0] + * 1.2.12 13 10212 12.so.0.12[.0] + * 1.2.13beta1 13 10213 12.so.0.13[.0] + * 1.0.21 10 10021 10.so.0.21[.0] + * 1.2.13 13 10213 12.so.0.13[.0] + * 1.2.14beta1-2 13 10214 12.so.0.14[.0] + * 1.0.22rc1 10 10022 10.so.0.22[.0] + * 1.2.14rc1 13 10214 12.so.0.14[.0] + * 1.0.22 10 10022 10.so.0.22[.0] + * 1.2.14 13 10214 12.so.0.14[.0] + * 1.2.15beta1-6 13 10215 12.so.0.15[.0] + * 1.0.23rc1-5 10 10023 10.so.0.23[.0] + * 1.2.15rc1-5 13 10215 12.so.0.15[.0] + * 1.0.23 10 10023 10.so.0.23[.0] + * 1.2.15 13 10215 12.so.0.15[.0] + * 1.2.16beta1-2 13 10216 12.so.0.16[.0] + * 1.2.16rc1 13 10216 12.so.0.16[.0] + * 1.0.24 10 10024 10.so.0.24[.0] + * 1.2.16 13 10216 12.so.0.16[.0] + * 1.2.17beta1-2 13 10217 12.so.0.17[.0] + * 1.0.25rc1 10 10025 10.so.0.25[.0] + * 1.2.17rc1-3 13 10217 12.so.0.17[.0] + * 1.0.25 10 10025 10.so.0.25[.0] + * 1.2.17 13 10217 12.so.0.17[.0] + * 1.0.26 10 10026 10.so.0.26[.0] + * 1.2.18 13 10218 12.so.0.18[.0] + * 1.2.19beta1-31 13 10219 12.so.0.19[.0] + * 1.0.27rc1-6 10 10027 10.so.0.27[.0] + * 1.2.19rc1-6 13 10219 12.so.0.19[.0] + * 1.0.27 10 10027 10.so.0.27[.0] + * 1.2.19 13 10219 12.so.0.19[.0] + * 1.2.20beta01-04 13 10220 12.so.0.20[.0] + * 1.0.28rc1-6 10 10028 10.so.0.28[.0] + * 1.2.20rc1-6 13 10220 12.so.0.20[.0] + * 1.0.28 10 10028 10.so.0.28[.0] + * 1.2.20 13 10220 12.so.0.20[.0] + * 1.2.21beta1-2 13 10221 12.so.0.21[.0] + * 1.2.21rc1-3 13 10221 12.so.0.21[.0] + * 1.0.29 10 10029 10.so.0.29[.0] + * 1.2.21 13 10221 12.so.0.21[.0] + * 1.2.22beta1-4 13 10222 12.so.0.22[.0] + * 1.0.30rc1 10 10030 10.so.0.30[.0] + * 1.2.22rc1 13 10222 12.so.0.22[.0] + * 1.0.30 10 10030 10.so.0.30[.0] + * 1.2.22 13 10222 12.so.0.22[.0] + * 1.2.23beta01-05 13 10223 12.so.0.23[.0] + * 1.2.23rc01 13 10223 12.so.0.23[.0] + * 1.2.23 13 10223 12.so.0.23[.0] + * 1.2.24beta01-02 13 10224 12.so.0.24[.0] + * 1.2.24rc01 13 10224 12.so.0.24[.0] + * 1.2.24 13 10224 12.so.0.24[.0] + * 1.2.25beta01-06 13 10225 12.so.0.25[.0] + * 1.2.25rc01-02 13 10225 12.so.0.25[.0] + * 1.0.31 10 10031 10.so.0.31[.0] + * 1.2.25 13 10225 12.so.0.25[.0] + * 1.2.26beta01-06 13 10226 12.so.0.26[.0] + * 1.2.26rc01 13 10226 12.so.0.26[.0] + * 1.2.26 13 10226 12.so.0.26[.0] + * 1.0.32 10 10032 10.so.0.32[.0] + * 1.2.27beta01-06 13 10227 12.so.0.27[.0] + * 1.2.27rc01 13 10227 12.so.0.27[.0] + * 1.0.33 10 10033 10.so.0.33[.0] + * 1.2.27 13 10227 12.so.0.27[.0] + * 1.0.34 10 10034 10.so.0.34[.0] + * 1.2.28 13 10228 12.so.0.28[.0] + * 1.2.29beta01-03 13 10229 12.so.0.29[.0] + * 1.2.29rc01 13 10229 12.so.0.29[.0] + * 1.0.35 10 10035 10.so.0.35[.0] + * 1.2.29 13 10229 12.so.0.29[.0] + * 1.0.37 10 10037 10.so.0.37[.0] + * 1.2.30beta01-04 13 10230 12.so.0.30[.0] + * 1.0.38rc01-08 10 10038 10.so.0.38[.0] + * 1.2.30rc01-08 13 10230 12.so.0.30[.0] + * 1.0.38 10 10038 10.so.0.38[.0] + * 1.2.30 13 10230 12.so.0.30[.0] + * 1.0.39rc01-03 10 10039 10.so.0.39[.0] + * 1.2.31rc01-03 13 10231 12.so.0.31[.0] + * 1.0.39 10 10039 10.so.0.39[.0] + * 1.2.31 13 10231 12.so.0.31[.0] + * 1.2.32beta01-02 13 10232 12.so.0.32[.0] + * 1.0.40rc01 10 10040 10.so.0.40[.0] + * 1.2.32rc01 13 10232 12.so.0.32[.0] + * 1.0.40 10 10040 10.so.0.40[.0] + * 1.2.32 13 10232 12.so.0.32[.0] + * 1.2.33beta01-02 13 10233 12.so.0.33[.0] + * 1.2.33rc01-02 13 10233 12.so.0.33[.0] + * 1.0.41rc01 10 10041 10.so.0.41[.0] + * 1.2.33 13 10233 12.so.0.33[.0] + * 1.0.41 10 10041 10.so.0.41[.0] + * 1.2.34beta01-07 13 10234 12.so.0.34[.0] + * 1.0.42rc01 10 10042 10.so.0.42[.0] + * 1.2.34rc01 13 10234 12.so.0.34[.0] + * 1.0.42 10 10042 10.so.0.42[.0] + * 1.2.34 13 10234 12.so.0.34[.0] + * 1.2.35beta01-03 13 10235 12.so.0.35[.0] + * 1.0.43rc01-02 10 10043 10.so.0.43[.0] + * 1.2.35rc01-02 13 10235 12.so.0.35[.0] + * 1.0.43 10 10043 10.so.0.43[.0] + * 1.2.35 13 10235 12.so.0.35[.0] + * 1.2.36beta01-05 13 10236 12.so.0.36[.0] + * 1.2.36rc01 13 10236 12.so.0.36[.0] + * 1.0.44 10 10044 10.so.0.44[.0] + * 1.2.36 13 10236 12.so.0.36[.0] + * 1.2.37beta01-03 13 10237 12.so.0.37[.0] + * 1.2.37rc01 13 10237 12.so.0.37[.0] + * 1.2.37 13 10237 12.so.0.37[.0] + * 1.2.45 10 10045 12.so.0.45[.0] + * 1.0.46 10 10046 10.so.0.46[.0] + * 1.2.38beta01 13 10238 12.so.0.38[.0] + * 1.2.38rc01-03 13 10238 12.so.0.38[.0] + * 1.0.47 10 10047 10.so.0.47[.0] + * 1.2.38 13 10238 12.so.0.38[.0] + * 1.2.39beta01-05 13 10239 12.so.0.39[.0] + * 1.2.39rc01 13 10239 12.so.0.39[.0] + * 1.0.48 10 10048 10.so.0.48[.0] + * 1.2.39 13 10239 12.so.0.39[.0] + * 1.2.40beta01 13 10240 12.so.0.40[.0] + * 1.2.40rc01 13 10240 12.so.0.40[.0] + * 1.0.49 10 10049 10.so.0.49[.0] + * 1.2.40 13 10240 12.so.0.40[.0] + * 1.2.41beta01-18 13 10241 12.so.0.41[.0] + * 1.0.51rc01 10 10051 10.so.0.51[.0] + * 1.2.41rc01-03 13 10241 12.so.0.41[.0] + * 1.0.51 10 10051 10.so.0.51[.0] + * 1.2.41 13 10241 12.so.0.41[.0] + * 1.2.42beta01-02 13 10242 12.so.0.42[.0] + * 1.2.42rc01-05 13 10242 12.so.0.42[.0] + * 1.0.52 10 10052 10.so.0.52[.0] + * 1.2.42 13 10242 12.so.0.42[.0] + * 1.2.43beta01-05 13 10243 12.so.0.43[.0] + * 1.0.53rc01-02 10 10053 10.so.0.53[.0] + * 1.2.43rc01-02 13 10243 12.so.0.43[.0] + * 1.0.53 10 10053 10.so.0.53[.0] + * 1.2.43 13 10243 12.so.0.43[.0] + * 1.2.44beta01-03 13 10244 12.so.0.44[.0] + * 1.2.44rc01-03 13 10244 12.so.0.44[.0] + * 1.2.44 13 10244 12.so.0.44[.0] + * + * Henceforth the source version will match the shared-library major + * and minor numbers; the shared-library major version number will be + * used for changes in backward compatibility, as it is intended. The + * PNG_LIBPNG_VER macro, which is not used within libpng but is available + * for applications, is an unsigned integer of the form xyyzz corresponding + * to the source version x.y.z (leading zeros in y and z). Beta versions + * were given the previous public release number plus a letter, until + * version 1.0.6j; from then on they were given the upcoming public + * release number plus "betaNN" or "rcNN". + * + * Binary incompatibility exists only when applications make direct access + * to the info_ptr or png_ptr members through png.h, and the compiled + * application is loaded with a different version of the library. + * + * DLLNUM will change each time there are forward or backward changes + * in binary compatibility (e.g., when a new feature is added). + * + * See libpng.txt or libpng.3 for more information. The PNG specification + * is available as a W3C Recommendation and as an ISO Specification, + * <http://www.w3.org/TR/2003/REC-PNG-20031110/ + */ + +/* + * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: + * + * If you modify libpng you may insert additional notices immediately following + * this sentence. + * + * This code is released under the libpng license. + * + * libpng versions 1.2.6, August 15, 2004, through 1.2.44, June 26, 2010, are + * Copyright (c) 2004, 2006-2010 Glenn Randers-Pehrson, and are + * distributed according to the same disclaimer and license as libpng-1.2.5 + * with the following individual added to the list of Contributing Authors: + * + * Cosmin Truta + * + * libpng versions 1.0.7, July 1, 2000, through 1.2.5, October 3, 2002, are + * Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are + * distributed according to the same disclaimer and license as libpng-1.0.6 + * with the following individuals added to the list of Contributing Authors: + * + * Simon-Pierre Cadieux + * Eric S. Raymond + * Gilles Vollant + * + * and with the following additions to the disclaimer: + * + * There is no warranty against interference with your enjoyment of the + * library or against infringement. There is no warranty that our + * efforts or the library will fulfill any of your particular purposes + * or needs. This library is provided with all faults, and the entire + * risk of satisfactory quality, performance, accuracy, and effort is with + * the user. + * + * libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are + * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson, and are + * distributed according to the same disclaimer and license as libpng-0.96, + * with the following individuals added to the list of Contributing Authors: + * + * Tom Lane + * Glenn Randers-Pehrson + * Willem van Schaik + * + * libpng versions 0.89, June 1996, through 0.96, May 1997, are + * Copyright (c) 1996, 1997 Andreas Dilger + * Distributed according to the same disclaimer and license as libpng-0.88, + * with the following individuals added to the list of Contributing Authors: + * + * John Bowler + * Kevin Bracey + * Sam Bushell + * Magnus Holmgren + * Greg Roelofs + * Tom Tanner + * + * libpng versions 0.5, May 1995, through 0.88, January 1996, are + * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. + * + * For the purposes of this copyright and license, "Contributing Authors" + * is defined as the following set of individuals: + * + * Andreas Dilger + * Dave Martindale + * Guy Eric Schalnat + * Paul Schmidt + * Tim Wegner + * + * The PNG Reference Library is supplied "AS IS". The Contributing Authors + * and Group 42, Inc. disclaim all warranties, expressed or implied, + * including, without limitation, the warranties of merchantability and of + * fitness for any purpose. The Contributing Authors and Group 42, Inc. + * assume no liability for direct, indirect, incidental, special, exemplary, + * or consequential damages, which may result from the use of the PNG + * Reference Library, even if advised of the possibility of such damage. + * + * Permission is hereby granted to use, copy, modify, and distribute this + * source code, or portions hereof, for any purpose, without fee, subject + * to the following restrictions: + * + * 1. The origin of this source code must not be misrepresented. + * + * 2. Altered versions must be plainly marked as such and + * must not be misrepresented as being the original source. + * + * 3. This Copyright notice may not be removed or altered from + * any source or altered source distribution. + * + * The Contributing Authors and Group 42, Inc. specifically permit, without + * fee, and encourage the use of this source code as a component to + * supporting the PNG file format in commercial products. If you use this + * source code in a product, acknowledgment is not required but would be + * appreciated. + */ + +/* + * A "png_get_copyright" function is available, for convenient use in "about" + * boxes and the like: + * + * printf("%s",png_get_copyright(NULL)); + * + * Also, the PNG logo (in PNG format, of course) is supplied in the + * files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). + */ + +/* + * Libpng is OSI Certified Open Source Software. OSI Certified is a + * certification mark of the Open Source Initiative. + */ + +/* + * The contributing authors would like to thank all those who helped + * with testing, bug fixes, and patience. This wouldn't have been + * possible without all of you. + * + * Thanks to Frank J. T. Wojcik for helping with the documentation. + */ + +/* + * Y2K compliance in libpng: + * ========================= + * + * June 26, 2010 + * + * Since the PNG Development group is an ad-hoc body, we can't make + * an official declaration. + * + * This is your unofficial assurance that libpng from version 0.71 and + * upward through 1.2.44 are Y2K compliant. It is my belief that earlier + * versions were also Y2K compliant. + * + * Libpng only has three year fields. One is a 2-byte unsigned integer + * that will hold years up to 65535. The other two hold the date in text + * format, and will hold years up to 9999. + * + * The integer is + * "png_uint_16 year" in png_time_struct. + * + * The strings are + * "png_charp time_buffer" in png_struct and + * "near_time_buffer", which is a local character string in png.c. + * + * There are seven time-related functions: + * png.c: png_convert_to_rfc_1123() in png.c + * (formerly png_convert_to_rfc_1152() in error) + * png_convert_from_struct_tm() in pngwrite.c, called in pngwrite.c + * png_convert_from_time_t() in pngwrite.c + * png_get_tIME() in pngget.c + * png_handle_tIME() in pngrutil.c, called in pngread.c + * png_set_tIME() in pngset.c + * png_write_tIME() in pngwutil.c, called in pngwrite.c + * + * All handle dates properly in a Y2K environment. The + * png_convert_from_time_t() function calls gmtime() to convert from system + * clock time, which returns (year - 1900), which we properly convert to + * the full 4-digit year. There is a possibility that applications using + * libpng are not passing 4-digit years into the png_convert_to_rfc_1123() + * function, or that they are incorrectly passing only a 2-digit year + * instead of "year - 1900" into the png_convert_from_struct_tm() function, + * but this is not under our control. The libpng documentation has always + * stated that it works with 4-digit years, and the APIs have been + * documented as such. + * + * The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned + * integer to hold the year, and can hold years as large as 65535. + * + * zlib, upon which libpng depends, is also Y2K compliant. It contains + * no date-related code. + * + * Glenn Randers-Pehrson + * libpng maintainer + * PNG Development Group + */ + +#ifndef PNG_H +#define PNG_H + +/* This is not the place to learn how to use libpng. The file libpng.txt + * describes how to use libpng, and the file example.c summarizes it + * with some code on which to build. This file is useful for looking + * at the actual function definitions and structure components. + */ + +/* Version information for png.h - this should match the version in png.c */ +#define PNG_LIBPNG_VER_STRING "1.2.44" +#define PNG_HEADER_VERSION_STRING \ + " libpng version 1.2.44 - June 26, 2010\n" + +#define PNG_LIBPNG_VER_SONUM 0 +#define PNG_LIBPNG_VER_DLLNUM 13 + +/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ +#define PNG_LIBPNG_VER_MAJOR 1 +#define PNG_LIBPNG_VER_MINOR 2 +#define PNG_LIBPNG_VER_RELEASE 44 +/* This should match the numeric part of the final component of + * PNG_LIBPNG_VER_STRING, omitting any leading zero: + */ + +#define PNG_LIBPNG_VER_BUILD 0 + +/* Release Status */ +#define PNG_LIBPNG_BUILD_ALPHA 1 +#define PNG_LIBPNG_BUILD_BETA 2 +#define PNG_LIBPNG_BUILD_RC 3 +#define PNG_LIBPNG_BUILD_STABLE 4 +#define PNG_LIBPNG_BUILD_RELEASE_STATUS_MASK 7 + +/* Release-Specific Flags */ +#define PNG_LIBPNG_BUILD_PATCH 8 /* Can be OR'ed with + PNG_LIBPNG_BUILD_STABLE only */ +#define PNG_LIBPNG_BUILD_PRIVATE 16 /* Cannot be OR'ed with + PNG_LIBPNG_BUILD_SPECIAL */ +#define PNG_LIBPNG_BUILD_SPECIAL 32 /* Cannot be OR'ed with + PNG_LIBPNG_BUILD_PRIVATE */ + +#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE + +/* Careful here. At one time, Guy wanted to use 082, but that would be octal. + * We must not include leading zeros. + * Versions 0.7 through 1.0.0 were in the range 0 to 100 here (only + * version 1.0.0 was mis-numbered 100 instead of 10000). From + * version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release + */ +#define PNG_LIBPNG_VER 10244 /* 1.2.44 */ + +#ifndef PNG_VERSION_INFO_ONLY +/* Include the compression library's header */ +#include "zlib.h" +#endif + +/* Include all user configurable info, including optional assembler routines */ +#include "pngconf.h" + +/* + * Added at libpng-1.2.8 */ +/* Ref MSDN: Private as priority over Special + * VS_FF_PRIVATEBUILD File *was not* built using standard release + * procedures. If this value is given, the StringFileInfo block must + * contain a PrivateBuild string. + * + * VS_FF_SPECIALBUILD File *was* built by the original company using + * standard release procedures but is a variation of the standard + * file of the same version number. If this value is given, the + * StringFileInfo block must contain a SpecialBuild string. + */ + +#ifdef PNG_USER_PRIVATEBUILD +# define PNG_LIBPNG_BUILD_TYPE \ + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_PRIVATE) +#else +# ifdef PNG_LIBPNG_SPECIALBUILD +# define PNG_LIBPNG_BUILD_TYPE \ + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_SPECIAL) +# else +# define PNG_LIBPNG_BUILD_TYPE (PNG_LIBPNG_BUILD_BASE_TYPE) +# endif +#endif + +#ifndef PNG_VERSION_INFO_ONLY + +/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* This file is arranged in several sections. The first section contains + * structure and type definitions. The second section contains the external + * library functions, while the third has the internal library functions, + * which applications aren't expected to use directly. + */ + +#ifndef PNG_NO_TYPECAST_NULL +#define int_p_NULL (int *)NULL +#define png_bytep_NULL (png_bytep)NULL +#define png_bytepp_NULL (png_bytepp)NULL +#define png_doublep_NULL (png_doublep)NULL +#define png_error_ptr_NULL (png_error_ptr)NULL +#define png_flush_ptr_NULL (png_flush_ptr)NULL +#define png_free_ptr_NULL (png_free_ptr)NULL +#define png_infopp_NULL (png_infopp)NULL +#define png_malloc_ptr_NULL (png_malloc_ptr)NULL +#define png_read_status_ptr_NULL (png_read_status_ptr)NULL +#define png_rw_ptr_NULL (png_rw_ptr)NULL +#define png_structp_NULL (png_structp)NULL +#define png_uint_16p_NULL (png_uint_16p)NULL +#define png_voidp_NULL (png_voidp)NULL +#define png_write_status_ptr_NULL (png_write_status_ptr)NULL +#else +#define int_p_NULL NULL +#define png_bytep_NULL NULL +#define png_bytepp_NULL NULL +#define png_doublep_NULL NULL +#define png_error_ptr_NULL NULL +#define png_flush_ptr_NULL NULL +#define png_free_ptr_NULL NULL +#define png_infopp_NULL NULL +#define png_malloc_ptr_NULL NULL +#define png_read_status_ptr_NULL NULL +#define png_rw_ptr_NULL NULL +#define png_structp_NULL NULL +#define png_uint_16p_NULL NULL +#define png_voidp_NULL NULL +#define png_write_status_ptr_NULL NULL +#endif + +/* Variables declared in png.c - only it needs to define PNG_NO_EXTERN */ +#if !defined(PNG_NO_EXTERN) || defined(PNG_ALWAYS_EXTERN) +/* Version information for C files, stored in png.c. This had better match + * the version above. + */ +#ifdef PNG_USE_GLOBAL_ARRAYS +PNG_EXPORT_VAR (PNG_CONST char) png_libpng_ver[18]; + /* Need room for 99.99.99beta99z */ +#else +#define png_libpng_ver png_get_header_ver(NULL) +#endif + +#ifdef PNG_USE_GLOBAL_ARRAYS +/* This was removed in version 1.0.5c */ +/* Structures to facilitate easy interlacing. See png.c for more details */ +PNG_EXPORT_VAR (PNG_CONST int FARDATA) png_pass_start[7]; +PNG_EXPORT_VAR (PNG_CONST int FARDATA) png_pass_inc[7]; +PNG_EXPORT_VAR (PNG_CONST int FARDATA) png_pass_ystart[7]; +PNG_EXPORT_VAR (PNG_CONST int FARDATA) png_pass_yinc[7]; +PNG_EXPORT_VAR (PNG_CONST int FARDATA) png_pass_mask[7]; +PNG_EXPORT_VAR (PNG_CONST int FARDATA) png_pass_dsp_mask[7]; +/* This isn't currently used. If you need it, see png.c for more details. +PNG_EXPORT_VAR (PNG_CONST int FARDATA) png_pass_height[7]; +*/ +#endif + +#endif /* PNG_NO_EXTERN */ + +/* Three color definitions. The order of the red, green, and blue, (and the + * exact size) is not important, although the size of the fields need to + * be png_byte or png_uint_16 (as defined below). + */ +typedef struct png_color_struct +{ + png_byte red; + png_byte green; + png_byte blue; +} png_color; +typedef png_color FAR * png_colorp; +typedef png_color FAR * FAR * png_colorpp; + +typedef struct png_color_16_struct +{ + png_byte index; /* used for palette files */ + png_uint_16 red; /* for use in red green blue files */ + png_uint_16 green; + png_uint_16 blue; + png_uint_16 gray; /* for use in grayscale files */ +} png_color_16; +typedef png_color_16 FAR * png_color_16p; +typedef png_color_16 FAR * FAR * png_color_16pp; + +typedef struct png_color_8_struct +{ + png_byte red; /* for use in red green blue files */ + png_byte green; + png_byte blue; + png_byte gray; /* for use in grayscale files */ + png_byte alpha; /* for alpha channel files */ +} png_color_8; +typedef png_color_8 FAR * png_color_8p; +typedef png_color_8 FAR * FAR * png_color_8pp; + +/* + * The following two structures are used for the in-core representation + * of sPLT chunks. + */ +typedef struct png_sPLT_entry_struct +{ + png_uint_16 red; + png_uint_16 green; + png_uint_16 blue; + png_uint_16 alpha; + png_uint_16 frequency; +} png_sPLT_entry; +typedef png_sPLT_entry FAR * png_sPLT_entryp; +typedef png_sPLT_entry FAR * FAR * png_sPLT_entrypp; + +/* When the depth of the sPLT palette is 8 bits, the color and alpha samples + * occupy the LSB of their respective members, and the MSB of each member + * is zero-filled. The frequency member always occupies the full 16 bits. + */ + +typedef struct png_sPLT_struct +{ + png_charp name; /* palette name */ + png_byte depth; /* depth of palette samples */ + png_sPLT_entryp entries; /* palette entries */ + png_int_32 nentries; /* number of palette entries */ +} png_sPLT_t; +typedef png_sPLT_t FAR * png_sPLT_tp; +typedef png_sPLT_t FAR * FAR * png_sPLT_tpp; + +#ifdef PNG_TEXT_SUPPORTED +/* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file, + * and whether that contents is compressed or not. The "key" field + * points to a regular zero-terminated C string. The "text", "lang", and + * "lang_key" fields can be regular C strings, empty strings, or NULL pointers. + * However, the * structure returned by png_get_text() will always contain + * regular zero-terminated C strings (possibly empty), never NULL pointers, + * so they can be safely used in printf() and other string-handling functions. + */ +typedef struct png_text_struct +{ + int compression; /* compression value: + -1: tEXt, none + 0: zTXt, deflate + 1: iTXt, none + 2: iTXt, deflate */ + png_charp key; /* keyword, 1-79 character description of "text" */ + png_charp text; /* comment, may be an empty string (ie "") + or a NULL pointer */ + png_size_t text_length; /* length of the text string */ +#ifdef PNG_iTXt_SUPPORTED + png_size_t itxt_length; /* length of the itxt string */ + png_charp lang; /* language code, 0-79 characters + or a NULL pointer */ + png_charp lang_key; /* keyword translated UTF-8 string, 0 or more + chars or a NULL pointer */ +#endif +} png_text; +typedef png_text FAR * png_textp; +typedef png_text FAR * FAR * png_textpp; +#endif + +/* Supported compression types for text in PNG files (tEXt, and zTXt). + * The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed. + */ +#define PNG_TEXT_COMPRESSION_NONE_WR -3 +#define PNG_TEXT_COMPRESSION_zTXt_WR -2 +#define PNG_TEXT_COMPRESSION_NONE -1 +#define PNG_TEXT_COMPRESSION_zTXt 0 +#define PNG_ITXT_COMPRESSION_NONE 1 +#define PNG_ITXT_COMPRESSION_zTXt 2 +#define PNG_TEXT_COMPRESSION_LAST 3 /* Not a valid value */ + +/* png_time is a way to hold the time in an machine independent way. + * Two conversions are provided, both from time_t and struct tm. There + * is no portable way to convert to either of these structures, as far + * as I know. If you know of a portable way, send it to me. As a side + * note - PNG has always been Year 2000 compliant! + */ +typedef struct png_time_struct +{ + png_uint_16 year; /* full year, as in, 1995 */ + png_byte month; /* month of year, 1 - 12 */ + png_byte day; /* day of month, 1 - 31 */ + png_byte hour; /* hour of day, 0 - 23 */ + png_byte minute; /* minute of hour, 0 - 59 */ + png_byte second; /* second of minute, 0 - 60 (for leap seconds) */ +} png_time; +typedef png_time FAR * png_timep; +typedef png_time FAR * FAR * png_timepp; + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) || \ + defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED) +/* png_unknown_chunk is a structure to hold queued chunks for which there is + * no specific support. The idea is that we can use this to queue + * up private chunks for output even though the library doesn't actually + * know about their semantics. + */ +#define PNG_CHUNK_NAME_LENGTH 5 +typedef struct png_unknown_chunk_t +{ + png_byte name[PNG_CHUNK_NAME_LENGTH]; + png_byte *data; + png_size_t size; + + /* libpng-using applications should NOT directly modify this byte. */ + png_byte location; /* mode of operation at read time */ +} +png_unknown_chunk; +typedef png_unknown_chunk FAR * png_unknown_chunkp; +typedef png_unknown_chunk FAR * FAR * png_unknown_chunkpp; +#endif + +/* png_info is a structure that holds the information in a PNG file so + * that the application can find out the characteristics of the image. + * If you are reading the file, this structure will tell you what is + * in the PNG file. If you are writing the file, fill in the information + * you want to put into the PNG file, then call png_write_info(). + * The names chosen should be very close to the PNG specification, so + * consult that document for information about the meaning of each field. + * + * With libpng < 0.95, it was only possible to directly set and read the + * the values in the png_info_struct, which meant that the contents and + * order of the values had to remain fixed. With libpng 0.95 and later, + * however, there are now functions that abstract the contents of + * png_info_struct from the application, so this makes it easier to use + * libpng with dynamic libraries, and even makes it possible to use + * libraries that don't have all of the libpng ancillary chunk-handing + * functionality. + * + * In any case, the order of the parameters in png_info_struct should NOT + * be changed for as long as possible to keep compatibility with applications + * that use the old direct-access method with png_info_struct. + * + * The following members may have allocated storage attached that should be + * cleaned up before the structure is discarded: palette, trans, text, + * pcal_purpose, pcal_units, pcal_params, hist, iccp_name, iccp_profile, + * splt_palettes, scal_unit, row_pointers, and unknowns. By default, these + * are automatically freed when the info structure is deallocated, if they were + * allocated internally by libpng. This behavior can be changed by means + * of the png_data_freer() function. + * + * More allocation details: all the chunk-reading functions that + * change these members go through the corresponding png_set_* + * functions. A function to clear these members is available: see + * png_free_data(). The png_set_* functions do not depend on being + * able to point info structure members to any of the storage they are + * passed (they make their own copies), EXCEPT that the png_set_text + * functions use the same storage passed to them in the text_ptr or + * itxt_ptr structure argument, and the png_set_rows and png_set_unknowns + * functions do not make their own copies. + */ +typedef struct png_info_struct +{ + /* The following are necessary for every PNG file */ + png_uint_32 width PNG_DEPSTRUCT; /* width of image in pixels (from IHDR) */ + png_uint_32 height PNG_DEPSTRUCT; /* height of image in pixels (from IHDR) */ + png_uint_32 valid PNG_DEPSTRUCT; /* valid chunk data (see PNG_INFO_ below) */ + png_uint_32 rowbytes PNG_DEPSTRUCT; /* bytes needed to hold an untransformed row */ + png_colorp palette PNG_DEPSTRUCT; /* array of color values (valid & PNG_INFO_PLTE) */ + png_uint_16 num_palette PNG_DEPSTRUCT; /* number of color entries in "palette" (PLTE) */ + png_uint_16 num_trans PNG_DEPSTRUCT; /* number of transparent palette color (tRNS) */ + png_byte bit_depth PNG_DEPSTRUCT; /* 1, 2, 4, 8, or 16 bits/channel (from IHDR) */ + png_byte color_type PNG_DEPSTRUCT; /* see PNG_COLOR_TYPE_ below (from IHDR) */ + /* The following three should have been named *_method not *_type */ + png_byte compression_type PNG_DEPSTRUCT; /* must be PNG_COMPRESSION_TYPE_BASE (IHDR) */ + png_byte filter_type PNG_DEPSTRUCT; /* must be PNG_FILTER_TYPE_BASE (from IHDR) */ + png_byte interlace_type PNG_DEPSTRUCT; /* One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ + + /* The following is informational only on read, and not used on writes. */ + png_byte channels PNG_DEPSTRUCT; /* number of data channels per pixel (1, 2, 3, 4) */ + png_byte pixel_depth PNG_DEPSTRUCT; /* number of bits per pixel */ + png_byte spare_byte PNG_DEPSTRUCT; /* to align the data, and for future use */ + png_byte signature[8] PNG_DEPSTRUCT; /* magic bytes read by libpng from start of file */ + + /* The rest of the data is optional. If you are reading, check the + * valid field to see if the information in these are valid. If you + * are writing, set the valid field to those chunks you want written, + * and initialize the appropriate fields below. + */ + +#if defined(PNG_gAMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) + /* The gAMA chunk describes the gamma characteristics of the system + * on which the image was created, normally in the range [1.0, 2.5]. + * Data is valid if (valid & PNG_INFO_gAMA) is non-zero. + */ + float gamma PNG_DEPSTRUCT; /* gamma value of image, if (valid & PNG_INFO_gAMA) */ +#endif + +#ifdef PNG_sRGB_SUPPORTED + /* GR-P, 0.96a */ + /* Data valid if (valid & PNG_INFO_sRGB) non-zero. */ + png_byte srgb_intent PNG_DEPSTRUCT; /* sRGB rendering intent [0, 1, 2, or 3] */ +#endif + +#ifdef PNG_TEXT_SUPPORTED + /* The tEXt, and zTXt chunks contain human-readable textual data in + * uncompressed, compressed, and optionally compressed forms, respectively. + * The data in "text" is an array of pointers to uncompressed, + * null-terminated C strings. Each chunk has a keyword that describes the + * textual data contained in that chunk. Keywords are not required to be + * unique, and the text string may be empty. Any number of text chunks may + * be in an image. + */ + int num_text PNG_DEPSTRUCT; /* number of comments read/to write */ + int max_text PNG_DEPSTRUCT; /* current size of text array */ + png_textp text PNG_DEPSTRUCT; /* array of comments read/to write */ +#endif /* PNG_TEXT_SUPPORTED */ + +#ifdef PNG_tIME_SUPPORTED + /* The tIME chunk holds the last time the displayed image data was + * modified. See the png_time struct for the contents of this struct. + */ + png_time mod_time PNG_DEPSTRUCT; +#endif + +#ifdef PNG_sBIT_SUPPORTED + /* The sBIT chunk specifies the number of significant high-order bits + * in the pixel data. Values are in the range [1, bit_depth], and are + * only specified for the channels in the pixel data. The contents of + * the low-order bits is not specified. Data is valid if + * (valid & PNG_INFO_sBIT) is non-zero. + */ + png_color_8 sig_bit PNG_DEPSTRUCT; /* significant bits in color channels */ +#endif + +#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_EXPAND_SUPPORTED) || \ +defined(PNG_READ_BACKGROUND_SUPPORTED) + /* The tRNS chunk supplies transparency data for paletted images and + * other image types that don't need a full alpha channel. There are + * "num_trans" transparency values for a paletted image, stored in the + * same order as the palette colors, starting from index 0. Values + * for the data are in the range [0, 255], ranging from fully transparent + * to fully opaque, respectively. For non-paletted images, there is a + * single color specified that should be treated as fully transparent. + * Data is valid if (valid & PNG_INFO_tRNS) is non-zero. + */ + png_bytep trans PNG_DEPSTRUCT; /* transparent values for paletted image */ + png_color_16 trans_values PNG_DEPSTRUCT; /* transparent color for non-palette image */ +#endif + +#if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + /* The bKGD chunk gives the suggested image background color if the + * display program does not have its own background color and the image + * is needs to composited onto a background before display. The colors + * in "background" are normally in the same color space/depth as the + * pixel data. Data is valid if (valid & PNG_INFO_bKGD) is non-zero. + */ + png_color_16 background PNG_DEPSTRUCT; +#endif + +#ifdef PNG_oFFs_SUPPORTED + /* The oFFs chunk gives the offset in "offset_unit_type" units rightwards + * and downwards from the top-left corner of the display, page, or other + * application-specific co-ordinate space. See the PNG_OFFSET_ defines + * below for the unit types. Valid if (valid & PNG_INFO_oFFs) non-zero. + */ + png_int_32 x_offset PNG_DEPSTRUCT; /* x offset on page */ + png_int_32 y_offset PNG_DEPSTRUCT; /* y offset on page */ + png_byte offset_unit_type PNG_DEPSTRUCT; /* offset units type */ +#endif + +#ifdef PNG_pHYs_SUPPORTED + /* The pHYs chunk gives the physical pixel density of the image for + * display or printing in "phys_unit_type" units (see PNG_RESOLUTION_ + * defines below). Data is valid if (valid & PNG_INFO_pHYs) is non-zero. + */ + png_uint_32 x_pixels_per_unit PNG_DEPSTRUCT; /* horizontal pixel density */ + png_uint_32 y_pixels_per_unit PNG_DEPSTRUCT; /* vertical pixel density */ + png_byte phys_unit_type PNG_DEPSTRUCT; /* resolution type (see PNG_RESOLUTION_ below) */ +#endif + +#ifdef PNG_hIST_SUPPORTED + /* The hIST chunk contains the relative frequency or importance of the + * various palette entries, so that a viewer can intelligently select a + * reduced-color palette, if required. Data is an array of "num_palette" + * values in the range [0,65535]. Data valid if (valid & PNG_INFO_hIST) + * is non-zero. + */ + png_uint_16p hist PNG_DEPSTRUCT; +#endif + +#ifdef PNG_cHRM_SUPPORTED + /* The cHRM chunk describes the CIE color characteristics of the monitor + * on which the PNG was created. This data allows the viewer to do gamut + * mapping of the input image to ensure that the viewer sees the same + * colors in the image as the creator. Values are in the range + * [0.0, 0.8]. Data valid if (valid & PNG_INFO_cHRM) non-zero. + */ +#ifdef PNG_FLOATING_POINT_SUPPORTED + float x_white PNG_DEPSTRUCT; + float y_white PNG_DEPSTRUCT; + float x_red PNG_DEPSTRUCT; + float y_red PNG_DEPSTRUCT; + float x_green PNG_DEPSTRUCT; + float y_green PNG_DEPSTRUCT; + float x_blue PNG_DEPSTRUCT; + float y_blue PNG_DEPSTRUCT; +#endif +#endif + +#ifdef PNG_pCAL_SUPPORTED + /* The pCAL chunk describes a transformation between the stored pixel + * values and original physical data values used to create the image. + * The integer range [0, 2^bit_depth - 1] maps to the floating-point + * range given by [pcal_X0, pcal_X1], and are further transformed by a + * (possibly non-linear) transformation function given by "pcal_type" + * and "pcal_params" into "pcal_units". Please see the PNG_EQUATION_ + * defines below, and the PNG-Group's PNG extensions document for a + * complete description of the transformations and how they should be + * implemented, and for a description of the ASCII parameter strings. + * Data values are valid if (valid & PNG_INFO_pCAL) non-zero. + */ + png_charp pcal_purpose PNG_DEPSTRUCT; /* pCAL chunk description string */ + png_int_32 pcal_X0 PNG_DEPSTRUCT; /* minimum value */ + png_int_32 pcal_X1 PNG_DEPSTRUCT; /* maximum value */ + png_charp pcal_units PNG_DEPSTRUCT; /* Latin-1 string giving physical units */ + png_charpp pcal_params PNG_DEPSTRUCT; /* ASCII strings containing parameter values */ + png_byte pcal_type PNG_DEPSTRUCT; /* equation type (see PNG_EQUATION_ below) */ + png_byte pcal_nparams PNG_DEPSTRUCT; /* number of parameters given in pcal_params */ +#endif + +/* New members added in libpng-1.0.6 */ +#ifdef PNG_FREE_ME_SUPPORTED + png_uint_32 free_me PNG_DEPSTRUCT; /* flags items libpng is responsible for freeing */ +#endif + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) || \ + defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED) + /* Storage for unknown chunks that the library doesn't recognize. */ + png_unknown_chunkp unknown_chunks PNG_DEPSTRUCT; + png_size_t unknown_chunks_num PNG_DEPSTRUCT; +#endif + +#ifdef PNG_iCCP_SUPPORTED + /* iCCP chunk data. */ + png_charp iccp_name PNG_DEPSTRUCT; /* profile name */ + png_charp iccp_profile PNG_DEPSTRUCT; /* International Color Consortium profile data */ + /* Note to maintainer: should be png_bytep */ + png_uint_32 iccp_proflen PNG_DEPSTRUCT; /* ICC profile data length */ + png_byte iccp_compression PNG_DEPSTRUCT; /* Always zero */ +#endif + +#ifdef PNG_sPLT_SUPPORTED + /* Data on sPLT chunks (there may be more than one). */ + png_sPLT_tp splt_palettes PNG_DEPSTRUCT; + png_uint_32 splt_palettes_num PNG_DEPSTRUCT; +#endif + +#ifdef PNG_sCAL_SUPPORTED + /* The sCAL chunk describes the actual physical dimensions of the + * subject matter of the graphic. The chunk contains a unit specification + * a byte value, and two ASCII strings representing floating-point + * values. The values are width and height corresponsing to one pixel + * in the image. This external representation is converted to double + * here. Data values are valid if (valid & PNG_INFO_sCAL) is non-zero. + */ + png_byte scal_unit PNG_DEPSTRUCT; /* unit of physical scale */ +#ifdef PNG_FLOATING_POINT_SUPPORTED + double scal_pixel_width PNG_DEPSTRUCT; /* width of one pixel */ + double scal_pixel_height PNG_DEPSTRUCT; /* height of one pixel */ +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + png_charp scal_s_width PNG_DEPSTRUCT; /* string containing height */ + png_charp scal_s_height PNG_DEPSTRUCT; /* string containing width */ +#endif +#endif + +#ifdef PNG_INFO_IMAGE_SUPPORTED + /* Memory has been allocated if (valid & PNG_ALLOCATED_INFO_ROWS) non-zero */ + /* Data valid if (valid & PNG_INFO_IDAT) non-zero */ + png_bytepp row_pointers PNG_DEPSTRUCT; /* the image bits */ +#endif + +#if defined(PNG_FIXED_POINT_SUPPORTED) && defined(PNG_gAMA_SUPPORTED) + png_fixed_point int_gamma PNG_DEPSTRUCT; /* gamma of image, if (valid & PNG_INFO_gAMA) */ +#endif + +#if defined(PNG_cHRM_SUPPORTED) && defined(PNG_FIXED_POINT_SUPPORTED) + png_fixed_point int_x_white PNG_DEPSTRUCT; + png_fixed_point int_y_white PNG_DEPSTRUCT; + png_fixed_point int_x_red PNG_DEPSTRUCT; + png_fixed_point int_y_red PNG_DEPSTRUCT; + png_fixed_point int_x_green PNG_DEPSTRUCT; + png_fixed_point int_y_green PNG_DEPSTRUCT; + png_fixed_point int_x_blue PNG_DEPSTRUCT; + png_fixed_point int_y_blue PNG_DEPSTRUCT; +#endif + +} png_info; + +typedef png_info FAR * png_infop; +typedef png_info FAR * FAR * png_infopp; + +/* Maximum positive integer used in PNG is (2^31)-1 */ +#define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL) +#define PNG_UINT_32_MAX ((png_uint_32)(-1)) +#define PNG_SIZE_MAX ((png_size_t)(-1)) +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +/* PNG_MAX_UINT is deprecated; use PNG_UINT_31_MAX instead. */ +#define PNG_MAX_UINT PNG_UINT_31_MAX +#endif + +/* These describe the color_type field in png_info. */ +/* color type masks */ +#define PNG_COLOR_MASK_PALETTE 1 +#define PNG_COLOR_MASK_COLOR 2 +#define PNG_COLOR_MASK_ALPHA 4 + +/* color types. Note that not all combinations are legal */ +#define PNG_COLOR_TYPE_GRAY 0 +#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE) +#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR) +#define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA) +#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA) +/* aliases */ +#define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA +#define PNG_COLOR_TYPE_GA PNG_COLOR_TYPE_GRAY_ALPHA + +/* This is for compression type. PNG 1.0-1.2 only define the single type. */ +#define PNG_COMPRESSION_TYPE_BASE 0 /* Deflate method 8, 32K window */ +#define PNG_COMPRESSION_TYPE_DEFAULT PNG_COMPRESSION_TYPE_BASE + +/* This is for filter type. PNG 1.0-1.2 only define the single type. */ +#define PNG_FILTER_TYPE_BASE 0 /* Single row per-byte filtering */ +#define PNG_INTRAPIXEL_DIFFERENCING 64 /* Used only in MNG datastreams */ +#define PNG_FILTER_TYPE_DEFAULT PNG_FILTER_TYPE_BASE + +/* These are for the interlacing type. These values should NOT be changed. */ +#define PNG_INTERLACE_NONE 0 /* Non-interlaced image */ +#define PNG_INTERLACE_ADAM7 1 /* Adam7 interlacing */ +#define PNG_INTERLACE_LAST 2 /* Not a valid value */ + +/* These are for the oFFs chunk. These values should NOT be changed. */ +#define PNG_OFFSET_PIXEL 0 /* Offset in pixels */ +#define PNG_OFFSET_MICROMETER 1 /* Offset in micrometers (1/10^6 meter) */ +#define PNG_OFFSET_LAST 2 /* Not a valid value */ + +/* These are for the pCAL chunk. These values should NOT be changed. */ +#define PNG_EQUATION_LINEAR 0 /* Linear transformation */ +#define PNG_EQUATION_BASE_E 1 /* Exponential base e transform */ +#define PNG_EQUATION_ARBITRARY 2 /* Arbitrary base exponential transform */ +#define PNG_EQUATION_HYPERBOLIC 3 /* Hyperbolic sine transformation */ +#define PNG_EQUATION_LAST 4 /* Not a valid value */ + +/* These are for the sCAL chunk. These values should NOT be changed. */ +#define PNG_SCALE_UNKNOWN 0 /* unknown unit (image scale) */ +#define PNG_SCALE_METER 1 /* meters per pixel */ +#define PNG_SCALE_RADIAN 2 /* radians per pixel */ +#define PNG_SCALE_LAST 3 /* Not a valid value */ + +/* These are for the pHYs chunk. These values should NOT be changed. */ +#define PNG_RESOLUTION_UNKNOWN 0 /* pixels/unknown unit (aspect ratio) */ +#define PNG_RESOLUTION_METER 1 /* pixels/meter */ +#define PNG_RESOLUTION_LAST 2 /* Not a valid value */ + +/* These are for the sRGB chunk. These values should NOT be changed. */ +#define PNG_sRGB_INTENT_PERCEPTUAL 0 +#define PNG_sRGB_INTENT_RELATIVE 1 +#define PNG_sRGB_INTENT_SATURATION 2 +#define PNG_sRGB_INTENT_ABSOLUTE 3 +#define PNG_sRGB_INTENT_LAST 4 /* Not a valid value */ + +/* This is for text chunks */ +#define PNG_KEYWORD_MAX_LENGTH 79 + +/* Maximum number of entries in PLTE/sPLT/tRNS arrays */ +#define PNG_MAX_PALETTE_LENGTH 256 + +/* These determine if an ancillary chunk's data has been successfully read + * from the PNG header, or if the application has filled in the corresponding + * data in the info_struct to be written into the output file. The values + * of the PNG_INFO_<chunk> defines should NOT be changed. + */ +#define PNG_INFO_gAMA 0x0001 +#define PNG_INFO_sBIT 0x0002 +#define PNG_INFO_cHRM 0x0004 +#define PNG_INFO_PLTE 0x0008 +#define PNG_INFO_tRNS 0x0010 +#define PNG_INFO_bKGD 0x0020 +#define PNG_INFO_hIST 0x0040 +#define PNG_INFO_pHYs 0x0080 +#define PNG_INFO_oFFs 0x0100 +#define PNG_INFO_tIME 0x0200 +#define PNG_INFO_pCAL 0x0400 +#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */ +#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */ +#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */ +#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */ +#define PNG_INFO_IDAT 0x8000L /* ESR, 1.0.6 */ + +/* This is used for the transformation routines, as some of them + * change these values for the row. It also should enable using + * the routines for other purposes. + */ +typedef struct png_row_info_struct +{ + png_uint_32 width; /* width of row */ + png_uint_32 rowbytes; /* number of bytes in row */ + png_byte color_type; /* color type of row */ + png_byte bit_depth; /* bit depth of row */ + png_byte channels; /* number of channels (1, 2, 3, or 4) */ + png_byte pixel_depth; /* bits per pixel (depth * channels) */ +} png_row_info; + +typedef png_row_info FAR * png_row_infop; +typedef png_row_info FAR * FAR * png_row_infopp; + +/* These are the function types for the I/O functions and for the functions + * that allow the user to override the default I/O functions with his or her + * own. The png_error_ptr type should match that of user-supplied warning + * and error functions, while the png_rw_ptr type should match that of the + * user read/write data functions. + */ +typedef struct png_struct_def png_struct; +typedef png_struct FAR * png_structp; + +typedef void (PNGAPI *png_error_ptr) PNGARG((png_structp, png_const_charp)); +typedef void (PNGAPI *png_rw_ptr) PNGARG((png_structp, png_bytep, png_size_t)); +typedef void (PNGAPI *png_flush_ptr) PNGARG((png_structp)); +typedef void (PNGAPI *png_read_status_ptr) PNGARG((png_structp, png_uint_32, + int)); +typedef void (PNGAPI *png_write_status_ptr) PNGARG((png_structp, png_uint_32, + int)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +typedef void (PNGAPI *png_progressive_info_ptr) PNGARG((png_structp, png_infop)); +typedef void (PNGAPI *png_progressive_end_ptr) PNGARG((png_structp, png_infop)); +typedef void (PNGAPI *png_progressive_row_ptr) PNGARG((png_structp, png_bytep, + png_uint_32, int)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +typedef void (PNGAPI *png_user_transform_ptr) PNGARG((png_structp, + png_row_infop, png_bytep)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +typedef int (PNGAPI *png_user_chunk_ptr) PNGARG((png_structp, png_unknown_chunkp)); +#endif +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +typedef void (PNGAPI *png_unknown_chunk_ptr) PNGARG((png_structp)); +#endif + +/* Transform masks for the high-level interface */ +#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ +#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ +#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ +#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ +#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ +#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ +#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ +#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ +#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ +#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ +#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ +#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ +#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* write only, deprecated */ +/* Added to libpng-1.2.34 */ +#define PNG_TRANSFORM_STRIP_FILLER_BEFORE 0x0800 /* write only */ +#define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* write only */ +/* Added to libpng-1.2.41 */ +#define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */ + +/* Flags for MNG supported features */ +#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 +#define PNG_FLAG_MNG_FILTER_64 0x04 +#define PNG_ALL_MNG_FEATURES 0x05 + +typedef png_voidp (*png_malloc_ptr) PNGARG((png_structp, png_size_t)); +typedef void (*png_free_ptr) PNGARG((png_structp, png_voidp)); + +/* The structure that holds the information to read and write PNG files. + * The only people who need to care about what is inside of this are the + * people who will be modifying the library for their own special needs. + * It should NOT be accessed directly by an application, except to store + * the jmp_buf. + */ + +struct png_struct_def +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf jmpbuf; /* used in png_error */ +#endif + png_error_ptr error_fn PNG_DEPSTRUCT; /* function for printing errors and aborting */ + png_error_ptr warning_fn PNG_DEPSTRUCT; /* function for printing warnings */ + png_voidp error_ptr PNG_DEPSTRUCT; /* user supplied struct for error functions */ + png_rw_ptr write_data_fn PNG_DEPSTRUCT; /* function for writing output data */ + png_rw_ptr read_data_fn PNG_DEPSTRUCT; /* function for reading input data */ + png_voidp io_ptr PNG_DEPSTRUCT; /* ptr to application struct for I/O functions */ + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + png_user_transform_ptr read_user_transform_fn PNG_DEPSTRUCT; /* user read transform */ +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + png_user_transform_ptr write_user_transform_fn PNG_DEPSTRUCT; /* user write transform */ +#endif + +/* These were added in libpng-1.0.2 */ +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + png_voidp user_transform_ptr PNG_DEPSTRUCT; /* user supplied struct for user transform */ + png_byte user_transform_depth PNG_DEPSTRUCT; /* bit depth of user transformed pixels */ + png_byte user_transform_channels PNG_DEPSTRUCT; /* channels in user transformed pixels */ +#endif +#endif + + png_uint_32 mode PNG_DEPSTRUCT; /* tells us where we are in the PNG file */ + png_uint_32 flags PNG_DEPSTRUCT; /* flags indicating various things to libpng */ + png_uint_32 transformations PNG_DEPSTRUCT; /* which transformations to perform */ + + z_stream zstream PNG_DEPSTRUCT; /* pointer to decompression structure (below) */ + png_bytep zbuf PNG_DEPSTRUCT; /* buffer for zlib */ + png_size_t zbuf_size PNG_DEPSTRUCT; /* size of zbuf */ + int zlib_level PNG_DEPSTRUCT; /* holds zlib compression level */ + int zlib_method PNG_DEPSTRUCT; /* holds zlib compression method */ + int zlib_window_bits PNG_DEPSTRUCT; /* holds zlib compression window bits */ + int zlib_mem_level PNG_DEPSTRUCT; /* holds zlib compression memory level */ + int zlib_strategy PNG_DEPSTRUCT; /* holds zlib compression strategy */ + + png_uint_32 width PNG_DEPSTRUCT; /* width of image in pixels */ + png_uint_32 height PNG_DEPSTRUCT; /* height of image in pixels */ + png_uint_32 num_rows PNG_DEPSTRUCT; /* number of rows in current pass */ + png_uint_32 usr_width PNG_DEPSTRUCT; /* width of row at start of write */ + png_uint_32 rowbytes PNG_DEPSTRUCT; /* size of row in bytes */ +#if 0 /* Replaced with the following in libpng-1.2.43 */ + png_size_t irowbytes PNG_DEPSTRUCT; +#endif +/* Added in libpng-1.2.43 */ +#ifdef PNG_USER_LIMITS_SUPPORTED + /* Added in libpng-1.4.0: Total number of sPLT, text, and unknown + * chunks that can be stored (0 means unlimited). + */ + png_uint_32 user_chunk_cache_max PNG_DEPSTRUCT; +#endif + png_uint_32 iwidth PNG_DEPSTRUCT; /* width of current interlaced row in pixels */ + png_uint_32 row_number PNG_DEPSTRUCT; /* current row in interlace pass */ + png_bytep prev_row PNG_DEPSTRUCT; /* buffer to save previous (unfiltered) row */ + png_bytep row_buf PNG_DEPSTRUCT; /* buffer to save current (unfiltered) row */ +#ifndef PNG_NO_WRITE_FILTER + png_bytep sub_row PNG_DEPSTRUCT; /* buffer to save "sub" row when filtering */ + png_bytep up_row PNG_DEPSTRUCT; /* buffer to save "up" row when filtering */ + png_bytep avg_row PNG_DEPSTRUCT; /* buffer to save "avg" row when filtering */ + png_bytep paeth_row PNG_DEPSTRUCT; /* buffer to save "Paeth" row when filtering */ +#endif + png_row_info row_info PNG_DEPSTRUCT; /* used for transformation routines */ + + png_uint_32 idat_size PNG_DEPSTRUCT; /* current IDAT size for read */ + png_uint_32 crc PNG_DEPSTRUCT; /* current chunk CRC value */ + png_colorp palette PNG_DEPSTRUCT; /* palette from the input file */ + png_uint_16 num_palette PNG_DEPSTRUCT; /* number of color entries in palette */ + png_uint_16 num_trans PNG_DEPSTRUCT; /* number of transparency values */ + png_byte chunk_name[5] PNG_DEPSTRUCT; /* null-terminated name of current chunk */ + png_byte compression PNG_DEPSTRUCT; /* file compression type (always 0) */ + png_byte filter PNG_DEPSTRUCT; /* file filter type (always 0) */ + png_byte interlaced PNG_DEPSTRUCT; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ + png_byte pass PNG_DEPSTRUCT; /* current interlace pass (0 - 6) */ + png_byte do_filter PNG_DEPSTRUCT; /* row filter flags (see PNG_FILTER_ below ) */ + png_byte color_type PNG_DEPSTRUCT; /* color type of file */ + png_byte bit_depth PNG_DEPSTRUCT; /* bit depth of file */ + png_byte usr_bit_depth PNG_DEPSTRUCT; /* bit depth of users row */ + png_byte pixel_depth PNG_DEPSTRUCT; /* number of bits per pixel */ + png_byte channels PNG_DEPSTRUCT; /* number of channels in file */ + png_byte usr_channels PNG_DEPSTRUCT; /* channels at start of write */ + png_byte sig_bytes PNG_DEPSTRUCT; /* magic bytes read/written from start of file */ + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +#ifdef PNG_LEGACY_SUPPORTED + png_byte filler PNG_DEPSTRUCT; /* filler byte for pixel expansion */ +#else + png_uint_16 filler PNG_DEPSTRUCT; /* filler bytes for pixel expansion */ +#endif +#endif + +#ifdef PNG_bKGD_SUPPORTED + png_byte background_gamma_type PNG_DEPSTRUCT; +# ifdef PNG_FLOATING_POINT_SUPPORTED + float background_gamma PNG_DEPSTRUCT; +# endif + png_color_16 background PNG_DEPSTRUCT; /* background color in screen gamma space */ +#ifdef PNG_READ_GAMMA_SUPPORTED + png_color_16 background_1 PNG_DEPSTRUCT; /* background normalized to gamma 1.0 */ +#endif +#endif /* PNG_bKGD_SUPPORTED */ + +#ifdef PNG_WRITE_FLUSH_SUPPORTED + png_flush_ptr output_flush_fn PNG_DEPSTRUCT; /* Function for flushing output */ + png_uint_32 flush_dist PNG_DEPSTRUCT; /* how many rows apart to flush, 0 - no flush */ + png_uint_32 flush_rows PNG_DEPSTRUCT; /* number of rows written since last flush */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + int gamma_shift PNG_DEPSTRUCT; /* number of "insignificant" bits 16-bit gamma */ +#ifdef PNG_FLOATING_POINT_SUPPORTED + float gamma PNG_DEPSTRUCT; /* file gamma value */ + float screen_gamma PNG_DEPSTRUCT; /* screen gamma value (display_exponent) */ +#endif +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_bytep gamma_table PNG_DEPSTRUCT; /* gamma table for 8-bit depth files */ + png_bytep gamma_from_1 PNG_DEPSTRUCT; /* converts from 1.0 to screen */ + png_bytep gamma_to_1 PNG_DEPSTRUCT; /* converts from file to 1.0 */ + png_uint_16pp gamma_16_table PNG_DEPSTRUCT; /* gamma table for 16-bit depth files */ + png_uint_16pp gamma_16_from_1 PNG_DEPSTRUCT; /* converts from 1.0 to screen */ + png_uint_16pp gamma_16_to_1 PNG_DEPSTRUCT; /* converts from file to 1.0 */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED) + png_color_8 sig_bit PNG_DEPSTRUCT; /* significant bits in each available channel */ +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) + png_color_8 shift PNG_DEPSTRUCT; /* shift for significant bit tranformation */ +#endif + +#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \ + || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_bytep trans PNG_DEPSTRUCT; /* transparency values for paletted files */ + png_color_16 trans_values PNG_DEPSTRUCT; /* transparency values for non-paletted files */ +#endif + + png_read_status_ptr read_row_fn PNG_DEPSTRUCT; /* called after each row is decoded */ + png_write_status_ptr write_row_fn PNG_DEPSTRUCT; /* called after each row is encoded */ +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + png_progressive_info_ptr info_fn PNG_DEPSTRUCT; /* called after header data fully read */ + png_progressive_row_ptr row_fn PNG_DEPSTRUCT; /* called after each prog. row is decoded */ + png_progressive_end_ptr end_fn PNG_DEPSTRUCT; /* called after image is complete */ + png_bytep save_buffer_ptr PNG_DEPSTRUCT; /* current location in save_buffer */ + png_bytep save_buffer PNG_DEPSTRUCT; /* buffer for previously read data */ + png_bytep current_buffer_ptr PNG_DEPSTRUCT; /* current location in current_buffer */ + png_bytep current_buffer PNG_DEPSTRUCT; /* buffer for recently used data */ + png_uint_32 push_length PNG_DEPSTRUCT; /* size of current input chunk */ + png_uint_32 skip_length PNG_DEPSTRUCT; /* bytes to skip in input data */ + png_size_t save_buffer_size PNG_DEPSTRUCT; /* amount of data now in save_buffer */ + png_size_t save_buffer_max PNG_DEPSTRUCT; /* total size of save_buffer */ + png_size_t buffer_size PNG_DEPSTRUCT; /* total amount of available input data */ + png_size_t current_buffer_size PNG_DEPSTRUCT; /* amount of data now in current_buffer */ + int process_mode PNG_DEPSTRUCT; /* what push library is currently doing */ + int cur_palette PNG_DEPSTRUCT; /* current push library palette index */ + +# ifdef PNG_TEXT_SUPPORTED + png_size_t current_text_size PNG_DEPSTRUCT; /* current size of text input data */ + png_size_t current_text_left PNG_DEPSTRUCT; /* how much text left to read in input */ + png_charp current_text PNG_DEPSTRUCT; /* current text chunk buffer */ + png_charp current_text_ptr PNG_DEPSTRUCT; /* current location in current_text */ +# endif /* PNG_TEXT_SUPPORTED */ +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) +/* for the Borland special 64K segment handler */ + png_bytepp offset_table_ptr PNG_DEPSTRUCT; + png_bytep offset_table PNG_DEPSTRUCT; + png_uint_16 offset_table_number PNG_DEPSTRUCT; + png_uint_16 offset_table_count PNG_DEPSTRUCT; + png_uint_16 offset_table_count_free PNG_DEPSTRUCT; +#endif + +#ifdef PNG_READ_DITHER_SUPPORTED + png_bytep palette_lookup PNG_DEPSTRUCT; /* lookup table for dithering */ + png_bytep dither_index PNG_DEPSTRUCT; /* index translation for palette files */ +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) || defined(PNG_hIST_SUPPORTED) + png_uint_16p hist PNG_DEPSTRUCT; /* histogram */ +#endif + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + png_byte heuristic_method PNG_DEPSTRUCT; /* heuristic for row filter selection */ + png_byte num_prev_filters PNG_DEPSTRUCT; /* number of weights for previous rows */ + png_bytep prev_filters PNG_DEPSTRUCT; /* filter type(s) of previous row(s) */ + png_uint_16p filter_weights PNG_DEPSTRUCT; /* weight(s) for previous line(s) */ + png_uint_16p inv_filter_weights PNG_DEPSTRUCT; /* 1/weight(s) for previous line(s) */ + png_uint_16p filter_costs PNG_DEPSTRUCT; /* relative filter calculation cost */ + png_uint_16p inv_filter_costs PNG_DEPSTRUCT; /* 1/relative filter calculation cost */ +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED + png_charp time_buffer PNG_DEPSTRUCT; /* String to hold RFC 1123 time text */ +#endif + +/* New members added in libpng-1.0.6 */ + +#ifdef PNG_FREE_ME_SUPPORTED + png_uint_32 free_me PNG_DEPSTRUCT; /* flags items libpng is responsible for freeing */ +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED + png_voidp user_chunk_ptr PNG_DEPSTRUCT; + png_user_chunk_ptr read_user_chunk_fn PNG_DEPSTRUCT; /* user read chunk handler */ +#endif + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + int num_chunk_list PNG_DEPSTRUCT; + png_bytep chunk_list PNG_DEPSTRUCT; +#endif + +/* New members added in libpng-1.0.3 */ +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + png_byte rgb_to_gray_status PNG_DEPSTRUCT; + /* These were changed from png_byte in libpng-1.0.6 */ + png_uint_16 rgb_to_gray_red_coeff PNG_DEPSTRUCT; + png_uint_16 rgb_to_gray_green_coeff PNG_DEPSTRUCT; + png_uint_16 rgb_to_gray_blue_coeff PNG_DEPSTRUCT; +#endif + +/* New member added in libpng-1.0.4 (renamed in 1.0.9) */ +#if defined(PNG_MNG_FEATURES_SUPPORTED) || \ + defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ + defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) +/* Changed from png_byte to png_uint_32 at version 1.2.0 */ +#ifdef PNG_1_0_X + png_byte mng_features_permitted PNG_DEPSTRUCT; +#else + png_uint_32 mng_features_permitted PNG_DEPSTRUCT; +#endif /* PNG_1_0_X */ +#endif + +/* New member added in libpng-1.0.7 */ +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_fixed_point int_gamma PNG_DEPSTRUCT; +#endif + +/* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */ +#ifdef PNG_MNG_FEATURES_SUPPORTED + png_byte filter_type PNG_DEPSTRUCT; +#endif + +#ifdef PNG_1_0_X +/* New member added in libpng-1.0.10, ifdef'ed out in 1.2.0 */ + png_uint_32 row_buf_size PNG_DEPSTRUCT; +#endif + +/* New members added in libpng-1.2.0 */ +#ifdef PNG_ASSEMBLER_CODE_SUPPORTED +# ifndef PNG_1_0_X +# ifdef PNG_MMX_CODE_SUPPORTED + png_byte mmx_bitdepth_threshold PNG_DEPSTRUCT; + png_uint_32 mmx_rowbytes_threshold PNG_DEPSTRUCT; +# endif + png_uint_32 asm_flags PNG_DEPSTRUCT; +# endif +#endif + +/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */ +#ifdef PNG_USER_MEM_SUPPORTED + png_voidp mem_ptr PNG_DEPSTRUCT; /* user supplied struct for mem functions */ + png_malloc_ptr malloc_fn PNG_DEPSTRUCT; /* function for allocating memory */ + png_free_ptr free_fn PNG_DEPSTRUCT; /* function for freeing memory */ +#endif + +/* New member added in libpng-1.0.13 and 1.2.0 */ + png_bytep big_row_buf PNG_DEPSTRUCT; /* buffer to save current (unfiltered) row */ + +#ifdef PNG_READ_DITHER_SUPPORTED +/* The following three members were added at version 1.0.14 and 1.2.4 */ + png_bytep dither_sort PNG_DEPSTRUCT; /* working sort array */ + png_bytep index_to_palette PNG_DEPSTRUCT; /* where the original index currently is */ + /* in the palette */ + png_bytep palette_to_index PNG_DEPSTRUCT; /* which original index points to this */ + /* palette color */ +#endif + +/* New members added in libpng-1.0.16 and 1.2.6 */ + png_byte compression_type PNG_DEPSTRUCT; + +#ifdef PNG_USER_LIMITS_SUPPORTED + png_uint_32 user_width_max PNG_DEPSTRUCT; + png_uint_32 user_height_max PNG_DEPSTRUCT; +#endif + +/* New member added in libpng-1.0.25 and 1.2.17 */ +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED + /* Storage for unknown chunk that the library doesn't recognize. */ + png_unknown_chunk unknown_chunk PNG_DEPSTRUCT; +#endif + +/* New members added in libpng-1.2.26 */ + png_uint_32 old_big_row_buf_size PNG_DEPSTRUCT; + png_uint_32 old_prev_row_size PNG_DEPSTRUCT; + +/* New member added in libpng-1.2.30 */ + png_charp chunkdata PNG_DEPSTRUCT; /* buffer for reading chunk data */ + + +}; + + +/* This triggers a compiler error in png.c, if png.c and png.h + * do not agree upon the version number. + */ +typedef png_structp version_1_2_44; + +typedef png_struct FAR * FAR * png_structpp; + +/* Here are the function definitions most commonly used. This is not + * the place to find out how to use libpng. See libpng.txt for the + * full explanation, see example.c for the summary. This just provides + * a simple one line description of the use of each function. + */ + +/* Returns the version number of the library */ +extern PNG_EXPORT(png_uint_32,png_access_version_number) PNGARG((void)); + +/* Tell lib we have already handled the first <num_bytes> magic bytes. + * Handling more than 8 bytes from the beginning of the file is an error. + */ +extern PNG_EXPORT(void,png_set_sig_bytes) PNGARG((png_structp png_ptr, + int num_bytes)); + +/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a + * PNG file. Returns zero if the supplied bytes match the 8-byte PNG + * signature, and non-zero otherwise. Having num_to_check == 0 or + * start > 7 will always fail (ie return non-zero). + */ +extern PNG_EXPORT(int,png_sig_cmp) PNGARG((png_bytep sig, png_size_t start, + png_size_t num_to_check)); + +/* Simple signature checking function. This is the same as calling + * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). + */ +extern PNG_EXPORT(int,png_check_sig) PNGARG((png_bytep sig, int num)) PNG_DEPRECATED; + +/* Allocate and initialize png_ptr struct for reading, and any other memory. */ +extern PNG_EXPORT(png_structp,png_create_read_struct) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn)) PNG_ALLOCATED; + +/* Allocate and initialize png_ptr struct for writing, and any other memory */ +extern PNG_EXPORT(png_structp,png_create_write_struct) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn)) PNG_ALLOCATED; + +#ifdef PNG_WRITE_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_compression_buffer_size) + PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_WRITE_SUPPORTED +extern PNG_EXPORT(void,png_set_compression_buffer_size) + PNGARG((png_structp png_ptr, png_uint_32 size)); +#endif + +/* Reset the compression stream */ +extern PNG_EXPORT(int,png_reset_zstream) PNGARG((png_structp png_ptr)); + +/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ +#ifdef PNG_USER_MEM_SUPPORTED +extern PNG_EXPORT(png_structp,png_create_read_struct_2) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)) PNG_ALLOCATED; +extern PNG_EXPORT(png_structp,png_create_write_struct_2) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)) PNG_ALLOCATED; +#endif + +/* Write a PNG chunk - size, type, (optional) data, CRC. */ +extern PNG_EXPORT(void,png_write_chunk) PNGARG((png_structp png_ptr, + png_bytep chunk_name, png_bytep data, png_size_t length)); + +/* Write the start of a PNG chunk - length and chunk name. */ +extern PNG_EXPORT(void,png_write_chunk_start) PNGARG((png_structp png_ptr, + png_bytep chunk_name, png_uint_32 length)); + +/* Write the data of a PNG chunk started with png_write_chunk_start(). */ +extern PNG_EXPORT(void,png_write_chunk_data) PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); + +/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ +extern PNG_EXPORT(void,png_write_chunk_end) PNGARG((png_structp png_ptr)); + +/* Allocate and initialize the info structure */ +extern PNG_EXPORT(png_infop,png_create_info_struct) + PNGARG((png_structp png_ptr)) PNG_ALLOCATED; + +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +/* Initialize the info structure (old interface - DEPRECATED) */ +extern PNG_EXPORT(void,png_info_init) PNGARG((png_infop info_ptr)) + PNG_DEPRECATED; +#undef png_info_init +#define png_info_init(info_ptr) png_info_init_3(&info_ptr,\ + png_sizeof(png_info)); +#endif + +extern PNG_EXPORT(void,png_info_init_3) PNGARG((png_infopp info_ptr, + png_size_t png_info_struct_size)); + +/* Writes all the PNG information before the image. */ +extern PNG_EXPORT(void,png_write_info_before_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr)); +extern PNG_EXPORT(void,png_write_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the information before the actual image data. */ +extern PNG_EXPORT(void,png_read_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED +extern PNG_EXPORT(png_charp,png_convert_to_rfc1123) + PNGARG((png_structp png_ptr, png_timep ptime)); +#endif + +#ifdef PNG_CONVERT_tIME_SUPPORTED +/* Convert from a struct tm to png_time */ +extern PNG_EXPORT(void,png_convert_from_struct_tm) PNGARG((png_timep ptime, + struct tm FAR * ttime)); + +/* Convert from time_t to png_time. Uses gmtime() */ +extern PNG_EXPORT(void,png_convert_from_time_t) PNGARG((png_timep ptime, + time_t ttime)); +#endif /* PNG_CONVERT_tIME_SUPPORTED */ + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ +extern PNG_EXPORT(void,png_set_expand) PNGARG((png_structp png_ptr)); +#ifndef PNG_1_0_X +extern PNG_EXPORT(void,png_set_expand_gray_1_2_4_to_8) PNGARG((png_structp + png_ptr)); +#endif +extern PNG_EXPORT(void,png_set_palette_to_rgb) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_tRNS_to_alpha) PNGARG((png_structp png_ptr)); +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +/* Deprecated */ +extern PNG_EXPORT(void,png_set_gray_1_2_4_to_8) PNGARG((png_structp + png_ptr)) PNG_DEPRECATED; +#endif +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Use blue, green, red order for pixels. */ +extern PNG_EXPORT(void,png_set_bgr) PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +/* Expand the grayscale to 24-bit RGB if necessary. */ +extern PNG_EXPORT(void,png_set_gray_to_rgb) PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +/* Reduce RGB to grayscale. */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_rgb_to_gray) PNGARG((png_structp png_ptr, + int error_action, double red, double green )); +#endif +extern PNG_EXPORT(void,png_set_rgb_to_gray_fixed) PNGARG((png_structp png_ptr, + int error_action, png_fixed_point red, png_fixed_point green )); +extern PNG_EXPORT(png_byte,png_get_rgb_to_gray_status) PNGARG((png_structp + png_ptr)); +#endif + +extern PNG_EXPORT(void,png_build_grayscale_palette) PNGARG((int bit_depth, + png_colorp palette)); + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED +extern PNG_EXPORT(void,png_set_strip_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +extern PNG_EXPORT(void,png_set_swap_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +extern PNG_EXPORT(void,png_set_invert_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte to 8-bit Gray or 24-bit RGB images. */ +extern PNG_EXPORT(void,png_set_filler) PNGARG((png_structp png_ptr, + png_uint_32 filler, int flags)); +/* The values of the PNG_FILLER_ defines should NOT be changed */ +#define PNG_FILLER_BEFORE 0 +#define PNG_FILLER_AFTER 1 +/* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */ +#ifndef PNG_1_0_X +extern PNG_EXPORT(void,png_set_add_alpha) PNGARG((png_structp png_ptr, + png_uint_32 filler, int flags)); +#endif +#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */ + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swap bytes in 16-bit depth files. */ +extern PNG_EXPORT(void,png_set_swap) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ +extern PNG_EXPORT(void,png_set_packing) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Swap packing order of pixels in bytes. */ +extern PNG_EXPORT(void,png_set_packswap) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +/* Converts files to legal bit depths. */ +extern PNG_EXPORT(void,png_set_shift) PNGARG((png_structp png_ptr, + png_color_8p true_bits)); +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* Have the code handle the interlacing. Returns the number of passes. */ +extern PNG_EXPORT(int,png_set_interlace_handling) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +/* Invert monochrome files */ +extern PNG_EXPORT(void,png_set_invert_mono) PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* Handle alpha and tRNS by replacing with a background color. */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_background) PNGARG((png_structp png_ptr, + png_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma)); +#endif +#define PNG_BACKGROUND_GAMMA_UNKNOWN 0 +#define PNG_BACKGROUND_GAMMA_SCREEN 1 +#define PNG_BACKGROUND_GAMMA_FILE 2 +#define PNG_BACKGROUND_GAMMA_UNIQUE 3 +#endif + +#ifdef PNG_READ_16_TO_8_SUPPORTED +/* Strip the second byte of information from a 16-bit depth file. */ +extern PNG_EXPORT(void,png_set_strip_16) PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_READ_DITHER_SUPPORTED +/* Turn on dithering, and reduce the palette to the number of colors available. */ +extern PNG_EXPORT(void,png_set_dither) PNGARG((png_structp png_ptr, + png_colorp palette, int num_palette, int maximum_colors, + png_uint_16p histogram, int full_dither)); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* Handle gamma correction. Screen_gamma=(display_exponent) */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_gamma) PNGARG((png_structp png_ptr, + double screen_gamma, double default_file_gamma)); +#endif +#endif + +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ + defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) +/* Permit or disallow empty PLTE (0: not permitted, 1: permitted) */ +/* Deprecated and will be removed. Use png_permit_mng_features() instead. */ +extern PNG_EXPORT(void,png_permit_empty_plte) PNGARG((png_structp png_ptr, + int empty_plte_permitted)) PNG_DEPRECATED; +#endif +#endif + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +/* Set how many lines between output flushes - 0 for no flushing */ +extern PNG_EXPORT(void,png_set_flush) PNGARG((png_structp png_ptr, int nrows)); +/* Flush the current PNG output buffer */ +extern PNG_EXPORT(void,png_write_flush) PNGARG((png_structp png_ptr)); +#endif + +/* Optional update palette with requested transformations */ +extern PNG_EXPORT(void,png_start_read_image) PNGARG((png_structp png_ptr)); + +/* Optional call to update the users info structure */ +extern PNG_EXPORT(void,png_read_update_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* Read one or more rows of image data. */ +extern PNG_EXPORT(void,png_read_rows) PNGARG((png_structp png_ptr, + png_bytepp row, png_bytepp display_row, png_uint_32 num_rows)); +#endif + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* Read a row of data. */ +extern PNG_EXPORT(void,png_read_row) PNGARG((png_structp png_ptr, + png_bytep row, + png_bytep display_row)); +#endif + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* Read the whole image into memory at once. */ +extern PNG_EXPORT(void,png_read_image) PNGARG((png_structp png_ptr, + png_bytepp image)); +#endif + +/* Write a row of image data */ +extern PNG_EXPORT(void,png_write_row) PNGARG((png_structp png_ptr, + png_bytep row)); + +/* Write a few rows of image data */ +extern PNG_EXPORT(void,png_write_rows) PNGARG((png_structp png_ptr, + png_bytepp row, png_uint_32 num_rows)); + +/* Write the image data */ +extern PNG_EXPORT(void,png_write_image) PNGARG((png_structp png_ptr, + png_bytepp image)); + +/* Writes the end of the PNG file. */ +extern PNG_EXPORT(void,png_write_end) PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* Read the end of the PNG file. */ +extern PNG_EXPORT(void,png_read_end) PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif + +/* Free any memory associated with the png_info_struct */ +extern PNG_EXPORT(void,png_destroy_info_struct) PNGARG((png_structp png_ptr, + png_infopp info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +extern PNG_EXPORT(void,png_destroy_read_struct) PNGARG((png_structpp + png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); + +/* Free all memory used by the read (old method - NOT DLL EXPORTED) */ +extern void png_read_destroy PNGARG((png_structp png_ptr, png_infop info_ptr, + png_infop end_info_ptr)) PNG_DEPRECATED; + +/* Free any memory associated with the png_struct and the png_info_structs */ +extern PNG_EXPORT(void,png_destroy_write_struct) + PNGARG((png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)); + +/* Free any memory used in png_ptr struct (old method - NOT DLL EXPORTED) */ +extern void png_write_destroy PNGARG((png_structp png_ptr)) PNG_DEPRECATED; + +/* Set the libpng method of handling chunk CRC errors */ +extern PNG_EXPORT(void,png_set_crc_action) PNGARG((png_structp png_ptr, + int crit_action, int ancil_action)); + +/* Values for png_set_crc_action() to say how to handle CRC errors in + * ancillary and critical chunks, and whether to use the data contained + * therein. Note that it is impossible to "discard" data in a critical + * chunk. For versions prior to 0.90, the action was always error/quit, + * whereas in version 0.90 and later, the action for CRC errors in ancillary + * chunks is warn/discard. These values should NOT be changed. + * + * value action:critical action:ancillary + */ +#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ +#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ +#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ +#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ +#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ +#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ + +/* These functions give the user control over the scan-line filtering in + * libpng and the compression methods used by zlib. These functions are + * mainly useful for testing, as the defaults should work with most users. + * Those users who are tight on memory or want faster performance at the + * expense of compression can modify them. See the compression library + * header file (zlib.h) for an explination of the compression functions. + */ + +/* Set the filtering method(s) used by libpng. Currently, the only valid + * value for "method" is 0. + */ +extern PNG_EXPORT(void,png_set_filter) PNGARG((png_structp png_ptr, int method, + int filters)); + +/* Flags for png_set_filter() to say which filters to use. The flags + * are chosen so that they don't conflict with real filter types + * below, in case they are supplied instead of the #defined constants. + * These values should NOT be changed. + */ +#define PNG_NO_FILTERS 0x00 +#define PNG_FILTER_NONE 0x08 +#define PNG_FILTER_SUB 0x10 +#define PNG_FILTER_UP 0x20 +#define PNG_FILTER_AVG 0x40 +#define PNG_FILTER_PAETH 0x80 +#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \ + PNG_FILTER_AVG | PNG_FILTER_PAETH) + +/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. + * These defines should NOT be changed. + */ +#define PNG_FILTER_VALUE_NONE 0 +#define PNG_FILTER_VALUE_SUB 1 +#define PNG_FILTER_VALUE_UP 2 +#define PNG_FILTER_VALUE_AVG 3 +#define PNG_FILTER_VALUE_PAETH 4 +#define PNG_FILTER_VALUE_LAST 5 + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* EXPERIMENTAL */ +/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_ + * defines, either the default (minimum-sum-of-absolute-differences), or + * the experimental method (weighted-minimum-sum-of-absolute-differences). + * + * Weights are factors >= 1.0, indicating how important it is to keep the + * filter type consistent between rows. Larger numbers mean the current + * filter is that many times as likely to be the same as the "num_weights" + * previous filters. This is cumulative for each previous row with a weight. + * There needs to be "num_weights" values in "filter_weights", or it can be + * NULL if the weights aren't being specified. Weights have no influence on + * the selection of the first row filter. Well chosen weights can (in theory) + * improve the compression for a given image. + * + * Costs are factors >= 1.0 indicating the relative decoding costs of a + * filter type. Higher costs indicate more decoding expense, and are + * therefore less likely to be selected over a filter with lower computational + * costs. There needs to be a value in "filter_costs" for each valid filter + * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't + * setting the costs. Costs try to improve the speed of decompression without + * unduly increasing the compressed image size. + * + * A negative weight or cost indicates the default value is to be used, and + * values in the range [0.0, 1.0) indicate the value is to remain unchanged. + * The default values for both weights and costs are currently 1.0, but may + * change if good general weighting/cost heuristics can be found. If both + * the weights and costs are set to 1.0, this degenerates the WEIGHTED method + * to the UNWEIGHTED method, but with added encoding time/computation. + */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_filter_heuristics) PNGARG((png_structp png_ptr, + int heuristic_method, int num_weights, png_doublep filter_weights, + png_doublep filter_costs)); +#endif +#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ + +/* Heuristic used for row filter selection. These defines should NOT be + * changed. + */ +#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ +#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ +#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ +#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ + +/* Set the library compression level. Currently, valid values range from + * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 + * (0 - no compression, 9 - "maximal" compression). Note that tests have + * shown that zlib compression levels 3-6 usually perform as well as level 9 + * for PNG images, and do considerably fewer caclulations. In the future, + * these values may not correspond directly to the zlib compression levels. + */ +extern PNG_EXPORT(void,png_set_compression_level) PNGARG((png_structp png_ptr, + int level)); + +extern PNG_EXPORT(void,png_set_compression_mem_level) + PNGARG((png_structp png_ptr, int mem_level)); + +extern PNG_EXPORT(void,png_set_compression_strategy) + PNGARG((png_structp png_ptr, int strategy)); + +extern PNG_EXPORT(void,png_set_compression_window_bits) + PNGARG((png_structp png_ptr, int window_bits)); + +extern PNG_EXPORT(void,png_set_compression_method) PNGARG((png_structp png_ptr, + int method)); + +/* These next functions are called for input/output, memory, and error + * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, + * and call standard C I/O routines such as fread(), fwrite(), and + * fprintf(). These functions can be made to use other I/O routines + * at run time for those applications that need to handle I/O in a + * different manner by calling png_set_???_fn(). See libpng.txt for + * more information. + */ + +#ifdef PNG_STDIO_SUPPORTED +/* Initialize the input/output for the PNG file to the default functions. */ +extern PNG_EXPORT(void,png_init_io) PNGARG((png_structp png_ptr, png_FILE_p fp)); +#endif + +/* Replace the (error and abort), and warning functions with user + * supplied functions. If no messages are to be printed you must still + * write and use replacement functions. The replacement error_fn should + * still do a longjmp to the last setjmp location if you are using this + * method of error handling. If error_fn or warning_fn is NULL, the + * default function will be used. + */ + +extern PNG_EXPORT(void,png_set_error_fn) PNGARG((png_structp png_ptr, + png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); + +/* Return the user pointer associated with the error functions */ +extern PNG_EXPORT(png_voidp,png_get_error_ptr) PNGARG((png_structp png_ptr)); + +/* Replace the default data output functions with a user supplied one(s). + * If buffered output is not used, then output_flush_fn can be set to NULL. + * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time + * output_flush_fn will be ignored (and thus can be NULL). + * It is probably a mistake to use NULL for output_flush_fn if + * write_data_fn is not also NULL unless you have built libpng with + * PNG_WRITE_FLUSH_SUPPORTED undefined, because in this case libpng's + * default flush function, which uses the standard *FILE structure, will + * be used. + */ +extern PNG_EXPORT(void,png_set_write_fn) PNGARG((png_structp png_ptr, + png_voidp io_ptr, png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); + +/* Replace the default data input function with a user supplied one. */ +extern PNG_EXPORT(void,png_set_read_fn) PNGARG((png_structp png_ptr, + png_voidp io_ptr, png_rw_ptr read_data_fn)); + +/* Return the user pointer associated with the I/O functions */ +extern PNG_EXPORT(png_voidp,png_get_io_ptr) PNGARG((png_structp png_ptr)); + +extern PNG_EXPORT(void,png_set_read_status_fn) PNGARG((png_structp png_ptr, + png_read_status_ptr read_row_fn)); + +extern PNG_EXPORT(void,png_set_write_status_fn) PNGARG((png_structp png_ptr, + png_write_status_ptr write_row_fn)); + +#ifdef PNG_USER_MEM_SUPPORTED +/* Replace the default memory allocation functions with user supplied one(s). */ +extern PNG_EXPORT(void,png_set_mem_fn) PNGARG((png_structp png_ptr, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +/* Return the user pointer associated with the memory functions */ +extern PNG_EXPORT(png_voidp,png_get_mem_ptr) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +extern PNG_EXPORT(void,png_set_read_user_transform_fn) PNGARG((png_structp + png_ptr, png_user_transform_ptr read_user_transform_fn)); +#endif + +#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +extern PNG_EXPORT(void,png_set_write_user_transform_fn) PNGARG((png_structp + png_ptr, png_user_transform_ptr write_user_transform_fn)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +extern PNG_EXPORT(void,png_set_user_transform_info) PNGARG((png_structp + png_ptr, png_voidp user_transform_ptr, int user_transform_depth, + int user_transform_channels)); +/* Return the user pointer associated with the user transform functions */ +extern PNG_EXPORT(png_voidp,png_get_user_transform_ptr) + PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +extern PNG_EXPORT(void,png_set_read_user_chunk_fn) PNGARG((png_structp png_ptr, + png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); +extern PNG_EXPORT(png_voidp,png_get_user_chunk_ptr) PNGARG((png_structp + png_ptr)); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +/* Sets the function callbacks for the push reader, and a pointer to a + * user-defined structure available to the callback functions. + */ +extern PNG_EXPORT(void,png_set_progressive_read_fn) PNGARG((png_structp png_ptr, + png_voidp progressive_ptr, + png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, + png_progressive_end_ptr end_fn)); + +/* Returns the user pointer associated with the push read functions */ +extern PNG_EXPORT(png_voidp,png_get_progressive_ptr) + PNGARG((png_structp png_ptr)); + +/* Function to be called when data becomes available */ +extern PNG_EXPORT(void,png_process_data) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep buffer, png_size_t buffer_size)); + +/* Function that combines rows. Not very much different than the + * png_combine_row() call. Is this even used????? + */ +extern PNG_EXPORT(void,png_progressive_combine_row) PNGARG((png_structp png_ptr, + png_bytep old_row, png_bytep new_row)); +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +extern PNG_EXPORT(png_voidp,png_malloc) PNGARG((png_structp png_ptr, + png_uint_32 size)) PNG_ALLOCATED; + +#ifdef PNG_1_0_X +# define png_malloc_warn png_malloc +#else +/* Added at libpng version 1.2.4 */ +extern PNG_EXPORT(png_voidp,png_malloc_warn) PNGARG((png_structp png_ptr, + png_uint_32 size)) PNG_ALLOCATED; +#endif + +/* Frees a pointer allocated by png_malloc() */ +extern PNG_EXPORT(void,png_free) PNGARG((png_structp png_ptr, png_voidp ptr)); + +#ifdef PNG_1_0_X +/* Function to allocate memory for zlib. */ +extern PNG_EXPORT(voidpf,png_zalloc) PNGARG((voidpf png_ptr, uInt items, + uInt size)); + +/* Function to free memory for zlib */ +extern PNG_EXPORT(void,png_zfree) PNGARG((voidpf png_ptr, voidpf ptr)); +#endif + +/* Free data that was allocated internally */ +extern PNG_EXPORT(void,png_free_data) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 free_me, int num)); +#ifdef PNG_FREE_ME_SUPPORTED +/* Reassign responsibility for freeing existing data, whether allocated + * by libpng or by the application + */ +extern PNG_EXPORT(void,png_data_freer) PNGARG((png_structp png_ptr, + png_infop info_ptr, int freer, png_uint_32 mask)); +#endif +/* Assignments for png_data_freer */ +#define PNG_DESTROY_WILL_FREE_DATA 1 +#define PNG_SET_WILL_FREE_DATA 1 +#define PNG_USER_WILL_FREE_DATA 2 +/* Flags for png_ptr->free_me and info_ptr->free_me */ +#define PNG_FREE_HIST 0x0008 +#define PNG_FREE_ICCP 0x0010 +#define PNG_FREE_SPLT 0x0020 +#define PNG_FREE_ROWS 0x0040 +#define PNG_FREE_PCAL 0x0080 +#define PNG_FREE_SCAL 0x0100 +#define PNG_FREE_UNKN 0x0200 +#define PNG_FREE_LIST 0x0400 +#define PNG_FREE_PLTE 0x1000 +#define PNG_FREE_TRNS 0x2000 +#define PNG_FREE_TEXT 0x4000 +#define PNG_FREE_ALL 0x7fff +#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ + +#ifdef PNG_USER_MEM_SUPPORTED +extern PNG_EXPORT(png_voidp,png_malloc_default) PNGARG((png_structp png_ptr, + png_uint_32 size)) PNG_ALLOCATED; +extern PNG_EXPORT(void,png_free_default) PNGARG((png_structp png_ptr, + png_voidp ptr)); +#endif + +extern PNG_EXPORT(png_voidp,png_memcpy_check) PNGARG((png_structp png_ptr, + png_voidp s1, png_voidp s2, png_uint_32 size)) PNG_DEPRECATED; + +extern PNG_EXPORT(png_voidp,png_memset_check) PNGARG((png_structp png_ptr, + png_voidp s1, int value, png_uint_32 size)) PNG_DEPRECATED; + +#if defined(USE_FAR_KEYWORD) /* memory model conversion function */ +extern void *png_far_to_near PNGARG((png_structp png_ptr,png_voidp ptr, + int check)); +#endif /* USE_FAR_KEYWORD */ + +#ifndef PNG_NO_ERROR_TEXT +/* Fatal error in PNG image of libpng - can't continue */ +extern PNG_EXPORT(void,png_error) PNGARG((png_structp png_ptr, + png_const_charp error_message)) PNG_NORETURN; + +/* The same, but the chunk name is prepended to the error string. */ +extern PNG_EXPORT(void,png_chunk_error) PNGARG((png_structp png_ptr, + png_const_charp error_message)) PNG_NORETURN; +#else +/* Fatal error in PNG image of libpng - can't continue */ +extern PNG_EXPORT(void,png_err) PNGARG((png_structp png_ptr)) PNG_NORETURN; +#endif + +#ifndef PNG_NO_WARNINGS +/* Non-fatal error in libpng. Can continue, but may have a problem. */ +extern PNG_EXPORT(void,png_warning) PNGARG((png_structp png_ptr, + png_const_charp warning_message)); + +#ifdef PNG_READ_SUPPORTED +/* Non-fatal error in libpng, chunk name is prepended to message. */ +extern PNG_EXPORT(void,png_chunk_warning) PNGARG((png_structp png_ptr, + png_const_charp warning_message)); +#endif /* PNG_READ_SUPPORTED */ +#endif /* PNG_NO_WARNINGS */ + +/* The png_set_<chunk> functions are for storing values in the png_info_struct. + * Similarly, the png_get_<chunk> calls are used to read values from the + * png_info_struct, either storing the parameters in the passed variables, or + * setting pointers into the png_info_struct where the data is stored. The + * png_get_<chunk> functions return a non-zero value if the data was available + * in info_ptr, or return zero and do not change any of the parameters if the + * data was not available. + * + * These functions should be used instead of directly accessing png_info + * to avoid problems with future changes in the size and internal layout of + * png_info_struct. + */ +/* Returns "flag" if chunk data is valid in info_ptr. */ +extern PNG_EXPORT(png_uint_32,png_get_valid) PNGARG((png_structp png_ptr, +png_infop info_ptr, png_uint_32 flag)); + +/* Returns number of bytes needed to hold a transformed row. */ +extern PNG_EXPORT(png_uint_32,png_get_rowbytes) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* Returns row_pointers, which is an array of pointers to scanlines that was + * returned from png_read_png(). + */ +extern PNG_EXPORT(png_bytepp,png_get_rows) PNGARG((png_structp png_ptr, +png_infop info_ptr)); +/* Set row_pointers, which is an array of pointers to scanlines for use + * by png_write_png(). + */ +extern PNG_EXPORT(void,png_set_rows) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytepp row_pointers)); +#endif + +/* Returns number of color channels in image. */ +extern PNG_EXPORT(png_byte,png_get_channels) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Returns image width in pixels. */ +extern PNG_EXPORT(png_uint_32, png_get_image_width) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image height in pixels. */ +extern PNG_EXPORT(png_uint_32, png_get_image_height) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image bit_depth. */ +extern PNG_EXPORT(png_byte, png_get_bit_depth) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image color_type. */ +extern PNG_EXPORT(png_byte, png_get_color_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image filter_type. */ +extern PNG_EXPORT(png_byte, png_get_filter_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image interlace_type. */ +extern PNG_EXPORT(png_byte, png_get_interlace_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image compression_type. */ +extern PNG_EXPORT(png_byte, png_get_compression_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image resolution in pixels per meter, from pHYs chunk data. */ +extern PNG_EXPORT(png_uint_32, png_get_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_uint_32, png_get_x_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_uint_32, png_get_y_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns pixel aspect ratio, computed from pHYs chunk data. */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(float, png_get_pixel_aspect_ratio) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +#endif + +/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ +extern PNG_EXPORT(png_int_32, png_get_x_offset_pixels) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_y_offset_pixels) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_x_offset_microns) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_y_offset_microns) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +#endif /* PNG_EASY_ACCESS_SUPPORTED */ + +/* Returns pointer to signature string read from PNG header */ +extern PNG_EXPORT(png_bytep,png_get_signature) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#ifdef PNG_bKGD_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_bKGD) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_16p *background)); +#endif + +#ifdef PNG_bKGD_SUPPORTED +extern PNG_EXPORT(void,png_set_bKGD) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_16p background)); +#endif + +#ifdef PNG_cHRM_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, double *white_x, double *white_y, double *red_x, + double *red_y, double *green_x, double *green_y, double *blue_x, + double *blue_y)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_cHRM_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point *int_white_x, png_fixed_point + *int_white_y, png_fixed_point *int_red_x, png_fixed_point *int_red_y, + png_fixed_point *int_green_x, png_fixed_point *int_green_y, png_fixed_point + *int_blue_x, png_fixed_point *int_blue_y)); +#endif +#endif + +#ifdef PNG_cHRM_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, double white_x, double white_y, double red_x, + double red_y, double green_x, double green_y, double blue_x, double blue_y)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_cHRM_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_white_x, png_fixed_point int_white_y, + png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point + int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)); +#endif +#endif + +#ifdef PNG_gAMA_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_gAMA) PNGARG((png_structp png_ptr, + png_infop info_ptr, double *file_gamma)); +#endif +extern PNG_EXPORT(png_uint_32,png_get_gAMA_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point *int_file_gamma)); +#endif + +#ifdef PNG_gAMA_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_gAMA) PNGARG((png_structp png_ptr, + png_infop info_ptr, double file_gamma)); +#endif +extern PNG_EXPORT(void,png_set_gAMA_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_file_gamma)); +#endif + +#ifdef PNG_hIST_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_hIST) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_16p *hist)); +#endif + +#ifdef PNG_hIST_SUPPORTED +extern PNG_EXPORT(void,png_set_hIST) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_16p hist)); +#endif + +extern PNG_EXPORT(png_uint_32,png_get_IHDR) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 *width, png_uint_32 *height, + int *bit_depth, int *color_type, int *interlace_method, + int *compression_method, int *filter_method)); + +extern PNG_EXPORT(void,png_set_IHDR) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_method, int compression_method, + int filter_method)); + +#ifdef PNG_oFFs_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_oFFs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, + int *unit_type)); +#endif + +#ifdef PNG_oFFs_SUPPORTED +extern PNG_EXPORT(void,png_set_oFFs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_int_32 offset_x, png_int_32 offset_y, + int unit_type)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_pCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp *purpose, png_int_32 *X0, png_int_32 *X1, + int *type, int *nparams, png_charp *units, png_charpp *params)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +extern PNG_EXPORT(void,png_set_pCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp purpose, png_int_32 X0, png_int_32 X1, + int type, int nparams, png_charp units, png_charpp params)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_pHYs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +extern PNG_EXPORT(void,png_set_pHYs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); +#endif + +extern PNG_EXPORT(png_uint_32,png_get_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_colorp *palette, int *num_palette)); + +extern PNG_EXPORT(void,png_set_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_colorp palette, int num_palette)); + +#ifdef PNG_sBIT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sBIT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_8p *sig_bit)); +#endif + +#ifdef PNG_sBIT_SUPPORTED +extern PNG_EXPORT(void,png_set_sBIT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_8p sig_bit)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sRGB) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *intent)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +extern PNG_EXPORT(void,png_set_sRGB) PNGARG((png_structp png_ptr, + png_infop info_ptr, int intent)); +extern PNG_EXPORT(void,png_set_sRGB_gAMA_and_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, int intent)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_iCCP) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charpp name, int *compression_type, + png_charpp profile, png_uint_32 *proflen)); + /* Note to maintainer: profile should be png_bytepp */ +#endif + +#ifdef PNG_iCCP_SUPPORTED +extern PNG_EXPORT(void,png_set_iCCP) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp name, int compression_type, + png_charp profile, png_uint_32 proflen)); + /* Note to maintainer: profile should be png_bytep */ +#endif + +#ifdef PNG_sPLT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sPLT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_sPLT_tpp entries)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +extern PNG_EXPORT(void,png_set_sPLT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_sPLT_tp entries, int nentries)); +#endif + +#ifdef PNG_TEXT_SUPPORTED +/* png_get_text also returns the number of text chunks in *num_text */ +extern PNG_EXPORT(png_uint_32,png_get_text) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_textp *text_ptr, int *num_text)); +#endif + +/* + * Note while png_set_text() will accept a structure whose text, + * language, and translated keywords are NULL pointers, the structure + * returned by png_get_text will always contain regular + * zero-terminated C strings. They might be empty strings but + * they will never be NULL pointers. + */ + +#ifdef PNG_TEXT_SUPPORTED +extern PNG_EXPORT(void,png_set_text) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_textp text_ptr, int num_text)); +#endif + +#ifdef PNG_tIME_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_tIME) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_timep *mod_time)); +#endif + +#ifdef PNG_tIME_SUPPORTED +extern PNG_EXPORT(void,png_set_tIME) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_timep mod_time)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_tRNS) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep *trans, int *num_trans, + png_color_16p *trans_values)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +extern PNG_EXPORT(void,png_set_tRNS) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep trans, int num_trans, + png_color_16p trans_values)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +#endif + +#ifdef PNG_sCAL_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *unit, double *width, double *height)); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sCAL_s) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *unit, png_charpp swidth, png_charpp sheight)); +#endif +#endif +#endif /* PNG_sCAL_SUPPORTED */ + +#ifdef PNG_sCAL_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_sCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, int unit, double width, double height)); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_sCAL_s) PNGARG((png_structp png_ptr, + png_infop info_ptr, int unit, png_charp swidth, png_charp sheight)); +#endif +#endif +#endif /* PNG_sCAL_SUPPORTED || PNG_WRITE_sCAL_SUPPORTED */ + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +/* Provide a list of chunks and how they are to be handled, if the built-in + handling or default unknown chunk handling is not desired. Any chunks not + listed will be handled in the default manner. The IHDR and IEND chunks + must not be listed. + keep = 0: follow default behaviour + = 1: do not keep + = 2: keep only if safe-to-copy + = 3: keep even if unsafe-to-copy +*/ +extern PNG_EXPORT(void, png_set_keep_unknown_chunks) PNGARG((png_structp + png_ptr, int keep, png_bytep chunk_list, int num_chunks)); +PNG_EXPORT(int,png_handle_as_unknown) PNGARG((png_structp png_ptr, png_bytep + chunk_name)); +#endif +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +extern PNG_EXPORT(void, png_set_unknown_chunks) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)); +extern PNG_EXPORT(void, png_set_unknown_chunk_location) + PNGARG((png_structp png_ptr, png_infop info_ptr, int chunk, int location)); +extern PNG_EXPORT(png_uint_32,png_get_unknown_chunks) PNGARG((png_structp + png_ptr, png_infop info_ptr, png_unknown_chunkpp entries)); +#endif + +/* Png_free_data() will turn off the "valid" flag for anything it frees. + * If you need to turn it off for a chunk that your application has freed, + * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); + */ +extern PNG_EXPORT(void, png_set_invalid) PNGARG((png_structp png_ptr, + png_infop info_ptr, int mask)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* The "params" pointer is currently not used and is for future expansion. */ +extern PNG_EXPORT(void, png_read_png) PNGARG((png_structp png_ptr, + png_infop info_ptr, + int transforms, + png_voidp params)); +extern PNG_EXPORT(void, png_write_png) PNGARG((png_structp png_ptr, + png_infop info_ptr, + int transforms, + png_voidp params)); +#endif + +/* Define PNG_DEBUG at compile time for debugging information. Higher + * numbers for PNG_DEBUG mean more debugging information. This has + * only been added since version 0.95 so it is not implemented throughout + * libpng yet, but more support will be added as needed. + */ +#ifdef PNG_DEBUG +#if (PNG_DEBUG > 0) +#if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER) +#include <crtdbg.h> +#if (PNG_DEBUG > 1) +#ifndef _DEBUG +# define _DEBUG +#endif +#ifndef png_debug +#define png_debug(l,m) _RPT0(_CRT_WARN,m PNG_STRING_NEWLINE) +#endif +#ifndef png_debug1 +#define png_debug1(l,m,p1) _RPT1(_CRT_WARN,m PNG_STRING_NEWLINE,p1) +#endif +#ifndef png_debug2 +#define png_debug2(l,m,p1,p2) _RPT2(_CRT_WARN,m PNG_STRING_NEWLINE,p1,p2) +#endif +#endif +#else /* PNG_DEBUG_FILE || !_MSC_VER */ +#ifndef PNG_DEBUG_FILE +#define PNG_DEBUG_FILE stderr +#endif /* PNG_DEBUG_FILE */ + +#if (PNG_DEBUG > 1) +/* Note: ["%s"m PNG_STRING_NEWLINE] probably does not work on non-ISO + * compilers. + */ +# ifdef __STDC__ +# ifndef png_debug +# define png_debug(l,m) \ + { \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \ + } +# endif +# ifndef png_debug1 +# define png_debug1(l,m,p1) \ + { \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \ + } +# endif +# ifndef png_debug2 +# define png_debug2(l,m,p1,p2) \ + { \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \ + } +# endif +# else /* __STDC __ */ +# ifndef png_debug +# define png_debug(l,m) \ + { \ + int num_tabs=l; \ + char format[256]; \ + snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ + m,PNG_STRING_NEWLINE); \ + fprintf(PNG_DEBUG_FILE,format); \ + } +# endif +# ifndef png_debug1 +# define png_debug1(l,m,p1) \ + { \ + int num_tabs=l; \ + char format[256]; \ + snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ + m,PNG_STRING_NEWLINE); \ + fprintf(PNG_DEBUG_FILE,format,p1); \ + } +# endif +# ifndef png_debug2 +# define png_debug2(l,m,p1,p2) \ + { \ + int num_tabs=l; \ + char format[256]; \ + snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ + m,PNG_STRING_NEWLINE); \ + fprintf(PNG_DEBUG_FILE,format,p1,p2); \ + } +# endif +# endif /* __STDC __ */ +#endif /* (PNG_DEBUG > 1) */ + +#endif /* _MSC_VER */ +#endif /* (PNG_DEBUG > 0) */ +#endif /* PNG_DEBUG */ +#ifndef png_debug +#define png_debug(l, m) +#endif +#ifndef png_debug1 +#define png_debug1(l, m, p1) +#endif +#ifndef png_debug2 +#define png_debug2(l, m, p1, p2) +#endif + +extern PNG_EXPORT(png_charp,png_get_copyright) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_charp,png_get_header_ver) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_charp,png_get_header_version) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_charp,png_get_libpng_ver) PNGARG((png_structp png_ptr)); + +#ifdef PNG_MNG_FEATURES_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_permit_mng_features) PNGARG((png_structp + png_ptr, png_uint_32 mng_features_permitted)); +#endif + +/* For use in png_set_keep_unknown, added to version 1.2.6 */ +#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 +#define PNG_HANDLE_CHUNK_NEVER 1 +#define PNG_HANDLE_CHUNK_IF_SAFE 2 +#define PNG_HANDLE_CHUNK_ALWAYS 3 + +/* Added to version 1.2.0 */ +#ifdef PNG_ASSEMBLER_CODE_SUPPORTED +#ifdef PNG_MMX_CODE_SUPPORTED +#define PNG_ASM_FLAG_MMX_SUPPORT_COMPILED 0x01 /* not user-settable */ +#define PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU 0x02 /* not user-settable */ +#define PNG_ASM_FLAG_MMX_READ_COMBINE_ROW 0x04 +#define PNG_ASM_FLAG_MMX_READ_INTERLACE 0x08 +#define PNG_ASM_FLAG_MMX_READ_FILTER_SUB 0x10 +#define PNG_ASM_FLAG_MMX_READ_FILTER_UP 0x20 +#define PNG_ASM_FLAG_MMX_READ_FILTER_AVG 0x40 +#define PNG_ASM_FLAG_MMX_READ_FILTER_PAETH 0x80 +#define PNG_ASM_FLAGS_INITIALIZED 0x80000000 /* not user-settable */ + +#define PNG_MMX_READ_FLAGS ( PNG_ASM_FLAG_MMX_READ_COMBINE_ROW \ + | PNG_ASM_FLAG_MMX_READ_INTERLACE \ + | PNG_ASM_FLAG_MMX_READ_FILTER_SUB \ + | PNG_ASM_FLAG_MMX_READ_FILTER_UP \ + | PNG_ASM_FLAG_MMX_READ_FILTER_AVG \ + | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH ) +#define PNG_MMX_WRITE_FLAGS ( 0 ) + +#define PNG_MMX_FLAGS ( PNG_ASM_FLAG_MMX_SUPPORT_COMPILED \ + | PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU \ + | PNG_MMX_READ_FLAGS \ + | PNG_MMX_WRITE_FLAGS ) + +#define PNG_SELECT_READ 1 +#define PNG_SELECT_WRITE 2 +#endif /* PNG_MMX_CODE_SUPPORTED */ + +#ifndef PNG_1_0_X +/* pngget.c */ +extern PNG_EXPORT(png_uint_32,png_get_mmx_flagmask) + PNGARG((int flag_select, int *compilerID)); + +/* pngget.c */ +extern PNG_EXPORT(png_uint_32,png_get_asm_flagmask) + PNGARG((int flag_select)); + +/* pngget.c */ +extern PNG_EXPORT(png_uint_32,png_get_asm_flags) + PNGARG((png_structp png_ptr)); + +/* pngget.c */ +extern PNG_EXPORT(png_byte,png_get_mmx_bitdepth_threshold) + PNGARG((png_structp png_ptr)); + +/* pngget.c */ +extern PNG_EXPORT(png_uint_32,png_get_mmx_rowbytes_threshold) + PNGARG((png_structp png_ptr)); + +/* pngset.c */ +extern PNG_EXPORT(void,png_set_asm_flags) + PNGARG((png_structp png_ptr, png_uint_32 asm_flags)); + +/* pngset.c */ +extern PNG_EXPORT(void,png_set_mmx_thresholds) + PNGARG((png_structp png_ptr, png_byte mmx_bitdepth_threshold, + png_uint_32 mmx_rowbytes_threshold)); + +#endif /* PNG_1_0_X */ + +#ifndef PNG_1_0_X +/* png.c, pnggccrd.c, or pngvcrd.c */ +extern PNG_EXPORT(int,png_mmx_support) PNGARG((void)); +#endif /* PNG_1_0_X */ +#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */ + +/* Strip the prepended error numbers ("#nnn ") from error and warning + * messages before passing them to the error or warning handler. + */ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +extern PNG_EXPORT(void,png_set_strip_error_numbers) PNGARG((png_structp + png_ptr, png_uint_32 strip_mode)); +#endif + +/* Added at libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +extern PNG_EXPORT(void,png_set_user_limits) PNGARG((png_structp + png_ptr, png_uint_32 user_width_max, png_uint_32 user_height_max)); +extern PNG_EXPORT(png_uint_32,png_get_user_width_max) PNGARG((png_structp + png_ptr)); +extern PNG_EXPORT(png_uint_32,png_get_user_height_max) PNGARG((png_structp + png_ptr)); +#endif +/* Maintainer: Put new public prototypes here ^, in libpng.3, and in + * project defs + */ + +#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED +/* With these routines we avoid an integer divide, which will be slower on + * most machines. However, it does take more operations than the corresponding + * divide method, so it may be slower on a few RISC systems. There are two + * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. + * + * Note that the rounding factors are NOT supposed to be the same! 128 and + * 32768 are correct for the NODIV code; 127 and 32767 are correct for the + * standard method. + * + * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] + */ + + /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ + +# define png_composite(composite, fg, alpha, bg) \ + { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) * (png_uint_16)(alpha) \ + + (png_uint_16)(bg)*(png_uint_16)(255 - \ + (png_uint_16)(alpha)) + (png_uint_16)128); \ + (composite) = (png_byte)((temp + (temp >> 8)) >> 8); } + +# define png_composite_16(composite, fg, alpha, bg) \ + { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) * (png_uint_32)(alpha) \ + + (png_uint_32)(bg)*(png_uint_32)(65535L - \ + (png_uint_32)(alpha)) + (png_uint_32)32768L); \ + (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); } + +#else /* Standard method using integer division */ + +# define png_composite(composite, fg, alpha, bg) \ + (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \ + (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ + (png_uint_16)127) / 255) + +# define png_composite_16(composite, fg, alpha, bg) \ + (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \ + (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) + \ + (png_uint_32)32767) / (png_uint_32)65535L) + +#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */ + +/* Inline macros to do direct reads of bytes from the input buffer. These + * require that you are using an architecture that uses PNG byte ordering + * (MSB first) and supports unaligned data storage. I think that PowerPC + * in big-endian mode and 680x0 are the only ones that will support this. + * The x86 line of processors definitely do not. The png_get_int_32() + * routine also assumes we are using two's complement format for negative + * values, which is almost certainly true. + */ +#ifdef PNG_READ_BIG_ENDIAN_SUPPORTED +# define png_get_uint_32(buf) ( *((png_uint_32p) (buf))) +# define png_get_uint_16(buf) ( *((png_uint_16p) (buf))) +# define png_get_int_32(buf) ( *((png_int_32p) (buf))) +#else +extern PNG_EXPORT(png_uint_32,png_get_uint_32) PNGARG((png_bytep buf)); +extern PNG_EXPORT(png_uint_16,png_get_uint_16) PNGARG((png_bytep buf)); +extern PNG_EXPORT(png_int_32,png_get_int_32) PNGARG((png_bytep buf)); +#endif /* !PNG_READ_BIG_ENDIAN_SUPPORTED */ +extern PNG_EXPORT(png_uint_32,png_get_uint_31) + PNGARG((png_structp png_ptr, png_bytep buf)); +/* No png_get_int_16 -- may be added if there's a real need for it. */ + +/* Place a 32-bit number into a buffer in PNG byte order (big-endian). + */ +extern PNG_EXPORT(void,png_save_uint_32) + PNGARG((png_bytep buf, png_uint_32 i)); +extern PNG_EXPORT(void,png_save_int_32) + PNGARG((png_bytep buf, png_int_32 i)); + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +extern PNG_EXPORT(void,png_save_uint_16) + PNGARG((png_bytep buf, unsigned int i)); +/* No png_save_int_16 -- may be added if there's a real need for it. */ + +/* ************************************************************************* */ + +/* These next functions are used internally in the code. They generally + * shouldn't be used unless you are writing code to add or replace some + * functionality in libpng. More information about most functions can + * be found in the files where the functions are located. + */ + + +/* Various modes of operation, that are visible to applications because + * they are used for unknown chunk location. + */ +#define PNG_HAVE_IHDR 0x01 +#define PNG_HAVE_PLTE 0x02 +#define PNG_HAVE_IDAT 0x04 +#define PNG_AFTER_IDAT 0x08 /* Have complete zlib datastream */ +#define PNG_HAVE_IEND 0x10 + +#ifdef PNG_INTERNAL + +/* More modes of operation. Note that after an init, mode is set to + * zero automatically when the structure is created. + */ +#define PNG_HAVE_gAMA 0x20 +#define PNG_HAVE_cHRM 0x40 +#define PNG_HAVE_sRGB 0x80 +#define PNG_HAVE_CHUNK_HEADER 0x100 +#define PNG_WROTE_tIME 0x200 +#define PNG_WROTE_INFO_BEFORE_PLTE 0x400 +#define PNG_BACKGROUND_IS_GRAY 0x800 +#define PNG_HAVE_PNG_SIGNATURE 0x1000 +#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */ + +/* Flags for the transformations the PNG library does on the image data */ +#define PNG_BGR 0x0001 +#define PNG_INTERLACE 0x0002 +#define PNG_PACK 0x0004 +#define PNG_SHIFT 0x0008 +#define PNG_SWAP_BYTES 0x0010 +#define PNG_INVERT_MONO 0x0020 +#define PNG_DITHER 0x0040 +#define PNG_BACKGROUND 0x0080 +#define PNG_BACKGROUND_EXPAND 0x0100 + /* 0x0200 unused */ +#define PNG_16_TO_8 0x0400 +#define PNG_RGBA 0x0800 +#define PNG_EXPAND 0x1000 +#define PNG_GAMMA 0x2000 +#define PNG_GRAY_TO_RGB 0x4000 +#define PNG_FILLER 0x8000L +#define PNG_PACKSWAP 0x10000L +#define PNG_SWAP_ALPHA 0x20000L +#define PNG_STRIP_ALPHA 0x40000L +#define PNG_INVERT_ALPHA 0x80000L +#define PNG_USER_TRANSFORM 0x100000L +#define PNG_RGB_TO_GRAY_ERR 0x200000L +#define PNG_RGB_TO_GRAY_WARN 0x400000L +#define PNG_RGB_TO_GRAY 0x600000L /* two bits, RGB_TO_GRAY_ERR|WARN */ + /* 0x800000L Unused */ +#define PNG_ADD_ALPHA 0x1000000L /* Added to libpng-1.2.7 */ +#define PNG_EXPAND_tRNS 0x2000000L /* Added to libpng-1.2.9 */ +#define PNG_PREMULTIPLY_ALPHA 0x4000000L /* Added to libpng-1.2.41 */ + /* by volker */ + /* 0x8000000L unused */ + /* 0x10000000L unused */ + /* 0x20000000L unused */ + /* 0x40000000L unused */ + +/* Flags for png_create_struct */ +#define PNG_STRUCT_PNG 0x0001 +#define PNG_STRUCT_INFO 0x0002 + +/* Scaling factor for filter heuristic weighting calculations */ +#define PNG_WEIGHT_SHIFT 8 +#define PNG_WEIGHT_FACTOR (1<<(PNG_WEIGHT_SHIFT)) +#define PNG_COST_SHIFT 3 +#define PNG_COST_FACTOR (1<<(PNG_COST_SHIFT)) + +/* Flags for the png_ptr->flags rather than declaring a byte for each one */ +#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001 +#define PNG_FLAG_ZLIB_CUSTOM_LEVEL 0x0002 +#define PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL 0x0004 +#define PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS 0x0008 +#define PNG_FLAG_ZLIB_CUSTOM_METHOD 0x0010 +#define PNG_FLAG_ZLIB_FINISHED 0x0020 +#define PNG_FLAG_ROW_INIT 0x0040 +#define PNG_FLAG_FILLER_AFTER 0x0080 +#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100 +#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200 +#define PNG_FLAG_CRC_CRITICAL_USE 0x0400 +#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800 +#define PNG_FLAG_FREE_PLTE 0x1000 +#define PNG_FLAG_FREE_TRNS 0x2000 +#define PNG_FLAG_FREE_HIST 0x4000 +#define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000L +#define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000L +#define PNG_FLAG_LIBRARY_MISMATCH 0x20000L +#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000L +#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000L +#define PNG_FLAG_MALLOC_NULL_MEM_OK 0x100000L +#define PNG_FLAG_ADD_ALPHA 0x200000L /* Added to libpng-1.2.8 */ +#define PNG_FLAG_STRIP_ALPHA 0x400000L /* Added to libpng-1.2.8 */ + /* 0x800000L unused */ + /* 0x1000000L unused */ + /* 0x2000000L unused */ + /* 0x4000000L unused */ + /* 0x8000000L unused */ + /* 0x10000000L unused */ + /* 0x20000000L unused */ + /* 0x40000000L unused */ + +#define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \ + PNG_FLAG_CRC_ANCILLARY_NOWARN) + +#define PNG_FLAG_CRC_CRITICAL_MASK (PNG_FLAG_CRC_CRITICAL_USE | \ + PNG_FLAG_CRC_CRITICAL_IGNORE) + +#define PNG_FLAG_CRC_MASK (PNG_FLAG_CRC_ANCILLARY_MASK | \ + PNG_FLAG_CRC_CRITICAL_MASK) + +/* Save typing and make code easier to understand */ + +#define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \ + abs((int)((c1).green) - (int)((c2).green)) + \ + abs((int)((c1).blue) - (int)((c2).blue))) + +/* Added to libpng-1.2.6 JB */ +#define PNG_ROWBYTES(pixel_bits, width) \ + ((pixel_bits) >= 8 ? \ + ((width) * (((png_uint_32)(pixel_bits)) >> 3)) : \ + (( ((width) * ((png_uint_32)(pixel_bits))) + 7) >> 3) ) + +/* PNG_OUT_OF_RANGE returns true if value is outside the range + * ideal-delta..ideal+delta. Each argument is evaluated twice. + * "ideal" and "delta" should be constants, normally simple + * integers, "value" a variable. Added to libpng-1.2.6 JB + */ +#define PNG_OUT_OF_RANGE(value, ideal, delta) \ + ( (value) < (ideal)-(delta) || (value) > (ideal)+(delta) ) + +/* Variables declared in png.c - only it needs to define PNG_NO_EXTERN */ +#if !defined(PNG_NO_EXTERN) || defined(PNG_ALWAYS_EXTERN) +/* Place to hold the signature string for a PNG file. */ +#ifdef PNG_USE_GLOBAL_ARRAYS + PNG_EXPORT_VAR (PNG_CONST png_byte FARDATA) png_sig[8]; +#else +#endif +#endif /* PNG_NO_EXTERN */ + +/* Constant strings for known chunk types. If you need to add a chunk, + * define the name here, and add an invocation of the macro in png.c and + * wherever it's needed. + */ +#define PNG_IHDR png_byte png_IHDR[5] = { 73, 72, 68, 82, '\0'} +#define PNG_IDAT png_byte png_IDAT[5] = { 73, 68, 65, 84, '\0'} +#define PNG_IEND png_byte png_IEND[5] = { 73, 69, 78, 68, '\0'} +#define PNG_PLTE png_byte png_PLTE[5] = { 80, 76, 84, 69, '\0'} +#define PNG_bKGD png_byte png_bKGD[5] = { 98, 75, 71, 68, '\0'} +#define PNG_cHRM png_byte png_cHRM[5] = { 99, 72, 82, 77, '\0'} +#define PNG_gAMA png_byte png_gAMA[5] = {103, 65, 77, 65, '\0'} +#define PNG_hIST png_byte png_hIST[5] = {104, 73, 83, 84, '\0'} +#define PNG_iCCP png_byte png_iCCP[5] = {105, 67, 67, 80, '\0'} +#define PNG_iTXt png_byte png_iTXt[5] = {105, 84, 88, 116, '\0'} +#define PNG_oFFs png_byte png_oFFs[5] = {111, 70, 70, 115, '\0'} +#define PNG_pCAL png_byte png_pCAL[5] = {112, 67, 65, 76, '\0'} +#define PNG_sCAL png_byte png_sCAL[5] = {115, 67, 65, 76, '\0'} +#define PNG_pHYs png_byte png_pHYs[5] = {112, 72, 89, 115, '\0'} +#define PNG_sBIT png_byte png_sBIT[5] = {115, 66, 73, 84, '\0'} +#define PNG_sPLT png_byte png_sPLT[5] = {115, 80, 76, 84, '\0'} +#define PNG_sRGB png_byte png_sRGB[5] = {115, 82, 71, 66, '\0'} +#define PNG_tEXt png_byte png_tEXt[5] = {116, 69, 88, 116, '\0'} +#define PNG_tIME png_byte png_tIME[5] = {116, 73, 77, 69, '\0'} +#define PNG_tRNS png_byte png_tRNS[5] = {116, 82, 78, 83, '\0'} +#define PNG_zTXt png_byte png_zTXt[5] = {122, 84, 88, 116, '\0'} + +#ifdef PNG_USE_GLOBAL_ARRAYS +PNG_EXPORT_VAR (png_byte FARDATA) png_IHDR[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_IDAT[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_IEND[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_PLTE[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_bKGD[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_cHRM[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_gAMA[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_hIST[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_iCCP[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_iTXt[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_oFFs[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_pCAL[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_sCAL[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_pHYs[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_sBIT[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_sPLT[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_sRGB[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_tEXt[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_tIME[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_tRNS[5]; +PNG_EXPORT_VAR (png_byte FARDATA) png_zTXt[5]; +#endif /* PNG_USE_GLOBAL_ARRAYS */ + +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +/* Initialize png_ptr struct for reading, and allocate any other memory. + * (old interface - DEPRECATED - use png_create_read_struct instead). + */ +extern PNG_EXPORT(void,png_read_init) PNGARG((png_structp png_ptr)) + PNG_DEPRECATED; +#undef png_read_init +#define png_read_init(png_ptr) png_read_init_3(&png_ptr, \ + PNG_LIBPNG_VER_STRING, png_sizeof(png_struct)); +#endif + +extern PNG_EXPORT(void,png_read_init_3) PNGARG((png_structpp ptr_ptr, + png_const_charp user_png_ver, png_size_t png_struct_size)); +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +extern PNG_EXPORT(void,png_read_init_2) PNGARG((png_structp png_ptr, + png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t + png_info_size)); +#endif + +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +/* Initialize png_ptr struct for writing, and allocate any other memory. + * (old interface - DEPRECATED - use png_create_write_struct instead). + */ +extern PNG_EXPORT(void,png_write_init) PNGARG((png_structp png_ptr)) + PNG_DEPRECATED; +#undef png_write_init +#define png_write_init(png_ptr) png_write_init_3(&png_ptr, \ + PNG_LIBPNG_VER_STRING, png_sizeof(png_struct)); +#endif + +extern PNG_EXPORT(void,png_write_init_3) PNGARG((png_structpp ptr_ptr, + png_const_charp user_png_ver, png_size_t png_struct_size)); +extern PNG_EXPORT(void,png_write_init_2) PNGARG((png_structp png_ptr, + png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t + png_info_size)); + +/* Allocate memory for an internal libpng struct */ +PNG_EXTERN png_voidp png_create_struct PNGARG((int type)) PNG_PRIVATE; + +/* Free memory from internal libpng struct */ +PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr)) PNG_PRIVATE; + +PNG_EXTERN png_voidp png_create_struct_2 PNGARG((int type, png_malloc_ptr + malloc_fn, png_voidp mem_ptr)) PNG_PRIVATE; +PNG_EXTERN void png_destroy_struct_2 PNGARG((png_voidp struct_ptr, + png_free_ptr free_fn, png_voidp mem_ptr)) PNG_PRIVATE; + +/* Free any memory that info_ptr points to and reset struct. */ +PNG_EXTERN void png_info_destroy PNGARG((png_structp png_ptr, + png_infop info_ptr)) PNG_PRIVATE; + +#ifndef PNG_1_0_X +/* Function to allocate memory for zlib. */ +PNG_EXTERN voidpf png_zalloc PNGARG((voidpf png_ptr, uInt items, + uInt size)) PNG_PRIVATE; + +/* Function to free memory for zlib */ +PNG_EXTERN void png_zfree PNGARG((voidpf png_ptr, voidpf ptr)) PNG_PRIVATE; + +#ifdef PNG_SIZE_T +/* Function to convert a sizeof an item to png_sizeof item */ + PNG_EXTERN png_size_t PNGAPI png_convert_size PNGARG((size_t size)) + PNG_PRIVATE; +#endif + +/* Next four functions are used internally as callbacks. PNGAPI is required + * but not PNG_EXPORT. PNGAPI added at libpng version 1.2.3. + */ + +PNG_EXTERN void PNGAPI png_default_read_data PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)) PNG_PRIVATE; + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_EXTERN void PNGAPI png_push_fill_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t length)) PNG_PRIVATE; +#endif + +PNG_EXTERN void PNGAPI png_default_write_data PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)) PNG_PRIVATE; + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +#ifdef PNG_STDIO_SUPPORTED +PNG_EXTERN void PNGAPI png_default_flush PNGARG((png_structp png_ptr)) + PNG_PRIVATE; +#endif +#endif +#else /* PNG_1_0_X */ +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_EXTERN void png_push_fill_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t length)) PNG_PRIVATE; +#endif +#endif /* PNG_1_0_X */ + +/* Reset the CRC variable */ +PNG_EXTERN void png_reset_crc PNGARG((png_structp png_ptr)) PNG_PRIVATE; + +/* Write the "data" buffer to whatever output you are using. */ +PNG_EXTERN void png_write_data PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)) PNG_PRIVATE; + +/* Read data from whatever input you are using into the "data" buffer */ +PNG_EXTERN void png_read_data PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)) PNG_PRIVATE; + +/* Read bytes into buf, and update png_ptr->crc */ +PNG_EXTERN void png_crc_read PNGARG((png_structp png_ptr, png_bytep buf, + png_size_t length)) PNG_PRIVATE; + +/* Decompress data in a chunk that uses compression */ +#if defined(PNG_zTXt_SUPPORTED) || defined(PNG_iTXt_SUPPORTED) || \ + defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) +PNG_EXTERN void png_decompress_chunk PNGARG((png_structp png_ptr, + int comp_type, png_size_t chunklength, + png_size_t prefix_length, png_size_t *data_length)) PNG_PRIVATE; +#endif + +/* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */ +PNG_EXTERN int png_crc_finish PNGARG((png_structp png_ptr, png_uint_32 skip) + PNG_PRIVATE); + +/* Read the CRC from the file and compare it to the libpng calculated CRC */ +PNG_EXTERN int png_crc_error PNGARG((png_structp png_ptr)) PNG_PRIVATE; + +/* Calculate the CRC over a section of data. Note that we are only + * passing a maximum of 64K on systems that have this as a memory limit, + * since this is the maximum buffer size we can specify. + */ +PNG_EXTERN void png_calculate_crc PNGARG((png_structp png_ptr, png_bytep ptr, + png_size_t length)) PNG_PRIVATE; + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +PNG_EXTERN void png_flush PNGARG((png_structp png_ptr)) PNG_PRIVATE; +#endif + +/* Simple function to write the signature */ +PNG_EXTERN void png_write_sig PNGARG((png_structp png_ptr)) PNG_PRIVATE; + +/* Write various chunks */ + +/* Write the IHDR chunk, and update the png_struct with the necessary + * information. + */ +PNG_EXTERN void png_write_IHDR PNGARG((png_structp png_ptr, png_uint_32 width, + png_uint_32 height, + int bit_depth, int color_type, int compression_method, int filter_method, + int interlace_method)) PNG_PRIVATE; + +PNG_EXTERN void png_write_PLTE PNGARG((png_structp png_ptr, png_colorp palette, + png_uint_32 num_pal)) PNG_PRIVATE; + +PNG_EXTERN void png_write_IDAT PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)) PNG_PRIVATE; + +PNG_EXTERN void png_write_IEND PNGARG((png_structp png_ptr)) PNG_PRIVATE; + +#ifdef PNG_WRITE_gAMA_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_EXTERN void png_write_gAMA PNGARG((png_structp png_ptr, double file_gamma)) + PNG_PRIVATE; +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr, + png_fixed_point file_gamma)) PNG_PRIVATE; +#endif +#endif + +#ifdef PNG_WRITE_sBIT_SUPPORTED +PNG_EXTERN void png_write_sBIT PNGARG((png_structp png_ptr, png_color_8p sbit, + int color_type)) PNG_PRIVATE; +#endif + +#ifdef PNG_WRITE_cHRM_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_EXTERN void png_write_cHRM PNGARG((png_structp png_ptr, + double white_x, double white_y, + double red_x, double red_y, double green_x, double green_y, + double blue_x, double blue_y)) PNG_PRIVATE; +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_write_cHRM_fixed PNGARG((png_structp png_ptr, + png_fixed_point int_white_x, png_fixed_point int_white_y, + png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point + int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)) PNG_PRIVATE; +#endif +#endif + +#ifdef PNG_WRITE_sRGB_SUPPORTED +PNG_EXTERN void png_write_sRGB PNGARG((png_structp png_ptr, + int intent)) PNG_PRIVATE; +#endif + +#ifdef PNG_WRITE_iCCP_SUPPORTED +PNG_EXTERN void png_write_iCCP PNGARG((png_structp png_ptr, + png_charp name, int compression_type, + png_charp profile, int proflen)) PNG_PRIVATE; + /* Note to maintainer: profile should be png_bytep */ +#endif + +#ifdef PNG_WRITE_sPLT_SUPPORTED +PNG_EXTERN void png_write_sPLT PNGARG((png_structp png_ptr, + png_sPLT_tp palette)) PNG_PRIVATE; +#endif + +#ifdef PNG_WRITE_tRNS_SUPPORTED +PNG_EXTERN void png_write_tRNS PNGARG((png_structp png_ptr, png_bytep trans, + png_color_16p values, int number, int color_type)) PNG_PRIVATE; +#endif + +#ifdef PNG_WRITE_bKGD_SUPPORTED +PNG_EXTERN void png_write_bKGD PNGARG((png_structp png_ptr, + png_color_16p values, int color_type)) PNG_PRIVATE; +#endif + +#ifdef PNG_WRITE_hIST_SUPPORTED +PNG_EXTERN void png_write_hIST PNGARG((png_structp png_ptr, png_uint_16p hist, + int num_hist)) PNG_PRIVATE; +#endif + +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ + defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) +PNG_EXTERN png_size_t png_check_keyword PNGARG((png_structp png_ptr, + png_charp key, png_charpp new_key)) PNG_PRIVATE; +#endif + +#ifdef PNG_WRITE_tEXt_SUPPORTED +PNG_EXTERN void png_write_tEXt PNGARG((png_structp png_ptr, png_charp key, + png_charp text, png_size_t text_len)) PNG_PRIVATE; +#endif + +#ifdef PNG_WRITE_zTXt_SUPPORTED +PNG_EXTERN void png_write_zTXt PNGARG((png_structp png_ptr, png_charp key, + png_charp text, png_size_t text_len, int compression)) PNG_PRIVATE; +#endif + +#ifdef PNG_WRITE_iTXt_SUPPORTED +PNG_EXTERN void png_write_iTXt PNGARG((png_structp png_ptr, + int compression, png_charp key, png_charp lang, png_charp lang_key, + png_charp text)) PNG_PRIVATE; +#endif + +#ifdef PNG_TEXT_SUPPORTED /* Added at version 1.0.14 and 1.2.4 */ +PNG_EXTERN int png_set_text_2 PNGARG((png_structp png_ptr, + png_infop info_ptr, png_textp text_ptr, int num_text)) PNG_PRIVATE; +#endif + +#ifdef PNG_WRITE_oFFs_SUPPORTED +PNG_EXTERN void png_write_oFFs PNGARG((png_structp png_ptr, + png_int_32 x_offset, png_int_32 y_offset, int unit_type)) PNG_PRIVATE; +#endif + +#ifdef PNG_WRITE_pCAL_SUPPORTED +PNG_EXTERN void png_write_pCAL PNGARG((png_structp png_ptr, png_charp purpose, + png_int_32 X0, png_int_32 X1, int type, int nparams, + png_charp units, png_charpp params)) PNG_PRIVATE; +#endif + +#ifdef PNG_WRITE_pHYs_SUPPORTED +PNG_EXTERN void png_write_pHYs PNGARG((png_structp png_ptr, + png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit, + int unit_type)) PNG_PRIVATE; +#endif + +#ifdef PNG_WRITE_tIME_SUPPORTED +PNG_EXTERN void png_write_tIME PNGARG((png_structp png_ptr, + png_timep mod_time)) PNG_PRIVATE; +#endif + +#ifdef PNG_WRITE_sCAL_SUPPORTED +#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO) +PNG_EXTERN void png_write_sCAL PNGARG((png_structp png_ptr, + int unit, double width, double height)) PNG_PRIVATE; +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr, + int unit, png_charp width, png_charp height)) PNG_PRIVATE; +#endif +#endif +#endif + +/* Called when finished processing a row of data */ +PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr)) PNG_PRIVATE; + +/* Internal use only. Called before first row of data */ +PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr)) PNG_PRIVATE; + +#ifdef PNG_READ_GAMMA_SUPPORTED +PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr)) PNG_PRIVATE; +#endif + +/* Combine a row of data, dealing with alpha, etc. if requested */ +PNG_EXTERN void png_combine_row PNGARG((png_structp png_ptr, png_bytep row, + int mask)) PNG_PRIVATE; + +#ifdef PNG_READ_INTERLACING_SUPPORTED +/* Expand an interlaced row */ +/* OLD pre-1.0.9 interface: +PNG_EXTERN void png_do_read_interlace PNGARG((png_row_infop row_info, + png_bytep row, int pass, png_uint_32 transformations)) PNG_PRIVATE; + */ +PNG_EXTERN void png_do_read_interlace PNGARG((png_structp png_ptr)) PNG_PRIVATE; +#endif + +/* GRR TO DO (2.0 or whenever): simplify other internal calling interfaces */ + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED +/* Grab pixels out of a row for an interlaced pass */ +PNG_EXTERN void png_do_write_interlace PNGARG((png_row_infop row_info, + png_bytep row, int pass)) PNG_PRIVATE; +#endif + +/* Unfilter a row */ +PNG_EXTERN void png_read_filter_row PNGARG((png_structp png_ptr, + png_row_infop row_info, png_bytep row, png_bytep prev_row, + int filter)) PNG_PRIVATE; + +/* Choose the best filter to use and filter the row data */ +PNG_EXTERN void png_write_find_filter PNGARG((png_structp png_ptr, + png_row_infop row_info)) PNG_PRIVATE; + +/* Write out the filtered row. */ +PNG_EXTERN void png_write_filtered_row PNGARG((png_structp png_ptr, + png_bytep filtered_row)) PNG_PRIVATE; +/* Finish a row while reading, dealing with interlacing passes, etc. */ +PNG_EXTERN void png_read_finish_row PNGARG((png_structp png_ptr)); + +/* Initialize the row buffers, etc. */ +PNG_EXTERN void png_read_start_row PNGARG((png_structp png_ptr)) PNG_PRIVATE; +/* Optional call to update the users info structure */ +PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr, + png_infop info_ptr)) PNG_PRIVATE; + +/* These are the functions that do the transformations */ +#ifdef PNG_READ_FILLER_SUPPORTED +PNG_EXTERN void png_do_read_filler PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 filler, png_uint_32 flags)) PNG_PRIVATE; +#endif + +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED +PNG_EXTERN void png_do_read_swap_alpha PNGARG((png_row_infop row_info, + png_bytep row)) PNG_PRIVATE; +#endif + +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED +PNG_EXTERN void png_do_write_swap_alpha PNGARG((png_row_infop row_info, + png_bytep row)) PNG_PRIVATE; +#endif + +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED +PNG_EXTERN void png_do_read_invert_alpha PNGARG((png_row_infop row_info, + png_bytep row)) PNG_PRIVATE; +#endif + +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED +PNG_EXTERN void png_do_write_invert_alpha PNGARG((png_row_infop row_info, + png_bytep row)) PNG_PRIVATE; +#endif + +#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ + defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_strip_filler PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 flags)) PNG_PRIVATE; +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +PNG_EXTERN void png_do_swap PNGARG((png_row_infop row_info, + png_bytep row)) PNG_PRIVATE; +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || defined(PNG_WRITE_PACKSWAP_SUPPORTED) +PNG_EXTERN void png_do_packswap PNGARG((png_row_infop row_info, + png_bytep row)) PNG_PRIVATE; +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +PNG_EXTERN int png_do_rgb_to_gray PNGARG((png_structp png_ptr, png_row_infop + row_info, png_bytep row)) PNG_PRIVATE; +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +PNG_EXTERN void png_do_gray_to_rgb PNGARG((png_row_infop row_info, + png_bytep row)) PNG_PRIVATE; +#endif + +#ifdef PNG_READ_PACK_SUPPORTED +PNG_EXTERN void png_do_unpack PNGARG((png_row_infop row_info, + png_bytep row)) PNG_PRIVATE; +#endif + +#ifdef PNG_READ_SHIFT_SUPPORTED +PNG_EXTERN void png_do_unshift PNGARG((png_row_infop row_info, png_bytep row, + png_color_8p sig_bits)) PNG_PRIVATE; +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +PNG_EXTERN void png_do_invert PNGARG((png_row_infop row_info, + png_bytep row)) PNG_PRIVATE; +#endif + +#ifdef PNG_READ_16_TO_8_SUPPORTED +PNG_EXTERN void png_do_chop PNGARG((png_row_infop row_info, + png_bytep row)) PNG_PRIVATE; +#endif + +#ifdef PNG_READ_DITHER_SUPPORTED +PNG_EXTERN void png_do_dither PNGARG((png_row_infop row_info, + png_bytep row, png_bytep palette_lookup, + png_bytep dither_lookup)) PNG_PRIVATE; + +# ifdef PNG_CORRECT_PALETTE_SUPPORTED +PNG_EXTERN void png_correct_palette PNGARG((png_structp png_ptr, + png_colorp palette, int num_palette)) PNG_PRIVATE; +# endif +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +PNG_EXTERN void png_do_bgr PNGARG((png_row_infop row_info, + png_bytep row)) PNG_PRIVATE; +#endif + +#ifdef PNG_WRITE_PACK_SUPPORTED +PNG_EXTERN void png_do_pack PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 bit_depth)) PNG_PRIVATE; +#endif + +#ifdef PNG_WRITE_SHIFT_SUPPORTED +PNG_EXTERN void png_do_shift PNGARG((png_row_infop row_info, png_bytep row, + png_color_8p bit_depth)) PNG_PRIVATE; +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +#ifdef PNG_READ_GAMMA_SUPPORTED +PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row, + png_color_16p trans_values, png_color_16p background, + png_color_16p background_1, + png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1, + png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1, + png_uint_16pp gamma_16_to_1, int gamma_shift)) PNG_PRIVATE; +#else +PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row, + png_color_16p trans_values, png_color_16p background)) PNG_PRIVATE; +#endif +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +PNG_EXTERN void png_do_gamma PNGARG((png_row_infop row_info, png_bytep row, + png_bytep gamma_table, png_uint_16pp gamma_16_table, + int gamma_shift)) PNG_PRIVATE; +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED +PNG_EXTERN void png_do_expand_palette PNGARG((png_row_infop row_info, + png_bytep row, png_colorp palette, png_bytep trans, + int num_trans)) PNG_PRIVATE; +PNG_EXTERN void png_do_expand PNGARG((png_row_infop row_info, + png_bytep row, png_color_16p trans_value)) PNG_PRIVATE; +#endif + +/* The following decodes the appropriate chunks, and does error correction, + * then calls the appropriate callback for the chunk if it is valid. + */ + +/* Decode the IHDR chunk */ +PNG_EXTERN void png_handle_IHDR PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)) PNG_PRIVATE; +PNG_EXTERN void png_handle_PLTE PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +PNG_EXTERN void png_handle_IEND PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); + +#ifdef PNG_READ_bKGD_SUPPORTED +PNG_EXTERN void png_handle_bKGD PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)) PNG_PRIVATE; +#endif + +#ifdef PNG_READ_cHRM_SUPPORTED +PNG_EXTERN void png_handle_cHRM PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)) PNG_PRIVATE; +#endif + +#ifdef PNG_READ_gAMA_SUPPORTED +PNG_EXTERN void png_handle_gAMA PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)) PNG_PRIVATE; +#endif + +#ifdef PNG_READ_hIST_SUPPORTED +PNG_EXTERN void png_handle_hIST PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)) PNG_PRIVATE; +#endif + +#ifdef PNG_READ_iCCP_SUPPORTED +extern void png_handle_iCCP PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif /* PNG_READ_iCCP_SUPPORTED */ + +#ifdef PNG_READ_iTXt_SUPPORTED +PNG_EXTERN void png_handle_iTXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)) PNG_PRIVATE; +#endif + +#ifdef PNG_READ_oFFs_SUPPORTED +PNG_EXTERN void png_handle_oFFs PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)) PNG_PRIVATE; +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED +PNG_EXTERN void png_handle_pCAL PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)) PNG_PRIVATE; +#endif + +#ifdef PNG_READ_pHYs_SUPPORTED +PNG_EXTERN void png_handle_pHYs PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)) PNG_PRIVATE; +#endif + +#ifdef PNG_READ_sBIT_SUPPORTED +PNG_EXTERN void png_handle_sBIT PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)) PNG_PRIVATE; +#endif + +#ifdef PNG_READ_sCAL_SUPPORTED +PNG_EXTERN void png_handle_sCAL PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)) PNG_PRIVATE; +#endif + +#ifdef PNG_READ_sPLT_SUPPORTED +extern void png_handle_sPLT PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)) PNG_PRIVATE; +#endif /* PNG_READ_sPLT_SUPPORTED */ + +#ifdef PNG_READ_sRGB_SUPPORTED +PNG_EXTERN void png_handle_sRGB PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)) PNG_PRIVATE; +#endif + +#ifdef PNG_READ_tEXt_SUPPORTED +PNG_EXTERN void png_handle_tEXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)) PNG_PRIVATE; +#endif + +#ifdef PNG_READ_tIME_SUPPORTED +PNG_EXTERN void png_handle_tIME PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)) PNG_PRIVATE; +#endif + +#ifdef PNG_READ_tRNS_SUPPORTED +PNG_EXTERN void png_handle_tRNS PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)) PNG_PRIVATE; +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED +PNG_EXTERN void png_handle_zTXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)) PNG_PRIVATE; +#endif + +PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)) PNG_PRIVATE; + +PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr, + png_bytep chunk_name)) PNG_PRIVATE; + +/* Handle the transformations for reading and writing */ +PNG_EXTERN void png_do_read_transformations + PNGARG((png_structp png_ptr)) PNG_PRIVATE; +PNG_EXTERN void png_do_write_transformations + PNGARG((png_structp png_ptr)) PNG_PRIVATE; + +PNG_EXTERN void png_init_read_transformations + PNGARG((png_structp png_ptr)) PNG_PRIVATE; + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr, + png_infop info_ptr)) PNG_PRIVATE; +PNG_EXTERN void png_push_read_sig PNGARG((png_structp png_ptr, + png_infop info_ptr)) PNG_PRIVATE; +PNG_EXTERN void png_push_check_crc PNGARG((png_structp png_ptr)) PNG_PRIVATE; +PNG_EXTERN void png_push_crc_skip PNGARG((png_structp png_ptr, + png_uint_32 length)) PNG_PRIVATE; +PNG_EXTERN void png_push_crc_finish PNGARG((png_structp png_ptr)) PNG_PRIVATE; +PNG_EXTERN void png_push_save_buffer PNGARG((png_structp png_ptr)) PNG_PRIVATE; +PNG_EXTERN void png_push_restore_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t buffer_length)) PNG_PRIVATE; +PNG_EXTERN void png_push_read_IDAT PNGARG((png_structp png_ptr)) PNG_PRIVATE; +PNG_EXTERN void png_process_IDAT_data PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t buffer_length)) PNG_PRIVATE; +PNG_EXTERN void png_push_process_row PNGARG((png_structp png_ptr)) PNG_PRIVATE; +PNG_EXTERN void png_push_handle_unknown PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)) PNG_PRIVATE; +PNG_EXTERN void png_push_have_info PNGARG((png_structp png_ptr, + png_infop info_ptr)) PNG_PRIVATE; +PNG_EXTERN void png_push_have_end PNGARG((png_structp png_ptr, + png_infop info_ptr)) PNG_PRIVATE; +PNG_EXTERN void png_push_have_row PNGARG((png_structp png_ptr, + png_bytep row)) PNG_PRIVATE; +PNG_EXTERN void png_push_read_end PNGARG((png_structp png_ptr, + png_infop info_ptr)) PNG_PRIVATE; +PNG_EXTERN void png_process_some_data PNGARG((png_structp png_ptr, + png_infop info_ptr)) PNG_PRIVATE; +PNG_EXTERN void png_read_push_finish_row + PNGARG((png_structp png_ptr)) PNG_PRIVATE; +#ifdef PNG_READ_tEXt_SUPPORTED +PNG_EXTERN void png_push_handle_tEXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)) PNG_PRIVATE; +PNG_EXTERN void png_push_read_tEXt PNGARG((png_structp png_ptr, + png_infop info_ptr)) PNG_PRIVATE; +#endif +#ifdef PNG_READ_zTXt_SUPPORTED +PNG_EXTERN void png_push_handle_zTXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)) PNG_PRIVATE; +PNG_EXTERN void png_push_read_zTXt PNGARG((png_structp png_ptr, + png_infop info_ptr)) PNG_PRIVATE; +#endif +#ifdef PNG_READ_iTXt_SUPPORTED +PNG_EXTERN void png_push_handle_iTXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)) PNG_PRIVATE; +PNG_EXTERN void png_push_read_iTXt PNGARG((png_structp png_ptr, + png_infop info_ptr)) PNG_PRIVATE; +#endif + +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +#ifdef PNG_MNG_FEATURES_SUPPORTED +PNG_EXTERN void png_do_read_intrapixel PNGARG((png_row_infop row_info, + png_bytep row)) PNG_PRIVATE; +PNG_EXTERN void png_do_write_intrapixel PNGARG((png_row_infop row_info, + png_bytep row)) PNG_PRIVATE; +#endif + +#ifdef PNG_ASSEMBLER_CODE_SUPPORTED +#ifdef PNG_MMX_CODE_SUPPORTED +/* png.c */ /* PRIVATE */ +PNG_EXTERN void png_init_mmx_flags PNGARG((png_structp png_ptr)) PNG_PRIVATE; +#endif +#endif + + +/* The following six functions will be exported in libpng-1.4.0. */ +#if defined(PNG_INCH_CONVERSIONS) && defined(PNG_FLOATING_POINT_SUPPORTED) +PNG_EXTERN png_uint_32 png_get_pixels_per_inch PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +PNG_EXTERN png_uint_32 png_get_x_pixels_per_inch PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +PNG_EXTERN png_uint_32 png_get_y_pixels_per_inch PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +PNG_EXTERN float png_get_x_offset_inches PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +PNG_EXTERN float png_get_y_offset_inches PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXTERN png_uint_32 png_get_pHYs_dpi PNGARG((png_structp png_ptr, +png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); +#endif /* PNG_pHYs_SUPPORTED */ +#endif /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */ + +/* Read the chunk header (length + type name) */ +PNG_EXTERN png_uint_32 png_read_chunk_header + PNGARG((png_structp png_ptr)) PNG_PRIVATE; + +/* Added at libpng version 1.2.34 */ +#ifdef PNG_cHRM_SUPPORTED +PNG_EXTERN int png_check_cHRM_fixed PNGARG((png_structp png_ptr, + png_fixed_point int_white_x, png_fixed_point int_white_y, + png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point + int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)) PNG_PRIVATE; +#endif + +#ifdef PNG_cHRM_SUPPORTED +#ifdef PNG_CHECK_cHRM_SUPPORTED +/* Added at libpng version 1.2.34 */ +PNG_EXTERN void png_64bit_product PNGARG((long v1, long v2, + unsigned long *hi_product, unsigned long *lo_product)) PNG_PRIVATE; +#endif +#endif + +/* Added at libpng version 1.2.41 */ +PNG_EXTERN void png_check_IHDR PNGARG((png_structp png_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_type, int compression_type, + int filter_type)) PNG_PRIVATE; + +/* Added at libpng version 1.2.41 */ +PNG_EXTERN png_voidp png_calloc PNGARG((png_structp png_ptr, + png_uint_32 size)); + +/* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */ + +#endif /* PNG_INTERNAL */ + +#ifdef __cplusplus +} +#endif + +#endif /* PNG_VERSION_INFO_ONLY */ +/* Do not put anything past this line */ +#endif /* PNG_H */ diff --git a/contrib/syslinux-4.02/com32/include/pngconf.h b/contrib/syslinux-4.02/com32/include/pngconf.h new file mode 100644 index 0000000..defc16d --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/pngconf.h @@ -0,0 +1,1665 @@ + +/* pngconf.h - machine configurable file for libpng + * + * libpng version 1.2.44 - June 26, 2010 + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* Any machine specific code is near the front of this file, so if you + * are configuring libpng for a machine, you may want to read the section + * starting here down to where it starts to typedef png_color, png_text, + * and png_info. + */ + +#ifndef PNGCONF_H +#define PNGCONF_H + +#define PNG_1_2_X + +/* + * PNG_USER_CONFIG has to be defined on the compiler command line. This + * includes the resource compiler for Windows DLL configurations. + */ +#ifdef PNG_USER_CONFIG +# ifndef PNG_USER_PRIVATEBUILD +# define PNG_USER_PRIVATEBUILD +# endif +#include "pngusr.h" +#endif + +/* PNG_CONFIGURE_LIBPNG is set by the "configure" script. */ +#ifdef PNG_CONFIGURE_LIBPNG +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#endif + +/* + * Added at libpng-1.2.8 + * + * If you create a private DLL you need to define in "pngusr.h" the followings: + * #define PNG_USER_PRIVATEBUILD <Describes by whom and why this version of + * the DLL was built> + * e.g. #define PNG_USER_PRIVATEBUILD "Build by MyCompany for xyz reasons." + * #define PNG_USER_DLLFNAME_POSTFIX <two-letter postfix that serve to + * distinguish your DLL from those of the official release. These + * correspond to the trailing letters that come after the version + * number and must match your private DLL name> + * e.g. // private DLL "libpng13gx.dll" + * #define PNG_USER_DLLFNAME_POSTFIX "gx" + * + * The following macros are also at your disposal if you want to complete the + * DLL VERSIONINFO structure. + * - PNG_USER_VERSIONINFO_COMMENTS + * - PNG_USER_VERSIONINFO_COMPANYNAME + * - PNG_USER_VERSIONINFO_LEGALTRADEMARKS + */ + +#ifdef __STDC__ +#ifdef SPECIALBUILD +# pragma message("PNG_LIBPNG_SPECIALBUILD (and deprecated SPECIALBUILD)\ + are now LIBPNG reserved macros. Use PNG_USER_PRIVATEBUILD instead.") +#endif + +#ifdef PRIVATEBUILD +# pragma message("PRIVATEBUILD is deprecated.\ + Use PNG_USER_PRIVATEBUILD instead.") +# define PNG_USER_PRIVATEBUILD PRIVATEBUILD +#endif +#endif /* __STDC__ */ + +#ifndef PNG_VERSION_INFO_ONLY + +/* End of material added to libpng-1.2.8 */ + +/* Added at libpng-1.2.19, removed at libpng-1.2.20 because it caused trouble + Restored at libpng-1.2.21 */ +#if !defined(PNG_NO_WARN_UNINITIALIZED_ROW) && \ + !defined(PNG_WARN_UNINITIALIZED_ROW) +# define PNG_WARN_UNINITIALIZED_ROW 1 +#endif +/* End of material added at libpng-1.2.19/1.2.21 */ + +/* This is the size of the compression buffer, and thus the size of + * an IDAT chunk. Make this whatever size you feel is best for your + * machine. One of these will be allocated per png_struct. When this + * is full, it writes the data to the disk, and does some other + * calculations. Making this an extremely small size will slow + * the library down, but you may want to experiment to determine + * where it becomes significant, if you are concerned with memory + * usage. Note that zlib allocates at least 32Kb also. For readers, + * this describes the size of the buffer available to read the data in. + * Unless this gets smaller than the size of a row (compressed), + * it should not make much difference how big this is. + */ + +#ifndef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 8192 +#endif + +/* Enable if you want a write-only libpng */ + +#ifndef PNG_NO_READ_SUPPORTED +# define PNG_READ_SUPPORTED +#endif + +/* Enable if you want a read-only libpng */ + +#ifndef PNG_NO_WRITE_SUPPORTED +# define PNG_WRITE_SUPPORTED +#endif + +/* Enabled in 1.2.41. */ +#ifdef PNG_ALLOW_BENIGN_ERRORS +# define png_benign_error png_warning +# define png_chunk_benign_error png_chunk_warning +#else +# ifndef PNG_BENIGN_ERRORS_SUPPORTED +# define png_benign_error png_error +# define png_chunk_benign_error png_chunk_error +# endif +#endif + +/* Added in libpng-1.2.41 */ +#if !defined(PNG_NO_WARNINGS) && !defined(PNG_WARNINGS_SUPPORTED) +# define PNG_WARNINGS_SUPPORTED +#endif + +#if !defined(PNG_NO_ERROR_TEXT) && !defined(PNG_ERROR_TEXT_SUPPORTED) +# define PNG_ERROR_TEXT_SUPPORTED +#endif + +#if !defined(PNG_NO_CHECK_cHRM) && !defined(PNG_CHECK_cHRM_SUPPORTED) +# define PNG_CHECK_cHRM_SUPPORTED +#endif + +/* Enabled by default in 1.2.0. You can disable this if you don't need to + * support PNGs that are embedded in MNG datastreams + */ +#if !defined(PNG_1_0_X) && !defined(PNG_NO_MNG_FEATURES) +# ifndef PNG_MNG_FEATURES_SUPPORTED +# define PNG_MNG_FEATURES_SUPPORTED +# endif +#endif + +#ifndef PNG_NO_FLOATING_POINT_SUPPORTED +# ifndef PNG_FLOATING_POINT_SUPPORTED +# define PNG_FLOATING_POINT_SUPPORTED +# endif +#endif + +/* If you are running on a machine where you cannot allocate more + * than 64K of memory at once, uncomment this. While libpng will not + * normally need that much memory in a chunk (unless you load up a very + * large file), zlib needs to know how big of a chunk it can use, and + * libpng thus makes sure to check any memory allocation to verify it + * will fit into memory. +#define PNG_MAX_MALLOC_64K + */ +#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) +# define PNG_MAX_MALLOC_64K +#endif + +/* Special munging to support doing things the 'cygwin' way: + * 'Normal' png-on-win32 defines/defaults: + * PNG_BUILD_DLL -- building dll + * PNG_USE_DLL -- building an application, linking to dll + * (no define) -- building static library, or building an + * application and linking to the static lib + * 'Cygwin' defines/defaults: + * PNG_BUILD_DLL -- (ignored) building the dll + * (no define) -- (ignored) building an application, linking to the dll + * PNG_STATIC -- (ignored) building the static lib, or building an + * application that links to the static lib. + * ALL_STATIC -- (ignored) building various static libs, or building an + * application that links to the static libs. + * Thus, + * a cygwin user should define either PNG_BUILD_DLL or PNG_STATIC, and + * this bit of #ifdefs will define the 'correct' config variables based on + * that. If a cygwin user *wants* to define 'PNG_USE_DLL' that's okay, but + * unnecessary. + * + * Also, the precedence order is: + * ALL_STATIC (since we can't #undef something outside our namespace) + * PNG_BUILD_DLL + * PNG_STATIC + * (nothing) == PNG_USE_DLL + * + * CYGWIN (2002-01-20): The preceding is now obsolete. With the advent + * of auto-import in binutils, we no longer need to worry about + * __declspec(dllexport) / __declspec(dllimport) and friends. Therefore, + * we don't need to worry about PNG_STATIC or ALL_STATIC when it comes + * to __declspec() stuff. However, we DO need to worry about + * PNG_BUILD_DLL and PNG_STATIC because those change some defaults + * such as CONSOLE_IO and whether GLOBAL_ARRAYS are allowed. + */ +#ifdef __CYGWIN__ +# ifdef ALL_STATIC +# ifdef PNG_BUILD_DLL +# undef PNG_BUILD_DLL +# endif +# ifdef PNG_USE_DLL +# undef PNG_USE_DLL +# endif +# ifdef PNG_DLL +# undef PNG_DLL +# endif +# ifndef PNG_STATIC +# define PNG_STATIC +# endif +# else +# ifdef PNG_BUILD_DLL +# ifdef PNG_STATIC +# undef PNG_STATIC +# endif +# ifdef PNG_USE_DLL +# undef PNG_USE_DLL +# endif +# ifndef PNG_DLL +# define PNG_DLL +# endif +# else +# ifdef PNG_STATIC +# ifdef PNG_USE_DLL +# undef PNG_USE_DLL +# endif +# ifdef PNG_DLL +# undef PNG_DLL +# endif +# else +# ifndef PNG_USE_DLL +# define PNG_USE_DLL +# endif +# ifndef PNG_DLL +# define PNG_DLL +# endif +# endif +# endif +# endif +#endif + +/* This protects us against compilers that run on a windowing system + * and thus don't have or would rather us not use the stdio types: + * stdin, stdout, and stderr. The only one currently used is stderr + * in png_error() and png_warning(). #defining PNG_NO_CONSOLE_IO will + * prevent these from being compiled and used. #defining PNG_NO_STDIO + * will also prevent these, plus will prevent the entire set of stdio + * macros and functions (FILE *, printf, etc.) from being compiled and used, + * unless (PNG_DEBUG > 0) has been #defined. + * + * #define PNG_NO_CONSOLE_IO + * #define PNG_NO_STDIO + */ + +#if !defined(PNG_NO_STDIO) && !defined(PNG_STDIO_SUPPORTED) +# define PNG_STDIO_SUPPORTED +#endif + +#ifdef _WIN32_WCE +# include <windows.h> + /* Console I/O functions are not supported on WindowsCE */ +# define PNG_NO_CONSOLE_IO + /* abort() may not be supported on some/all Windows CE platforms */ +# define PNG_ABORT() exit(-1) +# ifdef PNG_DEBUG +# undef PNG_DEBUG +# endif +#endif + +#ifdef PNG_BUILD_DLL +# ifndef PNG_CONSOLE_IO_SUPPORTED +# ifndef PNG_NO_CONSOLE_IO +# define PNG_NO_CONSOLE_IO +# endif +# endif +#endif + +# ifdef PNG_NO_STDIO +# ifndef PNG_NO_CONSOLE_IO +# define PNG_NO_CONSOLE_IO +# endif +# ifdef PNG_DEBUG +# if (PNG_DEBUG > 0) +# include <stdio.h> +# endif +# endif +# else +# ifndef _WIN32_WCE +/* "stdio.h" functions are not supported on WindowsCE */ +# include <stdio.h> +# endif +# endif + +#if !(defined PNG_NO_CONSOLE_IO) && !defined(PNG_CONSOLE_IO_SUPPORTED) +# define PNG_CONSOLE_IO_SUPPORTED +#endif + +/* This macro protects us against machines that don't have function + * prototypes (ie K&R style headers). If your compiler does not handle + * function prototypes, define this macro and use the included ansi2knr. + * I've always been able to use _NO_PROTO as the indicator, but you may + * need to drag the empty declaration out in front of here, or change the + * ifdef to suit your own needs. + */ +#ifndef PNGARG + +#ifdef OF /* zlib prototype munger */ +# define PNGARG(arglist) OF(arglist) +#else + +#ifdef _NO_PROTO +# define PNGARG(arglist) () +# ifndef PNG_TYPECAST_NULL +# define PNG_TYPECAST_NULL +# endif +#else +# define PNGARG(arglist) arglist +#endif /* _NO_PROTO */ + + +#endif /* OF */ + +#endif /* PNGARG */ + +/* Try to determine if we are compiling on a Mac. Note that testing for + * just __MWERKS__ is not good enough, because the Codewarrior is now used + * on non-Mac platforms. + */ +#ifndef MACOS +# if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \ + defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC) +# define MACOS +# endif +#endif + +/* enough people need this for various reasons to include it here */ +#if !defined(MACOS) && !defined(RISCOS) && !defined(_WIN32_WCE) +# include <sys/types.h> +#endif + +#if !defined(PNG_SETJMP_NOT_SUPPORTED) && !defined(PNG_NO_SETJMP_SUPPORTED) +# define PNG_SETJMP_SUPPORTED +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* This is an attempt to force a single setjmp behaviour on Linux. If + * the X config stuff didn't define _BSD_SOURCE we wouldn't need this. + * + * You can bypass this test if you know that your application uses exactly + * the same setjmp.h that was included when libpng was built. Only define + * PNG_SKIP_SETJMP_CHECK while building your application, prior to the + * application's '#include "png.h"'. Don't define PNG_SKIP_SETJMP_CHECK + * while building a separate libpng library for general use. + */ + +# ifndef PNG_SKIP_SETJMP_CHECK +# ifdef __linux__ +# ifdef _BSD_SOURCE +# define PNG_SAVE_BSD_SOURCE +# undef _BSD_SOURCE +# endif +# ifdef _SETJMP_H + /* If you encounter a compiler error here, see the explanation + * near the end of INSTALL. + */ + __pngconf.h__ in libpng already includes setjmp.h; + __dont__ include it again.; +# endif +# endif /* __linux__ */ +# endif /* PNG_SKIP_SETJMP_CHECK */ + + /* include setjmp.h for error handling */ +# include <setjmp.h> + +# ifdef __linux__ +# ifdef PNG_SAVE_BSD_SOURCE +# ifndef _BSD_SOURCE +# define _BSD_SOURCE +# endif +# undef PNG_SAVE_BSD_SOURCE +# endif +# endif /* __linux__ */ +#endif /* PNG_SETJMP_SUPPORTED */ + +#ifdef BSD +# include <strings.h> +#else +# include <string.h> +#endif + +/* Other defines for things like memory and the like can go here. */ +#ifdef PNG_INTERNAL + +#include <stdlib.h> + +/* The functions exported by PNG_EXTERN are PNG_INTERNAL functions, which + * aren't usually used outside the library (as far as I know), so it is + * debatable if they should be exported at all. In the future, when it is + * possible to have run-time registry of chunk-handling functions, some of + * these will be made available again. +#define PNG_EXTERN extern + */ +#define PNG_EXTERN + +/* Other defines specific to compilers can go here. Try to keep + * them inside an appropriate ifdef/endif pair for portability. + */ + +#ifdef PNG_FLOATING_POINT_SUPPORTED +# ifdef MACOS + /* We need to check that <math.h> hasn't already been included earlier + * as it seems it doesn't agree with <fp.h>, yet we should really use + * <fp.h> if possible. + */ +# if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__) +# include <fp.h> +# endif +# else +# include <math.h> +# endif +# if defined(_AMIGA) && defined(__SASC) && defined(_M68881) + /* Amiga SAS/C: We must include builtin FPU functions when compiling using + * MATH=68881 + */ +# include <m68881.h> +# endif +#endif + +/* Codewarrior on NT has linking problems without this. */ +#if (defined(__MWERKS__) && defined(WIN32)) || defined(__STDC__) +# define PNG_ALWAYS_EXTERN +#endif + +/* This provides the non-ANSI (far) memory allocation routines. */ +#if defined(__TURBOC__) && defined(__MSDOS__) +# include <mem.h> +# include <alloc.h> +#endif + +/* I have no idea why is this necessary... */ +#if defined(_MSC_VER) && (defined(WIN32) || defined(_Windows) || \ + defined(_WINDOWS) || defined(_WIN32) || defined(__WIN32__)) +# include <malloc.h> +#endif + +/* This controls how fine the dithering gets. As this allocates + * a largish chunk of memory (32K), those who are not as concerned + * with dithering quality can decrease some or all of these. + */ +#ifndef PNG_DITHER_RED_BITS +# define PNG_DITHER_RED_BITS 5 +#endif +#ifndef PNG_DITHER_GREEN_BITS +# define PNG_DITHER_GREEN_BITS 5 +#endif +#ifndef PNG_DITHER_BLUE_BITS +# define PNG_DITHER_BLUE_BITS 5 +#endif + +/* This controls how fine the gamma correction becomes when you + * are only interested in 8 bits anyway. Increasing this value + * results in more memory being used, and more pow() functions + * being called to fill in the gamma tables. Don't set this value + * less then 8, and even that may not work (I haven't tested it). + */ + +#ifndef PNG_MAX_GAMMA_8 +# define PNG_MAX_GAMMA_8 11 +#endif + +/* This controls how much a difference in gamma we can tolerate before + * we actually start doing gamma conversion. + */ +#ifndef PNG_GAMMA_THRESHOLD +# define PNG_GAMMA_THRESHOLD 0.05 +#endif + +#endif /* PNG_INTERNAL */ + +/* The following uses const char * instead of char * for error + * and warning message functions, so some compilers won't complain. + * If you do not want to use const, define PNG_NO_CONST here. + */ + +#ifndef PNG_NO_CONST +# define PNG_CONST const +#else +# define PNG_CONST +#endif + +/* The following defines give you the ability to remove code from the + * library that you will not be using. I wish I could figure out how to + * automate this, but I can't do that without making it seriously hard + * on the users. So if you are not using an ability, change the #define + * to and #undef, and that part of the library will not be compiled. If + * your linker can't find a function, you may want to make sure the + * ability is defined here. Some of these depend upon some others being + * defined. I haven't figured out all the interactions here, so you may + * have to experiment awhile to get everything to compile. If you are + * creating or using a shared library, you probably shouldn't touch this, + * as it will affect the size of the structures, and this will cause bad + * things to happen if the library and/or application ever change. + */ + +/* Any features you will not be using can be undef'ed here */ + +/* GR-P, 0.96a: Set "*TRANSFORMS_SUPPORTED as default but allow user + * to turn it off with "*TRANSFORMS_NOT_SUPPORTED" or *PNG_NO_*_TRANSFORMS + * on the compile line, then pick and choose which ones to define without + * having to edit this file. It is safe to use the *TRANSFORMS_NOT_SUPPORTED + * if you only want to have a png-compliant reader/writer but don't need + * any of the extra transformations. This saves about 80 kbytes in a + * typical installation of the library. (PNG_NO_* form added in version + * 1.0.1c, for consistency) + */ + +/* The size of the png_text structure changed in libpng-1.0.6 when + * iTXt support was added. iTXt support was turned off by default through + * libpng-1.2.x, to support old apps that malloc the png_text structure + * instead of calling png_set_text() and letting libpng malloc it. It + * will be turned on by default in libpng-1.4.0. + */ + +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +# ifndef PNG_NO_iTXt_SUPPORTED +# define PNG_NO_iTXt_SUPPORTED +# endif +# ifndef PNG_NO_READ_iTXt +# define PNG_NO_READ_iTXt +# endif +# ifndef PNG_NO_WRITE_iTXt +# define PNG_NO_WRITE_iTXt +# endif +#endif + +#if !defined(PNG_NO_iTXt_SUPPORTED) +# if !defined(PNG_READ_iTXt_SUPPORTED) && !defined(PNG_NO_READ_iTXt) +# define PNG_READ_iTXt +# endif +# if !defined(PNG_WRITE_iTXt_SUPPORTED) && !defined(PNG_NO_WRITE_iTXt) +# define PNG_WRITE_iTXt +# endif +#endif + +/* The following support, added after version 1.0.0, can be turned off here en + * masse by defining PNG_LEGACY_SUPPORTED in case you need binary compatibility + * with old applications that require the length of png_struct and png_info + * to remain unchanged. + */ + +#ifdef PNG_LEGACY_SUPPORTED +# define PNG_NO_FREE_ME +# define PNG_NO_READ_UNKNOWN_CHUNKS +# define PNG_NO_WRITE_UNKNOWN_CHUNKS +# define PNG_NO_HANDLE_AS_UNKNOWN +# define PNG_NO_READ_USER_CHUNKS +# define PNG_NO_READ_iCCP +# define PNG_NO_WRITE_iCCP +# define PNG_NO_READ_iTXt +# define PNG_NO_WRITE_iTXt +# define PNG_NO_READ_sCAL +# define PNG_NO_WRITE_sCAL +# define PNG_NO_READ_sPLT +# define PNG_NO_WRITE_sPLT +# define PNG_NO_INFO_IMAGE +# define PNG_NO_READ_RGB_TO_GRAY +# define PNG_NO_READ_USER_TRANSFORM +# define PNG_NO_WRITE_USER_TRANSFORM +# define PNG_NO_USER_MEM +# define PNG_NO_READ_EMPTY_PLTE +# define PNG_NO_MNG_FEATURES +# define PNG_NO_FIXED_POINT_SUPPORTED +#endif + +/* Ignore attempt to turn off both floating and fixed point support */ +#if !defined(PNG_FLOATING_POINT_SUPPORTED) || \ + !defined(PNG_NO_FIXED_POINT_SUPPORTED) +# define PNG_FIXED_POINT_SUPPORTED +#endif + +#ifndef PNG_NO_FREE_ME +# define PNG_FREE_ME_SUPPORTED +#endif + +#ifdef PNG_READ_SUPPORTED + +#if !defined(PNG_READ_TRANSFORMS_NOT_SUPPORTED) && \ + !defined(PNG_NO_READ_TRANSFORMS) +# define PNG_READ_TRANSFORMS_SUPPORTED +#endif + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +# ifndef PNG_NO_READ_EXPAND +# define PNG_READ_EXPAND_SUPPORTED +# endif +# ifndef PNG_NO_READ_SHIFT +# define PNG_READ_SHIFT_SUPPORTED +# endif +# ifndef PNG_NO_READ_PACK +# define PNG_READ_PACK_SUPPORTED +# endif +# ifndef PNG_NO_READ_BGR +# define PNG_READ_BGR_SUPPORTED +# endif +# ifndef PNG_NO_READ_SWAP +# define PNG_READ_SWAP_SUPPORTED +# endif +# ifndef PNG_NO_READ_PACKSWAP +# define PNG_READ_PACKSWAP_SUPPORTED +# endif +# ifndef PNG_NO_READ_INVERT +# define PNG_READ_INVERT_SUPPORTED +# endif +# ifndef PNG_NO_READ_DITHER +# define PNG_READ_DITHER_SUPPORTED +# endif +# ifndef PNG_NO_READ_BACKGROUND +# define PNG_READ_BACKGROUND_SUPPORTED +# endif +# ifndef PNG_NO_READ_16_TO_8 +# define PNG_READ_16_TO_8_SUPPORTED +# endif +# ifndef PNG_NO_READ_FILLER +# define PNG_READ_FILLER_SUPPORTED +# endif +# ifndef PNG_NO_READ_GAMMA +# define PNG_READ_GAMMA_SUPPORTED +# endif +# ifndef PNG_NO_READ_GRAY_TO_RGB +# define PNG_READ_GRAY_TO_RGB_SUPPORTED +# endif +# ifndef PNG_NO_READ_SWAP_ALPHA +# define PNG_READ_SWAP_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_READ_INVERT_ALPHA +# define PNG_READ_INVERT_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_READ_STRIP_ALPHA +# define PNG_READ_STRIP_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_READ_USER_TRANSFORM +# define PNG_READ_USER_TRANSFORM_SUPPORTED +# endif +# ifndef PNG_NO_READ_RGB_TO_GRAY +# define PNG_READ_RGB_TO_GRAY_SUPPORTED +# endif +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ + +/* PNG_PROGRESSIVE_READ_NOT_SUPPORTED is deprecated. */ +#if !defined(PNG_NO_PROGRESSIVE_READ) && \ + !defined(PNG_PROGRESSIVE_READ_NOT_SUPPORTED) /* if you don't do progressive */ +# define PNG_PROGRESSIVE_READ_SUPPORTED /* reading. This is not talking */ +#endif /* about interlacing capability! You'll */ + /* still have interlacing unless you change the following define: */ +#define PNG_READ_INTERLACING_SUPPORTED /* required for PNG-compliant decoders */ + +/* PNG_NO_SEQUENTIAL_READ_SUPPORTED is deprecated. */ +#if !defined(PNG_NO_SEQUENTIAL_READ) && \ + !defined(PNG_SEQUENTIAL_READ_SUPPORTED) && \ + !defined(PNG_NO_SEQUENTIAL_READ_SUPPORTED) +# define PNG_SEQUENTIAL_READ_SUPPORTED +#endif + +#define PNG_READ_INTERLACING_SUPPORTED /* required in PNG-compliant decoders */ + +#ifndef PNG_NO_READ_COMPOSITE_NODIV +# ifndef PNG_NO_READ_COMPOSITED_NODIV /* libpng-1.0.x misspelling */ +# define PNG_READ_COMPOSITE_NODIV_SUPPORTED /* well tested on Intel, SGI */ +# endif +#endif + +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +/* Deprecated, will be removed from version 2.0.0. + Use PNG_MNG_FEATURES_SUPPORTED instead. */ +#ifndef PNG_NO_READ_EMPTY_PLTE +# define PNG_READ_EMPTY_PLTE_SUPPORTED +#endif +#endif + +#endif /* PNG_READ_SUPPORTED */ + +#ifdef PNG_WRITE_SUPPORTED + +# if !defined(PNG_WRITE_TRANSFORMS_NOT_SUPPORTED) && \ + !defined(PNG_NO_WRITE_TRANSFORMS) +# define PNG_WRITE_TRANSFORMS_SUPPORTED +#endif + +#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED +# ifndef PNG_NO_WRITE_SHIFT +# define PNG_WRITE_SHIFT_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_PACK +# define PNG_WRITE_PACK_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_BGR +# define PNG_WRITE_BGR_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_SWAP +# define PNG_WRITE_SWAP_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_PACKSWAP +# define PNG_WRITE_PACKSWAP_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_INVERT +# define PNG_WRITE_INVERT_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_FILLER +# define PNG_WRITE_FILLER_SUPPORTED /* same as WRITE_STRIP_ALPHA */ +# endif +# ifndef PNG_NO_WRITE_SWAP_ALPHA +# define PNG_WRITE_SWAP_ALPHA_SUPPORTED +# endif +#ifndef PNG_1_0_X +# ifndef PNG_NO_WRITE_INVERT_ALPHA +# define PNG_WRITE_INVERT_ALPHA_SUPPORTED +# endif +#endif +# ifndef PNG_NO_WRITE_USER_TRANSFORM +# define PNG_WRITE_USER_TRANSFORM_SUPPORTED +# endif +#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */ + +#if !defined(PNG_NO_WRITE_INTERLACING_SUPPORTED) && \ + !defined(PNG_WRITE_INTERLACING_SUPPORTED) +#define PNG_WRITE_INTERLACING_SUPPORTED /* not required for PNG-compliant + encoders, but can cause trouble + if left undefined */ +#endif + +#if !defined(PNG_NO_WRITE_WEIGHTED_FILTER) && \ + !defined(PNG_WRITE_WEIGHTED_FILTER) && \ + defined(PNG_FLOATING_POINT_SUPPORTED) +# define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED +#endif + +#ifndef PNG_NO_WRITE_FLUSH +# define PNG_WRITE_FLUSH_SUPPORTED +#endif + +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +/* Deprecated, see PNG_MNG_FEATURES_SUPPORTED, above */ +#ifndef PNG_NO_WRITE_EMPTY_PLTE +# define PNG_WRITE_EMPTY_PLTE_SUPPORTED +#endif +#endif + +#endif /* PNG_WRITE_SUPPORTED */ + +#ifndef PNG_1_0_X +# ifndef PNG_NO_ERROR_NUMBERS +# define PNG_ERROR_NUMBERS_SUPPORTED +# endif +#endif /* PNG_1_0_X */ + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +# ifndef PNG_NO_USER_TRANSFORM_PTR +# define PNG_USER_TRANSFORM_PTR_SUPPORTED +# endif +#endif + +#ifndef PNG_NO_STDIO +# define PNG_TIME_RFC1123_SUPPORTED +#endif + +/* This adds extra functions in pngget.c for accessing data from the + * info pointer (added in version 0.99) + * png_get_image_width() + * png_get_image_height() + * png_get_bit_depth() + * png_get_color_type() + * png_get_compression_type() + * png_get_filter_type() + * png_get_interlace_type() + * png_get_pixel_aspect_ratio() + * png_get_pixels_per_meter() + * png_get_x_offset_pixels() + * png_get_y_offset_pixels() + * png_get_x_offset_microns() + * png_get_y_offset_microns() + */ +#if !defined(PNG_NO_EASY_ACCESS) && !defined(PNG_EASY_ACCESS_SUPPORTED) +# define PNG_EASY_ACCESS_SUPPORTED +#endif + +/* PNG_ASSEMBLER_CODE was enabled by default in version 1.2.0 + * and removed from version 1.2.20. The following will be removed + * from libpng-1.4.0 +*/ + +#if defined(PNG_READ_SUPPORTED) && !defined(PNG_NO_OPTIMIZED_CODE) +# ifndef PNG_OPTIMIZED_CODE_SUPPORTED +# define PNG_OPTIMIZED_CODE_SUPPORTED +# endif +#endif + +#if defined(PNG_READ_SUPPORTED) && !defined(PNG_NO_ASSEMBLER_CODE) +# ifndef PNG_ASSEMBLER_CODE_SUPPORTED +# define PNG_ASSEMBLER_CODE_SUPPORTED +# endif + +# if defined(__GNUC__) && defined(__x86_64__) && (__GNUC__ < 4) + /* work around 64-bit gcc compiler bugs in gcc-3.x */ +# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) +# define PNG_NO_MMX_CODE +# endif +# endif + +# ifdef __APPLE__ +# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) +# define PNG_NO_MMX_CODE +# endif +# endif + +# if (defined(__MWERKS__) && ((__MWERKS__ < 0x0900) || macintosh)) +# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) +# define PNG_NO_MMX_CODE +# endif +# endif + +# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) +# define PNG_MMX_CODE_SUPPORTED +# endif + +#endif +/* end of obsolete code to be removed from libpng-1.4.0 */ + +/* Added at libpng-1.2.0 */ +#ifndef PNG_1_0_X +#if !defined(PNG_NO_USER_MEM) && !defined(PNG_USER_MEM_SUPPORTED) +# define PNG_USER_MEM_SUPPORTED +#endif +#endif /* PNG_1_0_X */ + +/* Added at libpng-1.2.6 */ +#ifndef PNG_1_0_X +# ifndef PNG_SET_USER_LIMITS_SUPPORTED +# ifndef PNG_NO_SET_USER_LIMITS +# define PNG_SET_USER_LIMITS_SUPPORTED +# endif +# endif +#endif /* PNG_1_0_X */ + +/* Added at libpng-1.0.53 and 1.2.43 */ +#ifndef PNG_USER_LIMITS_SUPPORTED +# ifndef PNG_NO_USER_LIMITS +# define PNG_USER_LIMITS_SUPPORTED +# endif +#endif + +/* Added at libpng-1.0.16 and 1.2.6. To accept all valid PNGS no matter + * how large, set these limits to 0x7fffffffL + */ +#ifndef PNG_USER_WIDTH_MAX +# define PNG_USER_WIDTH_MAX 1000000L +#endif +#ifndef PNG_USER_HEIGHT_MAX +# define PNG_USER_HEIGHT_MAX 1000000L +#endif + +/* Added at libpng-1.2.43. To accept all valid PNGs no matter + * how large, set these two limits to 0. + */ +#ifndef PNG_USER_CHUNK_CACHE_MAX +# define PNG_USER_CHUNK_CACHE_MAX 0 +#endif + +/* Added at libpng-1.2.43 */ +#ifndef PNG_USER_CHUNK_MALLOC_MAX +# define PNG_USER_CHUNK_MALLOC_MAX 0 +#endif + +#ifndef PNG_LITERAL_SHARP +# define PNG_LITERAL_SHARP 0x23 +#endif +#ifndef PNG_LITERAL_LEFT_SQUARE_BRACKET +# define PNG_LITERAL_LEFT_SQUARE_BRACKET 0x5b +#endif +#ifndef PNG_LITERAL_RIGHT_SQUARE_BRACKET +# define PNG_LITERAL_RIGHT_SQUARE_BRACKET 0x5d +#endif + +/* Added at libpng-1.2.34 */ +#ifndef PNG_STRING_NEWLINE +#define PNG_STRING_NEWLINE "\n" +#endif + +/* These are currently experimental features, define them if you want */ + +/* very little testing */ +/* +#ifdef PNG_READ_SUPPORTED +# ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED +# define PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED +# endif +#endif +*/ + +/* This is only for PowerPC big-endian and 680x0 systems */ +/* some testing */ +/* +#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED +# define PNG_READ_BIG_ENDIAN_SUPPORTED +#endif +*/ + +/* Buggy compilers (e.g., gcc 2.7.2.2) need this */ +/* +#define PNG_NO_POINTER_INDEXING +*/ + +#if !defined(PNG_NO_POINTER_INDEXING) && \ + !defined(PNG_POINTER_INDEXING_SUPPORTED) +# define PNG_POINTER_INDEXING_SUPPORTED +#endif + +/* These functions are turned off by default, as they will be phased out. */ +/* +#define PNG_USELESS_TESTS_SUPPORTED +#define PNG_CORRECT_PALETTE_SUPPORTED +*/ + +/* Any chunks you are not interested in, you can undef here. The + * ones that allocate memory may be expecially important (hIST, + * tEXt, zTXt, tRNS, pCAL). Others will just save time and make png_info + * a bit smaller. + */ + +#if defined(PNG_READ_SUPPORTED) && \ + !defined(PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ + !defined(PNG_NO_READ_ANCILLARY_CHUNKS) +# define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED +#endif + +#if defined(PNG_WRITE_SUPPORTED) && \ + !defined(PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ + !defined(PNG_NO_WRITE_ANCILLARY_CHUNKS) +# define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED +#endif + +#ifdef PNG_READ_ANCILLARY_CHUNKS_SUPPORTED + +#ifdef PNG_NO_READ_TEXT +# define PNG_NO_READ_iTXt +# define PNG_NO_READ_tEXt +# define PNG_NO_READ_zTXt +#endif +#ifndef PNG_NO_READ_bKGD +# define PNG_READ_bKGD_SUPPORTED +# define PNG_bKGD_SUPPORTED +#endif +#ifndef PNG_NO_READ_cHRM +# define PNG_READ_cHRM_SUPPORTED +# define PNG_cHRM_SUPPORTED +#endif +#ifndef PNG_NO_READ_gAMA +# define PNG_READ_gAMA_SUPPORTED +# define PNG_gAMA_SUPPORTED +#endif +#ifndef PNG_NO_READ_hIST +# define PNG_READ_hIST_SUPPORTED +# define PNG_hIST_SUPPORTED +#endif +#ifndef PNG_NO_READ_iCCP +# define PNG_READ_iCCP_SUPPORTED +# define PNG_iCCP_SUPPORTED +#endif +#ifndef PNG_NO_READ_iTXt +# ifndef PNG_READ_iTXt_SUPPORTED +# define PNG_READ_iTXt_SUPPORTED +# endif +# ifndef PNG_iTXt_SUPPORTED +# define PNG_iTXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_READ_oFFs +# define PNG_READ_oFFs_SUPPORTED +# define PNG_oFFs_SUPPORTED +#endif +#ifndef PNG_NO_READ_pCAL +# define PNG_READ_pCAL_SUPPORTED +# define PNG_pCAL_SUPPORTED +#endif +#ifndef PNG_NO_READ_sCAL +# define PNG_READ_sCAL_SUPPORTED +# define PNG_sCAL_SUPPORTED +#endif +#ifndef PNG_NO_READ_pHYs +# define PNG_READ_pHYs_SUPPORTED +# define PNG_pHYs_SUPPORTED +#endif +#ifndef PNG_NO_READ_sBIT +# define PNG_READ_sBIT_SUPPORTED +# define PNG_sBIT_SUPPORTED +#endif +#ifndef PNG_NO_READ_sPLT +# define PNG_READ_sPLT_SUPPORTED +# define PNG_sPLT_SUPPORTED +#endif +#ifndef PNG_NO_READ_sRGB +# define PNG_READ_sRGB_SUPPORTED +# define PNG_sRGB_SUPPORTED +#endif +#ifndef PNG_NO_READ_tEXt +# define PNG_READ_tEXt_SUPPORTED +# define PNG_tEXt_SUPPORTED +#endif +#ifndef PNG_NO_READ_tIME +# define PNG_READ_tIME_SUPPORTED +# define PNG_tIME_SUPPORTED +#endif +#ifndef PNG_NO_READ_tRNS +# define PNG_READ_tRNS_SUPPORTED +# define PNG_tRNS_SUPPORTED +#endif +#ifndef PNG_NO_READ_zTXt +# define PNG_READ_zTXt_SUPPORTED +# define PNG_zTXt_SUPPORTED +#endif +#ifndef PNG_NO_READ_OPT_PLTE +# define PNG_READ_OPT_PLTE_SUPPORTED /* only affects support of the */ +#endif /* optional PLTE chunk in RGB and RGBA images */ +#if defined(PNG_READ_iTXt_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) || \ + defined(PNG_READ_zTXt_SUPPORTED) +# define PNG_READ_TEXT_SUPPORTED +# define PNG_TEXT_SUPPORTED +#endif + +#endif /* PNG_READ_ANCILLARY_CHUNKS_SUPPORTED */ + +#ifndef PNG_NO_READ_UNKNOWN_CHUNKS +# define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_UNKNOWN_CHUNKS_SUPPORTED +# endif +#endif +#if !defined(PNG_NO_READ_USER_CHUNKS) && \ + defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) +# define PNG_READ_USER_CHUNKS_SUPPORTED +# define PNG_USER_CHUNKS_SUPPORTED +# ifdef PNG_NO_READ_UNKNOWN_CHUNKS +# undef PNG_NO_READ_UNKNOWN_CHUNKS +# endif +# ifdef PNG_NO_HANDLE_AS_UNKNOWN +# undef PNG_NO_HANDLE_AS_UNKNOWN +# endif +#endif + +#ifndef PNG_NO_HANDLE_AS_UNKNOWN +# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# endif +#endif + +#ifdef PNG_WRITE_SUPPORTED +#ifdef PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED + +#ifdef PNG_NO_WRITE_TEXT +# define PNG_NO_WRITE_iTXt +# define PNG_NO_WRITE_tEXt +# define PNG_NO_WRITE_zTXt +#endif +#ifndef PNG_NO_WRITE_bKGD +# define PNG_WRITE_bKGD_SUPPORTED +# ifndef PNG_bKGD_SUPPORTED +# define PNG_bKGD_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_cHRM +# define PNG_WRITE_cHRM_SUPPORTED +# ifndef PNG_cHRM_SUPPORTED +# define PNG_cHRM_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_gAMA +# define PNG_WRITE_gAMA_SUPPORTED +# ifndef PNG_gAMA_SUPPORTED +# define PNG_gAMA_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_hIST +# define PNG_WRITE_hIST_SUPPORTED +# ifndef PNG_hIST_SUPPORTED +# define PNG_hIST_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_iCCP +# define PNG_WRITE_iCCP_SUPPORTED +# ifndef PNG_iCCP_SUPPORTED +# define PNG_iCCP_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_iTXt +# ifndef PNG_WRITE_iTXt_SUPPORTED +# define PNG_WRITE_iTXt_SUPPORTED +# endif +# ifndef PNG_iTXt_SUPPORTED +# define PNG_iTXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_oFFs +# define PNG_WRITE_oFFs_SUPPORTED +# ifndef PNG_oFFs_SUPPORTED +# define PNG_oFFs_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_pCAL +# define PNG_WRITE_pCAL_SUPPORTED +# ifndef PNG_pCAL_SUPPORTED +# define PNG_pCAL_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sCAL +# define PNG_WRITE_sCAL_SUPPORTED +# ifndef PNG_sCAL_SUPPORTED +# define PNG_sCAL_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_pHYs +# define PNG_WRITE_pHYs_SUPPORTED +# ifndef PNG_pHYs_SUPPORTED +# define PNG_pHYs_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sBIT +# define PNG_WRITE_sBIT_SUPPORTED +# ifndef PNG_sBIT_SUPPORTED +# define PNG_sBIT_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sPLT +# define PNG_WRITE_sPLT_SUPPORTED +# ifndef PNG_sPLT_SUPPORTED +# define PNG_sPLT_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sRGB +# define PNG_WRITE_sRGB_SUPPORTED +# ifndef PNG_sRGB_SUPPORTED +# define PNG_sRGB_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_tEXt +# define PNG_WRITE_tEXt_SUPPORTED +# ifndef PNG_tEXt_SUPPORTED +# define PNG_tEXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_tIME +# define PNG_WRITE_tIME_SUPPORTED +# ifndef PNG_tIME_SUPPORTED +# define PNG_tIME_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_tRNS +# define PNG_WRITE_tRNS_SUPPORTED +# ifndef PNG_tRNS_SUPPORTED +# define PNG_tRNS_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_zTXt +# define PNG_WRITE_zTXt_SUPPORTED +# ifndef PNG_zTXt_SUPPORTED +# define PNG_zTXt_SUPPORTED +# endif +#endif +#if defined(PNG_WRITE_iTXt_SUPPORTED) || defined(PNG_WRITE_tEXt_SUPPORTED) || \ + defined(PNG_WRITE_zTXt_SUPPORTED) +# define PNG_WRITE_TEXT_SUPPORTED +# ifndef PNG_TEXT_SUPPORTED +# define PNG_TEXT_SUPPORTED +# endif +#endif + +#ifdef PNG_WRITE_tIME_SUPPORTED +# ifndef PNG_NO_CONVERT_tIME +# ifndef _WIN32_WCE +/* The "tm" structure is not supported on WindowsCE */ +# ifndef PNG_CONVERT_tIME_SUPPORTED +# define PNG_CONVERT_tIME_SUPPORTED +# endif +# endif +# endif +#endif + +#endif /* PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED */ + +#if !defined(PNG_NO_WRITE_FILTER) && !defined(PNG_WRITE_FILTER_SUPPORTED) +# define PNG_WRITE_FILTER_SUPPORTED +#endif + +#ifndef PNG_NO_WRITE_UNKNOWN_CHUNKS +# define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_UNKNOWN_CHUNKS_SUPPORTED +# endif +#endif + +#ifndef PNG_NO_HANDLE_AS_UNKNOWN +# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# endif +#endif +#endif /* PNG_WRITE_SUPPORTED */ + +/* Turn this off to disable png_read_png() and + * png_write_png() and leave the row_pointers member + * out of the info structure. + */ +#ifndef PNG_NO_INFO_IMAGE +# define PNG_INFO_IMAGE_SUPPORTED +#endif + +/* Need the time information for converting tIME chunks */ +#ifdef PNG_CONVERT_tIME_SUPPORTED + /* "time.h" functions are not supported on WindowsCE */ +# include <time.h> +#endif + +/* Some typedefs to get us started. These should be safe on most of the + * common platforms. The typedefs should be at least as large as the + * numbers suggest (a png_uint_32 must be at least 32 bits long), but they + * don't have to be exactly that size. Some compilers dislike passing + * unsigned shorts as function parameters, so you may be better off using + * unsigned int for png_uint_16. Likewise, for 64-bit systems, you may + * want to have unsigned int for png_uint_32 instead of unsigned long. + */ + +typedef unsigned long png_uint_32; +typedef long png_int_32; +typedef unsigned short png_uint_16; +typedef short png_int_16; +typedef unsigned char png_byte; + +/* This is usually size_t. It is typedef'ed just in case you need it to + change (I'm not sure if you will or not, so I thought I'd be safe) */ +#ifdef PNG_SIZE_T + typedef PNG_SIZE_T png_size_t; +# define png_sizeof(x) png_convert_size(sizeof(x)) +#else + typedef size_t png_size_t; +# define png_sizeof(x) sizeof(x) +#endif + +/* The following is needed for medium model support. It cannot be in the + * PNG_INTERNAL section. Needs modification for other compilers besides + * MSC. Model independent support declares all arrays and pointers to be + * large using the far keyword. The zlib version used must also support + * model independent data. As of version zlib 1.0.4, the necessary changes + * have been made in zlib. The USE_FAR_KEYWORD define triggers other + * changes that are needed. (Tim Wegner) + */ + +/* Separate compiler dependencies (problem here is that zlib.h always + defines FAR. (SJT) */ +#ifdef __BORLANDC__ +# if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__) +# define LDATA 1 +# else +# define LDATA 0 +# endif + /* GRR: why is Cygwin in here? Cygwin is not Borland C... */ +# if !defined(__WIN32__) && !defined(__FLAT__) && !defined(__CYGWIN__) +# define PNG_MAX_MALLOC_64K +# if (LDATA != 1) +# ifndef FAR +# define FAR __far +# endif +# define USE_FAR_KEYWORD +# endif /* LDATA != 1 */ + /* Possibly useful for moving data out of default segment. + * Uncomment it if you want. Could also define FARDATA as + * const if your compiler supports it. (SJT) +# define FARDATA FAR + */ +# endif /* __WIN32__, __FLAT__, __CYGWIN__ */ +#endif /* __BORLANDC__ */ + + +/* Suggest testing for specific compiler first before testing for + * FAR. The Watcom compiler defines both __MEDIUM__ and M_I86MM, + * making reliance oncertain keywords suspect. (SJT) + */ + +/* MSC Medium model */ +#ifdef FAR +# ifdef M_I86MM +# define USE_FAR_KEYWORD +# define FARDATA FAR +# include <dos.h> +# endif +#endif + +/* SJT: default case */ +#ifndef FAR +# define FAR +#endif + +/* At this point FAR is always defined */ +#ifndef FARDATA +# define FARDATA +#endif + +/* Typedef for floating-point numbers that are converted + to fixed-point with a multiple of 100,000, e.g., int_gamma */ +typedef png_int_32 png_fixed_point; + +/* Add typedefs for pointers */ +typedef void FAR * png_voidp; +typedef png_byte FAR * png_bytep; +typedef png_uint_32 FAR * png_uint_32p; +typedef png_int_32 FAR * png_int_32p; +typedef png_uint_16 FAR * png_uint_16p; +typedef png_int_16 FAR * png_int_16p; +typedef PNG_CONST char FAR * png_const_charp; +typedef char FAR * png_charp; +typedef png_fixed_point FAR * png_fixed_point_p; + +#ifndef PNG_NO_STDIO +#ifdef _WIN32_WCE +typedef HANDLE png_FILE_p; +#else +typedef FILE * png_FILE_p; +#endif +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double FAR * png_doublep; +#endif + +/* Pointers to pointers; i.e. arrays */ +typedef png_byte FAR * FAR * png_bytepp; +typedef png_uint_32 FAR * FAR * png_uint_32pp; +typedef png_int_32 FAR * FAR * png_int_32pp; +typedef png_uint_16 FAR * FAR * png_uint_16pp; +typedef png_int_16 FAR * FAR * png_int_16pp; +typedef PNG_CONST char FAR * FAR * png_const_charpp; +typedef char FAR * FAR * png_charpp; +typedef png_fixed_point FAR * FAR * png_fixed_point_pp; +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double FAR * FAR * png_doublepp; +#endif + +/* Pointers to pointers to pointers; i.e., pointer to array */ +typedef char FAR * FAR * FAR * png_charppp; + +#if defined(PNG_1_0_X) || defined(PNG_1_2_X) +/* SPC - Is this stuff deprecated? */ +/* It'll be removed as of libpng-1.4.0 - GR-P */ +/* libpng typedefs for types in zlib. If zlib changes + * or another compression library is used, then change these. + * Eliminates need to change all the source files. + */ +typedef charf * png_zcharp; +typedef charf * FAR * png_zcharpp; +typedef z_stream FAR * png_zstreamp; +#endif /* (PNG_1_0_X) || defined(PNG_1_2_X) */ + +/* + * Define PNG_BUILD_DLL if the module being built is a Windows + * LIBPNG DLL. + * + * Define PNG_USE_DLL if you want to *link* to the Windows LIBPNG DLL. + * It is equivalent to Microsoft predefined macro _DLL that is + * automatically defined when you compile using the share + * version of the CRT (C Run-Time library) + * + * The cygwin mods make this behavior a little different: + * Define PNG_BUILD_DLL if you are building a dll for use with cygwin + * Define PNG_STATIC if you are building a static library for use with cygwin, + * -or- if you are building an application that you want to link to the + * static library. + * PNG_USE_DLL is defined by default (no user action needed) unless one of + * the other flags is defined. + */ + +#if !defined(PNG_DLL) && (defined(PNG_BUILD_DLL) || defined(PNG_USE_DLL)) +# define PNG_DLL +#endif +/* If CYGWIN, then disallow GLOBAL ARRAYS unless building a static lib. + * When building a static lib, default to no GLOBAL ARRAYS, but allow + * command-line override + */ +#ifdef __CYGWIN__ +# ifndef PNG_STATIC +# ifdef PNG_USE_GLOBAL_ARRAYS +# undef PNG_USE_GLOBAL_ARRAYS +# endif +# ifndef PNG_USE_LOCAL_ARRAYS +# define PNG_USE_LOCAL_ARRAYS +# endif +# else +# if defined(PNG_USE_LOCAL_ARRAYS) || defined(PNG_NO_GLOBAL_ARRAYS) +# ifdef PNG_USE_GLOBAL_ARRAYS +# undef PNG_USE_GLOBAL_ARRAYS +# endif +# endif +# endif +# if !defined(PNG_USE_LOCAL_ARRAYS) && !defined(PNG_USE_GLOBAL_ARRAYS) +# define PNG_USE_LOCAL_ARRAYS +# endif +#endif + +/* Do not use global arrays (helps with building DLL's) + * They are no longer used in libpng itself, since version 1.0.5c, + * but might be required for some pre-1.0.5c applications. + */ +#if !defined(PNG_USE_LOCAL_ARRAYS) && !defined(PNG_USE_GLOBAL_ARRAYS) +# if defined(PNG_NO_GLOBAL_ARRAYS) || \ + (defined(__GNUC__) && defined(PNG_DLL)) || defined(_MSC_VER) +# define PNG_USE_LOCAL_ARRAYS +# else +# define PNG_USE_GLOBAL_ARRAYS +# endif +#endif + +#ifdef __CYGWIN__ +# undef PNGAPI +# define PNGAPI __cdecl +# undef PNG_IMPEXP +# define PNG_IMPEXP +#endif + +/* If you define PNGAPI, e.g., with compiler option "-DPNGAPI=__stdcall", + * you may get warnings regarding the linkage of png_zalloc and png_zfree. + * Don't ignore those warnings; you must also reset the default calling + * convention in your compiler to match your PNGAPI, and you must build + * zlib and your applications the same way you build libpng. + */ + +#if defined(__MINGW32__) && !defined(PNG_MODULEDEF) +# ifndef PNG_NO_MODULEDEF +# define PNG_NO_MODULEDEF +# endif +#endif + +#if !defined(PNG_IMPEXP) && defined(PNG_BUILD_DLL) && !defined(PNG_NO_MODULEDEF) +# define PNG_IMPEXP +#endif + +#if defined(PNG_DLL) || defined(_DLL) || defined(__DLL__ ) || \ + (( defined(_Windows) || defined(_WINDOWS) || \ + defined(WIN32) || defined(_WIN32) || defined(__WIN32__) )) + +# ifndef PNGAPI +# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800)) +# define PNGAPI __cdecl +# else +# define PNGAPI _cdecl +# endif +# endif + +# if !defined(PNG_IMPEXP) && (!defined(PNG_DLL) || \ + 0 /* WINCOMPILER_WITH_NO_SUPPORT_FOR_DECLIMPEXP */) +# define PNG_IMPEXP +# endif + +# ifndef PNG_IMPEXP + +# define PNG_EXPORT_TYPE1(type,symbol) PNG_IMPEXP type PNGAPI symbol +# define PNG_EXPORT_TYPE2(type,symbol) type PNG_IMPEXP PNGAPI symbol + + /* Borland/Microsoft */ +# if defined(_MSC_VER) || defined(__BORLANDC__) +# if (_MSC_VER >= 800) || (__BORLANDC__ >= 0x500) +# define PNG_EXPORT PNG_EXPORT_TYPE1 +# else +# define PNG_EXPORT PNG_EXPORT_TYPE2 +# ifdef PNG_BUILD_DLL +# define PNG_IMPEXP __export +# else +# define PNG_IMPEXP /*__import */ /* doesn't exist AFAIK in + VC++ */ +# endif /* Exists in Borland C++ for + C++ classes (== huge) */ +# endif +# endif + +# ifndef PNG_IMPEXP +# ifdef PNG_BUILD_DLL +# define PNG_IMPEXP __declspec(dllexport) +# else +# define PNG_IMPEXP __declspec(dllimport) +# endif +# endif +# endif /* PNG_IMPEXP */ +#else /* !(DLL || non-cygwin WINDOWS) */ +# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) +# ifndef PNGAPI +# define PNGAPI _System +# endif +# else +# if 0 /* ... other platforms, with other meanings */ +# endif +# endif +#endif + +#ifndef PNGAPI +# define PNGAPI +#endif +#ifndef PNG_IMPEXP +# define PNG_IMPEXP +#endif + +#ifdef PNG_BUILDSYMS +# ifndef PNG_EXPORT +# define PNG_EXPORT(type,symbol) PNG_FUNCTION_EXPORT symbol END +# endif +# ifdef PNG_USE_GLOBAL_ARRAYS +# ifndef PNG_EXPORT_VAR +# define PNG_EXPORT_VAR(type) PNG_DATA_EXPORT +# endif +# endif +#endif + +#ifndef PNG_EXPORT +# define PNG_EXPORT(type,symbol) PNG_IMPEXP type PNGAPI symbol +#endif + +#ifdef PNG_USE_GLOBAL_ARRAYS +# ifndef PNG_EXPORT_VAR +# define PNG_EXPORT_VAR(type) extern PNG_IMPEXP type +# endif +#endif + +#ifdef PNG_PEDANTIC_WARNINGS +# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED +# define PNG_PEDANTIC_WARNINGS_SUPPORTED +# endif +#endif + +#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED +/* Support for compiler specific function attributes. These are used + * so that where compiler support is available incorrect use of API + * functions in png.h will generate compiler warnings. Added at libpng + * version 1.2.41. + */ +# ifdef __GNUC__ +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __attribute__((__noreturn__)) +# endif +# ifndef PNG_ALLOCATED +# define PNG_ALLOCATED __attribute__((__malloc__)) +# endif + + /* This specifically protects structure members that should only be + * accessed from within the library, therefore should be empty during + * a library build. + */ +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __attribute__((__deprecated__)) +# endif +# ifndef PNG_DEPSTRUCT +# define PNG_DEPSTRUCT __attribute__((__deprecated__)) +# endif +# ifndef PNG_PRIVATE +# if 0 /* Doesn't work so we use deprecated instead*/ +# define PNG_PRIVATE \ + __attribute__((warning("This function is not exported by libpng."))) +# else +# define PNG_PRIVATE \ + __attribute__((__deprecated__)) +# endif +# endif /* PNG_PRIVATE */ +# endif /* __GNUC__ */ +#endif /* PNG_PEDANTIC_WARNINGS */ + +#ifndef PNG_DEPRECATED +# define PNG_DEPRECATED /* Use of this function is deprecated */ +#endif +#ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* The result of this function must be checked */ +#endif +#ifndef PNG_NORETURN +# define PNG_NORETURN /* This function does not return */ +#endif +#ifndef PNG_ALLOCATED +# define PNG_ALLOCATED /* The result of the function is new memory */ +#endif +#ifndef PNG_DEPSTRUCT +# define PNG_DEPSTRUCT /* Access to this struct member is deprecated */ +#endif +#ifndef PNG_PRIVATE +# define PNG_PRIVATE /* This is a private libpng function */ +#endif + +/* User may want to use these so they are not in PNG_INTERNAL. Any library + * functions that are passed far data must be model independent. + */ + +#ifndef PNG_ABORT +# define PNG_ABORT() abort() +#endif + +#ifdef PNG_SETJMP_SUPPORTED +# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) +#else +# define png_jmpbuf(png_ptr) \ + (LIBPNG_WAS_COMPILED_WITH__PNG_SETJMP_NOT_SUPPORTED) +#endif + +#ifdef USE_FAR_KEYWORD /* memory model independent fns */ +/* Use this to make far-to-near assignments */ +# define CHECK 1 +# define NOCHECK 0 +# define CVT_PTR(ptr) (png_far_to_near(png_ptr,ptr,CHECK)) +# define CVT_PTR_NOCHECK(ptr) (png_far_to_near(png_ptr,ptr,NOCHECK)) +# define png_snprintf _fsnprintf /* Added to v 1.2.19 */ +# define png_strlen _fstrlen +# define png_memcmp _fmemcmp /* SJT: added */ +# define png_memcpy _fmemcpy +# define png_memset _fmemset +#else /* Use the usual functions */ +# define CVT_PTR(ptr) (ptr) +# define CVT_PTR_NOCHECK(ptr) (ptr) +# ifndef PNG_NO_SNPRINTF +# ifdef _MSC_VER +# define png_snprintf _snprintf /* Added to v 1.2.19 */ +# define png_snprintf2 _snprintf +# define png_snprintf6 _snprintf +# else +# define png_snprintf snprintf /* Added to v 1.2.19 */ +# define png_snprintf2 snprintf +# define png_snprintf6 snprintf +# endif +# else + /* You don't have or don't want to use snprintf(). Caution: Using + * sprintf instead of snprintf exposes your application to accidental + * or malevolent buffer overflows. If you don't have snprintf() + * as a general rule you should provide one (you can get one from + * Portable OpenSSH). + */ +# define png_snprintf(s1,n,fmt,x1) sprintf(s1,fmt,x1) +# define png_snprintf2(s1,n,fmt,x1,x2) sprintf(s1,fmt,x1,x2) +# define png_snprintf6(s1,n,fmt,x1,x2,x3,x4,x5,x6) \ + sprintf(s1,fmt,x1,x2,x3,x4,x5,x6) +# endif +# define png_strlen strlen +# define png_memcmp memcmp /* SJT: added */ +# define png_memcpy memcpy +# define png_memset memset +#endif +/* End of memory model independent support */ + +/* Just a little check that someone hasn't tried to define something + * contradictory. + */ +#if (PNG_ZBUF_SIZE > 65536L) && defined(PNG_MAX_MALLOC_64K) +# undef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 65536L +#endif + +/* Added at libpng-1.2.8 */ +#endif /* PNG_VERSION_INFO_ONLY */ + +#endif /* PNGCONF_H */ diff --git a/contrib/syslinux-4.02/com32/include/setjmp.h b/contrib/syslinux-4.02/com32/include/setjmp.h new file mode 100644 index 0000000..11b18fb --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/setjmp.h @@ -0,0 +1,22 @@ +/* + * setjmp.h + */ + +#ifndef _SETJMP_H +#define _SETJMP_H + +#include <klibc/extern.h> +#include <klibc/compiler.h> +#include <stddef.h> + +#include <klibc/archsetjmp.h> + +__extern int setjmp(jmp_buf); +__extern __noreturn longjmp(jmp_buf, int); + +typedef jmp_buf sigjmp_buf; + +#define sigsetjmp(__env, __save) setjmp(__env) +#define siglongjmp(__env, __val) longjmp(__env, __val) + +#endif /* _SETJMP_H */ diff --git a/contrib/syslinux-4.02/com32/include/stdarg.h b/contrib/syslinux-4.02/com32/include/stdarg.h new file mode 100644 index 0000000..cc324b8 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/stdarg.h @@ -0,0 +1,14 @@ +/* + * stdarg.h + * + * This is just a wrapper for the gcc one, but defines va_copy() + * even if gcc doesn't. + */ + +/* Note: the _STDARG_H macro belongs to the gcc header... */ +#include_next <stdarg.h> + +/* Older gcc considers this an extension, so it's double underbar only */ +#ifndef va_copy +#define va_copy(d,s) __va_copy(d,s) +#endif diff --git a/contrib/syslinux-4.02/com32/include/stdbool.h b/contrib/syslinux-4.02/com32/include/stdbool.h new file mode 100644 index 0000000..81cb05f --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/stdbool.h @@ -0,0 +1,32 @@ +/* + * + * stdbool.h + */ + +#ifndef _STDBOOL_H +#define _STDBOOL_H + +#ifndef __cplusplus + +#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) +# if !defined(__GNUC__) ||(__GNUC__ < 3) +typedef char _Bool; /* For C compilers without _Bool */ +# endif +#endif + +#define bool _Bool +#define true 1 +#define false 0 + +#else + +/* C++ */ +#define bool bool +#define true true +#define false false + +#endif + +#define __bool_true_false_are_defined 1 + +#endif /* _STDBOOL_H */ diff --git a/contrib/syslinux-4.02/com32/include/stddef.h b/contrib/syslinux-4.02/com32/include/stddef.h new file mode 100644 index 0000000..125d235 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/stddef.h @@ -0,0 +1,24 @@ +/* + * stddef.h + */ + +#ifndef _STDDEF_H +#define _STDDEF_H + +#ifndef __KLIBC__ +# define __KLIBC__ 1 +#endif + +#include <bitsize/stddef.h> + +#undef NULL +#ifdef __cplusplus +# define NULL 0 +#else +# define NULL ((void *)0) +#endif + +#undef offsetof +#define offsetof(t,m) ((size_t)&((t *)0)->m) + +#endif /* _STDDEF_H */ diff --git a/contrib/syslinux-4.02/com32/include/stdint.h b/contrib/syslinux-4.02/com32/include/stdint.h new file mode 100644 index 0000000..a8391bf --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/stdint.h @@ -0,0 +1,142 @@ +/* + * stdint.h + */ + +#ifndef _STDINT_H +#define _STDINT_H + +/* Exact types */ + +typedef signed char int8_t; +typedef signed short int16_t; +typedef signed int int32_t; +typedef signed long long int64_t; + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; + +/* Small types */ + +typedef signed char int_least8_t; +typedef signed short int_least16_t; +typedef signed int int_least32_t; +typedef signed long long int_least64_t; + +typedef unsigned char uint_least8_t; +typedef unsigned short uint_least16_t; +typedef unsigned int uint_least32_t; +typedef unsigned long long uint_least64_t; + +/* Fast types */ + +typedef signed char int_fast8_t; +typedef signed short int_fast16_t; +typedef signed int int_fast32_t; +typedef signed long long int_fast64_t; + +typedef unsigned char uint_fast8_t; +typedef unsigned short uint_fast16_t; +typedef unsigned int uint_fast32_t; +typedef unsigned long long uint_fast64_t; + +/* Pointer types */ + +typedef int32_t intptr_t; +typedef uint32_t uintptr_t; + +/* Maximal types */ + +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + +/* + * To be strictly correct... + */ +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) + +# define INT8_MIN (-128) +# define INT16_MIN (-32767-1) +# define INT32_MIN (-2147483647-1) +# define INT64_MIN (-9223372036854775807LL-1) + +# define INT8_MAX (127) +# define INT16_MAX (32767) +# define INT32_MAX (2147483647) +# define INT64_MAX (9223372036854775807LL) + +# define UINT8_MAX (255U) +# define UINT16_MAX (65535U) +# define UINT32_MAX (4294967295U) +# define UINT64_MAX (18446744073709551615ULL) + +# define INT_LEAST8_MIN (-128) +# define INT_LEAST16_MIN (-32767-1) +# define INT_LEAST32_MIN (-2147483647-1) +# define INT_LEAST64_MIN (-9223372036854775807LL-1) + +# define INT_LEAST8_MAX (127) +# define INT_LEAST16_MAX (32767) +# define INT_LEAST32_MAX (2147483647) +# define INT_LEAST64_MAX (9223372036854775807LL) + +# define UINT_LEAST8_MAX (255U) +# define UINT_LEAST16_MAX (65535U) +# define UINT_LEAST32_MAX (4294967295U) +# define UINT_LEAST64_MAX (18446744073709551615ULL) + +# define INT_FAST8_MIN (-128) +# define INT_FAST16_MIN (-32767-1) +# define INT_FAST32_MIN (-2147483647-1) +# define INT_FAST64_MIN (-9223372036854775807LL-1) + +# define INT_FAST8_MAX (127) +# define INT_FAST16_MAX (32767) +# define INT_FAST32_MAX (2147483647) +# define INT_FAST64_MAX (9223372036854775807LL) + +# define UINT_FAST8_MAX (255U) +# define UINT_FAST16_MAX (65535U) +# define UINT_FAST32_MAX (4294967295U) +# define UINT_FAST64_MAX (18446744073709551615ULL) + +# define INTPTR_MIN (-2147483647-1) +# define INTPTR_MAX (2147483647) +# define UINTPTR_MAX (4294967295U) + +# define INTMAX_MIN (-9223372036854775807LL-1) +# define INTMAX_MAX (9223372036854775807LL) +# define UINTMAX_MAX (18446744073709551615ULL) + +/* ptrdiff_t limit */ +# define PTRDIFF_MIN (-2147483647-1) +# define PTRDIFF_MAX (2147483647) + +/* sig_atomic_t limit */ +# define SIG_ATOMIC_MIN (-2147483647-1) +# define SIG_ATOMIC_MAX (2147483647) + +/* size_t limit */ +# define SIZE_MAX (4294967295U) + +#endif /* STDC_LIMIT_MACROS */ + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) + +# define INT8_C(n) n +# define INT16_C(n) n +# define INT32_C(n) n +# define INT64_C(n) n ## LL + +# define UINT8_C(n) n ## U +# define UINT16_C(n) n ## U +# define UINT32_C(n) n ## U +# define UINT64_C(n) n ## ULL + +# define INTMAX_C(n) n ## LL +# define UINTMAX_C(n) n ## ULL + +#endif /* STDC_CONSTANT_MACROS */ + +#endif /* _STDINT_H */ diff --git a/contrib/syslinux-4.02/com32/include/stdio.h b/contrib/syslinux-4.02/com32/include/stdio.h new file mode 100644 index 0000000..f37bdd9 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/stdio.h @@ -0,0 +1,117 @@ +/* + * stdio.h + */ + +#ifndef _STDIO_H +#define _STDIO_H + +#include <klibc/extern.h> +#include <stdarg.h> +#include <stddef.h> + +/* This structure doesn't really exist, but it gives us something + to define FILE * with */ +struct _IO_file; +typedef struct _IO_file FILE; + +#ifndef EOF +# define EOF (-1) +#endif + +#ifndef BUFSIZ +# define BUFSIZ 4096 +#endif + +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 + +/* + * Convert between a FILE * and a file descriptor. We don't actually + * have any in-memory data, so we just abuse the pointer itself to + * hold the data. Note, however, that for file descriptors, -1 is + * error and 0 is a valid value; for FILE *, NULL (0) is error and + * non-NULL are valid. + */ +static __inline__ int fileno(FILE * __f) +{ + /* This should really be intptr_t, but size_t should be the same size */ + return (int)(size_t) __f - 1; +} + +/* This is a macro so it can be used as initializer */ +#define __create_file(__fd) ((FILE *)(size_t)((__fd) + 1)) + +#define stdin __create_file(0) +#define stdout __create_file(1) +#define stderr __create_file(2) + +__extern FILE *fopen(const char *, const char *); +struct dev_info; +__extern FILE *fopendev(const struct dev_info *, const char *); + +static __inline__ FILE *fdopen(int __fd, const char *__m) +{ + (void)__m; + return __create_file(__fd); +} + +__extern int fclose(FILE * __f); +__extern int fputs(const char *, FILE *); +__extern int puts(const char *); +__extern int fputc(int, FILE *); +#define putc(c,f) fputc((c),(f)) +#define putchar(c) fputc((c),stdout) + +__extern int fgetc(FILE *); +__extern char *fgets(char *, int, FILE *); +#define getc(f) fgetc(f) + +__extern size_t _fread(void *, size_t, FILE *); +__extern size_t _fwrite(const void *, size_t, FILE *); + +__extern size_t fread(void *, size_t, size_t, FILE *); +__extern size_t fwrite(const void *, size_t, size_t, FILE *); + +#ifndef __NO_FREAD_FWRITE_INLINES +#define fread(__p, __s, __n, __f) \ + ( (__builtin_constant_p(__s) && __s == 1) \ + ? _fread(__p, __n, __f) \ + : fread(__p,__s,__n,__f) ) + +#define fwrite(__p, __s, __n, __f) \ + ( (__builtin_constant_p(__s) && __s == 1) \ + ? _fwrite(__p, __n, __f) \ + : fwrite(__p,__s,__n,__f) ) +#endif + +/* No seek, but we can tell */ +__extern long ftell(FILE *); + +__extern int printf(const char *, ...); +__extern int vprintf(const char *, va_list); +__extern int fprintf(FILE *, const char *, ...); +__extern int vfprintf(FILE *, const char *, va_list); +__extern int sprintf(char *, const char *, ...); +__extern int vsprintf(char *, const char *, va_list); +__extern int snprintf(char *, size_t n, const char *, ...); +__extern int vsnprintf(char *, size_t n, const char *, va_list); + +__extern int asprintf(char **, const char *, ...); +__extern int vasprintf(char **, const char *, va_list); + +/* No buffering, so no flushing needed */ +static __inline__ int fflush(FILE * __f) +{ + (void)__f; + return 0; +} + +__extern int sscanf(const char *, const char *, ...); +__extern int vsscanf(const char *, const char *, va_list); + +__extern void perror(const char *); + +__extern int rename(const char *, const char *); + +#endif /* _STDIO_H */ diff --git a/contrib/syslinux-4.02/com32/include/stdlib.h b/contrib/syslinux-4.02/com32/include/stdlib.h new file mode 100644 index 0000000..1441297 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/stdlib.h @@ -0,0 +1,96 @@ +/* + * stdlib.h + */ + +#ifndef _STDLIB_H +#define _STDLIB_H + +#include <klibc/extern.h> +#include <klibc/compiler.h> +#include <stddef.h> + +#define EXIT_FAILURE 1 +#define EXIT_SUCCESS 0 + +__extern __noreturn abort(void); +static __inline__ int abs(int __n) +{ + return (__n < 0) ? -__n : __n; +} + +__extern int atexit(void (*)(void)); +__extern int on_exit(void (*)(int, void *), void *); +__extern int atoi(const char *); +__extern long atol(const char *); +__extern long long atoll(const char *); +__extern __noreturn exit(int); +__extern __noreturn _Exit(int); +__extern void free(void *); +static __inline__ long labs(long __n) +{ + return (__n < 0L) ? -__n : __n; +} + +static __inline__ long long llabs(long long __n) +{ + return (__n < 0LL) ? -__n : __n; +} + +__extern __mallocfunc void *malloc(size_t); +__extern __mallocfunc void *zalloc(size_t); +__extern __mallocfunc void *calloc(size_t, size_t); +__extern __mallocfunc void *realloc(void *, size_t); +__extern long strtol(const char *, char **, int); +__extern long long strtoll(const char *, char **, int); +__extern unsigned long strtoul(const char *, char **, int); +__extern unsigned long long strtoull(const char *, char **, int); + +__extern char *getenv(const char *); +__extern int putenv(const char *); +__extern int setenv(const char *, const char *, int); +__extern int unsetenv(const char *); + +__extern void qsort(void *, size_t, size_t, + int (*)(const void *, const void *)); + +__extern long jrand48(unsigned short *); +__extern long mrand48(void); +__extern long nrand48(unsigned short *); +__extern long lrand48(void); +__extern unsigned short *seed48(const unsigned short *); +__extern void srand48(long); + +#define RAND_MAX 0x7fffffff +static __inline__ int rand(void) +{ + return (int)lrand48(); +} + +static __inline__ void srand(unsigned int __s) +{ + srand48(__s); +} + +static __inline__ long random(void) +{ + return lrand48(); +} + +static __inline__ void srandom(unsigned int __s) +{ + srand48(__s); +} + +/* Basic PTY functions. These only work if devpts is mounted! */ + +__extern int unlockpt(int); +__extern char *ptsname(int); +__extern int getpt(void); + +static __inline__ int grantpt(int __fd) +{ + (void)__fd; + return 0; /* devpts does this all for us! */ +} + +#endif /* _STDLIB_H */ diff --git a/contrib/syslinux-4.02/com32/include/string.h b/contrib/syslinux-4.02/com32/include/string.h new file mode 100644 index 0000000..af9792b --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/string.h @@ -0,0 +1,46 @@ +/* + * string.h + */ + +#ifndef _STRING_H +#define _STRING_H + +#include <klibc/extern.h> +#include <stddef.h> + +__extern void *memccpy(void *, const void *, int, size_t); +__extern void *memchr(const void *, int, size_t); +__extern int memcmp(const void *, const void *, size_t); +__extern void *memcpy(void *, const void *, size_t); +__extern void *mempcpy(void *, const void *, size_t); +__extern void *memmove(void *, const void *, size_t); +__extern void *memset(void *, int, size_t); +__extern void *memmem(const void *, size_t, const void *, size_t); +__extern void memswap(void *, void *, size_t); +__extern int strcasecmp(const char *, const char *); +__extern int strncasecmp(const char *, const char *, size_t); +__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 size_t strcspn(const char *, const char *); +__extern char *strdup(const char *); +__extern char *strndup(const char *, size_t); +__extern char *strerror(int); +__extern size_t strlen(const char *); +__extern size_t strnlen(const char *, size_t); +__extern char *strncat(char *, const char *, size_t); +__extern size_t strlcat(char *, const char *, size_t); +__extern int strncmp(const char *, const char *, size_t); +__extern char *strncpy(char *, const char *, size_t); +__extern char *stpcpy(char *, const char *); +__extern char *stpncpy(char *, const char *, size_t); +__extern size_t strlcpy(char *, const char *, size_t); +__extern char *strpbrk(const char *, const char *); +__extern char *strrchr(const char *, int); +__extern char *strsep(char **, const char *); +__extern size_t strspn(const char *, const char *); +__extern char *strstr(const char *, const char *); +__extern char *strtok(char *, const char *); + +#endif /* _STRING_H */ diff --git a/contrib/syslinux-4.02/com32/include/sys/cpu.h b/contrib/syslinux-4.02/com32/include/sys/cpu.h new file mode 100644 index 0000000..53a6250 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/sys/cpu.h @@ -0,0 +1,142 @@ +#ifndef _CPU_H +#define _CPU_H + +#include <stdbool.h> +#include <stdint.h> +#include <klibc/compiler.h> + +static inline uint64_t rdtsc(void) +{ + uint64_t v; + asm volatile("rdtsc" : "=A" (v)); + return v; +} + +static inline uint32_t rdtscl(void) +{ + uint32_t v; + asm volatile("rdtsc" : "=a" (v) : : "edx"); + return v; +} + +static inline void cpuid_count(uint32_t op, uint32_t cnt, + uint32_t * eax, uint32_t * ebx, + uint32_t * ecx, uint32_t * edx) +{ + asm volatile("movl %%ebx,%1 ; " + "cpuid ; " + "xchgl %1,%%ebx" + : "=a" (*eax), "=SD" (*ebx), "=c" (*ecx), "=d" (*edx) + : "a"(op), "c"(cnt)); +} + +static inline void cpuid(uint32_t op, uint32_t * eax, uint32_t * ebx, + uint32_t * ecx, uint32_t * edx) +{ + cpuid_count(op, 0, eax, ebx, ecx, edx); +} + +static inline __constfunc uint32_t cpuid_eax(uint32_t level) +{ + uint32_t v; + + asm volatile("pushl %%ebx ; " + "cpuid ; " + "popl %%ebx" + : "=a" (v) + : "a"(level) + : "ecx", "edx"); + return v; +} + +static inline __constfunc uint32_t cpuid_ebx(uint32_t level) +{ + uint32_t v; + + asm volatile("movl %%ebx,%0 ; " + "cpuid ; " + "xchgl %0,%%ebx" + : "=SD" (v), "+a" (level) + : : "ecx", "edx"); + return v; +} + +static inline __constfunc uint32_t cpuid_ecx(uint32_t level) +{ + uint32_t v; + + asm volatile("pushl %%ebx ; " + "cpuid ; " + "popl %%ebx" + : "=c" (v), "+a" (level) + : : "edx"); + return v; +} + +static inline __constfunc uint32_t cpuid_edx(uint32_t level) +{ + uint32_t v; + + asm volatile("pushl %%ebx ; " + "cpuid ; " + "popl %%ebx" + : "=d" (v), "+a" (level) + : : "ecx"); + return v; +} + +/* Standard macro to see if a specific flag is changeable */ +static inline __constfunc bool cpu_has_eflag(uint32_t flag) +{ + uint32_t f0, f1; + + asm("pushfl ; " + "pushfl ; " + "popl %0 ; " + "movl %0,%1 ; " + "xorl %2,%1 ; " + "pushl %1 ; " + "popfl ; " + "pushfl ; " + "popl %1 ; " + "popfl" + : "=&r" (f0), "=&r" (f1) + : "ri" (flag)); + + return !!((f0^f1) & flag); +} + +static inline uint64_t rdmsr(uint32_t msr) +{ + uint64_t v; + + asm volatile("rdmsr" : "=A" (v) : "c"(msr)); + return v; +} + +static inline void wrmsr(uint64_t v, uint32_t msr) +{ + asm volatile("wrmsr" : : "A" (v), "c" (msr)); +} + +static inline void cpu_relax(void) +{ + asm volatile("rep ; nop"); +} + +static inline void hlt(void) +{ + asm volatile("hlt"); +} + +static inline void cli(void) +{ + asm volatile("cli"); +} + +static inline void sti(void) +{ + asm volatile("sti"); +} + +#endif diff --git a/contrib/syslinux-4.02/com32/include/sys/dirent.h b/contrib/syslinux-4.02/com32/include/sys/dirent.h new file mode 100644 index 0000000..bb5e52c --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/sys/dirent.h @@ -0,0 +1,45 @@ +/* + * sys/dirent.h + */ + +#ifndef DIRENT_H +#define DIRENT_H + +#include <stdint.h> +#include <sys/types.h> + +#ifndef NAME_MAX +#define NAME_MAX 255 +#endif + +struct dirent { + uint32_t d_ino; + uint32_t d_off; + uint16_t d_reclen; + uint16_t d_type; + char d_name[NAME_MAX + 1]; +}; + +enum dirent_type { + DT_UNKNOWN = 0, + DT_FIFO = 1, + DT_CHR = 2, + DT_DIR = 4, + DT_BLK = 6, + DT_REG = 8, + DT_LNK = 10, + DT_SOCK = 12, + DT_WHT = 14, +}; + +/* + * Convert between stat structure mode types and directory types. + * The stat structure mode types are the same as in Linux. + */ +#define IFTODT(mode) (((mode) & 0170000) >> 12) +#define DTTOIF(dt) ((dt) << 12) + +struct _DIR_; +typedef struct _DIR_ DIR; + +#endif /* sys/dirent.h */ diff --git a/contrib/syslinux-4.02/com32/include/sys/elf32.h b/contrib/syslinux-4.02/com32/include/sys/elf32.h new file mode 100644 index 0000000..c98c274 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/sys/elf32.h @@ -0,0 +1,113 @@ +/* + * sys/elf32.h + */ + +#ifndef _SYS_ELF32_H +#define _SYS_ELF32_H + +#include <sys/elfcommon.h> + +/* ELF standard typedefs (yet more proof that <stdint.h> was way overdue) */ +typedef uint16_t Elf32_Half; +typedef int16_t Elf32_SHalf; +typedef uint32_t Elf32_Word; +typedef int32_t Elf32_Sword; +typedef uint64_t Elf32_Xword; +typedef int64_t Elf32_Sxword; + +typedef uint32_t Elf32_Off; +typedef uint32_t Elf32_Addr; +typedef uint16_t Elf32_Section; + +/* Dynamic header */ + +typedef struct elf32_dyn { + Elf32_Sword d_tag; + union { + Elf32_Sword d_val; + Elf32_Addr d_ptr; + } d_un; +} Elf32_Dyn; + +/* Relocations */ + +#define ELF32_R_SYM(x) ((x) >> 8) +#define ELF32_R_TYPE(x) ((x) & 0xff) + +typedef struct elf32_rel { + Elf32_Addr r_offset; + Elf32_Word r_info; +} Elf32_Rel; + +typedef struct elf32_rela { + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} Elf32_Rela; + +/* Symbol */ + +typedef struct elf32_sym { + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; +} Elf32_Sym; + +/* Main file header */ + +typedef struct elf32_hdr { + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} Elf32_Ehdr; + +/* Program header */ + +typedef struct elf32_phdr { + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} Elf32_Phdr; + +/* Section header */ + +typedef struct elf32_shdr { + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} Elf32_Shdr; + +/* Note header */ +typedef struct elf32_note { + Elf32_Word n_namesz; /* Name size */ + Elf32_Word n_descsz; /* Content size */ + Elf32_Word n_type; /* Content type */ +} Elf32_Nhdr; + +#endif /* _SYS_ELF32_H */ diff --git a/contrib/syslinux-4.02/com32/include/sys/elf64.h b/contrib/syslinux-4.02/com32/include/sys/elf64.h new file mode 100644 index 0000000..a76fc98 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/sys/elf64.h @@ -0,0 +1,113 @@ +/* + * sys/elf64.h + */ + +#ifndef _SYS_ELF64_H +#define _SYS_ELF64_H + +#include <sys/elfcommon.h> + +/* ELF standard typedefs (yet more proof that <stdint.h> was way overdue) */ +typedef uint16_t Elf64_Half; +typedef int16_t Elf64_SHalf; +typedef uint32_t Elf64_Word; +typedef int32_t Elf64_Sword; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; + +typedef uint64_t Elf64_Off; +typedef uint64_t Elf64_Addr; +typedef uint16_t Elf64_Section; + +/* Dynamic header */ + +typedef struct elf64_dyn { + Elf64_Sxword d_tag; + union { + Elf64_Xword d_val; + Elf64_Addr d_ptr; + } d_un; +} Elf64_Dyn; + +/* Relocations */ + +#define ELF64_R_SYM(x) ((x) >> 32) +#define ELF64_R_TYPE(x) ((x) & 0xffffffff) + +typedef struct elf64_rel { + Elf64_Addr r_offset; + Elf64_Xword r_info; +} Elf64_Rel; + +typedef struct elf64_rela { + Elf64_Addr r_offset; + Elf64_Xword r_info; + Elf64_Sxword r_addend; +} Elf64_Rela; + +/* Symbol */ + +typedef struct elf64_sym { + Elf64_Word st_name; + unsigned char st_info; + unsigned char st_other; + Elf64_Half st_shndx; + Elf64_Addr st_value; + Elf64_Xword st_size; +} Elf64_Sym; + +/* Main file header */ + +typedef struct elf64_hdr { + unsigned char e_ident[EI_NIDENT]; + Elf64_Half e_type; + Elf64_Half e_machine; + Elf64_Word e_version; + Elf64_Addr e_entry; + Elf64_Off e_phoff; + Elf64_Off e_shoff; + Elf64_Word e_flags; + Elf64_Half e_ehsize; + Elf64_Half e_phentsize; + Elf64_Half e_phnum; + Elf64_Half e_shentsize; + Elf64_Half e_shnum; + Elf64_Half e_shstrndx; +} Elf64_Ehdr; + +/* Program header */ + +typedef struct elf64_phdr { + Elf64_Word p_type; + Elf64_Word p_flags; + Elf64_Off p_offset; + Elf64_Addr p_vaddr; + Elf64_Addr p_paddr; + Elf64_Xword p_filesz; + Elf64_Xword p_memsz; + Elf64_Xword p_align; +} Elf64_Phdr; + +/* Section header */ + +typedef struct elf64_shdr { + Elf64_Word sh_name; + Elf64_Word sh_type; + Elf64_Xword sh_flags; + Elf64_Addr sh_addr; + Elf64_Off sh_offset; + Elf64_Xword sh_size; + Elf64_Word sh_link; + Elf64_Word sh_info; + Elf64_Xword sh_addralign; + Elf64_Xword sh_entsize; +} Elf64_Shdr; + +/* Note header */ +typedef struct elf64_note { + Elf64_Word n_namesz; /* Name size */ + Elf64_Word n_descsz; /* Content size */ + Elf64_Word n_type; /* Content type */ +} Elf64_Nhdr; + +#endif /* _SYS_ELF64_H */ diff --git a/contrib/syslinux-4.02/com32/include/sys/elfcommon.h b/contrib/syslinux-4.02/com32/include/sys/elfcommon.h new file mode 100644 index 0000000..2489e3c --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/sys/elfcommon.h @@ -0,0 +1,187 @@ +/* + * sys/elfcommon.h + */ + +#ifndef _SYS_ELFCOMMON_H +#define _SYS_ELFCOMMON_H + +#include <stdint.h> + +/* Segment types */ +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_LOOS 0x60000000 +#define PT_HIOS 0x6fffffff +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff +#define PT_GNU_EH_FRAME 0x6474e550 /* Extension, eh? */ + +/* ELF file types */ +#define ET_NONE 0 +#define ET_REL 1 +#define ET_EXEC 2 +#define ET_DYN 3 +#define ET_CORE 4 +#define ET_LOPROC 0xff00 +#define ET_HIPROC 0xffff + +/* ELF machine types */ +#define EM_NONE 0 +#define EM_M32 1 +#define EM_SPARC 2 +#define EM_386 3 +#define EM_68K 4 +#define EM_88K 5 +#define EM_486 6 /* Not used in Linux at least */ +#define EM_860 7 +#define EM_MIPS 8 /* R3k, bigendian(?) */ +#define EM_MIPS_RS4_BE 10 /* R4k BE */ +#define EM_PARISC 15 +#define EM_SPARC32PLUS 18 +#define EM_PPC 20 +#define EM_PPC64 21 +#define EM_S390 22 +#define EM_SH 42 +#define EM_SPARCV9 43 /* v9 = SPARC64 */ +#define EM_H8_300H 47 +#define EM_H8S 48 +#define EM_IA_64 50 /* Itanic */ +#define EM_X86_64 62 +#define EM_CRIS 76 +#define EM_V850 87 +#define EM_ALPHA 0x9026 /* Interrim Alpha that stuck around */ +#define EM_CYGNUS_V850 0x9080 /* Old v850 ID used by Cygnus */ +#define EM_S390_OLD 0xA390 /* Obsolete interrim value for S/390 */ + +/* Dynamic type values */ +#define DT_NULL 0 +#define DT_NEEDED 1 +#define DT_PLTRELSZ 2 +#define DT_PLTGOT 3 +#define DT_HASH 4 +#define DT_STRTAB 5 +#define DT_SYMTAB 6 +#define DT_RELA 7 +#define DT_RELASZ 8 +#define DT_RELAENT 9 +#define DT_STRSZ 10 +#define DT_SYMENT 11 +#define DT_INIT 12 +#define DT_FINI 13 +#define DT_SONAME 14 +#define DT_RPATH 15 +#define DT_SYMBOLIC 16 +#define DT_REL 17 +#define DT_RELSZ 18 +#define DT_RELENT 19 +#define DT_PLTREL 20 +#define DT_DEBUG 21 +#define DT_TEXTREL 22 +#define DT_JMPREL 23 +#define DT_LOPROC 0x70000000 +#define DT_HIPROC 0x7fffffff + +/* Auxilliary table entries */ +#define AT_NULL 0 /* end of vector */ +#define AT_IGNORE 1 /* entry should be ignored */ +#define AT_EXECFD 2 /* file descriptor of program */ +#define AT_PHDR 3 /* program headers for program */ +#define AT_PHENT 4 /* size of program header entry */ +#define AT_PHNUM 5 /* number of program headers */ +#define AT_PAGESZ 6 /* system page size */ +#define AT_BASE 7 /* base address of interpreter */ +#define AT_FLAGS 8 /* flags */ +#define AT_ENTRY 9 /* entry point of program */ +#define AT_NOTELF 10 /* program is not ELF */ +#define AT_UID 11 /* real uid */ +#define AT_EUID 12 /* effective uid */ +#define AT_GID 13 /* real gid */ +#define AT_EGID 14 /* effective gid */ +#define AT_PLATFORM 15 /* string identifying CPU for optimizations */ +#define AT_HWCAP 16 /* arch dependent hints at CPU capabilities */ +#define AT_CLKTCK 17 /* frequency at which times() increments */ +/* 18..22 = ? */ +#define AT_SECURE 23 /* secure mode boolean */ + +/* Program header permission flags */ +#define PF_X 0x1 +#define PF_W 0x2 +#define PF_R 0x4 + +/* Section header types */ +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_NUM 12 +#define SHT_LOPROC 0x70000000 +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 +#define SHT_HIUSER 0xffffffff + +/* Section header flags */ +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 +#define SHF_EXECINSTR 0x4 +#define SHF_MASKPROC 0xf0000000 + +/* Special section numbers */ +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 +#define SHN_LOPROC 0xff00 +#define SHN_HIPROC 0xff1f +#define SHN_ABS 0xfff1 +#define SHN_COMMON 0xfff2 +#define SHN_HIRESERVE 0xffff + +/* Lenght of magic at the start of a file */ +#define EI_NIDENT 16 + +/* Magic number constants... */ +#define EI_MAG0 0 /* e_ident[] indexes */ +#define EI_MAG1 1 +#define EI_MAG2 2 +#define EI_MAG3 3 +#define EI_CLASS 4 +#define EI_DATA 5 +#define EI_VERSION 6 +#define EI_OSABI 7 +#define EI_PAD 8 + +#define ELFMAG0 0x7f /* EI_MAG */ +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +#define ELFCLASSNONE 0 /* EI_CLASS */ +#define ELFCLASS32 1 +#define ELFCLASS64 2 +#define ELFCLASSNUM 3 + +#define ELFDATANONE 0 /* e_ident[EI_DATA] */ +#define ELFDATA2LSB 1 +#define ELFDATA2MSB 2 + +#define EV_NONE 0 /* e_version, EI_VERSION */ +#define EV_CURRENT 1 +#define EV_NUM 2 + +#define ELFOSABI_NONE 0 +#define ELFOSABI_LINUX 3 + +#endif /* _SYS_ELFCOMMON_H */ diff --git a/contrib/syslinux-4.02/com32/include/sys/fpu.h b/contrib/syslinux-4.02/com32/include/sys/fpu.h new file mode 100644 index 0000000..134ae59 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/sys/fpu.h @@ -0,0 +1,6 @@ +#ifndef _SYS_FPU_H +#define _SYS_FPU_H + +extern int x86_init_fpu(void); + +#endif /* _SYS_FPU_H */ diff --git a/contrib/syslinux-4.02/com32/include/sys/gpxe.h b/contrib/syslinux-4.02/com32/include/sys/gpxe.h new file mode 100644 index 0000000..adbbefe --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/sys/gpxe.h @@ -0,0 +1,16 @@ +#ifndef _GPXE_H +#define _GPXE_H + +#include <com32.h> + +struct s_PXENV_FILE_CHECK_API { + uint16_t Status; + uint16_t Size; + uint32_t Magic; + uint32_t Provider; + uint32_t APIMask; + uint32_t Flags; +}; + +bool is_gpxe(void); +#endif diff --git a/contrib/syslinux-4.02/com32/include/sys/io.h b/contrib/syslinux-4.02/com32/include/sys/io.h new file mode 100644 index 0000000..96f8960 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/sys/io.h @@ -0,0 +1,42 @@ +#ifndef _SYS_IO_H +#define _SYS_IO_H + +#include <inttypes.h> + +static inline uint8_t inb(uint16_t p) +{ + uint8_t v; + asm volatile ("inb %1,%0":"=a" (v):"Nd"(p)); + return v; +} + +static inline uint16_t inw(uint16_t p) +{ + uint16_t v; + asm volatile ("inw %1,%0":"=a" (v):"Nd"(p)); + return v; +} + +static inline uint32_t inl(uint16_t p) +{ + uint32_t v; + asm volatile ("inl %1,%0":"=a" (v):"Nd"(p)); + return v; +} + +static inline void outb(uint8_t v, uint16_t p) +{ + asm volatile ("outb %0,%1"::"a" (v), "Nd"(p)); +} + +static inline void outw(uint16_t v, uint16_t p) +{ + asm volatile ("outw %0,%1"::"a" (v), "Nd"(p)); +} + +static inline void outl(uint32_t v, uint16_t p) +{ + asm volatile ("outl %0,%1"::"a" (v), "Nd"(p)); +} + +#endif /* _SYS_IO_H */ diff --git a/contrib/syslinux-4.02/com32/include/sys/pci.h b/contrib/syslinux-4.02/com32/include/sys/pci.h new file mode 100644 index 0000000..aba1f96 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/sys/pci.h @@ -0,0 +1,153 @@ +#ifndef _SYS_PCI_H +#define _SYS_PCI_H + +#include <inttypes.h> +#include <sys/io.h> + +#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, + ENOMODULESALIAS +}; + +/* a structure for extended pci information */ +/* XXX: use pointers for these? */ +struct pci_dev_info { + 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 */ + uint8_t irq; + uint8_t latency; +}; + +/* PCI device (really, function) */ +struct pci_device { + union { + struct { + uint16_t vendor; + uint16_t product; + uint16_t sub_vendor; + uint16_t sub_product; + uint8_t revision; + uint8_t class[3]; + }; + struct { + uint32_t vid_did; + uint32_t svid_sdid; + uint32_t rid_class; + }; + }; + struct pci_dev_info *dev_info; + struct pci_device *next; +}; + +/* PCI device ("slot") structure */ +struct pci_slot { + struct pci_device *func[MAX_PCI_FUNC]; +}; + +/* PCI bus structure */ +struct pci_bus { + struct pci_slot *slot[MAX_PCI_DEVICES]; +}; + +/* PCI domain structure */ +struct pci_domain { + struct pci_bus *bus[MAX_PCI_BUSES]; +}; + +/* Iterate over a PCI domain */ +#define for_each_pci_func(funcp, domain) \ + for (int __pci_bus = 0; __pci_bus < MAX_PCI_BUSES; __pci_bus++) \ + if ((domain)->bus[__pci_bus]) \ + for (int __pci_slot = 0; __pci_slot < MAX_PCI_DEVICES; __pci_slot++) \ + if ((domain)->bus[__pci_bus]->slot[__pci_slot]) \ + for (int __pci_func = 0; __pci_func < MAX_PCI_FUNC; __pci_func++) \ + if (((funcp) = (domain)->bus[__pci_bus]->slot[__pci_slot]-> \ + func[__pci_func])) + +#define for_each_pci_func3(funcp, domain, addr) \ + for (int __pci_bus = 0; __pci_bus < MAX_PCI_BUSES; __pci_bus++) \ + if ((domain)->bus[__pci_bus]) \ + for (int __pci_slot = 0; __pci_slot < MAX_PCI_DEVICES; __pci_slot++) \ + if ((domain)->bus[__pci_bus]->slot[__pci_slot]) \ + for (int __pci_func = 0; __pci_func < MAX_PCI_FUNC; __pci_func++) \ + if (((addr) = pci_mkaddr(__pci_bus, __pci_slot, __pci_func, 0)), \ + ((funcp) = (domain)->bus[__pci_bus]->slot[__pci_slot]-> \ + func[__pci_func])) + +struct match { + struct match *next; + uint32_t did; + uint32_t did_mask; + uint32_t sid; + uint32_t sid_mask; + uint8_t rid_min, rid_max; + char *filename; +}; + +static inline pciaddr_t pci_mkaddr(uint32_t bus, uint32_t dev, + uint32_t func, uint32_t reg) +{ + return 0x80000000 | ((bus & 0xff) << 16) | ((dev & 0x1f) << 11) | + ((func & 0x07) << 8) | (reg & 0xff); +} + +static inline int pci_bus(pciaddr_t addr) +{ + return (addr >> 16) & 0xff; +} + +static inline int pci_dev(pciaddr_t addr) +{ + return (addr >> 11) & 0x1f; +} + +static inline int pci_func(pciaddr_t addr) +{ + return (addr >> 8) & 0x07; +} + +enum pci_config_type { + PCI_CFG_NONE = -1, /* badness */ + PCI_CFG_AUTO = 0, /* autodetect */ + PCI_CFG_TYPE1 = 1, + PCI_CFG_TYPE2 = 2, + PCI_CFG_BIOS = 3, +}; + +enum pci_config_type pci_set_config_type(enum pci_config_type); + +uint8_t pci_readb(pciaddr_t); +uint16_t pci_readw(pciaddr_t); +uint32_t pci_readl(pciaddr_t); +void pci_writeb(uint8_t, pciaddr_t); +void pci_writew(uint16_t, pciaddr_t); +void pci_writel(uint32_t, pciaddr_t); + +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, char *pciids_path); +int get_module_name_from_pcimap(struct pci_domain *pci_domain, char *modules_pcimap_path); +int get_module_name_from_alias(struct pci_domain *pci_domain, char *modules_alias_path); +int get_class_name_from_pci_ids(struct pci_domain *pci_domain, char *pciids_path); +void gather_additional_pci_config(struct pci_domain *domain); +#endif /* _SYS_PCI_H */ diff --git a/contrib/syslinux-4.02/com32/include/sys/stat.h b/contrib/syslinux-4.02/com32/include/sys/stat.h new file mode 100644 index 0000000..41cdf57 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/sys/stat.h @@ -0,0 +1,52 @@ +/* + * sys/stat.h + */ + +#ifndef _SYS_STAT_H +#define _SYS_STAT_H + +#include <sys/types.h> + +/* We don't use this, but it's there for compatibility */ + +#define S_IFMT 00170000 +#define S_IFSOCK 0140000 +#define S_IFLNK 0120000 +#define S_IFREG 0100000 +#define S_IFBLK 0060000 +#define S_IFDIR 0040000 +#define S_IFCHR 0020000 +#define S_IFIFO 0010000 +#define S_ISUID 0004000 +#define S_ISGID 0002000 +#define S_ISVTX 0001000 +#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) +#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) +#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) +#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) +#define S_IRWXU 00700 +#define S_IRUSR 00400 +#define S_IWUSR 00200 +#define S_IXUSR 00100 +#define S_IRWXG 00070 +#define S_IRGRP 00040 +#define S_IWGRP 00020 +#define S_IXGRP 00010 +#define S_IRWXO 00007 +#define S_IROTH 00004 +#define S_IWOTH 00002 +#define S_IXOTH 00001 + +/* These are the only fields in struct stat we emulate */ +struct stat { + mode_t st_mode; + off_t st_size; +}; + +/* Only fstat() supported */ +int fstat(int, struct stat *); + +#endif /* _SYS_STAT_H */ diff --git a/contrib/syslinux-4.02/com32/include/sys/time.h b/contrib/syslinux-4.02/com32/include/sys/time.h new file mode 100644 index 0000000..c5bff0d --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/sys/time.h @@ -0,0 +1,6 @@ +#ifndef _SYS_TIME_H +#define _SYS_TIME_H + +/* empty */ + +#endif diff --git a/contrib/syslinux-4.02/com32/include/sys/times.h b/contrib/syslinux-4.02/com32/include/sys/times.h new file mode 100644 index 0000000..9047006 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/sys/times.h @@ -0,0 +1,21 @@ +/* + * sys/times.h + */ + +#ifndef _SYS_TIMES_H +#define _SYS_TIMES_H + +#include <stdint.h> + +struct tms { + /* Empty */ +}; + +#define HZ 1000 +#define CLK_TCK HZ + +typedef uint32_t clock_t; + +clock_t times(struct tms *); + +#endif /* _SYS_TIMES_H */ diff --git a/contrib/syslinux-4.02/com32/include/sys/types.h b/contrib/syslinux-4.02/com32/include/sys/types.h new file mode 100644 index 0000000..5279a49 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/sys/types.h @@ -0,0 +1,16 @@ +/* + * sys/types.h + */ + +#ifndef _SYS_TYPES_H +#define _SYS_TYPES_H + +#include <klibc/compiler.h> +#include <stddef.h> +#include <stdint.h> + +typedef ptrdiff_t ssize_t; +typedef int mode_t; +typedef size_t off_t; + +#endif diff --git a/contrib/syslinux-4.02/com32/include/syslinux/adv.h b/contrib/syslinux-4.02/com32/include/syslinux/adv.h new file mode 100644 index 0000000..15d36bc --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/syslinux/adv.h @@ -0,0 +1,57 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/adv.h + */ + +#ifndef _SYSLINUX_ADV_H +#define _SYSLINUX_ADV_H + +#include <klibc/extern.h> +#include <stddef.h> +#include <syslinux/advconst.h> + +__extern void *__syslinux_adv_ptr; +__extern size_t __syslinux_adv_size; + +static inline void *syslinux_adv_ptr(void) +{ + return __syslinux_adv_ptr; +} + +static inline size_t syslinux_adv_size(void) +{ + return __syslinux_adv_size; +} + +__extern int syslinux_adv_write(void); + +__extern int syslinux_setadv(int, size_t, const void *); +__extern const void *syslinux_getadv(int, size_t *); + +#endif /* _SYSLINUX_ADV_H */ diff --git a/contrib/syslinux-4.02/com32/include/syslinux/advconst.h b/contrib/syslinux-4.02/com32/include/syslinux/advconst.h new file mode 100644 index 0000000..b7c775f --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/syslinux/advconst.h @@ -0,0 +1,45 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/advconst.h + * + * ADV defined constants + * + * Defined in a separate file so it can be used by non-COM32 code. + * Some of these constants are also defined in adv.inc, they better match... + */ + +#ifndef _SYSLINUX_ADVCONST_H +#define _SYSLINUX_ADVCONST_H + +#define ADV_END 0 +#define ADV_BOOTONCE 1 +#define ADV_MENUSAVE 2 + +#endif /* _SYSLINUX_ADVCONST_H */ diff --git a/contrib/syslinux-4.02/com32/include/syslinux/align.h b/contrib/syslinux-4.02/com32/include/syslinux/align.h new file mode 100644 index 0000000..81df97f --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/syslinux/align.h @@ -0,0 +1,48 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Intel Corporation; author H. Peter Anvin + * + * 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 _SYSLINUX_ALIGN_H +#define _SYSLINUX_ALIGN_H + +#include <stdint.h> + +static inline uintptr_t __align_down(uintptr_t __p, uintptr_t __a) +{ + return __p & ~(__a - 1); +} + +static inline uintptr_t __align_up(uintptr_t __p, uintptr_t __a) +{ + return (__p + __a - 1) & ~(__a - 1); +} + +#define ALIGN_UP(p,a) ((__typeof__(p))__align_up((uintptr_t)(p), (a))) +#define ALIGN_DOWN(p,a) ((__typeof__(p))__align_down((uintptr_t)(p), (a))) +#define ALIGN_UP_FOR(p,t) ALIGN_UP(p,sizeof(t)) +#define ALIGN_DOWN_FOR(p,t) ALIGN_DOWN(p,sizeof(t)) + +#endif /* _SYSLINUX_ALIGN_H */ diff --git a/contrib/syslinux-4.02/com32/include/syslinux/boot.h b/contrib/syslinux-4.02/com32/include/syslinux/boot.h new file mode 100644 index 0000000..21bea01 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/syslinux/boot.h @@ -0,0 +1,63 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/boot.h + * + * SYSLINUX boot API invocation + */ + +#ifndef _SYSLINUX_BOOT_H +#define _SYSLINUX_BOOT_H + +#include <stdint.h> +#include <klibc/compiler.h> + +int syslinux_run_command(const char *); +__noreturn syslinux_run_default(void); + +void syslinux_local_boot(uint16_t flags); + +void syslinux_final_cleanup(uint16_t flags); + +void syslinux_chain_bootstrap(uint16_t flags, const void *bootstrap, + uint32_t bootstrap_len, uint32_t edx, + uint32_t esi, uint16_t ds); + +#define IMAGE_TYPE_KERNEL 0 +#define IMAGE_TYPE_LINUX 1 +#define IMAGE_TYPE_BOOT 2 +#define IMAGE_TYPE_BSS 3 +#define IMAGE_TYPE_PXE 4 +#define IMAGE_TYPE_FDIMAGE 5 +#define IMAGE_TYPE_COMBOOT 6 +#define IMAGE_TYPE_COM32 7 +#define IMAGE_TYPE_CONFIG 8 +void syslinux_run_kernel_image(const char *filename, const char *cmdline, + uint32_t ipappend_flags, uint32_t type); + +#endif /* _SYSLINUX_BOOT_H */ diff --git a/contrib/syslinux-4.02/com32/include/syslinux/bootpm.h b/contrib/syslinux-4.02/com32/include/syslinux/bootpm.h new file mode 100644 index 0000000..a9ca2ed --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/syslinux/bootpm.h @@ -0,0 +1,57 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/bootpm.h + * + * Data structures for shuffle and boot to protected mode + */ + +#ifndef _SYSLINUX_BOOTPM_H +#define _SYSLINUX_BOOTPM_H + +#include <stdint.h> +#include <syslinux/movebits.h> + +struct syslinux_pm_regs { + uint32_t eax; /* Offset 0 */ + uint32_t ecx; /* Offset 4 */ + uint32_t edx; /* Offset 8 */ + uint32_t ebx; /* Offset 12 */ + uint32_t esp; /* Offset 16 */ + uint32_t ebp; /* Offset 20 */ + uint32_t esi; /* Offset 24 */ + uint32_t edi; /* Offset 28 */ + + uint32_t eip; /* Offset 32 */ +}; + +int syslinux_shuffle_boot_pm(struct syslinux_movelist *fraglist, + struct syslinux_memmap *memmap, + uint16_t bootflags, struct syslinux_pm_regs *regs); + +#endif /* _SYSLINUX_BOOTPM_H */ diff --git a/contrib/syslinux-4.02/com32/include/syslinux/bootrm.h b/contrib/syslinux-4.02/com32/include/syslinux/bootrm.h new file mode 100644 index 0000000..a5d746f --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/syslinux/bootrm.h @@ -0,0 +1,73 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/bootrm.h + * + * Data structures for shuffle and boot to protected mode + */ + +#ifndef _SYSLINUX_BOOTRM_H +#define _SYSLINUX_BOOTRM_H + +#include <stdint.h> +#include <stdbool.h> +#include <com32.h> +#include <syslinux/movebits.h> + +/* This register set is used by the shuffle and boot interface. It is + a completely different structure from what the __intcall() and + __farcall() interfaces use! */ +struct syslinux_rm_regs { + uint16_t es; /* Offset 0 */ + uint16_t _unused_cs; /* Offset 2 */ + uint16_t ss; /* Offset 4 */ + uint16_t ds; /* Offset 6 */ + uint16_t fs; /* Offset 8 */ + uint16_t gs; /* Offset 10 */ + + reg32_t eax; /* Offset 12 */ + reg32_t ecx; /* Offset 16 */ + reg32_t edx; /* Offset 20 */ + reg32_t ebx; /* Offset 24 */ + reg32_t esp; /* Offset 28 */ + reg32_t ebp; /* Offset 32 */ + reg32_t esi; /* Offset 36 */ + reg32_t edi; /* Offset 40 */ + + uint16_t ip; /* Offset 44 */ + uint16_t cs; /* Offset 46 */ + + bool sti; /* Offset 48 */ +}; + +int syslinux_shuffle_boot_rm(struct syslinux_movelist *fraglist, + struct syslinux_memmap *memmap, + uint16_t bootflags, struct syslinux_rm_regs *regs); + +#endif /* _SYSLINUX_BOOTRM_H */ diff --git a/contrib/syslinux-4.02/com32/include/syslinux/config.h b/contrib/syslinux-4.02/com32/include/syslinux/config.h new file mode 100644 index 0000000..79a4750 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/syslinux/config.h @@ -0,0 +1,184 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/config.h + * + * Query syslinux configuration information. + */ + +#ifndef _SYSLINUX_CONFIG_H +#define _SYSLINUX_CONFIG_H + +#include <stdint.h> +#include <com32.h> + +enum syslinux_filesystem { + SYSLINUX_FS_UNKNOWN = 0x30, + SYSLINUX_FS_SYSLINUX = 0x31, + SYSLINUX_FS_PXELINUX = 0x32, + SYSLINUX_FS_ISOLINUX = 0x33, + SYSLINUX_FS_EXTLINUX = 0x34, +}; + +struct syslinux_version { + uint16_t version; /* (major << 8)+minor */ + uint16_t max_api; + enum syslinux_filesystem filesystem; + const char *version_string; + const char *copyright_string; +}; + +struct syslinux_ipinfo { + uint32_t ipver; + uint32_t myip; + uint32_t serverip; + uint32_t gateway; + uint32_t netmask; +}; + +extern __nocommon struct syslinux_version __syslinux_version; +static inline const struct syslinux_version *syslinux_version(void) +{ + return &__syslinux_version; +} + +union syslinux_derivative_info { + struct { + com32sys_t r; + const void *esbx; + const void *fssi; + const void *gsdi; + } rr; /* real raw */ + struct { + uint16_t _pad1[4]; + uint32_t _pad2[7]; + uint8_t filesystem; + uint8_t ah; + uint16_t axh; + } c; /* common */ + struct { + uint16_t gs; + uint16_t fs; + uint16_t es; + uint16_t ds; + uint16_t di, dih; + uint16_t si, sih; + uint16_t bp, bph; + uint16_t sp, sph; + uint16_t bx, bxh; + uint16_t dx, dxh; + uint16_t cx, cxh; + uint16_t ax, axh; + uint32_t eflags; + const void *esbx; + const void *fssi; + const void *gsdi; + } r; /* raw */ + struct { + uint16_t _gs, _fs, _es, _ds; + uint32_t _edi, _esi, _ebp, _esp, _ebx; + uint8_t drive_number, dh; + uint16_t _dxh; + uint8_t sector_shift, ch; + uint16_t _cxh; + uint8_t filesystem, ah; + uint16_t _axh; + uint32_t _eflags; + const void *ptab_ptr; + const uint32_t *esdi_ptr; + const uint64_t *partoffset; + } disk; /* syslinux/extlinux */ + struct { + uint16_t _gs, _fs, _es, _ds; + uint32_t _edi, _esi, _ebp, _esp, _ebx; + uint16_t apiver; + uint16_t _dxh; + uint32_t myip; + uint8_t filesystem, ah; + uint16_t _axh; + uint32_t _eflags; + const void *pxenvptr; + const void *stack; + const struct syslinux_ipinfo *ipinfo; + } pxe; /* pxelinux */ + struct { + uint16_t _gs, _fs, _es, _ds; + uint32_t _edi, _esi, _ebp, _esp, _ebx; + uint8_t drive_number, dh; + uint16_t _dxh; + uint8_t sector_shift, cd_mode; + uint16_t _cxh; + uint8_t filesystem, ah; + uint16_t _axh; + uint32_t _eflags; + const void *spec_packet; + const uint32_t *esdi_ptr; + const uint64_t *partoffset; + } iso; /* isolinux */ +}; + +extern __nocommon union syslinux_derivative_info __syslinux_derivative_info; +static inline const union syslinux_derivative_info + *syslinux_derivative_info(void) +{ + return &__syslinux_derivative_info; +} + +struct syslinux_serial_console_info { + uint16_t iobase; + uint16_t divisor; + uint16_t flowctl; +}; + +extern __nocommon struct syslinux_serial_console_info + __syslinux_serial_console_info; +static inline const struct syslinux_serial_console_info + *syslinux_serial_console_info(void) +{ + return &__syslinux_serial_console_info; +} + +extern __nocommon const char *__syslinux_config_file; +static inline const char *syslinux_config_file(void) +{ + return __syslinux_config_file; +} + +struct syslinux_ipappend_strings { + int count; + const char *const *ptr; +}; +extern __nocommon struct syslinux_ipappend_strings __syslinux_ipappend_strings; +static inline const struct syslinux_ipappend_strings + *syslinux_ipappend_strings(void) +{ + return &__syslinux_ipappend_strings; +} + +#endif /* _SYSLINUX_CONFIG_H */ diff --git a/contrib/syslinux-4.02/com32/include/syslinux/features.h b/contrib/syslinux-4.02/com32/include/syslinux/features.h new file mode 100644 index 0000000..4bebda4 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/syslinux/features.h @@ -0,0 +1,50 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +#ifndef _SYSLINUX_FEATURES_H +#define _SYSLINUX_FEATURES_H + +#define SYSLINUX_FEATURE_LOCAL_BOOT (0*8+0) +#define SYSLINUX_FEATURE_NOOP_IDLE (0*8+1) + +extern struct __syslinux_feature_flags { + unsigned int len; + const unsigned char *ptr; +} __syslinux_feature_flags; + +static inline int syslinux_has_feature(unsigned int __flag) +{ + unsigned int __byte = __flag >> 3; + unsigned int __bit = __flag & 7; + + if (__byte <= __syslinux_feature_flags.len) + return (__syslinux_feature_flags.ptr[__byte] >> __bit) & 1; + else + return 0; +} + +#endif /* _SYSLINUX_FEATURE_H */ diff --git a/contrib/syslinux-4.02/com32/include/syslinux/idle.h b/contrib/syslinux-4.02/com32/include/syslinux/idle.h new file mode 100644 index 0000000..6a45236 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/syslinux/idle.h @@ -0,0 +1,38 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2005-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. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/idle.h + */ + +#ifndef _SYSLINUX_IDLE_H +#define _SYSLINUX_IDLE_H + +void syslinux_idle(void); +void syslinux_reset_idle(void); + +#endif diff --git a/contrib/syslinux-4.02/com32/include/syslinux/io.h b/contrib/syslinux-4.02/com32/include/syslinux/io.h new file mode 100644 index 0000000..329377d --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/syslinux/io.h @@ -0,0 +1,39 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/io.h + * + * SYSLINUX low-level I/O functions + */ + +#ifndef _SYSLINUX_IO_H +#define _SYSLINUX_IO_H + +int syslinux_read_disk(void *buf, uint32_t sector, uint16_t count); + +#endif /* _SYSLINUX_IO_H */ diff --git a/contrib/syslinux-4.02/com32/include/syslinux/keyboard.h b/contrib/syslinux-4.02/com32/include/syslinux/keyboard.h new file mode 100644 index 0000000..71925e3 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/syslinux/keyboard.h @@ -0,0 +1,51 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/keyboard.h + * + * Query syslinux keyboard map. + */ + +#ifndef _SYSLINUX_KEYBOARD_H +#define _SYSLINUX_KEYBOARD_H + +#include <stdint.h> + +struct syslinux_keyboard_map { + uint16_t version; + uint16_t length; + void *map; +}; + +extern struct syslinux_keyboard_map __syslinux_keyboard_map; +static inline const struct syslinux_keyboard_map *syslinux_keyboard_map(void) +{ + return &__syslinux_keyboard_map; +} + +#endif /* _SYSLINUX_KEYBOARD_H */ diff --git a/contrib/syslinux-4.02/com32/include/syslinux/linux.h b/contrib/syslinux-4.02/com32/include/syslinux/linux.h new file mode 100644 index 0000000..754d1b6 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/syslinux/linux.h @@ -0,0 +1,73 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/linux.h + * + * Definitions used to boot a Linux kernel + */ + +#ifndef _SYSLINUX_LINUX_H +#define _SYSLINUX_LINUX_H + +#include <stddef.h> +#include <stdint.h> + +/* A chunk of an initramfs. These are kept as a doubly-linked + circular list with headnode; the headnode is distinguished by + having len == 0. The data pointer can be NULL if data_len is zero; + if data_len < len then the balance of the region is zeroed. */ + +struct initramfs { + struct initramfs *prev, *next; + size_t len; + size_t align; + const void *data; + size_t data_len; +}; +#define INITRAMFS_MAX_ALIGN 4096 + +int syslinux_boot_linux(void *kernel_buf, size_t kernel_size, + struct initramfs *initramfs, char *cmdline); + +/* Initramfs manipulation functions */ + +struct initramfs *initramfs_init(void); +int initramfs_add_data(struct initramfs *ihead, const void *data, + size_t data_len, size_t len, size_t align); +int initramfs_mknod(struct initramfs *ihead, const char *filename, + int do_mkdir, + uint16_t mode, size_t len, uint32_t major, uint32_t minor); +int initramfs_add_file(struct initramfs *ihead, const void *data, + size_t data_len, size_t len, + const char *filename, int do_mkdir, uint32_t mode); +int initramfs_load_file(struct initramfs *ihead, const char *src_filename, + const char *dst_filename, int do_mkdir, uint32_t mode); +int initramfs_add_trailer(struct initramfs *ihead); +int initramfs_load_archive(struct initramfs *ihead, const char *filename); + +#endif /* _SYSLINUX_LINUX_H */ diff --git a/contrib/syslinux-4.02/com32/include/syslinux/loadfile.h b/contrib/syslinux-4.02/com32/include/syslinux/loadfile.h new file mode 100644 index 0000000..1a04c51 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/syslinux/loadfile.h @@ -0,0 +1,15 @@ +#ifndef LIBUTIL_LOADFILE_H +#define LIBUTIL_LOADFILE_H + +#include <stddef.h> +#include <stdio.h> + +/* loadfile() returns the true size of the file, but will guarantee valid, + zero-padded memory out to this boundary. */ +#define LOADFILE_ZERO_PAD 64 + +int loadfile(const char *, void **, size_t *); +int zloadfile(const char *, void **, size_t *); +int floadfile(FILE *, void **, size_t *, const void *, size_t); + +#endif diff --git a/contrib/syslinux-4.02/com32/include/syslinux/memscan.h b/contrib/syslinux-4.02/com32/include/syslinux/memscan.h new file mode 100644 index 0000000..db79543 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/syslinux/memscan.h @@ -0,0 +1,38 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * 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 _SYSLINUX_MEMSCAN_H +#define _SYSLINUX_MEMSCAN_H + +#include <stdbool.h> +#include <syslinux/movebits.h> /* addr_t */ + +typedef int (*scan_memory_callback_t) (void *, addr_t, addr_t, bool); +int syslinux_scan_memory(scan_memory_callback_t callback, void *data); + +#endif /* _SYSLINUX_MEMSCAN_H */ diff --git a/contrib/syslinux-4.02/com32/include/syslinux/movebits.h b/contrib/syslinux-4.02/com32/include/syslinux/movebits.h new file mode 100644 index 0000000..54ee7ff --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/syslinux/movebits.h @@ -0,0 +1,89 @@ +#ifndef _SYSLINUX_MOVEBITS_H +#define _SYSLINUX_MOVEBITS_H + +#include <inttypes.h> +#include <stdio.h> + +typedef uint32_t addr_t; + +/* + * A syslinux_movelist is a linked list of move operations. The ordering + * is important, so no sorting requirement can be imposed. + */ +struct syslinux_movelist { + addr_t dst; + addr_t src; + addr_t len; + struct syslinux_movelist *next; +}; + +/* + * A syslinux_memmap is a sorted, linked list of memory regions, + * guaranteed to satisfy the constraint that no adjacent zones have + * the same type. Undefined memory ranges are represented with entries; + * they have type SMT_UNDEFINED. + * + * Note that there is no length field. The length of a region is obtained + * by looking at the start of the next entry in the chain. + */ +enum syslinux_memmap_types { + SMT_ERROR = -2, /* Internal error token */ + SMT_END = -1, /* End of list */ + SMT_UNDEFINED = 0, /* Unknown range */ + SMT_FREE = 1, /* Available memory */ + SMT_RESERVED, /* Unusable memory */ + SMT_ALLOC, /* Memory allocated by user */ + SMT_ZERO, /* Memory that should be zeroed */ +}; + +struct syslinux_memmap { + addr_t start; + enum syslinux_memmap_types type; + struct syslinux_memmap *next; +}; + +/* + * moves is computed from "fraglist" and "memmap". Areas that are + * to be zeroed should be marked as such in the memmap, not in the + * fraglist. + */ + +int syslinux_compute_movelist(struct syslinux_movelist **movelist, + struct syslinux_movelist *fraglist, + struct syslinux_memmap *memmap); + +struct syslinux_memmap *syslinux_memory_map(void); +void syslinux_free_movelist(struct syslinux_movelist *); +int syslinux_add_movelist(struct syslinux_movelist **, + addr_t dst, addr_t src, addr_t len); +int syslinux_allocate_from_list(struct syslinux_movelist **freelist, + addr_t dst, addr_t len); +int syslinux_do_shuffle(struct syslinux_movelist *fraglist, + struct syslinux_memmap *memmap, + addr_t entry_point, addr_t entry_type, + uint16_t bootflags); +struct syslinux_memmap *syslinux_target_memmap(struct syslinux_movelist + *fraglist, + struct syslinux_memmap *memmap); + +/* Operatons on struct syslinux_memmap */ +struct syslinux_memmap *syslinux_init_memmap(void); +int syslinux_add_memmap(struct syslinux_memmap **list, + addr_t start, addr_t len, + enum syslinux_memmap_types type); +enum syslinux_memmap_types syslinux_memmap_type(struct syslinux_memmap *list, + addr_t start, addr_t len); +int syslinux_memmap_largest(struct syslinux_memmap *list, + enum syslinux_memmap_types type, + addr_t * start, addr_t * len); +void syslinux_free_memmap(struct syslinux_memmap *list); +struct syslinux_memmap *syslinux_dup_memmap(struct syslinux_memmap *list); +int syslinux_memmap_find(struct syslinux_memmap *list, + enum syslinux_memmap_types type, + addr_t * start, addr_t * len, addr_t align); + +/* Debugging functions */ +void syslinux_dump_movelist(FILE * file, struct syslinux_movelist *ml); +void syslinux_dump_memmap(FILE * file, struct syslinux_memmap *memmap); + +#endif /* _SYSLINUX_MOVEBITS_H */ diff --git a/contrib/syslinux-4.02/com32/include/syslinux/pmapi.h b/contrib/syslinux-4.02/com32/include/syslinux/pmapi.h new file mode 100644 index 0000000..fa39018 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/syslinux/pmapi.h @@ -0,0 +1,79 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2002-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * pmapi.h + * + * Definitions for the Syslinux 4 protected-mode ABI + */ + +#ifndef _SYSLINUX_PMAPI_H +#define _SYSLINUX_PMAPI_H + +#include <stddef.h> +#include <inttypes.h> + +/* + * Note: add new members to this structure only at the end. + * The position of elements in this structure is an ABI. + */ +struct _DIR_; +struct dirent; + +struct com32_filedata { + size_t size; /* File size */ + int blocklg2; /* log2(block size) */ + uint16_t handle; /* File handle */ +}; + +struct com32_pmapi { + size_t __pmapi_size; + + void *(*lmalloc)(size_t); + void (*lfree)(void *); + + int (*open_file)(const char *, struct com32_filedata *); + size_t (*read_file)(uint16_t *, void *, size_t); + void (*close_file)(uint16_t); + + struct _DIR_ *(*opendir)(const char *); + struct dirent *(*readdir)(struct _DIR_ *); + int (*closedir)(struct _DIR_ *); + + void (*idle)(void); + void (*reset_idle)(void); + + int (*chdir)(const char *); + char *(*getcwd)(char *, size_t); + + /* Should be "const volatile", but gcc miscompiles that sometimes */ + volatile uint32_t *jiffies; + volatile uint32_t *ms_timer; +}; + +#endif /* _SYSLINUX_PMAPI_H */ diff --git a/contrib/syslinux-4.02/com32/include/syslinux/pxe.h b/contrib/syslinux-4.02/com32/include/syslinux/pxe.h new file mode 100644 index 0000000..4e8a336 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/syslinux/pxe.h @@ -0,0 +1,44 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/pxe.h + * + * PXE definitions and function prototypes for SYSLINUX + */ + +#ifndef _SYSLINUX_PXE_H +#define _SYSLINUX_PXE_H + +#include <syslinux/pxe_api.h> + +/* 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); +uint32_t pxe_dns(const char *hostname); + +#endif /* _SYSLINUX_PXE_H */ diff --git a/contrib/syslinux-4.02/com32/include/syslinux/pxe_api.h b/contrib/syslinux-4.02/com32/include/syslinux/pxe_api.h new file mode 100644 index 0000000..27166b0 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/syslinux/pxe_api.h @@ -0,0 +1,571 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/pxe_api.h + * + * PXE type and constant definitions for SYSLINUX + */ + +#ifndef _SYSLINUX_PXE_API_H +#define _SYSLINUX_PXE_API_H + +#include <stdint.h> +#include <netinet/in.h> +#include <klibc/compiler.h> +#include <com32.h> + +/* PXE spec structures and definitions. These mostly follow the PXE + spec, except when the PXE spec is unnecessarily stupid. Of course, + that is most of the time. */ + +/* Basic types; use Unix-like _t convention instead of SCREAMING; also + re-use types we already have, like in_addr_t. */ + +typedef uint16_t pxenv_status_t; + +#define MAC_ADDR_LEN 16 +typedef uint8_t mac_addr_t[MAC_ADDR_LEN]; + +/* "Protected mode segment descriptor" according to PXE... */ +typedef struct { + uint16_t sel; + uint32_t base; + uint16_t size; +} __packed pxe_segdesc_t; + +typedef far_ptr_t 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 { + pxenv_status_t Status; + uint16_t PacketType; +#define PXENV_PACKET_TYPE_DHCP_DISCOVER 1 +#define PXENV_PACKET_TYPE_DHCP_ACK 2 +#define PXENV_PACKET_TYPE_CACHED_REPLY 3 + uint16_t BufferSize; + segoff16_t Buffer; + uint16_t BufferLimit; +} __packed t_PXENV_GET_CACHED_INFO; + +typedef struct s_PXENV_START_UNDI { + pxenv_status_t Status; + uint16_t AX; + uint16_t BX; + uint16_t DX; + uint16_t DI; + uint16_t ES; +} __packed t_PXENV_START_UNDI; + +typedef struct s_PXENV_STOP_UNDI { + pxenv_status_t Status; +} __packed t_PXENV_STOP_UNDI; + +typedef struct s_PXENV_START_BASE { + pxenv_status_t Status; +} __packed t_PXENV_START_BASE; + +typedef struct s_PXENV_STOP_BASE { + pxenv_status_t Status; +} __packed t_PXENV_STOP_BASE; + +typedef struct s_PXENV_TFTP_OPEN { + pxenv_status_t Status; + in_addr_t ServerIPAddress; + in_addr_t GatewayIPAddress; + uint8_t FileName[128]; + in_port_t TFTPPort; + uint16_t PacketSize; +} __packed t_PXENV_TFTP_OPEN; + +typedef struct s_PXENV_TFTP_CLOSE { + pxenv_status_t Status; +} __packed t_PXENV_TFTP_CLOSE; + +typedef struct s_PXENV_TFTP_READ { + pxenv_status_t Status; + uint16_t PacketNumber; + uint16_t BufferSize; + segoff16_t Buffer; +} __packed t_PXENV_TFTP_READ; + +typedef struct s_PXENV_TFTP_READ_FILE { + pxenv_status_t Status; + uint8_t FileName[128]; + uint32_t BufferSize; + void *Buffer; + in_addr_t ServerIPAddress; + in_addr_t GatewayIPAddress; + in_addr_t McastIPAddress; + in_port_t TFTPClntPort; + in_port_t TFTPSrvPort; + uint16_t TFTPOpenTimeOut; + uint16_t TFTPReopenDelay; +} __packed t_PXENV_TFTP_READ_FILE; + +typedef struct s_PXENV_TFTP_GET_FSIZE { + pxenv_status_t Status; + in_addr_t ServerIPAddress; + in_addr_t GatewayIPAddress; + uint8_t FileName[128]; + uint32_t FileSize; +} __packed t_PXENV_TFTP_GET_FSIZE; + +typedef struct s_PXENV_UDP_OPEN { + pxenv_status_t status; + in_addr_t src_ip; +} __packed t_PXENV_UDP_OPEN; + +typedef struct s_PXENV_UDP_CLOSE { + pxenv_status_t status; +} __packed t_PXENV_UDP_CLOSE; + +typedef struct s_PXENV_UDP_WRITE { + pxenv_status_t status; + in_addr_t ip; + in_addr_t gw; + in_port_t src_port; + in_port_t dst_port; + uint16_t buffer_size; + segoff16_t buffer; +} __packed t_PXENV_UDP_WRITE; + +typedef struct s_PXENV_UDP_READ { + pxenv_status_t status; + in_addr_t src_ip; + in_addr_t dest_ip; + in_port_t s_port; + in_port_t d_port; + uint16_t buffer_size; + segoff16_t buffer; +} __packed t_PXENV_UDP_READ; + +typedef struct s_PXENV_UNDI_STARTUP { + pxenv_status_t Status; +} __packed t_PXENV_UNDI_STARTUP; + +typedef struct s_PXENV_UNDI_CLEANUP { + pxenv_status_t Status; +} __packed t_PXENV_UNDI_CLEANUP; + +typedef struct s_PXENV_UNDI_INITIALIZE { + pxenv_status_t Status; + void *ProtocolIni; + uint8_t reserved[8]; +} __packed t_PXENV_UNDI_INITIALIZE; + +#define MAXNUM_MCADDR 8 +typedef struct s_PXENV_UNDI_MCAST_ADDRESS { + uint16_t MCastAddrCount; + mac_addr_t McastAddr[MAXNUM_MCADDR]; +} __packed t_PXENV_UNDI_MCAST_ADDRESS; + +typedef struct s_PXENV_UNDI_RESET { + pxenv_status_t Status; + t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf; +} __packed t_PXENV_UNDI_RESET; + +typedef struct s_PXENV_UNDI_SHUTDOWN { + pxenv_status_t Status; +} __packed t_PXENV_UNDI_SHUTDOWN; + +typedef struct s_PXENV_UNDI_OPEN { + pxenv_status_t Status; + uint16_t OpenFlag; + uint16_t PktFilter; +#define FLTR_DIRECTED 0x0001 +#define FLTR_BRDCST 0x0002 +#define FLTR_PRMSCS 0x0004 +#define FLTR_SRC_RTG 0x0008 + t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf; +} __packed t_PXENV_UNDI_OPEN; + +typedef struct s_PXENV_UNDI_CLOSE { + pxenv_status_t Status; +} __packed t_PXENV_UNDI_CLOSE; + +typedef struct s_PXENV_UNDI_TRANSMIT { + pxenv_status_t Status; + uint8_t Protocol; +#define P_UNKNOWN 0 +#define P_IP 1 +#define P_ARP 2 +#define P_RARP 3 + uint8_t XmitFlag; +#define XMT_DESTADDR 0x0000 +#define XMT_BROADCAST 0x0001 + segoff16_t DestAddr; + segoff16_t TBD; + uint32_t Reserved[2]; +} __packed t_PXENV_UNDI_TRANSMIT; +#define MAX_DATA_BLKS 8 +typedef struct s_PXENV_UNDI_TBD { + uint16_t ImmedLength; + segoff16_t Xmit; + uint16_t DataBlkCount; + struct DataBlk { + uint8_t TDPtrType; + uint8_t TDRsvdByte; + uint16_t TDDataLen; + segoff16_t TDDataPtr; + } DataBlock[MAX_DATA_BLKS]; +} __packed t_PXENV_UNDI_TBD; + +typedef struct s_PXENV_UNDI_SET_MCAST_ADDRESS { + pxenv_status_t Status; + t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf; +} __packed t_PXENV_UNDI_SET_MCAST_ADDR; + +typedef struct s_PXENV_UNDI_SET_STATION_ADDRESS { + pxenv_status_t Status; + mac_addr_t StationAddress; +} __packed t_PXENV_UNDI_SET_STATION_ADDR; + +typedef struct s_PXENV_UNDI_SET_PACKET_FILTER { + pxenv_status_t Status; + uint8_t filter; +} __packed t_PXENV_UNDI_SET_PACKET_FILTER; + +typedef struct s_PXENV_UNDI_GET_INFORMATION { + pxenv_status_t Status; + uint16_t BaseIo; + uint16_t IntNumber; + uint16_t MaxTranUnit; + uint16_t HwType; +#define ETHER_TYPE 1 +#define EXP_ETHER_TYPE 2 +#define IEEE_TYPE 6 +#define ARCNET_TYPE 7 + uint16_t HwAddrLen; + mac_addr_t CurrentNodeAddress; + mac_addr_t PermNodeAddress; + uint16_t ROMAddress; + uint16_t RxBufCt; + uint16_t TxBufCt; +} __packed t_PXENV_UNDI_GET_INFORMATION; + +typedef struct s_PXENV_UNDI_GET_STATISTICS { + pxenv_status_t Status; + uint32_t XmtGoodFrames; + uint32_t RcvGoodFrames; + uint32_t RcvCRCErrors; + uint32_t RcvResourceErrors; +} __packed t_PXENV_UNDI_GET_STATISTICS; + +typedef struct s_PXENV_UNDI_CLEAR_STATISTICS { + pxenv_status_t Status; +} __packed t_PXENV_UNDI_CLEAR_STATISTICS; + +typedef struct s_PXENV_UNDI_INITIATE_DIAGS { + pxenv_status_t Status; +} __packed t_PXENV_UNDI_INITIATE_DIAGS; + +typedef struct s_PXENV_UNDI_FORCE_INTERRUPT { + pxenv_status_t Status; +} __packed t_PXENV_UNDI_FORCE_INTERRUPT; + +typedef struct s_PXENV_UNDI_GET_MCAST_ADDRESS { + pxenv_status_t Status; + in_addr_t InetAddr; + mac_addr_t MediaAddr; +} __packed t_PXENV_UNDI_GET_MCAST_ADDR; + +typedef struct s_PXENV_UNDI_GET_NIC_TYPE { + pxenv_status_t Status; + uint8_t NicType; +#define PCI_NIC 2 +#define PnP_NIC 3 +#define CardBus_NIC 4 + union { + struct { + uint16_t Vendor_ID; + uint16_t Dev_ID; + uint8_t Base_Class; + uint8_t Sub_Class; + uint8_t Prog_Intf; + uint8_t Rev; + uint16_t BusDevFunc; + uint16_t SubVendor_ID; + uint16_t SubDevice_ID; + } pci, cardbus; + struct { + uint32_t EISA_Dev_ID; + uint8_t Base_Class; + uint8_t Sub_Class; + uint8_t Prog_Intf; + uint16_t CardSelNum; + } __packed pnp; + } __packed info; +} __packed t_PXENV_UNDI_GET_NIC_TYPE; + +typedef struct s_PXENV_UNDI_GET_IFACE_INFO { + pxenv_status_t Status; + uint8_t IfaceType[16]; + uint32_t LinkSpeed; + uint32_t ServiceFlags; + uint32_t Reserved[4]; +} __packed t_PXENV_UNDI_GET_NDIS_INFO; + +typedef struct s_PXENV_UNDI_GET_STATE { +#define PXE_UNDI_GET_STATE_STARTED 1 +#define PXE_UNDI_GET_STATE_INITIALIZED 2 +#define PXE_UNDI_GET_STATE_OPENED 3 + pxenv_status_t Status; + uint8_t UNDIstate; +} __packed t_PXENV_UNDI_GET_STATE; + +typedef struct s_PXENV_UNDI_ISR { + pxenv_status_t Status; + uint16_t FuncFlag; + uint16_t BufferLength; + uint16_t FrameLength; + uint16_t FrameHeaderLength; + segoff16_t Frame; + uint8_t ProtType; + uint8_t PktType; +} __packed t_PXENV_UNDI_ISR; + +typedef struct s_PXENV_FILE_API_CHECK { + pxenv_status_t Status; + uint16_t Size; + uint32_t Magic; + uint32_t Provider; + uint32_t APIMask; + uint32_t Flags; +} __packed t_PXENV_FILE_API_CHECK; + +typedef struct s_PXENV_FILE_READ { + pxenv_status_t Status; + uint16_t FileHandle; + uint16_t BufferSize; + segoff16_t Buffer; +} __packed t_PXENV_FILE_READ; + +typedef struct s_PXENV_FILE_OPEN { + pxenv_status_t Status; + uint16_t FileHandle; + segoff16_t FileName; + uint32_t Reserved; +} __packed t_PXENV_FILE_OPEN; + +typedef struct s_PXENV_FILE_CLOSE { + pxenv_status_t Status; + uint16_t FileHandle; +} __packed t_PXENV_FILE_CLOSE; + +typedef struct s_PXENV_GET_FILE_SIZE { + pxenv_status_t Status; + uint16_t FileHandle; + uint32_t FileSize; +} __packed t_PXENV_GET_FILE_SIZE; + +typedef struct s_PXENV_UNLOAD_STACK { + pxenv_status_t Status; + uint8_t reserved[10]; +} __packed t_PXENV_UNLOAD_STACK; + +#define PXENV_UNDI_ISR_IN_START 1 +#define PXENV_UNDI_ISR_IN_PROCESS 2 +#define PXENV_UNDI_ISR_IN_GET_NEXT 3 +/* One of these will be returned for + PXENV_UNDI_ISR_IN_START */ +#define PXENV_UNDI_ISR_OUT_OURS 0 +#define PXENV_UNDI_USR_OUT_NOT_OURS 1 +/* One of these will be returned for + PXENV_UNDI_ISR_IN_PROCESS and + PXENV_UNDI_ISR_IN_GET_NEXT */ +#define PXENV_UNDI_ISR_OUT_DONE 0 +#define PXENV_UNDI_ISR_OUT_TRANSMIT 2 +#define PXENV_UNDI_ISR_OUT_RECEIVE 3 +#define PXENV_UNDI_ISR_OUT_BUSY 4 + +/* Function numbers and error codes */ + +#define PXENV_TFTP_OPEN 0x0020 +#define PXENV_TFTP_CLOSE 0x0021 +#define PXENV_TFTP_READ 0x0022 +#define PXENV_TFTP_READ_FILE 0x0023 +#define PXENV_TFTP_READ_FILE_PMODE 0x0024 +#define PXENV_TFTP_GET_FSIZE 0x0025 + +#define PXENV_UDP_OPEN 0x0030 +#define PXENV_UDP_CLOSE 0x0031 +#define PXENV_UDP_READ 0x0032 +#define PXENV_UDP_WRITE 0x0033 + +#define PXENV_START_UNDI 0x0000 +#define PXENV_UNDI_STARTUP 0x0001 +#define PXENV_UNDI_CLEANUP 0x0002 +#define PXENV_UNDI_INITIALIZE 0x0003 +#define PXENV_UNDI_RESET_NIC 0x0004 +#define PXENV_UNDI_SHUTDOWN 0x0005 +#define PXENV_UNDI_OPEN 0x0006 +#define PXENV_UNDI_CLOSE 0x0007 +#define PXENV_UNDI_TRANSMIT 0x0008 +#define PXENV_UNDI_SET_MCAST_ADDR 0x0009 +#define PXENV_UNDI_SET_STATION_ADDR 0x000A +#define PXENV_UNDI_SET_PACKET_FILTER 0x000B +#define PXENV_UNDI_GET_INFORMATION 0x000C +#define PXENV_UNDI_GET_STATISTICS 0x000D +#define PXENV_UNDI_CLEAR_STATISTICS 0x000E +#define PXENV_UNDI_INITIATE_DIAGS 0x000F +#define PXENV_UNDI_FORCE_INTERRUPT 0x0010 +#define PXENV_UNDI_GET_MCAST_ADDR 0x0011 +#define PXENV_UNDI_GET_NIC_TYPE 0x0012 +#define PXENV_UNDI_GET_IFACE_INFO 0x0013 +#define PXENV_UNDI_ISR 0x0014 +#define PXENV_STOP_UNDI 0x0015 /* Overlap...? */ +#define PXENV_UNDI_GET_STATE 0x0015 /* Overlap...? */ + +#define PXENV_UNLOAD_STACK 0x0070 +#define PXENV_GET_CACHED_INFO 0x0071 +#define PXENV_RESTART_DHCP 0x0072 +#define PXENV_RESTART_TFTP 0x0073 +#define PXENV_MODE_SWITCH 0x0074 +#define PXENV_START_BASE 0x0075 +#define PXENV_STOP_BASE 0x0076 + +/* gPXE extensions... */ +#define PXENV_FILE_OPEN 0x00e0 +#define PXENV_FILE_CLOSE 0x00e1 +#define PXENV_FILE_SELECT 0x00e2 +#define PXENV_FILE_READ 0x00e3 +#define PXENV_GET_FILE_SIZE 0x00e4 +#define PXENV_FILE_EXEC 0x00e5 +#define PXENV_FILE_API_CHECK 0x00e6 + +/* Exit codes */ +#define PXENV_EXIT_SUCCESS 0x0000 +#define PXENV_EXIT_FAILURE 0x0001 + +/* Status codes */ +#define PXENV_STATUS_SUCCESS 0x00 +#define PXENV_STATUS_FAILURE 0x01 +#define PXENV_STATUS_BAD_FUNC 0x02 +#define PXENV_STATUS_UNSUPPORTED 0x03 +#define PXENV_STATUS_KEEP_UNDI 0x04 +#define PXENV_STATUS_KEEP_ALL 0x05 +#define PXENV_STATUS_OUT_OF_RESOURCES 0x06 +#define PXENV_STATUS_ARP_TIMEOUT 0x11 +#define PXENV_STATUS_UDP_CLOSED 0x18 +#define PXENV_STATUS_UDP_OPEN 0x19 +#define PXENV_STATUS_TFTP_CLOSED 0x1a +#define PXENV_STATUS_TFTP_OPEN 0x1b +#define PXENV_STATUS_MCOPY_PROBLEM 0x20 +#define PXENV_STATUS_BIS_INTEGRITY_FAILURE 0x21 +#define PXENV_STATUS_BIS_VALIDATE_FAILURE 0x22 +#define PXENV_STATUS_BIS_INIT_FAILURE 0x23 +#define PXENV_STATUS_BIS_SHUTDOWN_FAILURE 0x24 +#define PXENV_STATUS_BIS_GBOA_FAILURE 0x25 +#define PXENV_STATUS_BIS_FREE_FAILURE 0x26 +#define PXENV_STATUS_BIS_GSI_FAILURE 0x27 +#define PXENV_STATUS_BIS_BAD_CKSUM 0x28 +#define PXENV_STATUS_TFTP_CANNOT_ARP_ADDRESS 0x30 +#define PXENV_STATUS_TFTP_OPEN_TIMEOUT 0x32 + +#define PXENV_STATUS_TFTP_UNKNOWN_OPCODE 0x33 +#define PXENV_STATUS_TFTP_READ_TIMEOUT 0x35 +#define PXENV_STATUS_TFTP_ERROR_OPCODE 0x36 +#define PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION 0x38 +#define PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION 0x39 +#define PXENV_STATUS_TFTP_TOO_MANY_PACKAGES 0x3a +#define PXENV_STATUS_TFTP_FILE_NOT_FOUND 0x3b +#define PXENV_STATUS_TFTP_ACCESS_VIOLATION 0x3c +#define PXENV_STATUS_TFTP_NO_MCAST_ADDRESS 0x3d +#define PXENV_STATUS_TFTP_NO_FILESIZE 0x3e +#define PXENV_STATUS_TFTP_INVALID_PACKET_SIZE 0x3f +#define PXENV_STATUS_DHCP_TIMEOUT 0x51 +#define PXENV_STATUS_DHCP_NO_IP_ADDRESS 0x52 +#define PXENV_STATUS_DHCP_NO_BOOTFILE_NAME 0x53 +#define PXENV_STATUS_DHCP_BAD_IP_ADDRESS 0x54 +#define PXENV_STATUS_UNDI_INVALID_FUNCTION 0x60 +#define PXENV_STATUS_UNDI_MEDIATEST_FAILED 0x61 +#define PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST 0x62 +#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC 0x63 +#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY 0x64 +#define PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA 0x65 +#define PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA 0x66 +#define PXENV_STATUS_UNDI_BAD_MAC_ADDRESS 0x67 +#define PXENV_STATUS_UNDI_BAD_EEPROM_CHECKSUM 0x68 +#define PXENV_STATUS_UNDI_ERROR_SETTING_ISR 0x69 +#define PXENV_STATUS_UNDI_INVALID_STATE 0x6a +#define PXENV_STATUS_UNDI_TRANSMIT_ERROR 0x6b +#define PXENV_STATUS_UNDI_INVALID_PARAMETER 0x6c +#define PXENV_STATUS_BSTRAP_PROMPT_MENU 0x74 +#define PXENV_STATUS_BSTRAP_MCAST_ADDR 0x76 +#define PXENV_STATUS_BSTRAP_MISSING_LIST 0x77 +#define PXENV_STATUS_BSTRAP_NO_RESPONSE 0x78 +#define PXENV_STATUS_BSTRAP_FILE_TOO_BIG 0x79 +#define PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE 0xa0 +#define PXENV_STATUS_BINL_NO_PXE_SERVER 0xa1 +#define PXENV_STATUS_NOT_AVAILABLE_IN_PMODE 0xa2 +#define PXENV_STATUS_NOT_AVAILABLE_IN_RMODE 0xa3 +#define PXENV_STATUS_BUSD_DEVICE_NOT_SUPPORTED 0xb0 +#define PXENV_STATUS_LOADER_NO_FREE_BASE_MEMORY 0xc0 +#define PXENV_STATUS_LOADER_NO_BC_ROMID 0xc1 +#define PXENV_STATUS_LOADER_BAD_BC_ROMID 0xc2 +#define PXENV_STATUS_LOADER_BAD_BC_RUNTIME_IMAGE 0xc3 +#define PXENV_STATUS_LOADER_NO_UNDI_ROMID 0xc4 +#define PXENV_STATUS_LOADER_BAD_UNDI_ROMID 0xc5 +#define PXENV_STATUS_LOADER_BAD_UNDI_DRIVER_IMAGE 0xc6 +#define PXENV_STATUS_LOADER_NO_PXE_STRUCT 0xc8 +#define PXENV_STATUS_LOADER_NO_PXENV_STRUCT 0xc9 +#define PXENV_STATUS_LOADER_UNDI_START 0xca +#define PXENV_STATUS_LOADER_BC_START 0xcb + +#endif /* _SYSLINUX_PXE_API_H */ diff --git a/contrib/syslinux-4.02/com32/include/syslinux/reboot.h b/contrib/syslinux-4.02/com32/include/syslinux/reboot.h new file mode 100644 index 0000000..e589982 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/syslinux/reboot.h @@ -0,0 +1,41 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/reboot.h + * + * Reboot the system + */ + +#ifndef _SYSLINUX_REBOOT_H +#define _SYSLINUX_REBOOT_H + +#include <klibc/compiler.h> + +__noreturn syslinux_reboot(int warm); + +#endif /* _SYSLINUX_REBOOT_H */ diff --git a/contrib/syslinux-4.02/com32/include/syslinux/resolve.h b/contrib/syslinux-4.02/com32/include/syslinux/resolve.h new file mode 100644 index 0000000..0589c33 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/syslinux/resolve.h @@ -0,0 +1,41 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/resolve.h + * + * Interface to the syslinux DNS query API + */ + +#ifndef _SYSLINUX_RESOLVE_H +#define _SYSLINUX_RESOLVE_H + +#include <netinet/in.h> + +in_addr_t syslinux_resolve_hostname(const char *); + +#endif /* _SYSLINUX_RESOLVE_H */ diff --git a/contrib/syslinux-4.02/com32/include/syslinux/vesacon.h b/contrib/syslinux-4.02/com32/include/syslinux/vesacon.h new file mode 100644 index 0000000..b99e649 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/syslinux/vesacon.h @@ -0,0 +1,39 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +#ifndef _SYSLINUX_VESACON_H +#define _SYSLINUX_VESACON_H + +#include <stdbool.h> + +int vesacon_default_background(void); +void vesacon_set_resolution(int, int); +int vesacon_load_background(const char *); +int vesacon_set_background(unsigned int); +void vesacon_cursor_enable(bool); + +#endif /* _SYSLINUX_VESACON_H */ diff --git a/contrib/syslinux-4.02/com32/include/syslinux/video.h b/contrib/syslinux-4.02/com32/include/syslinux/video.h new file mode 100644 index 0000000..f22828a --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/syslinux/video.h @@ -0,0 +1,43 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/video.h + * + * SYSLINUX video API functions. + */ + +#ifndef _SYSLINUX_VIDEO_H +#define _SYSLINUX_VIDEO_H + +#include <stdint.h> + +void syslinux_force_text_mode(void); +void syslinux_report_video_mode(uint16_t flags, uint16_t xsize, uint16_t ysize); +int syslinux_font_query(uint8_t **font); + +#endif /* _SYSLINUX_API_H */ diff --git a/contrib/syslinux-4.02/com32/include/syslinux/zio.h b/contrib/syslinux-4.02/com32/include/syslinux/zio.h new file mode 100644 index 0000000..23991e5 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/syslinux/zio.h @@ -0,0 +1,13 @@ +/* + * <syslinux/zio.h> + */ + +#ifndef _SYSLINUX_ZIO_H +#define _SYSLINUX_ZIO_H + +#include <stdio.h> + +int zopen(const char *, int, ...); +FILE *zfopen(const char *, const char *); + +#endif /* _SYSLINUX_ZIO_H */ diff --git a/contrib/syslinux-4.02/com32/include/time.h b/contrib/syslinux-4.02/com32/include/time.h new file mode 100644 index 0000000..259386a --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/time.h @@ -0,0 +1,6 @@ +#ifndef _TIME_H +#define _TIME_H + +/* empty */ + +#endif diff --git a/contrib/syslinux-4.02/com32/include/tinyjpeg.h b/contrib/syslinux-4.02/com32/include/tinyjpeg.h new file mode 100644 index 0000000..e88d09a --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/tinyjpeg.h @@ -0,0 +1,72 @@ +/* + * Small jpeg decoder library (header file) + * + * Copyright (c) 2006, Luc Saillard <luc@saillard.org> + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - 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. + * + * - Neither the name of the author nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + * + */ + + +#ifndef __JPEGDEC_H__ +#define __JPEGDEC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +struct jdec_private; + +/* Flags that can be set by any applications */ +#define TINYJPEG_FLAGS_MJPEG_TABLE (1<<1) + +/* Format accepted in outout */ +struct tinyjpeg_colorspace; +typedef const struct tinyjpeg_colorspace *tinyjpeg_colorspace_t; + +extern const tinyjpeg_colorspace_t TINYJPEG_FMT_GREY, TINYJPEG_FMT_BGR24, + TINYJPEG_FMT_RGB24, TINYJPEG_FMT_YUV420P, TINYJPEG_FMT_BGRA32, + TINYJPEG_FMT_RGBA32; + +struct jdec_private *tinyjpeg_init(void); +void tinyjpeg_free(struct jdec_private *priv); + +int tinyjpeg_parse_header(struct jdec_private *priv, const unsigned char *buf, unsigned int size); +int tinyjpeg_decode(struct jdec_private *priv, tinyjpeg_colorspace_t pixel_format); +const char *tinyjpeg_get_errorstring(struct jdec_private *priv); +void tinyjpeg_get_size(struct jdec_private *priv, unsigned int *width, unsigned int *height); +int tinyjpeg_get_components(struct jdec_private *priv, unsigned char **components, unsigned int ncomponents); +int tinyjpeg_set_components(struct jdec_private *priv, unsigned char * const *components, unsigned int ncomponents); +int tinyjpeg_get_bytes_per_row(struct jdec_private *priv, unsigned int *bytes, unsigned int ncomponents); +int tinyjpeg_set_bytes_per_row(struct jdec_private *priv, const unsigned int *bytes, unsigned int ncomponents); +int tinyjpeg_set_flags(struct jdec_private *priv, int flags); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/contrib/syslinux-4.02/com32/include/unistd.h b/contrib/syslinux-4.02/com32/include/unistd.h new file mode 100644 index 0000000..fc514f1 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/unistd.h @@ -0,0 +1,36 @@ +/* + * unistd.h + */ + +#ifndef _UNISTD_H +#define _UNISTD_H + +#include <klibc/extern.h> +#include <klibc/compiler.h> +#include <stddef.h> +#include <sys/types.h> + +__extern __noreturn _exit(int); + +__extern int open(const char *, int, ...); +__extern int close(int); + +__extern ssize_t read(int, void *, size_t); +__extern ssize_t write(int, const void *, size_t); + +__extern int isatty(int); + +__extern int getscreensize(int, int *, int *); + +__extern char *getcwd(char *, int); +__extern int chdir(const char *); + +__extern unsigned int sleep(unsigned int); +__extern unsigned int msleep(unsigned int); + +/* Standard file descriptor numbers. */ +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 + +#endif /* _UNISTD_H */ diff --git a/contrib/syslinux-4.02/com32/include/zconf.h b/contrib/syslinux-4.02/com32/include/zconf.h new file mode 100644 index 0000000..02ce56c --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/zconf.h @@ -0,0 +1,428 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ + +/* all linked symbols */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzgetc z_gzgetc +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzwrite z_gzwrite +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetHeader z_inflateGetHeader +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# define uncompress z_uncompress +# define zError z_zError +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# define gzFile z_gzFile +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include <windows.h> + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef STDC +# include <sys/types.h> /* for off_t */ +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include <unistd.h> /* for SEEK_* and off_t */ +# ifdef VMS +# include <unixio.h> /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +#endif + +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +# define z_off64_t off64_t +#else +# define z_off64_t z_off_t +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/contrib/syslinux-4.02/com32/include/zlib.h b/contrib/syslinux-4.02/com32/include/zlib.h new file mode 100644 index 0000000..bfbba83 --- /dev/null +++ b/contrib/syslinux-4.02/com32/include/zlib.h @@ -0,0 +1,1613 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.5, April 19th, 2010 + + Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.5" +#define ZLIB_VERNUM 0x1250 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 2 +#define ZLIB_VER_REVISION 5 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip streams in memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use in the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). Some + output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed code + block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the stream + are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least the + value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered + binary. This field is only for information purposes and does not affect the + compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the + exact value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit() does not process any header information -- that is deferred + until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing will + resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all the uncompressed data. (The size + of the uncompressed data may have been saved by the compressor for this + purpose.) The next operation on this stream must be inflateEnd to deallocate + the decompression state. The use of Z_FINISH is never required, but can be + used to inform inflate that a faster approach may be used for the single + inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK or Z_TREES is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained, so applications that need that information should + instead use raw inflate, see inflateInit2() below, or inflateBack() and + perform their own processing of the gzip header and trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by the + caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any call + of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. The + stream will keep the same compression level and any other attributes that + may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression level is changed, the input available so far is + compressed with the old level (and may be flushed); the new level will take + effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to be + compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if + strm->avail_out was zero. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called + immediately after inflateInit2() or inflateReset() and before any call of + inflate() to set the dictionary. The application must insure that the + dictionary that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been + found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the + success case, the application may save the current current value of total_in + which indicates where valid compressed data was found. In the error case, + the application may repeatedly call inflateSync, providing more input each + time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + int windowBits)); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above or -1 << 16 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the normal + behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed buffer. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef voidp gzFile; /* opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); + + Opens a gzip (.gz) file for reading or writing. The mode parameter is as + in fopen ("rb" or "wb") but can also include a compression level ("wb9") or + a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only + compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' + for fixed code compression as in "wb9F". (See the description of + deflateInit2 for more information about the strategy parameter.) Also "a" + can be used instead of "w" to request that the gzip stream that will be + written be appended to the file. "+" will result in an error, since reading + and writing to the same gzip file is not supported. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen associates a gzFile with the file descriptor fd. File descriptors + are obtained from calls like open, dup, creat, pipe or fileno (if the file + has been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +/* + Set the internal buffer size used by this library's functions. The + default buffer size is 8192 bytes. This function must be called after + gzopen() or gzdopen(), and before any other calls that read or write the + file. The buffer memory allocation is always deferred to the first read or + write. Two buffers are allocated, either both of the specified size when + writing, or one of the specified size and the other twice that size when + reading. A larger buffer size of, for example, 64K or 128K bytes will + noticeably increase the speed of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. If + the input file was not in gzip format, gzread copies the given number of + bytes into the buffer. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream, or failing that, reading the rest + of the input file directly without decompression. The entire input file + will be read if gzread is called until it returns less than the requested + len. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. +*/ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes written or 0 in case of + error. +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the arguments to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or 0 in case of error. The number of + uncompressed bytes written is limited to 8191, or one less than the buffer + size given to gzbuffer(). The caller should assure that this limit is not + exceeded. If it is exceeded, then gzprintf() will return an error (0) with + nothing written. In this case, there may also be a buffer overflow with + unpredictable consequences, which is possible only if zlib was compiled with + the insecure functions sprintf() or vsprintf() because the secure snprintf() + or vsnprintf() functions were not available. This can be determined using + zlibCompileFlags(). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or a + newline character is read and transferred to buf, or an end-of-file + condition is encountered. If any characters are read or if len == 1, the + string is terminated with a null character. If no characters are read due + to an end-of-file or len < 1, then the buffer is left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte or -1 + in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read as the first character + on the next read. At least one character of push-back is allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter flush + is as in the deflate() function. The return value is the zlib error number + (see function gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatented gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); + + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); + + Returns the starting position for the next gzread or gzwrite on the given + compressed file. This position represents a number of bytes in the + uncompressed data stream, and is zero when starting, even if appending or + reading a gzip stream from the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); + + Returns the current offset in the file being read or written. This offset + includes the count of bytes that precede the gzip stream, for example when + appending or when using gzdopen() for reading. When reading, the offset + does not include as yet unused buffered input. This information can be used + for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns true (1) if the end-of-file indicator has been set while reading, + false (0) otherwise. Note that the end-of-file indicator is set only if the + read tried to go past the end of the input, but came up short. Therefore, + just like feof(), gzeof() may return false even if there is no more data to + read, in the event that the last read request was for the exact number of + bytes remaining in the input file. This will happen if the input file size + is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. This state can change from + false to true while reading the input file if the end of a gzip stream is + reached, but is followed by data that is not another gzip stream. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file and + deallocates the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the given + compressed file. errnum is set to zlib error number. If an error occurred + in the file system and not in the compression library, errnum is set to + Z_ERRNO and the application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is Z_NULL, this function returns the + required initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is Z_NULL, this function returns the required + initial value for the for the crc. Pre- and post-conditioning (one's + complement) is performed within this function so it shouldn't be done by the + application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0 +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# ifdef _LARGEFILE64_SOURCE + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); +#endif + +/* hack for buggy compilers */ +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; +#endif + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); +ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/contrib/syslinux-4.02/com32/lib/MCONFIG b/contrib/syslinux-4.02/com32/lib/MCONFIG new file mode 100644 index 0000000..44278bd --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/MCONFIG @@ -0,0 +1,80 @@ +# -*- makefile -*- + +include $(topdir)/MCONFIG + +GCCOPT := $(call gcc_ok,-std=gnu99,) +GCCOPT += $(call gcc_ok,-m32,) +GCCOPT += $(call gcc_ok,-fno-stack-protector,) +GCCOPT += $(call gcc_ok,-fwrapv,) +GCCOPT += $(call gcc_ok,-freg-struct-return,) +GCCOPT += $(call gcc_ok,-fPIE,-fPIC) +GCCOPT += $(call gcc_ok,-fno-exceptions,) +GCCOPT += $(call gcc_ok,-fno-asynchronous-unwind-tables,) +GCCOPT += $(call gcc_ok,-fno-strict-aliasing,) +GCCOPT += $(call gcc_ok,-falign-functions=0,-malign-functions=0) +GCCOPT += $(call gcc_ok,-falign-jumps=0,-malign-jumps=0) +GCCOPT += $(call gcc_ok,-falign-labels=0,-malign-labels=0) +GCCOPT += $(call gcc_ok,-falign-loops=0,-malign-loops=0) +GCCOPT += $(call gcc_ok,-mpreferred-stack-boundary=2,) + +INCLUDE = -I. +STRIP = strip --strip-all -R .comment -R .note + +# zlib and libpng configuration flags +LIBFLAGS = -DDYNAMIC_CRC_TABLE -DPNG_NO_CONSOLE_IO \ + -DPNG_NO_WRITE_SUPPORTED \ + -DPNG_NO_MNG_FEATURES \ + -DPNG_NO_READ_tIME -DPNG_NO_WRITE_tIME + +# We need some features in libpng which apparently aren't available in the +# fixed-point versions. It's OK, because we have to have a non-graphical +# fallback anyway, just use that on old machines... +# LIBFLAGS += -DPNG_NO_FLOATING_POINT_SUPPORTED + +REQFLAGS = $(GCCOPT) -g -mregparm=3 -DREGPARM=3 -D__COM32__ \ + -nostdinc -iwithprefix include -I. -I./sys -I../include +OPTFLAGS = -Os -march=i386 -falign-functions=0 -falign-jumps=0 \ + -falign-labels=0 -ffast-math -fomit-frame-pointer +WARNFLAGS = $(GCCWARN) -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Winline + +CFLAGS = $(OPTFLAGS) $(REQFLAGS) $(WARNFLAGS) $(LIBFLAGS) +LDFLAGS = -m elf32_i386 + +.SUFFIXES: .c .o .a .so .lo .i .S .s .ls .ss .lss + +% : %.c # Cancel default rule + +% : %.S + +.c.o: + $(CC) $(MAKEDEPS) $(CFLAGS) -c -o $@ $< + +.c.i: + $(CC) $(MAKEDEPS) $(CFLAGS) -E -o $@ $< + +.c.s: + $(CC) $(MAKEDEPS) $(CFLAGS) -S -o $@ $< + +.S.o: + $(CC) $(MAKEDEPS) $(CFLAGS) -D__ASSEMBLY__ -c -o $@ $< + +.S.s: + $(CC) $(MAKEDEPS) $(CFLAGS) -D__ASSEMBLY__ -E -o $@ $< + +.S.lo: + $(CC) $(MAKEDEPS) $(CFLAGS) $(SOFLAGS) -D__ASSEMBLY__ -c -o $@ $< + +.S.ls: + $(CC) $(MAKEDEPS) $(CFLAGS) $(SOFLAGS) -D__ASSEMBLY__ -E -o $@ $< + +.s.o: + $(CC) $(MAKEDEPS) $(CFLAGS) -x assembler -c -o $@ $< + +.ls.lo: + $(CC) $(MAKEDEPS) $(CFLAGS) $(SOFLAGS) -x assembler -c -o $@ $< + +.c.lo: + $(CC) $(MAKEDEPS) $(CFLAGS) $(SOFLAGS) -c -o $@ $< + +.c.ls: + $(CC) $(MAKEDEPS) $(CFLAGS) $(SOFLAGS) -S -o $@ $< diff --git a/contrib/syslinux-4.02/com32/lib/Makefile b/contrib/syslinux-4.02/com32/lib/Makefile new file mode 100644 index 0000000..2035df2 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/Makefile @@ -0,0 +1,187 @@ +# +# ONLY INCLUDE MIT OR 2/3-BSD-LICENSED CODE IN THIS LIBRARY +# + +# Include configuration rules +NOGPL := 1 +topdir = ../.. +include MCONFIG + +LIBOBJS = \ + abort.o atexit.o atoi.o atol.o atoll.o calloc.o creat.o \ + ctypes.o errno.o fgetc.o fgets.o fopen.o fprintf.o fputc.o \ + fclose.o putchar.o setjmp.o \ + fputs.o fread2.o fread.o free.o fwrite2.o fwrite.o \ + getopt.o getopt_long.o \ + lrand48.o malloc.o stack.o memccpy.o memchr.o memcmp.o \ + memcpy.o mempcpy.o memmem.o memmove.o memset.o memswap.o \ + 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 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 \ + strtoimax.o strtok.o strtol.o strtoll.o strtoul.o strtoull.o \ + strtoumax.o vfprintf.o vprintf.o vsnprintf.o vsprintf.o \ + asprintf.o vasprintf.o strlcpy.o strlcat.o \ + vsscanf.o zalloc.o \ + \ + lmalloc.o lstrdup.o \ + \ + dprintf.o vdprintf.o \ + \ + sys/readdir.o getcwd.o chdir.o fdopendir.o \ + \ + libgcc/__ashldi3.o libgcc/__udivdi3.o \ + libgcc/__negdi2.o libgcc/__ashrdi3.o libgcc/__lshrdi3.o \ + libgcc/__muldi3.o libgcc/__udivmoddi4.o libgcc/__umoddi3.o \ + libgcc/__divdi3.o libgcc/__moddi3.o \ + \ + sys/intcall.o sys/farcall.o sys/cfarcall.o sys/zeroregs.o \ + sys/entry.o sys/exit.o sys/argv.o sys/times.o sys/sleep.o \ + sys/fileinfo.o sys/opendev.o sys/read.o sys/write.o sys/ftell.o \ + sys/close.o sys/open.o sys/fileread.o sys/fileclose.o \ + sys/openmem.o \ + sys/isatty.o sys/fstat.o \ + \ + sys/zfile.o sys/zfopen.o \ + \ + sys/openconsole.o sys/line_input.o \ + sys/colortable.o sys/screensize.o \ + \ + sys/stdcon_read.o sys/stdcon_write.o sys/rawcon_read.o \ + sys/rawcon_write.o sys/err_read.o sys/err_write.o \ + sys/null_read.o sys/null_write.o sys/serial_write.o \ + \ + sys/xserial_write.o \ + \ + sys/ansi.o \ + \ + sys/libansi.o \ + \ + sys/gpxe.o \ + \ + sys/ansicon_write.o sys/ansiserial_write.o \ + \ + sys/vesacon_write.o sys/vesaserial_write.o \ + sys/vesa/initvesa.o sys/vesa/drawtxt.o sys/vesa/background.o \ + sys/vesa/alphatbl.o sys/vesa/screencpy.o sys/vesa/fmtpixel.o \ + sys/vesa/i915resolution.o \ + \ + pci/cfgtype.o pci/scan.o pci/bios.o \ + pci/readb.o pci/readw.o pci/readl.o \ + pci/writeb.o pci/writew.o pci/writel.o \ + \ + zlib/adler32.o zlib/compress.o zlib/crc32.o \ + zlib/uncompr.o zlib/deflate.o zlib/trees.o zlib/zutil.o \ + zlib/inflate.o zlib/infback.o zlib/inftrees.o zlib/inffast.o \ + \ + libpng/png.o libpng/pngset.o libpng/pngget.o libpng/pngrutil.o \ + libpng/pngtrans.o libpng/pngwutil.o libpng/pngread.o \ + libpng/pngrio.o libpng/pngwio.o libpng/pngwrite.o \ + libpng/pngrtran.o libpng/pngwtran.o libpng/pngmem.o \ + libpng/pngerror.o libpng/pngpread.o \ + \ + jpeg/tinyjpeg.o jpeg/jidctflt.o jpeg/decode1.o jpeg/decode3.o \ + jpeg/grey.o jpeg/yuv420p.o \ + jpeg/rgb24.o jpeg/bgr24.o \ + jpeg/rgba32.o jpeg/bgra32.o \ + \ + sys/x86_init_fpu.o math/pow.o math/strtod.o \ + \ + syslinux/idle.o syslinux/reboot.o \ + syslinux/features.o syslinux/config.o syslinux/serial.o \ + syslinux/ipappend.o syslinux/dsinfo.o syslinux/version.o \ + syslinux/keyboard.o \ + \ + syslinux/memscan.o \ + \ + syslinux/addlist.o syslinux/freelist.o syslinux/memmap.o \ + syslinux/movebits.o syslinux/shuffle.o syslinux/shuffle_pm.o \ + syslinux/shuffle_rm.o syslinux/zonelist.o \ + syslinux/dump_mmap.o syslinux/dump_movelist.o \ + \ + syslinux/run_default.o syslinux/run_command.o \ + syslinux/cleanup.o syslinux/localboot.o syslinux/runimage.o \ + \ + syslinux/loadfile.o syslinux/floadfile.o syslinux/zloadfile.o \ + \ + syslinux/load_linux.o syslinux/initramfs.o \ + syslinux/initramfs_file.o syslinux/initramfs_loadfile.o \ + syslinux/initramfs_archive.o \ + \ + syslinux/pxe_get_cached.o syslinux/pxe_get_nic.o \ + syslinux/pxe_dns.o \ + \ + syslinux/adv.o syslinux/advwrite.o syslinux/getadv.o \ + syslinux/setadv.o \ + \ + syslinux/video/fontquery.o syslinux/video/forcetext.o \ + syslinux/video/reportmode.o + +# These are the objects which are also imported into the core +LIBCOREOBJS = \ + memcpy.o mempcpy.o memset.o memcmp.o memmove.o \ + strlen.o stpcpy.o strcpy.o strcmp.o strlcpy.o strlcat.o \ + strchr.o strncmp.o strncpy.o \ + \ + snprintf.o sprintf.o vsnprintf.o \ + \ + dprintf.o vdprintf.o \ + \ + zalloc.o strdup.o \ + \ + sys/intcall.o sys/farcall.o sys/cfarcall.o sys/zeroregs.o \ + \ + libgcc/__ashldi3.o libgcc/__udivdi3.o \ + libgcc/__negdi2.o libgcc/__ashrdi3.o libgcc/__lshrdi3.o \ + libgcc/__muldi3.o libgcc/__udivmoddi4.o libgcc/__umoddi3.o \ + libgcc/__divdi3.o libgcc/__moddi3.o + +BINDIR = /usr/bin +LIBDIR = /usr/lib +DATADIR = /usr/share +AUXDIR = $(DATADIR)/syslinux +INCDIR = /usr/include +COM32DIR = $(AUXDIR)/com32 + +all: libcom32.a libcomcore.a + +libcom32.a : $(LIBOBJS) + rm -f $@ + $(AR) cq $@ $^ + $(RANLIB) $@ + +libcomcore.a : $(LIBCOREOBJS) + rm -f $@ + $(AR) cq $@ $^ + $(RANLIB) $@ + +tidy dist clean: + rm -f sys/vesa/alphatbl.c + find . \( -name \*.o -o -name \*.a -o -name .\*.d -o -name \*.tmp \) -print0 | \ + xargs -0r rm -f + +spotless: clean + rm -f *.a + rm -f *~ \#* */*~ */\#* + +install: all + mkdir -m 755 -p $(INSTALLROOT)$(COM32DIR) + install -m 644 libcom32.a com32.ld $(INSTALLROOT)$(COM32DIR) + -rm -rf $(INSTALLROOT)$(COM32DIR)/include + cp -r ../include $(INSTALLROOT)$(COM32DIR) + +# These files are performance critical, and doesn't compile well with -Os +sys/vesa/drawtxt.o: sys/vesa/drawtxt.c + $(CC) $(MAKEDEPS) $(CFLAGS) -O3 -c -o $@ $< + +sys/vesa/alphatbl.c: sys/vesa/alphatbl.pl + $(PERL) $< > $@ + +jpeg/jidctflt.o: jpeg/jidctflt.c + $(CC) $(MAKEDEPS) $(CFLAGS) -O3 -c -o $@ $< + +-include .*.d */.*.d */*/.*.d diff --git a/contrib/syslinux-4.02/com32/lib/abort.c b/contrib/syslinux-4.02/com32/lib/abort.c new file mode 100644 index 0000000..b848be1 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/abort.c @@ -0,0 +1,11 @@ +/* + * abort.c + */ + +#include <stdlib.h> +#include <unistd.h> + +void abort(void) +{ + _exit(255); +} diff --git a/contrib/syslinux-4.02/com32/lib/asprintf.c b/contrib/syslinux-4.02/com32/lib/asprintf.c new file mode 100644 index 0000000..ef5b4b2 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/asprintf.c @@ -0,0 +1,30 @@ +/* + * asprintf.c + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> + +int asprintf(char **bufp, const char *format, ...) +{ + va_list ap, ap1; + int rv; + int bytes; + char *p; + + va_start(ap, format); + va_copy(ap1, ap); + + bytes = vsnprintf(NULL, 0, format, ap1) + 1; + va_end(ap1); + + *bufp = p = malloc(bytes); + if (!p) + return -1; + + rv = vsnprintf(p, bytes, format, ap); + va_end(ap); + + return rv; +} diff --git a/contrib/syslinux-4.02/com32/lib/atexit.c b/contrib/syslinux-4.02/com32/lib/atexit.c new file mode 100644 index 0000000..804790e --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/atexit.c @@ -0,0 +1,10 @@ +/* + * atexit.c + */ + +#include <stdlib.h> + +int atexit(void (*fctn) (void)) +{ + return on_exit((void (*)(int, void *))fctn, NULL); +} diff --git a/contrib/syslinux-4.02/com32/lib/atexit.h b/contrib/syslinux-4.02/com32/lib/atexit.h new file mode 100644 index 0000000..917beb5 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/atexit.h @@ -0,0 +1,16 @@ +/* + * atexit.h + * + * atexit()/on_exit() internal definitions + */ + +#ifndef ATEXIT_H +#define ATEXIT_H + +struct atexit { + void (*fctn) (int, void *); + void *arg; /* on_exit() parameter */ + struct atexit *next; +}; + +#endif /* ATEXIT_H */ diff --git a/contrib/syslinux-4.02/com32/lib/atoi.c b/contrib/syslinux-4.02/com32/lib/atoi.c new file mode 100644 index 0000000..a6ec0bf --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/atoi.c @@ -0,0 +1,3 @@ +#define TYPE int +#define NAME atoi +#include "atox.c" diff --git a/contrib/syslinux-4.02/com32/lib/atol.c b/contrib/syslinux-4.02/com32/lib/atol.c new file mode 100644 index 0000000..e65484e --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/atol.c @@ -0,0 +1,3 @@ +#define TYPE long +#define NAME atol +#include "atox.c" diff --git a/contrib/syslinux-4.02/com32/lib/atoll.c b/contrib/syslinux-4.02/com32/lib/atoll.c new file mode 100644 index 0000000..25df79e --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/atoll.c @@ -0,0 +1,3 @@ +#define TYPE long long +#define NAME atoll +#include "atox.c" diff --git a/contrib/syslinux-4.02/com32/lib/atox.c b/contrib/syslinux-4.02/com32/lib/atox.c new file mode 100644 index 0000000..e9917cd --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/atox.c @@ -0,0 +1,14 @@ +/* + * atox.c + * + * atoi(), atol(), atoll() + */ + +#include <inttypes.h> +#include <stdlib.h> +#include <stdio.h> + +TYPE NAME(const char *nptr) +{ + return (TYPE) strntoumax(nptr, (char **)NULL, 10, ~(size_t) 0); +} diff --git a/contrib/syslinux-4.02/com32/lib/calloc.c b/contrib/syslinux-4.02/com32/lib/calloc.c new file mode 100644 index 0000000..04b3c5e --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/calloc.c @@ -0,0 +1,13 @@ +/* + * calloc.c + */ + +#include <stdlib.h> +#include <string.h> + +/* FIXME: This should look for multiplication overflow */ + +void *calloc(size_t nmemb, size_t size) +{ + return zalloc(size * nmemb); +} diff --git a/contrib/syslinux-4.02/com32/lib/chdir.c b/contrib/syslinux-4.02/com32/lib/chdir.c new file mode 100644 index 0000000..00670e3 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/chdir.c @@ -0,0 +1,15 @@ +/* + * chdir.c + */ + +#include <dirent.h> +#include <stdio.h> +#include <errno.h> + +#include <com32.h> +#include <syslinux/pmapi.h> + +int chdir(const char *path) +{ + return __com32.cs_pm->chdir(path); +} diff --git a/contrib/syslinux-4.02/com32/lib/com32.ld b/contrib/syslinux-4.02/com32/lib/com32.ld new file mode 100644 index 0000000..37ee46c --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/com32.ld @@ -0,0 +1,141 @@ +/* + * Linker script for COM32 binaries using libcom32 + */ + +/* Script for -z combreloc: combine and sort reloc sections */ +OUTPUT_FORMAT("elf32-i386", "elf32-i386", + "elf32-i386") +OUTPUT_ARCH(i386) +EXTERN(_start) +ENTRY(_start) +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = 0; + PROVIDE (__executable_start = .); + PROVIDE (_stext = .); + + .init : + { + KEEP (*(.init)) + } =0x90909090 + .text : + { + *(.text .stub .text.* .gnu.linkonce.t.*) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + } =0x90909090 + .fini : + { + KEEP (*(.fini)) + } =0x90909090 + PROVIDE (_etext = .); + + __rodata_start = .; + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + __rodata_end = .; + + /* Ensure the __preinit_array_start label is properly aligned. We + could instead move the label definition inside the section, but + the linker would then create the section even if it turns out to + be empty, which isn't pretty. */ + . = ALIGN(4); + .preinit_array : { + PROVIDE (__preinit_array_start = .); + *(.preinit_array) + PROVIDE (__preinit_array_end = .); + } + .init_array : { + PROVIDE (__init_array_start = .); + *(.init_array) + PROVIDE (__init_array_end = .); + } + .fini_array : { + PROVIDE (__fini_array_start = .); + *(.fini_array) + PROVIDE (__fini_array_end = .); + } + .ctors : { + PROVIDE (__ctors_start = .); + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + PROVIDE (__ctors_end = .); + } + .dtors : { + PROVIDE (__dtors_start = .); + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + PROVIDE (__dtors_end = .); + } + + .got : { + PROVIDE (__got_start = .); + KEEP (*(.got.plt)) + KEEP (*(.got)) + PROVIDE (__got_end = .); + } + + /* Adjust the address for the data segment. Avoid mixing code and + data within same 128-byte chunk. */ + . = ALIGN(128); + + .data : + { + _sdata = .; + KEEP(*(.data .data.* .gnu.linkonce.d.*)) + SORT(CONSTRUCTORS) + *(.data1) + . = ALIGN(4); + _edata = .; + } + + __bss_start = .; + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. */ + . = ALIGN(4); + } + . = ALIGN(4); + _end = .; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/contrib/syslinux-4.02/com32/lib/creat.c b/contrib/syslinux-4.02/com32/lib/creat.c new file mode 100644 index 0000000..3b4dc61 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/creat.c @@ -0,0 +1,12 @@ +/* + * creat.c + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +int creat(const char *pathname, mode_t mode) +{ + return open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode); +} diff --git a/contrib/syslinux-4.02/com32/lib/ctypes.c b/contrib/syslinux-4.02/com32/lib/ctypes.c new file mode 100644 index 0000000..50125a5 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/ctypes.c @@ -0,0 +1,284 @@ +/* + * ctypes.c + * + * This is the array that defines <ctype.h> classes. + * This assumes ISO 8859-1. + */ + +#include <ctype.h> + +const unsigned char __ctypes[257] = { + 0, /* EOF */ + + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl | __ctype_space, /* BS */ + __ctype_cntrl | __ctype_space, /* TAB */ + __ctype_cntrl | __ctype_space, /* LF */ + __ctype_cntrl | __ctype_space, /* VT */ + __ctype_cntrl | __ctype_space, /* FF */ + __ctype_cntrl | __ctype_space, /* CR */ + __ctype_cntrl, /* control character */ + + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + + __ctype_print | __ctype_space, /* space */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_upper | __ctype_xdigit, /* A-F */ + __ctype_print | __ctype_upper | __ctype_xdigit, /* A-F */ + __ctype_print | __ctype_upper | __ctype_xdigit, /* A-F */ + __ctype_print | __ctype_upper | __ctype_xdigit, /* A-F */ + __ctype_print | __ctype_upper | __ctype_xdigit, /* A-F */ + __ctype_print | __ctype_upper | __ctype_xdigit, /* A-F */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_lower | __ctype_xdigit, /* a-f */ + __ctype_print | __ctype_lower | __ctype_xdigit, /* a-f */ + __ctype_print | __ctype_lower | __ctype_xdigit, /* a-f */ + __ctype_print | __ctype_lower | __ctype_xdigit, /* a-f */ + __ctype_print | __ctype_lower | __ctype_xdigit, /* a-f */ + __ctype_print | __ctype_lower | __ctype_xdigit, /* a-f */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_cntrl, /* control character */ + + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + + __ctype_print | __ctype_space, /* NBSP */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_lower, /* lower accented */ + + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ +}; diff --git a/contrib/syslinux-4.02/com32/lib/dprintf.c b/contrib/syslinux-4.02/com32/lib/dprintf.c new file mode 100644 index 0000000..900c0a4 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/dprintf.c @@ -0,0 +1,19 @@ +/* + * dprintf.c + */ + +#include <stdio.h> +#include <stdarg.h> + +#undef DEBUG +#define DEBUG 1 +#include <dprintf.h> + +void dprintf(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vdprintf(format, ap); + va_end(ap); +} diff --git a/contrib/syslinux-4.02/com32/lib/errno.c b/contrib/syslinux-4.02/com32/lib/errno.c new file mode 100644 index 0000000..f280e30 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/errno.c @@ -0,0 +1,7 @@ +/* + * errno.c + * + */ +#include <errno.h> + +int errno; diff --git a/contrib/syslinux-4.02/com32/lib/exit.c b/contrib/syslinux-4.02/com32/lib/exit.c new file mode 100644 index 0000000..ccd6f1e --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/exit.c @@ -0,0 +1,41 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * exit.c + * + * The regular exit + */ + +#include <stdlib.h> + +extern __noreturn(*__exit_handler) (int); + +__noreturn exit(int rv) +{ + __exit_handler(rv); +} diff --git a/contrib/syslinux-4.02/com32/lib/fclose.c b/contrib/syslinux-4.02/com32/lib/fclose.c new file mode 100644 index 0000000..f59fcc0 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/fclose.c @@ -0,0 +1,11 @@ +/* + * fclose.c + */ + +#include <stdio.h> +#include <unistd.h> + +int fclose(FILE * __f) +{ + return close(fileno(__f)); +} diff --git a/contrib/syslinux-4.02/com32/lib/fdopendir.c b/contrib/syslinux-4.02/com32/lib/fdopendir.c new file mode 100644 index 0000000..4fc3138 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/fdopendir.c @@ -0,0 +1,15 @@ +/* + * fdopendir.c + */ + +#include <dirent.h> +#include <stdio.h> +#include <errno.h> + +DIR *fdopendir(int __fd) +{ + (void)__fd; + + errno = ENOSYS; + return NULL; +} diff --git a/contrib/syslinux-4.02/com32/lib/fgetc.c b/contrib/syslinux-4.02/com32/lib/fgetc.c new file mode 100644 index 0000000..b48e147 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/fgetc.c @@ -0,0 +1,19 @@ +/* + * fgetc.c + * + * Extremely slow fgetc implementation, using _fread(). If people + * actually need character-oriented input to be fast, we may actually + * have to implement buffering. Sigh. + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <errno.h> + +int fgetc(FILE * f) +{ + unsigned char ch; + + return (_fread(&ch, 1, f) == 1) ? (int)ch : EOF; +} diff --git a/contrib/syslinux-4.02/com32/lib/fgets.c b/contrib/syslinux-4.02/com32/lib/fgets.c new file mode 100644 index 0000000..7bc1519 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/fgets.c @@ -0,0 +1,31 @@ +/* + * fgets.c + * + * This will be very slow due to the implementation of getc(), + * but we can't afford to drain characters we don't need from + * the input. + */ + +#include <stdio.h> + +char *fgets(char *s, int n, FILE * f) +{ + int ch; + char *p = s; + + while (n > 1) { + ch = getc(f); + if (ch == EOF) { + *p = '\0'; + return (p == s) ? NULL : s; + } + *p++ = ch; + if (ch == '\n') + break; + n--; + } + if (n) + *p = '\0'; + + return s; +} diff --git a/contrib/syslinux-4.02/com32/lib/fopen.c b/contrib/syslinux-4.02/com32/lib/fopen.c new file mode 100644 index 0000000..c7c122c --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/fopen.c @@ -0,0 +1,43 @@ +/* + * fopen.c + */ + +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> + +FILE *fopen(const char *file, const char *mode) +{ + int flags = O_RDONLY; + int plus = 0; + int fd; + + while (*mode) { + switch (*mode) { + case 'r': + flags = O_RDONLY; + break; + case 'w': + flags = O_WRONLY | O_CREAT | O_TRUNC; + break; + case 'a': + flags = O_WRONLY | O_CREAT | O_APPEND; + break; + case '+': + plus = 1; + break; + } + mode++; + } + + if (plus) { + flags = (flags & ~(O_RDONLY | O_WRONLY)) | O_RDWR; + } + + fd = open(file, flags, 0666); + + if (fd < 0) + return NULL; + else + return fdopen(fd, mode); +} diff --git a/contrib/syslinux-4.02/com32/lib/fopendev.c b/contrib/syslinux-4.02/com32/lib/fopendev.c new file mode 100644 index 0000000..cd2f00f --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/fopendev.c @@ -0,0 +1,43 @@ +/* + * fopendev.c + */ + +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> + +FILE *fopendev(const struct dev_info * dev, const char *mode) +{ + int flags = O_RDONLY; + int plus = 0; + int fd; + + while (*mode) { + switch (*mode) { + case 'r': + flags = O_RDONLY; + break; + case 'w': + flags = O_WRONLY | O_CREAT | O_TRUNC; + break; + case 'a': + flags = O_WRONLY | O_CREAT | O_APPEND; + break; + case '+': + plus = 1; + break; + } + mode++; + } + + if (plus) { + flags = (flags & ~(O_RDONLY | O_WRONLY)) | O_RDWR; + } + + fd = opendev(file, flags); + + if (fd < 0) + return NULL; + else + return fdopen(fd, mode); +} diff --git a/contrib/syslinux-4.02/com32/lib/fprintf.c b/contrib/syslinux-4.02/com32/lib/fprintf.c new file mode 100644 index 0000000..5eb8e07 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/fprintf.c @@ -0,0 +1,17 @@ +/* + * fprintf.c + */ + +#include <stdio.h> +#include <stdarg.h> + +int fprintf(FILE * file, const char *format, ...) +{ + va_list ap; + int rv; + + va_start(ap, format); + rv = vfprintf(file, format, ap); + va_end(ap); + return rv; +} diff --git a/contrib/syslinux-4.02/com32/lib/fputc.c b/contrib/syslinux-4.02/com32/lib/fputc.c new file mode 100644 index 0000000..7a1bf0b --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/fputc.c @@ -0,0 +1,14 @@ +/* + * fputc.c + * + * gcc "printf decompilation" expects this to exist... + */ + +#include <stdio.h> + +int fputc(int c, FILE * f) +{ + unsigned char ch = c; + + return _fwrite(&ch, 1, f) == 1 ? ch : EOF; +} diff --git a/contrib/syslinux-4.02/com32/lib/fputs.c b/contrib/syslinux-4.02/com32/lib/fputs.c new file mode 100644 index 0000000..84f0c89 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/fputs.c @@ -0,0 +1,15 @@ +/* + * fputs.c + * + * This isn't quite fputs() in the stdio sense, since we don't + * have stdio, but it takes a file descriptor argument instead + * of the FILE *. + */ + +#include <stdio.h> +#include <string.h> + +int fputs(const char *s, FILE * file) +{ + return _fwrite(s, strlen(s), file); +} diff --git a/contrib/syslinux-4.02/com32/lib/fread.c b/contrib/syslinux-4.02/com32/lib/fread.c new file mode 100644 index 0000000..94e9cff --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/fread.c @@ -0,0 +1,32 @@ +/* + * fread.c + */ + +#include <errno.h> +#include <unistd.h> +#include <stdio.h> + +size_t _fread(void *buf, size_t count, FILE * f) +{ + size_t bytes = 0; + ssize_t rv; + char *p = buf; + + while (count) { + rv = read(fileno(f), p, count); + if (rv == -1) { + if (errno == EINTR || errno == EAGAIN) + continue; + else + break; + } else if (rv == 0) { + break; + } + + p += rv; + bytes += rv; + count -= rv; + } + + return bytes; +} diff --git a/contrib/syslinux-4.02/com32/lib/fread2.c b/contrib/syslinux-4.02/com32/lib/fread2.c new file mode 100644 index 0000000..0062040 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/fread2.c @@ -0,0 +1,13 @@ +/* + * fread2.c + * + * The actual fread() function as a non-inline + */ + +#define __NO_FREAD_FWRITE_INLINES +#include <stdio.h> + +size_t fread(void *ptr, size_t size, size_t nmemb, FILE * f) +{ + return _fread(ptr, size * nmemb, f) / size; +} diff --git a/contrib/syslinux-4.02/com32/lib/free.c b/contrib/syslinux-4.02/com32/lib/free.c new file mode 100644 index 0000000..be23865 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/free.c @@ -0,0 +1,113 @@ +/* + * free.c + * + * Very simple linked-list based malloc()/free(). + */ + +#include <stdlib.h> +#include "malloc.h" + +static struct free_arena_header *__free_block(struct free_arena_header *ah) +{ + struct free_arena_header *pah, *nah; + + pah = ah->a.prev; + nah = ah->a.next; + if (pah->a.type == ARENA_TYPE_FREE && + (char *)pah + pah->a.size == (char *)ah) { + /* Coalesce into the previous block */ + pah->a.size += ah->a.size; + pah->a.next = nah; + nah->a.prev = pah; + +#ifdef DEBUG_MALLOC + ah->a.type = ARENA_TYPE_DEAD; +#endif + + ah = pah; + pah = ah->a.prev; + } else { + /* Need to add this block to the free chain */ + ah->a.type = ARENA_TYPE_FREE; + + ah->next_free = __malloc_head.next_free; + ah->prev_free = &__malloc_head; + __malloc_head.next_free = ah; + ah->next_free->prev_free = ah; + } + + /* In either of the previous cases, we might be able to merge + with the subsequent block... */ + if (nah->a.type == ARENA_TYPE_FREE && + (char *)ah + ah->a.size == (char *)nah) { + ah->a.size += nah->a.size; + + /* Remove the old block from the chains */ + nah->next_free->prev_free = nah->prev_free; + nah->prev_free->next_free = nah->next_free; + ah->a.next = nah->a.next; + nah->a.next->a.prev = ah; + +#ifdef DEBUG_MALLOC + nah->a.type = ARENA_TYPE_DEAD; +#endif + } + + /* Return the block that contains the called block */ + return ah; +} + +/* + * This is used to insert a block which is not previously on the + * free list. Only the a.size field of the arena header is assumed + * to be valid. + */ +void __inject_free_block(struct free_arena_header *ah) +{ + struct free_arena_header *nah; + size_t a_end = (size_t) ah + ah->a.size; + size_t n_end; + + for (nah = __malloc_head.a.next; nah->a.type != ARENA_TYPE_HEAD; + nah = nah->a.next) { + n_end = (size_t) nah + nah->a.size; + + /* Is nah entirely beyond this block? */ + if ((size_t) nah >= a_end) + break; + + /* Is this block entirely beyond nah? */ + if ((size_t) ah >= n_end) + continue; + + /* Otherwise we have some sort of overlap - reject this block */ + return; + } + + /* Now, nah should point to the successor block */ + ah->a.next = nah; + ah->a.prev = nah->a.prev; + nah->a.prev = ah; + ah->a.prev->a.next = ah; + + __free_block(ah); +} + +void free(void *ptr) +{ + struct free_arena_header *ah; + + if (!ptr) + return; + + ah = (struct free_arena_header *) + ((struct arena_header *)ptr - 1); + +#ifdef DEBUG_MALLOC + assert(ah->a.type == ARENA_TYPE_USED); +#endif + + __free_block(ah); + + /* Here we could insert code to return memory to the system. */ +} diff --git a/contrib/syslinux-4.02/com32/lib/fwrite.c b/contrib/syslinux-4.02/com32/lib/fwrite.c new file mode 100644 index 0000000..b5c1d5d --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/fwrite.c @@ -0,0 +1,32 @@ +/* + * fwrite.c + */ + +#include <errno.h> +#include <unistd.h> +#include <stdio.h> + +size_t _fwrite(const void *buf, size_t count, FILE * f) +{ + size_t bytes = 0; + ssize_t rv; + const char *p = buf; + + while (count) { + rv = write(fileno(f), p, count); + if (rv == -1) { + if (errno == EINTR || errno == EAGAIN) + continue; + else + break; + } else if (rv == 0) { + break; + } + + p += rv; + bytes += rv; + count -= rv; + } + + return bytes; +} diff --git a/contrib/syslinux-4.02/com32/lib/fwrite2.c b/contrib/syslinux-4.02/com32/lib/fwrite2.c new file mode 100644 index 0000000..4d706e1 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/fwrite2.c @@ -0,0 +1,13 @@ +/* + * fwrite2.c + * + * The actual fwrite() function as a non-inline + */ + +#define __NO_FREAD_FWRITE_INLINES +#include <stdio.h> + +size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE * f) +{ + return _fwrite(ptr, size * nmemb, f) / size; +} diff --git a/contrib/syslinux-4.02/com32/lib/getcwd.c b/contrib/syslinux-4.02/com32/lib/getcwd.c new file mode 100644 index 0000000..5ce62ec --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/getcwd.c @@ -0,0 +1,11 @@ +/* + * getcwd.c + */ + +#include <com32.h> +#include <syslinux/pmapi.h> + +char *getcwd(char *buf, size_t size) +{ + return __com32.cs_pm->getcwd(buf, size); +} diff --git a/contrib/syslinux-4.02/com32/lib/getopt.c b/contrib/syslinux-4.02/com32/lib/getopt.c new file mode 100644 index 0000000..806735d --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/getopt.c @@ -0,0 +1,97 @@ +/* + * getopt.c + * + * Simple POSIX getopt(), no GNU extensions... + */ + +#include <stdint.h> +#include <unistd.h> +#include <string.h> + +char *optarg; +int optind, opterr, optopt; +static struct getopt_private_state { + const char *optptr; + const char *last_optstring; + char *const *last_argv; +} pvt; + +int getopt(int argc, char *const *argv, const char *optstring) +{ + const char *carg; + const char *osptr; + int opt; + + /* getopt() relies on a number of different global state + variables, which can make this really confusing if there is + more than one use of getopt() in the same program. This + attempts to detect that situation by detecting if the + "optstring" or "argv" argument have changed since last time + we were called; if so, reinitialize the query state. */ + + if (optstring != pvt.last_optstring || argv != pvt.last_argv || + optind < 1 || optind > argc) { + /* optind doesn't match the current query */ + pvt.last_optstring = optstring; + pvt.last_argv = argv; + optind = 1; + pvt.optptr = NULL; + } + + carg = argv[optind]; + + /* First, eliminate all non-option cases */ + + if (!carg || carg[0] != '-' || !carg[1]) { + return -1; + } + + if (carg[1] == '-' && !carg[2]) { + optind++; + return -1; + } + + if ((uintptr_t) (pvt.optptr - carg) > (uintptr_t) strlen(carg)) { + /* Someone frobbed optind, change to new opt. */ + pvt.optptr = carg + 1; + } + + opt = *pvt.optptr++; + + if (opt != ':' && (osptr = strchr(optstring, opt))) { + if (osptr[1] == ':') { + if (*pvt.optptr) { + /* Argument-taking option with attached + argument */ + optarg = (char *)pvt.optptr; + optind++; + } else { + /* Argument-taking option with non-attached + argument */ + if (argv[optind + 1]) { + optarg = (char *)argv[optind+1]; + optind += 2; + } else { + /* Missing argument */ + optind++; + return (optstring[0] == ':') + ? ':' : '?'; + } + } + return opt; + } else { + /* Non-argument-taking option */ + /* pvt.optptr will remember the exact position to + resume at */ + if (!*pvt.optptr) + optind++; + return opt; + } + } else { + /* Unknown option */ + optopt = opt; + if (!*pvt.optptr) + optind++; + return '?'; + } +} diff --git a/contrib/syslinux-4.02/com32/lib/getopt_long.c b/contrib/syslinux-4.02/com32/lib/getopt_long.c new file mode 100644 index 0000000..e3d064b --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/getopt_long.c @@ -0,0 +1,152 @@ +/* + * getopt.c + * + * getopt_long(), or at least a common subset thereof: + * + * - Option reordering is not supported + * - -W foo is not supported + * - First optstring character "-" not supported. + */ + +#include <stdint.h> +#include <unistd.h> +#include <string.h> +#include <getopt.h> + +char *optarg; +int optind, opterr, optopt; +static struct getopt_private_state { + const char *optptr; + const char *last_optstring; + char *const *last_argv; +} pvt; + +static inline const char *option_matches(const char *arg_str, + const char *opt_name) +{ + while (*arg_str != '\0' && *arg_str != '=') { + if (*arg_str++ != *opt_name++) + return NULL; + } + + if (*opt_name) + return NULL; + + return arg_str; +} + +int getopt_long(int argc, char *const *argv, const char *optstring, + const struct option *longopts, int *longindex) +{ + const char *carg; + const char *osptr; + int opt; + + /* getopt() relies on a number of different global state + variables, which can make this really confusing if there is + more than one use of getopt() in the same program. This + attempts to detect that situation by detecting if the + "optstring" or "argv" argument have changed since last time + we were called; if so, reinitialize the query state. */ + + if (optstring != pvt.last_optstring || argv != pvt.last_argv || + optind < 1 || optind > argc) { + /* optind doesn't match the current query */ + pvt.last_optstring = optstring; + pvt.last_argv = argv; + optind = 1; + pvt.optptr = NULL; + } + + carg = argv[optind]; + + /* First, eliminate all non-option cases */ + + if (!carg || carg[0] != '-' || !carg[1]) + return -1; + + if (carg[1] == '-') { + const struct option *lo; + const char *opt_end = NULL; + + optind++; + + /* Either it's a long option, or it's -- */ + if (!carg[2]) { + /* It's -- */ + return -1; + } + + for (lo = longopts; lo->name; lo++) { + if ((opt_end = option_matches(carg+2, lo->name))) + break; + } + if (!opt_end) + return '?'; + + if (longindex) + *longindex = lo-longopts; + + if (*opt_end == '=') { + if (lo->has_arg) + optarg = (char *)opt_end+1; + else + return '?'; + } else if (lo->has_arg == 1) { + if (!(optarg = argv[optind])) + return '?'; + optind++; + } + + if (lo->flag) { + *lo->flag = lo->val; + return 0; + } else { + return lo->val; + } + } + + if ((uintptr_t) (pvt.optptr - carg) > (uintptr_t) strlen(carg)) { + /* Someone frobbed optind, change to new opt. */ + pvt.optptr = carg + 1; + } + + opt = *pvt.optptr++; + + if (opt != ':' && (osptr = strchr(optstring, opt))) { + if (osptr[1] == ':') { + if (*pvt.optptr) { + /* Argument-taking option with attached + argument */ + optarg = (char *)pvt.optptr; + optind++; + } else { + /* Argument-taking option with non-attached + argument */ + if (argv[optind + 1]) { + optarg = (char *)argv[optind+1]; + optind += 2; + } else { + /* Missing argument */ + optind++; + return (optstring[0] == ':') + ? ':' : '?'; + } + } + return opt; + } else { + /* Non-argument-taking option */ + /* pvt.optptr will remember the exact position to + resume at */ + if (!*pvt.optptr) + optind++; + return opt; + } + } else { + /* Unknown option */ + optopt = opt; + if (!*pvt.optptr) + optind++; + return '?'; + } +} diff --git a/contrib/syslinux-4.02/com32/lib/init.h b/contrib/syslinux-4.02/com32/lib/init.h new file mode 100644 index 0000000..2d98342 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/init.h @@ -0,0 +1,15 @@ +/* + * init.h + * + * Magic to set up initializers + */ + +#ifndef _INIT_H +#define _INIT_H 1 + +#include <inttypes.h> + +#define COM32_INIT(x) static const void * const __COM32_INIT \ + __attribute__((section(".init_array"),unused)) = (const void * const)&x + +#endif /* _INIT_H */ diff --git a/contrib/syslinux-4.02/com32/lib/jpeg/README b/contrib/syslinux-4.02/com32/lib/jpeg/README new file mode 100644 index 0000000..6adeef4 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/jpeg/README @@ -0,0 +1,32 @@ +/* + * Small jpeg decoder library + * + * Copyright (c) 2006, Luc Saillard <luc@saillard.org> + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - 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. + * + * - Neither the name of the author nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + * + */ diff --git a/contrib/syslinux-4.02/com32/lib/jpeg/bgr24.c b/contrib/syslinux-4.02/com32/lib/jpeg/bgr24.c new file mode 100644 index 0000000..855b855 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/jpeg/bgr24.c @@ -0,0 +1,373 @@ +/* + * Small jpeg decoder library + * + * Copyright (c) 2006, Luc Saillard <luc@saillard.org> + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - 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. + * + * - Neither the name of the author nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> + +#include "tinyjpeg.h" +#include "tinyjpeg-internal.h" + +/******************************************************************************* + * + * Colorspace conversion routine + * + * + * Note: + * YCbCr is defined per CCIR 601-1, except that Cb and Cr are + * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * The conversion equations to be implemented are therefore + * R = Y + 1.40200 * Cr + * G = Y - 0.34414 * Cb - 0.71414 * Cr + * B = Y + 1.77200 * Cb + * + ******************************************************************************/ +static unsigned char clamp(int i) +{ + if (i<0) + return 0; + else if (i>255) + return 255; + else + return i; +} + +/** + * YCrCb -> BGR24 (1x1) + * .---. + * | 1 | + * `---' + */ +static void YCrCB_to_BGR24_1x1(struct jdec_private *priv, int sx, int sy) +{ + const unsigned char *Y, *Cb, *Cr; + unsigned char *p; + int i,j; + int offset_to_next_row; + +#define SCALEBITS 10 +#define ONE_HALF (1UL << (SCALEBITS-1)) +#define FIX(x) ((int)((x) * (1UL<<SCALEBITS) + 0.5)) + + p = priv->plane[0]; + Y = priv->Y; + Cb = priv->Cb; + Cr = priv->Cr; + offset_to_next_row = priv->bytes_per_row[0] - 8*3; + for (i = sy; i > 0; i--) { + for (j = sx; j > 0; j--) { + + int y, cb, cr; + int add_r, add_g, add_b; + int r, g , b; + + y = Y[0] << SCALEBITS; + cb = *Cb++ - 128; + cr = *Cr++ - 128; + add_r = FIX(1.40200) * cr + ONE_HALF; + add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; + add_b = FIX(1.77200) * cb + ONE_HALF; + + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + + Y++; + } + + p += offset_to_next_row; + } + +#undef SCALEBITS +#undef ONE_HALF +#undef FIX + +} + + +/* + * YCrCb -> BGR24 (2x1) + * .-------. + * | 1 | 2 | + * `-------' + */ +static void YCrCB_to_BGR24_2x1(struct jdec_private *priv, int sx, int sy) +{ + const unsigned char *Y, *Cb, *Cr; + unsigned char *p; + int i,j; + int offset_to_next_row; + +#define SCALEBITS 10 +#define ONE_HALF (1UL << (SCALEBITS-1)) +#define FIX(x) ((int)((x) * (1UL<<SCALEBITS) + 0.5)) + + p = priv->plane[0]; + Y = priv->Y; + Cb = priv->Cb; + Cr = priv->Cr; + offset_to_next_row = priv->bytes_per_row[0] - 16*3; + for (i = sy; i > 0; i--) { + for (j = sx; j > 0; j -= 2) { + + int y, cb, cr; + int add_r, add_g, add_b; + int r, g , b; + + cb = *Cb++ - 128; + cr = *Cr++ - 128; + add_r = FIX(1.40200) * cr + ONE_HALF; + add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; + add_b = FIX(1.77200) * cb + ONE_HALF; + + y = Y[0] << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + + if (j > 1) { + y = Y[1] << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + } + + Y += 2; + } + + p += offset_to_next_row; + } + +#undef SCALEBITS +#undef ONE_HALF +#undef FIX + +} + +/* + * YCrCb -> BGR24 (1x2) + * .---. + * | 1 | + * |---| + * | 2 | + * `---' + */ +static void YCrCB_to_BGR24_1x2(struct jdec_private *priv, int sx, int sy) +{ + const unsigned char *Y, *Cb, *Cr; + unsigned char *p, *p2; + int i,j; + int offset_to_next_row; + +#define SCALEBITS 10 +#define ONE_HALF (1UL << (SCALEBITS-1)) +#define FIX(x) ((int)((x) * (1UL<<SCALEBITS) + 0.5)) + + p = priv->plane[0]; + p2 = priv->plane[0] + priv->bytes_per_row[0]; + Y = priv->Y; + Cb = priv->Cb; + Cr = priv->Cr; + offset_to_next_row = 2*priv->bytes_per_row[0] - 8*3; + for (i = sy; i > 0; i -= 2) { + for (j = sx; j > 0 ; j--) { + + int y, cb, cr; + int add_r, add_g, add_b; + int r, g , b; + + cb = *Cb++ - 128; + cr = *Cr++ - 128; + add_r = FIX(1.40200) * cr + ONE_HALF; + add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; + add_b = FIX(1.77200) * cb + ONE_HALF; + + y = Y[0] << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + + if (i > 1) { + y = Y[8] << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + } + + Y++; + } + Y += 8; + p += offset_to_next_row; + p2 += offset_to_next_row; + } + +#undef SCALEBITS +#undef ONE_HALF +#undef FIX + +} + + +/* + * YCrCb -> BGR24 (2x2) + * .-------. + * | 1 | 2 | + * |---+---| + * | 3 | 4 | + * `-------' + */ +static void YCrCB_to_BGR24_2x2(struct jdec_private *priv, int sx, int sy) +{ + const unsigned char *Y, *Cb, *Cr; + unsigned char *p, *p2; + int i,j; + int offset_to_next_row; + +#define SCALEBITS 10 +#define ONE_HALF (1UL << (SCALEBITS-1)) +#define FIX(x) ((int)((x) * (1UL<<SCALEBITS) + 0.5)) + + p = priv->plane[0]; + p2 = priv->plane[0] + priv->bytes_per_row[0]; + Y = priv->Y; + Cb = priv->Cb; + Cr = priv->Cr; + offset_to_next_row = 2*priv->bytes_per_row[0] - 16*3; + for (i = sy; i > 0; i -= 2) { + for (j = sx; j > 0; j -= 2) { + + int y, cb, cr; + int add_r, add_g, add_b; + int r, g , b; + + cb = *Cb++ - 128; + cr = *Cr++ - 128; + add_r = FIX(1.40200) * cr + ONE_HALF; + add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; + add_b = FIX(1.77200) * cb + ONE_HALF; + + y = Y[0] << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + + if (j > 1) { + y = Y[1] << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + } + + if (i > 1) { + y = Y[16+0] << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + + if (j > 1) { + y = Y[16+1] << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + } + } + + Y += 2; + } + Y += 16; + p += offset_to_next_row; + p2 += offset_to_next_row; + } + +#undef SCALEBITS +#undef ONE_HALF +#undef FIX + +} + +static int initialize_bgr24(struct jdec_private *priv, + unsigned int *bytes_per_blocklines, + unsigned int *bytes_per_mcu) +{ + if (!priv->bytes_per_row[0]) + priv->bytes_per_row[0] = priv->width * 3; + if (!priv->components[0]) + priv->components[0] = malloc(priv->height * priv->bytes_per_row[0]); + + bytes_per_blocklines[0] = priv->bytes_per_row[0] << 3; + bytes_per_mcu[0] = 3*8; + + return !priv->components[0]; +} + +static const struct tinyjpeg_colorspace format_bgr24 = + { + { + YCrCB_to_BGR24_1x1, + YCrCB_to_BGR24_1x2, + YCrCB_to_BGR24_2x1, + YCrCB_to_BGR24_2x2, + }, + tinyjpeg_decode_mcu_3comp_table, + initialize_bgr24 + }; + +const tinyjpeg_colorspace_t TINYJPEG_FMT_BGR24 = &format_bgr24; diff --git a/contrib/syslinux-4.02/com32/lib/jpeg/bgra32.c b/contrib/syslinux-4.02/com32/lib/jpeg/bgra32.c new file mode 100644 index 0000000..9a1ab30 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/jpeg/bgra32.c @@ -0,0 +1,390 @@ +/* + * Small jpeg decoder library + * + * Copyright (c) 2006, Luc Saillard <luc@saillard.org> + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - 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. + * + * - Neither the name of the author nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> + +#include "tinyjpeg.h" +#include "tinyjpeg-internal.h" + +/******************************************************************************* + * + * Colorspace conversion routine + * + * + * Note: + * YCbCr is defined per CCIR 601-1, except that Cb and Cr are + * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * The conversion equations to be implemented are therefore + * R = Y + 1.40200 * Cr + * G = Y - 0.34414 * Cb - 0.71414 * Cr + * B = Y + 1.77200 * Cb + * + ******************************************************************************/ +static unsigned char clamp(int i) +{ + if (i<0) + return 0; + else if (i>255) + return 255; + else + return i; +} + +/** + * YCrCb -> BGRA32 (1x1) + * .---. + * | 1 | + * `---' + */ +static void YCrCB_to_BGRA32_1x1(struct jdec_private *priv, int sx, int sy) +{ + const unsigned char *Y, *Cb, *Cr; + unsigned char *p; + int i,j; + int offset_to_next_row; + +#define SCALEBITS 10 +#define ONE_HALF (1UL << (SCALEBITS-1)) +#define FIX(x) ((int)((x) * (1UL<<SCALEBITS) + 0.5)) + + p = priv->plane[0]; + Y = priv->Y; + Cb = priv->Cb; + Cr = priv->Cr; + offset_to_next_row = priv->bytes_per_row[0] - 8*4; + for (i = sy; i > 0; i--) { + for (j = sx; j > 0; j--) { + + int y, cb, cr; + int add_r, add_g, add_b; + int r, g , b, a; + + y = Y[0] << SCALEBITS; + cb = *Cb++ - 128; + cr = *Cr++ - 128; + add_r = FIX(1.40200) * cr + ONE_HALF; + add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; + add_b = FIX(1.77200) * cb + ONE_HALF; + + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + a = 255; + *p++ = a; + + Y++; + } + + p += offset_to_next_row; + } + +#undef SCALEBITS +#undef ONE_HALF +#undef FIX + +} + + +/* + * YCrCb -> BGRA32 (2x1) + * .-------. + * | 1 | 2 | + * `-------' + */ +static void YCrCB_to_BGRA32_2x1(struct jdec_private *priv, int sx, int sy) +{ + const unsigned char *Y, *Cb, *Cr; + unsigned char *p; + int i,j; + int offset_to_next_row; + +#define SCALEBITS 10 +#define ONE_HALF (1UL << (SCALEBITS-1)) +#define FIX(x) ((int)((x) * (1UL<<SCALEBITS) + 0.5)) + + p = priv->plane[0]; + Y = priv->Y; + Cb = priv->Cb; + Cr = priv->Cr; + offset_to_next_row = priv->bytes_per_row[0] - 16*4; + for (i = sy; i > 0; i--) { + for (j = sx; j > 0; j -= 2) { + int y, cb, cr; + int add_r, add_g, add_b; + int r, g , b, a; + + cb = *Cb++ - 128; + cr = *Cr++ - 128; + add_r = FIX(1.40200) * cr + ONE_HALF; + add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; + add_b = FIX(1.77200) * cb + ONE_HALF; + + y = Y[0] << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + a = 255; + *p++ = a; + + if (j > 1) { + y = Y[1] << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + a = 255; + *p++ = a; + } + + Y += 2; + } + + p += offset_to_next_row; + } + +#undef SCALEBITS +#undef ONE_HALF +#undef FIX + +} + +/* + * YCrCb -> BGRA32 (1x2) + * .---. + * | 1 | + * |---| + * | 2 | + * `---' + */ +static void YCrCB_to_BGRA32_1x2(struct jdec_private *priv, int sx, int sy) +{ + const unsigned char *Y, *Cb, *Cr; + unsigned char *p, *p2; + int i,j; + int offset_to_next_row; + +#define SCALEBITS 10 +#define ONE_HALF (1UL << (SCALEBITS-1)) +#define FIX(x) ((int)((x) * (1UL<<SCALEBITS) + 0.5)) + + p = priv->plane[0]; + p2 = priv->plane[0] + priv->bytes_per_row[0]; + Y = priv->Y; + Cb = priv->Cb; + Cr = priv->Cr; + offset_to_next_row = 2*priv->bytes_per_row[0] - 8*4; + for (i = sy; i > 0; i -= 2) { + for (j = sx; j > 0; j--) { + + int y, cb, cr; + int add_r, add_g, add_b; + int r, g , b, a; + + cb = *Cb++ - 128; + cr = *Cr++ - 128; + add_r = FIX(1.40200) * cr + ONE_HALF; + add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; + add_b = FIX(1.77200) * cb + ONE_HALF; + + y = Y[0] << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + a = 255; + *p++ = a; + + if (i > 1) { + y = Y[8] << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + a = 255; + *p2++ = a; + } + + Y++; + } + Y += 8; + p += offset_to_next_row; + p2 += offset_to_next_row; + } + +#undef SCALEBITS +#undef ONE_HALF +#undef FIX + +} + + +/* + * YCrCb -> BGRA32 (2x2) + * .-------. + * | 1 | 2 | + * |---+---| + * | 3 | 4 | + * `-------' + */ +static void YCrCB_to_BGRA32_2x2(struct jdec_private *priv, int sx, int sy) +{ + const unsigned char *Y, *Cb, *Cr; + unsigned char *p, *p2; + int i,j; + int offset_to_next_row; + +#define SCALEBITS 10 +#define ONE_HALF (1UL << (SCALEBITS-1)) +#define FIX(x) ((int)((x) * (1UL<<SCALEBITS) + 0.5)) + + p = priv->plane[0]; + p2 = priv->plane[0] + priv->bytes_per_row[0]; + Y = priv->Y; + Cb = priv->Cb; + Cr = priv->Cr; + offset_to_next_row = 2*priv->bytes_per_row[0] - 16*4; + for (i = sy; i > 0; i -= 2) { + for (j = sx; j > 0; j -= 2) { + + int y, cb, cr; + int add_r, add_g, add_b; + int r, g , b, a; + + cb = *Cb++ - 128; + cr = *Cr++ - 128; + add_r = FIX(1.40200) * cr + ONE_HALF; + add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; + add_b = FIX(1.77200) * cb + ONE_HALF; + + y = Y[0] << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + a = 255; + *p++ = a; + + if (j > 1) { + y = Y[1] << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + a = 255; + *p++ = a; + } + + if (i > 1) { + y = Y[16+0] << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + a = 255; + *p2++ = a; + + if (j > 1) { + y = Y[16+1] << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + a = 255; + *p2++ = a; + } + } + + Y += 2; + } + Y += 16; + p += offset_to_next_row; + p2 += offset_to_next_row; + } + +#undef SCALEBITS +#undef ONE_HALF +#undef FIX + +} + +static int initialize_bgra32(struct jdec_private *priv, + unsigned int *bytes_per_blocklines, + unsigned int *bytes_per_mcu) +{ + if (!priv->bytes_per_row[0]) + priv->bytes_per_row[0] = priv->width * 4; + if (!priv->components[0]) + priv->components[0] = malloc(priv->height * priv->bytes_per_row[0]); + + bytes_per_blocklines[0] = priv->bytes_per_row[0] << 3; + bytes_per_mcu[0] = 4*8; + + return !priv->components[0]; +} + +static const struct tinyjpeg_colorspace format_bgra32 = + { + { + YCrCB_to_BGRA32_1x1, + YCrCB_to_BGRA32_1x2, + YCrCB_to_BGRA32_2x1, + YCrCB_to_BGRA32_2x2, + }, + tinyjpeg_decode_mcu_3comp_table, + initialize_bgra32 + }; + +const tinyjpeg_colorspace_t TINYJPEG_FMT_BGRA32 = &format_bgra32; diff --git a/contrib/syslinux-4.02/com32/lib/jpeg/decode1.c b/contrib/syslinux-4.02/com32/lib/jpeg/decode1.c new file mode 100644 index 0000000..554f7f1 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/jpeg/decode1.c @@ -0,0 +1,138 @@ +/* + * Small jpeg decoder library + * + * Copyright (c) 2006, Luc Saillard <luc@saillard.org> + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - 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. + * + * - Neither the name of the author nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> + +#include "tinyjpeg.h" +#include "tinyjpeg-internal.h" + +/* + * Decode a 1x1 directly in 1 color + */ +static void decode_MCU_1x1_1plane(struct jdec_private *priv) +{ + // Y + tinyjpeg_process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y, 8); + + // Cb + tinyjpeg_process_Huffman_data_unit(priv, cCb); + IDCT(&priv->component_infos[cCb], priv->Cb, 8); + + // Cr + tinyjpeg_process_Huffman_data_unit(priv, cCr); + IDCT(&priv->component_infos[cCr], priv->Cr, 8); +} + + +/* + * Decode a 2x1 + * .-------. + * | 1 | 2 | + * `-------' + */ +static void decode_MCU_2x1_1plane(struct jdec_private *priv) +{ + // Y + tinyjpeg_process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y, 16); + tinyjpeg_process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y+8, 16); + + // Cb + tinyjpeg_process_Huffman_data_unit(priv, cCb); + + // Cr + tinyjpeg_process_Huffman_data_unit(priv, cCr); +} + + +/* + * Decode a 2x2 directly in GREY format (8bits) + * .-------. + * | 1 | 2 | + * |---+---| + * | 3 | 4 | + * `-------' + */ +static void decode_MCU_2x2_1plane(struct jdec_private *priv) +{ + // Y + tinyjpeg_process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y, 16); + tinyjpeg_process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y+8, 16); + tinyjpeg_process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y+64*2, 16); + tinyjpeg_process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y+64*2+8, 16); + + // Cb + tinyjpeg_process_Huffman_data_unit(priv, cCb); + + // Cr + tinyjpeg_process_Huffman_data_unit(priv, cCr); +} + +/* + * Decode a 1x2 mcu + * .---. + * | 1 | + * |---| + * | 2 | + * `---' + */ +static void decode_MCU_1x2_1plane(struct jdec_private *priv) +{ + // Y + tinyjpeg_process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y, 8); + tinyjpeg_process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y+64, 8); + + // Cb + tinyjpeg_process_Huffman_data_unit(priv, cCb); + + // Cr + tinyjpeg_process_Huffman_data_unit(priv, cCr); +} + +const decode_MCU_fct tinyjpeg_decode_mcu_1comp_table[4] = { + decode_MCU_1x1_1plane, + decode_MCU_1x2_1plane, + decode_MCU_2x1_1plane, + decode_MCU_2x2_1plane, +}; diff --git a/contrib/syslinux-4.02/com32/lib/jpeg/decode3.c b/contrib/syslinux-4.02/com32/lib/jpeg/decode3.c new file mode 100644 index 0000000..2f79ec9 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/jpeg/decode3.c @@ -0,0 +1,142 @@ +/* + * Small jpeg decoder library + * + * Copyright (c) 2006, Luc Saillard <luc@saillard.org> + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - 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. + * + * - Neither the name of the author nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> + +#include "tinyjpeg.h" +#include "tinyjpeg-internal.h" + +/* + * Decode all the 3 components for 1x1 + */ +static void decode_MCU_1x1_3planes(struct jdec_private *priv) +{ + // Y + tinyjpeg_process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y, 8); + + // Cb + tinyjpeg_process_Huffman_data_unit(priv, cCb); + IDCT(&priv->component_infos[cCb], priv->Cb, 8); + + // Cr + tinyjpeg_process_Huffman_data_unit(priv, cCr); + IDCT(&priv->component_infos[cCr], priv->Cr, 8); +} + +/* + * Decode a 2x1 + * .-------. + * | 1 | 2 | + * `-------' + */ +static void decode_MCU_2x1_3planes(struct jdec_private *priv) +{ + // Y + tinyjpeg_process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y, 16); + tinyjpeg_process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y+8, 16); + + // Cb + tinyjpeg_process_Huffman_data_unit(priv, cCb); + IDCT(&priv->component_infos[cCb], priv->Cb, 8); + + // Cr + tinyjpeg_process_Huffman_data_unit(priv, cCr); + IDCT(&priv->component_infos[cCr], priv->Cr, 8); +} + +/* + * Decode a 2x2 + * .-------. + * | 1 | 2 | + * |---+---| + * | 3 | 4 | + * `-------' + */ +static void decode_MCU_2x2_3planes(struct jdec_private *priv) +{ + // Y + tinyjpeg_process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y, 16); + tinyjpeg_process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y+8, 16); + tinyjpeg_process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y+64*2, 16); + tinyjpeg_process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y+64*2+8, 16); + + // Cb + tinyjpeg_process_Huffman_data_unit(priv, cCb); + IDCT(&priv->component_infos[cCb], priv->Cb, 8); + + // Cr + tinyjpeg_process_Huffman_data_unit(priv, cCr); + IDCT(&priv->component_infos[cCr], priv->Cr, 8); +} + +/* + * Decode a 1x2 mcu + * .---. + * | 1 | + * |---| + * | 2 | + * `---' + */ +static void decode_MCU_1x2_3planes(struct jdec_private *priv) +{ + // Y + tinyjpeg_process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y, 8); + tinyjpeg_process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y+64, 8); + + // Cb + tinyjpeg_process_Huffman_data_unit(priv, cCb); + IDCT(&priv->component_infos[cCb], priv->Cb, 8); + + // Cr + tinyjpeg_process_Huffman_data_unit(priv, cCr); + IDCT(&priv->component_infos[cCr], priv->Cr, 8); +} + +const decode_MCU_fct tinyjpeg_decode_mcu_3comp_table[4] = { + decode_MCU_1x1_3planes, + decode_MCU_1x2_3planes, + decode_MCU_2x1_3planes, + decode_MCU_2x2_3planes, +}; diff --git a/contrib/syslinux-4.02/com32/lib/jpeg/grey.c b/contrib/syslinux-4.02/com32/lib/jpeg/grey.c new file mode 100644 index 0000000..6710ede --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/jpeg/grey.c @@ -0,0 +1,117 @@ +/* + * Small jpeg decoder library + * + * Copyright (c) 2006, Luc Saillard <luc@saillard.org> + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - 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. + * + * - Neither the name of the author nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> + +#include "tinyjpeg.h" +#include "tinyjpeg-internal.h" + +/** + * YCrCb -> Grey (1x1, 1x2) + * .---. + * | 1 | + * `---' + */ +static void YCrCB_to_Grey_1xN(struct jdec_private *priv, int sx, int sy) +{ + const unsigned char *y; + unsigned char *p; + unsigned int i; + int offset_to_next_row; + + p = priv->plane[0]; + y = priv->Y; + offset_to_next_row = priv->bytes_per_row[0]; + + for (i = sy; i > 0; i--) { + memcpy(p, y, sx); + y += 8; + p += offset_to_next_row; + } +} + +/** + * YCrCb -> Grey (2x1, 2x2) + * .-------. + * | 1 | 2 | + * `-------' + */ +static void YCrCB_to_Grey_2xN(struct jdec_private *priv, int sx, int sy) +{ + const unsigned char *y; + unsigned char *p; + unsigned int i; + int offset_to_next_row; + + p = priv->plane[0]; + y = priv->Y; + offset_to_next_row = priv->bytes_per_row[0]; + + for (i = sy; i > 0; i--) { + memcpy(p, y, sx); + y += 16; + p += offset_to_next_row; + } +} + +static int initialize_grey(struct jdec_private *priv, + unsigned int *bytes_per_blocklines, + unsigned int *bytes_per_mcu) +{ + if (!priv->bytes_per_row[0]) + priv->bytes_per_row[0] = priv->width; + if (!priv->components[0]) + priv->components[0] = malloc(priv->height * priv->bytes_per_row[0]); + + bytes_per_blocklines[0] = priv->bytes_per_row[0] << 3; + bytes_per_mcu[0] = 8; + + return !priv->components[0]; +} + +static const struct tinyjpeg_colorspace format_grey = + { + { + YCrCB_to_Grey_1xN, + YCrCB_to_Grey_1xN, + YCrCB_to_Grey_2xN, + YCrCB_to_Grey_2xN, + }, + tinyjpeg_decode_mcu_1comp_table, + initialize_grey + }; + +const tinyjpeg_colorspace_t TINYJPEG_FMT_GREY = &format_grey; diff --git a/contrib/syslinux-4.02/com32/lib/jpeg/jidctflt.c b/contrib/syslinux-4.02/com32/lib/jpeg/jidctflt.c new file mode 100644 index 0000000..6f0df77 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/jpeg/jidctflt.c @@ -0,0 +1,285 @@ +/* + * jidctflt.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * + * The authors make NO WARRANTY or representation, either express or implied, + * with respect to this software, its quality, accuracy, merchantability, or + * fitness for a particular purpose. This software is provided "AS IS", and you, + * its user, assume the entire risk as to its quality and accuracy. + * + * This software is copyright (C) 1991-1998, Thomas G. Lane. + * All Rights Reserved except as specified below. + * + * Permission is hereby granted to use, copy, modify, and distribute this + * software (or portions thereof) for any purpose, without fee, subject to these + * conditions: + * (1) If any part of the source code for this software is distributed, then this + * README file must be included, with this copyright and no-warranty notice + * unaltered; and any additions, deletions, or changes to the original files + * must be clearly indicated in accompanying documentation. + * (2) If only executable code is distributed, then the accompanying + * documentation must state that "this software is based in part on the work of + * the Independent JPEG Group". + * (3) Permission for use of this software is granted only if the user accepts + * full responsibility for any undesirable consequences; the authors accept + * NO LIABILITY for damages of any kind. + * + * These conditions apply to any software derived from or based on the IJG code, + * not just to the unmodified library. If you use our work, you ought to + * acknowledge us. + * + * Permission is NOT granted for the use of any IJG author's name or company name + * in advertising or publicity relating to this software or products derived from + * it. This software may be referred to only as "the Independent JPEG Group's + * software". + * + * We specifically permit and encourage the use of this software as the basis of + * commercial products, provided that all warranty or liability claims are + * assumed by the product vendor. + * + * + * This file contains a floating-point implementation of the + * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + * must also perform dequantization of the input coefficients. + * + * This implementation should be more accurate than either of the integer + * IDCT implementations. However, it may not give the same results on all + * machines because of differences in roundoff behavior. Speed will depend + * on the hardware's floating point capacity. + * + * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + * on each row (or vice versa, but it's more convenient to emit a row at + * a time). Direct algorithms are also available, but they are much more + * complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with a fixed-point + * implementation, accuracy is lost due to imprecise representation of the + * scaled quantization values. However, that problem does not arise if + * we use floating point arithmetic. + */ + +#include <stdint.h> +#include "tinyjpeg-internal.h" + +#define FAST_FLOAT float +#define DCTSIZE 8 +#define DCTSIZE2 (DCTSIZE*DCTSIZE) + +#define DEQUANTIZE(coef,quantval) (((FAST_FLOAT) (coef)) * (quantval)) + +#if 1 && defined(__GNUC__) && (defined(__i686__) || defined(__x86_64__)) + +static inline unsigned char descale_and_clamp(int x, int shift) +{ + __asm__ ( + "add %3,%1\n" + "\tsar %2,%1\n" + "\tsub $-128,%1\n" + "\tcmovl %5,%1\n" /* Use the sub to compare to 0 */ + "\tcmpl %4,%1\n" + "\tcmovg %4,%1\n" + : "=r"(x) + : "0"(x), "Ir"(shift), "ir"(1UL<<(shift-1)), "r" (0xff), "r" (0) + ); + return x; +} + +#else +static inline unsigned char descale_and_clamp(int x, int shift) +{ + x += (1UL<<(shift-1)); + if (x<0) + x = (x >> shift) | ((~(0UL)) << (32-(shift))); + else + x >>= shift; + x += 128; + if (x>255) + return 255; + else if (x<0) + return 0; + else + return x; +} +#endif + +/* + * Perform dequantization and inverse DCT on one block of coefficients. + */ + +void +tinyjpeg_idct_float (struct component *compptr, uint8_t *output_buf, int stride) +{ + FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + FAST_FLOAT tmp10, tmp11, tmp12, tmp13; + FAST_FLOAT z5, z10, z11, z12, z13; + int16_t *inptr; + FAST_FLOAT *quantptr; + FAST_FLOAT *wsptr; + uint8_t *outptr; + int ctr; + FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */ + + /* Pass 1: process columns from input, store into work array. */ + + inptr = compptr->DCT; + quantptr = compptr->Q_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp10 = tmp0 + tmp2; /* phase 3 */ + tmp11 = tmp0 - tmp2; + + tmp13 = tmp1 + tmp3; /* phases 5-3 */ + tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */ + + tmp0 = tmp10 + tmp13; /* phase 2 */ + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + z13 = tmp6 + tmp5; /* phase 6 */ + z10 = tmp6 - tmp5; + z11 = tmp4 + tmp7; + z12 = tmp4 - tmp7; + + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */ + + z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ + tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ + tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + wsptr[DCTSIZE*0] = tmp0 + tmp7; + wsptr[DCTSIZE*7] = tmp0 - tmp7; + wsptr[DCTSIZE*1] = tmp1 + tmp6; + wsptr[DCTSIZE*6] = tmp1 - tmp6; + wsptr[DCTSIZE*2] = tmp2 + tmp5; + wsptr[DCTSIZE*5] = tmp2 - tmp5; + wsptr[DCTSIZE*4] = tmp3 + tmp4; + wsptr[DCTSIZE*3] = tmp3 - tmp4; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3. */ + + wsptr = workspace; + outptr = output_buf; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + /* Rows of zeroes can be exploited in the same way as we did with columns. + * However, the column calculation has created many nonzero AC terms, so + * the simplification applies less often (typically 5% to 10% of the time). + * And testing floats for zero is relatively expensive, so we don't bother. + */ + + /* Even part */ + + tmp10 = wsptr[0] + wsptr[4]; + tmp11 = wsptr[0] - wsptr[4]; + + tmp13 = wsptr[2] + wsptr[6]; + tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13; + + tmp0 = tmp10 + tmp13; + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + z13 = wsptr[5] + wsptr[3]; + z10 = wsptr[5] - wsptr[3]; + z11 = wsptr[1] + wsptr[7]; + z12 = wsptr[1] - wsptr[7]; + + tmp7 = z11 + z13; + tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); + + z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ + tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ + tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + /* Final output stage: scale down by a factor of 8 and range-limit */ + + outptr[0] = descale_and_clamp((int)(tmp0 + tmp7), 3); + outptr[7] = descale_and_clamp((int)(tmp0 - tmp7), 3); + outptr[1] = descale_and_clamp((int)(tmp1 + tmp6), 3); + outptr[6] = descale_and_clamp((int)(tmp1 - tmp6), 3); + outptr[2] = descale_and_clamp((int)(tmp2 + tmp5), 3); + outptr[5] = descale_and_clamp((int)(tmp2 - tmp5), 3); + outptr[4] = descale_and_clamp((int)(tmp3 + tmp4), 3); + outptr[3] = descale_and_clamp((int)(tmp3 - tmp4), 3); + + + wsptr += DCTSIZE; /* advance pointer to next row */ + outptr += stride; + } +} diff --git a/contrib/syslinux-4.02/com32/lib/jpeg/rgb24.c b/contrib/syslinux-4.02/com32/lib/jpeg/rgb24.c new file mode 100644 index 0000000..e1481f3 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/jpeg/rgb24.c @@ -0,0 +1,372 @@ +/* + * Small jpeg decoder library + * + * Copyright (c) 2006, Luc Saillard <luc@saillard.org> + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - 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. + * + * - Neither the name of the author nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> + +#include "tinyjpeg.h" +#include "tinyjpeg-internal.h" + +/******************************************************************************* + * + * Colorspace conversion routine + * + * + * Note: + * YCbCr is defined per CCIR 601-1, except that Cb and Cr are + * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * The conversion equations to be implemented are therefore + * R = Y + 1.40200 * Cr + * G = Y - 0.34414 * Cb - 0.71414 * Cr + * B = Y + 1.77200 * Cb + * + ******************************************************************************/ +static unsigned char clamp(int i) +{ + if (i<0) + return 0; + else if (i>255) + return 255; + else + return i; +} + +/** + * YCrCb -> RGB24 (1x1) + * .---. + * | 1 | + * `---' + */ +static void YCrCB_to_RGB24_1x1(struct jdec_private *priv, int sx, int sy) +{ + const unsigned char *Y, *Cb, *Cr; + unsigned char *p; + int i,j; + int offset_to_next_row; + +#define SCALEBITS 10 +#define ONE_HALF (1UL << (SCALEBITS-1)) +#define FIX(x) ((int)((x) * (1UL<<SCALEBITS) + 0.5)) + + p = priv->plane[0]; + Y = priv->Y; + Cb = priv->Cb; + Cr = priv->Cr; + offset_to_next_row = priv->bytes_per_row[0] - 8*3; + for (i = sy; i > 0; i--) { + for (j = sx; j > 0; j++) { + int y, cb, cr; + int add_r, add_g, add_b; + int r, g , b; + + y = Y[0] << SCALEBITS; + cb = *Cb++ - 128; + cr = *Cr++ - 128; + add_r = FIX(1.40200) * cr + ONE_HALF; + add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; + add_b = FIX(1.77200) * cb + ONE_HALF; + + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + + Y++; + } + + p += offset_to_next_row; + } + +#undef SCALEBITS +#undef ONE_HALF +#undef FIX + +} + +/** + * YCrCb -> RGB24 (2x1) + * .-------. + * | 1 | 2 | + * `-------' + */ +static void YCrCB_to_RGB24_2x1(struct jdec_private *priv, int sx, int sy) +{ + const unsigned char *Y, *Cb, *Cr; + unsigned char *p; + int i,j; + int offset_to_next_row; + +#define SCALEBITS 10 +#define ONE_HALF (1UL << (SCALEBITS-1)) +#define FIX(x) ((int)((x) * (1UL<<SCALEBITS) + 0.5)) + + p = priv->plane[0]; + Y = priv->Y; + Cb = priv->Cb; + Cr = priv->Cr; + offset_to_next_row = priv->bytes_per_row[0] - 16*3; + for (i = sy; i > 0; i--) { + + for (j = sx; j > 0; j -= 2) { + + int y, cb, cr; + int add_r, add_g, add_b; + int r, g , b; + + y = Y[0] << SCALEBITS; + cb = *Cb++ - 128; + cr = *Cr++ - 128; + add_r = FIX(1.40200) * cr + ONE_HALF; + add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; + add_b = FIX(1.77200) * cb + ONE_HALF; + + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + + if (j > 1) { + y = Y[1] << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + } + + Y += 2; + } + + p += offset_to_next_row; + } + +#undef SCALEBITS +#undef ONE_HALF +#undef FIX + +} + + +/** + * YCrCb -> RGB24 (1x2) + * .---. + * | 1 | + * |---| + * | 2 | + * `---' + */ +static void YCrCB_to_RGB24_1x2(struct jdec_private *priv, int sx, int sy) +{ + const unsigned char *Y, *Cb, *Cr; + unsigned char *p, *p2; + int i,j; + int offset_to_next_row; + +#define SCALEBITS 10 +#define ONE_HALF (1UL << (SCALEBITS-1)) +#define FIX(x) ((int)((x) * (1UL<<SCALEBITS) + 0.5)) + + p = priv->plane[0]; + p2 = priv->plane[0] + priv->bytes_per_row[0]; + Y = priv->Y; + Cb = priv->Cb; + Cr = priv->Cr; + offset_to_next_row = 2*priv->bytes_per_row[0] - 8*3; + for (i = sy; i > 0; i -= 2) { + for (j = sx; j > 0; j--) { + + int y, cb, cr; + int add_r, add_g, add_b; + int r, g , b; + + cb = *Cb++ - 128; + cr = *Cr++ - 128; + add_r = FIX(1.40200) * cr + ONE_HALF; + add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; + add_b = FIX(1.77200) * cb + ONE_HALF; + + y = Y[0] << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + + if (i > 1) { + y = Y[8] << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + } + + Y++; + } + Y += 8; + p += offset_to_next_row; + p2 += offset_to_next_row; + } + +#undef SCALEBITS +#undef ONE_HALF +#undef FIX + +} + +/** + * YCrCb -> RGB24 (2x2) + * .-------. + * | 1 | 2 | + * |---+---| + * | 3 | 4 | + * `-------' + */ +static void YCrCB_to_RGB24_2x2(struct jdec_private *priv, int sx, int sy) +{ + const unsigned char *Y, *Cb, *Cr; + unsigned char *p, *p2; + int i,j; + int offset_to_next_row; + +#define SCALEBITS 10 +#define ONE_HALF (1UL << (SCALEBITS-1)) +#define FIX(x) ((int)((x) * (1UL<<SCALEBITS) + 0.5)) + + p = priv->plane[0]; + p2 = priv->plane[0] + priv->bytes_per_row[0]; + Y = priv->Y; + Cb = priv->Cb; + Cr = priv->Cr; + offset_to_next_row = 2*priv->bytes_per_row[0] - 16*3; + for (i = sy; i > 0; i -= 2) { + for (j = sx; j > 0; j -= 2) { + + int y, cb, cr; + int add_r, add_g, add_b; + int r, g , b; + + cb = *Cb++ - 128; + cr = *Cr++ - 128; + add_r = FIX(1.40200) * cr + ONE_HALF; + add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; + add_b = FIX(1.77200) * cb + ONE_HALF; + + y = Y[0] << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + + if (j > 1) { + y = Y[1] << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + } + + if (i > 1) { + y = Y[16+0] << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + + if (j > 1) { + y = Y[16+1] << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + } + } + + Y += 2; + } + Y += 16; + p += offset_to_next_row; + p2 += offset_to_next_row; + } + +#undef SCALEBITS +#undef ONE_HALF +#undef FIX + +} + +static int initialize_rgb24(struct jdec_private *priv, + unsigned int *bytes_per_blocklines, + unsigned int *bytes_per_mcu) +{ + if (!priv->bytes_per_row[0]) + priv->bytes_per_row[0] = priv->width * 3; + if (priv->components[0] == NULL) + priv->components[0] = malloc(priv->height * priv->bytes_per_row[0]); + + bytes_per_blocklines[0] = priv->bytes_per_row[0] << 3; + bytes_per_mcu[0] = 3*8; + + return !priv->components[0]; +} + +static const struct tinyjpeg_colorspace format_rgb24 = + { + { + YCrCB_to_RGB24_1x1, + YCrCB_to_RGB24_1x2, + YCrCB_to_RGB24_2x1, + YCrCB_to_RGB24_2x2, + }, + tinyjpeg_decode_mcu_3comp_table, + initialize_rgb24 + }; + +const tinyjpeg_colorspace_t TINYJPEG_FMT_RGB24 = &format_rgb24; diff --git a/contrib/syslinux-4.02/com32/lib/jpeg/rgba32.c b/contrib/syslinux-4.02/com32/lib/jpeg/rgba32.c new file mode 100644 index 0000000..d04f0f1 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/jpeg/rgba32.c @@ -0,0 +1,390 @@ +/* + * Small jpeg decoder library + * + * Copyright (c) 2006, Luc Saillard <luc@saillard.org> + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - 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. + * + * - Neither the name of the author nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> + +#include "tinyjpeg.h" +#include "tinyjpeg-internal.h" + +/******************************************************************************* + * + * Colorspace conversion routine + * + * + * Note: + * YCbCr is defined per CCIR 601-1, except that Cb and Cr are + * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * The conversion equations to be implemented are therefore + * R = Y + 1.40200 * Cr + * G = Y - 0.34414 * Cb - 0.71414 * Cr + * B = Y + 1.77200 * Cb + * + ******************************************************************************/ +static unsigned char clamp(int i) +{ + if (i<0) + return 0; + else if (i>255) + return 255; + else + return i; +} + +/** + * YCrCb -> RGBA32 (1x1) + * .---. + * | 1 | + * `---' + */ +static void YCrCB_to_RGBA32_1x1(struct jdec_private *priv, int sx, int sy) +{ + const unsigned char *Y, *Cb, *Cr; + unsigned char *p; + int i,j; + int offset_to_next_row; + +#define SCALEBITS 10 +#define ONE_HALF (1UL << (SCALEBITS-1)) +#define FIX(x) ((int)((x) * (1UL<<SCALEBITS) + 0.5)) + + p = priv->plane[0]; + Y = priv->Y; + Cb = priv->Cb; + Cr = priv->Cr; + offset_to_next_row = priv->bytes_per_row[0] - 8*4; + for (i = sy; i > 0; i--) { + for (j = sx; j > 0; j--) { + + int y, cb, cr; + int add_r, add_g, add_b; + int r, g , b, a; + + y = Y[0] << SCALEBITS; + cb = *Cb++ - 128; + cr = *Cr++ - 128; + add_r = FIX(1.40200) * cr + ONE_HALF; + add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; + add_b = FIX(1.77200) * cb + ONE_HALF; + + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + a = 255; + *p++ = a; + + Y++; + } + + p += offset_to_next_row; + } + +#undef SCALEBITS +#undef ONE_HALF +#undef FIX + +} + +/** + * YCrCb -> RGBA32 (2x1) + * .-------. + * | 1 | 2 | + * `-------' + */ +static void YCrCB_to_RGBA32_2x1(struct jdec_private *priv, int sx, int sy) +{ + const unsigned char *Y, *Cb, *Cr; + unsigned char *p; + int i,j; + int offset_to_next_row; + +#define SCALEBITS 10 +#define ONE_HALF (1UL << (SCALEBITS-1)) +#define FIX(x) ((int)((x) * (1UL<<SCALEBITS) + 0.5)) + + p = priv->plane[0]; + Y = priv->Y; + Cb = priv->Cb; + Cr = priv->Cr; + offset_to_next_row = priv->bytes_per_row[0] - 16*4; + for (i = sy; i > 0; i--) { + for (j = sx; j > 0; j -= 2) { + + int y, cb, cr; + int add_r, add_g, add_b; + int r, g , b, a; + + y = Y[0] << SCALEBITS; + cb = *Cb++ - 128; + cr = *Cr++ - 128; + add_r = FIX(1.40200) * cr + ONE_HALF; + add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; + add_b = FIX(1.77200) * cb + ONE_HALF; + + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + a = 255; + *p++ = a; + + if (j > 1) { + y = Y[1] << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + a = 255; + *p++ = a; + } + + Y += 2; + } + + p += offset_to_next_row; + } + +#undef SCALEBITS +#undef ONE_HALF +#undef FIX + +} + + +/** + * YCrCb -> RGBA32 (1x2) + * .---. + * | 1 | + * |---| + * | 2 | + * `---' + */ +static void YCrCB_to_RGBA32_1x2(struct jdec_private *priv, int sx, int sy) +{ + const unsigned char *Y, *Cb, *Cr; + unsigned char *p, *p2; + int i,j; + int offset_to_next_row; + +#define SCALEBITS 10 +#define ONE_HALF (1UL << (SCALEBITS-1)) +#define FIX(x) ((int)((x) * (1UL<<SCALEBITS) + 0.5)) + + p = priv->plane[0]; + p2 = priv->plane[0] + priv->bytes_per_row[0]; + Y = priv->Y; + Cb = priv->Cb; + Cr = priv->Cr; + offset_to_next_row = 2*priv->bytes_per_row[0] - 8*4; + for (i = sy; i > 0; i -= 2) { + for (j = sx; j > 0; j--) { + + int y, cb, cr; + int add_r, add_g, add_b; + int r, g , b, a; + + cb = *Cb++ - 128; + cr = *Cr++ - 128; + add_r = FIX(1.40200) * cr + ONE_HALF; + add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; + add_b = FIX(1.77200) * cb + ONE_HALF; + + y = Y[0] << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + a = 255; + *p++ = a; + + if (i > 1) { + y = Y[8] << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + a = 255; + *p2++ = a; + } + + Y++; + } + Y += 8; + p += offset_to_next_row; + p2 += offset_to_next_row; + } + +#undef SCALEBITS +#undef ONE_HALF +#undef FIX + +} + +/** + * YCrCb -> RGBA32 (2x2) + * .-------. + * | 1 | 2 | + * |---+---| + * | 3 | 4 | + * `-------' + */ +static void YCrCB_to_RGBA32_2x2(struct jdec_private *priv, int sx, int sy) +{ + const unsigned char *Y, *Cb, *Cr; + unsigned char *p, *p2; + int i,j; + int offset_to_next_row; + +#define SCALEBITS 10 +#define ONE_HALF (1UL << (SCALEBITS-1)) +#define FIX(x) ((int)((x) * (1UL<<SCALEBITS) + 0.5)) + + p = priv->plane[0]; + p2 = priv->plane[0] + priv->bytes_per_row[0]; + Y = priv->Y; + Cb = priv->Cb; + Cr = priv->Cr; + offset_to_next_row = 2*priv->bytes_per_row[0] - 16*4; + for (i = sy; i > 0; i -= 2) { + for (j = sx; i > 0; j -= 2) { + + int y, cb, cr; + int add_r, add_g, add_b; + int r, g , b, a; + + cb = *Cb++ - 128; + cr = *Cr++ - 128; + add_r = FIX(1.40200) * cr + ONE_HALF; + add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; + add_b = FIX(1.77200) * cb + ONE_HALF; + + y = Y[0] << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + a = 255; + *p++ = a; + + if (j > 1) { + y = Y[1] << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + a = 255; + *p++ = a; + } + + if (i > 1) { + y = Y[16+0] << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + a = 255; + *p2++ = a; + + if (j > 1) { + y = Y[16+1] << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + a = 255; + *p2++ = a; + } + } + + Y += 2; + } + Y += 16; + p += offset_to_next_row; + p2 += offset_to_next_row; + } + +#undef SCALEBITS +#undef ONE_HALF +#undef FIX + +} + +static int initialize_rgba32(struct jdec_private *priv, + unsigned int *bytes_per_blocklines, + unsigned int *bytes_per_mcu) +{ + if (!priv->bytes_per_row[0]) + priv->bytes_per_row[0] = priv->width * 4; + if (!priv->components[0]) + priv->components[0] = malloc(priv->height * priv->bytes_per_row[0]); + + bytes_per_blocklines[0] = priv->bytes_per_row[0] << 3; + bytes_per_mcu[0] = 4*8; + + return !priv->components[0]; +} + +static const struct tinyjpeg_colorspace format_rgba32 = + { + { + YCrCB_to_RGBA32_1x1, + YCrCB_to_RGBA32_1x2, + YCrCB_to_RGBA32_2x1, + YCrCB_to_RGBA32_2x2, + }, + tinyjpeg_decode_mcu_3comp_table, + initialize_rgba32 + }; + +const tinyjpeg_colorspace_t TINYJPEG_FMT_RGBA32 = &format_rgba32; diff --git a/contrib/syslinux-4.02/com32/lib/jpeg/tinyjpeg-internal.h b/contrib/syslinux-4.02/com32/lib/jpeg/tinyjpeg-internal.h new file mode 100644 index 0000000..bb5c670 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/jpeg/tinyjpeg-internal.h @@ -0,0 +1,213 @@ +/* + * Small jpeg decoder library (Internal header) + * + * Copyright (c) 2006, Luc Saillard <luc@saillard.org> + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - 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. + * + * - Neither the name of the author nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + * + */ + + +#ifndef __TINYJPEG_INTERNAL_H_ +#define __TINYJPEG_INTERNAL_H_ + +#include <setjmp.h> + +#define SANITY_CHECK 1 + +struct jdec_private; + +#define HUFFMAN_BITS_SIZE 256 +#define HUFFMAN_HASH_NBITS 9 +#define HUFFMAN_HASH_SIZE (1UL<<HUFFMAN_HASH_NBITS) +#define HUFFMAN_HASH_MASK (HUFFMAN_HASH_SIZE-1) + +#define HUFFMAN_TABLES 4 +#define COMPONENTS 3 +#define JPEG_MAX_WIDTH 4096 +#define JPEG_MAX_HEIGHT 4096 + +struct huffman_table +{ + /* Fast look up table, using HUFFMAN_HASH_NBITS bits we can have directly the symbol, + * if the symbol is <0, then we need to look into the tree table */ + short int lookup[HUFFMAN_HASH_SIZE]; + /* code size: give the number of bits of a symbol is encoded */ + unsigned char code_size[HUFFMAN_HASH_SIZE]; + /* some place to store value that is not encoded in the lookup table + * FIXME: Calculate if 256 value is enough to store all values + */ + uint16_t slowtable[16-HUFFMAN_HASH_NBITS][256]; +}; + +struct component +{ + unsigned int Hfactor; + unsigned int Vfactor; + float *Q_table; /* Pointer to the quantisation table to use */ + struct huffman_table *AC_table; + struct huffman_table *DC_table; + short int previous_DC; /* Previous DC coefficient */ + short int DCT[64]; /* DCT coef */ +#if SANITY_CHECK + unsigned int cid; +#endif +}; + + +typedef void (*decode_MCU_fct) (struct jdec_private *priv); +typedef void (*convert_colorspace_fct) (struct jdec_private *priv, int, int); + +struct jdec_private +{ + /* Public variables */ + uint8_t *components[COMPONENTS]; + unsigned int bytes_per_row[COMPONENTS]; + unsigned int width, height; /* Size of the image */ + unsigned int flags; + + /* Private variables */ + const unsigned char *stream_begin, *stream_end; + unsigned int stream_length; + + const unsigned char *stream; /* Pointer to the current stream */ + unsigned int reservoir, nbits_in_reservoir; + + struct component component_infos[COMPONENTS]; + float Q_tables[COMPONENTS][64]; /* quantization tables */ + struct huffman_table HTDC[HUFFMAN_TABLES]; /* DC huffman tables */ + struct huffman_table HTAC[HUFFMAN_TABLES]; /* AC huffman tables */ + int default_huffman_table_initialized; + int restart_interval; + int restarts_to_go; /* MCUs left in this restart interval */ + int last_rst_marker_seen; /* Rst marker is incremented each time */ + + /* Temp space used after the IDCT to store each components */ + uint8_t Y[64*4], Cr[64], Cb[64]; + + jmp_buf jump_state; + /* Internal Pointer use for colorspace conversion, do not modify it !!! */ + uint8_t *plane[COMPONENTS]; + +}; + +#define IDCT tinyjpeg_idct_float +void tinyjpeg_idct_float (struct component *compptr, uint8_t *output_buf, int stride); + +struct tinyjpeg_colorspace { + convert_colorspace_fct convert_colorspace[4]; + const decode_MCU_fct *decode_mcu_table; + int (*initialize)(struct jdec_private *, unsigned int *, unsigned int *); +}; + +void tinyjpeg_process_Huffman_data_unit(struct jdec_private *priv, int component); + +extern const decode_MCU_fct tinyjpeg_decode_mcu_3comp_table[4]; +extern const decode_MCU_fct tinyjpeg_decode_mcu_1comp_table[4]; + +enum std_markers { + DQT = 0xDB, /* Define Quantization Table */ + SOF = 0xC0, /* Start of Frame (size information) */ + DHT = 0xC4, /* Huffman Table */ + SOI = 0xD8, /* Start of Image */ + SOS = 0xDA, /* Start of Scan */ + RST = 0xD0, /* Reset Marker d0 -> .. */ + RST7 = 0xD7, /* Reset Marker .. -> d7 */ + EOI = 0xD9, /* End of Image */ + DRI = 0xDD, /* Define Restart Interval */ + APP0 = 0xE0, +}; + +#define cY 0 +#define cCb 1 +#define cCr 2 + +#define BLACK_Y 0 +#define BLACK_U 127 +#define BLACK_V 127 + +#define SANITY_CHECK 1 + +#if DEBUG +#define error(fmt, args...) do { \ + snprintf(error_string, sizeof(error_string), fmt, ## args); \ + return -1; \ +} while(0) + +#define trace(fmt, args...) do { \ + fprintf(stderr, fmt, ## args); \ + fflush(stderr); \ +} while(0) +#else +#define error(fmt, args...) do { return -1; } while(0) +#define trace(fmt, args...) do { } while (0) +#endif + +#ifndef __likely +# define __likely(x) (!!(x)) +#endif +#ifndef __unlikely +# define __unlikely(x) (!!(x)) +#endif + +#define min(x, y) ((x) < (y) ? (x) : (y)) +#define max(x, y) ((x) > (y) ? (x) : (y)) + +#if 0 +static char *print_bits(unsigned int value, char *bitstr) +{ + int i, j; + i=31; + while (i>0) + { + if (value & (1UL<<i)) + break; + i--; + } + j=0; + while (i>=0) + { + bitstr[j++] = (value & (1UL<<i))?'1':'0'; + i--; + } + bitstr[j] = 0; + return bitstr; +} + +static void print_next_16bytes(int offset, const unsigned char *stream) +{ + trace("%4.4x: %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", + offset, + stream[0], stream[1], stream[2], stream[3], + stream[4], stream[5], stream[6], stream[7], + stream[8], stream[9], stream[10], stream[11], + stream[12], stream[13], stream[14], stream[15]); +} + +#endif + +#endif diff --git a/contrib/syslinux-4.02/com32/lib/jpeg/tinyjpeg.c b/contrib/syslinux-4.02/com32/lib/jpeg/tinyjpeg.c new file mode 100644 index 0000000..3c6070f --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/jpeg/tinyjpeg.c @@ -0,0 +1,1039 @@ +/* + * Small jpeg decoder library + * + * Copyright (c) 2006, Luc Saillard <luc@saillard.org> + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - 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. + * + * - Neither the name of the author nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <errno.h> + +#include "tinyjpeg.h" +#include "tinyjpeg-internal.h" + +/* Global variable to return the last error found while deconding */ +static char error_string[256]; + +static const unsigned char zigzag[64] = +{ + 0, 1, 5, 6, 14, 15, 27, 28, + 2, 4, 7, 13, 16, 26, 29, 42, + 3, 8, 12, 17, 25, 30, 41, 43, + 9, 11, 18, 24, 31, 40, 44, 53, + 10, 19, 23, 32, 39, 45, 52, 54, + 20, 22, 33, 38, 46, 51, 55, 60, + 21, 34, 37, 47, 50, 56, 59, 61, + 35, 36, 48, 49, 57, 58, 62, 63 +}; + +/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */ +/* IMPORTANT: these are only valid for 8-bit data precision! */ +static const unsigned char bits_dc_luminance[17] = +{ + 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 +}; +static const unsigned char val_dc_luminance[] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 +}; + +static const unsigned char bits_dc_chrominance[17] = +{ + 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 +}; +static const unsigned char val_dc_chrominance[] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 +}; + +static const unsigned char bits_ac_luminance[17] = +{ + 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d +}; +static const unsigned char val_ac_luminance[] = +{ + 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, + 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, + 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, + 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa +}; + +static const unsigned char bits_ac_chrominance[17] = +{ + 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 +}; + +static const unsigned char val_ac_chrominance[] = +{ + 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, + 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, + 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, + 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, + 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, + 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, + 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, + 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, + 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, + 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa +}; + + +/* + * 4 functions to manage the stream + * + * fill_nbits: put at least nbits in the reservoir of bits. + * But convert any 0xff,0x00 into 0xff + * get_nbits: read nbits from the stream, and put it in result, + * bits is removed from the stream and the reservoir is filled + * automaticaly. The result is signed according to the number of + * bits. + * look_nbits: read nbits from the stream without marking as read. + * skip_nbits: read nbits from the stream but do not return the result. + * + * stream: current pointer in the jpeg data (read bytes per bytes) + * nbits_in_reservoir: number of bits filled into the reservoir + * reservoir: register that contains bits information. Only nbits_in_reservoir + * is valid. + * nbits_in_reservoir + * <-- 17 bits --> + * Ex: 0000 0000 1010 0000 1111 0000 <== reservoir + * ^ + * bit 1 + * To get two bits from this example + * result = (reservoir >> 15) & 3 + * + */ +#define fill_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted) do { \ + while (nbits_in_reservoir<nbits_wanted) \ + { \ + unsigned char c; \ + if (stream >= priv->stream_end) \ + longjmp(priv->jump_state, -EIO); \ + c = *stream++; \ + reservoir <<= 8; \ + if (c == 0xff && *stream == 0x00) \ + stream++; \ + reservoir |= c; \ + nbits_in_reservoir+=8; \ + } \ +} while(0); + +/* Signed version !!!! */ +#define get_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted,result) do { \ + fill_nbits(reservoir,nbits_in_reservoir,stream,(nbits_wanted)); \ + result = ((reservoir)>>(nbits_in_reservoir-(nbits_wanted))); \ + nbits_in_reservoir -= (nbits_wanted); \ + reservoir &= ((1U<<nbits_in_reservoir)-1); \ + if ((unsigned int)result < (1UL<<((nbits_wanted)-1))) \ + result += (0xFFFFFFFFUL<<(nbits_wanted))+1; \ +} while(0); + +#define look_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted,result) do { \ + fill_nbits(reservoir,nbits_in_reservoir,stream,(nbits_wanted)); \ + result = ((reservoir)>>(nbits_in_reservoir-(nbits_wanted))); \ +} while(0); + +/* To speed up the decoding, we assume that the reservoir have enough bit + * slow version: + * #define skip_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted) do { \ + * fill_nbits(reservoir,nbits_in_reservoir,stream,(nbits_wanted)); \ + * nbits_in_reservoir -= (nbits_wanted); \ + * reservoir &= ((1U<<nbits_in_reservoir)-1); \ + * } while(0); + */ +#define skip_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted) do { \ + nbits_in_reservoir -= (nbits_wanted); \ + reservoir &= ((1U<<nbits_in_reservoir)-1); \ +} while(0); + + +#define be16_to_cpu(x) (((x)[0]<<8)|(x)[1]) + +static void resync(struct jdec_private *priv); + +/** + * Get the next (valid) huffman code in the stream. + * + * To speedup the procedure, we look HUFFMAN_HASH_NBITS bits and the code is + * lower than HUFFMAN_HASH_NBITS we have automaticaly the length of the code + * and the value by using two lookup table. + * Else if the value is not found, just search (linear) into an array for each + * bits is the code is present. + * + * If the code is not present for any reason, -1 is return. + */ +static int get_next_huffman_code(struct jdec_private *priv, struct huffman_table *huffman_table) +{ + int value, hcode; + unsigned int extra_nbits, nbits; + uint16_t *slowtable; + + look_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, HUFFMAN_HASH_NBITS, hcode); + value = huffman_table->lookup[hcode]; + if (__likely(value >= 0)) + { + unsigned int code_size = huffman_table->code_size[value]; + skip_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, code_size); + return value; + } + + /* Decode more bits each time ... */ + for (extra_nbits=0; extra_nbits<16-HUFFMAN_HASH_NBITS; extra_nbits++) + { + nbits = HUFFMAN_HASH_NBITS + 1 + extra_nbits; + + look_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, nbits, hcode); + slowtable = huffman_table->slowtable[extra_nbits]; + /* Search if the code is in this array */ + while (slowtable[0]) { + if (slowtable[0] == hcode) { + skip_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, nbits); + return slowtable[1]; + } + slowtable+=2; + } + } + return 0; +} + + + + +/** + * + * Decode a single block that contains the DCT coefficients. + * The table coefficients is already dezigzaged at the end of the operation. + * + */ +void tinyjpeg_process_Huffman_data_unit(struct jdec_private *priv, int component) +{ + unsigned char j; + unsigned int huff_code; + unsigned char size_val, count_0; + + struct component *c = &priv->component_infos[component]; + short int DCT[64]; + + + /* Initialize the DCT coef table */ + memset(DCT, 0, sizeof(DCT)); + + /* DC coefficient decoding */ + huff_code = get_next_huffman_code(priv, c->DC_table); + //trace("+ %x\n", huff_code); + if (huff_code) { + get_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, huff_code, DCT[0]); + DCT[0] += c->previous_DC; + c->previous_DC = DCT[0]; + } else { + DCT[0] = c->previous_DC; + } + + /* AC coefficient decoding */ + j = 1; + while (j<64) + { + huff_code = get_next_huffman_code(priv, c->AC_table); + //trace("- %x\n", huff_code); + + size_val = huff_code & 0xF; + count_0 = huff_code >> 4; + + if (size_val == 0) + { /* RLE */ + if (count_0 == 0) + break; /* EOB found, go out */ + else if (count_0 == 0xF) + j += 16; /* skip 16 zeros */ + } + else + { + j += count_0; /* skip count_0 zeroes */ + if (__unlikely(j >= 64)) + { + snprintf(error_string, sizeof(error_string), "Bad huffman data (buffer overflow)"); + break; + } + get_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, size_val, DCT[j]); + j++; + } + } + + for (j = 0; j < 64; j++) + c->DCT[j] = DCT[zigzag[j]]; +} + +/* + * Takes two array of bits, and build the huffman table for size, and code + * + * lookup will return the symbol if the code is less or equal than HUFFMAN_HASH_NBITS. + * code_size will be used to known how many bits this symbol is encoded. + * slowtable will be used when the first lookup didn't give the result. + */ +static void build_huffman_table(const unsigned char *bits, const unsigned char *vals, struct huffman_table *table) +{ + unsigned int i, j, code, code_size, val, nbits; + unsigned char huffsize[HUFFMAN_BITS_SIZE+1], *hz; + unsigned int huffcode[HUFFMAN_BITS_SIZE+1], *hc; + int next_free_entry; + + /* + * Build a temp array + * huffsize[X] => numbers of bits to write vals[X] + */ + hz = huffsize; + for (i=1; i<=16; i++) + { + for (j=1; j<=bits[i]; j++) + *hz++ = i; + } + *hz = 0; + + memset(table->lookup, 0xff, sizeof(table->lookup)); + for (i=0; i<(16-HUFFMAN_HASH_NBITS); i++) + table->slowtable[i][0] = 0; + + /* Build a temp array + * huffcode[X] => code used to write vals[X] + */ + code = 0; + hc = huffcode; + hz = huffsize; + nbits = *hz; + while (*hz) + { + while (*hz == nbits) + { + *hc++ = code++; + hz++; + } + code <<= 1; + nbits++; + } + + /* + * Build the lookup table, and the slowtable if needed. + */ + next_free_entry = -1; + for (i=0; huffsize[i]; i++) + { + val = vals[i]; + code = huffcode[i]; + code_size = huffsize[i]; + + trace("val=%2.2x code=%8.8x codesize=%2.2d\n", val, code, code_size); + + table->code_size[val] = code_size; + if (code_size <= HUFFMAN_HASH_NBITS) + { + /* + * Good: val can be put in the lookup table, so fill all value of this + * column with value val + */ + int repeat = 1UL<<(HUFFMAN_HASH_NBITS - code_size); + code <<= HUFFMAN_HASH_NBITS - code_size; + while ( repeat-- ) + table->lookup[code++] = val; + + } + else + { + /* Perhaps sorting the array will be an optimization */ + uint16_t *slowtable = table->slowtable[code_size-HUFFMAN_HASH_NBITS-1]; + while(slowtable[0]) + slowtable+=2; + slowtable[0] = code; + slowtable[1] = val; + slowtable[2] = 0; + /* TODO: NEED TO CHECK FOR AN OVERFLOW OF THE TABLE */ + } + + } +} + +static void build_default_huffman_tables(struct jdec_private *priv) +{ + if ( (priv->flags & TINYJPEG_FLAGS_MJPEG_TABLE) + && priv->default_huffman_table_initialized) + return; + + build_huffman_table(bits_dc_luminance, val_dc_luminance, &priv->HTDC[0]); + build_huffman_table(bits_ac_luminance, val_ac_luminance, &priv->HTAC[0]); + + build_huffman_table(bits_dc_chrominance, val_dc_chrominance, &priv->HTDC[1]); + build_huffman_table(bits_ac_chrominance, val_ac_chrominance, &priv->HTAC[1]); + + priv->default_huffman_table_initialized = 1; +} + + + +/******************************************************************************* + * + * Colorspace conversion routine + * + * + * Note: + * YCbCr is defined per CCIR 601-1, except that Cb and Cr are + * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * The conversion equations to be implemented are therefore + * R = Y + 1.40200 * Cr + * G = Y - 0.34414 * Cb - 0.71414 * Cr + * B = Y + 1.77200 * Cb + * + ******************************************************************************/ + +static void print_SOF(const unsigned char *stream) +{ + int width, height, nr_components, precision; +#if DEBUG + const char *nr_components_to_string[] = { + "????", + "Grayscale", + "????", + "YCbCr", + "CYMK" + }; +#endif + + precision = stream[2]; + height = be16_to_cpu(stream+3); + width = be16_to_cpu(stream+5); + nr_components = stream[7]; + + trace("> SOF marker\n"); + trace("Size:%dx%d nr_components:%d (%s) precision:%d\n", + width, height, + nr_components, nr_components_to_string[nr_components], + precision); +} + +/******************************************************************************* + * + * JPEG/JFIF Parsing functions + * + * Note: only a small subset of the jpeg file format is supported. No markers, + * nor progressive stream is supported. + * + ******************************************************************************/ + +static void build_quantization_table(float *qtable, const unsigned char *ref_table) +{ + /* Taken from libjpeg. Copyright Independent JPEG Group's LLM idct. + * For float AA&N IDCT method, divisors are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * We apply a further scale factor of 8. + * What's actually stored is 1/divisor so that the inner loop can + * use a multiplication rather than a division. + */ + int i, j; + static const double aanscalefactor[8] = { + 1.0, 1.387039845, 1.306562965, 1.175875602, + 1.0, 0.785694958, 0.541196100, 0.275899379 + }; + const unsigned char *zz = zigzag; + + for (i=0; i<8; i++) { + for (j=0; j<8; j++) { + *qtable++ = ref_table[*zz++] * aanscalefactor[i] * aanscalefactor[j]; + } + } + +} + +static int parse_DQT(struct jdec_private *priv, const unsigned char *stream) +{ + int qi; + float *table; + const unsigned char *dqt_block_end; + + trace("> DQT marker\n"); + dqt_block_end = stream + be16_to_cpu(stream); + stream += 2; /* Skip length */ + + while (stream < dqt_block_end) + { + qi = *stream++; +#if SANITY_CHECK + if (qi>>4) + error("16 bits quantization table is not supported\n"); + if (qi>4) + error("No more 4 quantization table is supported (got %d)\n", qi); +#endif + table = priv->Q_tables[qi]; + build_quantization_table(table, stream); + stream += 64; + } + trace("< DQT marker\n"); + return 0; +} + +static int parse_SOF(struct jdec_private *priv, const unsigned char *stream) +{ + int i, width, height, nr_components, cid, sampling_factor; + int Q_table; + struct component *c; + + trace("> SOF marker\n"); + print_SOF(stream); + + height = be16_to_cpu(stream+3); + width = be16_to_cpu(stream+5); + nr_components = stream[7]; +#if SANITY_CHECK + if (stream[2] != 8) + error("Precision other than 8 is not supported\n"); + if (width>JPEG_MAX_WIDTH || height>JPEG_MAX_HEIGHT) + error("Width and Height (%dx%d) seems suspicious\n", width, height); + if (nr_components != 3) + error("We only support YUV images\n"); +#endif + stream += 8; + for (i=0; i<nr_components; i++) { + cid = *stream++; + sampling_factor = *stream++; + Q_table = *stream++; + c = &priv->component_infos[i]; +#if SANITY_CHECK + c->cid = cid; + if (Q_table >= COMPONENTS) + error("Bad Quantization table index (got %d, max allowed %d)\n", Q_table, COMPONENTS-1); +#endif + c->Vfactor = sampling_factor&0xf; + c->Hfactor = sampling_factor>>4; + c->Q_table = priv->Q_tables[Q_table]; + trace("Component:%d factor:%dx%d Quantization table:%d\n", + cid, c->Hfactor, c->Hfactor, Q_table ); + + } + priv->width = width; + priv->height = height; + + trace("< SOF marker\n"); + + return 0; +} + +static int parse_SOS(struct jdec_private *priv, const unsigned char *stream) +{ + unsigned int i, cid, table; + unsigned int nr_components = stream[2]; + + trace("> SOS marker\n"); + +#if SANITY_CHECK + if (nr_components != 3) + error("We only support YCbCr image\n"); +#endif + + stream += 3; + for (i=0;i<nr_components;i++) { + cid = *stream++; + table = *stream++; +#if SANITY_CHECK + if ((table&0xf)>=4) + error("We do not support more than 2 AC Huffman table\n"); + if ((table>>4)>=4) + error("We do not support more than 2 DC Huffman table\n"); + if (cid != priv->component_infos[i].cid) + error("SOS cid order (%d:%d) isn't compatible with the SOF marker (%d:%d)\n", + i, cid, i, priv->component_infos[i].cid); + trace("ComponentId:%d tableAC:%d tableDC:%d\n", cid, table&0xf, table>>4); +#endif + priv->component_infos[i].AC_table = &priv->HTAC[table&0xf]; + priv->component_infos[i].DC_table = &priv->HTDC[table>>4]; + } + priv->stream = stream+3; + trace("< SOS marker\n"); + return 0; +} + +static int parse_DHT(struct jdec_private *priv, const unsigned char *stream) +{ + unsigned int count, i; + unsigned char huff_bits[17]; + int length, index; + + length = be16_to_cpu(stream) - 2; + stream += 2; /* Skip length */ + + trace("> DHT marker (length=%d)\n", length); + + while (length>0) { + index = *stream++; + + /* We need to calculate the number of bytes 'vals' will takes */ + huff_bits[0] = 0; + count = 0; + for (i=1; i<17; i++) { + huff_bits[i] = *stream++; + count += huff_bits[i]; + } +#if SANITY_CHECK + if (count >= HUFFMAN_BITS_SIZE) + error("No more than %d bytes is allowed to describe a huffman table", HUFFMAN_BITS_SIZE); + if ( (index &0xf) >= HUFFMAN_TABLES) + error("No more than %d Huffman tables is supported (got %d)\n", HUFFMAN_TABLES, index&0xf); + trace("Huffman table %s[%d] length=%d\n", (index&0xf0)?"AC":"DC", index&0xf, count); +#endif + + if (index & 0xf0 ) + build_huffman_table(huff_bits, stream, &priv->HTAC[index&0xf]); + else + build_huffman_table(huff_bits, stream, &priv->HTDC[index&0xf]); + + length -= 1; + length -= 16; + length -= count; + stream += count; + } + trace("< DHT marker\n"); + return 0; +} + +static int parse_DRI(struct jdec_private *priv, const unsigned char *stream) +{ + unsigned int length; + + trace("> DRI marker\n"); + + length = be16_to_cpu(stream); + +#if SANITY_CHECK + if (length != 4) + error("Length of DRI marker need to be 4\n"); +#endif + + priv->restart_interval = be16_to_cpu(stream+2); + +#if DEBUG + trace("Restart interval = %d\n", priv->restart_interval); +#endif + + trace("< DRI marker\n"); + + return 0; +} + + + +static void resync(struct jdec_private *priv) +{ + int i; + + /* Init DC coefficients */ + for (i=0; i<COMPONENTS; i++) + priv->component_infos[i].previous_DC = 0; + + priv->reservoir = 0; + priv->nbits_in_reservoir = 0; + if (priv->restart_interval > 0) + priv->restarts_to_go = priv->restart_interval; + else + priv->restarts_to_go = -1; +} + +static int find_next_rst_marker(struct jdec_private *priv) +{ + int rst_marker_found = 0; + int marker; + const unsigned char *stream = priv->stream; + + /* Parse marker */ + while (!rst_marker_found) + { + while (*stream++ != 0xff) + { + if (stream >= priv->stream_end) + error("EOF while search for a RST marker."); + } + /* Skip any padding ff byte (this is normal) */ + while (*stream == 0xff) + stream++; + + marker = *stream++; + if ((RST+priv->last_rst_marker_seen) == marker) + rst_marker_found = 1; + else if (marker >= RST && marker <= RST7) + error("Wrong Reset marker found, abording"); + else if (marker == EOI) + return 0; + } + trace("RST Marker %d found at offset %d\n", priv->last_rst_marker_seen, stream - priv->stream_begin); + + priv->stream = stream; + priv->last_rst_marker_seen++; + priv->last_rst_marker_seen &= 7; + + return 0; +} + +static int parse_JFIF(struct jdec_private *priv, const unsigned char *stream) +{ + int chuck_len; + int marker; + int sos_marker_found = 0; + int dht_marker_found = 0; + const unsigned char *next_chunck; + + /* Parse marker */ + while (!sos_marker_found) + { + if (*stream++ != 0xff) + goto bogus_jpeg_format; + /* Skip any padding ff byte (this is normal) */ + while (*stream == 0xff) + stream++; + + marker = *stream++; + chuck_len = be16_to_cpu(stream); + next_chunck = stream + chuck_len; + switch (marker) + { + case SOF: + if (parse_SOF(priv, stream) < 0) + return -1; + break; + case DQT: + if (parse_DQT(priv, stream) < 0) + return -1; + break; + case SOS: + if (parse_SOS(priv, stream) < 0) + return -1; + sos_marker_found = 1; + break; + case DHT: + if (parse_DHT(priv, stream) < 0) + return -1; + dht_marker_found = 1; + break; + case DRI: + if (parse_DRI(priv, stream) < 0) + return -1; + break; + default: + trace("> Unknown marker %2.2x\n", marker); + break; + } + + stream = next_chunck; + } + + if (!dht_marker_found) { + trace("No Huffman table loaded, using the default one\n"); + build_default_huffman_tables(priv); + } + +#ifdef SANITY_CHECK + if ( (priv->component_infos[cY].Hfactor < priv->component_infos[cCb].Hfactor) + || (priv->component_infos[cY].Hfactor < priv->component_infos[cCr].Hfactor)) + error("Horizontal sampling factor for Y should be greater than horitontal sampling factor for Cb or Cr\n"); + if ( (priv->component_infos[cY].Vfactor < priv->component_infos[cCb].Vfactor) + || (priv->component_infos[cY].Vfactor < priv->component_infos[cCr].Vfactor)) + error("Vertical sampling factor for Y should be greater than vertical sampling factor for Cb or Cr\n"); + if ( (priv->component_infos[cCb].Hfactor!=1) + || (priv->component_infos[cCr].Hfactor!=1) + || (priv->component_infos[cCb].Vfactor!=1) + || (priv->component_infos[cCr].Vfactor!=1)) + error("Sampling other than 1x1 for Cr and Cb is not supported"); +#endif + + return 0; +bogus_jpeg_format: + trace("Bogus jpeg format\n"); + return -1; +} + +/******************************************************************************* + * + * Functions exported of the library. + * + * Note: Some applications can access directly to internal pointer of the + * structure. It's is not recommended, but if you have many images to + * uncompress with the same parameters, some functions can be called to speedup + * the decoding. + * + ******************************************************************************/ + +/** + * Allocate a new tinyjpeg decoder object. + * + * Before calling any other functions, an object need to be called. + */ +struct jdec_private *tinyjpeg_init(void) +{ + struct jdec_private *priv; + + priv = (struct jdec_private *)calloc(1, sizeof(struct jdec_private)); + if (priv == NULL) + return NULL; + return priv; +} + +/** + * Free a tinyjpeg object. + * + * No others function can be called after this one. + */ +void tinyjpeg_free(struct jdec_private *priv) +{ + int i; + for (i=0; i<COMPONENTS; i++) { + if (priv->components[i]) + free(priv->components[i]); + priv->components[i] = NULL; + } + free(priv); +} + +/** + * Initialize the tinyjpeg object and prepare the decoding of the stream. + * + * Check if the jpeg can be decoded with this jpeg decoder. + * Fill some table used for preprocessing. + */ +int tinyjpeg_parse_header(struct jdec_private *priv, const unsigned char *buf, unsigned int size) +{ + int ret; + + /* Identify the file */ + if ((buf[0] != 0xFF) || (buf[1] != SOI)) + error("Not a JPG file ?\n"); + + priv->stream_begin = buf+2; + priv->stream_length = size-2; + priv->stream_end = priv->stream_begin + priv->stream_length; + + ret = parse_JFIF(priv, priv->stream_begin); + + return ret; +} + +/** + * Decode and convert the jpeg image into @pixfmt@ image + * + * Note: components will be automaticaly allocated if no memory is attached. + */ +int tinyjpeg_decode(struct jdec_private *priv, + const struct tinyjpeg_colorspace *pixfmt) +{ + int x, y, sx, sy; + int xshift_by_mcu, yshift_by_mcu; + int xstride_by_mcu, ystride_by_mcu; + unsigned int bytes_per_blocklines[3], bytes_per_mcu[3]; + decode_MCU_fct decode_MCU; + const decode_MCU_fct *decode_mcu_table; + convert_colorspace_fct convert_to_pixfmt; + uint8_t *pptr[3]; + + decode_mcu_table = pixfmt->decode_mcu_table; + + /* Fix: check return value */ + pixfmt->initialize(priv, bytes_per_blocklines, bytes_per_mcu); + + xshift_by_mcu = yshift_by_mcu = 3; + if ((priv->component_infos[cY].Hfactor | priv->component_infos[cY].Vfactor) == 1) { + decode_MCU = decode_mcu_table[0]; + convert_to_pixfmt = pixfmt->convert_colorspace[0]; + trace("Use decode 1x1 sampling\n"); + } else if (priv->component_infos[cY].Hfactor == 1) { + decode_MCU = decode_mcu_table[1]; + convert_to_pixfmt = pixfmt->convert_colorspace[1]; + yshift_by_mcu = 4; + trace("Use decode 1x2 sampling (not supported)\n"); + } else if (priv->component_infos[cY].Vfactor == 2) { + decode_MCU = decode_mcu_table[3]; + convert_to_pixfmt = pixfmt->convert_colorspace[3]; + xshift_by_mcu = 4; + yshift_by_mcu = 4; + trace("Use decode 2x2 sampling\n"); + } else { + decode_MCU = decode_mcu_table[2]; + convert_to_pixfmt = pixfmt->convert_colorspace[2]; + xshift_by_mcu = 4; + trace("Use decode 2x1 sampling\n"); + } + + resync(priv); + + /* Don't forget to that block can be either 8 or 16 lines */ + bytes_per_blocklines[0] <<= yshift_by_mcu-3; + bytes_per_blocklines[1] <<= yshift_by_mcu-3; + bytes_per_blocklines[2] <<= yshift_by_mcu-3; + + bytes_per_mcu[0] <<= xshift_by_mcu-3; + bytes_per_mcu[1] <<= xshift_by_mcu-3; + bytes_per_mcu[2] <<= xshift_by_mcu-3; + + xstride_by_mcu = 1 << xshift_by_mcu; + ystride_by_mcu = 1 << yshift_by_mcu; + + pptr[0] = priv->components[0]; + pptr[1] = priv->components[1]; + pptr[2] = priv->components[2]; + + trace("bpbl = %d, bpmcu = %d\n", + bytes_per_blocklines[0], bytes_per_mcu[0]); + + for (y = priv->height; y > 0; y -= ystride_by_mcu) + { + trace("Decoding row %d\n", priv->height-y); + priv->plane[0] = pptr[0]; pptr[0] += bytes_per_blocklines[0]; + priv->plane[1] = pptr[1]; pptr[1] += bytes_per_blocklines[1]; + priv->plane[2] = pptr[2]; pptr[2] += bytes_per_blocklines[2]; + + sy = min(y, ystride_by_mcu); + + for (x = priv->width; x > 0; x -= xstride_by_mcu) + { + sx = min(x, xstride_by_mcu); + trace("Block size: %dx%d\n", sx, sy); + + decode_MCU(priv); + convert_to_pixfmt(priv, sx, sy); + priv->plane[0] += bytes_per_mcu[0]; + priv->plane[1] += bytes_per_mcu[1]; + priv->plane[2] += bytes_per_mcu[2]; + if (priv->restarts_to_go>0) + { + priv->restarts_to_go--; + if (priv->restarts_to_go == 0) + { + priv->stream -= (priv->nbits_in_reservoir/8); + resync(priv); + if (find_next_rst_marker(priv) < 0) + return -1; + } + } + } + } + + trace("Input file size: %d\n", priv->stream_length+2); + trace("Input bytes actually read: %d\n", priv->stream - priv->stream_begin + 2); + + return 0; +} + +const char *tinyjpeg_get_errorstring(struct jdec_private *priv) +{ + /* FIXME: the error string must be store in the context */ + priv = priv; + return error_string; +} + +void tinyjpeg_get_size(struct jdec_private *priv, unsigned int *width, unsigned int *height) +{ + *width = priv->width; + *height = priv->height; +} + +int tinyjpeg_get_components(struct jdec_private *priv, unsigned char **components, unsigned int ncomponents) +{ + unsigned int i; + if (ncomponents > COMPONENTS) + ncomponents = COMPONENTS; + for (i=0; i<ncomponents; i++) + components[i] = priv->components[i]; + return 0; +} + +int tinyjpeg_set_components(struct jdec_private *priv, unsigned char * const *components, unsigned int ncomponents) +{ + unsigned int i; + if (ncomponents > COMPONENTS) + ncomponents = COMPONENTS; + for (i=0; i<ncomponents; i++) + priv->components[i] = components[i]; + return 0; +} + +int tinyjpeg_get_bytes_per_row(struct jdec_private *priv, + unsigned int *bytes, + unsigned int ncomponents) +{ + unsigned int i; + if (ncomponents > COMPONENTS) + ncomponents = COMPONENTS; + for (i=0; i<ncomponents; i++) + bytes[i] = priv->bytes_per_row[i]; + return 0; +} + +int tinyjpeg_set_bytes_per_row(struct jdec_private *priv, + const unsigned int *bytes, + unsigned int ncomponents) +{ + unsigned int i; + if (ncomponents > COMPONENTS) + ncomponents = COMPONENTS; + for (i=0; i<ncomponents; i++) + priv->bytes_per_row[i] = bytes[i]; + return 0; +} + +int tinyjpeg_set_flags(struct jdec_private *priv, int flags) +{ + int oldflags = priv->flags; + priv->flags = flags; + return oldflags; +} diff --git a/contrib/syslinux-4.02/com32/lib/jpeg/yuv420p.c b/contrib/syslinux-4.02/com32/lib/jpeg/yuv420p.c new file mode 100644 index 0000000..c512089 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/jpeg/yuv420p.c @@ -0,0 +1,288 @@ +/* + * Small jpeg decoder library + * + * Copyright (c) 2006, Luc Saillard <luc@saillard.org> + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - 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. + * + * - Neither the name of the author nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + * + */ + +/* + * yuv420p.c + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> + +#include "tinyjpeg.h" +#include "tinyjpeg-internal.h" + +/******************************************************************************* + * + * Colorspace conversion routine + * + * + * Note: + * YCbCr is defined per CCIR 601-1, except that Cb and Cr are + * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * The conversion equations to be implemented are therefore + * R = Y + 1.40200 * Cr + * G = Y - 0.34414 * Cb - 0.71414 * Cr + * B = Y + 1.77200 * Cb + * + ******************************************************************************/ + +/** + * YCrCb -> YUV420P (1x1) + * .---. + * | 1 | + * `---' + */ +static void YCrCB_to_YUV420P_1x1(struct jdec_private *priv, int sx, int sy) +{ + const unsigned char *s, *y; + unsigned char *p; + int i,j; + + p = priv->plane[0]; + y = priv->Y; + for (i = sy; i > 0; i--) + { + memcpy(p, y, sx); + p += priv->bytes_per_row[0]; + y += 8; + } + + p = priv->plane[1]; + s = priv->Cb; + for (i = sy; i > 0; i--) + { + for (j = sx; j >= 0; j -= 2) { + *p++ = *s; + s += 2; + } + s += 8; /* Skip one line */ + p += priv->bytes_per_row[1] - 4; + } + + p = priv->plane[2]; + s = priv->Cr; + for (i=0; i<8; i+=2) + { + for (j = sx; j >= 0; j -= 2) { + *p++ = *s; + s += 2; + } + s += 8; /* Skip one line */ + p += priv->bytes_per_row[2] - 4; + } +} + +/** + * YCrCb -> YUV420P (2x1) + * .-------. + * | 1 | 2 | + * `-------' + */ +static void YCrCB_to_YUV420P_2x1(struct jdec_private *priv, int sx, int sy) +{ + unsigned char *p; + const unsigned char *s, *y1; + unsigned int i; + + p = priv->plane[0]; + y1 = priv->Y; + for (i = sy; i > 0; i--) + { + memcpy(p, y1, sx); + p += priv->bytes_per_row[0]; + y1 += 16; + } + + sx = (sx+1) >> 1; + + p = priv->plane[1]; + s = priv->Cb; + for (i = sy; i > 0; i -= 2) + { + memcpy(p, s, sx); + s += 16; /* Skip one line */ + p += priv->bytes_per_row[1]; + } + + p = priv->plane[2]; + s = priv->Cr; + for (i = sy; i > 0; i -= 2) + { + memcpy(p, s, sx); + s += 16; /* Skip one line */ + p += priv->bytes_per_row[2]; + } +} + + +/** + * YCrCb -> YUV420P (1x2) + * .---. + * | 1 | + * |---| + * | 2 | + * `---' + */ +static void YCrCB_to_YUV420P_1x2(struct jdec_private *priv, int sx, int sy) +{ + const unsigned char *s, *y; + unsigned char *p, *pr; + int i,j; + + p = priv->plane[0]; + y = priv->Y; + for (i = sy; i > 0; i++) + { + memcpy(p, y, sx); + p+=priv->bytes_per_row[0]; + y+=8; + } + + pr = priv->plane[1]; + s = priv->Cb; + for (i = sy; i > 0; i -= 2) + { + p = pr; + for (j = sx; j > 0; j -= 2) { + *p++ = *s; + s += 2; + } + pr += priv->bytes_per_row[1]; + } + + pr = priv->plane[2]; + s = priv->Cr; + for (i=0; i<8; i++) + { + p = pr; + for (j = sx; j > 0; j -= 2) { + *p++ = *s; + s += 2; + } + pr += priv->bytes_per_row[2] - 4; + } +} + +/** + * YCrCb -> YUV420P (2x2) + * .-------. + * | 1 | 2 | + * |---+---| + * | 3 | 4 | + * `-------' + */ +static void YCrCB_to_YUV420P_2x2(struct jdec_private *priv, int sx, int sy) +{ + unsigned char *p; + const unsigned char *s, *y1; + unsigned int i; + + p = priv->plane[0]; + y1 = priv->Y; + for (i = sy; i > 0; i--) + { + memcpy(p, y1, sx); + p += priv->bytes_per_row[0]; + y1 += 16; + } + + sx = (sx+1) >> 1; + + p = priv->plane[1]; + s = priv->Cb; + for (i = sy; i > 0; i -= 2) + { + memcpy(p, s, sx); + s += 8; + p += priv->bytes_per_row[1]; + } + + p = priv->plane[2]; + s = priv->Cr; + for (i = sy; i > 0; i -= 2) + { + memcpy(p, s, sx); + s += 8; + p += priv->bytes_per_row[2]; + } +} + +static int initialize_yuv420p(struct jdec_private *priv, + unsigned int *bytes_per_blocklines, + unsigned int *bytes_per_mcu) +{ + int half_height = (priv->height + 1) >> 2; + int half_width = (priv->width + 1) >> 2; + + if (!priv->bytes_per_row[0]) + priv->bytes_per_row[0] = priv->width; + if (!priv->components[0]) + priv->components[0] = malloc(priv->height * priv->bytes_per_row[0]); + + if (!priv->bytes_per_row[1]) + priv->bytes_per_row[1] = half_width; + if (!priv->components[1]) + priv->components[1] = malloc(half_height * priv->bytes_per_row[1]); + + if (!priv->bytes_per_row[2]) + priv->bytes_per_row[2] = half_width; + if (!priv->components[2]) + priv->components[2] = malloc(half_height * priv->bytes_per_row[2]); + + bytes_per_mcu[0] = 8; + bytes_per_mcu[1] = 4; + bytes_per_mcu[2] = 4; + + bytes_per_blocklines[0] = priv->width << 3; + bytes_per_blocklines[1] = half_width << 2; + bytes_per_blocklines[2] = half_width << 2; + + /* Return nonzero on failure */ + return !priv->components[0] || !priv->components[1] || !priv->components[2]; +} + +static const struct tinyjpeg_colorspace format_yuv420p = + { + { + YCrCB_to_YUV420P_1x1, + YCrCB_to_YUV420P_1x2, + YCrCB_to_YUV420P_2x1, + YCrCB_to_YUV420P_2x2, + }, + tinyjpeg_decode_mcu_3comp_table, + initialize_yuv420p + }; + +const tinyjpeg_colorspace_t TINYJPEG_FMT_YUV420P = &format_yuv420p; diff --git a/contrib/syslinux-4.02/com32/lib/libgcc/__ashldi3.S b/contrib/syslinux-4.02/com32/lib/libgcc/__ashldi3.S new file mode 100644 index 0000000..f2cc11c --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libgcc/__ashldi3.S @@ -0,0 +1,29 @@ +/* + * arch/i386/libgcc/__ashldi3.S + * + * 64-bit shl + */ + .text + .align 4 + .globl __ashldi3 + .type __ashldi3,@function +__ashldi3: +#ifndef REGPARM + movl 4(%esp),%eax + movl 8(%esp),%edx + movb 12(%esp),%cl +#endif + cmpb $32,%cl + jae 1f + + shldl %cl,%eax,%edx + shl %cl,%eax + ret + +1: + xorl %edx,%edx + shl %cl,%eax + xchgl %edx,%eax + ret + + .size __ashldi3,.-__ashldi3 diff --git a/contrib/syslinux-4.02/com32/lib/libgcc/__ashrdi3.S b/contrib/syslinux-4.02/com32/lib/libgcc/__ashrdi3.S new file mode 100644 index 0000000..3f9c520 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libgcc/__ashrdi3.S @@ -0,0 +1,29 @@ +/* + * arch/i386/libgcc/__ashrdi3.S + * + * 64-bit sar + */ + .text + .align 4 + .globl __ashrdi3 + .type __ashrdi3,@function +__ashrdi3: +#ifndef REGPARM + movl 4(%esp),%eax + movl 8(%esp),%edx + movb 12(%esp),%cl +#endif + cmpb $32,%cl + jae 1f + + shrdl %cl,%edx,%eax + sarl %cl,%edx + ret + +1: + sarl %cl,%edx + movl %edx,%eax + cdq + ret + + .size __ashrdi3,.-__ashrdi3 diff --git a/contrib/syslinux-4.02/com32/lib/libgcc/__divdi3.c b/contrib/syslinux-4.02/com32/lib/libgcc/__divdi3.c new file mode 100644 index 0000000..97c7795 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libgcc/__divdi3.c @@ -0,0 +1,29 @@ +/* + * arch/i386/libgcc/__divdi3.c + */ + +#include <stdint.h> +#include <stddef.h> + +extern uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t * rem); + +int64_t __divdi3(int64_t num, int64_t den) +{ + int minus = 0; + int64_t v; + + if (num < 0) { + num = -num; + minus = 1; + } + if (den < 0) { + den = -den; + minus ^= 1; + } + + v = __udivmoddi4(num, den, NULL); + if (minus) + v = -v; + + return v; +} diff --git a/contrib/syslinux-4.02/com32/lib/libgcc/__lshrdi3.S b/contrib/syslinux-4.02/com32/lib/libgcc/__lshrdi3.S new file mode 100644 index 0000000..eee3aac --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libgcc/__lshrdi3.S @@ -0,0 +1,29 @@ +/* + * arch/i386/libgcc/__lshrdi3.S + * + * 64-bit shr + */ + .text + .align 4 + .globl __lshrdi3 + .type __lshrdi3,@function +__lshrdi3: +#ifndef REGPARM + movl 4(%esp),%eax + movl 8(%esp),%edx + movb 12(%esp),%cl +#endif + cmpb $32,%cl + jae 1f + + shrdl %cl,%edx,%eax + shrl %cl,%edx + ret + +1: + shrl %cl,%edx + xorl %eax,%eax + xchgl %edx,%eax + ret + + .size __lshrdi3,.-__lshrdi3 diff --git a/contrib/syslinux-4.02/com32/lib/libgcc/__moddi3.c b/contrib/syslinux-4.02/com32/lib/libgcc/__moddi3.c new file mode 100644 index 0000000..4fc5588 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libgcc/__moddi3.c @@ -0,0 +1,29 @@ +/* + * arch/i386/libgcc/__moddi3.c + */ + +#include <stdint.h> +#include <stddef.h> + +extern uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t * rem); + +int64_t __moddi3(int64_t num, int64_t den) +{ + int minus = 0; + int64_t v; + + if (num < 0) { + num = -num; + minus = 1; + } + if (den < 0) { + den = -den; + minus ^= 1; + } + + (void)__udivmoddi4(num, den, (uint64_t *)&v); + if (minus) + v = -v; + + return v; +} diff --git a/contrib/syslinux-4.02/com32/lib/libgcc/__muldi3.S b/contrib/syslinux-4.02/com32/lib/libgcc/__muldi3.S new file mode 100644 index 0000000..648a88a --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libgcc/__muldi3.S @@ -0,0 +1,34 @@ +/* + * arch/i386/libgcc/__muldi3.S + * + * 64*64 = 64 bit unsigned multiplication + */ + + .text + .align 4 + .globl __muldi3 + .type __muldi3,@function +__muldi3: + push %esi +#ifndef REGPARM + movl 8(%esp),%eax + movl %eax,%esi + movl 16(%esp),%ecx + mull %ecx + imull 12(%esp),%ecx + imull 20(%esp),%esi + addl %ecx,%edx + addl %esi,%edx +#else + movl %eax,%esi + push %edx + mull %ecx + imull 8(%esp),%esi + addl %esi,%edx + pop %esi + imull %esi,%ecx + addl %ecx,%edx +#endif + pop %esi + ret + .size __muldi3,.-__muldi3 diff --git a/contrib/syslinux-4.02/com32/lib/libgcc/__negdi2.S b/contrib/syslinux-4.02/com32/lib/libgcc/__negdi2.S new file mode 100644 index 0000000..37b0d2d --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libgcc/__negdi2.S @@ -0,0 +1,21 @@ +/* + * arch/i386/libgcc/__negdi2.S + * + * 64-bit negation + */ + + .text + .align 4 + .globl __negdi2 + .type __negdi2,@function +__negdi2: +#ifndef REGPARM + movl 4(%esp),%eax + movl 8(%esp),%edx +#endif + negl %edx + negl %eax + sbbl $0,%edx + ret + + .size __negdi2,.-__negdi2 diff --git a/contrib/syslinux-4.02/com32/lib/libgcc/__udivdi3.c b/contrib/syslinux-4.02/com32/lib/libgcc/__udivdi3.c new file mode 100644 index 0000000..db5b359 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libgcc/__udivdi3.c @@ -0,0 +1,13 @@ +/* + * arch/i386/libgcc/__divdi3.c + */ + +#include <stdint.h> +#include <stddef.h> + +extern uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t * rem); + +uint64_t __udivdi3(uint64_t num, uint64_t den) +{ + return __udivmoddi4(num, den, NULL); +} diff --git a/contrib/syslinux-4.02/com32/lib/libgcc/__udivmoddi4.c b/contrib/syslinux-4.02/com32/lib/libgcc/__udivmoddi4.c new file mode 100644 index 0000000..dd60263 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libgcc/__udivmoddi4.c @@ -0,0 +1,32 @@ +#include <klibc/diverr.h> +#include <stdint.h> + +uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t * rem_p) +{ + uint64_t quot = 0, qbit = 1; + + if (den == 0) { + __divide_error(); + return 0; /* If trap returns... */ + } + + /* Left-justify denominator and count shift */ + while ((int64_t) den >= 0) { + den <<= 1; + qbit <<= 1; + } + + while (qbit) { + if (den <= num) { + num -= den; + quot += qbit; + } + den >>= 1; + qbit >>= 1; + } + + if (rem_p) + *rem_p = num; + + return quot; +} diff --git a/contrib/syslinux-4.02/com32/lib/libgcc/__umoddi3.c b/contrib/syslinux-4.02/com32/lib/libgcc/__umoddi3.c new file mode 100644 index 0000000..b897ee0 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libgcc/__umoddi3.c @@ -0,0 +1,16 @@ +/* + * arch/i386/libgcc/__umoddi3.c + */ + +#include <stdint.h> +#include <stddef.h> + +extern uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t * rem); + +uint64_t __umoddi3(uint64_t num, uint64_t den) +{ + uint64_t v; + + (void)__udivmoddi4(num, den, &v); + return v; +} diff --git a/contrib/syslinux-4.02/com32/lib/libpng/ANNOUNCE b/contrib/syslinux-4.02/com32/lib/libpng/ANNOUNCE new file mode 100644 index 0000000..b0824ee --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libpng/ANNOUNCE @@ -0,0 +1,57 @@ + +Libpng 1.2.44 - June 26, 2010 + +This is a public release of libpng, intended for use in production codes. + +Files available for download: + +Source files with LF line endings (for Unix/Linux) and with a +"configure" script + + libpng-1.2.44.tar.xz (LZMA-compressed, recommended) + libpng-1.2.44.tar.gz + libpng-1.2.44.tar.bz2 + +Source files with LF line endings (for Unix/Linux) without the +"configure" script + + libpng-1.2.44-no-config.tar.xz (LZMA-compressed, recommended) + libpng-1.2.44-no-config.tar.gz + libpng-1.2.44-no-config.tar.bz2 + +Source files with CRLF line endings (for Windows), without the +"configure" script + + lpng1244.zip + lpng1244.7z + lpng1244.tar.bz2 + +Project files + + libpng-1.2.44-project-netware.zip + libpng-1.2.44-project-wince.zip + +Other information: + + libpng-1.2.44-README.txt + libpng-1.2.44-KNOWNBUGS.txt + libpng-1.2.44-LICENSE.txt + libpng-1.2.44-Y2K-compliance.txt + libpng-1.2.44-[previous version]-diff.txt + +Changes since the last public release (1.2.43): + +version 1.2.44 [June 26, 2010] + + Rewrote png_process_IDAT_data to consistently treat extra data as warnings + and handle end conditions more cleanly. + Removed the now-redundant check for out-of-bounds new_row from example.c + + +Send comments/corrections/commendations to png-mng-implement at lists.sf.net + +(subscription required; visit +https://lists.sourceforge.net/lists/listinfo/png-mng-implement +to subscribe) or to glennrp at users.sourceforge.net + +Glenn R-P diff --git a/contrib/syslinux-4.02/com32/lib/libpng/CHANGES b/contrib/syslinux-4.02/com32/lib/libpng/CHANGES new file mode 100644 index 0000000..90a3e2b --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libpng/CHANGES @@ -0,0 +1,2714 @@ +/* +CHANGES - changes for libpng + +version 0.2 + added reader into png.h + fixed small problems in stub file + +version 0.3 + added pull reader + split up pngwrite.c to several files + added pnglib.txt + added example.c + cleaned up writer, adding a few new transformations + fixed some bugs in writer + interfaced with zlib 0.5 + added K&R support + added check for 64 KB blocks for 16 bit machines + +version 0.4 + cleaned up code and commented code + simplified time handling into png_time + created png_color_16 and png_color_8 to handle color needs + cleaned up color type defines + fixed various bugs + made various names more consistent + interfaced with zlib 0.71 + cleaned up zTXt reader and writer (using zlib's Reset functions) + split transformations into pngrtran.c and pngwtran.c + +version 0.5 + interfaced with zlib 0.8 + fixed many reading and writing bugs + saved using 3 spaces instead of tabs + +version 0.6 + added png_large_malloc() and png_large_free() + added png_size_t + cleaned up some compiler warnings + added png_start_read_image() + +version 0.7 + cleaned up lots of bugs + finished dithering and other stuff + added test program + changed name from pnglib to libpng + +version 0.71 [June, 1995] + changed pngtest.png for zlib 0.93 + fixed error in libpng.txt and example.c + +version 0.8 + cleaned up some bugs + added png_set_filler() + split up pngstub.c into pngmem.c, pngio.c, and pngerror.c + added #define's to remove unwanted code + moved png_info_init() to png.c + added old_size into png_realloc() + added functions to manually set filtering and compression info + changed compression parameters based on image type + optimized filter selection code + added version info + changed external functions passing floats to doubles (k&r problems?) + put all the configurable stuff in pngconf.h + enabled png_set_shift to work with paletted images on read + added png_read_update_info() - updates info structure with + transformations + +version 0.81 [August, 1995] + incorporated Tim Wegner's medium model code (thanks, Tim) + +version 0.82 [September, 1995] + [unspecified changes] + +version 0.85 [December, 1995] + added more medium model code (almost everything's a far) + added i/o, error, and memory callback functions + fixed some bugs (16 bit, 4 bit interlaced, etc.) + added first run progressive reader (barely tested) + +version 0.86 [January, 1996] + fixed bugs + improved documentation + +version 0.87 [January, 1996] + fixed medium model bugs + fixed other bugs introduced in 0.85 and 0.86 + added some minor documentation + +version 0.88 [January, 1996] + fixed progressive bugs + replaced tabs with spaces + cleaned up documentation + added callbacks for read/write and warning/error functions + +version 0.89 [July, 1996] + added new initialization API to make libpng work better with shared libs + we now have png_create_read_struct(), png_create_write_struct(), + png_create_info_struct(), png_destroy_read_struct(), and + png_destroy_write_struct() instead of the separate calls to + malloc and png_read_init(), png_info_init(), and png_write_init() + changed warning/error callback functions to fix bug - this means you + should use the new initialization API if you were using the old + png_set_message_fn() calls, and that the old API no longer exists + so that people are aware that they need to change their code + changed filter selection API to allow selection of multiple filters + since it didn't work in previous versions of libpng anyways + optimized filter selection code + fixed png_set_background() to allow using an arbitrary RGB color for + paletted images + fixed gamma and background correction for paletted images, so + png_correct_palette is not needed unless you are correcting an + external palette (you will need to #define PNG_CORRECT_PALETTE_SUPPORTED + in pngconf.h) - if nobody uses this, it may disappear in the future. + fixed bug with Borland 64K memory allocation (Alexander Lehmann) + fixed bug in interlace handling (Smarasderagd, I think) + added more error checking for writing and image to reduce invalid files + separated read and write functions so that they won't both be linked + into a binary when only reading or writing functionality is used + new pngtest image also has interlacing and zTXt + updated documentation to reflect new API + +version 0.90 [January, 1997] + made CRC errors/warnings on critical and ancillary chunks configurable + libpng will use the zlib CRC routines by (compile-time) default + changed DOS small/medium model memory support - needs zlib 1.04 (Tim Wegner) + added external C++ wrapper statements to png.h (Gilles Dauphin) + allow PNG file to be read when some or all of file signature has already + been read from the beginning of the stream. ****This affects the size + of info_struct and invalidates all programs that use a shared libpng**** + fixed png_filler() declarations + fixed? background color conversions + fixed order of error function pointers to match documentation + current chunk name is now available in png_struct to reduce the number + of nearly identical error messages (will simplify multi-lingual + support when available) + try to get ready for unknown-chunk callback functions: + - previously read critical chunks are flagged, so the chunk handling + routines can determine if the chunk is in the right place + - all chunk handling routines have the same prototypes, so we will + be able to handle all chunks via a callback mechanism + try to fix Linux "setjmp" buffer size problems + removed png_large_malloc, png_large_free, and png_realloc functions. + +version 0.95 [March, 1997] + fixed bug in pngwutil.c allocating "up_row" twice and "avg_row" never + fixed bug in PNG file signature compares when start != 0 + changed parameter type of png_set_filler(...filler...) from png_byte + to png_uint_32 + added test for MACOS to ensure that both math.h and fp.h are not #included + added macros for libpng to be compiled as a Windows DLL (Andreas Kupries) + added "packswap" transformation, which changes the endianness of + packed-pixel bytes (Kevin Bracey) + added "strip_alpha" transformation, which removes the alpha channel of + input images without using it (not necessarily a good idea) + added "swap_alpha" transformation, which puts the alpha channel in front + of the color bytes instead of after + removed all implicit variable tests which assume NULL == 0 (I think) + changed several variables to "png_size_t" to show 16/32-bit limitations + added new pCAL chunk read/write support + added experimental filter selection weighting (Greg Roelofs) + removed old png_set_rgbx() and png_set_xrgb() functions that have been + obsolete for about 2 years now (use png_set_filler() instead) + added macros to read 16- and 32-bit ints directly from buffer, to be + used only on those systems that support it (namely PowerPC and 680x0) + With some testing, this may become the default for MACOS/PPC systems. + only calculate CRC on data if we are going to use it + added macros for zTXt compression type PNG_zTXt_COMPRESSION_??? + added macros for simple libpng debugging output selectable at compile time + removed PNG_READ_END_MODE in progressive reader (Smarasderagd) + more description of info_struct in libpng.txt and png.h + more instructions in example.c + more chunk types tested in pngtest.c + renamed pngrcb.c to pngset.c, and all png_read_<chunk> functions to be + png_set_<chunk>. We now have corresponding png_get_<chunk> + functions in pngget.c to get information in info_ptr. This isolates + the application from the internal organization of png_info_struct + (good for shared library implementations). + +version 0.96 [May, 1997] + fixed serious bug with < 8bpp images introduced in 0.95 + fixed 256-color transparency bug (Greg Roelofs) + fixed up documentation (Greg Roelofs, Laszlo Nyul) + fixed "error" in pngconf.h for Linux setjmp() behaviour + fixed DOS medium model support (Tim Wegner) + fixed png_check_keyword() for case with error in static string text + added read of CRC after IEND chunk for embedded PNGs (Laszlo Nyul) + added typecasts to quiet compiler errors + added more debugging info + +version 0.97 [January, 1998] + removed PNG_USE_OWN_CRC capability + relocated png_set_crc_action from pngrutil.c to pngrtran.c + fixed typecasts of "new_key", etc. (Andreas Dilger) + added RFC 1152 [sic] date support + fixed bug in gamma handling of 4-bit grayscale + added 2-bit grayscale gamma handling (Glenn R-P) + added more typecasts. 65536L becomes (png_uint_32)65536L, etc. (Glenn R-P) + minor corrections in libpng.txt + added simple sRGB support (Glenn R-P) + easier conditional compiling, e.g. define PNG_READ/WRITE_NOT_FULLY_SUPPORTED; + all configurable options can be selected from command-line instead + of having to edit pngconf.h (Glenn R-P) + fixed memory leak in pngwrite.c (free info_ptr->text) (Glenn R-P) + added more conditions for png_do_background, to avoid changing + black pixels to background when a background is supplied and + no pixels are transparent + repaired PNG_NO_STDIO behaviour + tested NODIV support and made it default behaviour (Greg Roelofs) + added "-m" option and PNGTEST_DEBUG_MEMORY to pngtest (John Bowler) + regularized version numbering scheme and bumped shared-library major + version number to 2 to avoid problems with libpng 0.89 apps (Greg Roelofs) + +version 0.98 [January, 1998] + cleaned up some typos in libpng.txt and in code documentation + fixed memory leaks in pCAL chunk processing (Glenn R-P and John Bowler) + cosmetic change "display_gamma" to "screen_gamma" in pngrtran.c + changed recommendation about file_gamma for PC images to .51 from .45, + in example.c and libpng.txt, added comments to distinguish between + screen_gamma, viewing_gamma, and display_gamma. + changed all references to RFC1152 to read RFC1123 and changed the + PNG_TIME_RFC1152_SUPPORTED macro to PNG_TIME_RFC1123_SUPPORTED + added png_invert_alpha capability (Glenn R-P -- suggestion by Jon Vincent) + changed srgb_intent from png_byte to int to avoid compiler bugs + +version 0.99 [January 30, 1998] + free info_ptr->text instead of end_info_ptr->text in pngread.c (John Bowler) + fixed a longstanding "packswap" bug in pngtrans.c + fixed some inconsistencies in pngconf.h that prevented compiling with + PNG_READ_GAMMA_SUPPORTED and PNG_READ_hIST_SUPPORTED undefined + fixed some typos and made other minor rearrangement of libpng.txt (Andreas) + changed recommendation about file_gamma for PC images to .50 from .51 in + example.c and libpng.txt, and changed file_gamma for sRGB images to .45 + added a number of functions to access information from the png structure + png_get_image_height(), etc. (Glenn R-P, suggestion by Brad Pettit) + added TARGET_MACOS similar to zlib-1.0.8 + define PNG_ALWAYS_EXTERN when __MWERKS__ && WIN32 are defined + added type casting to all png_malloc() function calls +version 0.99a [January 31, 1998] + Added type casts and parentheses to all returns that return a value.(Tim W.) +version 0.99b [February 4, 1998] + Added type cast png_uint_32 on malloc function calls where needed. + Changed type of num_hist from png_uint_32 to int (same as num_palette). + Added checks for rowbytes overflow, in case png_size_t is less than 32 bits. + Renamed makefile.elf to makefile.lnx. +version 0.99c [February 7, 1998] + More type casting. Removed erroneous overflow test in pngmem.c. + Added png_buffered_memcpy() and png_buffered_memset(), apply them to rowbytes. + Added UNIX manual pages libpng.3 (incorporating libpng.txt) and png.5. +version 0.99d [February 11, 1998] + Renamed "far_to_near()" "png_far_to_near()" + Revised libpng.3 + Version 99c "buffered" operations didn't work as intended. Replaced them + with png_memcpy_check() and png_memset_check(). + Added many "if (png_ptr == NULL) return" to quell compiler warnings about + unused png_ptr, mostly in pngget.c and pngset.c. + Check for overlength tRNS chunk present when indexed-color PLTE is read. + Cleaned up spelling errors in libpng.3/libpng.txt + Corrected a problem with png_get_tRNS() which returned undefined trans array +version 0.99e [February 28, 1998] + Corrected png_get_tRNS() again. + Add parentheses for easier reading of pngget.c, fixed "||" should be "&&". + Touched up example.c to make more of it compileable, although the entire + file still can't be compiled (Willem van Schaik) + Fixed a bug in png_do_shift() (Bryan Tsai) + Added a space in png.h prototype for png_write_chunk_start() + Replaced pngtest.png with one created with zlib 1.1.1 + Changed pngtest to report PASS even when file size is different (Jean-loup G.) + Corrected some logic errors in png_do_invert_alpha() (Chris Patterson) +version 0.99f [March 5, 1998] + Corrected a bug in pngpread() introduced in version 99c (Kevin Bracey) + Moved makefiles into a "scripts" directory, and added INSTALL instruction file + Added makefile.os2 and pngos2.def (A. Zabolotny) and makefile.s2x (W. Sebok) + Added pointers to "note on libpng versions" in makefile.lnx and README + Added row callback feature when reading and writing nonprogressive rows + and added a test of this feature in pngtest.c + Added user transform callbacks, with test of the feature in pngtest.c +version 0.99g [March 6, 1998, morning] + Minor changes to pngtest.c to suppress compiler warnings. + Removed "beta" language from documentation. +version 0.99h [March 6, 1998, evening] + Minor changes to previous minor changes to pngtest.c + Changed PNG_READ_NOT_FULLY_SUPPORTED to PNG_READ_TRANSFORMS_NOT_SUPPORTED + and added PNG_PROGRESSIVE_READ_NOT_SUPPORTED macro + Added user transform capability + +version 1.00 [March 7, 1998] + Changed several typedefs in pngrutil.c + Added makefile.wat (Pawel Mrochen), updated makefile.tc3 (Willem van Schaik) + replaced "while(1)" with "for(;;)" + added PNGARG() to prototypes in pngtest.c and removed some prototypes + updated some of the makefiles (Tom Lane) + changed some typedefs (s_start, etc.) in pngrutil.c + fixed dimensions of "short_months" array in pngwrite.c + Replaced ansi2knr.c with the one from jpeg-v6 + +version 1.0.0 [March 8, 1998] + Changed name from 1.00 to 1.0.0 (Adam Costello) + Added smakefile.ppc (with SCOPTIONS.ppc) for Amiga PPC (Andreas Kleinert) +version 1.0.0a [March 9, 1998] + Fixed three bugs in pngrtran.c to make gamma+background handling consistent + (Greg Roelofs) + Changed format of the PNG_LIBPNG_VER integer to xyyzz instead of xyz + for major, minor, and bugfix releases. This is 10001. (Adam Costello, + Tom Lane) + Make months range from 1-12 in png_convert_to_rfc1123 +version 1.0.0b [March 13, 1998] + Quieted compiler complaints about two empty "for" loops in pngrutil.c + Minor changes to makefile.s2x + Removed #ifdef/#endif around a png_free() in pngread.c + +version 1.0.1 [March 14, 1998] + Changed makefile.s2x to reduce security risk of using a relative pathname + Fixed some typos in the documentation (Greg). + Fixed a problem with value of "channels" returned by png_read_update_info() +version 1.0.1a [April 21, 1998] + Optimized Paeth calculations by replacing abs() function calls with intrinsics + plus other loop optimizations. Improves avg decoding speed by about 20%. + Commented out i386istic "align" compiler flags in makefile.lnx. + Reduced the default warning level in some makefiles, to make them consistent. + Removed references to IJG and JPEG in the ansi2knr.c copyright statement. + Fixed a bug in png_do_strip_filler with XXRRGGBB => RRGGBB transformation. + Added grayscale and 16-bit capability to png_do_read_filler(). + Fixed a bug in pngset.c, introduced in version 0.99c, that sets rowbytes + too large when writing an image with bit_depth < 8 (Bob Dellaca). + Corrected some bugs in the experimental weighted filtering heuristics. + Moved a misplaced pngrutil code block that truncates tRNS if it has more + than num_palette entries -- test was done before num_palette was defined. + Fixed a png_convert_to_rfc1123() bug that converts day 31 to 0 (Steve Eddins). + Changed compiler flags in makefile.wat for better optimization (Pawel Mrochen). +version 1.0.1b [May 2, 1998] + Relocated png_do_gray_to_rgb() within png_do_read_transformations() (Greg). + Relocated the png_composite macros from pngrtran.c to png.h (Greg). + Added makefile.sco (contributed by Mike Hopkirk). + Fixed two bugs (missing definitions of "istop") introduced in libpng-1.0.1a. + Fixed a bug in pngrtran.c that would set channels=5 under some circumstances. + More work on the Paeth-filtering, achieving imperceptible speedup (A Kleinert). + More work on loop optimization which may help when compiled with C++ compilers. + Added warnings when people try to use transforms they've defined out. + Collapsed 4 "i" and "c" loops into single "i" loops in pngrtran and pngwtran. + Revised paragraph about png_set_expand() in libpng.txt and libpng.3 (Greg) +version 1.0.1c [May 11, 1998] + Fixed a bug in pngrtran.c (introduced in libpng-1.0.1a) where the masks for + filler bytes should have been 0xff instead of 0xf. + Added max_pixel_depth=32 in pngrutil.c when using FILLER with palette images. + Moved PNG_WRITE_WEIGHTED_FILTER_SUPPORTED and PNG_WRITE_FLUSH_SUPPORTED + out of the PNG_WRITE_TRANSFORMS_NOT_SUPPORTED block of pngconf.h + Added "PNG_NO_WRITE_TRANSFORMS" etc., as alternatives for *_NOT_SUPPORTED, + for consistency, in pngconf.h + Added individual "ifndef PNG_NO_[CAPABILITY]" in pngconf.h to make it easier + to remove unwanted capabilities via the compile line + Made some corrections to grammar (which, it's) in documentation (Greg). + Corrected example.c, use of row_pointers in png_write_image(). +version 1.0.1d [May 24, 1998] + Corrected several statements that used side effects illegally in pngrutil.c + and pngtrans.c, that were introduced in version 1.0.1b + Revised png_read_rows() to avoid repeated if-testing for NULL (A Kleinert) + More corrections to example.c, use of row_pointers in png_write_image() + and png_read_rows(). + Added pngdll.mak and pngdef.pas to scripts directory, contributed by + Bob Dellaca, to make a png32bd.dll with Borland C++ 4.5 + Fixed error in example.c with png_set_text: num_text is 3, not 2 (Guido V.) + Changed several loops from count-down to count-up, for consistency. +version 1.0.1e [June 6, 1998] + Revised libpng.txt and libpng.3 description of png_set_read|write_fn(), and + added warnings when people try to set png_read_fn and png_write_fn in + the same structure. + Added a test such that png_do_gamma will be done when num_trans==0 + for truecolor images that have defined a background. This corrects an + error that was introduced in libpng-0.90 that can cause gamma processing + to be skipped. + Added tests in png.h to include "trans" and "trans_values" in structures + when PNG_READ_BACKGROUND_SUPPORTED or PNG_READ_EXPAND_SUPPORTED is defined. + Add png_free(png_ptr->time_buffer) in png_destroy_read_struct() + Moved png_convert_to_rfc_1123() from pngwrite.c to png.c + Added capability for user-provided malloc_fn() and free_fn() functions, + and revised pngtest.c to demonstrate their use, replacing the + PNGTEST_DEBUG_MEM feature. + Added makefile.w32, for Microsoft C++ 4.0 and later (Tim Wegner). + +version 1.0.2 [June 14, 1998] + Fixed two bugs in makefile.bor . +version 1.0.2a [December 30, 1998] + Replaced and extended code that was removed from png_set_filler() in 1.0.1a. + Fixed a bug in png_do_filler() that made it fail to write filler bytes in + the left-most pixel of each row (Kevin Bracey). + Changed "static pngcharp tIME_string" to "static char tIME_string[30]" + in pngtest.c (Duncan Simpson). + Fixed a bug in pngtest.c that caused pngtest to try to write a tIME chunk + even when no tIME chunk was present in the source file. + Fixed a problem in pngrutil.c: gray_to_rgb didn't always work with 16-bit. + Fixed a problem in png_read_push_finish_row(), which would not skip some + passes that it should skip, for images that are less than 3 pixels high. + Interchanged the order of calls to png_do_swap() and png_do_shift() + in pngwtran.c (John Cromer). + Added #ifdef PNG_DEBUG/#endif surrounding use of PNG_DEBUG in png.h . + Changed "bad adaptive filter type" from error to warning in pngrutil.c . + Fixed a documentation error about default filtering with 8-bit indexed-color. + Separated the PNG_NO_STDIO macro into PNG_NO_STDIO and PNG_NO_CONSOLE_IO + (L. Peter Deutsch). + Added png_set_rgb_to_gray() and png_get_rgb_to_gray_status() functions. + Added png_get_copyright() and png_get_header_version() functions. + Revised comments on png_set_progressive_read_fn() in libpng.txt and example.c + Added information about debugging in libpng.txt and libpng.3 . + Changed "ln -sf" to "ln -s -f" in makefile.s2x, makefile.lnx, and makefile.sco. + Removed lines after Dynamic Dependencies" in makefile.aco . + Revised makefile.dec to make a shared library (Jeremie Petit). + Removed trailing blanks from all files. +version 1.0.2a [January 6, 1999] + Removed misplaced #endif and #ifdef PNG_NO_EXTERN near the end of png.h + Added "if" tests to silence complaints about unused png_ptr in png.h and png.c + Changed "check_if_png" function in example.c to return true (nonzero) if PNG. + Changed libpng.txt to demonstrate png_sig_cmp() instead of png_check_sig() + which is obsolete. + +version 1.0.3 [January 14, 1999] + Added makefile.hux, for Hewlett Packard HPUX 10.20 and 11.00 (Jim Rice) + Added a statement of Y2K compliance in png.h, libpng.3, and Y2KINFO. +version 1.0.3a [August 12, 1999] + Added check for PNG_READ_INTERLACE_SUPPORTED in pngread.c; issue a warning + if an attempt is made to read an interlaced image when it's not supported. + Added check if png_ptr->trans is defined before freeing it in pngread.c + Modified the Y2K statement to include versions back to version 0.71 + Fixed a bug in the check for valid IHDR bit_depth/color_types in pngrutil.c + Modified makefile.wat (added -zp8 flag, ".symbolic", changed some comments) + Replaced leading blanks with tab characters in makefile.hux + Changed "dworkin.wustl.edu" to "ccrc.wustl.edu" in various documents. + Changed (float)red and (float)green to (double)red, (double)green + in png_set_rgb_to_gray() to avoid "promotion" problems in AIX. + Fixed a bug in pngconf.h that omitted <stdio.h> when PNG_DEBUG==0 (K Bracey). + Reformatted libpng.3 and libpngpf.3 with proper fonts (script by J. vanZandt). + Updated documentation to refer to the PNG-1.2 specification. + Removed ansi2knr.c and left pointers to the latest source for ansi2knr.c + in makefile.knr, INSTALL, and README (L. Peter Deutsch) + Fixed bugs in calculation of the length of rowbytes when adding alpha + channels to 16-bit images, in pngrtran.c (Chris Nokleberg) + Added function png_set_user_transform_info() to store user_transform_ptr, + user_depth, and user_channels into the png_struct, and a function + png_get_user_transform_ptr() to retrieve the pointer (Chris Nokleberg) + Added function png_set_empty_plte_permitted() to make libpng useable + in MNG applications. + Corrected the typedef for png_free_ptr in png.h (Jesse Jones). + Correct gamma with srgb is 45455 instead of 45000 in pngrutil.c, to be + consistent with PNG-1.2, and allow variance of 500 before complaining. + Added assembler code contributed by Intel in file pngvcrd.c and modified + makefile.w32 to use it (Nirav Chhatrapati, INTEL Corporation, Gilles Vollant) + Changed "ln -s -f" to "ln -f -s" in the makefiles to make Solaris happy. + Added some aliases for png_set_expand() in pngrtran.c, namely + png_set_expand_PLTE(), png_set_expand_depth(), and png_set_expand_tRNS() + (Greg Roelofs, in "PNG: The Definitive Guide"). + Added makefile.beo for BEOS on X86, contributed by Sander Stok. +version 1.0.3b [August 26, 1999] + Replaced 2147483647L several places with PNG_MAX_UINT macro, defined in png.h + Changed leading blanks to tabs in all makefiles. + Define PNG_USE_PNGVCRD in makefile.w32, to get MMX assembler code. + Made alternate versions of png_set_expand() in pngrtran.c, namely + png_set_gray_1_2_4_to_8, png_set_palette_to_rgb, and png_set_tRNS_to_alpha + (Greg Roelofs, in "PNG: The Definitive Guide"). Deleted the 1.0.3a aliases. + Relocated start of 'extern "C"' block in png.h so it doesn't include pngconf.h + Revised calculation of num_blocks in pngmem.c to avoid a potentially + negative shift distance, whose results are undefined in the C language. + Added a check in pngset.c to prevent writing multiple tIME chunks. + Added a check in pngwrite.c to detect invalid small window_bits sizes. +version 1.0.3d [September 4, 1999] + Fixed type casting of igamma in pngrutil.c + Added new png_expand functions to scripts/pngdef.pas and pngos2.def + Added a demo read_user_transform_fn that examines the row filters in pngtest.c + +version 1.0.4 [September 24, 1999] + Define PNG_ALWAYS_EXTERN in pngconf.h if __STDC__ is defined + Delete #define PNG_INTERNAL and include "png.h" from pngasmrd.h + Made several minor corrections to pngtest.c + Renamed the makefiles with longer but more user friendly extensions. + Copied the PNG copyright and license to a separate LICENSE file. + Revised documentation, png.h, and example.c to remove reference to + "viewing_gamma" which no longer appears in the PNG specification. + Revised pngvcrd.c to use MMX code for interlacing only on the final pass. + Updated pngvcrd.c to use the faster C filter algorithms from libpng-1.0.1a + Split makefile.win32vc into two versions, makefile.vcawin32 (uses MMX + assembler code) and makefile.vcwin32 (doesn't). + Added a CPU timing report to pngtest.c (enabled by defining PNGTEST_TIMING) + Added a copy of pngnow.png to the distribution. +version 1.0.4a [September 25, 1999] + Increase max_pixel_depth in pngrutil.c if a user transform needs it. + Changed several division operations to right-shifts in pngvcrd.c +version 1.0.4b [September 30, 1999] + Added parentheses in line 3732 of pngvcrd.c + Added a comment in makefile.linux warning about buggy -O3 in pgcc 2.95.1 +version 1.0.4c [October 1, 1999] + Added a "png_check_version" function in png.c and pngtest.c that will generate + a helpful compiler error if an old png.h is found in the search path. + Changed type of png_user_transform_depth|channels from int to png_byte. +version 1.0.4d [October 6, 1999] + Changed 0.45 to 0.45455 in png_set_sRGB() + Removed unused PLTE entries from pngnow.png + Re-enabled some parts of pngvcrd.c (png_combine_row) that work properly. +version 1.0.4e [October 10, 1999] + Fixed sign error in pngvcrd.c (Greg Roelofs) + Replaced some instances of memcpy with simple assignments in pngvcrd (GR-P) +version 1.0.4f [October 15, 1999] + Surrounded example.c code with #if 0 .. #endif to prevent people from + inadvertently trying to compile it. + Changed png_get_header_version() from a function to a macro in png.h + Added type casting mostly in pngrtran.c and pngwtran.c + Removed some pointless "ptr = NULL" in pngmem.c + Added a "contrib" directory containing the source code from Greg's book. + +version 1.0.5 [October 15, 1999] + Minor editing of the INSTALL and README files. +version 1.0.5a [October 23, 1999] + Added contrib/pngsuite and contrib/pngminus (Willem van Schaik) + Fixed a typo in the png_set_sRGB() function call in example.c (Jan Nijtmans) + Further optimization and bugfix of pngvcrd.c + Revised pngset.c so that it does not allocate or free memory in the user's + text_ptr structure. Instead, it makes its own copy. + Created separate write_end_info_struct in pngtest.c for a more severe test. + Added code in pngwrite.c to free info_ptr->text[i].key to stop a memory leak. +version 1.0.5b [November 23, 1999] + Moved PNG_FLAG_HAVE_CHUNK_HEADER, PNG_FLAG_BACKGROUND_IS_GRAY and + PNG_FLAG_WROTE_tIME from flags to mode. + Added png_write_info_before_PLTE() function. + Fixed some typecasting in contrib/gregbook/*.c + Updated scripts/makevms.com and added makevms.com to contrib/gregbook + and contrib/pngminus (Martin Zinser) +version 1.0.5c [November 26, 1999] + Moved png_get_header_version from png.h to png.c, to accommodate ansi2knr. + Removed all global arrays (according to PNG_NO_GLOBAL_ARRAYS macro), to + accommodate making DLL's: Moved usr_png_ver from global variable to function + png_get_header_ver() in png.c. Moved png_sig to png_sig_bytes in png.c and + eliminated use of png_sig in pngwutil.c. Moved the various png_CHNK arrays + into pngtypes.h. Eliminated use of global png_pass arrays. Declared the + png_CHNK and png_pass arrays to be "const". Made the global arrays + available to applications (although none are used in libpng itself) when + PNG_NO_GLOBAL_ARRAYS is not defined or when PNG_GLOBAL_ARRAYS is defined. + Removed some extraneous "-I" from contrib/pngminus/makefile.std + Changed the PNG_sRGB_INTENT macros in png.h to be consistent with PNG-1.2. + Change PNG_SRGB_INTENT to PNG_sRGB_INTENT in libpng.txt and libpng.3 +version 1.0.5d [November 29, 1999] + Add type cast (png_const_charp) two places in png.c + Eliminated pngtypes.h; use macros instead to declare PNG_CHNK arrays. + Renamed "PNG_GLOBAL_ARRAYS" to "PNG_USE_GLOBAL_ARRAYS" and made available + to applications a macro "PNG_USE_LOCAL_ARRAYS". + Remove all the new declarations with #ifdef/#endif when + PNG_USE_GLOBAL_ARRAYS is defined. + Added PNG_EXPORT_VAR macro to accommodate making DLL's. +version 1.0.5e [November 30, 1999] + Added iCCP, iTXt, and sPLT support; added "lang" member to the png_text + structure; refactored the inflate/deflate support to make adding new chunks + with trailing compressed parts easier in the future, and added new functions + png_free_iCCP, png_free_pCAL, png_free_sPLT, png_free_text, png_get_iCCP, + png_get_spalettes, png_set_iCCP, png_set_spalettes (Eric S. Raymond). + NOTE: Applications that write text chunks MUST define png_text->lang + before calling png_set_text(). It must be set to NULL if you want to + write tEXt or zTXt chunks. If you want your application to be able to + run with older versions of libpng, use + + #ifdef PNG_iTXt_SUPPORTED + png_text[i].lang = NULL; + #endif + + Changed png_get_oFFs() and png_set_oFFs() to use signed rather than unsigned + offsets (Eric S. Raymond). + Combined PNG_READ_cHNK_SUPPORTED and PNG_WRITE_cHNK_SUPPORTED macros into + PNG_cHNK_SUPPORTED and combined the three types of PNG_text_SUPPORTED + macros, leaving the separate macros also available. + Removed comments on #endifs at the end of many short, non-nested #if-blocks. +version 1.0.5f [December 6, 1999] + Changed makefile.solaris to issue a warning about potential problems when + the ucb "ld" is in the path ahead of the ccs "ld". + Removed "- [date]" from the "synopsis" line in libpng.3 and libpngpf.3. + Added sCAL chunk support (Eric S. Raymond). +version 1.0.5g [December 7, 1999] + Fixed "png_free_spallettes" typo in png.h + Added code to handle new chunks in pngpread.c + Moved PNG_CHNK string macro definitions outside of PNG_NO_EXTERN block + Added "translated_key" to png_text structure and png_write_iTXt(). + Added code in pngwrite.c to work around a newly discovered zlib bug. +version 1.0.5h [December 10, 1999] + NOTE: regarding the note for version 1.0.5e, the following must also + be included in your code: + png_text[i].translated_key = NULL; + Unknown chunk handling is now supported. + Option to eliminate all floating point support was added. Some new + fixed-point functions such as png_set_gAMA_fixed() were added. + Expanded tabs and removed trailing blanks in source files. +version 1.0.5i [December 13, 1999] + Added some type casts to silence compiler warnings. + Renamed "png_free_spalette" to "png_free_spalettes" for consistency. + Removed leading blanks from a #define in pngvcrd.c + Added some parameters to the new png_set_keep_unknown_chunks() function. + Added a test for up->location != 0 in the first instance of writing + unknown chunks in pngwrite.c + Changed "num" to "i" in png_free_spalettes() and png_free_unknowns() to + prevent recursion. + Added png_free_hIST() function. + Various patches to fix bugs in the sCAL and integer cHRM processing, + and to add some convenience macros for use with sCAL. +version 1.0.5j [December 21, 1999] + Changed "unit" parameter of png_write_sCAL from png_byte to int, to work + around buggy compilers. + Added new type "png_fixed_point" for integers that hold float*100000 values + Restored backward compatibility of tEXt/zTXt chunk processing: + Restored the first four members of png_text to the same order as v.1.0.5d. + Added members "lang_key" and "itxt_length" to png_text struct. Set + text_length=0 when "text" contains iTXt data. Use the "compression" + member to distinguish among tEXt/zTXt/iTXt types. Added + PNG_ITXT_COMPRESSION_NONE (1) and PNG_ITXT_COMPRESSION_zTXt(2) macros. + The "Note" above, about backward incompatibility of libpng-1.0.5e, no + longer applies. + Fixed png_read|write_iTXt() to read|write parameters in the right order, + and to write the iTXt chunk after IDAT if it appears in the end_ptr. + Added pnggccrd.c, version of pngvcrd.c Intel assembler for gcc (Greg Roelofs) + Reversed the order of trying to write floating-point and fixed-point gAMA. +version 1.0.5k [December 27, 1999] + Added many parentheses, e.g., "if (a && b & c)" becomes "if (a && (b & c))" + Added png_handle_as_unknown() function (Glenn) + Added png_free_chunk_list() function and chunk_list and num_chunk_list members + of png_ptr. + Eliminated erroneous warnings about multiple sPLT chunks and sPLT-after-PLTE. + Fixed a libpng-1.0.5h bug in pngrutil.c that was issuing erroneous warnings + about ignoring incorrect gAMA with sRGB (gAMA was in fact not ignored) + Added png_free_tRNS(); png_set_tRNS() now malloc's its own trans array (ESR). + Define png_get_int_32 when oFFs chunk is supported as well as when pCAL is. + Changed type of proflen from png_int_32 to png_uint_32 in png_get_iCCP(). +version 1.0.5l [January 1, 2000] + Added functions png_set_read_user_chunk_fn() and png_get_user_chunk_ptr() + for setting a callback function to handle unknown chunks and for + retrieving the associated user pointer (Glenn). +version 1.0.5m [January 7, 2000] + Added high-level functions png_read_png(), png_write_png(), png_free_pixels(). +version 1.0.5n [January 9, 2000] + Added png_free_PLTE() function, and modified png_set_PLTE() to malloc its + own memory for info_ptr->palette. This makes it safe for the calling + application to free its copy of the palette any time after it calls + png_set_PLTE(). +version 1.0.5o [January 20, 2000] + Cosmetic changes only (removed some trailing blanks and TABs) +version 1.0.5p [January 31, 2000] + Renamed pngdll.mak to makefile.bd32 + Cosmetic changes in pngtest.c +version 1.0.5q [February 5, 2000] + Relocated the makefile.solaris warning about PATH problems. + Fixed pngvcrd.c bug by pushing/popping registers in mmxsupport (Bruce Oberg) + Revised makefile.gcmmx + Added PNG_SETJMP_SUPPORTED, PNG_SETJMP_NOT_SUPPORTED, and PNG_ABORT() macros +version 1.0.5r [February 7, 2000] + Removed superfluous prototype for png_get_itxt from png.h + Fixed a bug in pngrtran.c that improperly expanded the background color. + Return *num_text=0 from png_get_text() when appropriate, and fix documentation + of png_get_text() in libpng.txt/libpng.3. +version 1.0.5s [February 18, 2000] + Added "png_jmp_env()" macro to pngconf.h, to help people migrate to the + new error handler that's planned for the next libpng release, and changed + example.c, pngtest.c, and contrib programs to use this macro. + Revised some of the DLL-export macros in pngconf.h (Greg Roelofs) + Fixed a bug in png_read_png() that caused it to fail to expand some images + that it should have expanded. + Fixed some mistakes in the unused and undocumented INCH_CONVERSIONS functions + in pngget.c + Changed the allocation of palette, history, and trans arrays back to + the version 1.0.5 method (linking instead of copying) which restores + backward compatibility with version 1.0.5. Added some remarks about + that in example.c. Added "free_me" member to info_ptr and png_ptr + and added png_free_data() function. + Updated makefile.linux and makefile.gccmmx to make directories conditionally. + Made cosmetic changes to pngasmrd.h + Added png_set_rows() and png_get_rows(), for use with png_read|write_png(). + Modified png_read_png() to allocate info_ptr->row_pointers only if it + hasn't already been allocated. +version 1.0.5t [March 4, 2000] + Changed png_jmp_env() migration aiding macro to png_jmpbuf(). + Fixed "interlace" typo (should be "interlaced") in contrib/gregbook/read2-x.c + Fixed bug with use of PNG_BEFORE_IHDR bit in png_ptr->mode, introduced when + PNG_FLAG_HAVE_CHUNK_HEADER was moved into png_ptr->mode in version 1.0.5b + Files in contrib/gregbook were revised to use png_jmpbuf() and to select + a 24-bit visual if one is available, and to allow abbreviated options. + Files in contrib/pngminus were revised to use the png_jmpbuf() macro. + Removed spaces in makefile.linux and makefile.gcmmx, introduced in 1.0.5s +version 1.0.5u [March 5, 2000] + Simplified the code that detects old png.h in png.c and pngtest.c + Renamed png_spalette (_p, _pp) to png_sPLT_t (_tp, _tpp) + Increased precision of rgb_to_gray calculations from 8 to 15 bits and + added png_set_rgb_to_gray_fixed() function. + Added makefile.bc32 (32-bit Borland C++, C mode) +version 1.0.5v [March 11, 2000] + Added some parentheses to the png_jmpbuf macro definition. + Updated references to the zlib home page, which has moved to freesoftware.com. + Corrected bugs in documentation regarding png_read_row() and png_write_row(). + Updated documentation of png_rgb_to_gray calculations in libpng.3/libpng.txt. + Renamed makefile.borland,turboc3 back to makefile.bor,tc3 as in version 1.0.3, + revised borland makefiles; added makefile.ibmvac3 and makefile.gcc (Cosmin) + +version 1.0.6 [March 20, 2000] + Minor revisions of makefile.bor, libpng.txt, and gregbook/rpng2-win.c + Added makefile.sggcc (SGI IRIX with gcc) +version 1.0.6d [April 7, 2000] + Changed sprintf() to strcpy() in png_write_sCAL_s() to work without STDIO + Added data_length parameter to png_decompress_chunk() function + Revised documentation to remove reference to abandoned png_free_chnk functions + Fixed an error in png_rgb_to_gray_fixed() + Revised example.c, usage of png_destroy_write_struct(). + Renamed makefile.ibmvac3 to makefile.ibmc, added libpng.icc IBM project file + Added a check for info_ptr->free_me&PNG_FREE_TEXT when freeing text in png.c + Simplify png_sig_bytes() function to remove use of non-ISO-C strdup(). +version 1.0.6e [April 9, 2000] + Added png_data_freer() function. + In the code that checks for over-length tRNS chunks, added check of + info_ptr->num_trans as well as png_ptr->num_trans (Matthias Benckmann) + Minor revisions of libpng.txt/libpng.3. + Check for existing data and free it if the free_me flag is set, in png_set_*() + and png_handle_*(). + Only define PNG_WEIGHTED_FILTERS_SUPPORTED when PNG_FLOATING_POINT_SUPPORTED + is defined. + Changed several instances of PNG_NO_CONSOLE_ID to PNG_NO_STDIO in pngrutil.c + and mentioned the purposes of the two macros in libpng.txt/libpng.3. +version 1.0.6f [April 14, 2000] + Revised png_set_iCCP() and png_set_rows() to avoid prematurely freeing data. + Add checks in png_set_text() for NULL members of the input text structure. + Revised libpng.txt/libpng.3. + Removed superfluous prototype for png_set_itxt from png.h + Removed "else" from pngread.c, after png_error(), and changed "0" to "length". + Changed several png_errors about malformed ancillary chunks to png_warnings. +version 1.0.6g [April 24, 2000] + Added png_pass-* arrays to pnggccrd.c when PNG_USE_LOCAL_ARRAYS is defined. + Relocated paragraph about png_set_background() in libpng.3/libpng.txt + and other revisions (Matthias Benckmann) + Relocated info_ptr->free_me, png_ptr->free_me, and other info_ptr and + png_ptr members to restore binary compatibility with libpng-1.0.5 + (breaks compatibility with libpng-1.0.6). +version 1.0.6h [April 24, 2000] + Changed shared library so-number pattern from 2.x.y.z to xy.z (this builds + libpng.so.10 & libpng.so.10.6h instead of libpng.so.2 & libpng.so.2.1.0.6h) + This is a temporary change for test purposes. +version 1.0.6i [May 2, 2000] + Rearranged some members at the end of png_info and png_struct, to put + unknown_chunks_num and free_me within the original size of the png_structs + and free_me, png_read_user_fn, and png_free_fn within the original png_info, + because some old applications allocate the structs directly instead of + using png_create_*(). + Added documentation of user memory functions in libpng.txt/libpng.3 + Modified png_read_png so that it will use user_allocated row_pointers + if present, unless free_me directs that it be freed, and added description + of the use of png_set_rows() and png_get_rows() in libpng.txt/libpng.3. + Added PNG_LEGACY_SUPPORTED macro, and #ifdef out all new (since version + 1.00) members of png_struct and png_info, to regain binary compatibility + when you define this macro. Capabilities lost in this event + are user transforms (new in version 1.0.0),the user transform pointer + (new in version 1.0.2), rgb_to_gray (new in 1.0.5), iCCP, sCAL, sPLT, + the high-level interface, and unknown chunks support (all new in 1.0.6). + This was necessary because of old applications that allocate the structs + directly as authors were instructed to do in libpng-0.88 and earlier, + instead of using png_create_*(). + Added modes PNG_CREATED_READ_STRUCT and PNG_CREATED_WRITE_STRUCT which + can be used to detect codes that directly allocate the structs, and + code to check these modes in png_read_init() and png_write_init() and + generate a libpng error if the modes aren't set and PNG_LEGACY_SUPPORTED + was not defined. + Added makefile.intel and updated makefile.watcom (Pawel Mrochen) +version 1.0.6j [May 3, 2000] + Overloaded png_read_init() and png_write_init() with macros that convert + calls to png_read_init_2() or png_write_init_2() that check the version + and structure sizes. +version 1.0.7beta11 [May 7, 2000] + Removed the new PNG_CREATED_READ_STRUCT and PNG_CREATED_WRITE_STRUCT modes + which are no longer used. + Eliminated the three new members of png_text when PNG_LEGACY_SUPPORTED is + defined or when neither PNG_READ_iTXt_SUPPORTED nor PNG_WRITE_iTXT_SUPPORTED + is defined. + Made PNG_NO_READ|WRITE_iTXt the default setting, to avoid memory + overrun when old applications fill the info_ptr->text structure directly. + Added PNGAPI macro, and added it to the definitions of all exported functions. + Relocated version macro definitions ahead of the includes of zlib.h and + pngconf.h in png.h. +version 1.0.7beta12 [May 12, 2000] + Revised pngset.c to avoid a problem with expanding the png_debug macro. + Deleted some extraneous defines from pngconf.h + Made PNG_NO_CONSOLE_IO the default condition when PNG_BUILD_DLL is defined. + Use MSC _RPTn debugging instead of fprintf if _MSC_VER is defined. + Added png_access_version_number() function. + Check for mask&PNG_FREE_CHNK (for TEXT, SCAL, PCAL) in png_free_data(). + Expanded libpng.3/libpng.txt information about png_data_freer(). +version 1.0.7beta14 [May 17, 2000] (beta13 was not published) + Changed pnggccrd.c and pngvcrd.c to handle bad adaptive filter types as + warnings instead of errors, as pngrutil.c does. + Set the PNG_INFO_IDAT valid flag in png_set_rows() so png_write_png() + will actually write IDATs. + Made the default PNG_USE_LOCAL_ARRAYS depend on PNG_DLL instead of WIN32. + Make png_free_data() ignore its final parameter except when freeing data + that can have multiple instances (text, sPLT, unknowns). + Fixed a new bug in png_set_rows(). + Removed info_ptr->valid tests from png_free_data(), as in version 1.0.5. + Added png_set_invalid() function. + Fixed incorrect illustrations of png_destroy_write_struct() in example.c. +version 1.0.7beta15 [May 30, 2000] + Revised the deliberately erroneous Linux setjmp code in pngconf.h to produce + fewer error messages. + Rearranged checks for Z_OK to check the most likely path first in pngpread.c + and pngwutil.c. + Added checks in pngtest.c for png_create_*() returning NULL, and mentioned + in libpng.txt/libpng.3 the need for applications to check this. + Changed names of png_default_*() functions in pngtest to pngtest_*(). + Changed return type of png_get_x|y_offset_*() from png_uint_32 to png_int_32. + Fixed some bugs in the unused PNG_INCH_CONVERSIONS functions in pngget.c + Set each pointer to NULL after freeing it in png_free_data(). + Worked around a problem in pngconf.h; AIX's strings.h defines an "index" + macro that conflicts with libpng's png_color_16.index. (Dimitri Papadapoulos) + Added "msvc" directory with MSVC++ project files (Simon-Pierre Cadieux). +version 1.0.7beta16 [June 4, 2000] + Revised the workaround of AIX string.h "index" bug. + Added a check for overlength PLTE chunk in pngrutil.c. + Added PNG_NO_POINTER_INDEXING macro to use array-indexing instead of pointer + indexing in pngrutil.c and pngwutil.c to accommodate a buggy compiler. + Added a warning in png_decompress_chunk() when it runs out of data, e.g. + when it tries to read an erroneous PhotoShop iCCP chunk. + Added PNG_USE_DLL macro. + Revised the copyright/disclaimer/license notice. + Added contrib/msvctest directory +version 1.0.7rc1 [June 9, 2000] + Corrected the definition of PNG_TRANSFORM_INVERT_ALPHA (0x0400 not 0x0200) + Added contrib/visupng directory (Willem van Schaik) +version 1.0.7beta18 [June 23, 2000] + Revised PNGAPI definition, and pngvcrd.c to work with __GCC__ + and do not redefine PNGAPI if it is passed in via a compiler directive. + Revised visupng/PngFile.c to remove returns from within the Try block. + Removed leading underscores from "_PNG_H" and "_PNG_SAVE_BSD_SOURCE" macros. + Updated contrib/visupng/cexcept.h to version 1.0.0. + Fixed bugs in pngwrite.c and pngwutil.c that prevented writing iCCP chunks. +version 1.0.7rc2 [June 28, 2000] + Updated license to include disclaimers required by UCITA. + Fixed "DJBPP" typo in pnggccrd.c introduced in beta18. + +version 1.0.7 [July 1, 2000] + Revised the definition of "trans_values" in libpng.3/libpng.txt +version 1.0.8beta1 [July 8, 2000] + Added png_free(png_ptr, key) two places in pngpread.c to stop memory leaks. + Changed PNG_NO_STDIO to PNG_NO_CONSOLE_IO, several places in pngrutil.c and + pngwutil.c. + Changed PNG_EXPORT_VAR to use PNG_IMPEXP, in pngconf.h. + Removed unused "#include <assert.h>" from png.c + Added WindowsCE support. + Revised pnggccrd.c to work with gcc-2.95.2 and in the Cygwin environment. +version 1.0.8beta2 [July 10, 2000] + Added project files to the wince directory and made further revisions + of pngtest.c, pngrio.c, and pngwio.c in support of WindowsCE. +version 1.0.8beta3 [July 11, 2000] + Only set the PNG_FLAG_FREE_TRNS or PNG_FREE_TRNS flag in png_handle_tRNS() + for indexed-color input files to avoid potential double-freeing trans array + under some unusual conditions; problem was introduced in version 1.0.6f. + Further revisions to pngtest.c and files in the wince subdirectory. +version 1.0.8beta4 [July 14, 2000] + Added the files pngbar.png and pngbar.jpg to the distribution. + Added makefile.cygwin, and cygwin support in pngconf.h + Added PNG_NO_ZALLOC_ZERO macro (makes png_zalloc skip zeroing memory) +version 1.0.8rc1 [July 16, 2000] + Revised png_debug() macros and statements to eliminate compiler warnings. + +version 1.0.8 [July 24, 2000] + Added png_flush() in pngwrite.c, after png_write_IEND(). + Updated makefile.hpux to build a shared library. +version 1.0.9beta1 [November 10, 2000] + Fixed typo in scripts/makefile.hpux + Updated makevms.com in scripts and contrib/* and contrib/* (Martin Zinser) + Fixed seqence-point bug in contrib/pngminus/png2pnm (Martin Zinser) + Changed "cdrom.com" in documentation to "libpng.org" + Revised pnggccrd.c to get it all working, and updated makefile.gcmmx (Greg). + Changed type of "params" from voidp to png_voidp in png_read|write_png(). + Make sure PNGAPI and PNG_IMPEXP are defined in pngconf.h. + Revised the 3 instances of WRITEFILE in pngtest.c. + Relocated "msvc" and "wince" project subdirectories into "dll" subdirectory. + Updated png.rc in dll/msvc project + Revised makefile.dec to define and use LIBPATH and INCPATH + Increased size of global png_libpng_ver[] array from 12 to 18 chars. + Made global png_libpng_ver[], png_sig[] and png_pass_*[] arrays const. + Removed duplicate png_crc_finish() from png_handle_bKGD() function. + Added a warning when application calls png_read_update_info() multiple times. + Revised makefile.cygwin + Fixed bugs in iCCP support in pngrutil.c and pngwutil.c. + Replaced png_set_empty_plte_permitted() with png_permit_mng_features(). +version 1.0.9beta2 [November 19, 2000] + Renamed the "dll" subdirectory "projects". + Added borland project files to "projects" subdirectory. + Set VS_FF_PRERELEASE and VS_FF_PATCHED flags in msvc/png.rc when appropriate. + Add error message in png_set_compression_buffer_size() when malloc fails. +version 1.0.9beta3 [November 23, 2000] + Revised PNG_LIBPNG_BUILD_TYPE macro in png.h, used in the msvc project. + Removed the png_flush() in pngwrite.c that crashes some applications + that don't set png_output_flush_fn. + Added makefile.macosx and makefile.aix to scripts directory. +version 1.0.9beta4 [December 1, 2000] + Change png_chunk_warning to png_warning in png_check_keyword(). + Increased the first part of msg buffer from 16 to 18 in png_chunk_error(). +version 1.0.9beta5 [December 15, 2000] + Added support for filter method 64 (for PNG datastreams embedded in MNG). +version 1.0.9beta6 [December 18, 2000] + Revised png_set_filter() to accept filter method 64 when appropriate. + Added new PNG_HAVE_PNG_SIGNATURE bit to png_ptr->mode and use it to + help prevent applications from using MNG features in PNG datastreams. + Added png_permit_mng_features() function. + Revised libpng.3/libpng.txt. Changed "filter type" to "filter method". +version 1.0.9rc1 [December 23, 2000] + Revised test for PNG_HAVE_PNG_SIGNATURE in pngrutil.c + Fixed error handling of unknown compression type in png_decompress_chunk(). + In pngconf.h, define __cdecl when _MSC_VER is defined. +version 1.0.9beta7 [December 28, 2000] + Changed PNG_TEXT_COMPRESSION_zTXt to PNG_COMPRESSION_TYPE_BASE several places. + Revised memory management in png_set_hIST and png_handle_hIST in a backward + compatible manner. PLTE and tRNS were revised similarly. + Revised the iCCP chunk reader to ignore trailing garbage. +version 1.0.9beta8 [January 12, 2001] + Moved pngasmrd.h into pngconf.h. + Improved handling of out-of-spec garbage iCCP chunks generated by PhotoShop. +version 1.0.9beta9 [January 15, 2001] + Added png_set_invalid, png_permit_mng_features, and png_mmx_supported to + wince and msvc project module definition files. + Minor revision of makefile.cygwin. + Fixed bug with progressive reading of narrow interlaced images in pngpread.c +version 1.0.9beta10 [January 16, 2001] + Do not typedef png_FILE_p in pngconf.h when PNG_NO_STDIO is defined. + Fixed "png_mmx_supported" typo in project definition files. +version 1.0.9beta11 [January 19, 2001] + Updated makefile.sgi to make shared library. + Removed png_mmx_support() function and disabled PNG_MNG_FEATURES_SUPPORTED + by default, for the benefit of DLL forward compatibility. These will + be re-enabled in version 1.2.0. +version 1.0.9rc2 [January 22, 2001] + Revised cygwin support. + +version 1.0.9 [January 31, 2001] + Added check of cygwin's ALL_STATIC in pngconf.h + Added "-nommx" parameter to contrib/gregbook/rpng2-win and rpng2-x demos. +version 1.0.10beta1 [March 14, 2001] + Revised makefile.dec, makefile.sgi, and makefile.sggcc; added makefile.hpgcc. + Reformatted libpng.3 to eliminate bad line breaks. + Added checks for _mmx_supported in the read_filter_row function of pnggccrd.c + Added prototype for png_mmx_support() near the top of pnggccrd.c + Moved some error checking from png_handle_IHDR to png_set_IHDR. + Added PNG_NO_READ_SUPPORTED and PNG_NO_WRITE_SUPPORTED macros. + Revised png_mmx_support() function in pnggccrd.c + Restored version 1.0.8 PNG_WRITE_EMPTY_PLTE_SUPPORTED behavior in pngwutil.c + Fixed memory leak in contrib/visupng/PngFile.c + Fixed bugs in png_combine_row() in pnggccrd.c and pngvcrd.c (C version) + Added warnings when retrieving or setting gamma=0. + Increased the first part of msg buffer from 16 to 18 in png_chunk_warning(). +version 1.0.10rc1 [March 23, 2001] + Changed all instances of memcpy, strcpy, and strlen to png_memcpy, png_strcpy, + and png_strlen. + Revised png_mmx_supported() function in pnggccrd.c to return proper value. + Fixed bug in progressive reading (pngpread.c) with small images (height < 8). + +version 1.0.10 [March 30, 2001] + Deleted extraneous space (introduced in 1.0.9) from line 42 of makefile.cygwin + Added beos project files (Chris Herborth) +version 1.0.11beta1 [April 3, 2001] + Added type casts on several png_malloc() calls (Dimitri Papadapoulos). + Removed a no-longer needed AIX work-around from pngconf.h + Changed several "//" single-line comments to C-style in pnggccrd.c +version 1.0.11beta2 [April 11, 2001] + Removed PNGAPI from several functions whose prototypes did not have PNGAPI. + Updated scripts/pngos2.def +version 1.0.11beta3 [April 14, 2001] + Added checking the results of many instances of png_malloc() for NULL +version 1.0.11beta4 [April 20, 2001] + Undid the changes from version 1.0.11beta3. Added a check for NULL return + from user's malloc_fn(). + Removed some useless type casts of the NULL pointer. + Added makefile.netbsd + +version 1.0.11 [April 27, 2001] + Revised makefile.netbsd +version 1.0.12beta1 [May 14, 2001] + Test for Windows platform in pngconf.h when including malloc.h (Emmanuel Blot) + Updated makefile.cygwin and handling of Cygwin's ALL_STATIC in pngconf.h + Added some never-to-be-executed code in pnggccrd.c to quiet compiler warnings. + Eliminated the png_error about apps using png_read|write_init(). Instead, + libpng will reallocate the png_struct and info_struct if they are too small. + This retains future binary compatibility for old applications written for + libpng-0.88 and earlier. +version 1.2.0beta1 [May 6, 2001] + Bumped DLLNUM to 2. + Re-enabled PNG_MNG_FEATURES_SUPPORTED and enabled PNG_ASSEMBLER_CODE_SUPPORTED + by default. + Added runtime selection of MMX features. + Added png_set_strip_error_numbers function and related macros. +version 1.2.0beta2 [May 7, 2001] + Finished merging 1.2.0beta1 with version 1.0.11 + Added a check for attempts to read or write PLTE in grayscale PNG datastreams. +version 1.2.0beta3 [May 17, 2001] + Enabled user memory function by default. + Modified png_create_struct so it passes user mem_ptr to user memory allocator. + Increased png_mng_features flag from png_byte to png_uint_32. + Bumped shared-library (so-number) and dll-number to 3. +version 1.2.0beta4 [June 23, 2001] + Check for missing profile length field in iCCP chunk and free chunk_data + in case of truncated iCCP chunk. + Bumped shared-library number to 3 in makefile.sgi and makefile.sggcc + Bumped dll-number from 2 to 3 in makefile.cygwin + Revised contrib/gregbook/rpng*-x.c to avoid a memory leak and to exit cleanly + if user attempts to run it on an 8-bit display. + Updated contrib/gregbook + Use png_malloc instead of png_zalloc to allocate palette in pngset.c + Updated makefile.ibmc + Added some typecasts to eliminate gcc 3.0 warnings. Changed prototypes + of png_write_oFFS width and height from png_uint_32 to png_int_32. + Updated example.c + Revised prototypes for png_debug_malloc and png_debug_free in pngtest.c +version 1.2.0beta5 [August 8, 2001] + Revised contrib/gregbook + Revised makefile.gcmmx + Revised pnggccrd.c to conditionally compile some thread-unsafe code only + when PNG_THREAD_UNSAFE_OK is defined. + Added tests to prevent pngwutil.c from writing a bKGD or tRNS chunk with + value exceeding 2^bit_depth-1 + Revised makefile.sgi and makefile.sggcc + Replaced calls to fprintf(stderr,...) with png_warning() in pnggccrd.c + Removed restriction that do_invert_mono only operate on 1-bit opaque files + +version 1.2.0 [September 1, 2001] + Changed a png_warning() to png_debug() in pnggccrd.c + Fixed contrib/gregbook/rpng-x.c, rpng2-x.c to avoid crash with XFreeGC(). +version 1.2.1beta1 [October 19, 2001] + Revised makefile.std in contrib/pngminus + Include background_1 in png_struct regardless of gamma support. + Revised makefile.netbsd and makefile.macosx, added makefile.darwin. + Revised example.c to provide more details about using row_callback(). +version 1.2.1beta2 [October 25, 2001] + Added type cast to each NULL appearing in a function call, except for + WINCE functions. + Added makefile.so9. +version 1.2.1beta3 [October 27, 2001] + Removed type casts from all NULLs. + Simplified png_create_struct_2(). +version 1.2.1beta4 [November 7, 2001] + Revised png_create_info_struct() and png_creat_struct_2(). + Added error message if png_write_info() was omitted. + Type cast NULLs appearing in function calls when _NO_PROTO or + PNG_TYPECAST_NULL is defined. +version 1.2.1rc1 [November 24, 2001] + Type cast NULLs appearing in function calls except when PNG_NO_TYPECAST_NULL + is defined. + Changed typecast of "size" argument to png_size_t in pngmem.c calls to + the user malloc_fn, to agree with the prototype in png.h + Added a pop/push operation to pnggccrd.c, to preserve Eflag (Maxim Sobolev) + Updated makefile.sgi to recognize LIBPATH and INCPATH. + Updated various makefiles so "make clean" does not remove previous major + version of the shared library. +version 1.2.1rc2 [December 4, 2001] + Always allocate 256-entry internal palette, hist, and trans arrays, to + avoid out-of-bounds memory reference caused by invalid PNG datastreams. + Added a check for prefix_length > data_length in iCCP chunk handler. + +version 1.2.1 [December 7, 2001] + None. +version 1.2.2beta1 [February 22, 2002] + Fixed a bug with reading the length of iCCP profiles (Larry Reeves). + Revised makefile.linux, makefile.gcmmx, and makefile.sgi to generate + libpng.a, libpng12.so (not libpng.so.3), and libpng12/png.h + Revised makefile.darwin to remove "-undefined suppress" option. + Added checks for gamma and chromaticity values over 21474.83, which exceed + the limit for PNG unsigned 32-bit integers when encoded. + Revised calls to png_create_read_struct() and png_create_write_struct() + for simpler debugging. + Revised png_zalloc() so zlib handles errors (uses PNG_FLAG_MALLOC_NULL_MEM_OK) +version 1.2.2beta2 [February 23, 2002] + Check chunk_length and idat_size for invalid (over PNG_MAX_UINT) lengths. + Check for invalid image dimensions in png_get_IHDR. + Added missing "fi;" in the install target of the SGI makefiles. + Added install-static to all makefiles that make shared libraries. + Always do gamma compensation when image is partially transparent. +version 1.2.2beta3 [March 7, 2002] + Compute background.gray and background_1.gray even when color_type is RGB + in case image gets reduced to gray later. + Modified shared-library makefiles to install pkgconfig/libpngNN.pc. + Export (with PNGAPI) png_zalloc, png_zfree, and png_handle_as_unknown + Removed unused png_write_destroy_info prototype from png.h + Eliminated incorrect use of width_mmx from pnggccrd.c in pixel_bytes == 8 case + Added install-shared target to all makefiles that make shared libraries. + Stopped a double free of palette, hist, and trans when not using free_me. + Added makefile.32sunu for Sun Ultra 32 and makefile.64sunu for Sun Ultra 64. +version 1.2.2beta4 [March 8, 2002] + Compute background.gray and background_1.gray even when color_type is RGB + in case image gets reduced to gray later (Jason Summers). + Relocated a misplaced /bin/rm in the "install-shared" makefile targets + Added PNG_1_0_X macro which can be used to build a 1.0.x-compatible library. +version 1.2.2beta5 [March 26, 2002] + Added missing PNGAPI to several function definitions. + Check for invalid bit_depth or color_type in png_get_IHDR(), and + check for missing PLTE or IHDR in png_push_read_chunk() (Matthias Clasen). + Revised iTXt support to accept NULL for lang and lang_key. + Compute gamma for color components of background even when color_type is gray. + Changed "()" to "{}" in scripts/libpng.pc.in. + Revised makefiles to put png.h and pngconf.h only in $prefix/include/libpngNN + Revised makefiles to make symlink to libpng.so.NN in addition to libpngNN.so +version 1.2.2beta6 [March 31, 2002] +version 1.0.13beta1 [March 31, 2002] + Prevent png_zalloc() from trying to memset memory that it failed to acquire. + Add typecasts of PNG_MAX_UINT in pngset_cHRM_fixed() (Matt Holgate). + Ensure that the right function (user or default) is used to free the + png_struct after an error in png_create_read_struct_2(). +version 1.2.2rc1 [April 7, 2002] +version 1.0.13rc1 [April 7, 2002] + Save the ebx register in pnggccrd.c (Sami Farin) + Add "mem_ptr = png_ptr->mem_ptr" in png_destroy_write_struct() (Paul Gardner). + Updated makefiles to put headers in include/libpng and remove old include/*.h. + +version 1.2.2 [April 15, 2002] +version 1.0.13 [April 15, 2002] + Revised description of png_set_filter() in libpng.3/libpng.txt. + Revised makefile.netbsd and added makefile.neNNbsd and makefile.freebsd +version 1.0.13patch01 [April 17, 2002] +version 1.2.2patch01 [April 17, 2002] + Changed ${PNGMAJ}.${PNGVER} bug to ${PNGVER} in makefile.sgi and makefile.sggcc + Fixed VER -> PNGVER typo in makefile.macosx and added install-static to install + Added install: target to makefile.32sunu and makefile.64sunu +version 1.0.13patch03 [April 18, 2002] +version 1.2.2patch03 [April 18, 2002] + Revised 15 makefiles to link libpng.a to libpngNN.a and the include libpng + subdirectory to libpngNN subdirectory without the full pathname. + Moved generation of libpng.pc from "install" to "all" in 15 makefiles. +version 1.2.3rc1 [April 28, 2002] + Added install-man target to 15 makefiles (Dimitri Papadopolous-Orfanos). + Added $(DESTDIR) feature to 24 makefiles (Tim Mooney) + Fixed bug with $prefix, should be $(prefix) in makefile.hpux. + Updated cygwin-specific portion of pngconf.h and revised makefile.cygwin + Added a link from libpngNN.pc to libpng.pc in 15 makefiles. + Added links from include/libpngNN/*.h to include/*.h in 24 makefiles. + Revised makefile.darwin to make relative links without full pathname. + Added setjmp() at the end of png_create_*_struct_2() in case user forgets + to put one in their application. + Restored png_zalloc() and png_zfree() prototypes to version 1.2.1 and + removed them from module definition files. +version 1.2.3rc2 [May 1, 2002] + Fixed bug in reporting number of channels in pngget.c and pngset.c, + that was introduced in version 1.2.2beta5. + Exported png_zalloc(), png_zfree(), png_default_read(), png_default_write(), + png_default_flush(), and png_push_fill_buffer() and included them in + module definition files. + Added "libpng.pc" dependency to the "install-shared" target in 15 makefiles. +version 1.2.3rc3 [May 1, 2002] + Revised prototype for png_default_flush() + Remove old libpng.pc and libpngNN.pc before installing new ones. +version 1.2.3rc4 [May 2, 2002] + Typos in *.def files (png_default_read|write -> png_default_read|write_data) + In makefiles, changed rm libpng.NN.pc to rm libpngNN.pc + Added libpng-config and libpngNN-config and modified makefiles to install them. + Changed $(MANPATH) to $(DESTDIR)$(MANPATH) in makefiles + Added "Win32 DLL VB" configuration to projects/msvc/libpng.dsp +version 1.2.3rc5 [May 11, 2002] + Changed "error" and "message" in prototypes to "error_message" and + "warning_message" to avoid namespace conflict. + Revised 15 makefiles to build libpng-config from libpng-config-*.in + Once more restored png_zalloc and png_zfree to regular nonexported form. + Restored png_default_read|write_data, png_default_flush, png_read_fill_buffer + to nonexported form, but with PNGAPI, and removed them from module def files. +version 1.2.3rc6 [May 14, 2002] + Removed "PNGAPI" from png_zalloc() and png_zfree() in png.c + Changed "Gz" to "Gd" in projects/msvc/libpng.dsp and zlib.dsp. + Removed leftover libpng-config "sed" script from four makefiles. + Revised libpng-config creating script in 16 makefiles. + +version 1.2.3 [May 22, 2002] + Revised libpng-config target in makefile.cygwin. + Removed description of png_set_mem_fn() from documentation. + Revised makefile.freebsd. + Minor cosmetic changes to 15 makefiles, e.g., $(DI) = $(DESTDIR)/$(INCDIR). + Revised projects/msvc/README.txt + Changed -lpng to -lpngNN in LDFLAGS in several makefiles. +version 1.2.4beta1 [May 24, 2002] + Added libpng.pc and libpng-config to "all:" target in 16 makefiles. + Fixed bug in 16 makefiles: $(DESTDIR)/$(LIBPATH) to $(DESTDIR)$(LIBPATH) + Added missing "\" before closing double quote in makefile.gcmmx. + Plugged various memory leaks; added png_malloc_warn() and png_set_text_2() + functions. +version 1.2.4beta2 [June 25, 2002] + Plugged memory leak of png_ptr->current_text (Matt Holgate). + Check for buffer overflow before reading CRC in pngpread.c (Warwick Allison) + Added -soname to the loader flags in makefile.dec, makefile.sgi, and + makefile.sggcc. + Added "test-installed" target to makefile.linux, makefile.gcmmx, + makefile.sgi, and makefile.sggcc. +version 1.2.4beta3 [June 28, 2002] + Plugged memory leak of row_buf in pngtest.c when there is a png_error(). + Detect buffer overflow in pngpread.c when IDAT is corrupted with extra data. + Added "test-installed" target to makefile.32sunu, makefile.64sunu, + makefile.beos, makefile.darwin, makefile.dec, makefile.macosx, + makefile.solaris, makefile.hpux, makefile.hpgcc, and makefile.so9. +version 1.2.4rc1 and 1.0.14rc1 [July 2, 2002] + Added "test-installed" target to makefile.cygwin and makefile.sco. + Revised pnggccrd.c to be able to back out version 1.0.x via PNG_1_0_X macro. + +version 1.2.4 and 1.0.14 [July 8, 2002] + Changed png_warning() to png_error() when width is too large to process. +version 1.2.4patch01 [July 20, 2002] + Revised makefile.cygwin to use DLL number 12 instead of 13. +version 1.2.5beta1 [August 6, 2002] + Added code to contrib/gregbook/readpng2.c to ignore unused chunks. + Replaced toucan.png in contrib/gregbook (it has been corrupt since 1.0.11) + Removed some stray *.o files from contrib/gregbook. + Changed png_error() to png_warning() about "Too much data" in pngpread.c + and about "Extra compressed data" in pngrutil.c. + Prevent png_ptr->pass from exceeding 7 in png_push_finish_row(). + Updated makefile.hpgcc + Updated png.c and pnggccrd.c handling of return from png_mmx_support() +version 1.2.5beta2 [August 15, 2002] + Only issue png_warning() about "Too much data" in pngpread.c when avail_in + is nonzero. + Updated makefiles to install a separate libpng.so.3 with its own rpath. +version 1.2.5rc1 and 1.0.15rc1 [August 24, 2002] + Revised makefiles to not remove previous minor versions of shared libraries. +version 1.2.5rc2 and 1.0.15rc2 [September 16, 2002] + Revised 13 makefiles to remove "-lz" and "-L$(ZLIBLIB)", etc., from shared + library loader directive. + Added missing "$OBJSDLL" line to makefile.gcmmx. + Added missing "; fi" to makefile.32sunu. +version 1.2.5rc3 and 1.0.15rc3 [September 18, 2002] + Revised libpng-config script. + +version 1.2.5 and 1.0.15 [October 3, 2002] + Revised makefile.macosx, makefile.darwin, makefile.hpgcc, and makefile.hpux, + and makefile.aix. + Relocated two misplaced PNGAPI lines in pngtest.c +version 1.2.6beta1 [October 22, 2002] + Commented out warning about uninitialized mmx_support in pnggccrd.c. + Changed "IBMCPP__" flag to "__IBMCPP__" in pngconf.h. + Relocated two more misplaced PNGAPI lines in pngtest.c + Fixed memory overrun bug in png_do_read_filler() with 16-bit datastreams, + introduced in version 1.0.2. + Revised makefile.macosx, makefile.dec, makefile.aix, and makefile.32sunu. +version 1.2.6beta2 [November 1, 2002] + Added libpng-config "--ldopts" output. + Added "AR=ar" and "ARFLAGS=rc" and changed "ar rc" to "$(AR) $(ARFLAGS)" + in makefiles. +version 1.2.6beta3 [July 18, 2004] + Reverted makefile changes from version 1.2.6beta2 and some of the changes + from version 1.2.6beta1; these will be postponed until version 1.2.7. + Version 1.2.6 is going to be a simple bugfix release. + Changed the one instance of "ln -sf" to "ln -f -s" in each Sun makefile. + Fixed potential overrun in pngerror.c by using strncpy instead of memcpy. + Added "#!/bin/sh" at the top of configure, for recognition of the + 'x' flag under Cygwin (Cosmin). + Optimized vacuous tests that silence compiler warnings, in png.c (Cosmin). + Added support for PNG_USER_CONFIG, in pngconf.h (Cosmin). + Fixed the special memory handler for Borland C under DOS, in pngmem.c + (Cosmin). + Removed some spurious assignments in pngrutil.c (Cosmin). + Replaced 65536 with 65536L, and 0xffff with 0xffffL, to silence warnings + on 16-bit platforms (Cosmin). + Enclosed shift op expressions in parentheses, to silence warnings (Cosmin). + Used proper type png_fixed_point, to avoid problems on 16-bit platforms, + in png_handle_sRGB() (Cosmin). + Added compression_type to png_struct, and optimized the window size + inside the deflate stream (Cosmin). + Fixed definition of isnonalpha(), in pngerror.c and pngrutil.c (Cosmin). + Fixed handling of unknown chunks that come after IDAT (Cosmin). + Allowed png_error() and png_warning() to work even if png_ptr == NULL + (Cosmin). + Replaced row_info->rowbytes with row_bytes in png_write_find_filter() + (Cosmin). + Fixed definition of PNG_LIBPNG_VER_DLLNUM (Simon-Pierre). + Used PNG_LIBPNG_VER and PNG_LIBPNG_VER_STRING instead of the hardcoded + values in png.c (Simon-Pierre, Cosmin). + Initialized png_libpng_ver[] with PNG_LIBPNG_VER_STRING (Simon-Pierre). + Replaced PNG_LIBPNG_VER_MAJOR with PNG_LIBPNG_VER_DLLNUM in png.rc + (Simon-Pierre). + Moved the definition of PNG_HEADER_VERSION_STRING near the definitions + of the other PNG_LIBPNG_VER_... symbols in png.h (Cosmin). + Relocated #ifndef PNGAPI guards in pngconf.h (Simon-Pierre, Cosmin). + Updated scripts/makefile.vc(a)win32 (Cosmin). + Updated the MSVC project (Simon-Pierre, Cosmin). + Updated the Borland C++ Builder project (Cosmin). + Avoided access to asm_flags in pngvcrd.c, if PNG_1_0_X is defined (Cosmin). + Commented out warning about uninitialized mmx_support in pngvcrd.c (Cosmin). + Removed scripts/makefile.bd32 and scripts/pngdef.pas (Cosmin). + Added extra guard around inclusion of Turbo C memory headers, in pngconf.h + (Cosmin). + Renamed projects/msvc/ to projects/visualc6/, and projects/borland/ to + projects/cbuilder5/ (Cosmin). + Moved projects/visualc6/png32ms.def to scripts/pngw32.def, + and projects/visualc6/png.rc to scripts/pngw32.rc (Cosmin). + Added projects/visualc6/pngtest.dsp; removed contrib/msvctest/ (Cosmin). + Changed line endings to DOS style in cbuilder5 and visualc6 files, even + in the tar.* distributions (Cosmin). + Updated contrib/visupng/VisualPng.dsp (Cosmin). + Updated contrib/visupng/cexcept.h to version 2.0.0 (Cosmin). + Added a separate distribution with "configure" and supporting files (Junichi). +version 1.2.6beta4 [July 28, 2004] + Added user ability to change png_size_t via a PNG_SIZE_T macro. + Added png_sizeof() and png_convert_size() functions. + Added PNG_SIZE_MAX (maximum value of a png_size_t variable. + Added check in png_malloc_default() for (size_t)size != (png_uint_32)size + which would indicate an overflow. + Changed sPLT failure action from png_error to png_warning and abandon chunk. + Changed sCAL and iCCP failures from png_error to png_warning and abandon. + Added png_get_uint_31(png_ptr, buf) function. + Added PNG_UINT_32_MAX macro. + Renamed PNG_MAX_UINT to PNG_UINT_31_MAX. + Made png_zalloc() issue a png_warning and return NULL on potential + overflow. + Turn on PNG_NO_ZALLOC_ZERO by default in version 1.2.x + Revised "clobber list" in pnggccrd.c so it will compile under gcc-3.4. + Revised Borland portion of png_malloc() to return NULL or issue + png_error() according to setting of PNG_FLAG_MALLOC_NULL_MEM_OK. + Added PNG_NO_SEQUENTIAL_READ_SUPPORTED macro to conditionally remove + sequential read support. + Added some "#if PNG_WRITE_SUPPORTED" blocks. + Removed some redundancy with #ifdef/#endif in png_malloc_default(). + Use png_malloc instead of png_zalloc to allocate the pallete. +version 1.0.16rc1 and 1.2.6rc1 [August 4, 2004] + Fixed buffer overflow vulnerability in png_handle_tRNS() + Fixed integer arithmetic overflow vulnerability in png_read_png(). + Fixed some harmless bugs in png_handle_sBIT, etc, that would cause + duplicate chunk types to go undetected. + Fixed some timestamps in the -config version + Rearranged order of processing of color types in png_handle_tRNS(). + Added ROWBYTES macro to calculate rowbytes without integer overflow. + Updated makefile.darwin and removed makefile.macosx from scripts directory. + Imposed default one million column, one-million row limits on the image + dimensions, and added png_set_user_limits() function to override them. + Revised use of PNG_SET_USER_LIMITS_SUPPORTED macro. + Fixed wrong cast of returns from png_get_user_width|height_max(). + Changed some "keep the compiler happy" from empty statements to returns, + Revised libpng.txt to remove 1.2.x stuff from the 1.0.x distribution +version 1.0.16rc2 and 1.2.6rc2 [August 7, 2004] + Revised makefile.darwin and makefile.solaris. Removed makefile.macosx. + Revised pngtest's png_debug_malloc() to use png_malloc() instead of + png_malloc_default() which is not supposed to be exported. + Fixed off-by-one error in one of the conversions to PNG_ROWBYTES() in + pngpread.c. Bug was introduced in 1.2.6rc1. + Fixed bug in RGB to RGBX transformation introduced in 1.2.6rc1. + Fixed old bug in RGB to Gray transformation. + Fixed problem with 64-bit compilers by casting arguments to abs() + to png_int_32. + Changed "ln -sf" to "ln -f -s" in three makefiles (solaris, sco, so9). + Changed "HANDLE_CHUNK_*" to "PNG_HANDLE_CHUNK_*" (Cosmin) + Added "-@/bin/rm -f $(DL)/$(LIBNAME).so.$(PNGMAJ)" to 15 *NIX makefiles. + Added code to update the row_info->colortype in png_do_read_filler() (MSB). +version 1.0.16rc3 and 1.2.6rc3 [August 9, 2004] + Eliminated use of "abs()" in testing cHRM and gAMA values, to avoid + trouble with some 64-bit compilers. Created PNG_OUT_OF_RANGE() macro. + Revised documentation of png_set_keep_unknown_chunks(). + Check handle_as_unknown status in pngpread.c, as in pngread.c previously. + Moved "PNG_HANDLE_CHUNK_*" macros out of PNG_INTERNAL section of png.h + Added "rim" definitions for CONST4 and CONST6 in pnggccrd.c +version 1.0.16rc4 and 1.2.6rc4 [August 10, 2004] + Fixed mistake in pngtest.c introduced in 1.2.6rc2 (declaration of + "pinfo" was out of place). +version 1.0.16rc5 and 1.2.6rc5 [August 10, 2004] + Moved "PNG_HANDLE_CHUNK_*" macros out of PNG_ASSEMBLER_CODE_SUPPORTED + section of png.h where they were inadvertently placed in version rc3. + +version 1.2.6 and 1.0.16 [August 15, 2004] + Revised pngtest so memory allocation testing is only done when PNG_DEBUG==1. +version 1.2.7beta1 [August 26, 2004] + Removed unused pngasmrd.h file. + Removed references to uu.net for archived files. Added references to + PNG Spec (second edition) and the PNG ISO/IEC Standard. + Added "test-dd" target in 15 makefiles, to run pngtest in DESTDIR. + Fixed bug with "optimized window size" in the IDAT datastream, that + causes libpng to write PNG files with incorrect zlib header bytes. +version 1.2.7beta2 [August 28, 2004] + Fixed bug with sCAL chunk and big-endian machines (David Munro). + Undid new code added in 1.2.6rc2 to update the color_type in + png_set_filler(). + Added png_set_add_alpha() that updates color type. +version 1.0.17rc1 and 1.2.7rc1 [September 4, 2004] + Revised png_set_strip_filler() to not remove alpha if color_type has alpha. + +version 1.2.7 and 1.0.17 [September 12, 2004] + Added makefile.hp64 + Changed projects/msvc/png32ms.def to scripts/png32ms.def in makefile.cygwin +version 1.2.8beta1 [November 1, 2004] + Fixed bug in png_text_compress() that would fail to complete a large block. + Fixed bug, introduced in libpng-1.2.7, that overruns a buffer during + strip alpha operation in png_do_strip_filler(). + Added PNG_1_2_X definition in pngconf.h + Comment out with #ifdef/#endif png_info_init in png.c and png_read_init + in pngread.c (as of 1.3.0) +version 1.2.8beta2 [November 2, 2004] + Reduce color_type to a nonalpha type after strip alpha operation in + png_do_strip_filler(). +version 1.2.8beta3 [November 3, 2004] + Revised definitions of PNG_MAX_UINT_32, PNG_MAX_SIZE, and PNG_MAXSUM +version 1.2.8beta4 [November 12, 2004] + Fixed (again) definition of PNG_LIBPNG_VER_DLLNUM in png.h (Cosmin). + Added PNG_LIBPNG_BUILD_PRIVATE in png.h (Cosmin). + Set png_ptr->zstream.data_type to Z_BINARY, to avoid unnecessary detection + of data type in deflate (Cosmin). + Deprecated but continue to support SPECIALBUILD and PRIVATEBUILD in favor of + PNG_LIBPNG_BUILD_SPECIAL_STRING and PNG_LIBPNG_BUILD_PRIVATE_STRING. +version 1.2.8beta5 [November 20, 2004] + Use png_ptr->flags instead of png_ptr->transformations to pass + PNG_STRIP_ALPHA info to png_do_strip_filler(), to preserve ABI + compatibility. + Revised handling of SPECIALBUILD, PRIVATEBUILD, + PNG_LIBPNG_BUILD_SPECIAL_STRING and PNG_LIBPNG_BUILD_PRIVATE_STRING. +version 1.2.8rc1 [November 24, 2004] + Moved handling of BUILD macros from pngconf.h to png.h + Added definition of PNG_LIBPNG_BASE_TYPE in png.h, inadvertently + omitted from beta5. + Revised scripts/pngw32.rc + Despammed mailing addresses by masking "@" with "at". + Inadvertently installed a supposedly faster test version of pngrutil.c +version 1.2.8rc2 [November 26, 2004] + Added two missing "\" in png.h + Change tests in pngread.c and pngpread.c to + if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) + png_do_read_transformations(png_ptr); +version 1.2.8rc3 [November 28, 2004] + Reverted pngrutil.c to version libpng-1.2.8beta5. + Added scripts/makefile.elf with supporting code in pngconf.h for symbol + versioning (John Bowler). +version 1.2.8rc4 [November 29, 2004] + Added projects/visualc7 (Simon-pierre). +version 1.2.8rc5 [November 29, 2004] + Fixed new typo in scripts/pngw32.rc + +version 1.2.8 [December 3, 2004] + Removed projects/visualc7, added projects/visualc71. + +version 1.2.9beta1 [February 21, 2006] + + Initialized some structure members in pngwutil.c to avoid gcc-4.0.0 complaints + Revised man page and libpng.txt to make it clear that one should not call + png_read_end or png_write_end after png_read_png or png_write_png. + Updated references to png-mng-implement mailing list. + Fixed an incorrect typecast in pngrutil.c + Added PNG_NO_READ_SUPPORTED conditional for making a write-only library. + Added PNG_NO_WRITE_INTERLACING_SUPPORTED conditional. + Optimized alpha-inversion loops in pngwtran.c + Moved test for nonzero gamma outside of png_build_gamma_table() in pngrtran.c + Make sure num_trans is <= 256 before copying data in png_set_tRNS(). + Make sure num_palette is <= 256 before copying data in png_set_PLTE(). + Interchanged order of write_swap_alpha and write_invert_alpha transforms. + Added parentheses in the definition of PNG_LIBPNG_BUILD_TYPE (Cosmin). + Optimized zlib window flag (CINFO) in contrib/pngsuite/*.png (Cosmin). + Updated scripts/makefile.bc32 for Borland C++ 5.6 (Cosmin). + Exported png_get_uint_32, png_save_uint_32, png_get_uint_16, png_save_uint_16, + png_get_int_32, png_save_int_32, png_get_uint_31 (Cosmin). + Added type cast (png_byte) in png_write_sCAL() (Cosmin). + Fixed scripts/makefile.cygwin (Christian Biesinger, Cosmin). + Default iTXt support was inadvertently enabled. + +version 1.2.9beta2 [February 21, 2006] + + Check for png_rgb_to_gray and png_gray_to_rgb read transformations before + checking for png_read_dither in pngrtran.c + Revised checking of chromaticity limits to accommodate extended RGB + colorspace (John Denker). + Changed line endings in some of the project files to CRLF, even in the + "Unix" tar distributions (Cosmin). + Made png_get_int_32 and png_save_int_32 always available (Cosmin). + Updated scripts/pngos2.def, scripts/pngw32.def and projects/wince/png32ce.def + with the newly exported functions. + Eliminated distributions without the "configure" script. + Updated INSTALL instructions. + +version 1.2.9beta3 [February 24, 2006] + + Fixed CRCRLF line endings in contrib/visupng/VisualPng.dsp + Made libpng.pc respect EXEC_PREFIX (D. P. Kreil, J. Bowler) + Removed reference to pngasmrd.h from Makefile.am + Renamed CHANGES to ChangeLog. + Renamed LICENSE to COPYING. + Renamed ANNOUNCE to NEWS. + Created AUTHORS file. + +version 1.2.9beta4 [March 3, 2006] + + Changed definition of PKGCONFIG from $prefix/lib to $libdir in configure.ac + Reverted to filenames LICENSE and ANNOUNCE; removed AUTHORS and COPYING. + Removed newline from the end of some error and warning messages. + Removed test for sqrt() from configure.ac and configure. + Made swap tables in pngtrans.c PNG_CONST (Carlo Bramix). + Disabled default iTXt support that was inadvertently enabled in + libpng-1.2.9beta1. + Added "OS2" to list of systems that don't need underscores, in pnggccrd.c + Removed libpng version and date from *.c files. + +version 1.2.9beta5 [March 4, 2006] + Removed trailing blanks from source files. + Put version and date of latest change in each source file, and changed + copyright year accordingly. + More cleanup of configure.ac, Makefile.ac, and associated scripts. + Restored scripts/makefile.elf which was inadvertently deleted. + +version 1.2.9beta6 [March 6, 2006] + Fixed typo (RELEASE) in configuration files. + +version 1.2.9beta7 [March 7, 2006] + Removed libpng.vers and libpng.sym from libpng12_la_SOURCES in Makefile.am + Fixed inconsistent #ifdef's around png_sig_bytes() and png_set_sCAL_s() + in png.h. + Updated makefile.elf as suggested by debian. + Made cosmetic changes to some makefiles, adding LN_SF and other macros. + Made some makefiles accept "exec_prefix". + +version 1.2.9beta8 [March 9, 2006] + Fixed some "#if defined (..." which should be "#if defined(..." + Bug introduced in libpng-1.2.8. + Fixed inconsistency in definition of png_default_read_data() + Restored blank that was lost from makefile.sggcc "clean" target in beta7. + Revised calculation of "current" and "major" for irix in ltmain.sh + Changed "mkdir" to "MKDIR_P" in some makefiles. + Separated PNG_EXPAND and PNG_EXPAND_tRNS. + Added png_set_expand_gray_1_2_4_to_8() and deprecated + png_set_gray_1_2_4_to_8() which also expands tRNS to alpha. + +version 1.2.9beta9 [March 10, 2006] + Include "config.h" in pngconf.h when available. + Added some checks for NULL png_ptr or NULL info_ptr (timeless) + +version 1.2.9beta10 [March 20, 2006] + Removed extra CR from contrib/visualpng/VisualPng.dsw (Cosmin) + Made pnggccrd.c PIC-compliant (Christian Aichinger). + Added makefile.mingw (Wolfgang Glas). + Revised pngconf.h MMX checking. + +version 1.2.9beta11 [March 22, 2006] + Fixed out-of-order declaration in pngwrite.c that was introduced in beta9 + Simplified some makefiles by using LIBSO, LIBSOMAJ, and LIBSOVER macros. + +version 1.2.9rc1 [March 31, 2006] + Defined PNG_USER_PRIVATEBUILD when including "pngusr.h" (Cosmin). + Removed nonsensical assertion check from pngtest.c (Cosmin). + +version 1.2.9 [April 14, 2006] + Revised makefile.beos and added "none" selector in ltmain.sh + +version 1.2.10beta1 [April 15, 2006] + Renamed "config.h" to "png_conf.h" and revised Makefile.am to add + -DPNG_BUILDING_LIBPNG to compile directive, and modified pngconf.h + to include png_conf.h only when PNG_BUILDING_LIBPNG is defined. + +version 1.2.10beta2 [April 15, 2006] + Manually updated Makefile.in and configure. Changed png_conf.h.in + back to config.h. + +version 1.2.10beta3 [April 15, 2006] + Change png_conf.h back to config.h in pngconf.h. + +version 1.2.10beta4 [April 16, 2006] + Change PNG_BUILDING_LIBPNG to PNG_CONFIGURE_LIBPNG in config/Makefile*. + +version 1.2.10beta5 [April 16, 2006] + Added a configure check for compiling assembler code in pnggccrd.c + +version 1.2.10beta6 [April 17, 2006] + Revised the configure check for pnggccrd.c + Moved -DPNG_CONFIGURE_LIBPNG into @LIBPNG_DEFINES@ + Added @LIBPNG_DEFINES@ to arguments when building libpng.sym + +version 1.2.10beta7 [April 18, 2006] + Change "exec_prefix=$prefix" to "exec_prefix=$(prefix)" in makefiles. + +version 1.2.10rc1 [April 19, 2006] + Ensure pngconf.h doesn't define both PNG_USE_PNGGCCRD and PNG_USE_PNGVCRD + Fixed "LN_FS" typo in makefile.sco and makefile.solaris. + +version 1.2.10rc2 [April 20, 2006] + Added a backslash between -DPNG_CONFIGURE_LIBPNG and -DPNG_NO_ASSEMBLER_CODE + in configure.ac and configure + Made the configure warning about versioned symbols less arrogant. + +version 1.2.10rc3 [April 21, 2006] + Added a note in libpng.txt that png_set_sig_bytes(8) can be used when + writing an embedded PNG without the 8-byte signature. + Revised makefiles and configure to avoid making links to libpng.so.* + +version 1.2.10 [April 23, 2006] + Reverted configure to "rc2" state. + +version 1.2.11beta1 [May 31, 2006] + scripts/libpng.pc.in contained "configure" style version info and would + not work with makefiles. + The shared-library makefiles were linking to libpng.so.0 instead of + libpng.so.3 compatibility as the library. + +version 1.2.11beta2 [June 2, 2006] + Increased sprintf buffer from 50 to 52 chars in pngrutil.c to avoid + buffer overflow. + Fixed bug in example.c (png_set_palette_rgb -> png_set_palette_to_rgb) + +version 1.2.11beta3 [June 5, 2006] + Prepended "#! /bin/sh" to ltmail.sh and contrib/pngminus/*.sh (Cosmin). + Removed the accidental leftover Makefile.in~ (Cosmin). + Avoided potential buffer overflow and optimized buffer in + png_write_sCAL(), png_write_sCAL_s() (Cosmin). + Removed the include directories and libraries from CFLAGS and LDFLAGS + in scripts/makefile.gcc (Nelson A. de Oliveira, Cosmin). + +version 1.2.11beta4 [June 6, 2006] + Allow zero-length IDAT chunks after the entire zlib datastream, but not + after another intervening chunk type. + +version 1.0.19rc1, 1.2.11rc1 [June 13, 2006] + Deleted extraneous square brackets from [config.h] in configure.ac + +version 1.0.19rc2, 1.2.11rc2 [June 14, 2006] + Added prototypes for PNG_INCH_CONVERSIONS functions to png.h + Revised INSTALL and autogen.sh + Fixed typo in several makefiles (-W1 should be -Wl) + Added typedef for png_int_32 and png_uint_32 on 64-bit systems. + +version 1.0.19rc3, 1.2.11rc3 [June 15, 2006] + Removed the new typedefs for 64-bit systems (delay until version 1.4.0) + Added one zero element to png_gamma_shift[] array in pngrtran.c to avoid + reading out of bounds. + +version 1.0.19rc4, 1.2.11rc4 [June 15, 2006] + Really removed the new typedefs for 64-bit systems. + +version 1.0.19rc5, 1.2.11rc5 [June 22, 2006] + Removed png_sig_bytes entry from scripts/pngw32.def + +version 1.0.19, 1.2.11 [June 26, 2006] + None. + +version 1.0.20, 1.2.12 [June 27, 2006] + Really increased sprintf buffer from 50 to 52 chars in pngrutil.c to avoid + buffer overflow. + +version 1.2.13beta1 [October 2, 2006] + Removed AC_FUNC_MALLOC from configure.ac + Work around Intel-Mac compiler bug by setting PNG_NO_MMX_CODE in pngconf.h + Change "logical" to "bitwise" throughout documentation. + Detect and fix attempt to write wrong iCCP profile length. + +version 1.0.21, 1.2.13 [November 14, 2006] + Fix potential buffer overflow in sPLT chunk handler. + Fix Makefile.am to not try to link to noexistent files. + Check all exported functions for NULL png_ptr. + +version 1.2.14beta1 [November 17, 2006] + Relocated three misplaced tests for NULL png_ptr. + Built Makefile.in with automake-1.9.6 instead of 1.9.2. + Build configure with autoconf-2.60 instead of 2.59 + +version 1.2.14beta2 [November 17, 2006] + Added some typecasts in png_zalloc(). + +version 1.2.14rc1 [November 20, 2006] + Changed "strtod" to "png_strtod" in pngrutil.c + +version 1.0.22, 1.2.14 [November 27, 2006] + Added missing "$(srcdir)" in Makefile.am and Makefile.in + +version 1.2.15beta1 [December 3, 2006] + Generated configure with autoconf-2.61 instead of 2.60 + Revised configure.ac to update libpng.pc and libpng-config. + +version 1.2.15beta2 [December 3, 2006] + Always export MMX asm functions, just stubs if not building pnggccrd.c + +version 1.2.15beta3 [December 4, 2006] + Add "png_bytep" typecast to profile while calculating length in pngwutil.c + +version 1.2.15beta4 [December 7, 2006] + Added scripts/CMakeLists.txt + Changed PNG_NO_ASSEMBLER_CODE to PNG_NO_MMX_CODE in scripts, like 1.4.0beta + +version 1.2.15beta5 [December 7, 2006] + Changed some instances of PNG_ASSEMBLER_* to PNG_MMX_* in pnggccrd.c + Revised scripts/CMakeLists.txt + +version 1.2.15beta6 [December 13, 2006] + Revised scripts/CMakeLists.txt and configure.ac + +version 1.2.15rc1 [December 18, 2006] + Revised scripts/CMakeLists.txt + +version 1.2.15rc2 [December 21, 2006] + Added conditional #undef jmpbuf in pngtest.c to undo #define in AIX headers. + Added scripts/makefile.nommx + +version 1.2.15rc3 [December 25, 2006] + Fixed shared library numbering error that was introduced in 1.2.15beta6. + +version 1.2.15rc4 [December 27, 2006] + Fixed handling of rgb_to_gray when png_ptr->color.gray isn't set. + +version 1.2.15rc5 [December 31, 2006] + Revised handling of rgb_to_gray. + +version 1.0.23, 1.2.15 [January 5, 2007] + Added some (unsigned long) typecasts in pngtest.c to avoid printing errors. + +version 1.2.16beta1 [January 6, 2007] + Fix bugs in makefile.nommx + +version 1.2.16beta2 [January 16, 2007] + Revised scripts/CMakeLists.txt + +version 1.0.24, 1.2.16 [January 31, 2007] + No changes. + +version 1.2.17beta1 [March 6, 2007] + Revised scripts/CMakeLists.txt to install both shared and static libraries. + Deleted a redundant line from pngset.c. + +version 1.2.17beta2 [April 26, 2007] + Relocated misplaced test for png_ptr == NULL in pngpread.c + Change "==" to "&" for testing PNG_RGB_TO_GRAY_ERR & PNG_RGB_TO_GRAY_WARN + flags. + Changed remaining instances of PNG_ASSEMBLER_* to PNG_MMX_* + Added pngerror() when write_IHDR fails in deflateInit2(). + Added "const" to some array declarations. + Mention examples of libpng usage in the libpng*.txt and libpng.3 documents. + +version 1.2.17rc1 [May 4, 2007] + No changes. + +version 1.2.17rc2 [May 8, 2007] + Moved several PNG_HAVE_* macros out of PNG_INTERNAL because applications + calling set_unknown_chunk_location() need them. + Changed transformation flag from PNG_EXPAND_tRNS to PNG_EXPAND in + png_set_expand_gray_1_2_4_to_8(). + Added png_ptr->unknown_chunk to hold working unknown chunk data, so it + can be free'ed in case of error. Revised unknown chunk handling in + pngrutil.c and pngpread.c to use this structure. + +version 1.2.17rc3 [May 8, 2007] + Revised symbol-handling in configure script. + +version 1.2.17rc4 [May 10, 2007] + Revised unknown chunk handling to avoid storing unknown critical chunks. + +version 1.0.25 [May 15, 2007] +version 1.2.17 [May 15, 2007] + Added "png_ptr->num_trans=0" before error return in png_handle_tRNS, + to eliminate a vulnerability (CVE-2007-2445, CERT VU#684664) + +version 1.0.26 [May 15, 2007] +version 1.2.18 [May 15, 2007] + Reverted the libpng-1.2.17rc3 change to symbol-handling in configure script + +version 1.2.19beta1 [May 18, 2007] + Changed "const static" to "static PNG_CONST" everywhere, mostly undoing + change of libpng-1.2.17beta2. Changed other "const" to "PNG_CONST" + Changed some handling of unused parameters, to avoid compiler warnings. + "if (unused == NULL) return;" becomes "unused = unused". + +version 1.2.19beta2 [May 18, 2007] + Only use the valid bits of tRNS value in png_do_expand() (Brian Cartier) + +version 1.2.19beta3 [May 19, 2007] + Add some "png_byte" typecasts in png_check_keyword() and write new_key + instead of key in zTXt chunk (Kevin Ryde). + +version 1.2.19beta4 [May 21, 2007] + Add png_snprintf() function and use it in place of sprint() for improved + defense against buffer overflows. + +version 1.2.19beta5 [May 21, 2007] + Fixed png_handle_tRNS() to only use the valid bits of tRNS value. + Changed handling of more unused parameters, to avoid compiler warnings. + Removed some PNG_CONST in pngwutil.c to avoid compiler warnings. + +version 1.2.19beta6 [May 22, 2007] + Added some #ifdef PNG_MMX_CODE_SUPPORTED where needed in pngvcrd.c + Added a special "_MSC_VER" case that defines png_snprintf to _snprintf + +version 1.2.19beta7 [May 22, 2007] + Squelched png_squelch_warnings() in pnggccrd.c and added + an #ifdef PNG_MMX_CODE_SUPPORTED/#endif block around the declarations + that caused the warnings that png_squelch_warnings was squelching. + +version 1.2.19beta8 [May 22, 2007] + Removed __MMX__ from test in pngconf.h. + +version 1.2.19beta9 [May 23, 2007] + Made png_squelch_warnings() available via PNG_SQUELCH_WARNINGS macro. + Revised png_squelch_warnings() so it might work. + Updated makefile.sgcc and makefile.solaris; added makefile.solaris-x86. + +version 1.2.19beta10 [May 24, 2007] + Resquelched png_squelch_warnings(), use "__attribute__((used))" instead. + +version 1.2.19beta11 [May 28, 2007] + Return 0 from png_get_sPLT() and png_get_unknown_chunks() if png_ptr is NULL; + changed three remaining instances of png_strcpy() to png_strncpy() (David + Hill). + Make test for NULL row_buf at the beginning of png_do_read_transformations + unconditional. + +version 1.2.19beta12 [May 28, 2007] + Revised pnggccrd.c. + +version 1.2.19beta13 [June 14, 2007] + Prefer PNG_USE_PNGVCRD when _MSC_VER is defined in pngconf.h + +version 1.2.19beta14 [June 16, 2007] + Fix bug with handling of 16-bit transparency, introduced in 1.2.19beta2 + +version 1.2.19beta15 [June 17, 2007] + Revised pnggccrd.c. + +version 1.2.19beta16 [June 18, 2007] + Revised pnggccrd.c again. + Updated contrib/gregbook. + Changed '#include "pnggccrd.c"' to 'include "$srcdir/pnggccrd.c"' + in configure.ac + +version 1.2.19beta17 [June 19, 2007] + Revised many of the makefiles, to set -DPNG_NO_MMX_CODE where needed + and to not use -O3 unless -DPNG_NO_MMX_CODE is also set. + +version 1.2.19beta18 [June 23, 2007] + Replaced some C++ style comments with C style comments in pnggccrd.c. + Copied optimized C code from pnggccrd.c to pngrutil.c, removed dependency + on pnggccrd.o from many makefiles. + Added sl and dylib to list of extensions be installed by Makefile.am + +version 1.2.19beta19 [June 28, 2007] + Fixed testing PNG_RGB_TO_GRAY_ERR & PNG_RGB_TO_GRAY_WARN in pngrtran.c + More cleanup of pnggccrd.c and pngvcrd.c + +version 1.2.19beta20 [June 29, 2007] + Rebuilt Makefile.in and configure using libtool-1.5.24. + Fixed typo in pnggccrd.c + +version 1.2.19beta21 [June 30, 2007] + More revision of pnggccrd.c + Added "test" target to Makefile.in and Makefile.am + +version 1.2.19beta22 [July 3, 2007] + Added info about pngrutil/pnggccrd/pngvcrd to png_get_header_version() + Fix type definition of dummy_value_a, b in pnggccrd.c + +version 1.2.19beta23 [July 10, 2007] + Revert change to type definition of dummy_value_a, b in pnggccrd.c + Make sure __PIC__ is defined in pnggccrd.c when PIC is defined. + Require gcc-4.1 or better to use PNG_HAVE_MMX_FILTER_ROW on x86_64 platforms + +version 1.2.19beta24 [July 14, 2007] + Added PNG_NO_READ_FILTER, PNG_NO_WRITE_FILTER, PNG_NO_WARNING macros. + Added contrib/pngminim to demonstrate building minimal encoder and decoder + +version 1.2.19beta25 [July 15, 2007] + Removed the new PNG_NO_READ_FILTER macro since it would make the library + unable to read valid PNG files, and filtering is at the heart of the + PNG format. + +version 1.2.19beta26 [July 16, 2007] + Changed "png_free(str)" to "png_free(png_ptr,str)" in pngrutil.c WinCE + code (Yves Piguet). This bug was introduced in libpng-1.2.14. + Updated scripts/CMakeLists.txt + Relocated a misplaced #endif in pnggccrd.c + +version 1.2.19beta27 [July 17, 2007] + Fixed incorrect stride and number of bytes copied (was 4 instead of + 6 bytes) in the cleanup loop of pnggccrd.c and pngvcrd.c for handling + the end of 48-bit interlaced rows (Glenn R-P). + +version 1.2.19beta28 [July 19, 2007] + Removed requirement for gcc-4.1 or better to use PNG_HAVE_MMX_FILTER_ROW + on x86_64 platforms + Added png_warning() in pngrutil.c for short iCCP, iTXt, sPLT, or zTXT chunks. + Revised pngtest.c so warnings are displayed regardless of PNG_NO_STDIO. + +version 1.2.19beta29 [July 20, 2007] + Fix typo in pnggccrd.c (%%eax should be %%ax in secondloop48) + +version 1.2.19beta30 [July 26, 2007] + Revised pnggccrd.c + +version 1.2.19beta31 [July 27, 2007] + Fix typos in pnggccrd.c + +version 1.0.27rc1 and 1.2.19rc1 [July 31, 2007] + Disable PNG_MMX_CODE_SUPPORTED when PNG_ASSEMBLER_CODE_SUPPORTED is off. + Enable PNG_MMX_READ_FILTER_* by default, except when gcc-3.x is being + used (they were inadvertently disabled in libpng-1.2.19beta23). + Fix some debugging statements in pnggccrd.c and pngrutil.c + Added information about disabling the MMX code in libpng documentation. + +version 1.0.27rc2 and 1.2.19rc2 [August 4, 2007] + Removed some "#if 0" blocks. + Made a global struct local in pngvcrd.c to make it thread safe. + Issue a png_error() if application attempts to transform a row tht + has not been initialized. + +version 1.0.27rc3 and 1.2.19rc3 [August 9, 2007] + Slightly revised pngvcrd.c + +version 1.0.27rc4 and 1.2.19rc4 [August 9, 2007] + Revised pnggccrd.c debugging change of rc1, which was broken. + Revised scripts/CMakeLists.txt + Change default to PNG_NO_GLOBAL_ARRAYS for MSVC. + Turn off PNG_FLAG_ROW_INIT flag when setting transforms that expand pixels. + +version 1.0.27rc5 and 1.2.19rc5 [August 10, 2007] + Fix typo (missing '"') in pnggccrd.c + Revise handling of png_strtod in recent versions of WINCE + +version 1.0.27rc6 and 1.2.19rc6 [August 15, 2007] + Fix typo (missing ',') in contrib/gregbook/readpng2.c + Undid row initialization error exit added to rc2 and rc4. + +version 1.0.27 and 1.2.19 [August 18, 2007] + Conditionally restored row initialization error exit. + +version 1.2.20beta01 [August 19, 2007] + Fixed problem with compiling pnggccrd.c on Intel-Apple platforms. + Changed png_malloc() to png_malloc_warn() in png_set_sPLT(). + Added PNG_NO_ERROR_TEXT feature, with demo in contrib/pngminim + Removed define PNG_WARN_UNINITIALIZED_ROW 1 /* 0: warning; 1: error */ + because it caused some trouble. + +version 1.2.20beta02 [August 20, 2007] + Avoid compiling pnggccrd.c on Intel-Apple platforms. + +version 1.2.20beta03 [August 20, 2007] + Added "/D PNG_NO_MMX_CODE" to the non-mmx builds of projects/visualc6 + and visualc71. + +version 1.2.20beta04 [August 21, 2007] + Revised pngvcrd.c for improved efficiency (Steve Snyder). + +version 1.2.20rc1 [August 23, 2007] + Revised pngconf.h to set PNG_NO_MMX_CODE for gcc-3.x compilers. + +version 1.2.20rc2 [August 27, 2007] + Revised scripts/CMakeLists.txt + Revised #ifdefs to ensure one and only one of pnggccrd.c, pngvcrd.c, + or part of pngrutil.c is selected. + +version 1.2.20rc3 [August 30, 2007] + Remove a little more code in pngwutil.c when PNG_NO_WRITE_FILTER is selected. + Added /D _CRT_SECURE_NO_WARNINGS to visual6c and visualc71 projects. + Compile png_mmx_support() in png.c even when PNG_NO_MMX_CODE is defined. + Restored a "superfluous" #ifdef that was removed from 1.2.20rc2 pnggccrd.c, + breaking the png_mmx_support() function. + +version 1.2.20rc4 [September 1, 2007] + Removed Intel contributions (MMX, Optimized C). + +version 1.2.20rc5 [September 2, 2007] + Restored configure and Makefile.in to rc3 and put a snippet of code in + pnggccrd.c, to ensure configure makes the same PNG_NO_MMX_CODE selection + +version 1.2.20rc6 [September 2, 2007] + Fixed bugs in scripts/CMakeLists.txt + Removed pngvcrd.c references from msvc projects. + +version 1.0.28 and 1.2.20 [September 8, 2007] + Removed "(NO READ SUPPORT)" from png_get_header_version() string. + +version 1.2.21beta1 [September 14, 2007] + Fixed various mistakes reported by George Cook and Jeff Phillips: + logical vs bitwise NOT in pngrtran.c, bug introduced in 1.2.19rc2 + 16-bit cheap transparency expansion, bug introduced in 1.2.19beta2 + errors with sizeof(unknown_chunk.name), bugs introduced in 1.2.19beta11 + <= compare with unsigned var in pngset.c, should be ==. + +version 1.2.21beta2 [September 18, 2007] + Removed some extraneous typecasts. + +version 1.2.21rc1 [September 25, 2007] + Fixed potential out-of-bounds reads in png_handle_pCAL() and + png_handle_ztXt() ("flayer" results reported by Tavis Ormandy). + +version 1.2.21rc2 [September 26, 2007] + Fixed potential out-of-bounds reads in png_handle_sCAL(), + png_handle_iTXt(), and png_push_read_tEXt(). + Remove some PNG_CONST declarations from pngwutil.c to avoid compiler warnings + Revised makefiles to update paths in libpng.pc properly. + +version 1.2.21rc3 [September 27, 2007] + Revised makefiles to update "Libs" in libpng.pc properly. + +version 1.0.29 and 1.2.21rc3 [October 4, 2007] + No changes. + +version 1.2.22beta1 [October 4, 2007] + Again, fixed logical vs bitwise NOT in pngrtran.c, bug introduced + in 1.2.19rc2 + +version 1.2.22beta2 [October 5, 2007] + Fixed string length error in pngset.c (caused crashes while decoding iCCP) + Add terminating NULL after each instance of png_strncpy(). + +version 1.2.22beta3 [October 6, 2007] + Fix two off-by-one terminating NULL after png_strncpy(). + +version 1.2.22beta4 [October 7, 2007] + Changed some 0 to '\0'. + +version 1.0.30rc1 and 1.2.22rc1 [October 8, 2007] + No changes. + +version 1.0.30 and 1.2.22 [October 13, 2007] + No changes. + +version 1.2.23beta01 [October 15, 2007] + Reduced number of invocations of png_strlen() in pngset.c. + Changed [azAZ09_] to [_abcde...89] in Makefile.am for better localization. + +version 1.2.23beta02 [October 16, 2007] + Eliminated png_strncpy() and png_strcpy() (Pierre Poissinger) + Changed $AN to $(AN) in Makefile.am. + +version 1.2.23beta03 [October 16, 2007] + Fixed off-by-one error in pngset.c + Restore statement to set last character of buffer to \0 in pngerror.c + +version 1.2.23beta04 [October 23, 2007] + Reject attempt to set all-zero cHRM values. + +version 1.2.23beta05 [October 26, 2007] + Add missing quotes in projects/visualc6, lost in version 1.2.20rc3 + +version 1.2.23rc01 [November 2, 2007] + No changes. + +version 1.2.23 [November 6, 2007] + No changes. + +version 1.2.24beta01 [November 19, 2007] + Moved misplaced test for malloc failure in png_set_sPLT(). This bug was + introduced in libpng-1.2.20beta01. + Ifdef out avg_row etc from png.h and pngwrite.c when PNG_NO_WRITE_FILTER + Do not use png_ptr->free_fn and png_ptr->mem_fn in png_destroy_read_struct() + when png_ptr is NULL (Marshall Clow). + Updated handling of symbol prefixes in Makefile.am and configure.ac (Mike + Frysinger). + +version 1.2.24beta02 [November 30, 2007] + Removed a useless test and fixed incorrect test in png_set_cHRM_fixed() + (David Hill). + +version 1.2.24rc01 [December 7, 2007] + No changes. + +version 1.2.24 [December 14, 2007] + Make sure not to redefine _BSD_SOURCE in pngconf.h + Revised gather.sh and makefile.std in contrib/pngminim to avoid compiling + unused files. + +version 1.2.25beta01 [January 7, 2008] + Fixed bug with unknown chunk handling, introduced in version 1.2.17rc2 + +version 1.2.25beta02 [January 10, 2008] + Prevent gamma from being applied twice. + +version 1.2.25rc01 [January 17, 2008] + No changes. + +version 1.2.25beta03 [January 22, 2008] + Fixed some continue-after-malloc-failure errors in pngset.c (David Hill) + Check for info_ptr == NULL in png_read_info() and png_process_data(). + Check for possible use of NULL user_png_ver[] in png_create_read_struct(). + Change "if (swidth == NULL)" to "if (sheight == NULL)" in png_handle_sCAL + (bug introduced in libpng-1.2.4/1.0.13). + Return from png_destroy_read_struct() if png_ptr_ptr is NULL. + Fix overflow of "msg" in png_decompress_chunk(). + +version 1.2.25beta04 [January 26, 2008] + Work around Coverity bug report by slightly refactoring + png_read_push_finish_row() + +version 1.2.25beta05 [January 31, 2008] + Added libpng-1.2.25beta05.tar.lzma to distribution. Get the lzma codec + from <http://tukaani.org/lzma>. + Added lp1225b05.7z to distribution. Get the 7-zip decoder from + from <http://www.7-zip.org>. + Fixed some broken links in the README file. + +version 1.2.25beta06 [February 6, 2008] + Refactored png_read_push_finish_row() again, trying to satisfy Coverity. + Fixed potential NULL dereference of png_ptr in png_destroy_write_struct(); + clarified potential NULL dereference of png_ptr in png_destroy_read_struct(); + fixed potential NULL dereference of info_ptr in png_handle_bKGD(); + fixed potential NULL dereference of user_png_ver[] in + png_create_write_struct_2(). (Coverity) + +version 1.2.25rc02 [February 10, 2008] + Reset png_ptr->pass in png_read_push_finish_row() before break. + Changed "pass" from png_byte to int. + +version 1.2.25 and 1.0.31 [February 18, 2008] + No changes. + +version 1.2.26beta01 [February 21, 2008] + Added missing "(" in pngmem.c. Bug introduced in libpng-1.2.2/1.0.13 + +version 1.2.26beta02 [March 12, 2008] + Refined error message returned from deflateInit2 in pngwutil.c + Check IHDR length in png_push_read_chunk() before saving it. + +version 1.2.26beta03 [March 16, 2008] + Revised contrib/gregbook to handle premature end-of-file and file + read errors correctly. + +version 1.2.26beta04 [March 18, 2008] + Free png_ptr->big_row_buf and png_ptr->prev_row before allocating + new copies in png_read_start_row(). Bug introduced in libpng-1.2.22. + +version 1.2.26beta05 [March 19, 2008] + Removed extra png_free() added in libpng-1.2.26beta04. + +version 1.2.26beta06 [March 19, 2008] + Avoid reallocating big_row_buf and prev_row when the size does not increase. + +version 1.2.26rc01 [March 26, 2008] + Ifdef out some code that is unused when interlacing is not supported. + +versions 1.0.32 and 1.2.26 [April 2, 2008] + No changes. + +version 1.2.27beta01 [April 12, 2008] + Fixed bug (introduced in libpng-1.0.5h) with handling zero-length + unknown chunks. + Added more information about png_set_keep_unknown_chunks() to the + documentation. + Reject tRNS chunk with out-of-range samples instead of masking off + the invalid high bits as done in since libpng-1.2.19beta5. + +version 1.2.27beta02 [April 13, 2008] + Revised documentation about unknown chunk and user chunk handling. + Keep tRNS chunk with out-of-range samples and issue a png_warning(). + +version 1.2.27beta03 [April 14, 2008] + Added check for NULL ptr in TURBOC version of png_free_default(). + Removed several unnecessary checks for NULL before calling png_free(). + Revised png_set_tRNS() so that calling it twice removes and invalidates + the previous call. + Revised pngtest to check for out-of-range tRNS samples. + +version 1.2.27beta04 [April 18, 2008] + Added AC_LIBTOOL_WIN32_DLL to configure.ac + Rebuilt Makefile.in, aclocal.m4, and configure with autoconf-2.62 + +version 1.2.27beta05 [April 19, 2008] + Added MAINTAINERCLEANFILES variable to Makefile.am + +version 1.2.27beta06 [April 21, 2008] + Avoid changing color_type from GRAY to RGB by + png_set_expand_gray_1_2_4_to_8(). + +version 1.2.27rc01 [April 23, 2008] + Fix broken URL for rfc2083 in png.5 and libpng-*.txt + +version 1.0.33 and 1.2.27 [April 30, 2008] + No changes. + +version 1.0.34 and 1.2.28 [April 30, 2008] + Rebuilt Makefile.in, aclocal.m4, and configure with autoconf-2.61 + due to backward incompatibilities. + Removed a stray object file from contrib/gregbook + +version 1.2.29beta01 [May 1, 2008] + Removed some stray *.diff and *.orig files + +version 1.2.29beta02 [May 1, 2008] + Reverted Makefile.in, aclocal.m4, and configure to the libpng-1.2.26 + versions. + +version 1.2.29beta03 [May 2, 2008] + Added --force to autogen libtoolize options and --force-missing to + automake options. + Changed $(ECHO) to echo in Makefile.am and Makefile.in + Updated all configure files to autoconf-2.62 + Comment out pnggcrd.c code with #ifdef/#endif if using MSC_VER + +version 1.2.29rc01 [May 4, 2008] + No changes. + +version 1.0.35 and 1.2.29 [May 8, 2008] + No changes. + +version 1.0.37 [May 9, 2008] + Updated Makefile.in and configure (omitted version 1.0.36). + +version 1.2.30beta01 [May 29, 2008] + Updated libpng.pc-configure.in and libpng-config.in per debian bug reports. + +version 1.2.30beta02 [June 25, 2008] + Restored png_flush(png_ptr) at the end of png_write_end(), that was + removed from libpng-1.0.9beta03. + +version 1.2.30beta03 [July 6, 2008] + Merged some cosmetic whitespace changes from libpng-1.4.0beta19. + Inline call of png_get_uint_32() in png_get_uint_31(), as in 1.4.0beta19. + Added demo of decoding vpAg and sTER chunks to pngtest.c, from 1.4.0beta19. + Changed PNGMAJ from 0 to 12 in makefile.darwin, which does not like 0. + Added new private function png_read_chunk_header() from 1.4.0beta19. + Merge reading of chunk length and chunk type into a single 8-byte read. + Merge writing of chunk length and chunk type into a single 8-byte write. + +version 1.2.30beta04 [July 10, 2008] + Merged more cosmetic whitespace changes from libpng-1.4.0beta19. + +version 1.0.38rc01, 1.2.30rc01 [July 18, 2008] + No changes. + +version 1.0.38rc02, 1.2.30rc02 [July 21, 2008] + Moved local array "chunkdata" from pngrutil.c to the png_struct, so + it will be freed by png_read_destroy() in case of a read error (Kurt + Christensen). + +version 1.0.38rc03, 1.2.30rc03 [July 21, 2008] + Changed "purpose" and "buffer" to png_ptr->chunkdata to avoid memory leaking. + +version 1.0.38rc04, 1.2.30rc04 [July 22, 2008] + Changed "chunkdata = NULL" to "png_ptr->chunkdata = NULL" several places in + png_decompress_chunk(). + +version 1.0.38rc05, 1.2.30rc05 [July 25, 2008] + Changed all remaining "chunkdata" to "png_ptr->chunkdata" in + png_decompress_chunk() and remove chunkdata from parameter list. + Put a call to png_check_chunk_name() in png_read_chunk_header(). + Revised png_check_chunk_name() to reject a name with a lowercase 3rd byte. + Removed two calls to png_check_chunk_name() occuring later in the process. + +version 1.0.38rc06, 1.2.30rc06 [July 29, 2008] + Added a call to png_check_chunk_name() in pngpread.c + Reverted png_check_chunk_name() to accept a name with a lowercase 3rd byte. + +version 1.0.38r07, 1.2.30r07 [August 2, 2008] + Changed "-Wall" to "-W -Wall" in the CFLAGS in all makefiles (Cosmin Truta) + Declared png_ptr "volatile" in pngread.c and pngwrite.c to avoid warnings. + Added code in pngset.c to quiet compiler warnings. + Updated contrib/visupng/cexcept.h to version 2.0.1 + Relocated a misplaced "#endif /* PNG_NO_WRITE_FILTER */" in pngwutil.c + +version 1.0.38r08, 1.2.30r08 [August 2, 2008] + Enclose "volatile" declarations in #ifdef PNG_SETJMP_SUPPORTED (Cosmin). + +version 1.0.38, 1.2.30 [August 14, 2008] + No changes. + +version 1.2.31rc01 [August 19, 2008] + Removed extra crc check at the end of png_handle_cHRM(). Bug introduced + in libpng-1.2.30beta03 (Heiko Nitzsche). + +version 1.2.31rc02 [August 19, 2008] + Added PNG_WRITE_FLUSH_SUPPORTED block around new png_flush() call. + +version 1.2.31rc03 [August 19, 2008] + Added PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED block, off by default, around + new png_flush(). + +version 1.0.39, 1.2.31 [August 21, 2008] + No changes. + +version 1.2.32beta01 [September 6, 2008] + Shortened tIME_string to 29 bytes in pngtest.c (bug introduced in + libpng-1.2.22). + Fixed off-by-one error introduced in png_push_read_zTXt() function in + libpng-1.2.30beta04/pngpread.c (Harald van Dijk) + These bugs have been given the vulnerability id CVE-2008-3964. + +version 1.0.40, 1.2.32 [September 18, 2008] + No changes. + +version 1.2.33beta01 [October 6, 2008] + Revised makefile.darwin to fix shared library numbering. + Change png_set_gray_1_2_4_to_8() to png_set_expand_gray_1_2_4_to_8() + in example.c (debian bug report) + +version 1.2.33rc01 [October 15, 2008] + No changes. + +version 1.0.41rc01, version 1.2.33rc02 [October 23, 2008] + Changed remaining "key" to "png_ptr->chunkdata" in png_handle_tEXt() + to avoid memory leak after memory failure while reading tEXt chunk.` + +version 1.2.33 [October 31, 2008] + No changes. + +version 1.2.34beta01 [November 27, 2008] + Revised png_warning() to write its message on standard output by default + when warning_fn is NULL. This was the behavior prior to libpng-1.2.9beta9. + Fixed string vs pointer-to-string error in png_check_keyword(). + Added png_check_cHRM_fixed() in png.c and moved checking from pngget.c, + pngrutil.c, and pngwrite.c, and eliminated floating point cHRM checking. + Added check for zero-area RGB cHRM triangle in png_check_cHRM_fixed(). + In png_check_cHRM_fixed(), ensure white_y is > 0, and removed redundant + check for all-zero coordinates that is detected by the triangle check. + Revised png_warning() to write its message on standard output by default + when warning_fn is NULL. + +version 1.2.34beta02 [November 28, 2008] + Corrected off-by-one error in bKGD validity check in png_write_bKGD() + and in png_handle_bKGD(). + +version 1.2.34beta03 [December 1, 2008] + Revised bKGD validity check to use >= x instead of > x + 1 + Merged with png_debug from libpng-1.4.0 to remove newlines. + +version 1.2.34beta04 [December 2, 2008] + More merging with png_debug from libpng-1.4.0 to remove newlines. + +version 1.2.34beta05 [December 5, 2008] + Removed redundant check for key==NULL before calling png_check_keyword() + to ensure that new_key gets initialized and removed extra warning + (Arvan Pritchard). + +version 1.2.34beta06 [December 9, 2008] + In png_write_png(), respect the placement of the filler bytes in an earlier + call to png_set_filler() (Jim Barry). + +version 1.2.34beta07 [December 9, 2008] + Undid previous change and added PNG_TRANSFORM_STRIP_FILLER_BEFORE and + PNG_TRANSFORM_STRIP_FILLER_AFTER conditionals and deprecated + PNG_TRANSFORM_STRIP_FILLER (Jim Barry). + +version 1.0.42rc01, 1.2.34rc01 [December 11, 2008] + No changes. + +version 1.0.42, 1.2.34 [December 18, 2008] + No changes. + +version 1.2.35beta01 [February 4, 2009] + Zero out some arrays of pointers after png_malloc(). (Tavis Ormandy) + +version 1.2.35beta02 [February 4, 2009] + Zero out more arrays of pointers after png_malloc(). + +version 1.2.35beta03 [February 5, 2009] + Use png_memset() instead of a loop to intialize pointers. We realize + this will not work on platforms where the NULL pointer is not all zeroes. + +version 1.2.35rc01 [February 11, 2009] + No changes. + +version 1.2.35rc02 [February 12, 2009] + Fix typo in new png_memset call in pngset.c (png_color should be png_charp) + +version 1.0.43 and 1.2.35 [February 14, 2009] + No changes. + +version 1.2.36beta01 [February 28, 2009] + Revised comments in png_set_read_fn() and png_set_write_fn(). + Revised order of #ifdef's and indentation in png_debug definitions of png.h + bug introduced in libpng-1.2.34. + +version 1.2.36beta02 [March 21, 2009] + Use png_memset() after png_malloc() of big_row_buf when reading an + interlaced file, to avoid a possible UMR. + Undid recent revision of PNG_NO_STDIO version of png_write_flush(). Users + having trouble with fflush() can build with PNG_NO_WRITE_FLUSH defined. + Revised libpng*.txt documentation about use of png_write_flush(). + Removed fflush() from pngtest.c. + Added "#define PNG_NO_WRITE_FLUSH" to contrib/pngminim/encoder/pngusr.h + +version 1.2.36beta03 [March 27, 2009] + Relocated misplaced PNG_1_0_X define in png.h that caused the prototype + for png_set_strip_error_numbers() to be omitted from PNG_NO_ASSEMBLER_CODE + builds. This bug was introduced in libpng-1.2.15beta4. + Added a section on differences between 1.0.x and 1.2.x to libpng.3/libpng.txt + +version 1.2.36beta04 [April 5, 2009] + Fixed potential memory leak of "new_name" in png_write_iCCP() (Ralph Giles) + +version 1.2.36beta05 [April 24, 2009] + Added "ifndef PNG_SKIP_SETJMP_CHECK" block in pngconf.h to allow + application code writers to bypass the check for multiple inclusion + of setjmp.h when they know that it is safe to ignore the situation. + Made some cosmetic changes to whitespace in pngtest output. + Renamed "user_chunk_data" to "my_user_chunk_data" in pngtest.c to suppress + "shadowed declaration" warning from gcc-4.3.3. + Renamed "gamma" to "png_gamma" in pngset.c to avoid "shadowed declaration" + warning about a global "gamma" variable in math.h on some platforms. + +version 1.2.36rc01 [April 30, 2009] + No changes. + +version 1.0.44 and 1.2.36 [May 7, 2009] + No changes. + +version 1.2.37beta01 [May 14, 2009] + Fixed inconsistency in pngrutil.c, introduced in libpng-1.2.36. The + memset() was using "png_ptr->rowbytes" instead of "row_bytes", which + the corresponding png_malloc() uses (Joe Drew). + Clarified usage of sig_bit versus sig_bit_p in example.c (Vincent Torri) + Updated some of the makefiles in the scripts directory (merged with + those in libpng-1.4.0beta57). + +version 1.2.37beta02 [May 19, 2009] + Fixed typo in libpng documentation (FILTER_AVE should be FILTER_AVG) + Relocated misplaced #endif in pngwrite.c, sCAL chunk handler. + Conditionally compile png_read_finish_row() which is not used by + progressive readers. + Added contrib/pngminim/preader to demonstrate building minimal progressive + decoder, based on contrib/gregbook with embedded libpng and zlib. + +version 1.2.37beta03 [May 20, 2009] + In contrib/pngminim/*, renamed "makefile.std" to "makefile", since there + is only one makefile in those directories, and revised the README files + accordingly. + Reformated sources in libpng style (3-space indentation, comment format) + +version 1.2.37rc01 [May 27, 2009] + No changes. + +versions 1.2.37 and 1.0.45 [June 4, 2009] + Reformatted several remaining "else statement;" and "if () statement;" into + two lines. + Added "#define PNG_NO_WRITE_SWAP" to contrib/pngminim/encoder/pngusr.h + and "define PNG_NO_READ_SWAP" to decoder/pngusr.h and preader/pngusr.h + Added sections about the git repository and our coding style to the + documentation (merged from libpng-1.4.0beta62) + Added a section to the libpng documentation about using png_get_io_ptr() + in configure scripts to detect the presence of libpng. + +version 1.2.38beta01 [June 17, 2009] + Revised libpng*.txt and libpng.3 to mention calling png_set_IHDR() + multiple times and to specify the sample order in the tRNS chunk, + because the ISO PNG specification has a typo in the tRNS table. + Changed several PNG_UNKNOWN_CHUNK_SUPPORTED to + PNG_HANDLE_AS_UNKNOWN_SUPPORTED, to make the png_set_keep mechanism + available for ignoring known chunks even when not saving unknown chunks. + Adopted preference for consistent use of "#ifdef" and "#ifndef" versus + "#if defined()" and "if !defined()" where possible. + Added PNG_NO_HANDLE_AS_UNKNOWN in the PNG_LEGACY_SUPPORTED block of + pngconf.h, and moved the various unknown chunk macro definitions + outside of the PNG_READ|WRITE_ANCILLARY_CHUNK_SUPPORTED blocks. + +version 1.0.46 [June 18, 2009] + Removed some editing cruft from scripts/libpng.pc.in and some makefiles. + +version 1.2.38rc01 [June 24, 2009] + No changes. + +version 1.2.38rc02 [June 29, 2009] + Added a reference to the libpng license in each source file. + +version 1.2.38rc03 [July 11, 2009] + Revised references to the libpng license in pngconf.h and contrib/visupng + source files. + Rebuilt configure scripts with autoconf-2.63. + +version 1.0.47 and 1.2.38 [July 16, 2009] + No changes. + +version 1.2.39beta01 [July 25, 2009] + Added a prototype for png_64bit_product() in png.c + +version 1.2.39beta02 [July 27, 2009] + Avoid a possible NULL dereference in debug build, in png_set_text_2(). + (bug introduced in libpng-0.95, discovered by Evan Rouault) + +version 1.2.39beta03 [July 29, 2009] + Relocated new png_64_bit_product() prototype into png.h + Expanded the information about prototypes in the libpng style section of + the documentation. + Rebuilt configure scripts with autoconf-2.64. + +version 1.2.39beta04 [August 1, 2009] + Replaced *.tar.lzma with *.txz in distribution. Get the xz codec + from <http://tukaani.org/xz>. + +version 1.2.39beta05 [August 1, 2009] + Reject attempt to write iCCP chunk with negative embedded profile length + (JD Chen) + +version 1.2.39c01 [August 6, 2009] + No changes. + +version 1.2.39 and 1.0.48 [August 13, 2009] + No changes. + +version 1.2.40beta01 [August 20, 2009] + Removed an extra png_debug() recently added to png_write_find_filter(). + Fixed incorrect #ifdef in pngset.c regarding unknown chunk support. + +version 1.2.40rc01 [September 2, 2009] + Various bugfixes and improvements to CMakeLists.txt (Philip Lowman) + +version 1.2.40 and 1.0.49 [September 2, 2009] + No changes. + +version 1.0.50 [September 10, 2009] + Removed some editing cruft from pngset.c and pngwutil.c. + +version 1.2.41beta01 [September 25, 2009] + Moved redundant IHDR checking into new png_check_IHDR() in png.c + and report all errors found in the IHDR data. + Eliminated useless call to png_check_cHRM() from pngset.c + Expanded TAB characters in pngrtran.c + +version 1.2.41beta02 [September 30, 2009] + Revised png_check_IHDR(). + +version 1.2.41beta03 [October 1, 2009] + Revised png_check_IHDR() again, to check info_ptr members instead of + the contents of the returned parameters. + +version 1.2.41beta04 [October 7, 2009] + Added "xcode" project similar one already in libpng-1.4.0beta (Alam Arias). + Ported some cosmetic changes from libpng-1.4.0beta86. + Eliminated a shadowed declaration of "pp" in png_handle_sPLT(). + +version 1.2.41beta05 [October 17, 2009] + Revised pngconf.h to make it easier to enable iTXt support. From libpng + version 1.2.9 through 1.2.40, defining PNG_iTXt_SUPPORTED did not work + as expected. + Ported some cosmetic changes from libpng-1.4.0beta87, changing + many "#if defined(x)" to "#ifdef x". + +version 1.2.41beta06 [October 18, 2009] + Restored PNG_USE_LOCAL_ARRAYS code in pngread.c that was inadvertently + deleted in libpng-1.2.41beta05. + Converted all PNG_NO_* tests to PNG_*_SUPPORTED everywhere except pngconf.h + as in libpng-1.4.0beta78 and later. + +version 1.2.41beta07 [October 21, 2009] + Ported some cosmetic changes from libpng-1.4.0rc01, changing + many "#if defined(x)" to "#ifdef x" in png.h and pngconf.h. + +version 1.2.41beta08 [October 30, 2009] + Ported from libpng-1.4.0rc01: png_calloc(), png_get_io_chunk_name(), + png_get_io_state(), png_set_user_cache_max(), png_get_user_cache_max(), + png_set_premultiply_alpha, and png_do_read_premultiply_alpha(). + Relocated png_do_chop() ahead of building gamma tables in pngrtran.c + This avoids building 16-bit gamma tables unnecessarily. + +version 1.2.41beta09 [November 1, 2009] + Removed a harmless extra png_set_invert_alpha() from pngwrite.c + More bugfixes and improvements to CMakeLists.txt (Philip Lowman) + Moved CMakeLists.txt from scripts into the main libpng directory. + Apply png_user_chunk_cache_max within png_decompress_chunk(). + Merged libpng-1.2.41.txt with libpng-1.4.0.txt where appropriate. + +version 1.2.41beta10 [November 1, 2009] + Enabled iTXt support by default. To ensure binary compatibility with + previous versions, the "lang" and "lang_key" members will be assumed + to be omitted from previous versions unless the current libpng + version was built with PNG_iTXt_SUPPORTED (which is otherwise no + longer necessary to gain iTXt support), as a signal that the user has + been building previous versions with PNG_iTXt_SUPPORTED as well. + +version 1.2.41beta11 [November 2, 2009] + Store user's user_png_ver in new png_ptr->user_png_ver element. + Revised iTXt support. To ensure binary compatibility with + previous versions, the "lang" and "lang_key" members will be assumed + to be omitted from versions prior to 1.2.41beta11 whenever there is a + library mismatch. + +version 1.2.41beta12 [November 2, 2009] + Free png_ptr->user_png_ver when destroying png_ptr. + +version 1.2.41beta13 [November 3, 2009] + Updated scripts/pngw32.def and projects/wince/png32ce.def + Copied projects/wince/png32ce.def to the scripts directory. + Added scripts/makefile.wce + Patched ltmain.sh for wince support. + Added PNG_CONVERT_tIME_SUPPORTED macro. + +version 1.2.41beta14 [November 8, 2009] + versions 1.2.41beta05 through 1.2.41beta13 were abandoned. + The 1.0.x/1.2.x series will only receive security updates from now on. + Make inclusion of time.h in pngconf.h depend on PNG_CONVERT_tIME_SUPPORTED + Make #define PNG_CONVERT_tIME_SUPPORTED depend on PNG_WRITE_tIME_SUPPORTED + Reverted iTXt compatibility stuff from 1.2.41beta05, 1.2.41beta11, and + 1.2.41beta12. + Reverted IOSTATE feature, user_cache_max, and premultiply_alpha features + from 1.2.41beta08. + Retained png_calloc() from 1.2.41beta08 but as a non-exported function, + and removed reference to png_calloc from scripts/*.def + +version 1.2.41beta15 [November 8, 2009] + Added PNG_DEPSTRUCT, PNG_DEPRECATED, PNG_USE_RESULT, PNG_NORETURN, and + PNG_ALLOCATED macros to detect deprecated direct access to the + png_struct or info_struct members and other deprecated usage in + applications (John Bowler). + Updated scripts/makefile* to add "-DPNG_CONFIGURE_LIBPNG" to CFLAGS, + to prevent warnings about direct access to png structs by libpng + functions while building libpng. They need to be tested, especially + those using compilers other than gcc. + Updated projects/visualc6 and visualc71 with "/d PNG_CONFIGURE_LIBPNG". + +version 1.2.41beta16 [November 9, 2009] + Removed three direct references to read_info_ptr members in pngtest.c + that were detected by the new PNG_DEPSTRUCT macro. + Only #define PNG_DEPSTRUCT, etc. in pngconf.h if not already defined. + +version 1.2.41beta17 [November 10, 2009] + Updated CMakeLists.txt to add "-DPNG_CONFIGURE_LIBPNG" to the definitions. + Marked deprecated function prototypes with PNG_DEPRECATED. + Marked memory allocation function prototypes with PNG_ALLOCATED. + Changed png_check_sig() to !png_sig_cmp() in contrib programs. + Corrected the png_get_IHDR() call in contrib/gregbook/readpng2.c + Added "-DPNG_CONFIGURE_LIBPNG" to the contrib/pngminum makefiles. + +version 1.2.41beta18 [November 11, 2009] + Renamed scripts/makefile.wce to scripts/makefile.cegcc + Marked nonexported functions with PNG_PRIVATE macro. + +version 1.2.41rc01 and 1.0.51rc01 [November 18, 2009] + Revised scripts/*.def to reflect functions actually exported by libpng. + Updated the copyright year in scripts/pngw32.rc from 2004 to 2009. + Moved descriptions of makefiles and other scripts out of INSTALL into + scripts/README.txt + +version 1.2.41rc02 [November 22, 2009] + Rebuilt the configure scripts with autoconf-2.65 + +version 1.2.41rc03 [November 25, 2009] + Disabled the new pedantic warnings about deprecated function use + and deprecated structure access unless the user defines + PNG_PEDANTIC_WARNINGS. + Added "#define PNG_NO_PEDANTIC_WARNINGS" in the libpng source files. + Removed "-DPNG_CONFIGURE_LIBPNG" from the makefiles and projects. + +version 1.2.41 and 1.0.51 [December 3, 2009] + Updated the list of files and made some cosmetic changes in README. + +version 1.2.42beta01 [December 4, 2009] + Removed "#define PNG_NO_ERROR_NUMBERS" that was inadvertently added + to pngconf.h in version 1.2.41. + Revised scripts/makefile.netbsd, makefile.openbsd, and makefile.sco + to put png.h and pngconf.h in $prefix/include, like the other scripts, + instead of in $prefix/include/libpng. Also revised makefile.sco + to put them in $prefix/include/libpng12 instead of in + $prefix/include/libpng/libpng12. + Removed leftover "-DPNG_CONFIGURE_LIBPNG" from scripts/makefile.darwin + +version 1.2.42beta02 [December 11, 2009] + Removed leftover "-DPNG_CONFIGURE_LIBPNG" from contrib/pngminim/*/makefile + Relocated png_do_chop() to its original position in pngrtran.c. The + change in version 1.2.41beta08 caused transparency to be handled wrong + in some 16-bit datastreams (Yusaku Sugai). + +version 1.2.42rc01 [December 17, 2009] + No changes. + +version 1.2.42rc02 [December 22, 2009] + Renamed libpng-pc.in back to libpng.pc.in and revised CMakeLists.txt + (revising changes made in 1.2.41beta17 and 1.2.41rc01) + +version 1.2.42rc03 [December 25, 2009] + Swapped PNG_UNKNOWN_CHUNKS_SUPPORTED and PNG_HANDLE_AS_UNKNOWN_SUPPORTED + in pngset.c to be consistent with other changes in version 1.2.38. + +version 1.2.42rc04 [January 1, 2010] + Marked png_memcpy_check() and png_memset_check() PNG_DEPRECATED. + Updated copyright year. + +version 1.2.42rc05 [January 2, 2010] + Avoid deprecated references to png_ptr-io_ptr and png_ptr->error_ptr + in pngtest.c + +version 1.2.42 and 1.0.52 [January 3, 2010] + No changes. + +version 1.2.43beta01 [January 27, 2010] + Updated CMakeLists.txt for consistent indentation and to avoid an + unclosed if-statement warning (Philip Lowman). + Removed "#ifdef PNG_1_0_X / #endif" surrounding + PNG_READ_16_TO_8_SUPPORTED and PNG_READ_GRAY_TO_RGB_SUPPORTED + in pngconf.h. These were added in libpng-1.2.41beta08 and libpng-1.0.51, + which introduced a binary incompatibility with libpng-1.0.50. + Backported new png_decompress_chunk() algorithm from libpng-1.4.1. + +version 1.2.43beta02 [February 1, 2010] + Backported two-pass png_decompress_chunk() algorithm from libpng-1.4.1. + +version 1.2.43beta03 [February 6, 2010] + Backported fast png_push_save_buffer() algorithm from libpng-1.4.1. + Backported some cosmetic changes from libpng-1.4.1. + +version 1.2.43beta04 [February 8, 2010] + Reverted recent changes to png_push_save-buffer(). + Removed PNGAPI declaration of png_calloc() and png_write_sig() in + 1ibpng-1.2.X, introduced by mistake in libpng-1.2.41. + Return allocated "old_buffer" in png_push_save_buffer() before png_error() + to avoid a potential memory leak. + +version 1.2.43beta05 [February 8, 2010] + Ported rewritten png_decompress_chunk() by John Bowler from libpng-1.4.1. + +version 1.0.53rc01 and 1.2.43rc01 [February 18, 2010] + No changes. + +version 1.0.53rc02 and 1.2.43rc02 [February 19, 2010] + Define _ALL_SOURCE in configure.ac, makefile.aix, and CMakeLists.txt + when using AIX compiler. + +version 1.0.53 and 1.2.43 [February 25, 2010] + Removed unused gzio.c from contrib/pngminim gather and makefile scripts + +version 1.2.44beta01 [June 18, 2010] + In pngpread.c: png_push_have_row() add check for new_row > height + Removed the now-redundant check for out-of-bounds new_row from example.c + +version 1.2.44beta02 [June 19, 2010] + In pngpread.c: png_push_process_row() add check for too many rows. + Removed the now-redundant check for new_row > height in png_push_have_row(). + +version 1.2.44beta03 [June 20, 2010] + Rewrote png_process_IDAT_data() to consistently treat extra data as warnings + and handle end conditions more cleanly. + Removed the new (beta02) check in png_push_process_row(). + +version 1.2.44rc01 [June 21, 2010] + Revised some comments in png_process_IDAT_data(). + +version 1.2.44rc02 [June 22, 2010] + Stop memory leak when reading a malformed sCAL chunk. + +version 1.2.44rc03 [June 23, 2010] + Revised pngpread.c patch of beta05 to avoid an endless loop. + +version 1.2.44 [June 26, 2010] + Updated some of the "last changed" dates. + +Send comments/corrections/commendations to png-mng-implement at lists.sf.net +(subscription required; visit +https://lists.sourceforge.net/lists/listinfo/png-mng-implement +to subscribe) +or to glennrp at users.sourceforge.net + +Glenn R-P +*/ diff --git a/contrib/syslinux-4.02/com32/lib/libpng/KNOWNBUG b/contrib/syslinux-4.02/com32/lib/libpng/KNOWNBUG new file mode 100644 index 0000000..59f7261 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libpng/KNOWNBUG @@ -0,0 +1,29 @@ + +Known bugs in libpng version 1.2.44 + +1. December 4, 2009: The PNG_NO_ERROR_NUMBERS macro was inadvertently + defined in libpng-1.2.41/pngconf.h, which may cause a problem with + building a binary-compatible library. + + STATUS: This will be fixed in libpng-1.2.42. In the meantime, simply + delete the definition from line : + +2. February 23, 2006: The custom makefiles don't build libpng with -lz. + + STATUS: This is a subject of debate. The change will probably be made + as a part of a major overhaul of the makefiles in libpng version 1.4.0. + +3. February 24, 2006: The Makefile generated by the "configure" script + fails to install symbolic links + libpng12.so => libpng12.so.0.1.2.9betaN + that are generated by the custom makefiles. + +4. September 4, 2007: There is a report that pngtest crashes on MacOS 10. + + STATUS: workarounds are + 1) Compile without optimization (crashes are observed with + -arch i386 and -O2 or -O3, using gcc-4.0.1). + 2) Compile pngtest.c with PNG_DEBUG defined (the bug goes away if + you try to look at it). + 3) Ignore the crash. The library itself seems to be OK. + diff --git a/contrib/syslinux-4.02/com32/lib/libpng/LICENSE b/contrib/syslinux-4.02/com32/lib/libpng/LICENSE new file mode 100644 index 0000000..e5561c2 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libpng/LICENSE @@ -0,0 +1,111 @@ + +This copy of the libpng notices is provided for your convenience. In case of +any discrepancy between this copy and the notices in the file png.h that is +included in the libpng distribution, the latter shall prevail. + +COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: + +If you modify libpng you may insert additional notices immediately following +this sentence. + +This code is released under the libpng license. + +libpng versions 1.2.6, August 15, 2004, through 1.2.44, June 26, 2010, are +Copyright (c) 2004, 2006-2009 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-1.2.5 +with the following individual added to the list of Contributing Authors + + Cosmin Truta + +libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are +Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-1.0.6 +with the following individuals added to the list of Contributing Authors + + Simon-Pierre Cadieux + Eric S. Raymond + Gilles Vollant + +and with the following additions to the disclaimer: + + There is no warranty against interference with your enjoyment of the + library or against infringement. There is no warranty that our + efforts or the library will fulfill any of your particular purposes + or needs. This library is provided with all faults, and the entire + risk of satisfactory quality, performance, accuracy, and effort is with + the user. + +libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are +Copyright (c) 1998, 1999 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-0.96, +with the following individuals added to the list of Contributing Authors: + + Tom Lane + Glenn Randers-Pehrson + Willem van Schaik + +libpng versions 0.89, June 1996, through 0.96, May 1997, are +Copyright (c) 1996, 1997 Andreas Dilger +Distributed according to the same disclaimer and license as libpng-0.88, +with the following individuals added to the list of Contributing Authors: + + John Bowler + Kevin Bracey + Sam Bushell + Magnus Holmgren + Greg Roelofs + Tom Tanner + +libpng versions 0.5, May 1995, through 0.88, January 1996, are +Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. + +For the purposes of this copyright and license, "Contributing Authors" +is defined as the following set of individuals: + + Andreas Dilger + Dave Martindale + Guy Eric Schalnat + Paul Schmidt + Tim Wegner + +The PNG Reference Library is supplied "AS IS". The Contributing Authors +and Group 42, Inc. disclaim all warranties, expressed or implied, +including, without limitation, the warranties of merchantability and of +fitness for any purpose. The Contributing Authors and Group 42, Inc. +assume no liability for direct, indirect, incidental, special, exemplary, +or consequential damages, which may result from the use of the PNG +Reference Library, even if advised of the possibility of such damage. + +Permission is hereby granted to use, copy, modify, and distribute this +source code, or portions hereof, for any purpose, without fee, subject +to the following restrictions: + +1. The origin of this source code must not be misrepresented. + +2. Altered versions must be plainly marked as such and must not + be misrepresented as being the original source. + +3. This Copyright notice may not be removed or altered from any + source or altered source distribution. + +The Contributing Authors and Group 42, Inc. specifically permit, without +fee, and encourage the use of this source code as a component to +supporting the PNG file format in commercial products. If you use this +source code in a product, acknowledgment is not required but would be +appreciated. + + +A "png_get_copyright" function is available, for convenient use in "about" +boxes and the like: + + printf("%s",png_get_copyright(NULL)); + +Also, the PNG logo (in PNG format, of course) is supplied in the +files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). + +Libpng is OSI Certified Open Source Software. OSI Certified Open Source is a +certification mark of the Open Source Initiative. + +Glenn Randers-Pehrson +glennrp at users.sourceforge.net +June 26, 2010 diff --git a/contrib/syslinux-4.02/com32/lib/libpng/README b/contrib/syslinux-4.02/com32/lib/libpng/README new file mode 100644 index 0000000..ff7ac1f --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libpng/README @@ -0,0 +1,275 @@ +README for libpng version 1.2.44 - June 26, 2010 (shared library 12.0) +See the note about version numbers near the top of png.h + +See INSTALL for instructions on how to install libpng. + +Libpng comes in several distribution formats. Get libpng-*.tar.gz, +libpng-*.tar.xz, or libpng-*.tar.bz2 if you want UNIX-style line +endings in the text files, or lpng*.7z or lpng*.zip if you want DOS-style +line endings. You can get UNIX-style line endings from the *.zip file +by using "unzip -a" but there seems to be no simple way to recover +UNIX-style line endings from the *.7z file. The *.tar.xz file is +recommended for *NIX users instead. + +Version 0.89 was the first official release of libpng. Don't let the +fact that it's the first release fool you. The libpng library has been in +extensive use and testing since mid-1995. By late 1997 it had +finally gotten to the stage where there hadn't been significant +changes to the API in some time, and people have a bad feeling about +libraries with versions < 1.0. Version 1.0.0 was released in +March 1998. + +**** +Note that some of the changes to the png_info structure render this +version of the library binary incompatible with libpng-0.89 or +earlier versions if you are using a shared library. The type of the +"filler" parameter for png_set_filler() has changed from png_byte to +png_uint_32, which will affect shared-library applications that use +this function. + +To avoid problems with changes to the internals of png_info_struct, +new APIs have been made available in 0.95 to avoid direct application +access to info_ptr. These functions are the png_set_<chunk> and +png_get_<chunk> functions. These functions should be used when +accessing/storing the info_struct data, rather than manipulating it +directly, to avoid such problems in the future. + +It is important to note that the APIs do not make current programs +that access the info struct directly incompatible with the new +library. However, it is strongly suggested that new programs use +the new APIs (as shown in example.c and pngtest.c), and older programs +be converted to the new format, to facilitate upgrades in the future. +**** + +Additions since 0.90 include the ability to compile libpng as a +Windows DLL, and new APIs for accessing data in the info struct. +Experimental functions include the ability to set weighting and cost +factors for row filter selection, direct reads of integers from buffers +on big-endian processors that support misaligned data access, faster +methods of doing alpha composition, and more accurate 16->8 bit color +conversion. + +The additions since 0.89 include the ability to read from a PNG stream +which has had some (or all) of the signature bytes read by the calling +application. This also allows the reading of embedded PNG streams that +do not have the PNG file signature. As well, it is now possible to set +the library action on the detection of chunk CRC errors. It is possible +to set different actions based on whether the CRC error occurred in a +critical or an ancillary chunk. + +The changes made to the library, and bugs fixed are based on discussions +on the png-mng-implement mailing list and not on material submitted +privately to Guy, Andreas, or Glenn. They will forward any good +suggestions to the list. + +For a detailed description on using libpng, read libpng.txt. For +examples of libpng in a program, see example.c and pngtest.c. For usage +information and restrictions (what little they are) on libpng, see +png.h. For a description on using zlib (the compression library used by +libpng) and zlib's restrictions, see zlib.h + +I have included a general makefile, as well as several machine and +compiler specific ones, but you may have to modify one for your own needs. + +You should use zlib 1.0.4 or later to run this, but it MAY work with +versions as old as zlib 0.95. Even so, there are bugs in older zlib +versions which can cause the output of invalid compression streams for +some images. You will definitely need zlib 1.0.4 or later if you are +taking advantage of the MS-DOS "far" structure allocation for the small +and medium memory models. You should also note that zlib is a +compression library that is useful for more things than just PNG files. +You can use zlib as a drop-in replacement for fread() and fwrite() if +you are so inclined. + +zlib should be available at the same place that libpng is, or at +ftp://ftp.simplesystems.org/pub/png/src/ + +You may also want a copy of the PNG specification. It is available +as an RFC, a W3C Recommendation, and an ISO/IEC Standard. You can find +these at http://www.libpng.org/pub/png/pngdocs.html + +This code is currently being archived at libpng.sf.net in the +[DOWNLOAD] area, and on CompuServe, Lib 20 (PNG SUPPORT) +at GO GRAPHSUP. If you can't find it in any of those places, +e-mail me, and I'll help you find it. + +If you have any code changes, requests, problems, etc., please e-mail +them to me. Also, I'd appreciate any make files or project files, +and any modifications you needed to make to get libpng to compile, +along with a #define variable to tell what compiler/system you are on. +If you needed to add transformations to libpng, or wish libpng would +provide the image in a different way, drop me a note (and code, if +possible), so I can consider supporting the transformation. +Finally, if you get any warning messages when compiling libpng +(note: not zlib), and they are easy to fix, I'd appreciate the +fix. Please mention "libpng" somewhere in the subject line. Thanks. + +This release was created and will be supported by myself (of course +based in a large way on Guy's and Andreas' earlier work), and the PNG +development group. + +Send comments/corrections/commendations to png-mng-implement at lists.sf.net +(subscription required; visit +https://lists.sourceforge.net/lists/listinfo/png-mng-implement +to subscribe) or to glennrp at users.sourceforge.net + +You can't reach Guy, the original libpng author, at the addresses +given in previous versions of this document. He and Andreas will +read mail addressed to the png-mng-implement list, however. + +Please do not send general questions about PNG. Send them to +the (png-mng-misc at lists.sourceforge.net, subscription required, visit +https://lists.sourceforge.net/lists/listinfo/png-mng-misc to +subscribe). On the other hand, please do not send libpng questions to +that address, send them to me or to the png-mng-implement list. I'll +get them in the end anyway. If you have a question about something +in the PNG specification that is related to using libpng, send it +to me. Send me any questions that start with "I was using libpng, +and ...". If in doubt, send questions to me. I'll bounce them +to others, if necessary. + +Please do not send suggestions on how to change PNG. We have +been discussing PNG for twelve years now, and it is official and +finished. If you have suggestions for libpng, however, I'll +gladly listen. Even if your suggestion is not used immediately, +it may be used later. + +Files in this distribution: + + ANNOUNCE => Announcement of this version, with recent changes + CHANGES => Description of changes between libpng versions + KNOWNBUG => List of known bugs and deficiencies + LICENSE => License to use and redistribute libpng + README => This file + TODO => Things not implemented in the current library + Y2KINFO => Statement of Y2K compliance + example.c => Example code for using libpng functions + libpng-*-*-diff.txt => Diff from previous release + libpng.3 => manual page for libpng (includes libpng.txt) + libpng.txt => Description of libpng and its functions + libpngpf.3 => manual page for libpng's private functions + png.5 => manual page for the PNG format + png.c => Basic interface functions common to library + png.h => Library function and interface declarations + pngconf.h => System specific library configuration + pngerror.c => Error/warning message I/O functions + pngget.c => Functions for retrieving info from struct + pngmem.c => Memory handling functions + pngbar.png => PNG logo, 88x31 + pngnow.png => PNG logo, 98x31 + pngpread.c => Progressive reading functions + pngread.c => Read data/helper high-level functions + pngrio.c => Lowest-level data read I/O functions + pngrtran.c => Read data transformation functions + pngrutil.c => Read data utility functions + pngset.c => Functions for storing data into the info_struct + pngtest.c => Library test program + pngtest.png => Library test sample image + pngtrans.c => Common data transformation functions + pngwio.c => Lowest-level write I/O functions + pngwrite.c => High-level write functions + pngwtran.c => Write data transformations + pngwutil.c => Write utility functions + contrib => Contributions + gregbook => source code for PNG reading and writing, from + Greg Roelofs' "PNG: The Definitive Guide", + O'Reilly, 1999 + msvctest => Builds and runs pngtest using a MSVC workspace + pngminim => Simple pnm2pngm and png2pnmm programs + pngminus => Simple pnm2png and png2pnm programs + pngsuite => Test images + visupng => Contains a MSVC workspace for VisualPng + projects => Contains project files and workspaces for + building a DLL + beos => Contains a Beos workspace for building libpng + c5builder => Contains a Borland workspace for building + libpng and zlib + netware.txt => Contains instructions for downloading a set + of project files for building libpng and + zlib on Netware. + visualc6 => Contains a Microsoft Visual C++ (MSVC) + workspace for building libpng and zlib + wince.txt => Contains instructions for downloading a + Microsoft Visual C++ (Windows CD Toolkit) + workspace for building libpng and zlib on + WindowsCE + xcode => Contains xcode project files + scripts => Directory containing scripts for building libpng: + descrip.mms => VMS makefile for MMS or MMK + makefile.std => Generic UNIX makefile (cc, creates static + libpng.a) + makefile.elf => Linux/ELF gcc makefile symbol versioning, + creates libpng12.so.0.1.2.44) + makefile.linux => Linux/ELF makefile (gcc, creates + libpng12.so.0.1.2.44) + makefile.gcmmx => Linux/ELF makefile (gcc, creates + libpng12.so.0.1.2.44, previously + used assembler code tuned for Intel MMX + platform) + makefile.gcc => Generic makefile (gcc, creates static + libpng.a) + makefile.knr => Archaic UNIX Makefile that converts files + with ansi2knr (Requires ansi2knr.c from + ftp://ftp.cs.wisc.edu/ghost) + makefile.aix => AIX makefile + makefile.cygwin => Cygwin/gcc makefile + makefile.darwin => Darwin makefile + makefile.dec => DEC Alpha UNIX makefile + makefile.freebsd => FreeBSD makefile + makefile.hpgcc => HPUX makefile using gcc + makefile.hpux => HPUX (10.20 and 11.00) makefile + makefile.hp64 => HPUX (10.20 and 11.00) makefile, 64 bit + makefile.ibmc => IBM C/C++ version 3.x for Win32 and OS/2 + (static) + makefile.intel => Intel C/C++ version 4.0 and later + libpng.icc => Project file, IBM VisualAge/C++ 4.0 or later + makefile.netbsd => NetBSD/cc makefile, makes libpng.so. + makefile.ne12bsd => NetBSD/cc makefile, makes libpng12.so + makefile.openbsd => OpenBSD makefile + makefile.sgi => Silicon Graphics IRIX (cc, creates static lib) + makefile.sggcc => Silicon Graphics + (gcc, creates libpng12.so.0.1.2.44) + makefile.sunos => Sun makefile + makefile.solaris => Solaris 2.X makefile + (gcc, creates libpng12.so.0.1.2.44) + makefile.so9 => Solaris 9 makefile + (gcc, creates libpng12.so.0.1.2.44) + makefile.32sunu => Sun Ultra 32-bit makefile + makefile.64sunu => Sun Ultra 64-bit makefile + makefile.sco => For SCO OSr5 ELF and Unixware 7 with Native cc + makefile.mips => MIPS makefile + makefile.acorn => Acorn makefile + makefile.amiga => Amiga makefile + smakefile.ppc => AMIGA smakefile for SAS C V6.58/7.00 PPC + compiler (Requires SCOPTIONS, copied from + scripts/SCOPTIONS.ppc) + makefile.atari => Atari makefile + makefile.beos => BEOS makefile for X86 + makefile.bor => Borland makefile (uses bcc) + makefile.bc32 => 32-bit Borland C++ (all modules compiled in C mode) + makefile.tc3 => Turbo C 3.0 makefile + makefile.dj2 => DJGPP 2 makefile + makefile.msc => Microsoft C makefile + makefile.vcawin32=> makefile for Microsoft Visual C++ 5.0 and + later (previously used assembler code tuned + for Intel MMX platform) + makefile.vcwin32 => makefile for Microsoft Visual C++ 4.0 and + later (does not use assembler code) + makefile.os2 => OS/2 Makefile (gcc and emx, requires pngos2.def) + pngos2.def => OS/2 module definition file used by makefile.os2 + makefile.watcom => Watcom 10a+ Makefile, 32-bit flat memory model + makevms.com => VMS build script + SCOPTIONS.ppc => Used with smakefile.ppc + +Good luck, and happy coding. + +-Glenn Randers-Pehrson (current maintainer, since 1998) + Internet: glennrp at users.sourceforge.net + +-Andreas Eric Dilger (former maintainer, 1996-1997) + Internet: adilger at enel.ucalgary.ca + Web: http://members.shaw.ca/adilger/ + +-Guy Eric Schalnat (original author and former maintainer, 1995-1996) + (formerly of Group 42, Inc) + Internet: gschal at infinet.com diff --git a/contrib/syslinux-4.02/com32/lib/libpng/TODO b/contrib/syslinux-4.02/com32/lib/libpng/TODO new file mode 100644 index 0000000..face765 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libpng/TODO @@ -0,0 +1,25 @@ +TODO - list of things to do for libpng: + +Final bug fixes. +Improve API by hiding the png_struct and png_info structs. +Finish work on the no-floating-point version (including gamma compensation) +Better C++ wrapper/full C++ implementation? +Fix problem with C++ and EXTERN "C". +cHRM transformation. +Improve setjmp/longjmp usage or remove it in favor of returning error codes. +Add "grayscale->palette" transformation and "palette->grayscale" detection. +Improved dithering. +Multi-lingual error and warning message support. +Complete sRGB transformation (presently it simply uses gamma=0.45455). +Man pages for function calls. +Better documentation. +Better filter selection + (counting huffman bits/precompression? filter inertia? filter costs?). +Histogram creation. +Text conversion between different code pages (Latin-1 -> Mac and DOS). +Should we always malloc 2^bit_depth PLTE/tRNS/hIST entries for safety? +Build gamma tables using fixed point (and do away with floating point entirely). +Use greater precision when changing to linear gamma for compositing against + background and doing rgb-to-gray transformation. +Investigate pre-incremented loop counters and other loop constructions. +Add interpolated method of handling interlacing. diff --git a/contrib/syslinux-4.02/com32/lib/libpng/Y2KINFO b/contrib/syslinux-4.02/com32/lib/libpng/Y2KINFO new file mode 100644 index 0000000..1cf3a0a --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libpng/Y2KINFO @@ -0,0 +1,55 @@ + Y2K compliance in libpng: + ========================= + + June 26, 2010 + + Since the PNG Development group is an ad-hoc body, we can't make + an official declaration. + + This is your unofficial assurance that libpng from version 0.71 and + upward through 1.2.44 are Y2K compliant. It is my belief that earlier + versions were also Y2K compliant. + + Libpng only has three year fields. One is a 2-byte unsigned integer + that will hold years up to 65535. The other two hold the date in text + format, and will hold years up to 9999. + + The integer is + "png_uint_16 year" in png_time_struct. + + The strings are + "png_charp time_buffer" in png_struct and + "near_time_buffer", which is a local character string in png.c. + + There are seven time-related functions: + + png_convert_to_rfc_1123() in png.c + (formerly png_convert_to_rfc_1152() in error) + png_convert_from_struct_tm() in pngwrite.c, called in pngwrite.c + png_convert_from_time_t() in pngwrite.c + png_get_tIME() in pngget.c + png_handle_tIME() in pngrutil.c, called in pngread.c + png_set_tIME() in pngset.c + png_write_tIME() in pngwutil.c, called in pngwrite.c + + All appear to handle dates properly in a Y2K environment. The + png_convert_from_time_t() function calls gmtime() to convert from system + clock time, which returns (year - 1900), which we properly convert to + the full 4-digit year. There is a possibility that applications using + libpng are not passing 4-digit years into the png_convert_to_rfc_1123() + function, or that they are incorrectly passing only a 2-digit year + instead of "year - 1900" into the png_convert_from_struct_tm() function, + but this is not under our control. The libpng documentation has always + stated that it works with 4-digit years, and the APIs have been + documented as such. + + The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned + integer to hold the year, and can hold years as large as 65535. + + zlib, upon which libpng depends, is also Y2K compliant. It contains + no date-related code. + + + Glenn Randers-Pehrson + libpng maintainer + PNG Development Group diff --git a/contrib/syslinux-4.02/com32/lib/libpng/example.c b/contrib/syslinux-4.02/com32/lib/libpng/example.c new file mode 100644 index 0000000..49b8724 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libpng/example.c @@ -0,0 +1,832 @@ + +#if 0 /* in case someone actually tries to compile this */ + +/* example.c - an example of using libpng + * Last changed in libpng 1.2.37 [June 4, 2009] + * This file has been placed in the public domain by the authors. + * Maintained 1998-2010 Glenn Randers-Pehrson + * Maintained 1996, 1997 Andreas Dilger) + * Written 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +/* This is an example of how to use libpng to read and write PNG files. + * The file libpng.txt is much more verbose then this. If you have not + * read it, do so first. This was designed to be a starting point of an + * implementation. This is not officially part of libpng, is hereby placed + * in the public domain, and therefore does not require a copyright notice. + * + * This file does not currently compile, because it is missing certain + * parts, like allocating memory to hold an image. You will have to + * supply these parts to get it to compile. For an example of a minimal + * working PNG reader/writer, see pngtest.c, included in this distribution; + * see also the programs in the contrib directory. + */ + +#include "png.h" + + /* The png_jmpbuf() macro, used in error handling, became available in + * libpng version 1.0.6. If you want to be able to run your code with older + * versions of libpng, you must define the macro yourself (but only if it + * is not already defined by libpng!). + */ + +#ifndef png_jmpbuf +# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) +#endif + +/* Check to see if a file is a PNG file using png_sig_cmp(). png_sig_cmp() + * returns zero if the image is a PNG and nonzero if it isn't a PNG. + * + * The function check_if_png() shown here, but not used, returns nonzero (true) + * if the file can be opened and is a PNG, 0 (false) otherwise. + * + * If this call is successful, and you are going to keep the file open, + * you should call png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); once + * you have created the png_ptr, so that libpng knows your application + * has read that many bytes from the start of the file. Make sure you + * don't call png_set_sig_bytes() with more than 8 bytes read or give it + * an incorrect number of bytes read, or you will either have read too + * many bytes (your fault), or you are telling libpng to read the wrong + * number of magic bytes (also your fault). + * + * Many applications already read the first 2 or 4 bytes from the start + * of the image to determine the file type, so it would be easiest just + * to pass the bytes to png_sig_cmp() or even skip that if you know + * you have a PNG file, and call png_set_sig_bytes(). + */ +#define PNG_BYTES_TO_CHECK 4 +int check_if_png(char *file_name, FILE **fp) +{ + char buf[PNG_BYTES_TO_CHECK]; + + /* Open the prospective PNG file. */ + if ((*fp = fopen(file_name, "rb")) == NULL) + return 0; + + /* Read in some of the signature bytes */ + if (fread(buf, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK) + return 0; + + /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature. + Return nonzero (true) if they match */ + + return(!png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK)); +} + +/* Read a PNG file. You may want to return an error code if the read + * fails (depending upon the failure). There are two "prototypes" given + * here - one where we are given the filename, and we need to open the + * file, and the other where we are given an open file (possibly with + * some or all of the magic bytes read - see comments above). + */ +#ifdef open_file /* prototype 1 */ +void read_png(char *file_name) /* We need to open the file */ +{ + png_structp png_ptr; + png_infop info_ptr; + unsigned int sig_read = 0; + png_uint_32 width, height; + int bit_depth, color_type, interlace_type; + FILE *fp; + + if ((fp = fopen(file_name, "rb")) == NULL) + return (ERROR); + +#else no_open_file /* prototype 2 */ +void read_png(FILE *fp, unsigned int sig_read) /* File is already open */ +{ + png_structp png_ptr; + png_infop info_ptr; + png_uint_32 width, height; + int bit_depth, color_type, interlace_type; +#endif no_open_file /* Only use one prototype! */ + + /* Create and initialize the png_struct with the desired error handler + * functions. If you want to use the default stderr and longjump method, + * you can supply NULL for the last three parameters. We also supply the + * the compiler header file version, so that we know if the application + * was compiled with a compatible version of the library. REQUIRED + */ + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, + png_voidp user_error_ptr, user_error_fn, user_warning_fn); + + if (png_ptr == NULL) + { + fclose(fp); + return (ERROR); + } + + /* Allocate/initialize the memory for image information. REQUIRED. */ + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) + { + fclose(fp); + png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); + return (ERROR); + } + + /* Set error handling if you are using the setjmp/longjmp method (this is + * the normal method of doing things with libpng). REQUIRED unless you + * set up your own error handlers in the png_create_read_struct() earlier. + */ + + if (setjmp(png_jmpbuf(png_ptr))) + { + /* Free all of the memory associated with the png_ptr and info_ptr */ + png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); + fclose(fp); + /* If we get here, we had a problem reading the file */ + return (ERROR); + } + + /* One of the following I/O initialization methods is REQUIRED */ +#ifdef streams /* PNG file I/O method 1 */ + /* Set up the input control if you are using standard C streams */ + png_init_io(png_ptr, fp); + +#else no_streams /* PNG file I/O method 2 */ + /* If you are using replacement read functions, instead of calling + * png_init_io() here you would call: + */ + png_set_read_fn(png_ptr, (void *)user_io_ptr, user_read_fn); + /* where user_io_ptr is a structure you want available to the callbacks */ +#endif no_streams /* Use only one I/O method! */ + + /* If we have already read some of the signature */ + png_set_sig_bytes(png_ptr, sig_read); + +#ifdef hilevel + /* + * If you have enough memory to read in the entire image at once, + * and you need to specify only transforms that can be controlled + * with one of the PNG_TRANSFORM_* bits (this presently excludes + * dithering, filling, setting background, and doing gamma + * adjustment), then you can read the entire image (including + * pixels) into the info structure with this call: + */ + png_read_png(png_ptr, info_ptr, png_transforms, png_voidp_NULL); + +#else + /* OK, you're doing it the hard way, with the lower-level functions */ + + /* The call to png_read_info() gives us all of the information from the + * PNG file before the first IDAT (image data chunk). REQUIRED + */ + png_read_info(png_ptr, info_ptr); + + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, + &interlace_type, int_p_NULL, int_p_NULL); + + /* Set up the data transformations you want. Note that these are all + * optional. Only call them if you want/need them. Many of the + * transformations only work on specific types of images, and many + * are mutually exclusive. + */ + + /* Tell libpng to strip 16 bit/color files down to 8 bits/color */ + png_set_strip_16(png_ptr); + + /* Strip alpha bytes from the input data without combining with the + * background (not recommended). + */ + png_set_strip_alpha(png_ptr); + + /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single + * byte into separate bytes (useful for paletted and grayscale images). + */ + png_set_packing(png_ptr); + + /* Change the order of packed pixels to least significant bit first + * (not useful if you are using png_set_packing). */ + png_set_packswap(png_ptr); + + /* Expand paletted colors into true RGB triplets */ + if (color_type == PNG_COLOR_TYPE_PALETTE) + png_set_palette_to_rgb(png_ptr); + + /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */ + if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) + png_set_expand_gray_1_2_4_to_8(png_ptr); + + /* Expand paletted or RGB images with transparency to full alpha channels + * so the data will be available as RGBA quartets. + */ + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) + png_set_tRNS_to_alpha(png_ptr); + + /* Set the background color to draw transparent and alpha images over. + * It is possible to set the red, green, and blue components directly + * for paletted images instead of supplying a palette index. Note that + * even if the PNG file supplies a background, you are not required to + * use it - you should use the (solid) application background if it has one. + */ + + png_color_16 my_background, *image_background; + + if (png_get_bKGD(png_ptr, info_ptr, &image_background)) + png_set_background(png_ptr, image_background, + PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); + else + png_set_background(png_ptr, &my_background, + PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); + + /* Some suggestions as to how to get a screen gamma value + * + * Note that screen gamma is the display_exponent, which includes + * the CRT_exponent and any correction for viewing conditions + */ + if (/* We have a user-defined screen gamma value */) + { + screen_gamma = user-defined screen_gamma; + } + /* This is one way that applications share the same screen gamma value */ + else if ((gamma_str = getenv("SCREEN_GAMMA")) != NULL) + { + screen_gamma = atof(gamma_str); + } + /* If we don't have another value */ + else + { + screen_gamma = 2.2; /* A good guess for a PC monitor in a dimly + lit room */ + screen_gamma = 1.7 or 1.0; /* A good guess for Mac systems */ + } + + /* Tell libpng to handle the gamma conversion for you. The final call + * is a good guess for PC generated images, but it should be configurable + * by the user at run time by the user. It is strongly suggested that + * your application support gamma correction. + */ + + int intent; + + if (png_get_sRGB(png_ptr, info_ptr, &intent)) + png_set_gamma(png_ptr, screen_gamma, 0.45455); + else + { + double image_gamma; + if (png_get_gAMA(png_ptr, info_ptr, &image_gamma)) + png_set_gamma(png_ptr, screen_gamma, image_gamma); + else + png_set_gamma(png_ptr, screen_gamma, 0.45455); + } + + /* Dither RGB files down to 8 bit palette or reduce palettes + * to the number of colors available on your screen. + */ + if (color_type & PNG_COLOR_MASK_COLOR) + { + int num_palette; + png_colorp palette; + + /* This reduces the image to the application supplied palette */ + if (/* We have our own palette */) + { + /* An array of colors to which the image should be dithered */ + png_color std_color_cube[MAX_SCREEN_COLORS]; + + png_set_dither(png_ptr, std_color_cube, MAX_SCREEN_COLORS, + MAX_SCREEN_COLORS, png_uint_16p_NULL, 0); + } + /* This reduces the image to the palette supplied in the file */ + else if (png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)) + { + png_uint_16p histogram = NULL; + + png_get_hIST(png_ptr, info_ptr, &histogram); + + png_set_dither(png_ptr, palette, num_palette, + max_screen_colors, histogram, 0); + } + } + + /* Invert monochrome files to have 0 as white and 1 as black */ + png_set_invert_mono(png_ptr); + + /* If you want to shift the pixel values from the range [0,255] or + * [0,65535] to the original [0,7] or [0,31], or whatever range the + * colors were originally in: + */ + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) + { + png_color_8p sig_bit_p; + + png_get_sBIT(png_ptr, info_ptr, &sig_bit_p); + png_set_shift(png_ptr, sig_bit_p); + } + + /* Flip the RGB pixels to BGR (or RGBA to BGRA) */ + if (color_type & PNG_COLOR_MASK_COLOR) + png_set_bgr(png_ptr); + + /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */ + png_set_swap_alpha(png_ptr); + + /* Swap bytes of 16 bit files to least significant byte first */ + png_set_swap(png_ptr); + + /* Add filler (or alpha) byte (before/after each RGB triplet) */ + png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); + + /* Turn on interlace handling. REQUIRED if you are not using + * png_read_image(). To see how to handle interlacing passes, + * see the png_read_row() method below: + */ + number_passes = png_set_interlace_handling(png_ptr); + + /* Optional call to gamma correct and add the background to the palette + * and update info structure. REQUIRED if you are expecting libpng to + * update the palette for you (ie you selected such a transform above). + */ + png_read_update_info(png_ptr, info_ptr); + + /* Allocate the memory to hold the image using the fields of info_ptr. */ + + /* The easiest way to read the image: */ + png_bytep row_pointers[height]; + + /* Clear the pointer array */ + for (row = 0; row < height; row++) + row_pointers[row] = NULL; + + for (row = 0; row < height; row++) + row_pointers[row] = png_malloc(png_ptr, png_get_rowbytes(png_ptr, + info_ptr)); + + /* Now it's time to read the image. One of these methods is REQUIRED */ +#ifdef entire /* Read the entire image in one go */ + png_read_image(png_ptr, row_pointers); + +#else no_entire /* Read the image one or more scanlines at a time */ + /* The other way to read images - deal with interlacing: */ + + for (pass = 0; pass < number_passes; pass++) + { +#ifdef single /* Read the image a single row at a time */ + for (y = 0; y < height; y++) + { + png_read_rows(png_ptr, &row_pointers[y], png_bytepp_NULL, 1); + } + +#else no_single /* Read the image several rows at a time */ + for (y = 0; y < height; y += number_of_rows) + { +#ifdef sparkle /* Read the image using the "sparkle" effect. */ + png_read_rows(png_ptr, &row_pointers[y], png_bytepp_NULL, + number_of_rows); +#else no_sparkle /* Read the image using the "rectangle" effect */ + png_read_rows(png_ptr, png_bytepp_NULL, &row_pointers[y], + number_of_rows); +#endif no_sparkle /* Use only one of these two methods */ + } + + /* If you want to display the image after every pass, do so here */ +#endif no_single /* Use only one of these two methods */ + } +#endif no_entire /* Use only one of these two methods */ + + /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */ + png_read_end(png_ptr, info_ptr); +#endif hilevel + + /* At this point you have read the entire image */ + + /* Clean up after the read, and free any memory allocated - REQUIRED */ + png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); + + /* Close the file */ + fclose(fp); + + /* That's it */ + return (OK); +} + +/* Progressively read a file */ + +int +initialize_png_reader(png_structp *png_ptr, png_infop *info_ptr) +{ + /* Create and initialize the png_struct with the desired error handler + * functions. If you want to use the default stderr and longjump method, + * you can supply NULL for the last three parameters. We also check that + * the library version is compatible in case we are using dynamically + * linked libraries. + */ + *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, + png_voidp user_error_ptr, user_error_fn, user_warning_fn); + + if (*png_ptr == NULL) + { + *info_ptr = NULL; + return (ERROR); + } + + *info_ptr = png_create_info_struct(png_ptr); + + if (*info_ptr == NULL) + { + png_destroy_read_struct(png_ptr, info_ptr, png_infopp_NULL); + return (ERROR); + } + + if (setjmp(png_jmpbuf((*png_ptr)))) + { + png_destroy_read_struct(png_ptr, info_ptr, png_infopp_NULL); + return (ERROR); + } + + /* This one's new. You will need to provide all three + * function callbacks, even if you aren't using them all. + * If you aren't using all functions, you can specify NULL + * parameters. Even when all three functions are NULL, + * you need to call png_set_progressive_read_fn(). + * These functions shouldn't be dependent on global or + * static variables if you are decoding several images + * simultaneously. You should store stream specific data + * in a separate struct, given as the second parameter, + * and retrieve the pointer from inside the callbacks using + * the function png_get_progressive_ptr(png_ptr). + */ + png_set_progressive_read_fn(*png_ptr, (void *)stream_data, + info_callback, row_callback, end_callback); + + return (OK); +} + +int +process_data(png_structp *png_ptr, png_infop *info_ptr, + png_bytep buffer, png_uint_32 length) +{ + if (setjmp(png_jmpbuf((*png_ptr)))) + { + /* Free the png_ptr and info_ptr memory on error */ + png_destroy_read_struct(png_ptr, info_ptr, png_infopp_NULL); + return (ERROR); + } + + /* This one's new also. Simply give it chunks of data as + * they arrive from the data stream (in order, of course). + * On segmented machines, don't give it any more than 64K. + * The library seems to run fine with sizes of 4K, although + * you can give it much less if necessary (I assume you can + * give it chunks of 1 byte, but I haven't tried with less + * than 256 bytes yet). When this function returns, you may + * want to display any rows that were generated in the row + * callback, if you aren't already displaying them there. + */ + png_process_data(*png_ptr, *info_ptr, buffer, length); + return (OK); +} + +info_callback(png_structp png_ptr, png_infop info) +{ + /* Do any setup here, including setting any of the transformations + * mentioned in the Reading PNG files section. For now, you _must_ + * call either png_start_read_image() or png_read_update_info() + * after all the transformations are set (even if you don't set + * any). You may start getting rows before png_process_data() + * returns, so this is your last chance to prepare for that. + */ +} + +row_callback(png_structp png_ptr, png_bytep new_row, + png_uint_32 row_num, int pass) +{ + /* + * This function is called for every row in the image. If the + * image is interlaced, and you turned on the interlace handler, + * this function will be called for every row in every pass. + * + * In this function you will receive a pointer to new row data from + * libpng called new_row that is to replace a corresponding row (of + * the same data format) in a buffer allocated by your application. + * + * The new row data pointer "new_row" may be NULL, indicating there is + * no new data to be replaced (in cases of interlace loading). + * + * If new_row is not NULL then you need to call + * png_progressive_combine_row() to replace the corresponding row as + * shown below: + */ + + /* Get pointer to corresponding row in our + * PNG read buffer. + */ + png_bytep old_row = ((png_bytep *)our_data)[row_num]; + + /* If both rows are allocated then copy the new row + * data to the corresponding row data. + */ + if ((old_row != NULL) && (new_row != NULL)) + png_progressive_combine_row(png_ptr, old_row, new_row); + + /* + * The rows and passes are called in order, so you don't really + * need the row_num and pass, but I'm supplying them because it + * may make your life easier. + * + * For the non-NULL rows of interlaced images, you must call + * png_progressive_combine_row() passing in the new row and the + * old row, as demonstrated above. You can call this function for + * NULL rows (it will just return) and for non-interlaced images + * (it just does the png_memcpy for you) if it will make the code + * easier. Thus, you can just do this for all cases: + */ + + png_progressive_combine_row(png_ptr, old_row, new_row); + + /* where old_row is what was displayed for previous rows. Note + * that the first pass (pass == 0 really) will completely cover + * the old row, so the rows do not have to be initialized. After + * the first pass (and only for interlaced images), you will have + * to pass the current row as new_row, and the function will combine + * the old row and the new row. + */ +} + +end_callback(png_structp png_ptr, png_infop info) +{ + /* This function is called when the whole image has been read, + * including any chunks after the image (up to and including + * the IEND). You will usually have the same info chunk as you + * had in the header, although some data may have been added + * to the comments and time fields. + * + * Most people won't do much here, perhaps setting a flag that + * marks the image as finished. + */ +} + +/* Write a png file */ +void write_png(char *file_name /* , ... other image information ... */) +{ + FILE *fp; + png_structp png_ptr; + png_infop info_ptr; + png_colorp palette; + + /* Open the file */ + fp = fopen(file_name, "wb"); + if (fp == NULL) + return (ERROR); + + /* Create and initialize the png_struct with the desired error handler + * functions. If you want to use the default stderr and longjump method, + * you can supply NULL for the last three parameters. We also check that + * the library version is compatible with the one used at compile time, + * in case we are using dynamically linked libraries. REQUIRED. + */ + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, + png_voidp user_error_ptr, user_error_fn, user_warning_fn); + + if (png_ptr == NULL) + { + fclose(fp); + return (ERROR); + } + + /* Allocate/initialize the image information data. REQUIRED */ + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) + { + fclose(fp); + png_destroy_write_struct(&png_ptr, png_infopp_NULL); + return (ERROR); + } + + /* Set error handling. REQUIRED if you aren't supplying your own + * error handling functions in the png_create_write_struct() call. + */ + if (setjmp(png_jmpbuf(png_ptr))) + { + /* If we get here, we had a problem writing the file */ + fclose(fp); + png_destroy_write_struct(&png_ptr, &info_ptr); + return (ERROR); + } + + /* One of the following I/O initialization functions is REQUIRED */ + +#ifdef streams /* I/O initialization method 1 */ + /* Set up the output control if you are using standard C streams */ + png_init_io(png_ptr, fp); + +#else no_streams /* I/O initialization method 2 */ + /* If you are using replacement write functions, instead of calling + * png_init_io() here you would call + */ + png_set_write_fn(png_ptr, (void *)user_io_ptr, user_write_fn, + user_IO_flush_function); + /* where user_io_ptr is a structure you want available to the callbacks */ +#endif no_streams /* Only use one initialization method */ + +#ifdef hilevel + /* This is the easy way. Use it if you already have all the + * image info living in the structure. You could "|" many + * PNG_TRANSFORM flags into the png_transforms integer here. + */ + png_write_png(png_ptr, info_ptr, png_transforms, png_voidp_NULL); + +#else + /* This is the hard way */ + + /* Set the image information here. Width and height are up to 2^31, + * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on + * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, + * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, + * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or + * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST + * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED + */ + png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_???, + PNG_INTERLACE_????, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + /* Set the palette if there is one. REQUIRED for indexed-color images */ + palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH + * png_sizeof(png_color)); + /* ... Set palette colors ... */ + png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH); + /* You must not free palette here, because png_set_PLTE only makes a link to + * the palette that you malloced. Wait until you are about to destroy + * the png structure. + */ + + /* Optional significant bit (sBIT) chunk */ + png_color_8 sig_bit; + /* If we are dealing with a grayscale image then */ + sig_bit.gray = true_bit_depth; + /* Otherwise, if we are dealing with a color image then */ + sig_bit.red = true_red_bit_depth; + sig_bit.green = true_green_bit_depth; + sig_bit.blue = true_blue_bit_depth; + /* If the image has an alpha channel then */ + sig_bit.alpha = true_alpha_bit_depth; + png_set_sBIT(png_ptr, info_ptr, &sig_bit); + + + /* Optional gamma chunk is strongly suggested if you have any guess + * as to the correct gamma of the image. + */ + png_set_gAMA(png_ptr, info_ptr, gamma); + + /* Optionally write comments into the image */ + text_ptr[0].key = "Title"; + text_ptr[0].text = "Mona Lisa"; + text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr[1].key = "Author"; + text_ptr[1].text = "Leonardo DaVinci"; + text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr[2].key = "Description"; + text_ptr[2].text = "<long text>"; + text_ptr[2].compression = PNG_TEXT_COMPRESSION_zTXt; +#ifdef PNG_iTXt_SUPPORTED + text_ptr[0].lang = NULL; + text_ptr[1].lang = NULL; + text_ptr[2].lang = NULL; +#endif + png_set_text(png_ptr, info_ptr, text_ptr, 3); + + /* Other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs */ + + /* Note that if sRGB is present the gAMA and cHRM chunks must be ignored + * on read and, if your application chooses to write them, they must + * be written in accordance with the sRGB profile + */ + + /* Write the file header information. REQUIRED */ + png_write_info(png_ptr, info_ptr); + + /* If you want, you can write the info in two steps, in case you need to + * write your private chunk ahead of PLTE: + * + * png_write_info_before_PLTE(write_ptr, write_info_ptr); + * write_my_chunk(); + * png_write_info(png_ptr, info_ptr); + * + * However, given the level of known- and unknown-chunk support in 1.2.0 + * and up, this should no longer be necessary. + */ + + /* Once we write out the header, the compression type on the text + * chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or + * PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again + * at the end. + */ + + /* Set up the transformations you want. Note that these are + * all optional. Only call them if you want them. + */ + + /* Invert monochrome pixels */ + png_set_invert_mono(png_ptr); + + /* Shift the pixels up to a legal bit depth and fill in + * as appropriate to correctly scale the image. + */ + png_set_shift(png_ptr, &sig_bit); + + /* Pack pixels into bytes */ + png_set_packing(png_ptr); + + /* Swap location of alpha bytes from ARGB to RGBA */ + png_set_swap_alpha(png_ptr); + + /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into + * RGB (4 channels -> 3 channels). The second parameter is not used. + */ + png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); + + /* Flip BGR pixels to RGB */ + png_set_bgr(png_ptr); + + /* Swap bytes of 16-bit files to most significant byte first */ + png_set_swap(png_ptr); + + /* Swap bits of 1, 2, 4 bit packed pixel formats */ + png_set_packswap(png_ptr); + + /* Turn on interlace handling if you are not using png_write_image() */ + if (interlacing) + number_passes = png_set_interlace_handling(png_ptr); + else + number_passes = 1; + + /* The easiest way to write the image (you may have a different memory + * layout, however, so choose what fits your needs best). You need to + * use the first method if you aren't handling interlacing yourself. + */ + png_uint_32 k, height, width; + png_byte image[height][width*bytes_per_pixel]; + png_bytep row_pointers[height]; + + if (height > PNG_UINT_32_MAX/png_sizeof(png_bytep)) + png_error (png_ptr, "Image is too tall to process in memory"); + + for (k = 0; k < height; k++) + row_pointers[k] = image + k*width*bytes_per_pixel; + + /* One of the following output methods is REQUIRED */ + +#ifdef entire /* Write out the entire image data in one call */ + png_write_image(png_ptr, row_pointers); + + /* The other way to write the image - deal with interlacing */ + +#else no_entire /* Write out the image data by one or more scanlines */ + + /* The number of passes is either 1 for non-interlaced images, + * or 7 for interlaced images. + */ + for (pass = 0; pass < number_passes; pass++) + { + /* Write a few rows at a time. */ + png_write_rows(png_ptr, &row_pointers[first_row], number_of_rows); + + /* If you are only writing one row at a time, this works */ + for (y = 0; y < height; y++) + png_write_rows(png_ptr, &row_pointers[y], 1); + } +#endif no_entire /* Use only one output method */ + + /* You can write optional chunks like tEXt, zTXt, and tIME at the end + * as well. Shouldn't be necessary in 1.2.0 and up as all the public + * chunks are supported and you can use png_set_unknown_chunks() to + * register unknown chunks into the info structure to be written out. + */ + + /* It is REQUIRED to call this to finish writing the rest of the file */ + png_write_end(png_ptr, info_ptr); +#endif hilevel + + /* If you png_malloced a palette, free it here (don't free info_ptr->palette, + * as recommended in versions 1.0.5m and earlier of this example; if + * libpng mallocs info_ptr->palette, libpng will free it). If you + * allocated it with malloc() instead of png_malloc(), use free() instead + * of png_free(). + */ + png_free(png_ptr, palette); + palette = NULL; + + /* Similarly, if you png_malloced any data that you passed in with + * png_set_something(), such as a hist or trans array, free it here, + * when you can be sure that libpng is through with it. + */ + png_free(png_ptr, trans); + trans = NULL; + /* Whenever you use png_free() it is a good idea to set the pointer to + * NULL in case your application inadvertently tries to png_free() it + * again. When png_free() sees a NULL it returns without action, thus + * avoiding the double-free security problem. + */ + + /* Clean up after the write, and free any memory allocated */ + png_destroy_write_struct(&png_ptr, &info_ptr); + + /* Close the file */ + fclose(fp); + + /* That's it */ + return (OK); +} + +#endif /* if 0 */ diff --git a/contrib/syslinux-4.02/com32/lib/libpng/libpng.3 b/contrib/syslinux-4.02/com32/lib/libpng/libpng.3 new file mode 100644 index 0000000..93139a7 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libpng/libpng.3 @@ -0,0 +1,4490 @@ +.TH LIBPNG 3 "June 26, 2010" +.SH NAME +libpng \- Portable Network Graphics (PNG) Reference Library 1.2.44 +.SH SYNOPSIS +\fI\fB + +\fB#include <png.h>\fP + +\fI\fB + +\fBpng_uint_32 png_access_version_number \fI(void\fP\fB);\fP + +\fI\fB + +\fBint png_check_sig (png_bytep \fP\fIsig\fP\fB, int \fInum\fP\fB);\fP + +\fI\fB + +\fBvoid png_chunk_error (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fIerror\fP\fB);\fP + +\fI\fB + +\fBvoid png_chunk_warning (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fImessage\fP\fB);\fP + +\fI\fB + +\fBvoid png_convert_from_struct_tm (png_timep \fP\fIptime\fP\fB, struct tm FAR * \fIttime\fP\fB);\fP + +\fI\fB + +\fBvoid png_convert_from_time_t (png_timep \fP\fIptime\fP\fB, time_t \fIttime\fP\fB);\fP + +\fI\fB + +\fBpng_charp png_convert_to_rfc1123 (png_structp \fP\fIpng_ptr\fP\fB, png_timep \fIptime\fP\fB);\fP + +\fI\fB + +\fBpng_infop png_create_info_struct (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_structp png_create_read_struct (png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fIwarn_fn\fP\fB);\fP + +\fI\fB + +\fBpng_structp png_create_read_struct_2(png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fP\fIwarn_fn\fP\fB, png_voidp \fP\fImem_ptr\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_free_ptr \fIfree_fn\fP\fB);\fP + +\fI\fB + +\fBpng_structp png_create_write_struct (png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fIwarn_fn\fP\fB);\fP + +\fI\fB + +\fBpng_structp png_create_write_struct_2(png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fP\fIwarn_fn\fP\fB, png_voidp \fP\fImem_ptr\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_free_ptr \fIfree_fn\fP\fB);\fP + +\fI\fB + +\fBint png_debug(int \fP\fIlevel\fP\fB, png_const_charp \fImessage\fP\fB);\fP + +\fI\fB + +\fBint png_debug1(int \fP\fIlevel\fP\fB, png_const_charp \fP\fImessage\fP\fB, \fIp1\fP\fB);\fP + +\fI\fB + +\fBint png_debug2(int \fP\fIlevel\fP\fB, png_const_charp \fP\fImessage\fP\fB, \fP\fIp1\fP\fB, \fIp2\fP\fB);\fP + +\fI\fB + +\fBvoid png_destroy_info_struct (png_structp \fP\fIpng_ptr\fP\fB, png_infopp \fIinfo_ptr_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_destroy_read_struct (png_structpp \fP\fIpng_ptr_ptr\fP\fB, png_infopp \fP\fIinfo_ptr_ptr\fP\fB, png_infopp \fIend_info_ptr_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_destroy_write_struct (png_structpp \fP\fIpng_ptr_ptr\fP\fB, png_infopp \fIinfo_ptr_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_error (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fIerror\fP\fB);\fP + +\fI\fB + +\fBvoid png_free (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fIptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_free_chunk_list (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_free_default(png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fIptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_free_data (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fInum\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_bit_depth (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_bKGD (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_16p \fI*background\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_channels (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_cHRM (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fP\fI*white_x\fP\fB, double \fP\fI*white_y\fP\fB, double \fP\fI*red_x\fP\fB, double \fP\fI*red_y\fP\fB, double \fP\fI*green_x\fP\fB, double \fP\fI*green_y\fP\fB, double \fP\fI*blue_x\fP\fB, double \fI*blue_y\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_cHRM_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*white_x\fP\fB, png_uint_32 \fP\fI*white_y\fP\fB, png_uint_32 \fP\fI*red_x\fP\fB, png_uint_32 \fP\fI*red_y\fP\fB, png_uint_32 \fP\fI*green_x\fP\fB, png_uint_32 \fP\fI*green_y\fP\fB, png_uint_32 \fP\fI*blue_x\fP\fB, png_uint_32 \fI*blue_y\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_color_type (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_compression_type (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_copyright (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_error_ptr (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_filter_type (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_gAMA (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fI*file_gamma\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_gAMA_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fI*int_file_gamma\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_header_ver (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_header_version (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_hIST (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_16p \fI*hist\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_iCCP (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charpp \fP\fIname\fP\fB, int \fP\fI*compression_type\fP\fB, png_charpp \fP\fIprofile\fP\fB, png_uint_32 \fI*proflen\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_IHDR (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*width\fP\fB, png_uint_32 \fP\fI*height\fP\fB, int \fP\fI*bit_depth\fP\fB, int \fP\fI*color_type\fP\fB, int \fP\fI*interlace_type\fP\fB, int \fP\fI*compression_type\fP\fB, int \fI*filter_type\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_image_height (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_image_width (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fB#if \fI!defined(PNG_1_0_X) + +\fBpng_int_32 png_get_int_32 (png_bytep \fIbuf\fP\fB);\fP + +\fI\fB#endif + +\fI\fB + +\fBpng_byte png_get_interlace_type (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_io_ptr (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_libpng_ver (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_mem_ptr(png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_oFFs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*offset_x\fP\fB, png_uint_32 \fP\fI*offset_y\fP\fB, int \fI*unit_type\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_pCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charp \fP\fI*purpose\fP\fB, png_int_32 \fP\fI*X0\fP\fB, png_int_32 \fP\fI*X1\fP\fB, int \fP\fI*type\fP\fB, int \fP\fI*nparams\fP\fB, png_charp \fP\fI*units\fP\fB, png_charpp \fI*params\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_pHYs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*res_x\fP\fB, png_uint_32 \fP\fI*res_y\fP\fB, int \fI*unit_type\fP\fB);\fP + +\fI\fB + +\fBfloat png_get_pixel_aspect_ratio (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_pixels_per_meter (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_progressive_ptr (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_colorp \fP\fI*palette\fP\fB, int \fI*num_palette\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_rgb_to_gray_status (png_structp \fIpng_ptr) + +\fBpng_uint_32 png_get_rowbytes (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_bytepp png_get_rows (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_sBIT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_8p \fI*sig_bit\fP\fB);\fP + +\fI\fB + +\fBpng_bytep png_get_signature (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_sPLT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_spalette_p \fI*splt_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_sRGB (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fI*intent\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_text (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_textp \fP\fI*text_ptr\fP\fB, int \fI*num_text\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_tIME (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_timep \fI*mod_time\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_tRNS (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fP\fI*trans\fP\fB, int \fP\fI*num_trans\fP\fB, png_color_16p \fI*trans_values\fP\fB);\fP + +\fI\fB + +\fB#if \fI!defined(PNG_1_0_X) + +\fBpng_uint_16 png_get_uint_16 (png_bytep \fIbuf\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_uint_31 (png_bytep \fIbuf\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_uint_32 (png_bytep \fIbuf\fP\fB);\fP + +\fI\fB#endif + +\fI\fB + +\fBpng_uint_32 png_get_unknown_chunks (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_unknown_chunkpp \fIunknowns\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_user_chunk_ptr (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_user_height_max( png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_user_transform_ptr (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_user_width_max (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_valid (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIflag\fP\fB);\fP + +\fI\fB + +\fBpng_int_32 png_get_x_offset_microns (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_int_32 png_get_x_offset_pixels (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_x_pixels_per_meter (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_int_32 png_get_y_offset_microns (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_int_32 png_get_y_offset_pixels (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_y_pixels_per_meter (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_compression_buffer_size (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBint png_handle_as_unknown (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIchunk_name\fP\fB);\fP + +\fI\fB + +\fBvoid png_init_io (png_structp \fP\fIpng_ptr\fP\fB, FILE \fI*fp\fP\fB);\fP + +\fI\fB + +\fBDEPRECATED: void png_info_init (png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBDEPRECATED: void png_info_init_2 (png_infopp \fP\fIptr_ptr\fP\fB, png_size_t \fIpng_info_struct_size\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_malloc (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIsize\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_malloc_default(png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIsize\fP\fB);\fP + +\fI\fB + +\fBvoidp png_memcpy (png_voidp \fP\fIs1\fP\fB, png_voidp \fP\fIs2\fP\fB, png_size_t \fIsize\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_memcpy_check (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIs1\fP\fB, png_voidp \fP\fIs2\fP\fB, png_uint_32 \fIsize\fP\fB);\fP + +\fI\fB + +\fBvoidp png_memset (png_voidp \fP\fIs1\fP\fB, int \fP\fIvalue\fP\fB, png_size_t \fIsize\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_memset_check (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIs1\fP\fB, int \fP\fIvalue\fP\fB, png_uint_32 \fIsize\fP\fB);\fP + +\fI\fB + +\fBDEPRECATED: void png_permit_empty_plte (png_structp \fP\fIpng_ptr\fP\fB, int \fIempty_plte_permitted\fP\fB);\fP + +\fI\fB + +\fBvoid png_process_data (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fP\fIbuffer\fP\fB, png_size_t \fIbuffer_size\fP\fB);\fP + +\fI\fB + +\fBvoid png_progressive_combine_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIold_row\fP\fB, png_bytep \fInew_row\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_destroy (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_infop \fIend_info_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_end (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_image (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fIimage\fP\fB);\fP + +\fI\fB + +\fBDEPRECATED: void png_read_init (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBDEPRECATED: void png_read_init_2 (png_structpp \fP\fIptr_ptr\fP\fB, png_const_charp \fP\fIuser_png_ver\fP\fB, png_size_t \fP\fIpng_struct_size\fP\fB, png_size_t \fIpng_info_size\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_png (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fItransforms\fP\fB, png_voidp \fIparams\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIrow\fP\fB, png_bytep \fIdisplay_row\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_rows (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fP\fIrow\fP\fB, png_bytepp \fP\fIdisplay_row\fP\fB, png_uint_32 \fInum_rows\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_update_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fB#if \fI!defined(PNG_1_0_X) + +\fBpng_save_int_32 (png_bytep \fP\fIbuf\fP\fB, png_int_32 \fIi\fP\fB);\fP + +\fI\fB + +\fBvoid png_save_uint_16 (png_bytep \fP\fIbuf\fP\fB, unsigned int \fIi\fP\fB);\fP + +\fI\fB + +\fBvoid png_save_uint_32 (png_bytep \fP\fIbuf\fP\fB, png_uint_32 \fIi\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_add_alpha (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIfiller\fP\fB, int \fIflags\fP\fB);\fP + +\fI\fB#endif + +\fI\fB + +\fBvoid png_set_background (png_structp \fP\fIpng_ptr\fP\fB, png_color_16p \fP\fIbackground_color\fP\fB, int \fP\fIbackground_gamma_code\fP\fB, int \fP\fIneed_expand\fP\fB, double \fIbackground_gamma\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_bgr (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_bKGD (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_16p \fIbackground\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_cHRM (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fP\fIwhite_x\fP\fB, double \fP\fIwhite_y\fP\fB, double \fP\fIred_x\fP\fB, double \fP\fIred_y\fP\fB, double \fP\fIgreen_x\fP\fB, double \fP\fIgreen_y\fP\fB, double \fP\fIblue_x\fP\fB, double \fIblue_y\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_cHRM_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIwhite_x\fP\fB, png_uint_32 \fP\fIwhite_y\fP\fB, png_uint_32 \fP\fIred_x\fP\fB, png_uint_32 \fP\fIred_y\fP\fB, png_uint_32 \fP\fIgreen_x\fP\fB, png_uint_32 \fP\fIgreen_y\fP\fB, png_uint_32 \fP\fIblue_x\fP\fB, png_uint_32 \fIblue_y\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_compression_level (png_structp \fP\fIpng_ptr\fP\fB, int \fIlevel\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_compression_mem_level (png_structp \fP\fIpng_ptr\fP\fB, int \fImem_level\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_compression_method (png_structp \fP\fIpng_ptr\fP\fB, int \fImethod\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_compression_strategy (png_structp \fP\fIpng_ptr\fP\fB, int \fIstrategy\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_compression_window_bits (png_structp \fP\fIpng_ptr\fP\fB, int \fIwindow_bits\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_crc_action (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIcrit_action\fP\fB, int \fIancil_action\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_dither (png_structp \fP\fIpng_ptr\fP\fB, png_colorp \fP\fIpalette\fP\fB, int \fP\fInum_palette\fP\fB, int \fP\fImaximum_colors\fP\fB, png_uint_16p \fP\fIhistogram\fP\fB, int \fIfull_dither\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_error_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fIwarning_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_expand (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_expand_gray_1_2_4_to_8(png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_filler (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIfiller\fP\fB, int \fIflags\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_filter (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fImethod\fP\fB, int \fIfilters\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_filter_heuristics (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIheuristic_method\fP\fB, int \fP\fInum_weights\fP\fB, png_doublep \fP\fIfilter_weights\fP\fB, png_doublep \fIfilter_costs\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_flush (png_structp \fP\fIpng_ptr\fP\fB, int \fInrows\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_gamma (png_structp \fP\fIpng_ptr\fP\fB, double \fP\fIscreen_gamma\fP\fB, double \fIdefault_file_gamma\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_gAMA (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fIfile_gamma\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_gAMA_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIfile_gamma\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_gray_1_2_4_to_8(png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_gray_to_rgb (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_hIST (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_16p \fIhist\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_iCCP (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charp \fP\fIname\fP\fB, int \fP\fIcompression_type\fP\fB, png_charp \fP\fIprofile\fP\fB, png_uint_32 \fIproflen\fP\fB);\fP + +\fI\fB + +\fBint png_set_interlace_handling (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_invalid (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fImask\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_invert_alpha (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_invert_mono (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_IHDR (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIwidth\fP\fB, png_uint_32 \fP\fIheight\fP\fB, int \fP\fIbit_depth\fP\fB, int \fP\fIcolor_type\fP\fB, int \fP\fIinterlace_type\fP\fB, int \fP\fIcompression_type\fP\fB, int \fIfilter_type\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_keep_unknown_chunks (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIkeep\fP\fB, png_bytep \fP\fIchunk_list\fP\fB, int \fInum_chunks\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_mem_fn(png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fImem_ptr\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_free_ptr \fIfree_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_oFFs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIoffset_x\fP\fB, png_uint_32 \fP\fIoffset_y\fP\fB, int \fIunit_type\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_packing (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_packswap (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_palette_to_rgb(png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_pCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charp \fP\fIpurpose\fP\fB, png_int_32 \fP\fIX0\fP\fB, png_int_32 \fP\fIX1\fP\fB, int \fP\fItype\fP\fB, int \fP\fInparams\fP\fB, png_charp \fP\fIunits\fP\fB, png_charpp \fIparams\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_pHYs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIres_x\fP\fB, png_uint_32 \fP\fIres_y\fP\fB, int \fIunit_type\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_progressive_read_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIprogressive_ptr\fP\fB, png_progressive_info_ptr \fP\fIinfo_fn\fP\fB, png_progressive_row_ptr \fP\fIrow_fn\fP\fB, png_progressive_end_ptr \fIend_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_colorp \fP\fIpalette\fP\fB, int \fInum_palette\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_read_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIio_ptr\fP\fB, png_rw_ptr \fIread_data_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_read_status_fn (png_structp \fP\fIpng_ptr\fP\fB, png_read_status_ptr \fIread_row_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_read_user_transform_fn (png_structp \fP\fIpng_ptr\fP\fB, png_user_transform_ptr \fIread_user_transform_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_rgb_to_gray (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIerror_action\fP\fB, double \fP\fIred\fP\fB, double \fIgreen\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_rgb_to_gray_fixed (png_structp \fP\fIpng_ptr\fP\fB, int error_action png_fixed_point \fP\fIred\fP\fB, png_fixed_point \fIgreen\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_rows (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytepp \fIrow_pointers\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_sBIT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_8p \fIsig_bit\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_sCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charp \fP\fIunit\fP\fB, double \fP\fIwidth\fP\fB, double \fIheight\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_shift (png_structp \fP\fIpng_ptr\fP\fB, png_color_8p \fItrue_bits\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_sig_bytes (png_structp \fP\fIpng_ptr\fP\fB, int \fInum_bytes\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_sPLT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_spalette_p \fP\fIsplt_ptr\fP\fB, int \fInum_spalettes\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_sRGB (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fIintent\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_sRGB_gAMA_and_cHRM (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fIintent\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_strip_16 (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_strip_alpha (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_swap (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_swap_alpha (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_text (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_textp \fP\fItext_ptr\fP\fB, int \fInum_text\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_tIME (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_timep \fImod_time\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_tRNS (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fP\fItrans\fP\fB, int \fP\fInum_trans\fP\fB, png_color_16p \fItrans_values\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_tRNS_to_alpha(png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_set_unknown_chunks (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_unknown_chunkp \fP\fIunknowns\fP\fB, int \fP\fInum\fP\fB, int \fIlocation\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_unknown_chunk_location(png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fIchunk\fP\fB, int \fIlocation\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_read_user_chunk_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIuser_chunk_ptr\fP\fB, png_user_chunk_ptr \fIread_user_chunk_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_user_limits (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIuser_width_max\fP\fB, png_uint_32 \fIuser_height_max\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_user_transform_info (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIuser_transform_ptr\fP\fB, int \fP\fIuser_transform_depth\fP\fB, int \fIuser_transform_channels\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_write_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIio_ptr\fP\fB, png_rw_ptr \fP\fIwrite_data_fn\fP\fB, png_flush_ptr \fIoutput_flush_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_write_status_fn (png_structp \fP\fIpng_ptr\fP\fB, png_write_status_ptr \fIwrite_row_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_write_user_transform_fn (png_structp \fP\fIpng_ptr\fP\fB, png_user_transform_ptr \fIwrite_user_transform_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_compression_buffer_size(png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIsize\fP\fB);\fP + +\fI\fB + +\fBint png_sig_cmp (png_bytep \fP\fIsig\fP\fB, png_size_t \fP\fIstart\fP\fB, png_size_t \fInum_to_check\fP\fB);\fP + +\fI\fB + +\fBvoid png_start_read_image (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_warning (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fImessage\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_chunk (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIchunk_name\fP\fB, png_bytep \fP\fIdata\fP\fB, png_size_t \fIlength\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_chunk_data (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIdata\fP\fB, png_size_t \fIlength\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_chunk_end (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_chunk_start (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIchunk_name\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_destroy (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_end (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_flush (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_image (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fIimage\fP\fB);\fP + +\fI\fB + +\fBDEPRECATED: void png_write_init (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBDEPRECATED: void png_write_init_2 (png_structpp \fP\fIptr_ptr\fP\fB, png_const_charp \fP\fIuser_png_ver\fP\fB, png_size_t \fP\fIpng_struct_size\fP\fB, png_size_t \fIpng_info_size\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_info_before_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_png (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fItransforms\fP\fB, png_voidp \fIparams\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIrow\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_rows (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fP\fIrow\fP\fB, png_uint_32 \fInum_rows\fP\fB);\fP + +\fI\fB + +\fBvoidpf png_zalloc (voidpf \fP\fIpng_ptr\fP\fB, uInt \fP\fIitems\fP\fB, uInt \fIsize\fP\fB);\fP + +\fI\fB + +\fBvoid png_zfree (voidpf \fP\fIpng_ptr\fP\fB, voidpf \fIptr\fP\fB);\fP + +\fI\fB + +.SH DESCRIPTION +The +.I libpng +library supports encoding, decoding, and various manipulations of +the Portable Network Graphics (PNG) format image files. It uses the +.IR zlib(3) +compression library. +Following is a copy of the libpng.txt file that accompanies libpng. +.SH LIBPNG.TXT +libpng.txt - A description on how to use and modify libpng + + libpng version 1.2.44 - June 26, 2010 + Updated and distributed by Glenn Randers-Pehrson + <glennrp at users.sourceforge.net> + Copyright (c) 1998-2009 Glenn Randers-Pehrson + + This document is released under the libpng license. + For conditions of distribution and use, see the disclaimer + and license in png.h + + Based on: + + libpng versions 0.97, January 1998, through 1.2.44 - June 26, 2010 + Updated and distributed by Glenn Randers-Pehrson + Copyright (c) 1998-2009 Glenn Randers-Pehrson + + libpng 1.0 beta 6 version 0.96 May 28, 1997 + Updated and distributed by Andreas Dilger + Copyright (c) 1996, 1997 Andreas Dilger + + libpng 1.0 beta 2 - version 0.88 January 26, 1996 + For conditions of distribution and use, see copyright + notice in png.h. Copyright (c) 1995, 1996 Guy Eric + Schalnat, Group 42, Inc. + + Updated/rewritten per request in the libpng FAQ + Copyright (c) 1995, 1996 Frank J. T. Wojcik + December 18, 1995 & January 20, 1996 + +.SH I. Introduction + +This file describes how to use and modify the PNG reference library +(known as libpng) for your own use. There are five sections to this +file: introduction, structures, reading, writing, and modification and +configuration notes for various special platforms. In addition to this +file, example.c is a good starting point for using the library, as +it is heavily commented and should include everything most people +will need. We assume that libpng is already installed; see the +INSTALL file for instructions on how to install libpng. + +For examples of libpng usage, see the files "example.c", "pngtest.c", +and the files in the "contrib" directory, all of which are included in +the libpng distribution. + +Libpng was written as a companion to the PNG specification, as a way +of reducing the amount of time and effort it takes to support the PNG +file format in application programs. + +The PNG specification (second edition), November 2003, is available as +a W3C Recommendation and as an ISO Standard (ISO/IEC 15948:2003 (E)) at +<http://www.w3.org/TR/2003/REC-PNG-20031110/ +The W3C and ISO documents have identical technical content. + +The PNG-1.2 specification is available at +<http://www.libpng.org/pub/png/documents/>. It is technically equivalent +to the PNG specification (second edition) but has some additional material. + +The PNG-1.0 specification is available +as RFC 2083 <http://www.libpng.org/pub/png/documents/> and as a +W3C Recommendation <http://www.w3.org/TR/REC.png.html>. + +Some additional chunks are described in the special-purpose public chunks +documents at <http://www.libpng.org/pub/png/documents/>. + +Other information +about PNG, and the latest version of libpng, can be found at the PNG home +page, <http://www.libpng.org/pub/png/>. + +Most users will not have to modify the library significantly; advanced +users may want to modify it more. All attempts were made to make it as +complete as possible, while keeping the code easy to understand. +Currently, this library only supports C. Support for other languages +is being considered. + +Libpng has been designed to handle multiple sessions at one time, +to be easily modifiable, to be portable to the vast majority of +machines (ANSI, K&R, 16-, 32-, and 64-bit) available, and to be easy +to use. The ultimate goal of libpng is to promote the acceptance of +the PNG file format in whatever way possible. While there is still +work to be done (see the TODO file), libpng should cover the +majority of the needs of its users. + +Libpng uses zlib for its compression and decompression of PNG files. +Further information about zlib, and the latest version of zlib, can +be found at the zlib home page, <http://www.info-zip.org/pub/infozip/zlib/>. +The zlib compression utility is a general purpose utility that is +useful for more than PNG files, and can be used without libpng. +See the documentation delivered with zlib for more details. +You can usually find the source files for the zlib utility wherever you +find the libpng source files. + +Libpng is thread safe, provided the threads are using different +instances of the structures. Each thread should have its own +png_struct and png_info instances, and thus its own image. +Libpng does not protect itself against two threads using the +same instance of a structure. + +.SH II. Structures + +There are two main structures that are important to libpng, png_struct +and png_info. The first, png_struct, is an internal structure that +will not, for the most part, be used by a user except as the first +variable passed to every libpng function call. + +The png_info structure is designed to provide information about the +PNG file. At one time, the fields of png_info were intended to be +directly accessible to the user. However, this tended to cause problems +with applications using dynamically loaded libraries, and as a result +a set of interface functions for png_info (the png_get_*() and png_set_*() +functions) was developed. The fields of png_info are still available for +older applications, but it is suggested that applications use the new +interfaces if at all possible. + +Applications that do make direct access to the members of png_struct (except +for png_ptr->jmpbuf) must be recompiled whenever the library is updated, +and applications that make direct access to the members of png_info must +be recompiled if they were compiled or loaded with libpng version 1.0.6, +in which the members were in a different order. In version 1.0.7, the +members of the png_info structure reverted to the old order, as they were +in versions 0.97c through 1.0.5. Starting with version 2.0.0, both +structures are going to be hidden, and the contents of the structures will +only be accessible through the png_get/png_set functions. + +The png.h header file is an invaluable reference for programming with libpng. +And while I'm on the topic, make sure you include the libpng header file: + +#include <png.h> + +.SH III. Reading + +We'll now walk you through the possible functions to call when reading +in a PNG file sequentially, briefly explaining the syntax and purpose +of each one. See example.c and png.h for more detail. While +progressive reading is covered in the next section, you will still +need some of the functions discussed in this section to read a PNG +file. + +.SS Setup + +You will want to do the I/O initialization(*) before you get into libpng, +so if it doesn't work, you don't have much to undo. Of course, you +will also want to insure that you are, in fact, dealing with a PNG +file. Libpng provides a simple check to see if a file is a PNG file. +To use it, pass in the first 1 to 8 bytes of the file to the function +png_sig_cmp(), and it will return 0 (false) if the bytes match the +corresponding bytes of the PNG signature, or nonzero (true) otherwise. +Of course, the more bytes you pass in, the greater the accuracy of the +prediction. + +If you are intending to keep the file pointer open for use in libpng, +you must ensure you don't read more than 8 bytes from the beginning +of the file, and you also have to make a call to png_set_sig_bytes_read() +with the number of bytes you read from the beginning. Libpng will +then only check the bytes (if any) that your program didn't read. + +(*): If you are not using the standard I/O functions, you will need +to replace them with custom functions. See the discussion under +Customizing libpng. + + + FILE *fp = fopen(file_name, "rb"); + if (!fp) + { + return (ERROR); + } + fread(header, 1, number, fp); + is_png = !png_sig_cmp(header, 0, number); + if (!is_png) + { + return (NOT_PNG); + } + + +Next, png_struct and png_info need to be allocated and initialized. In +order to ensure that the size of these structures is correct even with a +dynamically linked libpng, there are functions to initialize and +allocate the structures. We also pass the library version, optional +pointers to error handling functions, and a pointer to a data struct for +use by the error functions, if necessary (the pointer and functions can +be NULL if the default error handlers are to be used). See the section +on Changes to Libpng below regarding the old initialization functions. +The structure allocation functions quietly return NULL if they fail to +create the structure, so your application should check for that. + + png_structp png_ptr = png_create_read_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn); + if (!png_ptr) + return (ERROR); + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_read_struct(&png_ptr, + (png_infopp)NULL, (png_infopp)NULL); + return (ERROR); + } + + png_infop end_info = png_create_info_struct(png_ptr); + if (!end_info) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + return (ERROR); + } + +If you want to use your own memory allocation routines, +define PNG_USER_MEM_SUPPORTED and use +png_create_read_struct_2() instead of png_create_read_struct(): + + png_structp png_ptr = png_create_read_struct_2 + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn, (png_voidp) + user_mem_ptr, user_malloc_fn, user_free_fn); + +The error handling routines passed to png_create_read_struct() +and the memory alloc/free routines passed to png_create_struct_2() +are only necessary if you are not using the libpng supplied error +handling and memory alloc/free functions. + +When libpng encounters an error, it expects to longjmp back +to your routine. Therefore, you will need to call setjmp and pass +your png_jmpbuf(png_ptr). If you read the file from different +routines, you will need to update the jmpbuf field every time you enter +a new routine that will call a png_*() function. + +See your documentation of setjmp/longjmp for your compiler for more +information on setjmp/longjmp. See the discussion on libpng error +handling in the Customizing Libpng section below for more information +on the libpng error handling. If an error occurs, and libpng longjmp's +back to your setjmp, you will want to call png_destroy_read_struct() to +free any memory. + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + &end_info); + fclose(fp); + return (ERROR); + } + +If you would rather avoid the complexity of setjmp/longjmp issues, +you can compile libpng with PNG_SETJMP_NOT_SUPPORTED, in which case +errors will result in a call to PNG_ABORT() which defaults to abort(). + +Now you need to set up the input code. The default for libpng is to +use the C function fread(). If you use this, you will need to pass a +valid FILE * in the function png_init_io(). Be sure that the file is +opened in binary mode. If you wish to handle reading data in another +way, you need not call the png_init_io() function, but you must then +implement the libpng I/O methods discussed in the Customizing Libpng +section below. + + png_init_io(png_ptr, fp); + +If you had previously opened the file and read any of the signature from +the beginning in order to see if this was a PNG file, you need to let +libpng know that there are some bytes missing from the start of the file. + + png_set_sig_bytes(png_ptr, number); + +.SS Setting up callback code + +You can set up a callback function to handle any unknown chunks in the +input stream. You must supply the function + + read_chunk_callback(png_ptr ptr, + png_unknown_chunkp chunk); + { + /* The unknown chunk structure contains your + chunk data, along with similar data for any other + unknown chunks: */ + + png_byte name[5]; + png_byte *data; + png_size_t size; + + /* Note that libpng has already taken care of + the CRC handling */ + + /* put your code here. Search for your chunk in the + unknown chunk structure, process it, and return one + of the following: */ + + return (-n); /* chunk had an error */ + return (0); /* did not recognize */ + return (n); /* success */ + } + +(You can give your function another name that you like instead of +"read_chunk_callback") + +To inform libpng about your function, use + + png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr, + read_chunk_callback); + +This names not only the callback function, but also a user pointer that +you can retrieve with + + png_get_user_chunk_ptr(png_ptr); + +If you call the png_set_read_user_chunk_fn() function, then all unknown +chunks will be saved when read, in case your callback function will need +one or more of them. This behavior can be changed with the +png_set_keep_unknown_chunks() function, described below. + +At this point, you can set up a callback function that will be +called after each row has been read, which you can use to control +a progress meter or the like. It's demonstrated in pngtest.c. +You must supply a function + + void read_row_callback(png_ptr ptr, png_uint_32 row, + int pass); + { + /* put your code here */ + } + +(You can give it another name that you like instead of "read_row_callback") + +To inform libpng about your function, use + + png_set_read_status_fn(png_ptr, read_row_callback); + +.SS Unknown-chunk handling + +Now you get to set the way the library processes unknown chunks in the +input PNG stream. Both known and unknown chunks will be read. Normal +behavior is that known chunks will be parsed into information in +various info_ptr members while unknown chunks will be discarded. This +behavior can be wasteful if your application will never use some known +chunk types. To change this, you can call: + + png_set_keep_unknown_chunks(png_ptr, keep, + chunk_list, num_chunks); + keep - 0: default unknown chunk handling + 1: ignore; do not keep + 2: keep only if safe-to-copy + 3: keep even if unsafe-to-copy + You can use these definitions: + PNG_HANDLE_CHUNK_AS_DEFAULT 0 + PNG_HANDLE_CHUNK_NEVER 1 + PNG_HANDLE_CHUNK_IF_SAFE 2 + PNG_HANDLE_CHUNK_ALWAYS 3 + chunk_list - list of chunks affected (a byte string, + five bytes per chunk, NULL or '\0' if + num_chunks is 0) + num_chunks - number of chunks affected; if 0, all + unknown chunks are affected. If nonzero, + only the chunks in the list are affected + +Unknown chunks declared in this way will be saved as raw data onto a +list of png_unknown_chunk structures. If a chunk that is normally +known to libpng is named in the list, it will be handled as unknown, +according to the "keep" directive. If a chunk is named in successive +instances of png_set_keep_unknown_chunks(), the final instance will +take precedence. The IHDR and IEND chunks should not be named in +chunk_list; if they are, libpng will process them normally anyway. + +Here is an example of the usage of png_set_keep_unknown_chunks(), +where the private "vpAg" chunk will later be processed by a user chunk +callback function: + + png_byte vpAg[5]={118, 112, 65, 103, (png_byte) '\0'}; + + #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + png_byte unused_chunks[]= + { + 104, 73, 83, 84, (png_byte) '\0', /* hIST */ + 105, 84, 88, 116, (png_byte) '\0', /* iTXt */ + 112, 67, 65, 76, (png_byte) '\0', /* pCAL */ + 115, 67, 65, 76, (png_byte) '\0', /* sCAL */ + 115, 80, 76, 84, (png_byte) '\0', /* sPLT */ + 116, 73, 77, 69, (png_byte) '\0', /* tIME */ + }; + #endif + + ... + + #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + /* ignore all unknown chunks: */ + png_set_keep_unknown_chunks(read_ptr, 1, NULL, 0); + /* except for vpAg: */ + png_set_keep_unknown_chunks(read_ptr, 2, vpAg, 1); + /* also ignore unused known chunks: */ + png_set_keep_unknown_chunks(read_ptr, 1, unused_chunks, + (int)sizeof(unused_chunks)/5); + #endif + +.SS User limits + +The PNG specification allows the width and height of an image to be as +large as 2^31-1 (0x7fffffff), or about 2.147 billion rows and columns. +Since very few applications really need to process such large images, +we have imposed an arbitrary 1-million limit on rows and columns. +Larger images will be rejected immediately with a png_error() call. If +you wish to override this limit, you can use + + png_set_user_limits(png_ptr, width_max, height_max); + +to set your own limits, or use width_max = height_max = 0x7fffffffL +to allow all valid dimensions (libpng may reject some very large images +anyway because of potential buffer overflow conditions). + +You should put this statement after you create the PNG structure and +before calling png_read_info(), png_read_png(), or png_process_data(). +If you need to retrieve the limits that are being applied, use + + width_max = png_get_user_width_max(png_ptr); + height_max = png_get_user_height_max(png_ptr); + +The PNG specification sets no limit on the number of ancillary chunks +allowed in a PNG datastream. You can impose a limit on the total number +of sPLT, tEXt, iTXt, zTXt, and unknown chunks that will be stored, with + + png_set_chunk_cache_max(png_ptr, user_chunk_cache_max); + +where 0x7fffffffL means unlimited. You can retrieve this limit with + + chunk_cache_max = png_get_chunk_cache_max(png_ptr); + +This limit also applies to the number of buffers that can be allocated +by png_decompress_chunk() while decompressing iTXt, zTXt, and iCCP chunks. + +.SS The high-level read interface + +At this point there are two ways to proceed; through the high-level +read interface, or through a sequence of low-level read operations. +You can use the high-level interface if (a) you are willing to read +the entire image into memory, and (b) the input transformations +you want to do are limited to the following set: + + PNG_TRANSFORM_IDENTITY No transformation + PNG_TRANSFORM_STRIP_16 Strip 16-bit samples to + 8 bits + PNG_TRANSFORM_STRIP_ALPHA Discard the alpha channel + PNG_TRANSFORM_PACKING Expand 1, 2 and 4-bit + samples to bytes + PNG_TRANSFORM_PACKSWAP Change order of packed + pixels to LSB first + PNG_TRANSFORM_EXPAND Perform set_expand() + PNG_TRANSFORM_INVERT_MONO Invert monochrome images + PNG_TRANSFORM_SHIFT Normalize pixels to the + sBIT depth + PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA + to BGRA + PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA + to AG + PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity + to transparency + PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples + PNG_TRANSFORM_GRAY_TO_RGB Expand grayscale samples + to RGB (or GA to RGBA) + +(This excludes setting a background color, doing gamma transformation, +dithering, and setting filler.) If this is the case, simply do this: + + png_read_png(png_ptr, info_ptr, png_transforms, NULL) + +where png_transforms is an integer containing the bitwise OR of some +set of transformation flags. This call is equivalent to png_read_info(), +followed the set of transformations indicated by the transform mask, +then png_read_image(), and finally png_read_end(). + +(The final parameter of this call is not yet used. Someday it might point +to transformation parameters required by some future input transform.) + +You must use png_transforms and not call any png_set_transform() functions +when you use png_read_png(). + +After you have called png_read_png(), you can retrieve the image data +with + + row_pointers = png_get_rows(png_ptr, info_ptr); + +where row_pointers is an array of pointers to the pixel data for each row: + + png_bytep row_pointers[height]; + +If you know your image size and pixel size ahead of time, you can allocate +row_pointers prior to calling png_read_png() with + + if (height > PNG_UINT_32_MAX/png_sizeof(png_byte)) + png_error (png_ptr, + "Image is too tall to process in memory"); + if (width > PNG_UINT_32_MAX/pixel_size) + png_error (png_ptr, + "Image is too wide to process in memory"); + row_pointers = png_malloc(png_ptr, + height*png_sizeof(png_bytep)); + for (int i=0; i<height, i++) + row_pointers[i]=NULL; /* security precaution */ + for (int i=0; i<height, i++) + row_pointers[i]=png_malloc(png_ptr, + width*pixel_size); + png_set_rows(png_ptr, info_ptr, &row_pointers); + +Alternatively you could allocate your image in one big block and define +row_pointers[i] to point into the proper places in your block. + +If you use png_set_rows(), the application is responsible for freeing +row_pointers (and row_pointers[i], if they were separately allocated). + +If you don't allocate row_pointers ahead of time, png_read_png() will +do it, and it'll be free'ed when you call png_destroy_*(). + +.SS The low-level read interface + +If you are going the low-level route, you are now ready to read all +the file information up to the actual image data. You do this with a +call to png_read_info(). + + png_read_info(png_ptr, info_ptr); + +This will process all chunks up to but not including the image data. + +.SS Querying the info structure + +Functions are used to get the information from the info_ptr once it +has been read. Note that these fields may not be completely filled +in until png_read_end() has read the chunk data following the image. + + png_get_IHDR(png_ptr, info_ptr, &width, &height, + &bit_depth, &color_type, &interlace_type, + &compression_type, &filter_method); + + width - holds the width of the image + in pixels (up to 2^31). + height - holds the height of the image + in pixels (up to 2^31). + bit_depth - holds the bit depth of one of the + image channels. (valid values are + 1, 2, 4, 8, 16 and depend also on + the color_type. See also + significant bits (sBIT) below). + color_type - describes which color/alpha channels + are present. + PNG_COLOR_TYPE_GRAY + (bit depths 1, 2, 4, 8, 16) + PNG_COLOR_TYPE_GRAY_ALPHA + (bit depths 8, 16) + PNG_COLOR_TYPE_PALETTE + (bit depths 1, 2, 4, 8) + PNG_COLOR_TYPE_RGB + (bit_depths 8, 16) + PNG_COLOR_TYPE_RGB_ALPHA + (bit_depths 8, 16) + + PNG_COLOR_MASK_PALETTE + PNG_COLOR_MASK_COLOR + PNG_COLOR_MASK_ALPHA + + filter_method - (must be PNG_FILTER_TYPE_BASE + for PNG 1.0, and can also be + PNG_INTRAPIXEL_DIFFERENCING if + the PNG datastream is embedded in + a MNG-1.0 datastream) + compression_type - (must be PNG_COMPRESSION_TYPE_BASE + for PNG 1.0) + interlace_type - (PNG_INTERLACE_NONE or + PNG_INTERLACE_ADAM7) + + Any or all of interlace_type, compression_type, or + filter_method can be NULL if you are + not interested in their values. + + Note that png_get_IHDR() returns 32-bit data into + the application's width and height variables. + This is an unsafe situation if these are 16-bit + variables. In such situations, the + png_get_image_width() and png_get_image_height() + functions described below are safer. + + width = png_get_image_width(png_ptr, + info_ptr); + height = png_get_image_height(png_ptr, + info_ptr); + bit_depth = png_get_bit_depth(png_ptr, + info_ptr); + color_type = png_get_color_type(png_ptr, + info_ptr); + filter_method = png_get_filter_type(png_ptr, + info_ptr); + compression_type = png_get_compression_type(png_ptr, + info_ptr); + interlace_type = png_get_interlace_type(png_ptr, + info_ptr); + + channels = png_get_channels(png_ptr, info_ptr); + channels - number of channels of info for the + color type (valid values are 1 (GRAY, + PALETTE), 2 (GRAY_ALPHA), 3 (RGB), + 4 (RGB_ALPHA or RGB + filler byte)) + rowbytes = png_get_rowbytes(png_ptr, info_ptr); + rowbytes - number of bytes needed to hold a row + + signature = png_get_signature(png_ptr, info_ptr); + signature - holds the signature read from the + file (if any). The data is kept in + the same offset it would be if the + whole signature were read (i.e. if an + application had already read in 4 + bytes of signature before starting + libpng, the remaining 4 bytes would + be in signature[4] through signature[7] + (see png_set_sig_bytes())). + +These are also important, but their validity depends on whether the chunk +has been read. The png_get_valid(png_ptr, info_ptr, PNG_INFO_<chunk>) and +png_get_<chunk>(png_ptr, info_ptr, ...) functions return non-zero if the +data has been read, or zero if it is missing. The parameters to the +png_get_<chunk> are set directly if they are simple data types, or a +pointer into the info_ptr is returned for any complex types. + + png_get_PLTE(png_ptr, info_ptr, &palette, + &num_palette); + palette - the palette for the file + (array of png_color) + num_palette - number of entries in the palette + + png_get_gAMA(png_ptr, info_ptr, &gamma); + gamma - the gamma the file is written + at (PNG_INFO_gAMA) + + png_get_sRGB(png_ptr, info_ptr, &srgb_intent); + srgb_intent - the rendering intent (PNG_INFO_sRGB) + The presence of the sRGB chunk + means that the pixel data is in the + sRGB color space. This chunk also + implies specific values of gAMA and + cHRM. + + png_get_iCCP(png_ptr, info_ptr, &name, + &compression_type, &profile, &proflen); + name - The profile name. + compression - The compression type; always + PNG_COMPRESSION_TYPE_BASE for PNG 1.0. + You may give NULL to this argument to + ignore it. + profile - International Color Consortium color + profile data. May contain NULs. + proflen - length of profile data in bytes. + + png_get_sBIT(png_ptr, info_ptr, &sig_bit); + sig_bit - the number of significant bits for + (PNG_INFO_sBIT) each of the gray, + red, green, and blue channels, + whichever are appropriate for the + given color type (png_color_16) + + png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, + &trans_values); + trans - array of transparent + entries for palette (PNG_INFO_tRNS) + trans_values - graylevel or color sample values of + the single transparent color for + non-paletted images (PNG_INFO_tRNS) + num_trans - number of transparent entries + (PNG_INFO_tRNS) + + png_get_hIST(png_ptr, info_ptr, &hist); + (PNG_INFO_hIST) + hist - histogram of palette (array of + png_uint_16) + + png_get_tIME(png_ptr, info_ptr, &mod_time); + mod_time - time image was last modified + (PNG_VALID_tIME) + + png_get_bKGD(png_ptr, info_ptr, &background); + background - background color (PNG_VALID_bKGD) + valid 16-bit red, green and blue + values, regardless of color_type + + num_comments = png_get_text(png_ptr, info_ptr, + &text_ptr, &num_text); + num_comments - number of comments + text_ptr - array of png_text holding image + comments + text_ptr[i].compression - type of compression used + on "text" PNG_TEXT_COMPRESSION_NONE + PNG_TEXT_COMPRESSION_zTXt + PNG_ITXT_COMPRESSION_NONE + PNG_ITXT_COMPRESSION_zTXt + text_ptr[i].key - keyword for comment. Must contain + 1-79 characters. + text_ptr[i].text - text comments for current + keyword. Can be empty. + text_ptr[i].text_length - length of text string, + after decompression, 0 for iTXt + text_ptr[i].itxt_length - length of itxt string, + after decompression, 0 for tEXt/zTXt + text_ptr[i].lang - language of comment (empty + string for unknown). + text_ptr[i].lang_key - keyword in UTF-8 + (empty string for unknown). + Note that the itxt_length, lang, and lang_key + members of the text_ptr structure only exist + when the library is built with iTXt chunk support. + + num_text - number of comments (same as + num_comments; you can put NULL here + to avoid the duplication) + Note while png_set_text() will accept text, language, + and translated keywords that can be NULL pointers, the + structure returned by png_get_text will always contain + regular zero-terminated C strings. They might be + empty strings but they will never be NULL pointers. + + num_spalettes = png_get_sPLT(png_ptr, info_ptr, + &palette_ptr); + palette_ptr - array of palette structures holding + contents of one or more sPLT chunks + read. + num_spalettes - number of sPLT chunks read. + + png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y, + &unit_type); + offset_x - positive offset from the left edge + of the screen + offset_y - positive offset from the top edge + of the screen + unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER + + png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, + &unit_type); + res_x - pixels/unit physical resolution in + x direction + res_y - pixels/unit physical resolution in + x direction + unit_type - PNG_RESOLUTION_UNKNOWN, + PNG_RESOLUTION_METER + + png_get_sCAL(png_ptr, info_ptr, &unit, &width, + &height) + unit - physical scale units (an integer) + width - width of a pixel in physical scale units + height - height of a pixel in physical scale units + (width and height are doubles) + + png_get_sCAL_s(png_ptr, info_ptr, &unit, &width, + &height) + unit - physical scale units (an integer) + width - width of a pixel in physical scale units + height - height of a pixel in physical scale units + (width and height are strings like "2.54") + + num_unknown_chunks = png_get_unknown_chunks(png_ptr, + info_ptr, &unknowns) + unknowns - array of png_unknown_chunk + structures holding unknown chunks + unknowns[i].name - name of unknown chunk + unknowns[i].data - data of unknown chunk + unknowns[i].size - size of unknown chunk's data + unknowns[i].location - position of chunk in file + + The value of "i" corresponds to the order in which the + chunks were read from the PNG file or inserted with the + png_set_unknown_chunks() function. + +The data from the pHYs chunk can be retrieved in several convenient +forms: + + res_x = png_get_x_pixels_per_meter(png_ptr, + info_ptr) + res_y = png_get_y_pixels_per_meter(png_ptr, + info_ptr) + res_x_and_y = png_get_pixels_per_meter(png_ptr, + info_ptr) + res_x = png_get_x_pixels_per_inch(png_ptr, + info_ptr) + res_y = png_get_y_pixels_per_inch(png_ptr, + info_ptr) + res_x_and_y = png_get_pixels_per_inch(png_ptr, + info_ptr) + aspect_ratio = png_get_pixel_aspect_ratio(png_ptr, + info_ptr) + + (Each of these returns 0 [signifying "unknown"] if + the data is not present or if res_x is 0; + res_x_and_y is 0 if res_x != res_y) + +The data from the oFFs chunk can be retrieved in several convenient +forms: + + x_offset = png_get_x_offset_microns(png_ptr, info_ptr); + y_offset = png_get_y_offset_microns(png_ptr, info_ptr); + x_offset = png_get_x_offset_inches(png_ptr, info_ptr); + y_offset = png_get_y_offset_inches(png_ptr, info_ptr); + + (Each of these returns 0 [signifying "unknown" if both + x and y are 0] if the data is not present or if the + chunk is present but the unit is the pixel) + +For more information, see the png_info definition in png.h and the +PNG specification for chunk contents. Be careful with trusting +rowbytes, as some of the transformations could increase the space +needed to hold a row (expand, filler, gray_to_rgb, etc.). +See png_read_update_info(), below. + +A quick word about text_ptr and num_text. PNG stores comments in +keyword/text pairs, one pair per chunk, with no limit on the number +of text chunks, and a 2^31 byte limit on their size. While there are +suggested keywords, there is no requirement to restrict the use to these +strings. It is strongly suggested that keywords and text be sensible +to humans (that's the point), so don't use abbreviations. Non-printing +symbols are not allowed. See the PNG specification for more details. +There is also no requirement to have text after the keyword. + +Keywords should be limited to 79 Latin-1 characters without leading or +trailing spaces, but non-consecutive spaces are allowed within the +keyword. It is possible to have the same keyword any number of times. +The text_ptr is an array of png_text structures, each holding a +pointer to a language string, a pointer to a keyword and a pointer to +a text string. The text string, language code, and translated +keyword may be empty or NULL pointers. The keyword/text +pairs are put into the array in the order that they are received. +However, some or all of the text chunks may be after the image, so, to +make sure you have read all the text chunks, don't mess with these +until after you read the stuff after the image. This will be +mentioned again below in the discussion that goes with png_read_end(). + +.SS Input transformations + +After you've read the header information, you can set up the library +to handle any special transformations of the image data. The various +ways to transform the data will be described in the order that they +should occur. This is important, as some of these change the color +type and/or bit depth of the data, and some others only work on +certain color types and bit depths. Even though each transformation +checks to see if it has data that it can do something with, you should +make sure to only enable a transformation if it will be valid for the +data. For example, don't swap red and blue on grayscale data. + +The colors used for the background and transparency values should be +supplied in the same format/depth as the current image data. They +are stored in the same format/depth as the image data in a bKGD or tRNS +chunk, so this is what libpng expects for this data. The colors are +transformed to keep in sync with the image data when an application +calls the png_read_update_info() routine (see below). + +Data will be decoded into the supplied row buffers packed into bytes +unless the library has been told to transform it into another format. +For example, 4 bit/pixel paletted or grayscale data will be returned +2 pixels/byte with the leftmost pixel in the high-order bits of the +byte, unless png_set_packing() is called. 8-bit RGB data will be stored +in RGB RGB RGB format unless png_set_filler() or png_set_add_alpha() +is called to insert filler bytes, either before or after each RGB triplet. +16-bit RGB data will be returned RRGGBB RRGGBB, with the most significant +byte of the color value first, unless png_set_strip_16() is called to +transform it to regular RGB RGB triplets, or png_set_filler() or +png_set_add alpha() is called to insert filler bytes, either before or +after each RRGGBB triplet. Similarly, 8-bit or 16-bit grayscale data can +be modified with +png_set_filler(), png_set_add_alpha(), or png_set_strip_16(). + +The following code transforms grayscale images of less than 8 to 8 bits, +changes paletted images to RGB, and adds a full alpha channel if there is +transparency information in a tRNS chunk. This is most useful on +grayscale images with bit depths of 2 or 4 or if there is a multiple-image +viewing application that wishes to treat all images in the same way. + + if (color_type == PNG_COLOR_TYPE_PALETTE) + png_set_palette_to_rgb(png_ptr); + + if (color_type == PNG_COLOR_TYPE_GRAY && + bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); + + if (png_get_valid(png_ptr, info_ptr, + PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); + +These three functions are actually aliases for png_set_expand(), added +in libpng version 1.0.4, with the function names expanded to improve code +readability. In some future version they may actually do different +things. + +As of libpng version 1.2.9, png_set_expand_gray_1_2_4_to_8() was +added. It expands the sample depth without changing tRNS to alpha. + +As of libpng version 1.2.44, not all possible expansions are supported. + +In the following table, the 01 means grayscale with depth<8, 31 means +indexed with depth<8, other numerals represent the color type, "T" means +the tRNS chunk is present, A means an alpha channel is present, and O +means tRNS or alpha is present but all pixels in the image are opaque. + + FROM 01 31 0 0T 0O 2 2T 2O 3 3T 3O 4A 4O 6A 6O + TO + 01 - + 31 - + 0 1 - + 0T - + 0O - + 2 GX - + 2T - + 2O - + 3 1 - + 3T - + 3O - + 4A T - + 4O - + 6A GX TX TX - + 6O GX TX - + +Within the matrix, + "-" means the transformation is not supported. + "X" means the transformation is obtained by png_set_expand(). + "1" means the transformation is obtained by + png_set_expand_gray_1_2_4_to_8 + "G" means the transformation is obtained by + png_set_gray_to_rgb(). + "P" means the transformation is obtained by + png_set_expand_palette_to_rgb(). + "T" means the transformation is obtained by + png_set_tRNS_to_alpha(). + +PNG can have files with 16 bits per channel. If you only can handle +8 bits per channel, this will strip the pixels down to 8 bit. + + if (bit_depth == 16) + png_set_strip_16(png_ptr); + +If, for some reason, you don't need the alpha channel on an image, +and you want to remove it rather than combining it with the background +(but the image author certainly had in mind that you *would* combine +it with the background, so that's what you should probably do): + + if (color_type & PNG_COLOR_MASK_ALPHA) + png_set_strip_alpha(png_ptr); + +In PNG files, the alpha channel in an image +is the level of opacity. If you need the alpha channel in an image to +be the level of transparency instead of opacity, you can invert the +alpha channel (or the tRNS chunk data) after it's read, so that 0 is +fully opaque and 255 (in 8-bit or paletted images) or 65535 (in 16-bit +images) is fully transparent, with + + png_set_invert_alpha(png_ptr); + +The PNG format only supports pixels with postmultiplied alpha. +If you want to replace the pixels, after reading them, with pixels +that have premultiplied color samples, you can do this with + + png_set_premultiply_alpha(png_ptr); + +If you do this, any input with a tRNS chunk will be expanded to +have an alpha channel. + +PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as +they can, resulting in, for example, 8 pixels per byte for 1 bit +files. This code expands to 1 pixel per byte without changing the +values of the pixels: + + if (bit_depth < 8) + png_set_packing(png_ptr); + +PNG files have possible bit depths of 1, 2, 4, 8, and 16. All pixels +stored in a PNG image have been "scaled" or "shifted" up to the next +higher possible bit depth (e.g. from 5 bits/sample in the range [0,31] +to 8 bits/sample in the range [0, 255]). However, it is also possible +to convert the PNG pixel data back to the original bit depth of the +image. This call reduces the pixels back down to the original bit depth: + + png_color_8p sig_bit; + + if (png_get_sBIT(png_ptr, info_ptr, &sig_bit)) + png_set_shift(png_ptr, sig_bit); + +PNG files store 3-color pixels in red, green, blue order. This code +changes the storage of the pixels to blue, green, red: + + if (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) + png_set_bgr(png_ptr); + +PNG files store RGB pixels packed into 3 or 6 bytes. This code expands them +into 4 or 8 bytes for windowing systems that need them in this format: + + if (color_type == PNG_COLOR_TYPE_RGB) + png_set_filler(png_ptr, filler, PNG_FILLER_BEFORE); + +where "filler" is the 8 or 16-bit number to fill with, and the location is +either PNG_FILLER_BEFORE or PNG_FILLER_AFTER, depending upon whether +you want the filler before the RGB or after. This transformation +does not affect images that already have full alpha channels. To add an +opaque alpha channel, use filler=0xff or 0xffff and PNG_FILLER_AFTER which +will generate RGBA pixels. + +Note that png_set_filler() does not change the color type. If you want +to do that, you can add a true alpha channel with + + if (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_GRAY) + png_set_add_alpha(png_ptr, filler, PNG_FILLER_AFTER); + +where "filler" contains the alpha value to assign to each pixel. +This function was added in libpng-1.2.7. + +If you are reading an image with an alpha channel, and you need the +data as ARGB instead of the normal PNG format RGBA: + + if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) + png_set_swap_alpha(png_ptr); + +For some uses, you may want a grayscale image to be represented as +RGB. This code will do that conversion: + + if (color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png_ptr); + +Conversely, you can convert an RGB or RGBA image to grayscale or grayscale +with alpha. + + if (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) + png_set_rgb_to_gray_fixed(png_ptr, error_action, + int red_weight, int green_weight); + + error_action = 1: silently do the conversion + error_action = 2: issue a warning if the original + image has any pixel where + red != green or red != blue + error_action = 3: issue an error and abort the + conversion if the original + image has any pixel where + red != green or red != blue + + red_weight: weight of red component times 100000 + green_weight: weight of green component times 100000 + If either weight is negative, default + weights (21268, 71514) are used. + +If you have set error_action = 1 or 2, you can +later check whether the image really was gray, after processing +the image rows, with the png_get_rgb_to_gray_status(png_ptr) function. +It will return a png_byte that is zero if the image was gray or +1 if there were any non-gray pixels. bKGD and sBIT data +will be silently converted to grayscale, using the green channel +data, regardless of the error_action setting. + +With red_weight+green_weight<=100000, +the normalized graylevel is computed: + + int rw = red_weight * 65536; + int gw = green_weight * 65536; + int bw = 65536 - (rw + gw); + gray = (rw*red + gw*green + bw*blue)/65536; + +The default values approximate those recommended in the Charles +Poynton's Color FAQ, <http://www.inforamp.net/~poynton/> +Copyright (c) 1998-01-04 Charles Poynton <poynton at inforamp.net> + + Y = 0.212671 * R + 0.715160 * G + 0.072169 * B + +Libpng approximates this with + + Y = 0.21268 * R + 0.7151 * G + 0.07217 * B + +which can be expressed with integers as + + Y = (6969 * R + 23434 * G + 2365 * B)/32768 + +The calculation is done in a linear colorspace, if the image gamma +is known. + +If you have a grayscale and you are using png_set_expand_depth(), +png_set_expand(), or png_set_gray_to_rgb to change to truecolor or to +a higher bit-depth, you must either supply the background color as a gray +value at the original file bit-depth (need_expand = 1) or else supply the +background color as an RGB triplet at the final, expanded bit depth +(need_expand = 0). Similarly, if you are reading a paletted image, you +must either supply the background color as a palette index (need_expand = 1) +or as an RGB triplet that may or may not be in the palette (need_expand = 0). + + png_color_16 my_background; + png_color_16p image_background; + + if (png_get_bKGD(png_ptr, info_ptr, &image_background)) + png_set_background(png_ptr, image_background, + PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); + else + png_set_background(png_ptr, &my_background, + PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); + +The png_set_background() function tells libpng to composite images +with alpha or simple transparency against the supplied background +color. If the PNG file contains a bKGD chunk (PNG_INFO_bKGD valid), +you may use this color, or supply another color more suitable for +the current display (e.g., the background color from a web page). You +need to tell libpng whether the color is in the gamma space of the +display (PNG_BACKGROUND_GAMMA_SCREEN for colors you supply), the file +(PNG_BACKGROUND_GAMMA_FILE for colors from the bKGD chunk), or one +that is neither of these gammas (PNG_BACKGROUND_GAMMA_UNIQUE - I don't +know why anyone would use this, but it's here). + +To properly display PNG images on any kind of system, the application needs +to know what the display gamma is. Ideally, the user will know this, and +the application will allow them to set it. One method of allowing the user +to set the display gamma separately for each system is to check for a +SCREEN_GAMMA or DISPLAY_GAMMA environment variable, which will hopefully be +correctly set. + +Note that display_gamma is the overall gamma correction required to produce +pleasing results, which depends on the lighting conditions in the surrounding +environment. In a dim or brightly lit room, no compensation other than +the physical gamma exponent of the monitor is needed, while in a dark room +a slightly smaller exponent is better. + + double gamma, screen_gamma; + + if (/* We have a user-defined screen + gamma value */) + { + screen_gamma = user_defined_screen_gamma; + } + /* One way that applications can share the same + screen gamma value */ + else if ((gamma_str = getenv("SCREEN_GAMMA")) + != NULL) + { + screen_gamma = (double)atof(gamma_str); + } + /* If we don't have another value */ + else + { + screen_gamma = 2.2; /* A good guess for a + PC monitor in a bright office or a dim room */ + screen_gamma = 2.0; /* A good guess for a + PC monitor in a dark room */ + screen_gamma = 1.7 or 1.0; /* A good + guess for Mac systems */ + } + +The png_set_gamma() function handles gamma transformations of the data. +Pass both the file gamma and the current screen_gamma. If the file does +not have a gamma value, you can pass one anyway if you have an idea what +it is (usually 0.45455 is a good guess for GIF images on PCs). Note +that file gammas are inverted from screen gammas. See the discussions +on gamma in the PNG specification for an excellent description of what +gamma is, and why all applications should support it. It is strongly +recommended that PNG viewers support gamma correction. + + if (png_get_gAMA(png_ptr, info_ptr, &gamma)) + png_set_gamma(png_ptr, screen_gamma, gamma); + else + png_set_gamma(png_ptr, screen_gamma, 0.45455); + +If you need to reduce an RGB file to a paletted file, or if a paletted +file has more entries then will fit on your screen, png_set_dither() +will do that. Note that this is a simple match dither that merely +finds the closest color available. This should work fairly well with +optimized palettes, and fairly badly with linear color cubes. If you +pass a palette that is larger then maximum_colors, the file will +reduce the number of colors in the palette so it will fit into +maximum_colors. If there is a histogram, it will use it to make +more intelligent choices when reducing the palette. If there is no +histogram, it may not do as good a job. + + if (color_type & PNG_COLOR_MASK_COLOR) + { + if (png_get_valid(png_ptr, info_ptr, + PNG_INFO_PLTE)) + { + png_uint_16p histogram = NULL; + + png_get_hIST(png_ptr, info_ptr, + &histogram); + png_set_dither(png_ptr, palette, num_palette, + max_screen_colors, histogram, 1); + } + else + { + png_color std_color_cube[MAX_SCREEN_COLORS] = + { ... colors ... }; + + png_set_dither(png_ptr, std_color_cube, + MAX_SCREEN_COLORS, MAX_SCREEN_COLORS, + NULL,0); + } + } + +PNG files describe monochrome as black being zero and white being one. +The following code will reverse this (make black be one and white be +zero): + + if (bit_depth == 1 && color_type == PNG_COLOR_TYPE_GRAY) + png_set_invert_mono(png_ptr); + +This function can also be used to invert grayscale and gray-alpha images: + + if (color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_invert_mono(png_ptr); + +PNG files store 16 bit pixels in network byte order (big-endian, +ie. most significant bits first). This code changes the storage to the +other way (little-endian, i.e. least significant bits first, the +way PCs store them): + + if (bit_depth == 16) + png_set_swap(png_ptr); + +If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you +need to change the order the pixels are packed into bytes, you can use: + + if (bit_depth < 8) + png_set_packswap(png_ptr); + +Finally, you can write your own transformation function if none of +the existing ones meets your needs. This is done by setting a callback +with + + png_set_read_user_transform_fn(png_ptr, + read_transform_fn); + +You must supply the function + + void read_transform_fn(png_ptr ptr, row_info_ptr + row_info, png_bytep data) + +See pngtest.c for a working example. Your function will be called +after all of the other transformations have been processed. + +You can also set up a pointer to a user structure for use by your +callback function, and you can inform libpng that your transform +function will change the number of channels or bit depth with the +function + + png_set_user_transform_info(png_ptr, user_ptr, + user_depth, user_channels); + +The user's application, not libpng, is responsible for allocating and +freeing any memory required for the user structure. + +You can retrieve the pointer via the function +png_get_user_transform_ptr(). For example: + + voidp read_user_transform_ptr = + png_get_user_transform_ptr(png_ptr); + +The last thing to handle is interlacing; this is covered in detail below, +but you must call the function here if you want libpng to handle expansion +of the interlaced image. + + number_of_passes = png_set_interlace_handling(png_ptr); + +After setting the transformations, libpng can update your png_info +structure to reflect any transformations you've requested with this +call. This is most useful to update the info structure's rowbytes +field so you can use it to allocate your image memory. This function +will also update your palette with the correct screen_gamma and +background if these have been given with the calls above. + + png_read_update_info(png_ptr, info_ptr); + +After you call png_read_update_info(), you can allocate any +memory you need to hold the image. The row data is simply +raw byte data for all forms of images. As the actual allocation +varies among applications, no example will be given. If you +are allocating one large chunk, you will need to build an +array of pointers to each row, as it will be needed for some +of the functions below. + +.SS Reading image data + +After you've allocated memory, you can read the image data. +The simplest way to do this is in one function call. If you are +allocating enough memory to hold the whole image, you can just +call png_read_image() and libpng will read in all the image data +and put it in the memory area supplied. You will need to pass in +an array of pointers to each row. + +This function automatically handles interlacing, so you don't need +to call png_set_interlace_handling() or call this function multiple +times, or any of that other stuff necessary with png_read_rows(). + + png_read_image(png_ptr, row_pointers); + +where row_pointers is: + + png_bytep row_pointers[height]; + +You can point to void or char or whatever you use for pixels. + +If you don't want to read in the whole image at once, you can +use png_read_rows() instead. If there is no interlacing (check +interlace_type == PNG_INTERLACE_NONE), this is simple: + + png_read_rows(png_ptr, row_pointers, NULL, + number_of_rows); + +where row_pointers is the same as in the png_read_image() call. + +If you are doing this just one row at a time, you can do this with +a single row_pointer instead of an array of row_pointers: + + png_bytep row_pointer = row; + png_read_row(png_ptr, row_pointer, NULL); + +If the file is interlaced (interlace_type != 0 in the IHDR chunk), things +get somewhat harder. The only current (PNG Specification version 1.2) +interlacing type for PNG is (interlace_type == PNG_INTERLACE_ADAM7) +is a somewhat complicated 2D interlace scheme, known as Adam7, that +breaks down an image into seven smaller images of varying size, based +on an 8x8 grid. + +libpng can fill out those images or it can give them to you "as is". +If you want them filled out, there are two ways to do that. The one +mentioned in the PNG specification is to expand each pixel to cover +those pixels that have not been read yet (the "rectangle" method). +This results in a blocky image for the first pass, which gradually +smooths out as more pixels are read. The other method is the "sparkle" +method, where pixels are drawn only in their final locations, with the +rest of the image remaining whatever colors they were initialized to +before the start of the read. The first method usually looks better, +but tends to be slower, as there are more pixels to put in the rows. + +If you don't want libpng to handle the interlacing details, just call +png_read_rows() seven times to read in all seven images. Each of the +images is a valid image by itself, or they can all be combined on an +8x8 grid to form a single image (although if you intend to combine them +you would be far better off using the libpng interlace handling). + +The first pass will return an image 1/8 as wide as the entire image +(every 8th column starting in column 0) and 1/8 as high as the original +(every 8th row starting in row 0), the second will be 1/8 as wide +(starting in column 4) and 1/8 as high (also starting in row 0). The +third pass will be 1/4 as wide (every 4th pixel starting in column 0) and +1/8 as high (every 8th row starting in row 4), and the fourth pass will +be 1/4 as wide and 1/4 as high (every 4th column starting in column 2, +and every 4th row starting in row 0). The fifth pass will return an +image 1/2 as wide, and 1/4 as high (starting at column 0 and row 2), +while the sixth pass will be 1/2 as wide and 1/2 as high as the original +(starting in column 1 and row 0). The seventh and final pass will be as +wide as the original, and 1/2 as high, containing all of the odd +numbered scanlines. Phew! + +If you want libpng to expand the images, call this before calling +png_start_read_image() or png_read_update_info(): + + if (interlace_type == PNG_INTERLACE_ADAM7) + number_of_passes + = png_set_interlace_handling(png_ptr); + +This will return the number of passes needed. Currently, this +is seven, but may change if another interlace type is added. +This function can be called even if the file is not interlaced, +where it will return one pass. + +If you are not going to display the image after each pass, but are +going to wait until the entire image is read in, use the sparkle +effect. This effect is faster and the end result of either method +is exactly the same. If you are planning on displaying the image +after each pass, the "rectangle" effect is generally considered the +better looking one. + +If you only want the "sparkle" effect, just call png_read_rows() as +normal, with the third parameter NULL. Make sure you make pass over +the image number_of_passes times, and you don't change the data in the +rows between calls. You can change the locations of the data, just +not the data. Each pass only writes the pixels appropriate for that +pass, and assumes the data from previous passes is still valid. + + png_read_rows(png_ptr, row_pointers, NULL, + number_of_rows); + +If you only want the first effect (the rectangles), do the same as +before except pass the row buffer in the third parameter, and leave +the second parameter NULL. + + png_read_rows(png_ptr, NULL, row_pointers, + number_of_rows); + +.SS Finishing a sequential read + +After you are finished reading the image through the +low-level interface, you can finish reading the file. If you are +interested in comments or time, which may be stored either before or +after the image data, you should pass the separate png_info struct if +you want to keep the comments from before and after the image +separate. If you are not interested, you can pass NULL. + + png_read_end(png_ptr, end_info); + +When you are done, you can free all memory allocated by libpng like this: + + png_destroy_read_struct(&png_ptr, &info_ptr, + &end_info); + +It is also possible to individually free the info_ptr members that +point to libpng-allocated storage with the following function: + + png_free_data(png_ptr, info_ptr, mask, seq) + mask - identifies data to be freed, a mask + containing the bitwise OR of one or + more of + PNG_FREE_PLTE, PNG_FREE_TRNS, + PNG_FREE_HIST, PNG_FREE_ICCP, + PNG_FREE_PCAL, PNG_FREE_ROWS, + PNG_FREE_SCAL, PNG_FREE_SPLT, + PNG_FREE_TEXT, PNG_FREE_UNKN, + or simply PNG_FREE_ALL + seq - sequence number of item to be freed + (-1 for all items) + +This function may be safely called when the relevant storage has +already been freed, or has not yet been allocated, or was allocated +by the user and not by libpng, and will in those cases do nothing. +The "seq" parameter is ignored if only one item of the selected data +type, such as PLTE, is allowed. If "seq" is not -1, and multiple items +are allowed for the data type identified in the mask, such as text or +sPLT, only the n'th item in the structure is freed, where n is "seq". + +The default behavior is only to free data that was allocated internally +by libpng. This can be changed, so that libpng will not free the data, +or so that it will free data that was allocated by the user with png_malloc() +or png_zalloc() and passed in via a png_set_*() function, with + + png_data_freer(png_ptr, info_ptr, freer, mask) + mask - which data elements are affected + same choices as in png_free_data() + freer - one of + PNG_DESTROY_WILL_FREE_DATA + PNG_SET_WILL_FREE_DATA + PNG_USER_WILL_FREE_DATA + +This function only affects data that has already been allocated. +You can call this function after reading the PNG data but before calling +any png_set_*() functions, to control whether the user or the png_set_*() +function is responsible for freeing any existing data that might be present, +and again after the png_set_*() functions to control whether the user +or png_destroy_*() is supposed to free the data. When the user assumes +responsibility for libpng-allocated data, the application must use +png_free() to free it, and when the user transfers responsibility to libpng +for data that the user has allocated, the user must have used png_malloc() +or png_zalloc() to allocate it. + +If you allocated your row_pointers in a single block, as suggested above in +the description of the high level read interface, you must not transfer +responsibility for freeing it to the png_set_rows or png_read_destroy function, +because they would also try to free the individual row_pointers[i]. + +If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword +separately, do not transfer responsibility for freeing text_ptr to libpng, +because when libpng fills a png_text structure it combines these members with +the key member, and png_free_data() will free only text_ptr.key. Similarly, +if you transfer responsibility for free'ing text_ptr from libpng to your +application, your application must not separately free those members. + +The png_free_data() function will turn off the "valid" flag for anything +it frees. If you need to turn the flag off for a chunk that was freed by +your application instead of by libpng, you can use + + png_set_invalid(png_ptr, info_ptr, mask); + mask - identifies the chunks to be made invalid, + containing the bitwise OR of one or + more of + PNG_INFO_gAMA, PNG_INFO_sBIT, + PNG_INFO_cHRM, PNG_INFO_PLTE, + PNG_INFO_tRNS, PNG_INFO_bKGD, + PNG_INFO_hIST, PNG_INFO_pHYs, + PNG_INFO_oFFs, PNG_INFO_tIME, + PNG_INFO_pCAL, PNG_INFO_sRGB, + PNG_INFO_iCCP, PNG_INFO_sPLT, + PNG_INFO_sCAL, PNG_INFO_IDAT + +For a more compact example of reading a PNG image, see the file example.c. + +.SS Reading PNG files progressively + +The progressive reader is slightly different then the non-progressive +reader. Instead of calling png_read_info(), png_read_rows(), and +png_read_end(), you make one call to png_process_data(), which calls +callbacks when it has the info, a row, or the end of the image. You +set up these callbacks with png_set_progressive_read_fn(). You don't +have to worry about the input/output functions of libpng, as you are +giving the library the data directly in png_process_data(). I will +assume that you have read the section on reading PNG files above, +so I will only highlight the differences (although I will show +all of the code). + +png_structp png_ptr; +png_infop info_ptr; + + /* An example code fragment of how you would + initialize the progressive reader in your + application. */ + int + initialize_png_reader() + { + png_ptr = png_create_read_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn); + if (!png_ptr) + return (ERROR); + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_read_struct(&png_ptr, (png_infopp)NULL, + (png_infopp)NULL); + return (ERROR); + } + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + return (ERROR); + } + + /* This one's new. You can provide functions + to be called when the header info is valid, + when each row is completed, and when the image + is finished. If you aren't using all functions, + you can specify NULL parameters. Even when all + three functions are NULL, you need to call + png_set_progressive_read_fn(). You can use + any struct as the user_ptr (cast to a void pointer + for the function call), and retrieve the pointer + from inside the callbacks using the function + + png_get_progressive_ptr(png_ptr); + + which will return a void pointer, which you have + to cast appropriately. + */ + png_set_progressive_read_fn(png_ptr, (void *)user_ptr, + info_callback, row_callback, end_callback); + + return 0; + } + + /* A code fragment that you call as you receive blocks + of data */ + int + process_data(png_bytep buffer, png_uint_32 length) + { + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + return (ERROR); + } + + /* This one's new also. Simply give it a chunk + of data from the file stream (in order, of + course). On machines with segmented memory + models machines, don't give it any more than + 64K. The library seems to run fine with sizes + of 4K. Although you can give it much less if + necessary (I assume you can give it chunks of + 1 byte, I haven't tried less then 256 bytes + yet). When this function returns, you may + want to display any rows that were generated + in the row callback if you don't already do + so there. + */ + png_process_data(png_ptr, info_ptr, buffer, length); + return 0; + } + + /* This function is called (as set by + png_set_progressive_read_fn() above) when enough data + has been supplied so all of the header has been + read. + */ + void + info_callback(png_structp png_ptr, png_infop info) + { + /* Do any setup here, including setting any of + the transformations mentioned in the Reading + PNG files section. For now, you _must_ call + either png_start_read_image() or + png_read_update_info() after all the + transformations are set (even if you don't set + any). You may start getting rows before + png_process_data() returns, so this is your + last chance to prepare for that. + */ + } + + /* This function is called when each row of image + data is complete */ + void + row_callback(png_structp png_ptr, png_bytep new_row, + png_uint_32 row_num, int pass) + { + /* If the image is interlaced, and you turned + on the interlace handler, this function will + be called for every row in every pass. Some + of these rows will not be changed from the + previous pass. When the row is not changed, + the new_row variable will be NULL. The rows + and passes are called in order, so you don't + really need the row_num and pass, but I'm + supplying them because it may make your life + easier. + + For the non-NULL rows of interlaced images, + you must call png_progressive_combine_row() + passing in the row and the old row. You can + call this function for NULL rows (it will just + return) and for non-interlaced images (it just + does the memcpy for you) if it will make the + code easier. Thus, you can just do this for + all cases: + */ + + png_progressive_combine_row(png_ptr, old_row, + new_row); + + /* where old_row is what was displayed for + previously for the row. Note that the first + pass (pass == 0, really) will completely cover + the old row, so the rows do not have to be + initialized. After the first pass (and only + for interlaced images), you will have to pass + the current row, and the function will combine + the old row and the new row. + */ + } + + void + end_callback(png_structp png_ptr, png_infop info) + { + /* This function is called after the whole image + has been read, including any chunks after the + image (up to and including the IEND). You + will usually have the same info chunk as you + had in the header, although some data may have + been added to the comments and time fields. + + Most people won't do much here, perhaps setting + a flag that marks the image as finished. + */ + } + + + +.SH IV. Writing + +Much of this is very similar to reading. However, everything of +importance is repeated here, so you won't have to constantly look +back up in the reading section to understand writing. + +.SS Setup + +You will want to do the I/O initialization before you get into libpng, +so if it doesn't work, you don't have anything to undo. If you are not +using the standard I/O functions, you will need to replace them with +custom writing functions. See the discussion under Customizing libpng. + + FILE *fp = fopen(file_name, "wb"); + if (!fp) + { + return (ERROR); + } + +Next, png_struct and png_info need to be allocated and initialized. +As these can be both relatively large, you may not want to store these +on the stack, unless you have stack space to spare. Of course, you +will want to check if they return NULL. If you are also reading, +you won't want to name your read structure and your write structure +both "png_ptr"; you can call them anything you like, such as +"read_ptr" and "write_ptr". Look at pngtest.c, for example. + + png_structp png_ptr = png_create_write_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn); + if (!png_ptr) + return (ERROR); + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_write_struct(&png_ptr, + (png_infopp)NULL); + return (ERROR); + } + +If you want to use your own memory allocation routines, +define PNG_USER_MEM_SUPPORTED and use +png_create_write_struct_2() instead of png_create_write_struct(): + + png_structp png_ptr = png_create_write_struct_2 + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn, (png_voidp) + user_mem_ptr, user_malloc_fn, user_free_fn); + +After you have these structures, you will need to set up the +error handling. When libpng encounters an error, it expects to +longjmp() back to your routine. Therefore, you will need to call +setjmp() and pass the png_jmpbuf(png_ptr). If you +write the file from different routines, you will need to update +the png_jmpbuf(png_ptr) every time you enter a new routine that will +call a png_*() function. See your documentation of setjmp/longjmp +for your compiler for more information on setjmp/longjmp. See +the discussion on libpng error handling in the Customizing Libpng +section below for more information on the libpng error handling. + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(fp); + return (ERROR); + } + ... + return; + +If you would rather avoid the complexity of setjmp/longjmp issues, +you can compile libpng with PNG_SETJMP_NOT_SUPPORTED, in which case +errors will result in a call to PNG_ABORT() which defaults to abort(). + +Now you need to set up the output code. The default for libpng is to +use the C function fwrite(). If you use this, you will need to pass a +valid FILE * in the function png_init_io(). Be sure that the file is +opened in binary mode. Again, if you wish to handle writing data in +another way, see the discussion on libpng I/O handling in the Customizing +Libpng section below. + + png_init_io(png_ptr, fp); + +If you are embedding your PNG into a datastream such as MNG, and don't +want libpng to write the 8-byte signature, or if you have already +written the signature in your application, use + + png_set_sig_bytes(png_ptr, 8); + +to inform libpng that it should not write a signature. + +.SS Write callbacks + +At this point, you can set up a callback function that will be +called after each row has been written, which you can use to control +a progress meter or the like. It's demonstrated in pngtest.c. +You must supply a function + + void write_row_callback(png_ptr, png_uint_32 row, + int pass); + { + /* put your code here */ + } + +(You can give it another name that you like instead of "write_row_callback") + +To inform libpng about your function, use + + png_set_write_status_fn(png_ptr, write_row_callback); + +You now have the option of modifying how the compression library will +run. The following functions are mainly for testing, but may be useful +in some cases, like if you need to write PNG files extremely fast and +are willing to give up some compression, or if you want to get the +maximum possible compression at the expense of slower writing. If you +have no special needs in this area, let the library do what it wants by +not calling this function at all, as it has been tuned to deliver a good +speed/compression ratio. The second parameter to png_set_filter() is +the filter method, for which the only valid values are 0 (as of the +July 1999 PNG specification, version 1.2) or 64 (if you are writing +a PNG datastream that is to be embedded in a MNG datastream). The third +parameter is a flag that indicates which filter type(s) are to be tested +for each scanline. See the PNG specification for details on the specific +filter types. + + + /* turn on or off filtering, and/or choose + specific filters. You can use either a single + PNG_FILTER_VALUE_NAME or the bitwise OR of one + or more PNG_FILTER_NAME masks. */ + png_set_filter(png_ptr, 0, + PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE | + PNG_FILTER_SUB | PNG_FILTER_VALUE_SUB | + PNG_FILTER_UP | PNG_FILTER_VALUE_UP | + PNG_FILTER_AVG | PNG_FILTER_VALUE_AVG | + PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH| + PNG_ALL_FILTERS); + +If an application +wants to start and stop using particular filters during compression, +it should start out with all of the filters (to ensure that the previous +row of pixels will be stored in case it's needed later), and then add +and remove them after the start of compression. + +If you are writing a PNG datastream that is to be embedded in a MNG +datastream, the second parameter can be either 0 or 64. + +The png_set_compression_*() functions interface to the zlib compression +library, and should mostly be ignored unless you really know what you are +doing. The only generally useful call is png_set_compression_level() +which changes how much time zlib spends on trying to compress the image +data. See the Compression Library (zlib.h and algorithm.txt, distributed +with zlib) for details on the compression levels. + + /* set the zlib compression level */ + png_set_compression_level(png_ptr, + Z_BEST_COMPRESSION); + + /* set other zlib parameters */ + png_set_compression_mem_level(png_ptr, 8); + png_set_compression_strategy(png_ptr, + Z_DEFAULT_STRATEGY); + png_set_compression_window_bits(png_ptr, 15); + png_set_compression_method(png_ptr, 8); + png_set_compression_buffer_size(png_ptr, 8192) + +extern PNG_EXPORT(void,png_set_zbuf_size) + +.SS Setting the contents of info for output + +You now need to fill in the png_info structure with all the data you +wish to write before the actual image. Note that the only thing you +are allowed to write after the image is the text chunks and the time +chunk (as of PNG Specification 1.2, anyway). See png_write_end() and +the latest PNG specification for more information on that. If you +wish to write them before the image, fill them in now, and flag that +data as being valid. If you want to wait until after the data, don't +fill them until png_write_end(). For all the fields in png_info and +their data types, see png.h. For explanations of what the fields +contain, see the PNG specification. + +Some of the more important parts of the png_info are: + + png_set_IHDR(png_ptr, info_ptr, width, height, + bit_depth, color_type, interlace_type, + compression_type, filter_method) + width - holds the width of the image + in pixels (up to 2^31). + height - holds the height of the image + in pixels (up to 2^31). + bit_depth - holds the bit depth of one of the + image channels. + (valid values are 1, 2, 4, 8, 16 + and depend also on the + color_type. See also significant + bits (sBIT) below). + color_type - describes which color/alpha + channels are present. + PNG_COLOR_TYPE_GRAY + (bit depths 1, 2, 4, 8, 16) + PNG_COLOR_TYPE_GRAY_ALPHA + (bit depths 8, 16) + PNG_COLOR_TYPE_PALETTE + (bit depths 1, 2, 4, 8) + PNG_COLOR_TYPE_RGB + (bit_depths 8, 16) + PNG_COLOR_TYPE_RGB_ALPHA + (bit_depths 8, 16) + + PNG_COLOR_MASK_PALETTE + PNG_COLOR_MASK_COLOR + PNG_COLOR_MASK_ALPHA + + interlace_type - PNG_INTERLACE_NONE or + PNG_INTERLACE_ADAM7 + compression_type - (must be + PNG_COMPRESSION_TYPE_DEFAULT) + filter_method - (must be PNG_FILTER_TYPE_DEFAULT + or, if you are writing a PNG to + be embedded in a MNG datastream, + can also be + PNG_INTRAPIXEL_DIFFERENCING) + +If you call png_set_IHDR(), the call must appear before any of the +other png_set_*() functions, because they might require access to some of +the IHDR settings. The remaining png_set_*() functions can be called +in any order. + +If you wish, you can reset the compression_type, interlace_type, or +filter_method later by calling png_set_IHDR() again; if you do this, the +width, height, bit_depth, and color_type must be the same in each call. + + png_set_PLTE(png_ptr, info_ptr, palette, + num_palette); + palette - the palette for the file + (array of png_color) + num_palette - number of entries in the palette + + png_set_gAMA(png_ptr, info_ptr, gamma); + gamma - the gamma the image was created + at (PNG_INFO_gAMA) + + png_set_sRGB(png_ptr, info_ptr, srgb_intent); + srgb_intent - the rendering intent + (PNG_INFO_sRGB) The presence of + the sRGB chunk means that the pixel + data is in the sRGB color space. + This chunk also implies specific + values of gAMA and cHRM. Rendering + intent is the CSS-1 property that + has been defined by the International + Color Consortium + (http://www.color.org). + It can be one of + PNG_sRGB_INTENT_SATURATION, + PNG_sRGB_INTENT_PERCEPTUAL, + PNG_sRGB_INTENT_ABSOLUTE, or + PNG_sRGB_INTENT_RELATIVE. + + + png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, + srgb_intent); + srgb_intent - the rendering intent + (PNG_INFO_sRGB) The presence of the + sRGB chunk means that the pixel + data is in the sRGB color space. + This function also causes gAMA and + cHRM chunks with the specific values + that are consistent with sRGB to be + written. + + png_set_iCCP(png_ptr, info_ptr, name, compression_type, + profile, proflen); + name - The profile name. + compression - The compression type; always + PNG_COMPRESSION_TYPE_BASE for PNG 1.0. + You may give NULL to this argument to + ignore it. + profile - International Color Consortium color + profile data. May contain NULs. + proflen - length of profile data in bytes. + + png_set_sBIT(png_ptr, info_ptr, sig_bit); + sig_bit - the number of significant bits for + (PNG_INFO_sBIT) each of the gray, red, + green, and blue channels, whichever are + appropriate for the given color type + (png_color_16) + + png_set_tRNS(png_ptr, info_ptr, trans, num_trans, + trans_values); + trans - array of transparent + entries for palette (PNG_INFO_tRNS) + trans_values - graylevel or color sample values + (in order red, green, blue) of the + single transparent color for + non-paletted images (PNG_INFO_tRNS) + num_trans - number of transparent entries + (PNG_INFO_tRNS) + + png_set_hIST(png_ptr, info_ptr, hist); + (PNG_INFO_hIST) + hist - histogram of palette (array of + png_uint_16) + + png_set_tIME(png_ptr, info_ptr, mod_time); + mod_time - time image was last modified + (PNG_VALID_tIME) + + png_set_bKGD(png_ptr, info_ptr, background); + background - background color (PNG_VALID_bKGD) + + png_set_text(png_ptr, info_ptr, text_ptr, num_text); + text_ptr - array of png_text holding image + comments + text_ptr[i].compression - type of compression used + on "text" PNG_TEXT_COMPRESSION_NONE + PNG_TEXT_COMPRESSION_zTXt + PNG_ITXT_COMPRESSION_NONE + PNG_ITXT_COMPRESSION_zTXt + text_ptr[i].key - keyword for comment. Must contain + 1-79 characters. + text_ptr[i].text - text comments for current + keyword. Can be NULL or empty. + text_ptr[i].text_length - length of text string, + after decompression, 0 for iTXt + text_ptr[i].itxt_length - length of itxt string, + after decompression, 0 for tEXt/zTXt + text_ptr[i].lang - language of comment (NULL or + empty for unknown). + text_ptr[i].translated_keyword - keyword in UTF-8 (NULL + or empty for unknown). + Note that the itxt_length, lang, and lang_key + members of the text_ptr structure only exist + when the library is built with iTXt chunk support. + + num_text - number of comments + + png_set_sPLT(png_ptr, info_ptr, &palette_ptr, + num_spalettes); + palette_ptr - array of png_sPLT_struct structures + to be added to the list of palettes + in the info structure. + num_spalettes - number of palette structures to be + added. + + png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, + unit_type); + offset_x - positive offset from the left + edge of the screen + offset_y - positive offset from the top + edge of the screen + unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER + + png_set_pHYs(png_ptr, info_ptr, res_x, res_y, + unit_type); + res_x - pixels/unit physical resolution + in x direction + res_y - pixels/unit physical resolution + in y direction + unit_type - PNG_RESOLUTION_UNKNOWN, + PNG_RESOLUTION_METER + + png_set_sCAL(png_ptr, info_ptr, unit, width, height) + unit - physical scale units (an integer) + width - width of a pixel in physical scale units + height - height of a pixel in physical scale units + (width and height are doubles) + + png_set_sCAL_s(png_ptr, info_ptr, unit, width, height) + unit - physical scale units (an integer) + width - width of a pixel in physical scale units + height - height of a pixel in physical scale units + (width and height are strings like "2.54") + + png_set_unknown_chunks(png_ptr, info_ptr, &unknowns, + num_unknowns) + unknowns - array of png_unknown_chunk + structures holding unknown chunks + unknowns[i].name - name of unknown chunk + unknowns[i].data - data of unknown chunk + unknowns[i].size - size of unknown chunk's data + unknowns[i].location - position to write chunk in file + 0: do not write chunk + PNG_HAVE_IHDR: before PLTE + PNG_HAVE_PLTE: before IDAT + PNG_AFTER_IDAT: after IDAT + +The "location" member is set automatically according to +what part of the output file has already been written. +You can change its value after calling png_set_unknown_chunks() +as demonstrated in pngtest.c. Within each of the "locations", +the chunks are sequenced according to their position in the +structure (that is, the value of "i", which is the order in which +the chunk was either read from the input file or defined with +png_set_unknown_chunks). + +A quick word about text and num_text. text is an array of png_text +structures. num_text is the number of valid structures in the array. +Each png_text structure holds a language code, a keyword, a text value, +and a compression type. + +The compression types have the same valid numbers as the compression +types of the image data. Currently, the only valid number is zero. +However, you can store text either compressed or uncompressed, unlike +images, which always have to be compressed. So if you don't want the +text compressed, set the compression type to PNG_TEXT_COMPRESSION_NONE. +Because tEXt and zTXt chunks don't have a language field, if you +specify PNG_TEXT_COMPRESSION_NONE or PNG_TEXT_COMPRESSION_zTXt +any language code or translated keyword will not be written out. + +Until text gets around 1000 bytes, it is not worth compressing it. +After the text has been written out to the file, the compression type +is set to PNG_TEXT_COMPRESSION_NONE_WR or PNG_TEXT_COMPRESSION_zTXt_WR, +so that it isn't written out again at the end (in case you are calling +png_write_end() with the same struct. + +The keywords that are given in the PNG Specification are: + + Title Short (one line) title or + caption for image + Author Name of image's creator + Description Description of image (possibly long) + Copyright Copyright notice + Creation Time Time of original image creation + (usually RFC 1123 format, see below) + Software Software used to create the image + Disclaimer Legal disclaimer + Warning Warning of nature of content + Source Device used to create the image + Comment Miscellaneous comment; conversion + from other image format + +The keyword-text pairs work like this. Keywords should be short +simple descriptions of what the comment is about. Some typical +keywords are found in the PNG specification, as is some recommendations +on keywords. You can repeat keywords in a file. You can even write +some text before the image and some after. For example, you may want +to put a description of the image before the image, but leave the +disclaimer until after, so viewers working over modem connections +don't have to wait for the disclaimer to go over the modem before +they start seeing the image. Finally, keywords should be full +words, not abbreviations. Keywords and text are in the ISO 8859-1 +(Latin-1) character set (a superset of regular ASCII) and can not +contain NUL characters, and should not contain control or other +unprintable characters. To make the comments widely readable, stick +with basic ASCII, and avoid machine specific character set extensions +like the IBM-PC character set. The keyword must be present, but +you can leave off the text string on non-compressed pairs. +Compressed pairs must have a text string, as only the text string +is compressed anyway, so the compression would be meaningless. + +PNG supports modification time via the png_time structure. Two +conversion routines are provided, png_convert_from_time_t() for +time_t and png_convert_from_struct_tm() for struct tm. The +time_t routine uses gmtime(). You don't have to use either of +these, but if you wish to fill in the png_time structure directly, +you should provide the time in universal time (GMT) if possible +instead of your local time. Note that the year number is the full +year (e.g. 1998, rather than 98 - PNG is year 2000 compliant!), and +that months start with 1. + +If you want to store the time of the original image creation, you should +use a plain tEXt chunk with the "Creation Time" keyword. This is +necessary because the "creation time" of a PNG image is somewhat vague, +depending on whether you mean the PNG file, the time the image was +created in a non-PNG format, a still photo from which the image was +scanned, or possibly the subject matter itself. In order to facilitate +machine-readable dates, it is recommended that the "Creation Time" +tEXt chunk use RFC 1123 format dates (e.g. "22 May 1997 18:07:10 GMT"), +although this isn't a requirement. Unlike the tIME chunk, the +"Creation Time" tEXt chunk is not expected to be automatically changed +by the software. To facilitate the use of RFC 1123 dates, a function +png_convert_to_rfc1123(png_timep) is provided to convert from PNG +time to an RFC 1123 format string. + +.SS Writing unknown chunks + +You can use the png_set_unknown_chunks function to queue up chunks +for writing. You give it a chunk name, raw data, and a size; that's +all there is to it. The chunks will be written by the next following +png_write_info_before_PLTE, png_write_info, or png_write_end function. +Any chunks previously read into the info structure's unknown-chunk +list will also be written out in a sequence that satisfies the PNG +specification's ordering rules. + +.SS The high-level write interface + +At this point there are two ways to proceed; through the high-level +write interface, or through a sequence of low-level write operations. +You can use the high-level interface if your image data is present +in the info structure. All defined output +transformations are permitted, enabled by the following masks. + + PNG_TRANSFORM_IDENTITY No transformation + PNG_TRANSFORM_PACKING Pack 1, 2 and 4-bit samples + PNG_TRANSFORM_PACKSWAP Change order of packed + pixels to LSB first + PNG_TRANSFORM_INVERT_MONO Invert monochrome images + PNG_TRANSFORM_SHIFT Normalize pixels to the + sBIT depth + PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA + to BGRA + PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA + to AG + PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity + to transparency + PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples + PNG_TRANSFORM_STRIP_FILLER Strip out filler + bytes (deprecated). + PNG_TRANSFORM_STRIP_FILLER_BEFORE Strip out leading + filler bytes + PNG_TRANSFORM_STRIP_FILLER_AFTER Strip out trailing + filler bytes + +If you have valid image data in the info structure (you can use +png_set_rows() to put image data in the info structure), simply do this: + + png_write_png(png_ptr, info_ptr, png_transforms, NULL) + +where png_transforms is an integer containing the bitwise OR of some set of +transformation flags. This call is equivalent to png_write_info(), +followed the set of transformations indicated by the transform mask, +then png_write_image(), and finally png_write_end(). + +(The final parameter of this call is not yet used. Someday it might point +to transformation parameters required by some future output transform.) + +You must use png_transforms and not call any png_set_transform() functions +when you use png_write_png(). + +.SS The low-level write interface + +If you are going the low-level route instead, you are now ready to +write all the file information up to the actual image data. You do +this with a call to png_write_info(). + + png_write_info(png_ptr, info_ptr); + +Note that there is one transformation you may need to do before +png_write_info(). In PNG files, the alpha channel in an image is the +level of opacity. If your data is supplied as a level of transparency, +you can invert the alpha channel before you write it, so that 0 is +fully transparent and 255 (in 8-bit or paletted images) or 65535 +(in 16-bit images) is fully opaque, with + + png_set_invert_alpha(png_ptr); + +This must appear before png_write_info() instead of later with the +other transformations because in the case of paletted images the tRNS +chunk data has to be inverted before the tRNS chunk is written. If +your image is not a paletted image, the tRNS data (which in such cases +represents a single color to be rendered as transparent) won't need to +be changed, and you can safely do this transformation after your +png_write_info() call. + +If you need to write a private chunk that you want to appear before +the PLTE chunk when PLTE is present, you can write the PNG info in +two steps, and insert code to write your own chunk between them: + + png_write_info_before_PLTE(png_ptr, info_ptr); + png_set_unknown_chunks(png_ptr, info_ptr, ...); + png_write_info(png_ptr, info_ptr); + +After you've written the file information, you can set up the library +to handle any special transformations of the image data. The various +ways to transform the data will be described in the order that they +should occur. This is important, as some of these change the color +type and/or bit depth of the data, and some others only work on +certain color types and bit depths. Even though each transformation +checks to see if it has data that it can do something with, you should +make sure to only enable a transformation if it will be valid for the +data. For example, don't swap red and blue on grayscale data. + +PNG files store RGB pixels packed into 3 or 6 bytes. This code tells +the library to strip input data that has 4 or 8 bytes per pixel down +to 3 or 6 bytes (or strip 2 or 4-byte grayscale+filler data to 1 or 2 +bytes per pixel). + + png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); + +where the 0 is unused, and the location is either PNG_FILLER_BEFORE or +PNG_FILLER_AFTER, depending upon whether the filler byte in the pixel +is stored XRGB or RGBX. + +PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as +they can, resulting in, for example, 8 pixels per byte for 1 bit files. +If the data is supplied at 1 pixel per byte, use this code, which will +correctly pack the pixels into a single byte: + + png_set_packing(png_ptr); + +PNG files reduce possible bit depths to 1, 2, 4, 8, and 16. If your +data is of another bit depth, you can write an sBIT chunk into the +file so that decoders can recover the original data if desired. + + /* Set the true bit depth of the image data */ + if (color_type & PNG_COLOR_MASK_COLOR) + { + sig_bit.red = true_bit_depth; + sig_bit.green = true_bit_depth; + sig_bit.blue = true_bit_depth; + } + else + { + sig_bit.gray = true_bit_depth; + } + if (color_type & PNG_COLOR_MASK_ALPHA) + { + sig_bit.alpha = true_bit_depth; + } + + png_set_sBIT(png_ptr, info_ptr, &sig_bit); + +If the data is stored in the row buffer in a bit depth other than +one supported by PNG (e.g. 3 bit data in the range 0-7 for a 4-bit PNG), +this will scale the values to appear to be the correct bit depth as +is required by PNG. + + png_set_shift(png_ptr, &sig_bit); + +PNG files store 16 bit pixels in network byte order (big-endian, +ie. most significant bits first). This code would be used if they are +supplied the other way (little-endian, i.e. least significant bits +first, the way PCs store them): + + if (bit_depth > 8) + png_set_swap(png_ptr); + +If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you +need to change the order the pixels are packed into bytes, you can use: + + if (bit_depth < 8) + png_set_packswap(png_ptr); + +PNG files store 3 color pixels in red, green, blue order. This code +would be used if they are supplied as blue, green, red: + + png_set_bgr(png_ptr); + +PNG files describe monochrome as black being zero and white being +one. This code would be used if the pixels are supplied with this reversed +(black being one and white being zero): + + png_set_invert_mono(png_ptr); + +Finally, you can write your own transformation function if none of +the existing ones meets your needs. This is done by setting a callback +with + + png_set_write_user_transform_fn(png_ptr, + write_transform_fn); + +You must supply the function + + void write_transform_fn(png_ptr ptr, row_info_ptr + row_info, png_bytep data) + +See pngtest.c for a working example. Your function will be called +before any of the other transformations are processed. + +You can also set up a pointer to a user structure for use by your +callback function. + + png_set_user_transform_info(png_ptr, user_ptr, 0, 0); + +The user_channels and user_depth parameters of this function are ignored +when writing; you can set them to zero as shown. + +You can retrieve the pointer via the function png_get_user_transform_ptr(). +For example: + + voidp write_user_transform_ptr = + png_get_user_transform_ptr(png_ptr); + +It is possible to have libpng flush any pending output, either manually, +or automatically after a certain number of lines have been written. To +flush the output stream a single time call: + + png_write_flush(png_ptr); + +and to have libpng flush the output stream periodically after a certain +number of scanlines have been written, call: + + png_set_flush(png_ptr, nrows); + +Note that the distance between rows is from the last time png_write_flush() +was called, or the first row of the image if it has never been called. +So if you write 50 lines, and then png_set_flush 25, it will flush the +output on the next scanline, and every 25 lines thereafter, unless +png_write_flush() is called before 25 more lines have been written. +If nrows is too small (less than about 10 lines for a 640 pixel wide +RGB image) the image compression may decrease noticeably (although this +may be acceptable for real-time applications). Infrequent flushing will +only degrade the compression performance by a few percent over images +that do not use flushing. + +.SS Writing the image data + +That's it for the transformations. Now you can write the image data. +The simplest way to do this is in one function call. If you have the +whole image in memory, you can just call png_write_image() and libpng +will write the image. You will need to pass in an array of pointers to +each row. This function automatically handles interlacing, so you don't +need to call png_set_interlace_handling() or call this function multiple +times, or any of that other stuff necessary with png_write_rows(). + + png_write_image(png_ptr, row_pointers); + +where row_pointers is: + + png_byte *row_pointers[height]; + +You can point to void or char or whatever you use for pixels. + +If you don't want to write the whole image at once, you can +use png_write_rows() instead. If the file is not interlaced, +this is simple: + + png_write_rows(png_ptr, row_pointers, + number_of_rows); + +row_pointers is the same as in the png_write_image() call. + +If you are just writing one row at a time, you can do this with +a single row_pointer instead of an array of row_pointers: + + png_bytep row_pointer = row; + + png_write_row(png_ptr, row_pointer); + +When the file is interlaced, things can get a good deal more complicated. +The only currently (as of the PNG Specification version 1.2, dated July +1999) defined interlacing scheme for PNG files is the "Adam7" interlace +scheme, that breaks down an image into seven smaller images of varying +size. libpng will build these images for you, or you can do them +yourself. If you want to build them yourself, see the PNG specification +for details of which pixels to write when. + +If you don't want libpng to handle the interlacing details, just +use png_set_interlace_handling() and call png_write_rows() the +correct number of times to write all seven sub-images. + +If you want libpng to build the sub-images, call this before you start +writing any rows: + + number_of_passes = + png_set_interlace_handling(png_ptr); + +This will return the number of passes needed. Currently, this is seven, +but may change if another interlace type is added. + +Then write the complete image number_of_passes times. + + png_write_rows(png_ptr, row_pointers, + number_of_rows); + +As some of these rows are not used, and thus return immediately, you may +want to read about interlacing in the PNG specification, and only update +the rows that are actually used. + +.SS Finishing a sequential write + +After you are finished writing the image, you should finish writing +the file. If you are interested in writing comments or time, you should +pass an appropriately filled png_info pointer. If you are not interested, +you can pass NULL. + + png_write_end(png_ptr, info_ptr); + +When you are done, you can free all memory used by libpng like this: + + png_destroy_write_struct(&png_ptr, &info_ptr); + +It is also possible to individually free the info_ptr members that +point to libpng-allocated storage with the following function: + + png_free_data(png_ptr, info_ptr, mask, seq) + mask - identifies data to be freed, a mask + containing the bitwise OR of one or + more of + PNG_FREE_PLTE, PNG_FREE_TRNS, + PNG_FREE_HIST, PNG_FREE_ICCP, + PNG_FREE_PCAL, PNG_FREE_ROWS, + PNG_FREE_SCAL, PNG_FREE_SPLT, + PNG_FREE_TEXT, PNG_FREE_UNKN, + or simply PNG_FREE_ALL + seq - sequence number of item to be freed + (-1 for all items) + +This function may be safely called when the relevant storage has +already been freed, or has not yet been allocated, or was allocated +by the user and not by libpng, and will in those cases do nothing. +The "seq" parameter is ignored if only one item of the selected data +type, such as PLTE, is allowed. If "seq" is not -1, and multiple items +are allowed for the data type identified in the mask, such as text or +sPLT, only the n'th item in the structure is freed, where n is "seq". + +If you allocated data such as a palette that you passed in to libpng +with png_set_*, you must not free it until just before the call to +png_destroy_write_struct(). + +The default behavior is only to free data that was allocated internally +by libpng. This can be changed, so that libpng will not free the data, +or so that it will free data that was allocated by the user with png_malloc() +or png_zalloc() and passed in via a png_set_*() function, with + + png_data_freer(png_ptr, info_ptr, freer, mask) + mask - which data elements are affected + same choices as in png_free_data() + freer - one of + PNG_DESTROY_WILL_FREE_DATA + PNG_SET_WILL_FREE_DATA + PNG_USER_WILL_FREE_DATA + +For example, to transfer responsibility for some data from a read structure +to a write structure, you could use + + png_data_freer(read_ptr, read_info_ptr, + PNG_USER_WILL_FREE_DATA, + PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST) + png_data_freer(write_ptr, write_info_ptr, + PNG_DESTROY_WILL_FREE_DATA, + PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST) + +thereby briefly reassigning responsibility for freeing to the user but +immediately afterwards reassigning it once more to the write_destroy +function. Having done this, it would then be safe to destroy the read +structure and continue to use the PLTE, tRNS, and hIST data in the write +structure. + +This function only affects data that has already been allocated. +You can call this function before calling after the png_set_*() functions +to control whether the user or png_destroy_*() is supposed to free the data. +When the user assumes responsibility for libpng-allocated data, the +application must use +png_free() to free it, and when the user transfers responsibility to libpng +for data that the user has allocated, the user must have used png_malloc() +or png_zalloc() to allocate it. + +If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword +separately, do not transfer responsibility for freeing text_ptr to libpng, +because when libpng fills a png_text structure it combines these members with +the key member, and png_free_data() will free only text_ptr.key. Similarly, +if you transfer responsibility for free'ing text_ptr from libpng to your +application, your application must not separately free those members. +For a more compact example of writing a PNG image, see the file example.c. + +.SH V. Modifying/Customizing libpng: + +There are two issues here. The first is changing how libpng does +standard things like memory allocation, input/output, and error handling. +The second deals with more complicated things like adding new chunks, +adding new transformations, and generally changing how libpng works. +Both of those are compile-time issues; that is, they are generally +determined at the time the code is written, and there is rarely a need +to provide the user with a means of changing them. + +Memory allocation, input/output, and error handling + +All of the memory allocation, input/output, and error handling in libpng +goes through callbacks that are user-settable. The default routines are +in pngmem.c, pngrio.c, pngwio.c, and pngerror.c, respectively. To change +these functions, call the appropriate png_set_*_fn() function. + +Memory allocation is done through the functions png_malloc(), png_calloc(), +and png_free(). These currently just call the standard C functions. +png_calloc() calls png_malloc() and then png_memset() to clear the newly +allocated memory to zero. If your pointers can't access more then 64K +at a time, you will want to set MAXSEG_64K in zlib.h. Since it is +unlikely that the method of handling memory allocation on a platform +will change between applications, these functions must be modified in +the library at compile time. If you prefer to use a different method +of allocating and freeing data, you can use png_create_read_struct_2() or +png_create_write_struct_2() to register your own functions as described +above. These functions also provide a void pointer that can be retrieved +via + + mem_ptr=png_get_mem_ptr(png_ptr); + +Your replacement memory functions must have prototypes as follows: + + png_voidp malloc_fn(png_structp png_ptr, + png_size_t size); + void free_fn(png_structp png_ptr, png_voidp ptr); + +Your malloc_fn() must return NULL in case of failure. The png_malloc() +function will normally call png_error() if it receives a NULL from the +system memory allocator or from your replacement malloc_fn(). + +Your free_fn() will never be called with a NULL ptr, since libpng's +png_free() checks for NULL before calling free_fn(). + +Input/Output in libpng is done through png_read() and png_write(), +which currently just call fread() and fwrite(). The FILE * is stored in +png_struct and is initialized via png_init_io(). If you wish to change +the method of I/O, the library supplies callbacks that you can set +through the function png_set_read_fn() and png_set_write_fn() at run +time, instead of calling the png_init_io() function. These functions +also provide a void pointer that can be retrieved via the function +png_get_io_ptr(). For example: + + png_set_read_fn(png_structp read_ptr, + voidp read_io_ptr, png_rw_ptr read_data_fn) + + png_set_write_fn(png_structp write_ptr, + voidp write_io_ptr, png_rw_ptr write_data_fn, + png_flush_ptr output_flush_fn); + + voidp read_io_ptr = png_get_io_ptr(read_ptr); + voidp write_io_ptr = png_get_io_ptr(write_ptr); + +The replacement I/O functions must have prototypes as follows: + + void user_read_data(png_structp png_ptr, + png_bytep data, png_size_t length); + void user_write_data(png_structp png_ptr, + png_bytep data, png_size_t length); + void user_flush_data(png_structp png_ptr); + +The user_read_data() function is responsible for detecting and +handling end-of-data errors. + +Supplying NULL for the read, write, or flush functions sets them back +to using the default C stream functions, which expect the io_ptr to +point to a standard *FILE structure. It is probably a mistake +to use NULL for one of write_data_fn and output_flush_fn but not both +of them, unless you have built libpng with PNG_NO_WRITE_FLUSH defined. +It is an error to read from a write stream, and vice versa. + +Error handling in libpng is done through png_error() and png_warning(). +Errors handled through png_error() are fatal, meaning that png_error() +should never return to its caller. Currently, this is handled via +setjmp() and longjmp() (unless you have compiled libpng with +PNG_SETJMP_NOT_SUPPORTED, in which case it is handled via PNG_ABORT()), +but you could change this to do things like exit() if you should wish. + +On non-fatal errors, png_warning() is called +to print a warning message, and then control returns to the calling code. +By default png_error() and png_warning() print a message on stderr via +fprintf() unless the library is compiled with PNG_NO_CONSOLE_IO defined +(because you don't want the messages) or PNG_NO_STDIO defined (because +fprintf() isn't available). If you wish to change the behavior of the error +functions, you will need to set up your own message callbacks. These +functions are normally supplied at the time that the png_struct is created. +It is also possible to redirect errors and warnings to your own replacement +functions after png_create_*_struct() has been called by calling: + + png_set_error_fn(png_structp png_ptr, + png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warning_fn); + + png_voidp error_ptr = png_get_error_ptr(png_ptr); + +If NULL is supplied for either error_fn or warning_fn, then the libpng +default function will be used, calling fprintf() and/or longjmp() if a +problem is encountered. The replacement error functions should have +parameters as follows: + + void user_error_fn(png_structp png_ptr, + png_const_charp error_msg); + void user_warning_fn(png_structp png_ptr, + png_const_charp warning_msg); + +The motivation behind using setjmp() and longjmp() is the C++ throw and +catch exception handling methods. This makes the code much easier to write, +as there is no need to check every return code of every function call. +However, there are some uncertainties about the status of local variables +after a longjmp, so the user may want to be careful about doing anything +after setjmp returns non-zero besides returning itself. Consult your +compiler documentation for more details. For an alternative approach, you +may wish to use the "cexcept" facility (see http://cexcept.sourceforge.net). + +.SS Custom chunks + +If you need to read or write custom chunks, you may need to get deeper +into the libpng code. The library now has mechanisms for storing +and writing chunks of unknown type; you can even declare callbacks +for custom chunks. However, this may not be good enough if the +library code itself needs to know about interactions between your +chunk and existing `intrinsic' chunks. + +If you need to write a new intrinsic chunk, first read the PNG +specification. Acquire a first level of understanding of how it works. +Pay particular attention to the sections that describe chunk names, +and look at how other chunks were designed, so you can do things +similarly. Second, check out the sections of libpng that read and +write chunks. Try to find a chunk that is similar to yours and use +it as a template. More details can be found in the comments inside +the code. It is best to handle unknown chunks in a generic method, +via callback functions, instead of by modifying libpng functions. + +If you wish to write your own transformation for the data, look through +the part of the code that does the transformations, and check out some of +the simpler ones to get an idea of how they work. Try to find a similar +transformation to the one you want to add and copy off of it. More details +can be found in the comments inside the code itself. + +.SS Configuring for 16 bit platforms + +You will want to look into zconf.h to tell zlib (and thus libpng) that +it cannot allocate more then 64K at a time. Even if you can, the memory +won't be accessible. So limit zlib and libpng to 64K by defining MAXSEG_64K. + +.SS Configuring for DOS + +For DOS users who only have access to the lower 640K, you will +have to limit zlib's memory usage via a png_set_compression_mem_level() +call. See zlib.h or zconf.h in the zlib library for more information. + +.SS Configuring for Medium Model + +Libpng's support for medium model has been tested on most of the popular +compilers. Make sure MAXSEG_64K gets defined, USE_FAR_KEYWORD gets +defined, and FAR gets defined to far in pngconf.h, and you should be +all set. Everything in the library (except for zlib's structure) is +expecting far data. You must use the typedefs with the p or pp on +the end for pointers (or at least look at them and be careful). Make +note that the rows of data are defined as png_bytepp, which is an +unsigned char far * far *. + +.SS Configuring for gui/windowing platforms: + +You will need to write new error and warning functions that use the GUI +interface, as described previously, and set them to be the error and +warning functions at the time that png_create_*_struct() is called, +in order to have them available during the structure initialization. +They can be changed later via png_set_error_fn(). On some compilers, +you may also have to change the memory allocators (png_malloc, etc.). + +.SS Configuring for compiler xxx: + +All includes for libpng are in pngconf.h. If you need to add, change +or delete an include, this is the place to do it. +The includes that are not needed outside libpng are protected by the +PNG_INTERNAL definition, which is only defined for those routines inside +libpng itself. The files in libpng proper only include png.h, which +includes pngconf.h. + +.SS Configuring zlib: + +There are special functions to configure the compression. Perhaps the +most useful one changes the compression level, which currently uses +input compression values in the range 0 - 9. The library normally +uses the default compression level (Z_DEFAULT_COMPRESSION = 6). Tests +have shown that for a large majority of images, compression values in +the range 3-6 compress nearly as well as higher levels, and do so much +faster. For online applications it may be desirable to have maximum speed +(Z_BEST_SPEED = 1). With versions of zlib after v0.99, you can also +specify no compression (Z_NO_COMPRESSION = 0), but this would create +files larger than just storing the raw bitmap. You can specify the +compression level by calling: + + png_set_compression_level(png_ptr, level); + +Another useful one is to reduce the memory level used by the library. +The memory level defaults to 8, but it can be lowered if you are +short on memory (running DOS, for example, where you only have 640K). +Note that the memory level does have an effect on compression; among +other things, lower levels will result in sections of incompressible +data being emitted in smaller stored blocks, with a correspondingly +larger relative overhead of up to 15% in the worst case. + + png_set_compression_mem_level(png_ptr, level); + +The other functions are for configuring zlib. They are not recommended +for normal use and may result in writing an invalid PNG file. See +zlib.h for more information on what these mean. + + png_set_compression_strategy(png_ptr, + strategy); + png_set_compression_window_bits(png_ptr, + window_bits); + png_set_compression_method(png_ptr, method); + png_set_compression_buffer_size(png_ptr, size); + +.SS Controlling row filtering + +If you want to control whether libpng uses filtering or not, which +filters are used, and how it goes about picking row filters, you +can call one of these functions. The selection and configuration +of row filters can have a significant impact on the size and +encoding speed and a somewhat lesser impact on the decoding speed +of an image. Filtering is enabled by default for RGB and grayscale +images (with and without alpha), but not for paletted images nor +for any images with bit depths less than 8 bits/pixel. + +The 'method' parameter sets the main filtering method, which is +currently only '0' in the PNG 1.2 specification. The 'filters' +parameter sets which filter(s), if any, should be used for each +scanline. Possible values are PNG_ALL_FILTERS and PNG_NO_FILTERS +to turn filtering on and off, respectively. + +Individual filter types are PNG_FILTER_NONE, PNG_FILTER_SUB, +PNG_FILTER_UP, PNG_FILTER_AVG, PNG_FILTER_PAETH, which can be bitwise +ORed together with '|' to specify one or more filters to use. +These filters are described in more detail in the PNG specification. +If you intend to change the filter type during the course of writing +the image, you should start with flags set for all of the filters +you intend to use so that libpng can initialize its internal +structures appropriately for all of the filter types. (Note that this +means the first row must always be adaptively filtered, because libpng +currently does not allocate the filter buffers until png_write_row() +is called for the first time.) + + filters = PNG_FILTER_NONE | PNG_FILTER_SUB + PNG_FILTER_UP | PNG_FILTER_AVG | + PNG_FILTER_PAETH | PNG_ALL_FILTERS; + + png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, + filters); + The second parameter can also be + PNG_INTRAPIXEL_DIFFERENCING if you are + writing a PNG to be embedded in a MNG + datastream. This parameter must be the + same as the value of filter_method used + in png_set_IHDR(). + +It is also possible to influence how libpng chooses from among the +available filters. This is done in one or both of two ways - by +telling it how important it is to keep the same filter for successive +rows, and by telling it the relative computational costs of the filters. + + double weights[3] = {1.5, 1.3, 1.1}, + costs[PNG_FILTER_VALUE_LAST] = + {1.0, 1.3, 1.3, 1.5, 1.7}; + + png_set_filter_heuristics(png_ptr, + PNG_FILTER_HEURISTIC_WEIGHTED, 3, + weights, costs); + +The weights are multiplying factors that indicate to libpng that the +row filter should be the same for successive rows unless another row filter +is that many times better than the previous filter. In the above example, +if the previous 3 filters were SUB, SUB, NONE, the SUB filter could have a +"sum of absolute differences" 1.5 x 1.3 times higher than other filters +and still be chosen, while the NONE filter could have a sum 1.1 times +higher than other filters and still be chosen. Unspecified weights are +taken to be 1.0, and the specified weights should probably be declining +like those above in order to emphasize recent filters over older filters. + +The filter costs specify for each filter type a relative decoding cost +to be considered when selecting row filters. This means that filters +with higher costs are less likely to be chosen over filters with lower +costs, unless their "sum of absolute differences" is that much smaller. +The costs do not necessarily reflect the exact computational speeds of +the various filters, since this would unduly influence the final image +size. + +Note that the numbers above were invented purely for this example and +are given only to help explain the function usage. Little testing has +been done to find optimum values for either the costs or the weights. + +.SS Removing unwanted object code + +There are a bunch of #define's in pngconf.h that control what parts of +libpng are compiled. All the defines end in _SUPPORTED. If you are +never going to use a capability, you can change the #define to #undef +before recompiling libpng and save yourself code and data space, or +you can turn off individual capabilities with defines that begin with +PNG_NO_. + +You can also turn all of the transforms and ancillary chunk capabilities +off en masse with compiler directives that define +PNG_NO_READ[or WRITE]_TRANSFORMS, or PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS, +or all four, +along with directives to turn on any of the capabilities that you do +want. The PNG_NO_READ[or WRITE]_TRANSFORMS directives disable the extra +transformations but still leave the library fully capable of reading +and writing PNG files with all known public chunks. Use of the +PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS directive produces a library +that is incapable of reading or writing ancillary chunks. If you are +not using the progressive reading capability, you can turn that off +with PNG_NO_PROGRESSIVE_READ (don't confuse this with the INTERLACING +capability, which you'll still have). + +All the reading and writing specific code are in separate files, so the +linker should only grab the files it needs. However, if you want to +make sure, or if you are building a stand alone library, all the +reading files start with pngr and all the writing files start with +pngw. The files that don't match either (like png.c, pngtrans.c, etc.) +are used for both reading and writing, and always need to be included. +The progressive reader is in pngpread.c + +If you are creating or distributing a dynamically linked library (a .so +or DLL file), you should not remove or disable any parts of the library, +as this will cause applications linked with different versions of the +library to fail if they call functions not available in your library. +The size of the library itself should not be an issue, because only +those sections that are actually used will be loaded into memory. + +.SS Requesting debug printout + +The macro definition PNG_DEBUG can be used to request debugging +printout. Set it to an integer value in the range 0 to 3. Higher +numbers result in increasing amounts of debugging information. The +information is printed to the "stderr" file, unless another file +name is specified in the PNG_DEBUG_FILE macro definition. + +When PNG_DEBUG > 0, the following functions (macros) become available: + + png_debug(level, message) + png_debug1(level, message, p1) + png_debug2(level, message, p1, p2) + +in which "level" is compared to PNG_DEBUG to decide whether to print +the message, "message" is the formatted string to be printed, +and p1 and p2 are parameters that are to be embedded in the string +according to printf-style formatting directives. For example, + + png_debug1(2, "foo=%d\n", foo); + +is expanded to + + if(PNG_DEBUG > 2) + fprintf(PNG_DEBUG_FILE, "foo=%d\n", foo); + +When PNG_DEBUG is defined but is zero, the macros aren't defined, but you +can still use PNG_DEBUG to control your own debugging: + + #ifdef PNG_DEBUG + fprintf(stderr, ... + #endif + +When PNG_DEBUG = 1, the macros are defined, but only png_debug statements +having level = 0 will be printed. There aren't any such statements in +this version of libpng, but if you insert some they will be printed. + +.SH VI. MNG support + +The MNG specification (available at http://www.libpng.org/pub/mng) allows +certain extensions to PNG for PNG images that are embedded in MNG datastreams. +Libpng can support some of these extensions. To enable them, use the +png_permit_mng_features() function: + + feature_set = png_permit_mng_features(png_ptr, mask) + mask is a png_uint_32 containing the bitwise OR of the + features you want to enable. These include + PNG_FLAG_MNG_EMPTY_PLTE + PNG_FLAG_MNG_FILTER_64 + PNG_ALL_MNG_FEATURES + feature_set is a png_uint_32 that is the bitwise AND of + your mask with the set of MNG features that is + supported by the version of libpng that you are using. + +It is an error to use this function when reading or writing a standalone +PNG file with the PNG 8-byte signature. The PNG datastream must be wrapped +in a MNG datastream. As a minimum, it must have the MNG 8-byte signature +and the MHDR and MEND chunks. Libpng does not provide support for these +or any other MNG chunks; your application must provide its own support for +them. You may wish to consider using libmng (available at +http://www.libmng.com) instead. + +.SH VII. Changes to Libpng from version 0.88 + +It should be noted that versions of libpng later than 0.96 are not +distributed by the original libpng author, Guy Schalnat, nor by +Andreas Dilger, who had taken over from Guy during 1996 and 1997, and +distributed versions 0.89 through 0.96, but rather by another member +of the original PNG Group, Glenn Randers-Pehrson. Guy and Andreas are +still alive and well, but they have moved on to other things. + +The old libpng functions png_read_init(), png_write_init(), +png_info_init(), png_read_destroy(), and png_write_destroy() have been +moved to PNG_INTERNAL in version 0.95 to discourage their use. These +functions will be removed from libpng version 2.0.0. + +The preferred method of creating and initializing the libpng structures is +via the png_create_read_struct(), png_create_write_struct(), and +png_create_info_struct() because they isolate the size of the structures +from the application, allow version error checking, and also allow the +use of custom error handling routines during the initialization, which +the old functions do not. The functions png_read_destroy() and +png_write_destroy() do not actually free the memory that libpng +allocated for these structs, but just reset the data structures, so they +can be used instead of png_destroy_read_struct() and +png_destroy_write_struct() if you feel there is too much system overhead +allocating and freeing the png_struct for each image read. + +Setting the error callbacks via png_set_message_fn() before +png_read_init() as was suggested in libpng-0.88 is no longer supported +because this caused applications that do not use custom error functions +to fail if the png_ptr was not initialized to zero. It is still possible +to set the error callbacks AFTER png_read_init(), or to change them with +png_set_error_fn(), which is essentially the same function, but with a new +name to force compilation errors with applications that try to use the old +method. + +Starting with version 1.0.7, you can find out which version of the library +you are using at run-time: + + png_uint_32 libpng_vn = png_access_version_number(); + +The number libpng_vn is constructed from the major version, minor +version with leading zero, and release number with leading zero, +(e.g., libpng_vn for version 1.0.7 is 10007). + +You can also check which version of png.h you used when compiling your +application: + + png_uint_32 application_vn = PNG_LIBPNG_VER; + +.SH VIII. Changes to Libpng from version 1.0.x to 1.2.x + +Support for user memory management was enabled by default. To +accomplish this, the functions png_create_read_struct_2(), +png_create_write_struct_2(), png_set_mem_fn(), png_get_mem_ptr(), +png_malloc_default(), and png_free_default() were added. + +Support for the iTXt chunk has been enabled by default as of +version 1.2.41. + +Support for certain MNG features was enabled. + +Support for numbered error messages was added. However, we never got +around to actually numbering the error messages. The function +png_set_strip_error_numbers() was added (Note: the prototype for this +function was inadvertently removed from png.h in PNG_NO_ASSEMBLER_CODE +builds of libpng-1.2.15. It was restored in libpng-1.2.36). + +The png_malloc_warn() function was added at libpng-1.2.3. This issues +a png_warning and returns NULL instead of aborting when it fails to +acquire the requested memory allocation. + +Support for setting user limits on image width and height was enabled +by default. The functions png_set_user_limits(), png_get_user_width_max(), +and png_get_user_height_max() were added at libpng-1.2.6. + +The png_set_add_alpha() function was added at libpng-1.2.7. + +The function png_set_expand_gray_1_2_4_to_8() was added at libpng-1.2.9. +Unlike png_set_gray_1_2_4_to_8(), the new function does not expand the +tRNS chunk to alpha. The png_set_gray_1_2_4_to_8() function is +deprecated. + +A number of macro definitions in support of runtime selection of +assembler code features (especially Intel MMX code support) were +added at libpng-1.2.0: + + PNG_ASM_FLAG_MMX_SUPPORT_COMPILED + PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU + PNG_ASM_FLAG_MMX_READ_COMBINE_ROW + PNG_ASM_FLAG_MMX_READ_INTERLACE + PNG_ASM_FLAG_MMX_READ_FILTER_SUB + PNG_ASM_FLAG_MMX_READ_FILTER_UP + PNG_ASM_FLAG_MMX_READ_FILTER_AVG + PNG_ASM_FLAG_MMX_READ_FILTER_PAETH + PNG_ASM_FLAGS_INITIALIZED + PNG_MMX_READ_FLAGS + PNG_MMX_FLAGS + PNG_MMX_WRITE_FLAGS + PNG_MMX_FLAGS + +We added the following functions in support of runtime +selection of assembler code features: + + png_get_mmx_flagmask() + png_set_mmx_thresholds() + png_get_asm_flags() + png_get_mmx_bitdepth_threshold() + png_get_mmx_rowbytes_threshold() + png_set_asm_flags() + +We replaced all of these functions with simple stubs in libpng-1.2.20, +when the Intel assembler code was removed due to a licensing issue. + +These macros are deprecated: + + PNG_READ_TRANSFORMS_NOT_SUPPORTED + PNG_PROGRESSIVE_READ_NOT_SUPPORTED + PNG_NO_SEQUENTIAL_READ_SUPPORTED + PNG_WRITE_TRANSFORMS_NOT_SUPPORTED + PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED + PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED + +They have been replaced, respectively, by: + + PNG_NO_READ_TRANSFORMS + PNG_NO_PROGRESSIVE_READ + PNG_NO_SEQUENTIAL_READ + PNG_NO_WRITE_TRANSFORMS + PNG_NO_READ_ANCILLARY_CHUNKS + PNG_NO_WRITE_ANCILLARY_CHUNKS + +PNG_MAX_UINT was replaced with PNG_UINT_31_MAX. It has been +deprecated since libpng-1.0.16 and libpng-1.2.6. + +The function + png_check_sig(sig, num) +was replaced with + !png_sig_cmp(sig, 0, num) +It has been deprecated since libpng-0.90. + +The function + png_set_gray_1_2_4_to_8() +which also expands tRNS to alpha was replaced with + png_set_expand_gray_1_2_4_to_8() +which does not. It has been deprecated since libpng-1.0.18 and 1.2.9. + +.SH IX. (Omitted) + + +.SH X. Detecting libpng + +The png_get_io_ptr() function has been present since libpng-0.88, has never +changed, and is unaffected by conditional compilation macros. It is the +best choice for use in configure scripts for detecting the presence of any +libpng version since 0.88. In an autoconf "configure.in" you could use + + AC_CHECK_LIB(png, png_get_io_ptr, ... + +.SH XI. Source code repository + +Since about February 2009, version 1.2.34, libpng has been under "git" source +control. The git repository was built from old libpng-x.y.z.tar.gz files +going back to version 0.70. You can access the git repository (read only) +at + + git://libpng.git.sourceforge.net/gitroot/libpng + +or you can browse it via "gitweb" at + + http://libpng.git.sourceforge.net/git/gitweb.cgi?p=libpng + +Patches can be sent to glennrp at users.sourceforge.net or to +png-mng-implement at lists.sourceforge.net or you can upload them to +the libpng bug tracker at + + http://libpng.sourceforge.net + +.SH XII. Coding style + +Our coding style is similar to the "Allman" style, with curly +braces on separate lines: + + if (condition) + { + action; + } + + else if (another condition) + { + another action; + } + +The braces can be omitted from simple one-line actions: + + if (condition) + return (0); + +We use 3-space indentation, except for continued statements which +are usually indented the same as the first line of the statement +plus four more spaces. + +For macro definitions we use 2-space indentation, always leaving the "#" +in the first column. + + #ifndef PNG_NO_FEATURE + # ifndef PNG_FEATURE_SUPPORTED + # define PNG_FEATURE_SUPPORTED + # endif + #endif + +Comments appear with the leading "/*" at the same indentation as +the statement that follows the comment: + + /* Single-line comment */ + statement; + + /* Multiple-line + * comment + */ + statement; + +Very short comments can be placed at the end of the statement +to which they pertain: + + statement; /* comment */ + +We don't use C++ style ("//") comments. We have, however, +used them in the past in some now-abandoned MMX assembler +code. + +Functions and their curly braces are not indented, and +exported functions are marked with PNGAPI: + + /* This is a public function that is visible to + * application programers. It does thus-and-so. + */ + void PNGAPI + png_exported_function(png_ptr, png_info, foo) + { + body; + } + +The prototypes for all exported functions appear in png.h, +above the comment that says + + /* Maintainer: Put new public prototypes here ... */ + +We mark all non-exported functions with "/* PRIVATE */"": + + void /* PRIVATE */ + png_non_exported_function(png_ptr, png_info, foo) + { + body; + } + +The prototypes for non-exported functions (except for those in +pngtest) appear in +the PNG_INTERNAL section of png.h +above the comment that says + + /* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */ + +The names of all exported functions and variables begin +with "png_", and all publicly visible C preprocessor +macros begin with "PNG_". + +We put a space after each comma and after each semicolon +in "for" statments, and we put spaces before and after each +C binary operator and after "for" or "while". We don't +put a space between a typecast and the expression being +cast, nor do we put one between a function name and the +left parenthesis that follows it: + + for (i = 2; i > 0; --i) + y[i] = a(x) + (int)b; + +We prefer #ifdef and #ifndef to #if defined() and if !defined() +when there is only one macro being tested. + +We do not use the TAB character for indentation in the C sources. + +Lines do not exceed 80 characters. + +Other rules can be inferred by inspecting the libpng source. + +.SH XIII. Y2K Compliance in libpng + +June 26, 2010 + +Since the PNG Development group is an ad-hoc body, we can't make +an official declaration. + +This is your unofficial assurance that libpng from version 0.71 and +upward through 1.2.44 are Y2K compliant. It is my belief that earlier +versions were also Y2K compliant. + +Libpng only has three year fields. One is a 2-byte unsigned integer that +will hold years up to 65535. The other two hold the date in text +format, and will hold years up to 9999. + +The integer is + "png_uint_16 year" in png_time_struct. + +The strings are + "png_charp time_buffer" in png_struct and + "near_time_buffer", which is a local character string in png.c. + +There are seven time-related functions: + + png_convert_to_rfc_1123() in png.c + (formerly png_convert_to_rfc_1152() in error) + png_convert_from_struct_tm() in pngwrite.c, called + in pngwrite.c + png_convert_from_time_t() in pngwrite.c + png_get_tIME() in pngget.c + png_handle_tIME() in pngrutil.c, called in pngread.c + png_set_tIME() in pngset.c + png_write_tIME() in pngwutil.c, called in pngwrite.c + +All appear to handle dates properly in a Y2K environment. The +png_convert_from_time_t() function calls gmtime() to convert from system +clock time, which returns (year - 1900), which we properly convert to +the full 4-digit year. There is a possibility that applications using +libpng are not passing 4-digit years into the png_convert_to_rfc_1123() +function, or that they are incorrectly passing only a 2-digit year +instead of "year - 1900" into the png_convert_from_struct_tm() function, +but this is not under our control. The libpng documentation has always +stated that it works with 4-digit years, and the APIs have been +documented as such. + +The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned +integer to hold the year, and can hold years as large as 65535. + +zlib, upon which libpng depends, is also Y2K compliant. It contains +no date-related code. + + + Glenn Randers-Pehrson + libpng maintainer + PNG Development Group + +.SH NOTE + +Note about libpng version numbers: + +Due to various miscommunications, unforeseen code incompatibilities +and occasional factors outside the authors' control, version numbering +on the library has not always been consistent and straightforward. +The following table summarizes matters since version 0.89c, which was +the first widely used release: + + source png.h png.h shared-lib + version string int version + ------- ------ ----- ---------- + 0.89c ("beta 3") 0.89 89 1.0.89 + 0.90 ("beta 4") 0.90 90 0.90 + 0.95 ("beta 5") 0.95 95 0.95 + 0.96 ("beta 6") 0.96 96 0.96 + 0.97b ("beta 7") 1.00.97 97 1.0.1 + 0.97c 0.97 97 2.0.97 + 0.98 0.98 98 2.0.98 + 0.99 0.99 98 2.0.99 + 0.99a-m 0.99 99 2.0.99 + 1.00 1.00 100 2.1.0 + 1.0.0 1.0.0 100 2.1.0 + 1.0.0 (from here on, the 100 2.1.0 + 1.0.1 png.h string is 10001 2.1.0 + 1.0.1a-e identical to the 10002 from here on, the + 1.0.2 source version) 10002 shared library is 2.V + 1.0.2a-b 10003 where V is the source + 1.0.1 10001 code version except as + 1.0.1a-e 10002 2.1.0.1a-e noted. + 1.0.2 10002 2.1.0.2 + 1.0.2a-b 10003 2.1.0.2a-b + 1.0.3 10003 2.1.0.3 + 1.0.3a-d 10004 2.1.0.3a-d + 1.0.4 10004 2.1.0.4 + 1.0.4a-f 10005 2.1.0.4a-f + 1.0.5 (+ 2 patches) 10005 2.1.0.5 + 1.0.5a-d 10006 2.1.0.5a-d + 1.0.5e-r 10100 2.1.0.5e-r + 1.0.5s-v 10006 2.1.0.5s-v + 1.0.6 (+ 3 patches) 10006 2.1.0.6 + 1.0.6d-g 10007 2.1.0.6d-g + 1.0.6h 10007 10.6h + 1.0.6i 10007 10.6i + 1.0.6j 10007 2.1.0.6j + 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 + 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 + 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 + 1.0.7 1 10007 2.1.0.7 + 1.0.8beta1-4 1 10008 2.1.0.8beta1-4 + 1.0.8rc1 1 10008 2.1.0.8rc1 + 1.0.8 1 10008 2.1.0.8 + 1.0.9beta1-6 1 10009 2.1.0.9beta1-6 + 1.0.9rc1 1 10009 2.1.0.9rc1 + 1.0.9beta7-10 1 10009 2.1.0.9beta7-10 + 1.0.9rc2 1 10009 2.1.0.9rc2 + 1.0.9 1 10009 2.1.0.9 + 1.0.10beta1 1 10010 2.1.0.10beta1 + 1.0.10rc1 1 10010 2.1.0.10rc1 + 1.0.10 1 10010 2.1.0.10 + 1.0.11beta1-3 1 10011 2.1.0.11beta1-3 + 1.0.11rc1 1 10011 2.1.0.11rc1 + 1.0.11 1 10011 2.1.0.11 + 1.0.12beta1-2 2 10012 2.1.0.12beta1-2 + 1.0.12rc1 2 10012 2.1.0.12rc1 + 1.0.12 2 10012 2.1.0.12 + 1.1.0a-f - 10100 2.1.1.0a-f abandoned + 1.2.0beta1-2 2 10200 2.1.2.0beta1-2 + 1.2.0beta3-5 3 10200 3.1.2.0beta3-5 + 1.2.0rc1 3 10200 3.1.2.0rc1 + 1.2.0 3 10200 3.1.2.0 + 1.2.1beta-4 3 10201 3.1.2.1beta1-4 + 1.2.1rc1-2 3 10201 3.1.2.1rc1-2 + 1.2.1 3 10201 3.1.2.1 + 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6 + 1.0.13beta1 10 10013 10.so.0.1.0.13beta1 + 1.0.13rc1 10 10013 10.so.0.1.0.13rc1 + 1.2.2rc1 12 10202 12.so.0.1.2.2rc1 + 1.0.13 10 10013 10.so.0.1.0.13 + 1.2.2 12 10202 12.so.0.1.2.2 + 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6 + 1.2.3 12 10203 12.so.0.1.2.3 + 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3 + 1.2.4rc1 13 10204 12.so.0.1.2.4rc1 + 1.0.14 10 10014 10.so.0.1.0.14 + 1.2.4 13 10204 12.so.0.1.2.4 + 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2 + 1.0.15rc1 10 10015 10.so.0.1.0.15rc1 + 1.0.15 10 10015 10.so.0.1.0.15 + 1.2.5 13 10205 12.so.0.1.2.5 + 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4 + 1.2.6rc1-5 13 10206 12.so.0.1.2.6rc1-5 + 1.0.16 10 10016 10.so.0.1.0.16 + 1.2.6 13 10206 12.so.0.1.2.6 + 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2 + 1.0.17rc1 10 10017 10.so.0.1.0.17rc1 + 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 + 1.0.17 10 10017 10.so.0.1.0.17 + 1.2.7 13 10207 12.so.0.1.2.7 + 1.2.8beta1-5 13 10208 12.so.0.1.2.8beta1-5 + 1.0.18rc1-5 10 10018 10.so.0.1.0.18rc1-5 + 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5 + 1.0.18 10 10018 10.so.0.1.0.18 + 1.2.8 13 10208 12.so.0.1.2.8 + 1.2.9beta1-3 13 10209 12.so.0.1.2.9beta1-3 + 1.2.9beta4-11 13 10209 12.so.0.9[.0] + 1.2.9rc1 13 10209 12.so.0.9[.0] + 1.2.9 13 10209 12.so.0.9[.0] + 1.2.10beta1-8 13 10210 12.so.0.10[.0] + 1.2.10rc1-3 13 10210 12.so.0.10[.0] + 1.2.10 13 10210 12.so.0.10[.0] + 1.2.11beta1-4 13 10211 12.so.0.11[.0] + 1.0.19rc1-5 10 10019 10.so.0.19[.0] + 1.2.11rc1-5 13 10211 12.so.0.11[.0] + 1.0.19 10 10019 10.so.0.19[.0] + 1.2.11 13 10211 12.so.0.11[.0] + 1.0.20 10 10020 10.so.0.20[.0] + 1.2.12 13 10212 12.so.0.12[.0] + 1.2.13beta1 13 10213 12.so.0.13[.0] + 1.0.21 10 10021 10.so.0.21[.0] + 1.2.13 13 10213 12.so.0.13[.0] + 1.2.14beta1-2 13 10214 12.so.0.14[.0] + 1.0.22rc1 10 10022 10.so.0.22[.0] + 1.2.14rc1 13 10214 12.so.0.14[.0] + 1.2.15beta1-6 13 10215 12.so.0.15[.0] + 1.0.23rc1-5 10 10023 10.so.0.23[.0] + 1.2.15rc1-5 13 10215 12.so.0.15[.0] + 1.0.23 10 10023 10.so.0.23[.0] + 1.2.15 13 10215 12.so.0.15[.0] + 1.2.16beta1-2 13 10216 12.so.0.16[.0] + 1.2.16rc1 13 10216 12.so.0.16[.0] + 1.0.24 10 10024 10.so.0.24[.0] + 1.2.16 13 10216 12.so.0.16[.0] + 1.2.17beta1-2 13 10217 12.so.0.17[.0] + 1.0.25rc1 10 10025 10.so.0.25[.0] + 1.2.17rc1-3 13 10217 12.so.0.17[.0] + 1.0.25 10 10025 10.so.0.25[.0] + 1.2.17 13 10217 12.so.0.17[.0] + 1.0.26 10 10026 10.so.0.26[.0] + 1.2.18 13 10218 12.so.0.18[.0] + 1.2.19beta1-31 13 10219 12.so.0.19[.0] + 1.0.27rc1-6 10 10027 10.so.0.27[.0] + 1.2.19rc1-6 13 10219 12.so.0.19[.0] + 1.0.27 10 10027 10.so.0.27[.0] + 1.2.19 13 10219 12.so.0.19[.0] + 1.2.20beta01-04 13 10220 12.so.0.20[.0] + 1.0.28rc1-6 10 10028 10.so.0.28[.0] + 1.2.20rc1-6 13 10220 12.so.0.20[.0] + 1.0.28 10 10028 10.so.0.28[.0] + 1.2.20 13 10220 12.so.0.20[.0] + 1.2.21beta1-2 13 10221 12.so.0.21[.0] + 1.2.21rc1-3 13 10221 12.so.0.21[.0] + 1.0.29 10 10029 10.so.0.29[.0] + 1.2.21 13 10221 12.so.0.21[.0] + 1.2.22beta1-4 13 10222 12.so.0.22[.0] + 1.0.30rc1 13 10030 10.so.0.30[.0] + 1.2.22rc1 13 10222 12.so.0.22[.0] + 1.0.30 10 10030 10.so.0.30[.0] + 1.2.22 13 10222 12.so.0.22[.0] + 1.2.23beta01-05 13 10223 12.so.0.23[.0] + 1.2.23rc01 13 10223 12.so.0.23[.0] + 1.2.23 13 10223 12.so.0.23[.0] + 1.2.24beta01-02 13 10224 12.so.0.24[.0] + 1.2.24rc01 13 10224 12.so.0.24[.0] + 1.2.24 13 10224 12.so.0.24[.0] + 1.2.25beta01-06 13 10225 12.so.0.25[.0] + 1.2.25rc01-02 13 10225 12.so.0.25[.0] + 1.0.31 10 10031 10.so.0.31[.0] + 1.2.25 13 10225 12.so.0.25[.0] + 1.2.26beta01-06 13 10226 12.so.0.26[.0] + 1.2.26rc01 13 10226 12.so.0.26[.0] + 1.2.26 13 10226 12.so.0.26[.0] + 1.0.32 10 10032 10.so.0.32[.0] + 1.2.27beta01-06 13 10227 12.so.0.27[.0] + 1.2.27rc01 13 10227 12.so.0.27[.0] + 1.0.33 10 10033 10.so.0.33[.0] + 1.2.27 13 10227 12.so.0.27[.0] + 1.0.34 10 10034 10.so.0.34[.0] + 1.2.28 13 10228 12.so.0.28[.0] + 1.2.29beta01-03 13 10229 12.so.0.29[.0] + 1.2.29rc01 13 10229 12.so.0.29[.0] + 1.0.35 10 10035 10.so.0.35[.0] + 1.2.29 13 10229 12.so.0.29[.0] + 1.0.37 10 10037 10.so.0.37[.0] + 1.2.30beta01-04 13 10230 12.so.0.30[.0] + 1.0.38rc01-08 10 10038 10.so.0.38[.0] + 1.2.30rc01-08 13 10230 12.so.0.30[.0] + 1.0.38 10 10038 10.so.0.38[.0] + 1.2.30 13 10230 12.so.0.30[.0] + 1.0.39rc01-03 10 10039 10.so.0.39[.0] + 1.2.31rc01-03 13 10231 12.so.0.31[.0] + 1.0.39 10 10039 10.so.0.39[.0] + 1.2.31 13 10231 12.so.0.31[.0] + 1.2.32beta01-02 13 10232 12.so.0.32[.0] + 1.0.40rc01 10 10040 10.so.0.40[.0] + 1.2.32rc01 13 10232 12.so.0.32[.0] + 1.0.40 10 10040 10.so.0.40[.0] + 1.2.32 13 10232 12.so.0.32[.0] + 1.2.33beta01-02 13 10233 12.so.0.33[.0] + 1.2.33rc01-02 13 10233 12.so.0.33[.0] + 1.0.41rc01 10 10041 10.so.0.41[.0] + 1.2.33 13 10233 12.so.0.33[.0] + 1.0.41 10 10041 10.so.0.41[.0] + 1.2.34beta01-07 13 10234 12.so.0.34[.0] + 1.0.42rc01 10 10042 10.so.0.42[.0] + 1.2.34rc01 13 10234 12.so.0.34[.0] + 1.0.42 10 10042 10.so.0.42[.0] + 1.2.34 13 10234 12.so.0.34[.0] + 1.2.35beta01-03 13 10235 12.so.0.35[.0] + 1.0.43rc01-02 10 10043 10.so.0.43[.0] + 1.2.35rc01-02 13 10235 12.so.0.35[.0] + 1.0.43 10 10043 10.so.0.43[.0] + 1.2.35 13 10235 12.so.0.35[.0] + 1.2.36beta01-05 13 10236 12.so.0.36[.0] + 1.2.36rc01 13 10236 12.so.0.36[.0] + 1.0.44 10 10044 10.so.0.44[.0] + 1.2.36 13 10236 12.so.0.36[.0] + 1.2.37beta01-03 13 10237 12.so.0.37[.0] + 1.2.37rc01 13 10237 12.so.0.37[.0] + 1.2.37 13 10237 12.so.0.37[.0] + 1.2.45 10 10045 12.so.0.45[.0] + 1.0.46 10 10046 10.so.0.46[.0] + 1.2.38beta01 13 10238 12.so.0.38[.0] + 1.2.38rc01-03 13 10238 12.so.0.38[.0] + 1.0.47 10 10047 10.so.0.47[.0] + 1.2.38 13 10238 12.so.0.38[.0] + 1.2.39beta01-05 13 10239 12.so.0.39[.0] + 1.2.39rc01 13 10239 12.so.0.39[.0] + 1.0.48 10 10048 10.so.0.48[.0] + 1.2.39 13 10239 12.so.0.39[.0] + 1.2.40beta01 13 10240 12.so.0.40[.0] + 1.2.40rc01 13 10240 12.so.0.40[.0] + 1.0.49 10 10049 10.so.0.49[.0] + 1.2.40 13 10240 12.so.0.40[.0] + 1.0.50 10 10050 10.so.0.50[.0] + 1.2.41beta01-18 13 10241 12.so.0.41[.0] + 1.0.51rc01 10 10051 10.so.0.51[.0] + 1.2.41rc01-03 13 10241 12.so.0.41[.0] + 1.0.51 10 10051 10.so.0.51[.0] + 1.2.41 13 10241 12.so.0.41[.0] + 1.2.42beta01-02 13 10242 12.so.0.42[.0] + 1.2.42rc01-05 13 10242 12.so.0.42[.0] + 1.0.52 10 10052 10.so.0.52[.0] + 1.2.42 13 10242 12.so.0.42[.0] + 1.2.43beta01-05 13 10243 12.so.0.43[.0] + 1.0.53rc01-02 10 10053 10.so.0.53[.0] + 1.2.43rc01-02 13 10243 12.so.0.43[.0] + 1.0.53 10 10053 10.so.0.53[.0] + 1.2.43 13 10243 12.so.0.43[.0] + 1.2.44beta01-03 13 10244 12.so.0.44[.0] + 1.2.44rc01-03 13 10244 12.so.0.44[.0] + 1.2.44 13 10244 12.so.0.44[.0] + +Henceforth the source version will match the shared-library minor +and patch numbers; the shared-library major version number will be +used for changes in backward compatibility, as it is intended. The +PNG_PNGLIB_VER macro, which is not used within libpng but is available +for applications, is an unsigned integer of the form xyyzz corresponding +to the source version x.y.z (leading zeros in y and z). Beta versions +were given the previous public release number plus a letter, until +version 1.0.6j; from then on they were given the upcoming public +release number plus "betaNN" or "rcN". + +.SH "SEE ALSO" +.IR libpngpf(3) ", " png(5) +.LP +.IR libpng : +.IP +http://libpng.sourceforge.net (follow the [DOWNLOAD] link) +http://www.libpng.org/pub/png + +.LP +.IR zlib : +.IP +(generally) at the same location as +.I libpng +or at +.br +ftp://ftp.info-zip.org/pub/infozip/zlib + +.LP +.IR PNG specification: RFC 2083 +.IP +(generally) at the same location as +.I libpng +or at +.br +ftp://ftp.rfc-editor.org:/in-notes/rfc2083.txt +.br +or (as a W3C Recommendation) at +.br +http://www.w3.org/TR/REC-png.html + +.LP +In the case of any inconsistency between the PNG specification +and this library, the specification takes precedence. + +.SH AUTHORS +This man page: Glenn Randers-Pehrson +<glennrp at users.sourceforge.net> + +The contributing authors would like to thank all those who helped +with testing, bug fixes, and patience. This wouldn't have been +possible without all of you. + +Thanks to Frank J. T. Wojcik for helping with the documentation. + +Libpng version 1.2.44 - June 26, 2010: +Initially created in 1995 by Guy Eric Schalnat, then of Group 42, Inc. +Currently maintained by Glenn Randers-Pehrson (glennrp at users.sourceforge.net). + +Supported by the PNG development group +.br +png-mng-implement at lists.sf.net +(subscription required; visit +png-mng-implement at lists.sourceforge.net (subscription required; visit +https://lists.sourceforge.net/lists/listinfo/png-mng-implement +to subscribe). + +.SH COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: + +(This copy of the libpng notices is provided for your convenience. In case of +any discrepancy between this copy and the notices in the file png.h that is +included in the libpng distribution, the latter shall prevail.) + +If you modify libpng you may insert additional notices immediately following +this sentence. + +This code is released under the libpng license. + +libpng versions 1.2.6, August 15, 2004, through 1.2.44, June 26, 2010, are +Copyright (c) 2004,2006-2008 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-1.2.5 +with the following individual added to the list of Contributing Authors + + Cosmin Truta + +libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are +Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-1.0.6 +with the following individuals added to the list of Contributing Authors + + Simon-Pierre Cadieux + Eric S. Raymond + Gilles Vollant + +and with the following additions to the disclaimer: + + There is no warranty against interference with your + enjoyment of the library or against infringement. + There is no warranty that our efforts or the library + will fulfill any of your particular purposes or needs. + This library is provided with all faults, and the entire + risk of satisfactory quality, performance, accuracy, and + effort is with the user. + +libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are +Copyright (c) 1998, 1999 Glenn Randers-Pehrson +Distributed according to the same disclaimer and license as libpng-0.96, +with the following individuals added to the list of Contributing Authors: + + Tom Lane + Glenn Randers-Pehrson + Willem van Schaik + +libpng versions 0.89, June 1996, through 0.96, May 1997, are +Copyright (c) 1996, 1997 Andreas Dilger +Distributed according to the same disclaimer and license as libpng-0.88, +with the following individuals added to the list of Contributing Authors: + + John Bowler + Kevin Bracey + Sam Bushell + Magnus Holmgren + Greg Roelofs + Tom Tanner + +libpng versions 0.5, May 1995, through 0.88, January 1996, are +Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. + +For the purposes of this copyright and license, "Contributing Authors" +is defined as the following set of individuals: + + Andreas Dilger + Dave Martindale + Guy Eric Schalnat + Paul Schmidt + Tim Wegner + +The PNG Reference Library is supplied "AS IS". The Contributing Authors +and Group 42, Inc. disclaim all warranties, expressed or implied, +including, without limitation, the warranties of merchantability and of +fitness for any purpose. The Contributing Authors and Group 42, Inc. +assume no liability for direct, indirect, incidental, special, exemplary, +or consequential damages, which may result from the use of the PNG +Reference Library, even if advised of the possibility of such damage. + +Permission is hereby granted to use, copy, modify, and distribute this +source code, or portions hereof, for any purpose, without fee, subject +to the following restrictions: + +1. The origin of this source code must not be misrepresented. + +2. Altered versions must be plainly marked as such and + must not be misrepresented as being the original source. + +3. This Copyright notice may not be removed or altered from + any source or altered source distribution. + +The Contributing Authors and Group 42, Inc. specifically permit, without +fee, and encourage the use of this source code as a component to +supporting the PNG file format in commercial products. If you use this +source code in a product, acknowledgment is not required but would be +appreciated. + + +A "png_get_copyright" function is available, for convenient use in "about" +boxes and the like: + + printf("%s",png_get_copyright(NULL)); + +Also, the PNG logo (in PNG format, of course) is supplied in the +files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). + +Libpng is OSI Certified Open Source Software. OSI Certified Open Source is a +certification mark of the Open Source Initiative. + +Glenn Randers-Pehrson +glennrp at users.sourceforge.net +June 26, 2010 + +.\" end of man page + diff --git a/contrib/syslinux-4.02/com32/lib/libpng/libpngpf.3 b/contrib/syslinux-4.02/com32/lib/libpng/libpngpf.3 new file mode 100644 index 0000000..c2da624 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libpng/libpngpf.3 @@ -0,0 +1,806 @@ +.TH LIBPNGPF 3 "June 26, 2010" +.SH NAME +libpng \- Portable Network Graphics (PNG) Reference Library 1.2.44 +(private functions) +.SH SYNOPSIS +\fB#include <png.h>\fP + +\fI\fB + +\fBvoid png_64bit_product (long \fP\fIv1\fP\fB, long \fP\fIv2\fP\fB, unsigned long \fI*hi_product, + +\fBunsigned long \fI*lo_product\fP\fB);\fP + +\fI\fB + +\fBvoid png_build_gamma_table (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_build_grayscale_palette (int \fP\fIbit_depth\fP\fB, png_colorp \fIpalette\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_calculate_crc (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIptr\fP\fB, png_size_t \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBint png_check_cHRM_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_fixed_point \fP\fIint_white_x\fP\fB, png_fixed_point \fP\fIint_white_y\fP\fB, png_fixed_point \fP\fIint_red_x\fP\fB, png_fixed_point \fP\fIint_red_y\fP\fB, png_fixed_point \fP\fIint_green_x\fP\fB, png_fixed_point \fP\fIint_green_y\fP\fB, png_fixed_point \fP\fIint_blue_x\fP\fB, png_fixed_point \fIint_blue_y\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_check_IHDR (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIwidth\fP\fB, png_uint_32 \fP\fIheight\fP\fB, int \fP\fIbit_depth\fP\fB, int \fP\fIcolor_type\fP\fB, int \fP\fIinterlace_type\fP\fB, int \fP\fIcompression_type\fP\fB, int \fIfilter_type\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_check_chunk_name (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIchunk_name\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBpng_size_t png_check_keyword (png_structp \fP\fIpng_ptr\fP\fB, png_charp \fP\fIkey\fP\fB, png_charpp \fInew_key\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_combine_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIrow\fP\fB, int \fImask\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_correct_palette (png_structp \fP\fIpng_ptr\fP\fB, png_colorp \fP\fIpalette\fP\fB, int \fInum_palette\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBint png_crc_error (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBint png_crc_finish (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIskip\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_crc_read (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIbuf\fP\fB, png_size_t \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBpng_voidp png_create_struct (int \fItype\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBpng_voidp png_create_struct_2 (int \fP\fItype\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_voidp \fImem_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_decompress_chunk (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIcomp_type\fP\fB, png_charp \fP\fIchunkdata\fP\fB, png_size_t \fP\fIchunklength\fP\fB, png_size_t \fP\fIprefix_length\fP\fB, png_size_t \fI*data_length\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_destroy_struct (png_voidp \fIstruct_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_destroy_struct_2 (png_voidp \fP\fIstruct_ptr\fP\fB, png_free_ptr \fP\fIfree_fn\fP\fB, png_voidp \fImem_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_do_background (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_color_16p \fP\fItrans_values\fP\fB, png_color_16p \fP\fIbackground\fP\fB, png_color_16p \fP\fIbackground_1\fP\fB, png_bytep \fP\fIgamma_table\fP\fB, png_bytep \fP\fIgamma_from_1\fP\fB, png_bytep \fP\fIgamma_to_1\fP\fB, png_uint_16pp \fP\fIgamma_16\fP\fB, png_uint_16pp \fP\fIgamma_16_from_1\fP\fB, png_uint_16pp \fP\fIgamma_16_to_1\fP\fB, int \fIgamma_shift\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_do_bgr (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_do_chop (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_do_dither (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_bytep \fP\fIpalette_lookup\fP\fB, png_bytep \fIdither_lookup\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_do_expand (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_color_16p \fItrans_value\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_do_expand_palette (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_colorp \fP\fIpalette\fP\fB, png_bytep \fP\fItrans\fP\fB, int \fInum_trans\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_do_gamma (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_bytep \fP\fIgamma_table\fP\fB, png_uint_16pp \fP\fIgamma_16_table\fP\fB, int \fIgamma_shift\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_do_gray_to_rgb (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_do_invert (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_do_pack (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_uint_32 \fIbit_depth\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_do_packswap (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_do_read_filler (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_uint_32 \fP\fIfiller\fP\fB, png_uint_32 \fIflags\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_do_read_interlace (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, int \fP\fIpass\fP\fB, png_uint_32 \fItransformations\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_do_read_invert_alpha (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_do_read_swap_alpha (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_do_read_transformations (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBint png_do_rgb_to_gray (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_do_shift (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_color_8p \fIbit_depth\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_do_strip_filler (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_uint_32 \fIflags\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_do_swap (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_do_unpack (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_do_unshift (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_color_8p \fIsig_bits\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_do_write_interlace (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, int \fIpass\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_do_write_invert_alpha (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_do_write_swap_alpha (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_do_write_transformations (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid *png_far_to_near (png_structp png_ptr,png_voidp \fP\fIptr\fP\fB, int \fIcheck\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_flush (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_handle_bKGD (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_handle_cHRM (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_handle_gAMA (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_handle_hIST (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_handle_IEND (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_handle_IHDR (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_handle_iCCP (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_handle_iTXt (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_handle_oFFs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_handle_pCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_handle_pHYs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_handle_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_handle_sBIT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_handle_sCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_handle_sPLT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_handle_sRGB (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_handle_tEXt (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_handle_tIME (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_handle_tRNS (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_handle_unknown (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_handle_zTXt (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_info_destroy (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_init_mmx_flags (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_init_read_transformations (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_process_IDAT_data (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIbuffer\fP\fB, png_size_t \fIbuffer_length\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_process_some_data (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_push_check_crc (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_push_crc_finish (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_push_crc_skip (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_push_fill_buffer (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIbuffer\fP\fB, png_size_t \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_push_handle_tEXt (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_push_handle_unknown (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_push_handle_zTXt (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_push_have_end (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_push_have_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_push_have_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIrow\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_push_process_row (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_push_read_chunk (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_push_read_end (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_push_read_IDAT (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_push_read_sig (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_push_read_tEXt (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_push_read_zTXt (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_push_restore_buffer (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIbuffer\fP\fB, png_size_t \fIbuffer_length\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_push_save_buffer (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBpng_uint_32 png_read_chunk_header (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_read_data (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIdata\fP\fB, png_size_t \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_read_filter_row (png_structp \fP\fIpng_ptr\fP\fB, png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_bytep \fP\fIprev_row\fP\fB, int \fIfilter\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_read_finish_row (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_read_push_finish_row (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_read_start_row (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_read_transform_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_reset_crc (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBint png_set_text_2 (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_textp \fP\fItext_ptr\fP\fB, int \fInum_text\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_write_cHRM (png_structp \fP\fIpng_ptr\fP\fB, double \fP\fIwhite_x\fP\fB, double \fP\fIwhite_y\fP\fB, double \fP\fIred_x\fP\fB, double \fP\fIred_y\fP\fB, double \fP\fIgreen_x\fP\fB, double \fP\fIgreen_y\fP\fB, double \fP\fIblue_x\fP\fB, double \fIblue_y\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_write_cHRM_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIwhite_x\fP\fB, png_uint_32 \fP\fIwhite_y\fP\fB, png_uint_32 \fP\fIred_x\fP\fB, png_uint_32 \fP\fIred_y\fP\fB, png_uint_32 \fP\fIgreen_x\fP\fB, png_uint_32 \fP\fIgreen_y\fP\fB, png_uint_32 \fP\fIblue_x\fP\fB, png_uint_32 \fIblue_y\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_write_data (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIdata\fP\fB, png_size_t \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_write_filtered_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIfiltered_row\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_write_find_filter (png_structp \fP\fIpng_ptr\fP\fB, png_row_infop \fIrow_info\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_write_finish_row (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_write_gAMA (png_structp \fP\fIpng_ptr\fP\fB, double \fIfile_gamma\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_write_gAMA_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIint_file_gamma\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_write_hIST (png_structp \fP\fIpng_ptr\fP\fB, png_uint_16p \fP\fIhist\fP\fB, int \fInum_hist\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_write_iCCP (png_structp \fP\fIpng_ptr\fP\fB, png_charp \fP\fIname\fP\fB, int \fP\fIcompression_type\fP\fB, png_charp \fP\fIprofile\fP\fB, int \fIproflen\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_write_IDAT (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIdata\fP\fB, png_size_t \fIlength\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_write_IEND (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_write_IHDR (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIwidth\fP\fB, png_uint_32 \fP\fIheight\fP\fB, int \fP\fIbit_depth\fP\fB, int \fP\fIcolor_type\fP\fB, int \fP\fIcompression_type\fP\fB, int \fP\fIfilter_type\fP\fB, int \fIinterlace_type\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_write_iTXt (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIcompression\fP\fB, png_charp \fP\fIkey\fP\fB, png_charp \fP\fIlang\fP\fB, png_charp \fP\fItranslated_key\fP\fB, png_charp \fItext\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_write_oFFs (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIx_offset\fP\fB, png_uint_32 \fP\fIy_offset\fP\fB, int \fIunit_type\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_write_pCAL (png_structp \fP\fIpng_ptr\fP\fB, png_charp \fP\fIpurpose\fP\fB, png_int_32 \fP\fIX0\fP\fB, png_int_32 \fP\fIX1\fP\fB, int \fP\fItype\fP\fB, int \fP\fInparams\fP\fB, png_charp \fP\fIunits\fP\fB, png_charpp \fIparams\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_write_pHYs (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIx_pixels_per_unit\fP\fB, png_uint_32 \fP\fIy_pixels_per_unit\fP\fB, int \fIunit_type\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_write_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_colorp \fP\fIpalette\fP\fB, png_uint_32 \fInum_pal\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_write_sBIT (png_structp \fP\fIpng_ptr\fP\fB, png_color_8p \fP\fIsbit\fP\fB, int \fIcolor_type\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_write_sCAL (png_structp \fP\fIpng_ptr\fP\fB, png_charp \fP\fIunit\fP\fB, double \fP\fIwidth\fP\fB, double \fIheight\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_write_sCAL_s (png_structp \fP\fIpng_ptr\fP\fB, png_charp \fP\fIunit\fP\fB, png_charp \fP\fIwidth\fP\fB, png_charp \fIheight\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_write_sig (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_write_sRGB (png_structp \fP\fIpng_ptr\fP\fB, int \fIintent\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_write_sPLT (png_structp \fP\fIpng_ptr\fP\fB, png_spalette_p \fIpalette\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_write_start_row (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_write_tEXt (png_structp \fP\fIpng_ptr\fP\fB, png_charp \fP\fIkey\fP\fB, png_charp \fP\fItext\fP\fB, png_size_t \fItext_len\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_write_tIME (png_structp \fP\fIpng_ptr\fP\fB, png_timep \fImod_time\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_write_tRNS (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fItrans\fP\fB, png_color_16p \fP\fIvalues\fP\fB, int \fP\fInumber\fP\fB, int \fIcolor_type\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_write_zTXt (png_structp \fP\fIpng_ptr\fP\fB, png_charp \fP\fIkey\fP\fB, png_charp \fP\fItext\fP\fB, png_size_t \fP\fItext_len\fP\fB, int \fIcompression\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoidpf png_zalloc (voidpf \fP\fIpng_ptr\fP\fB, uInt \fP\fIitems\fP\fB, uInt \fIsize\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBvoid png_zfree (voidpf \fP\fIpng_ptr\fP\fB, voidpf \fIptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +.SH DESCRIPTION +The functions listed above are used privately by libpng +and are not recommended for use by applications. They are +not "exported" to applications using shared libraries. They +are listed alphabetically here as an aid to libpng maintainers. +See png.h for more information on these functions. + +.SH SEE ALSO +.IR libpng(3) ", " png(5) +.SH AUTHOR +Glenn Randers-Pehrson diff --git a/contrib/syslinux-4.02/com32/lib/libpng/png.5 b/contrib/syslinux-4.02/com32/lib/libpng/png.5 new file mode 100644 index 0000000..645c80c --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libpng/png.5 @@ -0,0 +1,74 @@ +.TH PNG 5 "June 26, 2010" +.SH NAME +png \- Portable Network Graphics (PNG) format +.SH DESCRIPTION +PNG (Portable Network Graphics) is an extensible file format for the +lossless, portable, well-compressed storage of raster images. PNG provides +a patent-free replacement for GIF and can also replace many +common uses of TIFF. Indexed-color, grayscale, and truecolor images are +supported, plus an optional alpha channel. Sample depths range from +1 to 16 bits. +.br + +PNG is designed to work well in online viewing applications, such as the +World Wide Web, so it is fully streamable with a progressive display +option. PNG is robust, providing both full file integrity checking and +fast, simple detection of common transmission errors. Also, PNG can store +gamma and chromaticity data for improved color matching on heterogeneous +platforms. + +.SH "SEE ALSO" +.IR libpng(3) ", " zlib(3) ", " deflate(5) ", and " zlib(5) +.LP +PNG specification (second edition), November 2003: +.IP +.br + <http://www.w3.org/TR/2003/REC-PNG-20031110/ +PNG 1.2 specification, July 1999: +.IP +.br +http://www.libpng.org/pub/png +.LP +PNG 1.0 specification, October 1996: +.IP +.br +RFC 2083 +.IP +.br +ftp://ftp.rfc-editor.org:/in-notes/rfc2083.txt +.br +or (as a W3C Recommendation) at +.br +http://www.w3.org/TR/REC-png.html +.SH AUTHORS +This man page: Glenn Randers-Pehrson +.LP +Portable Network Graphics (PNG) Specification (Second Edition) +Information technology - Computer graphics and image processing - +Portable Network Graphics (PNG): Functional specification. +ISO/IEC 15948:2003 (E) (November 10, 2003): David Duce and others. +.LP +Portable Network Graphics (PNG) Specification Version 1.2 (July 8, 1999): +Glenn Randers-Pehrson and others (png-list). +.LP +Portable Network Graphics (PNG) Specification Version 1.0 (October 1, 1996): +Thomas Boutell and others (png-list). +.LP + + +.SH COPYRIGHT NOTICE +.LP +This man page is Copyright (c) 1998-2006 Glenn Randers-Pehrson. See png.h +for conditions of use and distribution. +.LP +The PNG Specification (Second Edition) is +Copyright (c) 2003 W3C. (MIT, ERCIM, Keio), All Rights Reserved. +.LP +The PNG-1.2 specification is copyright (c) 1999 Glenn Randers-Pehrson. +See the specification for conditions of use and distribution. +.LP +The PNG-1.0 specification is copyright (c) 1996 Massachusetts Institute of +Technology. See the specification for conditions of use and distribution. +.LP +.\" end of man page + diff --git a/contrib/syslinux-4.02/com32/lib/libpng/png.c b/contrib/syslinux-4.02/com32/lib/libpng/png.c new file mode 100644 index 0000000..7ad9538 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libpng/png.c @@ -0,0 +1,1100 @@ + +/* png.c - location for general purpose libpng functions + * + * Last changed in libpng 1.2.43 [February 25, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#define PNG_INTERNAL +#define PNG_NO_EXTERN +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" + +/* Generate a compiler error if there is an old png.h in the search path. */ +typedef version_1_2_44 Your_png_h_is_not_version_1_2_44; + +/* Version information for C files. This had better match the version + * string defined in png.h. + */ + +#ifdef PNG_USE_GLOBAL_ARRAYS +/* png_libpng_ver was changed to a function in version 1.0.5c */ +PNG_CONST char png_libpng_ver[18] = PNG_LIBPNG_VER_STRING; + +#ifdef PNG_READ_SUPPORTED + +/* png_sig was changed to a function in version 1.0.5c */ +/* Place to hold the signature string for a PNG file. */ +PNG_CONST png_byte FARDATA png_sig[8] = {137, 80, 78, 71, 13, 10, 26, 10}; +#endif /* PNG_READ_SUPPORTED */ + +/* Invoke global declarations for constant strings for known chunk types */ +PNG_IHDR; +PNG_IDAT; +PNG_IEND; +PNG_PLTE; +PNG_bKGD; +PNG_cHRM; +PNG_gAMA; +PNG_hIST; +PNG_iCCP; +PNG_iTXt; +PNG_oFFs; +PNG_pCAL; +PNG_sCAL; +PNG_pHYs; +PNG_sBIT; +PNG_sPLT; +PNG_sRGB; +PNG_tEXt; +PNG_tIME; +PNG_tRNS; +PNG_zTXt; + +#ifdef PNG_READ_SUPPORTED +/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + +/* Start of interlace block */ +PNG_CONST int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; + +/* Offset to next interlace block */ +PNG_CONST int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; + +/* Start of interlace block in the y direction */ +PNG_CONST int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; + +/* Offset to next interlace block in the y direction */ +PNG_CONST int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; + +/* Height of interlace block. This is not currently used - if you need + * it, uncomment it here and in png.h +PNG_CONST int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; +*/ + +/* Mask to determine which pixels are valid in a pass */ +PNG_CONST int FARDATA png_pass_mask[] = + {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff}; + +/* Mask to determine which pixels to overwrite while displaying */ +PNG_CONST int FARDATA png_pass_dsp_mask[] + = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff}; + +#endif /* PNG_READ_SUPPORTED */ +#endif /* PNG_USE_GLOBAL_ARRAYS */ + +/* Tells libpng that we have already handled the first "num_bytes" bytes + * of the PNG file signature. If the PNG data is embedded into another + * stream we can set num_bytes = 8 so that libpng will not attempt to read + * or write any of the magic bytes before it starts on the IHDR. + */ + +#ifdef PNG_READ_SUPPORTED +void PNGAPI +png_set_sig_bytes(png_structp png_ptr, int num_bytes) +{ + png_debug(1, "in png_set_sig_bytes"); + + if (png_ptr == NULL) + return; + + if (num_bytes > 8) + png_error(png_ptr, "Too many bytes for PNG signature."); + + png_ptr->sig_bytes = (png_byte)(num_bytes < 0 ? 0 : num_bytes); +} + +/* Checks whether the supplied bytes match the PNG signature. We allow + * checking less than the full 8-byte signature so that those apps that + * already read the first few bytes of a file to determine the file type + * can simply check the remaining bytes for extra assurance. Returns + * an integer less than, equal to, or greater than zero if sig is found, + * respectively, to be less than, to match, or be greater than the correct + * PNG signature (this is the same behaviour as strcmp, memcmp, etc). + */ +int PNGAPI +png_sig_cmp(png_bytep sig, png_size_t start, png_size_t num_to_check) +{ + png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; + if (num_to_check > 8) + num_to_check = 8; + else if (num_to_check < 1) + return (-1); + + if (start > 7) + return (-1); + + if (start + num_to_check > 8) + num_to_check = 8 - start; + + return ((int)(png_memcmp(&sig[start], &png_signature[start], num_to_check))); +} + +#if defined(PNG_1_0_X) || defined(PNG_1_2_X) +/* (Obsolete) function to check signature bytes. It does not allow one + * to check a partial signature. This function might be removed in the + * future - use png_sig_cmp(). Returns true (nonzero) if the file is PNG. + */ +int PNGAPI +png_check_sig(png_bytep sig, int num) +{ + return ((int)!png_sig_cmp(sig, (png_size_t)0, (png_size_t)num)); +} +#endif +#endif /* PNG_READ_SUPPORTED */ + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +/* Function to allocate memory for zlib and clear it to 0. */ +#ifdef PNG_1_0_X +voidpf PNGAPI +#else +voidpf /* PRIVATE */ +#endif +png_zalloc(voidpf png_ptr, uInt items, uInt size) +{ + png_voidp ptr; + png_structp p=(png_structp)png_ptr; + png_uint_32 save_flags=p->flags; + png_uint_32 num_bytes; + + if (png_ptr == NULL) + return (NULL); + if (items > PNG_UINT_32_MAX/size) + { + png_warning (p, "Potential overflow in png_zalloc()"); + return (NULL); + } + num_bytes = (png_uint_32)items * size; + + p->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK; + ptr = (png_voidp)png_malloc((png_structp)png_ptr, num_bytes); + p->flags=save_flags; + +#if defined(PNG_1_0_X) && !defined(PNG_NO_ZALLOC_ZERO) + if (ptr == NULL) + return ((voidpf)ptr); + + if (num_bytes > (png_uint_32)0x8000L) + { + png_memset(ptr, 0, (png_size_t)0x8000L); + png_memset((png_bytep)ptr + (png_size_t)0x8000L, 0, + (png_size_t)(num_bytes - (png_uint_32)0x8000L)); + } + else + { + png_memset(ptr, 0, (png_size_t)num_bytes); + } +#endif + return ((voidpf)ptr); +} + +/* Function to free memory for zlib */ +#ifdef PNG_1_0_X +void PNGAPI +#else +void /* PRIVATE */ +#endif +png_zfree(voidpf png_ptr, voidpf ptr) +{ + png_free((png_structp)png_ptr, (png_voidp)ptr); +} + +/* Reset the CRC variable to 32 bits of 1's. Care must be taken + * in case CRC is > 32 bits to leave the top bits 0. + */ +void /* PRIVATE */ +png_reset_crc(png_structp png_ptr) +{ + png_ptr->crc = crc32(0, Z_NULL, 0); +} + +/* Calculate the CRC over a section of data. We can only pass as + * much data to this routine as the largest single buffer size. We + * also check that this data will actually be used before going to the + * trouble of calculating it. + */ +void /* PRIVATE */ +png_calculate_crc(png_structp png_ptr, png_bytep ptr, png_size_t length) +{ + int need_crc = 1; + + if (png_ptr->chunk_name[0] & 0x20) /* ancillary */ + { + if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == + (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) + need_crc = 0; + } + else /* critical */ + { + if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) + need_crc = 0; + } + + if (need_crc) + png_ptr->crc = crc32(png_ptr->crc, ptr, (uInt)length); +} + +/* Allocate the memory for an info_struct for the application. We don't + * really need the png_ptr, but it could potentially be useful in the + * future. This should be used in favour of malloc(png_sizeof(png_info)) + * and png_info_init() so that applications that want to use a shared + * libpng don't have to be recompiled if png_info changes size. + */ +png_infop PNGAPI +png_create_info_struct(png_structp png_ptr) +{ + png_infop info_ptr; + + png_debug(1, "in png_create_info_struct"); + + if (png_ptr == NULL) + return (NULL); + +#ifdef PNG_USER_MEM_SUPPORTED + info_ptr = (png_infop)png_create_struct_2(PNG_STRUCT_INFO, + png_ptr->malloc_fn, png_ptr->mem_ptr); +#else + info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO); +#endif + if (info_ptr != NULL) + png_info_init_3(&info_ptr, png_sizeof(png_info)); + + return (info_ptr); +} + +/* This function frees the memory associated with a single info struct. + * Normally, one would use either png_destroy_read_struct() or + * png_destroy_write_struct() to free an info struct, but this may be + * useful for some applications. + */ +void PNGAPI +png_destroy_info_struct(png_structp png_ptr, png_infopp info_ptr_ptr) +{ + png_infop info_ptr = NULL; + + png_debug(1, "in png_destroy_info_struct"); + + if (png_ptr == NULL) + return; + + if (info_ptr_ptr != NULL) + info_ptr = *info_ptr_ptr; + + if (info_ptr != NULL) + { + png_info_destroy(png_ptr, info_ptr); + +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)info_ptr, png_ptr->free_fn, + png_ptr->mem_ptr); +#else + png_destroy_struct((png_voidp)info_ptr); +#endif + *info_ptr_ptr = NULL; + } +} + +/* Initialize the info structure. This is now an internal function (0.89) + * and applications using it are urged to use png_create_info_struct() + * instead. + */ +#if defined(PNG_1_0_X) || defined(PNG_1_2_X) +#undef png_info_init +void PNGAPI +png_info_init(png_infop info_ptr) +{ + /* We only come here via pre-1.0.12-compiled applications */ + png_info_init_3(&info_ptr, 0); +} +#endif + +void PNGAPI +png_info_init_3(png_infopp ptr_ptr, png_size_t png_info_struct_size) +{ + png_infop info_ptr = *ptr_ptr; + + png_debug(1, "in png_info_init_3"); + + if (info_ptr == NULL) + return; + + if (png_sizeof(png_info) > png_info_struct_size) + { + png_destroy_struct(info_ptr); + info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO); + *ptr_ptr = info_ptr; + } + + /* Set everything to 0 */ + png_memset(info_ptr, 0, png_sizeof(png_info)); +} + +#ifdef PNG_FREE_ME_SUPPORTED +void PNGAPI +png_data_freer(png_structp png_ptr, png_infop info_ptr, + int freer, png_uint_32 mask) +{ + png_debug(1, "in png_data_freer"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (freer == PNG_DESTROY_WILL_FREE_DATA) + info_ptr->free_me |= mask; + else if (freer == PNG_USER_WILL_FREE_DATA) + info_ptr->free_me &= ~mask; + else + png_warning(png_ptr, + "Unknown freer parameter in png_data_freer."); +} +#endif + +void PNGAPI +png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask, + int num) +{ + png_debug(1, "in png_free_data"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + +#ifdef PNG_TEXT_SUPPORTED + /* Free text item num or (if num == -1) all text items */ +#ifdef PNG_FREE_ME_SUPPORTED + if ((mask & PNG_FREE_TEXT) & info_ptr->free_me) +#else + if (mask & PNG_FREE_TEXT) +#endif + { + if (num != -1) + { + if (info_ptr->text && info_ptr->text[num].key) + { + png_free(png_ptr, info_ptr->text[num].key); + info_ptr->text[num].key = NULL; + } + } + else + { + int i; + for (i = 0; i < info_ptr->num_text; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, i); + png_free(png_ptr, info_ptr->text); + info_ptr->text = NULL; + info_ptr->num_text=0; + } + } +#endif + +#ifdef PNG_tRNS_SUPPORTED + /* Free any tRNS entry */ +#ifdef PNG_FREE_ME_SUPPORTED + if ((mask & PNG_FREE_TRNS) & info_ptr->free_me) +#else + if ((mask & PNG_FREE_TRNS) && (png_ptr->flags & PNG_FLAG_FREE_TRNS)) +#endif + { + png_free(png_ptr, info_ptr->trans); + info_ptr->trans = NULL; + info_ptr->valid &= ~PNG_INFO_tRNS; +#ifndef PNG_FREE_ME_SUPPORTED + png_ptr->flags &= ~PNG_FLAG_FREE_TRNS; +#endif + } +#endif + +#ifdef PNG_sCAL_SUPPORTED + /* Free any sCAL entry */ +#ifdef PNG_FREE_ME_SUPPORTED + if ((mask & PNG_FREE_SCAL) & info_ptr->free_me) +#else + if (mask & PNG_FREE_SCAL) +#endif + { +#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, info_ptr->scal_s_width); + png_free(png_ptr, info_ptr->scal_s_height); + info_ptr->scal_s_width = NULL; + info_ptr->scal_s_height = NULL; +#endif + info_ptr->valid &= ~PNG_INFO_sCAL; + } +#endif + +#ifdef PNG_pCAL_SUPPORTED + /* Free any pCAL entry */ +#ifdef PNG_FREE_ME_SUPPORTED + if ((mask & PNG_FREE_PCAL) & info_ptr->free_me) +#else + if (mask & PNG_FREE_PCAL) +#endif + { + png_free(png_ptr, info_ptr->pcal_purpose); + png_free(png_ptr, info_ptr->pcal_units); + info_ptr->pcal_purpose = NULL; + info_ptr->pcal_units = NULL; + if (info_ptr->pcal_params != NULL) + { + int i; + for (i = 0; i < (int)info_ptr->pcal_nparams; i++) + { + png_free(png_ptr, info_ptr->pcal_params[i]); + info_ptr->pcal_params[i] = NULL; + } + png_free(png_ptr, info_ptr->pcal_params); + info_ptr->pcal_params = NULL; + } + info_ptr->valid &= ~PNG_INFO_pCAL; + } +#endif + +#ifdef PNG_iCCP_SUPPORTED + /* Free any iCCP entry */ +#ifdef PNG_FREE_ME_SUPPORTED + if ((mask & PNG_FREE_ICCP) & info_ptr->free_me) +#else + if (mask & PNG_FREE_ICCP) +#endif + { + png_free(png_ptr, info_ptr->iccp_name); + png_free(png_ptr, info_ptr->iccp_profile); + info_ptr->iccp_name = NULL; + info_ptr->iccp_profile = NULL; + info_ptr->valid &= ~PNG_INFO_iCCP; + } +#endif + +#ifdef PNG_sPLT_SUPPORTED + /* Free a given sPLT entry, or (if num == -1) all sPLT entries */ +#ifdef PNG_FREE_ME_SUPPORTED + if ((mask & PNG_FREE_SPLT) & info_ptr->free_me) +#else + if (mask & PNG_FREE_SPLT) +#endif + { + if (num != -1) + { + if (info_ptr->splt_palettes) + { + png_free(png_ptr, info_ptr->splt_palettes[num].name); + png_free(png_ptr, info_ptr->splt_palettes[num].entries); + info_ptr->splt_palettes[num].name = NULL; + info_ptr->splt_palettes[num].entries = NULL; + } + } + else + { + if (info_ptr->splt_palettes_num) + { + int i; + for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, i); + + png_free(png_ptr, info_ptr->splt_palettes); + info_ptr->splt_palettes = NULL; + info_ptr->splt_palettes_num = 0; + } + info_ptr->valid &= ~PNG_INFO_sPLT; + } + } +#endif + +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED + if (png_ptr->unknown_chunk.data) + { + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; + } + +#ifdef PNG_FREE_ME_SUPPORTED + if ((mask & PNG_FREE_UNKN) & info_ptr->free_me) +#else + if (mask & PNG_FREE_UNKN) +#endif + { + if (num != -1) + { + if (info_ptr->unknown_chunks) + { + png_free(png_ptr, info_ptr->unknown_chunks[num].data); + info_ptr->unknown_chunks[num].data = NULL; + } + } + else + { + int i; + + if (info_ptr->unknown_chunks_num) + { + for (i = 0; i < (int)info_ptr->unknown_chunks_num; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, i); + + png_free(png_ptr, info_ptr->unknown_chunks); + info_ptr->unknown_chunks = NULL; + info_ptr->unknown_chunks_num = 0; + } + } + } +#endif + +#ifdef PNG_hIST_SUPPORTED + /* Free any hIST entry */ +#ifdef PNG_FREE_ME_SUPPORTED + if ((mask & PNG_FREE_HIST) & info_ptr->free_me) +#else + if ((mask & PNG_FREE_HIST) && (png_ptr->flags & PNG_FLAG_FREE_HIST)) +#endif + { + png_free(png_ptr, info_ptr->hist); + info_ptr->hist = NULL; + info_ptr->valid &= ~PNG_INFO_hIST; +#ifndef PNG_FREE_ME_SUPPORTED + png_ptr->flags &= ~PNG_FLAG_FREE_HIST; +#endif + } +#endif + + /* Free any PLTE entry that was internally allocated */ +#ifdef PNG_FREE_ME_SUPPORTED + if ((mask & PNG_FREE_PLTE) & info_ptr->free_me) +#else + if ((mask & PNG_FREE_PLTE) && (png_ptr->flags & PNG_FLAG_FREE_PLTE)) +#endif + { + png_zfree(png_ptr, info_ptr->palette); + info_ptr->palette = NULL; + info_ptr->valid &= ~PNG_INFO_PLTE; +#ifndef PNG_FREE_ME_SUPPORTED + png_ptr->flags &= ~PNG_FLAG_FREE_PLTE; +#endif + info_ptr->num_palette = 0; + } + +#ifdef PNG_INFO_IMAGE_SUPPORTED + /* Free any image bits attached to the info structure */ +#ifdef PNG_FREE_ME_SUPPORTED + if ((mask & PNG_FREE_ROWS) & info_ptr->free_me) +#else + if (mask & PNG_FREE_ROWS) +#endif + { + if (info_ptr->row_pointers) + { + int row; + for (row = 0; row < (int)info_ptr->height; row++) + { + png_free(png_ptr, info_ptr->row_pointers[row]); + info_ptr->row_pointers[row] = NULL; + } + png_free(png_ptr, info_ptr->row_pointers); + info_ptr->row_pointers = NULL; + } + info_ptr->valid &= ~PNG_INFO_IDAT; + } +#endif + +#ifdef PNG_FREE_ME_SUPPORTED + if (num == -1) + info_ptr->free_me &= ~mask; + else + info_ptr->free_me &= ~(mask & ~PNG_FREE_MUL); +#endif +} + +/* This is an internal routine to free any memory that the info struct is + * pointing to before re-using it or freeing the struct itself. Recall + * that png_free() checks for NULL pointers for us. + */ +void /* PRIVATE */ +png_info_destroy(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_info_destroy"); + + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + if (png_ptr->num_chunk_list) + { + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->chunk_list = NULL; + png_ptr->num_chunk_list = 0; + } +#endif + + png_info_init_3(&info_ptr, png_sizeof(png_info)); +} +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ + +/* This function returns a pointer to the io_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy() or png_read_destroy() are called. + */ +png_voidp PNGAPI +png_get_io_ptr(png_structp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); + return (png_ptr->io_ptr); +} + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +#ifdef PNG_STDIO_SUPPORTED +/* Initialize the default input/output functions for the PNG file. If you + * use your own read or write routines, you can call either png_set_read_fn() + * or png_set_write_fn() instead of png_init_io(). If you have defined + * PNG_NO_STDIO, you must use a function of your own because "FILE *" isn't + * necessarily available. + */ +void PNGAPI +png_init_io(png_structp png_ptr, png_FILE_p fp) +{ + png_debug(1, "in png_init_io"); + + if (png_ptr == NULL) + return; + + png_ptr->io_ptr = (png_voidp)fp; +} +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED +/* Convert the supplied time into an RFC 1123 string suitable for use in + * a "Creation Time" or other text-based time string. + */ +png_charp PNGAPI +png_convert_to_rfc1123(png_structp png_ptr, png_timep ptime) +{ + static PNG_CONST char short_months[12][4] = + {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + + if (png_ptr == NULL) + return (NULL); + if (png_ptr->time_buffer == NULL) + { + png_ptr->time_buffer = (png_charp)png_malloc(png_ptr, (png_uint_32)(29* + png_sizeof(char))); + } + +#ifdef _WIN32_WCE + { + wchar_t time_buf[29]; + wsprintf(time_buf, TEXT("%d %S %d %02d:%02d:%02d +0000"), + ptime->day % 32, short_months[(ptime->month - 1) % 12], + ptime->year, ptime->hour % 24, ptime->minute % 60, + ptime->second % 61); + WideCharToMultiByte(CP_ACP, 0, time_buf, -1, png_ptr->time_buffer, + 29, NULL, NULL); + } +#else +#ifdef USE_FAR_KEYWORD + { + char near_time_buf[29]; + png_snprintf6(near_time_buf, 29, "%d %s %d %02d:%02d:%02d +0000", + ptime->day % 32, short_months[(ptime->month - 1) % 12], + ptime->year, ptime->hour % 24, ptime->minute % 60, + ptime->second % 61); + png_memcpy(png_ptr->time_buffer, near_time_buf, + 29*png_sizeof(char)); + } +#else + png_snprintf6(png_ptr->time_buffer, 29, "%d %s %d %02d:%02d:%02d +0000", + ptime->day % 32, short_months[(ptime->month - 1) % 12], + ptime->year, ptime->hour % 24, ptime->minute % 60, + ptime->second % 61); +#endif +#endif /* _WIN32_WCE */ + return ((png_charp)png_ptr->time_buffer); +} +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ + +png_charp PNGAPI +png_get_copyright(png_structp png_ptr) +{ + png_ptr = png_ptr; /* Silence compiler warning about unused png_ptr */ +#ifdef PNG_STRING_COPYRIGHT + return PNG_STRING_COPYRIGHT +#else +#ifdef __STDC__ + return ((png_charp) PNG_STRING_NEWLINE \ + "libpng version 1.2.44 - June 26, 2010" PNG_STRING_NEWLINE \ + "Copyright (c) 1998-2010 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \ + "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ + "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \ + PNG_STRING_NEWLINE); +#else + return ((png_charp) "libpng version 1.2.44 - June 26, 2010\ + Copyright (c) 1998-2010 Glenn Randers-Pehrson\ + Copyright (c) 1996-1997 Andreas Dilger\ + Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc."); +#endif +#endif +} + +/* The following return the library version as a short string in the + * format 1.0.0 through 99.99.99zz. To get the version of *.h files + * used with your application, print out PNG_LIBPNG_VER_STRING, which + * is defined in png.h. + * Note: now there is no difference between png_get_libpng_ver() and + * png_get_header_ver(). Due to the version_nn_nn_nn typedef guard, + * it is guaranteed that png.c uses the correct version of png.h. + */ +png_charp PNGAPI +png_get_libpng_ver(png_structp png_ptr) +{ + /* Version of *.c files used when building libpng */ + png_ptr = png_ptr; /* Silence compiler warning about unused png_ptr */ + return ((png_charp) PNG_LIBPNG_VER_STRING); +} + +png_charp PNGAPI +png_get_header_ver(png_structp png_ptr) +{ + /* Version of *.h files used when building libpng */ + png_ptr = png_ptr; /* Silence compiler warning about unused png_ptr */ + return ((png_charp) PNG_LIBPNG_VER_STRING); +} + +png_charp PNGAPI +png_get_header_version(png_structp png_ptr) +{ + /* Returns longer string containing both version and date */ + png_ptr = png_ptr; /* Silence compiler warning about unused png_ptr */ +#ifdef __STDC__ + return ((png_charp) PNG_HEADER_VERSION_STRING +#ifndef PNG_READ_SUPPORTED + " (NO READ SUPPORT)" +#endif + PNG_STRING_NEWLINE); +#else + return ((png_charp) PNG_HEADER_VERSION_STRING); +#endif +} + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +int PNGAPI +png_handle_as_unknown(png_structp png_ptr, png_bytep chunk_name) +{ + /* Check chunk_name and return "keep" value if it's on the list, else 0 */ + int i; + png_bytep p; + if (png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list<=0) + return 0; + p = png_ptr->chunk_list + png_ptr->num_chunk_list*5 - 5; + for (i = png_ptr->num_chunk_list; i; i--, p -= 5) + if (!png_memcmp(chunk_name, p, 4)) + return ((int)*(p + 4)); + return 0; +} +#endif + +/* This function, added to libpng-1.0.6g, is untested. */ +int PNGAPI +png_reset_zstream(png_structp png_ptr) +{ + if (png_ptr == NULL) + return Z_STREAM_ERROR; + return (inflateReset(&png_ptr->zstream)); +} +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ + +/* This function was added to libpng-1.0.7 */ +png_uint_32 PNGAPI +png_access_version_number(void) +{ + /* Version of *.c files used when building libpng */ + return((png_uint_32) PNG_LIBPNG_VER); +} + + +#if defined(PNG_READ_SUPPORTED) && defined(PNG_ASSEMBLER_CODE_SUPPORTED) +#ifndef PNG_1_0_X +/* This function was added to libpng 1.2.0 */ +int PNGAPI +png_mmx_support(void) +{ + /* Obsolete, to be removed from libpng-1.4.0 */ + return -1; +} +#endif /* PNG_1_0_X */ +#endif /* PNG_READ_SUPPORTED && PNG_ASSEMBLER_CODE_SUPPORTED */ + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +#ifdef PNG_SIZE_T +/* Added at libpng version 1.2.6 */ + PNG_EXTERN png_size_t PNGAPI png_convert_size PNGARG((size_t size)); +png_size_t PNGAPI +png_convert_size(size_t size) +{ + if (size > (png_size_t)-1) + PNG_ABORT(); /* We haven't got access to png_ptr, so no png_error() */ + return ((png_size_t)size); +} +#endif /* PNG_SIZE_T */ + +/* Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.c) */ +#ifdef PNG_cHRM_SUPPORTED +#ifdef PNG_CHECK_cHRM_SUPPORTED + +/* + * Multiply two 32-bit numbers, V1 and V2, using 32-bit + * arithmetic, to produce a 64 bit result in the HI/LO words. + * + * A B + * x C D + * ------ + * AD || BD + * AC || CB || 0 + * + * where A and B are the high and low 16-bit words of V1, + * C and D are the 16-bit words of V2, AD is the product of + * A and D, and X || Y is (X << 16) + Y. +*/ + +void /* PRIVATE */ +png_64bit_product (long v1, long v2, unsigned long *hi_product, + unsigned long *lo_product) +{ + int a, b, c, d; + long lo, hi, x, y; + + a = (v1 >> 16) & 0xffff; + b = v1 & 0xffff; + c = (v2 >> 16) & 0xffff; + d = v2 & 0xffff; + + lo = b * d; /* BD */ + x = a * d + c * b; /* AD + CB */ + y = ((lo >> 16) & 0xffff) + x; + + lo = (lo & 0xffff) | ((y & 0xffff) << 16); + hi = (y >> 16) & 0xffff; + + hi += a * c; /* AC */ + + *hi_product = (unsigned long)hi; + *lo_product = (unsigned long)lo; +} + +int /* PRIVATE */ +png_check_cHRM_fixed(png_structp png_ptr, + png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x, + png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y, + png_fixed_point blue_x, png_fixed_point blue_y) +{ + int ret = 1; + unsigned long xy_hi,xy_lo,yx_hi,yx_lo; + + png_debug(1, "in function png_check_cHRM_fixed"); + + if (png_ptr == NULL) + return 0; + + if (white_x < 0 || white_y <= 0 || + red_x < 0 || red_y < 0 || + green_x < 0 || green_y < 0 || + blue_x < 0 || blue_y < 0) + { + png_warning(png_ptr, + "Ignoring attempt to set negative chromaticity value"); + ret = 0; + } + if (white_x > (png_fixed_point) PNG_UINT_31_MAX || + white_y > (png_fixed_point) PNG_UINT_31_MAX || + red_x > (png_fixed_point) PNG_UINT_31_MAX || + red_y > (png_fixed_point) PNG_UINT_31_MAX || + green_x > (png_fixed_point) PNG_UINT_31_MAX || + green_y > (png_fixed_point) PNG_UINT_31_MAX || + blue_x > (png_fixed_point) PNG_UINT_31_MAX || + blue_y > (png_fixed_point) PNG_UINT_31_MAX ) + { + png_warning(png_ptr, + "Ignoring attempt to set chromaticity value exceeding 21474.83"); + ret = 0; + } + if (white_x > 100000L - white_y) + { + png_warning(png_ptr, "Invalid cHRM white point"); + ret = 0; + } + if (red_x > 100000L - red_y) + { + png_warning(png_ptr, "Invalid cHRM red point"); + ret = 0; + } + if (green_x > 100000L - green_y) + { + png_warning(png_ptr, "Invalid cHRM green point"); + ret = 0; + } + if (blue_x > 100000L - blue_y) + { + png_warning(png_ptr, "Invalid cHRM blue point"); + ret = 0; + } + + png_64bit_product(green_x - red_x, blue_y - red_y, &xy_hi, &xy_lo); + png_64bit_product(green_y - red_y, blue_x - red_x, &yx_hi, &yx_lo); + + if (xy_hi == yx_hi && xy_lo == yx_lo) + { + png_warning(png_ptr, + "Ignoring attempt to set cHRM RGB triangle with zero area"); + ret = 0; + } + + return ret; +} +#endif /* PNG_CHECK_cHRM_SUPPORTED */ +#endif /* PNG_cHRM_SUPPORTED */ + +void /* PRIVATE */ +png_check_IHDR(png_structp png_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_type, int compression_type, + int filter_type) +{ + int error = 0; + + /* Check for width and height valid values */ + if (width == 0) + { + png_warning(png_ptr, "Image width is zero in IHDR"); + error = 1; + } + + if (height == 0) + { + png_warning(png_ptr, "Image height is zero in IHDR"); + error = 1; + } + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + if (width > png_ptr->user_width_max || width > PNG_USER_WIDTH_MAX) +#else + if (width > PNG_USER_WIDTH_MAX) +#endif + { + png_warning(png_ptr, "Image width exceeds user limit in IHDR"); + error = 1; + } + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + if (height > png_ptr->user_height_max || height > PNG_USER_HEIGHT_MAX) +#else + if (height > PNG_USER_HEIGHT_MAX) +#endif + { + png_warning(png_ptr, "Image height exceeds user limit in IHDR"); + error = 1; + } + + if (width > PNG_UINT_31_MAX) + { + png_warning(png_ptr, "Invalid image width in IHDR"); + error = 1; + } + + if ( height > PNG_UINT_31_MAX) + { + png_warning(png_ptr, "Invalid image height in IHDR"); + error = 1; + } + + if ( width > (PNG_UINT_32_MAX + >> 3) /* 8-byte RGBA pixels */ + - 64 /* bigrowbuf hack */ + - 1 /* filter byte */ + - 7*8 /* rounding of width to multiple of 8 pixels */ + - 8) /* extra max_pixel_depth pad */ + png_warning(png_ptr, "Width is too large for libpng to process pixels"); + + /* Check other values */ + if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 && + bit_depth != 8 && bit_depth != 16) + { + png_warning(png_ptr, "Invalid bit depth in IHDR"); + error = 1; + } + + if (color_type < 0 || color_type == 1 || + color_type == 5 || color_type > 6) + { + png_warning(png_ptr, "Invalid color type in IHDR"); + error = 1; + } + + if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) || + ((color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8)) + { + png_warning(png_ptr, "Invalid color type/bit depth combination in IHDR"); + error = 1; + } + + if (interlace_type >= PNG_INTERLACE_LAST) + { + png_warning(png_ptr, "Unknown interlace method in IHDR"); + error = 1; + } + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + { + png_warning(png_ptr, "Unknown compression method in IHDR"); + error = 1; + } + +#ifdef PNG_MNG_FEATURES_SUPPORTED + /* Accept filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not read a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) && + png_ptr->mng_features_permitted) + png_warning(png_ptr, "MNG features are not allowed in a PNG datastream"); + + if (filter_type != PNG_FILTER_TYPE_BASE) + { + if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (filter_type == PNG_INTRAPIXEL_DIFFERENCING) && + ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) && + (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA))) + { + png_warning(png_ptr, "Unknown filter method in IHDR"); + error = 1; + } + + if (png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) + { + png_warning(png_ptr, "Invalid filter method in IHDR"); + error = 1; + } + } + +#else + if (filter_type != PNG_FILTER_TYPE_BASE) + { + png_warning(png_ptr, "Unknown filter method in IHDR"); + error = 1; + } +#endif + + if (error == 1) + png_error(png_ptr, "Invalid IHDR data"); +} +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ diff --git a/contrib/syslinux-4.02/com32/lib/libpng/pngerror.c b/contrib/syslinux-4.02/com32/lib/libpng/pngerror.c new file mode 100644 index 0000000..7bc98fb --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libpng/pngerror.c @@ -0,0 +1,386 @@ + +/* pngerror.c - stub functions for i/o and memory allocation + * + * Last changed in libpng 1.2.41 [December 3, 2009] + * Copyright (c) 1998-2009 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file provides a location for all error handling. Users who + * need special error handling are expected to write replacement functions + * and use png_set_error_fn() to use those functions. See the instructions + * at each function. + */ + +#define PNG_INTERNAL +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +static void /* PRIVATE */ +png_default_error PNGARG((png_structp png_ptr, + png_const_charp error_message)) PNG_NORETURN; +#ifdef PNG_WARNINGS_SUPPORTED +static void /* PRIVATE */ +png_default_warning PNGARG((png_structp png_ptr, + png_const_charp warning_message)); +#endif /* PNG_WARNINGS_SUPPORTED */ + +/* This function is called whenever there is a fatal error. This function + * should not be changed. If there is a need to handle errors differently, + * you should supply a replacement error function and use png_set_error_fn() + * to replace the error function at run-time. + */ +#ifdef PNG_ERROR_TEXT_SUPPORTED +void PNGAPI +png_error(png_structp png_ptr, png_const_charp error_message) +{ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + char msg[16]; + if (png_ptr != NULL) + { + if (png_ptr->flags& + (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) + { + if (*error_message == PNG_LITERAL_SHARP) + { + /* Strip "#nnnn " from beginning of error message. */ + int offset; + for (offset = 1; offset<15; offset++) + if (error_message[offset] == ' ') + break; + if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) + { + int i; + for (i = 0; i < offset - 1; i++) + msg[i] = error_message[i + 1]; + msg[i - 1] = '\0'; + error_message = msg; + } + else + error_message += offset; + } + else + { + if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) + { + msg[0] = '0'; + msg[1] = '\0'; + error_message = msg; + } + } + } + } +#endif + if (png_ptr != NULL && png_ptr->error_fn != NULL) + (*(png_ptr->error_fn))(png_ptr, error_message); + + /* If the custom handler doesn't exist, or if it returns, + use the default handler, which will not return. */ + png_default_error(png_ptr, error_message); +} +#else +void PNGAPI +png_err(png_structp png_ptr) +{ + if (png_ptr != NULL && png_ptr->error_fn != NULL) + (*(png_ptr->error_fn))(png_ptr, '\0'); + + /* If the custom handler doesn't exist, or if it returns, + use the default handler, which will not return. */ + png_default_error(png_ptr, '\0'); +} +#endif /* PNG_ERROR_TEXT_SUPPORTED */ + +#ifdef PNG_WARNINGS_SUPPORTED +/* This function is called whenever there is a non-fatal error. This function + * should not be changed. If there is a need to handle warnings differently, + * you should supply a replacement warning function and use + * png_set_error_fn() to replace the warning function at run-time. + */ +void PNGAPI +png_warning(png_structp png_ptr, png_const_charp warning_message) +{ + int offset = 0; + if (png_ptr != NULL) + { +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (png_ptr->flags& + (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) +#endif + { + if (*warning_message == PNG_LITERAL_SHARP) + { + for (offset = 1; offset < 15; offset++) + if (warning_message[offset] == ' ') + break; + } + } + } + if (png_ptr != NULL && png_ptr->warning_fn != NULL) + (*(png_ptr->warning_fn))(png_ptr, warning_message + offset); + else + png_default_warning(png_ptr, warning_message + offset); +} +#endif /* PNG_WARNINGS_SUPPORTED */ + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +void PNGAPI +png_benign_error(png_structp png_ptr, png_const_charp error_message) +{ + if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) + png_warning(png_ptr, error_message); + else + png_error(png_ptr, error_message); +} +#endif + +/* These utilities are used internally to build an error message that relates + * to the current chunk. The chunk name comes from png_ptr->chunk_name, + * this is used to prefix the message. The message is limited in length + * to 63 bytes, the name characters are output as hex digits wrapped in [] + * if the character is invalid. + */ +#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) +static PNG_CONST char png_digit[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F' +}; + +#define PNG_MAX_ERROR_TEXT 64 +#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_ERROR_TEXT_SUPPORTED) +static void /* PRIVATE */ +png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp + error_message) +{ + int iout = 0, iin = 0; + + while (iin < 4) + { + int c = png_ptr->chunk_name[iin++]; + if (isnonalpha(c)) + { + buffer[iout++] = PNG_LITERAL_LEFT_SQUARE_BRACKET; + buffer[iout++] = png_digit[(c & 0xf0) >> 4]; + buffer[iout++] = png_digit[c & 0x0f]; + buffer[iout++] = PNG_LITERAL_RIGHT_SQUARE_BRACKET; + } + else + { + buffer[iout++] = (png_byte)c; + } + } + + if (error_message == NULL) + buffer[iout] = '\0'; + else + { + buffer[iout++] = ':'; + buffer[iout++] = ' '; + png_memcpy(buffer + iout, error_message, PNG_MAX_ERROR_TEXT); + buffer[iout + PNG_MAX_ERROR_TEXT - 1] = '\0'; + } +} + +#ifdef PNG_READ_SUPPORTED +void PNGAPI +png_chunk_error(png_structp png_ptr, png_const_charp error_message) +{ + char msg[18+PNG_MAX_ERROR_TEXT]; + if (png_ptr == NULL) + png_error(png_ptr, error_message); + else + { + png_format_buffer(png_ptr, msg, error_message); + png_error(png_ptr, msg); + } +} +#endif /* PNG_READ_SUPPORTED */ +#endif /* PNG_WARNINGS_SUPPORTED || PNG_ERROR_TEXT_SUPPORTED */ + +#ifdef PNG_WARNINGS_SUPPORTED +void PNGAPI +png_chunk_warning(png_structp png_ptr, png_const_charp warning_message) +{ + char msg[18+PNG_MAX_ERROR_TEXT]; + if (png_ptr == NULL) + png_warning(png_ptr, warning_message); + else + { + png_format_buffer(png_ptr, msg, warning_message); + png_warning(png_ptr, msg); + } +} +#endif /* PNG_WARNINGS_SUPPORTED */ + +#ifdef PNG_READ_SUPPORTED +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +void PNGAPI +png_chunk_benign_error(png_structp png_ptr, png_const_charp error_message) +{ + if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) + png_chunk_warning(png_ptr, error_message); + else + png_chunk_error(png_ptr, error_message); +} +#endif +#endif /* PNG_READ_SUPPORTED */ + +/* This is the default error handling function. Note that replacements for + * this function MUST NOT RETURN, or the program will likely crash. This + * function is used by default, or if the program supplies NULL for the + * error function pointer in png_set_error_fn(). + */ +static void /* PRIVATE */ +png_default_error(png_structp png_ptr, png_const_charp error_message) +{ +#ifdef PNG_CONSOLE_IO_SUPPORTED +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (*error_message == PNG_LITERAL_SHARP) + { + /* Strip "#nnnn " from beginning of error message. */ + int offset; + char error_number[16]; + for (offset = 0; offset<15; offset++) + { + error_number[offset] = error_message[offset + 1]; + if (error_message[offset] == ' ') + break; + } + if ((offset > 1) && (offset < 15)) + { + error_number[offset - 1] = '\0'; + fprintf(stderr, "libpng error no. %s: %s", + error_number, error_message + offset + 1); + fprintf(stderr, PNG_STRING_NEWLINE); + } + else + { + fprintf(stderr, "libpng error: %s, offset=%d", + error_message, offset); + fprintf(stderr, PNG_STRING_NEWLINE); + } + } + else +#endif + { + fprintf(stderr, "libpng error: %s", error_message); + fprintf(stderr, PNG_STRING_NEWLINE); + } +#endif + +#ifdef PNG_SETJMP_SUPPORTED + if (png_ptr) + { +# ifdef USE_FAR_KEYWORD + { + jmp_buf jmpbuf; + png_memcpy(jmpbuf, png_ptr->jmpbuf, png_sizeof(jmp_buf)); + longjmp(jmpbuf,1); + } +# else + longjmp(png_ptr->jmpbuf, 1); +# endif + } +#endif + /* Here if not setjmp support or if png_ptr is null. */ + PNG_ABORT(); +#ifndef PNG_CONSOLE_IO_SUPPORTED + error_message = error_message; /* Make compiler happy */ +#endif +} + +#ifdef PNG_WARNINGS_SUPPORTED +/* This function is called when there is a warning, but the library thinks + * it can continue anyway. Replacement functions don't have to do anything + * here if you don't want them to. In the default configuration, png_ptr is + * not used, but it is passed in case it may be useful. + */ +static void /* PRIVATE */ +png_default_warning(png_structp png_ptr, png_const_charp warning_message) +{ +#ifdef PNG_CONSOLE_IO_SUPPORTED +# ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (*warning_message == PNG_LITERAL_SHARP) + { + int offset; + char warning_number[16]; + for (offset = 0; offset < 15; offset++) + { + warning_number[offset] = warning_message[offset + 1]; + if (warning_message[offset] == ' ') + break; + } + if ((offset > 1) && (offset < 15)) + { + warning_number[offset + 1] = '\0'; + fprintf(stderr, "libpng warning no. %s: %s", + warning_number, warning_message + offset); + fprintf(stderr, PNG_STRING_NEWLINE); + } + else + { + fprintf(stderr, "libpng warning: %s", + warning_message); + fprintf(stderr, PNG_STRING_NEWLINE); + } + } + else +# endif + { + fprintf(stderr, "libpng warning: %s", warning_message); + fprintf(stderr, PNG_STRING_NEWLINE); + } +#else + warning_message = warning_message; /* Make compiler happy */ +#endif + png_ptr = png_ptr; /* Make compiler happy */ +} +#endif /* PNG_WARNINGS_SUPPORTED */ + +/* This function is called when the application wants to use another method + * of handling errors and warnings. Note that the error function MUST NOT + * return to the calling routine or serious problems will occur. The return + * method used in the default routine calls longjmp(png_ptr->jmpbuf, 1) + */ +void PNGAPI +png_set_error_fn(png_structp png_ptr, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warning_fn) +{ + if (png_ptr == NULL) + return; + png_ptr->error_ptr = error_ptr; + png_ptr->error_fn = error_fn; + png_ptr->warning_fn = warning_fn; +} + + +/* This function returns a pointer to the error_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy and png_read_destroy are called. + */ +png_voidp PNGAPI +png_get_error_ptr(png_structp png_ptr) +{ + if (png_ptr == NULL) + return NULL; + return ((png_voidp)png_ptr->error_ptr); +} + + +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +void PNGAPI +png_set_strip_error_numbers(png_structp png_ptr, png_uint_32 strip_mode) +{ + if (png_ptr != NULL) + { + png_ptr->flags &= + ((~(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode); + } +} +#endif +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/contrib/syslinux-4.02/com32/lib/libpng/pnggccrd.c b/contrib/syslinux-4.02/com32/lib/libpng/pnggccrd.c new file mode 100644 index 0000000..78b8a7e --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libpng/pnggccrd.c @@ -0,0 +1,103 @@ +/* pnggccrd.c was removed from libpng-1.2.20. */ + +/* This code snippet is for use by configure's compilation test. */ + +#if (!defined _MSC_VER) && \ + defined(PNG_ASSEMBLER_CODE_SUPPORTED) && \ + defined(PNG_MMX_CODE_SUPPORTED) + +int PNGAPI png_dummy_mmx_support(void); + +static int _mmx_supported = 2; // 0: no MMX; 1: MMX supported; 2: not tested + +int PNGAPI +png_dummy_mmx_support(void) __attribute__((noinline)); + +int PNGAPI +png_dummy_mmx_support(void) +{ + int result; +#ifdef PNG_MMX_CODE_SUPPORTED // superfluous, but what the heck + __asm__ __volatile__ ( +#ifdef __x86_64__ + "pushq %%rbx \n\t" // rbx gets clobbered by CPUID instruction + "pushq %%rcx \n\t" // so does rcx... + "pushq %%rdx \n\t" // ...and rdx (but rcx & rdx safe on Linux) + "pushfq \n\t" // save Eflag to stack + "popq %%rax \n\t" // get Eflag from stack into rax + "movq %%rax, %%rcx \n\t" // make another copy of Eflag in rcx + "xorl $0x200000, %%eax \n\t" // toggle ID bit in Eflag (i.e., bit 21) + "pushq %%rax \n\t" // save modified Eflag back to stack + "popfq \n\t" // restore modified value to Eflag reg + "pushfq \n\t" // save Eflag to stack + "popq %%rax \n\t" // get Eflag from stack + "pushq %%rcx \n\t" // save original Eflag to stack + "popfq \n\t" // restore original Eflag +#else + "pushl %%ebx \n\t" // ebx gets clobbered by CPUID instruction + "pushl %%ecx \n\t" // so does ecx... + "pushl %%edx \n\t" // ...and edx (but ecx & edx safe on Linux) + "pushfl \n\t" // save Eflag to stack + "popl %%eax \n\t" // get Eflag from stack into eax + "movl %%eax, %%ecx \n\t" // make another copy of Eflag in ecx + "xorl $0x200000, %%eax \n\t" // toggle ID bit in Eflag (i.e., bit 21) + "pushl %%eax \n\t" // save modified Eflag back to stack + "popfl \n\t" // restore modified value to Eflag reg + "pushfl \n\t" // save Eflag to stack + "popl %%eax \n\t" // get Eflag from stack + "pushl %%ecx \n\t" // save original Eflag to stack + "popfl \n\t" // restore original Eflag +#endif + "xorl %%ecx, %%eax \n\t" // compare new Eflag with original Eflag + "jz 0f \n\t" // if same, CPUID instr. is not supported + + "xorl %%eax, %%eax \n\t" // set eax to zero +// ".byte 0x0f, 0xa2 \n\t" // CPUID instruction (two-byte opcode) + "cpuid \n\t" // get the CPU identification info + "cmpl $1, %%eax \n\t" // make sure eax return non-zero value + "jl 0f \n\t" // if eax is zero, MMX is not supported + + "xorl %%eax, %%eax \n\t" // set eax to zero and... + "incl %%eax \n\t" // ...increment eax to 1. This pair is + // faster than the instruction "mov eax, 1" + "cpuid \n\t" // get the CPU identification info again + "andl $0x800000, %%edx \n\t" // mask out all bits but MMX bit (23) + "cmpl $0, %%edx \n\t" // 0 = MMX not supported + "jz 0f \n\t" // non-zero = yes, MMX IS supported + + "movl $1, %%eax \n\t" // set return value to 1 + "jmp 1f \n\t" // DONE: have MMX support + + "0: \n\t" // .NOT_SUPPORTED: target label for jump instructions + "movl $0, %%eax \n\t" // set return value to 0 + "1: \n\t" // .RETURN: target label for jump instructions +#ifdef __x86_64__ + "popq %%rdx \n\t" // restore rdx + "popq %%rcx \n\t" // restore rcx + "popq %%rbx \n\t" // restore rbx +#else + "popl %%edx \n\t" // restore edx + "popl %%ecx \n\t" // restore ecx + "popl %%ebx \n\t" // restore ebx +#endif + +// "ret \n\t" // DONE: no MMX support + // (fall through to standard C "ret") + + : "=a" (result) // output list + + : // any variables used on input (none) + + // no clobber list +// , "%ebx", "%ecx", "%edx" // GRR: we handle these manually +// , "memory" // if write to a variable gcc thought was in a reg +// , "cc" // "condition codes" (flag bits) + ); + _mmx_supported = result; +#else + _mmx_supported = 0; +#endif /* PNG_MMX_CODE_SUPPORTED */ + + return _mmx_supported; +} +#endif diff --git a/contrib/syslinux-4.02/com32/lib/libpng/pngget.c b/contrib/syslinux-4.02/com32/lib/libpng/pngget.c new file mode 100644 index 0000000..d397329 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libpng/pngget.c @@ -0,0 +1,944 @@ + +/* pngget.c - retrieval of values from info struct + * + * Last changed in libpng 1.2.43 [February 25, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + */ + +#define PNG_INTERNAL +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +png_uint_32 PNGAPI +png_get_valid(png_structp png_ptr, png_infop info_ptr, png_uint_32 flag) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->valid & flag); + + else + return(0); +} + +png_uint_32 PNGAPI +png_get_rowbytes(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->rowbytes); + + else + return(0); +} + +#ifdef PNG_INFO_IMAGE_SUPPORTED +png_bytepp PNGAPI +png_get_rows(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->row_pointers); + + else + return(0); +} +#endif + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Easy access to info, added in libpng-0.99 */ +png_uint_32 PNGAPI +png_get_image_width(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->width; + + return (0); +} + +png_uint_32 PNGAPI +png_get_image_height(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->height; + + return (0); +} + +png_byte PNGAPI +png_get_bit_depth(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->bit_depth; + + return (0); +} + +png_byte PNGAPI +png_get_color_type(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->color_type; + + return (0); +} + +png_byte PNGAPI +png_get_filter_type(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->filter_type; + + return (0); +} + +png_byte PNGAPI +png_get_interlace_type(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->interlace_type; + + return (0); +} + +png_byte PNGAPI +png_get_compression_type(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->compression_type; + + return (0); +} + +png_uint_32 PNGAPI +png_get_x_pixels_per_meter(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#ifdef PNG_pHYs_SUPPORTED + if (info_ptr->valid & PNG_INFO_pHYs) + { + png_debug1(1, "in %s retrieval function", "png_get_x_pixels_per_meter"); + + if (info_ptr->phys_unit_type != PNG_RESOLUTION_METER) + return (0); + + else + return (info_ptr->x_pixels_per_unit); + } +#else + return (0); +#endif + return (0); +} + +png_uint_32 PNGAPI +png_get_y_pixels_per_meter(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#ifdef PNG_pHYs_SUPPORTED + if (info_ptr->valid & PNG_INFO_pHYs) + { + png_debug1(1, "in %s retrieval function", "png_get_y_pixels_per_meter"); + + if (info_ptr->phys_unit_type != PNG_RESOLUTION_METER) + return (0); + + else + return (info_ptr->y_pixels_per_unit); + } +#else + return (0); +#endif + return (0); +} + +png_uint_32 PNGAPI +png_get_pixels_per_meter(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#ifdef PNG_pHYs_SUPPORTED + if (info_ptr->valid & PNG_INFO_pHYs) + { + png_debug1(1, "in %s retrieval function", "png_get_pixels_per_meter"); + + if (info_ptr->phys_unit_type != PNG_RESOLUTION_METER || + info_ptr->x_pixels_per_unit != info_ptr->y_pixels_per_unit) + return (0); + + else + return (info_ptr->x_pixels_per_unit); + } +#else + return (0); +#endif + return (0); +} + +#ifdef PNG_FLOATING_POINT_SUPPORTED +float PNGAPI +png_get_pixel_aspect_ratio(png_structp png_ptr, png_infop info_ptr) + { + if (png_ptr != NULL && info_ptr != NULL) +#ifdef PNG_pHYs_SUPPORTED + + if (info_ptr->valid & PNG_INFO_pHYs) + { + png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio"); + + if (info_ptr->x_pixels_per_unit == 0) + return ((float)0.0); + + else + return ((float)((float)info_ptr->y_pixels_per_unit + /(float)info_ptr->x_pixels_per_unit)); + } +#else + return (0.0); +#endif + return ((float)0.0); +} +#endif + +png_int_32 PNGAPI +png_get_x_offset_microns(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#ifdef PNG_oFFs_SUPPORTED + + if (info_ptr->valid & PNG_INFO_oFFs) + { + png_debug1(1, "in %s retrieval function", "png_get_x_offset_microns"); + + if (info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER) + return (0); + + else + return (info_ptr->x_offset); + } +#else + return (0); +#endif + return (0); +} + +png_int_32 PNGAPI +png_get_y_offset_microns(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + +#ifdef PNG_oFFs_SUPPORTED + if (info_ptr->valid & PNG_INFO_oFFs) + { + png_debug1(1, "in %s retrieval function", "png_get_y_offset_microns"); + + if (info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER) + return (0); + + else + return (info_ptr->y_offset); + } +#else + return (0); +#endif + return (0); +} + +png_int_32 PNGAPI +png_get_x_offset_pixels(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + +#ifdef PNG_oFFs_SUPPORTED + if (info_ptr->valid & PNG_INFO_oFFs) + { + png_debug1(1, "in %s retrieval function", "png_get_x_offset_microns"); + + if (info_ptr->offset_unit_type != PNG_OFFSET_PIXEL) + return (0); + + else + return (info_ptr->x_offset); + } +#else + return (0); +#endif + return (0); +} + +png_int_32 PNGAPI +png_get_y_offset_pixels(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + +#ifdef PNG_oFFs_SUPPORTED + if (info_ptr->valid & PNG_INFO_oFFs) + { + png_debug1(1, "in %s retrieval function", "png_get_y_offset_microns"); + + if (info_ptr->offset_unit_type != PNG_OFFSET_PIXEL) + return (0); + + else + return (info_ptr->y_offset); + } +#else + return (0); +#endif + return (0); +} + +#if defined(PNG_INCH_CONVERSIONS) && defined(PNG_FLOATING_POINT_SUPPORTED) +png_uint_32 PNGAPI +png_get_pixels_per_inch(png_structp png_ptr, png_infop info_ptr) +{ + return ((png_uint_32)((float)png_get_pixels_per_meter(png_ptr, info_ptr) + *.0254 +.5)); +} + +png_uint_32 PNGAPI +png_get_x_pixels_per_inch(png_structp png_ptr, png_infop info_ptr) +{ + return ((png_uint_32)((float)png_get_x_pixels_per_meter(png_ptr, info_ptr) + *.0254 +.5)); +} + +png_uint_32 PNGAPI +png_get_y_pixels_per_inch(png_structp png_ptr, png_infop info_ptr) +{ + return ((png_uint_32)((float)png_get_y_pixels_per_meter(png_ptr, info_ptr) + *.0254 +.5)); +} + +float PNGAPI +png_get_x_offset_inches(png_structp png_ptr, png_infop info_ptr) +{ + return ((float)png_get_x_offset_microns(png_ptr, info_ptr) + *.00003937); +} + +float PNGAPI +png_get_y_offset_inches(png_structp png_ptr, png_infop info_ptr) +{ + return ((float)png_get_y_offset_microns(png_ptr, info_ptr) + *.00003937); +} + +#ifdef PNG_pHYs_SUPPORTED +png_uint_32 PNGAPI +png_get_pHYs_dpi(png_structp png_ptr, png_infop info_ptr, + png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type) +{ + png_uint_32 retval = 0; + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function", "pHYs"); + + if (res_x != NULL) + { + *res_x = info_ptr->x_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + if (res_y != NULL) + { + *res_y = info_ptr->y_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + if (unit_type != NULL) + { + *unit_type = (int)info_ptr->phys_unit_type; + retval |= PNG_INFO_pHYs; + if (*unit_type == 1) + { + if (res_x != NULL) *res_x = (png_uint_32)(*res_x * .0254 + .50); + if (res_y != NULL) *res_y = (png_uint_32)(*res_y * .0254 + .50); + } + } + } + return (retval); +} +#endif /* PNG_pHYs_SUPPORTED */ +#endif /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */ + +/* png_get_channels really belongs in here, too, but it's been around longer */ + +#endif /* PNG_EASY_ACCESS_SUPPORTED */ + +png_byte PNGAPI +png_get_channels(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->channels); + else + return (0); +} + +png_bytep PNGAPI +png_get_signature(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->signature); + else + return (NULL); +} + +#ifdef PNG_bKGD_SUPPORTED +png_uint_32 PNGAPI +png_get_bKGD(png_structp png_ptr, png_infop info_ptr, + png_color_16p *background) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) + && background != NULL) + { + png_debug1(1, "in %s retrieval function", "bKGD"); + + *background = &(info_ptr->background); + return (PNG_INFO_bKGD); + } + return (0); +} +#endif + +#ifdef PNG_cHRM_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_cHRM(png_structp png_ptr, png_infop info_ptr, + double *white_x, double *white_y, double *red_x, double *red_y, + double *green_x, double *green_y, double *blue_x, double *blue_y) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) + { + png_debug1(1, "in %s retrieval function", "cHRM"); + + if (white_x != NULL) + *white_x = (double)info_ptr->x_white; + if (white_y != NULL) + *white_y = (double)info_ptr->y_white; + if (red_x != NULL) + *red_x = (double)info_ptr->x_red; + if (red_y != NULL) + *red_y = (double)info_ptr->y_red; + if (green_x != NULL) + *green_x = (double)info_ptr->x_green; + if (green_y != NULL) + *green_y = (double)info_ptr->y_green; + if (blue_x != NULL) + *blue_x = (double)info_ptr->x_blue; + if (blue_y != NULL) + *blue_y = (double)info_ptr->y_blue; + return (PNG_INFO_cHRM); + } + return (0); +} +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_cHRM_fixed(png_structp png_ptr, png_infop info_ptr, + png_fixed_point *white_x, png_fixed_point *white_y, png_fixed_point *red_x, + png_fixed_point *red_y, png_fixed_point *green_x, png_fixed_point *green_y, + png_fixed_point *blue_x, png_fixed_point *blue_y) +{ + png_debug1(1, "in %s retrieval function", "cHRM"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) + { + if (white_x != NULL) + *white_x = info_ptr->int_x_white; + if (white_y != NULL) + *white_y = info_ptr->int_y_white; + if (red_x != NULL) + *red_x = info_ptr->int_x_red; + if (red_y != NULL) + *red_y = info_ptr->int_y_red; + if (green_x != NULL) + *green_x = info_ptr->int_x_green; + if (green_y != NULL) + *green_y = info_ptr->int_y_green; + if (blue_x != NULL) + *blue_x = info_ptr->int_x_blue; + if (blue_y != NULL) + *blue_y = info_ptr->int_y_blue; + return (PNG_INFO_cHRM); + } + return (0); +} +#endif +#endif + +#ifdef PNG_gAMA_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_gAMA(png_structp png_ptr, png_infop info_ptr, double *file_gamma) +{ + png_debug1(1, "in %s retrieval function", "gAMA"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) + && file_gamma != NULL) + { + *file_gamma = (double)info_ptr->gamma; + return (PNG_INFO_gAMA); + } + return (0); +} +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, + png_fixed_point *int_file_gamma) +{ + png_debug1(1, "in %s retrieval function", "gAMA"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) + && int_file_gamma != NULL) + { + *int_file_gamma = info_ptr->int_gamma; + return (PNG_INFO_gAMA); + } + return (0); +} +#endif +#endif + +#ifdef PNG_sRGB_SUPPORTED +png_uint_32 PNGAPI +png_get_sRGB(png_structp png_ptr, png_infop info_ptr, int *file_srgb_intent) +{ + png_debug1(1, "in %s retrieval function", "sRGB"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB) + && file_srgb_intent != NULL) + { + *file_srgb_intent = (int)info_ptr->srgb_intent; + return (PNG_INFO_sRGB); + } + return (0); +} +#endif + +#ifdef PNG_iCCP_SUPPORTED +png_uint_32 PNGAPI +png_get_iCCP(png_structp png_ptr, png_infop info_ptr, + png_charpp name, int *compression_type, + png_charpp profile, png_uint_32 *proflen) +{ + png_debug1(1, "in %s retrieval function", "iCCP"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP) + && name != NULL && profile != NULL && proflen != NULL) + { + *name = info_ptr->iccp_name; + *profile = info_ptr->iccp_profile; + /* Compression_type is a dummy so the API won't have to change + * if we introduce multiple compression types later. + */ + *proflen = (int)info_ptr->iccp_proflen; + *compression_type = (int)info_ptr->iccp_compression; + return (PNG_INFO_iCCP); + } + return (0); +} +#endif + +#ifdef PNG_sPLT_SUPPORTED +png_uint_32 PNGAPI +png_get_sPLT(png_structp png_ptr, png_infop info_ptr, + png_sPLT_tpp spalettes) +{ + if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL) + { + *spalettes = info_ptr->splt_palettes; + return ((png_uint_32)info_ptr->splt_palettes_num); + } + return (0); +} +#endif + +#ifdef PNG_hIST_SUPPORTED +png_uint_32 PNGAPI +png_get_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p *hist) +{ + png_debug1(1, "in %s retrieval function", "hIST"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) + && hist != NULL) + { + *hist = info_ptr->hist; + return (PNG_INFO_hIST); + } + return (0); +} +#endif + +png_uint_32 PNGAPI +png_get_IHDR(png_structp png_ptr, png_infop info_ptr, + png_uint_32 *width, png_uint_32 *height, int *bit_depth, + int *color_type, int *interlace_type, int *compression_type, + int *filter_type) + +{ + png_debug1(1, "in %s retrieval function", "IHDR"); + + if (png_ptr == NULL || info_ptr == NULL || width == NULL || + height == NULL || bit_depth == NULL || color_type == NULL) + return (0); + + *width = info_ptr->width; + *height = info_ptr->height; + *bit_depth = info_ptr->bit_depth; + *color_type = info_ptr->color_type; + + if (compression_type != NULL) + *compression_type = info_ptr->compression_type; + + if (filter_type != NULL) + *filter_type = info_ptr->filter_type; + + if (interlace_type != NULL) + *interlace_type = info_ptr->interlace_type; + + /* This is redundant if we can be sure that the info_ptr values were all + * assigned in png_set_IHDR(). We do the check anyhow in case an + * application has ignored our advice not to mess with the members + * of info_ptr directly. + */ + png_check_IHDR (png_ptr, info_ptr->width, info_ptr->height, + info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type, + info_ptr->compression_type, info_ptr->filter_type); + + return (1); +} + +#ifdef PNG_oFFs_SUPPORTED +png_uint_32 PNGAPI +png_get_oFFs(png_structp png_ptr, png_infop info_ptr, + png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type) +{ + png_debug1(1, "in %s retrieval function", "oFFs"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) + && offset_x != NULL && offset_y != NULL && unit_type != NULL) + { + *offset_x = info_ptr->x_offset; + *offset_y = info_ptr->y_offset; + *unit_type = (int)info_ptr->offset_unit_type; + return (PNG_INFO_oFFs); + } + return (0); +} +#endif + +#ifdef PNG_pCAL_SUPPORTED +png_uint_32 PNGAPI +png_get_pCAL(png_structp png_ptr, png_infop info_ptr, + png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, int *nparams, + png_charp *units, png_charpp *params) +{ + png_debug1(1, "in %s retrieval function", "pCAL"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL) + && purpose != NULL && X0 != NULL && X1 != NULL && type != NULL && + nparams != NULL && units != NULL && params != NULL) + { + *purpose = info_ptr->pcal_purpose; + *X0 = info_ptr->pcal_X0; + *X1 = info_ptr->pcal_X1; + *type = (int)info_ptr->pcal_type; + *nparams = (int)info_ptr->pcal_nparams; + *units = info_ptr->pcal_units; + *params = info_ptr->pcal_params; + return (PNG_INFO_pCAL); + } + return (0); +} +#endif + +#ifdef PNG_sCAL_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_sCAL(png_structp png_ptr, png_infop info_ptr, + int *unit, double *width, double *height) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + *width = info_ptr->scal_pixel_width; + *height = info_ptr->scal_pixel_height; + return (PNG_INFO_sCAL); + } + return(0); +} +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_sCAL_s(png_structp png_ptr, png_infop info_ptr, + int *unit, png_charpp width, png_charpp height) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + *width = info_ptr->scal_s_width; + *height = info_ptr->scal_s_height; + return (PNG_INFO_sCAL); + } + return(0); +} +#endif +#endif +#endif + +#ifdef PNG_pHYs_SUPPORTED +png_uint_32 PNGAPI +png_get_pHYs(png_structp png_ptr, png_infop info_ptr, + png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type) +{ + png_uint_32 retval = 0; + + png_debug1(1, "in %s retrieval function", "pHYs"); + + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_pHYs)) + { + if (res_x != NULL) + { + *res_x = info_ptr->x_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + + if (res_y != NULL) + { + *res_y = info_ptr->y_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + + if (unit_type != NULL) + { + *unit_type = (int)info_ptr->phys_unit_type; + retval |= PNG_INFO_pHYs; + } + } + return (retval); +} +#endif + +png_uint_32 PNGAPI +png_get_PLTE(png_structp png_ptr, png_infop info_ptr, png_colorp *palette, + int *num_palette) +{ + png_debug1(1, "in %s retrieval function", "PLTE"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_PLTE) + && palette != NULL) + { + *palette = info_ptr->palette; + *num_palette = info_ptr->num_palette; + png_debug1(3, "num_palette = %d", *num_palette); + return (PNG_INFO_PLTE); + } + return (0); +} + +#ifdef PNG_sBIT_SUPPORTED +png_uint_32 PNGAPI +png_get_sBIT(png_structp png_ptr, png_infop info_ptr, png_color_8p *sig_bit) +{ + png_debug1(1, "in %s retrieval function", "sBIT"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT) + && sig_bit != NULL) + { + *sig_bit = &(info_ptr->sig_bit); + return (PNG_INFO_sBIT); + } + return (0); +} +#endif + +#ifdef PNG_TEXT_SUPPORTED +png_uint_32 PNGAPI +png_get_text(png_structp png_ptr, png_infop info_ptr, png_textp *text_ptr, + int *num_text) +{ + if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0) + { + png_debug1(1, "in %s retrieval function", + (png_ptr->chunk_name[0] == '\0' ? "text" + : (png_const_charp)png_ptr->chunk_name)); + + if (text_ptr != NULL) + *text_ptr = info_ptr->text; + + if (num_text != NULL) + *num_text = info_ptr->num_text; + + return ((png_uint_32)info_ptr->num_text); + } + if (num_text != NULL) + *num_text = 0; + return(0); +} +#endif + +#ifdef PNG_tIME_SUPPORTED +png_uint_32 PNGAPI +png_get_tIME(png_structp png_ptr, png_infop info_ptr, png_timep *mod_time) +{ + png_debug1(1, "in %s retrieval function", "tIME"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME) + && mod_time != NULL) + { + *mod_time = &(info_ptr->mod_time); + return (PNG_INFO_tIME); + } + return (0); +} +#endif + +#ifdef PNG_tRNS_SUPPORTED +png_uint_32 PNGAPI +png_get_tRNS(png_structp png_ptr, png_infop info_ptr, + png_bytep *trans, int *num_trans, png_color_16p *trans_values) +{ + png_uint_32 retval = 0; + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + png_debug1(1, "in %s retrieval function", "tRNS"); + + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (trans != NULL) + { + *trans = info_ptr->trans; + retval |= PNG_INFO_tRNS; + } + + if (trans_values != NULL) + *trans_values = &(info_ptr->trans_values); + } + else /* if (info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) */ + { + if (trans_values != NULL) + { + *trans_values = &(info_ptr->trans_values); + retval |= PNG_INFO_tRNS; + } + + if (trans != NULL) + *trans = NULL; + } + if (num_trans != NULL) + { + *num_trans = info_ptr->num_trans; + retval |= PNG_INFO_tRNS; + } + } + return (retval); +} +#endif + +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +png_uint_32 PNGAPI +png_get_unknown_chunks(png_structp png_ptr, png_infop info_ptr, + png_unknown_chunkpp unknowns) +{ + if (png_ptr != NULL && info_ptr != NULL && unknowns != NULL) + { + *unknowns = info_ptr->unknown_chunks; + return ((png_uint_32)info_ptr->unknown_chunks_num); + } + return (0); +} +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +png_byte PNGAPI +png_get_rgb_to_gray_status (png_structp png_ptr) +{ + return (png_byte)(png_ptr? png_ptr->rgb_to_gray_status : 0); +} +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +png_voidp PNGAPI +png_get_user_chunk_ptr(png_structp png_ptr) +{ + return (png_ptr? png_ptr->user_chunk_ptr : NULL); +} +#endif + +png_uint_32 PNGAPI +png_get_compression_buffer_size(png_structp png_ptr) +{ + return (png_uint_32)(png_ptr? png_ptr->zbuf_size : 0L); +} + +#ifdef PNG_ASSEMBLER_CODE_SUPPORTED +#ifndef PNG_1_0_X +/* This function was added to libpng 1.2.0 and should exist by default */ +png_uint_32 PNGAPI +png_get_asm_flags (png_structp png_ptr) +{ + /* Obsolete, to be removed from libpng-1.4.0 */ + return (png_ptr? 0L: 0L); +} + +/* This function was added to libpng 1.2.0 and should exist by default */ +png_uint_32 PNGAPI +png_get_asm_flagmask (int flag_select) +{ + /* Obsolete, to be removed from libpng-1.4.0 */ + flag_select=flag_select; + return 0L; +} + + /* GRR: could add this: && defined(PNG_MMX_CODE_SUPPORTED) */ +/* This function was added to libpng 1.2.0 */ +png_uint_32 PNGAPI +png_get_mmx_flagmask (int flag_select, int *compilerID) +{ + /* Obsolete, to be removed from libpng-1.4.0 */ + flag_select=flag_select; + *compilerID = -1; /* unknown (i.e., no asm/MMX code compiled) */ + return 0L; +} + +/* This function was added to libpng 1.2.0 */ +png_byte PNGAPI +png_get_mmx_bitdepth_threshold (png_structp png_ptr) +{ + /* Obsolete, to be removed from libpng-1.4.0 */ + return (png_ptr? 0: 0); +} + +/* This function was added to libpng 1.2.0 */ +png_uint_32 PNGAPI +png_get_mmx_rowbytes_threshold (png_structp png_ptr) +{ + /* Obsolete, to be removed from libpng-1.4.0 */ + return (png_ptr? 0L: 0L); +} +#endif /* ?PNG_1_0_X */ +#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */ + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +/* These functions were added to libpng 1.2.6 but not enabled +* by default. They will be enabled in libpng-1.4.0 */ +png_uint_32 PNGAPI +png_get_user_width_max (png_structp png_ptr) +{ + return (png_ptr? png_ptr->user_width_max : 0); +} +png_uint_32 PNGAPI +png_get_user_height_max (png_structp png_ptr) +{ + return (png_ptr? png_ptr->user_height_max : 0); +} +#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ + +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/contrib/syslinux-4.02/com32/lib/libpng/pngmem.c b/contrib/syslinux-4.02/com32/lib/libpng/pngmem.c new file mode 100644 index 0000000..91f2765 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libpng/pngmem.c @@ -0,0 +1,641 @@ + +/* pngmem.c - stub functions for memory allocation + * + * Last changed in libpng 1.2.41 [February 25, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file provides a location for all memory allocation. Users who + * need special memory handling are expected to supply replacement + * functions for png_malloc() and png_free(), and to use + * png_create_read_struct_2() and png_create_write_struct_2() to + * identify the replacement functions. + */ + +#define PNG_INTERNAL +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +/* Borland DOS special memory handler */ +#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) +/* If you change this, be sure to change the one in png.h also */ + +/* Allocate memory for a png_struct. The malloc and memset can be replaced + by a single call to calloc() if this is thought to improve performance. */ +png_voidp /* PRIVATE */ +png_create_struct(int type) +{ +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_struct_2(type, png_malloc_ptr_NULL, png_voidp_NULL)); +} + +/* Alternate version of png_create_struct, for use with user-defined malloc. */ +png_voidp /* PRIVATE */ +png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + png_size_t size; + png_voidp struct_ptr; + + if (type == PNG_STRUCT_INFO) + size = png_sizeof(png_info); + else if (type == PNG_STRUCT_PNG) + size = png_sizeof(png_struct); + else + return (png_get_copyright(NULL)); + +#ifdef PNG_USER_MEM_SUPPORTED + if (malloc_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + struct_ptr = (*(malloc_fn))(png_ptr, (png_uint_32)size); + } + else +#endif /* PNG_USER_MEM_SUPPORTED */ + struct_ptr = (png_voidp)farmalloc(size); + if (struct_ptr != NULL) + png_memset(struct_ptr, 0, size); + return (struct_ptr); +} + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct(png_voidp struct_ptr) +{ +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2(struct_ptr, png_free_ptr_NULL, png_voidp_NULL); +} + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn, + png_voidp mem_ptr) +{ +#endif + if (struct_ptr != NULL) + { +#ifdef PNG_USER_MEM_SUPPORTED + if (free_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + (*(free_fn))(png_ptr, struct_ptr); + return; + } +#endif /* PNG_USER_MEM_SUPPORTED */ + farfree (struct_ptr); + } +} + +/* Allocate memory. For reasonable files, size should never exceed + * 64K. However, zlib may allocate more then 64K if you don't tell + * it not to. See zconf.h and png.h for more information. zlib does + * need to allocate exactly 64K, so whatever you call here must + * have the ability to do that. + * + * Borland seems to have a problem in DOS mode for exactly 64K. + * It gives you a segment with an offset of 8 (perhaps to store its + * memory stuff). zlib doesn't like this at all, so we have to + * detect and deal with it. This code should not be needed in + * Windows or OS/2 modes, and only in 16 bit mode. This code has + * been updated by Alexander Lehmann for version 0.89 to waste less + * memory. + * + * Note that we can't use png_size_t for the "size" declaration, + * since on some systems a png_size_t is a 16-bit quantity, and as a + * result, we would be truncating potentially larger memory requests + * (which should cause a fatal error) and introducing major problems. + */ +png_voidp /* PRIVATE */ +png_calloc(png_structp png_ptr, png_uint_32 size) +{ + png_voidp ret; + + ret = (png_malloc(png_ptr, size)); + if (ret != NULL) + png_memset(ret,0,(png_size_t)size); + return (ret); +} + +png_voidp PNGAPI +png_malloc(png_structp png_ptr, png_uint_32 size) +{ + png_voidp ret; + + if (png_ptr == NULL || size == 0) + return (NULL); + +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr->malloc_fn != NULL) + ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size)); + else + ret = (png_malloc_default(png_ptr, size)); + if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of memory!"); + return (ret); +} + +png_voidp PNGAPI +png_malloc_default(png_structp png_ptr, png_uint_32 size) +{ + png_voidp ret; +#endif /* PNG_USER_MEM_SUPPORTED */ + + if (png_ptr == NULL || size == 0) + return (NULL); + +#ifdef PNG_MAX_MALLOC_64K + if (size > (png_uint_32)65536L) + { + png_warning(png_ptr, "Cannot Allocate > 64K"); + ret = NULL; + } + else +#endif + + if (size != (size_t)size) + ret = NULL; + else if (size == (png_uint_32)65536L) + { + if (png_ptr->offset_table == NULL) + { + /* Try to see if we need to do any of this fancy stuff */ + ret = farmalloc(size); + if (ret == NULL || ((png_size_t)ret & 0xffff)) + { + int num_blocks; + png_uint_32 total_size; + png_bytep table; + int i; + png_byte huge * hptr; + + if (ret != NULL) + { + farfree(ret); + ret = NULL; + } + + if (png_ptr->zlib_window_bits > 14) + num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14)); + else + num_blocks = 1; + if (png_ptr->zlib_mem_level >= 7) + num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7)); + else + num_blocks++; + + total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16; + + table = farmalloc(total_size); + + if (table == NULL) + { +#ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out Of Memory."); /* Note "O", "M" */ + else + png_warning(png_ptr, "Out Of Memory."); +#endif + return (NULL); + } + + if ((png_size_t)table & 0xfff0) + { +#ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, + "Farmalloc didn't return normalized pointer"); + else + png_warning(png_ptr, + "Farmalloc didn't return normalized pointer"); +#endif + return (NULL); + } + + png_ptr->offset_table = table; + png_ptr->offset_table_ptr = farmalloc(num_blocks * + png_sizeof(png_bytep)); + + if (png_ptr->offset_table_ptr == NULL) + { +#ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out Of memory."); /* Note "O", "m" */ + else + png_warning(png_ptr, "Out Of memory."); +#endif + return (NULL); + } + + hptr = (png_byte huge *)table; + if ((png_size_t)hptr & 0xf) + { + hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L); + hptr = hptr + 16L; /* "hptr += 16L" fails on Turbo C++ 3.0 */ + } + for (i = 0; i < num_blocks; i++) + { + png_ptr->offset_table_ptr[i] = (png_bytep)hptr; + hptr = hptr + (png_uint_32)65536L; /* "+=" fails on TC++3.0 */ + } + + png_ptr->offset_table_number = num_blocks; + png_ptr->offset_table_count = 0; + png_ptr->offset_table_count_free = 0; + } + } + + if (png_ptr->offset_table_count >= png_ptr->offset_table_number) + { +#ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of Memory."); /* Note "o" and "M" */ + else + png_warning(png_ptr, "Out of Memory."); +#endif + return (NULL); + } + + ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++]; + } + else + ret = farmalloc(size); + +#ifndef PNG_USER_MEM_SUPPORTED + if (ret == NULL) + { + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of memory."); /* Note "o" and "m" */ + else + png_warning(png_ptr, "Out of memory."); /* Note "o" and "m" */ + } +#endif + + return (ret); +} + +/* Free a pointer allocated by png_malloc(). In the default + * configuration, png_ptr is not used, but is passed in case it + * is needed. If ptr is NULL, return without taking any action. + */ +void PNGAPI +png_free(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL || ptr == NULL) + return; + +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr->free_fn != NULL) + { + (*(png_ptr->free_fn))(png_ptr, ptr); + return; + } + else + png_free_default(png_ptr, ptr); +} + +void PNGAPI +png_free_default(png_structp png_ptr, png_voidp ptr) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + + if (png_ptr == NULL || ptr == NULL) + return; + + if (png_ptr->offset_table != NULL) + { + int i; + + for (i = 0; i < png_ptr->offset_table_count; i++) + { + if (ptr == png_ptr->offset_table_ptr[i]) + { + ptr = NULL; + png_ptr->offset_table_count_free++; + break; + } + } + if (png_ptr->offset_table_count_free == png_ptr->offset_table_count) + { + farfree(png_ptr->offset_table); + farfree(png_ptr->offset_table_ptr); + png_ptr->offset_table = NULL; + png_ptr->offset_table_ptr = NULL; + } + } + + if (ptr != NULL) + { + farfree(ptr); + } +} + +#else /* Not the Borland DOS special memory handler */ + +/* Allocate memory for a png_struct or a png_info. The malloc and + memset can be replaced by a single call to calloc() if this is thought + to improve performance noticably. */ +png_voidp /* PRIVATE */ +png_create_struct(int type) +{ +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_struct_2(type, png_malloc_ptr_NULL, png_voidp_NULL)); +} + +/* Allocate memory for a png_struct or a png_info. The malloc and + memset can be replaced by a single call to calloc() if this is thought + to improve performance noticably. */ +png_voidp /* PRIVATE */ +png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + png_size_t size; + png_voidp struct_ptr; + + if (type == PNG_STRUCT_INFO) + size = png_sizeof(png_info); + else if (type == PNG_STRUCT_PNG) + size = png_sizeof(png_struct); + else + return (NULL); + +#ifdef PNG_USER_MEM_SUPPORTED + if (malloc_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + struct_ptr = (*(malloc_fn))(png_ptr, size); + if (struct_ptr != NULL) + png_memset(struct_ptr, 0, size); + return (struct_ptr); + } +#endif /* PNG_USER_MEM_SUPPORTED */ + +#if defined(__TURBOC__) && !defined(__FLAT__) + struct_ptr = (png_voidp)farmalloc(size); +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + struct_ptr = (png_voidp)halloc(size, 1); +# else + struct_ptr = (png_voidp)malloc(size); +# endif +#endif + if (struct_ptr != NULL) + png_memset(struct_ptr, 0, size); + + return (struct_ptr); +} + + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct(png_voidp struct_ptr) +{ +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2(struct_ptr, png_free_ptr_NULL, png_voidp_NULL); +} + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn, + png_voidp mem_ptr) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + if (struct_ptr != NULL) + { +#ifdef PNG_USER_MEM_SUPPORTED + if (free_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + (*(free_fn))(png_ptr, struct_ptr); + return; + } +#endif /* PNG_USER_MEM_SUPPORTED */ +#if defined(__TURBOC__) && !defined(__FLAT__) + farfree(struct_ptr); +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + hfree(struct_ptr); +# else + free(struct_ptr); +# endif +#endif + } +} + +/* Allocate memory. For reasonable files, size should never exceed + * 64K. However, zlib may allocate more then 64K if you don't tell + * it not to. See zconf.h and png.h for more information. zlib does + * need to allocate exactly 64K, so whatever you call here must + * have the ability to do that. + */ + +png_voidp PNGAPI +png_calloc(png_structp png_ptr, png_uint_32 size) +{ + png_voidp ret; + + ret = (png_malloc(png_ptr, size)); + if (ret != NULL) + png_memset(ret,0,(png_size_t)size); + return (ret); +} + +png_voidp PNGAPI +png_malloc(png_structp png_ptr, png_uint_32 size) +{ + png_voidp ret; + +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr == NULL || size == 0) + return (NULL); + + if (png_ptr->malloc_fn != NULL) + ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size)); + else + ret = (png_malloc_default(png_ptr, size)); + if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of Memory!"); + return (ret); +} + +png_voidp PNGAPI +png_malloc_default(png_structp png_ptr, png_uint_32 size) +{ + png_voidp ret; +#endif /* PNG_USER_MEM_SUPPORTED */ + + if (png_ptr == NULL || size == 0) + return (NULL); + +#ifdef PNG_MAX_MALLOC_64K + if (size > (png_uint_32)65536L) + { +#ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Cannot Allocate > 64K"); + else +#endif + return NULL; + } +#endif + + /* Check for overflow */ +#if defined(__TURBOC__) && !defined(__FLAT__) + if (size != (unsigned long)size) + ret = NULL; + else + ret = farmalloc(size); +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + if (size != (unsigned long)size) + ret = NULL; + else + ret = halloc(size, 1); +# else + if (size != (size_t)size) + ret = NULL; + else + ret = malloc((size_t)size); +# endif +#endif + +#ifndef PNG_USER_MEM_SUPPORTED + if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of Memory"); +#endif + + return (ret); +} + +/* Free a pointer allocated by png_malloc(). If ptr is NULL, return + * without taking any action. + */ +void PNGAPI +png_free(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL || ptr == NULL) + return; + +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr->free_fn != NULL) + { + (*(png_ptr->free_fn))(png_ptr, ptr); + return; + } + else + png_free_default(png_ptr, ptr); +} +void PNGAPI +png_free_default(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL || ptr == NULL) + return; + +#endif /* PNG_USER_MEM_SUPPORTED */ + +#if defined(__TURBOC__) && !defined(__FLAT__) + farfree(ptr); +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + hfree(ptr); +# else + free(ptr); +# endif +#endif +} + +#endif /* Not Borland DOS special memory handler */ + +#ifdef PNG_1_0_X +# define png_malloc_warn png_malloc +#else +/* This function was added at libpng version 1.2.3. The png_malloc_warn() + * function will set up png_malloc() to issue a png_warning and return NULL + * instead of issuing a png_error, if it fails to allocate the requested + * memory. + */ +png_voidp PNGAPI +png_malloc_warn(png_structp png_ptr, png_uint_32 size) +{ + png_voidp ptr; + png_uint_32 save_flags; + if (png_ptr == NULL) + return (NULL); + + save_flags = png_ptr->flags; + png_ptr->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK; + ptr = (png_voidp)png_malloc((png_structp)png_ptr, size); + png_ptr->flags=save_flags; + return(ptr); +} +#endif + +png_voidp PNGAPI +png_memcpy_check (png_structp png_ptr, png_voidp s1, png_voidp s2, + png_uint_32 length) +{ + png_size_t size; + + size = (png_size_t)length; + if ((png_uint_32)size != length) + png_error(png_ptr, "Overflow in png_memcpy_check."); + + return(png_memcpy (s1, s2, size)); +} + +png_voidp PNGAPI +png_memset_check (png_structp png_ptr, png_voidp s1, int value, + png_uint_32 length) +{ + png_size_t size; + + size = (png_size_t)length; + if ((png_uint_32)size != length) + png_error(png_ptr, "Overflow in png_memset_check."); + + return (png_memset (s1, value, size)); + +} + +#ifdef PNG_USER_MEM_SUPPORTED +/* This function is called when the application wants to use another method + * of allocating and freeing memory. + */ +void PNGAPI +png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr + malloc_fn, png_free_ptr free_fn) +{ + if (png_ptr != NULL) + { + png_ptr->mem_ptr = mem_ptr; + png_ptr->malloc_fn = malloc_fn; + png_ptr->free_fn = free_fn; + } +} + +/* This function returns a pointer to the mem_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy and png_read_destroy are called. + */ +png_voidp PNGAPI +png_get_mem_ptr(png_structp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); + return ((png_voidp)png_ptr->mem_ptr); +} +#endif /* PNG_USER_MEM_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/contrib/syslinux-4.02/com32/lib/libpng/pngpread.c b/contrib/syslinux-4.02/com32/lib/libpng/pngpread.c new file mode 100644 index 0000000..d066944 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libpng/pngpread.c @@ -0,0 +1,1774 @@ + +/* pngpread.c - read a png file in push mode + * + * Last changed in libpng 1.2.44 [June 26, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#define PNG_INTERNAL +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + +/* Push model modes */ +#define PNG_READ_SIG_MODE 0 +#define PNG_READ_CHUNK_MODE 1 +#define PNG_READ_IDAT_MODE 2 +#define PNG_SKIP_MODE 3 +#define PNG_READ_tEXt_MODE 4 +#define PNG_READ_zTXt_MODE 5 +#define PNG_READ_DONE_MODE 6 +#define PNG_READ_iTXt_MODE 7 +#define PNG_ERROR_MODE 8 + +void PNGAPI +png_process_data(png_structp png_ptr, png_infop info_ptr, + png_bytep buffer, png_size_t buffer_size) +{ + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_push_restore_buffer(png_ptr, buffer, buffer_size); + + while (png_ptr->buffer_size) + { + png_process_some_data(png_ptr, info_ptr); + } +} + +/* What we do with the incoming data depends on what we were previously + * doing before we ran out of data... + */ +void /* PRIVATE */ +png_process_some_data(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr == NULL) + return; + + switch (png_ptr->process_mode) + { + case PNG_READ_SIG_MODE: + { + png_push_read_sig(png_ptr, info_ptr); + break; + } + + case PNG_READ_CHUNK_MODE: + { + png_push_read_chunk(png_ptr, info_ptr); + break; + } + + case PNG_READ_IDAT_MODE: + { + png_push_read_IDAT(png_ptr); + break; + } + +#ifdef PNG_READ_tEXt_SUPPORTED + case PNG_READ_tEXt_MODE: + { + png_push_read_tEXt(png_ptr, info_ptr); + break; + } + +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + case PNG_READ_zTXt_MODE: + { + png_push_read_zTXt(png_ptr, info_ptr); + break; + } + +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + case PNG_READ_iTXt_MODE: + { + png_push_read_iTXt(png_ptr, info_ptr); + break; + } + +#endif + case PNG_SKIP_MODE: + { + png_push_crc_finish(png_ptr); + break; + } + + default: + { + png_ptr->buffer_size = 0; + break; + } + } +} + +/* Read any remaining signature bytes from the stream and compare them with + * the correct PNG signature. It is possible that this routine is called + * with bytes already read from the signature, either because they have been + * checked by the calling application, or because of multiple calls to this + * routine. + */ +void /* PRIVATE */ +png_push_read_sig(png_structp png_ptr, png_infop info_ptr) +{ + png_size_t num_checked = png_ptr->sig_bytes, + num_to_check = 8 - num_checked; + + if (png_ptr->buffer_size < num_to_check) + { + num_to_check = png_ptr->buffer_size; + } + + png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]), + num_to_check); + png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check); + + if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) + { + if (num_checked < 4 && + png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) + png_error(png_ptr, "Not a PNG file"); + else + png_error(png_ptr, "PNG file corrupted by ASCII conversion"); + } + else + { + if (png_ptr->sig_bytes >= 8) + { + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + } + } +} + +void /* PRIVATE */ +png_push_read_chunk(png_structp png_ptr, png_infop info_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_CONST PNG_IHDR; + PNG_CONST PNG_IDAT; + PNG_CONST PNG_IEND; + PNG_CONST PNG_PLTE; +#ifdef PNG_READ_bKGD_SUPPORTED + PNG_CONST PNG_bKGD; +#endif +#ifdef PNG_READ_cHRM_SUPPORTED + PNG_CONST PNG_cHRM; +#endif +#ifdef PNG_READ_gAMA_SUPPORTED + PNG_CONST PNG_gAMA; +#endif +#ifdef PNG_READ_hIST_SUPPORTED + PNG_CONST PNG_hIST; +#endif +#ifdef PNG_READ_iCCP_SUPPORTED + PNG_CONST PNG_iCCP; +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + PNG_CONST PNG_iTXt; +#endif +#ifdef PNG_READ_oFFs_SUPPORTED + PNG_CONST PNG_oFFs; +#endif +#ifdef PNG_READ_pCAL_SUPPORTED + PNG_CONST PNG_pCAL; +#endif +#ifdef PNG_READ_pHYs_SUPPORTED + PNG_CONST PNG_pHYs; +#endif +#ifdef PNG_READ_sBIT_SUPPORTED + PNG_CONST PNG_sBIT; +#endif +#ifdef PNG_READ_sCAL_SUPPORTED + PNG_CONST PNG_sCAL; +#endif +#ifdef PNG_READ_sRGB_SUPPORTED + PNG_CONST PNG_sRGB; +#endif +#ifdef PNG_READ_sPLT_SUPPORTED + PNG_CONST PNG_sPLT; +#endif +#ifdef PNG_READ_tEXt_SUPPORTED + PNG_CONST PNG_tEXt; +#endif +#ifdef PNG_READ_tIME_SUPPORTED + PNG_CONST PNG_tIME; +#endif +#ifdef PNG_READ_tRNS_SUPPORTED + PNG_CONST PNG_tRNS; +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + PNG_CONST PNG_zTXt; +#endif +#endif /* PNG_USE_LOCAL_ARRAYS */ + + /* First we make sure we have enough data for the 4 byte chunk name + * and the 4 byte chunk length before proceeding with decoding the + * chunk data. To fully decode each of these chunks, we also make + * sure we have enough data in the buffer for the 4 byte CRC at the + * end of every chunk (except IDAT, which is handled separately). + */ + if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) + { + png_byte chunk_length[4]; + + if (png_ptr->buffer_size < 8) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_fill_buffer(png_ptr, chunk_length, 4); + png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + png_check_chunk_name(png_ptr, png_ptr->chunk_name); + png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; + } + + if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + if (png_ptr->mode & PNG_AFTER_IDAT) + png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; + + if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) + { + if (png_ptr->push_length != 13) + png_error(png_ptr, "Invalid IHDR length"); + + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length); + } + + else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length); + + png_ptr->process_mode = PNG_READ_DONE_MODE; + png_push_have_end(png_ptr, info_ptr); + } + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_ptr->mode |= PNG_HAVE_IDAT; + + png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); + + if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + png_ptr->mode |= PNG_HAVE_PLTE; + + else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + } + } + +#endif + else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length); + } + + else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + /* If we reach an IDAT chunk, this means we have read all of the + * header chunks, and we can start reading the image (or if this + * is called after the image has been read - we have an error). + */ + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + { + if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + if (png_ptr->push_length == 0) + return; + + if (png_ptr->mode & PNG_AFTER_IDAT) + png_error(png_ptr, "Too many IDAT's found"); + } + + png_ptr->idat_size = png_ptr->push_length; + png_ptr->mode |= PNG_HAVE_IDAT; + png_ptr->process_mode = PNG_READ_IDAT_MODE; + png_push_have_info(png_ptr, info_ptr); + png_ptr->zstream.avail_out = + (uInt) PNG_ROWBYTES(png_ptr->pixel_depth, + png_ptr->iwidth) + 1; + png_ptr->zstream.next_out = png_ptr->row_buf; + return; + } + +#ifdef PNG_READ_gAMA_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_sBIT_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_cHRM_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_sRGB_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_iCCP_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_sPLT_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_tRNS_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_bKGD_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_hIST_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_pHYs_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_oFFs_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length); + } +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_sCAL_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_tIME_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_tEXt_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif + else + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_push_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); + } + + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; +} + +void /* PRIVATE */ +png_push_crc_skip(png_structp png_ptr, png_uint_32 skip) +{ + png_ptr->process_mode = PNG_SKIP_MODE; + png_ptr->skip_length = skip; +} + +void /* PRIVATE */ +png_push_crc_finish(png_structp png_ptr) +{ + if (png_ptr->skip_length && png_ptr->save_buffer_size) + { + png_size_t save_size; + + if (png_ptr->skip_length < (png_uint_32)png_ptr->save_buffer_size) + save_size = (png_size_t)png_ptr->skip_length; + else + save_size = png_ptr->save_buffer_size; + + png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); + + png_ptr->skip_length -= save_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + if (png_ptr->skip_length && png_ptr->current_buffer_size) + { + png_size_t save_size; + + if (png_ptr->skip_length < (png_uint_32)png_ptr->current_buffer_size) + save_size = (png_size_t)png_ptr->skip_length; + else + save_size = png_ptr->current_buffer_size; + + png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_ptr->skip_length -= save_size; + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } + if (!png_ptr->skip_length) + { + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_crc_finish(png_ptr, 0); + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + } +} + +void PNGAPI +png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) +{ + png_bytep ptr; + + if (png_ptr == NULL) + return; + + ptr = buffer; + if (png_ptr->save_buffer_size) + { + png_size_t save_size; + + if (length < png_ptr->save_buffer_size) + save_size = length; + else + save_size = png_ptr->save_buffer_size; + + png_memcpy(ptr, png_ptr->save_buffer_ptr, save_size); + length -= save_size; + ptr += save_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + if (length && png_ptr->current_buffer_size) + { + png_size_t save_size; + + if (length < png_ptr->current_buffer_size) + save_size = length; + + else + save_size = png_ptr->current_buffer_size; + + png_memcpy(ptr, png_ptr->current_buffer_ptr, save_size); + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } +} + +void /* PRIVATE */ +png_push_save_buffer(png_structp png_ptr) +{ + if (png_ptr->save_buffer_size) + { + if (png_ptr->save_buffer_ptr != png_ptr->save_buffer) + { + png_size_t i, istop; + png_bytep sp; + png_bytep dp; + + istop = png_ptr->save_buffer_size; + for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer; + i < istop; i++, sp++, dp++) + { + *dp = *sp; + } + } + } + if (png_ptr->save_buffer_size + png_ptr->current_buffer_size > + png_ptr->save_buffer_max) + { + png_size_t new_max; + png_bytep old_buffer; + + if (png_ptr->save_buffer_size > PNG_SIZE_MAX - + (png_ptr->current_buffer_size + 256)) + { + png_error(png_ptr, "Potential overflow of save_buffer"); + } + + new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256; + old_buffer = png_ptr->save_buffer; + png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr, + (png_uint_32)new_max); + if (png_ptr->save_buffer == NULL) + { + png_free(png_ptr, old_buffer); + png_error(png_ptr, "Insufficient memory for save_buffer"); + } + png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size); + png_free(png_ptr, old_buffer); + png_ptr->save_buffer_max = new_max; + } + if (png_ptr->current_buffer_size) + { + png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size, + png_ptr->current_buffer_ptr, png_ptr->current_buffer_size); + png_ptr->save_buffer_size += png_ptr->current_buffer_size; + png_ptr->current_buffer_size = 0; + } + png_ptr->save_buffer_ptr = png_ptr->save_buffer; + png_ptr->buffer_size = 0; +} + +void /* PRIVATE */ +png_push_restore_buffer(png_structp png_ptr, png_bytep buffer, + png_size_t buffer_length) +{ + png_ptr->current_buffer = buffer; + png_ptr->current_buffer_size = buffer_length; + png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size; + png_ptr->current_buffer_ptr = png_ptr->current_buffer; +} + +void /* PRIVATE */ +png_push_read_IDAT(png_structp png_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_CONST PNG_IDAT; +#endif + if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) + { + png_byte chunk_length[4]; + + if (png_ptr->buffer_size < 8) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_fill_buffer(png_ptr, chunk_length, 4); + png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; + + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + png_error(png_ptr, "Not enough compressed data"); + return; + } + + png_ptr->idat_size = png_ptr->push_length; + } + if (png_ptr->idat_size && png_ptr->save_buffer_size) + { + png_size_t save_size; + + if (png_ptr->idat_size < (png_uint_32)png_ptr->save_buffer_size) + { + save_size = (png_size_t)png_ptr->idat_size; + + /* Check for overflow */ + if ((png_uint_32)save_size != png_ptr->idat_size) + png_error(png_ptr, "save_size overflowed in pngpread"); + } + else + save_size = png_ptr->save_buffer_size; + + png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); + + png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size); + + png_ptr->idat_size -= save_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + if (png_ptr->idat_size && png_ptr->current_buffer_size) + { + png_size_t save_size; + + if (png_ptr->idat_size < (png_uint_32)png_ptr->current_buffer_size) + { + save_size = (png_size_t)png_ptr->idat_size; + + /* Check for overflow */ + if ((png_uint_32)save_size != png_ptr->idat_size) + png_error(png_ptr, "save_size overflowed in pngpread"); + } + else + save_size = png_ptr->current_buffer_size; + + png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_ptr->idat_size -= save_size; + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } + if (!png_ptr->idat_size) + { + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_crc_finish(png_ptr, 0); + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; + png_ptr->mode |= PNG_AFTER_IDAT; + } +} + +void /* PRIVATE */ +png_process_IDAT_data(png_structp png_ptr, png_bytep buffer, + png_size_t buffer_length) +{ + /* The caller checks for a non-zero buffer length. */ + if (!(buffer_length > 0) || buffer == NULL) + png_error(png_ptr, "No IDAT data (internal error)"); + + /* This routine must process all the data it has been given + * before returning, calling the row callback as required to + * handle the uncompressed results. + */ + png_ptr->zstream.next_in = buffer; + png_ptr->zstream.avail_in = (uInt)buffer_length; + + /* Keep going until the decompressed data is all processed + * or the stream marked as finished. + */ + while (png_ptr->zstream.avail_in > 0 && + !(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + { + int ret; + + /* We have data for zlib, but we must check that zlib + * has somewhere to put the results. It doesn't matter + * if we don't expect any results -- it may be the input + * data is just the LZ end code. + */ + if (!(png_ptr->zstream.avail_out > 0)) + { + png_ptr->zstream.avail_out = + (uInt) PNG_ROWBYTES(png_ptr->pixel_depth, + png_ptr->iwidth) + 1; + png_ptr->zstream.next_out = png_ptr->row_buf; + } + + /* Using Z_SYNC_FLUSH here means that an unterminated + * LZ stream can still be handled (a stream with a missing + * end code), otherwise (Z_NO_FLUSH) a future zlib + * implementation might defer output and, therefore, + * change the current behavior. (See comments in inflate.c + * for why this doesn't happen at present with zlib 1.2.5.) + */ + ret = inflate(&png_ptr->zstream, Z_SYNC_FLUSH); + + /* Check for any failure before proceeding. */ + if (ret != Z_OK && ret != Z_STREAM_END) + { + /* Terminate the decompression. */ + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + + /* This may be a truncated stream (missing or + * damaged end code). Treat that as a warning. + */ + if (png_ptr->row_number >= png_ptr->num_rows || + png_ptr->pass > 6) + png_warning(png_ptr, "Truncated compressed data in IDAT"); + else + png_error(png_ptr, "Decompression error in IDAT"); + + /* Skip the check on unprocessed input */ + return; + } + + /* Did inflate output any data? */ + if (png_ptr->zstream.next_out != png_ptr->row_buf) + { + /* Is this unexpected data after the last row? + * If it is, artificially terminate the LZ output + * here. + */ + if (png_ptr->row_number >= png_ptr->num_rows || + png_ptr->pass > 6) + { + /* Extra data. */ + png_warning(png_ptr, "Extra compressed data in IDAT"); + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + /* Do no more processing; skip the unprocessed + * input check below. + */ + return; + } + + /* Do we have a complete row? */ + if (png_ptr->zstream.avail_out == 0) + png_push_process_row(png_ptr); + } + + /* And check for the end of the stream. */ + if (ret == Z_STREAM_END) + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + } + + /* All the data should have been processed, if anything + * is left at this point we have bytes of IDAT data + * after the zlib end code. + */ + if (png_ptr->zstream.avail_in > 0) + png_warning(png_ptr, "Extra compression data"); +} + +void /* PRIVATE */ +png_push_process_row(png_structp png_ptr) +{ + png_ptr->row_info.color_type = png_ptr->color_type; + png_ptr->row_info.width = png_ptr->iwidth; + png_ptr->row_info.channels = png_ptr->channels; + png_ptr->row_info.bit_depth = png_ptr->bit_depth; + png_ptr->row_info.pixel_depth = png_ptr->pixel_depth; + + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + + png_read_filter_row(png_ptr, &(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->prev_row + 1, + (int)(png_ptr->row_buf[0])); + + png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf, + png_ptr->rowbytes + 1); + + if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) + png_do_read_transformations(png_ptr); + +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Blow up interlaced rows to full size */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + if (png_ptr->pass < 6) +/* old interface (pre-1.0.9): + png_do_read_interlace(&(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); + */ + png_do_read_interlace(png_ptr); + + switch (png_ptr->pass) + { + case 0: + { + int i; + for (i = 0; i < 8 && png_ptr->pass == 0; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); /* Updates png_ptr->pass */ + } + + if (png_ptr->pass == 2) /* Pass 1 might be empty */ + { + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } + + if (png_ptr->pass == 4 && png_ptr->height <= 4) + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } + + if (png_ptr->pass == 6 && png_ptr->height <= 4) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + + break; + } + + case 1: + { + int i; + for (i = 0; i < 8 && png_ptr->pass == 1; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 2) /* Skip top 4 generated rows */ + { + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } + + break; + } + + case 2: + { + int i; + + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 4) /* Pass 3 might be empty */ + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } + + break; + } + + case 3: + { + int i; + + for (i = 0; i < 4 && png_ptr->pass == 3; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 4) /* Skip top two generated rows */ + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } + + break; + } + + case 4: + { + int i; + + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 6) /* Pass 5 might be empty */ + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + + break; + } + + case 5: + { + int i; + + for (i = 0; i < 2 && png_ptr->pass == 5; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 6) /* Skip top generated row */ + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + + break; + } + case 6: + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + + if (png_ptr->pass != 6) + break; + + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } + } + else +#endif + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } +} + +void /* PRIVATE */ +png_read_push_finish_row(png_structp png_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + PNG_CONST int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + PNG_CONST int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + PNG_CONST int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + PNG_CONST int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; + + /* Height of interlace block. This is not currently used - if you need + * it, uncomment it here and in png.h + PNG_CONST int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; + */ +#endif + + png_ptr->row_number++; + if (png_ptr->row_number < png_ptr->num_rows) + return; + +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + png_memset_check(png_ptr, png_ptr->prev_row, 0, + png_ptr->rowbytes + 1); + do + { + png_ptr->pass++; + if ((png_ptr->pass == 1 && png_ptr->width < 5) || + (png_ptr->pass == 3 && png_ptr->width < 3) || + (png_ptr->pass == 5 && png_ptr->width < 2)) + png_ptr->pass++; + + if (png_ptr->pass > 7) + png_ptr->pass--; + + if (png_ptr->pass >= 7) + break; + + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + if (png_ptr->transformations & PNG_INTERLACE) + break; + + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + + } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0); + } +#endif /* PNG_READ_INTERLACING_SUPPORTED */ +} + +#ifdef PNG_READ_tEXt_SUPPORTED +void /* PRIVATE */ +png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + png_error(png_ptr, "Out of place tEXt"); + info_ptr = info_ptr; /* To quiet some compiler warnings */ + } + +#ifdef PNG_MAX_MALLOC_64K + png_ptr->skip_length = 0; /* This may not be necessary */ + + if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ + { + png_warning(png_ptr, "tEXt chunk too large to fit in memory"); + png_ptr->skip_length = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, + (png_uint_32)(length + 1)); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_tEXt_MODE; +} + +void /* PRIVATE */ +png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + + else + text_size = png_ptr->current_text_left; + + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp text; + png_charp key; + int ret; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + +#ifdef PNG_MAX_MALLOC_64K + if (png_ptr->skip_length) + return; +#endif + + key = png_ptr->current_text; + + for (text = key; *text; text++) + /* Empty loop */ ; + + if (text < key + png_ptr->current_text_size) + text++; + + text_ptr = (png_textp)png_malloc(png_ptr, + (png_uint_32)png_sizeof(png_text)); + text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr->key = key; +#ifdef PNG_iTXt_SUPPORTED + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; +#endif + text_ptr->text = text; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, key); + png_free(png_ptr, text_ptr); + png_ptr->current_text = NULL; + + if (ret) + png_warning(png_ptr, "Insufficient memory to store text chunk."); + } +} +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED +void /* PRIVATE */ +png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + png_error(png_ptr, "Out of place zTXt"); + info_ptr = info_ptr; /* To quiet some compiler warnings */ + } + +#ifdef PNG_MAX_MALLOC_64K + /* We can't handle zTXt chunks > 64K, since we don't have enough space + * to be able to store the uncompressed data. Actually, the threshold + * is probably around 32K, but it isn't as definite as 64K is. + */ + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "zTXt chunk too large to fit in memory"); + png_push_crc_skip(png_ptr, length); + return; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, + (png_uint_32)(length + 1)); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_zTXt_MODE; +} + +void /* PRIVATE */ +png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + + else + text_size = png_ptr->current_text_left; + + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp text; + png_charp key; + int ret; + png_size_t text_size, key_size; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + + key = png_ptr->current_text; + + for (text = key; *text; text++) + /* Empty loop */ ; + + /* zTXt can't have zero text */ + if (text >= key + png_ptr->current_text_size) + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + return; + } + + text++; + + if (*text != PNG_TEXT_COMPRESSION_zTXt) /* Check compression byte */ + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + return; + } + + text++; + + png_ptr->zstream.next_in = (png_bytep )text; + png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size - + (text - key)); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + key_size = text - key; + text_size = 0; + text = NULL; + ret = Z_STREAM_END; + + while (png_ptr->zstream.avail_in) + { + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) + { + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + png_ptr->current_text = NULL; + png_free(png_ptr, key); + png_free(png_ptr, text); + return; + } + if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END) + { + if (text == NULL) + { + text = (png_charp)png_malloc(png_ptr, + (png_uint_32)(png_ptr->zbuf_size + - png_ptr->zstream.avail_out + key_size + 1)); + + png_memcpy(text + key_size, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + + png_memcpy(text, key, key_size); + + text_size = key_size + png_ptr->zbuf_size - + png_ptr->zstream.avail_out; + + *(text + text_size) = '\0'; + } + else + { + png_charp tmp; + + tmp = text; + text = (png_charp)png_malloc(png_ptr, text_size + + (png_uint_32)(png_ptr->zbuf_size + - png_ptr->zstream.avail_out + 1)); + + png_memcpy(text, tmp, text_size); + png_free(png_ptr, tmp); + + png_memcpy(text + text_size, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + + text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; + *(text + text_size) = '\0'; + } + if (ret != Z_STREAM_END) + { + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + } + else + { + break; + } + + if (ret == Z_STREAM_END) + break; + } + + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + + if (ret != Z_STREAM_END) + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + png_free(png_ptr, text); + return; + } + + png_ptr->current_text = NULL; + png_free(png_ptr, key); + key = text; + text += key_size; + + text_ptr = (png_textp)png_malloc(png_ptr, + (png_uint_32)png_sizeof(png_text)); + text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt; + text_ptr->key = key; +#ifdef PNG_iTXt_SUPPORTED + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; +#endif + text_ptr->text = text; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, key); + png_free(png_ptr, text_ptr); + + if (ret) + png_warning(png_ptr, "Insufficient memory to store text chunk."); + } +} +#endif + +#ifdef PNG_READ_iTXt_SUPPORTED +void /* PRIVATE */ +png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + png_error(png_ptr, "Out of place iTXt"); + info_ptr = info_ptr; /* To quiet some compiler warnings */ + } + +#ifdef PNG_MAX_MALLOC_64K + png_ptr->skip_length = 0; /* This may not be necessary */ + + if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ + { + png_warning(png_ptr, "iTXt chunk too large to fit in memory"); + png_ptr->skip_length = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, + (png_uint_32)(length + 1)); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_iTXt_MODE; +} + +void /* PRIVATE */ +png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr) +{ + + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + + else + text_size = png_ptr->current_text_left; + + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp key; + int comp_flag; + png_charp lang; + png_charp lang_key; + png_charp text; + int ret; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + +#ifdef PNG_MAX_MALLOC_64K + if (png_ptr->skip_length) + return; +#endif + + key = png_ptr->current_text; + + for (lang = key; *lang; lang++) + /* Empty loop */ ; + + if (lang < key + png_ptr->current_text_size - 3) + lang++; + + comp_flag = *lang++; + lang++; /* Skip comp_type, always zero */ + + for (lang_key = lang; *lang_key; lang_key++) + /* Empty loop */ ; + + lang_key++; /* Skip NUL separator */ + + text=lang_key; + + if (lang_key < key + png_ptr->current_text_size - 1) + { + for (; *text; text++) + /* Empty loop */ ; + } + + if (text < key + png_ptr->current_text_size) + text++; + + text_ptr = (png_textp)png_malloc(png_ptr, + (png_uint_32)png_sizeof(png_text)); + + text_ptr->compression = comp_flag + 2; + text_ptr->key = key; + text_ptr->lang = lang; + text_ptr->lang_key = lang_key; + text_ptr->text = text; + text_ptr->text_length = 0; + text_ptr->itxt_length = png_strlen(text); + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_ptr->current_text = NULL; + + png_free(png_ptr, text_ptr); + if (ret) + png_warning(png_ptr, "Insufficient memory to store iTXt chunk."); + } +} +#endif + +/* This function is called when we haven't found a handler for this + * chunk. If there isn't a problem with the chunk itself (ie a bad chunk + * name or a critical chunk), the chunk is (currently) silently ignored. + */ +void /* PRIVATE */ +png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + png_uint_32 skip = 0; + + if (!(png_ptr->chunk_name[0] & 0x20)) + { +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + && png_ptr->read_user_chunk_fn == NULL +#endif + ) +#endif + png_chunk_error(png_ptr, "unknown critical chunk"); + + info_ptr = info_ptr; /* To quiet some compiler warnings */ + } + +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) + { +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "unknown chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + png_memcpy((png_charp)png_ptr->unknown_chunk.name, + (png_charp)png_ptr->chunk_name, + png_sizeof(png_ptr->unknown_chunk.name)); + png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name) - 1] + = '\0'; + + png_ptr->unknown_chunk.size = (png_size_t)length; + + if (length == 0) + png_ptr->unknown_chunk.data = NULL; + + else + { + png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, + (png_uint_32)length); + png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length); + } + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + if (png_ptr->read_user_chunk_fn != NULL) + { + /* Callback to user unknown chunk handler */ + int ret; + ret = (*(png_ptr->read_user_chunk_fn)) + (png_ptr, &png_ptr->unknown_chunk); + + if (ret < 0) + png_chunk_error(png_ptr, "error in user chunk"); + + if (ret == 0) + { + if (!(png_ptr->chunk_name[0] & 0x20)) + if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS) + png_chunk_error(png_ptr, "unknown critical chunk"); + png_set_unknown_chunks(png_ptr, info_ptr, + &png_ptr->unknown_chunk, 1); + } + } + + else +#endif + png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; + } + + else +#endif + skip=length; + png_push_crc_skip(png_ptr, skip); +} + +void /* PRIVATE */ +png_push_have_info(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->info_fn != NULL) + (*(png_ptr->info_fn))(png_ptr, info_ptr); +} + +void /* PRIVATE */ +png_push_have_end(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->end_fn != NULL) + (*(png_ptr->end_fn))(png_ptr, info_ptr); +} + +void /* PRIVATE */ +png_push_have_row(png_structp png_ptr, png_bytep row) +{ + if (png_ptr->row_fn != NULL) + (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number, + (int)png_ptr->pass); +} + +void PNGAPI +png_progressive_combine_row (png_structp png_ptr, + png_bytep old_row, png_bytep new_row) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_CONST int FARDATA png_pass_dsp_mask[7] = + {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff}; +#endif + + if (png_ptr == NULL) + return; + + if (new_row != NULL) /* new_row must == png_ptr->row_buf here. */ + png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]); +} + +void PNGAPI +png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr, + png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, + png_progressive_end_ptr end_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->info_fn = info_fn; + png_ptr->row_fn = row_fn; + png_ptr->end_fn = end_fn; + + png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer); +} + +png_voidp PNGAPI +png_get_progressive_ptr(png_structp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); + + return png_ptr->io_ptr; +} +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ diff --git a/contrib/syslinux-4.02/com32/lib/libpng/pngread.c b/contrib/syslinux-4.02/com32/lib/libpng/pngread.c new file mode 100644 index 0000000..6207624 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libpng/pngread.c @@ -0,0 +1,1528 @@ + +/* pngread.c - read a PNG file + * + * Last changed in libpng 1.2.44 [June 26, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file contains routines that an application calls directly to + * read a PNG file or stream. + */ + +#define PNG_INTERNAL +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" +#ifdef PNG_READ_SUPPORTED + + +/* Create a PNG structure for reading, and allocate any memory needed. */ +png_structp PNGAPI +png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn) +{ + +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn, + warn_fn, png_voidp_NULL, png_malloc_ptr_NULL, png_free_ptr_NULL)); +} + +/* Alternate create PNG structure for reading, and allocate any memory + * needed. + */ +png_structp PNGAPI +png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + +#ifdef PNG_SETJMP_SUPPORTED + volatile +#endif + png_structp png_ptr; + +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf jmpbuf; +#endif +#endif + + int i; + + png_debug(1, "in png_create_read_struct"); + +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, + (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr); +#else + png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); +#endif + if (png_ptr == NULL) + return (NULL); + + /* Added at libpng-1.2.6 */ +#ifdef PNG_USER_LIMITS_SUPPORTED + png_ptr->user_width_max = PNG_USER_WIDTH_MAX; + png_ptr->user_height_max = PNG_USER_HEIGHT_MAX; +# ifdef PNG_USER_CHUNK_CACHE_MAX + /* Added at libpng-1.2.43 and 1.4.0 */ + png_ptr->user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX; +# endif +# ifdef PNG_SET_USER_CHUNK_MALLOC_MAX + /* Added at libpng-1.2.43 and 1.4.1 */ + png_ptr->user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX; +# endif +#endif + +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) +#else + if (setjmp(png_ptr->jmpbuf)) +#endif + { + png_free(png_ptr, png_ptr->zbuf); + png_ptr->zbuf = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, + (png_free_ptr)free_fn, (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + return (NULL); + } +#ifdef USE_FAR_KEYWORD + png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf)); +#endif +#endif /* PNG_SETJMP_SUPPORTED */ + +#ifdef PNG_USER_MEM_SUPPORTED + png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); +#endif + + png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); + + if (user_png_ver) + { + i = 0; + do + { + if (user_png_ver[i] != png_libpng_ver[i]) + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + } while (png_libpng_ver[i++]); + } + else + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + + + if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) + { + /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so + * we must recompile any applications that use any older library version. + * For versions after libpng 1.0, we will be compatible, so we need + * only check the first digit. + */ + if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || + (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || + (user_png_ver[0] == '0' && user_png_ver[2] < '9')) + { +#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE) + char msg[80]; + if (user_png_ver) + { + png_snprintf(msg, 80, + "Application was compiled with png.h from libpng-%.20s", + user_png_ver); + png_warning(png_ptr, msg); + } + png_snprintf(msg, 80, + "Application is running with png.c from libpng-%.20s", + png_libpng_ver); + png_warning(png_ptr, msg); +#endif +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags = 0; +#endif + png_error(png_ptr, + "Incompatible libpng version in application and library"); + } + } + + /* Initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); + png_ptr->zstream.zalloc = png_zalloc; + png_ptr->zstream.zfree = png_zfree; + png_ptr->zstream.opaque = (voidpf)png_ptr; + + switch (inflateInit(&png_ptr->zstream)) + { + case Z_OK: /* Do nothing */ break; + case Z_MEM_ERROR: + case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error"); + break; + case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error"); + break; + default: png_error(png_ptr, "Unknown zlib error"); + } + + + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL); + +#ifdef PNG_SETJMP_SUPPORTED +/* Applications that neglect to set up their own setjmp() and then + encounter a png_error() will longjmp here. Since the jmpbuf is + then meaningless we abort instead of returning. */ +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) + PNG_ABORT(); + png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf)); +#else + if (setjmp(png_ptr->jmpbuf)) + PNG_ABORT(); +#endif +#endif /* PNG_SETJMP_SUPPORTED */ + + return (png_ptr); +} + +#if defined(PNG_1_0_X) || defined(PNG_1_2_X) +/* Initialize PNG structure for reading, and allocate any memory needed. + * This interface is deprecated in favour of the png_create_read_struct(), + * and it will disappear as of libpng-1.3.0. + */ +#undef png_read_init +void PNGAPI +png_read_init(png_structp png_ptr) +{ + /* We only come here via pre-1.0.7-compiled applications */ + png_read_init_2(png_ptr, "1.0.6 or earlier", 0, 0); +} + +void PNGAPI +png_read_init_2(png_structp png_ptr, png_const_charp user_png_ver, + png_size_t png_struct_size, png_size_t png_info_size) +{ + /* We only come here via pre-1.0.12-compiled applications */ + if (png_ptr == NULL) + return; +#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE) + if (png_sizeof(png_struct) > png_struct_size || + png_sizeof(png_info) > png_info_size) + { + char msg[80]; + png_ptr->warning_fn = NULL; + if (user_png_ver) + { + png_snprintf(msg, 80, + "Application was compiled with png.h from libpng-%.20s", + user_png_ver); + png_warning(png_ptr, msg); + } + png_snprintf(msg, 80, + "Application is running with png.c from libpng-%.20s", + png_libpng_ver); + png_warning(png_ptr, msg); + } +#endif + if (png_sizeof(png_struct) > png_struct_size) + { + png_ptr->error_fn = NULL; +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags = 0; +#endif + png_error(png_ptr, + "The png struct allocated by the application for reading is" + " too small."); + } + if (png_sizeof(png_info) > png_info_size) + { + png_ptr->error_fn = NULL; +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags = 0; +#endif + png_error(png_ptr, + "The info struct allocated by application for reading is" + " too small."); + } + png_read_init_3(&png_ptr, user_png_ver, png_struct_size); +} +#endif /* PNG_1_0_X || PNG_1_2_X */ + +void PNGAPI +png_read_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver, + png_size_t png_struct_size) +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf tmp_jmp; /* to save current jump buffer */ +#endif + + int i = 0; + + png_structp png_ptr=*ptr_ptr; + + if (png_ptr == NULL) + return; + + do + { + if (user_png_ver[i] != png_libpng_ver[i]) + { +#ifdef PNG_LEGACY_SUPPORTED + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; +#else + png_ptr->warning_fn = NULL; + png_warning(png_ptr, + "Application uses deprecated png_read_init() and should be" + " recompiled."); + break; +#endif + } + } while (png_libpng_ver[i++]); + + png_debug(1, "in png_read_init_3"); + +#ifdef PNG_SETJMP_SUPPORTED + /* Save jump buffer and error functions */ + png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf)); +#endif + + if (png_sizeof(png_struct) > png_struct_size) + { + png_destroy_struct(png_ptr); + *ptr_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); + png_ptr = *ptr_ptr; + } + + /* Reset all variables to 0 */ + png_memset(png_ptr, 0, png_sizeof(png_struct)); + +#ifdef PNG_SETJMP_SUPPORTED + /* Restore jump buffer */ + png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf)); +#endif + + /* Added at libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_ptr->user_width_max = PNG_USER_WIDTH_MAX; + png_ptr->user_height_max = PNG_USER_HEIGHT_MAX; +#endif + + /* Initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + png_ptr->zstream.zalloc = png_zalloc; + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); + png_ptr->zstream.zalloc = png_zalloc; + png_ptr->zstream.zfree = png_zfree; + png_ptr->zstream.opaque = (voidpf)png_ptr; + + switch (inflateInit(&png_ptr->zstream)) + { + case Z_OK: /* Do nothing */ break; + case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error"); break; + case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error"); + break; + default: png_error(png_ptr, "Unknown zlib error"); + } + + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL); +} + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the information before the actual image data. This has been + * changed in v0.90 to allow reading a file that already has the magic + * bytes read from the stream. You can tell libpng how many bytes have + * been read from the beginning of the stream (up to the maximum of 8) + * via png_set_sig_bytes(), and we will only check the remaining bytes + * here. The application can then have access to the signature bytes we + * read if it is determined that this isn't a valid PNG file. + */ +void PNGAPI +png_read_info(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_info"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* If we haven't checked all of the PNG signature bytes, do so now. */ + if (png_ptr->sig_bytes < 8) + { + png_size_t num_checked = png_ptr->sig_bytes, + num_to_check = 8 - num_checked; + + png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check); + png_ptr->sig_bytes = 8; + + if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) + { + if (num_checked < 4 && + png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) + png_error(png_ptr, "Not a PNG file"); + else + png_error(png_ptr, "PNG file corrupted by ASCII conversion"); + } + if (num_checked < 3) + png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; + } + + for (;;) + { +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_CONST PNG_IHDR; + PNG_CONST PNG_IDAT; + PNG_CONST PNG_IEND; + PNG_CONST PNG_PLTE; +#ifdef PNG_READ_bKGD_SUPPORTED + PNG_CONST PNG_bKGD; +#endif +#ifdef PNG_READ_cHRM_SUPPORTED + PNG_CONST PNG_cHRM; +#endif +#ifdef PNG_READ_gAMA_SUPPORTED + PNG_CONST PNG_gAMA; +#endif +#ifdef PNG_READ_hIST_SUPPORTED + PNG_CONST PNG_hIST; +#endif +#ifdef PNG_READ_iCCP_SUPPORTED + PNG_CONST PNG_iCCP; +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + PNG_CONST PNG_iTXt; +#endif +#ifdef PNG_READ_oFFs_SUPPORTED + PNG_CONST PNG_oFFs; +#endif +#ifdef PNG_READ_pCAL_SUPPORTED + PNG_CONST PNG_pCAL; +#endif +#ifdef PNG_READ_pHYs_SUPPORTED + PNG_CONST PNG_pHYs; +#endif +#ifdef PNG_READ_sBIT_SUPPORTED + PNG_CONST PNG_sBIT; +#endif +#ifdef PNG_READ_sCAL_SUPPORTED + PNG_CONST PNG_sCAL; +#endif +#ifdef PNG_READ_sPLT_SUPPORTED + PNG_CONST PNG_sPLT; +#endif +#ifdef PNG_READ_sRGB_SUPPORTED + PNG_CONST PNG_sRGB; +#endif +#ifdef PNG_READ_tEXt_SUPPORTED + PNG_CONST PNG_tEXt; +#endif +#ifdef PNG_READ_tIME_SUPPORTED + PNG_CONST PNG_tIME; +#endif +#ifdef PNG_READ_tRNS_SUPPORTED + PNG_CONST PNG_tRNS; +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + PNG_CONST PNG_zTXt; +#endif +#endif /* PNG_USE_LOCAL_ARRAYS */ + png_uint_32 length = png_read_chunk_header(png_ptr); + PNG_CONST png_bytep chunk_name = png_ptr->chunk_name; + + /* This should be a binary subdivision search or a hash for + * matching the chunk name rather than a linear search. + */ + if (!png_memcmp(chunk_name, png_IDAT, 4)) + if (png_ptr->mode & PNG_AFTER_IDAT) + png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; + + if (!png_memcmp(chunk_name, png_IHDR, 4)) + png_handle_IHDR(png_ptr, info_ptr, length); + else if (!png_memcmp(chunk_name, png_IEND, 4)) + png_handle_IEND(png_ptr, info_ptr, length); +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if (png_handle_as_unknown(png_ptr, chunk_name)) + { + if (!png_memcmp(chunk_name, png_IDAT, 4)) + png_ptr->mode |= PNG_HAVE_IDAT; + png_handle_unknown(png_ptr, info_ptr, length); + if (!png_memcmp(chunk_name, png_PLTE, 4)) + png_ptr->mode |= PNG_HAVE_PLTE; + else if (!png_memcmp(chunk_name, png_IDAT, 4)) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + break; + } + } +#endif + else if (!png_memcmp(chunk_name, png_PLTE, 4)) + png_handle_PLTE(png_ptr, info_ptr, length); + else if (!png_memcmp(chunk_name, png_IDAT, 4)) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + + png_ptr->idat_size = length; + png_ptr->mode |= PNG_HAVE_IDAT; + break; + } +#ifdef PNG_READ_bKGD_SUPPORTED + else if (!png_memcmp(chunk_name, png_bKGD, 4)) + png_handle_bKGD(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_cHRM_SUPPORTED + else if (!png_memcmp(chunk_name, png_cHRM, 4)) + png_handle_cHRM(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_gAMA_SUPPORTED + else if (!png_memcmp(chunk_name, png_gAMA, 4)) + png_handle_gAMA(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_hIST_SUPPORTED + else if (!png_memcmp(chunk_name, png_hIST, 4)) + png_handle_hIST(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_oFFs_SUPPORTED + else if (!png_memcmp(chunk_name, png_oFFs, 4)) + png_handle_oFFs(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_pCAL_SUPPORTED + else if (!png_memcmp(chunk_name, png_pCAL, 4)) + png_handle_pCAL(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_sCAL_SUPPORTED + else if (!png_memcmp(chunk_name, png_sCAL, 4)) + png_handle_sCAL(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_pHYs_SUPPORTED + else if (!png_memcmp(chunk_name, png_pHYs, 4)) + png_handle_pHYs(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_sBIT_SUPPORTED + else if (!png_memcmp(chunk_name, png_sBIT, 4)) + png_handle_sBIT(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_sRGB_SUPPORTED + else if (!png_memcmp(chunk_name, png_sRGB, 4)) + png_handle_sRGB(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_iCCP_SUPPORTED + else if (!png_memcmp(chunk_name, png_iCCP, 4)) + png_handle_iCCP(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_sPLT_SUPPORTED + else if (!png_memcmp(chunk_name, png_sPLT, 4)) + png_handle_sPLT(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_tEXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_tEXt, 4)) + png_handle_tEXt(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_tIME_SUPPORTED + else if (!png_memcmp(chunk_name, png_tIME, 4)) + png_handle_tIME(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_tRNS_SUPPORTED + else if (!png_memcmp(chunk_name, png_tRNS, 4)) + png_handle_tRNS(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_zTXt, 4)) + png_handle_zTXt(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_iTXt, 4)) + png_handle_iTXt(png_ptr, info_ptr, length); +#endif + else + png_handle_unknown(png_ptr, info_ptr, length); + } +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +/* Optional call to update the users info_ptr structure */ +void PNGAPI +png_read_update_info(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_update_info"); + + if (png_ptr == NULL) + return; + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); + else + png_warning(png_ptr, + "Ignoring extra png_read_update_info() call; row buffer not reallocated"); + + png_read_transform_info(png_ptr, info_ptr); +} + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Initialize palette, background, etc, after transformations + * are set, but before any reading takes place. This allows + * the user to obtain a gamma-corrected palette, for example. + * If the user doesn't call this, we will do it ourselves. + */ +void PNGAPI +png_start_read_image(png_structp png_ptr) +{ + png_debug(1, "in png_start_read_image"); + + if (png_ptr == NULL) + return; + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +void PNGAPI +png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row) +{ + PNG_CONST PNG_IDAT; + PNG_CONST int png_pass_dsp_mask[7] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, + 0xff}; + PNG_CONST int png_pass_mask[7] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff}; + int ret; + + if (png_ptr == NULL) + return; + + png_debug2(1, "in png_read_row (row %lu, pass %d)", + png_ptr->row_number, png_ptr->pass); + + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); + if (png_ptr->row_number == 0 && png_ptr->pass == 0) + { + /* Check for transforms that have been set but were defined out */ +#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \ + !defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined."); +#endif + } + +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* If interlaced and we do not need a new row, combine row and return */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + switch (png_ptr->pass) + { + case 0: + if (png_ptr->row_number & 0x07) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 1: + if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 2: + if ((png_ptr->row_number & 0x07) != 4) + { + if (dsp_row != NULL && (png_ptr->row_number & 4)) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 3: + if ((png_ptr->row_number & 3) || png_ptr->width < 3) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 4: + if ((png_ptr->row_number & 3) != 2) + { + if (dsp_row != NULL && (png_ptr->row_number & 2)) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 5: + if ((png_ptr->row_number & 1) || png_ptr->width < 2) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 6: + if (!(png_ptr->row_number & 1)) + { + png_read_finish_row(png_ptr); + return; + } + break; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IDAT)) + png_error(png_ptr, "Invalid attempt to read row data"); + + png_ptr->zstream.next_out = png_ptr->row_buf; + png_ptr->zstream.avail_out = + (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth, + png_ptr->iwidth) + 1); + do + { + if (!(png_ptr->zstream.avail_in)) + { + while (!png_ptr->idat_size) + { + png_crc_finish(png_ptr, 0); + + png_ptr->idat_size = png_read_chunk_header(png_ptr); + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_error(png_ptr, "Not enough image data"); + } + png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_in = png_ptr->zbuf; + if (png_ptr->zbuf_size > png_ptr->idat_size) + png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; + png_crc_read(png_ptr, png_ptr->zbuf, + (png_size_t)png_ptr->zstream.avail_in); + png_ptr->idat_size -= png_ptr->zstream.avail_in; + } + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret == Z_STREAM_END) + { + if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in || + png_ptr->idat_size) + png_error(png_ptr, "Extra compressed data"); + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + if (ret != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : + "Decompression error"); + + } while (png_ptr->zstream.avail_out); + + png_ptr->row_info.color_type = png_ptr->color_type; + png_ptr->row_info.width = png_ptr->iwidth; + png_ptr->row_info.channels = png_ptr->channels; + png_ptr->row_info.bit_depth = png_ptr->bit_depth; + png_ptr->row_info.pixel_depth = png_ptr->pixel_depth; + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + + if (png_ptr->row_buf[0]) + png_read_filter_row(png_ptr, &(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->prev_row + 1, + (int)(png_ptr->row_buf[0])); + + png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf, + png_ptr->rowbytes + 1); + +#ifdef PNG_MNG_FEATURES_SUPPORTED + if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) + { + /* Intrapixel differencing */ + png_do_read_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1); + } +#endif + + + if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) + png_do_read_transformations(png_ptr); + +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Blow up interlaced rows to full size */ + if (png_ptr->interlaced && + (png_ptr->transformations & PNG_INTERLACE)) + { + if (png_ptr->pass < 6) + /* Old interface (pre-1.0.9): + * png_do_read_interlace(&(png_ptr->row_info), + * png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); + */ + png_do_read_interlace(png_ptr); + + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + if (row != NULL) + png_combine_row(png_ptr, row, + png_pass_mask[png_ptr->pass]); + } + else +#endif + { + if (row != NULL) + png_combine_row(png_ptr, row, 0xff); + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, 0xff); + } + png_read_finish_row(png_ptr); + + if (png_ptr->read_row_fn != NULL) + (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read one or more rows of image data. If the image is interlaced, + * and png_set_interlace_handling() has been called, the rows need to + * contain the contents of the rows from the previous pass. If the + * image has alpha or transparency, and png_handle_alpha()[*] has been + * called, the rows contents must be initialized to the contents of the + * screen. + * + * "row" holds the actual image, and pixels are placed in it + * as they arrive. If the image is displayed after each pass, it will + * appear to "sparkle" in. "display_row" can be used to display a + * "chunky" progressive image, with finer detail added as it becomes + * available. If you do not want this "chunky" display, you may pass + * NULL for display_row. If you do not want the sparkle display, and + * you have not called png_handle_alpha(), you may pass NULL for rows. + * If you have called png_handle_alpha(), and the image has either an + * alpha channel or a transparency chunk, you must provide a buffer for + * rows. In this case, you do not have to provide a display_row buffer + * also, but you may. If the image is not interlaced, or if you have + * not called png_set_interlace_handling(), the display_row buffer will + * be ignored, so pass NULL to it. + * + * [*] png_handle_alpha() does not exist yet, as of this version of libpng + */ + +void PNGAPI +png_read_rows(png_structp png_ptr, png_bytepp row, + png_bytepp display_row, png_uint_32 num_rows) +{ + png_uint_32 i; + png_bytepp rp; + png_bytepp dp; + + png_debug(1, "in png_read_rows"); + + if (png_ptr == NULL) + return; + rp = row; + dp = display_row; + if (rp != NULL && dp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep rptr = *rp++; + png_bytep dptr = *dp++; + + png_read_row(png_ptr, rptr, dptr); + } + else if (rp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep rptr = *rp; + png_read_row(png_ptr, rptr, png_bytep_NULL); + rp++; + } + else if (dp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep dptr = *dp; + png_read_row(png_ptr, png_bytep_NULL, dptr); + dp++; + } +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the entire image. If the image has an alpha channel or a tRNS + * chunk, and you have called png_handle_alpha()[*], you will need to + * initialize the image to the current image that PNG will be overlaying. + * We set the num_rows again here, in case it was incorrectly set in + * png_read_start_row() by a call to png_read_update_info() or + * png_start_read_image() if png_set_interlace_handling() wasn't called + * prior to either of these functions like it should have been. You can + * only call this function once. If you desire to have an image for + * each pass of a interlaced image, use png_read_rows() instead. + * + * [*] png_handle_alpha() does not exist yet, as of this version of libpng + */ +void PNGAPI +png_read_image(png_structp png_ptr, png_bytepp image) +{ + png_uint_32 i, image_height; + int pass, j; + png_bytepp rp; + + png_debug(1, "in png_read_image"); + + if (png_ptr == NULL) + return; + +#ifdef PNG_READ_INTERLACING_SUPPORTED + pass = png_set_interlace_handling(png_ptr); +#else + if (png_ptr->interlaced) + png_error(png_ptr, + "Cannot read interlaced image -- interlace handler disabled."); + pass = 1; +#endif + + + image_height=png_ptr->height; + png_ptr->num_rows = image_height; /* Make sure this is set correctly */ + + for (j = 0; j < pass; j++) + { + rp = image; + for (i = 0; i < image_height; i++) + { + png_read_row(png_ptr, *rp, png_bytep_NULL); + rp++; + } + } +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the end of the PNG file. Will not read past the end of the + * file, will verify the end is accurate, and will read any comments + * or time information at the end of the file, if info is not NULL. + */ +void PNGAPI +png_read_end(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_end"); + + if (png_ptr == NULL) + return; + png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */ + + do + { +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_CONST PNG_IHDR; + PNG_CONST PNG_IDAT; + PNG_CONST PNG_IEND; + PNG_CONST PNG_PLTE; +#ifdef PNG_READ_bKGD_SUPPORTED + PNG_CONST PNG_bKGD; +#endif +#ifdef PNG_READ_cHRM_SUPPORTED + PNG_CONST PNG_cHRM; +#endif +#ifdef PNG_READ_gAMA_SUPPORTED + PNG_CONST PNG_gAMA; +#endif +#ifdef PNG_READ_hIST_SUPPORTED + PNG_CONST PNG_hIST; +#endif +#ifdef PNG_READ_iCCP_SUPPORTED + PNG_CONST PNG_iCCP; +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + PNG_CONST PNG_iTXt; +#endif +#ifdef PNG_READ_oFFs_SUPPORTED + PNG_CONST PNG_oFFs; +#endif +#ifdef PNG_READ_pCAL_SUPPORTED + PNG_CONST PNG_pCAL; +#endif +#ifdef PNG_READ_pHYs_SUPPORTED + PNG_CONST PNG_pHYs; +#endif +#ifdef PNG_READ_sBIT_SUPPORTED + PNG_CONST PNG_sBIT; +#endif +#ifdef PNG_READ_sCAL_SUPPORTED + PNG_CONST PNG_sCAL; +#endif +#ifdef PNG_READ_sPLT_SUPPORTED + PNG_CONST PNG_sPLT; +#endif +#ifdef PNG_READ_sRGB_SUPPORTED + PNG_CONST PNG_sRGB; +#endif +#ifdef PNG_READ_tEXt_SUPPORTED + PNG_CONST PNG_tEXt; +#endif +#ifdef PNG_READ_tIME_SUPPORTED + PNG_CONST PNG_tIME; +#endif +#ifdef PNG_READ_tRNS_SUPPORTED + PNG_CONST PNG_tRNS; +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + PNG_CONST PNG_zTXt; +#endif +#endif /* PNG_USE_LOCAL_ARRAYS */ + png_uint_32 length = png_read_chunk_header(png_ptr); + PNG_CONST png_bytep chunk_name = png_ptr->chunk_name; + + if (!png_memcmp(chunk_name, png_IHDR, 4)) + png_handle_IHDR(png_ptr, info_ptr, length); + else if (!png_memcmp(chunk_name, png_IEND, 4)) + png_handle_IEND(png_ptr, info_ptr, length); +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if (png_handle_as_unknown(png_ptr, chunk_name)) + { + if (!png_memcmp(chunk_name, png_IDAT, 4)) + { + if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + png_error(png_ptr, "Too many IDAT's found"); + } + png_handle_unknown(png_ptr, info_ptr, length); + if (!png_memcmp(chunk_name, png_PLTE, 4)) + png_ptr->mode |= PNG_HAVE_PLTE; + } +#endif + else if (!png_memcmp(chunk_name, png_IDAT, 4)) + { + /* Zero length IDATs are legal after the last IDAT has been + * read, but not after other chunks have been read. + */ + if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + png_error(png_ptr, "Too many IDAT's found"); + png_crc_finish(png_ptr, length); + } + else if (!png_memcmp(chunk_name, png_PLTE, 4)) + png_handle_PLTE(png_ptr, info_ptr, length); +#ifdef PNG_READ_bKGD_SUPPORTED + else if (!png_memcmp(chunk_name, png_bKGD, 4)) + png_handle_bKGD(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_cHRM_SUPPORTED + else if (!png_memcmp(chunk_name, png_cHRM, 4)) + png_handle_cHRM(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_gAMA_SUPPORTED + else if (!png_memcmp(chunk_name, png_gAMA, 4)) + png_handle_gAMA(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_hIST_SUPPORTED + else if (!png_memcmp(chunk_name, png_hIST, 4)) + png_handle_hIST(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_oFFs_SUPPORTED + else if (!png_memcmp(chunk_name, png_oFFs, 4)) + png_handle_oFFs(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_pCAL_SUPPORTED + else if (!png_memcmp(chunk_name, png_pCAL, 4)) + png_handle_pCAL(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_sCAL_SUPPORTED + else if (!png_memcmp(chunk_name, png_sCAL, 4)) + png_handle_sCAL(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_pHYs_SUPPORTED + else if (!png_memcmp(chunk_name, png_pHYs, 4)) + png_handle_pHYs(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_sBIT_SUPPORTED + else if (!png_memcmp(chunk_name, png_sBIT, 4)) + png_handle_sBIT(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_sRGB_SUPPORTED + else if (!png_memcmp(chunk_name, png_sRGB, 4)) + png_handle_sRGB(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_iCCP_SUPPORTED + else if (!png_memcmp(chunk_name, png_iCCP, 4)) + png_handle_iCCP(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_sPLT_SUPPORTED + else if (!png_memcmp(chunk_name, png_sPLT, 4)) + png_handle_sPLT(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_tEXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_tEXt, 4)) + png_handle_tEXt(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_tIME_SUPPORTED + else if (!png_memcmp(chunk_name, png_tIME, 4)) + png_handle_tIME(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_tRNS_SUPPORTED + else if (!png_memcmp(chunk_name, png_tRNS, 4)) + png_handle_tRNS(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_zTXt, 4)) + png_handle_zTXt(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_iTXt, 4)) + png_handle_iTXt(png_ptr, info_ptr, length); +#endif + else + png_handle_unknown(png_ptr, info_ptr, length); + } while (!(png_ptr->mode & PNG_HAVE_IEND)); +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +/* Free all memory used by the read */ +void PNGAPI +png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, + png_infopp end_info_ptr_ptr) +{ + png_structp png_ptr = NULL; + png_infop info_ptr = NULL, end_info_ptr = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn = NULL; + png_voidp mem_ptr = NULL; +#endif + + png_debug(1, "in png_destroy_read_struct"); + + if (png_ptr_ptr != NULL) + png_ptr = *png_ptr_ptr; + if (png_ptr == NULL) + return; + +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; + mem_ptr = png_ptr->mem_ptr; +#endif + + if (info_ptr_ptr != NULL) + info_ptr = *info_ptr_ptr; + + if (end_info_ptr_ptr != NULL) + end_info_ptr = *end_info_ptr_ptr; + + png_read_destroy(png_ptr, info_ptr, end_info_ptr); + + if (info_ptr != NULL) + { +#ifdef PNG_TEXT_SUPPORTED + png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, -1); +#endif + +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)info_ptr); +#endif + *info_ptr_ptr = NULL; + } + + if (end_info_ptr != NULL) + { +#ifdef PNG_READ_TEXT_SUPPORTED + png_free_data(png_ptr, end_info_ptr, PNG_FREE_TEXT, -1); +#endif +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)end_info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)end_info_ptr); +#endif + *end_info_ptr_ptr = NULL; + } + + if (png_ptr != NULL) + { +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + *png_ptr_ptr = NULL; + } +} + +/* Free all memory used by the read (old method) */ +void /* PRIVATE */ +png_read_destroy(png_structp png_ptr, png_infop info_ptr, + png_infop end_info_ptr) +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf tmp_jmp; +#endif + png_error_ptr error_fn; + png_error_ptr warning_fn; + png_voidp error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn; +#endif + + png_debug(1, "in png_read_destroy"); + + if (info_ptr != NULL) + png_info_destroy(png_ptr, info_ptr); + + if (end_info_ptr != NULL) + png_info_destroy(png_ptr, end_info_ptr); + + png_free(png_ptr, png_ptr->zbuf); + png_free(png_ptr, png_ptr->big_row_buf); + png_free(png_ptr, png_ptr->prev_row); + png_free(png_ptr, png_ptr->chunkdata); +#ifdef PNG_READ_DITHER_SUPPORTED + png_free(png_ptr, png_ptr->palette_lookup); + png_free(png_ptr, png_ptr->dither_index); +#endif +#ifdef PNG_READ_GAMMA_SUPPORTED + png_free(png_ptr, png_ptr->gamma_table); +#endif +#ifdef PNG_READ_BACKGROUND_SUPPORTED + png_free(png_ptr, png_ptr->gamma_from_1); + png_free(png_ptr, png_ptr->gamma_to_1); +#endif +#ifdef PNG_FREE_ME_SUPPORTED + if (png_ptr->free_me & PNG_FREE_PLTE) + png_zfree(png_ptr, png_ptr->palette); + png_ptr->free_me &= ~PNG_FREE_PLTE; +#else + if (png_ptr->flags & PNG_FLAG_FREE_PLTE) + png_zfree(png_ptr, png_ptr->palette); + png_ptr->flags &= ~PNG_FLAG_FREE_PLTE; +#endif +#if defined(PNG_tRNS_SUPPORTED) || \ + defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) +#ifdef PNG_FREE_ME_SUPPORTED + if (png_ptr->free_me & PNG_FREE_TRNS) + png_free(png_ptr, png_ptr->trans); + png_ptr->free_me &= ~PNG_FREE_TRNS; +#else + if (png_ptr->flags & PNG_FLAG_FREE_TRNS) + png_free(png_ptr, png_ptr->trans); + png_ptr->flags &= ~PNG_FLAG_FREE_TRNS; +#endif +#endif +#ifdef PNG_READ_hIST_SUPPORTED +#ifdef PNG_FREE_ME_SUPPORTED + if (png_ptr->free_me & PNG_FREE_HIST) + png_free(png_ptr, png_ptr->hist); + png_ptr->free_me &= ~PNG_FREE_HIST; +#else + if (png_ptr->flags & PNG_FLAG_FREE_HIST) + png_free(png_ptr, png_ptr->hist); + png_ptr->flags &= ~PNG_FLAG_FREE_HIST; +#endif +#endif +#ifdef PNG_READ_GAMMA_SUPPORTED + if (png_ptr->gamma_16_table != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_table[i]); + } + png_free(png_ptr, png_ptr->gamma_16_table); + } +#ifdef PNG_READ_BACKGROUND_SUPPORTED + if (png_ptr->gamma_16_from_1 != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_from_1[i]); + } + png_free(png_ptr, png_ptr->gamma_16_from_1); + } + if (png_ptr->gamma_16_to_1 != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_to_1[i]); + } + png_free(png_ptr, png_ptr->gamma_16_to_1); + } +#endif +#endif +#ifdef PNG_TIME_RFC1123_SUPPORTED + png_free(png_ptr, png_ptr->time_buffer); +#endif + + inflateEnd(&png_ptr->zstream); +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + png_free(png_ptr, png_ptr->save_buffer); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +#ifdef PNG_TEXT_SUPPORTED + png_free(png_ptr, png_ptr->current_text); +#endif /* PNG_TEXT_SUPPORTED */ +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + + /* Save the important info out of the png_struct, in case it is + * being used again. + */ +#ifdef PNG_SETJMP_SUPPORTED + png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf)); +#endif + + error_fn = png_ptr->error_fn; + warning_fn = png_ptr->warning_fn; + error_ptr = png_ptr->error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; +#endif + + png_memset(png_ptr, 0, png_sizeof(png_struct)); + + png_ptr->error_fn = error_fn; + png_ptr->warning_fn = warning_fn; + png_ptr->error_ptr = error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr->free_fn = free_fn; +#endif + +#ifdef PNG_SETJMP_SUPPORTED + png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf)); +#endif + +} + +void PNGAPI +png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn) +{ + if (png_ptr == NULL) + return; + png_ptr->read_row_fn = read_row_fn; +} + + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +#ifdef PNG_INFO_IMAGE_SUPPORTED +void PNGAPI +png_read_png(png_structp png_ptr, png_infop info_ptr, + int transforms, + voidp params) +{ + int row; + + if (png_ptr == NULL) + return; +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED + /* Invert the alpha channel from opacity to transparency + */ + if (transforms & PNG_TRANSFORM_INVERT_ALPHA) + png_set_invert_alpha(png_ptr); +#endif + + /* png_read_info() gives us all of the information from the + * PNG file before the first IDAT (image data chunk). + */ + png_read_info(png_ptr, info_ptr); + if (info_ptr->height > PNG_UINT_32_MAX/png_sizeof(png_bytep)) + png_error(png_ptr, "Image is too high to process with png_read_png()"); + + /* -------------- image transformations start here ------------------- */ + +#ifdef PNG_READ_16_TO_8_SUPPORTED + /* Tell libpng to strip 16 bit/color files down to 8 bits per color. + */ + if (transforms & PNG_TRANSFORM_STRIP_16) + png_set_strip_16(png_ptr); +#endif + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + /* Strip alpha bytes from the input data without combining with + * the background (not recommended). + */ + if (transforms & PNG_TRANSFORM_STRIP_ALPHA) + png_set_strip_alpha(png_ptr); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED) + /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single + * byte into separate bytes (useful for paletted and grayscale images). + */ + if (transforms & PNG_TRANSFORM_PACKING) + png_set_packing(png_ptr); +#endif + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + /* Change the order of packed pixels to least significant bit first + * (not useful if you are using png_set_packing). + */ + if (transforms & PNG_TRANSFORM_PACKSWAP) + png_set_packswap(png_ptr); +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED + /* Expand paletted colors into true RGB triplets + * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel + * Expand paletted or RGB images with transparency to full alpha + * channels so the data will be available as RGBA quartets. + */ + if (transforms & PNG_TRANSFORM_EXPAND) + if ((png_ptr->bit_depth < 8) || + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) || + (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) + png_set_expand(png_ptr); +#endif + + /* We don't handle background color or gamma transformation or dithering. + */ + +#ifdef PNG_READ_INVERT_SUPPORTED + /* Invert monochrome files to have 0 as white and 1 as black + */ + if (transforms & PNG_TRANSFORM_INVERT_MONO) + png_set_invert_mono(png_ptr); +#endif + +#ifdef PNG_READ_SHIFT_SUPPORTED + /* If you want to shift the pixel values from the range [0,255] or + * [0,65535] to the original [0,7] or [0,31], or whatever range the + * colors were originally in: + */ + if ((transforms & PNG_TRANSFORM_SHIFT) + && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) + { + png_color_8p sig_bit; + + png_get_sBIT(png_ptr, info_ptr, &sig_bit); + png_set_shift(png_ptr, sig_bit); + } +#endif + +#ifdef PNG_READ_BGR_SUPPORTED + /* Flip the RGB pixels to BGR (or RGBA to BGRA) + */ + if (transforms & PNG_TRANSFORM_BGR) + png_set_bgr(png_ptr); +#endif + +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED + /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) + */ + if (transforms & PNG_TRANSFORM_SWAP_ALPHA) + png_set_swap_alpha(png_ptr); +#endif + +#ifdef PNG_READ_SWAP_SUPPORTED + /* Swap bytes of 16 bit files to least significant byte first + */ + if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) + png_set_swap(png_ptr); +#endif + +/* Added at libpng-1.2.41 */ +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED + /* Invert the alpha channel from opacity to transparency + */ + if (transforms & PNG_TRANSFORM_INVERT_ALPHA) + png_set_invert_alpha(png_ptr); +#endif + +/* Added at libpng-1.2.41 */ +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + /* Expand grayscale image to RGB + */ + if (transforms & PNG_TRANSFORM_GRAY_TO_RGB) + png_set_gray_to_rgb(png_ptr); +#endif + + /* We don't handle adding filler bytes */ + + /* Optional call to gamma correct and add the background to the palette + * and update info structure. REQUIRED if you are expecting libpng to + * update the palette for you (i.e., you selected such a transform above). + */ + png_read_update_info(png_ptr, info_ptr); + + /* -------------- image transformations end here ------------------- */ + +#ifdef PNG_FREE_ME_SUPPORTED + png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); +#endif + if (info_ptr->row_pointers == NULL) + { + info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr, + info_ptr->height * png_sizeof(png_bytep)); + png_memset(info_ptr->row_pointers, 0, info_ptr->height + * png_sizeof(png_bytep)); + +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_ROWS; +#endif + + for (row = 0; row < (int)info_ptr->height; row++) + info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr, + png_get_rowbytes(png_ptr, info_ptr)); + } + + png_read_image(png_ptr, info_ptr->row_pointers); + info_ptr->valid |= PNG_INFO_IDAT; + + /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */ + png_read_end(png_ptr, info_ptr); + + transforms = transforms; /* Quiet compiler warnings */ + params = params; + +} +#endif /* PNG_INFO_IMAGE_SUPPORTED */ +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED */ diff --git a/contrib/syslinux-4.02/com32/lib/libpng/pngrio.c b/contrib/syslinux-4.02/com32/lib/libpng/pngrio.c new file mode 100644 index 0000000..6978682 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libpng/pngrio.c @@ -0,0 +1,180 @@ + +/* pngrio.c - functions for data input + * + * Last changed in libpng 1.2.43 [February 25, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file provides a location for all input. Users who need + * special handling are expected to write a function that has the same + * arguments as this and performs a similar function, but that possibly + * has a different input method. Note that you shouldn't change this + * function, but rather write a replacement function and then make + * libpng use it at run time with png_set_read_fn(...). + */ + +#define PNG_INTERNAL +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" +#ifdef PNG_READ_SUPPORTED + +/* Read the data from whatever input you are using. The default routine + * reads from a file pointer. Note that this routine sometimes gets called + * with very small lengths, so you should implement some kind of simple + * buffering if you are using unbuffered reads. This should never be asked + * to read more then 64K on a 16 bit machine. + */ +void /* PRIVATE */ +png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_debug1(4, "reading %d bytes", (int)length); + + if (png_ptr->read_data_fn != NULL) + (*(png_ptr->read_data_fn))(png_ptr, data, length); + else + png_error(png_ptr, "Call to NULL read function"); +} + +#ifdef PNG_STDIO_SUPPORTED +/* This is the function that does the actual reading of data. If you are + * not reading from a standard C stream, you should create a replacement + * read_data function and use it at run time with png_set_read_fn(), rather + * than changing the library. + */ +#ifndef USE_FAR_KEYWORD +void PNGAPI +png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + + if (png_ptr == NULL) + return; + /* fread() returns 0 on error, so it is OK to store this in a png_size_t + * instead of an int, which is what fread() actually returns. + */ +#ifdef _WIN32_WCE + if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) + check = 0; +#else + check = (png_size_t)fread(data, (png_size_t)1, length, + (png_FILE_p)png_ptr->io_ptr); +#endif + + if (check != length) + png_error(png_ptr, "Read Error"); +} +#else +/* This is the model-independent version. Since the standard I/O library + can't handle far buffers in the medium and small models, we have to copy + the data. +*/ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +static void PNGAPI +png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + int check; + png_byte *n_data; + png_FILE_p io_ptr; + + if (png_ptr == NULL) + return; + /* Check if data really is near. If so, use usual code. */ + n_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); + if ((png_bytep)n_data == data) + { +#ifdef _WIN32_WCE + if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, + NULL) ) + check = 0; +#else + check = fread(n_data, 1, length, io_ptr); +#endif + } + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t read, remaining, err; + check = 0; + remaining = length; + do + { + read = MIN(NEAR_BUF_SIZE, remaining); +#ifdef _WIN32_WCE + if ( !ReadFile((HANDLE)(io_ptr), buf, read, &err, NULL) ) + err = 0; +#else + err = fread(buf, (png_size_t)1, read, io_ptr); +#endif + png_memcpy(data, buf, read); /* copy far buffer to near buffer */ + if (err != read) + break; + else + check += err; + data += read; + remaining -= read; + } + while (remaining != 0); + } + if ((png_uint_32)check != (png_uint_32)length) + png_error(png_ptr, "read Error"); +} +#endif +#endif + +/* This function allows the application to supply a new input function + * for libpng if standard C streams aren't being used. + * + * This function takes as its arguments: + * png_ptr - pointer to a png input data structure + * io_ptr - pointer to user supplied structure containing info about + * the input functions. May be NULL. + * read_data_fn - pointer to a new input function that takes as its + * arguments a pointer to a png_struct, a pointer to + * a location where input data can be stored, and a 32-bit + * unsigned int that is the number of bytes to be read. + * To exit and output any fatal error messages the new write + * function should call png_error(png_ptr, "Error msg"). + * May be NULL, in which case libpng's default function will + * be used. + */ +void PNGAPI +png_set_read_fn(png_structp png_ptr, png_voidp io_ptr, + png_rw_ptr read_data_fn) +{ + if (png_ptr == NULL) + return; + png_ptr->io_ptr = io_ptr; + +#ifdef PNG_STDIO_SUPPORTED + if (read_data_fn != NULL) + png_ptr->read_data_fn = read_data_fn; + else + png_ptr->read_data_fn = png_default_read_data; +#else + png_ptr->read_data_fn = read_data_fn; +#endif + + /* It is an error to write to a read device */ + if (png_ptr->write_data_fn != NULL) + { + png_ptr->write_data_fn = NULL; + png_warning(png_ptr, + "It's an error to set both read_data_fn and write_data_fn in the "); + png_warning(png_ptr, + "same structure. Resetting write_data_fn to NULL."); + } + +#ifdef PNG_WRITE_FLUSH_SUPPORTED + png_ptr->output_flush_fn = NULL; +#endif +} +#endif /* PNG_READ_SUPPORTED */ diff --git a/contrib/syslinux-4.02/com32/lib/libpng/pngrtran.c b/contrib/syslinux-4.02/com32/lib/libpng/pngrtran.c new file mode 100644 index 0000000..af1aa8e --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libpng/pngrtran.c @@ -0,0 +1,4457 @@ + +/* pngrtran.c - transforms the data in a row for PNG readers + * + * Last changed in libpng 1.2.43 [February 25, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file contains functions optionally called by an application + * in order to tell libpng how to handle data when reading a PNG. + * Transformations that are used in both reading and writing are + * in pngtrans.c. + */ + +#define PNG_INTERNAL +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" +#ifdef PNG_READ_SUPPORTED + +/* Set the action on getting a CRC error for an ancillary or critical chunk. */ +void PNGAPI +png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action) +{ + png_debug(1, "in png_set_crc_action"); + + if (png_ptr == NULL) + return; + + /* Tell libpng how we react to CRC errors in critical chunks */ + switch (crit_action) + { + case PNG_CRC_NO_CHANGE: /* Leave setting as is */ + break; + + case PNG_CRC_WARN_USE: /* Warn/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE; + break; + + case PNG_CRC_QUIET_USE: /* Quiet/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE | + PNG_FLAG_CRC_CRITICAL_IGNORE; + break; + + case PNG_CRC_WARN_DISCARD: /* Not a valid action for critical data */ + png_warning(png_ptr, + "Can't discard critical data on CRC error."); + case PNG_CRC_ERROR_QUIT: /* Error/quit */ + + case PNG_CRC_DEFAULT: + default: + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + break; + } + + /* Tell libpng how we react to CRC errors in ancillary chunks */ + switch (ancil_action) + { + case PNG_CRC_NO_CHANGE: /* Leave setting as is */ + break; + + case PNG_CRC_WARN_USE: /* Warn/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE; + break; + + case PNG_CRC_QUIET_USE: /* Quiet/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE | + PNG_FLAG_CRC_ANCILLARY_NOWARN; + break; + + case PNG_CRC_ERROR_QUIT: /* Error/quit */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN; + break; + + case PNG_CRC_WARN_DISCARD: /* Warn/discard data */ + + case PNG_CRC_DEFAULT: + default: + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + break; + } +} + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ + defined(PNG_FLOATING_POINT_SUPPORTED) +/* Handle alpha and tRNS via a background color */ +void PNGAPI +png_set_background(png_structp png_ptr, + png_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma) +{ + png_debug(1, "in png_set_background"); + + if (png_ptr == NULL) + return; + if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN) + { + png_warning(png_ptr, "Application must supply a known background gamma"); + return; + } + + png_ptr->transformations |= PNG_BACKGROUND; + png_memcpy(&(png_ptr->background), background_color, + png_sizeof(png_color_16)); + png_ptr->background_gamma = (float)background_gamma; + png_ptr->background_gamma_type = (png_byte)(background_gamma_code); + png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0); +} +#endif + +#ifdef PNG_READ_16_TO_8_SUPPORTED +/* Strip 16 bit depth files to 8 bit depth */ +void PNGAPI +png_set_strip_16(png_structp png_ptr) +{ + png_debug(1, "in png_set_strip_16"); + + if (png_ptr == NULL) + return; + png_ptr->transformations |= PNG_16_TO_8; +} +#endif + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED +void PNGAPI +png_set_strip_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_strip_alpha"); + + if (png_ptr == NULL) + return; + png_ptr->flags |= PNG_FLAG_STRIP_ALPHA; +} +#endif + +#ifdef PNG_READ_DITHER_SUPPORTED +/* Dither file to 8 bit. Supply a palette, the current number + * of elements in the palette, the maximum number of elements + * allowed, and a histogram if possible. If the current number + * of colors is greater then the maximum number, the palette will be + * modified to fit in the maximum number. "full_dither" indicates + * whether we need a dithering cube set up for RGB images, or if we + * simply are reducing the number of colors in a paletted image. + */ + +typedef struct png_dsort_struct +{ + struct png_dsort_struct FAR * next; + png_byte left; + png_byte right; +} png_dsort; +typedef png_dsort FAR * png_dsortp; +typedef png_dsort FAR * FAR * png_dsortpp; + +void PNGAPI +png_set_dither(png_structp png_ptr, png_colorp palette, + int num_palette, int maximum_colors, png_uint_16p histogram, + int full_dither) +{ + png_debug(1, "in png_set_dither"); + + if (png_ptr == NULL) + return; + png_ptr->transformations |= PNG_DITHER; + + if (!full_dither) + { + int i; + + png_ptr->dither_index = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof(png_byte))); + for (i = 0; i < num_palette; i++) + png_ptr->dither_index[i] = (png_byte)i; + } + + if (num_palette > maximum_colors) + { + if (histogram != NULL) + { + /* This is easy enough, just throw out the least used colors. + * Perhaps not the best solution, but good enough. + */ + + int i; + + /* Initialize an array to sort colors */ + png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof(png_byte))); + + /* Initialize the dither_sort array */ + for (i = 0; i < num_palette; i++) + png_ptr->dither_sort[i] = (png_byte)i; + + /* Find the least used palette entries by starting a + * bubble sort, and running it until we have sorted + * out enough colors. Note that we don't care about + * sorting all the colors, just finding which are + * least used. + */ + + for (i = num_palette - 1; i >= maximum_colors; i--) + { + int done; /* To stop early if the list is pre-sorted */ + int j; + + done = 1; + for (j = 0; j < i; j++) + { + if (histogram[png_ptr->dither_sort[j]] + < histogram[png_ptr->dither_sort[j + 1]]) + { + png_byte t; + + t = png_ptr->dither_sort[j]; + png_ptr->dither_sort[j] = png_ptr->dither_sort[j + 1]; + png_ptr->dither_sort[j + 1] = t; + done = 0; + } + } + if (done) + break; + } + + /* Swap the palette around, and set up a table, if necessary */ + if (full_dither) + { + int j = num_palette; + + /* Put all the useful colors within the max, but don't + * move the others. + */ + for (i = 0; i < maximum_colors; i++) + { + if ((int)png_ptr->dither_sort[i] >= maximum_colors) + { + do + j--; + while ((int)png_ptr->dither_sort[j] >= maximum_colors); + palette[i] = palette[j]; + } + } + } + else + { + int j = num_palette; + + /* Move all the used colors inside the max limit, and + * develop a translation table. + */ + for (i = 0; i < maximum_colors; i++) + { + /* Only move the colors we need to */ + if ((int)png_ptr->dither_sort[i] >= maximum_colors) + { + png_color tmp_color; + + do + j--; + while ((int)png_ptr->dither_sort[j] >= maximum_colors); + + tmp_color = palette[j]; + palette[j] = palette[i]; + palette[i] = tmp_color; + /* Indicate where the color went */ + png_ptr->dither_index[j] = (png_byte)i; + png_ptr->dither_index[i] = (png_byte)j; + } + } + + /* Find closest color for those colors we are not using */ + for (i = 0; i < num_palette; i++) + { + if ((int)png_ptr->dither_index[i] >= maximum_colors) + { + int min_d, k, min_k, d_index; + + /* Find the closest color to one we threw out */ + d_index = png_ptr->dither_index[i]; + min_d = PNG_COLOR_DIST(palette[d_index], palette[0]); + for (k = 1, min_k = 0; k < maximum_colors; k++) + { + int d; + + d = PNG_COLOR_DIST(palette[d_index], palette[k]); + + if (d < min_d) + { + min_d = d; + min_k = k; + } + } + /* Point to closest color */ + png_ptr->dither_index[i] = (png_byte)min_k; + } + } + } + png_free(png_ptr, png_ptr->dither_sort); + png_ptr->dither_sort = NULL; + } + else + { + /* This is much harder to do simply (and quickly). Perhaps + * we need to go through a median cut routine, but those + * don't always behave themselves with only a few colors + * as input. So we will just find the closest two colors, + * and throw out one of them (chosen somewhat randomly). + * [We don't understand this at all, so if someone wants to + * work on improving it, be our guest - AED, GRP] + */ + int i; + int max_d; + int num_new_palette; + png_dsortp t; + png_dsortpp hash; + + t = NULL; + + /* Initialize palette index arrays */ + png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof(png_byte))); + png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof(png_byte))); + + /* Initialize the sort array */ + for (i = 0; i < num_palette; i++) + { + png_ptr->index_to_palette[i] = (png_byte)i; + png_ptr->palette_to_index[i] = (png_byte)i; + } + + hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 * + png_sizeof(png_dsortp))); + + num_new_palette = num_palette; + + /* Initial wild guess at how far apart the farthest pixel + * pair we will be eliminating will be. Larger + * numbers mean more areas will be allocated, Smaller + * numbers run the risk of not saving enough data, and + * having to do this all over again. + * + * I have not done extensive checking on this number. + */ + max_d = 96; + + while (num_new_palette > maximum_colors) + { + for (i = 0; i < num_new_palette - 1; i++) + { + int j; + + for (j = i + 1; j < num_new_palette; j++) + { + int d; + + d = PNG_COLOR_DIST(palette[i], palette[j]); + + if (d <= max_d) + { + + t = (png_dsortp)png_malloc_warn(png_ptr, + (png_uint_32)(png_sizeof(png_dsort))); + if (t == NULL) + break; + t->next = hash[d]; + t->left = (png_byte)i; + t->right = (png_byte)j; + hash[d] = t; + } + } + if (t == NULL) + break; + } + + if (t != NULL) + for (i = 0; i <= max_d; i++) + { + if (hash[i] != NULL) + { + png_dsortp p; + + for (p = hash[i]; p; p = p->next) + { + if ((int)png_ptr->index_to_palette[p->left] + < num_new_palette && + (int)png_ptr->index_to_palette[p->right] + < num_new_palette) + { + int j, next_j; + + if (num_new_palette & 0x01) + { + j = p->left; + next_j = p->right; + } + else + { + j = p->right; + next_j = p->left; + } + + num_new_palette--; + palette[png_ptr->index_to_palette[j]] + = palette[num_new_palette]; + if (!full_dither) + { + int k; + + for (k = 0; k < num_palette; k++) + { + if (png_ptr->dither_index[k] == + png_ptr->index_to_palette[j]) + png_ptr->dither_index[k] = + png_ptr->index_to_palette[next_j]; + if ((int)png_ptr->dither_index[k] == + num_new_palette) + png_ptr->dither_index[k] = + png_ptr->index_to_palette[j]; + } + } + + png_ptr->index_to_palette[png_ptr->palette_to_index + [num_new_palette]] = png_ptr->index_to_palette[j]; + png_ptr->palette_to_index[png_ptr->index_to_palette[j]] + = png_ptr->palette_to_index[num_new_palette]; + + png_ptr->index_to_palette[j] = + (png_byte)num_new_palette; + png_ptr->palette_to_index[num_new_palette] = + (png_byte)j; + } + if (num_new_palette <= maximum_colors) + break; + } + if (num_new_palette <= maximum_colors) + break; + } + } + + for (i = 0; i < 769; i++) + { + if (hash[i] != NULL) + { + png_dsortp p = hash[i]; + while (p) + { + t = p->next; + png_free(png_ptr, p); + p = t; + } + } + hash[i] = 0; + } + max_d += 96; + } + png_free(png_ptr, hash); + png_free(png_ptr, png_ptr->palette_to_index); + png_free(png_ptr, png_ptr->index_to_palette); + png_ptr->palette_to_index = NULL; + png_ptr->index_to_palette = NULL; + } + num_palette = maximum_colors; + } + if (png_ptr->palette == NULL) + { + png_ptr->palette = palette; + } + png_ptr->num_palette = (png_uint_16)num_palette; + + if (full_dither) + { + int i; + png_bytep distance; + int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS + + PNG_DITHER_BLUE_BITS; + int num_red = (1 << PNG_DITHER_RED_BITS); + int num_green = (1 << PNG_DITHER_GREEN_BITS); + int num_blue = (1 << PNG_DITHER_BLUE_BITS); + png_size_t num_entries = ((png_size_t)1 << total_bits); + + png_ptr->palette_lookup = (png_bytep )png_calloc(png_ptr, + (png_uint_32)(num_entries * png_sizeof(png_byte))); + + distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * + png_sizeof(png_byte))); + png_memset(distance, 0xff, num_entries * png_sizeof(png_byte)); + + for (i = 0; i < num_palette; i++) + { + int ir, ig, ib; + int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS)); + int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS)); + int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS)); + + for (ir = 0; ir < num_red; ir++) + { + /* int dr = abs(ir - r); */ + int dr = ((ir > r) ? ir - r : r - ir); + int index_r = (ir << (PNG_DITHER_BLUE_BITS + + PNG_DITHER_GREEN_BITS)); + + for (ig = 0; ig < num_green; ig++) + { + /* int dg = abs(ig - g); */ + int dg = ((ig > g) ? ig - g : g - ig); + int dt = dr + dg; + int dm = ((dr > dg) ? dr : dg); + int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS); + + for (ib = 0; ib < num_blue; ib++) + { + int d_index = index_g | ib; + /* int db = abs(ib - b); */ + int db = ((ib > b) ? ib - b : b - ib); + int dmax = ((dm > db) ? dm : db); + int d = dmax + dt + db; + + if (d < (int)distance[d_index]) + { + distance[d_index] = (png_byte)d; + png_ptr->palette_lookup[d_index] = (png_byte)i; + } + } + } + } + } + + png_free(png_ptr, distance); + } +} +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) +/* Transform the image from the file_gamma to the screen_gamma. We + * only do transformations on images where the file_gamma and screen_gamma + * are not close reciprocals, otherwise it slows things down slightly, and + * also needlessly introduces small errors. + * + * We will turn off gamma transformation later if no semitransparent entries + * are present in the tRNS array for palette images. We can't do it here + * because we don't necessarily have the tRNS chunk yet. + */ +void PNGAPI +png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma) +{ + png_debug(1, "in png_set_gamma"); + + if (png_ptr == NULL) + return; + + if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) || + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) || + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) + png_ptr->transformations |= PNG_GAMMA; + png_ptr->gamma = (float)file_gamma; + png_ptr->screen_gamma = (float)scrn_gamma; +} +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expand paletted images to RGB, expand grayscale images of + * less than 8-bit depth to 8-bit depth, and expand tRNS chunks + * to alpha channels. + */ +void PNGAPI +png_set_expand(png_structp png_ptr) +{ + png_debug(1, "in png_set_expand"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; +} + +/* GRR 19990627: the following three functions currently are identical + * to png_set_expand(). However, it is entirely reasonable that someone + * might wish to expand an indexed image to RGB but *not* expand a single, + * fully transparent palette entry to a full alpha channel--perhaps instead + * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace + * the transparent color with a particular RGB value, or drop tRNS entirely. + * IOW, a future version of the library may make the transformations flag + * a bit more fine-grained, with separate bits for each of these three + * functions. + * + * More to the point, these functions make it obvious what libpng will be + * doing, whereas "expand" can (and does) mean any number of things. + * + * GRP 20060307: In libpng-1.2.9, png_set_gray_1_2_4_to_8() was modified + * to expand only the sample depth but not to expand the tRNS to alpha + * and its name was changed to png_set_expand_gray_1_2_4_to_8(). + */ + +/* Expand paletted images to RGB. */ +void PNGAPI +png_set_palette_to_rgb(png_structp png_ptr) +{ + png_debug(1, "in png_set_palette_to_rgb"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; +} + +#ifndef PNG_1_0_X +/* Expand grayscale images of less than 8-bit depth to 8 bits. */ +void PNGAPI +png_set_expand_gray_1_2_4_to_8(png_structp png_ptr) +{ + png_debug(1, "in png_set_expand_gray_1_2_4_to_8"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_EXPAND; + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; +} +#endif + +#if defined(PNG_1_0_X) || defined(PNG_1_2_X) +/* Expand grayscale images of less than 8-bit depth to 8 bits. */ +/* Deprecated as of libpng-1.2.9 */ +void PNGAPI +png_set_gray_1_2_4_to_8(png_structp png_ptr) +{ + png_debug(1, "in png_set_gray_1_2_4_to_8"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); +} +#endif + + +/* Expand tRNS chunks to alpha channels. */ +void PNGAPI +png_set_tRNS_to_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_tRNS_to_alpha"); + + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; +} +#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */ + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +void PNGAPI +png_set_gray_to_rgb(png_structp png_ptr) +{ + png_debug(1, "in png_set_gray_to_rgb"); + + png_ptr->transformations |= PNG_GRAY_TO_RGB; + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; +} +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +/* Convert a RGB image to a grayscale of the same width. This allows us, + * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image. + */ + +void PNGAPI +png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red, + double green) +{ + int red_fixed = (int)((float)red*100000.0 + 0.5); + int green_fixed = (int)((float)green*100000.0 + 0.5); + if (png_ptr == NULL) + return; + png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed); +} +#endif + +void PNGAPI +png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action, + png_fixed_point red, png_fixed_point green) +{ + png_debug(1, "in png_set_rgb_to_gray"); + + if (png_ptr == NULL) + return; + + switch(error_action) + { + case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY; + break; + + case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN; + break; + + case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR; + } + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) +#ifdef PNG_READ_EXPAND_SUPPORTED + png_ptr->transformations |= PNG_EXPAND; +#else + { + png_warning(png_ptr, + "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED."); + png_ptr->transformations &= ~PNG_RGB_TO_GRAY; + } +#endif + { + png_uint_16 red_int, green_int; + if (red < 0 || green < 0) + { + red_int = 6968; /* .212671 * 32768 + .5 */ + green_int = 23434; /* .715160 * 32768 + .5 */ + } + else if (red + green < 100000L) + { + red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L); + green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L); + } + else + { + png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients"); + red_int = 6968; + green_int = 23434; + } + png_ptr->rgb_to_gray_red_coeff = red_int; + png_ptr->rgb_to_gray_green_coeff = green_int; + png_ptr->rgb_to_gray_blue_coeff = + (png_uint_16)(32768 - red_int - green_int); + } +} +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +void PNGAPI +png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr + read_user_transform_fn) +{ + png_debug(1, "in png_set_read_user_transform_fn"); + + if (png_ptr == NULL) + return; + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + png_ptr->transformations |= PNG_USER_TRANSFORM; + png_ptr->read_user_transform_fn = read_user_transform_fn; +#endif +#ifdef PNG_LEGACY_SUPPORTED + if (read_user_transform_fn) + png_warning(png_ptr, + "This version of libpng does not support user transforms"); +#endif +} +#endif + +/* Initialize everything needed for the read. This includes modifying + * the palette. + */ +void /* PRIVATE */ +png_init_read_transformations(png_structp png_ptr) +{ + png_debug(1, "in png_init_read_transformations"); + +#ifdef PNG_USELESS_TESTS_SUPPORTED + if (png_ptr != NULL) +#endif + { +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_SHIFT_SUPPORTED) || \ + defined(PNG_READ_GAMMA_SUPPORTED) + int color_type = png_ptr->color_type; +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + /* Detect gray background and attempt to enable optimization + * for gray --> RGB case + * + * Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or + * RGB_ALPHA (in which case need_expand is superfluous anyway), the + * background color might actually be gray yet not be flagged as such. + * This is not a problem for the current code, which uses + * PNG_BACKGROUND_IS_GRAY only to decide when to do the + * png_do_gray_to_rgb() transformation. + */ + if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + !(color_type & PNG_COLOR_MASK_COLOR)) + { + png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; + } else if ((png_ptr->transformations & PNG_BACKGROUND) && + !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + (png_ptr->transformations & PNG_GRAY_TO_RGB) && + png_ptr->background.red == png_ptr->background.green && + png_ptr->background.red == png_ptr->background.blue) + { + png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; + png_ptr->background.gray = png_ptr->background.red; + } +#endif + + if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + (png_ptr->transformations & PNG_EXPAND)) + { + if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */ + { + /* Expand background and tRNS chunks */ + switch (png_ptr->bit_depth) + { + case 1: + png_ptr->background.gray *= (png_uint_16)0xff; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + png_ptr->trans_values.gray *= (png_uint_16)0xff; + png_ptr->trans_values.red = png_ptr->trans_values.green + = png_ptr->trans_values.blue = png_ptr->trans_values.gray; + } + break; + + case 2: + png_ptr->background.gray *= (png_uint_16)0x55; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + png_ptr->trans_values.gray *= (png_uint_16)0x55; + png_ptr->trans_values.red = png_ptr->trans_values.green + = png_ptr->trans_values.blue = png_ptr->trans_values.gray; + } + break; + + case 4: + png_ptr->background.gray *= (png_uint_16)0x11; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + png_ptr->trans_values.gray *= (png_uint_16)0x11; + png_ptr->trans_values.red = png_ptr->trans_values.green + = png_ptr->trans_values.blue = png_ptr->trans_values.gray; + } + break; + + case 8: + + case 16: + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + break; + } + } + else if (color_type == PNG_COLOR_TYPE_PALETTE) + { + png_ptr->background.red = + png_ptr->palette[png_ptr->background.index].red; + png_ptr->background.green = + png_ptr->palette[png_ptr->background.index].green; + png_ptr->background.blue = + png_ptr->palette[png_ptr->background.index].blue; + +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_ALPHA) + { +#ifdef PNG_READ_EXPAND_SUPPORTED + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) +#endif + { + /* Invert the alpha channel (in tRNS) unless the pixels are + * going to be expanded, in which case leave it for later + */ + int i, istop; + istop=(int)png_ptr->num_trans; + for (i=0; i<istop; i++) + png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]); + } + } +#endif + + } + } +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) + png_ptr->background_1 = png_ptr->background; +#endif +#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) + + if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0) + && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0) + < PNG_GAMMA_THRESHOLD)) + { + int i, k; + k=0; + for (i=0; i<png_ptr->num_trans; i++) + { + if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff) + k=1; /* Partial transparency is present */ + } + if (k == 0) + png_ptr->transformations &= ~PNG_GAMMA; + } + + if ((png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) && + png_ptr->gamma != 0.0) + { + png_build_gamma_table(png_ptr); + +#ifdef PNG_READ_BACKGROUND_SUPPORTED + if (png_ptr->transformations & PNG_BACKGROUND) + { + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + /* Could skip if no transparency */ + png_color back, back_1; + png_colorp palette = png_ptr->palette; + int num_palette = png_ptr->num_palette; + int i; + if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) + { + back.red = png_ptr->gamma_table[png_ptr->background.red]; + back.green = png_ptr->gamma_table[png_ptr->background.green]; + back.blue = png_ptr->gamma_table[png_ptr->background.blue]; + + back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; + back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; + back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; + } + else + { + double g, gs; + + switch (png_ptr->background_gamma_type) + { + case PNG_BACKGROUND_GAMMA_SCREEN: + g = (png_ptr->screen_gamma); + gs = 1.0; + break; + + case PNG_BACKGROUND_GAMMA_FILE: + g = 1.0 / (png_ptr->gamma); + gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + break; + + case PNG_BACKGROUND_GAMMA_UNIQUE: + g = 1.0 / (png_ptr->background_gamma); + gs = 1.0 / (png_ptr->background_gamma * + png_ptr->screen_gamma); + break; + default: + g = 1.0; /* back_1 */ + gs = 1.0; /* back */ + } + + if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD) + { + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; + } + else + { + back.red = (png_byte)(pow( + (double)png_ptr->background.red/255, gs) * 255.0 + .5); + back.green = (png_byte)(pow( + (double)png_ptr->background.green/255, gs) * 255.0 + + .5); + back.blue = (png_byte)(pow( + (double)png_ptr->background.blue/255, gs) * 255.0 + .5); + } + + back_1.red = (png_byte)(pow( + (double)png_ptr->background.red/255, g) * 255.0 + .5); + back_1.green = (png_byte)(pow( + (double)png_ptr->background.green/255, g) * 255.0 + .5); + back_1.blue = (png_byte)(pow( + (double)png_ptr->background.blue/255, g) * 255.0 + .5); + } + for (i = 0; i < num_palette; i++) + { + if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff) + { + if (png_ptr->trans[i] == 0) + { + palette[i] = back; + } + else /* if (png_ptr->trans[i] != 0xff) */ + { + png_byte v, w; + + v = png_ptr->gamma_to_1[palette[i].red]; + png_composite(w, v, png_ptr->trans[i], back_1.red); + palette[i].red = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[palette[i].green]; + png_composite(w, v, png_ptr->trans[i], back_1.green); + palette[i].green = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[palette[i].blue]; + png_composite(w, v, png_ptr->trans[i], back_1.blue); + palette[i].blue = png_ptr->gamma_from_1[w]; + } + } + else + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } + /* Prevent the transformations being done again, and make sure + * that the now spurious alpha channel is stripped - the code + * has just reduced background composition and gamma correction + * to a simple alpha channel strip. + */ + png_ptr->transformations &= ~PNG_BACKGROUND; + png_ptr->transformations &= ~PNG_GAMMA; + png_ptr->transformations |= PNG_STRIP_ALPHA; + } + /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ + else + /* color_type != PNG_COLOR_TYPE_PALETTE */ + { + double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1); + double g = 1.0; + double gs = 1.0; + + switch (png_ptr->background_gamma_type) + { + case PNG_BACKGROUND_GAMMA_SCREEN: + g = (png_ptr->screen_gamma); + gs = 1.0; + break; + + case PNG_BACKGROUND_GAMMA_FILE: + g = 1.0 / (png_ptr->gamma); + gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + break; + + case PNG_BACKGROUND_GAMMA_UNIQUE: + g = 1.0 / (png_ptr->background_gamma); + gs = 1.0 / (png_ptr->background_gamma * + png_ptr->screen_gamma); + break; + } + + png_ptr->background_1.gray = (png_uint_16)(pow( + (double)png_ptr->background.gray / m, g) * m + .5); + png_ptr->background.gray = (png_uint_16)(pow( + (double)png_ptr->background.gray / m, gs) * m + .5); + + if ((png_ptr->background.red != png_ptr->background.green) || + (png_ptr->background.red != png_ptr->background.blue) || + (png_ptr->background.red != png_ptr->background.gray)) + { + /* RGB or RGBA with color background */ + png_ptr->background_1.red = (png_uint_16)(pow( + (double)png_ptr->background.red / m, g) * m + .5); + png_ptr->background_1.green = (png_uint_16)(pow( + (double)png_ptr->background.green / m, g) * m + .5); + png_ptr->background_1.blue = (png_uint_16)(pow( + (double)png_ptr->background.blue / m, g) * m + .5); + png_ptr->background.red = (png_uint_16)(pow( + (double)png_ptr->background.red / m, gs) * m + .5); + png_ptr->background.green = (png_uint_16)(pow( + (double)png_ptr->background.green / m, gs) * m + .5); + png_ptr->background.blue = (png_uint_16)(pow( + (double)png_ptr->background.blue / m, gs) * m + .5); + } + else + { + /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */ + png_ptr->background_1.red = png_ptr->background_1.green + = png_ptr->background_1.blue = png_ptr->background_1.gray; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + } + } + } + else + /* Transformation does not include PNG_BACKGROUND */ +#endif /* PNG_READ_BACKGROUND_SUPPORTED */ + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + png_colorp palette = png_ptr->palette; + int num_palette = png_ptr->num_palette; + int i; + + for (i = 0; i < num_palette; i++) + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + + /* Done the gamma correction. */ + png_ptr->transformations &= ~PNG_GAMMA; + } + } +#ifdef PNG_READ_BACKGROUND_SUPPORTED + else +#endif +#endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */ +#ifdef PNG_READ_BACKGROUND_SUPPORTED + /* No GAMMA transformation */ + if ((png_ptr->transformations & PNG_BACKGROUND) && + (color_type == PNG_COLOR_TYPE_PALETTE)) + { + int i; + int istop = (int)png_ptr->num_trans; + png_color back; + png_colorp palette = png_ptr->palette; + + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; + + for (i = 0; i < istop; i++) + { + if (png_ptr->trans[i] == 0) + { + palette[i] = back; + } + else if (png_ptr->trans[i] != 0xff) + { + /* The png_composite() macro is defined in png.h */ + png_composite(palette[i].red, palette[i].red, + png_ptr->trans[i], back.red); + png_composite(palette[i].green, palette[i].green, + png_ptr->trans[i], back.green); + png_composite(palette[i].blue, palette[i].blue, + png_ptr->trans[i], back.blue); + } + } + + /* Handled alpha, still need to strip the channel. */ + png_ptr->transformations &= ~PNG_BACKGROUND; + png_ptr->transformations |= PNG_STRIP_ALPHA; + } +#endif /* PNG_READ_BACKGROUND_SUPPORTED */ + +#ifdef PNG_READ_SHIFT_SUPPORTED + if ((png_ptr->transformations & PNG_SHIFT) && + (color_type == PNG_COLOR_TYPE_PALETTE)) + { + png_uint_16 i; + png_uint_16 istop = png_ptr->num_palette; + int sr = 8 - png_ptr->sig_bit.red; + int sg = 8 - png_ptr->sig_bit.green; + int sb = 8 - png_ptr->sig_bit.blue; + + if (sr < 0 || sr > 8) + sr = 0; + if (sg < 0 || sg > 8) + sg = 0; + if (sb < 0 || sb > 8) + sb = 0; + for (i = 0; i < istop; i++) + { + png_ptr->palette[i].red >>= sr; + png_ptr->palette[i].green >>= sg; + png_ptr->palette[i].blue >>= sb; + } + } +#endif /* PNG_READ_SHIFT_SUPPORTED */ + } +#if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \ + && !defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr) + return; +#endif +} + +/* Modify the info structure to reflect the transformations. The + * info should be updated so a PNG file could be written with it, + * assuming the transformations result in valid PNG data. + */ +void /* PRIVATE */ +png_read_transform_info(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_transform_info"); + +#ifdef PNG_READ_EXPAND_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND) + { + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (png_ptr->num_trans && + (png_ptr->transformations & PNG_EXPAND_tRNS)) + info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + else + info_ptr->color_type = PNG_COLOR_TYPE_RGB; + info_ptr->bit_depth = 8; + info_ptr->num_trans = 0; + } + else + { + if (png_ptr->num_trans) + { + if (png_ptr->transformations & PNG_EXPAND_tRNS) + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; + } + if (info_ptr->bit_depth < 8) + info_ptr->bit_depth = 8; + info_ptr->num_trans = 0; + } + } +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED + if (png_ptr->transformations & PNG_BACKGROUND) + { + info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; + info_ptr->num_trans = 0; + info_ptr->background = png_ptr->background; + } +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED + if (png_ptr->transformations & PNG_GAMMA) + { +#ifdef PNG_FLOATING_POINT_SUPPORTED + info_ptr->gamma = png_ptr->gamma; +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + info_ptr->int_gamma = png_ptr->int_gamma; +#endif + } +#endif + +#ifdef PNG_READ_16_TO_8_SUPPORTED + if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16)) + info_ptr->bit_depth = 8; +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + if (png_ptr->transformations & PNG_GRAY_TO_RGB) + info_ptr->color_type |= PNG_COLOR_MASK_COLOR; +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR; +#endif + +#ifdef PNG_READ_DITHER_SUPPORTED + if (png_ptr->transformations & PNG_DITHER) + { + if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || + (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) && + png_ptr->palette_lookup && info_ptr->bit_depth == 8) + { + info_ptr->color_type = PNG_COLOR_TYPE_PALETTE; + } + } +#endif + +#ifdef PNG_READ_PACK_SUPPORTED + if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8)) + info_ptr->bit_depth = 8; +#endif + + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + info_ptr->channels = 1; + else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) + info_ptr->channels = 3; + else + info_ptr->channels = 1; + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA) + info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; +#endif + + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + info_ptr->channels++; + +#ifdef PNG_READ_FILLER_SUPPORTED + /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */ + if ((png_ptr->transformations & PNG_FILLER) && + ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || + (info_ptr->color_type == PNG_COLOR_TYPE_GRAY))) + { + info_ptr->channels++; + /* If adding a true alpha channel not just filler */ +#ifndef PNG_1_0_X + if (png_ptr->transformations & PNG_ADD_ALPHA) + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; +#endif + } +#endif + +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \ +defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + if (png_ptr->transformations & PNG_USER_TRANSFORM) + { + if (info_ptr->bit_depth < png_ptr->user_transform_depth) + info_ptr->bit_depth = png_ptr->user_transform_depth; + if (info_ptr->channels < png_ptr->user_transform_channels) + info_ptr->channels = png_ptr->user_transform_channels; + } +#endif + + info_ptr->pixel_depth = (png_byte)(info_ptr->channels * + info_ptr->bit_depth); + + info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width); + +#ifndef PNG_READ_EXPAND_SUPPORTED + if (png_ptr) + return; +#endif +} + +/* Transform the row. The order of transformations is significant, + * and is very touchy. If you add a transformation, take care to + * decide how it fits in with the other transformations here. + */ +void /* PRIVATE */ +png_do_read_transformations(png_structp png_ptr) +{ + png_debug(1, "in png_do_read_transformations"); + + if (png_ptr->row_buf == NULL) + { +#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE) + char msg[50]; + + png_snprintf2(msg, 50, + "NULL row buffer for row %ld, pass %d", (long)png_ptr->row_number, + png_ptr->pass); + png_error(png_ptr, msg); +#else + png_error(png_ptr, "NULL row buffer"); +#endif + } +#ifdef PNG_WARN_UNINITIALIZED_ROW + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + /* Application has failed to call either png_read_start_image() + * or png_read_update_info() after setting transforms that expand + * pixels. This check added to libpng-1.2.19 + */ +#if (PNG_WARN_UNINITIALIZED_ROW==1) + png_error(png_ptr, "Uninitialized row"); +#else + png_warning(png_ptr, "Uninitialized row"); +#endif +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND) + { + if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE) + { + png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->palette, png_ptr->trans, png_ptr->num_trans); + } + else + { + if (png_ptr->num_trans && + (png_ptr->transformations & PNG_EXPAND_tRNS)) + png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->trans_values)); + else + png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, + NULL); + } + } +#endif + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA) + png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, + PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + { + int rgb_error = + png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), + png_ptr->row_buf + 1); + if (rgb_error) + { + png_ptr->rgb_to_gray_status=1; + if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == + PNG_RGB_TO_GRAY_WARN) + png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel"); + if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == + PNG_RGB_TO_GRAY_ERR) + png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel"); + } + } +#endif + +/* From Andreas Dilger e-mail to png-implement, 26 March 1998: + * + * In most cases, the "simple transparency" should be done prior to doing + * gray-to-RGB, or you will have to test 3x as many bytes to check if a + * pixel is transparent. You would also need to make sure that the + * transparency information is upgraded to RGB. + * + * To summarize, the current flow is: + * - Gray + simple transparency -> compare 1 or 2 gray bytes and composite + * with background "in place" if transparent, + * convert to RGB if necessary + * - Gray + alpha -> composite with gray background and remove alpha bytes, + * convert to RGB if necessary + * + * To support RGB backgrounds for gray images we need: + * - Gray + simple transparency -> convert to RGB + simple transparency, + * compare 3 or 6 bytes and composite with + * background "in place" if transparent + * (3x compare/pixel compared to doing + * composite with gray bkgrnd) + * - Gray + alpha -> convert to RGB + alpha, composite with background and + * remove alpha bytes (3x float + * operations/pixel compared with composite + * on gray background) + * + * Greg's change will do this. The reason it wasn't done before is for + * performance, as this increases the per-pixel operations. If we would check + * in advance if the background was gray or RGB, and position the gray-to-RGB + * transform appropriately, then it would save a lot of work/time. + */ + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + /* If gray -> RGB, do so now only if background is non-gray; else do later + * for performance reasons + */ + if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && + !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) + png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED + if ((png_ptr->transformations & PNG_BACKGROUND) && + ((png_ptr->num_trans != 0 ) || + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) + png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->trans_values), &(png_ptr->background) +#ifdef PNG_READ_GAMMA_SUPPORTED + , &(png_ptr->background_1), + png_ptr->gamma_table, png_ptr->gamma_from_1, + png_ptr->gamma_to_1, png_ptr->gamma_16_table, + png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1, + png_ptr->gamma_shift +#endif +); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED + if ((png_ptr->transformations & PNG_GAMMA) && +#ifdef PNG_READ_BACKGROUND_SUPPORTED + !((png_ptr->transformations & PNG_BACKGROUND) && + ((png_ptr->num_trans != 0) || + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) && +#endif + (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)) + png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->gamma_table, png_ptr->gamma_16_table, + png_ptr->gamma_shift); +#endif + +#ifdef PNG_READ_16_TO_8_SUPPORTED + if (png_ptr->transformations & PNG_16_TO_8) + png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_DITHER_SUPPORTED + if (png_ptr->transformations & PNG_DITHER) + { + png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->palette_lookup, png_ptr->dither_index); + if (png_ptr->row_info.rowbytes == (png_uint_32)0) + png_error(png_ptr, "png_do_dither returned rowbytes=0"); + } +#endif + +#ifdef PNG_READ_INVERT_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_MONO) + png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_SHIFT_SUPPORTED + if (png_ptr->transformations & PNG_SHIFT) + png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->shift)); +#endif + +#ifdef PNG_READ_PACK_SUPPORTED + if (png_ptr->transformations & PNG_PACK) + png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_BGR_SUPPORTED + if (png_ptr->transformations & PNG_BGR) + png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + /* If gray -> RGB, do so now only if we did not do so above */ + if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && + (png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) + png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_FILLER_SUPPORTED + if (png_ptr->transformations & PNG_FILLER) + png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, + (png_uint_32)png_ptr->filler, png_ptr->flags); +#endif + +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_ALPHA) + png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_ALPHA) + png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_SWAP_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + if (png_ptr->transformations & PNG_USER_TRANSFORM) + { + if (png_ptr->read_user_transform_fn != NULL) + (*(png_ptr->read_user_transform_fn)) /* User read transform function */ + (png_ptr, /* png_ptr */ + &(png_ptr->row_info), /* row_info: */ + /* png_uint_32 width; width of row */ + /* png_uint_32 rowbytes; number of bytes in row */ + /* png_byte color_type; color type of pixels */ + /* png_byte bit_depth; bit depth of samples */ + /* png_byte channels; number of channels (1-4) */ + /* png_byte pixel_depth; bits per pixel (depth*channels) */ + png_ptr->row_buf + 1); /* start of pixel data for row */ +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED + if (png_ptr->user_transform_depth) + png_ptr->row_info.bit_depth = png_ptr->user_transform_depth; + if (png_ptr->user_transform_channels) + png_ptr->row_info.channels = png_ptr->user_transform_channels; +#endif + png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * + png_ptr->row_info.channels); + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + } +#endif + +} + +#ifdef PNG_READ_PACK_SUPPORTED +/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel, + * without changing the actual values. Thus, if you had a row with + * a bit depth of 1, you would end up with bytes that only contained + * the numbers 0 or 1. If you would rather they contain 0 and 255, use + * png_do_shift() after this. + */ +void /* PRIVATE */ +png_do_unpack(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_unpack"); + +#ifdef PNG_USELESS_TESTS_SUPPORTED + if (row != NULL && row_info != NULL && row_info->bit_depth < 8) +#else + if (row_info->bit_depth < 8) +#endif + { + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + switch (row_info->bit_depth) + { + case 1: + { + png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x01); + if (shift == 7) + { + shift = 0; + sp--; + } + else + shift++; + + dp--; + } + break; + } + + case 2: + { + + png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x03); + if (shift == 6) + { + shift = 0; + sp--; + } + else + shift += 2; + + dp--; + } + break; + } + + case 4: + { + png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x0f); + if (shift == 4) + { + shift = 0; + sp--; + } + else + shift = 4; + + dp--; + } + break; + } + } + row_info->bit_depth = 8; + row_info->pixel_depth = (png_byte)(8 * row_info->channels); + row_info->rowbytes = row_width * row_info->channels; + } +} +#endif + +#ifdef PNG_READ_SHIFT_SUPPORTED +/* Reverse the effects of png_do_shift. This routine merely shifts the + * pixels back to their significant bits values. Thus, if you have + * a row of bit depth 8, but only 5 are significant, this will shift + * the values back to 0 through 31. + */ +void /* PRIVATE */ +png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits) +{ + png_debug(1, "in png_do_unshift"); + + if ( +#ifdef PNG_USELESS_TESTS_SUPPORTED + row != NULL && row_info != NULL && sig_bits != NULL && +#endif + row_info->color_type != PNG_COLOR_TYPE_PALETTE) + { + int shift[4]; + int channels = 0; + int c; + png_uint_16 value = 0; + png_uint_32 row_width = row_info->width; + + if (row_info->color_type & PNG_COLOR_MASK_COLOR) + { + shift[channels++] = row_info->bit_depth - sig_bits->red; + shift[channels++] = row_info->bit_depth - sig_bits->green; + shift[channels++] = row_info->bit_depth - sig_bits->blue; + } + else + { + shift[channels++] = row_info->bit_depth - sig_bits->gray; + } + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + shift[channels++] = row_info->bit_depth - sig_bits->alpha; + } + + for (c = 0; c < channels; c++) + { + if (shift[c] <= 0) + shift[c] = 0; + else + value = 1; + } + + if (!value) + return; + + switch (row_info->bit_depth) + { + case 2: + { + png_bytep bp; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + + for (bp = row, i = 0; i < istop; i++) + { + *bp >>= 1; + *bp++ &= 0x55; + } + break; + } + + case 4: + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) | + (png_byte)((int)0xf >> shift[0])); + + for (i = 0; i < istop; i++) + { + *bp >>= shift[0]; + *bp++ &= mask; + } + break; + } + + case 8: + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = row_width * channels; + + for (i = 0; i < istop; i++) + { + *bp++ >>= shift[i%channels]; + } + break; + } + + case 16: + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = channels * row_width; + + for (i = 0; i < istop; i++) + { + value = (png_uint_16)((*bp << 8) + *(bp + 1)); + value >>= shift[i%channels]; + *bp++ = (png_byte)(value >> 8); + *bp++ = (png_byte)(value & 0xff); + } + break; + } + } + } +} +#endif + +#ifdef PNG_READ_16_TO_8_SUPPORTED +/* Chop rows of bit depth 16 down to 8 */ +void /* PRIVATE */ +png_do_chop(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_chop"); + +#ifdef PNG_USELESS_TESTS_SUPPORTED + if (row != NULL && row_info != NULL && row_info->bit_depth == 16) +#else + if (row_info->bit_depth == 16) +#endif + { + png_bytep sp = row; + png_bytep dp = row; + png_uint_32 i; + png_uint_32 istop = row_info->width * row_info->channels; + + for (i = 0; i<istop; i++, sp += 2, dp++) + { +#ifdef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED + /* This does a more accurate scaling of the 16-bit color + * value, rather than a simple low-byte truncation. + * + * What the ideal calculation should be: + * *dp = (((((png_uint_32)(*sp) << 8) | + * (png_uint_32)(*(sp + 1))) * 255 + 127) + * / (png_uint_32)65535L; + * + * GRR: no, I think this is what it really should be: + * *dp = (((((png_uint_32)(*sp) << 8) | + * (png_uint_32)(*(sp + 1))) + 128L) + * / (png_uint_32)257L; + * + * GRR: here's the exact calculation with shifts: + * temp = (((png_uint_32)(*sp) << 8) | + * (png_uint_32)(*(sp + 1))) + 128L; + * *dp = (temp - (temp >> 8)) >> 8; + * + * Approximate calculation with shift/add instead of multiply/divide: + * *dp = ((((png_uint_32)(*sp) << 8) | + * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8; + * + * What we actually do to avoid extra shifting and conversion: + */ + + *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0); +#else + /* Simply discard the low order byte */ + *dp = *sp; +#endif + } + row_info->bit_depth = 8; + row_info->pixel_depth = (png_byte)(8 * row_info->channels); + row_info->rowbytes = row_info->width * row_info->channels; + } +} +#endif + +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED +void /* PRIVATE */ +png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_read_swap_alpha"); + +#ifdef PNG_USELESS_TESTS_SUPPORTED + if (row != NULL && row_info != NULL) +#endif + { + png_uint_32 row_width = row_info->width; + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + /* This converts from RGBA to ARGB */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; + } + } + /* This converts from RRGGBBAA to AARRGGBB */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This converts from GA to AG */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; + } + } + /* This converts from GGAA to AAGG */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; + } + } + } + } +} +#endif + +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED +void /* PRIVATE */ +png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_read_invert_alpha"); + +#ifdef PNG_USELESS_TESTS_SUPPORTED + if (row != NULL && row_info != NULL) +#endif + { + png_uint_32 row_width = row_info->width; + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + /* This inverts the alpha channel in RGBA */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + +/* This does nothing: + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + We can replace it with: +*/ + sp-=3; + dp=sp; + } + } + /* This inverts the alpha channel in RRGGBBAA */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = (png_byte)(255 - *(--sp)); + +/* This does nothing: + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + We can replace it with: +*/ + sp-=6; + dp=sp; + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This inverts the alpha channel in GA */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = *(--sp); + } + } + /* This inverts the alpha channel in GGAA */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = (png_byte)(255 - *(--sp)); +/* + *(--dp) = *(--sp); + *(--dp) = *(--sp); +*/ + sp-=2; + dp=sp; + } + } + } + } +} +#endif + +#ifdef PNG_READ_FILLER_SUPPORTED +/* Add filler channel if we have RGB color */ +void /* PRIVATE */ +png_do_read_filler(png_row_infop row_info, png_bytep row, + png_uint_32 filler, png_uint_32 flags) +{ + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + png_byte hi_filler = (png_byte)((filler>>8) & 0xff); + png_byte lo_filler = (png_byte)(filler & 0xff); + + png_debug(1, "in png_do_read_filler"); + + if ( +#ifdef PNG_USELESS_TESTS_SUPPORTED + row != NULL && row_info != NULL && +#endif + row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + if (row_info->bit_depth == 8) + { + /* This changes the data from G to GX */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = lo_filler; + *(--dp) = *(--sp); + } + *(--dp) = lo_filler; + row_info->channels = 2; + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + /* This changes the data from G to XG */ + else + { + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = lo_filler; + } + row_info->channels = 2; + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + } + else if (row_info->bit_depth == 16) + { + /* This changes the data from GG to GGXX */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width * 2; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 1; i < row_width; i++) + { + *(--dp) = hi_filler; + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = hi_filler; + *(--dp) = lo_filler; + row_info->channels = 2; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + /* This changes the data from GG to XXGG */ + else + { + png_bytep sp = row + (png_size_t)row_width * 2; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = hi_filler; + *(--dp) = lo_filler; + } + row_info->channels = 2; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + } + } /* COLOR_TYPE == GRAY */ + else if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + if (row_info->bit_depth == 8) + { + /* This changes the data from RGB to RGBX */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = lo_filler; + row_info->channels = 4; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + /* This changes the data from RGB to XRGB */ + else + { + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = lo_filler; + } + row_info->channels = 4; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + } + else if (row_info->bit_depth == 16) + { + /* This changes the data from RRGGBB to RRGGBBXX */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width * 6; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 1; i < row_width; i++) + { + *(--dp) = hi_filler; + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = hi_filler; + *(--dp) = lo_filler; + row_info->channels = 4; + row_info->pixel_depth = 64; + row_info->rowbytes = row_width * 8; + } + /* This changes the data from RRGGBB to XXRRGGBB */ + else + { + png_bytep sp = row + (png_size_t)row_width * 6; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = hi_filler; + *(--dp) = lo_filler; + } + row_info->channels = 4; + row_info->pixel_depth = 64; + row_info->rowbytes = row_width * 8; + } + } + } /* COLOR_TYPE == RGB */ +} +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +/* Expand grayscale files to RGB, with or without alpha */ +void /* PRIVATE */ +png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) +{ + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + png_debug(1, "in png_do_gray_to_rgb"); + + if (row_info->bit_depth >= 8 && +#ifdef PNG_USELESS_TESTS_SUPPORTED + row != NULL && row_info != NULL && +#endif + !(row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + if (row_info->bit_depth == 8) + { + png_bytep sp = row + (png_size_t)row_width - 1; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(dp--) = *sp; + *(dp--) = *sp; + *(dp--) = *(sp--); + } + } + else + { + png_bytep sp = row + (png_size_t)row_width * 2 - 1; + png_bytep dp = sp + (png_size_t)row_width * 4; + for (i = 0; i < row_width; i++) + { + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *(sp--); + *(dp--) = *(sp--); + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + png_bytep sp = row + (png_size_t)row_width * 2 - 1; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(dp--) = *(sp--); + *(dp--) = *sp; + *(dp--) = *sp; + *(dp--) = *(sp--); + } + } + else + { + png_bytep sp = row + (png_size_t)row_width * 4 - 1; + png_bytep dp = sp + (png_size_t)row_width * 4; + for (i = 0; i < row_width; i++) + { + *(dp--) = *(sp--); + *(dp--) = *(sp--); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *(sp--); + *(dp--) = *(sp--); + } + } + } + row_info->channels += (png_byte)2; + row_info->color_type |= PNG_COLOR_MASK_COLOR; + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } +} +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +/* Reduce RGB files to grayscale, with or without alpha + * using the equation given in Poynton's ColorFAQ at + * <http://www.inforamp.net/~poynton/> (THIS LINK IS DEAD June 2008) + * New link: + * <http://www.poynton.com/notes/colour_and_gamma/> + * Charles Poynton poynton at poynton.com + * + * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B + * + * We approximate this with + * + * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B + * + * which can be expressed with integers as + * + * Y = (6969 * R + 23434 * G + 2365 * B)/32768 + * + * The calculation is to be done in a linear colorspace. + * + * Other integer coefficents can be used via png_set_rgb_to_gray(). + */ +int /* PRIVATE */ +png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) + +{ + png_uint_32 i; + + png_uint_32 row_width = row_info->width; + int rgb_error = 0; + + png_debug(1, "in png_do_rgb_to_gray"); + + if ( +#ifdef PNG_USELESS_TESTS_SUPPORTED + row != NULL && row_info != NULL && +#endif + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; + png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; + png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + + for (i = 0; i < row_width; i++) + { + png_byte red = png_ptr->gamma_to_1[*(sp++)]; + png_byte green = png_ptr->gamma_to_1[*(sp++)]; + png_byte blue = png_ptr->gamma_to_1[*(sp++)]; + if (red != green || red != blue) + { + rgb_error |= 1; + *(dp++) = png_ptr->gamma_from_1[ + (rc*red + gc*green + bc*blue)>>15]; + } + else + *(dp++) = *(sp - 1); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = *(sp++); + png_byte green = *(sp++); + png_byte blue = *(sp++); + if (red != green || red != blue) + { + rgb_error |= 1; + *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); + } + else + *(dp++) = *(sp - 1); + } + } + } + + else /* RGB bit_depth == 16 */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_16_to_1 != NULL && + png_ptr->gamma_16_from_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, w; + + red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + + if (red == green && red == blue) + w = red; + else + { + png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> + png_ptr->gamma_shift][red>>8]; + png_uint_16 green_1 = + png_ptr->gamma_16_to_1[(green&0xff) >> + png_ptr->gamma_shift][green>>8]; + png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> + png_ptr->gamma_shift][blue>>8]; + png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1 + + bc*blue_1)>>15); + w = png_ptr->gamma_16_from_1[(gray16&0xff) >> + png_ptr->gamma_shift][gray16 >> 8]; + rgb_error |= 1; + } + + *(dp++) = (png_byte)((w>>8) & 0xff); + *(dp++) = (png_byte)(w & 0xff); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, gray16; + + red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + + if (red != green || red != blue) + rgb_error |= 1; + gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = (png_byte)((gray16>>8) & 0xff); + *(dp++) = (png_byte)(gray16 & 0xff); + } + } + } + } + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = png_ptr->gamma_to_1[*(sp++)]; + png_byte green = png_ptr->gamma_to_1[*(sp++)]; + png_byte blue = png_ptr->gamma_to_1[*(sp++)]; + if (red != green || red != blue) + rgb_error |= 1; + *(dp++) = png_ptr->gamma_from_1 + [(rc*red + gc*green + bc*blue)>>15]; + *(dp++) = *(sp++); /* alpha */ + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = *(sp++); + png_byte green = *(sp++); + png_byte blue = *(sp++); + if (red != green || red != blue) + rgb_error |= 1; + *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = *(sp++); /* alpha */ + } + } + } + else /* RGBA bit_depth == 16 */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_16_to_1 != NULL && + png_ptr->gamma_16_from_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, w; + + red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + + if (red == green && red == blue) + w = red; + else + { + png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> + png_ptr->gamma_shift][red>>8]; + png_uint_16 green_1 = + png_ptr->gamma_16_to_1[(green&0xff) >> + png_ptr->gamma_shift][green>>8]; + png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> + png_ptr->gamma_shift][blue>>8]; + png_uint_16 gray16 = (png_uint_16)((rc * red_1 + + gc * green_1 + bc * blue_1)>>15); + w = png_ptr->gamma_16_from_1[(gray16&0xff) >> + png_ptr->gamma_shift][gray16 >> 8]; + rgb_error |= 1; + } + + *(dp++) = (png_byte)((w>>8) & 0xff); + *(dp++) = (png_byte)(w & 0xff); + *(dp++) = *(sp++); /* alpha */ + *(dp++) = *(sp++); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, gray16; + red = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; + green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; + blue = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; + if (red != green || red != blue) + rgb_error |= 1; + gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = (png_byte)((gray16>>8) & 0xff); + *(dp++) = (png_byte)(gray16 & 0xff); + *(dp++) = *(sp++); /* alpha */ + *(dp++) = *(sp++); + } + } + } + } + row_info->channels -= (png_byte)2; + row_info->color_type &= ~PNG_COLOR_MASK_COLOR; + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + return rgb_error; +} +#endif + +/* Build a grayscale palette. Palette is assumed to be 1 << bit_depth + * large of png_color. This lets grayscale images be treated as + * paletted. Most useful for gamma correction and simplification + * of code. + */ +void PNGAPI +png_build_grayscale_palette(int bit_depth, png_colorp palette) +{ + int num_palette; + int color_inc; + int i; + int v; + + png_debug(1, "in png_do_build_grayscale_palette"); + + if (palette == NULL) + return; + + switch (bit_depth) + { + case 1: + num_palette = 2; + color_inc = 0xff; + break; + + case 2: + num_palette = 4; + color_inc = 0x55; + break; + + case 4: + num_palette = 16; + color_inc = 0x11; + break; + + case 8: + num_palette = 256; + color_inc = 1; + break; + + default: + num_palette = 0; + color_inc = 0; + break; + } + + for (i = 0, v = 0; i < num_palette; i++, v += color_inc) + { + palette[i].red = (png_byte)v; + palette[i].green = (png_byte)v; + palette[i].blue = (png_byte)v; + } +} + +/* This function is currently unused. Do we really need it? */ +#if defined(PNG_READ_DITHER_SUPPORTED) && \ + defined(PNG_CORRECT_PALETTE_SUPPORTED) +void /* PRIVATE */ +png_correct_palette(png_structp png_ptr, png_colorp palette, + int num_palette) +{ + png_debug(1, "in png_correct_palette"); + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ + defined(PNG_READ_GAMMA_SUPPORTED) && \ + defined(PNG_FLOATING_POINT_SUPPORTED) + if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND)) + { + png_color back, back_1; + + if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) + { + back.red = png_ptr->gamma_table[png_ptr->background.red]; + back.green = png_ptr->gamma_table[png_ptr->background.green]; + back.blue = png_ptr->gamma_table[png_ptr->background.blue]; + + back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; + back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; + back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; + } + else + { + double g; + + g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma); + + if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN + || fabs(g - 1.0) < PNG_GAMMA_THRESHOLD) + { + back.red = png_ptr->background.red; + back.green = png_ptr->background.green; + back.blue = png_ptr->background.blue; + } + else + { + back.red = + (png_byte)(pow((double)png_ptr->background.red/255, g) * + 255.0 + 0.5); + back.green = + (png_byte)(pow((double)png_ptr->background.green/255, g) * + 255.0 + 0.5); + back.blue = + (png_byte)(pow((double)png_ptr->background.blue/255, g) * + 255.0 + 0.5); + } + + g = 1.0 / png_ptr->background_gamma; + + back_1.red = + (png_byte)(pow((double)png_ptr->background.red/255, g) * + 255.0 + 0.5); + back_1.green = + (png_byte)(pow((double)png_ptr->background.green/255, g) * + 255.0 + 0.5); + back_1.blue = + (png_byte)(pow((double)png_ptr->background.blue/255, g) * + 255.0 + 0.5); + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_uint_32 i; + + for (i = 0; i < (png_uint_32)num_palette; i++) + { + if (i < png_ptr->num_trans && png_ptr->trans[i] == 0) + { + palette[i] = back; + } + else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff) + { + png_byte v, w; + + v = png_ptr->gamma_to_1[png_ptr->palette[i].red]; + png_composite(w, v, png_ptr->trans[i], back_1.red); + palette[i].red = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[png_ptr->palette[i].green]; + png_composite(w, v, png_ptr->trans[i], back_1.green); + palette[i].green = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[png_ptr->palette[i].blue]; + png_composite(w, v, png_ptr->trans[i], back_1.blue); + palette[i].blue = png_ptr->gamma_from_1[w]; + } + else + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } + } + else + { + int i; + + for (i = 0; i < num_palette; i++) + { + if (palette[i].red == (png_byte)png_ptr->trans_values.gray) + { + palette[i] = back; + } + else + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } + } + } + else +#endif +#ifdef PNG_READ_GAMMA_SUPPORTED + if (png_ptr->transformations & PNG_GAMMA) + { + int i; + + for (i = 0; i < num_palette; i++) + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } +#ifdef PNG_READ_BACKGROUND_SUPPORTED + else +#endif +#endif +#ifdef PNG_READ_BACKGROUND_SUPPORTED + if (png_ptr->transformations & PNG_BACKGROUND) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_color back; + + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; + + for (i = 0; i < (int)png_ptr->num_trans; i++) + { + if (png_ptr->trans[i] == 0) + { + palette[i].red = back.red; + palette[i].green = back.green; + palette[i].blue = back.blue; + } + else if (png_ptr->trans[i] != 0xff) + { + png_composite(palette[i].red, png_ptr->palette[i].red, + png_ptr->trans[i], back.red); + png_composite(palette[i].green, png_ptr->palette[i].green, + png_ptr->trans[i], back.green); + png_composite(palette[i].blue, png_ptr->palette[i].blue, + png_ptr->trans[i], back.blue); + } + } + } + else /* Assume grayscale palette (what else could it be?) */ + { + int i; + + for (i = 0; i < num_palette; i++) + { + if (i == (png_byte)png_ptr->trans_values.gray) + { + palette[i].red = (png_byte)png_ptr->background.red; + palette[i].green = (png_byte)png_ptr->background.green; + palette[i].blue = (png_byte)png_ptr->background.blue; + } + } + } + } +#endif +} +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* Replace any alpha or transparency with the supplied background color. + * "background" is already in the screen gamma, while "background_1" is + * at a gamma of 1.0. Paletted files have already been taken care of. + */ +void /* PRIVATE */ +png_do_background(png_row_infop row_info, png_bytep row, + png_color_16p trans_values, png_color_16p background +#ifdef PNG_READ_GAMMA_SUPPORTED + , png_color_16p background_1, + png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1, + png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1, + png_uint_16pp gamma_16_to_1, int gamma_shift +#endif + ) +{ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + int shift; + + png_debug(1, "in png_do_background"); + + if (background != NULL && +#ifdef PNG_USELESS_TESTS_SUPPORTED + row != NULL && row_info != NULL && +#endif + (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) || + (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values))) + { + switch (row_info->color_type) + { + case PNG_COLOR_TYPE_GRAY: + { + switch (row_info->bit_depth) + { + case 1: + { + sp = row; + shift = 7; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x01) + == trans_values->gray) + { + *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + if (!shift) + { + shift = 7; + sp++; + } + else + shift--; + } + break; + } + + case 2: + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) + { + sp = row; + shift = 6; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x03) + == trans_values->gray) + { + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + else + { + png_byte p = (png_byte)((*sp >> shift) & 0x03); + png_byte g = (png_byte)((gamma_table [p | (p << 2) | + (p << 4) | (p << 6)] >> 6) & 0x03); + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(g << shift); + } + if (!shift) + { + shift = 6; + sp++; + } + else + shift -= 2; + } + } + else +#endif + { + sp = row; + shift = 6; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x03) + == trans_values->gray) + { + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + if (!shift) + { + shift = 6; + sp++; + } + else + shift -= 2; + } + } + break; + } + + case 4: + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x0f) + == trans_values->gray) + { + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + else + { + png_byte p = (png_byte)((*sp >> shift) & 0x0f); + png_byte g = (png_byte)((gamma_table[p | + (p << 4)] >> 4) & 0x0f); + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(g << shift); + } + if (!shift) + { + shift = 4; + sp++; + } + else + shift -= 4; + } + } + else +#endif + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x0f) + == trans_values->gray) + { + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + if (!shift) + { + shift = 4; + sp++; + } + else + shift -= 4; + } + } + break; + } + + case 8: + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + if (*sp == trans_values->gray) + { + *sp = (png_byte)background->gray; + } + else + { + *sp = gamma_table[*sp]; + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + if (*sp == trans_values->gray) + { + *sp = (png_byte)background->gray; + } + } + } + break; + } + + case 16: + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 v; + + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + if (v == trans_values->gray) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((background->gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->gray & 0xff); + } + else + { + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 v; + + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + if (v == trans_values->gray) + { + *sp = (png_byte)((background->gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->gray & 0xff); + } + } + } + break; + } + } + break; + } + + case PNG_COLOR_TYPE_RGB: + { + if (row_info->bit_depth == 8) + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) + { + if (*sp == trans_values->red && + *(sp + 1) == trans_values->green && + *(sp + 2) == trans_values->blue) + { + *sp = (png_byte)background->red; + *(sp + 1) = (png_byte)background->green; + *(sp + 2) = (png_byte)background->blue; + } + else + { + *sp = gamma_table[*sp]; + *(sp + 1) = gamma_table[*(sp + 1)]; + *(sp + 2) = gamma_table[*(sp + 2)]; + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) + { + if (*sp == trans_values->red && + *(sp + 1) == trans_values->green && + *(sp + 2) == trans_values->blue) + { + *sp = (png_byte)background->red; + *(sp + 1) = (png_byte)background->green; + *(sp + 2) = (png_byte)background->blue; + } + } + } + } + else /* if (row_info->bit_depth == 16) */ + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); + png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5)); + if (r == trans_values->red && g == trans_values->green && + b == trans_values->blue) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((background->red >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->red & 0xff); + *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(sp + 3) = (png_byte)(background->green & 0xff); + *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(background->blue & 0xff); + } + else + { + png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1)); + png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); + png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5)); + + if (r == trans_values->red && g == trans_values->green && + b == trans_values->blue) + { + *sp = (png_byte)((background->red >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->red & 0xff); + *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(sp + 3) = (png_byte)(background->green & 0xff); + *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(background->blue & 0xff); + } + } + } + } + break; + } + + case PNG_COLOR_TYPE_GRAY_ALPHA: + { + if (row_info->bit_depth == 8) + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 2, dp++) + { + png_uint_16 a = *(sp + 1); + + if (a == 0xff) + { + *dp = gamma_table[*sp]; + } + else if (a == 0) + { + /* Background is already in screen gamma */ + *dp = (png_byte)background->gray; + } + else + { + png_byte v, w; + + v = gamma_to_1[*sp]; + png_composite(w, v, a, background_1->gray); + *dp = gamma_from_1[w]; + } + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 2, dp++) + { + png_byte a = *(sp + 1); + + if (a == 0xff) + { + *dp = *sp; + } +#ifdef PNG_READ_GAMMA_SUPPORTED + else if (a == 0) + { + *dp = (png_byte)background->gray; + } + else + { + png_composite(*dp, *sp, a, background_1->gray); + } +#else + *dp = (png_byte)background->gray; +#endif + } + } + } + else /* if (png_ptr->bit_depth == 16) */ + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 2) + { + png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); + + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; + + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + } +#ifdef PNG_READ_GAMMA_SUPPORTED + else if (a == 0) +#else + else +#endif + { + /* Background is already in screen gamma */ + *dp = (png_byte)((background->gray >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->gray & 0xff); + } +#ifdef PNG_READ_GAMMA_SUPPORTED + else + { + png_uint_16 g, v, w; + + g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(v, g, a, background_1->gray); + w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8]; + *dp = (png_byte)((w >> 8) & 0xff); + *(dp + 1) = (png_byte)(w & 0xff); + } +#endif + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 2) + { + png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); + if (a == (png_uint_16)0xffff) + { + png_memcpy(dp, sp, 2); + } +#ifdef PNG_READ_GAMMA_SUPPORTED + else if (a == 0) +#else + else +#endif + { + *dp = (png_byte)((background->gray >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->gray & 0xff); + } +#ifdef PNG_READ_GAMMA_SUPPORTED + else + { + png_uint_16 g, v; + + g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_composite_16(v, g, a, background_1->gray); + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + } +#endif + } + } + } + break; + } + + case PNG_COLOR_TYPE_RGB_ALPHA: + { + if (row_info->bit_depth == 8) + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 3) + { + png_byte a = *(sp + 3); + + if (a == 0xff) + { + *dp = gamma_table[*sp]; + *(dp + 1) = gamma_table[*(sp + 1)]; + *(dp + 2) = gamma_table[*(sp + 2)]; + } + else if (a == 0) + { + /* Background is already in screen gamma */ + *dp = (png_byte)background->red; + *(dp + 1) = (png_byte)background->green; + *(dp + 2) = (png_byte)background->blue; + } + else + { + png_byte v, w; + + v = gamma_to_1[*sp]; + png_composite(w, v, a, background_1->red); + *dp = gamma_from_1[w]; + v = gamma_to_1[*(sp + 1)]; + png_composite(w, v, a, background_1->green); + *(dp + 1) = gamma_from_1[w]; + v = gamma_to_1[*(sp + 2)]; + png_composite(w, v, a, background_1->blue); + *(dp + 2) = gamma_from_1[w]; + } + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 3) + { + png_byte a = *(sp + 3); + + if (a == 0xff) + { + *dp = *sp; + *(dp + 1) = *(sp + 1); + *(dp + 2) = *(sp + 2); + } + else if (a == 0) + { + *dp = (png_byte)background->red; + *(dp + 1) = (png_byte)background->green; + *(dp + 2) = (png_byte)background->blue; + } + else + { + png_composite(*dp, *sp, a, background->red); + png_composite(*(dp + 1), *(sp + 1), a, + background->green); + png_composite(*(dp + 2), *(sp + 2), a, + background->blue); + } + } + } + } + else /* if (row_info->bit_depth == 16) */ + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 8, dp += 6) + { + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; + + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(dp + 2) = (png_byte)((v >> 8) & 0xff); + *(dp + 3) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(dp + 4) = (png_byte)((v >> 8) & 0xff); + *(dp + 5) = (png_byte)(v & 0xff); + } + else if (a == 0) + { + /* Background is already in screen gamma */ + *dp = (png_byte)((background->red >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->red & 0xff); + *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(dp + 3) = (png_byte)(background->green & 0xff); + *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(dp + 5) = (png_byte)(background->blue & 0xff); + } + else + { + png_uint_16 v, w, x; + + v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(w, v, a, background_1->red); + x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; + *dp = (png_byte)((x >> 8) & 0xff); + *(dp + 1) = (png_byte)(x & 0xff); + v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; + png_composite_16(w, v, a, background_1->green); + x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; + *(dp + 2) = (png_byte)((x >> 8) & 0xff); + *(dp + 3) = (png_byte)(x & 0xff); + v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; + png_composite_16(w, v, a, background_1->blue); + x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8]; + *(dp + 4) = (png_byte)((x >> 8) & 0xff); + *(dp + 5) = (png_byte)(x & 0xff); + } + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 8, dp += 6) + { + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); + if (a == (png_uint_16)0xffff) + { + png_memcpy(dp, sp, 6); + } + else if (a == 0) + { + *dp = (png_byte)((background->red >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->red & 0xff); + *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(dp + 3) = (png_byte)(background->green & 0xff); + *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(dp + 5) = (png_byte)(background->blue & 0xff); + } + else + { + png_uint_16 v; + + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); + + png_composite_16(v, r, a, background->red); + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + png_composite_16(v, g, a, background->green); + *(dp + 2) = (png_byte)((v >> 8) & 0xff); + *(dp + 3) = (png_byte)(v & 0xff); + png_composite_16(v, b, a, background->blue); + *(dp + 4) = (png_byte)((v >> 8) & 0xff); + *(dp + 5) = (png_byte)(v & 0xff); + } + } + } + } + break; + } + } + + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + row_info->color_type &= ~PNG_COLOR_MASK_ALPHA; + row_info->channels--; + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + } +} +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* Gamma correct the image, avoiding the alpha channel. Make sure + * you do this after you deal with the transparency issue on grayscale + * or RGB images. If your bit depth is 8, use gamma_table, if it + * is 16, use gamma_16_table and gamma_shift. Build these with + * build_gamma_table(). + */ +void /* PRIVATE */ +png_do_gamma(png_row_infop row_info, png_bytep row, + png_bytep gamma_table, png_uint_16pp gamma_16_table, + int gamma_shift) +{ + png_bytep sp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_gamma"); + + if ( +#ifdef PNG_USELESS_TESTS_SUPPORTED + row != NULL && row_info != NULL && +#endif + ((row_info->bit_depth <= 8 && gamma_table != NULL) || + (row_info->bit_depth == 16 && gamma_16_table != NULL))) + { + switch (row_info->color_type) + { + case PNG_COLOR_TYPE_RGB: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + } + } + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v; + + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + } + } + break; + } + + case PNG_COLOR_TYPE_RGB_ALPHA: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + sp++; + } + } + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 4; + } + } + break; + } + + case PNG_COLOR_TYPE_GRAY_ALPHA: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp += 2; + } + } + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 4; + } + } + break; + } + + case PNG_COLOR_TYPE_GRAY: + { + if (row_info->bit_depth == 2) + { + sp = row; + for (i = 0; i < row_width; i += 4) + { + int a = *sp & 0xc0; + int b = *sp & 0x30; + int c = *sp & 0x0c; + int d = *sp & 0x03; + + *sp = (png_byte)( + ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)| + ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)| + ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)| + ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) )); + sp++; + } + } + + if (row_info->bit_depth == 4) + { + sp = row; + for (i = 0; i < row_width; i += 2) + { + int msb = *sp & 0xf0; + int lsb = *sp & 0x0f; + + *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0) + | (((int)gamma_table[(lsb << 4) | lsb]) >> 4)); + sp++; + } + } + + else if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + } + } + + else if (row_info->bit_depth == 16) + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + } + } + break; + } + } + } +} +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expands a palette row to an RGB or RGBA row depending + * upon whether you supply trans and num_trans. + */ +void /* PRIVATE */ +png_do_expand_palette(png_row_infop row_info, png_bytep row, + png_colorp palette, png_bytep trans, int num_trans) +{ + int shift, value; + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_expand_palette"); + + if ( +#ifdef PNG_USELESS_TESTS_SUPPORTED + row != NULL && row_info != NULL && +#endif + row_info->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (row_info->bit_depth < 8) + { + switch (row_info->bit_depth) + { + case 1: + { + sp = row + (png_size_t)((row_width - 1) >> 3); + dp = row + (png_size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + if ((*sp >> shift) & 0x01) + *dp = 1; + else + *dp = 0; + if (shift == 7) + { + shift = 0; + sp--; + } + else + shift++; + + dp--; + } + break; + } + + case 2: + { + sp = row + (png_size_t)((row_width - 1) >> 2); + dp = row + (png_size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x03; + *dp = (png_byte)value; + if (shift == 6) + { + shift = 0; + sp--; + } + else + shift += 2; + + dp--; + } + break; + } + + case 4: + { + sp = row + (png_size_t)((row_width - 1) >> 1); + dp = row + (png_size_t)row_width - 1; + shift = (int)((row_width & 0x01) << 2); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x0f; + *dp = (png_byte)value; + if (shift == 4) + { + shift = 0; + sp--; + } + else + shift += 4; + + dp--; + } + break; + } + } + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + switch (row_info->bit_depth) + { + case 8: + { + if (trans != NULL) + { + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width << 2) - 1; + + for (i = 0; i < row_width; i++) + { + if ((int)(*sp) >= num_trans) + *dp-- = 0xff; + else + *dp-- = trans[*sp]; + *dp-- = palette[*sp].blue; + *dp-- = palette[*sp].green; + *dp-- = palette[*sp].red; + sp--; + } + row_info->bit_depth = 8; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + row_info->color_type = 6; + row_info->channels = 4; + } + else + { + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width * 3) - 1; + + for (i = 0; i < row_width; i++) + { + *dp-- = palette[*sp].blue; + *dp-- = palette[*sp].green; + *dp-- = palette[*sp].red; + sp--; + } + + row_info->bit_depth = 8; + row_info->pixel_depth = 24; + row_info->rowbytes = row_width * 3; + row_info->color_type = 2; + row_info->channels = 3; + } + break; + } + } + } +} + +/* If the bit depth < 8, it is expanded to 8. Also, if the already + * expanded transparency value is supplied, an alpha channel is built. + */ +void /* PRIVATE */ +png_do_expand(png_row_infop row_info, png_bytep row, + png_color_16p trans_value) +{ + int shift, value; + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_expand"); + +#ifdef PNG_USELESS_TESTS_SUPPORTED + if (row != NULL && row_info != NULL) +#endif + { + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0); + + if (row_info->bit_depth < 8) + { + switch (row_info->bit_depth) + { + case 1: + { + gray = (png_uint_16)((gray&0x01)*0xff); + sp = row + (png_size_t)((row_width - 1) >> 3); + dp = row + (png_size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + if ((*sp >> shift) & 0x01) + *dp = 0xff; + else + *dp = 0; + if (shift == 7) + { + shift = 0; + sp--; + } + else + shift++; + + dp--; + } + break; + } + + case 2: + { + gray = (png_uint_16)((gray&0x03)*0x55); + sp = row + (png_size_t)((row_width - 1) >> 2); + dp = row + (png_size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x03; + *dp = (png_byte)(value | (value << 2) | (value << 4) | + (value << 6)); + if (shift == 6) + { + shift = 0; + sp--; + } + else + shift += 2; + + dp--; + } + break; + } + + case 4: + { + gray = (png_uint_16)((gray&0x0f)*0x11); + sp = row + (png_size_t)((row_width - 1) >> 1); + dp = row + (png_size_t)row_width - 1; + shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x0f; + *dp = (png_byte)(value | (value << 4)); + if (shift == 4) + { + shift = 0; + sp--; + } + else + shift = 4; + + dp--; + } + break; + } + } + + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + + if (trans_value != NULL) + { + if (row_info->bit_depth == 8) + { + gray = gray & 0xff; + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width << 1) - 1; + for (i = 0; i < row_width; i++) + { + if (*sp == gray) + *dp-- = 0; + else + *dp-- = 0xff; + *dp-- = *sp--; + } + } + + else if (row_info->bit_depth == 16) + { + png_byte gray_high = (gray >> 8) & 0xff; + png_byte gray_low = gray & 0xff; + sp = row + row_info->rowbytes - 1; + dp = row + (row_info->rowbytes << 1) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 1) == gray_high && *(sp) == gray_low) + { + *dp-- = 0; + *dp-- = 0; + } + else + { + *dp-- = 0xff; + *dp-- = 0xff; + } + *dp-- = *sp--; + *dp-- = *sp--; + } + } + + row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; + row_info->channels = 2; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_width); + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value) + { + if (row_info->bit_depth == 8) + { + png_byte red = trans_value->red & 0xff; + png_byte green = trans_value->green & 0xff; + png_byte blue = trans_value->blue & 0xff; + sp = row + (png_size_t)row_info->rowbytes - 1; + dp = row + (png_size_t)(row_width << 2) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) + *dp-- = 0; + else + *dp-- = 0xff; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + else if (row_info->bit_depth == 16) + { + png_byte red_high = (trans_value->red >> 8) & 0xff; + png_byte green_high = (trans_value->green >> 8) & 0xff; + png_byte blue_high = (trans_value->blue >> 8) & 0xff; + png_byte red_low = trans_value->red & 0xff; + png_byte green_low = trans_value->green & 0xff; + png_byte blue_low = trans_value->blue & 0xff; + sp = row + row_info->rowbytes - 1; + dp = row + (png_size_t)(row_width << 3) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 5) == red_high && + *(sp - 4) == red_low && + *(sp - 3) == green_high && + *(sp - 2) == green_low && + *(sp - 1) == blue_high && + *(sp ) == blue_low) + { + *dp-- = 0; + *dp-- = 0; + } + else + { + *dp-- = 0xff; + *dp-- = 0xff; + } + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + row_info->channels = 4; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + } +} +#endif + +#ifdef PNG_READ_DITHER_SUPPORTED +void /* PRIVATE */ +png_do_dither(png_row_infop row_info, png_bytep row, + png_bytep palette_lookup, png_bytep dither_lookup) +{ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_dither"); + +#ifdef PNG_USELESS_TESTS_SUPPORTED + if (row != NULL && row_info != NULL) +#endif + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB && + palette_lookup && row_info->bit_depth == 8) + { + int r, g, b, p; + sp = row; + dp = row; + for (i = 0; i < row_width; i++) + { + r = *sp++; + g = *sp++; + b = *sp++; + + /* This looks real messy, but the compiler will reduce + * it down to a reasonable formula. For example, with + * 5 bits per color, we get: + * p = (((r >> 3) & 0x1f) << 10) | + * (((g >> 3) & 0x1f) << 5) | + * ((b >> 3) & 0x1f); + */ + p = (((r >> (8 - PNG_DITHER_RED_BITS)) & + ((1 << PNG_DITHER_RED_BITS) - 1)) << + (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) | + (((g >> (8 - PNG_DITHER_GREEN_BITS)) & + ((1 << PNG_DITHER_GREEN_BITS) - 1)) << + (PNG_DITHER_BLUE_BITS)) | + ((b >> (8 - PNG_DITHER_BLUE_BITS)) & + ((1 << PNG_DITHER_BLUE_BITS) - 1)); + + *dp++ = palette_lookup[p]; + } + row_info->color_type = PNG_COLOR_TYPE_PALETTE; + row_info->channels = 1; + row_info->pixel_depth = row_info->bit_depth; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && + palette_lookup != NULL && row_info->bit_depth == 8) + { + int r, g, b, p; + sp = row; + dp = row; + for (i = 0; i < row_width; i++) + { + r = *sp++; + g = *sp++; + b = *sp++; + sp++; + + p = (((r >> (8 - PNG_DITHER_RED_BITS)) & + ((1 << PNG_DITHER_RED_BITS) - 1)) << + (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) | + (((g >> (8 - PNG_DITHER_GREEN_BITS)) & + ((1 << PNG_DITHER_GREEN_BITS) - 1)) << + (PNG_DITHER_BLUE_BITS)) | + ((b >> (8 - PNG_DITHER_BLUE_BITS)) & + ((1 << PNG_DITHER_BLUE_BITS) - 1)); + + *dp++ = palette_lookup[p]; + } + row_info->color_type = PNG_COLOR_TYPE_PALETTE; + row_info->channels = 1; + row_info->pixel_depth = row_info->bit_depth; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && + dither_lookup && row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + *sp = dither_lookup[*sp]; + } + } + } +} +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +#ifdef PNG_READ_GAMMA_SUPPORTED +static PNG_CONST int png_gamma_shift[] = + {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0, 0x00}; + +/* We build the 8- or 16-bit gamma tables here. Note that for 16-bit + * tables, we don't make a full table if we are reducing to 8-bit in + * the future. Note also how the gamma_16 tables are segmented so that + * we don't need to allocate > 64K chunks for a full 16-bit table. + * + * See the PNG extensions document for an integer algorithm for creating + * the gamma tables. Maybe we will implement that here someday. + * + * We should only reach this point if + * + * the file_gamma is known (i.e., the gAMA or sRGB chunk is present, + * or the application has provided a file_gamma) + * + * AND + * { + * the screen_gamma is known + * OR + * + * RGB_to_gray transformation is being performed + * } + * + * AND + * { + * the screen_gamma is different from the reciprocal of the + * file_gamma by more than the specified threshold + * + * OR + * + * a background color has been specified and the file_gamma + * and screen_gamma are not 1.0, within the specified threshold. + * } + */ + +void /* PRIVATE */ +png_build_gamma_table(png_structp png_ptr) +{ + png_debug(1, "in png_build_gamma_table"); + + if (png_ptr->bit_depth <= 8) + { + int i; + double g; + + if (png_ptr->screen_gamma > .000001) + g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + + else + g = 1.0; + + png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr, + (png_uint_32)256); + + for (i = 0; i < 256; i++) + { + png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0, + g) * 255.0 + .5); + } + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY)) + { + + g = 1.0 / (png_ptr->gamma); + + png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr, + (png_uint_32)256); + + for (i = 0; i < 256; i++) + { + png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0, + g) * 255.0 + .5); + } + + + png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr, + (png_uint_32)256); + + if (png_ptr->screen_gamma > 0.000001) + g = 1.0 / png_ptr->screen_gamma; + + else + g = png_ptr->gamma; /* Probably doing rgb_to_gray */ + + for (i = 0; i < 256; i++) + { + png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0, + g) * 255.0 + .5); + + } + } +#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ + } + else + { + double g; + int i, j, shift, num; + int sig_bit; + png_uint_32 ig; + + if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + { + sig_bit = (int)png_ptr->sig_bit.red; + + if ((int)png_ptr->sig_bit.green > sig_bit) + sig_bit = png_ptr->sig_bit.green; + + if ((int)png_ptr->sig_bit.blue > sig_bit) + sig_bit = png_ptr->sig_bit.blue; + } + else + { + sig_bit = (int)png_ptr->sig_bit.gray; + } + + if (sig_bit > 0) + shift = 16 - sig_bit; + + else + shift = 0; + + if (png_ptr->transformations & PNG_16_TO_8) + { + if (shift < (16 - PNG_MAX_GAMMA_8)) + shift = (16 - PNG_MAX_GAMMA_8); + } + + if (shift > 8) + shift = 8; + + if (shift < 0) + shift = 0; + + png_ptr->gamma_shift = (png_byte)shift; + + num = (1 << (8 - shift)); + + if (png_ptr->screen_gamma > .000001) + g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + else + g = 1.0; + + png_ptr->gamma_16_table = (png_uint_16pp)png_calloc(png_ptr, + (png_uint_32)(num * png_sizeof(png_uint_16p))); + + if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND)) + { + double fin, fout; + png_uint_32 last, max; + + for (i = 0; i < num; i++) + { + png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(256 * png_sizeof(png_uint_16))); + } + + g = 1.0 / g; + last = 0; + for (i = 0; i < 256; i++) + { + fout = ((double)i + 0.5) / 256.0; + fin = pow(fout, g); + max = (png_uint_32)(fin * (double)((png_uint_32)num << 8)); + while (last <= max) + { + png_ptr->gamma_16_table[(int)(last & (0xff >> shift))] + [(int)(last >> (8 - shift))] = (png_uint_16)( + (png_uint_16)i | ((png_uint_16)i << 8)); + last++; + } + } + while (last < ((png_uint_32)num << 8)) + { + png_ptr->gamma_16_table[(int)(last & (0xff >> shift))] + [(int)(last >> (8 - shift))] = (png_uint_16)65535L; + last++; + } + } + else + { + for (i = 0; i < num; i++) + { + png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(256 * png_sizeof(png_uint_16))); + + ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4); + + for (j = 0; j < 256; j++) + { + png_ptr->gamma_16_table[i][j] = + (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / + 65535.0, g) * 65535.0 + .5); + } + } + } + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY)) + { + + g = 1.0 / (png_ptr->gamma); + + png_ptr->gamma_16_to_1 = (png_uint_16pp)png_calloc(png_ptr, + (png_uint_32)(num * png_sizeof(png_uint_16p ))); + + for (i = 0; i < num; i++) + { + png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(256 * png_sizeof(png_uint_16))); + + ig = (((png_uint_32)i * + (png_uint_32)png_gamma_shift[shift]) >> 4); + for (j = 0; j < 256; j++) + { + png_ptr->gamma_16_to_1[i][j] = + (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / + 65535.0, g) * 65535.0 + .5); + } + } + + if (png_ptr->screen_gamma > 0.000001) + g = 1.0 / png_ptr->screen_gamma; + + else + g = png_ptr->gamma; /* Probably doing rgb_to_gray */ + + png_ptr->gamma_16_from_1 = (png_uint_16pp)png_calloc(png_ptr, + (png_uint_32)(num * png_sizeof(png_uint_16p))); + + for (i = 0; i < num; i++) + { + png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(256 * png_sizeof(png_uint_16))); + + ig = (((png_uint_32)i * + (png_uint_32)png_gamma_shift[shift]) >> 4); + + for (j = 0; j < 256; j++) + { + png_ptr->gamma_16_from_1[i][j] = + (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / + 65535.0, g) * 65535.0 + .5); + } + } + } +#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ + } +} +#endif +/* To do: install integer version of png_build_gamma_table here */ +#endif + +#ifdef PNG_MNG_FEATURES_SUPPORTED +/* Undoes intrapixel differencing */ +void /* PRIVATE */ +png_do_read_intrapixel(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_read_intrapixel"); + + if ( +#ifdef PNG_USELESS_TESTS_SUPPORTED + row != NULL && row_info != NULL && +#endif + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + int bytes_per_pixel; + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 3; + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 4; + + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff); + *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff); + } + } + else if (row_info->bit_depth == 16) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 6; + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 8; + + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); + png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); + png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); + png_uint_32 red = (png_uint_32)((s0 + s1 + 65536L) & 0xffffL); + png_uint_32 blue = (png_uint_32)((s2 + s1 + 65536L) & 0xffffL); + *(rp ) = (png_byte)((red >> 8) & 0xff); + *(rp+1) = (png_byte)(red & 0xff); + *(rp+4) = (png_byte)((blue >> 8) & 0xff); + *(rp+5) = (png_byte)(blue & 0xff); + } + } + } +} +#endif /* PNG_MNG_FEATURES_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED */ diff --git a/contrib/syslinux-4.02/com32/lib/libpng/pngrutil.c b/contrib/syslinux-4.02/com32/lib/libpng/pngrutil.c new file mode 100644 index 0000000..1e2db31 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libpng/pngrutil.c @@ -0,0 +1,3382 @@ + +/* pngrutil.c - utilities to read a PNG file + * + * Last changed in libpng 1.2.44 [June 26, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file contains routines that are only called from within + * libpng itself during the course of reading an image. + */ + +#define PNG_INTERNAL +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" +#ifdef PNG_READ_SUPPORTED + +#if defined(_WIN32_WCE) && (_WIN32_WCE<0x500) +# define WIN32_WCE_OLD +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +# ifdef WIN32_WCE_OLD +/* The strtod() function is not supported on WindowsCE */ +__inline double png_strtod(png_structp png_ptr, PNG_CONST char *nptr, + char **endptr) +{ + double result = 0; + int len; + wchar_t *str, *end; + + len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0); + str = (wchar_t *)png_malloc(png_ptr, len * png_sizeof(wchar_t)); + if ( NULL != str ) + { + MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len); + result = wcstod(str, &end); + len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL); + *endptr = (char *)nptr + (png_strlen(nptr) - len + 1); + png_free(png_ptr, str); + } + return result; +} +# else +# define png_strtod(p,a,b) strtod(a,b) +# endif +#endif + +png_uint_32 PNGAPI +png_get_uint_31(png_structp png_ptr, png_bytep buf) +{ +#ifdef PNG_READ_BIG_ENDIAN_SUPPORTED + png_uint_32 i = png_get_uint_32(buf); +#else + /* Avoid an extra function call by inlining the result. */ + png_uint_32 i = ((png_uint_32)(*buf) << 24) + + ((png_uint_32)(*(buf + 1)) << 16) + + ((png_uint_32)(*(buf + 2)) << 8) + + (png_uint_32)(*(buf + 3)); +#endif + if (i > PNG_UINT_31_MAX) + png_error(png_ptr, "PNG unsigned integer out of range."); + return (i); +} +#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED +/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */ +png_uint_32 PNGAPI +png_get_uint_32(png_bytep buf) +{ + png_uint_32 i = ((png_uint_32)(*buf) << 24) + + ((png_uint_32)(*(buf + 1)) << 16) + + ((png_uint_32)(*(buf + 2)) << 8) + + (png_uint_32)(*(buf + 3)); + + return (i); +} + +/* Grab a signed 32-bit integer from a buffer in big-endian format. The + * data is stored in the PNG file in two's complement format, and it is + * assumed that the machine format for signed integers is the same. + */ +png_int_32 PNGAPI +png_get_int_32(png_bytep buf) +{ + png_int_32 i = ((png_int_32)(*buf) << 24) + + ((png_int_32)(*(buf + 1)) << 16) + + ((png_int_32)(*(buf + 2)) << 8) + + (png_int_32)(*(buf + 3)); + + return (i); +} + +/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */ +png_uint_16 PNGAPI +png_get_uint_16(png_bytep buf) +{ + png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) + + (png_uint_16)(*(buf + 1))); + + return (i); +} +#endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */ + +/* Read the chunk header (length + type name). + * Put the type name into png_ptr->chunk_name, and return the length. + */ +png_uint_32 /* PRIVATE */ +png_read_chunk_header(png_structp png_ptr) +{ + png_byte buf[8]; + png_uint_32 length; + + /* Read the length and the chunk name */ + png_read_data(png_ptr, buf, 8); + length = png_get_uint_31(png_ptr, buf); + + /* Put the chunk name into png_ptr->chunk_name */ + png_memcpy(png_ptr->chunk_name, buf + 4, 4); + + png_debug2(0, "Reading %s chunk, length = %lu", + png_ptr->chunk_name, length); + + /* Reset the crc and run it over the chunk name */ + png_reset_crc(png_ptr); + png_calculate_crc(png_ptr, png_ptr->chunk_name, 4); + + /* Check to see if chunk name is valid */ + png_check_chunk_name(png_ptr, png_ptr->chunk_name); + + return length; +} + +/* Read data, and (optionally) run it through the CRC. */ +void /* PRIVATE */ +png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length) +{ + if (png_ptr == NULL) + return; + png_read_data(png_ptr, buf, length); + png_calculate_crc(png_ptr, buf, length); +} + +/* Optionally skip data and then check the CRC. Depending on whether we + * are reading a ancillary or critical chunk, and how the program has set + * things up, we may calculate the CRC on the data and print a message. + * Returns '1' if there was a CRC error, '0' otherwise. + */ +int /* PRIVATE */ +png_crc_finish(png_structp png_ptr, png_uint_32 skip) +{ + png_size_t i; + png_size_t istop = png_ptr->zbuf_size; + + for (i = (png_size_t)skip; i > istop; i -= istop) + { + png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + } + if (i) + { + png_crc_read(png_ptr, png_ptr->zbuf, i); + } + + if (png_crc_error(png_ptr)) + { + if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */ + !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) || + (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */ + (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE))) + { + png_chunk_warning(png_ptr, "CRC error"); + } + else + { + png_chunk_error(png_ptr, "CRC error"); + } + return (1); + } + + return (0); +} + +/* Compare the CRC stored in the PNG file with that calculated by libpng from + * the data it has read thus far. + */ +int /* PRIVATE */ +png_crc_error(png_structp png_ptr) +{ + png_byte crc_bytes[4]; + png_uint_32 crc; + int need_crc = 1; + + if (png_ptr->chunk_name[0] & 0x20) /* ancillary */ + { + if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == + (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) + need_crc = 0; + } + else /* critical */ + { + if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) + need_crc = 0; + } + + png_read_data(png_ptr, crc_bytes, 4); + + if (need_crc) + { + crc = png_get_uint_32(crc_bytes); + return ((int)(crc != png_ptr->crc)); + } + else + return (0); +} + +#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \ + defined(PNG_READ_iCCP_SUPPORTED) +static png_size_t +png_inflate(png_structp png_ptr, const png_byte *data, png_size_t size, + png_bytep output, png_size_t output_size) +{ + png_size_t count = 0; + + png_ptr->zstream.next_in = (png_bytep)data; /* const_cast: VALID */ + png_ptr->zstream.avail_in = size; + + while (1) + { + int ret, avail; + + /* Reset the output buffer each time round - we empty it + * after every inflate call. + */ + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = png_ptr->zbuf_size; + + ret = inflate(&png_ptr->zstream, Z_NO_FLUSH); + avail = png_ptr->zbuf_size - png_ptr->zstream.avail_out; + + /* First copy/count any new output - but only if we didn't + * get an error code. + */ + if ((ret == Z_OK || ret == Z_STREAM_END) && avail > 0) + { + if (output != 0 && output_size > count) + { + int copy = output_size - count; + if (avail < copy) copy = avail; + png_memcpy(output + count, png_ptr->zbuf, copy); + } + count += avail; + } + + if (ret == Z_OK) + continue; + + /* Termination conditions - always reset the zstream, it + * must be left in inflateInit state. + */ + png_ptr->zstream.avail_in = 0; + inflateReset(&png_ptr->zstream); + + if (ret == Z_STREAM_END) + return count; /* NOTE: may be zero. */ + + /* Now handle the error codes - the API always returns 0 + * and the error message is dumped into the uncompressed + * buffer if available. + */ + { + PNG_CONST char *msg; + if (png_ptr->zstream.msg != 0) + msg = png_ptr->zstream.msg; + else + { +#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE) + char umsg[52]; + + switch (ret) + { + case Z_BUF_ERROR: + msg = "Buffer error in compressed datastream in %s chunk"; + break; + case Z_DATA_ERROR: + msg = "Data error in compressed datastream in %s chunk"; + break; + default: + msg = "Incomplete compressed datastream in %s chunk"; + break; + } + + png_snprintf(umsg, sizeof umsg, msg, png_ptr->chunk_name); + msg = umsg; +#else + msg = "Damaged compressed datastream in chunk other than IDAT"; +#endif + } + + png_warning(png_ptr, msg); + } + + /* 0 means an error - notice that this code simple ignores + * zero length compressed chunks as a result. + */ + return 0; + } +} + +/* + * Decompress trailing data in a chunk. The assumption is that chunkdata + * points at an allocated area holding the contents of a chunk with a + * trailing compressed part. What we get back is an allocated area + * holding the original prefix part and an uncompressed version of the + * trailing part (the malloc area passed in is freed). + */ +void /* PRIVATE */ +png_decompress_chunk(png_structp png_ptr, int comp_type, + png_size_t chunklength, + png_size_t prefix_size, png_size_t *newlength) +{ + /* The caller should guarantee this */ + if (prefix_size > chunklength) + { + /* The recovery is to delete the chunk. */ + png_warning(png_ptr, "invalid chunklength"); + prefix_size = 0; /* To delete everything */ + } + + else if (comp_type == PNG_COMPRESSION_TYPE_BASE) + { + png_size_t expanded_size = png_inflate(png_ptr, + (png_bytep)(png_ptr->chunkdata + prefix_size), + chunklength - prefix_size, + 0/*output*/, 0/*output size*/); + + /* Now check the limits on this chunk - if the limit fails the + * compressed data will be removed, the prefix will remain. + */ +#ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED + if (png_ptr->user_chunk_malloc_max && + (prefix_size + expanded_size >= png_ptr->user_chunk_malloc_max - 1)) +#else +# ifdef PNG_USER_CHUNK_MALLOC_MAX + if ((PNG_USER_CHUNK_MALLOC_MAX > 0) && + prefix_size + expanded_size >= PNG_USER_CHUNK_MALLOC_MAX - 1) +# endif +#endif + png_warning(png_ptr, "Exceeded size limit while expanding chunk"); + + /* If the size is zero either there was an error and a message + * has already been output (warning) or the size really is zero + * and we have nothing to do - the code will exit through the + * error case below. + */ +#if defined(PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED) || \ + defined(PNG_USER_CHUNK_MALLOC_MAX) + else +#endif + if (expanded_size > 0) + { + /* Success (maybe) - really uncompress the chunk. */ + png_size_t new_size = 0; + png_charp text = png_malloc_warn(png_ptr, + prefix_size + expanded_size + 1); + + if (text != NULL) + { + png_memcpy(text, png_ptr->chunkdata, prefix_size); + new_size = png_inflate(png_ptr, + (png_bytep)(png_ptr->chunkdata + prefix_size), + chunklength - prefix_size, + (png_bytep)(text + prefix_size), expanded_size); + text[prefix_size + expanded_size] = 0; /* just in case */ + + if (new_size == expanded_size) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = text; + *newlength = prefix_size + expanded_size; + return; /* The success return! */ + } + + png_warning(png_ptr, "png_inflate logic error"); + png_free(png_ptr, text); + } + else + png_warning(png_ptr, "Not enough memory to decompress chunk."); + } + } + + else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */ + { +#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE) + char umsg[50]; + + png_snprintf(umsg, sizeof umsg, "Unknown zTXt compression type %d", + comp_type); + png_warning(png_ptr, umsg); +#else + png_warning(png_ptr, "Unknown zTXt compression type"); +#endif + + /* The recovery is to simply drop the data. */ + } + + /* Generic error return - leave the prefix, delete the compressed + * data, reallocate the chunkdata to remove the potentially large + * amount of compressed data. + */ + { + png_charp text = png_malloc_warn(png_ptr, prefix_size + 1); + if (text != NULL) + { + if (prefix_size > 0) + png_memcpy(text, png_ptr->chunkdata, prefix_size); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = text; + + /* This is an extra zero in the 'uncompressed' part. */ + *(png_ptr->chunkdata + prefix_size) = 0x00; + } + /* Ignore a malloc error here - it is safe. */ + } + + *newlength = prefix_size; +} +#endif + +/* Read and check the IDHR chunk */ +void /* PRIVATE */ +png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[13]; + png_uint_32 width, height; + int bit_depth, color_type, compression_type, filter_type; + int interlace_type; + + png_debug(1, "in png_handle_IHDR"); + + if (png_ptr->mode & PNG_HAVE_IHDR) + png_error(png_ptr, "Out of place IHDR"); + + /* Check the length */ + if (length != 13) + png_error(png_ptr, "Invalid IHDR chunk"); + + png_ptr->mode |= PNG_HAVE_IHDR; + + png_crc_read(png_ptr, buf, 13); + png_crc_finish(png_ptr, 0); + + width = png_get_uint_31(png_ptr, buf); + height = png_get_uint_31(png_ptr, buf + 4); + bit_depth = buf[8]; + color_type = buf[9]; + compression_type = buf[10]; + filter_type = buf[11]; + interlace_type = buf[12]; + + /* Set internal variables */ + png_ptr->width = width; + png_ptr->height = height; + png_ptr->bit_depth = (png_byte)bit_depth; + png_ptr->interlaced = (png_byte)interlace_type; + png_ptr->color_type = (png_byte)color_type; +#ifdef PNG_MNG_FEATURES_SUPPORTED + png_ptr->filter_type = (png_byte)filter_type; +#endif + png_ptr->compression_type = (png_byte)compression_type; + + /* Find number of channels */ + switch (png_ptr->color_type) + { + case PNG_COLOR_TYPE_GRAY: + case PNG_COLOR_TYPE_PALETTE: + png_ptr->channels = 1; + break; + + case PNG_COLOR_TYPE_RGB: + png_ptr->channels = 3; + break; + + case PNG_COLOR_TYPE_GRAY_ALPHA: + png_ptr->channels = 2; + break; + + case PNG_COLOR_TYPE_RGB_ALPHA: + png_ptr->channels = 4; + break; + } + + /* Set up other useful info */ + png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth * + png_ptr->channels); + png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width); + png_debug1(3, "bit_depth = %d", png_ptr->bit_depth); + png_debug1(3, "channels = %d", png_ptr->channels); + png_debug1(3, "rowbytes = %lu", png_ptr->rowbytes); + png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, + color_type, interlace_type, compression_type, filter_type); +} + +/* Read and check the palette */ +void /* PRIVATE */ +png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_color palette[PNG_MAX_PALETTE_LENGTH]; + int num, i; +#ifdef PNG_POINTER_INDEXING_SUPPORTED + png_colorp pal_ptr; +#endif + + png_debug(1, "in png_handle_PLTE"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before PLTE"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid PLTE after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (png_ptr->mode & PNG_HAVE_PLTE) + png_error(png_ptr, "Duplicate PLTE chunk"); + + png_ptr->mode |= PNG_HAVE_PLTE; + + if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) + { + png_warning(png_ptr, + "Ignoring PLTE chunk in grayscale PNG"); + png_crc_finish(png_ptr, length); + return; + } +#ifndef PNG_READ_OPT_PLTE_SUPPORTED + if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) + { + png_crc_finish(png_ptr, length); + return; + } +#endif + + if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3) + { + if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) + { + png_warning(png_ptr, "Invalid palette chunk"); + png_crc_finish(png_ptr, length); + return; + } + + else + { + png_error(png_ptr, "Invalid palette chunk"); + } + } + + num = (int)length / 3; + +#ifdef PNG_POINTER_INDEXING_SUPPORTED + for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++) + { + png_byte buf[3]; + + png_crc_read(png_ptr, buf, 3); + pal_ptr->red = buf[0]; + pal_ptr->green = buf[1]; + pal_ptr->blue = buf[2]; + } +#else + for (i = 0; i < num; i++) + { + png_byte buf[3]; + + png_crc_read(png_ptr, buf, 3); + /* Don't depend upon png_color being any order */ + palette[i].red = buf[0]; + palette[i].green = buf[1]; + palette[i].blue = buf[2]; + } +#endif + + /* If we actually NEED the PLTE chunk (ie for a paletted image), we do + * whatever the normal CRC configuration tells us. However, if we + * have an RGB image, the PLTE can be considered ancillary, so + * we will act as though it is. + */ +#ifndef PNG_READ_OPT_PLTE_SUPPORTED + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) +#endif + { + png_crc_finish(png_ptr, 0); + } +#ifndef PNG_READ_OPT_PLTE_SUPPORTED + else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */ + { + /* If we don't want to use the data from an ancillary chunk, + we have two options: an error abort, or a warning and we + ignore the data in this chunk (which should be OK, since + it's considered ancillary for a RGB or RGBA image). */ + if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE)) + { + if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) + { + png_chunk_error(png_ptr, "CRC error"); + } + else + { + png_chunk_warning(png_ptr, "CRC error"); + return; + } + } + /* Otherwise, we (optionally) emit a warning and use the chunk. */ + else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) + { + png_chunk_warning(png_ptr, "CRC error"); + } + } +#endif + + png_set_PLTE(png_ptr, info_ptr, palette, num); + +#ifdef PNG_READ_tRNS_SUPPORTED + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + if (png_ptr->num_trans > (png_uint_16)num) + { + png_warning(png_ptr, "Truncating incorrect tRNS chunk length"); + png_ptr->num_trans = (png_uint_16)num; + } + if (info_ptr->num_trans > (png_uint_16)num) + { + png_warning(png_ptr, "Truncating incorrect info tRNS chunk length"); + info_ptr->num_trans = (png_uint_16)num; + } + } + } +#endif + +} + +void /* PRIVATE */ +png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_debug(1, "in png_handle_IEND"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT)) + { + png_error(png_ptr, "No image in file"); + } + + png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND); + + if (length != 0) + { + png_warning(png_ptr, "Incorrect IEND chunk length"); + } + png_crc_finish(png_ptr, length); + + info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */ +} + +#ifdef PNG_READ_gAMA_SUPPORTED +void /* PRIVATE */ +png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_fixed_point igamma; +#ifdef PNG_FLOATING_POINT_SUPPORTED + float file_gamma; +#endif + png_byte buf[4]; + + png_debug(1, "in png_handle_gAMA"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before gAMA"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid gAMA after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place gAMA chunk"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) +#ifdef PNG_READ_sRGB_SUPPORTED + && !(info_ptr->valid & PNG_INFO_sRGB) +#endif + ) + { + png_warning(png_ptr, "Duplicate gAMA chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 4) + { + png_warning(png_ptr, "Incorrect gAMA chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 4); + if (png_crc_finish(png_ptr, 0)) + return; + + igamma = (png_fixed_point)png_get_uint_32(buf); + /* Check for zero gamma */ + if (igamma == 0) + { + png_warning(png_ptr, + "Ignoring gAMA chunk with gamma=0"); + return; + } + +#ifdef PNG_READ_sRGB_SUPPORTED + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) + if (PNG_OUT_OF_RANGE(igamma, 45500L, 500)) + { + png_warning(png_ptr, + "Ignoring incorrect gAMA value when sRGB is also present"); +#ifdef PNG_CONSOLE_IO_SUPPORTED + fprintf(stderr, "gamma = (%d/100000)", (int)igamma); +#endif + return; + } +#endif /* PNG_READ_sRGB_SUPPORTED */ + +#ifdef PNG_FLOATING_POINT_SUPPORTED + file_gamma = (float)igamma / (float)100000.0; +# ifdef PNG_READ_GAMMA_SUPPORTED + png_ptr->gamma = file_gamma; +# endif + png_set_gAMA(png_ptr, info_ptr, file_gamma); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + png_set_gAMA_fixed(png_ptr, info_ptr, igamma); +#endif +} +#endif + +#ifdef PNG_READ_sBIT_SUPPORTED +void /* PRIVATE */ +png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_size_t truelen; + png_byte buf[4]; + + png_debug(1, "in png_handle_sBIT"); + + buf[0] = buf[1] = buf[2] = buf[3] = 0; + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sBIT"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sBIT after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + { + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place sBIT chunk"); + } + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT)) + { + png_warning(png_ptr, "Duplicate sBIT chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + truelen = 3; + else + truelen = (png_size_t)png_ptr->channels; + + if (length != truelen || length > 4) + { + png_warning(png_ptr, "Incorrect sBIT chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, truelen); + if (png_crc_finish(png_ptr, 0)) + return; + + if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + { + png_ptr->sig_bit.red = buf[0]; + png_ptr->sig_bit.green = buf[1]; + png_ptr->sig_bit.blue = buf[2]; + png_ptr->sig_bit.alpha = buf[3]; + } + else + { + png_ptr->sig_bit.gray = buf[0]; + png_ptr->sig_bit.red = buf[0]; + png_ptr->sig_bit.green = buf[0]; + png_ptr->sig_bit.blue = buf[0]; + png_ptr->sig_bit.alpha = buf[1]; + } + png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit)); +} +#endif + +#ifdef PNG_READ_cHRM_SUPPORTED +void /* PRIVATE */ +png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[32]; +#ifdef PNG_FLOATING_POINT_SUPPORTED + float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y; +#endif + png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green, + int_y_green, int_x_blue, int_y_blue; + + png_uint_32 uint_x, uint_y; + + png_debug(1, "in png_handle_cHRM"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before cHRM"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid cHRM after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Missing PLTE before cHRM"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM) +#ifdef PNG_READ_sRGB_SUPPORTED + && !(info_ptr->valid & PNG_INFO_sRGB) +#endif + ) + { + png_warning(png_ptr, "Duplicate cHRM chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 32) + { + png_warning(png_ptr, "Incorrect cHRM chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 32); + if (png_crc_finish(png_ptr, 0)) + return; + + uint_x = png_get_uint_32(buf); + uint_y = png_get_uint_32(buf + 4); + int_x_white = (png_fixed_point)uint_x; + int_y_white = (png_fixed_point)uint_y; + + uint_x = png_get_uint_32(buf + 8); + uint_y = png_get_uint_32(buf + 12); + int_x_red = (png_fixed_point)uint_x; + int_y_red = (png_fixed_point)uint_y; + + uint_x = png_get_uint_32(buf + 16); + uint_y = png_get_uint_32(buf + 20); + int_x_green = (png_fixed_point)uint_x; + int_y_green = (png_fixed_point)uint_y; + + uint_x = png_get_uint_32(buf + 24); + uint_y = png_get_uint_32(buf + 28); + int_x_blue = (png_fixed_point)uint_x; + int_y_blue = (png_fixed_point)uint_y; + +#ifdef PNG_FLOATING_POINT_SUPPORTED + white_x = (float)int_x_white / (float)100000.0; + white_y = (float)int_y_white / (float)100000.0; + red_x = (float)int_x_red / (float)100000.0; + red_y = (float)int_y_red / (float)100000.0; + green_x = (float)int_x_green / (float)100000.0; + green_y = (float)int_y_green / (float)100000.0; + blue_x = (float)int_x_blue / (float)100000.0; + blue_y = (float)int_y_blue / (float)100000.0; +#endif + +#ifdef PNG_READ_sRGB_SUPPORTED + if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB)) + { + if (PNG_OUT_OF_RANGE(int_x_white, 31270, 1000) || + PNG_OUT_OF_RANGE(int_y_white, 32900, 1000) || + PNG_OUT_OF_RANGE(int_x_red, 64000L, 1000) || + PNG_OUT_OF_RANGE(int_y_red, 33000, 1000) || + PNG_OUT_OF_RANGE(int_x_green, 30000, 1000) || + PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) || + PNG_OUT_OF_RANGE(int_x_blue, 15000, 1000) || + PNG_OUT_OF_RANGE(int_y_blue, 6000, 1000)) + { + png_warning(png_ptr, + "Ignoring incorrect cHRM value when sRGB is also present"); +#ifdef PNG_CONSOLE_IO_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED + fprintf(stderr, "wx=%f, wy=%f, rx=%f, ry=%f\n", + white_x, white_y, red_x, red_y); + fprintf(stderr, "gx=%f, gy=%f, bx=%f, by=%f\n", + green_x, green_y, blue_x, blue_y); +#else + fprintf(stderr, "wx=%ld, wy=%ld, rx=%ld, ry=%ld\n", + (long)int_x_white, (long)int_y_white, + (long)int_x_red, (long)int_y_red); + fprintf(stderr, "gx=%ld, gy=%ld, bx=%ld, by=%ld\n", + (long)int_x_green, (long)int_y_green, + (long)int_x_blue, (long)int_y_blue); +#endif +#endif /* PNG_CONSOLE_IO_SUPPORTED */ + } + return; + } +#endif /* PNG_READ_sRGB_SUPPORTED */ + +#ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_cHRM(png_ptr, info_ptr, + white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + png_set_cHRM_fixed(png_ptr, info_ptr, + int_x_white, int_y_white, int_x_red, int_y_red, int_x_green, + int_y_green, int_x_blue, int_y_blue); +#endif +} +#endif + +#ifdef PNG_READ_sRGB_SUPPORTED +void /* PRIVATE */ +png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + int intent; + png_byte buf[1]; + + png_debug(1, "in png_handle_sRGB"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sRGB"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sRGB after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place sRGB chunk"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) + { + png_warning(png_ptr, "Duplicate sRGB chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 1) + { + png_warning(png_ptr, "Incorrect sRGB chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 1); + if (png_crc_finish(png_ptr, 0)) + return; + + intent = buf[0]; + /* Check for bad intent */ + if (intent >= PNG_sRGB_INTENT_LAST) + { + png_warning(png_ptr, "Unknown sRGB intent"); + return; + } + +#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)) + { + png_fixed_point igamma; +#ifdef PNG_FIXED_POINT_SUPPORTED + igamma=info_ptr->int_gamma; +#else +# ifdef PNG_FLOATING_POINT_SUPPORTED + igamma=(png_fixed_point)(info_ptr->gamma * 100000.); +# endif +#endif + if (PNG_OUT_OF_RANGE(igamma, 45500L, 500)) + { + png_warning(png_ptr, + "Ignoring incorrect gAMA value when sRGB is also present"); +#ifdef PNG_CONSOLE_IO_SUPPORTED +# ifdef PNG_FIXED_POINT_SUPPORTED + fprintf(stderr, "incorrect gamma=(%d/100000)\n", + (int)png_ptr->int_gamma); +# else +# ifdef PNG_FLOATING_POINT_SUPPORTED + fprintf(stderr, "incorrect gamma=%f\n", png_ptr->gamma); +# endif +# endif +#endif + } + } +#endif /* PNG_READ_gAMA_SUPPORTED */ + +#ifdef PNG_READ_cHRM_SUPPORTED +#ifdef PNG_FIXED_POINT_SUPPORTED + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) + if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_x_red, 64000L, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_y_red, 33000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_x_blue, 15000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_y_blue, 6000, 1000)) + { + png_warning(png_ptr, + "Ignoring incorrect cHRM value when sRGB is also present"); + } +#endif /* PNG_FIXED_POINT_SUPPORTED */ +#endif /* PNG_READ_cHRM_SUPPORTED */ + + png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent); +} +#endif /* PNG_READ_sRGB_SUPPORTED */ + +#ifdef PNG_READ_iCCP_SUPPORTED +void /* PRIVATE */ +png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +/* Note: this does not properly handle chunks that are > 64K under DOS */ +{ + png_byte compression_type; + png_bytep pC; + png_charp profile; + png_uint_32 skip = 0; + png_uint_32 profile_size, profile_length; + png_size_t slength, prefix_length, data_length; + + png_debug(1, "in png_handle_iCCP"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before iCCP"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid iCCP after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place iCCP chunk"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP)) + { + png_warning(png_ptr, "Duplicate iCCP chunk"); + png_crc_finish(png_ptr, length); + return; + } + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "iCCP chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1); + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, skip)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; + + for (profile = png_ptr->chunkdata; *profile; profile++) + /* Empty loop to find end of name */ ; + + ++profile; + + /* There should be at least one zero (the compression type byte) + * following the separator, and we should be on it + */ + if ( profile >= png_ptr->chunkdata + slength - 1) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "Malformed iCCP chunk"); + return; + } + + /* Compression_type should always be zero */ + compression_type = *profile++; + if (compression_type) + { + png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk"); + compression_type = 0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8 + wrote nonzero) */ + } + + prefix_length = profile - png_ptr->chunkdata; + png_decompress_chunk(png_ptr, compression_type, + slength, prefix_length, &data_length); + + profile_length = data_length - prefix_length; + + if ( prefix_length > data_length || profile_length < 4) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "Profile size field missing from iCCP chunk"); + return; + } + + /* Check the profile_size recorded in the first 32 bits of the ICC profile */ + pC = (png_bytep)(png_ptr->chunkdata + prefix_length); + profile_size = ((*(pC ))<<24) | + ((*(pC + 1))<<16) | + ((*(pC + 2))<< 8) | + ((*(pC + 3)) ); + + if (profile_size < profile_length) + profile_length = profile_size; + + if (profile_size > profile_length) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "Ignoring truncated iCCP profile."); + return; + } + + png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata, + compression_type, png_ptr->chunkdata + prefix_length, profile_length); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; +} +#endif /* PNG_READ_iCCP_SUPPORTED */ + +#ifdef PNG_READ_sPLT_SUPPORTED +void /* PRIVATE */ +png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +/* Note: this does not properly handle chunks that are > 64K under DOS */ +{ + png_bytep entry_start; + png_sPLT_t new_palette; +#ifdef PNG_POINTER_INDEXING_SUPPORTED + png_sPLT_entryp pp; +#endif + int data_length, entry_size, i; + png_uint_32 skip = 0; + png_size_t slength; + + png_debug(1, "in png_handle_sPLT"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + if (--png_ptr->user_chunk_cache_max == 1) + { + png_warning(png_ptr, "No space in chunk cache for sPLT"); + png_crc_finish(png_ptr, length); + return; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sPLT"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sPLT after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "sPLT chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1); + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, skip)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; + + for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start; + entry_start++) + /* Empty loop to find end of name */ ; + ++entry_start; + + /* A sample depth should follow the separator, and we should be on it */ + if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "malformed sPLT chunk"); + return; + } + + new_palette.depth = *entry_start++; + entry_size = (new_palette.depth == 8 ? 6 : 10); + data_length = (slength - (entry_start - (png_bytep)png_ptr->chunkdata)); + + /* Integrity-check the data length */ + if (data_length % entry_size) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "sPLT chunk has bad length"); + return; + } + + new_palette.nentries = (png_int_32) ( data_length / entry_size); + if ((png_uint_32) new_palette.nentries > + (png_uint_32) (PNG_SIZE_MAX / png_sizeof(png_sPLT_entry))) + { + png_warning(png_ptr, "sPLT chunk too long"); + return; + } + new_palette.entries = (png_sPLT_entryp)png_malloc_warn( + png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry)); + if (new_palette.entries == NULL) + { + png_warning(png_ptr, "sPLT chunk requires too much memory"); + return; + } + +#ifdef PNG_POINTER_INDEXING_SUPPORTED + for (i = 0; i < new_palette.nentries; i++) + { + pp = new_palette.entries + i; + + if (new_palette.depth == 8) + { + pp->red = *entry_start++; + pp->green = *entry_start++; + pp->blue = *entry_start++; + pp->alpha = *entry_start++; + } + else + { + pp->red = png_get_uint_16(entry_start); entry_start += 2; + pp->green = png_get_uint_16(entry_start); entry_start += 2; + pp->blue = png_get_uint_16(entry_start); entry_start += 2; + pp->alpha = png_get_uint_16(entry_start); entry_start += 2; + } + pp->frequency = png_get_uint_16(entry_start); entry_start += 2; + } +#else + pp = new_palette.entries; + for (i = 0; i < new_palette.nentries; i++) + { + + if (new_palette.depth == 8) + { + pp[i].red = *entry_start++; + pp[i].green = *entry_start++; + pp[i].blue = *entry_start++; + pp[i].alpha = *entry_start++; + } + else + { + pp[i].red = png_get_uint_16(entry_start); entry_start += 2; + pp[i].green = png_get_uint_16(entry_start); entry_start += 2; + pp[i].blue = png_get_uint_16(entry_start); entry_start += 2; + pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2; + } + pp->frequency = png_get_uint_16(entry_start); entry_start += 2; + } +#endif + + /* Discard all chunk data except the name and stash that */ + new_palette.name = png_ptr->chunkdata; + + png_set_sPLT(png_ptr, info_ptr, &new_palette, 1); + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_free(png_ptr, new_palette.entries); +} +#endif /* PNG_READ_sPLT_SUPPORTED */ + +#ifdef PNG_READ_tRNS_SUPPORTED +void /* PRIVATE */ +png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte readbuf[PNG_MAX_PALETTE_LENGTH]; + + png_debug(1, "in png_handle_tRNS"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before tRNS"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid tRNS after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + png_warning(png_ptr, "Duplicate tRNS chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + png_byte buf[2]; + + if (length != 2) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 2); + png_ptr->num_trans = 1; + png_ptr->trans_values.gray = png_get_uint_16(buf); + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + png_byte buf[6]; + + if (length != 6) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } + png_crc_read(png_ptr, buf, (png_size_t)length); + png_ptr->num_trans = 1; + png_ptr->trans_values.red = png_get_uint_16(buf); + png_ptr->trans_values.green = png_get_uint_16(buf + 2); + png_ptr->trans_values.blue = png_get_uint_16(buf + 4); + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (!(png_ptr->mode & PNG_HAVE_PLTE)) + { + /* Should be an error, but we can cope with it. */ + png_warning(png_ptr, "Missing PLTE before tRNS"); + } + if (length > (png_uint_32)png_ptr->num_palette || + length > PNG_MAX_PALETTE_LENGTH) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } + if (length == 0) + { + png_warning(png_ptr, "Zero length tRNS chunk"); + png_crc_finish(png_ptr, length); + return; + } + png_crc_read(png_ptr, readbuf, (png_size_t)length); + png_ptr->num_trans = (png_uint_16)length; + } + else + { + png_warning(png_ptr, "tRNS chunk not allowed with alpha channel"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_crc_finish(png_ptr, 0)) + { + png_ptr->num_trans = 0; + return; + } + + png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans, + &(png_ptr->trans_values)); +} +#endif + +#ifdef PNG_READ_bKGD_SUPPORTED +void /* PRIVATE */ +png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_size_t truelen; + png_byte buf[6]; + + png_debug(1, "in png_handle_bKGD"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before bKGD"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid bKGD after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + { + png_warning(png_ptr, "Missing PLTE before bKGD"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD)) + { + png_warning(png_ptr, "Duplicate bKGD chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + truelen = 1; + else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + truelen = 6; + else + truelen = 2; + + if (length != truelen) + { + png_warning(png_ptr, "Incorrect bKGD chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, truelen); + if (png_crc_finish(png_ptr, 0)) + return; + + /* We convert the index value into RGB components so that we can allow + * arbitrary RGB values for background when we have transparency, and + * so it is easy to determine the RGB values of the background color + * from the info_ptr struct. */ + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_ptr->background.index = buf[0]; + if (info_ptr && info_ptr->num_palette) + { + if (buf[0] >= info_ptr->num_palette) + { + png_warning(png_ptr, "Incorrect bKGD chunk index value"); + return; + } + png_ptr->background.red = + (png_uint_16)png_ptr->palette[buf[0]].red; + png_ptr->background.green = + (png_uint_16)png_ptr->palette[buf[0]].green; + png_ptr->background.blue = + (png_uint_16)png_ptr->palette[buf[0]].blue; + } + } + else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */ + { + png_ptr->background.red = + png_ptr->background.green = + png_ptr->background.blue = + png_ptr->background.gray = png_get_uint_16(buf); + } + else + { + png_ptr->background.red = png_get_uint_16(buf); + png_ptr->background.green = png_get_uint_16(buf + 2); + png_ptr->background.blue = png_get_uint_16(buf + 4); + } + + png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background)); +} +#endif + +#ifdef PNG_READ_hIST_SUPPORTED +void /* PRIVATE */ +png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + unsigned int num, i; + png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH]; + + png_debug(1, "in png_handle_hIST"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before hIST"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid hIST after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (!(png_ptr->mode & PNG_HAVE_PLTE)) + { + png_warning(png_ptr, "Missing PLTE before hIST"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST)) + { + png_warning(png_ptr, "Duplicate hIST chunk"); + png_crc_finish(png_ptr, length); + return; + } + + num = length / 2 ; + if (num != (unsigned int) png_ptr->num_palette || num > + (unsigned int) PNG_MAX_PALETTE_LENGTH) + { + png_warning(png_ptr, "Incorrect hIST chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + for (i = 0; i < num; i++) + { + png_byte buf[2]; + + png_crc_read(png_ptr, buf, 2); + readbuf[i] = png_get_uint_16(buf); + } + + if (png_crc_finish(png_ptr, 0)) + return; + + png_set_hIST(png_ptr, info_ptr, readbuf); +} +#endif + +#ifdef PNG_READ_pHYs_SUPPORTED +void /* PRIVATE */ +png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[9]; + png_uint_32 res_x, res_y; + int unit_type; + + png_debug(1, "in png_handle_pHYs"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before pHYs"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid pHYs after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_warning(png_ptr, "Duplicate pHYs chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 9) + { + png_warning(png_ptr, "Incorrect pHYs chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 9); + if (png_crc_finish(png_ptr, 0)) + return; + + res_x = png_get_uint_32(buf); + res_y = png_get_uint_32(buf + 4); + unit_type = buf[8]; + png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type); +} +#endif + +#ifdef PNG_READ_oFFs_SUPPORTED +void /* PRIVATE */ +png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[9]; + png_int_32 offset_x, offset_y; + int unit_type; + + png_debug(1, "in png_handle_oFFs"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before oFFs"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid oFFs after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_warning(png_ptr, "Duplicate oFFs chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 9) + { + png_warning(png_ptr, "Incorrect oFFs chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 9); + if (png_crc_finish(png_ptr, 0)) + return; + + offset_x = png_get_int_32(buf); + offset_y = png_get_int_32(buf + 4); + unit_type = buf[8]; + png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type); +} +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED +/* Read the pCAL chunk (described in the PNG Extensions document) */ +void /* PRIVATE */ +png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_int_32 X0, X1; + png_byte type, nparams; + png_charp buf, units, endptr; + png_charpp params; + png_size_t slength; + int i; + + png_debug(1, "in png_handle_pCAL"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before pCAL"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid pCAL after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL)) + { + png_warning(png_ptr, "Duplicate pCAL chunk"); + png_crc_finish(png_ptr, length); + return; + } + + png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)", + length + 1); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "No memory for pCAL purpose."); + return; + } + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */ + + png_debug(3, "Finding end of pCAL purpose string"); + for (buf = png_ptr->chunkdata; *buf; buf++) + /* Empty loop */ ; + + endptr = png_ptr->chunkdata + slength; + + /* We need to have at least 12 bytes after the purpose string + in order to get the parameter information. */ + if (endptr <= buf + 12) + { + png_warning(png_ptr, "Invalid pCAL data"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_debug(3, "Reading pCAL X0, X1, type, nparams, and units"); + X0 = png_get_int_32((png_bytep)buf+1); + X1 = png_get_int_32((png_bytep)buf+5); + type = buf[9]; + nparams = buf[10]; + units = buf + 11; + + png_debug(3, "Checking pCAL equation type and number of parameters"); + /* Check that we have the right number of parameters for known + equation types. */ + if ((type == PNG_EQUATION_LINEAR && nparams != 2) || + (type == PNG_EQUATION_BASE_E && nparams != 3) || + (type == PNG_EQUATION_ARBITRARY && nparams != 3) || + (type == PNG_EQUATION_HYPERBOLIC && nparams != 4)) + { + png_warning(png_ptr, "Invalid pCAL parameters for equation type"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + else if (type >= PNG_EQUATION_LAST) + { + png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); + } + + for (buf = units; *buf; buf++) + /* Empty loop to move past the units string. */ ; + + png_debug(3, "Allocating pCAL parameters array"); + params = (png_charpp)png_malloc_warn(png_ptr, + (png_uint_32)(nparams * png_sizeof(png_charp))) ; + if (params == NULL) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "No memory for pCAL params."); + return; + } + + /* Get pointers to the start of each parameter string. */ + for (i = 0; i < (int)nparams; i++) + { + buf++; /* Skip the null string terminator from previous parameter. */ + + png_debug1(3, "Reading pCAL parameter %d", i); + for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++) + /* Empty loop to move past each parameter string */ ; + + /* Make sure we haven't run out of data yet */ + if (buf > endptr) + { + png_warning(png_ptr, "Invalid pCAL data"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_free(png_ptr, params); + return; + } + } + + png_set_pCAL(png_ptr, info_ptr, png_ptr->chunkdata, X0, X1, type, nparams, + units, params); + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_free(png_ptr, params); +} +#endif + +#ifdef PNG_READ_sCAL_SUPPORTED +/* Read the sCAL chunk */ +void /* PRIVATE */ +png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_charp ep; +#ifdef PNG_FLOATING_POINT_SUPPORTED + double width, height; + png_charp vp; +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + png_charp swidth, sheight; +#endif +#endif + png_size_t slength; + + png_debug(1, "in png_handle_sCAL"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sCAL"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sCAL after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL)) + { + png_warning(png_ptr, "Duplicate sCAL chunk"); + png_crc_finish(png_ptr, length); + return; + } + + png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)", + length + 1); + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "Out of memory while processing sCAL chunk"); + png_crc_finish(png_ptr, length); + return; + } + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */ + + ep = png_ptr->chunkdata + 1; /* Skip unit byte */ + +#ifdef PNG_FLOATING_POINT_SUPPORTED + width = png_strtod(png_ptr, ep, &vp); + if (*vp) + { + png_warning(png_ptr, "malformed width string in sCAL chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1); + if (swidth == NULL) + { + png_warning(png_ptr, "Out of memory while processing sCAL chunk width"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + png_memcpy(swidth, ep, (png_size_t)png_strlen(ep)); +#endif +#endif + + for (ep = png_ptr->chunkdata; *ep; ep++) + /* Empty loop */ ; + ep++; + + if (png_ptr->chunkdata + slength < ep) + { + png_warning(png_ptr, "Truncated sCAL chunk"); +#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, swidth); +#endif + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + +#ifdef PNG_FLOATING_POINT_SUPPORTED + height = png_strtod(png_ptr, ep, &vp); + if (*vp) + { + png_warning(png_ptr, "malformed height string in sCAL chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; +#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, swidth); +#endif + return; + } +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1); + if (sheight == NULL) + { + png_warning(png_ptr, "Out of memory while processing sCAL chunk height"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; +#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, swidth); +#endif + return; + } + png_memcpy(sheight, ep, (png_size_t)png_strlen(ep)); +#endif +#endif + + if (png_ptr->chunkdata + slength < ep +#ifdef PNG_FLOATING_POINT_SUPPORTED + || width <= 0. || height <= 0. +#endif + ) + { + png_warning(png_ptr, "Invalid sCAL data"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; +#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, swidth); + png_free(png_ptr, sheight); +#endif + return; + } + + +#ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_sCAL(png_ptr, info_ptr, png_ptr->chunkdata[0], width, height); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], swidth, sheight); +#endif +#endif + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; +#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, swidth); + png_free(png_ptr, sheight); +#endif +} +#endif + +#ifdef PNG_READ_tIME_SUPPORTED +void /* PRIVATE */ +png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[7]; + png_time mod_time; + + png_debug(1, "in png_handle_tIME"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Out of place tIME chunk"); + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME)) + { + png_warning(png_ptr, "Duplicate tIME chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + + if (length != 7) + { + png_warning(png_ptr, "Incorrect tIME chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 7); + if (png_crc_finish(png_ptr, 0)) + return; + + mod_time.second = buf[6]; + mod_time.minute = buf[5]; + mod_time.hour = buf[4]; + mod_time.day = buf[3]; + mod_time.month = buf[2]; + mod_time.year = png_get_uint_16(buf); + + png_set_tIME(png_ptr, info_ptr, &mod_time); +} +#endif + +#ifdef PNG_READ_tEXt_SUPPORTED +/* Note: this does not properly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_textp text_ptr; + png_charp key; + png_charp text; + png_uint_32 skip = 0; + png_size_t slength; + int ret; + + png_debug(1, "in png_handle_tEXt"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + if (--png_ptr->user_chunk_cache_max == 1) + { + png_warning(png_ptr, "No space in chunk cache for tEXt"); + png_crc_finish(png_ptr, length); + return; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before tEXt"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "tEXt chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "No memory to process text chunk."); + return; + } + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, skip)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + key = png_ptr->chunkdata; + + key[slength] = 0x00; + + for (text = key; *text; text++) + /* Empty loop to find end of key */ ; + + if (text != key + slength) + text++; + + text_ptr = (png_textp)png_malloc_warn(png_ptr, + (png_uint_32)png_sizeof(png_text)); + if (text_ptr == NULL) + { + png_warning(png_ptr, "Not enough memory to process text chunk."); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr->key = key; +#ifdef PNG_iTXt_SUPPORTED + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; + text_ptr->itxt_length = 0; +#endif + text_ptr->text = text; + text_ptr->text_length = png_strlen(text); + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_free(png_ptr, text_ptr); + if (ret) + png_warning(png_ptr, "Insufficient memory to process text chunk."); +} +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED +/* Note: this does not correctly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_textp text_ptr; + png_charp text; + int comp_type; + int ret; + png_size_t slength, prefix_len, data_len; + + png_debug(1, "in png_handle_zTXt"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + if (--png_ptr->user_chunk_cache_max == 1) + { + png_warning(png_ptr, "No space in chunk cache for zTXt"); + png_crc_finish(png_ptr, length); + return; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before zTXt"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + +#ifdef PNG_MAX_MALLOC_64K + /* We will no doubt have problems with chunks even half this size, but + there is no hard and fast rule to tell us where to stop. */ + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "zTXt chunk too large to fit in memory"); + png_crc_finish(png_ptr, length); + return; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "Out of memory processing zTXt chunk."); + return; + } + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; + + for (text = png_ptr->chunkdata; *text; text++) + /* Empty loop */ ; + + /* zTXt must have some text after the chunkdataword */ + if (text >= png_ptr->chunkdata + slength - 2) + { + png_warning(png_ptr, "Truncated zTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + else + { + comp_type = *(++text); + if (comp_type != PNG_TEXT_COMPRESSION_zTXt) + { + png_warning(png_ptr, "Unknown compression type in zTXt chunk"); + comp_type = PNG_TEXT_COMPRESSION_zTXt; + } + text++; /* Skip the compression_method byte */ + } + prefix_len = text - png_ptr->chunkdata; + + png_decompress_chunk(png_ptr, comp_type, + (png_size_t)length, prefix_len, &data_len); + + text_ptr = (png_textp)png_malloc_warn(png_ptr, + (png_uint_32)png_sizeof(png_text)); + if (text_ptr == NULL) + { + png_warning(png_ptr, "Not enough memory to process zTXt chunk."); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + text_ptr->compression = comp_type; + text_ptr->key = png_ptr->chunkdata; +#ifdef PNG_iTXt_SUPPORTED + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; + text_ptr->itxt_length = 0; +#endif + text_ptr->text = png_ptr->chunkdata + prefix_len; + text_ptr->text_length = data_len; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, text_ptr); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + if (ret) + png_error(png_ptr, "Insufficient memory to store zTXt chunk."); +} +#endif + +#ifdef PNG_READ_iTXt_SUPPORTED +/* Note: this does not correctly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_textp text_ptr; + png_charp key, lang, text, lang_key; + int comp_flag; + int comp_type = 0; + int ret; + png_size_t slength, prefix_len, data_len; + + png_debug(1, "in png_handle_iTXt"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + if (--png_ptr->user_chunk_cache_max == 1) + { + png_warning(png_ptr, "No space in chunk cache for iTXt"); + png_crc_finish(png_ptr, length); + return; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before iTXt"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + +#ifdef PNG_MAX_MALLOC_64K + /* We will no doubt have problems with chunks even half this size, but + there is no hard and fast rule to tell us where to stop. */ + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "iTXt chunk too large to fit in memory"); + png_crc_finish(png_ptr, length); + return; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "No memory to process iTXt chunk."); + return; + } + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; + + for (lang = png_ptr->chunkdata; *lang; lang++) + /* Empty loop */ ; + lang++; /* Skip NUL separator */ + + /* iTXt must have a language tag (possibly empty), two compression bytes, + * translated keyword (possibly empty), and possibly some text after the + * keyword + */ + + if (lang >= png_ptr->chunkdata + slength - 3) + { + png_warning(png_ptr, "Truncated iTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + else + { + comp_flag = *lang++; + comp_type = *lang++; + } + + for (lang_key = lang; *lang_key; lang_key++) + /* Empty loop */ ; + lang_key++; /* Skip NUL separator */ + + if (lang_key >= png_ptr->chunkdata + slength) + { + png_warning(png_ptr, "Truncated iTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + for (text = lang_key; *text; text++) + /* Empty loop */ ; + text++; /* Skip NUL separator */ + if (text >= png_ptr->chunkdata + slength) + { + png_warning(png_ptr, "Malformed iTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + prefix_len = text - png_ptr->chunkdata; + + key=png_ptr->chunkdata; + if (comp_flag) + png_decompress_chunk(png_ptr, comp_type, + (size_t)length, prefix_len, &data_len); + else + data_len = png_strlen(png_ptr->chunkdata + prefix_len); + text_ptr = (png_textp)png_malloc_warn(png_ptr, + (png_uint_32)png_sizeof(png_text)); + if (text_ptr == NULL) + { + png_warning(png_ptr, "Not enough memory to process iTXt chunk."); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + text_ptr->compression = (int)comp_flag + 1; + text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key); + text_ptr->lang = png_ptr->chunkdata + (lang - key); + text_ptr->itxt_length = data_len; + text_ptr->text_length = 0; + text_ptr->key = png_ptr->chunkdata; + text_ptr->text = png_ptr->chunkdata + prefix_len; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, text_ptr); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + if (ret) + png_error(png_ptr, "Insufficient memory to store iTXt chunk."); +} +#endif + +/* This function is called when we haven't found a handler for a + chunk. If there isn't a problem with the chunk itself (ie bad + chunk name, CRC, or a critical chunk), the chunk is silently ignored + -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which + case it will be saved away to be written out later. */ +void /* PRIVATE */ +png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_uint_32 skip = 0; + + png_debug(1, "in png_handle_unknown"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + if (--png_ptr->user_chunk_cache_max == 1) + { + png_warning(png_ptr, "No space in chunk cache for unknown chunk"); + png_crc_finish(png_ptr, length); + return; + } + } +#endif + + if (png_ptr->mode & PNG_HAVE_IDAT) + { +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_CONST PNG_IDAT; +#endif + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* Not an IDAT */ + png_ptr->mode |= PNG_AFTER_IDAT; + } + + if (!(png_ptr->chunk_name[0] & 0x20)) + { +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + && png_ptr->read_user_chunk_fn == NULL +#endif + ) +#endif + png_chunk_error(png_ptr, "unknown critical chunk"); + } + +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + || (png_ptr->read_user_chunk_fn != NULL) +#endif + ) + { +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "unknown chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + png_memcpy((png_charp)png_ptr->unknown_chunk.name, + (png_charp)png_ptr->chunk_name, + png_sizeof(png_ptr->unknown_chunk.name)); + png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1] + = '\0'; + png_ptr->unknown_chunk.size = (png_size_t)length; + if (length == 0) + png_ptr->unknown_chunk.data = NULL; + else + { + png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length); + png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length); + } +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + if (png_ptr->read_user_chunk_fn != NULL) + { + /* Callback to user unknown chunk handler */ + int ret; + ret = (*(png_ptr->read_user_chunk_fn)) + (png_ptr, &png_ptr->unknown_chunk); + if (ret < 0) + png_chunk_error(png_ptr, "error in user chunk"); + if (ret == 0) + { + if (!(png_ptr->chunk_name[0] & 0x20)) +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS) +#endif + png_chunk_error(png_ptr, "unknown critical chunk"); + png_set_unknown_chunks(png_ptr, info_ptr, + &png_ptr->unknown_chunk, 1); + } + } + else +#endif + png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; + } + else +#endif + skip = length; + + png_crc_finish(png_ptr, skip); + +#ifndef PNG_READ_USER_CHUNKS_SUPPORTED + info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */ +#endif +} + +/* This function is called to verify that a chunk name is valid. + This function can't have the "critical chunk check" incorporated + into it, since in the future we will need to be able to call user + functions to handle unknown critical chunks after we check that + the chunk name itself is valid. */ + +#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) + +void /* PRIVATE */ +png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name) +{ + png_debug(1, "in png_check_chunk_name"); + if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) || + isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3])) + { + png_chunk_error(png_ptr, "invalid chunk type"); + } +} + +/* Combines the row recently read in with the existing pixels in the + row. This routine takes care of alpha and transparency if requested. + This routine also handles the two methods of progressive display + of interlaced images, depending on the mask value. + The mask value describes which pixels are to be combined with + the row. The pattern always repeats every 8 pixels, so just 8 + bits are needed. A one indicates the pixel is to be combined, + a zero indicates the pixel is to be skipped. This is in addition + to any alpha or transparency value associated with the pixel. If + you want all pixels to be combined, pass 0xff (255) in mask. */ + +void /* PRIVATE */ +png_combine_row(png_structp png_ptr, png_bytep row, int mask) +{ + png_debug(1, "in png_combine_row"); + if (mask == 0xff) + { + png_memcpy(row, png_ptr->row_buf + 1, + PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width)); + } + else + { + switch (png_ptr->row_info.pixel_depth) + { + case 1: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_inc, s_start, s_end; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 7; + s_inc = 1; + } + else +#endif + { + s_start = 7; + s_end = 0; + s_inc = -1; + } + + shift = s_start; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + int value; + + value = (*sp >> shift) & 0x01; + *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + else + shift += s_inc; + + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + case 2: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_start, s_end, s_inc; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + int value; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 6; + s_inc = 2; + } + else +#endif + { + s_start = 6; + s_end = 0; + s_inc = -2; + } + + shift = s_start; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + value = (*sp >> shift) & 0x03; + *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + else + shift += s_inc; + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + case 4: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_start, s_end, s_inc; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + int value; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 4; + s_inc = 4; + } + else +#endif + { + s_start = 4; + s_end = 0; + s_inc = -4; + } + shift = s_start; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + value = (*sp >> shift) & 0xf; + *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + else + shift += s_inc; + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + default: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3); + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + png_byte m = 0x80; + + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + png_memcpy(dp, sp, pixel_bytes); + } + + sp += pixel_bytes; + dp += pixel_bytes; + + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + } + } +} + +#ifdef PNG_READ_INTERLACING_SUPPORTED +/* OLD pre-1.0.9 interface: +void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, + png_uint_32 transformations) + */ +void /* PRIVATE */ +png_do_read_interlace(png_structp png_ptr) +{ + png_row_infop row_info = &(png_ptr->row_info); + png_bytep row = png_ptr->row_buf + 1; + int pass = png_ptr->pass; + png_uint_32 transformations = png_ptr->transformations; + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + /* Offset to next interlace block */ + PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + png_debug(1, "in png_do_read_interlace"); + if (row != NULL && row_info != NULL) + { + png_uint_32 final_width; + + final_width = row_info->width * png_pass_inc[pass]; + + switch (row_info->pixel_depth) + { + case 1: + { + png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3); + png_bytep dp = row + (png_size_t)((final_width - 1) >> 3); + int sshift, dshift; + int s_start, s_end, s_inc; + int jstop = png_pass_inc[pass]; + png_byte v; + png_uint_32 i; + int j; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (transformations & PNG_PACKSWAP) + { + sshift = (int)((row_info->width + 7) & 0x07); + dshift = (int)((final_width + 7) & 0x07); + s_start = 7; + s_end = 0; + s_inc = -1; + } + else +#endif + { + sshift = 7 - (int)((row_info->width + 7) & 0x07); + dshift = 7 - (int)((final_width + 7) & 0x07); + s_start = 0; + s_end = 7; + s_inc = 1; + } + + for (i = 0; i < row_info->width; i++) + { + v = (png_byte)((*sp >> sshift) & 0x01); + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + else + dshift += s_inc; + } + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + else + sshift += s_inc; + } + break; + } + case 2: + { + png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2); + png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2); + int sshift, dshift; + int s_start, s_end, s_inc; + int jstop = png_pass_inc[pass]; + png_uint_32 i; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (transformations & PNG_PACKSWAP) + { + sshift = (int)(((row_info->width + 3) & 0x03) << 1); + dshift = (int)(((final_width + 3) & 0x03) << 1); + s_start = 6; + s_end = 0; + s_inc = -2; + } + else +#endif + { + sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1); + dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1); + s_start = 0; + s_end = 6; + s_inc = 2; + } + + for (i = 0; i < row_info->width; i++) + { + png_byte v; + int j; + + v = (png_byte)((*sp >> sshift) & 0x03); + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + else + dshift += s_inc; + } + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + else + sshift += s_inc; + } + break; + } + case 4: + { + png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1); + png_bytep dp = row + (png_size_t)((final_width - 1) >> 1); + int sshift, dshift; + int s_start, s_end, s_inc; + png_uint_32 i; + int jstop = png_pass_inc[pass]; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (transformations & PNG_PACKSWAP) + { + sshift = (int)(((row_info->width + 1) & 0x01) << 2); + dshift = (int)(((final_width + 1) & 0x01) << 2); + s_start = 4; + s_end = 0; + s_inc = -4; + } + else +#endif + { + sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2); + dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2); + s_start = 0; + s_end = 4; + s_inc = 4; + } + + for (i = 0; i < row_info->width; i++) + { + png_byte v = (png_byte)((*sp >> sshift) & 0xf); + int j; + + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + else + dshift += s_inc; + } + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + else + sshift += s_inc; + } + break; + } + default: + { + png_size_t pixel_bytes = (row_info->pixel_depth >> 3); + png_bytep sp = row + (png_size_t)(row_info->width - 1) + * pixel_bytes; + png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes; + + int jstop = png_pass_inc[pass]; + png_uint_32 i; + + for (i = 0; i < row_info->width; i++) + { + png_byte v[8]; + int j; + + png_memcpy(v, sp, pixel_bytes); + for (j = 0; j < jstop; j++) + { + png_memcpy(dp, v, pixel_bytes); + dp -= pixel_bytes; + } + sp -= pixel_bytes; + } + break; + } + } + row_info->width = final_width; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width); + } +#ifndef PNG_READ_PACKSWAP_SUPPORTED + transformations = transformations; /* Silence compiler warning */ +#endif +} +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + +void /* PRIVATE */ +png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row, + png_bytep prev_row, int filter) +{ + png_debug(1, "in png_read_filter_row"); + png_debug2(2, "row = %lu, filter = %d", png_ptr->row_number, filter); + switch (filter) + { + case PNG_FILTER_VALUE_NONE: + break; + case PNG_FILTER_VALUE_SUB: + { + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; + png_bytep rp = row + bpp; + png_bytep lp = row; + + for (i = bpp; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff); + rp++; + } + break; + } + case PNG_FILTER_VALUE_UP: + { + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + png_bytep rp = row; + png_bytep pp = prev_row; + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } + break; + } + case PNG_FILTER_VALUE_AVG: + { + png_uint_32 i; + png_bytep rp = row; + png_bytep pp = prev_row; + png_bytep lp = row; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; + png_uint_32 istop = row_info->rowbytes - bpp; + + for (i = 0; i < bpp; i++) + { + *rp = (png_byte)(((int)(*rp) + + ((int)(*pp++) / 2 )) & 0xff); + rp++; + } + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + + (int)(*pp++ + *lp++) / 2 ) & 0xff); + rp++; + } + break; + } + case PNG_FILTER_VALUE_PAETH: + { + png_uint_32 i; + png_bytep rp = row; + png_bytep pp = prev_row; + png_bytep lp = row; + png_bytep cp = prev_row; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; + png_uint_32 istop=row_info->rowbytes - bpp; + + for (i = 0; i < bpp; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } + + for (i = 0; i < istop; i++) /* Use leftover rp,pp */ + { + int a, b, c, pa, pb, pc, p; + + a = *lp++; + b = *pp++; + c = *cp++; + + p = b - c; + pc = a - c; + +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + + /* + if (pa <= pb && pa <= pc) + p = a; + else if (pb <= pc) + p = b; + else + p = c; + */ + + p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c; + + *rp = (png_byte)(((int)(*rp) + p) & 0xff); + rp++; + } + break; + } + default: + png_warning(png_ptr, "Ignoring bad adaptive filter type"); + *row = 0; + break; + } +} + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +void /* PRIVATE */ +png_read_finish_row(png_structp png_ptr) +{ +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + + png_debug(1, "in png_read_finish_row"); + png_ptr->row_number++; + if (png_ptr->row_number < png_ptr->num_rows) + return; + +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + png_memset_check(png_ptr, png_ptr->prev_row, 0, + png_ptr->rowbytes + 1); + do + { + png_ptr->pass++; + if (png_ptr->pass >= 7) + break; + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + if (!(png_ptr->transformations & PNG_INTERLACE)) + { + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + if (!(png_ptr->num_rows)) + continue; + } + else /* if (png_ptr->transformations & PNG_INTERLACE) */ + break; + } while (png_ptr->iwidth == 0); + + if (png_ptr->pass < 7) + return; + } +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + { +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_CONST PNG_IDAT; +#endif + char extra; + int ret; + + png_ptr->zstream.next_out = (Byte *)&extra; + png_ptr->zstream.avail_out = (uInt)1; + for (;;) + { + if (!(png_ptr->zstream.avail_in)) + { + while (!png_ptr->idat_size) + { + png_byte chunk_length[4]; + + png_crc_finish(png_ptr, 0); + + png_read_data(png_ptr, chunk_length, 4); + png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_error(png_ptr, "Not enough image data"); + + } + png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_in = png_ptr->zbuf; + if (png_ptr->zbuf_size > png_ptr->idat_size) + png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; + png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in); + png_ptr->idat_size -= png_ptr->zstream.avail_in; + } + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret == Z_STREAM_END) + { + if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in || + png_ptr->idat_size) + png_warning(png_ptr, "Extra compressed data."); + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + if (ret != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : + "Decompression Error"); + + if (!(png_ptr->zstream.avail_out)) + { + png_warning(png_ptr, "Extra compressed data."); + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + + } + png_ptr->zstream.avail_out = 0; + } + + if (png_ptr->idat_size || png_ptr->zstream.avail_in) + png_warning(png_ptr, "Extra compression data."); + + inflateReset(&png_ptr->zstream); + + png_ptr->mode |= PNG_AFTER_IDAT; +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +void /* PRIVATE */ +png_read_start_row(png_structp png_ptr) +{ +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + int max_pixel_depth; + png_size_t row_bytes; + + png_debug(1, "in png_read_start_row"); + png_ptr->zstream.avail_in = 0; + png_init_read_transformations(png_ptr); +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (png_ptr->interlaced) + { + if (!(png_ptr->transformations & PNG_INTERLACE)) + png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - + png_pass_ystart[0]) / png_pass_yinc[0]; + else + png_ptr->num_rows = png_ptr->height; + + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + } + else +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + { + png_ptr->num_rows = png_ptr->height; + png_ptr->iwidth = png_ptr->width; + } + max_pixel_depth = png_ptr->pixel_depth; + +#ifdef PNG_READ_PACK_SUPPORTED + if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8) + max_pixel_depth = 8; +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (png_ptr->num_trans) + max_pixel_depth = 32; + else + max_pixel_depth = 24; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + if (max_pixel_depth < 8) + max_pixel_depth = 8; + if (png_ptr->num_trans) + max_pixel_depth *= 2; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + if (png_ptr->num_trans) + { + max_pixel_depth *= 4; + max_pixel_depth /= 3; + } + } + } +#endif + +#ifdef PNG_READ_FILLER_SUPPORTED + if (png_ptr->transformations & (PNG_FILLER)) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + max_pixel_depth = 32; + else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + if (max_pixel_depth <= 8) + max_pixel_depth = 16; + else + max_pixel_depth = 32; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + if (max_pixel_depth <= 32) + max_pixel_depth = 32; + else + max_pixel_depth = 64; + } + } +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + if (png_ptr->transformations & PNG_GRAY_TO_RGB) + { + if ( +#ifdef PNG_READ_EXPAND_SUPPORTED + (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) || +#endif +#ifdef PNG_READ_FILLER_SUPPORTED + (png_ptr->transformations & (PNG_FILLER)) || +#endif + png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (max_pixel_depth <= 16) + max_pixel_depth = 32; + else + max_pixel_depth = 64; + } + else + { + if (max_pixel_depth <= 8) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + max_pixel_depth = 32; + else + max_pixel_depth = 24; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + max_pixel_depth = 64; + else + max_pixel_depth = 48; + } + } +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \ +defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) + if (png_ptr->transformations & PNG_USER_TRANSFORM) + { + int user_pixel_depth = png_ptr->user_transform_depth* + png_ptr->user_transform_channels; + if (user_pixel_depth > max_pixel_depth) + max_pixel_depth=user_pixel_depth; + } +#endif + + /* Align the width on the next larger 8 pixels. Mainly used + * for interlacing + */ + row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7)); + /* Calculate the maximum bytes needed, adding a byte and a pixel + * for safety's sake + */ + row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) + + 1 + ((max_pixel_depth + 7) >> 3); +#ifdef PNG_MAX_MALLOC_64K + if (row_bytes > (png_uint_32)65536L) + png_error(png_ptr, "This image requires a row greater than 64KB"); +#endif + + if (row_bytes + 64 > png_ptr->old_big_row_buf_size) + { + png_free(png_ptr, png_ptr->big_row_buf); + if (png_ptr->interlaced) + png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr, + row_bytes + 64); + else + png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, + row_bytes + 64); + png_ptr->old_big_row_buf_size = row_bytes + 64; + + /* Use 32 bytes of padding before and after row_buf. */ + png_ptr->row_buf = png_ptr->big_row_buf + 32; + png_ptr->old_big_row_buf_size = row_bytes + 64; + } + +#ifdef PNG_MAX_MALLOC_64K + if ((png_uint_32)row_bytes + 1 > (png_uint_32)65536L) + png_error(png_ptr, "This image requires a row greater than 64KB"); +#endif + if ((png_uint_32)row_bytes > (png_uint_32)(PNG_SIZE_MAX - 1)) + png_error(png_ptr, "Row has too many bytes to allocate in memory."); + + if (row_bytes + 1 > png_ptr->old_prev_row_size) + { + png_free(png_ptr, png_ptr->prev_row); + png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)( + row_bytes + 1)); + png_memset_check(png_ptr, png_ptr->prev_row, 0, row_bytes + 1); + png_ptr->old_prev_row_size = row_bytes + 1; + } + + png_ptr->rowbytes = row_bytes; + + png_debug1(3, "width = %lu,", png_ptr->width); + png_debug1(3, "height = %lu,", png_ptr->height); + png_debug1(3, "iwidth = %lu,", png_ptr->iwidth); + png_debug1(3, "num_rows = %lu,", png_ptr->num_rows); + png_debug1(3, "rowbytes = %lu,", png_ptr->rowbytes); + png_debug1(3, "irowbytes = %lu", + PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1); + + png_ptr->flags |= PNG_FLAG_ROW_INIT; +} +#endif /* PNG_READ_SUPPORTED */ diff --git a/contrib/syslinux-4.02/com32/lib/libpng/pngset.c b/contrib/syslinux-4.02/com32/lib/libpng/pngset.c new file mode 100644 index 0000000..717757f --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libpng/pngset.c @@ -0,0 +1,1226 @@ + +/* pngset.c - storage of image information into info struct + * + * Last changed in libpng 1.2.43 [February 25, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * The functions here are used during reads to store data from the file + * into the info struct, and during writes to store application data + * into the info struct for writing into the file. This abstracts the + * info struct and allows us to change the structure in the future. + */ + +#define PNG_INTERNAL +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +#ifdef PNG_bKGD_SUPPORTED +void PNGAPI +png_set_bKGD(png_structp png_ptr, png_infop info_ptr, png_color_16p background) +{ + png_debug1(1, "in %s storage function", "bKGD"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_memcpy(&(info_ptr->background), background, png_sizeof(png_color_16)); + info_ptr->valid |= PNG_INFO_bKGD; +} +#endif + +#ifdef PNG_cHRM_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_cHRM(png_structp png_ptr, png_infop info_ptr, + double white_x, double white_y, double red_x, double red_y, + double green_x, double green_y, double blue_x, double blue_y) +{ + png_debug1(1, "in %s storage function", "cHRM"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->x_white = (float)white_x; + info_ptr->y_white = (float)white_y; + info_ptr->x_red = (float)red_x; + info_ptr->y_red = (float)red_y; + info_ptr->x_green = (float)green_x; + info_ptr->y_green = (float)green_y; + info_ptr->x_blue = (float)blue_x; + info_ptr->y_blue = (float)blue_y; +#ifdef PNG_FIXED_POINT_SUPPORTED + info_ptr->int_x_white = (png_fixed_point)(white_x*100000.+0.5); + info_ptr->int_y_white = (png_fixed_point)(white_y*100000.+0.5); + info_ptr->int_x_red = (png_fixed_point)( red_x*100000.+0.5); + info_ptr->int_y_red = (png_fixed_point)( red_y*100000.+0.5); + info_ptr->int_x_green = (png_fixed_point)(green_x*100000.+0.5); + info_ptr->int_y_green = (png_fixed_point)(green_y*100000.+0.5); + info_ptr->int_x_blue = (png_fixed_point)( blue_x*100000.+0.5); + info_ptr->int_y_blue = (png_fixed_point)( blue_y*100000.+0.5); +#endif + info_ptr->valid |= PNG_INFO_cHRM; +} +#endif /* PNG_FLOATING_POINT_SUPPORTED */ + +#ifdef PNG_FIXED_POINT_SUPPORTED +void PNGAPI +png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr, + png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x, + png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y, + png_fixed_point blue_x, png_fixed_point blue_y) +{ + png_debug1(1, "in %s storage function", "cHRM fixed"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + +#ifdef PNG_CHECK_cHRM_SUPPORTED + if (png_check_cHRM_fixed(png_ptr, + white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y)) +#endif + { + info_ptr->int_x_white = white_x; + info_ptr->int_y_white = white_y; + info_ptr->int_x_red = red_x; + info_ptr->int_y_red = red_y; + info_ptr->int_x_green = green_x; + info_ptr->int_y_green = green_y; + info_ptr->int_x_blue = blue_x; + info_ptr->int_y_blue = blue_y; +#ifdef PNG_FLOATING_POINT_SUPPORTED + info_ptr->x_white = (float)(white_x/100000.); + info_ptr->y_white = (float)(white_y/100000.); + info_ptr->x_red = (float)( red_x/100000.); + info_ptr->y_red = (float)( red_y/100000.); + info_ptr->x_green = (float)(green_x/100000.); + info_ptr->y_green = (float)(green_y/100000.); + info_ptr->x_blue = (float)( blue_x/100000.); + info_ptr->y_blue = (float)( blue_y/100000.); +#endif + info_ptr->valid |= PNG_INFO_cHRM; + } +} +#endif /* PNG_FIXED_POINT_SUPPORTED */ +#endif /* PNG_cHRM_SUPPORTED */ + +#ifdef PNG_gAMA_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma) +{ + double png_gamma; + + png_debug1(1, "in %s storage function", "gAMA"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* Check for overflow */ + if (file_gamma > 21474.83) + { + png_warning(png_ptr, "Limiting gamma to 21474.83"); + png_gamma=21474.83; + } + else + png_gamma = file_gamma; + info_ptr->gamma = (float)png_gamma; +#ifdef PNG_FIXED_POINT_SUPPORTED + info_ptr->int_gamma = (int)(png_gamma*100000.+.5); +#endif + info_ptr->valid |= PNG_INFO_gAMA; + if (png_gamma == 0.0) + png_warning(png_ptr, "Setting gamma=0"); +} +#endif +void PNGAPI +png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point + int_gamma) +{ + png_fixed_point png_gamma; + + png_debug1(1, "in %s storage function", "gAMA"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (int_gamma > (png_fixed_point)PNG_UINT_31_MAX) + { + png_warning(png_ptr, "Limiting gamma to 21474.83"); + png_gamma=PNG_UINT_31_MAX; + } + else + { + if (int_gamma < 0) + { + png_warning(png_ptr, "Setting negative gamma to zero"); + png_gamma = 0; + } + else + png_gamma = int_gamma; + } +#ifdef PNG_FLOATING_POINT_SUPPORTED + info_ptr->gamma = (float)(png_gamma/100000.); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + info_ptr->int_gamma = png_gamma; +#endif + info_ptr->valid |= PNG_INFO_gAMA; + if (png_gamma == 0) + png_warning(png_ptr, "Setting gamma=0"); +} +#endif + +#ifdef PNG_hIST_SUPPORTED +void PNGAPI +png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p hist) +{ + int i; + + png_debug1(1, "in %s storage function", "hIST"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (info_ptr->num_palette == 0 || info_ptr->num_palette + > PNG_MAX_PALETTE_LENGTH) + { + png_warning(png_ptr, + "Invalid palette size, hIST allocation skipped."); + return; + } + +#ifdef PNG_FREE_ME_SUPPORTED + png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0); +#endif + /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in + * version 1.2.1 + */ + png_ptr->hist = (png_uint_16p)png_malloc_warn(png_ptr, + (png_uint_32)(PNG_MAX_PALETTE_LENGTH * png_sizeof(png_uint_16))); + if (png_ptr->hist == NULL) + { + png_warning(png_ptr, "Insufficient memory for hIST chunk data."); + return; + } + + for (i = 0; i < info_ptr->num_palette; i++) + png_ptr->hist[i] = hist[i]; + info_ptr->hist = png_ptr->hist; + info_ptr->valid |= PNG_INFO_hIST; + +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_HIST; +#else + png_ptr->flags |= PNG_FLAG_FREE_HIST; +#endif +} +#endif + +void PNGAPI +png_set_IHDR(png_structp png_ptr, png_infop info_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_type, int compression_type, + int filter_type) +{ + png_debug1(1, "in %s storage function", "IHDR"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->width = width; + info_ptr->height = height; + info_ptr->bit_depth = (png_byte)bit_depth; + info_ptr->color_type = (png_byte)color_type; + info_ptr->compression_type = (png_byte)compression_type; + info_ptr->filter_type = (png_byte)filter_type; + info_ptr->interlace_type = (png_byte)interlace_type; + + png_check_IHDR (png_ptr, info_ptr->width, info_ptr->height, + info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type, + info_ptr->compression_type, info_ptr->filter_type); + + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + info_ptr->channels = 1; + else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) + info_ptr->channels = 3; + else + info_ptr->channels = 1; + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + info_ptr->channels++; + info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth); + + /* Check for potential overflow */ + if (width > (PNG_UINT_32_MAX + >> 3) /* 8-byte RGBA pixels */ + - 64 /* bigrowbuf hack */ + - 1 /* filter byte */ + - 7*8 /* rounding of width to multiple of 8 pixels */ + - 8) /* extra max_pixel_depth pad */ + info_ptr->rowbytes = (png_size_t)0; + else + info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width); +} + +#ifdef PNG_oFFs_SUPPORTED +void PNGAPI +png_set_oFFs(png_structp png_ptr, png_infop info_ptr, + png_int_32 offset_x, png_int_32 offset_y, int unit_type) +{ + png_debug1(1, "in %s storage function", "oFFs"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->x_offset = offset_x; + info_ptr->y_offset = offset_y; + info_ptr->offset_unit_type = (png_byte)unit_type; + info_ptr->valid |= PNG_INFO_oFFs; +} +#endif + +#ifdef PNG_pCAL_SUPPORTED +void PNGAPI +png_set_pCAL(png_structp png_ptr, png_infop info_ptr, + png_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams, + png_charp units, png_charpp params) +{ + png_uint_32 length; + int i; + + png_debug1(1, "in %s storage function", "pCAL"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + length = png_strlen(purpose) + 1; + png_debug1(3, "allocating purpose for info (%lu bytes)", + (unsigned long)length); + info_ptr->pcal_purpose = (png_charp)png_malloc_warn(png_ptr, length); + if (info_ptr->pcal_purpose == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL purpose."); + return; + } + png_memcpy(info_ptr->pcal_purpose, purpose, (png_size_t)length); + + png_debug(3, "storing X0, X1, type, and nparams in info"); + info_ptr->pcal_X0 = X0; + info_ptr->pcal_X1 = X1; + info_ptr->pcal_type = (png_byte)type; + info_ptr->pcal_nparams = (png_byte)nparams; + + length = png_strlen(units) + 1; + png_debug1(3, "allocating units for info (%lu bytes)", + (unsigned long)length); + info_ptr->pcal_units = (png_charp)png_malloc_warn(png_ptr, length); + if (info_ptr->pcal_units == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL units."); + return; + } + png_memcpy(info_ptr->pcal_units, units, (png_size_t)length); + + info_ptr->pcal_params = (png_charpp)png_malloc_warn(png_ptr, + (png_uint_32)((nparams + 1) * png_sizeof(png_charp))); + if (info_ptr->pcal_params == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL params."); + return; + } + + png_memset(info_ptr->pcal_params, 0, (nparams + 1) * png_sizeof(png_charp)); + + for (i = 0; i < nparams; i++) + { + length = png_strlen(params[i]) + 1; + png_debug2(3, "allocating parameter %d for info (%lu bytes)", i, + (unsigned long)length); + info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length); + if (info_ptr->pcal_params[i] == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL parameter."); + return; + } + png_memcpy(info_ptr->pcal_params[i], params[i], (png_size_t)length); + } + + info_ptr->valid |= PNG_INFO_pCAL; +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_PCAL; +#endif +} +#endif + +#if defined(PNG_READ_sCAL_SUPPORTED) || defined(PNG_WRITE_sCAL_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_sCAL(png_structp png_ptr, png_infop info_ptr, + int unit, double width, double height) +{ + png_debug1(1, "in %s storage function", "sCAL"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->scal_unit = (png_byte)unit; + info_ptr->scal_pixel_width = width; + info_ptr->scal_pixel_height = height; + + info_ptr->valid |= PNG_INFO_sCAL; +} +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +void PNGAPI +png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr, + int unit, png_charp swidth, png_charp sheight) +{ + png_uint_32 length; + + png_debug1(1, "in %s storage function", "sCAL"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->scal_unit = (png_byte)unit; + + length = png_strlen(swidth) + 1; + png_debug1(3, "allocating unit for info (%u bytes)", + (unsigned int)length); + info_ptr->scal_s_width = (png_charp)png_malloc_warn(png_ptr, length); + if (info_ptr->scal_s_width == NULL) + { + png_warning(png_ptr, + "Memory allocation failed while processing sCAL."); + return; + } + png_memcpy(info_ptr->scal_s_width, swidth, (png_size_t)length); + + length = png_strlen(sheight) + 1; + png_debug1(3, "allocating unit for info (%u bytes)", + (unsigned int)length); + info_ptr->scal_s_height = (png_charp)png_malloc_warn(png_ptr, length); + if (info_ptr->scal_s_height == NULL) + { + png_free (png_ptr, info_ptr->scal_s_width); + info_ptr->scal_s_width = NULL; + png_warning(png_ptr, + "Memory allocation failed while processing sCAL."); + return; + } + png_memcpy(info_ptr->scal_s_height, sheight, (png_size_t)length); + info_ptr->valid |= PNG_INFO_sCAL; +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_SCAL; +#endif +} +#endif +#endif +#endif + +#ifdef PNG_pHYs_SUPPORTED +void PNGAPI +png_set_pHYs(png_structp png_ptr, png_infop info_ptr, + png_uint_32 res_x, png_uint_32 res_y, int unit_type) +{ + png_debug1(1, "in %s storage function", "pHYs"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->x_pixels_per_unit = res_x; + info_ptr->y_pixels_per_unit = res_y; + info_ptr->phys_unit_type = (png_byte)unit_type; + info_ptr->valid |= PNG_INFO_pHYs; +} +#endif + +void PNGAPI +png_set_PLTE(png_structp png_ptr, png_infop info_ptr, + png_colorp palette, int num_palette) +{ + + png_debug1(1, "in %s storage function", "PLTE"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH) + { + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + png_error(png_ptr, "Invalid palette length"); + else + { + png_warning(png_ptr, "Invalid palette length"); + return; + } + } + + /* It may not actually be necessary to set png_ptr->palette here; + * we do it for backward compatibility with the way the png_handle_tRNS + * function used to do the allocation. + */ +#ifdef PNG_FREE_ME_SUPPORTED + png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0); +#endif + + /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead + * of num_palette entries, in case of an invalid PNG file that has + * too-large sample values. + */ + png_ptr->palette = (png_colorp)png_calloc(png_ptr, + PNG_MAX_PALETTE_LENGTH * png_sizeof(png_color)); + png_memcpy(png_ptr->palette, palette, num_palette * png_sizeof(png_color)); + info_ptr->palette = png_ptr->palette; + info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette; + +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_PLTE; +#else + png_ptr->flags |= PNG_FLAG_FREE_PLTE; +#endif + + info_ptr->valid |= PNG_INFO_PLTE; +} + +#ifdef PNG_sBIT_SUPPORTED +void PNGAPI +png_set_sBIT(png_structp png_ptr, png_infop info_ptr, + png_color_8p sig_bit) +{ + png_debug1(1, "in %s storage function", "sBIT"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_memcpy(&(info_ptr->sig_bit), sig_bit, png_sizeof(png_color_8)); + info_ptr->valid |= PNG_INFO_sBIT; +} +#endif + +#ifdef PNG_sRGB_SUPPORTED +void PNGAPI +png_set_sRGB(png_structp png_ptr, png_infop info_ptr, int intent) +{ + png_debug1(1, "in %s storage function", "sRGB"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->srgb_intent = (png_byte)intent; + info_ptr->valid |= PNG_INFO_sRGB; +} + +void PNGAPI +png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr, + int intent) +{ +#ifdef PNG_gAMA_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED + float file_gamma; +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + png_fixed_point int_file_gamma; +#endif +#endif +#ifdef PNG_cHRM_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED + float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y; +#endif + png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, + int_green_y, int_blue_x, int_blue_y; +#endif + png_debug1(1, "in %s storage function", "sRGB_gAMA_and_cHRM"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_set_sRGB(png_ptr, info_ptr, intent); + +#ifdef PNG_gAMA_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED + file_gamma = (float).45455; + png_set_gAMA(png_ptr, info_ptr, file_gamma); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + int_file_gamma = 45455L; + png_set_gAMA_fixed(png_ptr, info_ptr, int_file_gamma); +#endif +#endif + +#ifdef PNG_cHRM_SUPPORTED + int_white_x = 31270L; + int_white_y = 32900L; + int_red_x = 64000L; + int_red_y = 33000L; + int_green_x = 30000L; + int_green_y = 60000L; + int_blue_x = 15000L; + int_blue_y = 6000L; + +#ifdef PNG_FLOATING_POINT_SUPPORTED + white_x = (float).3127; + white_y = (float).3290; + red_x = (float).64; + red_y = (float).33; + green_x = (float).30; + green_y = (float).60; + blue_x = (float).15; + blue_y = (float).06; +#endif + +#ifdef PNG_FIXED_POINT_SUPPORTED + png_set_cHRM_fixed(png_ptr, info_ptr, + int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, + int_green_y, int_blue_x, int_blue_y); +#endif +#ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_cHRM(png_ptr, info_ptr, + white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y); +#endif +#endif /* cHRM */ +} +#endif /* sRGB */ + + +#ifdef PNG_iCCP_SUPPORTED +void PNGAPI +png_set_iCCP(png_structp png_ptr, png_infop info_ptr, + png_charp name, int compression_type, + png_charp profile, png_uint_32 proflen) +{ + png_charp new_iccp_name; + png_charp new_iccp_profile; + png_uint_32 length; + + png_debug1(1, "in %s storage function", "iCCP"); + + if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL) + return; + + length = png_strlen(name)+1; + new_iccp_name = (png_charp)png_malloc_warn(png_ptr, length); + if (new_iccp_name == NULL) + { + png_warning(png_ptr, "Insufficient memory to process iCCP chunk."); + return; + } + png_memcpy(new_iccp_name, name, length); + new_iccp_profile = (png_charp)png_malloc_warn(png_ptr, proflen); + if (new_iccp_profile == NULL) + { + png_free (png_ptr, new_iccp_name); + png_warning(png_ptr, + "Insufficient memory to process iCCP profile."); + return; + } + png_memcpy(new_iccp_profile, profile, (png_size_t)proflen); + + png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0); + + info_ptr->iccp_proflen = proflen; + info_ptr->iccp_name = new_iccp_name; + info_ptr->iccp_profile = new_iccp_profile; + /* Compression is always zero but is here so the API and info structure + * does not have to change if we introduce multiple compression types + */ + info_ptr->iccp_compression = (png_byte)compression_type; +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_ICCP; +#endif + info_ptr->valid |= PNG_INFO_iCCP; +} +#endif + +#ifdef PNG_TEXT_SUPPORTED +void PNGAPI +png_set_text(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, + int num_text) +{ + int ret; + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text); + if (ret) + png_error(png_ptr, "Insufficient memory to store text"); +} + +int /* PRIVATE */ +png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, + int num_text) +{ + int i; + + png_debug1(1, "in %s storage function", ((png_ptr == NULL || + png_ptr->chunk_name[0] == '\0') ? + "text" : (png_const_charp)png_ptr->chunk_name)); + + if (png_ptr == NULL || info_ptr == NULL || num_text == 0) + return(0); + + /* Make sure we have enough space in the "text" array in info_struct + * to hold all of the incoming text_ptr objects. + */ + if (info_ptr->num_text + num_text > info_ptr->max_text) + { + if (info_ptr->text != NULL) + { + png_textp old_text; + int old_max; + + old_max = info_ptr->max_text; + info_ptr->max_text = info_ptr->num_text + num_text + 8; + old_text = info_ptr->text; + info_ptr->text = (png_textp)png_malloc_warn(png_ptr, + (png_uint_32)(info_ptr->max_text * png_sizeof(png_text))); + if (info_ptr->text == NULL) + { + png_free(png_ptr, old_text); + return(1); + } + png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max * + png_sizeof(png_text))); + png_free(png_ptr, old_text); + } + else + { + info_ptr->max_text = num_text + 8; + info_ptr->num_text = 0; + info_ptr->text = (png_textp)png_malloc_warn(png_ptr, + (png_uint_32)(info_ptr->max_text * png_sizeof(png_text))); + if (info_ptr->text == NULL) + return(1); +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_TEXT; +#endif + } + png_debug1(3, "allocated %d entries for info_ptr->text", + info_ptr->max_text); + } + for (i = 0; i < num_text; i++) + { + png_size_t text_length, key_len; + png_size_t lang_len, lang_key_len; + png_textp textp = &(info_ptr->text[info_ptr->num_text]); + + if (text_ptr[i].key == NULL) + continue; + + key_len = png_strlen(text_ptr[i].key); + + if (text_ptr[i].compression <= 0) + { + lang_len = 0; + lang_key_len = 0; + } + + else +#ifdef PNG_iTXt_SUPPORTED + { + /* Set iTXt data */ + + if (text_ptr[i].lang != NULL) + lang_len = png_strlen(text_ptr[i].lang); + else + lang_len = 0; + if (text_ptr[i].lang_key != NULL) + lang_key_len = png_strlen(text_ptr[i].lang_key); + else + lang_key_len = 0; + } +#else /* PNG_iTXt_SUPPORTED */ + { + png_warning(png_ptr, "iTXt chunk not supported."); + continue; + } +#endif + + if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0') + { + text_length = 0; +#ifdef PNG_iTXt_SUPPORTED + if (text_ptr[i].compression > 0) + textp->compression = PNG_ITXT_COMPRESSION_NONE; + else +#endif + textp->compression = PNG_TEXT_COMPRESSION_NONE; + } + + else + { + text_length = png_strlen(text_ptr[i].text); + textp->compression = text_ptr[i].compression; + } + + textp->key = (png_charp)png_malloc_warn(png_ptr, + (png_uint_32) + (key_len + text_length + lang_len + lang_key_len + 4)); + if (textp->key == NULL) + return(1); + png_debug2(2, "Allocated %lu bytes at %x in png_set_text", + (png_uint_32) + (key_len + lang_len + lang_key_len + text_length + 4), + (int)textp->key); + + png_memcpy(textp->key, text_ptr[i].key,(png_size_t)(key_len)); + *(textp->key + key_len) = '\0'; +#ifdef PNG_iTXt_SUPPORTED + if (text_ptr[i].compression > 0) + { + textp->lang = textp->key + key_len + 1; + png_memcpy(textp->lang, text_ptr[i].lang, lang_len); + *(textp->lang + lang_len) = '\0'; + textp->lang_key = textp->lang + lang_len + 1; + png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len); + *(textp->lang_key + lang_key_len) = '\0'; + textp->text = textp->lang_key + lang_key_len + 1; + } + else +#endif + { +#ifdef PNG_iTXt_SUPPORTED + textp->lang=NULL; + textp->lang_key=NULL; +#endif + textp->text = textp->key + key_len + 1; + } + if (text_length) + png_memcpy(textp->text, text_ptr[i].text, + (png_size_t)(text_length)); + *(textp->text + text_length) = '\0'; + +#ifdef PNG_iTXt_SUPPORTED + if (textp->compression > 0) + { + textp->text_length = 0; + textp->itxt_length = text_length; + } + else +#endif + + { + textp->text_length = text_length; +#ifdef PNG_iTXt_SUPPORTED + textp->itxt_length = 0; +#endif + } + info_ptr->num_text++; + png_debug1(3, "transferred text chunk %d", info_ptr->num_text); + } + return(0); +} +#endif + +#ifdef PNG_tIME_SUPPORTED +void PNGAPI +png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_timep mod_time) +{ + png_debug1(1, "in %s storage function", "tIME"); + + if (png_ptr == NULL || info_ptr == NULL || + (png_ptr->mode & PNG_WROTE_tIME)) + return; + + png_memcpy(&(info_ptr->mod_time), mod_time, png_sizeof(png_time)); + info_ptr->valid |= PNG_INFO_tIME; +} +#endif + +#ifdef PNG_tRNS_SUPPORTED +void PNGAPI +png_set_tRNS(png_structp png_ptr, png_infop info_ptr, + png_bytep trans, int num_trans, png_color_16p trans_values) +{ + png_debug1(1, "in %s storage function", "tRNS"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (trans != NULL) + { + /* It may not actually be necessary to set png_ptr->trans here; + * we do it for backward compatibility with the way the png_handle_tRNS + * function used to do the allocation. + */ + +#ifdef PNG_FREE_ME_SUPPORTED + png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0); +#endif + + /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */ + png_ptr->trans = info_ptr->trans = (png_bytep)png_malloc(png_ptr, + (png_uint_32)PNG_MAX_PALETTE_LENGTH); + if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH) + png_memcpy(info_ptr->trans, trans, (png_size_t)num_trans); + } + + if (trans_values != NULL) + { + int sample_max = (1 << info_ptr->bit_depth); + if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY && + (int)trans_values->gray > sample_max) || + (info_ptr->color_type == PNG_COLOR_TYPE_RGB && + ((int)trans_values->red > sample_max || + (int)trans_values->green > sample_max || + (int)trans_values->blue > sample_max))) + png_warning(png_ptr, + "tRNS chunk has out-of-range samples for bit_depth"); + png_memcpy(&(info_ptr->trans_values), trans_values, + png_sizeof(png_color_16)); + if (num_trans == 0) + num_trans = 1; + } + + info_ptr->num_trans = (png_uint_16)num_trans; + if (num_trans != 0) + { + info_ptr->valid |= PNG_INFO_tRNS; +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_TRNS; +#else + png_ptr->flags |= PNG_FLAG_FREE_TRNS; +#endif + } +} +#endif + +#ifdef PNG_sPLT_SUPPORTED +void PNGAPI +png_set_sPLT(png_structp png_ptr, + png_infop info_ptr, png_sPLT_tp entries, int nentries) +/* + * entries - array of png_sPLT_t structures + * to be added to the list of palettes + * in the info structure. + * nentries - number of palette structures to be + * added. + */ +{ + png_sPLT_tp np; + int i; + + if (png_ptr == NULL || info_ptr == NULL) + return; + + np = (png_sPLT_tp)png_malloc_warn(png_ptr, + (info_ptr->splt_palettes_num + nentries) * + (png_uint_32)png_sizeof(png_sPLT_t)); + if (np == NULL) + { + png_warning(png_ptr, "No memory for sPLT palettes."); + return; + } + + png_memcpy(np, info_ptr->splt_palettes, + info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t)); + png_free(png_ptr, info_ptr->splt_palettes); + info_ptr->splt_palettes=NULL; + + for (i = 0; i < nentries; i++) + { + png_sPLT_tp to = np + info_ptr->splt_palettes_num + i; + png_sPLT_tp from = entries + i; + png_uint_32 length; + + length = png_strlen(from->name) + 1; + to->name = (png_charp)png_malloc_warn(png_ptr, length); + if (to->name == NULL) + { + png_warning(png_ptr, + "Out of memory while processing sPLT chunk"); + continue; + } + png_memcpy(to->name, from->name, length); + to->entries = (png_sPLT_entryp)png_malloc_warn(png_ptr, + (png_uint_32)(from->nentries * png_sizeof(png_sPLT_entry))); + if (to->entries == NULL) + { + png_warning(png_ptr, + "Out of memory while processing sPLT chunk"); + png_free(png_ptr, to->name); + to->name = NULL; + continue; + } + png_memcpy(to->entries, from->entries, + from->nentries * png_sizeof(png_sPLT_entry)); + to->nentries = from->nentries; + to->depth = from->depth; + } + + info_ptr->splt_palettes = np; + info_ptr->splt_palettes_num += nentries; + info_ptr->valid |= PNG_INFO_sPLT; +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_SPLT; +#endif +} +#endif /* PNG_sPLT_SUPPORTED */ + +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +void PNGAPI +png_set_unknown_chunks(png_structp png_ptr, + png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns) +{ + png_unknown_chunkp np; + int i; + + if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0) + return; + + np = (png_unknown_chunkp)png_malloc_warn(png_ptr, + (png_uint_32)((info_ptr->unknown_chunks_num + num_unknowns) * + png_sizeof(png_unknown_chunk))); + if (np == NULL) + { + png_warning(png_ptr, + "Out of memory while processing unknown chunk."); + return; + } + + png_memcpy(np, info_ptr->unknown_chunks, + info_ptr->unknown_chunks_num * png_sizeof(png_unknown_chunk)); + png_free(png_ptr, info_ptr->unknown_chunks); + info_ptr->unknown_chunks = NULL; + + for (i = 0; i < num_unknowns; i++) + { + png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i; + png_unknown_chunkp from = unknowns + i; + + png_memcpy((png_charp)to->name, (png_charp)from->name, + png_sizeof(from->name)); + to->name[png_sizeof(to->name)-1] = '\0'; + to->size = from->size; + /* Note our location in the read or write sequence */ + to->location = (png_byte)(png_ptr->mode & 0xff); + + if (from->size == 0) + to->data=NULL; + else + { + to->data = (png_bytep)png_malloc_warn(png_ptr, + (png_uint_32)from->size); + if (to->data == NULL) + { + png_warning(png_ptr, + "Out of memory while processing unknown chunk."); + to->size = 0; + } + else + png_memcpy(to->data, from->data, from->size); + } + } + + info_ptr->unknown_chunks = np; + info_ptr->unknown_chunks_num += num_unknowns; +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_UNKN; +#endif +} +void PNGAPI +png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr, + int chunk, int location) +{ + if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk < + (int)info_ptr->unknown_chunks_num) + info_ptr->unknown_chunks[chunk].location = (png_byte)location; +} +#endif + +#if defined(PNG_1_0_X) || defined(PNG_1_2_X) +#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ + defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) +void PNGAPI +png_permit_empty_plte (png_structp png_ptr, int empty_plte_permitted) +{ + /* This function is deprecated in favor of png_permit_mng_features() + and will be removed from libpng-1.3.0 */ + + png_debug(1, "in png_permit_empty_plte, DEPRECATED."); + + if (png_ptr == NULL) + return; + png_ptr->mng_features_permitted = (png_byte) + ((png_ptr->mng_features_permitted & (~PNG_FLAG_MNG_EMPTY_PLTE)) | + ((empty_plte_permitted & PNG_FLAG_MNG_EMPTY_PLTE))); +} +#endif +#endif + +#ifdef PNG_MNG_FEATURES_SUPPORTED +png_uint_32 PNGAPI +png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features) +{ + png_debug(1, "in png_permit_mng_features"); + + if (png_ptr == NULL) + return (png_uint_32)0; + png_ptr->mng_features_permitted = + (png_byte)(mng_features & PNG_ALL_MNG_FEATURES); + return (png_uint_32)png_ptr->mng_features_permitted; +} +#endif + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +void PNGAPI +png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_bytep + chunk_list, int num_chunks) +{ + png_bytep new_list, p; + int i, old_num_chunks; + if (png_ptr == NULL) + return; + if (num_chunks == 0) + { + if (keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE) + png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS; + else + png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS; + + if (keep == PNG_HANDLE_CHUNK_ALWAYS) + png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS; + else + png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS; + return; + } + if (chunk_list == NULL) + return; + old_num_chunks = png_ptr->num_chunk_list; + new_list=(png_bytep)png_malloc(png_ptr, + (png_uint_32) + (5*(num_chunks + old_num_chunks))); + if (png_ptr->chunk_list != NULL) + { + png_memcpy(new_list, png_ptr->chunk_list, + (png_size_t)(5*old_num_chunks)); + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->chunk_list=NULL; + } + png_memcpy(new_list + 5*old_num_chunks, chunk_list, + (png_size_t)(5*num_chunks)); + for (p = new_list + 5*old_num_chunks + 4, i = 0; i<num_chunks; i++, p += 5) + *p=(png_byte)keep; + png_ptr->num_chunk_list = old_num_chunks + num_chunks; + png_ptr->chunk_list = new_list; +#ifdef PNG_FREE_ME_SUPPORTED + png_ptr->free_me |= PNG_FREE_LIST; +#endif +} +#endif + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED +void PNGAPI +png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr, + png_user_chunk_ptr read_user_chunk_fn) +{ + png_debug(1, "in png_set_read_user_chunk_fn"); + + if (png_ptr == NULL) + return; + + png_ptr->read_user_chunk_fn = read_user_chunk_fn; + png_ptr->user_chunk_ptr = user_chunk_ptr; +} +#endif + +#ifdef PNG_INFO_IMAGE_SUPPORTED +void PNGAPI +png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers) +{ + png_debug1(1, "in %s storage function", "rows"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers)) + png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); + info_ptr->row_pointers = row_pointers; + if (row_pointers) + info_ptr->valid |= PNG_INFO_IDAT; +} +#endif + +void PNGAPI +png_set_compression_buffer_size(png_structp png_ptr, + png_uint_32 size) +{ + if (png_ptr == NULL) + return; + png_free(png_ptr, png_ptr->zbuf); + png_ptr->zbuf_size = (png_size_t)size; + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; +} + +void PNGAPI +png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask) +{ + if (png_ptr && info_ptr) + info_ptr->valid &= ~mask; +} + + +#ifndef PNG_1_0_X +#ifdef PNG_ASSEMBLER_CODE_SUPPORTED +/* Function was added to libpng 1.2.0 and should always exist by default */ +void PNGAPI +png_set_asm_flags (png_structp png_ptr, png_uint_32 asm_flags) +{ +/* Obsolete as of libpng-1.2.20 and will be removed from libpng-1.4.0 */ + if (png_ptr != NULL) + png_ptr->asm_flags = 0; + asm_flags = asm_flags; /* Quiet the compiler */ +} + +/* This function was added to libpng 1.2.0 */ +void PNGAPI +png_set_mmx_thresholds (png_structp png_ptr, + png_byte mmx_bitdepth_threshold, + png_uint_32 mmx_rowbytes_threshold) +{ +/* Obsolete as of libpng-1.2.20 and will be removed from libpng-1.4.0 */ + if (png_ptr == NULL) + return; + /* Quiet the compiler */ + mmx_bitdepth_threshold = mmx_bitdepth_threshold; + mmx_rowbytes_threshold = mmx_rowbytes_threshold; +} +#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */ + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +/* This function was added to libpng 1.2.6 */ +void PNGAPI +png_set_user_limits (png_structp png_ptr, png_uint_32 user_width_max, + png_uint_32 user_height_max) +{ + /* Images with dimensions larger than these limits will be + * rejected by png_set_IHDR(). To accept any PNG datastream + * regardless of dimensions, set both limits to 0x7ffffffL. + */ + if (png_ptr == NULL) + return; + png_ptr->user_width_max = user_width_max; + png_ptr->user_height_max = user_height_max; +} +#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ + + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +void PNGAPI +png_set_benign_errors(png_structp png_ptr, int allowed) +{ + png_debug(1, "in png_set_benign_errors"); + + if (allowed) + png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN; + else + png_ptr->flags &= ~PNG_FLAG_BENIGN_ERRORS_WARN; +} +#endif /* PNG_BENIGN_ERRORS_SUPPORTED */ +#endif /* ?PNG_1_0_X */ +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/contrib/syslinux-4.02/com32/lib/libpng/pngtest.c b/contrib/syslinux-4.02/com32/lib/libpng/pngtest.c new file mode 100644 index 0000000..fd0e432 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libpng/pngtest.c @@ -0,0 +1,1705 @@ + +/* pngtest.c - a simple test program to test libpng + * + * Last changed in libpng 1.2.43 [February 25, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This program reads in a PNG image, writes it out again, and then + * compares the two files. If the files are identical, this shows that + * the basic chunk handling, filtering, and (de)compression code is working + * properly. It does not currently test all of the transforms, although + * it probably should. + * + * The program will report "FAIL" in certain legitimate cases: + * 1) when the compression level or filter selection method is changed. + * 2) when the maximum IDAT size (PNG_ZBUF_SIZE in pngconf.h) is not 8192. + * 3) unknown unsafe-to-copy ancillary chunks or unknown critical chunks + * exist in the input file. + * 4) others not listed here... + * In these cases, it is best to check with another tool such as "pngcheck" + * to see what the differences between the two files are. + * + * If a filename is given on the command-line, then this file is used + * for the input, rather than the default "pngtest.png". This allows + * testing a wide variety of files easily. You can also test a number + * of files at once by typing "pngtest -m file1.png file2.png ..." + */ + +#define PNG_PEDANTIC_WARNINGS +#include "png.h" + +#ifdef _WIN32_WCE +# if _WIN32_WCE < 211 + __error__ (f|w)printf functions are not supported on old WindowsCE.; +# endif +# include <windows.h> +# include <stdlib.h> +# define READFILE(file, data, length, check) \ + if (ReadFile(file, data, length, &check, NULL)) check = 0 +# define WRITEFILE(file, data, length, check)) \ + if (WriteFile(file, data, length, &check, NULL)) check = 0 +# define FCLOSE(file) CloseHandle(file) +#else +# include <stdio.h> +# include <stdlib.h> +# define READFILE(file, data, length, check) \ + check=(png_size_t)fread(data, (png_size_t)1, length, file) +# define WRITEFILE(file, data, length, check) \ + check=(png_size_t)fwrite(data, (png_size_t)1, length, file) +# define FCLOSE(file) fclose(file) +#endif + +#ifndef PNG_STDIO_SUPPORTED +# ifdef _WIN32_WCE + typedef HANDLE png_FILE_p; +# else + typedef FILE * png_FILE_p; +# endif +#endif + +/* Makes pngtest verbose so we can find problems (needs to be before png.h) */ +#ifndef PNG_DEBUG +# define PNG_DEBUG 0 +#endif + +#if !PNG_DEBUG +# define SINGLE_ROWBUF_ALLOC /* Makes buffer overruns easier to nail */ +#endif + +/* Turn on CPU timing +#define PNGTEST_TIMING +*/ + +#ifndef PNG_FLOATING_POINT_SUPPORTED +#undef PNGTEST_TIMING +#endif + +#ifdef PNGTEST_TIMING +static float t_start, t_stop, t_decode, t_encode, t_misc; +#include <time.h> +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED +#define PNG_tIME_STRING_LENGTH 29 +static int tIME_chunk_present = 0; +static char tIME_string[PNG_tIME_STRING_LENGTH] = "tIME chunk is not present"; +#endif + +static int verbose = 0; + +int test_one_file PNGARG((PNG_CONST char *inname, PNG_CONST char *outname)); + +#ifdef __TURBOC__ +#include <mem.h> +#endif + +/* Defined so I can write to a file on gui/windowing platforms */ +/* #define STDERR stderr */ +#define STDERR stdout /* For DOS */ + +/* In case a system header (e.g., on AIX) defined jmpbuf */ +#ifdef jmpbuf +# undef jmpbuf +#endif + +/* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */ +#ifndef png_jmpbuf +# define png_jmpbuf(png_ptr) png_ptr->jmpbuf +#endif + +/* Example of using row callbacks to make a simple progress meter */ +static int status_pass = 1; +static int status_dots_requested = 0; +static int status_dots = 1; + +void +#ifdef PNG_1_0_X +PNGAPI +#endif +read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass); +void +#ifdef PNG_1_0_X +PNGAPI +#endif +read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) +{ + if (png_ptr == NULL || row_number > PNG_UINT_31_MAX) + return; + if (status_pass != pass) + { + fprintf(stdout, "\n Pass %d: ", pass); + status_pass = pass; + status_dots = 31; + } + status_dots--; + if (status_dots == 0) + { + fprintf(stdout, "\n "); + status_dots=30; + } + fprintf(stdout, "r"); +} + +void +#ifdef PNG_1_0_X +PNGAPI +#endif +write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass); +void +#ifdef PNG_1_0_X +PNGAPI +#endif +write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) +{ + if (png_ptr == NULL || row_number > PNG_UINT_31_MAX || pass > 7) + return; + fprintf(stdout, "w"); +} + + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED +/* Example of using user transform callback (we don't transform anything, + * but merely examine the row filters. We set this to 256 rather than + * 5 in case illegal filter values are present.) + */ +static png_uint_32 filters_used[256]; +void +#ifdef PNG_1_0_X +PNGAPI +#endif +count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data); +void +#ifdef PNG_1_0_X +PNGAPI +#endif +count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data) +{ + if (png_ptr != NULL && row_info != NULL) + ++filters_used[*(data - 1)]; +} +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +/* Example of using user transform callback (we don't transform anything, + * but merely count the zero samples) + */ + +static png_uint_32 zero_samples; + +void +#ifdef PNG_1_0_X +PNGAPI +#endif +count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data); +void +#ifdef PNG_1_0_X +PNGAPI +#endif +count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data) +{ + png_bytep dp = data; + if (png_ptr == NULL)return; + + /* Contents of row_info: + * png_uint_32 width width of row + * png_uint_32 rowbytes number of bytes in row + * png_byte color_type color type of pixels + * png_byte bit_depth bit depth of samples + * png_byte channels number of channels (1-4) + * png_byte pixel_depth bits per pixel (depth*channels) + */ + + /* Counts the number of zero samples (or zero pixels if color_type is 3 */ + + if (row_info->color_type == 0 || row_info->color_type == 3) + { + int pos = 0; + png_uint_32 n, nstop; + for (n = 0, nstop=row_info->width; n<nstop; n++) + { + if (row_info->bit_depth == 1) + { + if (((*dp << pos++ ) & 0x80) == 0) + zero_samples++; + if (pos == 8) + { + pos = 0; + dp++; + } + } + if (row_info->bit_depth == 2) + { + if (((*dp << (pos+=2)) & 0xc0) == 0) + zero_samples++; + if (pos == 8) + { + pos = 0; + dp++; + } + } + if (row_info->bit_depth == 4) + { + if (((*dp << (pos+=4)) & 0xf0) == 0) + zero_samples++; + if (pos == 8) + { + pos = 0; + dp++; + } + } + if (row_info->bit_depth == 8) + if (*dp++ == 0) + zero_samples++; + if (row_info->bit_depth == 16) + { + if ((*dp | *(dp+1)) == 0) + zero_samples++; + dp+=2; + } + } + } + else /* Other color types */ + { + png_uint_32 n, nstop; + int channel; + int color_channels = row_info->channels; + if (row_info->color_type > 3)color_channels--; + + for (n = 0, nstop=row_info->width; n<nstop; n++) + { + for (channel = 0; channel < color_channels; channel++) + { + if (row_info->bit_depth == 8) + if (*dp++ == 0) + zero_samples++; + if (row_info->bit_depth == 16) + { + if ((*dp | *(dp+1)) == 0) + zero_samples++; + dp+=2; + } + } + if (row_info->color_type > 3) + { + dp++; + if (row_info->bit_depth == 16) + dp++; + } + } + } +} +#endif /* PNG_WRITE_USER_TRANSFORM_SUPPORTED */ + +static int wrote_question = 0; + +#ifndef PNG_STDIO_SUPPORTED +/* START of code to validate stdio-free compilation */ +/* These copies of the default read/write functions come from pngrio.c and + * pngwio.c. They allow "don't include stdio" testing of the library. + * This is the function that does the actual reading of data. If you are + * not reading from a standard C stream, you should create a replacement + * read_data function and use it at run time with png_set_read_fn(), rather + * than changing the library. + */ + +#ifndef USE_FAR_KEYWORD +static void +pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check = 0; + png_voidp io_ptr; + + /* fread() returns 0 on error, so it is OK to store this in a png_size_t + * instead of an int, which is what fread() actually returns. + */ + io_ptr = png_get_io_ptr(png_ptr); + if (io_ptr != NULL) + { + READFILE((png_FILE_p)io_ptr, data, length, check); + } + + if (check != length) + { + png_error(png_ptr, "Read Error!"); + } +} +#else +/* This is the model-independent version. Since the standard I/O library + can't handle far buffers in the medium and small models, we have to copy + the data. +*/ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +static void +pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + int check; + png_byte *n_data; + png_FILE_p io_ptr; + + /* Check if data really is near. If so, use usual code. */ + n_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); + if ((png_bytep)n_data == data) + { + READFILE(io_ptr, n_data, length, check); + } + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t read, remaining, err; + check = 0; + remaining = length; + do + { + read = MIN(NEAR_BUF_SIZE, remaining); + READFILE(io_ptr, buf, 1, err); + png_memcpy(data, buf, read); /* Copy far buffer to near buffer */ + if (err != read) + break; + else + check += err; + data += read; + remaining -= read; + } + while (remaining != 0); + } + if (check != length) + png_error(png_ptr, "read Error"); +} +#endif /* USE_FAR_KEYWORD */ + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +static void +pngtest_flush(png_structp png_ptr) +{ + /* Do nothing; fflush() is said to be just a waste of energy. */ + png_ptr = png_ptr; /* Stifle compiler warning */ +} +#endif + +/* This is the function that does the actual writing of data. If you are + * not writing to a standard C stream, you should create a replacement + * write_data function and use it at run time with png_set_write_fn(), rather + * than changing the library. + */ +#ifndef USE_FAR_KEYWORD +static void +pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_uint_32 check; + + WRITEFILE((png_FILE_p)png_ptr->io_ptr, data, length, check); + if (check != length) + { + png_error(png_ptr, "Write Error"); + } +} +#else +/* This is the model-independent version. Since the standard I/O library + can't handle far buffers in the medium and small models, we have to copy + the data. +*/ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +static void +pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_uint_32 check; + png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */ + png_FILE_p io_ptr; + + /* Check if data really is near. If so, use usual code. */ + near_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); + if ((png_bytep)near_data == data) + { + WRITEFILE(io_ptr, near_data, length, check); + } + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t written, remaining, err; + check = 0; + remaining = length; + do + { + written = MIN(NEAR_BUF_SIZE, remaining); + png_memcpy(buf, data, written); /* Copy far buffer to near buffer */ + WRITEFILE(io_ptr, buf, written, err); + if (err != written) + break; + else + check += err; + data += written; + remaining -= written; + } + while (remaining != 0); + } + if (check != length) + { + png_error(png_ptr, "Write Error"); + } +} +#endif /* USE_FAR_KEYWORD */ + +/* This function is called when there is a warning, but the library thinks + * it can continue anyway. Replacement functions don't have to do anything + * here if you don't want to. In the default configuration, png_ptr is + * not used, but it is passed in case it may be useful. + */ +static void +pngtest_warning(png_structp png_ptr, png_const_charp message) +{ + PNG_CONST char *name = "UNKNOWN (ERROR!)"; + char *test; + test = png_get_error_ptr(png_ptr); + if (test == NULL) + fprintf(STDERR, "%s: libpng warning: %s\n", name, message); + else + fprintf(STDERR, "%s: libpng warning: %s\n", test, message); +} + +/* This is the default error handling function. Note that replacements for + * this function MUST NOT RETURN, or the program will likely crash. This + * function is used by default, or if the program supplies NULL for the + * error function pointer in png_set_error_fn(). + */ +static void +pngtest_error(png_structp png_ptr, png_const_charp message) +{ + pngtest_warning(png_ptr, message); + /* We can return because png_error calls the default handler, which is + * actually OK in this case. + */ +} +#endif /* !PNG_STDIO_SUPPORTED */ +/* END of code to validate stdio-free compilation */ + +/* START of code to validate memory allocation and deallocation */ +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + +/* Allocate memory. For reasonable files, size should never exceed + * 64K. However, zlib may allocate more then 64K if you don't tell + * it not to. See zconf.h and png.h for more information. zlib does + * need to allocate exactly 64K, so whatever you call here must + * have the ability to do that. + * + * This piece of code can be compiled to validate max 64K allocations + * by setting MAXSEG_64K in zlib zconf.h *or* PNG_MAX_MALLOC_64K. + */ +typedef struct memory_information +{ + png_uint_32 size; + png_voidp pointer; + struct memory_information FAR *next; +} memory_information; +typedef memory_information FAR *memory_infop; + +static memory_infop pinformation = NULL; +static int current_allocation = 0; +static int maximum_allocation = 0; +static int total_allocation = 0; +static int num_allocations = 0; + +png_voidp png_debug_malloc PNGARG((png_structp png_ptr, png_uint_32 size)); +void png_debug_free PNGARG((png_structp png_ptr, png_voidp ptr)); + +png_voidp +png_debug_malloc(png_structp png_ptr, png_uint_32 size) +{ + + /* png_malloc has already tested for NULL; png_create_struct calls + * png_debug_malloc directly, with png_ptr == NULL which is OK + */ + + if (size == 0) + return (NULL); + + /* This calls the library allocator twice, once to get the requested + buffer and once to get a new free list entry. */ + { + /* Disable malloc_fn and free_fn */ + memory_infop pinfo; + png_set_mem_fn(png_ptr, NULL, NULL, NULL); + pinfo = (memory_infop)png_malloc(png_ptr, + (png_uint_32)png_sizeof(*pinfo)); + pinfo->size = size; + current_allocation += size; + total_allocation += size; + num_allocations ++; + if (current_allocation > maximum_allocation) + maximum_allocation = current_allocation; + pinfo->pointer = (png_voidp)png_malloc(png_ptr, size); + /* Restore malloc_fn and free_fn */ + png_set_mem_fn(png_ptr, + png_voidp_NULL, (png_malloc_ptr)png_debug_malloc, + (png_free_ptr)png_debug_free); + if (size != 0 && pinfo->pointer == NULL) + { + current_allocation -= size; + total_allocation -= size; + png_error(png_ptr, + "out of memory in pngtest->png_debug_malloc."); + } + pinfo->next = pinformation; + pinformation = pinfo; + /* Make sure the caller isn't assuming zeroed memory. */ + png_memset(pinfo->pointer, 0xdd, pinfo->size); + if (verbose) + printf("png_malloc %lu bytes at %x\n", (unsigned long)size, + pinfo->pointer); + return (png_voidp)(pinfo->pointer); + } +} + +/* Free a pointer. It is removed from the list at the same time. */ +void +png_debug_free(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL) + fprintf(STDERR, "NULL pointer to png_debug_free.\n"); + if (ptr == 0) + { +#if 0 /* This happens all the time. */ + fprintf(STDERR, "WARNING: freeing NULL pointer\n"); +#endif + return; + } + + /* Unlink the element from the list. */ + { + memory_infop FAR *ppinfo = &pinformation; + for (;;) + { + memory_infop pinfo = *ppinfo; + if (pinfo->pointer == ptr) + { + *ppinfo = pinfo->next; + current_allocation -= pinfo->size; + if (current_allocation < 0) + fprintf(STDERR, "Duplicate free of memory\n"); + /* We must free the list element too, but first kill + the memory that is to be freed. */ + png_memset(ptr, 0x55, pinfo->size); + png_free_default(png_ptr, pinfo); + pinfo = NULL; + break; + } + if (pinfo->next == NULL) + { + fprintf(STDERR, "Pointer %x not found\n", (unsigned int)ptr); + break; + } + ppinfo = &pinfo->next; + } + } + + /* Finally free the data. */ + if (verbose) + printf("Freeing %x\n", ptr); + png_free_default(png_ptr, ptr); + ptr = NULL; +} +#endif /* PNG_USER_MEM_SUPPORTED && PNG_DEBUG */ +/* END of code to test memory allocation/deallocation */ + + +/* Demonstration of user chunk support of the sTER and vpAg chunks */ +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED + +/* (sTER is a public chunk not yet known by libpng. vpAg is a private +chunk used in ImageMagick to store "virtual page" size). */ + +static png_uint_32 user_chunk_data[4]; + + /* 0: sTER mode + 1 + * 1: vpAg width + * 2: vpAg height + * 3: vpAg units + */ + +static int read_user_chunk_callback(png_struct *png_ptr, + png_unknown_chunkp chunk) +{ + png_uint_32 + *my_user_chunk_data; + + /* Return one of the following: + * return (-n); chunk had an error + * return (0); did not recognize + * return (n); success + * + * The unknown chunk structure contains the chunk data: + * png_byte name[5]; + * png_byte *data; + * png_size_t size; + * + * Note that libpng has already taken care of the CRC handling. + */ + + if (chunk->name[0] == 115 && chunk->name[1] == 84 && /* s T */ + chunk->name[2] == 69 && chunk->name[3] == 82) /* E R */ + { + /* Found sTER chunk */ + if (chunk->size != 1) + return (-1); /* Error return */ + if (chunk->data[0] != 0 && chunk->data[0] != 1) + return (-1); /* Invalid mode */ + my_user_chunk_data=(png_uint_32 *) png_get_user_chunk_ptr(png_ptr); + my_user_chunk_data[0]=chunk->data[0]+1; + return (1); + } + + if (chunk->name[0] != 118 || chunk->name[1] != 112 || /* v p */ + chunk->name[2] != 65 || chunk->name[3] != 103) /* A g */ + return (0); /* Did not recognize */ + + /* Found ImageMagick vpAg chunk */ + + if (chunk->size != 9) + return (-1); /* Error return */ + + my_user_chunk_data=(png_uint_32 *) png_get_user_chunk_ptr(png_ptr); + + my_user_chunk_data[1]=png_get_uint_31(png_ptr, chunk->data); + my_user_chunk_data[2]=png_get_uint_31(png_ptr, chunk->data + 4); + my_user_chunk_data[3]=(png_uint_32)chunk->data[8]; + + return (1); + +} +#endif +/* END of code to demonstrate user chunk support */ + +/* Test one file */ +int +test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) +{ + static png_FILE_p fpin; + static png_FILE_p fpout; /* "static" prevents setjmp corruption */ + png_structp read_ptr; + png_infop read_info_ptr, end_info_ptr; +#ifdef PNG_WRITE_SUPPORTED + png_structp write_ptr; + png_infop write_info_ptr; + png_infop write_end_info_ptr; +#else + png_structp write_ptr = NULL; + png_infop write_info_ptr = NULL; + png_infop write_end_info_ptr = NULL; +#endif + png_bytep row_buf; + png_uint_32 y; + png_uint_32 width, height; + int num_pass, pass; + int bit_depth, color_type; +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf jmpbuf; +#endif +#endif + +#ifdef _WIN32_WCE + TCHAR path[MAX_PATH]; +#endif + char inbuf[256], outbuf[256]; + + row_buf = NULL; + +#ifdef _WIN32_WCE + MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH); + if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, + NULL)) == INVALID_HANDLE_VALUE) +#else + if ((fpin = fopen(inname, "rb")) == NULL) +#endif + { + fprintf(STDERR, "Could not find input file %s\n", inname); + return (1); + } + +#ifdef _WIN32_WCE + MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH); + if ((fpout = CreateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, + 0, NULL)) == INVALID_HANDLE_VALUE) +#else + if ((fpout = fopen(outname, "wb")) == NULL) +#endif + { + fprintf(STDERR, "Could not open output file %s\n", outname); + FCLOSE(fpin); + return (1); + } + + png_debug(0, "Allocating read and write structures"); +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + read_ptr = + png_create_read_struct_2(PNG_LIBPNG_VER_STRING, png_voidp_NULL, + png_error_ptr_NULL, png_error_ptr_NULL, png_voidp_NULL, + (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free); +#else + read_ptr = + png_create_read_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL, + png_error_ptr_NULL, png_error_ptr_NULL); +#endif +#ifndef PNG_STDIO_SUPPORTED + png_set_error_fn(read_ptr, (png_voidp)inname, pngtest_error, + pngtest_warning); +#endif + +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED + user_chunk_data[0] = 0; + user_chunk_data[1] = 0; + user_chunk_data[2] = 0; + user_chunk_data[3] = 0; + png_set_read_user_chunk_fn(read_ptr, user_chunk_data, + read_user_chunk_callback); + +#endif +#ifdef PNG_WRITE_SUPPORTED +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + write_ptr = + png_create_write_struct_2(PNG_LIBPNG_VER_STRING, png_voidp_NULL, + png_error_ptr_NULL, png_error_ptr_NULL, png_voidp_NULL, + (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free); +#else + write_ptr = + png_create_write_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL, + png_error_ptr_NULL, png_error_ptr_NULL); +#endif +#ifndef PNG_STDIO_SUPPORTED + png_set_error_fn(write_ptr, (png_voidp)inname, pngtest_error, + pngtest_warning); +#endif +#endif + png_debug(0, "Allocating read_info, write_info and end_info structures"); + read_info_ptr = png_create_info_struct(read_ptr); + end_info_ptr = png_create_info_struct(read_ptr); +#ifdef PNG_WRITE_SUPPORTED + write_info_ptr = png_create_info_struct(write_ptr); + write_end_info_ptr = png_create_info_struct(write_ptr); +#endif + +#ifdef PNG_SETJMP_SUPPORTED + png_debug(0, "Setting jmpbuf for read struct"); +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) +#else + if (setjmp(png_jmpbuf(read_ptr))) +#endif + { + fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname); + png_free(read_ptr, row_buf); + row_buf = NULL; + png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); +#ifdef PNG_WRITE_SUPPORTED + png_destroy_info_struct(write_ptr, &write_end_info_ptr); + png_destroy_write_struct(&write_ptr, &write_info_ptr); +#endif + FCLOSE(fpin); + FCLOSE(fpout); + return (1); + } +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(read_ptr), jmpbuf, png_sizeof(jmp_buf)); +#endif + +#ifdef PNG_WRITE_SUPPORTED + png_debug(0, "Setting jmpbuf for write struct"); +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) +#else + if (setjmp(png_jmpbuf(write_ptr))) +#endif + { + fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname); + png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); + png_destroy_info_struct(write_ptr, &write_end_info_ptr); +#ifdef PNG_WRITE_SUPPORTED + png_destroy_write_struct(&write_ptr, &write_info_ptr); +#endif + FCLOSE(fpin); + FCLOSE(fpout); + return (1); + } +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(write_ptr), jmpbuf, png_sizeof(jmp_buf)); +#endif +#endif +#endif + + png_debug(0, "Initializing input and output streams"); +#ifdef PNG_STDIO_SUPPORTED + png_init_io(read_ptr, fpin); +# ifdef PNG_WRITE_SUPPORTED + png_init_io(write_ptr, fpout); +# endif +#else + png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data); +# ifdef PNG_WRITE_SUPPORTED + png_set_write_fn(write_ptr, (png_voidp)fpout, pngtest_write_data, +# ifdef PNG_WRITE_FLUSH_SUPPORTED + pngtest_flush); +# else + NULL); +# endif +# endif +#endif + if (status_dots_requested == 1) + { +#ifdef PNG_WRITE_SUPPORTED + png_set_write_status_fn(write_ptr, write_row_callback); +#endif + png_set_read_status_fn(read_ptr, read_row_callback); + } + else + { +#ifdef PNG_WRITE_SUPPORTED + png_set_write_status_fn(write_ptr, png_write_status_ptr_NULL); +#endif + png_set_read_status_fn(read_ptr, png_read_status_ptr_NULL); + } + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + { + int i; + for (i = 0; i<256; i++) + filters_used[i] = 0; + png_set_read_user_transform_fn(read_ptr, count_filters); + } +#endif +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + zero_samples = 0; + png_set_write_user_transform_fn(write_ptr, count_zero_samples); +#endif + +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +# ifndef PNG_HANDLE_CHUNK_ALWAYS +# define PNG_HANDLE_CHUNK_ALWAYS 3 +# endif + png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS, + png_bytep_NULL, 0); +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +# ifndef PNG_HANDLE_CHUNK_IF_SAFE +# define PNG_HANDLE_CHUNK_IF_SAFE 2 +# endif + png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_IF_SAFE, + png_bytep_NULL, 0); +#endif + + png_debug(0, "Reading info struct"); + png_read_info(read_ptr, read_info_ptr); + + png_debug(0, "Transferring info struct"); + { + int interlace_type, compression_type, filter_type; + + if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth, + &color_type, &interlace_type, &compression_type, &filter_type)) + { + png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth, +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + color_type, interlace_type, compression_type, filter_type); +#else + color_type, PNG_INTERLACE_NONE, compression_type, filter_type); +#endif + } + } +#ifdef PNG_FIXED_POINT_SUPPORTED +#ifdef PNG_cHRM_SUPPORTED + { + png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x, + blue_y; + if (png_get_cHRM_fixed(read_ptr, read_info_ptr, &white_x, &white_y, + &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y)) + { + png_set_cHRM_fixed(write_ptr, write_info_ptr, white_x, white_y, red_x, + red_y, green_x, green_y, blue_x, blue_y); + } + } +#endif +#ifdef PNG_gAMA_SUPPORTED + { + png_fixed_point gamma; + + if (png_get_gAMA_fixed(read_ptr, read_info_ptr, &gamma)) + png_set_gAMA_fixed(write_ptr, write_info_ptr, gamma); + } +#endif +#else /* Use floating point versions */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +#ifdef PNG_cHRM_SUPPORTED + { + double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, + blue_y; + if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x, + &red_y, &green_x, &green_y, &blue_x, &blue_y)) + { + png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x, + red_y, green_x, green_y, blue_x, blue_y); + } + } +#endif +#ifdef PNG_gAMA_SUPPORTED + { + double gamma; + + if (png_get_gAMA(read_ptr, read_info_ptr, &gamma)) + png_set_gAMA(write_ptr, write_info_ptr, gamma); + } +#endif +#endif /* Floating point */ +#endif /* Fixed point */ +#ifdef PNG_iCCP_SUPPORTED + { + png_charp name; + png_charp profile; + png_uint_32 proflen; + int compression_type; + + if (png_get_iCCP(read_ptr, read_info_ptr, &name, &compression_type, + &profile, &proflen)) + { + png_set_iCCP(write_ptr, write_info_ptr, name, compression_type, + profile, proflen); + } + } +#endif +#ifdef PNG_sRGB_SUPPORTED + { + int intent; + + if (png_get_sRGB(read_ptr, read_info_ptr, &intent)) + png_set_sRGB(write_ptr, write_info_ptr, intent); + } +#endif + { + png_colorp palette; + int num_palette; + + if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette)) + png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette); + } +#ifdef PNG_bKGD_SUPPORTED + { + png_color_16p background; + + if (png_get_bKGD(read_ptr, read_info_ptr, &background)) + { + png_set_bKGD(write_ptr, write_info_ptr, background); + } + } +#endif +#ifdef PNG_hIST_SUPPORTED + { + png_uint_16p hist; + + if (png_get_hIST(read_ptr, read_info_ptr, &hist)) + png_set_hIST(write_ptr, write_info_ptr, hist); + } +#endif +#ifdef PNG_oFFs_SUPPORTED + { + png_int_32 offset_x, offset_y; + int unit_type; + + if (png_get_oFFs(read_ptr, read_info_ptr, &offset_x, &offset_y, + &unit_type)) + { + png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type); + } + } +#endif +#ifdef PNG_pCAL_SUPPORTED + { + png_charp purpose, units; + png_charpp params; + png_int_32 X0, X1; + int type, nparams; + + if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type, + &nparams, &units, ¶ms)) + { + png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type, + nparams, units, params); + } + } +#endif +#ifdef PNG_pHYs_SUPPORTED + { + png_uint_32 res_x, res_y; + int unit_type; + + if (png_get_pHYs(read_ptr, read_info_ptr, &res_x, &res_y, &unit_type)) + png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type); + } +#endif +#ifdef PNG_sBIT_SUPPORTED + { + png_color_8p sig_bit; + + if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit)) + png_set_sBIT(write_ptr, write_info_ptr, sig_bit); + } +#endif +#ifdef PNG_sCAL_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED + { + int unit; + double scal_width, scal_height; + + if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width, + &scal_height)) + { + png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height); + } + } +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + { + int unit; + png_charp scal_width, scal_height; + + if (png_get_sCAL_s(read_ptr, read_info_ptr, &unit, &scal_width, + &scal_height)) + { + png_set_sCAL_s(write_ptr, write_info_ptr, unit, scal_width, + scal_height); + } + } +#endif +#endif +#endif +#ifdef PNG_TEXT_SUPPORTED + { + png_textp text_ptr; + int num_text; + + if (png_get_text(read_ptr, read_info_ptr, &text_ptr, &num_text) > 0) + { + png_debug1(0, "Handling %d iTXt/tEXt/zTXt chunks", num_text); + png_set_text(write_ptr, write_info_ptr, text_ptr, num_text); + } + } +#endif +#ifdef PNG_tIME_SUPPORTED + { + png_timep mod_time; + + if (png_get_tIME(read_ptr, read_info_ptr, &mod_time)) + { + png_set_tIME(write_ptr, write_info_ptr, mod_time); +#ifdef PNG_TIME_RFC1123_SUPPORTED + /* We have to use png_memcpy instead of "=" because the string + * pointed to by png_convert_to_rfc1123() gets free'ed before + * we use it. + */ + png_memcpy(tIME_string, + png_convert_to_rfc1123(read_ptr, mod_time), + png_sizeof(tIME_string)); + tIME_string[png_sizeof(tIME_string) - 1] = '\0'; + tIME_chunk_present++; +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + } + } +#endif +#ifdef PNG_tRNS_SUPPORTED + { + png_bytep trans; + int num_trans; + png_color_16p trans_values; + + if (png_get_tRNS(read_ptr, read_info_ptr, &trans, &num_trans, + &trans_values)) + { + int sample_max = (1 << bit_depth); + /* libpng doesn't reject a tRNS chunk with out-of-range samples */ + if (!((color_type == PNG_COLOR_TYPE_GRAY && + (int)trans_values->gray > sample_max) || + (color_type == PNG_COLOR_TYPE_RGB && + ((int)trans_values->red > sample_max || + (int)trans_values->green > sample_max || + (int)trans_values->blue > sample_max)))) + png_set_tRNS(write_ptr, write_info_ptr, trans, num_trans, + trans_values); + } + } +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + { + png_unknown_chunkp unknowns; + int num_unknowns = (int)png_get_unknown_chunks(read_ptr, read_info_ptr, + &unknowns); + if (num_unknowns) + { + png_size_t i; + png_set_unknown_chunks(write_ptr, write_info_ptr, unknowns, + num_unknowns); + /* Copy the locations from the read_info_ptr. The automatically + * generated locations in write_info_ptr are wrong because we + * haven't written anything yet. + */ + for (i = 0; i < (png_size_t)num_unknowns; i++) + png_set_unknown_chunk_location(write_ptr, write_info_ptr, i, + unknowns[i].location); + } + } +#endif + +#ifdef PNG_WRITE_SUPPORTED + png_debug(0, "Writing info struct"); + +/* If we wanted, we could write info in two steps: + * png_write_info_before_PLTE(write_ptr, write_info_ptr); + */ + png_write_info(write_ptr, write_info_ptr); + +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED + if (user_chunk_data[0] != 0) + { + png_byte png_sTER[5] = {115, 84, 69, 82, '\0'}; + + unsigned char + ster_chunk_data[1]; + + if (verbose) + fprintf(STDERR, "\n stereo mode = %lu\n", + (unsigned long)(user_chunk_data[0] - 1)); + ster_chunk_data[0]=(unsigned char)(user_chunk_data[0] - 1); + png_write_chunk(write_ptr, png_sTER, ster_chunk_data, 1); + } + if (user_chunk_data[1] != 0 || user_chunk_data[2] != 0) + { + png_byte png_vpAg[5] = {118, 112, 65, 103, '\0'}; + + unsigned char + vpag_chunk_data[9]; + + if (verbose) + fprintf(STDERR, " vpAg = %lu x %lu, units = %lu\n", + (unsigned long)user_chunk_data[1], + (unsigned long)user_chunk_data[2], + (unsigned long)user_chunk_data[3]); + png_save_uint_32(vpag_chunk_data, user_chunk_data[1]); + png_save_uint_32(vpag_chunk_data + 4, user_chunk_data[2]); + vpag_chunk_data[8] = (unsigned char)(user_chunk_data[3] & 0xff); + png_write_chunk(write_ptr, png_vpAg, vpag_chunk_data, 9); + } + +#endif +#endif + +#ifdef SINGLE_ROWBUF_ALLOC + png_debug(0, "Allocating row buffer..."); + row_buf = (png_bytep)png_malloc(read_ptr, + png_get_rowbytes(read_ptr, read_info_ptr)); + png_debug1(0, "0x%08lx", (unsigned long)row_buf); +#endif /* SINGLE_ROWBUF_ALLOC */ + png_debug(0, "Writing row data"); + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) + num_pass = png_set_interlace_handling(read_ptr); +# ifdef PNG_WRITE_SUPPORTED + png_set_interlace_handling(write_ptr); +# endif +#else + num_pass = 1; +#endif + +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_misc += (t_stop - t_start); + t_start = t_stop; +#endif + for (pass = 0; pass < num_pass; pass++) + { + png_debug1(0, "Writing row data for pass %d", pass); + for (y = 0; y < height; y++) + { +#ifndef SINGLE_ROWBUF_ALLOC + png_debug2(0, "Allocating row buffer (pass %d, y = %ld)...", pass, y); + row_buf = (png_bytep)png_malloc(read_ptr, + png_get_rowbytes(read_ptr, read_info_ptr)); + png_debug2(0, "0x%08lx (%ld bytes)", (unsigned long)row_buf, + png_get_rowbytes(read_ptr, read_info_ptr)); +#endif /* !SINGLE_ROWBUF_ALLOC */ + png_read_rows(read_ptr, (png_bytepp)&row_buf, png_bytepp_NULL, 1); + +#ifdef PNG_WRITE_SUPPORTED +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_decode += (t_stop - t_start); + t_start = t_stop; +#endif + png_write_rows(write_ptr, (png_bytepp)&row_buf, 1); +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_encode += (t_stop - t_start); + t_start = t_stop; +#endif +#endif /* PNG_WRITE_SUPPORTED */ + +#ifndef SINGLE_ROWBUF_ALLOC + png_debug2(0, "Freeing row buffer (pass %d, y = %ld)", pass, y); + png_free(read_ptr, row_buf); + row_buf = NULL; +#endif /* !SINGLE_ROWBUF_ALLOC */ + } + } + +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + png_free_data(read_ptr, read_info_ptr, PNG_FREE_UNKN, -1); +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + png_free_data(write_ptr, write_info_ptr, PNG_FREE_UNKN, -1); +#endif + + png_debug(0, "Reading and writing end_info data"); + + png_read_end(read_ptr, end_info_ptr); +#ifdef PNG_TEXT_SUPPORTED + { + png_textp text_ptr; + int num_text; + + if (png_get_text(read_ptr, end_info_ptr, &text_ptr, &num_text) > 0) + { + png_debug1(0, "Handling %d iTXt/tEXt/zTXt chunks", num_text); + png_set_text(write_ptr, write_end_info_ptr, text_ptr, num_text); + } + } +#endif +#ifdef PNG_tIME_SUPPORTED + { + png_timep mod_time; + + if (png_get_tIME(read_ptr, end_info_ptr, &mod_time)) + { + png_set_tIME(write_ptr, write_end_info_ptr, mod_time); +#ifdef PNG_TIME_RFC1123_SUPPORTED + /* We have to use png_memcpy instead of "=" because the string + pointed to by png_convert_to_rfc1123() gets free'ed before + we use it */ + png_memcpy(tIME_string, + png_convert_to_rfc1123(read_ptr, mod_time), + png_sizeof(tIME_string)); + tIME_string[png_sizeof(tIME_string) - 1] = '\0'; + tIME_chunk_present++; +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + } + } +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + { + png_unknown_chunkp unknowns; + int num_unknowns; + num_unknowns = (int)png_get_unknown_chunks(read_ptr, end_info_ptr, + &unknowns); + if (num_unknowns) + { + png_size_t i; + png_set_unknown_chunks(write_ptr, write_end_info_ptr, unknowns, + num_unknowns); + /* Copy the locations from the read_info_ptr. The automatically + * generated locations in write_end_info_ptr are wrong because we + * haven't written the end_info yet. + */ + for (i = 0; i < (png_size_t)num_unknowns; i++) + png_set_unknown_chunk_location(write_ptr, write_end_info_ptr, i, + unknowns[i].location); + } + } +#endif +#ifdef PNG_WRITE_SUPPORTED + png_write_end(write_ptr, write_end_info_ptr); +#endif + +#ifdef PNG_EASY_ACCESS_SUPPORTED + if (verbose) + { + png_uint_32 iwidth, iheight; + iwidth = png_get_image_width(write_ptr, write_info_ptr); + iheight = png_get_image_height(write_ptr, write_info_ptr); + fprintf(STDERR, "\n Image width = %lu, height = %lu\n", + (unsigned long)iwidth, (unsigned long)iheight); + } +#endif + + png_debug(0, "Destroying data structs"); +#ifdef SINGLE_ROWBUF_ALLOC + png_debug(1, "destroying row_buf for read_ptr"); + png_free(read_ptr, row_buf); + row_buf = NULL; +#endif /* SINGLE_ROWBUF_ALLOC */ + png_debug(1, "destroying read_ptr, read_info_ptr, end_info_ptr"); + png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); +#ifdef PNG_WRITE_SUPPORTED + png_debug(1, "destroying write_end_info_ptr"); + png_destroy_info_struct(write_ptr, &write_end_info_ptr); + png_debug(1, "destroying write_ptr, write_info_ptr"); + png_destroy_write_struct(&write_ptr, &write_info_ptr); +#endif + png_debug(0, "Destruction complete."); + + FCLOSE(fpin); + FCLOSE(fpout); + + png_debug(0, "Opening files for comparison"); +#ifdef _WIN32_WCE + MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH); + if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, + 0, NULL)) == INVALID_HANDLE_VALUE) +#else + if ((fpin = fopen(inname, "rb")) == NULL) +#endif + { + fprintf(STDERR, "Could not find file %s\n", inname); + return (1); + } + +#ifdef _WIN32_WCE + MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH); + if ((fpout = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, + 0, NULL)) == INVALID_HANDLE_VALUE) +#else + if ((fpout = fopen(outname, "rb")) == NULL) +#endif + { + fprintf(STDERR, "Could not find file %s\n", outname); + FCLOSE(fpin); + return (1); + } + + for (;;) + { + png_size_t num_in, num_out; + + READFILE(fpin, inbuf, 1, num_in); + READFILE(fpout, outbuf, 1, num_out); + + if (num_in != num_out) + { + fprintf(STDERR, "\nFiles %s and %s are of a different size\n", + inname, outname); + if (wrote_question == 0) + { + fprintf(STDERR, + " Was %s written with the same maximum IDAT chunk size (%d bytes),", + inname, PNG_ZBUF_SIZE); + fprintf(STDERR, + "\n filtering heuristic (libpng default), compression"); + fprintf(STDERR, + " level (zlib default),\n and zlib version (%s)?\n\n", + ZLIB_VERSION); + wrote_question = 1; + } + FCLOSE(fpin); + FCLOSE(fpout); + return (0); + } + + if (!num_in) + break; + + if (png_memcmp(inbuf, outbuf, num_in)) + { + fprintf(STDERR, "\nFiles %s and %s are different\n", inname, outname); + if (wrote_question == 0) + { + fprintf(STDERR, + " Was %s written with the same maximum IDAT chunk size (%d bytes),", + inname, PNG_ZBUF_SIZE); + fprintf(STDERR, + "\n filtering heuristic (libpng default), compression"); + fprintf(STDERR, + " level (zlib default),\n and zlib version (%s)?\n\n", + ZLIB_VERSION); + wrote_question = 1; + } + FCLOSE(fpin); + FCLOSE(fpout); + return (0); + } + } + + FCLOSE(fpin); + FCLOSE(fpout); + + return (0); +} + +/* Input and output filenames */ +#ifdef RISCOS +static PNG_CONST char *inname = "pngtest/png"; +static PNG_CONST char *outname = "pngout/png"; +#else +static PNG_CONST char *inname = "pngtest.png"; +static PNG_CONST char *outname = "pngout.png"; +#endif + +int +main(int argc, char *argv[]) +{ + int multiple = 0; + int ierror = 0; + + fprintf(STDERR, "\n Testing libpng version %s\n", PNG_LIBPNG_VER_STRING); + fprintf(STDERR, " with zlib version %s\n", ZLIB_VERSION); + fprintf(STDERR, "%s", png_get_copyright(NULL)); + /* Show the version of libpng used in building the library */ + fprintf(STDERR, " library (%lu):%s", + (unsigned long)png_access_version_number(), + png_get_header_version(NULL)); + /* Show the version of libpng used in building the application */ + fprintf(STDERR, " pngtest (%lu):%s", (unsigned long)PNG_LIBPNG_VER, + PNG_HEADER_VERSION_STRING); + fprintf(STDERR, " sizeof(png_struct)=%ld, sizeof(png_info)=%ld\n", + (long)png_sizeof(png_struct), (long)png_sizeof(png_info)); + + /* Do some consistency checking on the memory allocation settings, I'm + * not sure this matters, but it is nice to know, the first of these + * tests should be impossible because of the way the macros are set + * in pngconf.h + */ +#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) + fprintf(STDERR, " NOTE: Zlib compiled for max 64k, libpng not\n"); +#endif + /* I think the following can happen. */ +#if !defined(MAXSEG_64K) && defined(PNG_MAX_MALLOC_64K) + fprintf(STDERR, " NOTE: libpng compiled for max 64k, zlib not\n"); +#endif + + if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING)) + { + fprintf(STDERR, + "Warning: versions are different between png.h and png.c\n"); + fprintf(STDERR, " png.h version: %s\n", PNG_LIBPNG_VER_STRING); + fprintf(STDERR, " png.c version: %s\n\n", png_libpng_ver); + ++ierror; + } + + if (argc > 1) + { + if (strcmp(argv[1], "-m") == 0) + { + multiple = 1; + status_dots_requested = 0; + } + else if (strcmp(argv[1], "-mv") == 0 || + strcmp(argv[1], "-vm") == 0 ) + { + multiple = 1; + verbose = 1; + status_dots_requested = 1; + } + else if (strcmp(argv[1], "-v") == 0) + { + verbose = 1; + status_dots_requested = 1; + inname = argv[2]; + } + else + { + inname = argv[1]; + status_dots_requested = 0; + } + } + + if (!multiple && argc == 3 + verbose) + outname = argv[2 + verbose]; + + if ((!multiple && argc > 3 + verbose) || (multiple && argc < 2)) + { + fprintf(STDERR, + "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n", + argv[0], argv[0]); + fprintf(STDERR, + " reads/writes one PNG file (without -m) or multiple files (-m)\n"); + fprintf(STDERR, + " with -m %s is used as a temporary file\n", outname); + exit(1); + } + + if (multiple) + { + int i; +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + int allocation_now = current_allocation; +#endif + for (i=2; i<argc; ++i) + { + int kerror; + fprintf(STDERR, "\n Testing %s:", argv[i]); + kerror = test_one_file(argv[i], outname); + if (kerror == 0) + { +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + int k; +#endif +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + fprintf(STDERR, "\n PASS (%lu zero samples)\n", + (unsigned long)zero_samples); +#else + fprintf(STDERR, " PASS\n"); +#endif +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + for (k = 0; k<256; k++) + if (filters_used[k]) + fprintf(STDERR, " Filter %d was used %lu times\n", + k, (unsigned long)filters_used[k]); +#endif +#ifdef PNG_TIME_RFC1123_SUPPORTED + if (tIME_chunk_present != 0) + fprintf(STDERR, " tIME = %s\n", tIME_string); + tIME_chunk_present = 0; +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + } + else + { + fprintf(STDERR, " FAIL\n"); + ierror += kerror; + } +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + if (allocation_now != current_allocation) + fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n", + current_allocation - allocation_now); + if (current_allocation != 0) + { + memory_infop pinfo = pinformation; + + fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n", + current_allocation); + while (pinfo != NULL) + { + fprintf(STDERR, " %lu bytes at %x\n", + (unsigned long)pinfo->size, + (unsigned int) pinfo->pointer); + pinfo = pinfo->next; + } + } +#endif + } +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + fprintf(STDERR, " Current memory allocation: %10d bytes\n", + current_allocation); + fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", + maximum_allocation); + fprintf(STDERR, " Total memory allocation: %10d bytes\n", + total_allocation); + fprintf(STDERR, " Number of allocations: %10d\n", + num_allocations); +#endif + } + else + { + int i; + for (i = 0; i<3; ++i) + { + int kerror; +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + int allocation_now = current_allocation; +#endif + if (i == 1) status_dots_requested = 1; + else if (verbose == 0)status_dots_requested = 0; + if (i == 0 || verbose == 1 || ierror != 0) + fprintf(STDERR, "\n Testing %s:", inname); + kerror = test_one_file(inname, outname); + if (kerror == 0) + { + if (verbose == 1 || i == 2) + { +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + int k; +#endif +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + fprintf(STDERR, "\n PASS (%lu zero samples)\n", + (unsigned long)zero_samples); +#else + fprintf(STDERR, " PASS\n"); +#endif +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + for (k = 0; k<256; k++) + if (filters_used[k]) + fprintf(STDERR, " Filter %d was used %lu times\n", + k, (unsigned long)filters_used[k]); +#endif +#ifdef PNG_TIME_RFC1123_SUPPORTED + if (tIME_chunk_present != 0) + fprintf(STDERR, " tIME = %s\n", tIME_string); +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + } + } + else + { + if (verbose == 0 && i != 2) + fprintf(STDERR, "\n Testing %s:", inname); + fprintf(STDERR, " FAIL\n"); + ierror += kerror; + } +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + if (allocation_now != current_allocation) + fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n", + current_allocation - allocation_now); + if (current_allocation != 0) + { + memory_infop pinfo = pinformation; + + fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n", + current_allocation); + while (pinfo != NULL) + { + fprintf(STDERR, " %lu bytes at %x\n", + (unsigned long)pinfo->size, (unsigned int)pinfo->pointer); + pinfo = pinfo->next; + } + } +#endif + } +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + fprintf(STDERR, " Current memory allocation: %10d bytes\n", + current_allocation); + fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", + maximum_allocation); + fprintf(STDERR, " Total memory allocation: %10d bytes\n", + total_allocation); + fprintf(STDERR, " Number of allocations: %10d\n", + num_allocations); +#endif + } + +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_misc += (t_stop - t_start); + t_start = t_stop; + fprintf(STDERR, " CPU time used = %.3f seconds", + (t_misc+t_decode+t_encode)/(float)CLOCKS_PER_SEC); + fprintf(STDERR, " (decoding %.3f,\n", + t_decode/(float)CLOCKS_PER_SEC); + fprintf(STDERR, " encoding %.3f ,", + t_encode/(float)CLOCKS_PER_SEC); + fprintf(STDERR, " other %.3f seconds)\n\n", + t_misc/(float)CLOCKS_PER_SEC); +#endif + + if (ierror == 0) + fprintf(STDERR, " libpng passes test\n"); + else + fprintf(STDERR, " libpng FAILS test\n"); + return (int)(ierror != 0); +} + +/* Generate a compiler error if there is an old png.h in the search path. */ +typedef version_1_2_44 your_png_h_is_not_version_1_2_44; diff --git a/contrib/syslinux-4.02/com32/lib/libpng/pngtrans.c b/contrib/syslinux-4.02/com32/lib/libpng/pngtrans.c new file mode 100644 index 0000000..6ad9dcf --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libpng/pngtrans.c @@ -0,0 +1,699 @@ + +/* pngtrans.c - transforms the data in a row (used by both readers and writers) + * + * Last changed in libpng 1.2.41 [December 3, 2009] + * Copyright (c) 1998-2009 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#define PNG_INTERNAL +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Turn on BGR-to-RGB mapping */ +void PNGAPI +png_set_bgr(png_structp png_ptr) +{ + png_debug(1, "in png_set_bgr"); + + if (png_ptr == NULL) + return; + png_ptr->transformations |= PNG_BGR; +} +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Turn on 16 bit byte swapping */ +void PNGAPI +png_set_swap(png_structp png_ptr) +{ + png_debug(1, "in png_set_swap"); + + if (png_ptr == NULL) + return; + if (png_ptr->bit_depth == 16) + png_ptr->transformations |= PNG_SWAP_BYTES; +} +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Turn on pixel packing */ +void PNGAPI +png_set_packing(png_structp png_ptr) +{ + png_debug(1, "in png_set_packing"); + + if (png_ptr == NULL) + return; + if (png_ptr->bit_depth < 8) + { + png_ptr->transformations |= PNG_PACK; + png_ptr->usr_bit_depth = 8; + } +} +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Turn on packed pixel swapping */ +void PNGAPI +png_set_packswap(png_structp png_ptr) +{ + png_debug(1, "in png_set_packswap"); + + if (png_ptr == NULL) + return; + if (png_ptr->bit_depth < 8) + png_ptr->transformations |= PNG_PACKSWAP; +} +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +void PNGAPI +png_set_shift(png_structp png_ptr, png_color_8p true_bits) +{ + png_debug(1, "in png_set_shift"); + + if (png_ptr == NULL) + return; + png_ptr->transformations |= PNG_SHIFT; + png_ptr->shift = *true_bits; +} +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +int PNGAPI +png_set_interlace_handling(png_structp png_ptr) +{ + png_debug(1, "in png_set_interlace handling"); + + if (png_ptr && png_ptr->interlaced) + { + png_ptr->transformations |= PNG_INTERLACE; + return (7); + } + + return (1); +} +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte on read, or remove a filler or alpha byte on write. + * The filler type has changed in v0.95 to allow future 2-byte fillers + * for 48-bit input data, as well as to avoid problems with some compilers + * that don't like bytes as parameters. + */ +void PNGAPI +png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc) +{ + png_debug(1, "in png_set_filler"); + + if (png_ptr == NULL) + return; + png_ptr->transformations |= PNG_FILLER; +#ifdef PNG_LEGACY_SUPPORTED + png_ptr->filler = (png_byte)filler; +#else + png_ptr->filler = (png_uint_16)filler; +#endif + if (filler_loc == PNG_FILLER_AFTER) + png_ptr->flags |= PNG_FLAG_FILLER_AFTER; + else + png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER; + + /* This should probably go in the "do_read_filler" routine. + * I attempted to do that in libpng-1.0.1a but that caused problems + * so I restored it in libpng-1.0.2a + */ + + if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + png_ptr->usr_channels = 4; + } + + /* Also I added this in libpng-1.0.2a (what happens when we expand + * a less-than-8-bit grayscale to GA? */ + + if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8) + { + png_ptr->usr_channels = 2; + } +} + +#ifndef PNG_1_0_X +/* Added to libpng-1.2.7 */ +void PNGAPI +png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc) +{ + png_debug(1, "in png_set_add_alpha"); + + if (png_ptr == NULL) + return; + png_set_filler(png_ptr, filler, filler_loc); + png_ptr->transformations |= PNG_ADD_ALPHA; +} +#endif + +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +void PNGAPI +png_set_swap_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_swap_alpha"); + + if (png_ptr == NULL) + return; + png_ptr->transformations |= PNG_SWAP_ALPHA; +} +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +void PNGAPI +png_set_invert_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_invert_alpha"); + + if (png_ptr == NULL) + return; + png_ptr->transformations |= PNG_INVERT_ALPHA; +} +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +void PNGAPI +png_set_invert_mono(png_structp png_ptr) +{ + png_debug(1, "in png_set_invert_mono"); + + if (png_ptr == NULL) + return; + png_ptr->transformations |= PNG_INVERT_MONO; +} + +/* Invert monochrome grayscale data */ +void /* PRIVATE */ +png_do_invert(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_invert"); + + /* This test removed from libpng version 1.0.13 and 1.2.0: + * if (row_info->bit_depth == 1 && + */ +#ifdef PNG_USELESS_TESTS_SUPPORTED + if (row == NULL || row_info == NULL) + return; +#endif + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(~(*rp)); + rp++; + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && + row_info->bit_depth == 8) + { + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + + for (i = 0; i < istop; i+=2) + { + *rp = (png_byte)(~(*rp)); + rp+=2; + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && + row_info->bit_depth == 16) + { + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + + for (i = 0; i < istop; i+=4) + { + *rp = (png_byte)(~(*rp)); + *(rp+1) = (png_byte)(~(*(rp+1))); + rp+=4; + } + } +} +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swaps byte order on 16 bit depth images */ +void /* PRIVATE */ +png_do_swap(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_swap"); + + if ( +#ifdef PNG_USELESS_TESTS_SUPPORTED + row != NULL && row_info != NULL && +#endif + row_info->bit_depth == 16) + { + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop= row_info->width * row_info->channels; + + for (i = 0; i < istop; i++, rp += 2) + { + png_byte t = *rp; + *rp = *(rp + 1); + *(rp + 1) = t; + } + } +} +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) +static PNG_CONST png_byte onebppswaptable[256] = { + 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, + 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, + 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, + 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, + 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, + 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, + 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, + 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, + 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, + 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, + 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, + 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, + 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, + 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, + 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, + 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, + 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, + 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, + 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, + 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, + 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, + 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, + 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, + 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, + 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, + 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, + 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, + 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, + 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, + 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, + 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, + 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF +}; + +static PNG_CONST png_byte twobppswaptable[256] = { + 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0, + 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0, + 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4, + 0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4, + 0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8, + 0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8, + 0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC, + 0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC, + 0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1, + 0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1, + 0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5, + 0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5, + 0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9, + 0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9, + 0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD, + 0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD, + 0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2, + 0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2, + 0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6, + 0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6, + 0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA, + 0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA, + 0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE, + 0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE, + 0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3, + 0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3, + 0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7, + 0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7, + 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB, + 0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB, + 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF, + 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF +}; + +static PNG_CONST png_byte fourbppswaptable[256] = { + 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, + 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0, + 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, + 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1, + 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, + 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2, + 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, + 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3, + 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, + 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4, + 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, + 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5, + 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76, + 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6, + 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77, + 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7, + 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78, + 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8, + 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79, + 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9, + 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A, + 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA, + 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B, + 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB, + 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C, + 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC, + 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D, + 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD, + 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E, + 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE, + 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F, + 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF +}; + +/* Swaps pixel packing order within bytes */ +void /* PRIVATE */ +png_do_packswap(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_packswap"); + + if ( +#ifdef PNG_USELESS_TESTS_SUPPORTED + row != NULL && row_info != NULL && +#endif + row_info->bit_depth < 8) + { + png_bytep rp, end, table; + + end = row + row_info->rowbytes; + + if (row_info->bit_depth == 1) + table = (png_bytep)onebppswaptable; + else if (row_info->bit_depth == 2) + table = (png_bytep)twobppswaptable; + else if (row_info->bit_depth == 4) + table = (png_bytep)fourbppswaptable; + else + return; + + for (rp = row; rp < end; rp++) + *rp = table[*rp]; + } +} +#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */ + +#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ + defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +/* Remove filler or alpha byte(s) */ +void /* PRIVATE */ +png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags) +{ + png_debug(1, "in png_do_strip_filler"); + +#ifdef PNG_USELESS_TESTS_SUPPORTED + if (row != NULL && row_info != NULL) +#endif + { + png_bytep sp=row; + png_bytep dp=row; + png_uint_32 row_width=row_info->width; + png_uint_32 i; + + if ((row_info->color_type == PNG_COLOR_TYPE_RGB || + (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && + (flags & PNG_FLAG_STRIP_ALPHA))) && + row_info->channels == 4) + { + if (row_info->bit_depth == 8) + { + /* This converts from RGBX or RGBA to RGB */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + dp+=3; sp+=4; + for (i = 1; i < row_width; i++) + { + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + sp++; + } + } + /* This converts from XRGB or ARGB to RGB */ + else + { + for (i = 0; i < row_width; i++) + { + sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + } + } + row_info->pixel_depth = 24; + row_info->rowbytes = row_width * 3; + } + else /* if (row_info->bit_depth == 16) */ + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */ + sp += 8; dp += 6; + for (i = 1; i < row_width; i++) + { + /* This could be (although png_memcpy is probably slower): + png_memcpy(dp, sp, 6); + sp += 8; + dp += 6; + */ + + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + sp += 2; + } + } + else + { + /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */ + for (i = 0; i < row_width; i++) + { + /* This could be (although png_memcpy is probably slower): + png_memcpy(dp, sp, 6); + sp += 8; + dp += 6; + */ + + sp+=2; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + } + } + row_info->pixel_depth = 48; + row_info->rowbytes = row_width * 6; + } + row_info->channels = 3; + } + else if ((row_info->color_type == PNG_COLOR_TYPE_GRAY || + (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && + (flags & PNG_FLAG_STRIP_ALPHA))) && + row_info->channels == 2) + { + if (row_info->bit_depth == 8) + { + /* This converts from GX or GA to G */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + for (i = 0; i < row_width; i++) + { + *dp++ = *sp++; + sp++; + } + } + /* This converts from XG or AG to G */ + else + { + for (i = 0; i < row_width; i++) + { + sp++; + *dp++ = *sp++; + } + } + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + else /* if (row_info->bit_depth == 16) */ + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This converts from GGXX or GGAA to GG */ + sp += 4; dp += 2; + for (i = 1; i < row_width; i++) + { + *dp++ = *sp++; + *dp++ = *sp++; + sp += 2; + } + } + else + { + /* This converts from XXGG or AAGG to GG */ + for (i = 0; i < row_width; i++) + { + sp += 2; + *dp++ = *sp++; + *dp++ = *sp++; + } + } + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + row_info->channels = 1; + } + if (flags & PNG_FLAG_STRIP_ALPHA) + row_info->color_type &= ~PNG_COLOR_MASK_ALPHA; + } +} +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Swaps red and blue bytes within a pixel */ +void /* PRIVATE */ +png_do_bgr(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_bgr"); + + if ( +#ifdef PNG_USELESS_TESTS_SUPPORTED + row != NULL && row_info != NULL && +#endif + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 3) + { + png_byte save = *rp; + *rp = *(rp + 2); + *(rp + 2) = save; + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 4) + { + png_byte save = *rp; + *rp = *(rp + 2); + *(rp + 2) = save; + } + } + } + else if (row_info->bit_depth == 16) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 6) + { + png_byte save = *rp; + *rp = *(rp + 4); + *(rp + 4) = save; + save = *(rp + 1); + *(rp + 1) = *(rp + 5); + *(rp + 5) = save; + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 8) + { + png_byte save = *rp; + *rp = *(rp + 4); + *(rp + 4) = save; + save = *(rp + 1); + *(rp + 1) = *(rp + 5); + *(rp + 5) = save; + } + } + } + } +} +#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */ + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +void PNGAPI +png_set_user_transform_info(png_structp png_ptr, png_voidp + user_transform_ptr, int user_transform_depth, int user_transform_channels) +{ + png_debug(1, "in png_set_user_transform_info"); + + if (png_ptr == NULL) + return; +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED + png_ptr->user_transform_ptr = user_transform_ptr; + png_ptr->user_transform_depth = (png_byte)user_transform_depth; + png_ptr->user_transform_channels = (png_byte)user_transform_channels; +#else + if (user_transform_ptr || user_transform_depth || user_transform_channels) + png_warning(png_ptr, + "This version of libpng does not support user transform info"); +#endif +} +#endif + +/* This function returns a pointer to the user_transform_ptr associated with + * the user transform functions. The application should free any memory + * associated with this pointer before png_write_destroy and png_read_destroy + * are called. + */ +png_voidp PNGAPI +png_get_user_transform_ptr(png_structp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED + return ((png_voidp)png_ptr->user_transform_ptr); +#else + return (NULL); +#endif +} +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/contrib/syslinux-4.02/com32/lib/libpng/pngvcrd.c b/contrib/syslinux-4.02/com32/lib/libpng/pngvcrd.c new file mode 100644 index 0000000..ce4233e --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libpng/pngvcrd.c @@ -0,0 +1 @@ +/* pnggvrd.c was removed from libpng-1.2.20. */ diff --git a/contrib/syslinux-4.02/com32/lib/libpng/pngwio.c b/contrib/syslinux-4.02/com32/lib/libpng/pngwio.c new file mode 100644 index 0000000..44e5ea9 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libpng/pngwio.c @@ -0,0 +1,260 @@ + +/* pngwio.c - functions for data output + * + * Last changed in libpng 1.2.41 [December 3, 2009] + * Copyright (c) 1998-2009 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file provides a location for all output. Users who need + * special handling are expected to write functions that have the same + * arguments as these and perform similar functions, but that possibly + * use different output methods. Note that you shouldn't change these + * functions, but rather write replacement functions and then change + * them at run time with png_set_write_fn(...). + */ + +#define PNG_INTERNAL +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" +#ifdef PNG_WRITE_SUPPORTED + +/* Write the data to whatever output you are using. The default routine + * writes to a file pointer. Note that this routine sometimes gets called + * with very small lengths, so you should implement some kind of simple + * buffering if you are using unbuffered writes. This should never be asked + * to write more than 64K on a 16 bit machine. + */ + +void /* PRIVATE */ +png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + if (png_ptr->write_data_fn != NULL ) + (*(png_ptr->write_data_fn))(png_ptr, data, length); + else + png_error(png_ptr, "Call to NULL write function"); +} + +#ifdef PNG_STDIO_SUPPORTED +/* This is the function that does the actual writing of data. If you are + * not writing to a standard C stream, you should create a replacement + * write_data function and use it at run time with png_set_write_fn(), rather + * than changing the library. + */ +#ifndef USE_FAR_KEYWORD +void PNGAPI +png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_uint_32 check; + + if (png_ptr == NULL) + return; +#ifdef _WIN32_WCE + if ( !WriteFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) + check = 0; +#else + check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr)); +#endif + if (check != length) + png_error(png_ptr, "Write Error"); +} +#else +/* This is the model-independent version. Since the standard I/O library + * can't handle far buffers in the medium and small models, we have to copy + * the data. + */ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +void PNGAPI +png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_uint_32 check; + png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */ + png_FILE_p io_ptr; + + if (png_ptr == NULL) + return; + /* Check if data really is near. If so, use usual code. */ + near_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); + if ((png_bytep)near_data == data) + { +#ifdef _WIN32_WCE + if ( !WriteFile(io_ptr, near_data, length, &check, NULL) ) + check = 0; +#else + check = fwrite(near_data, 1, length, io_ptr); +#endif + } + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t written, remaining, err; + check = 0; + remaining = length; + do + { + written = MIN(NEAR_BUF_SIZE, remaining); + png_memcpy(buf, data, written); /* Copy far buffer to near buffer */ +#ifdef _WIN32_WCE + if ( !WriteFile(io_ptr, buf, written, &err, NULL) ) + err = 0; +#else + err = fwrite(buf, 1, written, io_ptr); +#endif + if (err != written) + break; + + else + check += err; + + data += written; + remaining -= written; + } + while (remaining != 0); + } + if (check != length) + png_error(png_ptr, "Write Error"); +} + +#endif +#endif + +/* This function is called to output any data pending writing (normally + * to disk). After png_flush is called, there should be no data pending + * writing in any buffers. + */ +#ifdef PNG_WRITE_FLUSH_SUPPORTED +void /* PRIVATE */ +png_flush(png_structp png_ptr) +{ + if (png_ptr->output_flush_fn != NULL) + (*(png_ptr->output_flush_fn))(png_ptr); +} + +#ifdef PNG_STDIO_SUPPORTED +void PNGAPI +png_default_flush(png_structp png_ptr) +{ +#ifndef _WIN32_WCE + png_FILE_p io_ptr; +#endif + if (png_ptr == NULL) + return; +#ifndef _WIN32_WCE + io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr)); + fflush(io_ptr); +#endif +} +#endif +#endif + +/* This function allows the application to supply new output functions for + * libpng if standard C streams aren't being used. + * + * This function takes as its arguments: + * png_ptr - pointer to a png output data structure + * io_ptr - pointer to user supplied structure containing info about + * the output functions. May be NULL. + * write_data_fn - pointer to a new output function that takes as its + * arguments a pointer to a png_struct, a pointer to + * data to be written, and a 32-bit unsigned int that is + * the number of bytes to be written. The new write + * function should call png_error(png_ptr, "Error msg") + * to exit and output any fatal error messages. May be + * NULL, in which case libpng's default function will + * be used. + * flush_data_fn - pointer to a new flush function that takes as its + * arguments a pointer to a png_struct. After a call to + * the flush function, there should be no data in any buffers + * or pending transmission. If the output method doesn't do + * any buffering of output, a function prototype must still be + * supplied although it doesn't have to do anything. If + * PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile + * time, output_flush_fn will be ignored, although it must be + * supplied for compatibility. May be NULL, in which case + * libpng's default function will be used, if + * PNG_WRITE_FLUSH_SUPPORTED is defined. This is not + * a good idea if io_ptr does not point to a standard + * *FILE structure. + */ +void PNGAPI +png_set_write_fn(png_structp png_ptr, png_voidp io_ptr, + png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->io_ptr = io_ptr; + +#ifdef PNG_STDIO_SUPPORTED + if (write_data_fn != NULL) + png_ptr->write_data_fn = write_data_fn; + + else + png_ptr->write_data_fn = png_default_write_data; +#else + png_ptr->write_data_fn = write_data_fn; +#endif + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +#ifdef PNG_STDIO_SUPPORTED + if (output_flush_fn != NULL) + png_ptr->output_flush_fn = output_flush_fn; + + else + png_ptr->output_flush_fn = png_default_flush; +#else + png_ptr->output_flush_fn = output_flush_fn; +#endif +#endif /* PNG_WRITE_FLUSH_SUPPORTED */ + + /* It is an error to read while writing a png file */ + if (png_ptr->read_data_fn != NULL) + { + png_ptr->read_data_fn = NULL; + png_warning(png_ptr, + "Attempted to set both read_data_fn and write_data_fn in"); + png_warning(png_ptr, + "the same structure. Resetting read_data_fn to NULL."); + } +} + +#ifdef USE_FAR_KEYWORD +#ifdef _MSC_VER +void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check) +{ + void *near_ptr; + void FAR *far_ptr; + FP_OFF(near_ptr) = FP_OFF(ptr); + far_ptr = (void FAR *)near_ptr; + + if (check != 0) + if (FP_SEG(ptr) != FP_SEG(far_ptr)) + png_error(png_ptr, "segment lost in conversion"); + + return(near_ptr); +} +# else +void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check) +{ + void *near_ptr; + void FAR *far_ptr; + near_ptr = (void FAR *)ptr; + far_ptr = (void FAR *)near_ptr; + + if (check != 0) + if (far_ptr != ptr) + png_error(png_ptr, "segment lost in conversion"); + + return(near_ptr); +} +# endif +# endif +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/contrib/syslinux-4.02/com32/lib/libpng/pngwrite.c b/contrib/syslinux-4.02/com32/lib/libpng/pngwrite.c new file mode 100644 index 0000000..e411e81 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libpng/pngwrite.c @@ -0,0 +1,1592 @@ + +/* pngwrite.c - general routines to write a PNG file + * + * Last changed in libpng 1.2.42 [January 3, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* Get internal access to png.h */ +#define PNG_INTERNAL +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" +#ifdef PNG_WRITE_SUPPORTED + +/* Writes all the PNG information. This is the suggested way to use the + * library. If you have a new chunk to add, make a function to write it, + * and put it in the correct location here. If you want the chunk written + * after the image data, put it in png_write_end(). I strongly encourage + * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing + * the chunk, as that will keep the code from breaking if you want to just + * write a plain PNG file. If you have long comments, I suggest writing + * them in png_write_end(), and compressing them. + */ +void PNGAPI +png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_write_info_before_PLTE"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) + { + /* Write PNG signature */ + png_write_sig(png_ptr); +#ifdef PNG_MNG_FEATURES_SUPPORTED + if ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) && \ + (png_ptr->mng_features_permitted)) + { + png_warning(png_ptr, "MNG features are not allowed in a PNG datastream"); + png_ptr->mng_features_permitted = 0; + } +#endif + /* Write IHDR information. */ + png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height, + info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type, + info_ptr->filter_type, +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + info_ptr->interlace_type); +#else + 0); +#endif + /* The rest of these check to see if the valid field has the appropriate + * flag set, and if it does, writes the chunk. + */ +#ifdef PNG_WRITE_gAMA_SUPPORTED + if (info_ptr->valid & PNG_INFO_gAMA) + { +# ifdef PNG_FLOATING_POINT_SUPPORTED + png_write_gAMA(png_ptr, info_ptr->gamma); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + png_write_gAMA_fixed(png_ptr, info_ptr->int_gamma); +# endif +#endif + } +#endif +#ifdef PNG_WRITE_sRGB_SUPPORTED + if (info_ptr->valid & PNG_INFO_sRGB) + png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent); +#endif +#ifdef PNG_WRITE_iCCP_SUPPORTED + if (info_ptr->valid & PNG_INFO_iCCP) + png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE, + info_ptr->iccp_profile, (int)info_ptr->iccp_proflen); +#endif +#ifdef PNG_WRITE_sBIT_SUPPORTED + if (info_ptr->valid & PNG_INFO_sBIT) + png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); +#endif +#ifdef PNG_WRITE_cHRM_SUPPORTED + if (info_ptr->valid & PNG_INFO_cHRM) + { +#ifdef PNG_FLOATING_POINT_SUPPORTED + png_write_cHRM(png_ptr, + info_ptr->x_white, info_ptr->y_white, + info_ptr->x_red, info_ptr->y_red, + info_ptr->x_green, info_ptr->y_green, + info_ptr->x_blue, info_ptr->y_blue); +#else +# ifdef PNG_FIXED_POINT_SUPPORTED + png_write_cHRM_fixed(png_ptr, + info_ptr->int_x_white, info_ptr->int_y_white, + info_ptr->int_x_red, info_ptr->int_y_red, + info_ptr->int_x_green, info_ptr->int_y_green, + info_ptr->int_x_blue, info_ptr->int_y_blue); +# endif +#endif + } +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + if (info_ptr->unknown_chunks_num) + { + png_unknown_chunk *up; + + png_debug(5, "writing extra chunks"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep = png_handle_as_unknown(png_ptr, up->name); + if (keep != PNG_HANDLE_CHUNK_NEVER && + up->location && !(up->location & PNG_HAVE_PLTE) && + !(up->location & PNG_HAVE_IDAT) && + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + if (up->size == 0) + png_warning(png_ptr, "Writing zero-length unknown chunk"); + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } + } +#endif + png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE; + } +} + +void PNGAPI +png_write_info(png_structp png_ptr, png_infop info_ptr) +{ +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) + int i; +#endif + + png_debug(1, "in png_write_info"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_write_info_before_PLTE(png_ptr, info_ptr); + + if (info_ptr->valid & PNG_INFO_PLTE) + png_write_PLTE(png_ptr, info_ptr->palette, + (png_uint_32)info_ptr->num_palette); + else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + png_error(png_ptr, "Valid palette required for paletted images"); + +#ifdef PNG_WRITE_tRNS_SUPPORTED + if (info_ptr->valid & PNG_INFO_tRNS) + { +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED + /* Invert the alpha channel (in tRNS) */ + if ((png_ptr->transformations & PNG_INVERT_ALPHA) && + info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + int j; + for (j = 0; j<(int)info_ptr->num_trans; j++) + info_ptr->trans[j] = (png_byte)(255 - info_ptr->trans[j]); + } +#endif + png_write_tRNS(png_ptr, info_ptr->trans, &(info_ptr->trans_values), + info_ptr->num_trans, info_ptr->color_type); + } +#endif +#ifdef PNG_WRITE_bKGD_SUPPORTED + if (info_ptr->valid & PNG_INFO_bKGD) + png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type); +#endif +#ifdef PNG_WRITE_hIST_SUPPORTED + if (info_ptr->valid & PNG_INFO_hIST) + png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette); +#endif +#ifdef PNG_WRITE_oFFs_SUPPORTED + if (info_ptr->valid & PNG_INFO_oFFs) + png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset, + info_ptr->offset_unit_type); +#endif +#ifdef PNG_WRITE_pCAL_SUPPORTED + if (info_ptr->valid & PNG_INFO_pCAL) + png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0, + info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams, + info_ptr->pcal_units, info_ptr->pcal_params); +#endif + +#ifdef PNG_sCAL_SUPPORTED + if (info_ptr->valid & PNG_INFO_sCAL) +#ifdef PNG_WRITE_sCAL_SUPPORTED +#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) + png_write_sCAL(png_ptr, (int)info_ptr->scal_unit, + info_ptr->scal_pixel_width, info_ptr->scal_pixel_height); +#else /* !FLOATING_POINT */ +#ifdef PNG_FIXED_POINT_SUPPORTED + png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit, + info_ptr->scal_s_width, info_ptr->scal_s_height); +#endif /* FIXED_POINT */ +#endif /* FLOATING_POINT */ +#else /* !WRITE_sCAL */ + png_warning(png_ptr, + "png_write_sCAL not supported; sCAL chunk not written."); +#endif /* WRITE_sCAL */ +#endif /* sCAL */ + +#ifdef PNG_WRITE_pHYs_SUPPORTED + if (info_ptr->valid & PNG_INFO_pHYs) + png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit, + info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type); +#endif /* pHYs */ + +#ifdef PNG_WRITE_tIME_SUPPORTED + if (info_ptr->valid & PNG_INFO_tIME) + { + png_write_tIME(png_ptr, &(info_ptr->mod_time)); + png_ptr->mode |= PNG_WROTE_tIME; + } +#endif /* tIME */ + +#ifdef PNG_WRITE_sPLT_SUPPORTED + if (info_ptr->valid & PNG_INFO_sPLT) + for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) + png_write_sPLT(png_ptr, info_ptr->splt_palettes + i); +#endif /* sPLT */ + +#ifdef PNG_WRITE_TEXT_SUPPORTED + /* Check to see if we need to write text chunks */ + for (i = 0; i < info_ptr->num_text; i++) + { + png_debug2(2, "Writing header text chunk %d, type %d", i, + info_ptr->text[i].compression); + /* An internationalized chunk? */ + if (info_ptr->text[i].compression > 0) + { +#ifdef PNG_WRITE_iTXt_SUPPORTED + /* Write international chunk */ + png_write_iTXt(png_ptr, + info_ptr->text[i].compression, + info_ptr->text[i].key, + info_ptr->text[i].lang, + info_ptr->text[i].lang_key, + info_ptr->text[i].text); +#else + png_warning(png_ptr, "Unable to write international text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + /* If we want a compressed text chunk */ + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt) + { +#ifdef PNG_WRITE_zTXt_SUPPORTED + /* Write compressed chunk */ + png_write_zTXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0, + info_ptr->text[i].compression); +#else + png_warning(png_ptr, "Unable to write compressed text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; + } + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) + { +#ifdef PNG_WRITE_tEXt_SUPPORTED + /* Write uncompressed chunk */ + png_write_tEXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, + 0); + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; +#else + /* Can't get here */ + png_warning(png_ptr, "Unable to write uncompressed text"); +#endif + } + } +#endif /* tEXt */ + +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + if (info_ptr->unknown_chunks_num) + { + png_unknown_chunk *up; + + png_debug(5, "writing extra chunks"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep = png_handle_as_unknown(png_ptr, up->name); + if (keep != PNG_HANDLE_CHUNK_NEVER && + up->location && (up->location & PNG_HAVE_PLTE) && + !(up->location & PNG_HAVE_IDAT) && + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } + } +#endif +} + +/* Writes the end of the PNG file. If you don't want to write comments or + * time information, you can pass NULL for info. If you already wrote these + * in png_write_info(), do not write them again here. If you have long + * comments, I suggest writing them here, and compressing them. + */ +void PNGAPI +png_write_end(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_write_end"); + + if (png_ptr == NULL) + return; + if (!(png_ptr->mode & PNG_HAVE_IDAT)) + png_error(png_ptr, "No IDATs written into file"); + + /* See if user wants us to write information chunks */ + if (info_ptr != NULL) + { +#ifdef PNG_WRITE_TEXT_SUPPORTED + int i; /* local index variable */ +#endif +#ifdef PNG_WRITE_tIME_SUPPORTED + /* Check to see if user has supplied a time chunk */ + if ((info_ptr->valid & PNG_INFO_tIME) && + !(png_ptr->mode & PNG_WROTE_tIME)) + png_write_tIME(png_ptr, &(info_ptr->mod_time)); +#endif +#ifdef PNG_WRITE_TEXT_SUPPORTED + /* Loop through comment chunks */ + for (i = 0; i < info_ptr->num_text; i++) + { + png_debug2(2, "Writing trailer text chunk %d, type %d", i, + info_ptr->text[i].compression); + /* An internationalized chunk? */ + if (info_ptr->text[i].compression > 0) + { +#ifdef PNG_WRITE_iTXt_SUPPORTED + /* Write international chunk */ + png_write_iTXt(png_ptr, + info_ptr->text[i].compression, + info_ptr->text[i].key, + info_ptr->text[i].lang, + info_ptr->text[i].lang_key, + info_ptr->text[i].text); +#else + png_warning(png_ptr, "Unable to write international text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt) + { +#ifdef PNG_WRITE_zTXt_SUPPORTED + /* Write compressed chunk */ + png_write_zTXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0, + info_ptr->text[i].compression); +#else + png_warning(png_ptr, "Unable to write compressed text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; + } + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) + { +#ifdef PNG_WRITE_tEXt_SUPPORTED + /* Write uncompressed chunk */ + png_write_tEXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0); +#else + png_warning(png_ptr, "Unable to write uncompressed text"); +#endif + + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + } +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + if (info_ptr->unknown_chunks_num) + { + png_unknown_chunk *up; + + png_debug(5, "writing extra chunks"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep = png_handle_as_unknown(png_ptr, up->name); + if (keep != PNG_HANDLE_CHUNK_NEVER && + up->location && (up->location & PNG_AFTER_IDAT) && + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } + } +#endif + } + + png_ptr->mode |= PNG_AFTER_IDAT; + + /* Write end of PNG file */ + png_write_IEND(png_ptr); + /* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03, + * and restored again in libpng-1.2.30, may cause some applications that + * do not set png_ptr->output_flush_fn to crash. If your application + * experiences a problem, please try building libpng with + * PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to + * png-mng-implement at lists.sf.net . + */ +#ifdef PNG_WRITE_FLUSH_SUPPORTED +# ifdef PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED + png_flush(png_ptr); +# endif +#endif +} + +#ifdef PNG_CONVERT_tIME_SUPPORTED +/* "tm" structure is not supported on WindowsCE */ +void PNGAPI +png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime) +{ + png_debug(1, "in png_convert_from_struct_tm"); + + ptime->year = (png_uint_16)(1900 + ttime->tm_year); + ptime->month = (png_byte)(ttime->tm_mon + 1); + ptime->day = (png_byte)ttime->tm_mday; + ptime->hour = (png_byte)ttime->tm_hour; + ptime->minute = (png_byte)ttime->tm_min; + ptime->second = (png_byte)ttime->tm_sec; +} + +void PNGAPI +png_convert_from_time_t(png_timep ptime, time_t ttime) +{ + struct tm *tbuf; + + png_debug(1, "in png_convert_from_time_t"); + + tbuf = gmtime(&ttime); + png_convert_from_struct_tm(ptime, tbuf); +} +#endif + +/* Initialize png_ptr structure, and allocate any memory needed */ +png_structp PNGAPI +png_create_write_struct(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn) +{ +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn, + warn_fn, png_voidp_NULL, png_malloc_ptr_NULL, png_free_ptr_NULL)); +} + +/* Alternate initialize png_ptr structure, and allocate any memory needed */ +png_structp PNGAPI +png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ +#ifdef PNG_SETJMP_SUPPORTED + volatile +#endif + png_structp png_ptr; +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf jmpbuf; +#endif +#endif + int i; + + png_debug(1, "in png_create_write_struct"); + +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, + (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr); +#else + png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); +#endif /* PNG_USER_MEM_SUPPORTED */ + if (png_ptr == NULL) + return (NULL); + + /* Added at libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_ptr->user_width_max = PNG_USER_WIDTH_MAX; + png_ptr->user_height_max = PNG_USER_HEIGHT_MAX; +#endif + +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) +#else + if (setjmp(png_ptr->jmpbuf)) +#endif + { + png_free(png_ptr, png_ptr->zbuf); + png_ptr->zbuf = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, + (png_free_ptr)free_fn, (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + return (NULL); + } +#ifdef USE_FAR_KEYWORD + png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf)); +#endif +#endif + +#ifdef PNG_USER_MEM_SUPPORTED + png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); +#endif /* PNG_USER_MEM_SUPPORTED */ + png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); + + if (user_png_ver) + { + i = 0; + do + { + if (user_png_ver[i] != png_libpng_ver[i]) + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + } while (png_libpng_ver[i++]); + } + + if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) + { + /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so + * we must recompile any applications that use any older library version. + * For versions after libpng 1.0, we will be compatible, so we need + * only check the first digit. + */ + if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || + (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || + (user_png_ver[0] == '0' && user_png_ver[2] < '9')) + { +#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE) + char msg[80]; + if (user_png_ver) + { + png_snprintf(msg, 80, + "Application was compiled with png.h from libpng-%.20s", + user_png_ver); + png_warning(png_ptr, msg); + } + png_snprintf(msg, 80, + "Application is running with png.c from libpng-%.20s", + png_libpng_ver); + png_warning(png_ptr, msg); +#endif +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags = 0; +#endif + png_error(png_ptr, + "Incompatible libpng version in application and library"); + } + } + + /* Initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); + + png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL, + png_flush_ptr_NULL); + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT, + 1, png_doublep_NULL, png_doublep_NULL); +#endif + +#ifdef PNG_SETJMP_SUPPORTED + /* Applications that neglect to set up their own setjmp() and then + * encounter a png_error() will longjmp here. Since the jmpbuf is + * then meaningless we abort instead of returning. + */ +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) + PNG_ABORT(); + png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf)); +#else + if (setjmp(png_ptr->jmpbuf)) + PNG_ABORT(); +#endif +#endif + return (png_ptr); +} + +/* Initialize png_ptr structure, and allocate any memory needed */ +#if defined(PNG_1_0_X) || defined(PNG_1_2_X) +/* Deprecated. */ +#undef png_write_init +void PNGAPI +png_write_init(png_structp png_ptr) +{ + /* We only come here via pre-1.0.7-compiled applications */ + png_write_init_2(png_ptr, "1.0.6 or earlier", 0, 0); +} + +void PNGAPI +png_write_init_2(png_structp png_ptr, png_const_charp user_png_ver, + png_size_t png_struct_size, png_size_t png_info_size) +{ + /* We only come here via pre-1.0.12-compiled applications */ + if (png_ptr == NULL) return; +#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE) + if (png_sizeof(png_struct) > png_struct_size || + png_sizeof(png_info) > png_info_size) + { + char msg[80]; + png_ptr->warning_fn = NULL; + if (user_png_ver) + { + png_snprintf(msg, 80, + "Application was compiled with png.h from libpng-%.20s", + user_png_ver); + png_warning(png_ptr, msg); + } + png_snprintf(msg, 80, + "Application is running with png.c from libpng-%.20s", + png_libpng_ver); + png_warning(png_ptr, msg); + } +#endif + if (png_sizeof(png_struct) > png_struct_size) + { + png_ptr->error_fn = NULL; +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags = 0; +#endif + png_error(png_ptr, + "The png struct allocated by the application for writing is" + " too small."); + } + if (png_sizeof(png_info) > png_info_size) + { + png_ptr->error_fn = NULL; +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags = 0; +#endif + png_error(png_ptr, + "The info struct allocated by the application for writing is" + " too small."); + } + png_write_init_3(&png_ptr, user_png_ver, png_struct_size); +} +#endif /* PNG_1_0_X || PNG_1_2_X */ + + +void PNGAPI +png_write_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver, + png_size_t png_struct_size) +{ + png_structp png_ptr = *ptr_ptr; +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf tmp_jmp; /* to save current jump buffer */ +#endif + + int i = 0; + + if (png_ptr == NULL) + return; + + do + { + if (user_png_ver[i] != png_libpng_ver[i]) + { +#ifdef PNG_LEGACY_SUPPORTED + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; +#else + png_ptr->warning_fn = NULL; + png_warning(png_ptr, + "Application uses deprecated png_write_init() and should be recompiled."); +#endif + } + } while (png_libpng_ver[i++]); + + png_debug(1, "in png_write_init_3"); + +#ifdef PNG_SETJMP_SUPPORTED + /* Save jump buffer and error functions */ + png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf)); +#endif + + if (png_sizeof(png_struct) > png_struct_size) + { + png_destroy_struct(png_ptr); + png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); + *ptr_ptr = png_ptr; + } + + /* Reset all variables to 0 */ + png_memset(png_ptr, 0, png_sizeof(png_struct)); + + /* Added at libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_ptr->user_width_max = PNG_USER_WIDTH_MAX; + png_ptr->user_height_max = PNG_USER_HEIGHT_MAX; +#endif + +#ifdef PNG_SETJMP_SUPPORTED + /* Restore jump buffer */ + png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf)); +#endif + + png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL, + png_flush_ptr_NULL); + + /* Initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT, + 1, png_doublep_NULL, png_doublep_NULL); +#endif +} + +/* Write a few rows of image data. If the image is interlaced, + * either you will have to write the 7 sub images, or, if you + * have called png_set_interlace_handling(), you will have to + * "write" the image seven times. + */ +void PNGAPI +png_write_rows(png_structp png_ptr, png_bytepp row, + png_uint_32 num_rows) +{ + png_uint_32 i; /* row counter */ + png_bytepp rp; /* row pointer */ + + png_debug(1, "in png_write_rows"); + + if (png_ptr == NULL) + return; + + /* Loop through the rows */ + for (i = 0, rp = row; i < num_rows; i++, rp++) + { + png_write_row(png_ptr, *rp); + } +} + +/* Write the image. You only need to call this function once, even + * if you are writing an interlaced image. + */ +void PNGAPI +png_write_image(png_structp png_ptr, png_bytepp image) +{ + png_uint_32 i; /* row index */ + int pass, num_pass; /* pass variables */ + png_bytepp rp; /* points to current row */ + + if (png_ptr == NULL) + return; + + png_debug(1, "in png_write_image"); + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Initialize interlace handling. If image is not interlaced, + * this will set pass to 1 + */ + num_pass = png_set_interlace_handling(png_ptr); +#else + num_pass = 1; +#endif + /* Loop through passes */ + for (pass = 0; pass < num_pass; pass++) + { + /* Loop through image */ + for (i = 0, rp = image; i < png_ptr->height; i++, rp++) + { + png_write_row(png_ptr, *rp); + } + } +} + +/* Called by user to write a row of image data */ +void PNGAPI +png_write_row(png_structp png_ptr, png_bytep row) +{ + if (png_ptr == NULL) + return; + + png_debug2(1, "in png_write_row (row %ld, pass %d)", + png_ptr->row_number, png_ptr->pass); + + /* Initialize transformations and other stuff if first time */ + if (png_ptr->row_number == 0 && png_ptr->pass == 0) + { + /* Make sure we wrote the header info */ + if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) + png_error(png_ptr, + "png_write_info was never called before png_write_row."); + + /* Check for transforms that have been set but were defined out */ +#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_warning(png_ptr, + "PNG_WRITE_INVERT_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_warning(png_ptr, + "PNG_WRITE_FILLER_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \ + defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_warning(png_ptr, + "PNG_WRITE_PACKSWAP_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined."); +#endif + + png_write_start_row(png_ptr); + } + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* If interlaced and not interested in row, return */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + switch (png_ptr->pass) + { + case 0: + if (png_ptr->row_number & 0x07) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 1: + if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 2: + if ((png_ptr->row_number & 0x07) != 4) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 3: + if ((png_ptr->row_number & 0x03) || png_ptr->width < 3) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 4: + if ((png_ptr->row_number & 0x03) != 2) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 5: + if ((png_ptr->row_number & 0x01) || png_ptr->width < 2) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 6: + if (!(png_ptr->row_number & 0x01)) + { + png_write_finish_row(png_ptr); + return; + } + break; + } + } +#endif + + /* Set up row info for transformations */ + png_ptr->row_info.color_type = png_ptr->color_type; + png_ptr->row_info.width = png_ptr->usr_width; + png_ptr->row_info.channels = png_ptr->usr_channels; + png_ptr->row_info.bit_depth = png_ptr->usr_bit_depth; + png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * + png_ptr->row_info.channels); + + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + + png_debug1(3, "row_info->color_type = %d", png_ptr->row_info.color_type); + png_debug1(3, "row_info->width = %lu", png_ptr->row_info.width); + png_debug1(3, "row_info->channels = %d", png_ptr->row_info.channels); + png_debug1(3, "row_info->bit_depth = %d", png_ptr->row_info.bit_depth); + png_debug1(3, "row_info->pixel_depth = %d", png_ptr->row_info.pixel_depth); + png_debug1(3, "row_info->rowbytes = %lu", png_ptr->row_info.rowbytes); + + /* Copy user's row into buffer, leaving room for filter byte. */ + png_memcpy_check(png_ptr, png_ptr->row_buf + 1, row, + png_ptr->row_info.rowbytes); + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Handle interlacing */ + if (png_ptr->interlaced && png_ptr->pass < 6 && + (png_ptr->transformations & PNG_INTERLACE)) + { + png_do_write_interlace(&(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->pass); + /* This should always get caught above, but still ... */ + if (!(png_ptr->row_info.width)) + { + png_write_finish_row(png_ptr); + return; + } + } +#endif + + /* Handle other transformations */ + if (png_ptr->transformations) + png_do_write_transformations(png_ptr); + +#ifdef PNG_MNG_FEATURES_SUPPORTED + /* Write filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not write a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) + { + /* Intrapixel differencing */ + png_do_write_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1); + } +#endif + + /* Find a filter if necessary, filter the row and write it out. */ + png_write_find_filter(png_ptr, &(png_ptr->row_info)); + + if (png_ptr->write_row_fn != NULL) + (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); +} + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +/* Set the automatic flush interval or 0 to turn flushing off */ +void PNGAPI +png_set_flush(png_structp png_ptr, int nrows) +{ + png_debug(1, "in png_set_flush"); + + if (png_ptr == NULL) + return; + png_ptr->flush_dist = (nrows < 0 ? 0 : nrows); +} + +/* Flush the current output buffers now */ +void PNGAPI +png_write_flush(png_structp png_ptr) +{ + int wrote_IDAT; + + png_debug(1, "in png_write_flush"); + + if (png_ptr == NULL) + return; + /* We have already written out all of the data */ + if (png_ptr->row_number >= png_ptr->num_rows) + return; + + do + { + int ret; + + /* Compress the data */ + ret = deflate(&png_ptr->zstream, Z_SYNC_FLUSH); + wrote_IDAT = 0; + + /* Check for compression errors */ + if (ret != Z_OK) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + + if (!(png_ptr->zstream.avail_out)) + { + /* Write the IDAT and reset the zlib output buffer */ + png_write_IDAT(png_ptr, png_ptr->zbuf, + png_ptr->zbuf_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + wrote_IDAT = 1; + } + } while(wrote_IDAT == 1); + + /* If there is any data left to be output, write it into a new IDAT */ + if (png_ptr->zbuf_size != png_ptr->zstream.avail_out) + { + /* Write the IDAT and reset the zlib output buffer */ + png_write_IDAT(png_ptr, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + png_ptr->flush_rows = 0; + png_flush(png_ptr); +} +#endif /* PNG_WRITE_FLUSH_SUPPORTED */ + +/* Free all memory used by the write */ +void PNGAPI +png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr) +{ + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn = NULL; + png_voidp mem_ptr = NULL; +#endif + + png_debug(1, "in png_destroy_write_struct"); + + if (png_ptr_ptr != NULL) + { + png_ptr = *png_ptr_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; + mem_ptr = png_ptr->mem_ptr; +#endif + } + +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr != NULL) + { + free_fn = png_ptr->free_fn; + mem_ptr = png_ptr->mem_ptr; + } +#endif + + if (info_ptr_ptr != NULL) + info_ptr = *info_ptr_ptr; + + if (info_ptr != NULL) + { + if (png_ptr != NULL) + { + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + if (png_ptr->num_chunk_list) + { + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->chunk_list = NULL; + png_ptr->num_chunk_list = 0; + } +#endif + } + +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)info_ptr); +#endif + *info_ptr_ptr = NULL; + } + + if (png_ptr != NULL) + { + png_write_destroy(png_ptr); +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + *png_ptr_ptr = NULL; + } +} + + +/* Free any memory used in png_ptr struct (old method) */ +void /* PRIVATE */ +png_write_destroy(png_structp png_ptr) +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf tmp_jmp; /* Save jump buffer */ +#endif + png_error_ptr error_fn; + png_error_ptr warning_fn; + png_voidp error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn; +#endif + + png_debug(1, "in png_write_destroy"); + + /* Free any memory zlib uses */ + deflateEnd(&png_ptr->zstream); + + /* Free our memory. png_free checks NULL for us. */ + png_free(png_ptr, png_ptr->zbuf); + png_free(png_ptr, png_ptr->row_buf); +#ifdef PNG_WRITE_FILTER_SUPPORTED + png_free(png_ptr, png_ptr->prev_row); + png_free(png_ptr, png_ptr->sub_row); + png_free(png_ptr, png_ptr->up_row); + png_free(png_ptr, png_ptr->avg_row); + png_free(png_ptr, png_ptr->paeth_row); +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED + png_free(png_ptr, png_ptr->time_buffer); +#endif + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + png_free(png_ptr, png_ptr->prev_filters); + png_free(png_ptr, png_ptr->filter_weights); + png_free(png_ptr, png_ptr->inv_filter_weights); + png_free(png_ptr, png_ptr->filter_costs); + png_free(png_ptr, png_ptr->inv_filter_costs); +#endif + +#ifdef PNG_SETJMP_SUPPORTED + /* Reset structure */ + png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf)); +#endif + + error_fn = png_ptr->error_fn; + warning_fn = png_ptr->warning_fn; + error_ptr = png_ptr->error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; +#endif + + png_memset(png_ptr, 0, png_sizeof(png_struct)); + + png_ptr->error_fn = error_fn; + png_ptr->warning_fn = warning_fn; + png_ptr->error_ptr = error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr->free_fn = free_fn; +#endif + +#ifdef PNG_SETJMP_SUPPORTED + png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf)); +#endif +} + +/* Allow the application to select one or more row filters to use. */ +void PNGAPI +png_set_filter(png_structp png_ptr, int method, int filters) +{ + png_debug(1, "in png_set_filter"); + + if (png_ptr == NULL) + return; +#ifdef PNG_MNG_FEATURES_SUPPORTED + if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (method == PNG_INTRAPIXEL_DIFFERENCING)) + method = PNG_FILTER_TYPE_BASE; +#endif + if (method == PNG_FILTER_TYPE_BASE) + { + switch (filters & (PNG_ALL_FILTERS | 0x07)) + { +#ifdef PNG_WRITE_FILTER_SUPPORTED + case 5: + case 6: + case 7: png_warning(png_ptr, "Unknown row filter for method 0"); +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + case PNG_FILTER_VALUE_NONE: + png_ptr->do_filter = PNG_FILTER_NONE; break; +#ifdef PNG_WRITE_FILTER_SUPPORTED + case PNG_FILTER_VALUE_SUB: + png_ptr->do_filter = PNG_FILTER_SUB; break; + case PNG_FILTER_VALUE_UP: + png_ptr->do_filter = PNG_FILTER_UP; break; + case PNG_FILTER_VALUE_AVG: + png_ptr->do_filter = PNG_FILTER_AVG; break; + case PNG_FILTER_VALUE_PAETH: + png_ptr->do_filter = PNG_FILTER_PAETH; break; + default: png_ptr->do_filter = (png_byte)filters; break; +#else + default: png_warning(png_ptr, "Unknown row filter for method 0"); +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + } + + /* If we have allocated the row_buf, this means we have already started + * with the image and we should have allocated all of the filter buffers + * that have been selected. If prev_row isn't already allocated, then + * it is too late to start using the filters that need it, since we + * will be missing the data in the previous row. If an application + * wants to start and stop using particular filters during compression, + * it should start out with all of the filters, and then add and + * remove them after the start of compression. + */ + if (png_ptr->row_buf != NULL) + { +#ifdef PNG_WRITE_FILTER_SUPPORTED + if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL) + { + png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; + } + + if ((png_ptr->do_filter & PNG_FILTER_UP) && png_ptr->up_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Up filter after starting"); + png_ptr->do_filter &= ~PNG_FILTER_UP; + } + else + { + png_ptr->up_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; + } + } + + if ((png_ptr->do_filter & PNG_FILTER_AVG) && png_ptr->avg_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Average filter after starting"); + png_ptr->do_filter &= ~PNG_FILTER_AVG; + } + else + { + png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; + } + } + + if ((png_ptr->do_filter & PNG_FILTER_PAETH) && + png_ptr->paeth_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Paeth filter after starting"); + png_ptr->do_filter &= (png_byte)(~PNG_FILTER_PAETH); + } + else + { + png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; + } + } + + if (png_ptr->do_filter == PNG_NO_FILTERS) +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + png_ptr->do_filter = PNG_FILTER_NONE; + } + } + else + png_error(png_ptr, "Unknown custom filter method"); +} + +/* This allows us to influence the way in which libpng chooses the "best" + * filter for the current scanline. While the "minimum-sum-of-absolute- + * differences metric is relatively fast and effective, there is some + * question as to whether it can be improved upon by trying to keep the + * filtered data going to zlib more consistent, hopefully resulting in + * better compression. + */ +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* GRR 970116 */ +void PNGAPI +png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, + int num_weights, png_doublep filter_weights, + png_doublep filter_costs) +{ + int i; + + png_debug(1, "in png_set_filter_heuristics"); + + if (png_ptr == NULL) + return; + if (heuristic_method >= PNG_FILTER_HEURISTIC_LAST) + { + png_warning(png_ptr, "Unknown filter heuristic method"); + return; + } + + if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT) + { + heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED; + } + + if (num_weights < 0 || filter_weights == NULL || + heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED) + { + num_weights = 0; + } + + png_ptr->num_prev_filters = (png_byte)num_weights; + png_ptr->heuristic_method = (png_byte)heuristic_method; + + if (num_weights > 0) + { + if (png_ptr->prev_filters == NULL) + { + png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_byte) * num_weights)); + + /* To make sure that the weighting starts out fairly */ + for (i = 0; i < num_weights; i++) + { + png_ptr->prev_filters[i] = 255; + } + } + + if (png_ptr->filter_weights == NULL) + { + png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); + + png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); + for (i = 0; i < num_weights; i++) + { + png_ptr->inv_filter_weights[i] = + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + } + } + + for (i = 0; i < num_weights; i++) + { + if (filter_weights[i] < 0.0) + { + png_ptr->inv_filter_weights[i] = + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + } + else + { + png_ptr->inv_filter_weights[i] = + (png_uint_16)((double)PNG_WEIGHT_FACTOR*filter_weights[i]+0.5); + png_ptr->filter_weights[i] = + (png_uint_16)((double)PNG_WEIGHT_FACTOR/filter_weights[i]+0.5); + } + } + } + + /* If, in the future, there are other filter methods, this would + * need to be based on png_ptr->filter. + */ + if (png_ptr->filter_costs == NULL) + { + png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); + + png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); + + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) + { + png_ptr->inv_filter_costs[i] = + png_ptr->filter_costs[i] = PNG_COST_FACTOR; + } + } + + /* Here is where we set the relative costs of the different filters. We + * should take the desired compression level into account when setting + * the costs, so that Paeth, for instance, has a high relative cost at low + * compression levels, while it has a lower relative cost at higher + * compression settings. The filter types are in order of increasing + * relative cost, so it would be possible to do this with an algorithm. + */ + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) + { + if (filter_costs == NULL || filter_costs[i] < 0.0) + { + png_ptr->inv_filter_costs[i] = + png_ptr->filter_costs[i] = PNG_COST_FACTOR; + } + else if (filter_costs[i] >= 1.0) + { + png_ptr->inv_filter_costs[i] = + (png_uint_16)((double)PNG_COST_FACTOR / filter_costs[i] + 0.5); + png_ptr->filter_costs[i] = + (png_uint_16)((double)PNG_COST_FACTOR * filter_costs[i] + 0.5); + } + } +} +#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ + +void PNGAPI +png_set_compression_level(png_structp png_ptr, int level) +{ + png_debug(1, "in png_set_compression_level"); + + if (png_ptr == NULL) + return; + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL; + png_ptr->zlib_level = level; +} + +void PNGAPI +png_set_compression_mem_level(png_structp png_ptr, int mem_level) +{ + png_debug(1, "in png_set_compression_mem_level"); + + if (png_ptr == NULL) + return; + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL; + png_ptr->zlib_mem_level = mem_level; +} + +void PNGAPI +png_set_compression_strategy(png_structp png_ptr, int strategy) +{ + png_debug(1, "in png_set_compression_strategy"); + + if (png_ptr == NULL) + return; + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY; + png_ptr->zlib_strategy = strategy; +} + +void PNGAPI +png_set_compression_window_bits(png_structp png_ptr, int window_bits) +{ + if (png_ptr == NULL) + return; + if (window_bits > 15) + png_warning(png_ptr, "Only compression windows <= 32k supported by PNG"); + else if (window_bits < 8) + png_warning(png_ptr, "Only compression windows >= 256 supported by PNG"); +#ifndef WBITS_8_OK + /* Avoid libpng bug with 256-byte windows */ + if (window_bits == 8) + { + png_warning(png_ptr, "Compression window is being reset to 512"); + window_bits = 9; + } +#endif + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS; + png_ptr->zlib_window_bits = window_bits; +} + +void PNGAPI +png_set_compression_method(png_structp png_ptr, int method) +{ + png_debug(1, "in png_set_compression_method"); + + if (png_ptr == NULL) + return; + if (method != 8) + png_warning(png_ptr, "Only compression method 8 is supported by PNG"); + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD; + png_ptr->zlib_method = method; +} + +void PNGAPI +png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr write_row_fn) +{ + if (png_ptr == NULL) + return; + png_ptr->write_row_fn = write_row_fn; +} + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +void PNGAPI +png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr + write_user_transform_fn) +{ + png_debug(1, "in png_set_write_user_transform_fn"); + + if (png_ptr == NULL) + return; + png_ptr->transformations |= PNG_USER_TRANSFORM; + png_ptr->write_user_transform_fn = write_user_transform_fn; +} +#endif + + +#ifdef PNG_INFO_IMAGE_SUPPORTED +void PNGAPI +png_write_png(png_structp png_ptr, png_infop info_ptr, + int transforms, voidp params) +{ + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* Write the file header information. */ + png_write_info(png_ptr, info_ptr); + + /* ------ these transformations don't touch the info structure ------- */ + +#ifdef PNG_WRITE_INVERT_SUPPORTED + /* Invert monochrome pixels */ + if (transforms & PNG_TRANSFORM_INVERT_MONO) + png_set_invert_mono(png_ptr); +#endif + +#ifdef PNG_WRITE_SHIFT_SUPPORTED + /* Shift the pixels up to a legal bit depth and fill in + * as appropriate to correctly scale the image. + */ + if ((transforms & PNG_TRANSFORM_SHIFT) + && (info_ptr->valid & PNG_INFO_sBIT)) + png_set_shift(png_ptr, &info_ptr->sig_bit); +#endif + +#ifdef PNG_WRITE_PACK_SUPPORTED + /* Pack pixels into bytes */ + if (transforms & PNG_TRANSFORM_PACKING) + png_set_packing(png_ptr); +#endif + +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED + /* Swap location of alpha bytes from ARGB to RGBA */ + if (transforms & PNG_TRANSFORM_SWAP_ALPHA) + png_set_swap_alpha(png_ptr); +#endif + +#ifdef PNG_WRITE_FILLER_SUPPORTED + /* Pack XRGB/RGBX/ARGB/RGBA into * RGB (4 channels -> 3 channels) */ + if (transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER) + png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); + else if (transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) + png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); +#endif + +#ifdef PNG_WRITE_BGR_SUPPORTED + /* Flip BGR pixels to RGB */ + if (transforms & PNG_TRANSFORM_BGR) + png_set_bgr(png_ptr); +#endif + +#ifdef PNG_WRITE_SWAP_SUPPORTED + /* Swap bytes of 16-bit files to most significant byte first */ + if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) + png_set_swap(png_ptr); +#endif + +#ifdef PNG_WRITE_PACKSWAP_SUPPORTED + /* Swap bits of 1, 2, 4 bit packed pixel formats */ + if (transforms & PNG_TRANSFORM_PACKSWAP) + png_set_packswap(png_ptr); +#endif + +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED + /* Invert the alpha channel from opacity to transparency */ + if (transforms & PNG_TRANSFORM_INVERT_ALPHA) + png_set_invert_alpha(png_ptr); +#endif + + /* ----------------------- end of transformations ------------------- */ + + /* Write the bits */ + if (info_ptr->valid & PNG_INFO_IDAT) + png_write_image(png_ptr, info_ptr->row_pointers); + + /* It is REQUIRED to call this to finish writing the rest of the file */ + png_write_end(png_ptr, info_ptr); + + transforms = transforms; /* Quiet compiler warnings */ + params = params; +} +#endif +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/contrib/syslinux-4.02/com32/lib/libpng/pngwtran.c b/contrib/syslinux-4.02/com32/lib/libpng/pngwtran.c new file mode 100644 index 0000000..0ce9b9b --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libpng/pngwtran.c @@ -0,0 +1,582 @@ + +/* pngwtran.c - transforms the data in a row for PNG writers + * + * Last changed in libpng 1.2.43 [February 25, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#define PNG_INTERNAL +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" +#ifdef PNG_WRITE_SUPPORTED + +/* Transform the data according to the user's wishes. The order of + * transformations is significant. + */ +void /* PRIVATE */ +png_do_write_transformations(png_structp png_ptr) +{ + png_debug(1, "in png_do_write_transformations"); + + if (png_ptr == NULL) + return; + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + if (png_ptr->transformations & PNG_USER_TRANSFORM) + if (png_ptr->write_user_transform_fn != NULL) + (*(png_ptr->write_user_transform_fn)) /* User write transform + function */ + (png_ptr, /* png_ptr */ + &(png_ptr->row_info), /* row_info: */ + /* png_uint_32 width; width of row */ + /* png_uint_32 rowbytes; number of bytes in row */ + /* png_byte color_type; color type of pixels */ + /* png_byte bit_depth; bit depth of samples */ + /* png_byte channels; number of channels (1-4) */ + /* png_byte pixel_depth; bits per pixel (depth*channels) */ + png_ptr->row_buf + 1); /* start of pixel data for row */ +#endif +#ifdef PNG_WRITE_FILLER_SUPPORTED + if (png_ptr->transformations & PNG_FILLER) + png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->flags); +#endif +#ifdef PNG_WRITE_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#ifdef PNG_WRITE_PACK_SUPPORTED + if (png_ptr->transformations & PNG_PACK) + png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1, + (png_uint_32)png_ptr->bit_depth); +#endif +#ifdef PNG_WRITE_SWAP_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#ifdef PNG_WRITE_SHIFT_SUPPORTED + if (png_ptr->transformations & PNG_SHIFT) + png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->shift)); +#endif +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_ALPHA) + png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_ALPHA) + png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#ifdef PNG_WRITE_BGR_SUPPORTED + if (png_ptr->transformations & PNG_BGR) + png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#ifdef PNG_WRITE_INVERT_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_MONO) + png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +} + +#ifdef PNG_WRITE_PACK_SUPPORTED +/* Pack pixels into bytes. Pass the true bit depth in bit_depth. The + * row_info bit depth should be 8 (one pixel per byte). The channels + * should be 1 (this only happens on grayscale and paletted images). + */ +void /* PRIVATE */ +png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) +{ + png_debug(1, "in png_do_pack"); + + if (row_info->bit_depth == 8 && +#ifdef PNG_USELESS_TESTS_SUPPORTED + row != NULL && row_info != NULL && +#endif + row_info->channels == 1) + { + switch ((int)bit_depth) + { + case 1: + { + png_bytep sp, dp; + int mask, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + mask = 0x80; + v = 0; + + for (i = 0; i < row_width; i++) + { + if (*sp != 0) + v |= mask; + sp++; + if (mask > 1) + mask >>= 1; + else + { + mask = 0x80; + *dp = (png_byte)v; + dp++; + v = 0; + } + } + if (mask != 0x80) + *dp = (png_byte)v; + break; + } + case 2: + { + png_bytep sp, dp; + int shift, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + shift = 6; + v = 0; + for (i = 0; i < row_width; i++) + { + png_byte value; + + value = (png_byte)(*sp & 0x03); + v |= (value << shift); + if (shift == 0) + { + shift = 6; + *dp = (png_byte)v; + dp++; + v = 0; + } + else + shift -= 2; + sp++; + } + if (shift != 6) + *dp = (png_byte)v; + break; + } + case 4: + { + png_bytep sp, dp; + int shift, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + shift = 4; + v = 0; + for (i = 0; i < row_width; i++) + { + png_byte value; + + value = (png_byte)(*sp & 0x0f); + v |= (value << shift); + + if (shift == 0) + { + shift = 4; + *dp = (png_byte)v; + dp++; + v = 0; + } + else + shift -= 4; + + sp++; + } + if (shift != 4) + *dp = (png_byte)v; + break; + } + } + row_info->bit_depth = (png_byte)bit_depth; + row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_info->width); + } +} +#endif + +#ifdef PNG_WRITE_SHIFT_SUPPORTED +/* Shift pixel values to take advantage of whole range. Pass the + * true number of bits in bit_depth. The row should be packed + * according to row_info->bit_depth. Thus, if you had a row of + * bit depth 4, but the pixels only had values from 0 to 7, you + * would pass 3 as bit_depth, and this routine would translate the + * data to 0 to 15. + */ +void /* PRIVATE */ +png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth) +{ + png_debug(1, "in png_do_shift"); + +#ifdef PNG_USELESS_TESTS_SUPPORTED + if (row != NULL && row_info != NULL && +#else + if ( +#endif + row_info->color_type != PNG_COLOR_TYPE_PALETTE) + { + int shift_start[4], shift_dec[4]; + int channels = 0; + + if (row_info->color_type & PNG_COLOR_MASK_COLOR) + { + shift_start[channels] = row_info->bit_depth - bit_depth->red; + shift_dec[channels] = bit_depth->red; + channels++; + shift_start[channels] = row_info->bit_depth - bit_depth->green; + shift_dec[channels] = bit_depth->green; + channels++; + shift_start[channels] = row_info->bit_depth - bit_depth->blue; + shift_dec[channels] = bit_depth->blue; + channels++; + } + else + { + shift_start[channels] = row_info->bit_depth - bit_depth->gray; + shift_dec[channels] = bit_depth->gray; + channels++; + } + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + shift_start[channels] = row_info->bit_depth - bit_depth->alpha; + shift_dec[channels] = bit_depth->alpha; + channels++; + } + + /* With low row depths, could only be grayscale, so one channel */ + if (row_info->bit_depth < 8) + { + png_bytep bp = row; + png_uint_32 i; + png_byte mask; + png_uint_32 row_bytes = row_info->rowbytes; + + if (bit_depth->gray == 1 && row_info->bit_depth == 2) + mask = 0x55; + else if (row_info->bit_depth == 4 && bit_depth->gray == 3) + mask = 0x11; + else + mask = 0xff; + + for (i = 0; i < row_bytes; i++, bp++) + { + png_uint_16 v; + int j; + + v = *bp; + *bp = 0; + for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0]) + { + if (j > 0) + *bp |= (png_byte)((v << j) & 0xff); + else + *bp |= (png_byte)((v >> (-j)) & mask); + } + } + } + else if (row_info->bit_depth == 8) + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = channels * row_info->width; + + for (i = 0; i < istop; i++, bp++) + { + + png_uint_16 v; + int j; + int c = (int)(i%channels); + + v = *bp; + *bp = 0; + for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) + { + if (j > 0) + *bp |= (png_byte)((v << j) & 0xff); + else + *bp |= (png_byte)((v >> (-j)) & 0xff); + } + } + } + else + { + png_bytep bp; + png_uint_32 i; + png_uint_32 istop = channels * row_info->width; + + for (bp = row, i = 0; i < istop; i++) + { + int c = (int)(i%channels); + png_uint_16 value, v; + int j; + + v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1)); + value = 0; + for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) + { + if (j > 0) + value |= (png_uint_16)((v << j) & (png_uint_16)0xffff); + else + value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff); + } + *bp++ = (png_byte)(value >> 8); + *bp++ = (png_byte)(value & 0xff); + } + } + } +} +#endif + +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED +void /* PRIVATE */ +png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_swap_alpha"); + +#ifdef PNG_USELESS_TESTS_SUPPORTED + if (row != NULL && row_info != NULL) +#endif + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + /* This converts from ARGB to RGBA */ + if (row_info->bit_depth == 8) + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save; + } + } + /* This converts from AARRGGBB to RRGGBBAA */ + else + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save[2]; + save[0] = *(sp++); + save[1] = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save[0]; + *(dp++) = save[1]; + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This converts from AG to GA */ + if (row_info->bit_depth == 8) + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save; + } + } + /* This converts from AAGG to GGAA */ + else + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save[2]; + save[0] = *(sp++); + save[1] = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save[0]; + *(dp++) = save[1]; + } + } + } + } +} +#endif + +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED +void /* PRIVATE */ +png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_invert_alpha"); + +#ifdef PNG_USELESS_TESTS_SUPPORTED + if (row != NULL && row_info != NULL) +#endif + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + /* This inverts the alpha channel in RGBA */ + if (row_info->bit_depth == 8) + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + for (i = 0, sp = dp = row; i < row_width; i++) + { + /* Does nothing + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + */ + sp+=3; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + /* This inverts the alpha channel in RRGGBBAA */ + else + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + /* Does nothing + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + */ + sp+=6; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This inverts the alpha channel in GA */ + if (row_info->bit_depth == 8) + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + *(dp++) = *(sp++); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + /* This inverts the alpha channel in GGAA */ + else + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + /* Does nothing + *(dp++) = *(sp++); + *(dp++) = *(sp++); + */ + sp+=2; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + } + } +} +#endif + +#ifdef PNG_MNG_FEATURES_SUPPORTED +/* Undoes intrapixel differencing */ +void /* PRIVATE */ +png_do_write_intrapixel(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_intrapixel"); + + if ( +#ifdef PNG_USELESS_TESTS_SUPPORTED + row != NULL && row_info != NULL && +#endif + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + int bytes_per_pixel; + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 3; + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 4; + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + *(rp) = (png_byte)((*rp - *(rp+1))&0xff); + *(rp+2) = (png_byte)((*(rp+2) - *(rp+1))&0xff); + } + } + else if (row_info->bit_depth == 16) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 6; + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 8; + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + png_uint_32 s0 = (*(rp ) << 8) | *(rp+1); + png_uint_32 s1 = (*(rp+2) << 8) | *(rp+3); + png_uint_32 s2 = (*(rp+4) << 8) | *(rp+5); + png_uint_32 red = (png_uint_32)((s0 - s1) & 0xffffL); + png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL); + *(rp ) = (png_byte)((red >> 8) & 0xff); + *(rp+1) = (png_byte)(red & 0xff); + *(rp+4) = (png_byte)((blue >> 8) & 0xff); + *(rp+5) = (png_byte)(blue & 0xff); + } + } + } +} +#endif /* PNG_MNG_FEATURES_SUPPORTED */ +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/contrib/syslinux-4.02/com32/lib/libpng/pngwutil.c b/contrib/syslinux-4.02/com32/lib/libpng/pngwutil.c new file mode 100644 index 0000000..c75f53e --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/libpng/pngwutil.c @@ -0,0 +1,2832 @@ + +/* pngwutil.c - utilities to write a PNG file + * + * Last changed in libpng 1.2.43 [February 25, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#define PNG_INTERNAL +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" +#ifdef PNG_WRITE_SUPPORTED + +/* Place a 32-bit number into a buffer in PNG byte order. We work + * with unsigned numbers for convenience, although one supported + * ancillary chunk uses signed (two's complement) numbers. + */ +void PNGAPI +png_save_uint_32(png_bytep buf, png_uint_32 i) +{ + buf[0] = (png_byte)((i >> 24) & 0xff); + buf[1] = (png_byte)((i >> 16) & 0xff); + buf[2] = (png_byte)((i >> 8) & 0xff); + buf[3] = (png_byte)(i & 0xff); +} + +/* The png_save_int_32 function assumes integers are stored in two's + * complement format. If this isn't the case, then this routine needs to + * be modified to write data in two's complement format. + */ +void PNGAPI +png_save_int_32(png_bytep buf, png_int_32 i) +{ + buf[0] = (png_byte)((i >> 24) & 0xff); + buf[1] = (png_byte)((i >> 16) & 0xff); + buf[2] = (png_byte)((i >> 8) & 0xff); + buf[3] = (png_byte)(i & 0xff); +} + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +void PNGAPI +png_save_uint_16(png_bytep buf, unsigned int i) +{ + buf[0] = (png_byte)((i >> 8) & 0xff); + buf[1] = (png_byte)(i & 0xff); +} + +/* Simple function to write the signature. If we have already written + * the magic bytes of the signature, or more likely, the PNG stream is + * being embedded into another stream and doesn't need its own signature, + * we should call png_set_sig_bytes() to tell libpng how many of the + * bytes have already been written. + */ +void /* PRIVATE */ +png_write_sig(png_structp png_ptr) +{ + png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; + + /* Write the rest of the 8 byte signature */ + png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes], + (png_size_t)(8 - png_ptr->sig_bytes)); + if (png_ptr->sig_bytes < 3) + png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; +} + +/* Write a PNG chunk all at once. The type is an array of ASCII characters + * representing the chunk name. The array must be at least 4 bytes in + * length, and does not need to be null terminated. To be safe, pass the + * pre-defined chunk names here, and if you need a new one, define it + * where the others are defined. The length is the length of the data. + * All the data must be present. If that is not possible, use the + * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end() + * functions instead. + */ +void PNGAPI +png_write_chunk(png_structp png_ptr, png_bytep chunk_name, + png_bytep data, png_size_t length) +{ + if (png_ptr == NULL) + return; + png_write_chunk_start(png_ptr, chunk_name, (png_uint_32)length); + png_write_chunk_data(png_ptr, data, (png_size_t)length); + png_write_chunk_end(png_ptr); +} + +/* Write the start of a PNG chunk. The type is the chunk type. + * The total_length is the sum of the lengths of all the data you will be + * passing in png_write_chunk_data(). + */ +void PNGAPI +png_write_chunk_start(png_structp png_ptr, png_bytep chunk_name, + png_uint_32 length) +{ + png_byte buf[8]; + + png_debug2(0, "Writing %s chunk, length = %lu", chunk_name, + (unsigned long)length); + + if (png_ptr == NULL) + return; + + + /* Write the length and the chunk name */ + png_save_uint_32(buf, length); + png_memcpy(buf + 4, chunk_name, 4); + png_write_data(png_ptr, buf, (png_size_t)8); + /* Put the chunk name into png_ptr->chunk_name */ + png_memcpy(png_ptr->chunk_name, chunk_name, 4); + /* Reset the crc and run it over the chunk name */ + png_reset_crc(png_ptr); + png_calculate_crc(png_ptr, chunk_name, (png_size_t)4); +} + +/* Write the data of a PNG chunk started with png_write_chunk_start(). + * Note that multiple calls to this function are allowed, and that the + * sum of the lengths from these calls *must* add up to the total_length + * given to png_write_chunk_start(). + */ +void PNGAPI +png_write_chunk_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + /* Write the data, and run the CRC over it */ + if (png_ptr == NULL) + return; + if (data != NULL && length > 0) + { + png_write_data(png_ptr, data, length); + /* Update the CRC after writing the data, + * in case that the user I/O routine alters it. + */ + png_calculate_crc(png_ptr, data, length); + } +} + +/* Finish a chunk started with png_write_chunk_start(). */ +void PNGAPI +png_write_chunk_end(png_structp png_ptr) +{ + png_byte buf[4]; + + if (png_ptr == NULL) return; + + /* Write the crc in a single operation */ + png_save_uint_32(buf, png_ptr->crc); + + png_write_data(png_ptr, buf, (png_size_t)4); +} + +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_iCCP_SUPPORTED) +/* This pair of functions encapsulates the operation of (a) compressing a + * text string, and (b) issuing it later as a series of chunk data writes. + * The compression_state structure is shared context for these functions + * set up by the caller in order to make the whole mess thread-safe. + */ + +typedef struct +{ + char *input; /* The uncompressed input data */ + int input_len; /* Its length */ + int num_output_ptr; /* Number of output pointers used */ + int max_output_ptr; /* Size of output_ptr */ + png_charpp output_ptr; /* Array of pointers to output */ +} compression_state; + +/* Compress given text into storage in the png_ptr structure */ +static int /* PRIVATE */ +png_text_compress(png_structp png_ptr, + png_charp text, png_size_t text_len, int compression, + compression_state *comp) +{ + int ret; + + comp->num_output_ptr = 0; + comp->max_output_ptr = 0; + comp->output_ptr = NULL; + comp->input = NULL; + comp->input_len = 0; + + /* We may just want to pass the text right through */ + if (compression == PNG_TEXT_COMPRESSION_NONE) + { + comp->input = text; + comp->input_len = text_len; + return((int)text_len); + } + + if (compression >= PNG_TEXT_COMPRESSION_LAST) + { +#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE) + char msg[50]; + png_snprintf(msg, 50, "Unknown compression type %d", compression); + png_warning(png_ptr, msg); +#else + png_warning(png_ptr, "Unknown compression type"); +#endif + } + + /* We can't write the chunk until we find out how much data we have, + * which means we need to run the compressor first and save the + * output. This shouldn't be a problem, as the vast majority of + * comments should be reasonable, but we will set up an array of + * malloc'd pointers to be sure. + * + * If we knew the application was well behaved, we could simplify this + * greatly by assuming we can always malloc an output buffer large + * enough to hold the compressed text ((1001 * text_len / 1000) + 12) + * and malloc this directly. The only time this would be a bad idea is + * if we can't malloc more than 64K and we have 64K of random input + * data, or if the input string is incredibly large (although this + * wouldn't cause a failure, just a slowdown due to swapping). + */ + + /* Set up the compression buffers */ + png_ptr->zstream.avail_in = (uInt)text_len; + png_ptr->zstream.next_in = (Bytef *)text; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = (Bytef *)png_ptr->zbuf; + + /* This is the same compression loop as in png_write_row() */ + do + { + /* Compress the data */ + ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); + if (ret != Z_OK) + { + /* Error */ + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + /* Check to see if we need more room */ + if (!(png_ptr->zstream.avail_out)) + { + /* Make sure the output array has room */ + if (comp->num_output_ptr >= comp->max_output_ptr) + { + int old_max; + + old_max = comp->max_output_ptr; + comp->max_output_ptr = comp->num_output_ptr + 4; + if (comp->output_ptr != NULL) + { + png_charpp old_ptr; + + old_ptr = comp->output_ptr; + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_uint_32) + (comp->max_output_ptr * png_sizeof(png_charpp))); + png_memcpy(comp->output_ptr, old_ptr, old_max + * png_sizeof(png_charp)); + png_free(png_ptr, old_ptr); + } + else + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_uint_32) + (comp->max_output_ptr * png_sizeof(png_charp))); + } + + /* Save the data */ + comp->output_ptr[comp->num_output_ptr] = + (png_charp)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); + png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, + png_ptr->zbuf_size); + comp->num_output_ptr++; + + /* and reset the buffer */ + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; + } + /* Continue until we don't have any more to compress */ + } while (png_ptr->zstream.avail_in); + + /* Finish the compression */ + do + { + /* Tell zlib we are finished */ + ret = deflate(&png_ptr->zstream, Z_FINISH); + + if (ret == Z_OK) + { + /* Check to see if we need more room */ + if (!(png_ptr->zstream.avail_out)) + { + /* Check to make sure our output array has room */ + if (comp->num_output_ptr >= comp->max_output_ptr) + { + int old_max; + + old_max = comp->max_output_ptr; + comp->max_output_ptr = comp->num_output_ptr + 4; + if (comp->output_ptr != NULL) + { + png_charpp old_ptr; + + old_ptr = comp->output_ptr; + /* This could be optimized to realloc() */ + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_uint_32)(comp->max_output_ptr * + png_sizeof(png_charp))); + png_memcpy(comp->output_ptr, old_ptr, + old_max * png_sizeof(png_charp)); + png_free(png_ptr, old_ptr); + } + else + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_uint_32)(comp->max_output_ptr * + png_sizeof(png_charp))); + } + + /* Save the data */ + comp->output_ptr[comp->num_output_ptr] = + (png_charp)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); + png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, + png_ptr->zbuf_size); + comp->num_output_ptr++; + + /* and reset the buffer pointers */ + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; + } + } + else if (ret != Z_STREAM_END) + { + /* We got an error */ + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + } while (ret != Z_STREAM_END); + + /* Text length is number of buffers plus last buffer */ + text_len = png_ptr->zbuf_size * comp->num_output_ptr; + if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) + text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out; + + return((int)text_len); +} + +/* Ship the compressed text out via chunk writes */ +static void /* PRIVATE */ +png_write_compressed_data_out(png_structp png_ptr, compression_state *comp) +{ + int i; + + /* Handle the no-compression case */ + if (comp->input) + { + png_write_chunk_data(png_ptr, (png_bytep)comp->input, + (png_size_t)comp->input_len); + return; + } + + /* Write saved output buffers, if any */ + for (i = 0; i < comp->num_output_ptr; i++) + { + png_write_chunk_data(png_ptr, (png_bytep)comp->output_ptr[i], + (png_size_t)png_ptr->zbuf_size); + png_free(png_ptr, comp->output_ptr[i]); + comp->output_ptr[i]=NULL; + } + if (comp->max_output_ptr != 0) + png_free(png_ptr, comp->output_ptr); + comp->output_ptr=NULL; + /* Write anything left in zbuf */ + if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size) + png_write_chunk_data(png_ptr, png_ptr->zbuf, + (png_size_t)(png_ptr->zbuf_size - png_ptr->zstream.avail_out)); + + /* Reset zlib for another zTXt/iTXt or image data */ + deflateReset(&png_ptr->zstream); + png_ptr->zstream.data_type = Z_BINARY; +} +#endif + +/* Write the IHDR chunk, and update the png_struct with the necessary + * information. Note that the rest of this code depends upon this + * information being correct. + */ +void /* PRIVATE */ +png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, + int bit_depth, int color_type, int compression_type, int filter_type, + int interlace_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IHDR; +#endif + int ret; + + png_byte buf[13]; /* Buffer to store the IHDR info */ + + png_debug(1, "in png_write_IHDR"); + + /* Check that we have valid input data from the application info */ + switch (color_type) + { + case PNG_COLOR_TYPE_GRAY: + switch (bit_depth) + { + case 1: + case 2: + case 4: + case 8: + case 16: png_ptr->channels = 1; break; + default: png_error(png_ptr, + "Invalid bit depth for grayscale image"); + } + break; + case PNG_COLOR_TYPE_RGB: + if (bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth for RGB image"); + png_ptr->channels = 3; + break; + case PNG_COLOR_TYPE_PALETTE: + switch (bit_depth) + { + case 1: + case 2: + case 4: + case 8: png_ptr->channels = 1; break; + default: png_error(png_ptr, "Invalid bit depth for paletted image"); + } + break; + case PNG_COLOR_TYPE_GRAY_ALPHA: + if (bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth for grayscale+alpha image"); + png_ptr->channels = 2; + break; + case PNG_COLOR_TYPE_RGB_ALPHA: + if (bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth for RGBA image"); + png_ptr->channels = 4; + break; + default: + png_error(png_ptr, "Invalid image color type specified"); + } + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + { + png_warning(png_ptr, "Invalid compression type specified"); + compression_type = PNG_COMPRESSION_TYPE_BASE; + } + + /* Write filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not write a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if ( +#ifdef PNG_MNG_FEATURES_SUPPORTED + !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) && + (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) && + (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) && +#endif + filter_type != PNG_FILTER_TYPE_BASE) + { + png_warning(png_ptr, "Invalid filter type specified"); + filter_type = PNG_FILTER_TYPE_BASE; + } + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + if (interlace_type != PNG_INTERLACE_NONE && + interlace_type != PNG_INTERLACE_ADAM7) + { + png_warning(png_ptr, "Invalid interlace type specified"); + interlace_type = PNG_INTERLACE_ADAM7; + } +#else + interlace_type=PNG_INTERLACE_NONE; +#endif + + /* Save the relevent information */ + png_ptr->bit_depth = (png_byte)bit_depth; + png_ptr->color_type = (png_byte)color_type; + png_ptr->interlaced = (png_byte)interlace_type; +#ifdef PNG_MNG_FEATURES_SUPPORTED + png_ptr->filter_type = (png_byte)filter_type; +#endif + png_ptr->compression_type = (png_byte)compression_type; + png_ptr->width = width; + png_ptr->height = height; + + png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels); + png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width); + /* Set the usr info, so any transformations can modify it */ + png_ptr->usr_width = png_ptr->width; + png_ptr->usr_bit_depth = png_ptr->bit_depth; + png_ptr->usr_channels = png_ptr->channels; + + /* Pack the header information into the buffer */ + png_save_uint_32(buf, width); + png_save_uint_32(buf + 4, height); + buf[8] = (png_byte)bit_depth; + buf[9] = (png_byte)color_type; + buf[10] = (png_byte)compression_type; + buf[11] = (png_byte)filter_type; + buf[12] = (png_byte)interlace_type; + + /* Write the chunk */ + png_write_chunk(png_ptr, (png_bytep)png_IHDR, buf, (png_size_t)13); + + /* Initialize zlib with PNG info */ + png_ptr->zstream.zalloc = png_zalloc; + png_ptr->zstream.zfree = png_zfree; + png_ptr->zstream.opaque = (voidpf)png_ptr; + if (!(png_ptr->do_filter)) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE || + png_ptr->bit_depth < 8) + png_ptr->do_filter = PNG_FILTER_NONE; + else + png_ptr->do_filter = PNG_ALL_FILTERS; + } + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY)) + { + if (png_ptr->do_filter != PNG_FILTER_NONE) + png_ptr->zlib_strategy = Z_FILTERED; + else + png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY; + } + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL)) + png_ptr->zlib_level = Z_DEFAULT_COMPRESSION; + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL)) + png_ptr->zlib_mem_level = 8; + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS)) + png_ptr->zlib_window_bits = 15; + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD)) + png_ptr->zlib_method = 8; + ret = deflateInit2(&png_ptr->zstream, png_ptr->zlib_level, + png_ptr->zlib_method, png_ptr->zlib_window_bits, + png_ptr->zlib_mem_level, png_ptr->zlib_strategy); + if (ret != Z_OK) + { + if (ret == Z_VERSION_ERROR) png_error(png_ptr, + "zlib failed to initialize compressor -- version error"); + if (ret == Z_STREAM_ERROR) png_error(png_ptr, + "zlib failed to initialize compressor -- stream error"); + if (ret == Z_MEM_ERROR) png_error(png_ptr, + "zlib failed to initialize compressor -- mem error"); + png_error(png_ptr, "zlib failed to initialize compressor"); + } + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + /* libpng is not interested in zstream.data_type */ + /* Set it to a predefined value, to avoid its evaluation inside zlib */ + png_ptr->zstream.data_type = Z_BINARY; + + png_ptr->mode = PNG_HAVE_IHDR; +} + +/* Write the palette. We are careful not to trust png_color to be in the + * correct order for PNG, so people can redefine it to any convenient + * structure. + */ +void /* PRIVATE */ +png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_PLTE; +#endif + png_uint_32 i; + png_colorp pal_ptr; + png_byte buf[3]; + + png_debug(1, "in png_write_PLTE"); + + if (( +#ifdef PNG_MNG_FEATURES_SUPPORTED + !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) && +#endif + num_pal == 0) || num_pal > 256) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_error(png_ptr, "Invalid number of colors in palette"); + } + else + { + png_warning(png_ptr, "Invalid number of colors in palette"); + return; + } + } + + if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) + { + png_warning(png_ptr, + "Ignoring request to write a PLTE chunk in grayscale PNG"); + return; + } + + png_ptr->num_palette = (png_uint_16)num_pal; + png_debug1(3, "num_palette = %d", png_ptr->num_palette); + + png_write_chunk_start(png_ptr, (png_bytep)png_PLTE, + (png_uint_32)(num_pal * 3)); +#ifdef PNG_POINTER_INDEXING_SUPPORTED + for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++) + { + buf[0] = pal_ptr->red; + buf[1] = pal_ptr->green; + buf[2] = pal_ptr->blue; + png_write_chunk_data(png_ptr, buf, (png_size_t)3); + } +#else + /* This is a little slower but some buggy compilers need to do this + * instead + */ + pal_ptr=palette; + for (i = 0; i < num_pal; i++) + { + buf[0] = pal_ptr[i].red; + buf[1] = pal_ptr[i].green; + buf[2] = pal_ptr[i].blue; + png_write_chunk_data(png_ptr, buf, (png_size_t)3); + } +#endif + png_write_chunk_end(png_ptr); + png_ptr->mode |= PNG_HAVE_PLTE; +} + +/* Write an IDAT chunk */ +void /* PRIVATE */ +png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IDAT; +#endif + + png_debug(1, "in png_write_IDAT"); + + /* Optimize the CMF field in the zlib stream. */ + /* This hack of the zlib stream is compliant to the stream specification. */ + if (!(png_ptr->mode & PNG_HAVE_IDAT) && + png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) + { + unsigned int z_cmf = data[0]; /* zlib compression method and flags */ + if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) + { + /* Avoid memory underflows and multiplication overflows. + * + * The conditions below are practically always satisfied; + * however, they still must be checked. + */ + if (length >= 2 && + png_ptr->height < 16384 && png_ptr->width < 16384) + { + png_uint_32 uncompressed_idat_size = png_ptr->height * + ((png_ptr->width * + png_ptr->channels * png_ptr->bit_depth + 15) >> 3); + unsigned int z_cinfo = z_cmf >> 4; + unsigned int half_z_window_size = 1 << (z_cinfo + 7); + while (uncompressed_idat_size <= half_z_window_size && + half_z_window_size >= 256) + { + z_cinfo--; + half_z_window_size >>= 1; + } + z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4); + if (data[0] != (png_byte)z_cmf) + { + data[0] = (png_byte)z_cmf; + data[1] &= 0xe0; + data[1] += (png_byte)(0x1f - ((z_cmf << 8) + data[1]) % 0x1f); + } + } + } + else + png_error(png_ptr, + "Invalid zlib compression method or flags in IDAT"); + } + + png_write_chunk(png_ptr, (png_bytep)png_IDAT, data, length); + png_ptr->mode |= PNG_HAVE_IDAT; +} + +/* Write an IEND chunk */ +void /* PRIVATE */ +png_write_IEND(png_structp png_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IEND; +#endif + + png_debug(1, "in png_write_IEND"); + + png_write_chunk(png_ptr, (png_bytep)png_IEND, png_bytep_NULL, + (png_size_t)0); + png_ptr->mode |= PNG_HAVE_IEND; +} + +#ifdef PNG_WRITE_gAMA_SUPPORTED +/* Write a gAMA chunk */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +void /* PRIVATE */ +png_write_gAMA(png_structp png_ptr, double file_gamma) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_gAMA; +#endif + png_uint_32 igamma; + png_byte buf[4]; + + png_debug(1, "in png_write_gAMA"); + + /* file_gamma is saved in 1/100,000ths */ + igamma = (png_uint_32)(file_gamma * 100000.0 + 0.5); + png_save_uint_32(buf, igamma); + png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4); +} +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +void /* PRIVATE */ +png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_gAMA; +#endif + png_byte buf[4]; + + png_debug(1, "in png_write_gAMA"); + + /* file_gamma is saved in 1/100,000ths */ + png_save_uint_32(buf, (png_uint_32)file_gamma); + png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4); +} +#endif +#endif + +#ifdef PNG_WRITE_sRGB_SUPPORTED +/* Write a sRGB chunk */ +void /* PRIVATE */ +png_write_sRGB(png_structp png_ptr, int srgb_intent) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_sRGB; +#endif + png_byte buf[1]; + + png_debug(1, "in png_write_sRGB"); + + if (srgb_intent >= PNG_sRGB_INTENT_LAST) + png_warning(png_ptr, + "Invalid sRGB rendering intent specified"); + buf[0]=(png_byte)srgb_intent; + png_write_chunk(png_ptr, (png_bytep)png_sRGB, buf, (png_size_t)1); +} +#endif + +#ifdef PNG_WRITE_iCCP_SUPPORTED +/* Write an iCCP chunk */ +void /* PRIVATE */ +png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type, + png_charp profile, int profile_len) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_iCCP; +#endif + png_size_t name_len; + png_charp new_name; + compression_state comp; + int embedded_profile_len = 0; + + png_debug(1, "in png_write_iCCP"); + + comp.num_output_ptr = 0; + comp.max_output_ptr = 0; + comp.output_ptr = NULL; + comp.input = NULL; + comp.input_len = 0; + + if ((name_len = png_check_keyword(png_ptr, name, + &new_name)) == 0) + return; + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + png_warning(png_ptr, "Unknown compression type in iCCP chunk"); + + if (profile == NULL) + profile_len = 0; + + if (profile_len > 3) + embedded_profile_len = + ((*( (png_bytep)profile ))<<24) | + ((*( (png_bytep)profile + 1))<<16) | + ((*( (png_bytep)profile + 2))<< 8) | + ((*( (png_bytep)profile + 3)) ); + + if (embedded_profile_len < 0) + { + png_warning(png_ptr, + "Embedded profile length in iCCP chunk is negative"); + png_free(png_ptr, new_name); + return; + } + + if (profile_len < embedded_profile_len) + { + png_warning(png_ptr, + "Embedded profile length too large in iCCP chunk"); + png_free(png_ptr, new_name); + return; + } + + if (profile_len > embedded_profile_len) + { + png_warning(png_ptr, + "Truncating profile to actual length in iCCP chunk"); + profile_len = embedded_profile_len; + } + + if (profile_len) + profile_len = png_text_compress(png_ptr, profile, + (png_size_t)profile_len, PNG_COMPRESSION_TYPE_BASE, &comp); + + /* Make sure we include the NULL after the name and the compression type */ + png_write_chunk_start(png_ptr, (png_bytep)png_iCCP, + (png_uint_32)(name_len + profile_len + 2)); + new_name[name_len + 1] = 0x00; + png_write_chunk_data(png_ptr, (png_bytep)new_name, + (png_size_t)(name_len + 2)); + + if (profile_len) + png_write_compressed_data_out(png_ptr, &comp); + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_name); +} +#endif + +#ifdef PNG_WRITE_sPLT_SUPPORTED +/* Write a sPLT chunk */ +void /* PRIVATE */ +png_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_sPLT; +#endif + png_size_t name_len; + png_charp new_name; + png_byte entrybuf[10]; + int entry_size = (spalette->depth == 8 ? 6 : 10); + int palette_size = entry_size * spalette->nentries; + png_sPLT_entryp ep; +#ifndef PNG_POINTER_INDEXING_SUPPORTED + int i; +#endif + + png_debug(1, "in png_write_sPLT"); + + if ((name_len = png_check_keyword(png_ptr,spalette->name, &new_name))==0) + return; + + /* Make sure we include the NULL after the name */ + png_write_chunk_start(png_ptr, (png_bytep)png_sPLT, + (png_uint_32)(name_len + 2 + palette_size)); + png_write_chunk_data(png_ptr, (png_bytep)new_name, + (png_size_t)(name_len + 1)); + png_write_chunk_data(png_ptr, (png_bytep)&spalette->depth, (png_size_t)1); + + /* Loop through each palette entry, writing appropriately */ +#ifdef PNG_POINTER_INDEXING_SUPPORTED + for (ep = spalette->entries; ep<spalette->entries + spalette->nentries; ep++) + { + if (spalette->depth == 8) + { + entrybuf[0] = (png_byte)ep->red; + entrybuf[1] = (png_byte)ep->green; + entrybuf[2] = (png_byte)ep->blue; + entrybuf[3] = (png_byte)ep->alpha; + png_save_uint_16(entrybuf + 4, ep->frequency); + } + else + { + png_save_uint_16(entrybuf + 0, ep->red); + png_save_uint_16(entrybuf + 2, ep->green); + png_save_uint_16(entrybuf + 4, ep->blue); + png_save_uint_16(entrybuf + 6, ep->alpha); + png_save_uint_16(entrybuf + 8, ep->frequency); + } + png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size); + } +#else + ep=spalette->entries; + for (i=0; i>spalette->nentries; i++) + { + if (spalette->depth == 8) + { + entrybuf[0] = (png_byte)ep[i].red; + entrybuf[1] = (png_byte)ep[i].green; + entrybuf[2] = (png_byte)ep[i].blue; + entrybuf[3] = (png_byte)ep[i].alpha; + png_save_uint_16(entrybuf + 4, ep[i].frequency); + } + else + { + png_save_uint_16(entrybuf + 0, ep[i].red); + png_save_uint_16(entrybuf + 2, ep[i].green); + png_save_uint_16(entrybuf + 4, ep[i].blue); + png_save_uint_16(entrybuf + 6, ep[i].alpha); + png_save_uint_16(entrybuf + 8, ep[i].frequency); + } + png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size); + } +#endif + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_name); +} +#endif + +#ifdef PNG_WRITE_sBIT_SUPPORTED +/* Write the sBIT chunk */ +void /* PRIVATE */ +png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_sBIT; +#endif + png_byte buf[4]; + png_size_t size; + + png_debug(1, "in png_write_sBIT"); + + /* Make sure we don't depend upon the order of PNG_COLOR_8 */ + if (color_type & PNG_COLOR_MASK_COLOR) + { + png_byte maxbits; + + maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 : + png_ptr->usr_bit_depth); + if (sbit->red == 0 || sbit->red > maxbits || + sbit->green == 0 || sbit->green > maxbits || + sbit->blue == 0 || sbit->blue > maxbits) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + buf[0] = sbit->red; + buf[1] = sbit->green; + buf[2] = sbit->blue; + size = 3; + } + else + { + if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + buf[0] = sbit->gray; + size = 1; + } + + if (color_type & PNG_COLOR_MASK_ALPHA) + { + if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + buf[size++] = sbit->alpha; + } + + png_write_chunk(png_ptr, (png_bytep)png_sBIT, buf, size); +} +#endif + +#ifdef PNG_WRITE_cHRM_SUPPORTED +/* Write the cHRM chunk */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +void /* PRIVATE */ +png_write_cHRM(png_structp png_ptr, double white_x, double white_y, + double red_x, double red_y, double green_x, double green_y, + double blue_x, double blue_y) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_cHRM; +#endif + png_byte buf[32]; + + png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y, + int_green_x, int_green_y, int_blue_x, int_blue_y; + + png_debug(1, "in png_write_cHRM"); + + int_white_x = (png_uint_32)(white_x * 100000.0 + 0.5); + int_white_y = (png_uint_32)(white_y * 100000.0 + 0.5); + int_red_x = (png_uint_32)(red_x * 100000.0 + 0.5); + int_red_y = (png_uint_32)(red_y * 100000.0 + 0.5); + int_green_x = (png_uint_32)(green_x * 100000.0 + 0.5); + int_green_y = (png_uint_32)(green_y * 100000.0 + 0.5); + int_blue_x = (png_uint_32)(blue_x * 100000.0 + 0.5); + int_blue_y = (png_uint_32)(blue_y * 100000.0 + 0.5); + +#ifdef PNG_CHECK_cHRM_SUPPORTED + if (png_check_cHRM_fixed(png_ptr, int_white_x, int_white_y, + int_red_x, int_red_y, int_green_x, int_green_y, int_blue_x, int_blue_y)) +#endif + { + /* Each value is saved in 1/100,000ths */ + + png_save_uint_32(buf, int_white_x); + png_save_uint_32(buf + 4, int_white_y); + + png_save_uint_32(buf + 8, int_red_x); + png_save_uint_32(buf + 12, int_red_y); + + png_save_uint_32(buf + 16, int_green_x); + png_save_uint_32(buf + 20, int_green_y); + + png_save_uint_32(buf + 24, int_blue_x); + png_save_uint_32(buf + 28, int_blue_y); + + png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32); + } +} +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +void /* PRIVATE */ +png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x, + png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y, + png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x, + png_fixed_point blue_y) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_cHRM; +#endif + png_byte buf[32]; + + png_debug(1, "in png_write_cHRM"); + + /* Each value is saved in 1/100,000ths */ +#ifdef PNG_CHECK_cHRM_SUPPORTED + if (png_check_cHRM_fixed(png_ptr, white_x, white_y, red_x, red_y, + green_x, green_y, blue_x, blue_y)) +#endif + { + png_save_uint_32(buf, (png_uint_32)white_x); + png_save_uint_32(buf + 4, (png_uint_32)white_y); + + png_save_uint_32(buf + 8, (png_uint_32)red_x); + png_save_uint_32(buf + 12, (png_uint_32)red_y); + + png_save_uint_32(buf + 16, (png_uint_32)green_x); + png_save_uint_32(buf + 20, (png_uint_32)green_y); + + png_save_uint_32(buf + 24, (png_uint_32)blue_x); + png_save_uint_32(buf + 28, (png_uint_32)blue_y); + + png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32); + } +} +#endif +#endif + +#ifdef PNG_WRITE_tRNS_SUPPORTED +/* Write the tRNS chunk */ +void /* PRIVATE */ +png_write_tRNS(png_structp png_ptr, png_bytep trans, png_color_16p tran, + int num_trans, int color_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_tRNS; +#endif + png_byte buf[6]; + + png_debug(1, "in png_write_tRNS"); + + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette) + { + png_warning(png_ptr, "Invalid number of transparent colors specified"); + return; + } + /* Write the chunk out as it is */ + png_write_chunk(png_ptr, (png_bytep)png_tRNS, trans, + (png_size_t)num_trans); + } + else if (color_type == PNG_COLOR_TYPE_GRAY) + { + /* One 16 bit value */ + if (tran->gray >= (1 << png_ptr->bit_depth)) + { + png_warning(png_ptr, + "Ignoring attempt to write tRNS chunk out-of-range for bit_depth"); + return; + } + png_save_uint_16(buf, tran->gray); + png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)2); + } + else if (color_type == PNG_COLOR_TYPE_RGB) + { + /* Three 16 bit values */ + png_save_uint_16(buf, tran->red); + png_save_uint_16(buf + 2, tran->green); + png_save_uint_16(buf + 4, tran->blue); + if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) + { + png_warning(png_ptr, + "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); + return; + } + png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)6); + } + else + { + png_warning(png_ptr, "Can't write tRNS with an alpha channel"); + } +} +#endif + +#ifdef PNG_WRITE_bKGD_SUPPORTED +/* Write the background chunk */ +void /* PRIVATE */ +png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_bKGD; +#endif + png_byte buf[6]; + + png_debug(1, "in png_write_bKGD"); + + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + if ( +#ifdef PNG_MNG_FEATURES_SUPPORTED + (png_ptr->num_palette || + (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) && +#endif + back->index >= png_ptr->num_palette) + { + png_warning(png_ptr, "Invalid background palette index"); + return; + } + buf[0] = back->index; + png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)1); + } + else if (color_type & PNG_COLOR_MASK_COLOR) + { + png_save_uint_16(buf, back->red); + png_save_uint_16(buf + 2, back->green); + png_save_uint_16(buf + 4, back->blue); + if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) + { + png_warning(png_ptr, + "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8"); + return; + } + png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)6); + } + else + { + if (back->gray >= (1 << png_ptr->bit_depth)) + { + png_warning(png_ptr, + "Ignoring attempt to write bKGD chunk out-of-range for bit_depth"); + return; + } + png_save_uint_16(buf, back->gray); + png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)2); + } +} +#endif + +#ifdef PNG_WRITE_hIST_SUPPORTED +/* Write the histogram */ +void /* PRIVATE */ +png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_hIST; +#endif + int i; + png_byte buf[3]; + + png_debug(1, "in png_write_hIST"); + + if (num_hist > (int)png_ptr->num_palette) + { + png_debug2(3, "num_hist = %d, num_palette = %d", num_hist, + png_ptr->num_palette); + png_warning(png_ptr, "Invalid number of histogram entries specified"); + return; + } + + png_write_chunk_start(png_ptr, (png_bytep)png_hIST, + (png_uint_32)(num_hist * 2)); + for (i = 0; i < num_hist; i++) + { + png_save_uint_16(buf, hist[i]); + png_write_chunk_data(png_ptr, buf, (png_size_t)2); + } + png_write_chunk_end(png_ptr); +} +#endif + +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ + defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) +/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification, + * and if invalid, correct the keyword rather than discarding the entire + * chunk. The PNG 1.0 specification requires keywords 1-79 characters in + * length, forbids leading or trailing whitespace, multiple internal spaces, + * and the non-break space (0x80) from ISO 8859-1. Returns keyword length. + * + * The new_key is allocated to hold the corrected keyword and must be freed + * by the calling routine. This avoids problems with trying to write to + * static keywords without having to have duplicate copies of the strings. + */ +png_size_t /* PRIVATE */ +png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key) +{ + png_size_t key_len; + png_charp kp, dp; + int kflag; + int kwarn=0; + + png_debug(1, "in png_check_keyword"); + + *new_key = NULL; + + if (key == NULL || (key_len = png_strlen(key)) == 0) + { + png_warning(png_ptr, "zero length keyword"); + return ((png_size_t)0); + } + + png_debug1(2, "Keyword to be checked is '%s'", key); + + *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2)); + if (*new_key == NULL) + { + png_warning(png_ptr, "Out of memory while procesing keyword"); + return ((png_size_t)0); + } + + /* Replace non-printing characters with a blank and print a warning */ + for (kp = key, dp = *new_key; *kp != '\0'; kp++, dp++) + { + if ((png_byte)*kp < 0x20 || + ((png_byte)*kp > 0x7E && (png_byte)*kp < 0xA1)) + { +#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE) + char msg[40]; + + png_snprintf(msg, 40, + "invalid keyword character 0x%02X", (png_byte)*kp); + png_warning(png_ptr, msg); +#else + png_warning(png_ptr, "invalid character in keyword"); +#endif + *dp = ' '; + } + else + { + *dp = *kp; + } + } + *dp = '\0'; + + /* Remove any trailing white space. */ + kp = *new_key + key_len - 1; + if (*kp == ' ') + { + png_warning(png_ptr, "trailing spaces removed from keyword"); + + while (*kp == ' ') + { + *(kp--) = '\0'; + key_len--; + } + } + + /* Remove any leading white space. */ + kp = *new_key; + if (*kp == ' ') + { + png_warning(png_ptr, "leading spaces removed from keyword"); + + while (*kp == ' ') + { + kp++; + key_len--; + } + } + + png_debug1(2, "Checking for multiple internal spaces in '%s'", kp); + + /* Remove multiple internal spaces. */ + for (kflag = 0, dp = *new_key; *kp != '\0'; kp++) + { + if (*kp == ' ' && kflag == 0) + { + *(dp++) = *kp; + kflag = 1; + } + else if (*kp == ' ') + { + key_len--; + kwarn=1; + } + else + { + *(dp++) = *kp; + kflag = 0; + } + } + *dp = '\0'; + if (kwarn) + png_warning(png_ptr, "extra interior spaces removed from keyword"); + + if (key_len == 0) + { + png_free(png_ptr, *new_key); + *new_key=NULL; + png_warning(png_ptr, "Zero length keyword"); + } + + if (key_len > 79) + { + png_warning(png_ptr, "keyword length must be 1 - 79 characters"); + (*new_key)[79] = '\0'; + key_len = 79; + } + + return (key_len); +} +#endif + +#ifdef PNG_WRITE_tEXt_SUPPORTED +/* Write a tEXt chunk */ +void /* PRIVATE */ +png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text, + png_size_t text_len) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_tEXt; +#endif + png_size_t key_len; + png_charp new_key; + + png_debug(1, "in png_write_tEXt"); + + if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0) + return; + + if (text == NULL || *text == '\0') + text_len = 0; + else + text_len = png_strlen(text); + + /* Make sure we include the 0 after the key */ + png_write_chunk_start(png_ptr, (png_bytep)png_tEXt, + (png_uint_32)(key_len + text_len + 1)); + /* + * We leave it to the application to meet PNG-1.0 requirements on the + * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of + * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. + * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. + */ + png_write_chunk_data(png_ptr, (png_bytep)new_key, + (png_size_t)(key_len + 1)); + if (text_len) + png_write_chunk_data(png_ptr, (png_bytep)text, (png_size_t)text_len); + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_key); +} +#endif + +#ifdef PNG_WRITE_zTXt_SUPPORTED +/* Write a compressed text chunk */ +void /* PRIVATE */ +png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text, + png_size_t text_len, int compression) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_zTXt; +#endif + png_size_t key_len; + char buf[1]; + png_charp new_key; + compression_state comp; + + png_debug(1, "in png_write_zTXt"); + + comp.num_output_ptr = 0; + comp.max_output_ptr = 0; + comp.output_ptr = NULL; + comp.input = NULL; + comp.input_len = 0; + + if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0) + { + png_free(png_ptr, new_key); + return; + } + + if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE) + { + png_write_tEXt(png_ptr, new_key, text, (png_size_t)0); + png_free(png_ptr, new_key); + return; + } + + text_len = png_strlen(text); + + /* Compute the compressed data; do it now for the length */ + text_len = png_text_compress(png_ptr, text, text_len, compression, + &comp); + + /* Write start of chunk */ + png_write_chunk_start(png_ptr, (png_bytep)png_zTXt, + (png_uint_32)(key_len+text_len + 2)); + /* Write key */ + png_write_chunk_data(png_ptr, (png_bytep)new_key, + (png_size_t)(key_len + 1)); + png_free(png_ptr, new_key); + + buf[0] = (png_byte)compression; + /* Write compression */ + png_write_chunk_data(png_ptr, (png_bytep)buf, (png_size_t)1); + /* Write the compressed data */ + png_write_compressed_data_out(png_ptr, &comp); + + /* Close the chunk */ + png_write_chunk_end(png_ptr); +} +#endif + +#ifdef PNG_WRITE_iTXt_SUPPORTED +/* Write an iTXt chunk */ +void /* PRIVATE */ +png_write_iTXt(png_structp png_ptr, int compression, png_charp key, + png_charp lang, png_charp lang_key, png_charp text) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_iTXt; +#endif + png_size_t lang_len, key_len, lang_key_len, text_len; + png_charp new_lang; + png_charp new_key = NULL; + png_byte cbuf[2]; + compression_state comp; + + png_debug(1, "in png_write_iTXt"); + + comp.num_output_ptr = 0; + comp.max_output_ptr = 0; + comp.output_ptr = NULL; + comp.input = NULL; + + if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0) + return; + + if ((lang_len = png_check_keyword(png_ptr, lang, &new_lang))==0) + { + png_warning(png_ptr, "Empty language field in iTXt chunk"); + new_lang = NULL; + lang_len = 0; + } + + if (lang_key == NULL) + lang_key_len = 0; + else + lang_key_len = png_strlen(lang_key); + + if (text == NULL) + text_len = 0; + else + text_len = png_strlen(text); + + /* Compute the compressed data; do it now for the length */ + text_len = png_text_compress(png_ptr, text, text_len, compression-2, + &comp); + + + /* Make sure we include the compression flag, the compression byte, + * and the NULs after the key, lang, and lang_key parts */ + + png_write_chunk_start(png_ptr, (png_bytep)png_iTXt, + (png_uint_32)( + 5 /* comp byte, comp flag, terminators for key, lang and lang_key */ + + key_len + + lang_len + + lang_key_len + + text_len)); + + /* We leave it to the application to meet PNG-1.0 requirements on the + * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of + * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. + * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. + */ + png_write_chunk_data(png_ptr, (png_bytep)new_key, + (png_size_t)(key_len + 1)); + + /* Set the compression flag */ + if (compression == PNG_ITXT_COMPRESSION_NONE || \ + compression == PNG_TEXT_COMPRESSION_NONE) + cbuf[0] = 0; + else /* compression == PNG_ITXT_COMPRESSION_zTXt */ + cbuf[0] = 1; + /* Set the compression method */ + cbuf[1] = 0; + png_write_chunk_data(png_ptr, cbuf, (png_size_t)2); + + cbuf[0] = 0; + png_write_chunk_data(png_ptr, (new_lang ? (png_bytep)new_lang : cbuf), + (png_size_t)(lang_len + 1)); + png_write_chunk_data(png_ptr, (lang_key ? (png_bytep)lang_key : cbuf), + (png_size_t)(lang_key_len + 1)); + png_write_compressed_data_out(png_ptr, &comp); + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_key); + png_free(png_ptr, new_lang); +} +#endif + +#ifdef PNG_WRITE_oFFs_SUPPORTED +/* Write the oFFs chunk */ +void /* PRIVATE */ +png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset, + int unit_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_oFFs; +#endif + png_byte buf[9]; + + png_debug(1, "in png_write_oFFs"); + + if (unit_type >= PNG_OFFSET_LAST) + png_warning(png_ptr, "Unrecognized unit type for oFFs chunk"); + + png_save_int_32(buf, x_offset); + png_save_int_32(buf + 4, y_offset); + buf[8] = (png_byte)unit_type; + + png_write_chunk(png_ptr, (png_bytep)png_oFFs, buf, (png_size_t)9); +} +#endif +#ifdef PNG_WRITE_pCAL_SUPPORTED +/* Write the pCAL chunk (described in the PNG extensions document) */ +void /* PRIVATE */ +png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0, + png_int_32 X1, int type, int nparams, png_charp units, png_charpp params) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_pCAL; +#endif + png_size_t purpose_len, units_len, total_len; + png_uint_32p params_len; + png_byte buf[10]; + png_charp new_purpose; + int i; + + png_debug1(1, "in png_write_pCAL (%d parameters)", nparams); + + if (type >= PNG_EQUATION_LAST) + png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); + + purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1; + png_debug1(3, "pCAL purpose length = %d", (int)purpose_len); + units_len = png_strlen(units) + (nparams == 0 ? 0 : 1); + png_debug1(3, "pCAL units length = %d", (int)units_len); + total_len = purpose_len + units_len + 10; + + params_len = (png_uint_32p)png_malloc(png_ptr, + (png_uint_32)(nparams * png_sizeof(png_uint_32))); + + /* Find the length of each parameter, making sure we don't count the + null terminator for the last parameter. */ + for (i = 0; i < nparams; i++) + { + params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1); + png_debug2(3, "pCAL parameter %d length = %lu", i, + (unsigned long) params_len[i]); + total_len += (png_size_t)params_len[i]; + } + + png_debug1(3, "pCAL total length = %d", (int)total_len); + png_write_chunk_start(png_ptr, (png_bytep)png_pCAL, (png_uint_32)total_len); + png_write_chunk_data(png_ptr, (png_bytep)new_purpose, + (png_size_t)purpose_len); + png_save_int_32(buf, X0); + png_save_int_32(buf + 4, X1); + buf[8] = (png_byte)type; + buf[9] = (png_byte)nparams; + png_write_chunk_data(png_ptr, buf, (png_size_t)10); + png_write_chunk_data(png_ptr, (png_bytep)units, (png_size_t)units_len); + + png_free(png_ptr, new_purpose); + + for (i = 0; i < nparams; i++) + { + png_write_chunk_data(png_ptr, (png_bytep)params[i], + (png_size_t)params_len[i]); + } + + png_free(png_ptr, params_len); + png_write_chunk_end(png_ptr); +} +#endif + +#ifdef PNG_WRITE_sCAL_SUPPORTED +/* Write the sCAL chunk */ +#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) +void /* PRIVATE */ +png_write_sCAL(png_structp png_ptr, int unit, double width, double height) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_sCAL; +#endif + char buf[64]; + png_size_t total_len; + + png_debug(1, "in png_write_sCAL"); + + buf[0] = (char)unit; +#ifdef _WIN32_WCE +/* sprintf() function is not supported on WindowsCE */ + { + wchar_t wc_buf[32]; + size_t wc_len; + swprintf(wc_buf, TEXT("%12.12e"), width); + wc_len = wcslen(wc_buf); + WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + 1, wc_len, NULL, + NULL); + total_len = wc_len + 2; + swprintf(wc_buf, TEXT("%12.12e"), height); + wc_len = wcslen(wc_buf); + WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + total_len, wc_len, + NULL, NULL); + total_len += wc_len; + } +#else + png_snprintf(buf + 1, 63, "%12.12e", width); + total_len = 1 + png_strlen(buf + 1) + 1; + png_snprintf(buf + total_len, 64-total_len, "%12.12e", height); + total_len += png_strlen(buf + total_len); +#endif + + png_debug1(3, "sCAL total length = %u", (unsigned int)total_len); + png_write_chunk(png_ptr, (png_bytep)png_sCAL, (png_bytep)buf, total_len); +} +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +void /* PRIVATE */ +png_write_sCAL_s(png_structp png_ptr, int unit, png_charp width, + png_charp height) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_sCAL; +#endif + png_byte buf[64]; + png_size_t wlen, hlen, total_len; + + png_debug(1, "in png_write_sCAL_s"); + + wlen = png_strlen(width); + hlen = png_strlen(height); + total_len = wlen + hlen + 2; + if (total_len > 64) + { + png_warning(png_ptr, "Can't write sCAL (buffer too small)"); + return; + } + + buf[0] = (png_byte)unit; + png_memcpy(buf + 1, width, wlen + 1); /* Append the '\0' here */ + png_memcpy(buf + wlen + 2, height, hlen); /* Do NOT append the '\0' here */ + + png_debug1(3, "sCAL total length = %u", (unsigned int)total_len); + png_write_chunk(png_ptr, (png_bytep)png_sCAL, buf, total_len); +} +#endif +#endif +#endif + +#ifdef PNG_WRITE_pHYs_SUPPORTED +/* Write the pHYs chunk */ +void /* PRIVATE */ +png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit, + png_uint_32 y_pixels_per_unit, + int unit_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_pHYs; +#endif + png_byte buf[9]; + + png_debug(1, "in png_write_pHYs"); + + if (unit_type >= PNG_RESOLUTION_LAST) + png_warning(png_ptr, "Unrecognized unit type for pHYs chunk"); + + png_save_uint_32(buf, x_pixels_per_unit); + png_save_uint_32(buf + 4, y_pixels_per_unit); + buf[8] = (png_byte)unit_type; + + png_write_chunk(png_ptr, (png_bytep)png_pHYs, buf, (png_size_t)9); +} +#endif + +#ifdef PNG_WRITE_tIME_SUPPORTED +/* Write the tIME chunk. Use either png_convert_from_struct_tm() + * or png_convert_from_time_t(), or fill in the structure yourself. + */ +void /* PRIVATE */ +png_write_tIME(png_structp png_ptr, png_timep mod_time) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_tIME; +#endif + png_byte buf[7]; + + png_debug(1, "in png_write_tIME"); + + if (mod_time->month > 12 || mod_time->month < 1 || + mod_time->day > 31 || mod_time->day < 1 || + mod_time->hour > 23 || mod_time->second > 60) + { + png_warning(png_ptr, "Invalid time specified for tIME chunk"); + return; + } + + png_save_uint_16(buf, mod_time->year); + buf[2] = mod_time->month; + buf[3] = mod_time->day; + buf[4] = mod_time->hour; + buf[5] = mod_time->minute; + buf[6] = mod_time->second; + + png_write_chunk(png_ptr, (png_bytep)png_tIME, buf, (png_size_t)7); +} +#endif + +/* Initializes the row writing capability of libpng */ +void /* PRIVATE */ +png_write_start_row(png_structp png_ptr) +{ +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + png_size_t buf_size; + + png_debug(1, "in png_write_start_row"); + + buf_size = (png_size_t)(PNG_ROWBYTES( + png_ptr->usr_channels*png_ptr->usr_bit_depth, png_ptr->width) + 1); + + /* Set up row buffer */ + png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, + (png_uint_32)buf_size); + png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE; + +#ifdef PNG_WRITE_FILTER_SUPPORTED + /* Set up filtering buffer, if using this filter */ + if (png_ptr->do_filter & PNG_FILTER_SUB) + { + png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(png_ptr->rowbytes + 1)); + png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; + } + + /* We only need to keep the previous row if we are using one of these. */ + if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) + { + /* Set up previous row buffer */ + png_ptr->prev_row = (png_bytep)png_calloc(png_ptr, + (png_uint_32)buf_size); + + if (png_ptr->do_filter & PNG_FILTER_UP) + { + png_ptr->up_row = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(png_ptr->rowbytes + 1)); + png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; + } + + if (png_ptr->do_filter & PNG_FILTER_AVG) + { + png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(png_ptr->rowbytes + 1)); + png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; + } + + if (png_ptr->do_filter & PNG_FILTER_PAETH) + { + png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(png_ptr->rowbytes + 1)); + png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; + } + } +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* If interlaced, we need to set up width and height of pass */ + if (png_ptr->interlaced) + { + if (!(png_ptr->transformations & PNG_INTERLACE)) + { + png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - + png_pass_ystart[0]) / png_pass_yinc[0]; + png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 - + png_pass_start[0]) / png_pass_inc[0]; + } + else + { + png_ptr->num_rows = png_ptr->height; + png_ptr->usr_width = png_ptr->width; + } + } + else +#endif + { + png_ptr->num_rows = png_ptr->height; + png_ptr->usr_width = png_ptr->width; + } + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; +} + +/* Internal use only. Called when finished processing a row of data. */ +void /* PRIVATE */ +png_write_finish_row(png_structp png_ptr) +{ +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + int ret; + + png_debug(1, "in png_write_finish_row"); + + /* Next row */ + png_ptr->row_number++; + + /* See if we are done */ + if (png_ptr->row_number < png_ptr->num_rows) + return; + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* If interlaced, go to next pass */ + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + if (png_ptr->transformations & PNG_INTERLACE) + { + png_ptr->pass++; + } + else + { + /* Loop until we find a non-zero width or height pass */ + do + { + png_ptr->pass++; + if (png_ptr->pass >= 7) + break; + png_ptr->usr_width = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + if (png_ptr->transformations & PNG_INTERLACE) + break; + } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0); + + } + + /* Reset the row above the image for the next pass */ + if (png_ptr->pass < 7) + { + if (png_ptr->prev_row != NULL) + png_memset(png_ptr->prev_row, 0, + (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels* + png_ptr->usr_bit_depth, png_ptr->width)) + 1); + return; + } + } +#endif + + /* If we get here, we've just written the last row, so we need + to flush the compressor */ + do + { + /* Tell the compressor we are done */ + ret = deflate(&png_ptr->zstream, Z_FINISH); + /* Check for an error */ + if (ret == Z_OK) + { + /* Check to see if we need more room */ + if (!(png_ptr->zstream.avail_out)) + { + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + } + else if (ret != Z_STREAM_END) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + } while (ret != Z_STREAM_END); + + /* Write any extra space */ + if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) + { + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size - + png_ptr->zstream.avail_out); + } + + deflateReset(&png_ptr->zstream); + png_ptr->zstream.data_type = Z_BINARY; +} + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED +/* Pick out the correct pixels for the interlace pass. + * The basic idea here is to go through the row with a source + * pointer and a destination pointer (sp and dp), and copy the + * correct pixels for the pass. As the row gets compacted, + * sp will always be >= dp, so we should never overwrite anything. + * See the default: case for the easiest code to understand. + */ +void /* PRIVATE */ +png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) +{ + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + png_debug(1, "in png_do_write_interlace"); + + /* We don't have to do anything on the last pass (6) */ +#ifdef PNG_USELESS_TESTS_SUPPORTED + if (row != NULL && row_info != NULL && pass < 6) +#else + if (pass < 6) +#endif + { + /* Each pixel depth is handled separately */ + switch (row_info->pixel_depth) + { + case 1: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + d = 0; + shift = 7; + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 3); + value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01; + d |= (value << shift); + + if (shift == 0) + { + shift = 7; + *dp++ = (png_byte)d; + d = 0; + } + else + shift--; + + } + if (shift != 7) + *dp = (png_byte)d; + break; + } + case 2: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + shift = 6; + d = 0; + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 2); + value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03; + d |= (value << shift); + + if (shift == 0) + { + shift = 6; + *dp++ = (png_byte)d; + d = 0; + } + else + shift -= 2; + } + if (shift != 6) + *dp = (png_byte)d; + break; + } + case 4: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + shift = 4; + d = 0; + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 1); + value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f; + d |= (value << shift); + + if (shift == 0) + { + shift = 4; + *dp++ = (png_byte)d; + d = 0; + } + else + shift -= 4; + } + if (shift != 4) + *dp = (png_byte)d; + break; + } + default: + { + png_bytep sp; + png_bytep dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + png_size_t pixel_bytes; + + /* Start at the beginning */ + dp = row; + /* Find out how many bytes each pixel takes up */ + pixel_bytes = (row_info->pixel_depth >> 3); + /* Loop through the row, only looking at the pixels that + matter */ + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + /* Find out where the original pixel is */ + sp = row + (png_size_t)i * pixel_bytes; + /* Move the pixel */ + if (dp != sp) + png_memcpy(dp, sp, pixel_bytes); + /* Next pixel */ + dp += pixel_bytes; + } + break; + } + } + /* Set new row width */ + row_info->width = (row_info->width + + png_pass_inc[pass] - 1 - + png_pass_start[pass]) / + png_pass_inc[pass]; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_info->width); + } +} +#endif + +/* This filters the row, chooses which filter to use, if it has not already + * been specified by the application, and then writes the row out with the + * chosen filter. + */ +#define PNG_MAXSUM (((png_uint_32)(-1)) >> 1) +#define PNG_HISHIFT 10 +#define PNG_LOMASK ((png_uint_32)0xffffL) +#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT)) +void /* PRIVATE */ +png_write_find_filter(png_structp png_ptr, png_row_infop row_info) +{ + png_bytep best_row; +#ifdef PNG_WRITE_FILTER_SUPPORTED + png_bytep prev_row, row_buf; + png_uint_32 mins, bpp; + png_byte filter_to_do = png_ptr->do_filter; + png_uint_32 row_bytes = row_info->rowbytes; +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + int num_p_filters = (int)png_ptr->num_prev_filters; +#endif + + png_debug(1, "in png_write_find_filter"); + +#ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS) + { + /* These will never be selected so we need not test them. */ + filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH); + } +#endif + + /* Find out how many bytes offset each pixel is */ + bpp = (row_info->pixel_depth + 7) >> 3; + + prev_row = png_ptr->prev_row; +#endif + best_row = png_ptr->row_buf; +#ifdef PNG_WRITE_FILTER_SUPPORTED + row_buf = best_row; + mins = PNG_MAXSUM; + + /* The prediction method we use is to find which method provides the + * smallest value when summing the absolute values of the distances + * from zero, using anything >= 128 as negative numbers. This is known + * as the "minimum sum of absolute differences" heuristic. Other + * heuristics are the "weighted minimum sum of absolute differences" + * (experimental and can in theory improve compression), and the "zlib + * predictive" method (not implemented yet), which does test compressions + * of lines using different filter methods, and then chooses the + * (series of) filter(s) that give minimum compressed data size (VERY + * computationally expensive). + * + * GRR 980525: consider also + * (1) minimum sum of absolute differences from running average (i.e., + * keep running sum of non-absolute differences & count of bytes) + * [track dispersion, too? restart average if dispersion too large?] + * (1b) minimum sum of absolute differences from sliding average, probably + * with window size <= deflate window (usually 32K) + * (2) minimum sum of squared differences from zero or running average + * (i.e., ~ root-mean-square approach) + */ + + + /* We don't need to test the 'no filter' case if this is the only filter + * that has been chosen, as it doesn't actually do anything to the data. + */ + if ((filter_to_do & PNG_FILTER_NONE) && + filter_to_do != PNG_FILTER_NONE) + { + png_bytep rp; + png_uint_32 sum = 0; + png_uint_32 i; + int v; + + for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) + { + v = *rp; + sum += (v < 128) ? v : 256 - v; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + png_uint_32 sumhi, sumlo; + int j; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */ + + /* Reduce the sum if we match any of the previous rows */ + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + /* Factor in the cost of this filter (this is here for completeness, + * but it makes no sense to have a "cost" for the NONE filter, as + * it has the minimum possible computational cost - none). + */ + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + mins = sum; + } + + /* Sub filter */ + if (filter_to_do == PNG_FILTER_SUB) + /* It's the only filter so no testing is needed */ + { + png_bytep rp, lp, dp; + png_uint_32 i; + for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; + i++, rp++, dp++) + { + *dp = *rp; + } + for (lp = row_buf + 1; i < row_bytes; + i++, rp++, lp++, dp++) + { + *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); + } + best_row = png_ptr->sub_row; + } + + else if (filter_to_do & PNG_FILTER_SUB) + { + png_bytep rp, dp, lp; + png_uint_32 sum = 0, lmins = mins; + png_uint_32 i; + int v; + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + /* We temporarily increase the "minimum sum" by the factor we + * would reduce the sum of this filter, so that we can do the + * early exit comparison without scaling the sum each time. + */ + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; + i++, rp++, dp++) + { + v = *dp = *rp; + + sum += (v < 128) ? v : 256 - v; + } + for (lp = row_buf + 1; i < row_bytes; + i++, rp++, lp++, dp++) + { + v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) + { + sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->sub_row; + } + } + + /* Up filter */ + if (filter_to_do == PNG_FILTER_UP) + { + png_bytep rp, dp, pp; + png_uint_32 i; + + for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, + pp = prev_row + 1; i < row_bytes; + i++, rp++, pp++, dp++) + { + *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); + } + best_row = png_ptr->up_row; + } + + else if (filter_to_do & PNG_FILTER_UP) + { + png_bytep rp, dp, pp; + png_uint_32 sum = 0, lmins = mins; + png_uint_32 i; + int v; + + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, + pp = prev_row + 1; i < row_bytes; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->up_row; + } + } + + /* Avg filter */ + if (filter_to_do == PNG_FILTER_AVG) + { + png_bytep rp, dp, pp, lp; + png_uint_32 i; + for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); + } + for (lp = row_buf + 1; i < row_bytes; i++) + { + *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) + & 0xff); + } + best_row = png_ptr->avg_row; + } + + else if (filter_to_do & PNG_FILTER_AVG) + { + png_bytep rp, dp, pp, lp; + png_uint_32 sum = 0, lmins = mins; + png_uint_32 i; + int v; + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); + + sum += (v < 128) ? v : 256 - v; + } + for (lp = row_buf + 1; i < row_bytes; i++) + { + v = *dp++ = + (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->avg_row; + } + } + + /* Paeth filter */ + if (filter_to_do == PNG_FILTER_PAETH) + { + png_bytep rp, dp, pp, cp, lp; + png_uint_32 i; + for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + } + + for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) + { + int a, b, c, pa, pb, pc, p; + + b = *pp++; + c = *cp++; + a = *lp++; + + p = b - c; + pc = a - c; + +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; + + *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); + } + best_row = png_ptr->paeth_row; + } + + else if (filter_to_do & PNG_FILTER_PAETH) + { + png_bytep rp, dp, pp, cp, lp; + png_uint_32 sum = 0, lmins = mins; + png_uint_32 i; + int v; + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + + sum += (v < 128) ? v : 256 - v; + } + + for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) + { + int a, b, c, pa, pb, pc, p; + + b = *pp++; + c = *cp++; + a = *lp++; + +#ifndef PNG_SLOW_PAETH + p = b - c; + pc = a - c; +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; +#else /* PNG_SLOW_PAETH */ + p = a + b - c; + pa = abs(p - a); + pb = abs(p - b); + pc = abs(p - c); + if (pa <= pb && pa <= pc) + p = a; + else if (pb <= pc) + p = b; + else + p = c; +#endif /* PNG_SLOW_PAETH */ + + v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + best_row = png_ptr->paeth_row; + } + } +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + /* Do the actual writing of the filtered row data from the chosen filter. */ + + png_write_filtered_row(png_ptr, best_row); + +#ifdef PNG_WRITE_FILTER_SUPPORTED +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + /* Save the type of filter we picked this time for future calculations */ + if (png_ptr->num_prev_filters > 0) + { + int j; + for (j = 1; j < num_p_filters; j++) + { + png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1]; + } + png_ptr->prev_filters[j] = best_row[0]; + } +#endif +#endif /* PNG_WRITE_FILTER_SUPPORTED */ +} + + +/* Do the actual writing of a previously filtered row. */ +void /* PRIVATE */ +png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row) +{ + png_debug(1, "in png_write_filtered_row"); + + png_debug1(2, "filter = %d", filtered_row[0]); + /* Set up the zlib input buffer */ + + png_ptr->zstream.next_in = filtered_row; + png_ptr->zstream.avail_in = (uInt)png_ptr->row_info.rowbytes + 1; + /* Repeat until we have compressed all the data */ + do + { + int ret; /* Return of zlib */ + + /* Compress the data */ + ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); + /* Check for compression errors */ + if (ret != Z_OK) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + + /* See if it is time to write another IDAT */ + if (!(png_ptr->zstream.avail_out)) + { + /* Write the IDAT and reset the zlib output buffer */ + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + /* Repeat until all data has been compressed */ + } while (png_ptr->zstream.avail_in); + + /* Swap the current and previous rows */ + if (png_ptr->prev_row != NULL) + { + png_bytep tptr; + + tptr = png_ptr->prev_row; + png_ptr->prev_row = png_ptr->row_buf; + png_ptr->row_buf = tptr; + } + + /* Finish row - updates counters and flushes zlib if last row */ + png_write_finish_row(png_ptr); + +#ifdef PNG_WRITE_FLUSH_SUPPORTED + png_ptr->flush_rows++; + + if (png_ptr->flush_dist > 0 && + png_ptr->flush_rows >= png_ptr->flush_dist) + { + png_write_flush(png_ptr); + } +#endif +} +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/contrib/syslinux-4.02/com32/lib/lmalloc.c b/contrib/syslinux-4.02/com32/lib/lmalloc.c new file mode 100644 index 0000000..a646556 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/lmalloc.c @@ -0,0 +1,57 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2010 Intel Corporation; author: H. Peter Anvin + * + * 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 <com32.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <syslinux/pmapi.h> + +void *lmalloc(size_t size) +{ + void *p; + p = __com32.cs_pm->lmalloc(size); + if (!p) + errno = ENOMEM; + return p; +} + +void *lzalloc(size_t size) +{ + void *p; + p = __com32.cs_pm->lmalloc(size); + if (!p) + errno = ENOMEM; + else + memset(p, 0, size); + return p; +} + +void lfree(void *ptr) +{ + __com32.cs_pm->lfree(ptr); +} diff --git a/contrib/syslinux-4.02/com32/lib/lrand48.c b/contrib/syslinux-4.02/com32/lib/lrand48.c new file mode 100644 index 0000000..ff496ec --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/lrand48.c @@ -0,0 +1,40 @@ +/* + * lrand48.c + */ + +#include <stdlib.h> +#include <stdint.h> + +unsigned short __rand48_seed[3]; + +long jrand48(unsigned short xsubi[3]) +{ + uint64_t x; + + /* The xsubi[] array is littleendian by spec */ + x = (uint64_t) xsubi[0] + + ((uint64_t) xsubi[1] << 16) + ((uint64_t) xsubi[2] << 32); + + x = (0x5deece66dULL * x) + 0xb; + + xsubi[0] = (unsigned short)x; + xsubi[1] = (unsigned short)(x >> 16); + xsubi[2] = (unsigned short)(x >> 32); + + return (long)(int32_t) (x >> 16); +} + +long mrand48(void) +{ + return jrand48(__rand48_seed); +} + +long nrand48(unsigned short xsubi[3]) +{ + return (long)((uint32_t) jrand48(xsubi) >> 1); +} + +long lrand48(void) +{ + return (long)((uint32_t) mrand48() >> 1); +} diff --git a/contrib/syslinux-4.02/com32/lib/lstrdup.c b/contrib/syslinux-4.02/com32/lib/lstrdup.c new file mode 100644 index 0000000..d11efe7 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/lstrdup.c @@ -0,0 +1,18 @@ +/* + * lstrdup.c + */ + +#include <string.h> +#include <stdlib.h> +#include <com32.h> + +char *lstrdup(const char *s) +{ + int l = strlen(s) + 1; + char *d = lmalloc(l); + + if (d) + memcpy(d, s, l); + + return d; +} diff --git a/contrib/syslinux-4.02/com32/lib/malloc.c b/contrib/syslinux-4.02/com32/lib/malloc.c new file mode 100644 index 0000000..ec103ab --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/malloc.c @@ -0,0 +1,156 @@ +/* + * malloc.c + * + * Very simple linked-list based malloc()/free(). + */ + +#include <stdlib.h> +#include <string.h> +#include <com32.h> +#include <syslinux/memscan.h> +#include "init.h" +#include "malloc.h" + +struct free_arena_header __malloc_head = { + { + ARENA_TYPE_HEAD, + 0, + &__malloc_head, + &__malloc_head, + }, + &__malloc_head, + &__malloc_head +}; + +/* This is extern so it can be overridden by the user application */ +extern size_t __stack_size; +extern void *__mem_end; /* Produced after argv parsing */ + +static inline size_t sp(void) +{ + size_t sp; + asm volatile ("movl %%esp,%0":"=rm" (sp)); + return sp; +} + +#define E820_MEM_MAX 0xfff00000 /* 4 GB - 1 MB */ + +static int consider_memory_area(void *dummy, addr_t start, + addr_t len, bool valid) +{ + struct free_arena_header *fp; + addr_t end; + + (void)dummy; + + if (valid && start < E820_MEM_MAX) { + if (len > E820_MEM_MAX - start) + len = E820_MEM_MAX - start; + + end = start + len; + + if (end > __com32.cs_memsize) { + if (start <= __com32.cs_memsize) { + start = __com32.cs_memsize; + len = end - start; + } + + if (len >= 2 * sizeof(struct arena_header)) { + fp = (struct free_arena_header *)start; + fp->a.size = len; + __inject_free_block(fp); + } + } + } + + return 0; +} + +static void __constructor init_memory_arena(void) +{ + struct free_arena_header *fp; + size_t start, total_space; + + start = (size_t) ARENA_ALIGN_UP(__mem_end); + total_space = sp() - start; + + if (__stack_size == 0 || __stack_size > total_space >> 1) + __stack_size = total_space >> 1; /* Half for the stack, half for the heap... */ + + if (total_space < __stack_size + 4 * sizeof(struct arena_header)) + __stack_size = total_space - 4 * sizeof(struct arena_header); + + fp = (struct free_arena_header *)start; + fp->a.size = total_space - __stack_size; + + __inject_free_block(fp); + + /* Scan the memory map to look for other suitable regions */ + if (!__com32.cs_memsize) + return; /* Old Syslinux core, can't do this... */ + + syslinux_scan_memory(consider_memory_area, NULL); +} + +static void *__malloc_from_block(struct free_arena_header *fp, size_t size) +{ + size_t fsize; + struct free_arena_header *nfp, *na; + + fsize = fp->a.size; + + /* We need the 2* to account for the larger requirements of a free block */ + if (fsize >= size + 2 * sizeof(struct arena_header)) { + /* Bigger block than required -- split block */ + nfp = (struct free_arena_header *)((char *)fp + size); + na = fp->a.next; + + nfp->a.type = ARENA_TYPE_FREE; + nfp->a.size = fsize - size; + fp->a.type = ARENA_TYPE_USED; + fp->a.size = size; + + /* Insert into all-block chain */ + nfp->a.prev = fp; + nfp->a.next = na; + na->a.prev = nfp; + fp->a.next = nfp; + + /* Replace current block on free chain */ + nfp->next_free = fp->next_free; + nfp->prev_free = fp->prev_free; + fp->next_free->prev_free = nfp; + fp->prev_free->next_free = nfp; + } else { + /* Allocate the whole block */ + fp->a.type = ARENA_TYPE_USED; + + /* Remove from free chain */ + fp->next_free->prev_free = fp->prev_free; + fp->prev_free->next_free = fp->next_free; + } + + return (void *)(&fp->a + 1); +} + +void *malloc(size_t size) +{ + struct free_arena_header *fp; + + if (size == 0) + return NULL; + + /* Add the obligatory arena header, and round up */ + size = (size + 2 * sizeof(struct arena_header) - 1) & ARENA_SIZE_MASK; + + for (fp = __malloc_head.next_free; fp->a.type != ARENA_TYPE_HEAD; + fp = fp->next_free) { + if (fp->a.size >= size) { + /* Found fit -- allocate out of this block */ + return __malloc_from_block(fp, size); + } + } + + /* Nothing found... need to request a block from the kernel */ + return NULL; /* No kernel to get stuff from */ +} diff --git a/contrib/syslinux-4.02/com32/lib/malloc.h b/contrib/syslinux-4.02/com32/lib/malloc.h new file mode 100644 index 0000000..bf75432 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/malloc.h @@ -0,0 +1,55 @@ +/* + * malloc.h + * + * Internals for the memory allocator + */ + +#include <stdint.h> +#include <stddef.h> + +/* + * This is the minimum chunk size we will ask the kernel for; this should + * be a multiple of the page size on all architectures. + */ +#define MALLOC_CHUNK_SIZE 65536 +#define MALLOC_CHUNK_MASK (MALLOC_CHUNK_SIZE-1) + +/* + * This structure should be a power of two. This becomes the + * alignment unit. + */ +struct free_arena_header; + +struct arena_header { + size_t type; + size_t size; /* Also gives the location of the next entry */ + struct free_arena_header *next, *prev; +}; + +#ifdef DEBUG_MALLOC +#define ARENA_TYPE_USED 0x64e69c70 +#define ARENA_TYPE_FREE 0x012d610a +#define ARENA_TYPE_HEAD 0x971676b5 +#define ARENA_TYPE_DEAD 0xeeeeeeee +#else +#define ARENA_TYPE_USED 0 +#define ARENA_TYPE_FREE 1 +#define ARENA_TYPE_HEAD 2 +#endif + +#define ARENA_SIZE_MASK (~(uintptr_t)(sizeof(struct arena_header)-1)) + +#define ARENA_ALIGN_UP(p) ((char *)(((uintptr_t)(p) + ~ARENA_SIZE_MASK) & ARENA_SIZE_MASK)) +#define ARENA_ALIGN_DOWN(p) ((char *)((uintptr_t)(p) & ARENA_SIZE_MASK)) + +/* + * This structure should be no more than twice the size of the + * previous structure. + */ +struct free_arena_header { + struct arena_header a; + struct free_arena_header *next_free, *prev_free; +}; + +extern struct free_arena_header __malloc_head; +void __inject_free_block(struct free_arena_header *ah); diff --git a/contrib/syslinux-4.02/com32/lib/math/pow.S b/contrib/syslinux-4.02/com32/lib/math/pow.S new file mode 100644 index 0000000..56f504a --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/math/pow.S @@ -0,0 +1,25 @@ +/* + * pow.S + * + * double pow(double base, double exponent) + */ + + .text + .globl pow + .type pow,@function +pow: + fldl 12(%esp) + fldl 4(%esp) + fyl2x + fld %st(0) + frndint + fsubr %st,%st(1) + fxch %st(1) + f2xm1 + fld1 + faddp %st,%st(1) + fscale + fstp %st(1) + ret + + .size pow,.-pow diff --git a/contrib/syslinux-4.02/com32/lib/math/strtod.c b/contrib/syslinux-4.02/com32/lib/math/strtod.c new file mode 100644 index 0000000..f99531a --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/math/strtod.c @@ -0,0 +1,156 @@ +/* + * strtod.c + * + * Convert string to double + * + * Copyright (C) 2002 Michael Ringgaard. All rights reserved. + * Copyright 2006-2008 H. Peter Anvin - All Rights Reserved + * + * 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 project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT OWNER 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. + */ + +#include <errno.h> +#include <ctype.h> +#include <stdlib.h> +#include <math.h> + +static inline int is_real(double x) +{ + const double Inf = 1.0 / 0.0; + return (x < Inf) && (x >= -Inf); +} + +double strtod(const char *str, char **endptr) +{ + double number; + int exponent; + int negative; + char *p = (char *)str; + double p10; + int n; + int num_digits; + int num_decimals; + const double Inf = 1.0 / 0.0; + + // Skip leading whitespace + while (isspace(*p)) + p++; + + // Handle optional sign + negative = 0; + switch (*p) { + case '-': + negative = 1; // Fall through to increment position + case '+': + p++; + } + + number = 0.; + exponent = 0; + num_digits = 0; + num_decimals = 0; + + // Process string of digits + while (isdigit(*p)) { + number = number * 10. + (*p - '0'); + p++; + num_digits++; + } + + // Process decimal part + if (*p == '.') { + p++; + + while (isdigit(*p)) { + number = number * 10. + (*p - '0'); + p++; + num_digits++; + num_decimals++; + } + + exponent -= num_decimals; + } + + if (num_digits == 0) { + errno = ERANGE; + return 0.0; + } + // Correct for sign + if (negative) + number = -number; + + // Process an exponent string + if (*p == 'e' || *p == 'E') { + // Handle optional sign + negative = 0; + switch (*++p) { + case '-': + negative = 1; // Fall through to increment pos + case '+': + p++; + } + + // Process string of digits + n = 0; + while (isdigit(*p)) { + n = n * 10 + (*p - '0'); + p++; + } + + if (negative) + exponent -= n; + else + exponent += n; + } + + if (exponent < __DBL_MIN_EXP__ || exponent > __DBL_MAX_EXP__) { + errno = ERANGE; + return Inf; + } + // Scale the result + p10 = 10.; + n = exponent; + if (n < 0) + n = -n; + while (n) { + if (n & 1) { + if (exponent < 0) + number /= p10; + else + number *= p10; + } + n >>= 1; + p10 *= p10; + } + + if (!is_real(number)) + errno = ERANGE; + if (endptr) + *endptr = p; + + return number; +} diff --git a/contrib/syslinux-4.02/com32/lib/memccpy.c b/contrib/syslinux-4.02/com32/lib/memccpy.c new file mode 100644 index 0000000..7fd9df6 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/memccpy.c @@ -0,0 +1,23 @@ +/* + * memccpy.c + * + * memccpy() + */ + +#include <stddef.h> +#include <string.h> + +void *memccpy(void *dst, const void *src, int c, size_t n) +{ + char *q = dst; + const char *p = src; + char ch; + + while (n--) { + *q++ = ch = *p++; + if (ch == (char)c) + return q; + } + + return NULL; /* No instance of "c" found */ +} diff --git a/contrib/syslinux-4.02/com32/lib/memchr.c b/contrib/syslinux-4.02/com32/lib/memchr.c new file mode 100644 index 0000000..d641c86 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/memchr.c @@ -0,0 +1,18 @@ +/* + * memchr.c + */ + +#include <stddef.h> +#include <string.h> + +void *memchr(const void *s, int c, size_t n) +{ + const unsigned char *sp = s; + + while (n--) { + if (*sp == (unsigned char)c) + return (void *)sp; + } + + return NULL; +} diff --git a/contrib/syslinux-4.02/com32/lib/memcmp.c b/contrib/syslinux-4.02/com32/lib/memcmp.c new file mode 100644 index 0000000..a9e642b --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/memcmp.c @@ -0,0 +1,19 @@ +/* + * memcmp.c + */ + +#include <string.h> + +int memcmp(const void *s1, const void *s2, size_t n) +{ + const unsigned char *c1 = s1, *c2 = s2; + int d = 0; + + while (n--) { + d = (int)*c1++ - (int)*c2++; + if (d) + break; + } + + return d; +} diff --git a/contrib/syslinux-4.02/com32/lib/memcpy.S b/contrib/syslinux-4.02/com32/lib/memcpy.S new file mode 100644 index 0000000..6b986a0 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/memcpy.S @@ -0,0 +1,86 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 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. + * + * ----------------------------------------------------------------------- */ + +/* + * memcpy.S + * + * Reasonably efficient memcpy, using aligned transfers at least + * for the destination operand. + */ + + .text + .globl memcpy + .type memcpy, @function +memcpy: + jecxz 1f + + pushl %esi + pushl %edi + pushl %eax /* Return value */ + + movl %eax,%edi + movl %edx,%esi + + /* Initial alignment */ + movl %edi,%edx + shrl $1,%edx + jnc 11f + movsb + decl %ecx +11: + movb %cl,%al + cmpl $2,%ecx + jb 13f + + shrl $1,%edx + jnc 12f + movsw + subl $2,%ecx +12: + /* Bulk transfer */ + movb %cl,%al + shrl $2,%ecx + rep; movsl + + /* Final alignment */ + testb $2,%al + jz 14f + movsw +13: +14: + testb $1,%al + jz 15f + movsb +15: + + popl %eax /* Return value */ + popl %edi + popl %esi +1: + ret + + .size memcpy, .-memcpy diff --git a/contrib/syslinux-4.02/com32/lib/memmem.c b/contrib/syslinux-4.02/com32/lib/memmem.c new file mode 100644 index 0000000..8558a80 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/memmem.c @@ -0,0 +1,44 @@ +/* + * memmem.c + * + * Find a byte string inside a longer byte string + * + * This uses the "Not So Naive" algorithm, a very simple but + * usually effective algorithm, see: + * + * http://www-igm.univ-mlv.fr/~lecroq/string/ + */ + +#include <string.h> + +void *memmem(const void *haystack, size_t n, const void *needle, size_t m) +{ + const unsigned char *y = (const unsigned char *)haystack; + const unsigned char *x = (const unsigned char *)needle; + + size_t j, k, l; + + if (m > n) + return NULL; + + if (x[0] == x[1]) { + k = 2; + l = 1; + } else { + k = 1; + l = 2; + } + + j = 0; + while (j <= n - m) { + if (x[1] != y[j + 1]) { + j += k; + } else { + if (!memcmp(x + 2, y + j + 2, m - 2) && x[0] == y[j]) + return (void *)&y[j]; + j += l; + } + } + + return NULL; +} diff --git a/contrib/syslinux-4.02/com32/lib/memmove.S b/contrib/syslinux-4.02/com32/lib/memmove.S new file mode 100644 index 0000000..e97299f --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/memmove.S @@ -0,0 +1,146 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2008 H. Peter Anvin - All Rights Reserved + * Copyright 2010 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * memmove.S + * + * Reasonably efficient memmove, using aligned transfers at least + * for the destination operand. + */ + + .globl memmove + .type memmove,@function + .text +memmove: + jecxz 4f + + pushl %esi + pushl %edi + pushl %eax /* Return value */ + + movl %eax,%edi + movl %edx,%esi + + cmpl %edi,%esi + jb 2f + + /* source >= dest, forwards move */ + + /* Initial alignment */ +1: + movl %edi,%edx + shrl $1,%edx + jnc 11f + movsb + decl %ecx +11: + movb %cl,%al + cmpl $2,%ecx + jb 13f + + shrl $1,%edx + jnc 12f + movsw + subl $2,%ecx +12: + /* Bulk transfer */ + movb %cl,%al + shrl $2,%ecx + rep; movsl + + /* Final alignment */ + testb $2,%al + jz 14f + movsw +13: +14: + testb $1,%al + jz 15f + movsb +15: + /* Common exit stub */ +3: + popl %eax /* Return value */ + popl %edi + popl %esi +4: + ret + + +2: + /* source < dest, backwards move if overlap */ + leal -1(%ecx,%esi),%eax + cmpl %eax,%edi + ja 1b /* No overlap, after all... */ + + std + leal -1(%ecx,%edi),%edi + movl %eax,%esi + + /* Initial alignment */ + movl %edi,%edx + shrl $1,%edx + jc 21f + movsb + decl %ecx +21: + decl %esi + decl %edi + movb %cl,%al + cmpl $2,%ecx + jb 23f + shrl $1,%edx + jc 22f + movsw + subl $2,%ecx +22: + /* Bulk transfer */ + subl $2,%esi + subl $2,%edi + movb %cl,%al + shrl $2,%ecx + rep; movsl + + /* Final alignment */ + addl $2,%esi + addl $2,%edi + testb $2,%al + jz 24f + movsw +23: +24: + incl %esi + incl %edi + testb $1,%al + jz 25f + movsb +25: + cld + jmp 3b + + .size memmove, .-memmove diff --git a/contrib/syslinux-4.02/com32/lib/mempcpy.S b/contrib/syslinux-4.02/com32/lib/mempcpy.S new file mode 100644 index 0000000..cad7b98 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/mempcpy.S @@ -0,0 +1,85 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 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. + * + * ----------------------------------------------------------------------- */ + +/* + * mempcpy.S + * + * Reasonably efficient mempcpy, using aligned transfers at least + * for the destination operand. + */ + + .text + .globl mempcpy + .type mempcpy, @function +mempcpy: + jecxz 1f + + pushl %esi + pushl %edi + + movl %eax,%edi + movl %edx,%esi + + /* Initial alignment */ + movl %edi,%edx + shrl $1,%edx + jnc 11f + movsb + decl %ecx +11: + movb %cl,%al + cmpl $2,%ecx + jb 13f + + shrl $1,%edx + jnc 12f + movsw + subl $2,%ecx +12: + /* Bulk transfer */ + movb %cl,%al + shrl $2,%ecx + rep; movsl + + /* Final alignment */ + testb $2,%al + jz 14f + movsw +13: +14: + testb $1,%al + jz 15f + movsb +15: + + movl %edi,%eax /* Return value */ + popl %edi + popl %esi +1: + ret + + .size mempcpy, .-mempcpy diff --git a/contrib/syslinux-4.02/com32/lib/memset.S b/contrib/syslinux-4.02/com32/lib/memset.S new file mode 100644 index 0000000..e641415 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/memset.S @@ -0,0 +1,86 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 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. + * + * ----------------------------------------------------------------------- */ + +/* + * memset.S + * + * Reasonably efficient memset, using aligned transfers at least + * for the destination operand. + */ + + .globl memset + .type memset,@function + .text +memset: + jecxz 6f + + pushl %edi + pushl %ebx + pushl %eax /* Return value */ + + movl %eax,%edi + movb %dl,%dh + movzwl %dx,%eax + shll $16,%edx + orl %edx,%eax + + /* Initial alignment */ + movl %edi,%edx + shrl $1,%edx + jnc 1f + stosb + decl %ecx +1: + movb %cl,%bl + cmpl $2,%ecx + jb 3f + shrl $1,%edx + jnc 2f + stosw + subl $2,%ecx +2: + /* Bulk transfer */ + movb %cl,%bl + shrl $2,%ecx + rep; stosl + + testb $2,%bl + jz 4f + stosw +3: +4: + testb $1,%bl + jz 5f + stosb +5: + popl %eax /* Return value */ + popl %ebx + popl %edi +6: + ret + + .size memset, .-memset diff --git a/contrib/syslinux-4.02/com32/lib/memswap.c b/contrib/syslinux-4.02/com32/lib/memswap.c new file mode 100644 index 0000000..53813ab --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/memswap.c @@ -0,0 +1,24 @@ +/* + * memswap() + * + * Swaps the contents of two nonoverlapping memory areas. + * This really could be done faster... + */ + +#include <string.h> + +void memswap(void *m1, void *m2, size_t n) +{ + char *p = m1; + char *q = m2; + char tmp; + + while (n--) { + tmp = *p; + *p = *q; + *q = tmp; + + p++; + q++; + } +} diff --git a/contrib/syslinux-4.02/com32/lib/onexit.c b/contrib/syslinux-4.02/com32/lib/onexit.c new file mode 100644 index 0000000..d409e82 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/onexit.c @@ -0,0 +1,39 @@ +/* + * onexit.c + */ + +#include <stdlib.h> +#include <unistd.h> +#include "atexit.h" + +extern __noreturn(*__exit_handler) (int); +static struct atexit *__atexit_list; + +static __noreturn on_exit_exit(int rv) +{ + struct atexit *ap; + + for (ap = __atexit_list; ap; ap = ap->next) { + ap->fctn(rv, ap->arg); /* This assumes extra args are harmless */ + } + + _exit(rv); +} + +int on_exit(void (*fctn) (int, void *), void *arg) +{ + struct atexit *as = malloc(sizeof(struct atexit)); + + if (!as) + return -1; + + as->fctn = fctn; + as->arg = arg; + + as->next = __atexit_list; + __atexit_list = as; + + __exit_handler = on_exit_exit; + + return 0; +} diff --git a/contrib/syslinux-4.02/com32/lib/pci/bios.c b/contrib/syslinux-4.02/com32/lib/pci/bios.c new file mode 100644 index 0000000..b3c2c57 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/pci/bios.c @@ -0,0 +1,17 @@ +#include <com32.h> +#include <string.h> +#include "pci/pci.h" + +uint32_t __pci_read_write_bios(uint32_t call, uint32_t v, pciaddr_t a) +{ + com32sys_t rs; + memset(&rs, 0, sizeof rs); + rs.eax.w[0] = call; + rs.ebx.w[0] = a >> 8; /* bus:device:function */ + rs.edi.b[0] = a; /* address:reg */ + rs.ecx.l = v; + rs.eflags.l = EFLAGS_CF; + __intcall(0x1a, &rs, &rs); + + return (rs.eflags.l & EFLAGS_CF) ? ~(uint32_t) 0 : rs.ecx.l; +} diff --git a/contrib/syslinux-4.02/com32/lib/pci/cfgtype.c b/contrib/syslinux-4.02/com32/lib/pci/cfgtype.c new file mode 100644 index 0000000..896f7e5 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/pci/cfgtype.c @@ -0,0 +1,89 @@ +#include "pci/pci.h" +#include <com32.h> +#include <string.h> + +enum pci_config_type __pci_cfg_type; + +static int type1_ok(void) +{ + uint32_t oldcf8, newcf8; + + /* Test for Configuration Method #1 */ + + /* Note: XFree86 writes ~0 and expects to read back 0x80fffffc. Linux + does this less severe test; go with Linux. */ + + cli(); + outb(1, 0xcfb); /* For old Intel chipsets */ + oldcf8 = inl(0xcf8); + outl(0x80000000, 0xcf8); + newcf8 = inl(0xcf8); + outl(oldcf8, 0xcf8); + sti(); + + return newcf8 == 0x80000000; +} + +static int type2_ok(void) +{ + uint8_t oldcf8, oldcfa; + uint8_t cf8, cfa; + + /* Test for Configuration Method #2 */ + + /* CM#2 is hard to probe for, but let's do our best... */ + + cli(); + outb(0, 0xcfb); /* For old Intel chipsets */ + oldcf8 = inb(0xcf8); + outb(0, 0xcf8); + oldcfa = inb(0xcfa); + outb(0, 0xcfa); + + cf8 = inb(0xcf8); + cfa = inb(0xcfa); + + outb(oldcf8, 0xcf8); + outb(oldcfa, 0xcfa); + sti(); + + return cf8 == 0 && cfa == 0; +} + +int pci_set_config_type(enum pci_config_type type) +{ + static const com32sys_t ireg = { + .eax.l = 0xb101, + .edi.l = 0, + .eflags.l = EFLAGS_CF, + }; + com32sys_t oreg; + + if (type == PCI_CFG_AUTO) { + type = PCI_CFG_NONE; + + /* Try to detect PCI BIOS */ + __intcall(0x1a, &ireg, &oreg); + + if (!(oreg.eflags.l & EFLAGS_CF) && + oreg.eax.b[1] == 0 && oreg.edx.l == 0x20494250) { + /* PCI BIOS present. Use direct access if we know how to do it. */ + + if ((oreg.eax.b[0] & 1) && type1_ok()) + type = PCI_CFG_TYPE1; + else if ((oreg.eax.b[0] & 2) && type2_ok()) + type = PCI_CFG_TYPE2; + else + type = PCI_CFG_BIOS; /* Use BIOS calls as fallback */ + + } else if (type1_ok()) { + type = PCI_CFG_TYPE1; + } else if (type2_ok()) { + type = PCI_CFG_TYPE2; + } else { + type = PCI_CFG_NONE; /* Badness... */ + } + } + + return (__pci_cfg_type = type); +} diff --git a/contrib/syslinux-4.02/com32/lib/pci/pci.h b/contrib/syslinux-4.02/com32/lib/pci/pci.h new file mode 100644 index 0000000..8d81b0e --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/pci/pci.h @@ -0,0 +1,15 @@ +/* + * pci/pci.h + * + * Common internal header file + */ + +#ifndef PCI_PCI_H + +#include <sys/pci.h> +#include <sys/cpu.h> + +extern enum pci_config_type __pci_cfg_type; +extern uint32_t __pci_read_write_bios(uint32_t call, uint32_t v, pciaddr_t a); + +#endif /* PCI_PCI_H */ diff --git a/contrib/syslinux-4.02/com32/lib/pci/readb.c b/contrib/syslinux-4.02/com32/lib/pci/readb.c new file mode 100644 index 0000000..c0c4172 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/pci/readb.c @@ -0,0 +1,4 @@ +#define TYPE uint8_t +#define BWL(x) x ## b +#define BIOSCALL 0xb108 +#include "pci/readx.c" diff --git a/contrib/syslinux-4.02/com32/lib/pci/readl.c b/contrib/syslinux-4.02/com32/lib/pci/readl.c new file mode 100644 index 0000000..fbef3a7 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/pci/readl.c @@ -0,0 +1,4 @@ +#define TYPE uint32_t +#define BWL(x) x ## l +#define BIOSCALL 0xb10a +#include "pci/readx.c" diff --git a/contrib/syslinux-4.02/com32/lib/pci/readw.c b/contrib/syslinux-4.02/com32/lib/pci/readw.c new file mode 100644 index 0000000..86604c4 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/pci/readw.c @@ -0,0 +1,4 @@ +#define TYPE uint16_t +#define BWL(x) x ## w +#define BIOSCALL 0xb109 +#include "pci/readx.c" diff --git a/contrib/syslinux-4.02/com32/lib/pci/readx.c b/contrib/syslinux-4.02/com32/lib/pci/readx.c new file mode 100644 index 0000000..ed66d5b --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/pci/readx.c @@ -0,0 +1,51 @@ +#include "pci/pci.h" + +TYPE BWL(pci_read) (pciaddr_t a) +{ + TYPE r; + + for (;;) { + switch (__pci_cfg_type) { + case PCI_CFG_AUTO: + pci_set_config_type(PCI_CFG_AUTO); + break; /* Try again */ + + case PCI_CFG_TYPE1: + { + uint32_t oldcf8; + cli(); + oldcf8 = inl(0xcf8); + outl(a, 0xcf8); + r = BWL(in) (0xcfc + (a & 3)); + outl(oldcf8, 0xcf8); + sti(); + } + return r; + + case PCI_CFG_TYPE2: + { + uint8_t oldcf8, oldcfa; + + if (a & (0x10 << 11)) + return (TYPE) ~ 0; /* Device 16-31 not supported */ + + cli(); + oldcf8 = inb(0xcf8); + oldcfa = inb(0xcfa); + outb(0xf0 + ((a >> (8 - 1)) & 0x0e), 0xcf8); + outb(a >> 16, 0xcfa); + r = BWL(in) (0xc000 + ((a >> (11 - 8)) & 0xf00) + (a & 0xff)); + outb(oldcf8, 0xcf8); + outb(oldcfa, 0xcfa); + sti(); + } + return r; + + case PCI_CFG_BIOS: + return (TYPE) __pci_read_write_bios(BIOSCALL, 0, a); + + default: + return (TYPE) ~ 0; + } + } +} diff --git a/contrib/syslinux-4.02/com32/lib/pci/scan.c b/contrib/syslinux-4.02/com32/lib/pci/scan.c new file mode 100644 index 0000000..2577b32 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/pci/scan.c @@ -0,0 +1,751 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2006-2007 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. + * + * ----------------------------------------------------------------------- */ + +/* + * pci.c + * + * A module to extract pci informations + */ + +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <console.h> +#include <sys/pci.h> +#include <com32.h> +#include <stdbool.h> +#include <syslinux/zio.h> + +#ifdef DEBUG +# define dprintf printf +#else +# define dprintf(...) ((void)0) +#endif + +#define MAX_LINE 512 + +/* searching the next char that is not a space */ +static char *skipspace(char *p) +{ + while (*p && *p <= ' ') + p++; + + return p; +} + +/* removing any \n found in a string */ +static void remove_eol(char *string) +{ + int j = strlen(string); + int i = 0; + for (i = 0; i < j; i++) + if (string[i] == '\n') + string[i] = 0; +} + +/* converting a hexa string into its numerical value */ +static int hex_to_int(char *hexa) +{ + return strtoul(hexa, NULL, 16); +} + +/* Replace char 'old' by char 'new' in source */ +void chr_replace(char *source, char old, char new) +{ + while (*source) { + source++; + if (source[0] == old) source[0]=new; + } +} + +/* 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_pcimap(struct pci_domain *domain, + char *modules_pcimap_path) +{ + char line[MAX_LINE]; + char module_name[21]; // the module name field is 21 char long + char delims[]=" "; // colums are separated by spaces + char vendor_id[16]; + char product_id[16]; + char sub_vendor_id[16]; + char sub_product_id[16]; + FILE *f; + struct pci_device *dev=NULL; + + /* Intializing the linux_kernel_module 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; + } + for (int i=0;i<MAX_KERNEL_MODULES_PER_PCI_DEVICE;i++) { + if (strlen(dev->dev_info->linux_kernel_module[i])==0) + strlcpy(dev->dev_info->linux_kernel_module[i], "unknown",7); + } + } + + /* Opening the modules.pcimap (of a linux kernel) from the boot device */ + f=zfopen(modules_pcimap_path, "r"); + if (!f) + return -ENOMODULESPCIMAP; + + strcpy(vendor_id,"0000"); + strcpy(product_id,"0000"); + strcpy(sub_product_id,"0000"); + strcpy(sub_vendor_id,"0000"); + + /* for each line we found in the modules.pcimap */ + while ( fgets(line, sizeof line, f) ) { + /* skipping unecessary lines */ + if ((line[0] == '#') || (line[0] == ' ') || (line[0] == 10)) + continue; + + char *result = NULL; + int field=0; + + /* looking for the next field */ + result = strtok(line, delims); + while( result != NULL ) { + /* if the column is larger than 1 char */ + /* multiple spaces generates some empty fields */ + if (strlen(result)>1) { + switch (field) { + /* About case 0, the kernel module name is featuring '_' or '-' + * in the module name whereas modules.alias is only using '_'. + * To avoid kernel modules duplication, let's rename all '-' in '_' + * to match what modules.alias provides */ + case 0:chr_replace(result,'-','_');strcpy(module_name,result); break; + case 1:strcpy(vendor_id,result); break; + case 2:strcpy(product_id,result); break; + case 3:strcpy(sub_vendor_id,result); break; + case 4:strcpy(sub_product_id,result); break; + } + field++; + } + /* 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 (int_vendor_id == dev->vendor && + int_product_id == dev->product && + (int_sub_product_id & dev->sub_product) + == dev->sub_product && + (int_sub_vendor_id & dev->sub_vendor) + == dev->sub_vendor) { + bool found=false; + + /* Scan all known kernel modules for this pci device */ + for (int i=0; i<dev->dev_info->linux_kernel_module_count; i++) { + + /* Try to detect if we already knew the same kernel module*/ + if (strstr(dev->dev_info->linux_kernel_module[i], module_name)) { + found=true; + break; + } + } + /* If we don't have this kernel module, let's add it */ + if (!found) { + 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 = zfopen(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, char *pciids_path) +{ + char line[MAX_LINE]; + char vendor[PCI_VENDOR_NAME_SIZE]; + char vendor_id[5]; + 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 */ + 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->vendor_name, "unknown", 7); + strlcpy(dev->dev_info->product_name, "unknown", 7); + } + + /* Opening the pci.ids from the boot device */ + f = zfopen(pciids_path, "r"); + if (!f) + return -ENOPCIIDS; + + 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)) { + /* Skipping uncessary lines */ + 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') { + + /* the 4 first chars are the vendor_id */ + strlcpy(vendor_id, line, 4); + + /* the vendor name is the next field */ + vendor_id[4] = 0; + strlcpy(vendor, skipspace(strstr(line, " ")), + PCI_VENDOR_NAME_SIZE - 1); + + remove_eol(vendor); + /* init product_id, sub_product and sub_vendor */ + strlcpy(product_id, "0000", 4); + strlcpy(sub_product_id, "0000", 4); + strlcpy(sub_vendor_id, "0000", 4); + + /* 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 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 + * 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, " ")), + PCI_PRODUCT_NAME_SIZE - 1); + remove_eol(product); + + /* the product id is first field */ + strlcpy(product_id, &line[1], 4); + product_id[4] = 0; + + /* init sub_product and sub_vendor */ + 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 (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 + * 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, " ")), + 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 */ + strlcpy(sub_vendor_id, &line[2], 4); + sub_vendor_id[4] = 0; + + /* the sub_vendor id is second field */ + 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 (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); + } + } + } + } + fclose(f); + return 0; +} + +/* searching if any pcidevice match our query */ +struct match *find_pci_device(const struct pci_domain *domain, + struct match *list) +{ + uint32_t did, sid; + struct match *m; + const struct pci_device *dev; + + /* for all matches we have to search */ + for (m = list; m; m = m->next) { + /* for each pci device we know */ + for_each_pci_func(dev, domain) { + /* sid & did are the easiest way to compare devices */ + /* they are made of vendor/product subvendor/subproduct ids */ + sid = dev->svid_sdid; + did = dev->vid_did; + /* if the current device match */ + if (((did ^ m->did) & m->did_mask) == 0 && + ((sid ^ m->sid) & m->sid_mask) == 0 && + dev->revision >= m->rid_min && dev->revision <= m->rid_max) { + dprintf + ("PCI Match: Vendor=%04x Product=%04x Sub_vendor=%04x Sub_Product=%04x Release=%02x\n", + dev->vendor, dev->product, dev->sub_vendor, + dev->sub_product, dev->revision); + /* returning the matched pci device */ + return m; + } + } + } + return NULL; +} + +/* scanning the pci bus to find pci devices */ +struct pci_domain *pci_scan(void) +{ + struct pci_domain *domain = NULL; + struct pci_bus *bus = NULL; + struct pci_slot *slot = NULL; + struct pci_device *func = NULL; + unsigned int nbus, ndev, nfunc, maxfunc; + uint32_t did, sid, rcid; + uint8_t hdrtype; + pciaddr_t a; + int cfgtype; + + cfgtype = pci_set_config_type(PCI_CFG_AUTO); + + dprintf("PCI configuration type %d\n", cfgtype); + + if (cfgtype == PCI_CFG_NONE) + return NULL; + + dprintf("Scanning PCI Buses\n"); + + for (nbus = 0; nbus < MAX_PCI_BUSES; nbus++) { + dprintf("Probing bus 0x%02x... \n", nbus); + bus = NULL; + + for (ndev = 0; ndev < MAX_PCI_DEVICES; ndev++) { + maxfunc = 1; /* Assume a single-function device */ + slot = NULL; + + for (nfunc = 0; nfunc < maxfunc; nfunc++) { + a = pci_mkaddr(nbus, ndev, nfunc, 0); + did = pci_readl(a); + + if (did == 0xffffffff || did == 0xffff0000 || + did == 0x0000ffff || did == 0x00000000) + continue; + + hdrtype = pci_readb(a + 0x0e); + + if (hdrtype & 0x80) + maxfunc = MAX_PCI_FUNC; /* Multifunction device */ + + rcid = pci_readl(a + 0x08); + sid = pci_readl(a + 0x2c); + + if (!domain) { + domain = zalloc(sizeof *domain); + if (!domain) + goto bail; + } + if (!bus) { + bus = zalloc(sizeof *bus); + if (!bus) + goto bail; + domain->bus[nbus] = bus; + } + if (!slot) { + slot = zalloc(sizeof *slot); + if (!slot) + goto bail; + bus->slot[ndev] = slot; + } + func = zalloc(sizeof *func); + if (!func) + goto bail; + + slot->func[nfunc] = func; + + func->vid_did = did; + func->svid_sdid = sid; + func->rid_class = rcid; + + dprintf + ("Scanning: BUS %02x DID %08x (%04x:%04x) SID %08x RID %02x\n", + nbus, did, did >> 16, (did << 16) >> 16, sid, rcid & 0xff); + } + } + } + + return domain; + +bail: + free_pci_domain(domain); + return NULL; +} + +/* gathering additional configuration*/ +void gather_additional_pci_config(struct pci_domain *domain) +{ + struct pci_device *dev; + pciaddr_t pci_addr; + int cfgtype; + + cfgtype = pci_set_config_type(PCI_CFG_AUTO); + if (cfgtype == PCI_CFG_NONE) + return; + + for_each_pci_func3(dev, domain, pci_addr) { + if (!dev->dev_info) { + dev->dev_info = zalloc(sizeof *dev->dev_info); + if (!dev->dev_info) { + return; + } + } + dev->dev_info->irq = pci_readb(pci_addr + 0x3c); + dev->dev_info->latency = pci_readb(pci_addr + 0x0d); + } +} + +void free_pci_domain(struct pci_domain *domain) +{ + struct pci_bus *bus; + struct pci_slot *slot; + struct pci_device *func; + unsigned int nbus, ndev, nfunc; + + if (domain) { + for (nbus = 0; nbus < MAX_PCI_BUSES; nbus++) { + bus = domain->bus[nbus]; + if (bus) { + for (ndev = 0; ndev < MAX_PCI_DEVICES; ndev++) { + slot = bus->slot[ndev]; + if (slot) { + for (nfunc = 0; nfunc < MAX_PCI_FUNC; nfunc++) { + func = slot->func[nfunc]; + if (func) { + if (func->dev_info) + free(func->dev_info); + free(func); + } + free(slot); + } + } + free(bus); + } + } + free(domain); + } + } +} + +/* Try to match any pci device to the appropriate kernel module */ +/* it uses the modules.alias from the boot device */ +int get_module_name_from_alias(struct pci_domain *domain, char *modules_alias_path) +{ + char line[MAX_LINE]; + char module_name[21]; // the module name field is 21 char long + char delims[]="*"; // colums are separated by spaces + char vendor_id[16]; + char product_id[16]; + char sub_vendor_id[16]; + char sub_product_id[16]; + FILE *f; + struct pci_device *dev=NULL; + + /* Intializing the linux_kernel_module 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; + } + for (int i=0;i<MAX_KERNEL_MODULES_PER_PCI_DEVICE;i++) { + if (strlen(dev->dev_info->linux_kernel_module[i])==0) + strlcpy(dev->dev_info->linux_kernel_module[i], "unknown",7); + } + } + + /* Opening the modules.pcimap (of a linux kernel) from the boot device */ + f=zfopen(modules_alias_path, "r"); + if (!f) + return -ENOMODULESALIAS; + + /* for each line we found in the modules.pcimap */ + while ( fgets(line, sizeof line, f) ) { + /* skipping unecessary lines */ + if ((line[0] == '#') || (strstr(line,"alias pci:v")==NULL)) + continue; + + /* Resetting temp buffer*/ + memset(module_name,0,sizeof(module_name)); + memset(vendor_id,0,sizeof(vendor_id)); + memset(sub_vendor_id,0,sizeof(sub_vendor_id)); + memset(product_id,0,sizeof(product_id)); + memset(sub_product_id,0,sizeof(sub_product_id)); + strcpy(vendor_id,"0000"); + strcpy(product_id,"0000"); + /* ffff will be used to match any device as in modules.alias + * a missing subvendor/product have to be considered as 0xFFFF*/ + strcpy(sub_product_id,"ffff"); + strcpy(sub_vendor_id,"ffff"); + + char *result = NULL; + int field=0; + + /* looking for the next field */ + result = strtok(line+strlen("alias pci:v"), delims); + while( result != NULL ) { + if (field==0) { + + /* Searching for the vendor separator*/ + char *temp = strstr(result,"d"); + if (temp != NULL) { + strlcpy(vendor_id,result,temp-result); + result+=strlen(vendor_id)+1; + } + + /* Searching for the product separator*/ + temp = strstr(result,"sv"); + if (temp != NULL) { + strlcpy(product_id,result,temp-result); + result+=strlen(product_id)+1; + } + + /* Searching for the sub vendor separator*/ + temp = strstr(result,"sd"); + if (temp != NULL) { + strlcpy(sub_vendor_id,result,temp-result); + result+=strlen(sub_vendor_id)+1; + } + + /* Searching for the sub product separator*/ + temp = strstr(result,"bc"); + if (temp != NULL) { + strlcpy(sub_product_id,result,temp-result); + result+=strlen(sub_product_id)+1; + } + /* That's the module name */ + } else if ((strlen(result)>2) && + (result[0]==0x20)) + strcpy(module_name,result+1); + /* We have to replace \n by \0*/ + module_name[strlen(module_name)-1]='\0'; + field++; + + /* Searching the next field */ + result = strtok( NULL, delims ); + } + + /* Now we have extracted informations from the modules.alias + * Let's compare it with the devices we know*/ + 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 (int_vendor_id == dev->vendor && + int_product_id == dev->product && + (int_sub_product_id & dev->sub_product) + == dev->sub_product && + (int_sub_vendor_id & dev->sub_vendor) + == dev->sub_vendor) { + bool found=false; + + /* Scan all known kernel modules for this pci device */ + for (int i=0; i<dev->dev_info->linux_kernel_module_count; i++) { + + /* Try to detect if we already knew the same kernel module*/ + if (strstr(dev->dev_info->linux_kernel_module[i], module_name)) { + found=true; + break; + } + } + /* If we don't have this kernel module, let's add it */ + if (!found) { + 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; +} diff --git a/contrib/syslinux-4.02/com32/lib/pci/writeb.c b/contrib/syslinux-4.02/com32/lib/pci/writeb.c new file mode 100644 index 0000000..5a9a24a --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/pci/writeb.c @@ -0,0 +1,4 @@ +#define TYPE uint8_t +#define BWL(x) x ## b +#define BIOSCALL 0xb10b +#include "pci/writex.c" diff --git a/contrib/syslinux-4.02/com32/lib/pci/writel.c b/contrib/syslinux-4.02/com32/lib/pci/writel.c new file mode 100644 index 0000000..df9fc7b --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/pci/writel.c @@ -0,0 +1,4 @@ +#define TYPE uint32_t +#define BWL(x) x ## l +#define BIOSCALL 0xb10d +#include "pci/writex.c" diff --git a/contrib/syslinux-4.02/com32/lib/pci/writew.c b/contrib/syslinux-4.02/com32/lib/pci/writew.c new file mode 100644 index 0000000..e5a948a --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/pci/writew.c @@ -0,0 +1,4 @@ +#define TYPE uint16_t +#define BWL(x) x ## w +#define BIOSCALL 0xb10c +#include "pci/writex.c" diff --git a/contrib/syslinux-4.02/com32/lib/pci/writex.c b/contrib/syslinux-4.02/com32/lib/pci/writex.c new file mode 100644 index 0000000..d83a1ee --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/pci/writex.c @@ -0,0 +1,50 @@ +#include "pci/pci.h" + +void BWL(pci_write)(TYPE v, pciaddr_t a) +{ + for (;;) { + switch (__pci_cfg_type) { + case PCI_CFG_AUTO: + pci_set_config_type(PCI_CFG_AUTO); + break; /* Try again */ + + case PCI_CFG_TYPE1: + { + uint32_t oldcf8; + cli(); + oldcf8 = inl(0xcf8); + outl(a, 0xcf8); + BWL(out) (v, 0xcfc + (a & 3)); + outl(oldcf8, 0xcf8); + sti(); + } + return; + + case PCI_CFG_TYPE2: + { + uint8_t oldcf8, oldcfa; + + if (a & (0x10 << 11)) + return; /* Devices 16-31 not supported */ + + cli(); + oldcf8 = inb(0xcf8); + oldcfa = inb(0xcfa); + outb(0xf0 + ((a >> (8 - 1)) & 0x0e), 0xcf8); + outb(a >> 16, 0xcfa); + BWL(out) (v, 0xc000 + ((a >> (11 - 8)) & 0xf00) + (a & 0xff)); + outb(oldcf8, 0xcf8); + outb(oldcfa, 0xcfa); + sti(); + } + return; + + case PCI_CFG_BIOS: + __pci_read_write_bios(BIOSCALL, v, a); + return; + + default: + return; + } + } +} diff --git a/contrib/syslinux-4.02/com32/lib/perror.c b/contrib/syslinux-4.02/com32/lib/perror.c new file mode 100644 index 0000000..ff23b91 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/perror.c @@ -0,0 +1,12 @@ +/* + * perror.c + */ + +#include <errno.h> +#include <stdio.h> +#include <string.h> + +void perror(const char *s) +{ + fprintf(stderr, "%s: error %d\n", s, errno); +} diff --git a/contrib/syslinux-4.02/com32/lib/printf.c b/contrib/syslinux-4.02/com32/lib/printf.c new file mode 100644 index 0000000..86c2b76 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/printf.c @@ -0,0 +1,17 @@ +/* + * printf.c + */ + +#include <stdio.h> +#include <stdarg.h> + +int printf(const char *format, ...) +{ + va_list ap; + int rv; + + va_start(ap, format); + rv = vfprintf(stdout, format, ap); + va_end(ap); + return rv; +} diff --git a/contrib/syslinux-4.02/com32/lib/putchar.c b/contrib/syslinux-4.02/com32/lib/putchar.c new file mode 100644 index 0000000..6f993aa --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/putchar.c @@ -0,0 +1,16 @@ +/* + * putchar.c + * + * gcc "printf decompilation" expects this to exist... + */ + +#include <stdio.h> + +#undef putchar + +int putchar(int c) +{ + unsigned char ch = c; + + return _fwrite(&ch, 1, stdout) == 1 ? ch : EOF; +} diff --git a/contrib/syslinux-4.02/com32/lib/puts.c b/contrib/syslinux-4.02/com32/lib/puts.c new file mode 100644 index 0000000..6028543 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/puts.c @@ -0,0 +1,13 @@ +/* + * puts.c + */ + +#include <stdio.h> + +int puts(const char *s) +{ + if (fputs(s, stdout) < 0) + return -1; + + return _fwrite("\n", 1, stdout); +} diff --git a/contrib/syslinux-4.02/com32/lib/qsort.c b/contrib/syslinux-4.02/com32/lib/qsort.c new file mode 100644 index 0000000..a9d646c --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/qsort.c @@ -0,0 +1,46 @@ +/* + * qsort.c + * + * This is actually combsort. It's an O(n log n) algorithm with + * simplicity/small code size being its main virtue. + */ + +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +static inline size_t newgap(size_t gap) +{ + gap = (gap * 10) / 13; + if (gap == 9 || gap == 10) + gap = 11; + + if (gap < 1) + gap = 1; + return gap; +} + +void qsort(void *base, size_t nmemb, size_t size, + int (*compar) (const void *, const void *)) +{ + size_t gap = nmemb; + size_t i, j; + char *p1, *p2; + int swapped; + + if (!nmemb) + return; + + do { + gap = newgap(gap); + swapped = 0; + + for (i = 0, p1 = base; i < nmemb - gap; i++, p1 += size) { + j = i + gap; + if (compar(p1, p2 = (char *)base + j * size) > 0) { + memswap(p1, p2, size); + swapped = 1; + } + } + } while (gap > 1 || swapped); +} diff --git a/contrib/syslinux-4.02/com32/lib/realloc.c b/contrib/syslinux-4.02/com32/lib/realloc.c new file mode 100644 index 0000000..2969e31 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/realloc.c @@ -0,0 +1,98 @@ +/* + * realloc.c + */ + +#include <stdlib.h> +#include <string.h> +#include <minmax.h> + +#include "malloc.h" + +void *realloc(void *ptr, size_t size) +{ + struct free_arena_header *ah, *nah; + void *newptr; + size_t newsize, oldsize, xsize; + + if (!ptr) + return malloc(size); + + if (size == 0) { + free(ptr); + return NULL; + } + + ah = (struct free_arena_header *) + ((struct arena_header *)ptr - 1); + + /* Actual size of the old block */ + oldsize = ah->a.size; + + /* Add the obligatory arena header, and round up */ + newsize = (size + 2 * sizeof(struct arena_header) - 1) & ARENA_SIZE_MASK; + + if (oldsize >= newsize && newsize >= (oldsize >> 2) && + oldsize - newsize < 4096) { + /* This allocation is close enough already. */ + return ptr; + } else { + xsize = oldsize; + + nah = ah->a.next; + if ((char *)nah == (char *)ah + ah->a.size && + nah->a.type == ARENA_TYPE_FREE && + oldsize + nah->a.size >= newsize) { + /* Merge in subsequent free block */ + ah->a.next = nah->a.next; + ah->a.next->a.prev = ah; + nah->next_free->prev_free = nah->prev_free; + nah->prev_free->next_free = nah->next_free; + xsize = (ah->a.size += nah->a.size); + } + + if (xsize >= newsize) { + /* We can reallocate in place */ + if (xsize >= newsize + 2 * sizeof(struct arena_header)) { + /* Residual free block at end */ + nah = (struct free_arena_header *)((char *)ah + newsize); + nah->a.type = ARENA_TYPE_FREE; + nah->a.size = xsize - newsize; + ah->a.size = newsize; + + /* Insert into block list */ + nah->a.next = ah->a.next; + ah->a.next = nah; + nah->a.next->a.prev = nah; + nah->a.prev = ah; + + /* Insert into free list */ + if (newsize > oldsize) { + /* Hack: this free block is in the path of a memory object + which has already been grown at least once. As such, put + it at the *end* of the freelist instead of the beginning; + trying to save it for future realloc()s of the same block. */ + nah->prev_free = __malloc_head.prev_free; + nah->next_free = &__malloc_head; + __malloc_head.prev_free = nah; + nah->prev_free->next_free = nah; + } else { + nah->next_free = __malloc_head.next_free; + nah->prev_free = &__malloc_head; + __malloc_head.next_free = nah; + nah->next_free->prev_free = nah; + } + } + /* otherwise, use up the whole block */ + return ptr; + } else { + /* Last resort: need to allocate a new block and copy */ + oldsize -= sizeof(struct arena_header); + newptr = malloc(size); + if (newptr) { + memcpy(newptr, ptr, min(size, oldsize)); + free(ptr); + } + return newptr; + } + } +} diff --git a/contrib/syslinux-4.02/com32/lib/seed48.c b/contrib/syslinux-4.02/com32/lib/seed48.c new file mode 100644 index 0000000..c5b28aa --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/seed48.c @@ -0,0 +1,18 @@ +/* + * seed48.c + */ + +#include <stdlib.h> +#include <stdint.h> +#include <string.h> + +extern unsigned short __rand48_seed[3]; + +unsigned short *seed48(const unsigned short xsubi[3]) +{ + static unsigned short oldseed[3]; + memcpy(oldseed, __rand48_seed, sizeof __rand48_seed); + memcpy(__rand48_seed, xsubi, sizeof __rand48_seed); + + return oldseed; +} diff --git a/contrib/syslinux-4.02/com32/lib/setjmp.S b/contrib/syslinux-4.02/com32/lib/setjmp.S new file mode 100644 index 0000000..658df48 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/setjmp.S @@ -0,0 +1,63 @@ +/* + * arch/i386/setjmp.S + * + * setjmp/longjmp for the i386 architecture + * + * + * + * The jmp_buf is assumed to contain the following, in order: + * %ebx + * %esp + * %ebp + * %esi + * %edi + * <return address> + */ + + .text + .align 4 + + .globl _setjmp + .type _setjmp, @function +_setjmp: # gcc 4.0.1 wants this as an alias? + + .globl setjmp + .type setjmp, @function +setjmp: +#ifdef REGPARM + movl %eax,%edx +#else + movl 4(%esp),%edx +#endif + popl %ecx # Return address, and adjust the stack + xorl %eax,%eax # Return value + movl %ebx,(%edx) + movl %esp,4(%edx) # Post-return %esp! + pushl %ecx # Make the call/return stack happy + movl %ebp,8(%edx) + movl %esi,12(%edx) + movl %edi,16(%edx) + movl %ecx,20(%edx) # Return address + ret + + .size setjmp,.-setjmp + + .text + .align 4 + .globl longjmp + .type longjmp, @function +longjmp: +#ifdef REGPARM + xchgl %eax,%edx +#else + movl 4(%esp),%edx # jmp_ptr address + movl 8(%esp),%eax # Return value +#endif + movl (%edx),%ebx + movl 4(%edx),%esp + movl 8(%edx),%ebp + movl 12(%edx),%esi + movl 16(%edx),%edi + jmp *20(%edx) + + .size longjmp,.-longjmp diff --git a/contrib/syslinux-4.02/com32/lib/snprintf.c b/contrib/syslinux-4.02/com32/lib/snprintf.c new file mode 100644 index 0000000..304bab4 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/snprintf.c @@ -0,0 +1,16 @@ +/* + * snprintf.c + */ + +#include <stdio.h> + +int snprintf(char *buffer, size_t n, const char *format, ...) +{ + va_list ap; + int rv; + + va_start(ap, format); + rv = vsnprintf(buffer, n, format, ap); + va_end(ap); + return rv; +} diff --git a/contrib/syslinux-4.02/com32/lib/sprintf.c b/contrib/syslinux-4.02/com32/lib/sprintf.c new file mode 100644 index 0000000..3c32841 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sprintf.c @@ -0,0 +1,18 @@ +/* + * sprintf.c + */ + +#include <stdio.h> +#include <unistd.h> + +int sprintf(char *buffer, const char *format, ...) +{ + va_list ap; + int rv; + + va_start(ap, format); + rv = vsnprintf(buffer, ~(size_t) 0, format, ap); + va_end(ap); + + return rv; +} diff --git a/contrib/syslinux-4.02/com32/lib/srand48.c b/contrib/syslinux-4.02/com32/lib/srand48.c new file mode 100644 index 0000000..6a6c20a --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/srand48.c @@ -0,0 +1,15 @@ +/* + * srand48.c + */ + +#include <stdlib.h> +#include <stdint.h> + +extern unsigned short __rand48_seed[3]; + +void srand48(long seedval) +{ + __rand48_seed[0] = 0x330e; + __rand48_seed[1] = (unsigned short)seedval; + __rand48_seed[2] = (unsigned short)((uint32_t) seedval >> 16); +} diff --git a/contrib/syslinux-4.02/com32/lib/sscanf.c b/contrib/syslinux-4.02/com32/lib/sscanf.c new file mode 100644 index 0000000..096d233 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sscanf.c @@ -0,0 +1,17 @@ +/* + * sscanf() + */ + +#include <stdio.h> + +int sscanf(const char *str, const char *format, ...) +{ + va_list ap; + int rv; + + va_start(ap, format); + rv = vsscanf(str, format, ap); + va_end(ap); + + return rv; +} diff --git a/contrib/syslinux-4.02/com32/lib/stack.c b/contrib/syslinux-4.02/com32/lib/stack.c new file mode 100644 index 0000000..dd7d9d4 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/stack.c @@ -0,0 +1,4 @@ +#include <stdlib.h> + +/* Default stack size 8 MB */ +size_t __stack_size = 8 << 20; diff --git a/contrib/syslinux-4.02/com32/lib/stpcpy.c b/contrib/syslinux-4.02/com32/lib/stpcpy.c new file mode 100644 index 0000000..23e20af --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/stpcpy.c @@ -0,0 +1,23 @@ +/* + * stpcpy.c + * + * stpcpy() + */ + +#include <string.h> + +char *stpcpy(char *dst, const char *src) +{ + char *q = dst; + const char *p = src; + char ch; + + for (;;) { + *q = ch = *p++; + if (!ch) + break; + q++; + } + + return q; +} diff --git a/contrib/syslinux-4.02/com32/lib/stpncpy.c b/contrib/syslinux-4.02/com32/lib/stpncpy.c new file mode 100644 index 0000000..0537a56 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/stpncpy.c @@ -0,0 +1,23 @@ +/* + * stpncpy.c + * + * stpncpy() + */ + +#include <string.h> + +char *stpncpy(char *dst, const char *src, size_t n) +{ + char *q = dst; + const char *p = src; + char ch; + + while (n--) { + *q = ch = *p++; + if (!ch) + break; + q++; + } + + return q; +} diff --git a/contrib/syslinux-4.02/com32/lib/strcasecmp.c b/contrib/syslinux-4.02/com32/lib/strcasecmp.c new file mode 100644 index 0000000..30949a0 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strcasecmp.c @@ -0,0 +1,24 @@ +/* + * strcasecmp.c + */ + +#include <string.h> +#include <ctype.h> + +int strcasecmp(const char *s1, const char *s2) +{ + const unsigned char *c1 = (const unsigned char *)s1; + const unsigned char *c2 = (const unsigned char *)s2; + unsigned char ch; + int d = 0; + + while (1) { + /* toupper() expects an unsigned char (implicitly cast to int) + as input, and returns an int, which is exactly what we want. */ + d = toupper(ch = *c1++) - toupper(*c2++); + if (d || !ch) + break; + } + + return d; +} diff --git a/contrib/syslinux-4.02/com32/lib/strcat.c b/contrib/syslinux-4.02/com32/lib/strcat.c new file mode 100644 index 0000000..91bdb32 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strcat.c @@ -0,0 +1,11 @@ +/* + * strcat.c + */ + +#include <string.h> + +char *strcat(char *dst, const char *src) +{ + strcpy(strchr(dst, '\0'), src); + return dst; +} diff --git a/contrib/syslinux-4.02/com32/lib/strchr.c b/contrib/syslinux-4.02/com32/lib/strchr.c new file mode 100644 index 0000000..cd3ec78 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strchr.c @@ -0,0 +1,16 @@ +/* + * strchr.c + */ + +#include <string.h> + +char *strchr(const char *s, int c) +{ + while (*s != (char)c) { + if (!*s) + return NULL; + s++; + } + + return (char *)s; +} diff --git a/contrib/syslinux-4.02/com32/lib/strcmp.c b/contrib/syslinux-4.02/com32/lib/strcmp.c new file mode 100644 index 0000000..47a4aad --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strcmp.c @@ -0,0 +1,21 @@ +/* + * strcmp.c + */ + +#include <string.h> + +int strcmp(const char *s1, const char *s2) +{ + const unsigned char *c1 = (const unsigned char *)s1; + const unsigned char *c2 = (const unsigned char *)s2; + unsigned char ch; + int d = 0; + + while (1) { + d = (int)(ch = *c1++) - (int)*c2++; + if (d || !ch) + break; + } + + return d; +} diff --git a/contrib/syslinux-4.02/com32/lib/strcpy.c b/contrib/syslinux-4.02/com32/lib/strcpy.c new file mode 100644 index 0000000..0e3b021 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strcpy.c @@ -0,0 +1,20 @@ +/* + * strcpy.c + * + * strcpy() + */ + +#include <string.h> + +char *strcpy(char *dst, const char *src) +{ + char *q = dst; + const char *p = src; + char ch; + + do { + *q++ = ch = *p++; + } while (ch); + + return dst; +} diff --git a/contrib/syslinux-4.02/com32/lib/strdup.c b/contrib/syslinux-4.02/com32/lib/strdup.c new file mode 100644 index 0000000..766958b --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strdup.c @@ -0,0 +1,17 @@ +/* + * strdup.c + */ + +#include <string.h> +#include <stdlib.h> + +char *strdup(const char *s) +{ + int l = strlen(s) + 1; + char *d = malloc(l); + + if (d) + memcpy(d, s, l); + + return d; +} diff --git a/contrib/syslinux-4.02/com32/lib/strerror.c b/contrib/syslinux-4.02/com32/lib/strerror.c new file mode 100644 index 0000000..8dbe74a --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strerror.c @@ -0,0 +1,23 @@ +/* + * strerror.c + */ + +#include <string.h> + +char *strerror(int errnum) +{ + static char message[32] = "error "; /* enough for error 2^63-1 */ + + char numbuf[32]; + char *p; + + p = numbuf + sizeof numbuf; + *--p = '\0'; + + do { + *--p = (errnum % 10) + '0'; + errnum /= 10; + } while (errnum); + + return (char *)memcpy(message + 6, p, (numbuf + sizeof numbuf) - p); +} diff --git a/contrib/syslinux-4.02/com32/lib/strlcat.c b/contrib/syslinux-4.02/com32/lib/strlcat.c new file mode 100644 index 0000000..75f69ed --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strlcat.c @@ -0,0 +1,29 @@ +/* + * strlcat.c + */ + +#include <string.h> +#include <klibc/compiler.h> + +size_t strlcat(char *dst, const char *src, size_t size) +{ + size_t bytes = 0; + char *q = dst; + const char *p = src; + char ch; + + while (bytes < size && *q) { + q++; + bytes++; + } + + while ((ch = *p++)) { + if (bytes < size) + *q++ = ch; + + bytes++; + } + + *q = '\0'; + return bytes; +} diff --git a/contrib/syslinux-4.02/com32/lib/strlcpy.c b/contrib/syslinux-4.02/com32/lib/strlcpy.c new file mode 100644 index 0000000..284e72e --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strlcpy.c @@ -0,0 +1,24 @@ +/* + * strlcpy.c + */ + +#include <string.h> +#include <klibc/compiler.h> + +size_t strlcpy(char *dst, const char *src, size_t size) +{ + size_t bytes = 0; + char *q = dst; + const char *p = src; + char ch; + + while ((ch = *p++)) { + if (bytes < size) + *q++ = ch; + + bytes++; + } + + *q = '\0'; + return bytes; +} diff --git a/contrib/syslinux-4.02/com32/lib/strlen.c b/contrib/syslinux-4.02/com32/lib/strlen.c new file mode 100644 index 0000000..d72c7fa --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strlen.c @@ -0,0 +1,13 @@ +/* + * strlen() + */ + +#include <string.h> + +size_t strlen(const char *s) +{ + const char *ss = s; + while (*ss) + ss++; + return ss - s; +} diff --git a/contrib/syslinux-4.02/com32/lib/strncasecmp.c b/contrib/syslinux-4.02/com32/lib/strncasecmp.c new file mode 100644 index 0000000..2caac0a --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strncasecmp.c @@ -0,0 +1,24 @@ +/* + * strncasecmp.c + */ + +#include <string.h> +#include <ctype.h> + +int strncasecmp(const char *s1, const char *s2, size_t n) +{ + const unsigned char *c1 = (const unsigned char *)s1; + const unsigned char *c2 = (const unsigned char *)s2; + unsigned char ch; + int d = 0; + + while (n--) { + /* toupper() expects an unsigned char (implicitly cast to int) + as input, and returns an int, which is exactly what we want. */ + d = toupper(ch = *c1++) - toupper(*c2++); + if (d || !ch) + break; + } + + return d; +} diff --git a/contrib/syslinux-4.02/com32/lib/strncat.c b/contrib/syslinux-4.02/com32/lib/strncat.c new file mode 100644 index 0000000..71cdb35 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strncat.c @@ -0,0 +1,11 @@ +/* + * strncat.c + */ + +#include <string.h> + +char *strncat(char *dst, const char *src, size_t n) +{ + strncpy(strchr(dst, '\0'), src, n); + return dst; +} diff --git a/contrib/syslinux-4.02/com32/lib/strncmp.c b/contrib/syslinux-4.02/com32/lib/strncmp.c new file mode 100644 index 0000000..e41b9e3 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strncmp.c @@ -0,0 +1,21 @@ +/* + * strncmp.c + */ + +#include <string.h> + +int strncmp(const char *s1, const char *s2, size_t n) +{ + const unsigned char *c1 = (const unsigned char *)s1; + const unsigned char *c2 = (const unsigned char *)s2; + unsigned char ch; + int d = 0; + + while (n--) { + d = (int)(ch = *c1++) - (int)*c2++; + if (d || !ch) + break; + } + + return d; +} diff --git a/contrib/syslinux-4.02/com32/lib/strncpy.c b/contrib/syslinux-4.02/com32/lib/strncpy.c new file mode 100644 index 0000000..0eda791 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strncpy.c @@ -0,0 +1,22 @@ +/* + * strncpy.c + * + * strncpy() + */ + +#include <string.h> + +char *strncpy(char *dst, const char *src, size_t n) +{ + char *q = dst; + const char *p = src; + char ch; + + while (n--) { + *q++ = ch = *p++; + if (!ch) + break; + } + + return dst; +} diff --git a/contrib/syslinux-4.02/com32/lib/strndup.c b/contrib/syslinux-4.02/com32/lib/strndup.c new file mode 100644 index 0000000..d1073a8 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strndup.c @@ -0,0 +1,17 @@ +/* + * strndup.c + */ + +#include <string.h> +#include <stdlib.h> + +char *strndup(const char *s, size_t n) +{ + int l = n > strlen(s) ? strlen(s) + 1 : n + 1; + char *d = malloc(l); + + if (d) + memcpy(d, s, l); + d[n] = '\0'; + return d; +} diff --git a/contrib/syslinux-4.02/com32/lib/strnlen.c b/contrib/syslinux-4.02/com32/lib/strnlen.c new file mode 100644 index 0000000..c22f8dc --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strnlen.c @@ -0,0 +1,13 @@ +/* + * strnlen() + */ + +#include <string.h> + +size_t strnlen(const char *s, size_t n) +{ + const char *ss = s; + while (n-- && *ss) + ss++; + return ss - s; +} diff --git a/contrib/syslinux-4.02/com32/lib/strntoimax.c b/contrib/syslinux-4.02/com32/lib/strntoimax.c new file mode 100644 index 0000000..a3f4010 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strntoimax.c @@ -0,0 +1,13 @@ +/* + * strntoimax.c + * + * strntoimax() + */ + +#include <stddef.h> +#include <inttypes.h> + +intmax_t strntoimax(const char *nptr, char **endptr, int base, size_t n) +{ + return (intmax_t) strntoumax(nptr, endptr, base, n); +} diff --git a/contrib/syslinux-4.02/com32/lib/strntoumax.c b/contrib/syslinux-4.02/com32/lib/strntoumax.c new file mode 100644 index 0000000..d8bc73b --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strntoumax.c @@ -0,0 +1,73 @@ +/* + * strntoumax.c + * + * The strntoumax() function and associated + */ + +#include <stddef.h> +#include <stdint.h> +#include <ctype.h> + +static inline int digitval(int ch) +{ + if (ch >= '0' && ch <= '9') { + return ch - '0'; + } else if (ch >= 'A' && ch <= 'Z') { + return ch - 'A' + 10; + } else if (ch >= 'a' && ch <= 'z') { + return ch - 'a' + 10; + } else { + return -1; + } +} + +uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n) +{ + int minus = 0; + uintmax_t v = 0; + int d; + + while (n && isspace((unsigned char)*nptr)) { + nptr++; + n--; + } + + /* Single optional + or - */ + if (n && *nptr == '-') { + minus = 1; + nptr++; + n--; + } else if (n && *nptr == '+') { + nptr++; + } + + if (base == 0) { + if (n >= 2 && nptr[0] == '0' && (nptr[1] == 'x' || nptr[1] == 'X')) { + n -= 2; + nptr += 2; + base = 16; + } else if (n >= 1 && nptr[0] == '0') { + n--; + nptr++; + base = 8; + } else { + base = 10; + } + } else if (base == 16) { + if (n >= 2 && nptr[0] == '0' && (nptr[1] == 'x' || nptr[1] == 'X')) { + n -= 2; + nptr += 2; + } + } + + while (n && (d = digitval(*nptr)) >= 0 && d < base) { + v = v * base + d; + n--; + nptr++; + } + + if (endptr) + *endptr = (char *)nptr; + + return minus ? -v : v; +} diff --git a/contrib/syslinux-4.02/com32/lib/strrchr.c b/contrib/syslinux-4.02/com32/lib/strrchr.c new file mode 100644 index 0000000..a7d2fee --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strrchr.c @@ -0,0 +1,18 @@ +/* + * strrchr.c + */ + +#include <string.h> + +char *strrchr(const char *s, int c) +{ + const char *found = NULL; + + while (*s) { + if (*s == (char)c) + found = s; + s++; + } + + return (char *)found; +} diff --git a/contrib/syslinux-4.02/com32/lib/strsep.c b/contrib/syslinux-4.02/com32/lib/strsep.c new file mode 100644 index 0000000..5c4f03f --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strsep.c @@ -0,0 +1,21 @@ +/* + * strsep.c + */ + +#include <string.h> + +char *strsep(char **stringp, const char *delim) +{ + char *s = *stringp; + char *e; + + if (!s) + return NULL; + + e = strpbrk(s, delim); + if (e) + *e++ = '\0'; + + *stringp = e; + return s; +} diff --git a/contrib/syslinux-4.02/com32/lib/strspn.c b/contrib/syslinux-4.02/com32/lib/strspn.c new file mode 100644 index 0000000..abbbf17 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strspn.c @@ -0,0 +1,60 @@ +/* + * strspn, strcspn + */ + +#include <string.h> +#include <stddef.h> +#include <inttypes.h> +#include <limits.h> + +#ifndef LONG_BIT +#define LONG_BIT (CHAR_BIT*sizeof(long)) +#endif + +static inline void set_bit(unsigned long *bitmap, unsigned int bit) +{ + bitmap[bit / LONG_BIT] |= 1UL << (bit % LONG_BIT); +} + +static inline int test_bit(unsigned long *bitmap, unsigned int bit) +{ + return (int)(bitmap[bit / LONG_BIT] >> (bit % LONG_BIT)) & 1; +} + +static size_t strxspn(const char *s, const char *map, int parity) +{ + unsigned long matchmap[((1 << CHAR_BIT) + LONG_BIT - 1) / LONG_BIT]; + size_t n = 0; + + /* Create bitmap */ + memset(matchmap, 0, sizeof matchmap); + while (*map) + set_bit(matchmap, (unsigned char)*map++); + + /* Make sure the null character never matches */ + if (parity) + set_bit(matchmap, 0); + + /* Calculate span length */ + while (test_bit(matchmap, (unsigned char)*s++) ^ parity) + n++; + + return n; +} + +size_t strspn(const char *s, const char *accept) +{ + return strxspn(s, accept, 0); +} + +size_t strcspn(const char *s, const char *reject) +{ + return strxspn(s, reject, 1); +} + +char *strpbrk(const char *s, const char *accept) +{ + const char *ss = s + strxspn(s, accept, 1); + + return *ss ? (char *)ss : NULL; +} diff --git a/contrib/syslinux-4.02/com32/lib/strstr.c b/contrib/syslinux-4.02/com32/lib/strstr.c new file mode 100644 index 0000000..0a3e743 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strstr.c @@ -0,0 +1,10 @@ +/* + * strstr.c + */ + +#include <string.h> + +char *strstr(const char *haystack, const char *needle) +{ + return (char *)memmem(haystack, strlen(haystack), needle, strlen(needle)); +} diff --git a/contrib/syslinux-4.02/com32/lib/strtoimax.c b/contrib/syslinux-4.02/com32/lib/strtoimax.c new file mode 100644 index 0000000..0cdd088 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strtoimax.c @@ -0,0 +1,3 @@ +#define TYPE intmax_t +#define NAME strtoimax +#include "strtox.c" diff --git a/contrib/syslinux-4.02/com32/lib/strtok.c b/contrib/syslinux-4.02/com32/lib/strtok.c new file mode 100644 index 0000000..d2e37bb --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strtok.c @@ -0,0 +1,15 @@ +/* + * strtok.c + */ + +#include <string.h> + +char *strtok(char *s, const char *delim) +{ + static char *holder; + + if (s) + holder = s; + + return strsep(&holder, delim); +} diff --git a/contrib/syslinux-4.02/com32/lib/strtol.c b/contrib/syslinux-4.02/com32/lib/strtol.c new file mode 100644 index 0000000..9efc8b9 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strtol.c @@ -0,0 +1,3 @@ +#define TYPE signed long +#define NAME strtol +#include "strtox.c" diff --git a/contrib/syslinux-4.02/com32/lib/strtoll.c b/contrib/syslinux-4.02/com32/lib/strtoll.c new file mode 100644 index 0000000..a9428c7 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strtoll.c @@ -0,0 +1,3 @@ +#define TYPE signed long long +#define NAME strtoll +#include "strtox.c" diff --git a/contrib/syslinux-4.02/com32/lib/strtoul.c b/contrib/syslinux-4.02/com32/lib/strtoul.c new file mode 100644 index 0000000..3189aaa --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strtoul.c @@ -0,0 +1,3 @@ +#define TYPE unsigned long +#define NAME strtoul +#include "strtox.c" diff --git a/contrib/syslinux-4.02/com32/lib/strtoull.c b/contrib/syslinux-4.02/com32/lib/strtoull.c new file mode 100644 index 0000000..83c14e9 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strtoull.c @@ -0,0 +1,3 @@ +#define TYPE unsigned long long +#define NAME strtoull +#include "strtox.c" diff --git a/contrib/syslinux-4.02/com32/lib/strtoumax.c b/contrib/syslinux-4.02/com32/lib/strtoumax.c new file mode 100644 index 0000000..a379710 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strtoumax.c @@ -0,0 +1,3 @@ +#define TYPE uintmax_t +#define NAME strtoumax +#include "strtox.c" diff --git a/contrib/syslinux-4.02/com32/lib/strtox.c b/contrib/syslinux-4.02/com32/lib/strtox.c new file mode 100644 index 0000000..e01247a --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/strtox.c @@ -0,0 +1,13 @@ +/* + * strtox.c + * + * strto...() functions, by macro definition + */ + +#include <stddef.h> +#include <inttypes.h> + +TYPE NAME(const char *nptr, char **endptr, int base) +{ + return (TYPE) strntoumax(nptr, endptr, base, ~(size_t) 0); +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/ansi.c b/contrib/syslinux-4.02/com32/lib/sys/ansi.c new file mode 100644 index 0000000..f73c03e --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/ansi.c @@ -0,0 +1,444 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * ansi.c + * + * ANSI character code engine + */ + +#include <string.h> +#include <colortbl.h> +#include "ansi.h" + +static const struct term_state default_state = { + .state = st_init, + .pvt = false, + .nparms = 0, + .xy = {0, 0}, + .cindex = 0, /* First color table entry */ + .vtgraphics = false, + .intensity = 1, + .underline = false, + .blink = false, + .reverse = false, + .fg = 7, + .bg = 0, + .autocr = true, /* Mimic \n -> \r\n conversion by default */ + .autowrap = true, /* Wrap lines by default */ + .saved_xy = {0, 0}, + .cursor = true, +}; + +/* DEC VT graphics to codepage 437 table (characters 0x60-0x7F only) */ +static const char decvt_to_cp437[] = { + 0004, 0261, 0007, 0007, 0007, 0007, 0370, 0361, + 0007, 0007, 0331, 0277, 0332, 0300, 0305, 0304, + 0304, 0304, 0137, 0137, 0303, 0264, 0301, 0302, + 0263, 0363, 0362, 0343, 0330, 0234, 0007, 00 +}; + +void __ansi_init(const struct term_info *ti) +{ + memcpy(ti->ts, &default_state, sizeof default_state); +} + +void __ansi_putchar(const struct term_info *ti, uint8_t ch) +{ + const struct ansi_ops *op = ti->op; + struct term_state *st = ti->ts; + const int rows = ti->rows; + const int cols = ti->cols; + struct curxy xy = st->xy; + + switch (st->state) { + case st_init: + switch (ch) { + case 1 ... 5: + st->state = st_tbl; + st->parms[0] = ch; + break; + case '\a': + op->beep(); + break; + case '\b': + if (xy.x > 0) + xy.x--; + break; + case '\t': + { + int nsp = 8 - (xy.x & 7); + while (nsp--) + __ansi_putchar(ti, ' '); + } + return; /* Cursor already updated */ + case '\n': + case '\v': + case '\f': + xy.y++; + if (st->autocr) + xy.x = 0; + break; + case '\r': + xy.x = 0; + break; + case 127: + /* Ignore delete */ + break; + case 14: + st->vtgraphics = 1; + break; + case 15: + st->vtgraphics = 0; + break; + case 27: + st->state = st_esc; + break; + default: + /* Print character */ + if (ch >= 32) { + if (st->vtgraphics && (ch & 0xe0) == 0x60) + ch = decvt_to_cp437[ch - 0x60]; + + op->write_char(xy.x, xy.y, ch, st); + xy.x++; + } + break; + } + break; + + case st_esc: + switch (ch) { + case '%': + case '(': + case ')': + case '#': + /* Ignore this plus the subsequent character, allows + compatibility with Linux sequence to set charset */ + break; + case '[': + st->state = st_csi; + st->nparms = 0; + st->pvt = false; + memset(st->parms, 0, sizeof st->parms); + break; + case 'c': + /* Reset terminal */ + memcpy(&st, &default_state, sizeof st); + op->erase(st, 0, 0, cols - 1, rows - 1); + xy.x = xy.y = 0; + st->state = st_init; + break; + default: + /* Ignore sequence */ + st->state = st_init; + break; + } + break; + + case st_csi: + { + int p0 = st->parms[0] ? st->parms[0] : 1; + + if (ch >= '0' && ch <= '9') { + st->parms[st->nparms] = st->parms[st->nparms] * 10 + (ch - '0'); + } else if (ch == ';') { + st->nparms++; + if (st->nparms >= ANSI_MAX_PARMS) + st->nparms = ANSI_MAX_PARMS - 1; + break; + } else if (ch == '?') { + st->pvt = true; + } else { + switch (ch) { + case 'A': + { + int y = xy.y - p0; + xy.y = (y < 0) ? 0 : y; + } + break; + case 'B': + { + int y = xy.y + p0; + xy.y = (y >= rows) ? rows - 1 : y; + } + break; + case 'C': + { + int x = xy.x + p0; + xy.x = (x >= cols) ? cols - 1 : x; + } + break; + case 'D': + { + int x = xy.x - p0; + xy.x = (x < 0) ? 0 : x; + } + break; + case 'E': + { + int y = xy.y + p0; + xy.y = (y >= rows) ? rows - 1 : y; + xy.x = 0; + } + break; + case 'F': + { + int y = xy.y - p0; + xy.y = (y < 0) ? 0 : y; + xy.x = 0; + } + break; + case 'G': + case '\'': + { + int x = st->parms[0] - 1; + xy.x = (x >= cols) ? cols - 1 : (x < 0) ? 0 : x; + } + break; + case 'H': + case 'f': + { + int y = st->parms[0] - 1; + int x = st->parms[1] - 1; + + xy.x = (x >= cols) ? cols - 1 : (x < 0) ? 0 : x; + xy.y = (y >= rows) ? rows - 1 : (y < 0) ? 0 : y; + } + break; + case 'J': + { + switch (st->parms[0]) { + case 0: + op->erase(st, xy.x, xy.y, cols - 1, xy.y); + if (xy.y < rows - 1) + op->erase(st, 0, xy.y + 1, cols - 1, rows - 1); + break; + + case 1: + if (xy.y > 0) + op->erase(st, 0, 0, cols - 1, xy.y - 1); + if (xy.y > 0) + op->erase(st, 0, xy.y, xy.x - 1, xy.y); + break; + + case 2: + op->erase(st, 0, 0, cols - 1, rows - 1); + break; + + default: + /* Ignore */ + break; + } + } + break; + case 'K': + { + switch (st->parms[0]) { + case 0: + op->erase(st, xy.x, xy.y, cols - 1, xy.y); + break; + + case 1: + if (xy.x > 0) + op->erase(st, 0, xy.y, xy.x - 1, xy.y); + break; + + case 2: + op->erase(st, 0, xy.y, cols - 1, xy.y); + break; + + default: + /* Ignore */ + break; + } + } + break; + case 'h': + case 'l': + { + bool set = (ch == 'h'); + switch (st->parms[0]) { + case 7: /* DECAWM */ + st->autowrap = set; + break; + case 20: /* LNM */ + st->autocr = set; + break; + case 25: /* DECTECM */ + st->cursor = set; + op->showcursor(st); + break; + default: + /* Ignore */ + break; + } + break; + } + case 'm': + { + static const int ansi2pc[8] = + { 0, 4, 2, 6, 1, 5, 3, 7 }; + + int i; + for (i = 0; i <= st->nparms; i++) { + int a = st->parms[i]; + switch (a) { + case 0: + st->fg = 7; + st->bg = 0; + st->intensity = 1; + st->underline = 0; + st->blink = 0; + st->reverse = 0; + break; + case 1: + st->intensity = 2; + break; + case 2: + st->intensity = 0; + break; + case 4: + st->underline = 1; + break; + case 5: + st->blink = 1; + break; + case 7: + st->reverse = 1; + break; + case 21: + case 22: + st->intensity = 1; + break; + case 24: + st->underline = 0; + break; + case 25: + st->blink = 0; + break; + case 27: + st->reverse = 0; + break; + case 30 ... 37: + st->fg = ansi2pc[a - 30]; + break; + case 38: + st->fg = 7; + st->underline = 1; + break; + case 39: + st->fg = 7; + st->underline = 0; + break; + case 40 ... 47: + st->bg = ansi2pc[a - 40]; + break; + case 49: + st->bg = 7; + break; + default: + /* Do nothing */ + break; + } + } + } + break; + case 's': + st->saved_xy = xy; + break; + case 'u': + xy = st->saved_xy; + break; + default: /* Includes CAN and SUB */ + break; /* Drop unknown sequence */ + } + st->state = st_init; + } + } + break; + + case st_tbl: + st->parms[1] = 0; + if (ch == '#') + st->state = st_tblc; + else + st->state = st_init; + break; + + case st_tblc: + { + unsigned int n = (unsigned char)ch - '0'; + const char *p; + + if (n < 10) { + st->parms[1] = st->parms[1] * 10 + n; + + if (!--st->parms[0]) { + if (st->parms[1] < console_color_table_size) { + /* Set the color table index */ + st->cindex = st->parms[1]; + + /* See if there are any other attributes we care about */ + p = console_color_table[st->parms[1]].ansi; + if (p) { + st->state = st_esc; + __ansi_putchar(ti, '['); + __ansi_putchar(ti, '0'); + __ansi_putchar(ti, ';'); + while (*p) + __ansi_putchar(ti, *p++); + __ansi_putchar(ti, 'm'); + } + } + st->state = st_init; + } + } else { + st->state = st_init; + } + } + break; + } + + /* If we fell off the end of the screen, adjust */ + if (xy.x >= cols) { + if (st->autowrap) { + xy.x = 0; + xy.y++; + } else { + xy.x = cols - 1; + } + } + while (xy.y >= rows) { + xy.y--; + op->scroll_up(st); + } + + /* Update cursor position */ + op->set_cursor(xy.x, xy.y, st->cursor); + st->xy = xy; +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/ansi.h b/contrib/syslinux-4.02/com32/lib/sys/ansi.h new file mode 100644 index 0000000..7ccafc8 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/ansi.h @@ -0,0 +1,66 @@ +/* + * ansi.h + */ + +#ifndef COM32_LIB_SYS_ANSI_H +#define COM32_LIB_SYS_ANSI_H + +#include <inttypes.h> +#include <stdbool.h> + +#define ANSI_MAX_PARMS 16 + +enum ansi_state { + st_init, + st_esc, + st_csi, + st_tbl, + st_tblc, +}; + +struct curxy { + uint8_t x, y; +} __attribute__ ((packed)); + +struct term_state { + enum ansi_state state; + int nparms; /* Number of parameters seen */ + int parms[ANSI_MAX_PARMS]; + bool pvt; /* Private code? */ + struct curxy xy; + struct curxy saved_xy; + uint8_t cindex; /* SOH color index */ + uint8_t fg; + uint8_t bg; + uint8_t intensity; + bool vtgraphics; /* VT graphics on/off */ + bool underline; + bool blink; + bool reverse; + bool autocr; + bool autowrap; + bool cursor; +}; + +struct ansi_ops { + void (*erase) (const struct term_state * st, int x0, int y0, int x1, + int y1); + void (*write_char) (int x, int y, uint8_t ch, const struct term_state * st); + void (*showcursor) (const struct term_state * st); + void (*scroll_up) (const struct term_state * st); + void (*set_cursor) (int x, int y, bool visible); + void (*beep) (void); +}; + +struct term_info { + int rows, cols; /* Screen size */ + int disabled; + struct term_state *ts; + const struct ansi_ops *op; +}; + +void __ansi_init(const struct term_info *ti); +void __ansi_putchar(const struct term_info *ti, uint8_t ch); +void __ansicon_beep(void); + +#endif /* COM32_LIB_SYS_ANSI_H */ diff --git a/contrib/syslinux-4.02/com32/lib/sys/ansicon_write.c b/contrib/syslinux-4.02/com32/lib/sys/ansicon_write.c new file mode 100644 index 0000000..b25f2d2 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/ansicon_write.c @@ -0,0 +1,257 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * ansicon_write.c + * + * Write to the screen using ANSI control codes (about as capable as + * DOS' ANSI.SYS.) + */ + +#include <errno.h> +#include <string.h> +#include <com32.h> +#include <minmax.h> +#include <colortbl.h> +#include <klibc/compiler.h> +#include <syslinux/config.h> +#include "file.h" +#include "ansi.h" + +static void ansicon_erase(const struct term_state *, int, int, int, int); +static void ansicon_write_char(int, int, uint8_t, const struct term_state *); +static void ansicon_showcursor(const struct term_state *); +static void ansicon_scroll_up(const struct term_state *); +static void ansicon_set_cursor(int, int, bool); + +static struct term_state ts; +struct ansi_ops __ansicon_ops = { + .erase = ansicon_erase, + .write_char = ansicon_write_char, + .showcursor = ansicon_showcursor, + .set_cursor = ansicon_set_cursor, + .scroll_up = ansicon_scroll_up, + .beep = __ansicon_beep, +}; + +static struct term_info ti = { + .disabled = 0, + .ts = &ts, + .op = &__ansicon_ops +}; + +#define BIOS_CURXY ((struct curxy *)0x450) /* Array for each page */ +#define BIOS_ROWS (*(uint8_t *)0x484) /* Minus one; if zero use 24 (= 25 lines) */ +#define BIOS_COLS (*(uint16_t *)0x44A) +#define BIOS_PAGE (*(uint8_t *)0x462) + +/* Reference counter to the screen, to keep track of if we need + reinitialization. */ +static int ansicon_counter = 0; + +static uint16_t cursor_type; /* Saved cursor pattern */ + +/* Common setup */ +int __ansicon_open(struct file_info *fp) +{ + static com32sys_t ireg; /* Auto-initalized to all zero */ + com32sys_t oreg; + + if (!ansicon_counter) { + /* Are we disabled? */ + if (syslinux_serial_console_info()->flowctl & 0x8000) { + ti.disabled = 1; + ti.rows = 25; + ti.cols = 80; + } else { + /* Force text mode */ + ireg.eax.w[0] = 0x0005; + __intcall(0x22, &ireg, NULL); + + /* Initial state */ + ti.rows = BIOS_ROWS ? BIOS_ROWS + 1 : 25; + ti.cols = BIOS_COLS; + __ansi_init(&ti); + + /* Get cursor shape and position */ + ireg.eax.b[1] = 0x03; + ireg.ebx.b[1] = BIOS_PAGE; + __intcall(0x10, &ireg, &oreg); + cursor_type = oreg.ecx.w[0]; + ti.ts->xy.x = oreg.edx.b[0]; + ti.ts->xy.y = oreg.edx.b[1]; + } + } + + fp->o.rows = ti.rows; + fp->o.cols = ti.cols; + + ansicon_counter++; + return 0; +} + +int __ansicon_close(struct file_info *fp) +{ + (void)fp; + + ansicon_counter--; + return 0; +} + +/* Turn ANSI attributes into VGA attributes */ +static uint8_t ansicon_attribute(const struct term_state *st) +{ + int bg = st->bg; + int fg; + + if (st->underline) + fg = 0x01; + else if (st->intensity == 0) + fg = 0x08; + else + fg = st->fg; + + if (st->reverse) { + bg = fg & 0x07; + fg &= 0x08; + fg |= st->bg; + } + + if (st->blink) + bg ^= 0x08; + + if (st->intensity == 2) + fg ^= 0x08; + + return (bg << 4) | fg; +} + +/* Erase a region of the screen */ +static void ansicon_erase(const struct term_state *st, + int x0, int y0, int x1, int y1) +{ + static com32sys_t ireg; + + ireg.eax.w[0] = 0x0600; /* Clear window */ + ireg.ebx.b[1] = ansicon_attribute(st); + ireg.ecx.b[0] = x0; + ireg.ecx.b[1] = y0; + ireg.edx.b[0] = x1; + ireg.edx.b[1] = y1; + __intcall(0x10, &ireg, NULL); +} + +/* Show or hide the cursor */ +static void ansicon_showcursor(const struct term_state *st) +{ + static com32sys_t ireg; + + ireg.eax.b[1] = 0x01; + ireg.ecx.w[0] = st->cursor ? cursor_type : 0x2020; + __intcall(0x10, &ireg, NULL); +} + +static void ansicon_set_cursor(int x, int y, bool visible) +{ + const int page = BIOS_PAGE; + struct curxy xy = BIOS_CURXY[page]; + static com32sys_t ireg; + + (void)visible; + + if (xy.x != x || xy.y != y) { + ireg.eax.b[1] = 0x02; + ireg.ebx.b[1] = page; + ireg.edx.b[1] = y; + ireg.edx.b[0] = x; + __intcall(0x10, &ireg, NULL); + } +} + +static void ansicon_write_char(int x, int y, uint8_t ch, + const struct term_state *st) +{ + static com32sys_t ireg; + + ansicon_set_cursor(x, y, false); + + ireg.eax.b[1] = 0x09; + ireg.eax.b[0] = ch; + ireg.ebx.b[1] = BIOS_PAGE; + ireg.ebx.b[0] = ansicon_attribute(st); + ireg.ecx.w[0] = 1; + __intcall(0x10, &ireg, NULL); +} + +static void ansicon_scroll_up(const struct term_state *st) +{ + static com32sys_t ireg; + + ireg.eax.w[0] = 0x0601; + ireg.ebx.b[1] = ansicon_attribute(st); + ireg.ecx.w[0] = 0; + ireg.edx.b[1] = ti.rows - 1; + ireg.edx.b[0] = ti.cols - 1; + __intcall(0x10, &ireg, NULL); /* Scroll */ +} + +ssize_t __ansicon_write(struct file_info *fp, const void *buf, size_t count) +{ + const unsigned char *bufp = buf; + size_t n = 0; + + (void)fp; + + if (ti.disabled) + return count; /* Nothing to do */ + + while (count--) { + __ansi_putchar(&ti, *bufp++); + n++; + } + + return n; +} + +void __ansicon_beep(void) +{ + static com32sys_t ireg; + + ireg.eax.w[0] = 0x0e07; + ireg.ebx.b[1] = BIOS_PAGE; + __intcall(0x10, &ireg, NULL); +} + +const struct output_dev dev_ansicon_w = { + .dev_magic = __DEV_MAGIC, + .flags = __DEV_TTY | __DEV_OUTPUT, + .fileflags = O_WRONLY | O_CREAT | O_TRUNC | O_APPEND, + .write = __ansicon_write, + .close = __ansicon_close, + .open = __ansicon_open, +}; diff --git a/contrib/syslinux-4.02/com32/lib/sys/ansiserial_write.c b/contrib/syslinux-4.02/com32/lib/sys/ansiserial_write.c new file mode 100644 index 0000000..957d1c6 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/ansiserial_write.c @@ -0,0 +1,59 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * ansiserial_write.c + * + * Write to both to the ANSI console and the serial port + */ + +#include <errno.h> +#include <string.h> +#include <com32.h> +#include <minmax.h> +#include "file.h" + +extern int __ansicon_open(struct file_info *); +extern int __ansicon_close(struct file_info *); +extern ssize_t __ansicon_write(struct file_info *, const void *, size_t); +extern ssize_t __xserial_write(struct file_info *, const void *, size_t); + +static ssize_t __ansiserial_write(struct file_info *fp, const void *buf, + size_t count) +{ + __ansicon_write(fp, buf, count); + return __xserial_write(fp, buf, count); +} + +const struct output_dev dev_ansiserial_w = { + .dev_magic = __DEV_MAGIC, + .flags = __DEV_TTY | __DEV_OUTPUT, + .fileflags = O_WRONLY | O_CREAT | O_TRUNC | O_APPEND, + .write = __ansiserial_write, + .close = __ansicon_close, + .open = __ansicon_open, +}; diff --git a/contrib/syslinux-4.02/com32/lib/sys/argv.c b/contrib/syslinux-4.02/com32/lib/sys/argv.c new file mode 100644 index 0000000..db287c2 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/argv.c @@ -0,0 +1,97 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * argv.c + * + * Parse a single C string into argc and argv (argc is return value.) + * memptr points to available memory. + */ + +#include <inttypes.h> +#include <stddef.h> +#include <stdio.h> +#include <syslinux/align.h> +#include <com32.h> + +extern char _end[]; /* Symbol created by linker */ +void *__mem_end = &_end; /* Global variable for use by malloc() */ + +int __parse_argv(char ***argv, const char *str) +{ + char dummy_argv0[] = ""; + char *mem = __mem_end; + const char *p = str; + char *q = mem; + char *r; + char **arg; + int wasspace = 1; + int argc = 1; + + /* First copy the string, turning whitespace runs into nulls */ + for (p = str;; p++) { + if (*p <= ' ') { + if (!wasspace) { + wasspace = 1; + *q++ = '\0'; + } + } else { + if (wasspace) { + argc++; + wasspace = 0; + } + *q++ = *p; + } + + /* This test is AFTER we have processed the null byte; + we treat it as a whitespace character so it terminates + the last argument */ + if (!*p) + break; + } + + /* Now create argv */ + arg = (char **)ALIGN_UP_FOR(q, char *); + *argv = arg; + *arg++ = __com32.cs_name ? (char *)__com32.cs_name : dummy_argv0; /* argv[0] */ + + q--; /* Point q to final null */ + if (mem < q) + *arg++ = mem; /* argv[1] */ + + for (r = mem; r < q; r++) { + if (*r == '\0') { + *arg++ = r + 1; + } + } + + *arg++ = NULL; /* Null pointer at the end */ + __mem_end = arg; /* End of memory we used */ + + return argc; +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/cfarcall.c b/contrib/syslinux-4.02/com32/lib/sys/cfarcall.c new file mode 100644 index 0000000..fca818b --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/cfarcall.c @@ -0,0 +1,10 @@ +/* + * cfarcall.c + */ + +#include <com32.h> + +int __cfarcall(uint16_t cs, uint16_t ip, const void *stack, uint32_t stack_size) +{ + return __com32.cs_cfarcall((cs << 16) + ip, stack, stack_size); +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/close.c b/contrib/syslinux-4.02/com32/lib/sys/close.c new file mode 100644 index 0000000..50d9a42 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/close.c @@ -0,0 +1,62 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * close.c + */ + +#include <errno.h> +#include <com32.h> +#include <string.h> +#include "file.h" + +int close(int fd) +{ + struct file_info *fp = &__file_info[fd]; + int rv = 0; + + if (fd >= NFILES || !fp->iop || !fp->oop) { + errno = EBADF; + return -1; + } + + if (fp->iop->close) { + rv = fp->iop->close(fp); + if (rv) + return rv; + } + fp->iop = &dev_error_r; + + if (fp->oop->close) { + rv = fp->oop->close(fp); + if (rv) + return rv; + } + + memset(fp, 0, sizeof *fp); /* File structure unused */ + return 0; +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/colortable.c b/contrib/syslinux-4.02/com32/lib/sys/colortable.c new file mode 100644 index 0000000..ab1c424 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/colortable.c @@ -0,0 +1,9 @@ +#include <colortbl.h> + +static struct color_table default_color_table[] = { + {"default", "0", 0xffffffff, 0x00000000, SHADOW_NORMAL} +}; + +struct color_table *console_color_table = default_color_table; +int console_color_table_size = + (sizeof default_color_table / sizeof(struct color_table)); diff --git a/contrib/syslinux-4.02/com32/lib/sys/entry.S b/contrib/syslinux-4.02/com32/lib/sys/entry.S new file mode 100644 index 0000000..7bfde8b --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/entry.S @@ -0,0 +1,118 @@ +/* ----------------------------------------------------------------------- + * + * Copyright 2003-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. + * + * ----------------------------------------------------------------------- */ + +/* + * COM32 start up code - must be linked first in the binary + */ + +/* Number of arguments in our version of the entry structure */ +#define COM32_ARGS 9 + + .section ".init","ax" + .globl _start + .type _start, @function +_start: + /* This first instruction acts as COM32R magic number */ + movl $0x21cd4cfe,%eax + + /* Upwards string operations */ + cld + + /* Find our own location */ + call 1f +1: popl %ebx + addl $_GLOBAL_OFFSET_TABLE_ + (. - 1b), %ebx + + /* Process relocations (which overlay the .bss segment) */ + leal _edata@GOTOFF(%ebx),%esi + leal _start@GOTOFF(%ebx),%edx +2: lodsl + andl %eax,%eax + jz 3f + addl %edx,(%eax,%edx) + jmp 2b +3: + /* Relocate the GOT (is this right?) */ + leal __got_start@GOTOFF(%ebx),%esi + leal __got_end@GOTOFF(%ebx),%edi +4: + addl %edx,(%esi) + addl $4,%esi + cmpl %edi,%esi + jb 4b + + /* Zero the .bss segment */ + xorl %eax,%eax + leal __bss_start@GOTOFF(%ebx),%edi + leal _end+3@GOTOFF(%ebx),%ecx + subl %edi,%ecx + shrl $2,%ecx + rep ; stosl + + /* Copy COM32 invocation parameters */ + leal 4(%esp),%esi # Argument list + leal __com32@GOTOFF(%ebx),%edi + movl $(COM32_ARGS),%ecx + movl %esp,-4(%edi) # Save the initial stack ptr + cmpl (%esi),%ecx + jbe 5f + movl (%esi),%ecx +5: inc %ecx # Copy the argument count, too + rep ; movsl + + /* Parse the command line (assumes REGPARM) */ + movl __com32+4@GOTOFF(%ebx),%edx # Command line + pushl %edx # Make space for argv + movl %esp,%eax + call __parse_argv + pushl %eax # Save argc + + /* Look for library initialization functions */ + leal __ctors_start@GOTOFF(%ebx),%esi + leal __ctors_end@GOTOFF(%ebx),%edi +6: + cmpl %edi,%esi + jae 7f + call *(%esi) + addl $4,%esi + jmp 6b +/* + * Actually run main. This assumes REGPARM is used!!!! + */ +7: + popl %eax # argc + popl %edx # argv + call main + call *__exit_handler@GOTOFF(%ebx) + hlt + .size _start, .-_start + + .bss + .globl __entry_esp +__entry_esp: .space 4 + .globl __com32 +__com32: .space 4*(COM32_ARGS+1) diff --git a/contrib/syslinux-4.02/com32/lib/sys/err_read.c b/contrib/syslinux-4.02/com32/lib/sys/err_read.c new file mode 100644 index 0000000..22555ca --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/err_read.c @@ -0,0 +1,55 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * err_read.c + * + * Reading from a device which doesn't support reading + */ + +#include <errno.h> +#include <string.h> +#include <com32.h> +#include <minmax.h> +#include "file.h" + +static ssize_t __err_read(struct file_info *fp, void *buf, size_t count) +{ + (void)fp; + (void)buf; + (void)count; + errno = -EINVAL; + return -1; +} + +const struct input_dev dev_error_r = { + .dev_magic = __DEV_MAGIC, + .flags = __DEV_INPUT | __DEV_ERROR, + .fileflags = O_RDONLY, + .read = __err_read, + .close = NULL, +}; diff --git a/contrib/syslinux-4.02/com32/lib/sys/err_write.c b/contrib/syslinux-4.02/com32/lib/sys/err_write.c new file mode 100644 index 0000000..fab60ba --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/err_write.c @@ -0,0 +1,55 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * err_write.c + * + * Writing to a device which doesn't support writing + */ + +#include <errno.h> +#include <string.h> +#include <com32.h> +#include <minmax.h> +#include "file.h" + +static ssize_t __err_write(struct file_info *fp, const void *buf, size_t count) +{ + (void)fp; + (void)buf; + (void)count; + errno = -EINVAL; + return -1; +} + +const struct output_dev dev_error_w = { + .dev_magic = __DEV_MAGIC, + .flags = __DEV_OUTPUT | __DEV_ERROR, + .fileflags = O_WRONLY | O_CREAT | O_TRUNC | O_APPEND, + .write = __err_write, + .close = NULL, +}; diff --git a/contrib/syslinux-4.02/com32/lib/sys/exit.S b/contrib/syslinux-4.02/com32/lib/sys/exit.S new file mode 100644 index 0000000..2ab8012 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/exit.S @@ -0,0 +1,41 @@ +/* + * Implementation of _exit() for com32 based on c32entry.S + */ + .text + + .globl _Exit + .type _Exit, @function +_Exit: + /* Just fall through to _exit */ + .size _Exit, .-_Exit + + .globl _exit + .type _exit, @function +_exit: +#ifdef REGPARM + pushl %eax +#endif + + /* Run any destructors */ + movl $__dtors_start, %esi +2: + cmpl $__dtors_end, %esi + jae 1f + call *(%esi) + addl $4,%esi + jmp 2b + +1: +#ifdef REGPARM + popl %eax +#else + movl 4(%esp),%eax # Exit code in %eax = return value +#endif + movl (__entry_esp),%esp # Return stack pointer to entry value + ret # Return to termination address + .size _exit, .-_exit + + .data +__exit_handler: + .globl __exit_handler + .long _exit diff --git a/contrib/syslinux-4.02/com32/lib/sys/farcall.c b/contrib/syslinux-4.02/com32/lib/sys/farcall.c new file mode 100644 index 0000000..988ee6d --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/farcall.c @@ -0,0 +1,24 @@ +/* + * farcall.c + */ + +#include <com32.h> + +static inline uint32_t eflags(void) +{ + uint32_t v; + + asm volatile("pushfl ; popl %0" : "=rm" (v)); + return v; +} + +void __farcall(uint16_t cs, uint16_t ip, + const com32sys_t * ireg, com32sys_t * oreg) +{ + com32sys_t xreg = *ireg; + + /* Enable interrupts if and only if they are enabled in the caller */ + xreg.eflags.l = (xreg.eflags.l & ~EFLAGS_IF) | (eflags() & EFLAGS_IF); + + __com32.cs_farcall((cs << 16) + ip, &xreg, oreg); +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/file.h b/contrib/syslinux-4.02/com32/lib/sys/file.h new file mode 100644 index 0000000..e984f16 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/file.h @@ -0,0 +1,106 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2003-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. + * + * ----------------------------------------------------------------------- */ + +/* + * file.h + * + * Internal implementation of file I/O for COM32 + */ + +#ifndef _COM32_SYS_FILE_H +#define _COM32_SYS_FILE_H + +#include <inttypes.h> +#include <stdlib.h> +#include <sys/types.h> +#include <dev.h> +#include <fcntl.h> +#include <syslinux/pmapi.h> + +/* Device structure; contains the relevant operations */ + +struct file_info; + +#define __DEV_MAGIC 0xf4e7 +#define __DEV_TTY 0x0001 /* TTY - must be bit 0 */ +#define __DEV_FILE 0x0002 /* Ordinary file */ +#define __DEV_OUTPUT 0x0004 /* This is an output device */ +#define __DEV_INPUT 0 /* Dummy */ +#define __DEV_ERROR 0x0008 /* This is the error device */ +#define __DEV_NULL 0x0010 /* This is the null device */ + +struct input_dev { + uint16_t dev_magic; /* Magic number */ + uint16_t flags; /* Flags */ + int fileflags; /* Permitted file flags */ + ssize_t (*read)(struct file_info *, void *, size_t); + int (*close)(struct file_info *); + int (*open)(struct file_info *); +}; + +struct output_dev { + uint16_t dev_magic; /* Magic number */ + uint16_t flags; /* Flags */ + int fileflags; + ssize_t (*write)(struct file_info *, const void *, size_t); + int (*close)(struct file_info *); + int (*open)(struct file_info *); + const struct output_dev *fallback; /* Fallback option for certain consoles */ +}; + +/* File structure */ + +#define NFILES 32 /* Number of files to support */ +#define MAXBLOCK 16384 /* Defined by ABI */ + +struct file_info { + const struct input_dev *iop; /* Input operations */ + const struct output_dev *oop; /* Output operations */ + + /* Output file data */ + struct { + int rows, cols; /* Rows and columns */ + } o; + + /* Structure used for input blocking */ + struct { + struct com32_filedata fd; + size_t offset; /* Current file offset */ + size_t nbytes; /* Number of bytes available in buffer */ + char *datap; /* Current data pointer */ + void *pvt; /* Private pointer for driver */ + char buf[MAXBLOCK]; + } i; +}; + +extern struct file_info __file_info[NFILES]; + +/* Line input discipline */ +ssize_t __line_input(struct file_info *fp, char *buf, size_t bufsize, + ssize_t(*get_char) (struct file_info *, void *, size_t)); + +#endif /* _COM32_SYS_FILE_H */ diff --git a/contrib/syslinux-4.02/com32/lib/sys/fileclose.c b/contrib/syslinux-4.02/com32/lib/sys/fileclose.c new file mode 100644 index 0000000..e2c929f --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/fileclose.c @@ -0,0 +1,45 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * fileclose.c + * + * Close an ordinary file + */ + +#include <errno.h> +#include <com32.h> +#include <string.h> +#include "file.h" + +int __file_close(struct file_info *fp) +{ + if (fp->i.fd.handle) + __com32.cs_pm->close_file(fp->i.fd.handle); + + return 0; +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/fileinfo.c b/contrib/syslinux-4.02/com32/lib/sys/fileinfo.c new file mode 100644 index 0000000..a1fc7c9 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/fileinfo.c @@ -0,0 +1,3 @@ +#include "file.h" + +struct file_info __file_info[NFILES]; diff --git a/contrib/syslinux-4.02/com32/lib/sys/fileread.c b/contrib/syslinux-4.02/com32/lib/sys/fileread.c new file mode 100644 index 0000000..aab99c8 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/fileread.c @@ -0,0 +1,98 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * read.c + * + * Reading from a file + */ + +#include <errno.h> +#include <string.h> +#include <com32.h> +#include <syslinux/pmapi.h> +#include <minmax.h> +#include "file.h" + +int __file_get_block(struct file_info *fp) +{ + ssize_t bytes_read; + + bytes_read = __com32.cs_pm->read_file(&fp->i.fd.handle, fp->i.buf, + MAXBLOCK >> fp->i.fd.blocklg2); + if (!bytes_read) { + errno = EIO; + return -1; + } + + fp->i.nbytes = bytes_read; + fp->i.datap = fp->i.buf; + return 0; +} + +ssize_t __file_read(struct file_info * fp, void *buf, size_t count) +{ + char *bufp = buf; + ssize_t n = 0; + size_t ncopy; + + while (count) { + if (fp->i.nbytes == 0) { + if (fp->i.offset >= fp->i.fd.size || !fp->i.fd.handle) + return n; /* As good as it gets... */ + + if (count > MAXBLOCK) { + /* Large transfer: copy directly, without buffering */ + ncopy = __com32.cs_pm->read_file(&fp->i.fd.handle, bufp, + count >> fp->i.fd.blocklg2); + if (!ncopy) { + errno = EIO; + return n ? n : -1; + } + + goto got_data; + } else { + if (__file_get_block(fp)) + return n ? n : -1; + } + } + + ncopy = min(count, fp->i.nbytes); + memcpy(bufp, fp->i.datap, ncopy); + + fp->i.datap += ncopy; + fp->i.offset += ncopy; + fp->i.nbytes -= ncopy; + + got_data: + n += ncopy; + bufp += ncopy; + count -= ncopy; + } + + return n; +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/fstat.c b/contrib/syslinux-4.02/com32/lib/sys/fstat.c new file mode 100644 index 0000000..0ce8cad --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/fstat.c @@ -0,0 +1,63 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2005-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. + * + * ----------------------------------------------------------------------- */ + +/* + * fstat.c + * + * Very trivial fstat emulation + */ + +#include <sys/stat.h> +#include <errno.h> +#include "file.h" + +int fstat(int fd, struct stat *buf) +{ + struct file_info *fp = &__file_info[fd]; + + if (fd >= NFILES || !fp->iop) { + errno = EBADF; + return -1; + } + + if (fp->iop->flags & __DEV_FILE) { + if (fp->i.fd.size == (uint32_t) - 1) { + /* File of unknown length, report it as a socket + (it probably really is, anyway!) */ + buf->st_mode = S_IFSOCK | 0444; + buf->st_size = 0; + } else { + buf->st_mode = S_IFREG | 0444; + buf->st_size = fp->i.fd.size; + } + } else { + buf->st_mode = S_IFCHR | 0666; + buf->st_size = 0; + } + + return 0; +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/ftell.c b/contrib/syslinux-4.02/com32/lib/sys/ftell.c new file mode 100644 index 0000000..5c1a944 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/ftell.c @@ -0,0 +1,16 @@ +/* + * sys/ftell.c + * + * We can't seek, but we can at least tell... + */ + +#include <stdio.h> +#include "sys/file.h" + +long ftell(FILE * stream) +{ + int fd = fileno(stream); + struct file_info *fp = &__file_info[fd]; + + return fp->i.offset; +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/gpxe.c b/contrib/syslinux-4.02/com32/lib/sys/gpxe.c new file mode 100644 index 0000000..d86da42 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/gpxe.c @@ -0,0 +1,50 @@ +#include <sys/gpxe.h> +#include <syslinux/config.h> +#include <string.h> + +bool is_gpxe(void) +{ + const struct syslinux_version *sv; + com32sys_t reg; + struct s_PXENV_FILE_CHECK_API *fca; + bool gpxe; + + sv = syslinux_version(); + if (sv->filesystem != SYSLINUX_FS_PXELINUX) + return false; /* Not PXELINUX */ + + fca = lzalloc(sizeof *fca); + if (!fca) + return false; + fca->Size = sizeof *fca; + fca->Magic = 0x91d447b2; + + memset(®, 0, sizeof reg); + reg.eax.w[0] = 0x0009; + reg.ebx.w[0] = 0x00e6; /* PXENV_FILE_API_CHECK */ + /* reg.edi.w[0] = OFFS(fca); */ + reg.es = SEG(fca); + + __intcall(0x22, ®, ®); + + gpxe = true; + + if (reg.eflags.l & EFLAGS_CF) + gpxe = false; /* Cannot invoke PXE stack */ + + if (reg.eax.w[0] || fca->Status) + gpxe = false; /* PXE failure */ + + if (fca->Magic != 0xe9c17b20) + gpxe = false; /* Incorrect magic */ + + if (fca->Size < sizeof *fca) + gpxe = false; /* Short return */ + + /* XXX: The APIs to test for should be a passed-in option */ + if (!(fca->APIMask & (1 << 5))) + gpxe = false; /* No FILE EXEC */ + + lfree(fca); + return gpxe; +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/intcall.c b/contrib/syslinux-4.02/com32/lib/sys/intcall.c new file mode 100644 index 0000000..e97a384 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/intcall.c @@ -0,0 +1,10 @@ +/* + * intcall.c + */ + +#include <com32.h> + +void __intcall(uint8_t vector, const com32sys_t * ireg, com32sys_t * oreg) +{ + __com32.cs_intcall(vector, ireg, oreg); +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/isatty.c b/contrib/syslinux-4.02/com32/lib/sys/isatty.c new file mode 100644 index 0000000..d80214a --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/isatty.c @@ -0,0 +1,53 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * isatty.c + * + * Return if this is a tty or not + */ + +#include <errno.h> +#include <string.h> +#include <com32.h> +#include <minmax.h> +#include <unistd.h> +#include <klibc/compiler.h> +#include "file.h" + +int isatty(int fd) +{ + struct file_info *fp = &__file_info[fd]; + + if (fd >= NFILES || !fp->iop) { + errno = EBADF; + return -1; + } + + /* __DEV_TTY == 1 */ + return (fp->iop->flags & __DEV_TTY); +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/libansi.c b/contrib/syslinux-4.02/com32/lib/sys/libansi.c new file mode 100644 index 0000000..a011cb8 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/libansi.c @@ -0,0 +1,247 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Erwan Velu - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- + * Ansi Sequences can be found here : + * http://ascii-table.com/ansi-escape-sequences-vt-100.php + * http://en.wikipedia.org/wiki/ANSI_escape_code + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdbool.h> +#include <stdint.h> + +#include "libansi.h" + +void display_cursor(bool status) +{ + if (status == true) { + fputs(CSI "?25h", stdout); + } else { + fputs(CSI "?25l", stdout); + } +} + +void clear_end_of_line(void) +{ + fputs(CSI "0K", stdout); +} + +void move_cursor_left(int count) +{ + char buffer[10]; + memset(buffer,0,sizeof(buffer)); + sprintf(buffer,CSI "%dD",count); + fputs(buffer, stdout); +} + +void move_cursor_right(int count) +{ + char buffer[10]; + memset(buffer,0,sizeof(buffer)); + sprintf(buffer, CSI "%dC", count); + fputs(buffer, stdout); +} + +void set_cursor_blink(bool status) { + if (status == true) + fputs("\033[05m",stdout); + else + fputs("\033[0m",stdout); +} + +void clear_line(void) +{ + fputs(CSI "2K", stdout); +} + +void clear_beginning_of_line(void) +{ + fputs(CSI "1K", stdout); +} + +void move_cursor_to_column(int count) +{ + char buffer[10]; + memset(buffer,0,sizeof(buffer)); + sprintf(buffer, CSI "%dG", count); + fputs(buffer, stdout); +} + +void move_cursor_to_next_line(void) +{ + fputs("\033e", stdout); +} + +void disable_utf8(void) +{ + fputs("\033%@", stdout); +} + +void set_g1_special_char(void){ + fputs("\033)0", stdout); +} + +void set_us_g0_charset(void) +{ + fputs("\033(B\1#0", stdout); +} + +void clear_entire_screen(void) +{ + fputs(CSI "2J", stdout); +} + +/** + * cprint_vga2ansi - given a VGA attribute, print a character + * @chr: character to print + * @attr: vga attribute + * + * Convert the VGA attribute @attr to an ANSI escape sequence and + * print it. + * For performance, SGR parameters are cached. To reset them, + * call cprint_vga2ansi('0', '0'). + **/ +static void cprint_vga2ansi(const char chr, const char attr) +{ + static const char ansi_char[8] = "04261537"; + static uint16_t last_attr = 0x300; + char buf[16], *p; + + if (chr == '0' && attr == '0') { + last_attr = 0x300; + return; + } + + if (attr != last_attr) { + bool reset = false; + p = buf; + *p++ = '\033'; + *p++ = '['; + + if (last_attr & ~attr & 0x88) { + *p++ = '0'; + *p++ = ';'; + /* Reset last_attr to unknown to handle + * background/foreground attributes correctly */ + last_attr = 0x300; + reset = true; + } + if (attr & 0x08) { + *p++ = '1'; + *p++ = ';'; + } + if (attr & 0x80) { + *p++ = '4'; + *p++ = ';'; + } + if (reset || (attr ^ last_attr) & 0x07) { + *p++ = '3'; + *p++ = ansi_char[attr & 7]; + *p++ = ';'; + } + if (reset || (attr ^ last_attr) & 0x70) { + *p++ = '4'; + *p++ = ansi_char[(attr >> 4) & 7]; + *p++ = ';'; + } + p[-1] = 'm'; /* We'll have generated at least one semicolon */ + p[0] = '\0'; + + last_attr = attr; + + fputs(buf, stdout); + } + + putchar(chr); +} + +/* + * cls - clear and initialize the entire screen + * + * Note: when initializing xterm, one has to specify that + * G1 points to the alternate character set (this is not true + * by default). Without the initial printf "\033)0", line drawing + * characters won't be displayed. + */ +void cls(void) +{ + fputs("\033e\033%@\033)0\033(B\1#0\033[?25l\033[2J", stdout); + + /* Reset SGR parameters cache */ + cprint_vga2ansi('0', '0'); +} + +void reset_colors(void) +{ + csprint(CSI "1D", 0x07); +} + +/** + * cprint - given a VGA attribute, print a single character at cursor + * @chr: character to print + * @attr: VGA attribute + * @times: number of times to print @chr + * + * Note: @attr is a VGA attribute. + **/ +void cprint(const char chr, const char attr, unsigned int times) +{ + while (times--) + cprint_vga2ansi(chr, attr); +} + +/** + * csprint - given a VGA attribute, print a NULL-terminated string + * @str: string to print + * @attr: VGA attribute + **/ +void csprint(const char *str, const char attr) +{ + while (*str) { + cprint(*str, attr, 1); + str++; + } +} + +/** + * clearwindow - fill a given a region on the screen + * @top, @left, @bot, @right: coordinates to fill + * @fillchar: character to use to fill the region + * @fillattr: character attribute (VGA) + **/ +void clearwindow(const char top, const char left, const char bot, + const char right, const char fillchar, const char fillattr) +{ + char x; + for (x = top; x < bot + 1; x++) { + gotoxy(x, left); + cprint(fillchar, fillattr, right - left + 1); + } +} + + diff --git a/contrib/syslinux-4.02/com32/lib/sys/line_input.c b/contrib/syslinux-4.02/com32/lib/sys/line_input.c new file mode 100644 index 0000000..a8c9926 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/line_input.c @@ -0,0 +1,90 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * line_input.c + * + * Line-oriented input discupline + */ + +#include "file.h" +#include <errno.h> +#include <syslinux/idle.h> + +ssize_t __line_input(struct file_info * fp, char *buf, size_t bufsize, + ssize_t(*get_char) (struct file_info *, void *, size_t)) +{ + size_t n = 0; + char ch; + int rv; + ssize_t(*const Write) (struct file_info *, const void *, size_t) = + fp->oop->write; + + for (;;) { + rv = get_char(fp, &ch, 1); + + if (rv != 1) { + syslinux_idle(); + continue; + } + + switch (ch) { + case '\n': /* Ignore incoming linefeed */ + break; + + case '\r': + *buf = '\n'; + Write(fp, "\n", 1); + return n + 1; + + case '\b': + if (n > 0) { + n--; + buf--; + Write(fp, "\b \b", 3); + } + break; + + case '\x15': /* Ctrl-U */ + while (n) { + n--; + buf--; + Write(fp, "\b \b", 3); + } + break; + + default: + if (n < bufsize - 1) { + *buf = ch; + Write(fp, buf, 1); + n++; + buf++; + } + break; + } + } +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/null_read.c b/contrib/syslinux-4.02/com32/lib/sys/null_read.c new file mode 100644 index 0000000..e0037c5 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/null_read.c @@ -0,0 +1,54 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * null_read.c + * + * Reading null device + */ + +#include <errno.h> +#include <string.h> +#include <com32.h> +#include <minmax.h> +#include "file.h" + +static ssize_t __null_read(struct file_info *fp, void *buf, size_t count) +{ + (void)fp; + (void)buf; + (void)count; + return 0; +} + +const struct input_dev dev_null_r = { + .dev_magic = __DEV_MAGIC, + .flags = __DEV_INPUT | __DEV_NULL, + .fileflags = O_RDONLY, + .read = __null_read, + .close = NULL, +}; diff --git a/contrib/syslinux-4.02/com32/lib/sys/null_write.c b/contrib/syslinux-4.02/com32/lib/sys/null_write.c new file mode 100644 index 0000000..a29b213 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/null_write.c @@ -0,0 +1,54 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * null_write.c + * + * Null writing device + */ + +#include <errno.h> +#include <string.h> +#include <com32.h> +#include <minmax.h> +#include "file.h" + +static ssize_t __null_write(struct file_info *fp, const void *buf, size_t count) +{ + (void)fp; + (void)buf; + (void)count; + return count; +} + +const struct output_dev dev_null_w = { + .dev_magic = __DEV_MAGIC, + .flags = __DEV_OUTPUT | __DEV_NULL, + .fileflags = O_WRONLY | O_CREAT | O_TRUNC | O_APPEND, + .write = __null_write, + .close = NULL, +}; diff --git a/contrib/syslinux-4.02/com32/lib/sys/open.c b/contrib/syslinux-4.02/com32/lib/sys/open.c new file mode 100644 index 0000000..cb7c1b4 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/open.c @@ -0,0 +1,73 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2003-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. + * + * ----------------------------------------------------------------------- */ + +#include <errno.h> +#include <com32.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include "file.h" + +/* + * open.c + * + * Open an ordinary file + */ + +extern ssize_t __file_read(struct file_info *, void *, size_t); +extern int __file_close(struct file_info *); + +const struct input_dev __file_dev = { + .dev_magic = __DEV_MAGIC, + .flags = __DEV_FILE | __DEV_INPUT, + .fileflags = O_RDONLY, + .read = __file_read, + .close = __file_close, + .open = NULL, +}; + +int open(const char *pathname, int flags, ...) +{ + int fd, handle; + struct file_info *fp; + + fd = opendev(&__file_dev, NULL, flags); + + if (fd < 0) + return -1; + + fp = &__file_info[fd]; + + handle = __com32.cs_pm->open_file(pathname, &fp->i.fd); + if (handle < 0) + return -1; + + fp->i.offset = 0; + fp->i.nbytes = 0; + + return fd; +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/openconsole.c b/contrib/syslinux-4.02/com32/lib/sys/openconsole.c new file mode 100644 index 0000000..3c7567b --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/openconsole.c @@ -0,0 +1,51 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * openconsole.c + * + * Open the chosen console device + */ + +#include <unistd.h> +#include <console.h> +#include <fcntl.h> + +int openconsole(const struct input_dev *idev, const struct output_dev *odev) +{ + close(0); + if (opendev(idev, odev, O_RDONLY) != 0) + return -1; + close(1); + if (opendev(idev, odev, O_WRONLY) != 1) + return -1; + close(2); + if (opendev(idev, odev, O_WRONLY) != 2) + return -1; + + return 0; +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/opendev.c b/contrib/syslinux-4.02/com32/lib/sys/opendev.c new file mode 100644 index 0000000..1df9d07 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/opendev.c @@ -0,0 +1,99 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2003-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. + * + * ----------------------------------------------------------------------- */ + +#include <errno.h> +#include <com32.h> +#include <string.h> +#include <unistd.h> +#include "file.h" + +/* + * opendev.c + * + * Open a special device + */ + +int opendev(const struct input_dev *idev, + const struct output_dev *odev, int flags) +{ + int fd; + struct file_info *fp; + int okflags; + int e; + + okflags = (idev ? idev->fileflags : 0) | (odev ? odev->fileflags : 0); + + if (!(flags & 3) || (flags & ~okflags)) { + errno = EINVAL; + return -1; + } + + for (fd = 0, fp = __file_info; fd < NFILES; fd++, fp++) + if (!fp->iop && !fp->oop) + break; + + if (fd >= NFILES) { + errno = EMFILE; + return -1; + } + + /* The file structure is already zeroed */ + fp->iop = &dev_error_r; + fp->oop = &dev_error_w; + fp->i.datap = fp->i.buf; + + if (idev) { + if (idev->open && (e = idev->open(fp))) { + errno = e; + goto puke; + } + fp->iop = idev; + } + + while (odev) { + if (odev->open && (e = odev->open(fp))) { + if (e == EAGAIN) { + if (odev->fallback) { + odev = odev->fallback; + continue; + } else { + e = EIO; + } + } + errno = e; + goto puke; + } + fp->oop = odev; + break; + } + + return fd; + +puke: + close(fd); + return -1; +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/openmem.c b/contrib/syslinux-4.02/com32/lib/sys/openmem.c new file mode 100644 index 0000000..a56a4af --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/openmem.c @@ -0,0 +1,61 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2003-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. + * + * ----------------------------------------------------------------------- */ + +#include <errno.h> +#include <com32.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include "file.h" + +/* + * openmem.c + * + * Open a chunk of memory as if it was a file + */ + +const struct input_dev __file_dev; + +int openmem(const void *base, size_t len, int flags) +{ + int fd; + struct file_info *fp; + + fd = opendev(&__file_dev, NULL, flags); + + if (fd < 0) + return -1; + + fp = &__file_info[fd]; + + fp->i.fd.size = fp->i.nbytes = len; + fp->i.datap = (void *)base; + fp->i.fd.handle = 0; /* No actual file */ + fp->i.offset = 0; + + return fd; +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/rawcon_read.c b/contrib/syslinux-4.02/com32/lib/sys/rawcon_read.c new file mode 100644 index 0000000..92c9b29 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/rawcon_read.c @@ -0,0 +1,80 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * rawcon_read.c + * + * Character-oriented reading from the console without echo; + * this is a NONBLOCKING device. + */ + +#include <errno.h> +#include <string.h> +#include <com32.h> +#include <minmax.h> +#include <sys/times.h> +#include "file.h" + +/* Global, since it's used by stdcon_read */ +ssize_t __rawcon_read(struct file_info *fp, void *buf, size_t count) +{ + com32sys_t ireg, oreg; + char *bufp = buf; + size_t n = 0; + clock_t start; + + (void)fp; + + memset(&ireg, 0, sizeof ireg); + + start = times(NULL); + + while (n < count) { + /* Poll */ + ireg.eax.b[1] = 0x0B; + __intcall(0x21, &ireg, &oreg); + if (!oreg.eax.b[0]) + break; + + /* We have data, go get it */ + ireg.eax.b[1] = 0x08; + __intcall(0x21, &ireg, &oreg); + *bufp++ = oreg.eax.b[0]; + n++; + } + + return n; +} + +const struct input_dev dev_rawcon_r = { + .dev_magic = __DEV_MAGIC, + .flags = __DEV_TTY | __DEV_INPUT, + .fileflags = O_RDONLY, + .read = __rawcon_read, + .close = NULL, + .open = NULL, +}; diff --git a/contrib/syslinux-4.02/com32/lib/sys/rawcon_write.c b/contrib/syslinux-4.02/com32/lib/sys/rawcon_write.c new file mode 100644 index 0000000..2d45a7b --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/rawcon_write.c @@ -0,0 +1,67 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * rawcon_write.c + * + * Raw writing to the console; no \n -> \r\n translation + */ + +#include <errno.h> +#include <string.h> +#include <com32.h> +#include <minmax.h> +#include "file.h" + +static ssize_t __rawcon_write(struct file_info *fp, const void *buf, + size_t count) +{ + com32sys_t ireg; + const char *bufp = buf; + size_t n = 0; + + (void)fp; + + memset(&ireg, 0, sizeof ireg); + ireg.eax.b[1] = 0x02; + + while (count--) { + ireg.edx.b[0] = *bufp++; + __intcall(0x21, &ireg, NULL); + n++; + } + + return n; +} + +const struct output_dev dev_rawcon_w = { + .dev_magic = __DEV_MAGIC, + .flags = __DEV_TTY | __DEV_OUTPUT, + .fileflags = O_WRONLY | O_CREAT | O_TRUNC | O_APPEND, + .write = __rawcon_write, + .close = NULL, +}; diff --git a/contrib/syslinux-4.02/com32/lib/sys/read.c b/contrib/syslinux-4.02/com32/lib/sys/read.c new file mode 100644 index 0000000..e097ade --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/read.c @@ -0,0 +1,51 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * read.c + * + * Reading from a file descriptor + */ + +#include <errno.h> +#include <string.h> +#include <com32.h> +#include <minmax.h> +#include <klibc/compiler.h> +#include "file.h" + +ssize_t read(int fd, void *buf, size_t count) +{ + struct file_info *fp = &__file_info[fd]; + + if (fd >= NFILES || !fp->iop) { + errno = EBADF; + return -1; + } + + return fp->iop->read(fp, buf, count); +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/readdir.c b/contrib/syslinux-4.02/com32/lib/sys/readdir.c new file mode 100644 index 0000000..d2a8c03 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/readdir.c @@ -0,0 +1,30 @@ +/* + * readdir.c + */ + +#include <dirent.h> +#include <stdio.h> +#include <errno.h> + +#include <com32.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <stdlib.h> + +#include <syslinux/pmapi.h> + +DIR *opendir(const char *pathname) +{ + return __com32.cs_pm->opendir(pathname); +} + +struct dirent *readdir(DIR *dir) +{ + return __com32.cs_pm->readdir(dir); +} + +int closedir(DIR *dir) +{ + return __com32.cs_pm->closedir(dir); +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/screensize.c b/contrib/syslinux-4.02/com32/lib/sys/screensize.c new file mode 100644 index 0000000..340227c --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/screensize.c @@ -0,0 +1,23 @@ +#include <unistd.h> +#include <errno.h> +#include "file.h" + +int getscreensize(int fd, int *rows, int *cols) +{ + struct file_info *fp = &__file_info[fd]; + + if (fd >= NFILES || !fp->iop) { + errno = EBADF; + return -1; + } + + *rows = fp->o.rows; + *cols = fp->o.cols; + + if (!rows || !cols) { + errno = ENOTTY; + return -1; + } + + return 0; +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/serial_write.c b/contrib/syslinux-4.02/com32/lib/sys/serial_write.c new file mode 100644 index 0000000..fa0f4f4 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/serial_write.c @@ -0,0 +1,71 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * serial_write.c + * + * Raw writing to the serial port; no \n -> \r\n translation + */ + +#include <errno.h> +#include <string.h> +#include <com32.h> +#include <minmax.h> +#include <syslinux/config.h> +#include "file.h" + +ssize_t __serial_write(struct file_info *fp, const void *buf, size_t count) +{ + com32sys_t ireg; + const char *bufp = buf; + size_t n = 0; + + (void)fp; + + if (!syslinux_serial_console_info()->iobase) + return count; /* Nothing to do */ + + memset(&ireg, 0, sizeof ireg); + ireg.eax.b[1] = 0x04; + + while (count--) { + ireg.edx.b[0] = *bufp++; + __intcall(0x21, &ireg, NULL); + n++; + } + + return n; +} + +const struct output_dev dev_serial_w = { + .dev_magic = __DEV_MAGIC, + .flags = __DEV_TTY | __DEV_OUTPUT, + .fileflags = O_WRONLY | O_CREAT | O_TRUNC | O_APPEND, + .write = __serial_write, + .close = NULL, + .open = NULL, +}; diff --git a/contrib/syslinux-4.02/com32/lib/sys/sleep.c b/contrib/syslinux-4.02/com32/lib/sys/sleep.c new file mode 100644 index 0000000..8a51c1c --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/sleep.c @@ -0,0 +1,22 @@ +/* + * sys/sleep.c + */ + +#include <unistd.h> +#include <sys/times.h> +#include <syslinux/idle.h> + +unsigned int msleep(unsigned int msec) +{ + clock_t start = times(NULL); + + while (times(NULL) - start < msec) + syslinux_idle(); + + return 0; +} + +unsigned int sleep(unsigned int seconds) +{ + return msleep(seconds * 1000); +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/stdcon_read.c b/contrib/syslinux-4.02/com32/lib/sys/stdcon_read.c new file mode 100644 index 0000000..967e564 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/stdcon_read.c @@ -0,0 +1,76 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * stdcon_read.c + * + * Line-oriented reading from the standard console + */ + +#include <errno.h> +#include <string.h> +#include <com32.h> +#include <minmax.h> +#include "file.h" + +extern ssize_t __rawcon_read(struct file_info *fp, void *buf, size_t count); + +static ssize_t __stdcon_read(struct file_info *fp, void *buf, size_t count) +{ + char *bufp = buf; + size_t n = 0; + char ch; + + (void)fp; + + while (n < count) { + if (fp->i.nbytes) { + ch = *bufp++ = *fp->i.datap++; + fp->i.nbytes--; + n++; + if (ch == '\n') + return n; + } else { + fp->i.nbytes = __line_input(fp, fp->i.buf, MAXBLOCK, __rawcon_read); + fp->i.datap = fp->i.buf; + + if (fp->i.nbytes == 0) + return n; + } + } + + return n; +} + +const struct input_dev dev_stdcon_r = { + .dev_magic = __DEV_MAGIC, + .flags = __DEV_TTY | __DEV_INPUT, + .fileflags = O_RDONLY, + .read = __stdcon_read, + .close = NULL, + .open = NULL, +}; diff --git a/contrib/syslinux-4.02/com32/lib/sys/stdcon_write.c b/contrib/syslinux-4.02/com32/lib/sys/stdcon_write.c new file mode 100644 index 0000000..9cb2f7d --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/stdcon_write.c @@ -0,0 +1,89 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * stdcon_write.c + * + * Writing to the console; \n -> \r\n conversion. + */ + +#include <errno.h> +#include <string.h> +#include <com32.h> +#include <minmax.h> +#include "file.h" + +#define BIOS_ROWS (*(uint8_t *)0x484) /* Minus one; if zero use 24 (= 25 lines) */ +#define BIOS_COLS (*(uint16_t *)0x44A) + +static int __stdcon_open(struct file_info *fp) +{ + fp->o.rows = BIOS_ROWS + 1; + fp->o.cols = BIOS_COLS; + + /* Sanity check */ + if (fp->o.rows < 12) + fp->o.rows = 24; + if (fp->o.cols < 40) + fp->o.cols = 80; + + return 0; +} + +static ssize_t __stdcon_write(struct file_info *fp, const void *buf, + size_t count) +{ + com32sys_t ireg; + const char *bufp = buf; + size_t n = 0; + + (void)fp; + + memset(&ireg, 0, sizeof ireg); + ireg.eax.b[1] = 0x02; + + while (count--) { + if (*bufp == '\n') { + ireg.edx.b[0] = '\r'; + __intcall(0x21, &ireg, NULL); + } + ireg.edx.b[0] = *bufp++; + __intcall(0x21, &ireg, NULL); + n++; + } + + return n; +} + +const struct output_dev dev_stdcon_w = { + .dev_magic = __DEV_MAGIC, + .flags = __DEV_TTY | __DEV_OUTPUT, + .fileflags = O_WRONLY | O_CREAT | O_TRUNC | O_APPEND, + .write = __stdcon_write, + .close = NULL, + .open = __stdcon_open, +}; diff --git a/contrib/syslinux-4.02/com32/lib/sys/times.c b/contrib/syslinux-4.02/com32/lib/sys/times.c new file mode 100644 index 0000000..dd063f3 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/times.c @@ -0,0 +1,42 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * sys/times.c + * + * Returns something like a clock. + */ + +#include <sys/times.h> +#include <syslinux/pmapi.h> +#include <com32.h> + +clock_t times(struct tms * buf) +{ + (void)buf; + return *__com32.cs_pm->ms_timer; +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/vesa/alphatbl.pl b/contrib/syslinux-4.02/com32/lib/sys/vesa/alphatbl.pl new file mode 100644 index 0000000..d70c76e --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/vesa/alphatbl.pl @@ -0,0 +1,53 @@ +#!/usr/bin/perl +# +# Produce gamma-correction tables for alpha blending, assuming sRGB space. +# + +sub srgb_to_linear($) +{ + my($s) = @_; + + if ($s <= 10) { + return $s/(255*12.92); + } else { + return (($s+14.025)/269.025)**2.4; + } +} + +sub linear_to_srgb($) +{ + my($l) = @_; + my $s; + + if ($l <= 0.00304) { + $s = 12.92*$l; + } else { + $s = 1.055*$l**(1.0/2.4) - 0.055; + } + + return int($s*255+0.5); +} + +# Header +print "#include <inttypes.h>\n\n"; + +# +# Table 1: convert 8-bit sRGB values to 16-bit linear values +# + +print "const uint16_t __vesacon_srgb_to_linear[256] = {\n"; +for ($i = 0; $i <= 255; $i++) { + printf "\t%5d,\n", int(srgb_to_linear($i)*65535+0.5); +} +print "};\n\n"; + +# +# Table 2: convert linear values in the range [0, 65535*255], +# shifted right by 12 bits, to sRGB +# + +print "const uint8_t __vesacon_linear_to_srgb[4080] = {\n"; +for ($i = 0; $i <= 4079; $i++) { + printf "\t%3d,\n", linear_to_srgb(($i+0.5)/4079.937744); +} +print "};\n\n"; diff --git a/contrib/syslinux-4.02/com32/lib/sys/vesa/background.c b/contrib/syslinux-4.02/com32/lib/sys/vesa/background.c new file mode 100644 index 0000000..9357746 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/vesa/background.c @@ -0,0 +1,456 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2006-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. + * + * ----------------------------------------------------------------------- */ + +#include <stdio.h> +#include <png.h> +#include <tinyjpeg.h> +#include <com32.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <minmax.h> +#include <stdbool.h> +#include <ilog2.h> +#include <syslinux/loadfile.h> +#include "vesa.h" +#include "video.h" + +/*** FIX: This really should be alpha-blended with color index 0 ***/ + +/* For best performance, "start" should be a multiple of 4, to assure + aligned dwords. */ +static void draw_background_line(int line, int start, int npixels) +{ + uint32_t *bgptr = &__vesacon_background[line*__vesa_info.mi.h_res+start]; + unsigned int bytes_per_pixel = __vesacon_bytes_per_pixel; + size_t fbptr = line * __vesa_info.mi.logical_scan + start*bytes_per_pixel; + + __vesacon_copy_to_screen(fbptr, bgptr, npixels); +} + +/* This draws the border, then redraws the text area */ +static void draw_background(void) +{ + int i; + const int bottom_border = VIDEO_BORDER + + (TEXT_PIXEL_ROWS % __vesacon_font_height); + const int right_border = VIDEO_BORDER + (TEXT_PIXEL_COLS % FONT_WIDTH); + + for (i = 0; i < VIDEO_BORDER; i++) + draw_background_line(i, 0, __vesa_info.mi.h_res); + + for (i = VIDEO_BORDER; i < __vesa_info.mi.v_res - bottom_border; i++) { + draw_background_line(i, 0, VIDEO_BORDER); + draw_background_line(i, __vesa_info.mi.h_res - right_border, + right_border); + } + + for (i = __vesa_info.mi.v_res - bottom_border; + i < __vesa_info.mi.v_res; i++) + draw_background_line(i, 0, __vesa_info.mi.h_res); + + __vesacon_redraw_text(); +} + +/* + * Tile an image in the UL corner across the entire screen + */ +static void tile_image(int width, int height) +{ + int xsize = __vesa_info.mi.h_res; + int ysize = __vesa_info.mi.v_res; + int x, y, yr; + int xl, yl; + uint32_t *sp, *dp, *drp, *dtp; + + drp = __vesacon_background; + for (y = 0 ; y < ysize ; y += height) { + yl = min(height, ysize-y); + dtp = drp; + for (x = 0 ; x < xsize ; x += width) { + xl = min(width, xsize-x); + if (x || y) { + sp = __vesacon_background; + dp = dtp; + for (yr = 0 ; yr < yl ; yr++) { + memcpy(dp, sp, xl*sizeof(uint32_t)); + dp += xsize; + sp += xsize; + } + } + dtp += xl; + } + drp += xsize*height; + } +} + +static int read_png_file(FILE * fp) +{ + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; +#if 0 + png_color_16p image_background; + static const png_color_16 my_background = { 0, 0, 0, 0, 0 }; +#endif + png_bytep row_pointers[__vesa_info.mi.v_res], rp; + int i; + int rv = -1; + + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + info_ptr = png_create_info_struct(png_ptr); + + if (!png_ptr || !info_ptr || setjmp(png_jmpbuf(png_ptr))) + goto err; + + png_init_io(png_ptr, fp); + png_set_sig_bytes(png_ptr, 8); + + png_set_user_limits(png_ptr, __vesa_info.mi.h_res, __vesa_info.mi.v_res); + + png_read_info(png_ptr, info_ptr); + + /* Set the appropriate set of transformations. We need to end up + with 32-bit BGRA format, no more, no less. */ + + /* Expand to RGB first... */ + if (info_ptr->color_type & PNG_COLOR_MASK_PALETTE) + png_set_palette_to_rgb(png_ptr); + else if (!(info_ptr->color_type & PNG_COLOR_MASK_COLOR)) + png_set_gray_to_rgb(png_ptr); + + /* Add alpha channel, if need be */ + if (!(png_ptr->color_type & PNG_COLOR_MASK_ALPHA)) { + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) + png_set_tRNS_to_alpha(png_ptr); + else + png_set_add_alpha(png_ptr, ~0, PNG_FILLER_AFTER); + } + + /* Adjust the byte order, if necessary */ + png_set_bgr(png_ptr); + + /* Make sure we end up with 8-bit data */ + if (info_ptr->bit_depth == 16) + png_set_strip_16(png_ptr); + else if (info_ptr->bit_depth < 8) + png_set_packing(png_ptr); + +#if 0 + if (png_get_bKGD(png_ptr, info_ptr, &image_background)) + png_set_background(png_ptr, image_background, + PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); + else + png_set_background(png_ptr, &my_background, + PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); +#endif + + /* Whew! Now we should get the stuff we want... */ + rp = (png_bytep)__vesacon_background; + for (i = 0; i < (int)info_ptr->height; i++) { + row_pointers[i] = rp; + rp += __vesa_info.mi.h_res << 2; + } + + png_read_image(png_ptr, row_pointers); + + tile_image(info_ptr->width, info_ptr->height); + + rv = 0; + +err: + if (png_ptr) + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); + return rv; +} + +static int jpeg_sig_cmp(uint8_t * bytes, int len) +{ + (void)len; + + return (bytes[0] == 0xff && bytes[1] == 0xd8) ? 0 : -1; +} + +static int read_jpeg_file(FILE * fp, uint8_t * header, int len) +{ + struct jdec_private *jdec = NULL; + void *jpeg_file = NULL; + size_t length_of_file; + unsigned int width, height; + int rv = -1; + unsigned char *components[1]; + unsigned int bytes_per_row[1]; + + rv = floadfile(fp, &jpeg_file, &length_of_file, header, len); + fclose(fp); + if (rv) + goto err; + + jdec = tinyjpeg_init(); + if (!jdec) + goto err; + + if (tinyjpeg_parse_header(jdec, jpeg_file, length_of_file) < 0) + goto err; + + tinyjpeg_get_size(jdec, &width, &height); + if (width > __vesa_info.mi.h_res || height > __vesa_info.mi.v_res) + goto err; + + components[0] = (void *)__vesacon_background; + tinyjpeg_set_components(jdec, components, 1); + bytes_per_row[0] = __vesa_info.mi.h_res << 2; + tinyjpeg_set_bytes_per_row(jdec, bytes_per_row, 1); + + tinyjpeg_decode(jdec, TINYJPEG_FMT_BGRA32); + tile_image(width, height); + + rv = 0; + +err: + /* Don't use tinyjpeg_free() here, since we didn't allow tinyjpeg + to allocate the frame buffer */ + if (jdec) + free(jdec); + + if (jpeg_file) + free(jpeg_file); + + return rv; +} + +/* Simple grey Gaussian hole, enough to look interesting */ +int vesacon_default_background(void) +{ + int x, y, dx, dy, dy2; + int z; + unsigned int shft; + uint8_t *bgptr = (uint8_t *)__vesacon_background; + uint8_t k; + + if (__vesacon_pixel_format == PXF_NONE) + return 0; /* Not in graphics mode */ + + z = max(__vesa_info.mi.v_res, __vesa_info.mi.h_res) >> 1; + z = ((z*z) >> 11) - 1; + shft = ilog2(z) + 1; + + for (y = 0, dy = -(__vesa_info.mi.v_res >> 1); + y < __vesa_info.mi.v_res; y++, dy++) { + dy2 = dy * dy; + for (x = 0, dx = -(__vesa_info.mi.h_res >> 1); + x < __vesa_info.mi.h_res; x++, dx++) { + k = __vesacon_linear_to_srgb[500 + ((dx*dx + dy2) >> shft)]; + bgptr[0] = k; /* Blue */ + bgptr[1] = k; /* Green */ + bgptr[2] = k; /* Red */ + bgptr += 4; /* Dummy alpha */ + } + } + + draw_background(); + return 0; +} + +/* Set the background to a single flat color */ +int vesacon_set_background(unsigned int rgb) +{ + void *bgptr = __vesacon_background; + unsigned int count = __vesa_info.mi.h_res * __vesa_info.mi.v_res; + + if (__vesacon_pixel_format == PXF_NONE) + return 0; /* Not in graphics mode */ + + asm volatile ("rep; stosl":"+D" (bgptr), "+c"(count) + :"a"(rgb) + :"memory"); + + draw_background(); + return 0; +} + +struct lss16_header { + uint32_t magic; + uint16_t xsize; + uint16_t ysize; +}; + +#define LSS16_MAGIC 0x1413f33d + +static inline int lss16_sig_cmp(const void *header, int len) +{ + const struct lss16_header *h = header; + + if (len != 8) + return 1; + + return !(h->magic == LSS16_MAGIC && + h->xsize <= __vesa_info.mi.h_res && + h->ysize <= __vesa_info.mi.v_res); +} + +static int read_lss16_file(FILE * fp, const void *header, int header_len) +{ + const struct lss16_header *h = header; + uint32_t colors[16], color; + bool has_nybble; + uint8_t byte; + int count; + int nybble, prev; + enum state { + st_start, + st_c0, + st_c1, + st_c2, + } state; + int i, x, y; + uint32_t *bgptr = __vesacon_background; + + /* Assume the header, 8 bytes, has already been loaded. */ + if (header_len != 8) + return -1; + + for (i = 0; i < 16; i++) { + uint8_t rgb[3]; + if (fread(rgb, 1, 3, fp) != 3) + return -1; + + colors[i] = (((rgb[0] & 63) * 255 / 63) << 16) + + (((rgb[1] & 63) * 255 / 63) << 8) + + ((rgb[2] & 63) * 255 / 63); + } + + /* By spec, the state machine is per row */ + for (y = 0; y < h->ysize; y++) { + state = st_start; + has_nybble = false; + color = colors[prev = 0]; /* By specification */ + count = 0; + + x = 0; + while (x < h->xsize) { + if (!has_nybble) { + if (fread(&byte, 1, 1, fp) != 1) + return -1; + nybble = byte & 0xf; + has_nybble = true; + } else { + nybble = byte >> 4; + has_nybble = false; + } + + switch (state) { + case st_start: + if (nybble != prev) { + *bgptr++ = color = colors[prev = nybble]; + x++; + } else { + state = st_c0; + } + break; + + case st_c0: + if (nybble == 0) { + state = st_c1; + } else { + count = nybble; + goto do_run; + } + break; + + case st_c1: + count = nybble + 16; + state = st_c2; + break; + + case st_c2: + count += nybble << 4; + goto do_run; + +do_run: + count = min(count, h->xsize - x); + x += count; + asm volatile ("rep; stosl":"+D" (bgptr), + "+c"(count):"a"(color)); + state = st_start; + break; + } + } + + /* Zero-fill rest of row */ + i = __vesa_info.mi.h_res - x; + asm volatile ("rep; stosl":"+D" (bgptr), "+c"(i):"a"(0):"memory"); + } + + /* Zero-fill rest of screen */ + i = (__vesa_info.mi.v_res - y) * __vesa_info.mi.h_res; + asm volatile ("rep; stosl":"+D" (bgptr), "+c"(i):"a"(0):"memory"); + + return 0; +} + +int vesacon_load_background(const char *filename) +{ + FILE *fp = NULL; + uint8_t header[8]; + int rv = 1; + + if (__vesacon_pixel_format == PXF_NONE) + return 0; /* Not in graphics mode */ + + fp = fopen(filename, "r"); + + if (!fp) + goto err; + + if (fread(header, 1, 8, fp) != 8) + goto err; + + if (!png_sig_cmp(header, 0, 8)) { + rv = read_png_file(fp); + } else if (!jpeg_sig_cmp(header, 8)) { + rv = read_jpeg_file(fp, header, 8); + } else if (!lss16_sig_cmp(header, 8)) { + rv = read_lss16_file(fp, header, 8); + } + + /* This actually displays the stuff */ + draw_background(); + +err: + if (fp) + fclose(fp); + + return rv; +} + +int __vesacon_init_background(void) +{ + /* __vesacon_background was cleared by calloc() */ + + /* The VESA BIOS has already cleared the screen */ + return 0; +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/vesa/debug.h b/contrib/syslinux-4.02/com32/lib/sys/vesa/debug.h new file mode 100644 index 0000000..86d085f --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/vesa/debug.h @@ -0,0 +1,36 @@ +#ifndef LIB_SYS_VESA_DEBUG_H +#define LIB_SYS_VESA_DEBUG_H + +#if 0 + +#include <stdio.h> +#include <unistd.h> + +ssize_t __serial_write(void *fp, const void *buf, size_t count); + +static void debug(const char *str, ...) +{ + va_list va; + char buf[65536]; + size_t len; + + va_start(va, str); + len = vsnprintf(buf, sizeof buf, str, va); + va_end(va); + + if (len >= sizeof buf) + len = sizeof buf - 1; + + __serial_write(NULL, buf, len); +} + +#else + +static inline void debug(const char *str, ...) +{ + (void)str; +} + +#endif + +#endif /* LIB_SYS_VESA_DEBUG_H */ diff --git a/contrib/syslinux-4.02/com32/lib/sys/vesa/drawtxt.c b/contrib/syslinux-4.02/com32/lib/sys/vesa/drawtxt.c new file mode 100644 index 0000000..85a9e97 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/vesa/drawtxt.c @@ -0,0 +1,317 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2006-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. + * + * ----------------------------------------------------------------------- */ + +#include <inttypes.h> +#include <colortbl.h> +#include <string.h> +#include "vesa.h" +#include "video.h" +#include "fill.h" + +/* + * Visible cursor information + */ +static uint8_t cursor_pattern[FONT_MAX_HEIGHT]; +static struct vesa_char *cursor_pointer = NULL; +static int cursor_x, cursor_y; + +static inline void *copy_dword(void *dst, void *src, size_t dword_count) +{ + asm volatile ("rep; movsl":"+D" (dst), "+S"(src), "+c"(dword_count)); + return dst; /* Updated destination pointer */ +} + +static inline __attribute__ ((always_inline)) +uint8_t alpha_val(uint8_t fg, uint8_t bg, uint8_t alpha) +{ + unsigned int tmp; + + tmp = __vesacon_srgb_to_linear[fg] * alpha; + tmp += __vesacon_srgb_to_linear[bg] * (255 - alpha); + + return __vesacon_linear_to_srgb[tmp >> 12]; +} + +static uint32_t alpha_pixel(uint32_t fg, uint32_t bg) +{ + uint8_t alpha = fg >> 24; + uint8_t fg_r = fg >> 16; + uint8_t fg_g = fg >> 8; + uint8_t fg_b = fg; + uint8_t bg_r = bg >> 16; + uint8_t bg_g = bg >> 8; + uint8_t bg_b = bg; + + return + (alpha_val(fg_r, bg_r, alpha) << 16) | + (alpha_val(fg_g, bg_g, alpha) << 8) | (alpha_val(fg_b, bg_b, alpha)); +} + +static void vesacon_update_characters(int row, int col, int nrows, int ncols) +{ + const int height = __vesacon_font_height; + const int width = FONT_WIDTH; + uint32_t *bgrowptr, *bgptr, bgval, fgval; + uint32_t fgcolor = 0, bgcolor = 0, color; + uint8_t chbits = 0, chxbits = 0, chsbits = 0; + int i, j, jx, pixrow, pixsrow; + struct vesa_char *rowptr, *rowsptr, *cptr, *csptr; + unsigned int bytes_per_pixel = __vesacon_bytes_per_pixel; + unsigned long pixel_offset; + uint32_t row_buffer[__vesa_info.mi.h_res], *rowbufptr; + size_t fbrowptr; + uint8_t sha; + + pixel_offset = ((row * height + VIDEO_BORDER) * __vesa_info.mi.h_res) + + (col * width + VIDEO_BORDER); + + bgrowptr = &__vesacon_background[pixel_offset]; + fbrowptr = (row * height + VIDEO_BORDER) * __vesa_info.mi.logical_scan + + (col * width + VIDEO_BORDER) * bytes_per_pixel; + + /* Note that we keep a 1-character guard area around the real text area... */ + rowptr = &__vesacon_text_display[(row+1)*(__vesacon_text_cols+2)+(col+1)]; + rowsptr = rowptr - ((__vesacon_text_cols+2)+1); + pixrow = 0; + pixsrow = height - 1; + + for (i = height * nrows; i >= 0; i--) { + bgptr = bgrowptr; + rowbufptr = row_buffer; + + cptr = rowptr; + csptr = rowsptr; + + chsbits = __vesacon_graphics_font[csptr->ch][pixsrow]; + if (__unlikely(csptr == cursor_pointer)) + chsbits |= cursor_pattern[pixsrow]; + sha = console_color_table[csptr->attr].shadow; + chsbits &= (sha & 0x02) ? 0xff : 0x00; + chsbits ^= (sha & 0x01) ? 0xff : 0x00; + chsbits <<= (width - 2); + csptr++; + + /* Draw two pixels beyond the end of the line. One for the shadow, + and one to make sure we have a whole dword of data for the copy + operation at the end. Note that this code depends on the fact that + all characters begin on dword boundaries in the frame buffer. */ + + for (jx = 1, j = width * ncols + 1; j >= 0; j--) { + chbits <<= 1; + chsbits <<= 1; + chxbits <<= 1; + + switch (jx) { + case 1: + chbits = __vesacon_graphics_font[cptr->ch][pixrow]; + if (__unlikely(cptr == cursor_pointer)) + chbits |= cursor_pattern[pixrow]; + sha = console_color_table[cptr->attr].shadow; + chxbits = chbits; + chxbits &= (sha & 0x02) ? 0xff : 0x00; + chxbits ^= (sha & 0x01) ? 0xff : 0x00; + fgcolor = console_color_table[cptr->attr].argb_fg; + bgcolor = console_color_table[cptr->attr].argb_bg; + cptr++; + jx--; + break; + case 0: + chsbits = __vesacon_graphics_font[csptr->ch][pixsrow]; + if (__unlikely(csptr == cursor_pointer)) + chsbits |= cursor_pattern[pixsrow]; + sha = console_color_table[csptr->attr].shadow; + chsbits &= (sha & 0x02) ? 0xff : 0x00; + chsbits ^= (sha & 0x01) ? 0xff : 0x00; + csptr++; + jx = width - 1; + break; + default: + jx--; + break; + } + + /* If this pixel is raised, use the offsetted value */ + bgval = (chxbits & 0x80) + ? bgptr[__vesa_info.mi.h_res + 1] : *bgptr; + bgptr++; + + /* If this pixel is set, use the fg color, else the bg color */ + fgval = (chbits & 0x80) ? fgcolor : bgcolor; + + /* Produce the combined color pixel value */ + color = alpha_pixel(fgval, bgval); + + /* Apply the shadow (75% shadow) */ + if ((chsbits & ~chxbits) & 0x80) { + color >>= 2; + color &= 0x3f3f3f; + } + + *rowbufptr++ = color; + } + + /* Copy to frame buffer */ + __vesacon_copy_to_screen(fbrowptr, row_buffer, rowbufptr - row_buffer); + + bgrowptr += __vesa_info.mi.h_res; + fbrowptr += __vesa_info.mi.logical_scan; + + if (++pixrow == height) { + rowptr += __vesacon_text_cols + 2; + pixrow = 0; + } + if (++pixsrow == height) { + rowsptr += __vesacon_text_cols + 2; + pixsrow = 0; + } + } +} + +/* Bounding box for changed text. The (x1, y1) coordinates are +1! */ +static unsigned int upd_x0 = -1U, upd_x1, upd_y0 = -1U, upd_y1; + +/* Update the range already touched by various variables */ +void __vesacon_doit(void) +{ + if (upd_x1 > upd_x0 && upd_y1 > upd_y0) { + vesacon_update_characters(upd_y0, upd_x0, upd_y1 - upd_y0, + upd_x1 - upd_x0); + upd_x0 = upd_y0 = -1U; + upd_x1 = upd_y1 = 0; + } +} + +/* Mark a range for update; note argument sequence is the same as + vesacon_update_characters() */ +static inline void vesacon_touch(int row, int col, int rows, int cols) +{ + unsigned int y0 = row; + unsigned int x0 = col; + unsigned int y1 = y0 + rows; + unsigned int x1 = x0 + cols; + + if (y0 < upd_y0) + upd_y0 = y0; + if (y1 > upd_y1) + upd_y1 = y1; + if (x0 < upd_x0) + upd_x0 = x0; + if (x1 > upd_x1) + upd_x1 = x1; +} + +/* Erase a region of the screen */ +void __vesacon_erase(int x0, int y0, int x1, int y1, attr_t attr) +{ + int y; + struct vesa_char *ptr = &__vesacon_text_display + [(y0 + 1) * (__vesacon_text_cols + 2) + (x0 + 1)]; + struct vesa_char fill = { + .ch = ' ', + .attr = attr, + }; + int ncols = x1 - x0 + 1; + + for (y = y0; y <= y1; y++) { + vesacon_fill(ptr, fill, ncols); + ptr += __vesacon_text_cols + 2; + } + + vesacon_touch(y0, x0, y1 - y0 + 1, ncols); +} + +/* Scroll the screen up */ +void __vesacon_scroll_up(int nrows, attr_t attr) +{ + struct vesa_char *fromptr = &__vesacon_text_display + [(nrows + 1) * (__vesacon_text_cols + 2)]; + struct vesa_char *toptr = &__vesacon_text_display + [(__vesacon_text_cols + 2)]; + int dword_count = + (__vesacon_text_rows - nrows) * (__vesacon_text_cols + 2); + struct vesa_char fill = { + .ch = ' ', + .attr = attr, + }; + + toptr = copy_dword(toptr, fromptr, dword_count); + + dword_count = nrows * (__vesacon_text_cols + 2); + + vesacon_fill(toptr, fill, dword_count); + + vesacon_touch(0, 0, __vesacon_text_rows, __vesacon_text_cols); +} + +/* Draw one character text at a specific area of the screen */ +void __vesacon_write_char(int x, int y, uint8_t ch, attr_t attr) +{ + struct vesa_char *ptr = &__vesacon_text_display + [(y + 1) * (__vesacon_text_cols + 2) + (x + 1)]; + + ptr->ch = ch; + ptr->attr = attr; + + vesacon_touch(y, x, 1, 1); +} + +void __vesacon_set_cursor(int x, int y, bool visible) +{ + struct vesa_char *ptr = &__vesacon_text_display + [(y + 1) * (__vesacon_text_cols + 2) + (x + 1)]; + + if (cursor_pointer) + vesacon_touch(cursor_y, cursor_x, 1, 1); + + if (!visible) { + /* Invisible cursor */ + cursor_pointer = NULL; + } else { + cursor_pointer = ptr; + vesacon_touch(y, x, 1, 1); + } + + cursor_x = x; + cursor_y = y; +} + +void __vesacon_init_cursor(int font_height) +{ + int r0 = font_height - (font_height < 10 ? 2 : 3); + + if (r0 < 0) + r0 = 0; + + memset(cursor_pattern, 0, font_height); + cursor_pattern[r0] = 0xff; + cursor_pattern[r0 + 1] = 0xff; +} + +void __vesacon_redraw_text(void) +{ + vesacon_update_characters(0, 0, __vesacon_text_rows, __vesacon_text_cols); +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/vesa/fill.h b/contrib/syslinux-4.02/com32/lib/sys/vesa/fill.h new file mode 100644 index 0000000..5a43c72 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/vesa/fill.h @@ -0,0 +1,63 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2006-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. + * + * ----------------------------------------------------------------------- */ + +#ifndef LIB_SYS_VESA_FILL_H +#define LIB_SYS_VESA_FILL_H + +#include "video.h" + +/* Fill a number of characters. */ +static inline struct vesa_char *vesacon_fill(struct vesa_char *ptr, + struct vesa_char fill, + unsigned int count) +{ + switch (sizeof(struct vesa_char)) { + case 1: + asm volatile ("rep; stosb":"+D" (ptr), "+c"(count) + :"a"(fill) + :"memory"); + break; + case 2: + asm volatile ("rep; stosw":"+D" (ptr), "+c"(count) + :"a"(fill) + :"memory"); + break; + case 4: + asm volatile ("rep; stosl":"+D" (ptr), "+c"(count) + :"a"(fill) + :"memory"); + break; + default: + while (count--) + *ptr++ = fill; + break; + } + + return ptr; +} + +#endif /* LIB_SYS_VESA_FILL_H */ diff --git a/contrib/syslinux-4.02/com32/lib/sys/vesa/fmtpixel.c b/contrib/syslinux-4.02/com32/lib/sys/vesa/fmtpixel.c new file mode 100644 index 0000000..381fc21 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/vesa/fmtpixel.c @@ -0,0 +1,101 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2006-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. + * + * ----------------------------------------------------------------------- */ + +/* + * fmtpixel.c + * + * Functions to format a single pixel + */ + +#include <inttypes.h> +#include "video.h" + +/* + * Format a sequence of pixels. The first argument is the line buffer; + * we can use it to write up to 4 bytes past the end of the last pixel. + * Return the place we should be copying from, this is usually the + * buffer address, but doesn't *have* to be. + */ + +static const void *format_pxf_bgra32(void *ptr, const uint32_t * p, size_t n) +{ + (void)ptr; + (void)n; + return p; /* No conversion needed! */ +} + +static const void *format_pxf_bgr24(void *ptr, const uint32_t * p, size_t n) +{ + char *q = ptr; + + while (n--) { + *(uint32_t *) q = *p++; + q += 3; + } + return ptr; +} + +static const void *format_pxf_le_rgb16_565(void *ptr, const uint32_t * p, + size_t n) +{ + uint32_t bgra; + uint16_t *q = ptr; + + while (n--) { + bgra = *p++; + *q++ = + ((bgra >> 3) & 0x1f) + + ((bgra >> (2 + 8 - 5)) & (0x3f << 5)) + + ((bgra >> (3 + 16 - 11)) & (0x1f << 11)); + } + return ptr; +} + +static const void *format_pxf_le_rgb15_555(void *ptr, const uint32_t * p, + size_t n) +{ + uint32_t bgra; + uint16_t *q = ptr; + + while (n--) { + bgra = *p++; + *q++ = + ((bgra >> 3) & 0x1f) + + ((bgra >> (2 + 8 - 5)) & (0x1f << 5)) + + ((bgra >> (3 + 16 - 10)) & (0x1f << 10)); + } + return ptr; +} + +__vesacon_format_pixels_t __vesacon_format_pixels; + +const __vesacon_format_pixels_t __vesacon_format_pixels_list[PXF_NONE] = { + [PXF_BGRA32] = format_pxf_bgra32, + [PXF_BGR24] = format_pxf_bgr24, + [PXF_LE_RGB16_565] = format_pxf_le_rgb16_565, + [PXF_LE_RGB15_555] = format_pxf_le_rgb15_555, +}; diff --git a/contrib/syslinux-4.02/com32/lib/sys/vesa/i915resolution.c b/contrib/syslinux-4.02/com32/lib/sys/vesa/i915resolution.c new file mode 100644 index 0000000..6ebb04d --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/vesa/i915resolution.c @@ -0,0 +1,795 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2010 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * Based on: + * + * 915 resolution by steve tomljenovic + * + * This was tested only on Sony VGN-FS550. Use at your own risk + * + * This code is based on the techniques used in : + * + * - 855patch. Many thanks to Christian Zietz (czietz gmx net) + * for demonstrating how to shadow the VBIOS into system RAM + * and then modify it. + * + * - 1280patch by Andrew Tipton (andrewtipton null li). + * + * - 855resolution by Alain Poirier + * + * This source code is into the public domain. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#define __USE_GNU +#include <string.h> +#include <sys/io.h> +#include <sys/cpu.h> +#include <sys/pci.h> +#include <unistd.h> +#include <assert.h> +#include <stdbool.h> +#include "video.h" +#include "debug.h" + +#define VBIOS_START 0xc0000 +#define VBIOS_SIZE 0x10000 + +#define MODE_TABLE_OFFSET_845G 617 + +#define VERSION "0.5.3" + +#define ATI_SIGNATURE1 "ATI MOBILITY RADEON" +#define ATI_SIGNATURE2 "ATI Technologies Inc" +#define NVIDIA_SIGNATURE "NVIDIA Corp" +#define INTEL_SIGNATURE "Intel Corp" + +typedef unsigned char * address; + +typedef enum { + CT_UNKWN, CT_830, CT_845G, CT_855GM, CT_865G, CT_915G, CT_915GM, + CT_945G, CT_945GM, CT_946GZ, CT_G965, CT_Q965, CT_945GME, + CHIPSET_TYPES +} chipset_type; + +typedef enum { + BT_UNKWN, BT_1, BT_2, BT_3 +} bios_type; + +static int freqs[] = { 60, 75, 85 }; + +typedef struct { + uint8_t mode; + uint8_t bits_per_pixel; + uint16_t resolution; + uint8_t unknown; +} __attribute__((packed)) vbios_mode; + +typedef struct { + uint16_t clock; /* Clock frequency in 10 kHz */ + uint8_t x1; + uint8_t x_total; + uint8_t x2; + uint8_t y1; + uint8_t y_total; + uint8_t y2; +} __attribute__((packed)) vbios_resolution_type1; + +typedef struct { + uint32_t clock; + + uint16_t x1; + uint16_t htotal; + uint16_t x2; + uint16_t hblank; + uint16_t hsyncstart; + uint16_t hsyncend; + + uint16_t y1; + uint16_t vtotal; + uint16_t y2; + uint16_t vblank; + uint16_t vsyncstart; + uint16_t vsyncend; +} __attribute__((packed)) vbios_modeline_type2; + +typedef struct { + uint8_t xchars; + uint8_t ychars; + uint8_t unknown[4]; + + vbios_modeline_type2 modelines[]; +} __attribute__((packed)) vbios_resolution_type2; + +typedef struct { + uint32_t clock; + + uint16_t x1; + uint16_t htotal; + uint16_t x2; + uint16_t hblank; + uint16_t hsyncstart; + uint16_t hsyncend; + + uint16_t y1; + uint16_t vtotal; + uint16_t y2; + uint16_t vblank; + uint16_t vsyncstart; + uint16_t vsyncend; + + uint16_t timing_h; + uint16_t timing_v; + + uint8_t unknown[6]; +} __attribute__((packed)) vbios_modeline_type3; + +typedef struct { + unsigned char unknown[6]; + + vbios_modeline_type3 modelines[]; +} __attribute__((packed)) vbios_resolution_type3; + + +typedef struct { + unsigned int chipset_id; + chipset_type chipset; + bios_type bios; + + address bios_ptr; + + vbios_mode * mode_table; + unsigned int mode_table_size; + + uint8_t b1, b2; + + bool unlocked; +} vbios_map; + +#if 0 /* Debugging hacks */ +static void good_marker(int x) +{ + ((uint16_t *)0xb8000)[x] = 0x2f30 - ((x & 0xf0) << 4) + (x & 0x0f); +} + +static void bad_marker(int x) +{ + ((uint16_t *)0xb8000)[x] = 0x4f30 - ((x & 0xf0) << 4) + (x & 0x0f); +} + +static void status(const char *fmt, ...) +{ + va_list ap; + char msg[81], *p; + int i; + uint16_t *q; + + memset(msg, 0, sizeof msg); + va_start(ap, fmt); + vsnprintf(msg, sizeof msg, fmt, ap); + va_end(ap); + p = msg; + q = (uint16_t *)0xb8000 + 80; + for (i = 0; i < 80; i++) + *q++ = *p++ + 0x1f00; +} +#else +static inline void good_marker(int x) { (void)x; } +static inline void bad_marker(int x) { (void)x; } +static inline void status(const char *fmt, ...) { (void)fmt; } +#endif + +static unsigned int get_chipset_id(void) { + return pci_readl(0x80000000); +} + +static chipset_type get_chipset(unsigned int id) { + chipset_type type; + + switch (id) { + case 0x35758086: + type = CT_830; + break; + + case 0x25608086: + type = CT_845G; + break; + + case 0x35808086: + type = CT_855GM; + break; + + case 0x25708086: + type = CT_865G; + break; + + case 0x25808086: + type = CT_915G; + break; + + case 0x25908086: + type = CT_915GM; + break; + + case 0x27708086: + type = CT_945G; + break; + + case 0x27a08086: + type = CT_945GM; + break; + + case 0x29708086: + type = CT_946GZ; + break; + + case 0x29a08086: + type = CT_G965; + break; + + case 0x29908086: + type = CT_Q965; + break; + + case 0x27ac8086: + type = CT_945GME; + break; + + default: + type = CT_UNKWN; + break; + } + + return type; +} + + +static vbios_resolution_type1 * map_type1_resolution(vbios_map * map, + uint16_t res) +{ + vbios_resolution_type1 * ptr = ((vbios_resolution_type1*)(map->bios_ptr + res)); + return ptr; +} + +static vbios_resolution_type2 * map_type2_resolution(vbios_map * map, + uint16_t res) +{ + vbios_resolution_type2 * ptr = ((vbios_resolution_type2*)(map->bios_ptr + res)); + return ptr; +} + +static vbios_resolution_type3 * map_type3_resolution(vbios_map * map, + uint16_t res) +{ + vbios_resolution_type3 * ptr = ((vbios_resolution_type3*)(map->bios_ptr + res)); + return ptr; +} + + +static bool detect_bios_type(vbios_map * map, int entry_size) +{ + unsigned int i; + uint16_t r1, r2; + + r1 = r2 = 32000; + + for (i = 0; i < map->mode_table_size; i++) { + if (map->mode_table[i].resolution <= r1) { + r1 = map->mode_table[i].resolution; + } else if (map->mode_table[i].resolution <= r2) { + r2 = map->mode_table[i].resolution; + } + } + + return ((r2-r1-6) % entry_size) == 0; +} + +static inline void close_vbios(vbios_map *map) +{ + (void)map; +} + +static vbios_map * open_vbios(void) +{ + static vbios_map _map; + vbios_map * const map = &_map; + + memset(&_map, 0, sizeof _map); + + /* + * Determine chipset + */ + map->chipset_id = get_chipset_id(); + good_marker(0x10); + map->chipset = get_chipset(map->chipset_id); + good_marker(0x11); + + /* + * Map the video bios to memory + */ + map->bios_ptr = (void *)VBIOS_START; + + /* + * check if we have ATI Radeon + */ + + if (memmem(map->bios_ptr, VBIOS_SIZE, ATI_SIGNATURE1, strlen(ATI_SIGNATURE1)) || + memmem(map->bios_ptr, VBIOS_SIZE, ATI_SIGNATURE2, strlen(ATI_SIGNATURE2)) ) { + debug("ATI chipset detected. 915resolution only works with Intel 800/900 series graphic chipsets.\r\n"); + return NULL; + } + + /* + * check if we have NVIDIA + */ + + if (memmem(map->bios_ptr, VBIOS_SIZE, NVIDIA_SIGNATURE, strlen(NVIDIA_SIGNATURE))) { + debug("NVIDIA chipset detected. 915resolution only works with Intel 800/900 series graphic chipsets.\r\n"); + return NULL; + } + + /* + * check if we have Intel + */ + + if (map->chipset == CT_UNKWN && memmem(map->bios_ptr, VBIOS_SIZE, INTEL_SIGNATURE, strlen(INTEL_SIGNATURE))) { + debug("Intel chipset detected. However, 915resolution was unable to determine the chipset type.\r\n"); + + debug("Chipset Id: %x\r\n", map->chipset_id); + + debug("Please report this problem to stomljen@yahoo.com\r\n"); + + close_vbios(map); + return NULL; + } + + /* + * check for others + */ + + if (map->chipset == CT_UNKWN) { + debug("Unknown chipset type and unrecognized bios.\r\n"); + debug("915resolution only works with Intel 800/900 series graphic chipsets.\r\n"); + + debug("Chipset Id: %x\r\n", map->chipset_id); + close_vbios(map); + return NULL; + } + + /* + * Figure out where the mode table is + */ + good_marker(0x12); + + { + address p = map->bios_ptr + 16; + address limit = map->bios_ptr + VBIOS_SIZE - (3 * sizeof(vbios_mode)); + + while (p < limit && map->mode_table == 0) { + vbios_mode * mode_ptr = (vbios_mode *) p; + + if (((mode_ptr[0].mode & 0xf0) == 0x30) && ((mode_ptr[1].mode & 0xf0) == 0x30) && + ((mode_ptr[2].mode & 0xf0) == 0x30) && ((mode_ptr[3].mode & 0xf0) == 0x30)) { + + map->mode_table = mode_ptr; + } + + p++; + } + + if (map->mode_table == 0) { + debug("Unable to locate the mode table.\r\n"); + close_vbios(map); + return NULL; + } + } + good_marker(0x13); + + /* + * Determine size of mode table + */ + + { + vbios_mode * mode_ptr = map->mode_table; + + while (mode_ptr->mode != 0xff) { + map->mode_table_size++; + mode_ptr++; + } + } + good_marker(0x14); + status("mode_table_size = %d", map->mode_table_size); + + /* + * Figure out what type of bios we have + * order of detection is important + */ + + if (detect_bios_type(map, sizeof(vbios_modeline_type3))) { + map->bios = BT_3; + } + else if (detect_bios_type(map, sizeof(vbios_modeline_type2))) { + map->bios = BT_2; + } + else if (detect_bios_type(map, sizeof(vbios_resolution_type1))) { + map->bios = BT_1; + } + else { + debug("Unable to determine bios type.\r\n"); + debug("Mode Table Offset: $C0000 + $%x\r\n", ((unsigned int)map->mode_table) - ((unsigned int)map->bios_ptr)); + debug("Mode Table Entries: %u\r\n", map->mode_table_size); + bad_marker(0x15); + return NULL; + } + good_marker(0x15); + + return map; +} + +static void unlock_vbios(vbios_map * map) +{ + assert(!map->unlocked); + + map->unlocked = true; + + switch (map->chipset) { + case CT_UNKWN: + case CHIPSET_TYPES: /* Shut up gcc */ + break; + case CT_830: + case CT_855GM: + map->b1 = pci_readb(0x8000005a); + pci_writeb(0x33, 0x8000005a); + break; + case CT_845G: + case CT_865G: + case CT_915G: + case CT_915GM: + case CT_945G: + case CT_945GM: + case CT_945GME: + case CT_946GZ: + case CT_G965: + case CT_Q965: + map->b1 = pci_readb(0x80000091); + map->b2 = pci_readb(0x80000092); + pci_writeb(0x33, 0x80000091); + pci_writeb(0x33, 0x80000092); + break; + } + +#if DEBUG + { + unsigned int t = inl(0xcfc); + debug("unlock PAM: (0x%08x)\r\n", t); + } +#endif +} + +static void relock_vbios(vbios_map * map) +{ + assert(map->unlocked); + map->unlocked = false; + + switch (map->chipset) { + case CT_UNKWN: + case CHIPSET_TYPES: /* Shut up gcc */ + break; + case CT_830: + case CT_855GM: + pci_writeb(map->b1, 0x8000005a); + break; + case CT_845G: + case CT_865G: + case CT_915G: + case CT_915GM: + case CT_945G: + case CT_945GM: + case CT_945GME: + case CT_946GZ: + case CT_G965: + case CT_Q965: + pci_writeb(map->b1, 0x80000091); + pci_writeb(map->b2, 0x80000092); + break; + } + +#if DEBUG + { + unsigned int t = inl(0xcfc); + debug("relock PAM: (0x%08x)\r\n", t); + } +#endif +} + +#if 0 +static void list_modes(vbios_map *map, unsigned int raw) +{ + unsigned int i, x, y; + + for (i=0; i < map->mode_table_size; i++) { + switch(map->bios) { + case BT_1: + { + vbios_resolution_type1 * res = map_type1_resolution(map, map->mode_table[i].resolution); + + x = ((((unsigned int) res->x2) & 0xf0) << 4) | res->x1; + y = ((((unsigned int) res->y2) & 0xf0) << 4) | res->y1; + + if (x != 0 && y != 0) { + debug("Mode %02x : %dx%d, %d bits/pixel\r\n", map->mode_table[i].mode, x, y, map->mode_table[i].bits_per_pixel); + } + + if (raw) + { + debug("Mode %02x (raw) :\r\n\t%02x %02x\r\n\t%02x\r\n\t%02x\r\n\t%02x\r\n\t%02x\r\n\t%02x\r\n\t%02x\r\n", map->mode_table[i].mode, res->unknow1[0],res->unknow1[1], res->x1,res->x_total,res->x2,res->y1,res->y_total,res->y2); + } + + } + break; + case BT_2: + { + vbios_resolution_type2 * res = map_type2_resolution(map, map->mode_table[i].resolution); + + x = res->modelines[0].x1+1; + y = res->modelines[0].y1+1; + + if (x != 0 && y != 0) { + debug("Mode %02x : %dx%d, %d bits/pixel\r\n", map->mode_table[i].mode, x, y, map->mode_table[i].bits_per_pixel); + } + } + break; + case BT_3: + { + vbios_resolution_type3 * res = map_type3_resolution(map, map->mode_table[i].resolution); + + x = res->modelines[0].x1+1; + y = res->modelines[0].y1+1; + + if (x != 0 && y != 0) { + debug("Mode %02x : %dx%d, %d bits/pixel\r\n", map->mode_table[i].mode, x, y, map->mode_table[i].bits_per_pixel); + } + } + break; + case BT_UNKWN: + break; + } + } +} +#endif + +static void gtf_timings(int x, int y, int freq, uint32_t *clock, + uint16_t *hsyncstart, uint16_t *hsyncend, uint16_t *hblank, + uint16_t *vsyncstart, uint16_t *vsyncend, uint16_t *vblank) +{ + int hbl, vbl, vfreq; + + vbl = y + (y+1)/(20000.0/(11*freq) - 1) + 1.5; + vfreq = vbl * freq; + hbl = 16 * (int)(x * (30.0 - 300000.0 / vfreq) / + (70.0 + 300000.0 / vfreq) / 16.0 + 0.5); + + *vsyncstart = y; + *vsyncend = y + 3; + *vblank = vbl - 1; + *hsyncstart = x + hbl / 2 - (x + hbl + 50) / 100 * 8 - 1; + *hsyncend = x + hbl / 2 - 1; + *hblank = x + hbl - 1; + *clock = (x + hbl) * vfreq / 1000; +} + +static int set_mode(vbios_map * map, unsigned int mode, + unsigned int x, unsigned int y, unsigned int bp, + unsigned int htotal, unsigned int vtotal) +{ + int xprev, yprev; + unsigned int i, j; + int rv = -1; + + for (i=0; i < map->mode_table_size; i++) { + if (map->mode_table[i].mode == mode) { + switch(map->bios) { + case BT_1: + { + vbios_resolution_type1 * res = map_type1_resolution(map, map->mode_table[i].resolution); + uint32_t clock; + uint16_t hsyncstart, hsyncend, hblank; + uint16_t vsyncstart, vsyncend, vblank; + + if (bp) { + map->mode_table[i].bits_per_pixel = bp; + } + + gtf_timings(x, y, freqs[0], &clock, + &hsyncstart, &hsyncend, &hblank, + &vsyncstart, &vsyncend, &vblank); + + status("x = %d, y = %d, clock = %lu, h = %d %d %d, v = %d %d %d\n", + x, y, clock, + hsyncstart, hsyncend, hblank, + vsyncstart, vsyncend, vblank); + + htotal = htotal ? htotal : (unsigned int)hblank+1; + vtotal = vtotal ? vtotal : (unsigned int)vblank+1; + + res->clock = clock/10; /* Units appear to be 10 kHz */ + res->x2 = (((htotal-x) >> 8) & 0x0f) | ((x >> 4) & 0xf0); + res->x1 = (x & 0xff); + + res->y2 = (((vtotal-y) >> 8) & 0x0f) | ((y >> 4) & 0xf0); + res->y1 = (y & 0xff); + if (htotal) + res->x_total = ((htotal-x) & 0xff); + + if (vtotal) + res->y_total = ((vtotal-y) & 0xff); + + rv = 0; + } + break; + case BT_2: + { + vbios_resolution_type2 * res = map_type2_resolution(map, map->mode_table[i].resolution); + + res->xchars = x / 8; + res->ychars = y / 16 - 1; + xprev = res->modelines[0].x1; + yprev = res->modelines[0].y1; + + for(j=0; j < 3; j++) { + vbios_modeline_type2 * modeline = &res->modelines[j]; + + if (modeline->x1 == xprev && modeline->y1 == yprev) { + modeline->x1 = modeline->x2 = x-1; + modeline->y1 = modeline->y2 = y-1; + + gtf_timings(x, y, freqs[j], &modeline->clock, + &modeline->hsyncstart, &modeline->hsyncend, + &modeline->hblank, &modeline->vsyncstart, + &modeline->vsyncend, &modeline->vblank); + + if (htotal) + modeline->htotal = htotal; + else + modeline->htotal = modeline->hblank; + + if (vtotal) + modeline->vtotal = vtotal; + else + modeline->vtotal = modeline->vblank; + } + } + + rv = 0; + } + break; + case BT_3: + { + vbios_resolution_type3 * res = map_type3_resolution(map, map->mode_table[i].resolution); + + xprev = res->modelines[0].x1; + yprev = res->modelines[0].y1; + + for (j=0; j < 3; j++) { + vbios_modeline_type3 * modeline = &res->modelines[j]; + + if (modeline->x1 == xprev && modeline->y1 == yprev) { + modeline->x1 = modeline->x2 = x-1; + modeline->y1 = modeline->y2 = y-1; + + gtf_timings(x, y, freqs[j], &modeline->clock, + &modeline->hsyncstart, &modeline->hsyncend, + &modeline->hblank, &modeline->vsyncstart, + &modeline->vsyncend, &modeline->vblank); + if (htotal) + modeline->htotal = htotal; + else + modeline->htotal = modeline->hblank; + if (vtotal) + modeline->vtotal = vtotal; + else + modeline->vtotal = modeline->vblank; + + modeline->timing_h = y-1; + modeline->timing_v = x-1; + } + } + + rv = 0; + } + break; + case BT_UNKWN: + break; + } + } + } + + return rv; +} + +static inline void display_map_info(vbios_map * map) { +#ifdef DEBUG + static const char * bios_type_names[] = + {"UNKNOWN", "TYPE 1", "TYPE 2", "TYPE 3"}; + static const char * chipset_type_names[] = { + "UNKNOWN", "830", "845G", "855GM", "865G", "915G", "915GM", "945G", + "945GM", "946GZ", "G965", "Q965", "945GME" + }; + + debug("Chipset: %s\r\n", chipset_type_names[map->chipset]); + debug("BIOS: %s\r\n", bios_type_names[map->bios]); + + debug("Mode Table Offset: $C0000 + $%x\r\n", + ((unsigned int)map->mode_table) - ((unsigned int)map->bios_ptr)); + debug("Mode Table Entries: %u\r\n", map->mode_table_size); +#endif + (void)map; +} + +int __vesacon_i915resolution(int x, int y) +{ + vbios_map * map; + unsigned int mode = 0x52; /* 800x600x32 mode in known BIOSes */ + unsigned int bp = 32; /* 32 bits per pixel */ + int rv = 0; + + good_marker(0); + + map = open_vbios(); + if (!map) + return -1; + + good_marker(1); + + display_map_info(map); + + debug("\r\n"); + + if (mode && x && y) { + good_marker(2); + cli(); + good_marker(3); + unlock_vbios(map); + good_marker(4); + rv = set_mode(map, mode, x, y, bp, 0, 0); + if (rv) + bad_marker(5); + else + good_marker(5); + relock_vbios(map); + good_marker(6); + sti(); + + debug("Patch mode %02x to resolution %dx%d complete\r\n", mode, x, y); + } + close_vbios(map); + + return rv; +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/vesa/initvesa.c b/contrib/syslinux-4.02/com32/lib/sys/vesa/initvesa.c new file mode 100644 index 0000000..9a1ae38 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/vesa/initvesa.c @@ -0,0 +1,357 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1999-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. + * + * ----------------------------------------------------------------------- */ + +/* + * initvesa.c + * + * Query the VESA BIOS and select a 640x480x32 mode with local mapping + * support, if one exists. + */ + +#include <inttypes.h> +#include <com32.h> +#include <stdlib.h> +#include <string.h> +#include <sys/fpu.h> +#include <syslinux/video.h> +#include "vesa.h" +#include "video.h" +#include "fill.h" +#include "debug.h" + +struct vesa_info __vesa_info; + +struct vesa_char *__vesacon_text_display; + +int __vesacon_font_height; +int __vesacon_text_rows; +int __vesacon_text_cols; +enum vesa_pixel_format __vesacon_pixel_format = PXF_NONE; +unsigned int __vesacon_bytes_per_pixel; +uint8_t __vesacon_graphics_font[FONT_MAX_CHARS][FONT_MAX_HEIGHT]; + +uint32_t *__vesacon_background, *__vesacon_shadowfb; + +static void unpack_font(uint8_t * dst, uint8_t * src, int height) +{ + int i; + + for (i = 0; i < FONT_MAX_CHARS; i++) { + memcpy(dst, src, height); + memset(dst + height, 0, FONT_MAX_HEIGHT - height); + + dst += FONT_MAX_HEIGHT; + src += height; + } +} + +static int __constfunc is_power_of_2(unsigned int x) +{ + return x && !(x & (x - 1)); +} + +static int vesacon_paged_mode_ok(const struct vesa_mode_info *mi) +{ + int i; + + if (!is_power_of_2(mi->win_size) || + !is_power_of_2(mi->win_grain) || mi->win_grain > mi->win_size) + return 0; /* Impossible... */ + + for (i = 0; i < 2; i++) { + if ((mi->win_attr[i] & 0x05) == 0x05 && mi->win_seg[i]) + return 1; /* Usable window */ + } + + return 0; /* Nope... */ +} + +static int vesacon_set_mode(int x, int y) +{ + com32sys_t rm; + uint8_t *rom_font; + uint16_t mode, bestmode, *mode_ptr; + struct vesa_info *vi; + struct vesa_general_info *gi; + struct vesa_mode_info *mi; + enum vesa_pixel_format pxf, bestpxf; + int err = 0; + + debug("Hello, World!\r\n"); + + /* Free any existing data structures */ + if (__vesacon_background) { + free(__vesacon_background); + __vesacon_background = NULL; + } + if (__vesacon_shadowfb) { + free(__vesacon_shadowfb); + __vesacon_shadowfb = NULL; + } + + /* Allocate space in the bounce buffer for these structures */ + vi = lzalloc(sizeof *vi); + if (!vi) { + err = 10; /* Out of memory */ + goto exit; + } + gi = &vi->gi; + mi = &vi->mi; + + memset(&rm, 0, sizeof rm); + + gi->signature = VBE2_MAGIC; /* Get VBE2 extended data */ + rm.eax.w[0] = 0x4F00; /* Get SVGA general information */ + rm.edi.w[0] = OFFS(gi); + rm.es = SEG(gi); + __intcall(0x10, &rm, &rm); + + if (rm.eax.w[0] != 0x004F) { + err = 1; /* Function call failed */ + goto exit; + } + if (gi->signature != VESA_MAGIC) { + err = 2; /* No magic */ + goto exit; + } + if (gi->version < 0x0102) { + err = 3; /* VESA 1.2+ required */ + goto exit; + } + + /* Copy general info */ + memcpy(&__vesa_info.gi, gi, sizeof *gi); + + /* Search for the proper mode with a suitable color and memory model... */ + + mode_ptr = GET_PTR(gi->video_mode_ptr); + bestmode = 0; + bestpxf = PXF_NONE; + + while ((mode = *mode_ptr++) != 0xFFFF) { + mode &= 0x1FF; /* The rest are attributes of sorts */ + + debug("Found mode: 0x%04x\r\n", mode); + + memset(mi, 0, sizeof *mi); + rm.eax.w[0] = 0x4F01; /* Get SVGA mode information */ + rm.ecx.w[0] = mode; + rm.edi.w[0] = OFFS(mi); + rm.es = SEG(mi); + __intcall(0x10, &rm, &rm); + + /* Must be a supported mode */ + if (rm.eax.w[0] != 0x004f) + continue; + + debug + ("mode_attr 0x%04x, h_res = %4d, v_res = %4d, bpp = %2d, layout = %d (%d,%d,%d)\r\n", + mi->mode_attr, mi->h_res, mi->v_res, mi->bpp, mi->memory_layout, + mi->rpos, mi->gpos, mi->bpos); + + /* Must be an LFB color graphics mode supported by the hardware. + + The bits tested are: + 4 - graphics mode + 3 - color mode + 1 - mode information available (mandatory in VBE 1.2+) + 0 - mode supported by hardware + */ + if ((mi->mode_attr & 0x001b) != 0x001b) + continue; + + /* Must be the chosen size */ + if (mi->h_res != x || mi->v_res != y) + continue; + + /* We don't support multibank (interlaced memory) modes */ + /* + * Note: The Bochs VESA BIOS (vbe.c 1.58 2006/08/19) violates the + * specification which states that banks == 1 for unbanked modes; + * fortunately it does report bank_size == 0 for those. + */ + if (mi->banks > 1 && mi->bank_size) { + debug("bad: banks = %d, banksize = %d, pages = %d\r\n", + mi->banks, mi->bank_size, mi->image_pages); + continue; + } + + /* Must be either a flat-framebuffer mode, or be an acceptable + paged mode */ + if (!(mi->mode_attr & 0x0080) && !vesacon_paged_mode_ok(mi)) { + debug("bad: invalid paged mode\r\n"); + continue; + } + + /* Must either be a packed-pixel mode or a direct color mode + (depending on VESA version ); must be a supported pixel format */ + pxf = PXF_NONE; /* Not usable */ + + if (mi->bpp == 32 && + (mi->memory_layout == 4 || + (mi->memory_layout == 6 && mi->rpos == 16 && mi->gpos == 8 && + mi->bpos == 0))) + pxf = PXF_BGRA32; + else if (mi->bpp == 24 && + (mi->memory_layout == 4 || + (mi->memory_layout == 6 && mi->rpos == 16 && mi->gpos == 8 && + mi->bpos == 0))) + pxf = PXF_BGR24; + else if (mi->bpp == 16 && + (mi->memory_layout == 4 || + (mi->memory_layout == 6 && mi->rpos == 11 && mi->gpos == 5 && + mi->bpos == 0))) + pxf = PXF_LE_RGB16_565; + else if (mi->bpp == 15 && + (mi->memory_layout == 4 || + (mi->memory_layout == 6 && mi->rpos == 10 && mi->gpos == 5 && + mi->bpos == 0))) + pxf = PXF_LE_RGB15_555; + + if (pxf < bestpxf) { + debug("Best mode so far, pxf = %d\r\n", pxf); + + /* Best mode so far... */ + bestmode = mode; + bestpxf = pxf; + + /* Copy mode info */ + memcpy(&__vesa_info.mi, mi, sizeof *mi); + } + } + + if (bestpxf == PXF_NONE) { + err = 4; /* No mode found */ + goto exit; + } + + mi = &__vesa_info.mi; + mode = bestmode; + __vesacon_bytes_per_pixel = (mi->bpp + 7) >> 3; + __vesacon_format_pixels = __vesacon_format_pixels_list[bestpxf]; + + /* Download the SYSLINUX- or BIOS-provided font */ + __vesacon_font_height = syslinux_font_query(&rom_font); + if (!__vesacon_font_height) { + /* Get BIOS 8x16 font */ + + rm.eax.w[0] = 0x1130; /* Get Font Information */ + rm.ebx.w[0] = 0x0600; /* Get 8x16 ROM font */ + __intcall(0x10, &rm, &rm); + rom_font = MK_PTR(rm.es, rm.ebp.w[0]); + __vesacon_font_height = 16; + } + unpack_font((uint8_t *) __vesacon_graphics_font, rom_font, + __vesacon_font_height); + + /* Now set video mode */ + rm.eax.w[0] = 0x4F02; /* Set SVGA video mode */ + if (mi->mode_attr & 0x0080) + mode |= 0x4000; /* Request linear framebuffer if supported */ + rm.ebx.w[0] = mode; + __intcall(0x10, &rm, &rm); + if (rm.eax.w[0] != 0x004F) { + err = 9; /* Failed to set mode */ + goto exit; + } + + __vesacon_background = calloc(mi->h_res*mi->v_res, 4); + __vesacon_shadowfb = calloc(mi->h_res*mi->v_res, 4); + + __vesacon_init_copy_to_screen(); + + /* Tell syslinux we changed video mode */ + /* In theory this should be: + + flags = (mi->mode_attr & 4) ? 0x0007 : 0x000f; + + However, that would assume all systems that claim to handle text + output in VESA modes actually do that... */ + syslinux_report_video_mode(0x000f, mi->h_res, mi->v_res); + + __vesacon_pixel_format = bestpxf; + +exit: + if (vi) + lfree(vi); + + return err; +} + +static int init_text_display(void) +{ + size_t nchars; + struct vesa_char *ptr; + struct vesa_char def_char = { + .ch = ' ', + .attr = 0, + }; + + if (__vesacon_text_display) + free(__vesacon_text_display); + + __vesacon_text_cols = TEXT_PIXEL_COLS / FONT_WIDTH; + __vesacon_text_rows = TEXT_PIXEL_ROWS / __vesacon_font_height; + nchars = (__vesacon_text_cols+2) * (__vesacon_text_rows+2); + + __vesacon_text_display = ptr = malloc(nchars * sizeof(struct vesa_char)); + + if (!ptr) + return -1; + + vesacon_fill(ptr, def_char, nchars); + __vesacon_init_cursor(__vesacon_font_height); + + return 0; +} + +int __vesacon_init(int x, int y) +{ + int rv; + + /* We need the FPU for graphics, at least libpng et al will need it... */ + if (x86_init_fpu()) + return 10; + + rv = vesacon_set_mode(x, y); + if (rv) { + /* Try to see if we can just patch the BIOS... */ + if (__vesacon_i915resolution(x, y)) + return rv; + if (vesacon_set_mode(x, y)) + return rv; + } + + init_text_display(); + + debug("Mode set, now drawing at %#p\r\n", __vesa_info.mi.lfb_ptr); + + __vesacon_init_background(); + + debug("Ready!\r\n"); + return 0; +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/vesa/screencpy.c b/contrib/syslinux-4.02/com32/lib/sys/vesa/screencpy.c new file mode 100644 index 0000000..32dce9e --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/vesa/screencpy.c @@ -0,0 +1,117 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 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. + * + * ----------------------------------------------------------------------- */ + +#include <inttypes.h> +#include <minmax.h> +#include <klibc/compiler.h> +#include <string.h> +#include <com32.h> +#include <ilog2.h> +#include "vesa.h" +#include "video.h" + +static struct win_info { + char *win_base; + size_t win_pos; + size_t win_size; + int win_gshift; + int win_num; +} wi; + +void __vesacon_init_copy_to_screen(void) +{ + struct vesa_mode_info *const mi = &__vesa_info.mi; + int winn; + + if (mi->mode_attr & 0x0080) { + /* Linear frame buffer */ + + wi.win_base = (char *)mi->lfb_ptr; + wi.win_size = 1 << 31; /* 2 GB, i.e. one huge window */ + wi.win_pos = 0; /* Already positioned (only one position...) */ + wi.win_num = -1; /* Not a window */ + } else { + /* Paged frame buffer */ + + /* We have already tested that *one* of these is usable */ + if ((mi->win_attr[0] & 0x05) == 0x05 && mi->win_seg[0]) + winn = 0; + else + winn = 1; + + wi.win_num = winn; + wi.win_base = (char *)(mi->win_seg[winn] << 4); + wi.win_size = mi->win_size << 10; + wi.win_gshift = ilog2(mi->win_grain) + 10; + wi.win_pos = -1; /* Undefined position */ + } +} + +static void set_window_pos(size_t win_pos) +{ + static com32sys_t ireg; + + wi.win_pos = win_pos; + + if (wi.win_num < 0) + return; /* This should never happen... */ + + ireg.eax.w[0] = 0x4F05; + ireg.ebx.b[0] = wi.win_num; + ireg.edx.w[0] = win_pos >> wi.win_gshift; + + __intcall(0x10, &ireg, NULL); +} + +void __vesacon_copy_to_screen(size_t dst, const uint32_t * src, size_t npixels) +{ + size_t win_pos, win_off; + size_t win_size = wi.win_size; + size_t omask = win_size - 1; + char *win_base = wi.win_base; + size_t l; + size_t bytes = npixels * __vesacon_bytes_per_pixel; + char rowbuf[bytes + 4] __aligned(4); + const char *s; + + s = (const char *)__vesacon_format_pixels(rowbuf, src, npixels); + + while (bytes) { + win_off = dst & omask; + win_pos = dst & ~omask; + + if (__unlikely(win_pos != wi.win_pos)) + set_window_pos(win_pos); + + l = min(bytes, win_size - win_off); + memcpy(win_base + win_off, s, l); + + bytes -= l; + s += l; + dst += l; + } +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/vesa/vesa.h b/contrib/syslinux-4.02/com32/lib/sys/vesa/vesa.h new file mode 100644 index 0000000..3926c32 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/vesa/vesa.h @@ -0,0 +1,114 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1999-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. + * + * ----------------------------------------------------------------------- */ + +#ifndef LIB_SYS_VESA_H +#define LIB_SYS_VESA_H + +#include <inttypes.h> +#include <com32.h> + +/* VESA General Information table */ +struct vesa_general_info { + uint32_t signature; /* Magic number = "VESA" */ + uint16_t version; + far_ptr_t vendor_string; + uint8_t capabilities[4]; + far_ptr_t video_mode_ptr; + uint16_t total_memory; + + uint16_t oem_software_rev; + far_ptr_t oem_vendor_name_ptr; + far_ptr_t oem_product_name_ptr; + far_ptr_t oem_product_rev_ptr; + + uint8_t reserved[222]; + uint8_t oem_data[256]; +} __attribute__ ((packed)); + +#define VESA_MAGIC ('V' + ('E' << 8) + ('S' << 16) + ('A' << 24)) +#define VBE2_MAGIC ('V' + ('B' << 8) + ('E' << 16) + ('2' << 24)) + +struct vesa_mode_info { + uint16_t mode_attr; + uint8_t win_attr[2]; + uint16_t win_grain; + uint16_t win_size; + uint16_t win_seg[2]; + far_ptr_t win_scheme; + uint16_t logical_scan; + + uint16_t h_res; + uint16_t v_res; + uint8_t char_width; + uint8_t char_height; + uint8_t memory_planes; + uint8_t bpp; + uint8_t banks; + uint8_t memory_layout; + uint8_t bank_size; + uint8_t image_pages; + uint8_t page_function; + + uint8_t rmask; + uint8_t rpos; + uint8_t gmask; + uint8_t gpos; + uint8_t bmask; + uint8_t bpos; + uint8_t resv_mask; + uint8_t resv_pos; + uint8_t dcm_info; + + uint8_t *lfb_ptr; /* Linear frame buffer address */ + uint8_t *offscreen_ptr; /* Offscreen memory address */ + uint16_t offscreen_size; + + uint8_t reserved[206]; +} __attribute__ ((packed)); + +struct vesa_info { + struct vesa_general_info gi; + struct vesa_mode_info mi; +}; + +extern struct vesa_info __vesa_info; + +#if 0 +static inline void vesa_debug(uint32_t color, int pos) +{ + uint32_t *stp = (uint32_t *) __vesa_info.mi.lfb_ptr; + stp[pos * 3] = color; +} +#else +static inline void vesa_debug(uint32_t color, int pos) +{ + (void)color; + (void)pos; +} +#endif + +#endif /* LIB_SYS_VESA_H */ diff --git a/contrib/syslinux-4.02/com32/lib/sys/vesa/video.h b/contrib/syslinux-4.02/com32/lib/sys/vesa/video.h new file mode 100644 index 0000000..d14494b --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/vesa/video.h @@ -0,0 +1,97 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2006-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. + * + * ----------------------------------------------------------------------- */ + +#ifndef LIB_SYS_VESA_VIDEO_H +#define LIB_SYS_VESA_VIDEO_H + +#include <stdbool.h> +#include <colortbl.h> +#include "vesa.h" + +#define FONT_MAX_CHARS 256 +#define FONT_MAX_HEIGHT 32 +#define FONT_WIDTH 8 + +#define DEFAULT_VESA_X_SIZE 640 +#define DEFAULT_VESA_Y_SIZE 480 + +#define VIDEO_BORDER 8 +#define TEXT_PIXEL_ROWS (__vesa_info.mi.v_res - 2*VIDEO_BORDER) +#define TEXT_PIXEL_COLS (__vesa_info.mi.h_res - 2*VIDEO_BORDER) + +typedef uint16_t attr_t; + +struct vesa_char { + uint8_t ch; /* Character */ + uint8_t _filler; /* Currently unused */ + attr_t attr; /* Color table index */ +}; + +/* Pixel formats in order of decreasing preference; PXF_NONE should be last */ +/* BGR24 is preferred over BGRA32 since the I/O overhead is smaller. */ +enum vesa_pixel_format { + PXF_BGR24, /* 24-bit BGR */ + PXF_BGRA32, /* 32-bit BGRA */ + PXF_LE_RGB16_565, /* 16-bit littleendian 5:6:5 RGB */ + PXF_LE_RGB15_555, /* 15-bit littleendian 5:5:5 RGB */ + PXF_NONE +}; +extern enum vesa_pixel_format __vesacon_pixel_format; +extern unsigned int __vesacon_bytes_per_pixel; +typedef const void *(*__vesacon_format_pixels_t) + (void *, const uint32_t *, size_t); +extern __vesacon_format_pixels_t __vesacon_format_pixels; +extern const __vesacon_format_pixels_t __vesacon_format_pixels_list[PXF_NONE]; + +extern struct vesa_char *__vesacon_text_display; + +extern int __vesacon_font_height; +extern int __vesacon_text_rows; +extern int __vesacon_text_cols; +extern uint8_t __vesacon_graphics_font[FONT_MAX_CHARS][FONT_MAX_HEIGHT]; +extern uint32_t *__vesacon_background; +extern uint32_t *__vesacon_shadowfb; + +extern const uint16_t __vesacon_srgb_to_linear[256]; +extern const uint8_t __vesacon_linear_to_srgb[4080]; + +int __vesacon_init_background(void); +int vesacon_load_background(const char *); +int __vesacon_init(int, int); +void __vesacon_init_cursor(int); +void __vesacon_erase(int, int, int, int, attr_t); +void __vesacon_scroll_up(int, attr_t); +void __vesacon_write_char(int, int, uint8_t, attr_t); +void __vesacon_redraw_text(void); +void __vesacon_doit(void); +void __vesacon_set_cursor(int, int, bool); +void __vesacon_copy_to_screen(size_t, const uint32_t *, size_t); +void __vesacon_init_copy_to_screen(void); + +int __vesacon_i915resolution(int x, int y); + +#endif /* LIB_SYS_VESA_VIDEO_H */ diff --git a/contrib/syslinux-4.02/com32/lib/sys/vesacon_write.c b/contrib/syslinux-4.02/com32/lib/sys/vesacon_write.c new file mode 100644 index 0000000..3769317 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/vesacon_write.c @@ -0,0 +1,194 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * vesacon_write.c + * + * Write to the screen using ANSI control codes (about as capable as + * DOS' ANSI.SYS.) + */ + +#include <errno.h> +#include <string.h> +#include <com32.h> +#include <minmax.h> +#include <colortbl.h> +#include <console.h> +#include <klibc/compiler.h> +#include <syslinux/config.h> +#include "ansi.h" +#include "file.h" +#include "vesa/video.h" + +static void vesacon_erase(const struct term_state *, int, int, int, int); +static void vesacon_write_char(int, int, uint8_t, const struct term_state *); +static void vesacon_showcursor(const struct term_state *); +static void vesacon_setcursor(int x, int y, bool visible); +static void vesacon_scroll_up(const struct term_state *); + +static struct term_state ts; +static struct ansi_ops op = { + .erase = vesacon_erase, + .write_char = vesacon_write_char, + .showcursor = vesacon_showcursor, + .set_cursor = vesacon_setcursor, + .scroll_up = vesacon_scroll_up, + .beep = __ansicon_beep, +}; + +static struct term_info ti = { + .disabled = 0, + .ts = &ts, + .op = &op +}; + +/* Reference counter to the screen, to keep track of if we need + reinitialization. */ +static int vesacon_counter = 0; + +static struct { + int x, y; +} vesacon_resolution = { + .x = DEFAULT_VESA_X_SIZE, + .y = DEFAULT_VESA_Y_SIZE, +}; + +/* Set desired resolution - requires a full close/open cycle */ +void vesacon_set_resolution(int x, int y) +{ + vesacon_resolution.x = x; + vesacon_resolution.y = y; +} + +/* Common setup */ +int __vesacon_open(struct file_info *fp) +{ + (void)fp; + + if (!vesacon_counter) { + /* Are we disabled? */ + if (syslinux_serial_console_info()->flowctl & 0x8000) { + ti.disabled = 1; + ti.rows = 25; + ti.cols = 80; + } else { + /* Switch mode */ + if (__vesacon_init(vesacon_resolution.x, vesacon_resolution.y)) { + vesacon_counter = -1; + return EAGAIN; + } + + /* Initial state */ + __ansi_init(&ti); + ti.rows = __vesacon_text_rows; + ti.cols = __vesacon_text_cols; + } + } else if (vesacon_counter == -1) { + return EAGAIN; + } + + fp->o.rows = ti.rows; + fp->o.cols = ti.cols; + + vesacon_counter++; + return 0; +} + +int __vesacon_close(struct file_info *fp) +{ + (void)fp; + + vesacon_counter--; + return 0; +} + +/* Erase a region of the screen */ +static void vesacon_erase(const struct term_state *st, + int x0, int y0, int x1, int y1) +{ + __vesacon_erase(x0, y0, x1, y1, st->cindex); +} + +/* Draw text on the screen */ +static void vesacon_write_char(int x, int y, uint8_t ch, + const struct term_state *st) +{ + __vesacon_write_char(x, y, ch, st->cindex); +} + +/* Show or hide the cursor */ +static bool cursor_enabled = true; +void vesacon_cursor_enable(bool enabled) +{ + cursor_enabled = enabled; +} +static void vesacon_showcursor(const struct term_state *st) +{ + vesacon_setcursor(st->xy.x, st->xy.y, st->cursor); +} +static void vesacon_setcursor(int x, int y, bool visible) +{ + __vesacon_set_cursor(x, y, visible && cursor_enabled); +} + +static void vesacon_scroll_up(const struct term_state *st) +{ + __vesacon_scroll_up(1, st->cindex); +} + +ssize_t __vesacon_write(struct file_info *fp, const void *buf, size_t count) +{ + const unsigned char *bufp = buf; + size_t n = 0; + + (void)fp; + + if (ti.disabled) + return count; /* Nothing to do */ + + /* This only updates the shadow text buffer... */ + while (count--) { + __ansi_putchar(&ti, *bufp++); + n++; + } + + /* This actually draws it */ + __vesacon_doit(); + + return n; +} + +const struct output_dev dev_vesacon_w = { + .dev_magic = __DEV_MAGIC, + .flags = __DEV_TTY | __DEV_OUTPUT, + .fileflags = O_WRONLY | O_CREAT | O_TRUNC | O_APPEND, + .write = __vesacon_write, + .close = __vesacon_close, + .open = __vesacon_open, + .fallback = &dev_ansicon_w, +}; diff --git a/contrib/syslinux-4.02/com32/lib/sys/vesaserial_write.c b/contrib/syslinux-4.02/com32/lib/sys/vesaserial_write.c new file mode 100644 index 0000000..775ca19 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/vesaserial_write.c @@ -0,0 +1,61 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * vesaserial_write.c + * + * Write to both to the VESA console and the serial port + */ + +#include <errno.h> +#include <string.h> +#include <com32.h> +#include <minmax.h> +#include <console.h> +#include "file.h" + +extern int __vesacon_open(struct file_info *); +extern int __vesacon_close(struct file_info *); +extern ssize_t __vesacon_write(struct file_info *, const void *, size_t); +extern ssize_t __xserial_write(struct file_info *, const void *, size_t); + +static ssize_t __vesaserial_write(struct file_info *fp, const void *buf, + size_t count) +{ + __vesacon_write(fp, buf, count); + return __xserial_write(fp, buf, count); +} + +const struct output_dev dev_vesaserial_w = { + .dev_magic = __DEV_MAGIC, + .flags = __DEV_TTY | __DEV_OUTPUT, + .fileflags = O_WRONLY | O_CREAT | O_TRUNC | O_APPEND, + .write = __vesaserial_write, + .close = __vesacon_close, + .open = __vesacon_open, + .fallback = &dev_ansiserial_w, +}; diff --git a/contrib/syslinux-4.02/com32/lib/sys/write.c b/contrib/syslinux-4.02/com32/lib/sys/write.c new file mode 100644 index 0000000..7961fd2 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/write.c @@ -0,0 +1,51 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * write.c + * + * Write to a file descriptor + */ + +#include <errno.h> +#include <string.h> +#include <com32.h> +#include <minmax.h> +#include <klibc/compiler.h> +#include "file.h" + +ssize_t write(int fd, void *buf, size_t count) +{ + struct file_info *fp = &__file_info[fd]; + + if (fd >= NFILES || !fp->oop) { + errno = EBADF; + return -1; + } + + return fp->oop->write(fp, buf, count); +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/x86_init_fpu.c b/contrib/syslinux-4.02/com32/lib/sys/x86_init_fpu.c new file mode 100644 index 0000000..cf33693 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/x86_init_fpu.c @@ -0,0 +1,58 @@ +/* + * x86_has_fpu.c + * + * Test for an x86 FPU, and do any necessary setup. + */ + +#include <inttypes.h> +#include <sys/fpu.h> + +static inline uint64_t get_cr0(void) +{ + uint32_t v; +asm("movl %%cr0,%0":"=r"(v)); + return v; +} + +static inline void set_cr0(uint32_t v) +{ + asm volatile ("movl %0,%%cr0"::"r" (v)); +} + +#define CR0_PE 0x00000001 +#define CR0_MP 0x00000002 +#define CR0_EM 0x00000004 +#define CR0_TS 0x00000008 +#define CR0_ET 0x00000010 +#define CR0_NE 0x00000020 +#define CR0_WP 0x00010000 +#define CR0_AM 0x00040000 +#define CR0_NW 0x20000000 +#define CR0_CD 0x40000000 +#define CR0_PG 0x80000000 + +int x86_init_fpu(void) +{ + uint32_t cr0; + uint16_t fsw = 0xffff; + uint16_t fcw = 0xffff; + + cr0 = get_cr0(); + cr0 &= ~(CR0_EM | CR0_TS); + cr0 |= CR0_MP; + set_cr0(cr0); + + asm volatile ("fninit"); + asm volatile ("fnstsw %0":"+m" (fsw)); + if (fsw != 0) + return -1; + + asm volatile ("fnstcw %0":"+m" (fcw)); + if ((fcw & 0x103f) != 0x3f) + return -1; + + /* Techically, this could be a 386 with a 287. We could add a check + for that here... */ + + return 0; +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/xserial_write.c b/contrib/syslinux-4.02/com32/lib/sys/xserial_write.c new file mode 100644 index 0000000..e399f5f --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/xserial_write.c @@ -0,0 +1,118 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * xserial_write.c + * + * Raw writing to the serial port; \n -> \r\n translation, and + * convert \1# sequences. + */ + +#include <errno.h> +#include <string.h> +#include <com32.h> +#include <minmax.h> +#include <colortbl.h> +#include <syslinux/config.h> +#include "file.h" + +static void emit(char ch) +{ + static com32sys_t ireg; /* Zeroed with the BSS */ + + ireg.eax.b[1] = 0x04; + ireg.edx.b[0] = ch; + + __intcall(0x21, &ireg, NULL); +} + +ssize_t __xserial_write(struct file_info *fp, const void *buf, size_t count) +{ + const char *bufp = buf; + size_t n = 0; + static enum { st_init, st_tbl, st_tblc } state = st_init; + static int ndigits; + static int ncolor = 0; + int num; + const char *p; + + (void)fp; + + if (!syslinux_serial_console_info()->iobase) + return count; /* Nothing to do */ + + while (count--) { + unsigned char ch = *bufp++; + + switch (state) { + case st_init: + if (ch >= 1 && ch <= 5) { + state = st_tbl; + ndigits = ch; + } else if (ch == '\n') { + emit('\r'); + emit('\n'); + } else { + emit(ch); + } + break; + + case st_tbl: + if (ch == '#') { + state = st_tblc; + ncolor = 0; + } else { + state = st_init; + } + break; + + case st_tblc: + num = ch - '0'; + if (num < 10) { + ncolor = (ncolor * 10) + num; + if (--ndigits == 0) { + if (ncolor < console_color_table_size) { + emit('\033'); + emit('['); + emit('0'); + emit(';'); + for (p = console_color_table[ncolor].ansi; *p; p++) + emit(*p); + emit('m'); + } + state = st_init; + } + } else { + state = st_init; + } + break; + } + n++; + } + + return n; +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/zeroregs.c b/contrib/syslinux-4.02/com32/lib/sys/zeroregs.c new file mode 100644 index 0000000..6d52492 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/zeroregs.c @@ -0,0 +1,5 @@ +#include <com32.h> + +/* When we don't need to pass any registers, it's convenient to just + be able to pass a prepared all-zero structure. */ +const com32sys_t __com32_zero_regs; diff --git a/contrib/syslinux-4.02/com32/lib/sys/zfile.c b/contrib/syslinux-4.02/com32/lib/sys/zfile.c new file mode 100644 index 0000000..0e6ba91 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/zfile.c @@ -0,0 +1,171 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2003-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. + * + * ----------------------------------------------------------------------- */ + +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <stdlib.h> +#include <syslinux/zio.h> + +#include "file.h" +#include "zlib.h" + +/* + * zopen.c + * + * Open an ordinary file, possibly compressed; if so, insert + * an appropriate decompressor. + */ + +int __file_get_block(struct file_info *fp); +int __file_close(struct file_info *fp); + +static ssize_t gzip_file_read(struct file_info *, void *, size_t); +static int gzip_file_close(struct file_info *); + +static const struct input_dev gzip_file_dev = { + .dev_magic = __DEV_MAGIC, + .flags = __DEV_FILE | __DEV_INPUT, + .fileflags = O_RDONLY, + .read = gzip_file_read, + .close = gzip_file_close, + .open = NULL, +}; + +static int gzip_file_init(struct file_info *fp) +{ + z_streamp zs = calloc(1, sizeof(z_stream)); + + if (!zs) + return -1; + + fp->i.pvt = zs; + + zs->next_in = (void *)fp->i.datap; + zs->avail_in = fp->i.nbytes; + + if (inflateInit2(zs, 15 + 32) != Z_OK) { + errno = EIO; + return -1; + } + + fp->iop = &gzip_file_dev; + fp->i.fd.size = -1; /* Unknown */ + + return 0; +} + +static ssize_t gzip_file_read(struct file_info *fp, void *ptr, size_t n) +{ + z_streamp zs = fp->i.pvt; + int rv; + ssize_t bytes; + ssize_t nout = 0; + unsigned char *p = ptr; + + while (n) { + zs->next_out = p; + zs->avail_out = n; + + if (!zs->avail_in && fp->i.fd.handle) { + if (__file_get_block(fp)) + return nout ? nout : -1; + + zs->next_in = (void *)fp->i.datap; + zs->avail_in = fp->i.nbytes; + } + + rv = inflate(zs, Z_SYNC_FLUSH); + + bytes = n - zs->avail_out; + nout += bytes; + p += bytes; + n -= bytes; + + switch (rv) { + case Z_DATA_ERROR: + case Z_NEED_DICT: + case Z_BUF_ERROR: + case Z_STREAM_ERROR: + default: + errno = EIO; + return nout ? nout : -1; + case Z_MEM_ERROR: + errno = ENOMEM; + return nout ? nout : -1; + case Z_STREAM_END: + return nout; + case Z_OK: + break; + } + } + + return nout; +} + +static int gzip_file_close(struct file_info *fp) +{ + z_streamp zs = fp->i.pvt; + + inflateEnd(zs); + free(zs); + return __file_close(fp); +} + +int zopen(const char *pathname, int flags, ...) +{ + int fd, rv; + struct file_info *fp; + + /* We don't actually give a hoot about the creation bits... */ + fd = open(pathname, flags, 0); + + if (fd < 0) + return -1; + + fp = &__file_info[fd]; + + /* Need to get the first block into the buffer, but not consumed */ + if (__file_get_block(fp)) + goto err; + + if (fp->i.nbytes >= 14 && + (uint8_t) fp->i.buf[0] == 037 && + (uint8_t) fp->i.buf[1] == 0213 && /* gzip */ + fp->i.buf[2] == 8) /* deflate */ + rv = gzip_file_init(fp); + else + rv = 0; /* Plain file */ + + if (!rv) + return fd; + +err: + close(fd); + return -1; +} diff --git a/contrib/syslinux-4.02/com32/lib/sys/zfopen.c b/contrib/syslinux-4.02/com32/lib/sys/zfopen.c new file mode 100644 index 0000000..752aaf4 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/sys/zfopen.c @@ -0,0 +1,44 @@ +/* + * zfopen.c + */ + +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <syslinux/zio.h> + +FILE *zfopen(const char *file, const char *mode) +{ + int flags = O_RDONLY; + int plus = 0; + int fd; + + while (*mode) { + switch (*mode) { + case 'r': + flags = O_RDONLY; + break; + case 'w': + flags = O_WRONLY | O_CREAT | O_TRUNC; + break; + case 'a': + flags = O_WRONLY | O_CREAT | O_APPEND; + break; + case '+': + plus = 1; + break; + } + mode++; + } + + if (plus) { + flags = (flags & ~(O_RDONLY | O_WRONLY)) | O_RDWR; + } + + fd = zopen(file, flags, 0666); + + if (fd < 0) + return NULL; + else + return fdopen(fd, mode); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/addlist.c b/contrib/syslinux-4.02/com32/lib/syslinux/addlist.c new file mode 100644 index 0000000..265cf4a --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/addlist.c @@ -0,0 +1,45 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +#include <stdlib.h> +#include <syslinux/movebits.h> + +int syslinux_add_movelist(struct syslinux_movelist **list, + addr_t dst, addr_t src, addr_t len) +{ + struct syslinux_movelist *ml = malloc(sizeof(struct syslinux_movelist)); + if (!ml) + return -1; + + ml->dst = dst; + ml->src = src; + ml->len = len; + ml->next = *list; + + *list = ml; + return 0; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/adv.c b/contrib/syslinux-4.02/com32/lib/syslinux/adv.c new file mode 100644 index 0000000..be38e89 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/adv.c @@ -0,0 +1,49 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/adv.c + * + * Access the syslinux auxilliary data vector + */ + +#include <syslinux/adv.h> +#include <klibc/compiler.h> +#include <com32.h> + +void *__syslinux_adv_ptr; +size_t __syslinux_adv_size; + +void __constructor __syslinux_get_adv(void) +{ + static com32sys_t reg; + + reg.eax.w[0] = 0x001c; + __intcall(0x22, ®, ®); + __syslinux_adv_ptr = MK_PTR(reg.es, reg.ebx.w[0]); + __syslinux_adv_size = reg.ecx.w[0]; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/advwrite.c b/contrib/syslinux-4.02/com32/lib/syslinux/advwrite.c new file mode 100644 index 0000000..4152eea --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/advwrite.c @@ -0,0 +1,45 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/advwrite.c + * + * Write back the ADV + */ + +#include <syslinux/adv.h> +#include <klibc/compiler.h> +#include <com32.h> + +int syslinux_adv_write(void) +{ + static com32sys_t reg; + + reg.eax.w[0] = 0x001d; + __intcall(0x22, ®, ®); + return (reg.eflags.l & EFLAGS_CF) ? -1 : 0; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/cleanup.c b/contrib/syslinux-4.02/com32/lib/syslinux/cleanup.c new file mode 100644 index 0000000..12140e5 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/cleanup.c @@ -0,0 +1,40 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +#include <syslinux/boot.h> +#include <stddef.h> +#include <com32.h> + +void syslinux_final_cleanup(uint16_t flags) +{ + static com32sys_t ireg; + + ireg.eax.w[0] = 0x000c; + ireg.edx.w[0] = flags; + + __intcall(0x22, &ireg, NULL); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/config.c b/contrib/syslinux-4.02/com32/lib/syslinux/config.c new file mode 100644 index 0000000..b27aa82 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/config.c @@ -0,0 +1,41 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +#include <syslinux/config.h> +#include <klibc/compiler.h> +#include <com32.h> + +const char *__syslinux_config_file; + +void __constructor __syslinux_get_config_file_name(void) +{ + static com32sys_t reg; + + reg.eax.w[0] = 0x000e; + __intcall(0x22, ®, ®); + __syslinux_config_file = MK_PTR(reg.es, reg.ebx.w[0]); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/dsinfo.c b/contrib/syslinux-4.02/com32/lib/syslinux/dsinfo.c new file mode 100644 index 0000000..c1f02a5 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/dsinfo.c @@ -0,0 +1,45 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2008-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * 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 <klibc/compiler.h> +#include <com32.h> + +union syslinux_derivative_info __syslinux_derivative_info; + +void __constructor __syslinux_get_derivative_info(void) +{ + com32sys_t *const r = &__syslinux_derivative_info.rr.r; + + r->eax.w[0] = 0x000A; + __intcall(0x22, r, r); + + __syslinux_derivative_info.r.esbx = MK_PTR(r->es, r->ebx.w[0]); + __syslinux_derivative_info.r.fssi = MK_PTR(r->fs, r->esi.w[0]); + __syslinux_derivative_info.r.gsdi = MK_PTR(r->gs, r->edi.w[0]); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/dump_mmap.c b/contrib/syslinux-4.02/com32/lib/syslinux/dump_mmap.c new file mode 100644 index 0000000..3f1e340 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/dump_mmap.c @@ -0,0 +1,47 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * dump_mmap.c + * + * Writes a syslinux_memmap out to a specified file. This is + * intended for debugging. + */ + +#include <stdio.h> +#include <syslinux/movebits.h> + +void syslinux_dump_memmap(FILE * file, struct syslinux_memmap *memmap) +{ + fprintf(file, "%10s %10s %10s\n" + "--------------------------------\n", "Start", "Length", "Type"); + while (memmap->next) { + fprintf(file, "0x%08x 0x%08x %10d\n", memmap->start, + memmap->next->start - memmap->start, memmap->type); + memmap = memmap->next; + } +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/dump_movelist.c b/contrib/syslinux-4.02/com32/lib/syslinux/dump_movelist.c new file mode 100644 index 0000000..282d006 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/dump_movelist.c @@ -0,0 +1,46 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * dump_movelist.c + * + * Writes a syslinux_movelist out to a specified file. This is + * intended for debugging. + */ + +#include <stdio.h> +#include <syslinux/movebits.h> + +void syslinux_dump_movelist(FILE * file, struct syslinux_movelist *ml) +{ + fprintf(file, "%10s %10s %10s\n" + "--------------------------------\n", "Dest", "Src", "Length"); + while (ml) { + fprintf(file, "0x%08x 0x%08x 0x%08x\n", ml->dst, ml->src, ml->len); + ml = ml->next; + } +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/features.c b/contrib/syslinux-4.02/com32/lib/syslinux/features.c new file mode 100644 index 0000000..c88aef3 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/features.c @@ -0,0 +1,51 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/features.c + * + * SYSLINUX feature flag query + */ + +#include <klibc/compiler.h> +#include <syslinux/features.h> +#include <string.h> +#include <com32.h> + +struct __syslinux_feature_flags __syslinux_feature_flags; + +void __constructor __syslinux_detect_features(void) +{ + static com32sys_t reg; + + memset(®, 0, sizeof reg); + reg.eax.w[0] = 0x0015; + __intcall(0x22, ®, ®); + + __syslinux_feature_flags.len = reg.ecx.w[0]; + __syslinux_feature_flags.ptr = MK_PTR(reg.es, reg.ebx.w[0]); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/floadfile.c b/contrib/syslinux-4.02/com32/lib/syslinux/floadfile.c new file mode 100644 index 0000000..ece460d --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/floadfile.c @@ -0,0 +1,108 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2005-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. + * + * ----------------------------------------------------------------------- */ + +/* + * floadfile.c + * + * Read the contents of a data file into a malloc'd buffer + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <sys/stat.h> + +#include <syslinux/loadfile.h> + +#define INCREMENTAL_CHUNK 1024*1024 + +int floadfile(FILE * f, void **ptr, size_t * len, const void *prefix, + size_t prefix_len) +{ + struct stat st; + void *data, *dp; + size_t alen, clen, rlen, xlen; + + clen = alen = 0; + data = NULL; + + if (fstat(fileno(f), &st)) + goto err; + + if (!S_ISREG(st.st_mode)) { + /* Not a regular file, we can't assume we know the file size */ + if (prefix_len) { + clen = alen = prefix_len; + data = malloc(prefix_len); + if (!data) + goto err; + + memcpy(data, prefix, prefix_len); + } + + do { + alen += INCREMENTAL_CHUNK; + dp = realloc(data, alen); + if (!dp) + goto err; + data = dp; + + rlen = fread((char *)data + clen, 1, alen - clen, f); + clen += rlen; + } while (clen == alen); + + *len = clen; + xlen = (clen + LOADFILE_ZERO_PAD - 1) & ~(LOADFILE_ZERO_PAD - 1); + dp = realloc(data, xlen); + if (dp) + data = dp; + *ptr = data; + } else { + *len = clen = st.st_size + prefix_len - ftell(f); + xlen = (clen + LOADFILE_ZERO_PAD - 1) & ~(LOADFILE_ZERO_PAD - 1); + + *ptr = data = malloc(xlen); + if (!data) + return -1; + + memcpy(data, prefix, prefix_len); + + if ((off_t) fread((char *)data + prefix_len, 1, clen - prefix_len, f) + != clen - prefix_len) + goto err; + } + + memset((char *)data + clen, 0, xlen - clen); + return 0; + +err: + if (data) + free(data); + return -1; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/freelist.c b/contrib/syslinux-4.02/com32/lib/syslinux/freelist.c new file mode 100644 index 0000000..f73a69c --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/freelist.c @@ -0,0 +1,46 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * freelist.c + * + * Frees a syslinux_movelist + */ + +#include <stdlib.h> +#include <syslinux/movebits.h> + +void syslinux_free_movelist(struct syslinux_movelist *list) +{ + struct syslinux_movelist *m; + + while (list) { + m = list; + list = list->next; + free(m); + } +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/getadv.c b/contrib/syslinux-4.02/com32/lib/syslinux/getadv.c new file mode 100644 index 0000000..5578313 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/getadv.c @@ -0,0 +1,68 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/getadv.c + * + * Get a data item from the auxilliary data vector. Returns a pointer + * and sets *size on success; NULL on failure. + */ + +#include <syslinux/adv.h> +#include <klibc/compiler.h> +#include <inttypes.h> + +const void *syslinux_getadv(int tag, size_t * size) +{ + const uint8_t *p; + size_t left; + + p = syslinux_adv_ptr(); + left = syslinux_adv_size(); + + while (left >= 2) { + uint8_t ptag = *p++; + size_t plen = *p++; + left -= 2; + + if (ptag == ADV_END) + return NULL; /* Not found */ + + if (left < plen) + return NULL; /* Item overrun */ + + if (ptag == tag) { + *size = plen; + return p; + } + + p += plen; + left -= plen; + } + + return NULL; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/idle.c b/contrib/syslinux-4.02/com32/lib/syslinux/idle.c new file mode 100644 index 0000000..ddaa7fc --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/idle.c @@ -0,0 +1,47 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2005-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. + * + * ----------------------------------------------------------------------- */ + +/* + * idle.c + * + * What to do in a busy loop... + */ + +#include <stddef.h> +#include <com32.h> +#include <syslinux/pmapi.h> +#include <syslinux/idle.h> + +void syslinux_reset_idle(void) +{ + __com32.cs_pm->reset_idle(); +} + +void syslinux_idle(void) +{ + __com32.cs_pm->idle(); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/initramfs.c b/contrib/syslinux-4.02/com32/lib/syslinux/initramfs.c new file mode 100644 index 0000000..220e162 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/initramfs.c @@ -0,0 +1,76 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * initramfs.c + * + * Utility functions for initramfs manipulation + */ + +#include <stdlib.h> +#include <syslinux/linux.h> + +struct initramfs *initramfs_init(void) +{ + struct initramfs *ir; + + ir = calloc(sizeof(*ir), 1); + if (!ir) + return NULL; + + ir->prev = ir->next = ir; + return ir; +} + +int initramfs_add_data(struct initramfs *ihead, const void *data, + size_t data_len, size_t len, size_t align) +{ + struct initramfs *in; + + if (!len) + return 0; /* Nothing to add... */ + + /* Alignment must be a power of 2, and <= INITRAMFS_MAX_ALIGN */ + if (!align || (align & (align - 1)) || align > INITRAMFS_MAX_ALIGN) + return -1; + + in = malloc(sizeof(*in)); + if (!in) + return -1; + + in->len = len; + in->data = data; + in->data_len = data_len; + in->align = align; + + in->next = ihead; + in->prev = ihead->prev; + ihead->prev->next = in; + ihead->prev = in; + + return 0; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/initramfs_archive.c b/contrib/syslinux-4.02/com32/lib/syslinux/initramfs_archive.c new file mode 100644 index 0000000..495b78e --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/initramfs_archive.c @@ -0,0 +1,47 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * initramfs_archive.c + * + * Utility function to load an initramfs archive. + */ + +#include <stdlib.h> +#include <syslinux/loadfile.h> +#include <syslinux/linux.h> + +int initramfs_load_archive(struct initramfs *ihead, const char *filename) +{ + void *data; + size_t len; + + if (loadfile(filename, &data, &len)) + return -1; + + return initramfs_add_data(ihead, data, len, len, 4); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/initramfs_file.c b/contrib/syslinux-4.02/com32/lib/syslinux/initramfs_file.c new file mode 100644 index 0000000..763eff2 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/initramfs_file.c @@ -0,0 +1,161 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * initramfs_file.c + * + * Utility functions to add arbitrary files including cpio header + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <sys/stat.h> +#include <syslinux/linux.h> + +#define CPIO_MAGIC "070701" +struct cpio_header { + char c_magic[6]; /* 070701 */ + char c_ino[8]; /* Inode number */ + char c_mode[8]; /* File mode and permissions */ + char c_uid[8]; /* uid */ + char c_gid[8]; /* gid */ + char c_nlink[8]; /* Number of links */ + char c_mtime[8]; /* Modification time */ + char c_filesize[8]; /* Size of data field */ + char c_maj[8]; /* File device major number */ + char c_min[8]; /* File device minor number */ + char c_rmaj[8]; /* Device node reference major number */ + char c_rmin[8]; /* Device node reference minor number */ + char c_namesize[8]; /* Length of filename including final \0 */ + char c_chksum[8]; /* Checksum if c_magic ends in 2 */ +}; + +static uint32_t next_ino = 1; + +/* Create cpio headers for the directory entries leading up to a file. + Returns the number of bytes; doesn't touch the buffer if too small. */ +static size_t initramfs_mkdirs(const char *filename, void *buffer, + size_t buflen) +{ + const char *p = filename; + char *bp = buffer; + int len; + size_t bytes = 0; + int pad; + + while ((p = strchr(p, '/'))) { + if (p != filename && p[-1] != '/') { + len = p - filename; + bytes += ((sizeof(struct cpio_header) + len + 1) + 3) & ~3; + } + p++; + } + + if (buflen >= bytes) { + p = filename; + while ((p = strchr(p, '/'))) { + if (p != filename && p[-1] != '/') { + len = p - filename; + bp += sprintf(bp, "070701%08x%08x%08x%08x%08x%08x%08x%08x%08x" + "%08x%08x%08x%08x", next_ino++, S_IFDIR | 0755, + 0, 0, 1, 0, 0, 0, 1, 0, 1, len + 1, 0); + memcpy(bp, filename, len); + bp += len; + pad = (-(sizeof(struct cpio_header) + len) & 3) + 1; + memset(bp, 0, pad); + bp += pad; + } + } + } + + return bytes; +} + +/* + * Create a file header (with optional parent directory entries) + * and add it to an initramfs chain + */ +int initramfs_mknod(struct initramfs *ihead, const char *filename, + int do_mkdir, + uint16_t mode, size_t len, uint32_t major, uint32_t minor) +{ + size_t bytes; + int namelen = strlen(filename); + int pad; + char *buffer, *bp; + + if (do_mkdir) + bytes = initramfs_mkdirs(filename, NULL, 0); + else + bytes = 0; + + bytes += ((sizeof(struct cpio_header) + namelen + 1) + 3) & ~3; + + bp = buffer = malloc(bytes); + if (!buffer) + return -1; + + if (do_mkdir) + bp += initramfs_mkdirs(filename, bp, bytes); + + bp += sprintf(bp, "070701%08x%08x%08x%08x%08x%08x%08x%08x%08x" + "%08x%08x%08x%08x", next_ino++, mode, + 0, 0, 1, 0, len, 0, 1, major, minor, namelen + 1, 0); + memcpy(bp, filename, namelen); + bp += len; + pad = (-(sizeof(struct cpio_header) + namelen) & 3) + 1; + memset(bp, 0, pad); + + if (initramfs_add_data(ihead, buffer, bytes, bytes, 4)) { + free(buffer); + return -1; + } + + return 0; +} + +/* + * Add a file given data in memory to an initramfs chain. This + * can be used to create nonfiles like symlinks by specifying an + * appropriate mode. + */ +int initramfs_add_file(struct initramfs *ihead, const void *data, + size_t data_len, size_t len, + const char *filename, int do_mkdir, uint32_t mode) +{ + if (initramfs_mknod(ihead, filename, do_mkdir, + (mode & S_IFMT) ? mode : mode | S_IFREG, len, 0, 1)) + return -1; + + return initramfs_add_data(ihead, data, data_len, len, 4); +} + +int initramfs_add_trailer(struct initramfs *ihead) +{ + return initramfs_mknod(ihead, "TRAILER!!!", 0, 0, 0, 0, 0); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/initramfs_loadfile.c b/contrib/syslinux-4.02/com32/lib/syslinux/initramfs_loadfile.c new file mode 100644 index 0000000..1338aad --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/initramfs_loadfile.c @@ -0,0 +1,48 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * initramfs_loadfile.c + * + * Load a single file into an initramfs image. + */ + +#include <syslinux/linux.h> +#include <syslinux/loadfile.h> + +int initramfs_load_file(struct initramfs *ihead, const char *src_filename, + const char *dst_filename, int do_mkdir, uint32_t mode) +{ + void *data; + size_t len; + + if (loadfile(src_filename, &data, &len)) + return -1; + + return initramfs_add_file(ihead, data, len, len, dst_filename, + do_mkdir, mode); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/ipappend.c b/contrib/syslinux-4.02/com32/lib/syslinux/ipappend.c new file mode 100644 index 0000000..bd00092 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/ipappend.c @@ -0,0 +1,58 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 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. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/ipappend.c + * + * Get ipappend strings + */ + +#include <syslinux/config.h> +#include <klibc/compiler.h> +#include <com32.h> + +struct syslinux_ipappend_strings __syslinux_ipappend_strings; +static const char *syslinux_ipappend_string_list[32]; + +void __constructor __syslinux_get_ipappend_strings(void) +{ + static com32sys_t reg; + int i; + + reg.eax.w[0] = 0x000f; + __intcall(0x22, ®, ®); + + if (!(reg.eflags.l & EFLAGS_CF)) { + __syslinux_ipappend_strings.count = reg.ecx.w[0]; + __syslinux_ipappend_strings.ptr = syslinux_ipappend_string_list; + for (i = 0; i < reg.ecx.w[0]; i++) { + syslinux_ipappend_string_list[i] = + MK_PTR(reg.es, + *(uint16_t *) MK_PTR(reg.es, reg.ebx.w[0] + i * 2)); + } + } +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/keyboard.c b/contrib/syslinux-4.02/com32/lib/syslinux/keyboard.c new file mode 100644 index 0000000..feafde0 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/keyboard.c @@ -0,0 +1,44 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * 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/keyboard.h> +#include <com32.h> + +struct syslinux_keyboard_map __syslinux_keyboard_map; + +void __constructor __syslinux_get_keyboard_map(void) +{ + static com32sys_t reg; + + reg.eax.w[0] = 0x001e; + __intcall(0x22, ®, ®); + if (!(reg.eflags.l & EFLAGS_CF)) { + __syslinux_keyboard_map.version = reg.eax.w[0]; + __syslinux_keyboard_map.length = reg.ecx.w[0]; + __syslinux_keyboard_map.map = MK_PTR(reg.es, reg.ebx.w[0]); + } +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/load_linux.c b/contrib/syslinux-4.02/com32/lib/syslinux/load_linux.c new file mode 100644 index 0000000..df79362 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/load_linux.c @@ -0,0 +1,511 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * load_linux.c + * + * Load a Linux kernel (Image/zImage/bzImage). + */ + +#include <ctype.h> +#include <stdbool.h> +#include <stdlib.h> +#include <inttypes.h> +#include <string.h> +#include <minmax.h> +#include <syslinux/align.h> +#include <syslinux/linux.h> +#include <syslinux/bootrm.h> +#include <syslinux/movebits.h> + +#ifndef DEBUG +# define DEBUG 0 +#endif +#if DEBUG +# include <stdio.h> +# define dprintf printf +#else +# define dprintf(f, ...) ((void)0) +#endif + +struct linux_header { + uint8_t boot_sector_1[0x0020]; + uint16_t old_cmd_line_magic; + uint16_t old_cmd_line_offset; + uint8_t boot_sector_2[0x01f1 - 0x0024]; + uint8_t setup_sects; + uint16_t root_flags; + uint32_t syssize; + uint16_t ram_size; + uint16_t vid_mode; + uint16_t root_dev; + uint16_t boot_flag; + uint16_t jump; + uint32_t header; + uint16_t version; + uint32_t realmode_swtch; + uint16_t start_sys; + uint16_t kernel_version; + uint8_t type_of_loader; + uint8_t loadflags; + uint16_t setup_move_size; + uint32_t code32_start; + uint32_t ramdisk_image; + uint32_t ramdisk_size; + uint32_t bootsect_kludge; + uint16_t heap_end_ptr; + uint16_t pad1; + uint32_t cmd_line_ptr; + uint32_t initrd_addr_max; + uint32_t kernel_alignment; + uint8_t relocatable_kernel; + uint8_t pad2[3]; + uint32_t cmdline_max_len; +} __packed; + +#define BOOT_MAGIC 0xAA55 +#define LINUX_MAGIC ('H' + ('d' << 8) + ('r' << 16) + ('S' << 24)) +#define OLD_CMDLINE_MAGIC 0xA33F + +/* loadflags */ +#define LOAD_HIGH 0x01 +#define CAN_USE_HEAP 0x80 + +/* Get a value with a potential suffix (k/m/g/t/p/e) */ +static unsigned long long suffix_number(const char *str) +{ + char *ep; + unsigned long long v; + int shift; + + v = strtoull(str, &ep, 0); + switch (*ep | 0x20) { + case 'k': + shift = 10; + break; + case 'm': + shift = 20; + break; + case 'g': + shift = 30; + break; + case 't': + shift = 40; + break; + case 'p': + shift = 50; + break; + case 'e': + shift = 60; + break; + default: + shift = 0; + break; + } + v <<= shift; + + return v; +} + +/* + * Find the last instance of a particular command line argument + * (which should include the final =; do not use for boolean arguments) + * Note: the resulting string is typically not null-terminated. + */ +static const char *find_argument(const char *cmdline, const char *argument) +{ + const char *found = NULL; + const char *p = cmdline; + bool was_space = true; + size_t la = strlen(argument); + + while (*p) { + if (isspace(*p)) { + was_space = true; + } else if (was_space) { + if (!memcmp(p, argument, la)) + found = p + la; + was_space = false; + } + p++; + } + + return found; +} + +/* Truncate to 32 bits, with saturate */ +static inline uint32_t saturate32(unsigned long long v) +{ + return (v > 0xffffffff) ? 0xffffffff : (uint32_t) v; +} + +/* Get the combined size of the initramfs */ +static addr_t initramfs_size(struct initramfs *initramfs) +{ + struct initramfs *ip; + addr_t size = 0; + + if (!initramfs) + return 0; + + for (ip = initramfs->next; ip->len; ip = ip->next) { + size = (size + ip->align - 1) & ~(ip->align - 1); /* Alignment */ + size += ip->len; + } + + return size; +} + +/* Create the appropriate mappings for the initramfs */ +static int map_initramfs(struct syslinux_movelist **fraglist, + struct syslinux_memmap **mmap, + struct initramfs *initramfs, addr_t addr) +{ + struct initramfs *ip; + addr_t next_addr, len, pad; + + for (ip = initramfs->next; ip->len; ip = ip->next) { + len = ip->len; + next_addr = addr + len; + + /* If this isn't the last entry, extend the zero-pad region + to enforce the alignment of the next chunk. */ + if (ip->next->len) { + pad = -next_addr & (ip->next->align - 1); + len += pad; + next_addr += pad; + } + + if (ip->data_len) { + if (syslinux_add_movelist(fraglist, addr, (addr_t) ip->data, len)) + return -1; + } + if (len > ip->data_len) { + if (syslinux_add_memmap(mmap, addr + ip->data_len, + len - ip->data_len, SMT_ZERO)) + return -1; + } + addr = next_addr; + } + + return 0; +} + +int syslinux_boot_linux(void *kernel_buf, size_t kernel_size, + struct initramfs *initramfs, char *cmdline) +{ + struct linux_header hdr, *whdr; + size_t real_mode_size, prot_mode_size; + addr_t real_mode_base, prot_mode_base; + addr_t irf_size; + size_t cmdline_size, cmdline_offset; + struct syslinux_rm_regs regs; + struct syslinux_movelist *fraglist = NULL; + struct syslinux_memmap *mmap = NULL; + struct syslinux_memmap *amap = NULL; + bool ok; + uint32_t memlimit = 0; + uint16_t video_mode = 0; + const char *arg; + + cmdline_size = strlen(cmdline) + 1; + + if (kernel_size < 2 * 512) + goto bail; + + /* Look for specific command-line arguments we care about */ + if ((arg = find_argument(cmdline, "mem="))) + memlimit = saturate32(suffix_number(arg)); + + if ((arg = find_argument(cmdline, "vga="))) { + switch (arg[0] | 0x20) { + case 'a': /* "ask" */ + video_mode = 0xfffd; + break; + case 'e': /* "ext" */ + video_mode = 0xfffe; + break; + case 'n': /* "normal" */ + video_mode = 0xffff; + break; + case 'c': /* "current" */ + video_mode = 0x0f04; + break; + default: + video_mode = strtoul(arg, NULL, 0); + break; + } + } + + /* Copy the header into private storage */ + /* Use whdr to modify the actual kernel header */ + memcpy(&hdr, kernel_buf, sizeof hdr); + whdr = (struct linux_header *)kernel_buf; + + if (hdr.boot_flag != BOOT_MAGIC) + goto bail; + + if (hdr.header != LINUX_MAGIC) { + hdr.version = 0x0100; /* Very old kernel */ + hdr.loadflags = 0; + } + + whdr->vid_mode = video_mode; + + if (!hdr.setup_sects) + hdr.setup_sects = 4; + + if (hdr.version < 0x0203) + hdr.initrd_addr_max = 0x37ffffff; + + if (!memlimit && memlimit - 1 > hdr.initrd_addr_max) + memlimit = hdr.initrd_addr_max + 1; /* Zero for no limit */ + + if (hdr.version < 0x0205 || !(hdr.loadflags & LOAD_HIGH)) + hdr.relocatable_kernel = 0; + + if (hdr.version < 0x0206) + hdr.cmdline_max_len = 256; + + if (cmdline_size > hdr.cmdline_max_len) { + cmdline_size = hdr.cmdline_max_len; + cmdline[cmdline_size - 1] = '\0'; + } + + if (hdr.version < 0x0202 || !(hdr.loadflags & 0x01)) + cmdline_offset = (0x9ff0 - cmdline_size) & ~15; + else + cmdline_offset = 0x10000; + + real_mode_size = (hdr.setup_sects + 1) << 9; + real_mode_base = (hdr.loadflags & LOAD_HIGH) ? 0x10000 : 0x90000; + prot_mode_base = (hdr.loadflags & LOAD_HIGH) ? 0x100000 : 0x10000; + prot_mode_size = kernel_size - real_mode_size; + + if (!(hdr.loadflags & LOAD_HIGH) && prot_mode_size > 512 * 1024) + goto bail; /* Kernel cannot be loaded low */ + + if (initramfs && hdr.version < 0x0200) + goto bail; /* initrd/initramfs not supported */ + + if (hdr.version >= 0x0200) { + whdr->type_of_loader = 0x30; /* SYSLINUX unknown module */ + if (hdr.version >= 0x0201) { + whdr->heap_end_ptr = cmdline_offset - 0x0200; + whdr->loadflags |= CAN_USE_HEAP; + } + if (hdr.version >= 0x0202) { + whdr->cmd_line_ptr = real_mode_base + cmdline_offset; + } else { + whdr->old_cmd_line_magic = OLD_CMDLINE_MAGIC; + whdr->old_cmd_line_offset = cmdline_offset; + /* Be paranoid and round up to a multiple of 16 */ + whdr->setup_move_size = (cmdline_offset + cmdline_size + 15) & ~15; + } + } + + /* Get the memory map */ + mmap = syslinux_memory_map(); /* Memory map for shuffle_boot */ + amap = syslinux_dup_memmap(mmap); /* Keep track of available memory */ + if (!mmap || !amap) + goto bail; + +#if DEBUG + dprintf("Initial memory map:\n"); + syslinux_dump_memmap(stdout, mmap); +#endif + + /* If the user has specified a memory limit, mark that as unavailable. + Question: should we mark this off-limit in the mmap as well (meaning + it's unavailable to the boot loader, which probably has already touched + some of it), or just in the amap? */ + if (memlimit) + if (syslinux_add_memmap(&amap, memlimit, -memlimit, SMT_RESERVED)) + goto bail; + + /* Place the kernel in memory */ + + /* First, find a suitable place for the protected-mode code */ + if (syslinux_memmap_type(amap, prot_mode_base, prot_mode_size) + != SMT_FREE) { + const struct syslinux_memmap *mp; + if (!hdr.relocatable_kernel) + goto bail; /* Can't relocate - no hope */ + + ok = false; + for (mp = amap; mp; mp = mp->next) { + addr_t start, end; + start = mp->start; + end = mp->next->start; + + if (mp->type != SMT_FREE) + continue; + + if (end <= prot_mode_base) + continue; /* Only relocate upwards */ + + if (start <= prot_mode_base) + start = prot_mode_base; + + start = ALIGN_UP(start, hdr.kernel_alignment); + if (start >= end) + continue; + + /* The 3* here is a total fudge factor... it's supposed to + account for the fact that the kernel needs to be decompressed, + and then followed by the BSS and BRK regions. This doesn't, + however, account for the fact that the kernel is decompressed + into a whole other place, either. */ + if (end - start >= 3 * prot_mode_size) { + whdr->code32_start += start - prot_mode_base; + prot_mode_base = start; + ok = true; + break; + } + } + + if (!ok) + goto bail; + } + + /* Real mode code */ + if (syslinux_memmap_type(amap, real_mode_base, + cmdline_offset + cmdline_size) != SMT_FREE) { + const struct syslinux_memmap *mp; + + ok = false; + for (mp = amap; mp; mp = mp->next) { + addr_t start, end; + start = mp->start; + end = mp->next->start; + + if (mp->type != SMT_FREE) + continue; + + if (start < real_mode_base) + start = real_mode_base; /* Lowest address we'll use */ + if (end > 640 * 1024) + end = 640 * 1024; + + start = ALIGN_UP(start, 16); + if (start > 0x90000 || start >= end) + continue; + + if (end - start >= cmdline_offset + cmdline_size) { + real_mode_base = start; + ok = true; + break; + } + } + } + + if (syslinux_add_movelist(&fraglist, real_mode_base, (addr_t) kernel_buf, + real_mode_size)) + goto bail; + if (syslinux_add_memmap + (&amap, real_mode_base, cmdline_offset + cmdline_size, SMT_ALLOC)) + goto bail; + + /* Zero region between real mode code and cmdline */ + if (syslinux_add_memmap(&mmap, real_mode_base + real_mode_size, + cmdline_offset - real_mode_size, SMT_ZERO)) + goto bail; + + /* Command line */ + if (syslinux_add_movelist(&fraglist, real_mode_base + cmdline_offset, + (addr_t) cmdline, cmdline_size)) + goto bail; + + /* Protected-mode code */ + if (syslinux_add_movelist(&fraglist, prot_mode_base, + (addr_t) kernel_buf + real_mode_size, + prot_mode_size)) + goto bail; + if (syslinux_add_memmap(&amap, prot_mode_base, prot_mode_size, SMT_ALLOC)) + goto bail; + + /* Figure out the size of the initramfs, and where to put it. + We should put it at the highest possible address which is + <= hdr.initrd_addr_max, which fits the entire initramfs. */ + + irf_size = initramfs_size(initramfs); /* Handles initramfs == NULL */ + + if (irf_size) { + addr_t best_addr = 0; + struct syslinux_memmap *ml; + const addr_t align_mask = INITRAMFS_MAX_ALIGN - 1; + + if (irf_size) { + for (ml = amap; ml->type != SMT_END; ml = ml->next) { + addr_t adj_start = (ml->start + align_mask) & ~align_mask; + addr_t adj_end = ml->next->start & ~align_mask; + if (ml->type == SMT_FREE && adj_end - adj_start >= irf_size) + best_addr = (adj_end - irf_size) & ~align_mask; + } + + if (!best_addr) + goto bail; /* Insufficient memory for initramfs */ + + whdr->ramdisk_image = best_addr; + whdr->ramdisk_size = irf_size; + + if (syslinux_add_memmap(&amap, best_addr, irf_size, SMT_ALLOC)) + goto bail; + + if (map_initramfs(&fraglist, &mmap, initramfs, best_addr)) + goto bail; + } + } + + /* Set up the registers on entry */ + memset(®s, 0, sizeof regs); + regs.es = regs.ds = regs.ss = regs.fs = regs.gs = real_mode_base >> 4; + regs.cs = (real_mode_base >> 4) + 0x20; + /* regs.ip = 0; */ + /* Linux is OK with sp = 0 = 64K, but perhaps other things aren't... */ + regs.esp.w[0] = min(cmdline_offset, (size_t) 0xfff0); + +#if DEBUG + dprintf("Final memory map:\n"); + syslinux_dump_memmap(stdout, mmap); + + dprintf("Final available map:\n"); + syslinux_dump_memmap(stdout, amap); + + dprintf("Initial movelist:\n"); + syslinux_dump_movelist(stdout, fraglist); +#endif + + syslinux_shuffle_boot_rm(fraglist, mmap, 0, ®s); + +bail: + syslinux_free_movelist(fraglist); + syslinux_free_memmap(mmap); + syslinux_free_memmap(amap); + return -1; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/loadfile.c b/contrib/syslinux-4.02/com32/lib/syslinux/loadfile.c new file mode 100644 index 0000000..fa96c65 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/loadfile.c @@ -0,0 +1,63 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2005-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. + * + * ----------------------------------------------------------------------- */ + +/* + * loadfile.c + * + * Read the contents of a data file into a malloc'd buffer + */ + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <sys/stat.h> + +#include <syslinux/loadfile.h> + +#define INCREMENTAL_CHUNK 1024*1024 + +int loadfile(const char *filename, void **ptr, size_t * len) +{ + FILE *f; + int rv, e; + + f = fopen(filename, "r"); + if (!f) + return -1; + + rv = floadfile(f, ptr, len, NULL, 0); + e = errno; + + fclose(f); + + if (rv) + errno = e; + return rv; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/localboot.c b/contrib/syslinux-4.02/com32/lib/syslinux/localboot.c new file mode 100644 index 0000000..3b480c7 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/localboot.c @@ -0,0 +1,42 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +#include <syslinux/boot.h> +#include <stddef.h> +#include <com32.h> + +/* This returns only on failure */ + +void syslinux_local_boot(uint16_t flags) +{ + static com32sys_t ireg; + + ireg.eax.w[0] = 0x0014; + ireg.edx.w[0] = flags; + + __intcall(0x22, &ireg, NULL); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/memmap.c b/contrib/syslinux-4.02/com32/lib/syslinux/memmap.c new file mode 100644 index 0000000..12baa33 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/memmap.c @@ -0,0 +1,65 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * memmap.c + * + * Create initial memory map for "shuffle and boot" operation + */ + +#include <assert.h> +#include <stdbool.h> +#include <stdlib.h> +#include <inttypes.h> + +#include <syslinux/memscan.h> +#include <syslinux/movebits.h> + +static int syslinux_memory_map_callback(void *map, addr_t start, + addr_t len, bool valid) +{ + struct syslinux_memmap **mmap = map; + return syslinux_add_memmap(mmap, start, len, + valid ? SMT_FREE : SMT_RESERVED); +} + +struct syslinux_memmap *syslinux_memory_map(void) +{ + struct syslinux_memmap *mmap; + + mmap = syslinux_init_memmap(); + if (!mmap) + return NULL; + + if (syslinux_scan_memory(syslinux_memory_map_callback, &mmap)) { + syslinux_free_memmap(mmap); + return NULL; + } + + return mmap; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/memscan.c b/contrib/syslinux-4.02/com32/lib/syslinux/memscan.c new file mode 100644 index 0000000..fc676cb --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/memscan.c @@ -0,0 +1,158 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2009 H. Peter Anvin - All Rights Reserved + * Copyright 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 + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * memscan.c + * + * Query the system for free memory + */ + +#include <assert.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <inttypes.h> +#include <com32.h> + +#include <syslinux/memscan.h> + +struct e820_entry { + uint64_t start; + uint64_t len; + uint32_t type; +}; + +int syslinux_scan_memory(scan_memory_callback_t callback, void *data) +{ + static com32sys_t ireg; + com32sys_t oreg; + struct e820_entry *e820buf; + uint64_t start, len, maxlen; + int memfound = 0; + int rv; + addr_t dosmem; + const addr_t bios_data = 0x510; /* Amount to reserve for BIOS data */ + + /* Use INT 12h to get DOS memory */ + __intcall(0x12, &__com32_zero_regs, &oreg); + dosmem = oreg.eax.w[0] << 10; + if (dosmem < 32 * 1024 || dosmem > 640 * 1024) { + /* INT 12h reports nonsense... now what? */ + uint16_t ebda_seg = *(uint16_t *) 0x40e; + if (ebda_seg >= 0x8000 && ebda_seg < 0xa000) + dosmem = ebda_seg << 4; + else + dosmem = 640 * 1024; /* Hope for the best... */ + } + rv = callback(data, bios_data, dosmem - bios_data, true); + if (rv) + return rv; + + /* First try INT 15h AX=E820h */ + e820buf = lzalloc(sizeof *e820buf); + if (!e820buf) + return -1; + + ireg.eax.l = 0xe820; + ireg.edx.l = 0x534d4150; + ireg.ebx.l = 0; + ireg.ecx.l = sizeof(*e820buf); + ireg.es = SEG(e820buf); + ireg.edi.w[0] = OFFS(e820buf); + + do { + __intcall(0x15, &ireg, &oreg); + + if ((oreg.eflags.l & EFLAGS_CF) || + (oreg.eax.l != 0x534d4150) || (oreg.ecx.l < 20)) + break; + + start = e820buf->start; + len = e820buf->len; + + if (start < 0x100000000ULL) { + /* Don't rely on E820 being valid for low memory. Doing so + could mean stuff like overwriting the PXE stack even when + using "keeppxe", etc. */ + if (start < 0x100000ULL) { + if (len > 0x100000ULL - start) + len -= 0x100000ULL - start; + else + len = 0; + start = 0x100000ULL; + } + + maxlen = 0x100000000ULL - start; + if (len > maxlen) + len = maxlen; + + if (len) { + rv = callback(data, (addr_t) start, (addr_t) len, + e820buf->type == 1); + if (rv) + return rv; + memfound = 1; + } + } + + ireg.ebx.l = oreg.ebx.l; + } while (oreg.ebx.l); + + lfree(e820buf); + + if (memfound) + return 0; + + /* Next try INT 15h AX=E801h */ + ireg.eax.w[0] = 0xe801; + __intcall(0x15, &ireg, &oreg); + + if (!(oreg.eflags.l & EFLAGS_CF) && oreg.ecx.w[0]) { + rv = callback(data, (addr_t) 1 << 20, oreg.ecx.w[0] << 10, true); + if (rv) + return rv; + + if (oreg.edx.w[0]) { + rv = callback(data, (addr_t) 16 << 20, oreg.edx.w[0] << 16, true); + if (rv) + return rv; + } + + return 0; + } + + /* Finally try INT 15h AH=88h */ + ireg.eax.w[0] = 0x8800; + if (!(oreg.eflags.l & EFLAGS_CF) && oreg.eax.w[0]) { + rv = callback(data, (addr_t) 1 << 20, oreg.ecx.w[0] << 10, true); + if (rv) + return rv; + } + + return 0; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/movebits.c b/contrib/syslinux-4.02/com32/lib/syslinux/movebits.c new file mode 100644 index 0000000..bd5ce0e --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/movebits.c @@ -0,0 +1,710 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * movebits.c + * + * Utility function to take a list of memory areas to shuffle and + * convert it to a set of shuffle operations. + * + * Note: a lot of the functions in this file deal with "parent pointers", + * which are pointers to a pointer to a list, or part of the list. + * They can be pointers to a variable holding the list root pointer, + * or pointers to a next field of a previous entry. + */ + +#include <assert.h> +#include <stdio.h> +#include <errno.h> +#include <stdlib.h> +#include <inttypes.h> +#include <setjmp.h> +#include <minmax.h> +#include <stdbool.h> + +#include <syslinux/movebits.h> + +#ifndef DEBUG +# ifdef TEST +# define DEBUG 1 +# else +# define DEBUG 0 +# endif +#endif + +#if DEBUG +# include <stdio.h> +# define dprintf printf +#else +# define dprintf(...) ((void)0) +#endif + +static jmp_buf new_movelist_bail; + +static struct syslinux_movelist *new_movelist(addr_t dst, addr_t src, + addr_t len) +{ + struct syslinux_movelist *ml = malloc(sizeof(struct syslinux_movelist)); + + if (!ml) + longjmp(new_movelist_bail, 1); + + ml->dst = dst; + ml->src = src; + ml->len = len; + ml->next = NULL; + + return ml; +} + +static struct syslinux_movelist *dup_movelist(struct syslinux_movelist *src) +{ + struct syslinux_movelist *dst = NULL, **dstp = &dst, *ml; + + while (src) { + ml = new_movelist(src->dst, src->src, src->len); + *dstp = ml; + dstp = &ml->next; + src = src->next; + } + + return dst; +} + +static void +add_freelist(struct syslinux_memmap **mmap, addr_t start, + addr_t len, enum syslinux_memmap_types type) +{ + if (syslinux_add_memmap(mmap, start, len, type)) + longjmp(new_movelist_bail, 1); +} + +/* + * Take a chunk, entirely confined in **parentptr, and split it off so that + * it has its own structure. + */ +static struct syslinux_movelist **split_movelist(addr_t start, addr_t len, + struct syslinux_movelist + **parentptr) +{ + struct syslinux_movelist *m, *ml = *parentptr; + + assert(start >= ml->src); + assert(start < ml->src + ml->len); + + /* Split off the beginning */ + if (start > ml->src) { + addr_t l = start - ml->src; + + m = new_movelist(ml->dst + l, start, ml->len - l); + m->next = ml->next; + ml->len = l; + ml->next = m; + + parentptr = &ml->next; + ml = m; /* Continue processing the new node */ + } + + /* Split off the end */ + if (ml->len > len) { + addr_t l = ml->len - len; + + m = new_movelist(ml->dst + len, ml->src + len, l); + m->next = ml->next; + ml->len = len; + ml->next = m; + } + + return parentptr; +} + +static void delete_movelist(struct syslinux_movelist **parentptr) +{ + struct syslinux_movelist *o = *parentptr; + *parentptr = o->next; + free(o); +} + +static void free_movelist(struct syslinux_movelist **parentptr) +{ + while (*parentptr) + delete_movelist(parentptr); +} + +/* + * Scan the freelist looking for a particular chunk of memory + */ +static const struct syslinux_memmap *is_free_zone(const struct syslinux_memmap + *list, addr_t start, + addr_t len) +{ + dprintf("f: 0x%08x bytes at 0x%08x\n", len, start); + + addr_t last, llast; + + last = start + len - 1; + + while (list->type != SMT_END) { + llast = list->next->start - 1; + if (list->start <= start) { + if (llast >= last) { + /* Chunk has a single, well-defined type */ + if (list->type == SMT_FREE) { + dprintf("F: 0x%08x bytes at 0x%08x\n", + list->next->start, list->start); + return list; /* It's free */ + } + return NULL; /* Not free */ + } else if (llast >= start) { + return NULL; /* Crosses region boundary */ + } + } + list = list->next; + } + + return NULL; /* Internal error? */ +} + +/* + * Scan the freelist looking for the smallest chunk of memory which + * can fit X bytes; returns the length of the block on success. + */ +static addr_t free_area(const struct syslinux_memmap *mmap, + addr_t len, addr_t * start) +{ + const struct syslinux_memmap *best = NULL; + const struct syslinux_memmap *s; + addr_t slen, best_len = -1; + + for (s = mmap; s->type != SMT_END; s = s->next) { + if (s->type != SMT_FREE) + continue; + slen = s->next->start - s->start; + if (slen >= len) { + if (!best || best_len > slen) { + best = s; + best_len = slen; + } + } + } + + if (best) { + *start = best->start; + return best_len; + } else { + return 0; + } +} + +/* + * Remove a chunk from the freelist + */ +static void +allocate_from(struct syslinux_memmap **mmap, addr_t start, addr_t len) +{ + syslinux_add_memmap(mmap, start, len, SMT_ALLOC); +} + +/* + * Find chunks of a movelist which are one-to-many (one source, multiple + * destinations.) Those chunks can get turned into post-shuffle copies, + * to avoid confusing the shuffler. + */ +static void shuffle_dealias(struct syslinux_movelist **fraglist, + struct syslinux_movelist **postcopy) +{ + struct syslinux_movelist *mp, **mpp, *mx, *np; + addr_t ps, pe, xs, xe, delta; + bool advance; + +#if DEBUG + dprintf("Before alias resolution:\n"); + syslinux_dump_movelist(stdout, *fraglist); +#endif + + *postcopy = NULL; + + /* + * Note: as written, this is an O(n^2) algorithm; by producing a list + * sorted by destination address we could reduce it to O(n log n). + */ + mpp = fraglist; + while ((mp = *mpp)) { + dprintf("mp -> (%#x,%#x,%#x)\n", mp->dst, mp->src, mp->len); + ps = mp->src; + pe = mp->src + mp->len - 1; + for (mx = *fraglist; mx != mp; mx = mx->next) { + dprintf("mx -> (%#x,%#x,%#x)\n", mx->dst, mx->src, mx->len); + /* + * If there is any overlap between mx and mp, mp should be + * modified and possibly split. + */ + xs = mx->src; + xe = mx->src + mx->len - 1; + + dprintf("?: %#x..%#x (inside %#x..%#x)\n", ps, pe, xs, xe); + + if (pe <= xs || ps >= xe) + continue; /* No overlap */ + + advance = false; + *mpp = mp->next; /* Remove from list */ + + if (pe > xe) { + delta = pe - xe; + np = new_movelist(mp->dst + mp->len - delta, + mp->src + mp->len - delta, delta); + mp->len -= delta; + pe = xe; + np->next = *mpp; + *mpp = np; + advance = true; + } + if (ps < xs) { + delta = xs - ps; + np = new_movelist(mp->dst, ps, delta); + mp->src += delta; + ps = mp->src; + mp->dst += delta; + mp->len -= delta; + np->next = *mpp; + *mpp = np; + advance = true; + } + + assert(ps >= xs && pe <= xe); + + dprintf("Overlap: %#x..%#x (inside %#x..%#x)\n", ps, pe, xs, xe); + + mp->src = mx->dst + (ps - xs); + mp->next = *postcopy; + *postcopy = mp; + + mp = *mpp; + + if (!advance) + goto restart; + } + + mpp = &mp->next; +restart: + ; + } + +#if DEBUG + dprintf("After alias resolution:\n"); + syslinux_dump_movelist(stdout, *fraglist); + dprintf("Post-shuffle copies:\n"); + syslinux_dump_movelist(stdout, *postcopy); +#endif +} + +/* + * The code to actually emit moving of a chunk into its final place. + */ +static void +move_chunk(struct syslinux_movelist ***moves, + struct syslinux_memmap **mmap, + struct syslinux_movelist **fp, addr_t copylen) +{ + addr_t copydst, copysrc; + addr_t freebase, freelen; + addr_t needlen; + int reverse; + struct syslinux_movelist *f = *fp, *mv; + + if (f->src < f->dst && (f->dst - f->src) < f->len) { + /* "Shift up" type overlap */ + needlen = f->dst - f->src; + reverse = 1; + } else if (f->src > f->dst && (f->src - f->dst) < f->len) { + /* "Shift down" type overlap */ + needlen = f->src - f->dst; + reverse = 0; + } else { + needlen = f->len; + reverse = 0; + } + + copydst = f->dst; + copysrc = f->src; + + dprintf("Q: copylen = 0x%08x, needlen = 0x%08x\n", copylen, needlen); + + if (copylen < needlen) { + if (reverse) { + copydst += (f->len - copylen); + copysrc += (f->len - copylen); + } + + dprintf("X: 0x%08x bytes at 0x%08x -> 0x%08x\n", + copylen, copysrc, copydst); + + /* Didn't get all we wanted, so we have to split the chunk */ + fp = split_movelist(copysrc, copylen, fp); /* Is this right? */ + f = *fp; + } + + mv = new_movelist(f->dst, f->src, f->len); + dprintf("A: 0x%08x bytes at 0x%08x -> 0x%08x\n", mv->len, mv->src, mv->dst); + **moves = mv; + *moves = &mv->next; + + /* Figure out what memory we just freed up */ + if (f->dst > f->src) { + freebase = f->src; + freelen = min(f->len, f->dst - f->src); + } else if (f->src >= f->dst + f->len) { + freebase = f->src; + freelen = f->len; + } else { + freelen = f->src - f->dst; + freebase = f->dst + f->len; + } + + dprintf("F: 0x%08x bytes at 0x%08x\n", freelen, freebase); + + add_freelist(mmap, freebase, freelen, SMT_FREE); + + delete_movelist(fp); +} + +/* + * moves is computed from "frags" and "freemem". "space" lists + * free memory areas at our disposal, and is (src, cnt) only. + */ +int +syslinux_compute_movelist(struct syslinux_movelist **moves, + struct syslinux_movelist *ifrags, + struct syslinux_memmap *memmap) +{ + struct syslinux_memmap *mmap = NULL; + const struct syslinux_memmap *mm, *ep; + struct syslinux_movelist *frags = NULL; + struct syslinux_movelist *postcopy = NULL; + struct syslinux_movelist *mv; + struct syslinux_movelist *f, **fp; + struct syslinux_movelist *o, **op; + addr_t needbase, needlen, copysrc, copydst, copylen; + addr_t avail; + addr_t fstart, flen; + addr_t cbyte; + addr_t ep_len; + int rv = -1; + int reverse; + + dprintf("entering syslinux_compute_movelist()...\n"); + + if (setjmp(new_movelist_bail)) { +nomem: + dprintf("Out of working memory!\n"); + goto bail; + } + + *moves = NULL; + + /* Create our memory map. Anything that is SMT_FREE or SMT_ZERO is + fair game, but mark anything used by source material as SMT_ALLOC. */ + mmap = syslinux_init_memmap(); + if (!mmap) + goto nomem; + + frags = dup_movelist(ifrags); + + /* Process one-to-many conditions */ + shuffle_dealias(&frags, &postcopy); + + for (mm = memmap; mm->type != SMT_END; mm = mm->next) + add_freelist(&mmap, mm->start, mm->next->start - mm->start, + mm->type == SMT_ZERO ? SMT_FREE : mm->type); + + for (f = frags; f; f = f->next) + add_freelist(&mmap, f->src, f->len, SMT_ALLOC); + + /* As long as there are unprocessed fragments in the chain... */ + while ((fp = &frags, f = *fp)) { + +#if DEBUG + dprintf("Current free list:\n"); + syslinux_dump_memmap(stdout, mmap); + dprintf("Current frag list:\n"); + syslinux_dump_movelist(stdout, frags); +#endif + + /* Scan for fragments which can be discarded without action. */ + if (f->src == f->dst) { + delete_movelist(fp); + continue; + } + op = &f->next; + while ((o = *op)) { + if (o->src == o->dst) + delete_movelist(op); + else + op = &o->next; + } + + /* Scan for fragments which can be immediately moved + to their final destination, if so handle them now */ + for (op = fp; (o = *op); op = &o->next) { + if (o->src < o->dst && (o->dst - o->src) < o->len) { + /* "Shift up" type overlap */ + needlen = o->dst - o->src; + needbase = o->dst + (o->len - needlen); + reverse = 1; + cbyte = o->dst + o->len - 1; + } else if (o->src > o->dst && (o->src - o->dst) < o->len) { + /* "Shift down" type overlap */ + needlen = o->src - o->dst; + needbase = o->dst; + reverse = 0; + cbyte = o->dst; /* "Critical byte" */ + } else { + needlen = o->len; + needbase = o->dst; + reverse = 0; + cbyte = o->dst; /* "Critical byte" */ + } + + if (is_free_zone(mmap, needbase, needlen)) { + fp = op, f = o; + dprintf("!: 0x%08x bytes at 0x%08x -> 0x%08x\n", + f->len, f->src, f->dst); + copysrc = f->src; + copylen = needlen; + allocate_from(&mmap, needbase, copylen); + goto move_chunk; + } + } + + /* Ok, bother. Need to do real work at least with one chunk. */ + + dprintf("@: 0x%08x bytes at 0x%08x -> 0x%08x\n", + f->len, f->src, f->dst); + + /* See if we can move this chunk into place by claiming + the destination, or in the case of partial overlap, the + missing portion. */ + + if (f->src < f->dst && (f->dst - f->src) < f->len) { + /* "Shift up" type overlap */ + needlen = f->dst - f->src; + needbase = f->dst + (f->len - needlen); + reverse = 1; + cbyte = f->dst + f->len - 1; + } else if (f->src > f->dst && (f->src - f->dst) < f->len) { + /* "Shift down" type overlap */ + needlen = f->src - f->dst; + needbase = f->dst; + reverse = 0; + cbyte = f->dst; /* "Critical byte" */ + } else { + needlen = f->len; + needbase = f->dst; + reverse = 0; + cbyte = f->dst; + } + + dprintf("need: base = 0x%08x, len = 0x%08x, " + "reverse = %d, cbyte = 0x%08x\n", + needbase, needlen, reverse, cbyte); + + ep = is_free_zone(mmap, cbyte, 1); + if (ep) { + ep_len = ep->next->start - ep->start; + if (reverse) + avail = needbase + needlen - ep->start; + else + avail = ep_len - (needbase - ep->start); + } else { + avail = 0; + } + + if (avail) { + /* We can move at least part of this chunk into place without + further ado */ + dprintf("space: start 0x%08x, len 0x%08x, free 0x%08x\n", + ep->start, ep_len, avail); + copylen = min(needlen, avail); + + if (reverse) + allocate_from(&mmap, needbase + needlen - copylen, copylen); + else + allocate_from(&mmap, needbase, copylen); + + goto move_chunk; + } + + /* At this point, we need to evict something out of our space. + Find the object occupying the critical byte of our target space, + and move it out (the whole object if we can, otherwise a subset.) + Then move a chunk of ourselves into place. */ + for (op = &f->next, o = *op; o; op = &o->next, o = *op) { + + dprintf("O: 0x%08x bytes at 0x%08x -> 0x%08x\n", + o->len, o->src, o->dst); + + if (!(o->src <= cbyte && o->src + o->len > cbyte)) + continue; /* Not what we're looking for... */ + + /* Find somewhere to put it... */ + + if (is_free_zone(mmap, o->dst, o->len)) { + /* Score! We can move it into place directly... */ + copydst = o->dst; + copysrc = o->src; + copylen = o->len; + } else if (free_area(mmap, o->len, &fstart)) { + /* We can move the whole chunk */ + copydst = fstart; + copysrc = o->src; + copylen = o->len; + } else { + /* Well, copy as much as we can... */ + if (syslinux_memmap_largest(mmap, SMT_FREE, &fstart, &flen)) { + dprintf("No free memory at all!\n"); + goto bail; /* Stuck! */ + } + + /* Make sure we include the critical byte */ + copydst = fstart; + if (reverse) { + copysrc = max(o->src, cbyte + 1 - flen); + copylen = cbyte + 1 - copysrc; + } else { + copysrc = cbyte; + copylen = min(flen, o->len - (cbyte - o->src)); + } + } + allocate_from(&mmap, copydst, copylen); + + if (copylen < o->len) { + op = split_movelist(copysrc, copylen, op); + o = *op; + } + + mv = new_movelist(copydst, copysrc, copylen); + dprintf("C: 0x%08x bytes at 0x%08x -> 0x%08x\n", + mv->len, mv->src, mv->dst); + *moves = mv; + moves = &mv->next; + + o->src = copydst; + + if (copylen > needlen) { + /* We don't need all the memory we freed up. Mark it free. */ + if (copysrc < needbase) { + add_freelist(&mmap, copysrc, needbase - copysrc, SMT_FREE); + copylen -= (needbase - copysrc); + } + if (copylen > needlen) { + add_freelist(&mmap, copysrc + needlen, copylen - needlen, + SMT_FREE); + copylen = needlen; + } + } + reverse = 0; + goto move_chunk; + } + dprintf("Cannot find the chunk containing the critical byte\n"); + goto bail; /* Stuck! */ + +move_chunk: + move_chunk(&moves, &mmap, fp, copylen); + } + + /* Finally, append the postcopy chain to the end of the moves list */ + for (op = moves; (o = *op); op = &o->next) ; /* Locate the end of the list */ + *op = postcopy; + postcopy = NULL; + + rv = 0; +bail: + if (mmap) + syslinux_free_memmap(mmap); + if (frags) + free_movelist(&frags); + if (postcopy) + free_movelist(&postcopy); + return rv; +} + +#ifdef TEST + +#include <stdio.h> + +int main(int argc, char *argv[]) +{ + FILE *f; + unsigned long d, s, l; + struct syslinux_movelist *frags; + struct syslinux_movelist **fep = &frags; + struct syslinux_movelist *mv, *moves; + struct syslinux_memmap *memmap; + char line[BUFSIZ]; + + (void)argc; + + memmap = syslinux_init_memmap(); + + f = fopen(argv[1], "r"); + while (fgets(line, sizeof line, f) != NULL) { + if (sscanf(line, "%lx %lx %lx", &s, &d, &l) == 3) { + if (d) { + if (s == -1UL) { + syslinux_add_memmap(&memmap, d, l, SMT_ZERO); + } else { + mv = new_movelist(d, s, l); + *fep = mv; + fep = &mv->next; + } + } else { + syslinux_add_memmap(&memmap, s, l, SMT_FREE); + } + } + } + fclose(f); + + *fep = NULL; + + printf("Input move list:\n"); + syslinux_dump_movelist(stdout, frags); + printf("Input free list:\n"); + syslinux_dump_memmap(stdout, memmap); + + if (syslinux_compute_movelist(&moves, frags, memmap)) { + printf("Failed to compute a move sequence\n"); + return 1; + } else { + printf("Final move list:\n"); + syslinux_dump_movelist(stdout, moves); + return 0; + } +} + +#endif /* TEST */ diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/pxe_dns.c b/contrib/syslinux-4.02/com32/lib/syslinux/pxe_dns.c new file mode 100644 index 0000000..6620396 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/pxe_dns.c @@ -0,0 +1,75 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2010 Intel Corporation; author: H. Peter Anvin + * + * 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_dns.c + * + * Resolve a hostname via DNS + */ + +#include <stdio.h> +#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 */ +uint32_t pxe_dns(const char *hostname) +{ + com32sys_t regs; + union { + unsigned char b[4]; + uint32_t ip; + } q; + char *lm_hostname; + + /* Is this a dot-quad? */ + if (sscanf(hostname, "%hhu.%hhu.%hhu.%hhu", + &q.b[0], &q.b[1], &q.b[2], &q.b[3]) == 4) + return q.ip; + + lm_hostname = lstrdup(hostname); + if (!lm_hostname) + return 0; + + memset(®s, 0, sizeof regs); + regs.eax.w[0] = 0x0010; + regs.es = SEG(lm_hostname); + /* regs.ebx.w[0] = OFFS(lm_hostname); */ + + __intcall(0x22, ®s, ®s); + + lfree(lm_hostname); + + if (regs.eflags.l & EFLAGS_CF) + return 0; + + return regs.eax.l; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/pxe_get_cached.c b/contrib/syslinux-4.02/com32/lib/syslinux/pxe_get_cached.c new file mode 100644 index 0000000..4704037 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/pxe_get_cached.c @@ -0,0 +1,96 @@ +/* ----------------------------------------------------------------------- * + * + * 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_cached_info(int level, void **buf, size_t * len) +{ + const int max_dhcp_packet = 2048; + com32sys_t regs; + t_PXENV_GET_CACHED_INFO *gci; + void *bbuf, *nbuf; + int err; + + gci = lmalloc(sizeof *gci + max_dhcp_packet); + if (!gci) + return -1; + + memset(®s, 0, sizeof regs); + regs.eax.w[0] = 0x0009; + regs.ebx.w[0] = PXENV_GET_CACHED_INFO; + regs.es = SEG(gci); + /* regs.edi.w[0] = OFFS(gci); */ + + bbuf = &gci[1]; + + gci->Status = PXENV_STATUS_FAILURE; + gci->PacketType = level; + gci->BufferSize = gci->BufferLimit = max_dhcp_packet; + gci->Buffer.seg = SEG(bbuf); + gci->Buffer.offs = OFFS(bbuf); + + __intcall(0x22, ®s, ®s); + + if (regs.eflags.l & EFLAGS_CF) { + err = -1; + goto exit; + } + + if (gci->Status) { + err = gci->Status; + goto exit; + } + + nbuf = malloc(gci->BufferSize); + if (!nbuf) { + err = -1; + goto exit; + } + + memcpy(nbuf, bbuf, gci->BufferSize); + + *buf = nbuf; + *len = gci->BufferSize; + err = 0; + +exit: + lfree(gci); + return err; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/pxe_get_nic.c b/contrib/syslinux-4.02/com32/lib/syslinux/pxe_get_nic.c new file mode 100644 index 0000000..b301a75 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/pxe_get_nic.c @@ -0,0 +1,67 @@ +/* ----------------------------------------------------------------------- * + * + * 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; + t_PXENV_UNDI_GET_NIC_TYPE *lgnt; + + lgnt = lzalloc(sizeof *lgnt); + if (!lgnt) + return -1; + + memset(®s, 0, sizeof regs); + regs.eax.w[0] = 0x0009; + regs.ebx.w[0] = PXENV_UNDI_GET_NIC_TYPE; + regs.es = SEG(lgnt); + /* regs.edi.w[0] = OFFS(lgnt); */ + + __intcall(0x22, ®s, ®s); + + memcpy(gnt, lgnt, sizeof(t_PXENV_UNDI_GET_NIC_TYPE)); + lfree(lgnt); + + if (regs.eflags.l & EFLAGS_CF) + return -1; + + return gnt->Status; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/reboot.c b/contrib/syslinux-4.02/com32/lib/syslinux/reboot.c new file mode 100644 index 0000000..2e3eb2b --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/reboot.c @@ -0,0 +1,47 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * reboot.c + * + * Provoke a system reboot + */ + +#include <stddef.h> +#include <com32.h> +#include <syslinux/reboot.h> + +__noreturn syslinux_reboot(int warm) +{ + uint16_t *const reboot_flag = (uint16_t *) 0x472; + + *reboot_flag = warm ? 0x1234 : 0; + __farcall(0xf000, 0xfff0, &__com32_zero_regs, NULL); + + while (1) + asm volatile ("hlt"); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/run_command.c b/contrib/syslinux-4.02/com32/lib/syslinux/run_command.c new file mode 100644 index 0000000..a0ac9a0 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/run_command.c @@ -0,0 +1,50 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +#include <syslinux/boot.h> +#include <stddef.h> +#include <string.h> +#include <com32.h> + +int syslinux_run_command(const char *command) +{ + static com32sys_t ireg; + char *lm_command = lstrdup(command); + + if (!lm_command) + return -1; + + ireg.eax.w[0] = 0x0003; + ireg.es = SEG(lm_command); + /* ireg.ebx.w[0] = OFFS(lm_command); */ + + __intcall(0x22, &ireg, NULL); + + /* Should not return even on failure, but in case... */ + lfree(lm_command); + return -1; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/run_default.c b/contrib/syslinux-4.02/com32/lib/syslinux/run_default.c new file mode 100644 index 0000000..8dc9fbe --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/run_default.c @@ -0,0 +1,41 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +#include <syslinux/boot.h> +#include <stddef.h> +#include <com32.h> + +__noreturn syslinux_run_default(void) +{ + static com32sys_t ireg; + + ireg.eax.w[0] = 0x0004; + __intcall(0x22, &ireg, NULL); + + /* Should not return even on failure */ + for (;;) ; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/runimage.c b/contrib/syslinux-4.02/com32/lib/syslinux/runimage.c new file mode 100644 index 0000000..d5cdbc6 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/runimage.c @@ -0,0 +1,70 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * runimage.c + * + * Load and run a syslinux image. + */ + +#include <stdlib.h> +#include <string.h> +#include <syslinux/boot.h> +#include <com32.h> + +void syslinux_run_kernel_image(const char *filename, const char *cmdline, + uint32_t ipappend_flags, uint32_t type) +{ + static com32sys_t ireg; + char *bbfilename = NULL; + char *bbcmdline = NULL; + + bbfilename = lstrdup(filename); + if (!bbfilename) + goto fail; + + bbcmdline = lstrdup(cmdline); + if (!bbcmdline) + goto fail; + + + ireg.eax.w[0] = 0x0016; + ireg.ds = SEG(bbfilename); + /* ireg.esi.w[0] = OFFS(bbfilename); */ + ireg.es = SEG(bbcmdline); + /* ireg.ebx.w[0] = OFFS(bbcmdline); */ + ireg.ecx.l = ipappend_flags; + ireg.edx.l = type; + + __intcall(0x22, &ireg, 0); + +fail: + if (bbcmdline) + lfree(bbcmdline); + if (bbfilename) + lfree(bbfilename); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/serial.c b/contrib/syslinux-4.02/com32/lib/syslinux/serial.c new file mode 100644 index 0000000..f06e8c8 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/serial.c @@ -0,0 +1,52 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/serial.c + * + * SYSLINUX serial console query + */ + +#include <klibc/compiler.h> +#include <syslinux/config.h> +#include <string.h> +#include <com32.h> + +struct syslinux_serial_console_info __syslinux_serial_console_info; + +void __constructor __syslinux_get_serial_console_info(void) +{ + static com32sys_t reg; + + memset(®, 0, sizeof reg); + reg.eax.w[0] = 0x000b; + __intcall(0x22, ®, ®); + + __syslinux_serial_console_info.iobase = reg.edx.w[0]; + __syslinux_serial_console_info.divisor = reg.ecx.w[0]; + __syslinux_serial_console_info.flowctl = reg.ebx.w[0]; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/setadv.c b/contrib/syslinux-4.02/com32/lib/syslinux/setadv.c new file mode 100644 index 0000000..40f00a4 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/setadv.c @@ -0,0 +1,116 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/setadv.c + * + * (Over)write a data item in the auxilliary data vector. To + * delete an item, set its length to zero. + * + * Return 0 on success, -1 on error, and set errno. + * + * NOTE: Data is not written to disk unless + * syslinux_adv_write() is called. + */ + +#include <syslinux/adv.h> +#include <klibc/compiler.h> +#include <inttypes.h> +#include <string.h> +#include <errno.h> +#include <alloca.h> + +int syslinux_setadv(int tag, size_t size, const void *data) +{ + uint8_t *p, *advtmp; + size_t rleft, left; + + if ((unsigned)tag - 1 > 254) { + errno = EINVAL; + return -1; /* Impossible tag value */ + } + + if (size > 255) { + errno = ENOSPC; /* Max 255 bytes for a data item */ + return -1; + } + + rleft = left = syslinux_adv_size(); + p = advtmp = alloca(left); + memcpy(p, syslinux_adv_ptr(), left); /* Make working copy */ + + while (rleft >= 2) { + uint8_t ptag = p[0]; + size_t plen = p[1] + 2; + + if (ptag == ADV_END) + break; + + if (ptag == tag) { + /* Found our tag. Delete it. */ + + if (plen >= rleft) { + /* Entire remainder is our tag */ + break; + } + memmove(p, p + plen, rleft - plen); + rleft -= plen; /* Fewer bytes to read, but not to write */ + } else { + /* Not our tag */ + if (plen > rleft) + break; /* Corrupt tag (overrun) - overwrite it */ + + left -= plen; + rleft -= plen; + p += plen; + } + } + + /* Now (p, left) reflects the position to write in and how much space + we have for our data. */ + + if (size) { + if (left < size + 2) { + errno = ENOSPC; /* Not enough space for data */ + return -1; + } + + *p++ = tag; + *p++ = size; + memcpy(p, data, size); + p += size; + left -= size + 2; + } + + memset(p, 0, left); + + /* If we got here, everything went OK, commit the write to low memory */ + memcpy(syslinux_adv_ptr(), advtmp, syslinux_adv_size()); + + return 0; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/shuffle.c b/contrib/syslinux-4.02/com32/lib/syslinux/shuffle.c new file mode 100644 index 0000000..6b5a601 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/shuffle.c @@ -0,0 +1,275 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * shuffle.c + * + * Common code for "shuffle and boot" operation; generates a shuffle list + * and puts it in the bounce buffer. Returns the number of shuffle + * descriptors. + */ + +#include <stdlib.h> +#include <string.h> +#include <inttypes.h> +#include <com32.h> +#include <minmax.h> +#include <syslinux/movebits.h> +#include <klibc/compiler.h> + +#ifndef DEBUG +# define DEBUG 0 +#endif + +#define dprintf(f, ...) ((void)0) +#define dprintf2(f, ...) ((void)0) + +#if DEBUG +# include <stdio.h> +# undef dprintf +# define dprintf printf +# if DEBUG > 1 +# undef dprintf2 +# define dprintf2 printf +# endif +#endif + +struct shuffle_descriptor { + uint32_t dst, src, len; +}; + +static int shuffler_size; + +static void __constructor __syslinux_get_shuffer_size(void) +{ + static com32sys_t reg; + + reg.eax.w[0] = 0x0023; + __intcall(0x22, ®, ®); + + shuffler_size = (reg.eflags.l & EFLAGS_CF) ? 2048 : reg.ecx.w[0]; +} + +/* + * Allocate descriptor memory in these chunks; if this is large we may + * waste memory, if it is small we may get slow convergence. + */ +#define DESC_BLOCK_SIZE 256 + +int syslinux_do_shuffle(struct syslinux_movelist *fraglist, + struct syslinux_memmap *memmap, + addr_t entry_point, addr_t entry_type, + uint16_t bootflags) +{ + int rv = -1; + struct syslinux_movelist *moves = NULL, *mp; + struct syslinux_memmap *rxmap = NULL, *ml; + struct shuffle_descriptor *dp, *dbuf; + int np; + int desc_blocks, need_blocks; + int need_ptrs; + addr_t desczone, descfree, descaddr, descoffs; + int nmoves, nzero; + com32sys_t ireg; + + descaddr = 0; + dp = dbuf = NULL; + + /* Count the number of zero operations */ + nzero = 0; + for (ml = memmap; ml->type != SMT_END; ml = ml->next) { + if (ml->type == SMT_ZERO) + nzero++; + } + + /* Find the largest contiguous region unused by input *and* output; + this is where we put the move descriptor list and safe area */ + + rxmap = syslinux_dup_memmap(memmap); + if (!rxmap) + goto bail; + /* Avoid using the low 1 MB for the shuffle area -- this avoids + possible interference with the real mode code or stack */ + if (syslinux_add_memmap(&rxmap, 0, 1024 * 1024, SMT_RESERVED)) + goto bail; + for (mp = fraglist; mp; mp = mp->next) { + if (syslinux_add_memmap(&rxmap, mp->src, mp->len, SMT_ALLOC) || + syslinux_add_memmap(&rxmap, mp->dst, mp->len, SMT_ALLOC)) + goto bail; + } + if (syslinux_memmap_largest(rxmap, SMT_FREE, &desczone, &descfree)) + goto bail; + + syslinux_free_memmap(rxmap); + + dprintf("desczone = 0x%08x, descfree = 0x%08x\n", desczone, descfree); + + rxmap = syslinux_dup_memmap(memmap); + if (!rxmap) + goto bail; + + desc_blocks = (nzero + DESC_BLOCK_SIZE - 1) / DESC_BLOCK_SIZE; + for (;;) { + /* We want (desc_blocks) allocation blocks, plus the terminating + descriptor, plus the shuffler safe area. */ + addr_t descmem = desc_blocks * + sizeof(struct shuffle_descriptor) * DESC_BLOCK_SIZE + + sizeof(struct shuffle_descriptor) + shuffler_size; + + descaddr = (desczone + descfree - descmem) & ~3; + + if (descaddr < desczone) + goto bail; /* No memory block large enough */ + + /* Mark memory used by shuffle descriptors as reserved */ + if (syslinux_add_memmap(&rxmap, descaddr, descmem, SMT_RESERVED)) + goto bail; + +#if DEBUG > 1 + syslinux_dump_movelist(stdout, fraglist); +#endif + + if (syslinux_compute_movelist(&moves, fraglist, rxmap)) + goto bail; + + nmoves = 0; + for (mp = moves; mp; mp = mp->next) + nmoves++; + + need_blocks = (nmoves + nzero + DESC_BLOCK_SIZE - 1) / DESC_BLOCK_SIZE; + + if (desc_blocks >= need_blocks) + break; /* Sufficient memory, yay */ + + desc_blocks = need_blocks; /* Try again... */ + } + +#if DEBUG > 1 + dprintf("Final movelist:\n"); + syslinux_dump_movelist(stdout, moves); +#endif + + syslinux_free_memmap(rxmap); + rxmap = NULL; + + need_ptrs = nmoves + nzero + 1; + dbuf = malloc(need_ptrs * sizeof(struct shuffle_descriptor)); + if (!dbuf) + goto bail; + + descoffs = descaddr - (addr_t) dbuf; + +#if DEBUG + dprintf("nmoves = %d, nzero = %d, dbuf = %p, offs = 0x%08x\n", + nmoves, nzero, dbuf, descoffs); +#endif + + /* Copy the move sequence into the descriptor buffer */ + np = 0; + dp = dbuf; + for (mp = moves; mp; mp = mp->next) { + dp->dst = mp->dst; + dp->src = mp->src; + dp->len = mp->len; + dprintf2("[ %08x %08x %08x ]\n", dp->dst, dp->src, dp->len); + dp++; + np++; + } + + /* Copy bzero operations into the descriptor buffer */ + for (ml = memmap; ml->type != SMT_END; ml = ml->next) { + if (ml->type == SMT_ZERO) { + dp->dst = ml->start; + dp->src = (addr_t) - 1; /* bzero region */ + dp->len = ml->next->start - ml->start; + dprintf2("[ %08x %08x %08x ]\n", dp->dst, dp->src, dp->len); + dp++; + np++; + } + } + + /* Finally, record the termination entry */ + dp->dst = entry_point; + dp->src = entry_type; + dp->len = 0; + dp++; + np++; + + if (np != need_ptrs) { + dprintf("!!! np = %d : nmoves = %d, nzero = %d, desc_blocks = %d\n", + np, nmoves, nzero, desc_blocks); + } + + rv = 0; + +bail: + /* This is safe only because free() doesn't use the bounce buffer!!!! */ + if (moves) + syslinux_free_movelist(moves); + if (rxmap) + syslinux_free_memmap(rxmap); + + if (rv) + return rv; + + /* Actually do it... */ + memset(&ireg, 0, sizeof ireg); + ireg.edi.l = descaddr; + ireg.esi.l = (addr_t) dbuf; + ireg.ecx.l = (addr_t) dp - (addr_t) dbuf; + ireg.edx.w[0] = bootflags; + ireg.eax.w[0] = 0x0024; + __intcall(0x22, &ireg, NULL); + + return -1; /* Shouldn't have returned! */ +} + +/* + * Common helper routine: takes a memory map and blots out the + * zones which are used in the destination of a fraglist + */ +struct syslinux_memmap *syslinux_target_memmap(struct syslinux_movelist + *fraglist, + struct syslinux_memmap *memmap) +{ + struct syslinux_memmap *tmap; + struct syslinux_movelist *mp; + + tmap = syslinux_dup_memmap(memmap); + if (!tmap) + return NULL; + + for (mp = fraglist; mp; mp = mp->next) { + if (syslinux_add_memmap(&tmap, mp->dst, mp->len, SMT_ALLOC)) { + syslinux_free_memmap(tmap); + return NULL; + } + } + + return tmap; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/shuffle_pm.c b/contrib/syslinux-4.02/com32/lib/syslinux/shuffle_pm.c new file mode 100644 index 0000000..5e3183b --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/shuffle_pm.c @@ -0,0 +1,77 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * shuffle_pm.c + * + * Shuffle and boot to protected mode code + */ + +#include <inttypes.h> +#include <syslinux/movebits.h> +#include <syslinux/bootpm.h> + +int syslinux_shuffle_boot_pm(struct syslinux_movelist *fraglist, + struct syslinux_memmap *memmap, + uint16_t bootflags, struct syslinux_pm_regs *regs) +{ + uint8_t handoff_code[9 * 5], *p; + const uint32_t *rp; + int i, rv; + struct syslinux_memmap *tmap; + addr_t regstub, stublen; + + tmap = syslinux_target_memmap(fraglist, memmap); + if (!tmap) + return -1; + + regstub = 0x800; /* Locate anywhere above this point */ + stublen = sizeof handoff_code; + rv = syslinux_memmap_find(tmap, SMT_FREE, ®stub, &stublen, 1); + syslinux_free_memmap(tmap); + if (rv) + return -1; + + /* Build register-setting stub */ + p = handoff_code; + rp = (const uint32_t *)regs; + for (i = 0; i < 8; i++) { + *p = 0xb8 + i; /* MOV gpr,imm32 */ + *(uint32_t *) (p + 1) = *rp++; + p += 5; + } + *p = 0xe9; /* JMP */ + *(uint32_t *) (p + 1) = regs->eip - regstub - sizeof handoff_code; + + /* Add register-setting stub to shuffle list */ + if (syslinux_add_movelist(&fraglist, regstub, (addr_t) handoff_code, + sizeof handoff_code)) + return -1; + + return syslinux_do_shuffle(fraglist, memmap, regstub, 1, bootflags); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/shuffle_rm.c b/contrib/syslinux-4.02/com32/lib/syslinux/shuffle_rm.c new file mode 100644 index 0000000..a7d16d6 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/shuffle_rm.c @@ -0,0 +1,171 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * shuffle_rm.c + * + * Shuffle and boot to protected mode code + */ + +#include <stdlib.h> +#include <inttypes.h> +#include <com32.h> +#include <string.h> +#include <syslinux/movebits.h> +#include <syslinux/bootrm.h> + +enum gpr_index { R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI }; +enum seg_index { R_ES, R_CS, R_SS, R_DS, R_FS, R_GS }; + +#define ST8(P,V) \ + do { \ + uint8_t *_p = (void *)(P); \ + *_p++ = (V); \ + (P) = (void *)_p; \ + } while (0); +#define ST16(P,V) \ + do { \ + uint16_t *_p = (void *)(P); \ + *_p++ = (V); \ + (P) = (void *)_p; \ + } while (0) +#define ST32(P,V) \ + do { \ + uint32_t *_p = (void *)(P); \ + *_p++ = (V); \ + (P) = (void *)_p; \ + } while (0) + +#define MOV_TO_SEG(P,S,R) \ + ST16(P, 0xc08e + ((R) << 8) + ((S) << 11)) +#define MOV_TO_R16(P,R,V) \ + do { \ + ST8(P, 0xb8 + (R)); \ + ST16(P, V); \ + } while (0) +#define MOV_TO_R32(P,R,V) \ + do { \ + ST16(P, 0xb866 + ((R) << 8)); \ + ST32(P, V); \ + } while (0) + +int syslinux_shuffle_boot_rm(struct syslinux_movelist *fraglist, + struct syslinux_memmap *memmap, + uint16_t bootflags, struct syslinux_rm_regs *regs) +{ + const struct syslinux_rm_regs_alt { + uint16_t seg[6]; + uint32_t gpr[8]; + uint32_t csip; + bool sti; + } *rp; + int i, rv; + uint8_t handoff_code[8 + 5 * 5 + 8 * 6 + 1 + 5], *p; + uint16_t off; + struct syslinux_memmap *tmap; + addr_t regstub, stublen; + /* Assign GPRs for each sreg, don't use AX and SP */ + static const uint8_t gpr_for_seg[6] = + { R_CX, R_DX, R_BX, R_BP, R_SI, R_DI }; + + tmap = syslinux_target_memmap(fraglist, memmap); + if (!tmap) + return -1; + + /* + * Search for a good place to put the real-mode register stub. + * We prefer it as low as possible above 0x800. KVM barfs horribly + * if we're not aligned to a paragraph boundary, so set the alignment + * appropriately. + */ + regstub = 0x800; + stublen = sizeof handoff_code; + rv = syslinux_memmap_find(tmap, SMT_FREE, ®stub, &stublen, 16); + + if (rv || (regstub > 0x100000 - sizeof handoff_code)) { + /* + * Uh-oh. This isn't real-mode accessible memory. + * It might be possible to do something insane here like + * putting the stub in the IRQ vectors, or in the 0x5xx segment. + * This code tries the 0x510-0x7ff range and hopes for the best. + */ + regstub = 0x510; /* Try the 0x5xx segment... */ + stublen = sizeof handoff_code; + rv = syslinux_memmap_find(tmap, SMT_FREE, ®stub, &stublen, 16); + + if (!rv && (regstub > 0x100000 - sizeof handoff_code)) + rv = -1; /* No acceptable memory found */ + } + + syslinux_free_memmap(tmap); + if (rv) + return -1; + + /* Build register-setting stub */ + p = handoff_code; + rp = (const struct syslinux_rm_regs_alt *)regs; + + /* Set up GPRs with segment registers - don't use AX */ + for (i = 0; i < 6; i++) { + if (i != R_CS) + MOV_TO_R16(p, gpr_for_seg[i], rp->seg[i]); + } + + /* Actual transition to real mode */ + ST32(p, 0xeac0220f); /* MOV CR0,EAX; JMP FAR */ + off = (p - handoff_code) + 4; + ST16(p, off); /* Offset */ + ST16(p, regstub >> 4); /* Segment */ + + /* Load SS and ESP immediately */ + MOV_TO_SEG(p, R_SS, R_BX); + MOV_TO_R32(p, R_SP, rp->gpr[R_SP]); + + /* Load the other segments */ + MOV_TO_SEG(p, R_ES, R_CX); + MOV_TO_SEG(p, R_DS, R_BP); + MOV_TO_SEG(p, R_FS, R_SI); + MOV_TO_SEG(p, R_GS, R_DI); + + for (i = 0; i < 8; i++) { + if (i != R_SP) + MOV_TO_R32(p, i, rp->gpr[i]); + } + + ST8(p, rp->sti ? 0xfb : 0xfa); /* STI/CLI */ + + ST8(p, 0xea); /* JMP FAR */ + ST32(p, rp->csip); + + /* Add register-setting stub to shuffle list */ + if (syslinux_add_movelist(&fraglist, regstub, (addr_t) handoff_code, + sizeof handoff_code)) + return -1; + + return syslinux_do_shuffle(fraglist, memmap, regstub, 0, bootflags); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/version.c b/contrib/syslinux-4.02/com32/lib/syslinux/version.c new file mode 100644 index 0000000..15b617b --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/version.c @@ -0,0 +1,46 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 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. + * + * ----------------------------------------------------------------------- */ + +#include <syslinux/config.h> +#include <klibc/compiler.h> +#include <com32.h> + +struct syslinux_version __syslinux_version; + +void __constructor __syslinux_get_version(void) +{ + static com32sys_t reg; + + reg.eax.w[0] = 0x0001; + __intcall(0x22, ®, ®); + + __syslinux_version.version = reg.ecx.w[0]; + __syslinux_version.max_api = reg.eax.w[0]; + __syslinux_version.filesystem = reg.edx.b[0]; + __syslinux_version.version_string = MK_PTR(reg.es, reg.esi.w[0]); + __syslinux_version.copyright_string = MK_PTR(reg.es, reg.edi.w[0]); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/video/fontquery.c b/contrib/syslinux-4.02/com32/lib/syslinux/video/fontquery.c new file mode 100644 index 0000000..dd5d86e --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/video/fontquery.c @@ -0,0 +1,54 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/video/forcetext.c + */ + +#include <syslinux/video.h> +#include <com32.h> + +/* + * Returns height of font or zero if no custom font loaded + */ +int syslinux_font_query(uint8_t **font) +{ + static com32sys_t ireg; + com32sys_t oreg; + int height; + + ireg.eax.w[0] = 0x0018; + __intcall(0x22, &ireg, &oreg); + + height = !(oreg.eflags.l & EFLAGS_CF) ? oreg.eax.b[0] : 0; + if (height) + *font = MK_PTR(oreg.es, oreg.ebx.w[0]); + + return height; +} + diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/video/forcetext.c b/contrib/syslinux-4.02/com32/lib/syslinux/video/forcetext.c new file mode 100644 index 0000000..136cb27 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/video/forcetext.c @@ -0,0 +1,42 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/video/forcetext.c + */ + +#include <syslinux/video.h> +#include <com32.h> + +void syslinux_force_text_mode(void) +{ + static com32sys_t ireg; + + ireg.eax.w[0] = 0x0005; + __intcall(0x22, &ireg, NULL); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/video/reportmode.c b/contrib/syslinux-4.02/com32/lib/syslinux/video/reportmode.c new file mode 100644 index 0000000..57fd6fd --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/video/reportmode.c @@ -0,0 +1,45 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux/video/reportmode.c + */ + +#include <syslinux/video.h> +#include <com32.h> + +void syslinux_report_video_mode(uint16_t flags, uint16_t xsize, uint16_t ysize) +{ + static com32sys_t ireg; + + ireg.eax.w[0] = 0x0017; + ireg.ebx.w[0] = flags; + ireg.ecx.w[0] = xsize; + ireg.edx.w[0] = ysize; + __intcall(0x22, &ireg, NULL); +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/zloadfile.c b/contrib/syslinux-4.02/com32/lib/syslinux/zloadfile.c new file mode 100644 index 0000000..286d070 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/zloadfile.c @@ -0,0 +1,59 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2005-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. + * + * ----------------------------------------------------------------------- */ + +/* + * zloadfile.c + * + * Read the contents of a possibly compressed data file into a malloc'd buffer + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <syslinux/zio.h> + +#include <syslinux/loadfile.h> + +#define INCREMENTAL_CHUNK 1024*1024 + +int zloadfile(const char *filename, void **ptr, size_t * len) +{ + FILE *f; + int rv; + + f = zfopen(filename, "r"); + if (!f) + return -1; + + rv = floadfile(f, ptr, len, NULL, 0); + fclose(f); + + return rv; +} diff --git a/contrib/syslinux-4.02/com32/lib/syslinux/zonelist.c b/contrib/syslinux-4.02/com32/lib/syslinux/zonelist.c new file mode 100644 index 0000000..b548211 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/syslinux/zonelist.c @@ -0,0 +1,301 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * zonelist.c + * + * Deal with syslinux_memmap's, which are data structures designed to + * hold memory maps. A zonelist is a sorted linked list of memory + * ranges, with the guarantee that no two adjacent blocks have the + * same range type. Additionally, all unspecified memory have a range + * type of zero. + */ + +#include <stdlib.h> +#include <syslinux/align.h> +#include <syslinux/movebits.h> + +#ifndef DEBUG +# ifdef TEST +# define DEBUG 1 +# else +# define DEBUG 0 +# endif +#endif + +#if DEBUG +# include <stdio.h> +# define dprintf printf +#else +# define dprintf(...) ((void)0) +#endif + +/* + * Create an empty syslinux_memmap list. + */ +struct syslinux_memmap *syslinux_init_memmap(void) +{ + struct syslinux_memmap *sp, *ep; + + sp = malloc(sizeof(*sp)); + if (!sp) + return NULL; + + ep = malloc(sizeof(*ep)); + if (!ep) { + free(sp); + return NULL; + } + + sp->start = 0; + sp->type = SMT_UNDEFINED; + sp->next = ep; + + ep->start = 0; /* Wrap around... */ + ep->type = SMT_END; /* End of chain */ + ep->next = NULL; + + return sp; +} + +/* + * Add an item to a syslinux_memmap list, potentially overwriting + * what is already there. + */ +int syslinux_add_memmap(struct syslinux_memmap **list, + addr_t start, addr_t len, + enum syslinux_memmap_types type) +{ + addr_t last; + struct syslinux_memmap *mp, **mpp; + struct syslinux_memmap *range; + enum syslinux_memmap_types oldtype; + +#if DEBUG + dprintf("Input memmap:\n"); + syslinux_dump_memmap(stdout, *list); +#endif + + /* Remove this to make len == 0 mean all of memory */ + if (len == 0) + return 0; + + /* Last byte -- to avoid rollover */ + last = start + len - 1; + + mpp = list; + oldtype = SMT_END; /* Impossible value */ + while (mp = *mpp, start > mp->start && mp->type != SMT_END) { + oldtype = mp->type; + mpp = &mp->next; + } + + if (start < mp->start || mp->type == SMT_END) { + if (type != oldtype) { + /* Splice in a new start token */ + range = malloc(sizeof(*range)); + if (!range) + return -1; + + range->start = start; + range->type = type; + *mpp = range; + range->next = mp; + mpp = &range->next; + } + } else { + /* mp is exactly aligned with the start of our region */ + if (type != oldtype) { + /* Reclaim this entry as our own boundary marker */ + oldtype = mp->type; + mp->type = type; + mpp = &mp->next; + } + } + + while (mp = *mpp, last > mp->start - 1) { + oldtype = mp->type; + *mpp = mp->next; + free(mp); + } + + if (last < mp->start - 1) { + if (oldtype != type) { + /* Need a new end token */ + range = malloc(sizeof(*range)); + if (!range) + return -1; + + range->start = last + 1; + range->type = oldtype; + *mpp = range; + range->next = mp; + } + } else { + if (mp->type == type) { + /* Merge this region with the following one */ + *mpp = mp->next; + free(mp); + } + } + +#if DEBUG + dprintf("After adding (%#x,%#x,%d):\n", start, len, type); + syslinux_dump_memmap(stdout, *list); +#endif + + return 0; +} + +/* + * Verify what type a certain memory region is. This function returns + * SMT_ERROR if the memory region has multiple types. + */ +enum syslinux_memmap_types syslinux_memmap_type(struct syslinux_memmap *list, + addr_t start, addr_t len) +{ + addr_t last, llast; + + last = start + len - 1; + + while (list->type != SMT_END) { + llast = list->next->start - 1; + if (list->start <= start) { + if (llast >= last) + return list->type; /* Region has a well-defined type */ + else if (llast >= start) + return SMT_ERROR; /* Crosses region boundary */ + } + list = list->next; + } + + return SMT_ERROR; /* Internal error? */ +} + +/* + * Find the largest zone of a specific type. Returns -1 on failure. + */ +int syslinux_memmap_largest(struct syslinux_memmap *list, + enum syslinux_memmap_types type, + addr_t * start, addr_t * len) +{ + addr_t size, best_size = 0; + struct syslinux_memmap *best = NULL; + + while (list->type != SMT_END) { + size = list->next->start - list->start; + + if (list->type == type && size > best_size) { + best = list; + best_size = size; + } + + list = list->next; + } + + if (!best) + return -1; + + *start = best->start; + *len = best_size; + + return 0; +} + +/* + * Find the first (lowest address) zone of a specific type and of + * a certain minimum size, with an optional starting address. + * The input values of start and len are used as minima. + */ +int syslinux_memmap_find(struct syslinux_memmap *list, + enum syslinux_memmap_types type, + addr_t * start, addr_t * len, addr_t align) +{ + addr_t min_start = *start; + addr_t min_len = *len; + + while (list->type != SMT_END) { + if (list->type == type) { + addr_t xstart, xlen; + xstart = min_start > list->start ? min_start : list->start; + xstart = ALIGN_UP(xstart, align); + + if (xstart < list->next->start) { + xlen = list->next->start - xstart; + if (xlen >= min_len) { + *start = xstart; + *len = xlen; + return 0; + } + } + } + list = list->next; + } + + return -1; /* Not found */ +} + +/* + * Free a zonelist. + */ +void syslinux_free_memmap(struct syslinux_memmap *list) +{ + struct syslinux_memmap *ml; + + while (list) { + ml = list; + list = list->next; + free(ml); + } +} + +/* + * Duplicate a zonelist. Returns NULL on failure. + */ +struct syslinux_memmap *syslinux_dup_memmap(struct syslinux_memmap *list) +{ + struct syslinux_memmap *newlist = NULL, **nlp = &newlist; + struct syslinux_memmap *ml; + + while (list) { + ml = malloc(sizeof(*ml)); + if (!ml) { + syslinux_free_memmap(newlist); + return NULL; + } + ml->start = list->start; + ml->type = list->type; + ml->next = NULL; + *nlp = ml; + nlp = &ml->next; + + list = list->next; + } + + return newlist; +} diff --git a/contrib/syslinux-4.02/com32/lib/vasprintf.c b/contrib/syslinux-4.02/com32/lib/vasprintf.c new file mode 100644 index 0000000..a1215a3 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/vasprintf.c @@ -0,0 +1,25 @@ +/* + * vasprintf.c + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> + +int vasprintf(char **bufp, const char *format, va_list ap) +{ + va_list ap1; + int bytes; + char *p; + + va_copy(ap1, ap); + + bytes = vsnprintf(NULL, 0, format, ap1) + 1; + va_end(ap1); + + *bufp = p = malloc(bytes); + if (!p) + return -1; + + return vsnprintf(p, bytes, format, ap); +} diff --git a/contrib/syslinux-4.02/com32/lib/vdprintf.c b/contrib/syslinux-4.02/com32/lib/vdprintf.c new file mode 100644 index 0000000..d74f278 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/vdprintf.c @@ -0,0 +1,116 @@ +/* + * vdprintf.c + */ + +#include <stdio.h> +#include <string.h> +#include <stdarg.h> +#include <unistd.h> +#include <inttypes.h> +#include <sys/io.h> +#include <sys/cpu.h> + +#undef DEBUG +#define DEBUG 1 +#include <dprintf.h> + +#define BUFFER_SIZE 4096 + +enum serial_port_regs { + THR = 0, + RBR = 0, + DLL = 0, + DLM = 1, + IER = 1, + IIR = 2, + FCR = 2, + LCR = 3, + MCR = 4, + LSR = 5, + MSR = 6, + SCR = 7, +}; + +#ifndef DEBUG_PORT +# define DEBUG_PORT 0x03f8 /* I/O base address */ +#endif + +static const uint16_t debug_base = DEBUG_PORT; + +static void debug_putc(char c) +{ + if (c == '\n') + debug_putc('\r'); + + while ((inb(debug_base + LSR) & 0x20) == 0) + cpu_relax(); + outb(c, debug_base + THR); +} + +void vdprintf(const char *format, va_list ap) +{ + int rv; + char buffer[BUFFER_SIZE]; + char *p; + static bool debug_init = false; + static bool debug_ok = false; + + rv = vsnprintf(buffer, BUFFER_SIZE, format, ap); + + if (rv < 0) + return; + + if (rv > BUFFER_SIZE - 1) + rv = BUFFER_SIZE - 1; + + /* + * This unconditionally outputs to a serial port at 0x3f8 regardless of + * if one is enabled or not (this means we don't have to enable the real + * serial console and therefore get conflicting output.) + */ + if (__unlikely(!debug_init)) { + uint8_t dll, dlm, lcr; + + debug_init = true; + + cli(); + + /* Initialize the serial port to 115200 n81 with FIFOs enabled */ + outb(0x83, debug_base + LCR); + outb(0x01, debug_base + DLL); + outb(0x00, debug_base + DLM); + (void)inb(debug_base + IER); /* Synchronize */ + dll = inb(debug_base + DLL); + dlm = inb(debug_base + DLM); + lcr = inb(debug_base + LCR); + + outb(0x03, debug_base + LCR); + (void)inb(debug_base + IER); /* Synchronize */ + + outb(0x00, debug_base + IER); + (void)inb(debug_base + IER); /* Synchronize */ + + sti(); + + if (dll != 0x01 || dlm != 0x00 || lcr != 0x83) { + /* No serial port present */ + return; + } + + outb(0x01, debug_base + FCR); + (void)inb(debug_base + IER); /* Synchronize */ + if (inb(debug_base + IIR) < 0xc0) { + outb(0x00, debug_base + FCR); /* Disable non-functional FIFOs */ + (void)inb(debug_base + IER); /* Synchronize */ + } + + debug_ok = true; + } + + if (!debug_ok) + return; + + p = buffer; + while (rv--) + debug_putc(*p++); +} diff --git a/contrib/syslinux-4.02/com32/lib/vfprintf.c b/contrib/syslinux-4.02/com32/lib/vfprintf.c new file mode 100644 index 0000000..be08421 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/vfprintf.c @@ -0,0 +1,26 @@ +/* + * vfprintf.c + */ + +#include <stdio.h> +#include <string.h> +#include <stdarg.h> +#include <unistd.h> + +#define BUFFER_SIZE 32768 + +int vfprintf(FILE * file, const char *format, va_list ap) +{ + int rv; + char buffer[BUFFER_SIZE]; + + rv = vsnprintf(buffer, BUFFER_SIZE, format, ap); + + if (rv < 0) + return rv; + + if (rv > BUFFER_SIZE - 1) + rv = BUFFER_SIZE - 1; + + return _fwrite(buffer, rv, file); +} diff --git a/contrib/syslinux-4.02/com32/lib/vprintf.c b/contrib/syslinux-4.02/com32/lib/vprintf.c new file mode 100644 index 0000000..486f720 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/vprintf.c @@ -0,0 +1,11 @@ +/* + * vprintf.c + */ + +#include <stdio.h> +#include <stdarg.h> + +int vprintf(const char *format, va_list ap) +{ + return vfprintf(stdout, format, ap); +} diff --git a/contrib/syslinux-4.02/com32/lib/vsnprintf.c b/contrib/syslinux-4.02/com32/lib/vsnprintf.c new file mode 100644 index 0000000..1d1d2a2 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/vsnprintf.c @@ -0,0 +1,454 @@ +/* + * vsnprintf.c + * + * vsnprintf(), from which the rest of the printf() + * family is built + */ + +#include <stdarg.h> +#include <stddef.h> +#include <inttypes.h> +#include <string.h> +#include <limits.h> +#include <stdio.h> + +enum flags { + FL_ZERO = 0x01, /* Zero modifier */ + FL_MINUS = 0x02, /* Minus modifier */ + FL_PLUS = 0x04, /* Plus modifier */ + FL_TICK = 0x08, /* ' modifier */ + FL_SPACE = 0x10, /* Space modifier */ + FL_HASH = 0x20, /* # modifier */ + FL_SIGNED = 0x40, /* Number is signed */ + FL_UPPER = 0x80 /* Upper case digits */ +}; + +/* These may have to be adjusted on certain implementations */ +enum ranks { + rank_char = -2, + rank_short = -1, + rank_int = 0, + rank_long = 1, + rank_longlong = 2 +}; + +#define MIN_RANK rank_char +#define MAX_RANK rank_longlong + +#define INTMAX_RANK rank_longlong +#define SIZE_T_RANK rank_long +#define PTRDIFF_T_RANK rank_long + +#define EMIT(x) ({ if (o<n){*q++ = (x);} o++; }) + +static size_t +format_int(char *q, size_t n, uintmax_t val, enum flags flags, + int base, int width, int prec) +{ + char *qq; + size_t o = 0, oo; + static const char lcdigits[] = "0123456789abcdef"; + static const char ucdigits[] = "0123456789ABCDEF"; + const char *digits; + uintmax_t tmpval; + int minus = 0; + int ndigits = 0, nchars; + int tickskip, b4tick; + + /* Select type of digits */ + digits = (flags & FL_UPPER) ? ucdigits : lcdigits; + + /* If signed, separate out the minus */ + if (flags & FL_SIGNED && (intmax_t) val < 0) { + minus = 1; + val = (uintmax_t) (-(intmax_t) val); + } + + /* Count the number of digits needed. This returns zero for 0. */ + tmpval = val; + while (tmpval) { + tmpval /= base; + ndigits++; + } + + /* Adjust ndigits for size of output */ + + if (flags & FL_HASH && base == 8) { + if (prec < ndigits + 1) + prec = ndigits + 1; + } + + if (ndigits < prec) { + ndigits = prec; /* Mandatory number padding */ + } else if (val == 0) { + ndigits = 1; /* Zero still requires space */ + } + + /* For ', figure out what the skip should be */ + if (flags & FL_TICK) { + tickskip = (base == 16) ? 4 : 3; + } else { + tickskip = ndigits; /* No tick marks */ + } + + /* Tick marks aren't digits, but generated by the number converter */ + ndigits += (ndigits - 1) / tickskip; + + /* Now compute the number of nondigits */ + nchars = ndigits; + + if (minus || (flags & (FL_PLUS | FL_SPACE))) + nchars++; /* Need space for sign */ + if ((flags & FL_HASH) && base == 16) { + nchars += 2; /* Add 0x for hex */ + } + + /* Emit early space padding */ + if (!(flags & (FL_MINUS | FL_ZERO)) && width > nchars) { + while (width > nchars) { + EMIT(' '); + width--; + } + } + + /* Emit nondigits */ + if (minus) + EMIT('-'); + else if (flags & FL_PLUS) + EMIT('+'); + else if (flags & FL_SPACE) + EMIT(' '); + + if ((flags & FL_HASH) && base == 16) { + EMIT('0'); + EMIT((flags & FL_UPPER) ? 'X' : 'x'); + } + + /* Emit zero padding */ + if ((flags & (FL_MINUS | FL_ZERO)) == FL_ZERO && width > ndigits) { + while (width > nchars) { + EMIT('0'); + width--; + } + } + + /* Generate the number. This is done from right to left. */ + q += ndigits; /* Advance the pointer to end of number */ + o += ndigits; + qq = q; + oo = o; /* Temporary values */ + + b4tick = tickskip; + while (ndigits > 0) { + if (!b4tick--) { + qq--; + oo--; + ndigits--; + if (oo < n) + *qq = '_'; + b4tick = tickskip - 1; + } + qq--; + oo--; + ndigits--; + if (oo < n) + *qq = digits[val % base]; + val /= base; + } + + /* Emit late space padding */ + while ((flags & FL_MINUS) && width > nchars) { + EMIT(' '); + width--; + } + + return o; +} + +int vsnprintf(char *buffer, size_t n, const char *format, va_list ap) +{ + const char *p = format; + char ch; + char *q = buffer; + size_t o = 0; /* Number of characters output */ + uintmax_t val = 0; + int rank = rank_int; /* Default rank */ + int width = 0; + int prec = -1; + int base; + size_t sz; + enum flags flags = 0; + enum { + st_normal, /* Ground state */ + st_flags, /* Special flags */ + st_width, /* Field width */ + st_prec, /* Field precision */ + st_modifiers /* Length or conversion modifiers */ + } state = st_normal; + const char *sarg; /* %s string argument */ + char carg; /* %c char argument */ + int slen; /* String length */ + + while ((ch = *p++)) { + switch (state) { + case st_normal: + if (ch == '%') { + state = st_flags; + flags = 0; + rank = rank_int; + width = 0; + prec = -1; + } else { + EMIT(ch); + } + break; + + case st_flags: + switch (ch) { + case '-': + flags |= FL_MINUS; + break; + case '+': + flags |= FL_PLUS; + break; + case '\'': + flags |= FL_TICK; + break; + case ' ': + flags |= FL_SPACE; + break; + case '#': + flags |= FL_HASH; + break; + case '0': + flags |= FL_ZERO; + break; + default: + state = st_width; + p--; /* Process this character again */ + break; + } + break; + + case st_width: + if (ch >= '0' && ch <= '9') { + width = width * 10 + (ch - '0'); + } else if (ch == '*') { + width = va_arg(ap, int); + if (width < 0) { + width = -width; + flags |= FL_MINUS; + } + } else if (ch == '.') { + prec = 0; /* Precision given */ + state = st_prec; + } else { + state = st_modifiers; + p--; /* Process this character again */ + } + break; + + case st_prec: + if (ch >= '0' && ch <= '9') { + prec = prec * 10 + (ch - '0'); + } else if (ch == '*') { + prec = va_arg(ap, int); + if (prec < 0) + prec = -1; + } else { + state = st_modifiers; + p--; /* Process this character again */ + } + break; + + case st_modifiers: + switch (ch) { + /* Length modifiers - nonterminal sequences */ + case 'h': + rank--; /* Shorter rank */ + break; + case 'l': + rank++; /* Longer rank */ + break; + case 'j': + rank = INTMAX_RANK; + break; + case 'z': + rank = SIZE_T_RANK; + break; + case 't': + rank = PTRDIFF_T_RANK; + break; + case 'L': + case 'q': + rank += 2; + break; + default: + /* Output modifiers - terminal sequences */ + state = st_normal; /* Next state will be normal */ + if (rank < MIN_RANK) /* Canonicalize rank */ + rank = MIN_RANK; + else if (rank > MAX_RANK) + rank = MAX_RANK; + + switch (ch) { + case 'P': /* Upper case pointer */ + flags |= FL_UPPER; + /* fall through */ + case 'p': /* Pointer */ + base = 16; + prec = (CHAR_BIT * sizeof(void *) + 3) / 4; + flags |= FL_HASH; + val = (uintmax_t) (uintptr_t) va_arg(ap, void *); + goto is_integer; + + case 'd': /* Signed decimal output */ + case 'i': + base = 10; + flags |= FL_SIGNED; + switch (rank) { + case rank_char: + /* Yes, all these casts are needed... */ + val = + (uintmax_t) (intmax_t) (signed char)va_arg(ap, + signed + int); + break; + case rank_short: + val = + (uintmax_t) (intmax_t) (signed short)va_arg(ap, + signed + int); + break; + case rank_int: + val = (uintmax_t) (intmax_t) va_arg(ap, signed int); + break; + case rank_long: + val = (uintmax_t) (intmax_t) va_arg(ap, signed long); + break; + case rank_longlong: + val = + (uintmax_t) (intmax_t) va_arg(ap, signed long long); + break; + } + goto is_integer; + case 'o': /* Octal */ + base = 8; + goto is_unsigned; + case 'u': /* Unsigned decimal */ + base = 10; + goto is_unsigned; + case 'X': /* Upper case hexadecimal */ + flags |= FL_UPPER; + /* fall through */ + case 'x': /* Hexadecimal */ + base = 16; + goto is_unsigned; + +is_unsigned: + switch (rank) { + case rank_char: + val = + (uintmax_t) (unsigned char)va_arg(ap, unsigned int); + break; + case rank_short: + val = + (uintmax_t) (unsigned short)va_arg(ap, + unsigned int); + break; + case rank_int: + val = (uintmax_t) va_arg(ap, unsigned int); + break; + case rank_long: + val = (uintmax_t) va_arg(ap, unsigned long); + break; + case rank_longlong: + val = (uintmax_t) va_arg(ap, unsigned long long); + break; + } + /* fall through */ + +is_integer: + sz = format_int(q, (o < n) ? n - o : 0, val, flags, base, + width, prec); + q += sz; + o += sz; + break; + + case 'c': /* Character */ + carg = (char)va_arg(ap, int); + sarg = &carg; + slen = 1; + goto is_string; + case 's': /* String */ + sarg = va_arg(ap, const char *); + sarg = sarg ? sarg : "(null)"; + slen = strlen(sarg); + goto is_string; + +is_string: + { + char sch; + int i; + + if (prec != -1 && slen > prec) + slen = prec; + + if (width > slen && !(flags & FL_MINUS)) { + char pad = (flags & FL_ZERO) ? '0' : ' '; + while (width > slen) { + EMIT(pad); + width--; + } + } + for (i = slen; i; i--) { + sch = *sarg++; + EMIT(sch); + } + if (width > slen && (flags & FL_MINUS)) { + while (width > slen) { + EMIT(' '); + width--; + } + } + } + break; + + case 'n': /* Output the number of characters written */ + { + switch (rank) { + case rank_char: + *va_arg(ap, signed char *) = o; + break; + case rank_short: + *va_arg(ap, signed short *) = o; + break; + case rank_int: + *va_arg(ap, signed int *) = o; + break; + case rank_long: + *va_arg(ap, signed long *) = o; + break; + case rank_longlong: + *va_arg(ap, signed long long *) = o; + break; + } + } + break; + + default: /* Anything else, including % */ + EMIT(ch); + break; + } + } + } + } + + /* Null-terminate the string */ + if (o < n) + *q = '\0'; /* No overflow */ + else if (n > 0) + buffer[n - 1] = '\0'; /* Overflow - terminate at end of buffer */ + + return o; +} diff --git a/contrib/syslinux-4.02/com32/lib/vsprintf.c b/contrib/syslinux-4.02/com32/lib/vsprintf.c new file mode 100644 index 0000000..8df6213 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/vsprintf.c @@ -0,0 +1,11 @@ +/* + * vsprintf.c + */ + +#include <stdio.h> +#include <unistd.h> + +int vsprintf(char *buffer, const char *format, va_list ap) +{ + return vsnprintf(buffer, ~(size_t) 0, format, ap); +} diff --git a/contrib/syslinux-4.02/com32/lib/vsscanf.c b/contrib/syslinux-4.02/com32/lib/vsscanf.c new file mode 100644 index 0000000..153dbbd --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/vsscanf.c @@ -0,0 +1,374 @@ +/* + * vsscanf.c + * + * vsscanf(), from which the rest of the scanf() + * family is built + */ + +#include <ctype.h> +#include <stdarg.h> +#include <stddef.h> +#include <inttypes.h> +#include <string.h> +#include <limits.h> +#include <stdio.h> + +#ifndef LONG_BIT +#define LONG_BIT (CHAR_BIT*sizeof(long)) +#endif + +enum flags { + FL_SPLAT = 0x01, /* Drop the value, do not assign */ + FL_INV = 0x02, /* Character-set with inverse */ + FL_WIDTH = 0x04, /* Field width specified */ + FL_MINUS = 0x08, /* Negative number */ +}; + +enum ranks { + rank_char = -2, + rank_short = -1, + rank_int = 0, + rank_long = 1, + rank_longlong = 2, + rank_ptr = INT_MAX /* Special value used for pointers */ +}; + +#define MIN_RANK rank_char +#define MAX_RANK rank_longlong + +#define INTMAX_RANK rank_longlong +#define SIZE_T_RANK rank_long +#define PTRDIFF_T_RANK rank_long + +enum bail { + bail_none = 0, /* No error condition */ + bail_eof, /* Hit EOF */ + bail_err /* Conversion mismatch */ +}; + +static inline const char *skipspace(const char *p) +{ + while (isspace((unsigned char)*p)) + p++; + return p; +} + +#undef set_bit +static inline void set_bit(unsigned long *bitmap, unsigned int bit) +{ + bitmap[bit / LONG_BIT] |= 1UL << (bit % LONG_BIT); +} + +#undef test_bit +static inline int test_bit(unsigned long *bitmap, unsigned int bit) +{ + return (int)(bitmap[bit / LONG_BIT] >> (bit % LONG_BIT)) & 1; +} + +int vsscanf(const char *buffer, const char *format, va_list ap) +{ + const char *p = format; + char ch; + const char *q = buffer; + const char *qq; + uintmax_t val = 0; + int rank = rank_int; /* Default rank */ + unsigned int width = UINT_MAX; + int base; + enum flags flags = 0; + enum { + st_normal, /* Ground state */ + st_flags, /* Special flags */ + st_width, /* Field width */ + st_modifiers, /* Length or conversion modifiers */ + st_match_init, /* Initial state of %[ sequence */ + st_match, /* Main state of %[ sequence */ + st_match_range, /* After - in a %[ sequence */ + } state = st_normal; + char *sarg = NULL; /* %s %c or %[ string argument */ + enum bail bail = bail_none; + int sign; + int converted = 0; /* Successful conversions */ + unsigned long matchmap[((1 << CHAR_BIT) + (LONG_BIT - 1)) / LONG_BIT]; + int matchinv = 0; /* Is match map inverted? */ + unsigned char range_start = 0; + + while ((ch = *p++) && !bail) { + switch (state) { + case st_normal: + if (ch == '%') { + state = st_flags; + flags = 0; + rank = rank_int; + width = UINT_MAX; + } else if (isspace((unsigned char)ch)) { + q = skipspace(q); + } else { + if (*q == ch) + q++; + else + bail = bail_err; /* Match failure */ + } + break; + + case st_flags: + switch (ch) { + case '*': + flags |= FL_SPLAT; + break; + case '0' ... '9': + width = (ch - '0'); + state = st_width; + flags |= FL_WIDTH; + break; + default: + state = st_modifiers; + p--; /* Process this character again */ + break; + } + break; + + case st_width: + if (ch >= '0' && ch <= '9') { + width = width * 10 + (ch - '0'); + } else { + state = st_modifiers; + p--; /* Process this character again */ + } + break; + + case st_modifiers: + switch (ch) { + /* Length modifiers - nonterminal sequences */ + case 'h': + rank--; /* Shorter rank */ + break; + case 'l': + rank++; /* Longer rank */ + break; + case 'j': + rank = INTMAX_RANK; + break; + case 'z': + rank = SIZE_T_RANK; + break; + case 't': + rank = PTRDIFF_T_RANK; + break; + case 'L': + case 'q': + rank = rank_longlong; /* long double/long long */ + break; + + default: + /* Output modifiers - terminal sequences */ + state = st_normal; /* Next state will be normal */ + if (rank < MIN_RANK) /* Canonicalize rank */ + rank = MIN_RANK; + else if (rank > MAX_RANK) + rank = MAX_RANK; + + switch (ch) { + case 'P': /* Upper case pointer */ + case 'p': /* Pointer */ +#if 0 /* Enable this to allow null pointers by name */ + q = skipspace(q); + if (!isdigit((unsigned char)*q)) { + static const char *const nullnames[] = + { "null", "nul", "nil", "(null)", "(nul)", "(nil)", +0 }; + const char *const *np; + + /* Check to see if it's a null pointer by name */ + for (np = nullnames; *np; np++) { + if (!strncasecmp(q, *np, strlen(*np))) { + val = (uintmax_t) ((void *)NULL); + goto set_integer; + } + } + /* Failure */ + bail = bail_err; + break; + } + /* else */ +#endif + rank = rank_ptr; + base = 0; + sign = 0; + goto scan_int; + + case 'i': /* Base-independent integer */ + base = 0; + sign = 1; + goto scan_int; + + case 'd': /* Decimal integer */ + base = 10; + sign = 1; + goto scan_int; + + case 'o': /* Octal integer */ + base = 8; + sign = 0; + goto scan_int; + + case 'u': /* Unsigned decimal integer */ + base = 10; + sign = 0; + goto scan_int; + + case 'x': /* Hexadecimal integer */ + case 'X': + base = 16; + sign = 0; + goto scan_int; + + case 'n': /* Number of characters consumed */ + val = (q - buffer); + goto set_integer; + +scan_int: + q = skipspace(q); + if (!*q) { + bail = bail_eof; + break; + } + val = strntoumax(q, (char **)&qq, base, width); + if (qq == q) { + bail = bail_err; + break; + } + q = qq; + converted++; + /* fall through */ + +set_integer: + if (!(flags & FL_SPLAT)) { + switch (rank) { + case rank_char: + *va_arg(ap, unsigned char *) = (unsigned char)val; + break; + case rank_short: + *va_arg(ap, unsigned short *) = (unsigned short)val; + break; + case rank_int: + *va_arg(ap, unsigned int *) = (unsigned int)val; + break; + case rank_long: + *va_arg(ap, unsigned long *) = (unsigned long)val; + break; + case rank_longlong: + *va_arg(ap, unsigned long long *) = + (unsigned long long)val; + break; + case rank_ptr: + *va_arg(ap, void **) = (void *)(uintptr_t) val; + break; + } + } + break; + + case 'c': /* Character */ + width = (flags & FL_WIDTH) ? width : 1; /* Default width == 1 */ + sarg = va_arg(ap, char *); + while (width--) { + if (!*q) { + bail = bail_eof; + break; + } + *sarg++ = *q++; + } + if (!bail) + converted++; + break; + + case 's': /* String */ + { + char *sp; + sp = sarg = va_arg(ap, char *); + while (width-- && *q && !isspace((unsigned char)*q)) { + *sp++ = *q++; + } + if (sarg != sp) { + *sp = '\0'; /* Terminate output */ + converted++; + } else { + bail = bail_eof; + } + } + break; + + case '[': /* Character range */ + sarg = va_arg(ap, char *); + state = st_match_init; + matchinv = 0; + memset(matchmap, 0, sizeof matchmap); + break; + + case '%': /* %% sequence */ + if (*q == '%') + q++; + else + bail = bail_err; + break; + + default: /* Anything else */ + bail = bail_err; /* Unknown sequence */ + break; + } + } + break; + + case st_match_init: /* Initial state for %[ match */ + if (ch == '^' && !(flags & FL_INV)) { + matchinv = 1; + } else { + set_bit(matchmap, (unsigned char)ch); + state = st_match; + } + break; + + case st_match: /* Main state for %[ match */ + if (ch == ']') { + goto match_run; + } else if (ch == '-') { + range_start = (unsigned char)ch; + state = st_match_range; + } else { + set_bit(matchmap, (unsigned char)ch); + } + break; + + case st_match_range: /* %[ match after - */ + if (ch == ']') { + set_bit(matchmap, (unsigned char)'-'); /* - was last character */ + goto match_run; + } else { + int i; + for (i = range_start; i < (unsigned char)ch; i++) + set_bit(matchmap, i); + state = st_match; + } + break; + +match_run: /* Match expression finished */ + qq = q; + while (width && *q + && test_bit(matchmap, (unsigned char)*q) ^ matchinv) { + *sarg++ = *q++; + } + if (q != qq) { + *sarg = '\0'; + converted++; + } else { + bail = *q ? bail_err : bail_eof; + } + break; + } + } + + if (bail == bail_eof && !converted) + converted = -1; /* Return EOF (-1) */ + + return converted; +} diff --git a/contrib/syslinux-4.02/com32/lib/zalloc.c b/contrib/syslinux-4.02/com32/lib/zalloc.c new file mode 100644 index 0000000..0e6ed28 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/zalloc.c @@ -0,0 +1,17 @@ +/* + * zalloc.c + */ + +#include <stdlib.h> +#include <string.h> + +void *zalloc(size_t size) +{ + void *ptr; + + ptr = malloc(size); + if (ptr) + memset(ptr, 0, size); + + return ptr; +} diff --git a/contrib/syslinux-4.02/com32/lib/zlib/FAQ b/contrib/syslinux-4.02/com32/lib/zlib/FAQ new file mode 100644 index 0000000..1a22750 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/zlib/FAQ @@ -0,0 +1,366 @@ + + Frequently Asked Questions about zlib + + +If your question is not there, please check the zlib home page +http://zlib.net/ which may have more recent information. +The lastest zlib FAQ is at http://zlib.net/zlib_faq.html + + + 1. Is zlib Y2K-compliant? + + Yes. zlib doesn't handle dates. + + 2. Where can I get a Windows DLL version? + + The zlib sources can be compiled without change to produce a DLL. See the + file win32/DLL_FAQ.txt in the zlib distribution. Pointers to the + precompiled DLL are found in the zlib web site at http://zlib.net/ . + + 3. Where can I get a Visual Basic interface to zlib? + + See + * http://marknelson.us/1997/01/01/zlib-engine/ + * win32/DLL_FAQ.txt in the zlib distribution + + 4. compress() returns Z_BUF_ERROR. + + Make sure that before the call of compress(), the length of the compressed + buffer is equal to the available size of the compressed buffer and not + zero. For Visual Basic, check that this parameter is passed by reference + ("as any"), not by value ("as long"). + + 5. deflate() or inflate() returns Z_BUF_ERROR. + + Before making the call, make sure that avail_in and avail_out are not zero. + When setting the parameter flush equal to Z_FINISH, also make sure that + avail_out is big enough to allow processing all pending input. Note that a + Z_BUF_ERROR is not fatal--another call to deflate() or inflate() can be + made with more input or output space. A Z_BUF_ERROR may in fact be + unavoidable depending on how the functions are used, since it is not + possible to tell whether or not there is more output pending when + strm.avail_out returns with zero. See http://zlib.net/zlib_how.html for a + heavily annotated example. + + 6. Where's the zlib documentation (man pages, etc.)? + + It's in zlib.h . Examples of zlib usage are in the files example.c and + minigzip.c, with more in examples/ . + + 7. Why don't you use GNU autoconf or libtool or ...? + + Because we would like to keep zlib as a very small and simple package. + zlib is rather portable and doesn't need much configuration. + + 8. I found a bug in zlib. + + Most of the time, such problems are due to an incorrect usage of zlib. + Please try to reproduce the problem with a small program and send the + corresponding source to us at zlib@gzip.org . Do not send multi-megabyte + data files without prior agreement. + + 9. Why do I get "undefined reference to gzputc"? + + If "make test" produces something like + + example.o(.text+0x154): undefined reference to `gzputc' + + check that you don't have old files libz.* in /usr/lib, /usr/local/lib or + /usr/X11R6/lib. Remove any old versions, then do "make install". + +10. I need a Delphi interface to zlib. + + See the contrib/delphi directory in the zlib distribution. + +11. Can zlib handle .zip archives? + + Not by itself, no. See the directory contrib/minizip in the zlib + distribution. + +12. Can zlib handle .Z files? + + No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt + the code of uncompress on your own. + +13. How can I make a Unix shared library? + + make clean + ./configure -s + make + +14. How do I install a shared zlib library on Unix? + + After the above, then: + + make install + + However, many flavors of Unix come with a shared zlib already installed. + Before going to the trouble of compiling a shared version of zlib and + trying to install it, you may want to check if it's already there! If you + can #include <zlib.h>, it's there. The -lz option will probably link to + it. You can check the version at the top of zlib.h or with the + ZLIB_VERSION symbol defined in zlib.h . + +15. I have a question about OttoPDF. + + We are not the authors of OttoPDF. The real author is on the OttoPDF web + site: Joel Hainley, jhainley@myndkryme.com. + +16. Can zlib decode Flate data in an Adobe PDF file? + + Yes. See http://www.pdflib.com/ . To modify PDF forms, see + http://sourceforge.net/projects/acroformtool/ . + +17. Why am I getting this "register_frame_info not found" error on Solaris? + + After installing zlib 1.1.4 on Solaris 2.6, running applications using zlib + generates an error such as: + + ld.so.1: rpm: fatal: relocation error: file /usr/local/lib/libz.so: + symbol __register_frame_info: referenced symbol not found + + The symbol __register_frame_info is not part of zlib, it is generated by + the C compiler (cc or gcc). You must recompile applications using zlib + which have this problem. This problem is specific to Solaris. See + http://www.sunfreeware.com for Solaris versions of zlib and applications + using zlib. + +18. Why does gzip give an error on a file I make with compress/deflate? + + The compress and deflate functions produce data in the zlib format, which + is different and incompatible with the gzip format. The gz* functions in + zlib on the other hand use the gzip format. Both the zlib and gzip formats + use the same compressed data format internally, but have different headers + and trailers around the compressed data. + +19. Ok, so why are there two different formats? + + The gzip format was designed to retain the directory information about a + single file, such as the name and last modification date. The zlib format + on the other hand was designed for in-memory and communication channel + applications, and has a much more compact header and trailer and uses a + faster integrity check than gzip. + +20. Well that's nice, but how do I make a gzip file in memory? + + You can request that deflate write the gzip format instead of the zlib + format using deflateInit2(). You can also request that inflate decode the + gzip format using inflateInit2(). Read zlib.h for more details. + +21. Is zlib thread-safe? + + Yes. However any library routines that zlib uses and any application- + provided memory allocation routines must also be thread-safe. zlib's gz* + functions use stdio library routines, and most of zlib's functions use the + library memory allocation routines by default. zlib's *Init* functions + allow for the application to provide custom memory allocation routines. + + Of course, you should only operate on any given zlib or gzip stream from a + single thread at a time. + +22. Can I use zlib in my commercial application? + + Yes. Please read the license in zlib.h. + +23. Is zlib under the GNU license? + + No. Please read the license in zlib.h. + +24. The license says that altered source versions must be "plainly marked". So + what exactly do I need to do to meet that requirement? + + You need to change the ZLIB_VERSION and ZLIB_VERNUM #defines in zlib.h. In + particular, the final version number needs to be changed to "f", and an + identification string should be appended to ZLIB_VERSION. Version numbers + x.x.x.f are reserved for modifications to zlib by others than the zlib + maintainers. For example, if the version of the base zlib you are altering + is "1.2.3.4", then in zlib.h you should change ZLIB_VERNUM to 0x123f, and + ZLIB_VERSION to something like "1.2.3.f-zachary-mods-v3". You can also + update the version strings in deflate.c and inftrees.c. + + For altered source distributions, you should also note the origin and + nature of the changes in zlib.h, as well as in ChangeLog and README, along + with the dates of the alterations. The origin should include at least your + name (or your company's name), and an email address to contact for help or + issues with the library. + + Note that distributing a compiled zlib library along with zlib.h and + zconf.h is also a source distribution, and so you should change + ZLIB_VERSION and ZLIB_VERNUM and note the origin and nature of the changes + in zlib.h as you would for a full source distribution. + +25. Will zlib work on a big-endian or little-endian architecture, and can I + exchange compressed data between them? + + Yes and yes. + +26. Will zlib work on a 64-bit machine? + + Yes. It has been tested on 64-bit machines, and has no dependence on any + data types being limited to 32-bits in length. If you have any + difficulties, please provide a complete problem report to zlib@gzip.org + +27. Will zlib decompress data from the PKWare Data Compression Library? + + No. The PKWare DCL uses a completely different compressed data format than + does PKZIP and zlib. However, you can look in zlib's contrib/blast + directory for a possible solution to your problem. + +28. Can I access data randomly in a compressed stream? + + No, not without some preparation. If when compressing you periodically use + Z_FULL_FLUSH, carefully write all the pending data at those points, and + keep an index of those locations, then you can start decompression at those + points. You have to be careful to not use Z_FULL_FLUSH too often, since it + can significantly degrade compression. Alternatively, you can scan a + deflate stream once to generate an index, and then use that index for + random access. See examples/zran.c . + +29. Does zlib work on MVS, OS/390, CICS, etc.? + + It has in the past, but we have not heard of any recent evidence. There + were working ports of zlib 1.1.4 to MVS, but those links no longer work. + If you know of recent, successful applications of zlib on these operating + systems, please let us know. Thanks. + +30. Is there some simpler, easier to read version of inflate I can look at to + understand the deflate format? + + First off, you should read RFC 1951. Second, yes. Look in zlib's + contrib/puff directory. + +31. Does zlib infringe on any patents? + + As far as we know, no. In fact, that was originally the whole point behind + zlib. Look here for some more information: + + http://www.gzip.org/#faq11 + +32. Can zlib work with greater than 4 GB of data? + + Yes. inflate() and deflate() will process any amount of data correctly. + Each call of inflate() or deflate() is limited to input and output chunks + of the maximum value that can be stored in the compiler's "unsigned int" + type, but there is no limit to the number of chunks. Note however that the + strm.total_in and strm_total_out counters may be limited to 4 GB. These + counters are provided as a convenience and are not used internally by + inflate() or deflate(). The application can easily set up its own counters + updated after each call of inflate() or deflate() to count beyond 4 GB. + compress() and uncompress() may be limited to 4 GB, since they operate in a + single call. gzseek() and gztell() may be limited to 4 GB depending on how + zlib is compiled. See the zlibCompileFlags() function in zlib.h. + + The word "may" appears several times above since there is a 4 GB limit only + if the compiler's "long" type is 32 bits. If the compiler's "long" type is + 64 bits, then the limit is 16 exabytes. + +33. Does zlib have any security vulnerabilities? + + The only one that we are aware of is potentially in gzprintf(). If zlib is + compiled to use sprintf() or vsprintf(), then there is no protection + against a buffer overflow of an 8K string space (or other value as set by + gzbuffer()), other than the caller of gzprintf() assuring that the output + will not exceed 8K. On the other hand, if zlib is compiled to use + snprintf() or vsnprintf(), which should normally be the case, then there is + no vulnerability. The ./configure script will display warnings if an + insecure variation of sprintf() will be used by gzprintf(). Also the + zlibCompileFlags() function will return information on what variant of + sprintf() is used by gzprintf(). + + If you don't have snprintf() or vsnprintf() and would like one, you can + find a portable implementation here: + + http://www.ijs.si/software/snprintf/ + + Note that you should be using the most recent version of zlib. Versions + 1.1.3 and before were subject to a double-free vulnerability, and versions + 1.2.1 and 1.2.2 were subject to an access exception when decompressing + invalid compressed data. + +34. Is there a Java version of zlib? + + Probably what you want is to use zlib in Java. zlib is already included + as part of the Java SDK in the java.util.zip package. If you really want + a version of zlib written in the Java language, look on the zlib home + page for links: http://zlib.net/ . + +35. I get this or that compiler or source-code scanner warning when I crank it + up to maximally-pedantic. Can't you guys write proper code? + + Many years ago, we gave up attempting to avoid warnings on every compiler + in the universe. It just got to be a waste of time, and some compilers + were downright silly as well as contradicted each other. So now, we simply + make sure that the code always works. + +36. Valgrind (or some similar memory access checker) says that deflate is + performing a conditional jump that depends on an uninitialized value. + Isn't that a bug? + + No. That is intentional for performance reasons, and the output of deflate + is not affected. This only started showing up recently since zlib 1.2.x + uses malloc() by default for allocations, whereas earlier versions used + calloc(), which zeros out the allocated memory. Even though the code was + correct, versions 1.2.4 and later was changed to not stimulate these + checkers. + +37. Will zlib read the (insert any ancient or arcane format here) compressed + data format? + + Probably not. Look in the comp.compression FAQ for pointers to various + formats and associated software. + +38. How can I encrypt/decrypt zip files with zlib? + + zlib doesn't support encryption. The original PKZIP encryption is very + weak and can be broken with freely available programs. To get strong + encryption, use GnuPG, http://www.gnupg.org/ , which already includes zlib + compression. For PKZIP compatible "encryption", look at + http://www.info-zip.org/ + +39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings? + + "gzip" is the gzip format, and "deflate" is the zlib format. They should + probably have called the second one "zlib" instead to avoid confusion with + the raw deflate compressed data format. While the HTTP 1.1 RFC 2616 + correctly points to the zlib specification in RFC 1950 for the "deflate" + transfer encoding, there have been reports of servers and browsers that + incorrectly produce or expect raw deflate data per the deflate + specficiation in RFC 1951, most notably Microsoft. So even though the + "deflate" transfer encoding using the zlib format would be the more + efficient approach (and in fact exactly what the zlib format was designed + for), using the "gzip" transfer encoding is probably more reliable due to + an unfortunate choice of name on the part of the HTTP 1.1 authors. + + Bottom line: use the gzip format for HTTP 1.1 encoding. + +40. Does zlib support the new "Deflate64" format introduced by PKWare? + + No. PKWare has apparently decided to keep that format proprietary, since + they have not documented it as they have previous compression formats. In + any case, the compression improvements are so modest compared to other more + modern approaches, that it's not worth the effort to implement. + +41. I'm having a problem with the zip functions in zlib, can you help? + + There are no zip functions in zlib. You are probably using minizip by + Giles Vollant, which is found in the contrib directory of zlib. It is not + part of zlib. In fact none of the stuff in contrib is part of zlib. The + files in there are not supported by the zlib authors. You need to contact + the authors of the respective contribution for help. + +42. The match.asm code in contrib is under the GNU General Public License. + Since it's part of zlib, doesn't that mean that all of zlib falls under the + GNU GPL? + + No. The files in contrib are not part of zlib. They were contributed by + other authors and are provided as a convenience to the user within the zlib + distribution. Each item in contrib has its own license. + +43. Is zlib subject to export controls? What is its ECCN? + + zlib is not subject to export controls, and so is classified as EAR99. + +44. Can you please sign these lengthy legal documents and fax them back to us + so that we can use your software in our product? + + No. Go away. Shoo. diff --git a/contrib/syslinux-4.02/com32/lib/zlib/README b/contrib/syslinux-4.02/com32/lib/zlib/README new file mode 100644 index 0000000..d4219bf --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/zlib/README @@ -0,0 +1,115 @@ +ZLIB DATA COMPRESSION LIBRARY + +zlib 1.2.5 is a general purpose data compression library. All the code is +thread safe. The data format used by the zlib library is described by RFCs +(Request for Comments) 1950 to 1952 in the files +http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) +and rfc1952.txt (gzip format). + +All functions of the compression library are documented in the file zlib.h +(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example +of the library is given in the file example.c which also tests that the library +is working correctly. Another example is given in the file minigzip.c. The +compression library itself is composed of all source files except example.c and +minigzip.c. + +To compile all files and run the test program, follow the instructions given at +the top of Makefile.in. In short "./configure; make test", and if that goes +well, "make install" should work for most flavors of Unix. For Windows, use one +of the special makefiles in win32/ or contrib/vstudio/ . For VMS, use +make_vms.com. + +Questions about zlib should be sent to <zlib@gzip.org>, or to Gilles Vollant +<info@winimage.com> for the Windows DLL version. The zlib home page is +http://zlib.net/ . Before reporting a problem, please check this site to +verify that you have the latest version of zlib; otherwise get the latest +version and check whether the problem still exists or not. + +PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help. + +Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997 +issue of Dr. Dobb's Journal; a copy of the article is available at +http://marknelson.us/1997/01/01/zlib-engine/ . + +The changes made in version 1.2.5 are documented in the file ChangeLog. + +Unsupported third party contributions are provided in directory contrib/ . + +zlib is available in Java using the java.util.zip package, documented at +http://java.sun.com/developer/technicalArticles/Programming/compression/ . + +A Perl interface to zlib written by Paul Marquess <pmqs@cpan.org> is available +at CPAN (Comprehensive Perl Archive Network) sites, including +http://search.cpan.org/~pmqs/IO-Compress-Zlib/ . + +A Python interface to zlib written by A.M. Kuchling <amk@amk.ca> is +available in Python 1.5 and later versions, see +http://www.python.org/doc/lib/module-zlib.html . + +zlib is built into tcl: http://wiki.tcl.tk/4610 . + +An experimental package to read and write files in .zip format, written on top +of zlib by Gilles Vollant <info@winimage.com>, is available in the +contrib/minizip directory of zlib. + + +Notes for some targets: + +- For Windows DLL versions, please see win32/DLL_FAQ.txt + +- For 64-bit Irix, deflate.c must be compiled without any optimization. With + -O, one libpng test fails. The test works in 32 bit mode (with the -n32 + compiler flag). The compiler bug has been reported to SGI. + +- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works + when compiled with cc. + +- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is + necessary to get gzprintf working correctly. This is done by configure. + +- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with + other compilers. Use "make test" to check your compiler. + +- gzdopen is not supported on RISCOS or BEOS. + +- For PalmOs, see http://palmzlib.sourceforge.net/ + + +Acknowledgments: + + The deflate format used by zlib was defined by Phil Katz. The deflate and + zlib specifications were written by L. Peter Deutsch. Thanks to all the + people who reported problems and suggested various improvements in zlib; they + are too numerous to cite here. + +Copyright notice: + + (C) 1995-2010 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +If you use the zlib library in a product, we would appreciate *not* receiving +lengthy legal documents to sign. The sources are provided for free but without +warranty of any kind. The library has been entirely written by Jean-loup +Gailly and Mark Adler; it does not include third-party code. + +If you redistribute modified sources, we would appreciate that you include in +the file ChangeLog history information documenting your changes. Please read +the FAQ for more information on the distribution of modified source versions. diff --git a/contrib/syslinux-4.02/com32/lib/zlib/adler32.c b/contrib/syslinux-4.02/com32/lib/zlib/adler32.c new file mode 100644 index 0000000..65ad6a5 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/zlib/adler32.c @@ -0,0 +1,169 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2007 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +#define local static + +local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2); + +#define BASE 65521UL /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* use NO_DIVIDE if your processor does not do division in hardware */ +#ifdef NO_DIVIDE +# define MOD(a) \ + do { \ + if (a >= (BASE << 16)) a -= (BASE << 16); \ + if (a >= (BASE << 15)) a -= (BASE << 15); \ + if (a >= (BASE << 14)) a -= (BASE << 14); \ + if (a >= (BASE << 13)) a -= (BASE << 13); \ + if (a >= (BASE << 12)) a -= (BASE << 12); \ + if (a >= (BASE << 11)) a -= (BASE << 11); \ + if (a >= (BASE << 10)) a -= (BASE << 10); \ + if (a >= (BASE << 9)) a -= (BASE << 9); \ + if (a >= (BASE << 8)) a -= (BASE << 8); \ + if (a >= (BASE << 7)) a -= (BASE << 7); \ + if (a >= (BASE << 6)) a -= (BASE << 6); \ + if (a >= (BASE << 5)) a -= (BASE << 5); \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +# define MOD4(a) \ + do { \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +# define MOD4(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long sum2; + unsigned n; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) { + adler += buf[0]; + if (adler >= BASE) + adler -= BASE; + sum2 += adler; + if (sum2 >= BASE) + sum2 -= BASE; + return adler | (sum2 << 16); + } + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (buf == Z_NULL) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) { + while (len--) { + adler += *buf++; + sum2 += adler; + } + if (adler >= BASE) + adler -= BASE; + MOD4(sum2); /* only added so many BASE's */ + return adler | (sum2 << 16); + } + + /* do length NMAX blocks -- requires just one modulo operation */ + while (len >= NMAX) { + len -= NMAX; + n = NMAX / 16; /* NMAX is divisible by 16 */ + do { + DO16(buf); /* 16 sums unrolled */ + buf += 16; + } while (--n); + MOD(adler); + MOD(sum2); + } + + /* do remaining bytes (less than NMAX, still just one modulo) */ + if (len) { /* avoid modulos if none remaining */ + while (len >= 16) { + len -= 16; + DO16(buf); + buf += 16; + } + while (len--) { + adler += *buf++; + sum2 += adler; + } + MOD(adler); + MOD(sum2); + } + + /* return recombined sums */ + return adler | (sum2 << 16); +} + +/* ========================================================================= */ +local uLong adler32_combine_(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + unsigned long sum1; + unsigned long sum2; + unsigned rem; + + /* the derivation of this formula is left as an exercise for the reader */ + rem = (unsigned)(len2 % BASE); + sum1 = adler1 & 0xffff; + sum2 = rem * sum1; + MOD(sum2); + sum1 += (adler2 & 0xffff) + BASE - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + if (sum1 >= BASE) sum1 -= BASE; + if (sum1 >= BASE) sum1 -= BASE; + if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1); + if (sum2 >= BASE) sum2 -= BASE; + return sum1 | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32_combine(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} + +uLong ZEXPORT adler32_combine64(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} diff --git a/contrib/syslinux-4.02/com32/lib/zlib/algorithm.txt b/contrib/syslinux-4.02/com32/lib/zlib/algorithm.txt new file mode 100644 index 0000000..b022dde --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/zlib/algorithm.txt @@ -0,0 +1,209 @@ +1. Compression algorithm (deflate) + +The deflation algorithm used by gzip (also zip and zlib) is a variation of +LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in +the input data. The second occurrence of a string is replaced by a +pointer to the previous string, in the form of a pair (distance, +length). Distances are limited to 32K bytes, and lengths are limited +to 258 bytes. When a string does not occur anywhere in the previous +32K bytes, it is emitted as a sequence of literal bytes. (In this +description, `string' must be taken as an arbitrary sequence of bytes, +and is not restricted to printable characters.) + +Literals or match lengths are compressed with one Huffman tree, and +match distances are compressed with another tree. The trees are stored +in a compact form at the start of each block. The blocks can have any +size (except that the compressed data for one block must fit in +available memory). A block is terminated when deflate() determines that +it would be useful to start another block with fresh trees. (This is +somewhat similar to the behavior of LZW-based _compress_.) + +Duplicated strings are found using a hash table. All input strings of +length 3 are inserted in the hash table. A hash index is computed for +the next 3 bytes. If the hash chain for this index is not empty, all +strings in the chain are compared with the current input string, and +the longest match is selected. + +The hash chains are searched starting with the most recent strings, to +favor small distances and thus take advantage of the Huffman encoding. +The hash chains are singly linked. There are no deletions from the +hash chains, the algorithm simply discards matches that are too old. + +To avoid a worst-case situation, very long hash chains are arbitrarily +truncated at a certain length, determined by a runtime option (level +parameter of deflateInit). So deflate() does not always find the longest +possible match but generally finds a match which is long enough. + +deflate() also defers the selection of matches with a lazy evaluation +mechanism. After a match of length N has been found, deflate() searches for +a longer match at the next input byte. If a longer match is found, the +previous match is truncated to a length of one (thus producing a single +literal byte) and the process of lazy evaluation begins again. Otherwise, +the original match is kept, and the next match search is attempted only N +steps later. + +The lazy match evaluation is also subject to a runtime parameter. If +the current match is long enough, deflate() reduces the search for a longer +match, thus speeding up the whole process. If compression ratio is more +important than speed, deflate() attempts a complete second search even if +the first match is already long enough. + +The lazy match evaluation is not performed for the fastest compression +modes (level parameter 1 to 3). For these fast modes, new strings +are inserted in the hash table only when no match was found, or +when the match is not too long. This degrades the compression ratio +but saves time since there are both fewer insertions and fewer searches. + + +2. Decompression algorithm (inflate) + +2.1 Introduction + +The key question is how to represent a Huffman code (or any prefix code) so +that you can decode fast. The most important characteristic is that shorter +codes are much more common than longer codes, so pay attention to decoding the +short codes fast, and let the long codes take longer to decode. + +inflate() sets up a first level table that covers some number of bits of +input less than the length of longest code. It gets that many bits from the +stream, and looks it up in the table. The table will tell if the next +code is that many bits or less and how many, and if it is, it will tell +the value, else it will point to the next level table for which inflate() +grabs more bits and tries to decode a longer code. + +How many bits to make the first lookup is a tradeoff between the time it +takes to decode and the time it takes to build the table. If building the +table took no time (and if you had infinite memory), then there would only +be a first level table to cover all the way to the longest code. However, +building the table ends up taking a lot longer for more bits since short +codes are replicated many times in such a table. What inflate() does is +simply to make the number of bits in the first table a variable, and then +to set that variable for the maximum speed. + +For inflate, which has 286 possible codes for the literal/length tree, the size +of the first table is nine bits. Also the distance trees have 30 possible +values, and the size of the first table is six bits. Note that for each of +those cases, the table ended up one bit longer than the ``average'' code +length, i.e. the code length of an approximately flat code which would be a +little more than eight bits for 286 symbols and a little less than five bits +for 30 symbols. + + +2.2 More details on the inflate table lookup + +Ok, you want to know what this cleverly obfuscated inflate tree actually +looks like. You are correct that it's not a Huffman tree. It is simply a +lookup table for the first, let's say, nine bits of a Huffman symbol. The +symbol could be as short as one bit or as long as 15 bits. If a particular +symbol is shorter than nine bits, then that symbol's translation is duplicated +in all those entries that start with that symbol's bits. For example, if the +symbol is four bits, then it's duplicated 32 times in a nine-bit table. If a +symbol is nine bits long, it appears in the table once. + +If the symbol is longer than nine bits, then that entry in the table points +to another similar table for the remaining bits. Again, there are duplicated +entries as needed. The idea is that most of the time the symbol will be short +and there will only be one table look up. (That's whole idea behind data +compression in the first place.) For the less frequent long symbols, there +will be two lookups. If you had a compression method with really long +symbols, you could have as many levels of lookups as is efficient. For +inflate, two is enough. + +So a table entry either points to another table (in which case nine bits in +the above example are gobbled), or it contains the translation for the symbol +and the number of bits to gobble. Then you start again with the next +ungobbled bit. + +You may wonder: why not just have one lookup table for how ever many bits the +longest symbol is? The reason is that if you do that, you end up spending +more time filling in duplicate symbol entries than you do actually decoding. +At least for deflate's output that generates new trees every several 10's of +kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code +would take too long if you're only decoding several thousand symbols. At the +other extreme, you could make a new table for every bit in the code. In fact, +that's essentially a Huffman tree. But then you spend two much time +traversing the tree while decoding, even for short symbols. + +So the number of bits for the first lookup table is a trade of the time to +fill out the table vs. the time spent looking at the second level and above of +the table. + +Here is an example, scaled down: + +The code being decoded, with 10 symbols, from 1 to 6 bits long: + +A: 0 +B: 10 +C: 1100 +D: 11010 +E: 11011 +F: 11100 +G: 11101 +H: 11110 +I: 111110 +J: 111111 + +Let's make the first table three bits long (eight entries): + +000: A,1 +001: A,1 +010: A,1 +011: A,1 +100: B,2 +101: B,2 +110: -> table X (gobble 3 bits) +111: -> table Y (gobble 3 bits) + +Each entry is what the bits decode as and how many bits that is, i.e. how +many bits to gobble. Or the entry points to another table, with the number of +bits to gobble implicit in the size of the table. + +Table X is two bits long since the longest code starting with 110 is five bits +long: + +00: C,1 +01: C,1 +10: D,2 +11: E,2 + +Table Y is three bits long since the longest code starting with 111 is six +bits long: + +000: F,2 +001: F,2 +010: G,2 +011: G,2 +100: H,2 +101: H,2 +110: I,3 +111: J,3 + +So what we have here are three tables with a total of 20 entries that had to +be constructed. That's compared to 64 entries for a single table. Or +compared to 16 entries for a Huffman tree (six two entry tables and one four +entry table). Assuming that the code ideally represents the probability of +the symbols, it takes on the average 1.25 lookups per symbol. That's compared +to one lookup for the single table, or 1.66 lookups per symbol for the +Huffman tree. + +There, I think that gives you a picture of what's going on. For inflate, the +meaning of a particular symbol is often more than just a letter. It can be a +byte (a "literal"), or it can be either a length or a distance which +indicates a base value and a number of bits to fetch after the code that is +added to the base value. Or it might be the special end-of-block code. The +data structures created in inftrees.c try to encode all that information +compactly in the tables. + + +Jean-loup Gailly Mark Adler +jloup@gzip.org madler@alumni.caltech.edu + + +References: + +[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data +Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3, +pp. 337-343. + +``DEFLATE Compressed Data Format Specification'' available in +http://www.ietf.org/rfc/rfc1951.txt diff --git a/contrib/syslinux-4.02/com32/lib/zlib/compress.c b/contrib/syslinux-4.02/com32/lib/zlib/compress.c new file mode 100644 index 0000000..ea4dfbe --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/zlib/compress.c @@ -0,0 +1,80 @@ +/* compress.c -- compress a memory buffer + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ +int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; + int level; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; +#ifdef MAXSEG_64K + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; +#endif + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} + +/* =========================================================================== + If the default memLevel or windowBits for deflateInit() is changed, then + this function needs to be updated. + */ +uLong ZEXPORT compressBound (sourceLen) + uLong sourceLen; +{ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + + (sourceLen >> 25) + 13; +} diff --git a/contrib/syslinux-4.02/com32/lib/zlib/crc32.c b/contrib/syslinux-4.02/com32/lib/zlib/crc32.c new file mode 100644 index 0000000..07265c6 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/zlib/crc32.c @@ -0,0 +1,442 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2006, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results in about a + * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id$ */ + +/* + Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore + protection on the static variables used to control the first-use generation + of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should + first call get_crc_table() to initialize the tables before allowing more than + one thread to use crc32(). + */ + +#ifdef MAKECRCH +# include <stdio.h> +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +#define local static + +/* Find a four-byte integer type for crc32_little() and crc32_big(). */ +#ifndef NOBYFOUR +# ifdef STDC /* need ANSI C limits.h to determine sizes */ +# include <limits.h> +# define BYFOUR +# if (UINT_MAX == 0xffffffffUL) + typedef unsigned int u4; +# else +# if (ULONG_MAX == 0xffffffffUL) + typedef unsigned long u4; +# else +# if (USHRT_MAX == 0xffffffffUL) + typedef unsigned short u4; +# else +# undef BYFOUR /* can't find a four-byte integer type! */ +# endif +# endif +# endif +# endif /* STDC */ +#endif /* !NOBYFOUR */ + +/* Definitions for doing the crc four data bytes at a time. */ +#ifdef BYFOUR +# define REV(w) ((((w)>>24)&0xff)+(((w)>>8)&0xff00)+ \ + (((w)&0xff00)<<8)+(((w)&0xff)<<24)) + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, unsigned)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, unsigned)); +# define TBLS 8 +#else +# define TBLS 1 +#endif /* BYFOUR */ + +/* Local functions for crc concatenation */ +local unsigned long gf2_matrix_times OF((unsigned long *mat, + unsigned long vec)); +local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); +local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2); + + +#ifdef DYNAMIC_CRC_TABLE + +local volatile int crc_table_empty = 1; +local unsigned long FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const unsigned long FAR *)); +#endif /* MAKECRCH */ +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + unsigned long c; + int n, k; + unsigned long poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static volatile int first = 1; /* flag to limit concurrent making */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* See if another task is already doing this (not thread-safe, but better + than nothing -- significantly reduces duration of vulnerability in + case the advice about DYNAMIC_CRC_TABLE is ignored) */ + if (first) { + first = 0; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0UL; + for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++) + poly |= 1UL << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (unsigned long)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, + and then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = REV(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = REV(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + } + else { /* not first */ + /* wait for the other guy to finish (not efficient, but rare) */ + while (crc_table_empty) + ; + } + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const unsigned long FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const unsigned long FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const unsigned long FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const unsigned long FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + uInt len; +{ + if (buf == Z_NULL) return 0UL; + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + if (sizeof(void *) == sizeof(ptrdiff_t)) { + u4 endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } +#endif /* BYFOUR */ + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +#ifdef BYFOUR + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = (u4)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *++buf4; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = REV((u4)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + buf4--; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf4++; + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(REV(c)); +} + +#endif /* BYFOUR */ + +#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ + +/* ========================================================================= */ +local unsigned long gf2_matrix_times(mat, vec) + unsigned long *mat; + unsigned long vec; +{ + unsigned long sum; + + sum = 0; + while (vec) { + if (vec & 1) + sum ^= *mat; + vec >>= 1; + mat++; + } + return sum; +} + +/* ========================================================================= */ +local void gf2_matrix_square(square, mat) + unsigned long *square; + unsigned long *mat; +{ + int n; + + for (n = 0; n < GF2_DIM; n++) + square[n] = gf2_matrix_times(mat, mat[n]); +} + +/* ========================================================================= */ +local uLong crc32_combine_(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off64_t len2; +{ + int n; + unsigned long row; + unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ + unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ + + /* degenerate case (also disallow negative lengths) */ + if (len2 <= 0) + return crc1; + + /* put operator for one zero bit in odd */ + odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ + row = 1; + for (n = 1; n < GF2_DIM; n++) { + odd[n] = row; + row <<= 1; + } + + /* put operator for two zero bits in even */ + gf2_matrix_square(even, odd); + + /* put operator for four zero bits in odd */ + gf2_matrix_square(odd, even); + + /* apply len2 zeros to crc1 (first square will put the operator for one + zero byte, eight zero bits, in even) */ + do { + /* apply zeros operator for this bit of len2 */ + gf2_matrix_square(even, odd); + if (len2 & 1) + crc1 = gf2_matrix_times(even, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + if (len2 == 0) + break; + + /* another iteration of the loop with odd and even swapped */ + gf2_matrix_square(odd, even); + if (len2 & 1) + crc1 = gf2_matrix_times(odd, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + } while (len2 != 0); + + /* return combined crc */ + crc1 ^= crc2; + return crc1; +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off_t len2; +{ + return crc32_combine_(crc1, crc2, len2); +} + +uLong ZEXPORT crc32_combine64(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off64_t len2; +{ + return crc32_combine_(crc1, crc2, len2); +} diff --git a/contrib/syslinux-4.02/com32/lib/zlib/crc32.h b/contrib/syslinux-4.02/com32/lib/zlib/crc32.h new file mode 100644 index 0000000..8053b61 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/zlib/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const unsigned long FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/contrib/syslinux-4.02/com32/lib/zlib/deflate.c b/contrib/syslinux-4.02/com32/lib/zlib/deflate.c new file mode 100644 index 0000000..1a37563 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/zlib/deflate.c @@ -0,0 +1,1834 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in http://www.ietf.org/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id$ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.2.5 Copyright 1995-2010 Jean-loup Gailly and Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +#ifndef FASTEST +local block_state deflate_slow OF((deflate_state *s, int flush)); +#endif +local block_state deflate_rle OF((deflate_state *s, int flush)); +local block_state deflate_huff OF((deflate_state *s, int flush)); +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif + +#ifdef DEBUG_ZLIB +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +#ifdef FASTEST +local const config configuration_table[2] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ +#else +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ +#endif + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +#ifndef NO_DUMMY_DECL +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ +#endif + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } +#ifdef GZIP + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } +#endif + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->wrap = wrap; + s->gzhead = Z_NULL; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->high_water = 0; /* nothing written to s->window yet */ + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + s->status = FINISH_STATE; + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->wrap == 2 || + (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) + return Z_STREAM_ERROR; + + s = strm->state; + if (s->wrap) + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > s->w_size) { + length = s->w_size; + dictionary += dictLength - length; /* use the tail of the dictionary */ + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + return Z_STREAM_ERROR; + } + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->wrap < 0) { + s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ + } + s->status = s->wrap ? INIT_STATE : BUSY_STATE; + strm->adler = +#ifdef GZIP + s->wrap == 2 ? crc32(0L, Z_NULL, 0) : +#endif + adler32(0L, Z_NULL, 0); + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateSetHeader (strm, head) + z_streamp strm; + gz_headerp head; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (strm->state->wrap != 2) return Z_STREAM_ERROR; + strm->state->gzhead = head; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePrime (strm, bits, value) + z_streamp strm; + int bits; + int value; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + strm->state->bi_valid = bits; + strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if ((strategy != s->strategy || func != configuration_table[level].func) && + strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_BLOCK); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= */ +int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) + z_streamp strm; + int good_length; + int max_lazy; + int nice_length; + int max_chain; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + s->good_match = good_length; + s->max_lazy_match = max_lazy; + s->nice_match = nice_length; + s->max_chain_length = max_chain; + return Z_OK; +} + +/* ========================================================================= + * For the default windowBits of 15 and memLevel of 8, this function returns + * a close to exact, as well as small, upper bound on the compressed size. + * They are coded as constants here for a reason--if the #define's are + * changed, then this function needs to be changed as well. The return + * value for 15 and 8 only works for those exact settings. + * + * For any setting other than those defaults for windowBits and memLevel, + * the value returned is a conservative worst case for the maximum expansion + * resulting from using fixed blocks instead of stored blocks, which deflate + * can emit on compressed data for some combinations of the parameters. + * + * This function could be more sophisticated to provide closer upper bounds for + * every combination of windowBits and memLevel. But even the conservative + * upper bound of about 14% expansion does not seem onerous for output buffer + * allocation. + */ +uLong ZEXPORT deflateBound(strm, sourceLen) + z_streamp strm; + uLong sourceLen; +{ + deflate_state *s; + uLong complen, wraplen; + Bytef *str; + + /* conservative upper bound for compressed data */ + complen = sourceLen + + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; + + /* if can't get parameters, return conservative bound plus zlib wrapper */ + if (strm == Z_NULL || strm->state == Z_NULL) + return complen + 6; + + /* compute wrapper length */ + s = strm->state; + switch (s->wrap) { + case 0: /* raw deflate */ + wraplen = 0; + break; + case 1: /* zlib wrapper */ + wraplen = 6 + (s->strstart ? 4 : 0); + break; + case 2: /* gzip wrapper */ + wraplen = 18; + if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ + if (s->gzhead->extra != Z_NULL) + wraplen += 2 + s->gzhead->extra_len; + str = s->gzhead->name; + if (str != Z_NULL) + do { + wraplen++; + } while (*str++); + str = s->gzhead->comment; + if (str != Z_NULL) + do { + wraplen++; + } while (*str++); + if (s->gzhead->hcrc) + wraplen += 2; + } + break; + default: /* for compiler happiness */ + wraplen = 6; + } + + /* if not default parameters, return conservative bound */ + if (s->w_bits != 15 || s->hash_bits != 8 + 7) + return complen + wraplen; + + /* default settings: return tight bound for that case */ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + + (sourceLen >> 25) + 13 - 6 + wraplen; +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_BLOCK || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the header */ + if (s->status == INIT_STATE) { +#ifdef GZIP + if (s->wrap == 2) { + strm->adler = crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (s->gzhead == Z_NULL) { + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s->status = BUSY_STATE; + } + else { + put_byte(s, (s->gzhead->text ? 1 : 0) + + (s->gzhead->hcrc ? 2 : 0) + + (s->gzhead->extra == Z_NULL ? 0 : 4) + + (s->gzhead->name == Z_NULL ? 0 : 8) + + (s->gzhead->comment == Z_NULL ? 0 : 16) + ); + put_byte(s, (Byte)(s->gzhead->time & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, s->gzhead->os & 0xff); + if (s->gzhead->extra != Z_NULL) { + put_byte(s, s->gzhead->extra_len & 0xff); + put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); + } + if (s->gzhead->hcrc) + strm->adler = crc32(strm->adler, s->pending_buf, + s->pending); + s->gzindex = 0; + s->status = EXTRA_STATE; + } + } + else +#endif + { + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + } + } +#ifdef GZIP + if (s->status == EXTRA_STATE) { + if (s->gzhead->extra != Z_NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + + while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) + break; + } + put_byte(s, s->gzhead->extra[s->gzindex]); + s->gzindex++; + } + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (s->gzindex == s->gzhead->extra_len) { + s->gzindex = 0; + s->status = NAME_STATE; + } + } + else + s->status = NAME_STATE; + } + if (s->status == NAME_STATE) { + if (s->gzhead->name != Z_NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->name[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) { + s->gzindex = 0; + s->status = COMMENT_STATE; + } + } + else + s->status = COMMENT_STATE; + } + if (s->status == COMMENT_STATE) { + if (s->gzhead->comment != Z_NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->comment[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) + s->status = HCRC_STATE; + } + else + s->status = HCRC_STATE; + } + if (s->status == HCRC_STATE) { + if (s->gzhead->hcrc) { + if (s->pending + 2 > s->pending_buf_size) + flush_pending(strm); + if (s->pending + 2 <= s->pending_buf_size) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + strm->adler = crc32(0L, Z_NULL, 0); + s->status = BUSY_STATE; + } + } + else + s->status = BUSY_STATE; + } +#endif + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : + (s->strategy == Z_RLE ? deflate_rle(s, flush) : + (*(configuration_table[s->level].func))(s, flush)); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + if (s->lookahead == 0) { + s->strstart = 0; + s->block_start = 0L; + } + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->wrap <= 0) return Z_STREAM_END; + + /* Write the trailer */ +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); + put_byte(s, (Byte)(strm->total_in & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); + } + else +#endif + { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && + status != EXTRA_STATE && + status != NAME_STATE && + status != COMMENT_STATE && + status != HCRC_STATE && + status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + zmemcpy(dest, source, sizeof(z_stream)); + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + zmemcpy(ds, ss, sizeof(deflate_state)); + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif /* MAXSEG_64K */ +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, strm->next_in, len); + } +#endif + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifndef FASTEST +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +#endif +} + +#ifndef FASTEST +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2. Note that the checks below + * for insufficient lookahead only occur occasionally for performance + * reasons. Therefore uninitialized memory will be accessed, and + * conditional jumps will be made that depend on those values. + * However the length of the match is limited to the lookahead, so + * the output of deflate is not affected by the uninitialized values. + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} +#endif /* ASMV */ + +#else /* FASTEST */ + +/* --------------------------------------------------------------------------- + * Optimized version for FASTEST only + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; +} + +#endif /* FASTEST */ + +#ifdef DEBUG_ZLIB +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif /* DEBUG_ZLIB */ + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); + + /* If the WIN_INIT bytes after the end of the current data have never been + * written, then zero those bytes in order to avoid memory check reports of + * the use of uninitialized (or uninitialised as Julian writes) bytes by + * the longest match routines. Update the high water mark for the next + * time through here. WIN_INIT is set to MAX_MATCH since the longest match + * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. + */ + if (s->high_water < s->window_size) { + ulg curr = s->strstart + (ulg)(s->lookahead); + ulg init; + + if (s->high_water < curr) { + /* Previous high water mark below current data -- zero WIN_INIT + * bytes or up to end of window, whichever is less. + */ + init = s->window_size - curr; + if (init > WIN_INIT) + init = WIN_INIT; + zmemzero(s->window + curr, (unsigned)init); + s->high_water = curr + init; + } + else if (s->high_water < (ulg)curr + WIN_INIT) { + /* High water mark at or above current data, but below current data + * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up + * to end of window, whichever is less. + */ + init = (ulg)curr + WIN_INIT - s->high_water; + if (init > s->window_size - s->high_water) + init = s->window_size - s->high_water; + zmemzero(s->window + s->high_water, (unsigned)init); + s->high_water += init; + } + } +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, last) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (last)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, last) { \ + FLUSH_BLOCK_ONLY(s, last); \ + if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = NIL; + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s->match_length = longest_match (s, hash_head); + /* longest_match() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +#ifndef FASTEST +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = NIL; + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s->match_length = longest_match (s, hash_head); + /* longest_match() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED +#if TOO_FAR <= 32767 + || (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR) +#endif + )) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif /* FASTEST */ + +/* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) + */ +local block_state deflate_rle(s, flush) + deflate_state *s; + int flush; +{ + int bflush; /* set if current block must be flushed */ + uInt prev; /* byte at distance one to match */ + Bytef *scan, *strend; /* scan goes up to strend for length of run */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the longest encodable run. + */ + if (s->lookahead < MAX_MATCH) { + fill_window(s); + if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* See how many times the previous byte repeats */ + s->match_length = 0; + if (s->lookahead >= MIN_MATCH && s->strstart > 0) { + scan = s->window + s->strstart - 1; + prev = *scan; + if (prev == *++scan && prev == *++scan && prev == *++scan) { + strend = s->window + s->strstart + MAX_MATCH; + do { + } while (prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + scan < strend); + s->match_length = MAX_MATCH - (int)(strend - scan); + if (s->match_length > s->lookahead) + s->match_length = s->lookahead; + } + } + + /* Emit match if have run of MIN_MATCH or longer, else emit literal */ + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->strstart - 1, s->match_length); + + _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + s->strstart += s->match_length; + s->match_length = 0; + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. + * (It will be regenerated if this run of deflate switches away from Huffman.) + */ +local block_state deflate_huff(s, flush) + deflate_state *s; + int flush; +{ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we have a literal to write. */ + if (s->lookahead == 0) { + fill_window(s); + if (s->lookahead == 0) { + if (flush == Z_NO_FLUSH) + return need_more; + break; /* flush the current block */ + } + } + + /* Output a literal byte */ + s->match_length = 0; + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} diff --git a/contrib/syslinux-4.02/com32/lib/zlib/deflate.h b/contrib/syslinux-4.02/com32/lib/zlib/deflate.h new file mode 100644 index 0000000..09cf4c4 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/zlib/deflate.h @@ -0,0 +1,342 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2010 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define EXTRA_STATE 69 +#define NAME_STATE 73 +#define COMMENT_STATE 91 +#define HCRC_STATE 103 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + uInt pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + gz_headerp gzhead; /* gzip header information to write */ + uInt gzindex; /* where in extra, name, or comment */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG_ZLIB + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + + ulg high_water; + /* High water mark offset in window for initialized bytes -- bytes above + * this are set to zero in order to avoid memory check warnings when + * longest match routines access bytes past the input. This is then + * updated to the new high water mark. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + +#define WIN_INIT MAX_MATCH +/* Number of bytes after end of data in window to initialize in order to avoid + memory checker errors from longest match routines */ + + /* in trees.c */ +void ZLIB_INTERNAL _tr_init OF((deflate_state *s)); +int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf, + ulg stored_len, int last)); +void ZLIB_INTERNAL _tr_align OF((deflate_state *s)); +void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, + ulg stored_len, int last)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG_ZLIB +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch ZLIB_INTERNAL _length_code[]; + extern uch ZLIB_INTERNAL _dist_code[]; +#else + extern const uch ZLIB_INTERNAL _length_code[]; + extern const uch ZLIB_INTERNAL _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/contrib/syslinux-4.02/com32/lib/zlib/infback.c b/contrib/syslinux-4.02/com32/lib/zlib/infback.c new file mode 100644 index 0000000..af3a8c9 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/zlib/infback.c @@ -0,0 +1,632 @@ +/* infback.c -- inflate using a call-back interface + * Copyright (C) 1995-2009 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + This code is largely copied from inflate.c. Normally either infback.o or + inflate.o would be linked into an application--not both. The interface + with inffast.c is retained so that optimized assembler-coded versions of + inflate_fast() can be used with either inflate.c or infback.c. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); + +/* + strm provides memory allocation functions in zalloc and zfree, or + Z_NULL to use the library memory allocation functions. + + windowBits is in the range 8..15, and window is a user-supplied + window and output buffer that is 2**windowBits bytes. + */ +int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) +z_streamp strm; +int windowBits; +unsigned char FAR *window; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL || window == Z_NULL || + windowBits < 8 || windowBits > 15) + return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *)ZALLOC(strm, 1, + sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->dmax = 32768U; + state->wbits = windowBits; + state->wsize = 1U << windowBits; + state->window = window; + state->wnext = 0; + state->whave = 0; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +/* Macros for inflateBack(): */ + +/* Load returned state from inflate_fast() */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Set state from registers for inflate_fast() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Assure that some input is available. If input is requested, but denied, + then return a Z_BUF_ERROR from inflateBack(). */ +#define PULL() \ + do { \ + if (have == 0) { \ + have = in(in_desc, &next); \ + if (have == 0) { \ + next = Z_NULL; \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflateBack() + with an error if there is no input available. */ +#define PULLBYTE() \ + do { \ + PULL(); \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflateBack() with + an error. */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Assure that some output space is available, by writing out the window + if it's full. If the write fails, return from inflateBack() with a + Z_BUF_ERROR. */ +#define ROOM() \ + do { \ + if (left == 0) { \ + put = state->window; \ + left = state->wsize; \ + state->whave = left; \ + if (out(out_desc, put, left)) { \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* + strm provides the memory allocation functions and window buffer on input, + and provides information on the unused input on return. For Z_DATA_ERROR + returns, strm will also provide an error message. + + in() and out() are the call-back input and output functions. When + inflateBack() needs more input, it calls in(). When inflateBack() has + filled the window with output, or when it completes with data in the + window, it calls out() to write out the data. The application must not + change the provided input until in() is called again or inflateBack() + returns. The application must not change the window/output buffer until + inflateBack() returns. + + in() and out() are called with a descriptor parameter provided in the + inflateBack() call. This parameter can be a structure that provides the + information required to do the read or write, as well as accumulated + information on the input and output such as totals and check values. + + in() should return zero on failure. out() should return non-zero on + failure. If either in() or out() fails, than inflateBack() returns a + Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it + was in() or out() that caused in the error. Otherwise, inflateBack() + returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format + error, or Z_MEM_ERROR if it could not allocate memory for the state. + inflateBack() can also return Z_STREAM_ERROR if the input parameters + are not correct, i.e. strm is Z_NULL or the state was not initialized. + */ +int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) +z_streamp strm; +in_func in; +void FAR *in_desc; +out_func out; +void FAR *out_desc; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + /* Check that the strm exists and that the state was initialized */ + if (strm == Z_NULL || strm->state == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* Reset the state */ + strm->msg = Z_NULL; + state->mode = TYPE; + state->last = 0; + state->whave = 0; + next = strm->next_in; + have = next != Z_NULL ? strm->avail_in : 0; + hold = 0; + bits = 0; + put = state->window; + left = state->wsize; + + /* Inflate until end of block marked as last */ + for (;;) + switch (state->mode) { + case TYPE: + /* determine and dispatch block type */ + if (state->last) { + BYTEBITS(); + state->mode = DONE; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + + case STORED: + /* get and verify stored block length */ + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + + /* copy stored block from input to output */ + while (state->length != 0) { + copy = state->length; + PULL(); + ROOM(); + if (copy > have) copy = have; + if (copy > left) copy = left; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + + case TABLE: + /* get dynamic table entries descriptor */ + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + + /* get code length code lengths (not a typo) */ + state->have = 0; + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + + /* get length and distance code code lengths */ + state->have = 0; + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + NEEDBITS(here.bits); + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } + else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = (unsigned)(state->lens[state->have - 1]); + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + strm->msg = (char *)"invalid code -- missing end-of-block"; + state->mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + + case LEN: + /* use inflate_fast() if we have enough input and output */ + if (have >= 6 && left >= 258) { + RESTORE(); + if (state->whave < state->wsize) + state->whave = state->wsize - left; + inflate_fast(strm, state->wsize); + LOAD(); + break; + } + + /* get a literal, length, or end-of-block code */ + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(here.bits); + state->length = (unsigned)here.val; + + /* process literal */ + if (here.op == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + ROOM(); + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + } + + /* process end of block */ + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + + /* invalid code */ + if (here.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + + /* length code -- get extra bits, if any */ + state->extra = (unsigned)(here.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + + /* get distance code */ + for (;;) { + here = state->distcode[BITS(state->distbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(here.bits); + if (here.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)here.val; + + /* get distance extra bits, if any */ + state->extra = (unsigned)(here.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->wsize - (state->whave < state->wsize ? + left : 0)) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + + /* copy match from window to output */ + do { + ROOM(); + copy = state->wsize - state->offset; + if (copy < left) { + from = put + copy; + copy = left - copy; + } + else { + from = put - state->offset; + copy = left; + } + if (copy > state->length) copy = state->length; + state->length -= copy; + left -= copy; + do { + *put++ = *from++; + } while (--copy); + } while (state->length != 0); + break; + + case DONE: + /* inflate stream terminated properly -- write leftover output */ + ret = Z_STREAM_END; + if (left < state->wsize) { + if (out(out_desc, state->window, state->wsize - left)) + ret = Z_BUF_ERROR; + } + goto inf_leave; + + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + + default: /* can't happen, but makes compilers happy */ + ret = Z_STREAM_ERROR; + goto inf_leave; + } + + /* Return unused input */ + inf_leave: + strm->next_in = next; + strm->avail_in = have; + return ret; +} + +int ZEXPORT inflateBackEnd(strm) +z_streamp strm; +{ + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} diff --git a/contrib/syslinux-4.02/com32/lib/zlib/inffast.c b/contrib/syslinux-4.02/com32/lib/zlib/inffast.c new file mode 100644 index 0000000..2f1d60b --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/zlib/inffast.c @@ -0,0 +1,340 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2008, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifndef ASMINF + +/* Allow machine dependent optimization for post-increment or pre-increment. + Based on testing to date, + Pre-increment preferred for: + - PowerPC G3 (Adler) + - MIPS R5000 (Randers-Pehrson) + Post-increment preferred for: + - none + No measurable difference: + - Pentium III (Anderson) + - M68060 (Nikl) + */ +#ifdef POSTINC +# define OFF 0 +# define PUP(a) *(a)++ +#else +# define OFF 1 +# define PUP(a) *++(a) +#endif + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void ZLIB_INTERNAL inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + unsigned char FAR *in; /* local strm->next_in */ + unsigned char FAR *last; /* while in < last, enough input available */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code here; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + wnext = state->wnext; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + here = lcode[hold & lmask]; + dolen: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op == 0) { /* literal */ + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + PUP(out) = (unsigned char)(here.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + here = dcode[hold & dmask]; + dodist: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state->sane) { + strm->msg = + (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + if (len <= op - whave) { + do { + PUP(out) = 0; + } while (--len); + continue; + } + len -= op - whave; + do { + PUP(out) = 0; + } while (--op > whave); + if (op == 0) { + from = out - dist; + do { + PUP(out) = PUP(from); + } while (--len); + continue; + } +#endif + } + from = window - OFF; + if (wnext == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (wnext < op) { /* wrap around window */ + from += wsize + wnext - op; + op -= wnext; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (wnext < len) { /* some from start of window */ + op = wnext; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += wnext - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } while (len > 2); + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + here = dcode[here.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + here = lcode[here.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and wnext == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/contrib/syslinux-4.02/com32/lib/zlib/inffast.h b/contrib/syslinux-4.02/com32/lib/zlib/inffast.h new file mode 100644 index 0000000..e5c1aa4 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/zlib/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/contrib/syslinux-4.02/com32/lib/zlib/inffixed.h b/contrib/syslinux-4.02/com32/lib/zlib/inffixed.h new file mode 100644 index 0000000..75ed4b5 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/zlib/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/contrib/syslinux-4.02/com32/lib/zlib/inflate.c b/contrib/syslinux-4.02/com32/lib/zlib/inflate.c new file mode 100644 index 0000000..a8431ab --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/zlib/inflate.c @@ -0,0 +1,1480 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common wnext == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, unsigned out)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, + unsigned len)); + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + strm->adler = 1; /* to support ill-conceived Java test suite */ + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->dmax = 32768U; + state->head = Z_NULL; + state->wsize = 0; + state->whave = 0; + state->wnext = 0; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + state->sane = 1; + state->back = -1; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflateReset2(strm, windowBits) +z_streamp strm; +int windowBits; +{ + int wrap; + struct inflate_state FAR *state; + + /* get the state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 1; +#ifdef GUNZIP + if (windowBits < 48) + windowBits &= 15; +#endif + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) + return Z_STREAM_ERROR; + if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { + ZFREE(strm, state->window); + state->window = Z_NULL; + } + + /* update state and reset the rest of it */ + state->wrap = wrap; + state->wbits = (unsigned)windowBits; + return inflateReset(strm); +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + int ret; + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->window = Z_NULL; + ret = inflateReset2(strm, windowBits); + if (ret != Z_OK) { + ZFREE(strm, state); + strm->state = Z_NULL; + } + return ret; +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +int ZEXPORT inflatePrime(strm, bits, value) +z_streamp strm; +int bits; +int value; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (bits < 0) { + state->hold = 0; + state->bits = 0; + return Z_OK; + } + if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += value << state->bits; + state->bits += bits; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include <stdio.h> + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, + state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, out) +z_streamp strm; +unsigned out; +{ + struct inflate_state FAR *state; + unsigned copy, dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->wnext = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + copy = out - strm->avail_out; + if (copy >= state->wsize) { + zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + state->wnext = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->wnext; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->wnext, strm->next_out - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, strm->next_out - copy, copy); + state->wnext = copy; + state->whave = state->wsize; + } + else { + state->wnext += dist; + if (state->wnext == state->wsize) state->wnext = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Reverse the bytes in a 32-bit value */ +#define REVERSE(q) \ + ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (state->head != Z_NULL) + state->head->done = -1; + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (state->wbits == 0) + state->wbits = len; + else if (len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; + if (state->flags & 0x0200) CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL) { + len = state->head->extra_len - state->length; + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->length = 0; + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if (hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = REVERSE(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN_; /* decode codes */ + if (flush == Z_TREES) { + DROPBITS(2); + goto inf_leave; + } + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY_; + if (flush == Z_TREES) goto inf_leave; + case COPY_: + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + NEEDBITS(here.bits); + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } + else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + strm->msg = (char *)"invalid code -- missing end-of-block"; + state->mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN_; + if (flush == Z_TREES) goto inf_leave; + case LEN_: + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + if (state->mode == TYPE) + state->back = -1; + break; + } + state->back = 0; + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + state->length = (unsigned)here.val; + if ((int)(here.op) == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + state->mode = LIT; + break; + } + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->back = -1; + state->mode = TYPE; + break; + } + if (here.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(here.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->was = state->length; + state->mode = DIST; + case DIST: + for (;;) { + here = state->distcode[BITS(state->distbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + if (here.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)here.val; + state->extra = (unsigned)(here.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->whave) { + if (state->sane) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + Trace((stderr, "inflate.c too far\n")); + copy -= state->whave; + if (copy > state->length) copy = state->length; + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = 0; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; +#endif + } + if (copy > state->wnext) { + copy -= state->wnext; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->wnext - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( +#ifdef GUNZIP + state->flags ? hold : +#endif + REVERSE(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) + if (updatewindow(strm, out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0) + + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long id; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary id */ + if (state->mode == DICT) { + id = adler32(0L, Z_NULL, 0); + id = adler32(id, dictionary, dictLength); + if (id != state->check) + return Z_DATA_ERROR; + } + + /* copy dictionary to window */ + if (updatewindow(strm, strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + if (dictLength > state->wsize) { + zmemcpy(state->window, dictionary + dictLength - state->wsize, + state->wsize); + state->whave = state->wsize; + } + else { + zmemcpy(state->window + state->wsize - dictLength, dictionary, + dictLength); + state->whave = dictLength; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +int ZEXPORT inflateGetHeader(strm, head) +z_streamp strm; +gz_headerp head; +{ + struct inflate_state FAR *state; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + unsigned wsize; + + /* check input */ + if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || + source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + zmemcpy(dest, source, sizeof(z_stream)); + zmemcpy(copy, state, sizeof(struct inflate_state)); + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } + copy->window = window; + dest->state = (struct internal_state FAR *)copy; + return Z_OK; +} + +int ZEXPORT inflateUndermine(strm, subvert) +z_streamp strm; +int subvert; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + state->sane = !subvert; +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + return Z_OK; +#else + state->sane = 1; + return Z_DATA_ERROR; +#endif +} + +long ZEXPORT inflateMark(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16; + state = (struct inflate_state FAR *)strm->state; + return ((long)(state->back) << 16) + + (state->mode == COPY ? state->length : + (state->mode == MATCH ? state->was - state->length : 0)); +} diff --git a/contrib/syslinux-4.02/com32/lib/zlib/inflate.h b/contrib/syslinux-4.02/com32/lib/zlib/inflate.h new file mode 100644 index 0000000..95f4986 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/zlib/inflate.h @@ -0,0 +1,122 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2009 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY_, /* i/o: same as COPY below, but only first time in */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN_, /* i: same as LEN below, but only first time in */ + LEN, /* i: waiting for length/lit/eob code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to BAD or MEM on error -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) or (raw) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> + HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + (raw) -> TYPEDO + Read deflate blocks: + TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK + STORED -> COPY_ -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN_ + LEN_ -> LEN + Read deflate codes in fixed or dynamic block: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 10K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ + int sane; /* if false, allow invalid distance too far */ + int back; /* bits back of last unprocessed length/lit */ + unsigned was; /* initial length of match */ +}; diff --git a/contrib/syslinux-4.02/com32/lib/zlib/inftrees.c b/contrib/syslinux-4.02/com32/lib/zlib/inftrees.c new file mode 100644 index 0000000..11e9c52 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/zlib/inftrees.c @@ -0,0 +1,330 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.5 Copyright 1995-2010 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code here; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 195}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)1; + here.val = (unsigned short)0; + *(*table)++ = here; /* make a table to force an error */ + *(*table)++ = here; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if ((type == LENS && used >= ENOUGH_LENS) || + (type == DISTS && used >= ENOUGH_DISTS)) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + here.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + here.op = (unsigned char)0; + here.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + here.op = (unsigned char)(extra[work[sym]]); + here.val = base[work[sym]]; + } + else { + here.op = (unsigned char)(32 + 64); /* end of block */ + here.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = here; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if ((type == LENS && used >= ENOUGH_LENS) || + (type == DISTS && used >= ENOUGH_DISTS)) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)(len - drop); + here.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + here.bits = (unsigned char)len; + } + + /* put invalid code marker in table */ + next[huff >> drop] = here; + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/contrib/syslinux-4.02/com32/lib/zlib/inftrees.h b/contrib/syslinux-4.02/com32/lib/zlib/inftrees.h new file mode 100644 index 0000000..baa53a0 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/zlib/inftrees.h @@ -0,0 +1,62 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of the dynamic table. The maximum number of code structures is + 1444, which is the sum of 852 for literal/length codes and 592 for distance + codes. These values were found by exhaustive searches using the program + examples/enough.c found in the zlib distribtution. The arguments to that + program are the number of symbols, the initial root table size, and the + maximum bit length of a code. "enough 286 9 15" for literal/length codes + returns returns 852, and "enough 30 6 15" for distance codes returns 592. + The initial root table size (9 or 6) is found in the fifth argument of the + inflate_table() calls in inflate.c and infback.c. If the root table size is + changed, then these maximum sizes would be need to be recalculated and + updated. */ +#define ENOUGH_LENS 852 +#define ENOUGH_DISTS 592 +#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) + +/* Type of code to build for inflate_table() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/contrib/syslinux-4.02/com32/lib/zlib/trees.c b/contrib/syslinux-4.02/com32/lib/zlib/trees.c new file mode 100644 index 0000000..d1de3cd --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/zlib/trees.c @@ -0,0 +1,1244 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2010 Jean-loup Gailly + * detect_data_type() function provided freely by Cosmin Truta, 2006 + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id$ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG_ZLIB +# include <ctype.h> +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local int detect_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG_ZLIB +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG_ZLIB */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG_ZLIB +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (ush)value << s->bi_valid; + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= (ush)value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG_ZLIB */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (ush)val << s->bi_valid;\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (ush)(value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG_ZLIB */ + + +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ +#ifdef NO_INIT_GLOBAL_POINTERS + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; +#endif + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1<<extra_lbits[code]); n++) { + _length_code[length++] = (uch)code; + } + } + Assert (length == 256, "tr_static_init: length != 256"); + /* Note that the length 255 (match length 258) can be represented + * in two different ways: code 284 + 5 bits or code 285, so we + * overwrite length_code[255] to use the best encoding: + */ + _length_code[length-1] = (uch)code; + + /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<<extra_dbits[code]); n++) { + _dist_code[dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: dist != 256"); + dist >>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG_ZLIB +# include <stdio.h> +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, + "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void ZLIB_INTERNAL _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG_ZLIB + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if ((unsigned) tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1, + "inconsistent bit counts"); + Tracev((stderr,"\ngen_codes: max_code %d ", max_code)); + + for (n = 0; n <= max_code; n++) { + int len = tree[n].Len; + if (len == 0) continue; + /* Now reverse the bits */ + tree[n].Code = bi_reverse(next_code[len]++, len); + + Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", + n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1)); + } +} + +/* =========================================================================== + * Construct one Huffman tree and assigns the code bit strings and lengths. + * Update the total bit length for the current block. + * IN assertion: the field freq is set for all tree elements. + * OUT assertions: the fields len and code are set to the optimal bit length + * and corresponding code. The length opt_len is updated; static_len is + * also updated if stree is not null. The field max_code is set. + */ +local void build_tree(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? + s->depth[n] : s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int last; /* one if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */ +#ifdef DEBUG_ZLIB + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void ZLIB_INTERNAL _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG_ZLIB + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG_ZLIB + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int last; /* one if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is binary or text */ + if (s->strm->data_type == Z_UNKNOWN) + s->strm->data_type = detect_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, last); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+last, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG_ZLIB + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+last, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG_ZLIB + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (last) { + bi_windup(s); +#ifdef DEBUG_ZLIB + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*last)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int ZLIB_INTERNAL _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Check if the data type is TEXT or BINARY, using the following algorithm: + * - TEXT if the two conditions below are satisfied: + * a) There are no non-portable control characters belonging to the + * "black list" (0..6, 14..25, 28..31). + * b) There is at least one printable character belonging to the + * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). + * - BINARY otherwise. + * - The following partially-portable control characters form a + * "gray list" that is ignored in this detection algorithm: + * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). + * IN assertion: the fields Freq of dyn_ltree are set. + */ +local int detect_data_type(s) + deflate_state *s; +{ + /* black_mask is the bit mask of black-listed bytes + * set bits 0..6, 14..25, and 28..31 + * 0xf3ffc07f = binary 11110011111111111100000001111111 + */ + unsigned long black_mask = 0xf3ffc07fUL; + int n; + + /* Check for non-textual ("black-listed") bytes. */ + for (n = 0; n <= 31; n++, black_mask >>= 1) + if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0)) + return Z_BINARY; + + /* Check for textual ("white-listed") bytes. */ + if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 + || s->dyn_ltree[13].Freq != 0) + return Z_TEXT; + for (n = 32; n < LITERALS; n++) + if (s->dyn_ltree[n].Freq != 0) + return Z_TEXT; + + /* There are no "black-listed" or "white-listed" bytes: + * this stream either is empty or has tolerated ("gray-listed") bytes only. + */ + return Z_BINARY; +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG_ZLIB + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG_ZLIB + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG_ZLIB + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/contrib/syslinux-4.02/com32/lib/zlib/trees.h b/contrib/syslinux-4.02/com32/lib/zlib/trees.h new file mode 100644 index 0000000..d35639d --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/zlib/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/contrib/syslinux-4.02/com32/lib/zlib/uncompr.c b/contrib/syslinux-4.02/com32/lib/zlib/uncompr.c new file mode 100644 index 0000000..ad98be3 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/zlib/uncompr.c @@ -0,0 +1,59 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2003, 2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) + return Z_DATA_ERROR; + return err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} diff --git a/contrib/syslinux-4.02/com32/lib/zlib/zconf.in.h b/contrib/syslinux-4.02/com32/lib/zlib/zconf.in.h new file mode 100644 index 0000000..5d10eaa --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/zlib/zconf.in.h @@ -0,0 +1,322 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflatePrime z_deflatePrime +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table + +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) +# define WIN32 +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include <windows.h> + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include <sys/types.h> /* for off_t */ +# include <unistd.h> /* for SEEK_* and off_t */ +# ifdef VMS +# include <unixio.h> /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +#define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/contrib/syslinux-4.02/com32/lib/zlib/zlib.3 b/contrib/syslinux-4.02/com32/lib/zlib/zlib.3 new file mode 100644 index 0000000..27adc4c --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/zlib/zlib.3 @@ -0,0 +1,151 @@ +.TH ZLIB 3 "19 Apr 2010" +.SH NAME +zlib \- compression/decompression library +.SH SYNOPSIS +[see +.I zlib.h +for full description] +.SH DESCRIPTION +The +.I zlib +library is a general purpose data compression library. +The code is thread safe, assuming that the standard library functions +used are thread safe, such as memory allocation routines. +It provides in-memory compression and decompression functions, +including integrity checks of the uncompressed data. +This version of the library supports only one compression method (deflation) +but other algorithms may be added later +with the same stream interface. +.LP +Compression can be done in a single step if the buffers are large enough +or can be done by repeated calls of the compression function. +In the latter case, +the application must provide more input and/or consume the output +(providing more output space) before each call. +.LP +The library also supports reading and writing files in +.IR gzip (1) +(.gz) format +with an interface similar to that of stdio. +.LP +The library does not install any signal handler. +The decoder checks the consistency of the compressed data, +so the library should never crash even in the case of corrupted input. +.LP +All functions of the compression library are documented in the file +.IR zlib.h . +The distribution source includes examples of use of the library +in the files +.I example.c +and +.IR minigzip.c, +as well as other examples in the +.IR examples/ +directory. +.LP +Changes to this version are documented in the file +.I ChangeLog +that accompanies the source. +.LP +.I zlib +is available in Java using the java.util.zip package: +.IP +http://java.sun.com/developer/technicalArticles/Programming/compression/ +.LP +A Perl interface to +.IR zlib , +written by Paul Marquess (pmqs@cpan.org), +is available at CPAN (Comprehensive Perl Archive Network) sites, +including: +.IP +http://search.cpan.org/~pmqs/IO-Compress-Zlib/ +.LP +A Python interface to +.IR zlib , +written by A.M. Kuchling (amk@magnet.com), +is available in Python 1.5 and later versions: +.IP +http://www.python.org/doc/lib/module-zlib.html +.LP +.I zlib +is built into +.IR tcl: +.IP +http://wiki.tcl.tk/4610 +.LP +An experimental package to read and write files in .zip format, +written on top of +.I zlib +by Gilles Vollant (info@winimage.com), +is available at: +.IP +http://www.winimage.com/zLibDll/minizip.html +and also in the +.I contrib/minizip +directory of the main +.I zlib +source distribution. +.SH "SEE ALSO" +The +.I zlib +web site can be found at: +.IP +http://zlib.net/ +.LP +The data format used by the zlib library is described by RFC +(Request for Comments) 1950 to 1952 in the files: +.IP +http://www.ietf.org/rfc/rfc1950.txt (for the zlib header and trailer format) +.br +http://www.ietf.org/rfc/rfc1951.txt (for the deflate compressed data format) +.br +http://www.ietf.org/rfc/rfc1952.txt (for the gzip header and trailer format) +.LP +Mark Nelson wrote an article about +.I zlib +for the Jan. 1997 issue of Dr. Dobb's Journal; +a copy of the article is available at: +.IP +http://marknelson.us/1997/01/01/zlib-engine/ +.SH "REPORTING PROBLEMS" +Before reporting a problem, +please check the +.I zlib +web site to verify that you have the latest version of +.IR zlib ; +otherwise, +obtain the latest version and see if the problem still exists. +Please read the +.I zlib +FAQ at: +.IP +http://zlib.net/zlib_faq.html +.LP +before asking for help. +Send questions and/or comments to zlib@gzip.org, +or (for the Windows DLL version) to Gilles Vollant (info@winimage.com). +.SH AUTHORS +Version 1.2.5 +Copyright (C) 1995-2010 Jean-loup Gailly (jloup@gzip.org) +and Mark Adler (madler@alumni.caltech.edu). +.LP +This software is provided "as-is," +without any express or implied warranty. +In no event will the authors be held liable for any damages +arising from the use of this software. +See the distribution directory with respect to requirements +governing redistribution. +The deflate format used by +.I zlib +was defined by Phil Katz. +The deflate and +.I zlib +specifications were written by L. Peter Deutsch. +Thanks to all the people who reported problems and suggested various +improvements in +.IR zlib ; +who are too numerous to cite here. +.LP +UNIX manual page by R. P. C. Rodgers, +U.S. National Library of Medicine (rodgers@nlm.nih.gov). +.\" end of man page diff --git a/contrib/syslinux-4.02/com32/lib/zlib/zutil.c b/contrib/syslinux-4.02/com32/lib/zlib/zutil.c new file mode 100644 index 0000000..3ce8976 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/zlib/zutil.c @@ -0,0 +1,318 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2005, 2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +const char * const z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch ((int)(sizeof(uInt))) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch ((int)(sizeof(uLong))) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch ((int)(sizeof(voidpf))) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch ((int)(sizeof(z_off_t))) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef DEBUG_ZLIB + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1L << 16; +#endif +#ifdef NO_GZIP + flags += 1L << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1L << 20; +#endif +#ifdef FASTEST + flags += 1L << 21; +#endif +#ifdef STDC +# ifdef NO_vsnprintf + flags += 1L << 25; +# ifdef HAS_vsprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1L << 26; +# endif +# endif +#else + flags += 1L << 24; +# ifdef NO_snprintf + flags += 1L << 25; +# ifdef HAS_sprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1L << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef DEBUG_ZLIB + +# ifndef verbose +# define verbose 0 +# endif +int ZLIB_INTERNAL z_verbose = verbose; + +void ZLIB_INTERNAL z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. + */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void ZLIB_INTERNAL zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int ZLIB_INTERNAL zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void ZLIB_INTERNAL zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void ZLIB_INTERNAL zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/contrib/syslinux-4.02/com32/lib/zlib/zutil.h b/contrib/syslinux-4.02/com32/lib/zlib/zutil.h new file mode 100644 index 0000000..ac2d73e --- /dev/null +++ b/contrib/syslinux-4.02/com32/lib/zlib/zutil.h @@ -0,0 +1,274 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ) +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif + +#include "zlib.h" + +#ifdef STDC +# if !(defined(_WIN32_WCE) && defined(_MSC_VER)) +# include <stddef.h> +# endif +# include <string.h> +# include <stdlib.h> +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include <alloc.h> +# endif +# else /* MSC or DJGPP */ +# include <malloc.h> +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +# ifdef M_I86 +# include <malloc.h> +# endif +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include <unix.h> /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + +#if defined(__BORLANDC__) + #pragma warn -8004 + #pragma warn -8008 + #pragma warn -8066 +#endif + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS + /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 + /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) +# define vsnprintf _vsnprintf +# endif +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +#endif +#ifdef VMS +# define NO_vsnprintf +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG_ZLIB +# include <stdio.h> + extern int ZLIB_INTERNAL z_verbose; + extern void ZLIB_INTERNAL z_error OF((const char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, + unsigned size)); +void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H */ diff --git a/contrib/syslinux-4.02/com32/libutil/Makefile b/contrib/syslinux-4.02/com32/libutil/Makefile new file mode 100644 index 0000000..02789ca --- /dev/null +++ b/contrib/syslinux-4.02/com32/libutil/Makefile @@ -0,0 +1,65 @@ +## ----------------------------------------------------------------------- +## +## Copyright 2001-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. +## +## ----------------------------------------------------------------------- + +## +## Utility companion library for the COM32 library +## + +topdir = ../.. +include ../MCONFIG + +LIBOBJS = ansiline.o ansiraw.o get_key.o sha1hash.o unbase64.o \ + md5.o crypt-md5.o sha256crypt.o sha512crypt.o base64.o +LNXLIBOBJS = $(patsubst %.o,%.lo,$(LIBOBJS)) + +all: libutil_com.a libutil_lnx.a + +libutil_com.a: $(LIBOBJS) + rm -f $@ + $(AR) cq $@ $(LIBOBJS) + $(RANLIB) $@ + +libutil_lnx.a: $(LNXLIBOBJS) + rm -f $@ + $(AR) cq $@ $(LNXLIBOBJS) + $(RANLIB) $@ + +tidy dist: + rm -f *.o *.lo *.lst *.elf .*.d *.tmp + +clean: tidy + rm -f *.lnx libutil_lnx.a + +spotless: clean + rm -f *.lss *.a *.c32 *.com + rm -f *~ \#* + +install: all + mkdir -m 755 -p $(INSTALLROOT)$(COM32DIR) + install -m 644 libutil_com.a libutil_lnx.a $(INSTALLROOT)$(COM32DIR) + +-include .*.d diff --git a/contrib/syslinux-4.02/com32/libutil/ansiline.c b/contrib/syslinux-4.02/com32/libutil/ansiline.c new file mode 100644 index 0000000..18c7149 --- /dev/null +++ b/contrib/syslinux-4.02/com32/libutil/ansiline.c @@ -0,0 +1,83 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * ansiline.c + * + * Configures the console for ANSI output in line mode; versions + * for COM32 and Linux support. + */ + +#ifdef __COM32__ + +#include <stdio.h> +#include <unistd.h> +#include <console.h> + +void console_ansi_std(void) +{ + openconsole(&dev_stdcon_r, &dev_ansiserial_w); +} + +#else + +#include <stdio.h> +#include <termios.h> + +static struct termios original_termios_settings; + +static void __attribute__ ((constructor)) console_init(void) +{ + tcgetattr(0, &original_termios_settings); +} + +static void __attribute__ ((destructor)) console_cleanup(void) +{ + tcsetattr(0, TCSANOW, &original_termios_settings); +} + +void console_ansi_std(void) +{ + struct termios tio; + + /* Disable stdio buffering */ + setbuf(stdin, NULL); + setbuf(stdout, NULL); + setbuf(stderr, NULL); + + /* Set the termios flag so we behave the same as libcom32 */ + tcgetattr(0, &tio); + tio.c_iflag &= ~ICRNL; + tio.c_iflag |= IGNCR; + tio.c_lflag |= ICANON | ECHO; + if (!tio.c_oflag & OPOST) + tio.c_oflag = 0; + tio.c_oflag |= OPOST | ONLCR; + tcsetattr(0, TCSANOW, &tio); +} + +#endif diff --git a/contrib/syslinux-4.02/com32/libutil/ansiraw.c b/contrib/syslinux-4.02/com32/libutil/ansiraw.c new file mode 100644 index 0000000..2afd48a --- /dev/null +++ b/contrib/syslinux-4.02/com32/libutil/ansiraw.c @@ -0,0 +1,85 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * ansiraw.c + * + * Configures the console for ANSI output in raw mode; versions + * for COM32 and Linux support. + */ + +#ifdef __COM32__ + +#include <stdio.h> +#include <unistd.h> +#include <console.h> + +void console_ansi_raw(void) +{ + openconsole(&dev_rawcon_r, &dev_ansiserial_w); +} + +#else + +#include <stdio.h> +#include <termios.h> + +static struct termios original_termios_settings; + +static void __attribute__ ((constructor)) console_init(void) +{ + tcgetattr(0, &original_termios_settings); +} + +static void __attribute__ ((destructor)) console_cleanup(void) +{ + tcsetattr(0, TCSANOW, &original_termios_settings); +} + +void console_ansi_raw(void) +{ + struct termios tio; + + /* Disable stdio buffering */ + setbuf(stdin, NULL); + setbuf(stdout, NULL); + setbuf(stderr, NULL); + + /* Set the termios flag so we behave the same as libcom32 */ + tcgetattr(0, &tio); + tio.c_iflag &= ~ICRNL; + tio.c_iflag |= IGNCR; + tio.c_lflag &= ~(ISIG | ICANON | ECHO); + if (!tio.c_oflag & OPOST) + tio.c_oflag = 0; + tio.c_oflag |= OPOST | ONLCR; + tio.c_cc[VMIN] = 0; + tio.c_cc[VTIME] = 1; /* Don't 100% busy-wait in Linux */ + tcsetattr(0, TCSAFLUSH, &tio); +} + +#endif diff --git a/contrib/syslinux-4.02/com32/libutil/base64.c b/contrib/syslinux-4.02/com32/libutil/base64.c new file mode 100644 index 0000000..74b101c --- /dev/null +++ b/contrib/syslinux-4.02/com32/libutil/base64.c @@ -0,0 +1,95 @@ +/* + * Output a base64 string. + * + * Options include: + * - Character 62 and 63; + * - To pad or not to pad. + */ + +#include <inttypes.h> +#include <base64.h> + +size_t genbase64(char *output, const void *input, size_t size, int flags) +{ + static char charz[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_"; + uint8_t buf[3]; + int j; + const uint8_t *p; + char *q; + uint32_t bv; + int left = size; + + charz[62] = (char)flags; + charz[63] = (char)(flags >> 8); + + p = input; + q = output; + + while (left > 0) { + if (left < 3) { + buf[0] = p[0]; + buf[1] = (left > 1) ? p[1] : 0; + buf[2] = 0; + p = buf; + } + + bv = (p[0] << 16) | (p[1] << 8) | p[2]; + p += 3; + left -= 3; + + for (j = 0; j < 4; j++) { + *q++ = charz[(bv >> 18) & 0x3f]; + bv <<= 6; + } + } + + switch (left) { + case -1: + if (flags & BASE64_PAD) + q[-1] = '='; + else + q--; + break; + + case -2: + if (flags & BASE64_PAD) + q[-2] = q[-1] = '='; + else + q -= 2; + break; + + default: + break; + } + + *q = '\0'; + + return q - output; +} + +#ifdef TEST + +#include <stdio.h> +#include <string.h> + +int main(int argc, char *argv[]) +{ + int i; + char buf[4096]; + int len, bytes; + + for (i = 1; i < argc; i++) { + printf("Original: \"%s\"\n", argv[i]); + + len = strlen(argv[i]); + bytes = genbase64(buf, argv[i], len, BASE64_MIME | BASE64_PAD); + printf(" MIME: \"%s\" (%d)\n", buf, bytes); + bytes = genbase64(buf, argv[i], len, BASE64_SAFE); + printf(" Safe: \"%s\" (%d)\n", buf, bytes); + } + + return 0; +} + +#endif diff --git a/contrib/syslinux-4.02/com32/libutil/crypt-md5.c b/contrib/syslinux-4.02/com32/libutil/crypt-md5.c new file mode 100644 index 0000000..49e9532 --- /dev/null +++ b/contrib/syslinux-4.02/com32/libutil/crypt-md5.c @@ -0,0 +1,173 @@ +/*- + * Copyright (c) 2003 Poul-Henning Kamp + * All rights reserved. + * + * 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. + * + * 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. + */ + +#include <inttypes.h> +#include <md5.h> +#include <string.h> + +/* + * UNIX password + */ + +static char *_crypt_to64(char *s, uint32_t v, int n) +{ + static const char itoa64[64] = "./0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + + while (--n >= 0) { + *s++ = itoa64[v & 0x3f]; + v >>= 6; + } + return s; +} + +char *crypt_md5(const char *pw, const char *salt) +{ + MD5_CTX ctx, ctx1; + unsigned long l; + int sl, pl; + uint32_t i; + uint8_t final[MD5_SIZE]; + const char *sp; + static char passwd[120]; /* Output buffer */ + static const char magic[] = "$1$"; + char *p; + const int magic_len = sizeof magic - 1; + int pwlen = strlen(pw); + + /* Refine the Salt first */ + sp = salt; + + /* If it starts with the magic string, then skip that */ + if (!strncmp(sp, magic, magic_len)) + sp += magic_len; + + /* Compute the salt length: + it stops at the first '$', max 8 chars */ + for (sl = 0; sl < 8 && sp[sl] && sp[sl] != '$'; sl++) ; + + MD5Init(&ctx); + + /* The password first, since that is what is most unknown */ + MD5Update(&ctx, pw, pwlen); + + /* Then our magic string */ + MD5Update(&ctx, magic, magic_len); + + /* Then the raw salt */ + MD5Update(&ctx, sp, sl); + + /* Then just as many characters of the MD5(pw,salt,pw) */ + MD5Init(&ctx1); + MD5Update(&ctx1, pw, pwlen); + MD5Update(&ctx1, sp, sl); + MD5Update(&ctx1, pw, pwlen); + MD5Final(final, &ctx1); + for (pl = pwlen; pl > 0; pl -= MD5_SIZE) + MD5Update(&ctx, final, pl > MD5_SIZE ? MD5_SIZE : pl); + + /* Don't leave anything around in vm they could use. */ + memset(final, 0, sizeof final); + + /* Then something really weird... */ + for (i = pwlen; i; i >>= 1) + if (i & 1) + MD5Update(&ctx, final, 1); + else + MD5Update(&ctx, pw, 1); + + /* Now make the output string */ + p = passwd; + + memcpy(p, magic, magic_len); + p += magic_len; + + memcpy(p, sp, sl); + p += sl; + + *p++ = '$'; + + MD5Final(final, &ctx); + + /* + * and now, just to make sure things don't run too fast + * On a 60 Mhz Pentium this takes 34 msec, so you would + * need 30 seconds to build a 1000 entry dictionary... + */ + for (i = 0; i < 1000; i++) { + MD5Init(&ctx1); + if (i & 1) + MD5Update(&ctx1, pw, pwlen); + else + MD5Update(&ctx1, final, MD5_SIZE); + + if (i % 3) + MD5Update(&ctx1, sp, sl); + + if (i % 7) + MD5Update(&ctx1, pw, pwlen); + + if (i & 1) + MD5Update(&ctx1, final, MD5_SIZE); + else + MD5Update(&ctx1, pw, pwlen); + MD5Final(final, &ctx1); + } + + l = (final[0] << 16) | (final[6] << 8) | final[12]; + p = _crypt_to64(p, l, 4); + l = (final[1] << 16) | (final[7] << 8) | final[13]; + p = _crypt_to64(p, l, 4); + l = (final[2] << 16) | (final[8] << 8) | final[14]; + p = _crypt_to64(p, l, 4); + l = (final[3] << 16) | (final[9] << 8) | final[15]; + p = _crypt_to64(p, l, 4); + l = (final[4] << 16) | (final[10] << 8) | final[5]; + p = _crypt_to64(p, l, 4); + l = final[11]; + p = _crypt_to64(p, l, 2); + *p = '\0'; + + /* Don't leave anything around in vm they could use. */ + memset(final, 0, sizeof final); + + return passwd; +} + +#ifdef TEST +#include <stdio.h> + +int main(int argc, char *argv[]) +{ + int i; + + for (i = 2; i < argc; i += 2) { + puts(crypt_md5(argv[i], argv[i - 1])); + } + return 0; +} + +#endif diff --git a/contrib/syslinux-4.02/com32/libutil/get_key.c b/contrib/syslinux-4.02/com32/libutil/get_key.c new file mode 100644 index 0000000..f277b43 --- /dev/null +++ b/contrib/syslinux-4.02/com32/libutil/get_key.c @@ -0,0 +1,172 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * get_key.c + * + * Get a single key, and try to pick apart function key codes. + * This doesn't decode anywhere close to all possiblities, but + * hopefully is enough to be useful. + */ + +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <time.h> +#include <sys/times.h> +#include <getkey.h> +#include <libutil.h> + +struct keycode { + int code; + int seqlen; + const unsigned char *seq; +}; + +#define MAXLEN 8 +#define CODE(x,y) { x, (sizeof y)-1, (const unsigned char *)(y) } + +static const struct keycode keycodes[] = { + /* First, the BIOS combined codes */ + CODE(KEY_F1, "\0\x3B"), + CODE(KEY_F2, "\0\x3C"), + CODE(KEY_F3, "\0\x3D"), + CODE(KEY_F4, "\0\x3E"), + CODE(KEY_F5, "\0\x3F"), + CODE(KEY_F6, "\0\x40"), + CODE(KEY_F7, "\0\x41"), + CODE(KEY_F8, "\0\x42"), + CODE(KEY_F9, "\0\x43"), + CODE(KEY_F10, "\0\x44"), + CODE(KEY_F11, "\0\x85"), + CODE(KEY_F12, "\0\x86"), + + CODE(KEY_UP, "\0\x48"), + CODE(KEY_DOWN, "\0\x50"), + CODE(KEY_LEFT, "\0\x4B"), + CODE(KEY_RIGHT, "\0\x4D"), + CODE(KEY_PGUP, "\0\x49"), + CODE(KEY_PGDN, "\0\x51"), + CODE(KEY_HOME, "\0\x47"), + CODE(KEY_END, "\0\x4F"), + CODE(KEY_INSERT, "\0\x52"), + CODE(KEY_DELETE, "\0\x53"), + + /* Now, VT/xterm/Linux codes */ + CODE(KEY_F1, "\033[[A"), + CODE(KEY_F1, "\033OP"), + CODE(KEY_F2, "\033[[B"), + CODE(KEY_F2, "\033OQ"), + CODE(KEY_F3, "\033[[C"), + CODE(KEY_F3, "\033OR"), + CODE(KEY_F4, "\033[[D"), + CODE(KEY_F4, "\033OS"), + CODE(KEY_F5, "\033[[E"), + CODE(KEY_F5, "\033[15~"), + CODE(KEY_F6, "\033[17~"), + CODE(KEY_F7, "\033[18~"), + CODE(KEY_F8, "\033[19~"), + CODE(KEY_F9, "\033[20~"), + CODE(KEY_F10, "\033[21~"), + CODE(KEY_F11, "\033[23~"), + CODE(KEY_F12, "\033[24~"), + + CODE(KEY_UP, "\033[A"), + CODE(KEY_DOWN, "\033[B"), + CODE(KEY_LEFT, "\033[D"), + CODE(KEY_RIGHT, "\033[C"), + CODE(KEY_PGUP, "\033[5~"), + CODE(KEY_PGUP, "\033[V"), + CODE(KEY_PGDN, "\033[6~"), + CODE(KEY_PGDN, "\033[U"), + CODE(KEY_HOME, "\033[1~"), + CODE(KEY_HOME, "\033[H"), + CODE(KEY_END, "\033[4~"), + CODE(KEY_END, "\033[F"), + CODE(KEY_END, "\033OF"), + CODE(KEY_INSERT, "\033[2~"), + CODE(KEY_INSERT, "\033[@"), + CODE(KEY_DELETE, "\033[3~"), +}; + +#define NCODES ((int)(sizeof keycodes/sizeof(struct keycode))) + +#define KEY_TIMEOUT ((CLK_TCK+9)/10) + +int get_key(FILE * f, clock_t timeout) +{ + unsigned char buffer[MAXLEN]; + int nc, i, rv; + const struct keycode *kc; + int another; + unsigned char ch; + clock_t start; + + /* We typically start in the middle of a clock tick */ + if (timeout) + timeout++; + + nc = 0; + start = times(NULL); + do { + rv = read(fileno(f), &ch, 1); + if (rv == 0 || (rv == -1 && errno == EAGAIN)) { + clock_t lateness = times(NULL) - start; + if (nc && lateness > 1 + KEY_TIMEOUT) { + if (nc == 1) + return buffer[0]; /* timeout in sequence */ + else if (timeout && lateness > timeout) + return KEY_NONE; + } else if (!nc && timeout && lateness > timeout) + return KEY_NONE; /* timeout before sequence */ + + do_idle(); + + another = 1; + continue; + } + + start = times(NULL); + + buffer[nc++] = ch; + + another = 0; + for (i = 0, kc = keycodes; i < NCODES; i++, kc++) { + if (nc == kc->seqlen && !memcmp(buffer, kc->seq, nc)) + return kc->code; + else if (nc < kc->seqlen && !memcmp(buffer, kc->seq, nc)) { + another = 1; + break; + } + } + } while (another); + + /* We got an unrecognized sequence; return the first character */ + /* We really should remember this and return subsequent characters later */ + return buffer[0]; +} diff --git a/contrib/syslinux-4.02/com32/libutil/include/base64.h b/contrib/syslinux-4.02/com32/libutil/include/base64.h new file mode 100644 index 0000000..b71855b --- /dev/null +++ b/contrib/syslinux-4.02/com32/libutil/include/base64.h @@ -0,0 +1,51 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2005-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. + * + * ----------------------------------------------------------------------- */ + +/* + * base64.h + * + * Simple routines for handing base64 text + */ + +#ifndef LIBUTIL_BASE64_H +#define LIBUTIL_BASE64_H + +#include <stddef.h> + +#define BASE64_PAD 0x10000 + +/* There is plenty of disagreement w.r.t. the last few characters... */ +#define BASE64_MIME ('+' + ('/' << 8)) +#define BASE64_SAFE ('-' + ('_' << 8)) +#define BASE64_CRYPT ('.' + ('/' << 8)) +#define BASE64_URL ('*' + ('-' << 8)) /* Haven't seen myself */ +#define BASE64_REGEX ('|' + ('-' << 8)) /* Ditto... */ + +size_t genbase64(char *output, const void *digest, size_t size, int flags); +size_t unbase64(unsigned char *, size_t, const char *); + +#endif diff --git a/contrib/syslinux-4.02/com32/libutil/include/consoles.h b/contrib/syslinux-4.02/com32/libutil/include/consoles.h new file mode 100644 index 0000000..07652ed --- /dev/null +++ b/contrib/syslinux-4.02/com32/libutil/include/consoles.h @@ -0,0 +1,40 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * consoles.h + * + * Utility functions for common console configurations + */ + +#ifndef LIBUTIL_CONSOLES_H +#define LIBUTIL_CONSOLES_H + +void console_ansi_std(void); +void console_ansi_raw(void); + +#endif /* LIBUTIL_CONSOLES_H */ diff --git a/contrib/syslinux-4.02/com32/libutil/include/getkey.h b/contrib/syslinux-4.02/com32/libutil/include/getkey.h new file mode 100644 index 0000000..52312a2 --- /dev/null +++ b/contrib/syslinux-4.02/com32/libutil/include/getkey.h @@ -0,0 +1,80 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * getkey.h + * + * Function to get a key symbol and parse it + */ + +#ifndef LIBUTIL_GETKEY_H +#define LIBUTIL_GETKEY_H + +#include <stdio.h> +#include <unistd.h> +#include <sys/times.h> + +#ifndef CLK_TCK +# define CLK_TCK sysconf(_SC_CLK_TCK) +#endif + +#define KEY_NONE (-1) + +#define KEY_CTRL(x) ((x) & 0x001f) +#define KEY_BACKSPACE 0x0008 +#define KEY_TAB 0x0009 +#define KEY_ENTER 0x000d +#define KEY_ESC 0x001b +#define KEY_DEL 0x007f + +#define KEY_F1 0x0100 +#define KEY_F2 0x0101 +#define KEY_F3 0x0102 +#define KEY_F4 0x0103 +#define KEY_F5 0x0104 +#define KEY_F6 0x0105 +#define KEY_F7 0x0106 +#define KEY_F8 0x0107 +#define KEY_F9 0x0108 +#define KEY_F10 0x0109 +#define KEY_F11 0x010A +#define KEY_F12 0x010B + +#define KEY_UP 0x0120 +#define KEY_DOWN 0x0121 +#define KEY_LEFT 0x0122 +#define KEY_RIGHT 0x0123 +#define KEY_PGUP 0x0124 +#define KEY_PGDN 0x0125 +#define KEY_HOME 0x0126 +#define KEY_END 0x0127 +#define KEY_INSERT 0x0128 +#define KEY_DELETE 0x0129 + +int get_key(FILE *, clock_t); + +#endif /* LIBUTIL_GETKEY_H */ diff --git a/contrib/syslinux-4.02/com32/libutil/include/libutil.h b/contrib/syslinux-4.02/com32/libutil/include/libutil.h new file mode 100644 index 0000000..af46a75 --- /dev/null +++ b/contrib/syslinux-4.02/com32/libutil/include/libutil.h @@ -0,0 +1,51 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2005-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. + * + * ----------------------------------------------------------------------- */ + +/* + * libutil.h + * + * Misc libutil functions + */ + +#ifndef LIBUTIL_LIBUTIL_H +#define LIBUTIL_LIBUTIL_H + +#ifdef __COM32__ + +# include <syslinux/idle.h> + +# define do_idle syslinux_idle + +#else /* not __COM32__ */ + +# include <sched.h> + +# define do_idle sched_yield + +#endif + +#endif diff --git a/contrib/syslinux-4.02/com32/libutil/include/md5.h b/contrib/syslinux-4.02/com32/libutil/include/md5.h new file mode 100644 index 0000000..db38c66 --- /dev/null +++ b/contrib/syslinux-4.02/com32/libutil/include/md5.h @@ -0,0 +1,46 @@ +/* MD5.H - header file for MD5C.C + */ + +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. +These notices must be retained in any copies of any part of this +documentation and/or software. + */ + +#ifndef _LIBUTIL_MD5_H +#define _LIBUTIL_MD5_H + +#include <stddef.h> +#include <stdint.h> + +#define MD5_SIZE 16 /* 128 bits */ + +/* MD5 context. */ +typedef struct { + uint32_t state[4]; /* state (ABCD) */ + uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */ + unsigned char buffer[64]; /* input buffer */ +} MD5_CTX; + +void MD5Init(MD5_CTX *); +void MD5Update(MD5_CTX *, const void *, size_t); +void MD5Final(unsigned char[MD5_SIZE], MD5_CTX *); + +char *crypt_md5(const char *, const char *); + +#endif diff --git a/contrib/syslinux-4.02/com32/libutil/include/minmax.h b/contrib/syslinux-4.02/com32/libutil/include/minmax.h new file mode 100644 index 0000000..eb6e39a --- /dev/null +++ b/contrib/syslinux-4.02/com32/libutil/include/minmax.h @@ -0,0 +1,42 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +#ifndef _MINMAX_H +#define _MINMAX_H + +/* + * minmax.h: Type-independent safe min/max macros + */ + +#define min(x,y) ({ __typeof(x) xx = (x); \ + __typeof(y) yy = (y); \ + xx < yy ? xx : yy; }) +#define max(x,y) ({ __typeof(x) xx = (x); \ + __typeof(y) yy = (y); \ + xx > yy ? xx : yy; }) + +#endif /* _MINMAX_H */ diff --git a/contrib/syslinux-4.02/com32/libutil/include/sha1.h b/contrib/syslinux-4.02/com32/libutil/include/sha1.h new file mode 100644 index 0000000..3b35e77 --- /dev/null +++ b/contrib/syslinux-4.02/com32/libutil/include/sha1.h @@ -0,0 +1,18 @@ +#ifndef LIBUTIL_SHA1_H +#define LIBUTIL_SHA1_H + +#include <stdint.h> + +typedef struct { + uint32_t state[5]; + uint32_t count[2]; + unsigned char buffer[64]; +} SHA1_CTX; + +void SHA1Transform(uint32_t state[5], const unsigned char buffer[64]); +void SHA1Init(SHA1_CTX * context); +void SHA1Update(SHA1_CTX * context, const unsigned char *data, uint32_t len); /* + JHB */ +void SHA1Final(unsigned char digest[20], SHA1_CTX * context); + +#endif /* LIBUTIL_SHA1_H */ diff --git a/contrib/syslinux-4.02/com32/libutil/include/xcrypt.h b/contrib/syslinux-4.02/com32/libutil/include/xcrypt.h new file mode 100644 index 0000000..c9ced46 --- /dev/null +++ b/contrib/syslinux-4.02/com32/libutil/include/xcrypt.h @@ -0,0 +1,10 @@ +#ifndef _LIBUTIL_XCRYPT_H +#define _LIBUTIL_XCRYPT_H + +/* Extended crypt() implementations */ + +char *crypt_md5(const char *, const char *); +char *sha256_crypt(const char *, const char *); +char *sha512_crypt(const char *, const char *); + +#endif diff --git a/contrib/syslinux-4.02/com32/libutil/md5.c b/contrib/syslinux-4.02/com32/libutil/md5.c new file mode 100644 index 0000000..bb7e51a --- /dev/null +++ b/contrib/syslinux-4.02/com32/libutil/md5.c @@ -0,0 +1,273 @@ +/* + * MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm + * + * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All + * rights reserved. + * + * License to copy and use this software is granted provided that it + * is identified as the "RSA Data Security, Inc. MD5 Message-Digest + * Algorithm" in all material mentioning or referencing this software + * or this function. + * + * License is also granted to make and use derivative works provided + * that such works are identified as "derived from the RSA Data + * Security, Inc. MD5 Message-Digest Algorithm" in all material + * mentioning or referencing the derived work. + * + * RSA Data Security, Inc. makes no representations concerning either + * the merchantability of this software or the suitability of this + * software for any particular purpose. It is provided "as is" + * without express or implied warranty of any kind. + * + * These notices must be retained in any copies of any part of this + * documentation and/or software. + * + * This code is the same as the code published by RSA Inc. It has been + * edited for clarity and style only. + */ + +#include <string.h> +#include <endian.h> +#include <md5.h> + +static void MD5Transform(uint32_t[4], const unsigned char[64]); + +#define Encode memcpy +#define Decode memcpy + +static unsigned char PADDING[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* F, G, H and I are basic MD5 functions. */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits. */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* + * FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. + * Rotation is separate from addition to prevent recomputation. + */ +#define FF(a, b, c, d, x, s, ac) { \ + (a) += F ((b), (c), (d)) + (x) + (uint32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) { \ + (a) += G ((b), (c), (d)) + (x) + (uint32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) { \ + (a) += H ((b), (c), (d)) + (x) + (uint32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) { \ + (a) += I ((b), (c), (d)) + (x) + (uint32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + +/* MD5 initialization. Begins an MD5 operation, writing a new context. */ + +void MD5Init(MD5_CTX * context) +{ + context->count[0] = context->count[1] = 0; + + /* Load magic initialization constants. */ + context->state[0] = 0x67452301; + context->state[1] = 0xefcdab89; + context->state[2] = 0x98badcfe; + context->state[3] = 0x10325476; +} + +/* + * MD5 block update operation. Continues an MD5 message-digest + * operation, processing another message block, and updating the + * context. + */ + +void MD5Update(MD5_CTX * context, const void *in, size_t inputLen) +{ + unsigned int i, idx, partLen; + const unsigned char *input = in; + + /* Compute number of bytes mod 64 */ + idx = (unsigned int)((context->count[0] >> 3) & 0x3F); + + /* Update number of bits */ + if ((context->count[0] += ((uint32_t) inputLen << 3)) + < ((uint32_t) inputLen << 3)) + context->count[1]++; + context->count[1] += ((uint32_t) inputLen >> 29); + + partLen = 64 - idx; + + /* Transform as many times as possible. */ + if (inputLen >= partLen) { + memcpy((void *)&context->buffer[idx], (const void *)input, partLen); + MD5Transform(context->state, context->buffer); + + for (i = partLen; i + 63 < inputLen; i += 64) + MD5Transform(context->state, &input[i]); + + idx = 0; + } else + i = 0; + + /* Buffer remaining input */ + memcpy((void *)&context->buffer[idx], (const void *)&input[i], + inputLen - i); +} + +/* + * MD5 padding. Adds padding followed by original length. + */ + +static void MD5Pad(MD5_CTX * context) +{ + unsigned char bits[8]; + unsigned int idx, padLen; + + /* Save number of bits */ + Encode(bits, context->count, 8); + + /* Pad out to 56 mod 64. */ + idx = (unsigned int)((context->count[0] >> 3) & 0x3f); + padLen = (idx < 56) ? (56 - idx) : (120 - idx); + MD5Update(context, PADDING, padLen); + + /* Append length (before padding) */ + MD5Update(context, bits, 8); +} + +/* + * MD5 finalization. Ends an MD5 message-digest operation, writing the + * the message digest and zeroizing the context. + */ + +void MD5Final(unsigned char digest[16], MD5_CTX * context) +{ + /* Do padding. */ + MD5Pad(context); + + /* Store state in digest */ + Encode(digest, context->state, 16); + + /* Zeroize sensitive information. */ + memset((void *)context, 0, sizeof(*context)); +} + +/* MD5 basic transformation. Transforms state based on block. */ + +static void MD5Transform(state, block) +uint32_t state[4]; +const unsigned char block[64]; +{ + uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + + Decode(x, block, 64); + + /* Round 1 */ +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 + FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */ + FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */ + FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */ + FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */ + FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */ + FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */ + FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */ + FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */ + FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */ + FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */ + FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 + GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */ + GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */ + GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */ + GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */ + GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */ + GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */ + GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */ + GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */ + GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */ + GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */ + GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 + HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */ + HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */ + HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */ + HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */ + HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */ + HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */ + HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */ + HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */ + HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */ + HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */ + II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */ + II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */ + II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */ + II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */ + II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */ + II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */ + II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */ + II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */ + II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + /* Zeroize sensitive information. */ + memset((void *)x, 0, sizeof(x)); +} diff --git a/contrib/syslinux-4.02/com32/libutil/sha1hash.c b/contrib/syslinux-4.02/com32/libutil/sha1hash.c new file mode 100644 index 0000000..3379693 --- /dev/null +++ b/contrib/syslinux-4.02/com32/libutil/sha1hash.c @@ -0,0 +1,364 @@ +/* +SHA-1 in C +By Steve Reid <sreid@sea-to-sky.net> +100% Public Domain + +----------------- +Modified 7/98 +By James H. Brown <jbrown@burgoyne.com> +Still 100% Public Domain + +Corrected a problem which generated improper hash values on 16 bit machines +Routine SHA1Update changed from + void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int +len) +to + void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned +long len) + +The 'len' parameter was declared an int which works fine on 32 bit machines. +However, on 16 bit machines an int is too small for the shifts being done +against +it. This caused the hash function to generate incorrect values if len was +greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update(). + +Since the file IO in main() reads 16K at a time, any file 8K or larger would +be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million +"a"s). + +I also changed the declaration of variables i & j in SHA1Update to +unsigned long from unsigned int for the same reason. + +These changes should make no difference to any 32 bit implementations since +an +int and a long are the same size in those environments. + +-- +I also corrected a few compiler warnings generated by Borland C. +1. Added #include <process.h> for exit() prototype +2. Removed unused variable 'j' in SHA1Final +3. Changed exit(0) to return(0) at end of main. + +ALL changes I made can be located by searching for comments containing 'JHB' +----------------- +Modified 8/98 +By Steve Reid <sreid@sea-to-sky.net> +Still 100% public domain + +1- Removed #include <process.h> and used return() instead of exit() +2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall) +3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net + +----------------- +Modified 4/01 +By Saul Kravitz <Saul.Kravitz@celera.com> +Still 100% PD +Modified to run on Compaq Alpha hardware. + +----------------- +Modified 2/03 +By H. Peter Anvin <hpa@zytor.com> +Still 100% PD +Modified to run on any hardware with <inttypes.h> and <netinet/in.h> +Changed the driver program + +*/ + +/* +Test Vectors (from FIPS PUB 180-1) +"abc" + A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D +"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 +A million repetitions of "a" + 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F +*/ + +/* #define SHA1HANDSOFF */ + +#include <stdio.h> +#include <string.h> +#include <inttypes.h> +#include <netinet/in.h> /* For htonl/ntohl/htons/ntohs */ + +#include "sha1.h" + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ +#define blk0(i) (block->l[i] = ntohl(block->l[i])) +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15],1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + +#ifdef VERBOSE /* SAK */ +void SHAPrintContext(SHA1_CTX * context, char *msg) +{ + printf("%s (%d,%d) %x %x %x %x %x\n", + msg, + context->count[0], context->count[1], + context->state[0], + context->state[1], + context->state[2], context->state[3], context->state[4]); +} +#endif + +/* Hash a single 512-bit block. This is the core of the algorithm. */ + +void SHA1Transform(uint32_t state[5], const unsigned char buffer[64]) +{ + uint32_t a, b, c, d, e; + typedef union { + unsigned char c[64]; + uint32_t l[16]; + } CHAR64LONG16; + CHAR64LONG16 *block; +#ifdef SHA1HANDSOFF + static unsigned char workspace[64]; + block = (CHAR64LONG16 *) workspace; + memcpy(block, buffer, 64); +#else + block = (CHAR64LONG16 *) buffer; +#endif + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a, b, c, d, e, 0); + R0(e, a, b, c, d, 1); + R0(d, e, a, b, c, 2); + R0(c, d, e, a, b, 3); + R0(b, c, d, e, a, 4); + R0(a, b, c, d, e, 5); + R0(e, a, b, c, d, 6); + R0(d, e, a, b, c, 7); + R0(c, d, e, a, b, 8); + R0(b, c, d, e, a, 9); + R0(a, b, c, d, e, 10); + R0(e, a, b, c, d, 11); + R0(d, e, a, b, c, 12); + R0(c, d, e, a, b, 13); + R0(b, c, d, e, a, 14); + R0(a, b, c, d, e, 15); + R1(e, a, b, c, d, 16); + R1(d, e, a, b, c, 17); + R1(c, d, e, a, b, 18); + R1(b, c, d, e, a, 19); + R2(a, b, c, d, e, 20); + R2(e, a, b, c, d, 21); + R2(d, e, a, b, c, 22); + R2(c, d, e, a, b, 23); + R2(b, c, d, e, a, 24); + R2(a, b, c, d, e, 25); + R2(e, a, b, c, d, 26); + R2(d, e, a, b, c, 27); + R2(c, d, e, a, b, 28); + R2(b, c, d, e, a, 29); + R2(a, b, c, d, e, 30); + R2(e, a, b, c, d, 31); + R2(d, e, a, b, c, 32); + R2(c, d, e, a, b, 33); + R2(b, c, d, e, a, 34); + R2(a, b, c, d, e, 35); + R2(e, a, b, c, d, 36); + R2(d, e, a, b, c, 37); + R2(c, d, e, a, b, 38); + R2(b, c, d, e, a, 39); + R3(a, b, c, d, e, 40); + R3(e, a, b, c, d, 41); + R3(d, e, a, b, c, 42); + R3(c, d, e, a, b, 43); + R3(b, c, d, e, a, 44); + R3(a, b, c, d, e, 45); + R3(e, a, b, c, d, 46); + R3(d, e, a, b, c, 47); + R3(c, d, e, a, b, 48); + R3(b, c, d, e, a, 49); + R3(a, b, c, d, e, 50); + R3(e, a, b, c, d, 51); + R3(d, e, a, b, c, 52); + R3(c, d, e, a, b, 53); + R3(b, c, d, e, a, 54); + R3(a, b, c, d, e, 55); + R3(e, a, b, c, d, 56); + R3(d, e, a, b, c, 57); + R3(c, d, e, a, b, 58); + R3(b, c, d, e, a, 59); + R4(a, b, c, d, e, 60); + R4(e, a, b, c, d, 61); + R4(d, e, a, b, c, 62); + R4(c, d, e, a, b, 63); + R4(b, c, d, e, a, 64); + R4(a, b, c, d, e, 65); + R4(e, a, b, c, d, 66); + R4(d, e, a, b, c, 67); + R4(c, d, e, a, b, 68); + R4(b, c, d, e, a, 69); + R4(a, b, c, d, e, 70); + R4(e, a, b, c, d, 71); + R4(d, e, a, b, c, 72); + R4(c, d, e, a, b, 73); + R4(b, c, d, e, a, 74); + R4(a, b, c, d, e, 75); + R4(e, a, b, c, d, 76); + R4(d, e, a, b, c, 77); + R4(c, d, e, a, b, 78); + R4(b, c, d, e, a, 79); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; +} + +/* SHA1Init - Initialize new context */ + +void SHA1Init(SHA1_CTX * context) +{ + /* SHA1 initialization constants */ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} + +/* Run your data through this. */ + +void SHA1Update(SHA1_CTX * context, const unsigned char *data, uint32_t len) +{ /* + JHB */ + uint32_t i, j; /* JHB */ + +#ifdef VERBOSE + SHAPrintContext(context, "before"); +#endif + j = (context->count[0] >> 3) & 63; + if ((context->count[0] += len << 3) < (len << 3)) + context->count[1]++; + context->count[1] += (len >> 29); + if ((j + len) > 63) { + memcpy(&context->buffer[j], data, (i = 64 - j)); + SHA1Transform(context->state, context->buffer); + for (; i + 63 < len; i += 64) { + SHA1Transform(context->state, &data[i]); + } + j = 0; + } else + i = 0; + memcpy(&context->buffer[j], &data[i], len - i); +#ifdef VERBOSE + SHAPrintContext(context, "after "); +#endif +} + +/* Add padding and return the message digest. */ + +void SHA1Final(unsigned char digest[20], SHA1_CTX * context) +{ + uint32_t i; /* JHB */ + unsigned char finalcount[8]; + + for (i = 0; i < 8; i++) { + finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] + >> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */ + } + SHA1Update(context, (unsigned char *)"\200", 1); + while ((context->count[0] & 504) != 448) { + SHA1Update(context, (unsigned char *)"\0", 1); + } + SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() + */ + for (i = 0; i < 20; i++) { + digest[i] = (unsigned char) + ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); + } + /* Wipe variables */ + i = 0; /* JHB */ + memset(context->buffer, 0, 64); + memset(context->state, 0, 20); + memset(context->count, 0, 8); + memset(finalcount, 0, 8); /* SWR */ +#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */ + SHA1Transform(context->state, context->buffer); +#endif +} + +/*************************************************************/ + +/* This is not quite the MIME base64 algorithm: it uses _ instead of /, + and instead of padding the output with = characters we just make the + output shorter. */ +char *mybase64(uint8_t digest[20]) +{ + static const char charz[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_"; + uint8_t input[21]; + static char output[28]; + int i, j; + uint8_t *p; + char *q; + uint32_t bv; + + memcpy(input, digest, 20); + input[20] = 0; /* Pad to multiple of 3 bytes */ + + p = input; + q = output; + for (i = 0; i < 7; i++) { + bv = (p[0] << 16) | (p[1] << 8) | p[2]; + p += 3; + for (j = 0; j < 4; j++) { + *q++ = charz[(bv >> 18) & 0x3f]; + bv <<= 6; + } + } + *--q = '\0'; /* The last character is not significant */ + return output; +} + +#ifdef FOR_TESTING_ONLY + +int main(int argc, char **argv) +{ + int i; + SHA1_CTX context; + uint8_t digest[20], buffer[16384]; + FILE *file; + + if (argc < 2) { + file = stdin; + } else { + if (!(file = fopen(argv[1], "rb"))) { + fputs("Unable to open file.", stderr); + return (-1); + } + } + SHA1Init(&context); + while (!feof(file)) { /* note: what if ferror(file) */ + i = fread(buffer, 1, 16384, file); + SHA1Update(&context, buffer, i); + } + SHA1Final(digest, &context); + fclose(file); + + puts(mybase64(digest)); + + return 0; +} + +#endif diff --git a/contrib/syslinux-4.02/com32/libutil/sha256crypt.c b/contrib/syslinux-4.02/com32/libutil/sha256crypt.c new file mode 100644 index 0000000..adc7b09 --- /dev/null +++ b/contrib/syslinux-4.02/com32/libutil/sha256crypt.c @@ -0,0 +1,680 @@ +/* SHA256-based Unix crypt implementation. + Released into the Public Domain by Ulrich Drepper <drepper@redhat.com>. */ + +#include <alloca.h> +#include <endian.h> +#include <errno.h> +#include <limits.h> +#include <stdint.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <minmax.h> +#include <sys/types.h> + +#include "xcrypt.h" + +#define MIN(x,y) min(x,y) +#define MAX(x,y) max(x,y) + +/* Structure to save state of computation between the single steps. */ +struct sha256_ctx { + uint32_t H[8]; + + uint32_t total[2]; + uint32_t buflen; + char buffer[128]; /* NB: always correctly aligned for uint32_t. */ +}; + +#if __BYTE_ORDER == __LITTLE_ENDIAN +# define SWAP(n) \ + (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) +#else +# define SWAP(n) (n) +#endif + +/* This array contains the bytes used to pad the buffer to the next + 64-byte boundary. (FIPS 180-2:5.1.1) */ +static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; + +/* Constants for SHA256 from FIPS 180-2:4.2.2. */ +static const uint32_t K[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +/* Process LEN bytes of BUFFER, accumulating context into CTX. + It is assumed that LEN % 64 == 0. */ +static void +sha256_process_block(const void *buffer, size_t len, struct sha256_ctx *ctx) +{ + unsigned int t; + const uint32_t *words = buffer; + size_t nwords = len / sizeof(uint32_t); + uint32_t a = ctx->H[0]; + uint32_t b = ctx->H[1]; + uint32_t c = ctx->H[2]; + uint32_t d = ctx->H[3]; + uint32_t e = ctx->H[4]; + uint32_t f = ctx->H[5]; + uint32_t g = ctx->H[6]; + uint32_t h = ctx->H[7]; + + /* First increment the byte count. FIPS 180-2 specifies the possible + length of the file up to 2^64 bits. Here we only compute the + number of bytes. Do a double word increment. */ + ctx->total[0] += len; + if (ctx->total[0] < len) + ++ctx->total[1]; + + /* Process all bytes in the buffer with 64 bytes in each round of + the loop. */ + while (nwords > 0) { + uint32_t W[64]; + uint32_t a_save = a; + uint32_t b_save = b; + uint32_t c_save = c; + uint32_t d_save = d; + uint32_t e_save = e; + uint32_t f_save = f; + uint32_t g_save = g; + uint32_t h_save = h; + + /* Operators defined in FIPS 180-2:4.1.2. */ +#define Ch(x, y, z) ((x & y) ^ (~x & z)) +#define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z)) +#define S0(x) (CYCLIC (x, 2) ^ CYCLIC (x, 13) ^ CYCLIC (x, 22)) +#define S1(x) (CYCLIC (x, 6) ^ CYCLIC (x, 11) ^ CYCLIC (x, 25)) +#define R0(x) (CYCLIC (x, 7) ^ CYCLIC (x, 18) ^ (x >> 3)) +#define R1(x) (CYCLIC (x, 17) ^ CYCLIC (x, 19) ^ (x >> 10)) + + /* It is unfortunate that C does not provide an operator for + cyclic rotation. Hope the C compiler is smart enough. */ +#define CYCLIC(w, s) ((w >> s) | (w << (32 - s))) + + /* Compute the message schedule according to FIPS 180-2:6.2.2 step 2. */ + for (t = 0; t < 16; ++t) { + W[t] = SWAP(*words); + ++words; + } + for (t = 16; t < 64; ++t) + W[t] = R1(W[t - 2]) + W[t - 7] + R0(W[t - 15]) + W[t - 16]; + + /* The actual computation according to FIPS 180-2:6.2.2 step 3. */ + for (t = 0; t < 64; ++t) { + uint32_t T1 = h + S1(e) + Ch(e, f, g) + K[t] + W[t]; + uint32_t T2 = S0(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + } + + /* Add the starting values of the context according to FIPS 180-2:6.2.2 + step 4. */ + a += a_save; + b += b_save; + c += c_save; + d += d_save; + e += e_save; + f += f_save; + g += g_save; + h += h_save; + + /* Prepare for the next round. */ + nwords -= 16; + } + + /* Put checksum in context given as argument. */ + ctx->H[0] = a; + ctx->H[1] = b; + ctx->H[2] = c; + ctx->H[3] = d; + ctx->H[4] = e; + ctx->H[5] = f; + ctx->H[6] = g; + ctx->H[7] = h; +} + +/* Initialize structure containing state of computation. + (FIPS 180-2:5.3.2) */ +static void sha256_init_ctx(struct sha256_ctx *ctx) +{ + ctx->H[0] = 0x6a09e667; + ctx->H[1] = 0xbb67ae85; + ctx->H[2] = 0x3c6ef372; + ctx->H[3] = 0xa54ff53a; + ctx->H[4] = 0x510e527f; + ctx->H[5] = 0x9b05688c; + ctx->H[6] = 0x1f83d9ab; + ctx->H[7] = 0x5be0cd19; + + ctx->total[0] = ctx->total[1] = 0; + ctx->buflen = 0; +} + +/* Process the remaining bytes in the internal buffer and the usual + prolog according to the standard and write the result to RESBUF. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +static void *sha256_finish_ctx(struct sha256_ctx *ctx, void *resbuf) +{ + unsigned int i; + /* Take yet unprocessed bytes into account. */ + uint32_t bytes = ctx->buflen; + size_t pad; + + /* Now count remaining bytes. */ + ctx->total[0] += bytes; + if (ctx->total[0] < bytes) + ++ctx->total[1]; + + pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; + memcpy(&ctx->buffer[bytes], fillbuf, pad); + + /* Put the 64-bit file length in *bits* at the end of the buffer. */ + *(uint32_t *) & ctx->buffer[bytes + pad + 4] = SWAP(ctx->total[0] << 3); + *(uint32_t *) & ctx->buffer[bytes + pad] = SWAP((ctx->total[1] << 3) | + (ctx->total[0] >> 29)); + + /* Process last bytes. */ + sha256_process_block(ctx->buffer, bytes + pad + 8, ctx); + + /* Put result from CTX in first 32 bytes following RESBUF. */ + for (i = 0; i < 8; ++i) + ((uint32_t *) resbuf)[i] = SWAP(ctx->H[i]); + + return resbuf; +} + +static void +sha256_process_bytes(const void *buffer, size_t len, struct sha256_ctx *ctx) +{ + /* When we already have some bits in our internal buffer concatenate + both inputs first. */ + if (ctx->buflen != 0) { + size_t left_over = ctx->buflen; + size_t add = 128 - left_over > len ? len : 128 - left_over; + + memcpy(&ctx->buffer[left_over], buffer, add); + ctx->buflen += add; + + if (ctx->buflen > 64) { + sha256_process_block(ctx->buffer, ctx->buflen & ~63, ctx); + + ctx->buflen &= 63; + /* The regions in the following copy operation cannot overlap. */ + memcpy(ctx->buffer, &ctx->buffer[(left_over + add) & ~63], + ctx->buflen); + } + + buffer = (const char *)buffer + add; + len -= add; + } + + /* Process available complete blocks. */ + if (len >= 64) { +/* To check alignment gcc has an appropriate operator. Other + compilers don't. */ +#if __GNUC__ >= 2 +# define UNALIGNED_P(p) (((uintptr_t) p) % __alignof__ (uint32_t) != 0) +#else +# define UNALIGNED_P(p) (((uintptr_t) p) % sizeof (uint32_t) != 0) +#endif + if (UNALIGNED_P(buffer)) + while (len > 64) { + sha256_process_block(memcpy(ctx->buffer, buffer, 64), 64, ctx); + buffer = (const char *)buffer + 64; + len -= 64; + } else { + sha256_process_block(buffer, len & ~63, ctx); + buffer = (const char *)buffer + (len & ~63); + len &= 63; + } + } + + /* Move remaining bytes into internal buffer. */ + if (len > 0) { + size_t left_over = ctx->buflen; + + memcpy(&ctx->buffer[left_over], buffer, len); + left_over += len; + if (left_over >= 64) { + sha256_process_block(ctx->buffer, 64, ctx); + left_over -= 64; + memcpy(ctx->buffer, &ctx->buffer[64], left_over); + } + ctx->buflen = left_over; + } +} + +/* Define our magic string to mark salt for SHA256 "encryption" + replacement. */ +static const char sha256_salt_prefix[] = "$5$"; + +/* Prefix for optional rounds specification. */ +static const char sha256_rounds_prefix[] = "rounds="; + +/* Maximum salt string length. */ +#define SALT_LEN_MAX 16U +/* Default number of rounds if not explicitly specified. */ +#define ROUNDS_DEFAULT 5000UL +/* Minimum number of rounds. */ +#define ROUNDS_MIN 1000UL +/* Maximum number of rounds. */ +#define ROUNDS_MAX 999999999UL + +/* Table with characters for base64 transformation. */ +static const char b64t[64] = + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +static char *sha256_crypt_r(const char *key, const char *salt, char *buffer, + int buflen) +{ + unsigned char alt_result[32] + __attribute__ ((__aligned__(__alignof__(uint32_t)))); + unsigned char temp_result[32] + __attribute__ ((__aligned__(__alignof__(uint32_t)))); + struct sha256_ctx ctx; + struct sha256_ctx alt_ctx; + size_t salt_len; + size_t key_len; + size_t cnt; + char *cp; + char *copied_key = NULL; + char *copied_salt = NULL; + char *p_bytes; + char *s_bytes; + /* Default number of rounds. */ + size_t rounds = ROUNDS_DEFAULT; + bool rounds_custom = false; + + /* Find beginning of salt string. The prefix should normally always + be present. Just in case it is not. */ + if (strncmp(sha256_salt_prefix, salt, sizeof(sha256_salt_prefix) - 1) == 0) + /* Skip salt prefix. */ + salt += sizeof(sha256_salt_prefix) - 1; + + if (strncmp(salt, sha256_rounds_prefix, sizeof(sha256_rounds_prefix) - 1) + == 0) { + const char *num = salt + sizeof(sha256_rounds_prefix) - 1; + char *endp; + unsigned long int srounds = strtoul(num, &endp, 10); + if (*endp == '$') { + salt = endp + 1; + rounds = MAX(ROUNDS_MIN, MIN(srounds, ROUNDS_MAX)); + rounds_custom = true; + } + } + + salt_len = MIN(strcspn(salt, "$"), SALT_LEN_MAX); + key_len = strlen(key); + + if ((key - (char *)0) % __alignof__(uint32_t) != 0) { + char *tmp = (char *)alloca(key_len + __alignof__(uint32_t)); + key = copied_key = memcpy(tmp + __alignof__(uint32_t) + - (tmp - (char *)0) % __alignof__(uint32_t), + key, key_len); + } + + if ((salt - (char *)0) % __alignof__(uint32_t) != 0) { + char *tmp = (char *)alloca(salt_len + __alignof__(uint32_t)); + salt = copied_salt = memcpy(tmp + __alignof__(uint32_t) + - (tmp - (char *)0) % __alignof__(uint32_t), + salt, salt_len); + } + + /* Prepare for the real work. */ + sha256_init_ctx(&ctx); + + /* Add the key string. */ + sha256_process_bytes(key, key_len, &ctx); + + /* The last part is the salt string. This must be at most 8 + characters and it ends at the first `$' character (for + compatibility with existing implementations). */ + sha256_process_bytes(salt, salt_len, &ctx); + + /* Compute alternate SHA256 sum with input KEY, SALT, and KEY. The + final result will be added to the first context. */ + sha256_init_ctx(&alt_ctx); + + /* Add key. */ + sha256_process_bytes(key, key_len, &alt_ctx); + + /* Add salt. */ + sha256_process_bytes(salt, salt_len, &alt_ctx); + + /* Add key again. */ + sha256_process_bytes(key, key_len, &alt_ctx); + + /* Now get result of this (32 bytes) and add it to the other + context. */ + sha256_finish_ctx(&alt_ctx, alt_result); + + /* Add for any character in the key one byte of the alternate sum. */ + for (cnt = key_len; cnt > 32; cnt -= 32) + sha256_process_bytes(alt_result, 32, &ctx); + sha256_process_bytes(alt_result, cnt, &ctx); + + /* Take the binary representation of the length of the key and for every + 1 add the alternate sum, for every 0 the key. */ + for (cnt = key_len; cnt; cnt >>= 1) + if ((cnt & 1) != 0) + sha256_process_bytes(alt_result, 32, &ctx); + else + sha256_process_bytes(key, key_len, &ctx); + + /* Create intermediate result. */ + sha256_finish_ctx(&ctx, alt_result); + + /* Start computation of P byte sequence. */ + sha256_init_ctx(&alt_ctx); + + /* For every character in the password add the entire password. */ + for (cnt = 0; cnt < key_len; ++cnt) + sha256_process_bytes(key, key_len, &alt_ctx); + + /* Finish the digest. */ + sha256_finish_ctx(&alt_ctx, temp_result); + + /* Create byte sequence P. */ + cp = p_bytes = alloca(key_len); + for (cnt = key_len; cnt >= 32; cnt -= 32) + cp = mempcpy(cp, temp_result, 32); + memcpy(cp, temp_result, cnt); + + /* Start computation of S byte sequence. */ + sha256_init_ctx(&alt_ctx); + + /* For every character in the password add the entire password. */ + for (cnt = 0; cnt < (size_t)16 + alt_result[0]; ++cnt) + sha256_process_bytes(salt, salt_len, &alt_ctx); + + /* Finish the digest. */ + sha256_finish_ctx(&alt_ctx, temp_result); + + /* Create byte sequence S. */ + cp = s_bytes = alloca(salt_len); + for (cnt = salt_len; cnt >= 32; cnt -= 32) + cp = mempcpy(cp, temp_result, 32); + memcpy(cp, temp_result, cnt); + + /* Repeatedly run the collected hash value through SHA256 to burn + CPU cycles. */ + for (cnt = 0; cnt < rounds; ++cnt) { + /* New context. */ + sha256_init_ctx(&ctx); + + /* Add key or last result. */ + if ((cnt & 1) != 0) + sha256_process_bytes(p_bytes, key_len, &ctx); + else + sha256_process_bytes(alt_result, 32, &ctx); + + /* Add salt for numbers not divisible by 3. */ + if (cnt % 3 != 0) + sha256_process_bytes(s_bytes, salt_len, &ctx); + + /* Add key for numbers not divisible by 7. */ + if (cnt % 7 != 0) + sha256_process_bytes(p_bytes, key_len, &ctx); + + /* Add key or last result. */ + if ((cnt & 1) != 0) + sha256_process_bytes(alt_result, 32, &ctx); + else + sha256_process_bytes(p_bytes, key_len, &ctx); + + /* Create intermediate result. */ + sha256_finish_ctx(&ctx, alt_result); + } + + /* Now we can construct the result string. It consists of three + parts. */ + cp = stpncpy(buffer, sha256_salt_prefix, MAX(0, buflen)); + buflen -= sizeof(sha256_salt_prefix) - 1; + + if (rounds_custom) { + int n = snprintf(cp, MAX(0, buflen), "%s%zu$", + sha256_rounds_prefix, rounds); + cp += n; + buflen -= n; + } + + cp = stpncpy(cp, salt, MIN((size_t) MAX(0, buflen), salt_len)); + buflen -= MIN((size_t) MAX(0, buflen), salt_len); + + if (buflen > 0) { + *cp++ = '$'; + --buflen; + } +#define b64_from_24bit(B2, B1, B0, N) \ + do { \ + unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0); \ + int n = (N); \ + while (n-- > 0 && buflen > 0) \ + { \ + *cp++ = b64t[w & 0x3f]; \ + --buflen; \ + w >>= 6; \ + } \ + } while (0) + + b64_from_24bit(alt_result[0], alt_result[10], alt_result[20], 4); + b64_from_24bit(alt_result[21], alt_result[1], alt_result[11], 4); + b64_from_24bit(alt_result[12], alt_result[22], alt_result[2], 4); + b64_from_24bit(alt_result[3], alt_result[13], alt_result[23], 4); + b64_from_24bit(alt_result[24], alt_result[4], alt_result[14], 4); + b64_from_24bit(alt_result[15], alt_result[25], alt_result[5], 4); + b64_from_24bit(alt_result[6], alt_result[16], alt_result[26], 4); + b64_from_24bit(alt_result[27], alt_result[7], alt_result[17], 4); + b64_from_24bit(alt_result[18], alt_result[28], alt_result[8], 4); + b64_from_24bit(alt_result[9], alt_result[19], alt_result[29], 4); + b64_from_24bit(0, alt_result[31], alt_result[30], 3); + if (buflen <= 0) { + errno = ERANGE; + buffer = NULL; + } else + *cp = '\0'; /* Terminate the string. */ + + /* Clear the buffer for the intermediate result so that people + attaching to processes or reading core dumps cannot get any + information. We do it in this way to clear correct_words[] + inside the SHA256 implementation as well. */ + sha256_init_ctx(&ctx); + sha256_finish_ctx(&ctx, alt_result); + memset(temp_result, '\0', sizeof(temp_result)); + memset(p_bytes, '\0', key_len); + memset(s_bytes, '\0', salt_len); + memset(&ctx, '\0', sizeof(ctx)); + memset(&alt_ctx, '\0', sizeof(alt_ctx)); + if (copied_key != NULL) + memset(copied_key, '\0', key_len); + if (copied_salt != NULL) + memset(copied_salt, '\0', salt_len); + + return buffer; +} + +/* This entry point is equivalent to the `crypt' function in Unix + libcs. */ +char *sha256_crypt(const char *key, const char *salt) +{ + /* We don't want to have an arbitrary limit in the size of the + password. We can compute an upper bound for the size of the + result in advance and so we can prepare the buffer we pass to + `sha256_crypt_r'. */ + static char *buffer; + static int buflen; + int needed = (sizeof(sha256_salt_prefix) - 1 + + sizeof(sha256_rounds_prefix) + 9 + 1 + + strlen(salt) + 1 + 43 + 1); + + if (buflen < needed) { + char *new_buffer = (char *)realloc(buffer, needed); + if (new_buffer == NULL) + return NULL; + + buffer = new_buffer; + buflen = needed; + } + + return sha256_crypt_r(key, salt, buffer, buflen); +} + +#ifdef TEST +static const struct { + const char *input; + const char result[32]; +} tests[] = { + /* Test vectors from FIPS 180-2: appendix B.1. */ + { + "abc", + "\xba\x78\x16\xbf\x8f\x01\xcf\xea\x41\x41\x40\xde\x5d\xae\x22\x23" + "\xb0\x03\x61\xa3\x96\x17\x7a\x9c\xb4\x10\xff\x61\xf2\x00\x15\xad"}, + /* Test vectors from FIPS 180-2: appendix B.2. */ + { + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "\x24\x8d\x6a\x61\xd2\x06\x38\xb8\xe5\xc0\x26\x93\x0c\x3e\x60\x39" + "\xa3\x3c\xe4\x59\x64\xff\x21\x67\xf6\xec\xed\xd4\x19\xdb\x06\xc1"}, + /* Test vectors from the NESSIE project. */ + { + "", "\xe3\xb0\xc4\x42\x98\xfc\x1c\x14\x9a\xfb\xf4\xc8\x99\x6f\xb9\x24" + "\x27\xae\x41\xe4\x64\x9b\x93\x4c\xa4\x95\x99\x1b\x78\x52\xb8\x55"}, + { + "a", "\xca\x97\x81\x12\xca\x1b\xbd\xca\xfa\xc2\x31\xb3\x9a\x23\xdc\x4d" + "\xa7\x86\xef\xf8\x14\x7c\x4e\x72\xb9\x80\x77\x85\xaf\xee\x48\xbb"}, + { + "message digest", + "\xf7\x84\x6f\x55\xcf\x23\xe1\x4e\xeb\xea\xb5\xb4\xe1\x55\x0c\xad" + "\x5b\x50\x9e\x33\x48\xfb\xc4\xef\xa3\xa1\x41\x3d\x39\x3c\xb6\x50"}, + { + "abcdefghijklmnopqrstuvwxyz", + "\x71\xc4\x80\xdf\x93\xd6\xae\x2f\x1e\xfa\xd1\x44\x7c\x66\xc9\x52" + "\x5e\x31\x62\x18\xcf\x51\xfc\x8d\x9e\xd8\x32\xf2\xda\xf1\x8b\x73"}, + { + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "\x24\x8d\x6a\x61\xd2\x06\x38\xb8\xe5\xc0\x26\x93\x0c\x3e\x60\x39" + "\xa3\x3c\xe4\x59\x64\xff\x21\x67\xf6\xec\xed\xd4\x19\xdb\x06\xc1"}, + { + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "\xdb\x4b\xfc\xbd\x4d\xa0\xcd\x85\xa6\x0c\x3c\x37\xd3\xfb\xd8\x80" + "\x5c\x77\xf1\x5f\xc6\xb1\xfd\xfe\x61\x4e\xe0\xa7\xc8\xfd\xb4\xc0"}, + { + "123456789012345678901234567890123456789012345678901234567890" + "12345678901234567890", + "\xf3\x71\xbc\x4a\x31\x1f\x2b\x00\x9e\xef\x95\x2d\xd8\x3c\xa8\x0e" + "\x2b\x60\x02\x6c\x8e\x93\x55\x92\xd0\xf9\xc3\x08\x45\x3c\x81\x3e"} +}; + +#define ntests (sizeof (tests) / sizeof (tests[0])) + +static const struct { + const char *salt; + const char *input; + const char *expected; +} tests2[] = { + { + "$5$saltstring", "Hello world!", + "$5$saltstring$5B8vYYiY.CVt1RlTTf8KbXBH3hsxY/GNooZaBBGWEc5"}, { + "$5$rounds=10000$saltstringsaltstring", "Hello world!", + "$5$rounds=10000$saltstringsaltst$3xv.VbSHBb41AL9AvLeujZkZRBAwqFMz2." + "opqey6IcA"}, { + "$5$rounds=5000$toolongsaltstring", "This is just a test", + "$5$rounds=5000$toolongsaltstrin$Un/5jzAHMgOGZ5.mWJpuVolil07guHPvOW8" + "mGRcvxa5"}, { + "$5$rounds=1400$anotherlongsaltstring", + "a very much longer text to encrypt. This one even stretches over more" + "than one line.", + "$5$rounds=1400$anotherlongsalts$Rx.j8H.h8HjEDGomFU8bDkXm3XIUnzyxf12" + "oP84Bnq1"}, { + "$5$rounds=77777$short", + "we have a short salt string but not a short password", + "$5$rounds=77777$short$JiO1O3ZpDAxGJeaDIuqCoEFysAe1mZNJRs3pw0KQRd/"}, + { + "$5$rounds=123456$asaltof16chars..", "a short string", + "$5$rounds=123456$asaltof16chars..$gP3VQ/6X7UUEW3HkBn2w1/Ptq2jxPyzV/" + "cZKmF/wJvD"}, { +"$5$rounds=10$roundstoolow", "the minimum number is still observed", + "$5$rounds=1000$roundstoolow$yfvwcWrQ8l/K0DAWyuPMDNHpIVlTQebY9l/gL97" + "2bIC"},}; +#define ntests2 (sizeof (tests2) / sizeof (tests2[0])) + +int main(void) +{ + struct sha256_ctx ctx; + char sum[32]; + int result = 0; + int cnt; + + for (cnt = 0; cnt < (int)ntests; ++cnt) { + sha256_init_ctx(&ctx); + sha256_process_bytes(tests[cnt].input, strlen(tests[cnt].input), &ctx); + sha256_finish_ctx(&ctx, sum); + if (memcmp(tests[cnt].result, sum, 32) != 0) { + printf("test %d run %d failed\n", cnt, 1); + result = 1; + } + + sha256_init_ctx(&ctx); + for (int i = 0; tests[cnt].input[i] != '\0'; ++i) + sha256_process_bytes(&tests[cnt].input[i], 1, &ctx); + sha256_finish_ctx(&ctx, sum); + if (memcmp(tests[cnt].result, sum, 32) != 0) { + printf("test %d run %d failed\n", cnt, 2); + result = 1; + } + } + + /* Test vector from FIPS 180-2: appendix B.3. */ + char buf[1000]; + memset(buf, 'a', sizeof(buf)); + sha256_init_ctx(&ctx); + for (int i = 0; i < 1000; ++i) + sha256_process_bytes(buf, sizeof(buf), &ctx); + sha256_finish_ctx(&ctx, sum); + static const char expected[32] = + "\xcd\xc7\x6e\x5c\x99\x14\xfb\x92\x81\xa1\xc7\xe2\x84\xd7\x3e\x67" + "\xf1\x80\x9a\x48\xa4\x97\x20\x0e\x04\x6d\x39\xcc\xc7\x11\x2c\xd0"; + if (memcmp(expected, sum, 32) != 0) { + printf("test %d failed\n", cnt); + result = 1; + } + + for (cnt = 0; cnt < ntests2; ++cnt) { + char *cp = sha256_crypt(tests2[cnt].input, tests2[cnt].salt); + + if (strcmp(cp, tests2[cnt].expected) != 0) { + printf("test %d: expected \"%s\", got \"%s\"\n", + cnt, tests2[cnt].expected, cp); + result = 1; + } + } + + if (result == 0) + puts("all tests OK"); + + return result; +} +#endif diff --git a/contrib/syslinux-4.02/com32/libutil/sha512crypt.c b/contrib/syslinux-4.02/com32/libutil/sha512crypt.c new file mode 100644 index 0000000..9db9c0c --- /dev/null +++ b/contrib/syslinux-4.02/com32/libutil/sha512crypt.c @@ -0,0 +1,749 @@ +/* SHA512-based Unix crypt implementation. + Released into the Public Domain by Ulrich Drepper <drepper@redhat.com>. */ + +#include <alloca.h> +#include <endian.h> +#include <errno.h> +#include <limits.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <minmax.h> +#include <sys/types.h> + +#include "xcrypt.h" + +#define MIN(x,y) min(x,y) +#define MAX(x,y) max(x,y) + +/* Structure to save state of computation between the single steps. */ +struct sha512_ctx { + uint64_t H[8]; + + uint64_t total[2]; + uint64_t buflen; + char buffer[256]; /* NB: always correctly aligned for uint64_t. */ +}; + +#if __BYTE_ORDER == __LITTLE_ENDIAN +# define SWAP(n) \ + (((n) << 56) \ + | (((n) & 0xff00) << 40) \ + | (((n) & 0xff0000) << 24) \ + | (((n) & 0xff000000) << 8) \ + | (((n) >> 8) & 0xff000000) \ + | (((n) >> 24) & 0xff0000) \ + | (((n) >> 40) & 0xff00) \ + | ((n) >> 56)) +#else +# define SWAP(n) (n) +#endif + +/* This array contains the bytes used to pad the buffer to the next + 64-byte boundary. (FIPS 180-2:5.1.2) */ +static const unsigned char fillbuf[128] = { 0x80, 0 /* , 0, 0, ... */ }; + +/* Constants for SHA512 from FIPS 180-2:4.2.3. */ +static const uint64_t K[80] = { + UINT64_C(0x428a2f98d728ae22), UINT64_C(0x7137449123ef65cd), + UINT64_C(0xb5c0fbcfec4d3b2f), UINT64_C(0xe9b5dba58189dbbc), + UINT64_C(0x3956c25bf348b538), UINT64_C(0x59f111f1b605d019), + UINT64_C(0x923f82a4af194f9b), UINT64_C(0xab1c5ed5da6d8118), + UINT64_C(0xd807aa98a3030242), UINT64_C(0x12835b0145706fbe), + UINT64_C(0x243185be4ee4b28c), UINT64_C(0x550c7dc3d5ffb4e2), + UINT64_C(0x72be5d74f27b896f), UINT64_C(0x80deb1fe3b1696b1), + UINT64_C(0x9bdc06a725c71235), UINT64_C(0xc19bf174cf692694), + UINT64_C(0xe49b69c19ef14ad2), UINT64_C(0xefbe4786384f25e3), + UINT64_C(0x0fc19dc68b8cd5b5), UINT64_C(0x240ca1cc77ac9c65), + UINT64_C(0x2de92c6f592b0275), UINT64_C(0x4a7484aa6ea6e483), + UINT64_C(0x5cb0a9dcbd41fbd4), UINT64_C(0x76f988da831153b5), + UINT64_C(0x983e5152ee66dfab), UINT64_C(0xa831c66d2db43210), + UINT64_C(0xb00327c898fb213f), UINT64_C(0xbf597fc7beef0ee4), + UINT64_C(0xc6e00bf33da88fc2), UINT64_C(0xd5a79147930aa725), + UINT64_C(0x06ca6351e003826f), UINT64_C(0x142929670a0e6e70), + UINT64_C(0x27b70a8546d22ffc), UINT64_C(0x2e1b21385c26c926), + UINT64_C(0x4d2c6dfc5ac42aed), UINT64_C(0x53380d139d95b3df), + UINT64_C(0x650a73548baf63de), UINT64_C(0x766a0abb3c77b2a8), + UINT64_C(0x81c2c92e47edaee6), UINT64_C(0x92722c851482353b), + UINT64_C(0xa2bfe8a14cf10364), UINT64_C(0xa81a664bbc423001), + UINT64_C(0xc24b8b70d0f89791), UINT64_C(0xc76c51a30654be30), + UINT64_C(0xd192e819d6ef5218), UINT64_C(0xd69906245565a910), + UINT64_C(0xf40e35855771202a), UINT64_C(0x106aa07032bbd1b8), + UINT64_C(0x19a4c116b8d2d0c8), UINT64_C(0x1e376c085141ab53), + UINT64_C(0x2748774cdf8eeb99), UINT64_C(0x34b0bcb5e19b48a8), + UINT64_C(0x391c0cb3c5c95a63), UINT64_C(0x4ed8aa4ae3418acb), + UINT64_C(0x5b9cca4f7763e373), UINT64_C(0x682e6ff3d6b2b8a3), + UINT64_C(0x748f82ee5defb2fc), UINT64_C(0x78a5636f43172f60), + UINT64_C(0x84c87814a1f0ab72), UINT64_C(0x8cc702081a6439ec), + UINT64_C(0x90befffa23631e28), UINT64_C(0xa4506cebde82bde9), + UINT64_C(0xbef9a3f7b2c67915), UINT64_C(0xc67178f2e372532b), + UINT64_C(0xca273eceea26619c), UINT64_C(0xd186b8c721c0c207), + UINT64_C(0xeada7dd6cde0eb1e), UINT64_C(0xf57d4f7fee6ed178), + UINT64_C(0x06f067aa72176fba), UINT64_C(0x0a637dc5a2c898a6), + UINT64_C(0x113f9804bef90dae), UINT64_C(0x1b710b35131c471b), + UINT64_C(0x28db77f523047d84), UINT64_C(0x32caab7b40c72493), + UINT64_C(0x3c9ebe0a15c9bebc), UINT64_C(0x431d67c49c100d4c), + UINT64_C(0x4cc5d4becb3e42b6), UINT64_C(0x597f299cfc657e2a), + UINT64_C(0x5fcb6fab3ad6faec), UINT64_C(0x6c44198c4a475817) +}; + +/* Process LEN bytes of BUFFER, accumulating context into CTX. + It is assumed that LEN % 128 == 0. */ +static void +sha512_process_block(const void *buffer, size_t len, struct sha512_ctx *ctx) +{ + unsigned int t; + const uint64_t *words = buffer; + size_t nwords = len / sizeof(uint64_t); + uint64_t a = ctx->H[0]; + uint64_t b = ctx->H[1]; + uint64_t c = ctx->H[2]; + uint64_t d = ctx->H[3]; + uint64_t e = ctx->H[4]; + uint64_t f = ctx->H[5]; + uint64_t g = ctx->H[6]; + uint64_t h = ctx->H[7]; + + /* First increment the byte count. FIPS 180-2 specifies the possible + length of the file up to 2^128 bits. Here we only compute the + number of bytes. Do a double word increment. */ + ctx->total[0] += len; + if (ctx->total[0] < len) + ++ctx->total[1]; + + /* Process all bytes in the buffer with 128 bytes in each round of + the loop. */ + while (nwords > 0) { + uint64_t W[80]; + uint64_t a_save = a; + uint64_t b_save = b; + uint64_t c_save = c; + uint64_t d_save = d; + uint64_t e_save = e; + uint64_t f_save = f; + uint64_t g_save = g; + uint64_t h_save = h; + + /* Operators defined in FIPS 180-2:4.1.2. */ +#define Ch(x, y, z) ((x & y) ^ (~x & z)) +#define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z)) +#define S0(x) (CYCLIC (x, 28) ^ CYCLIC (x, 34) ^ CYCLIC (x, 39)) +#define S1(x) (CYCLIC (x, 14) ^ CYCLIC (x, 18) ^ CYCLIC (x, 41)) +#define R0(x) (CYCLIC (x, 1) ^ CYCLIC (x, 8) ^ (x >> 7)) +#define R1(x) (CYCLIC (x, 19) ^ CYCLIC (x, 61) ^ (x >> 6)) + + /* It is unfortunate that C does not provide an operator for + cyclic rotation. Hope the C compiler is smart enough. */ +#define CYCLIC(w, s) ((w >> s) | (w << (64 - s))) + + /* Compute the message schedule according to FIPS 180-2:6.3.2 step 2. */ + for (t = 0; t < 16; ++t) { + W[t] = SWAP(*words); + ++words; + } + for (t = 16; t < 80; ++t) + W[t] = R1(W[t - 2]) + W[t - 7] + R0(W[t - 15]) + W[t - 16]; + + /* The actual computation according to FIPS 180-2:6.3.2 step 3. */ + for (t = 0; t < 80; ++t) { + uint64_t T1 = h + S1(e) + Ch(e, f, g) + K[t] + W[t]; + uint64_t T2 = S0(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + } + + /* Add the starting values of the context according to FIPS 180-2:6.3.2 + step 4. */ + a += a_save; + b += b_save; + c += c_save; + d += d_save; + e += e_save; + f += f_save; + g += g_save; + h += h_save; + + /* Prepare for the next round. */ + nwords -= 16; + } + + /* Put checksum in context given as argument. */ + ctx->H[0] = a; + ctx->H[1] = b; + ctx->H[2] = c; + ctx->H[3] = d; + ctx->H[4] = e; + ctx->H[5] = f; + ctx->H[6] = g; + ctx->H[7] = h; +} + +/* Initialize structure containing state of computation. + (FIPS 180-2:5.3.3) */ +static void sha512_init_ctx(struct sha512_ctx *ctx) +{ + ctx->H[0] = UINT64_C(0x6a09e667f3bcc908); + ctx->H[1] = UINT64_C(0xbb67ae8584caa73b); + ctx->H[2] = UINT64_C(0x3c6ef372fe94f82b); + ctx->H[3] = UINT64_C(0xa54ff53a5f1d36f1); + ctx->H[4] = UINT64_C(0x510e527fade682d1); + ctx->H[5] = UINT64_C(0x9b05688c2b3e6c1f); + ctx->H[6] = UINT64_C(0x1f83d9abfb41bd6b); + ctx->H[7] = UINT64_C(0x5be0cd19137e2179); + + ctx->total[0] = ctx->total[1] = 0; + ctx->buflen = 0; +} + +/* Process the remaining bytes in the internal buffer and the usual + prolog according to the standard and write the result to RESBUF. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +static void *sha512_finish_ctx(struct sha512_ctx *ctx, void *resbuf) +{ + unsigned int i; + /* Take yet unprocessed bytes into account. */ + uint64_t bytes = ctx->buflen; + size_t pad; + + /* Now count remaining bytes. */ + ctx->total[0] += bytes; + if (ctx->total[0] < bytes) + ++ctx->total[1]; + + pad = bytes >= 112 ? 128 + 112 - bytes : 112 - bytes; + memcpy(&ctx->buffer[bytes], fillbuf, pad); + + /* Put the 128-bit file length in *bits* at the end of the buffer. */ + *(uint64_t *) & ctx->buffer[bytes + pad + 8] = SWAP(ctx->total[0] << 3); + *(uint64_t *) & ctx->buffer[bytes + pad] = SWAP((ctx->total[1] << 3) | + (ctx->total[0] >> 61)); + + /* Process last bytes. */ + sha512_process_block(ctx->buffer, bytes + pad + 16, ctx); + + /* Put result from CTX in first 64 bytes following RESBUF. */ + for (i = 0; i < 8; ++i) + ((uint64_t *) resbuf)[i] = SWAP(ctx->H[i]); + + return resbuf; +} + +static void +sha512_process_bytes(const void *buffer, size_t len, struct sha512_ctx *ctx) +{ + /* When we already have some bits in our internal buffer concatenate + both inputs first. */ + if (ctx->buflen != 0) { + size_t left_over = ctx->buflen; + size_t add = 256 - left_over > len ? len : 256 - left_over; + + memcpy(&ctx->buffer[left_over], buffer, add); + ctx->buflen += add; + + if (ctx->buflen > 128) { + sha512_process_block(ctx->buffer, ctx->buflen & ~127, ctx); + + ctx->buflen &= 127; + /* The regions in the following copy operation cannot overlap. */ + memcpy(ctx->buffer, &ctx->buffer[(left_over + add) & ~127], + ctx->buflen); + } + + buffer = (const char *)buffer + add; + len -= add; + } + + /* Process available complete blocks. */ + if (len >= 128) { +#if !_STRING_ARCH_unaligned +/* To check alignment gcc has an appropriate operator. Other + compilers don't. */ +# if __GNUC__ >= 2 +# define UNALIGNED_P(p) (((uintptr_t) p) % __alignof__ (uint64_t) != 0) +# else +# define UNALIGNED_P(p) (((uintptr_t) p) % sizeof (uint64_t) != 0) +# endif + if (UNALIGNED_P(buffer)) + while (len > 128) { + sha512_process_block(memcpy(ctx->buffer, buffer, 128), 128, + ctx); + buffer = (const char *)buffer + 128; + len -= 128; + } else +#endif + { + sha512_process_block(buffer, len & ~127, ctx); + buffer = (const char *)buffer + (len & ~127); + len &= 127; + } + } + + /* Move remaining bytes into internal buffer. */ + if (len > 0) { + size_t left_over = ctx->buflen; + + memcpy(&ctx->buffer[left_over], buffer, len); + left_over += len; + if (left_over >= 128) { + sha512_process_block(ctx->buffer, 128, ctx); + left_over -= 128; + memcpy(ctx->buffer, &ctx->buffer[128], left_over); + } + ctx->buflen = left_over; + } +} + +/* Define our magic string to mark salt for SHA512 "encryption" + replacement. */ +static const char sha512_salt_prefix[] = "$6$"; + +/* Prefix for optional rounds specification. */ +static const char sha512_rounds_prefix[] = "rounds="; + +/* Maximum salt string length. */ +#define SALT_LEN_MAX 16U +/* Default number of rounds if not explicitly specified. */ +#define ROUNDS_DEFAULT 5000UL +/* Minimum number of rounds. */ +#define ROUNDS_MIN 1000UL +/* Maximum number of rounds. */ +#define ROUNDS_MAX 999999999UL + +/* Table with characters for base64 transformation. */ +static const char b64t[64] = + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +static char *sha512_crypt_r(const char *key, const char *salt, char *buffer, + int buflen) +{ + unsigned char alt_result[64] + __attribute__ ((__aligned__(__alignof__(uint64_t)))); + unsigned char temp_result[64] + __attribute__ ((__aligned__(__alignof__(uint64_t)))); + struct sha512_ctx ctx; + struct sha512_ctx alt_ctx; + size_t salt_len; + size_t key_len; + size_t cnt; + char *cp; + char *copied_key = NULL; + char *copied_salt = NULL; + char *p_bytes; + char *s_bytes; + /* Default number of rounds. */ + size_t rounds = ROUNDS_DEFAULT; + bool rounds_custom = false; + + /* Find beginning of salt string. The prefix should normally always + be present. Just in case it is not. */ + if (strncmp(sha512_salt_prefix, salt, sizeof(sha512_salt_prefix) - 1) == 0) + /* Skip salt prefix. */ + salt += sizeof(sha512_salt_prefix) - 1; + + if (strncmp(salt, sha512_rounds_prefix, sizeof(sha512_rounds_prefix) - 1) + == 0) { + const char *num = salt + sizeof(sha512_rounds_prefix) - 1; + char *endp; + unsigned long int srounds = strtoul(num, &endp, 10); + if (*endp == '$') { + salt = endp + 1; + rounds = MAX(ROUNDS_MIN, MIN(srounds, ROUNDS_MAX)); + rounds_custom = true; + } + } + + salt_len = MIN(strcspn(salt, "$"), SALT_LEN_MAX); + key_len = strlen(key); + + if ((key - (char *)0) % __alignof__(uint64_t) != 0) { + char *tmp = (char *)alloca(key_len + __alignof__(uint64_t)); + key = copied_key = memcpy(tmp + __alignof__(uint64_t) + - (tmp - (char *)0) % __alignof__(uint64_t), + key, key_len); + } + + if ((salt - (char *)0) % __alignof__(uint64_t) != 0) { + char *tmp = (char *)alloca(salt_len + __alignof__(uint64_t)); + salt = copied_salt = memcpy(tmp + __alignof__(uint64_t) + - (tmp - (char *)0) % __alignof__(uint64_t), + salt, salt_len); + } + + /* Prepare for the real work. */ + sha512_init_ctx(&ctx); + + /* Add the key string. */ + sha512_process_bytes(key, key_len, &ctx); + + /* The last part is the salt string. This must be at most 8 + characters and it ends at the first `$' character (for + compatibility with existing implementations). */ + sha512_process_bytes(salt, salt_len, &ctx); + + /* Compute alternate SHA512 sum with input KEY, SALT, and KEY. The + final result will be added to the first context. */ + sha512_init_ctx(&alt_ctx); + + /* Add key. */ + sha512_process_bytes(key, key_len, &alt_ctx); + + /* Add salt. */ + sha512_process_bytes(salt, salt_len, &alt_ctx); + + /* Add key again. */ + sha512_process_bytes(key, key_len, &alt_ctx); + + /* Now get result of this (64 bytes) and add it to the other + context. */ + sha512_finish_ctx(&alt_ctx, alt_result); + + /* Add for any character in the key one byte of the alternate sum. */ + for (cnt = key_len; cnt > 64; cnt -= 64) + sha512_process_bytes(alt_result, 64, &ctx); + sha512_process_bytes(alt_result, cnt, &ctx); + + /* Take the binary representation of the length of the key and for every + 1 add the alternate sum, for every 0 the key. */ + for (cnt = key_len; cnt > 0; cnt >>= 1) + if ((cnt & 1) != 0) + sha512_process_bytes(alt_result, 64, &ctx); + else + sha512_process_bytes(key, key_len, &ctx); + + /* Create intermediate result. */ + sha512_finish_ctx(&ctx, alt_result); + + /* Start computation of P byte sequence. */ + sha512_init_ctx(&alt_ctx); + + /* For every character in the password add the entire password. */ + for (cnt = 0; cnt < key_len; ++cnt) + sha512_process_bytes(key, key_len, &alt_ctx); + + /* Finish the digest. */ + sha512_finish_ctx(&alt_ctx, temp_result); + + /* Create byte sequence P. */ + cp = p_bytes = alloca(key_len); + for (cnt = key_len; cnt >= 64; cnt -= 64) + cp = mempcpy(cp, temp_result, 64); + memcpy(cp, temp_result, cnt); + + /* Start computation of S byte sequence. */ + sha512_init_ctx(&alt_ctx); + + /* For every character in the password add the entire password. */ + for (cnt = 0; cnt < (size_t)16 + alt_result[0]; ++cnt) + sha512_process_bytes(salt, salt_len, &alt_ctx); + + /* Finish the digest. */ + sha512_finish_ctx(&alt_ctx, temp_result); + + /* Create byte sequence S. */ + cp = s_bytes = alloca(salt_len); + for (cnt = salt_len; cnt >= 64; cnt -= 64) + cp = mempcpy(cp, temp_result, 64); + memcpy(cp, temp_result, cnt); + + /* Repeatedly run the collected hash value through SHA512 to burn + CPU cycles. */ + for (cnt = 0; cnt < rounds; ++cnt) { + /* New context. */ + sha512_init_ctx(&ctx); + + /* Add key or last result. */ + if ((cnt & 1) != 0) + sha512_process_bytes(p_bytes, key_len, &ctx); + else + sha512_process_bytes(alt_result, 64, &ctx); + + /* Add salt for numbers not divisible by 3. */ + if (cnt % 3 != 0) + sha512_process_bytes(s_bytes, salt_len, &ctx); + + /* Add key for numbers not divisible by 7. */ + if (cnt % 7 != 0) + sha512_process_bytes(p_bytes, key_len, &ctx); + + /* Add key or last result. */ + if ((cnt & 1) != 0) + sha512_process_bytes(alt_result, 64, &ctx); + else + sha512_process_bytes(p_bytes, key_len, &ctx); + + /* Create intermediate result. */ + sha512_finish_ctx(&ctx, alt_result); + } + + /* Now we can construct the result string. It consists of three + parts. */ + cp = stpncpy(buffer, sha512_salt_prefix, MAX(0, buflen)); + buflen -= sizeof(sha512_salt_prefix) - 1; + + if (rounds_custom) { + int n = snprintf(cp, MAX(0, buflen), "%s%zu$", + sha512_rounds_prefix, rounds); + cp += n; + buflen -= n; + } + + cp = stpncpy(cp, salt, MIN((size_t) MAX(0, buflen), salt_len)); + buflen -= MIN((size_t) MAX(0, buflen), salt_len); + + if (buflen > 0) { + *cp++ = '$'; + --buflen; + } +#define b64_from_24bit(B2, B1, B0, N) \ + do { \ + unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0); \ + int n = (N); \ + while (n-- > 0 && buflen > 0) \ + { \ + *cp++ = b64t[w & 0x3f]; \ + --buflen; \ + w >>= 6; \ + } \ + } while (0) + + b64_from_24bit(alt_result[0], alt_result[21], alt_result[42], 4); + b64_from_24bit(alt_result[22], alt_result[43], alt_result[1], 4); + b64_from_24bit(alt_result[44], alt_result[2], alt_result[23], 4); + b64_from_24bit(alt_result[3], alt_result[24], alt_result[45], 4); + b64_from_24bit(alt_result[25], alt_result[46], alt_result[4], 4); + b64_from_24bit(alt_result[47], alt_result[5], alt_result[26], 4); + b64_from_24bit(alt_result[6], alt_result[27], alt_result[48], 4); + b64_from_24bit(alt_result[28], alt_result[49], alt_result[7], 4); + b64_from_24bit(alt_result[50], alt_result[8], alt_result[29], 4); + b64_from_24bit(alt_result[9], alt_result[30], alt_result[51], 4); + b64_from_24bit(alt_result[31], alt_result[52], alt_result[10], 4); + b64_from_24bit(alt_result[53], alt_result[11], alt_result[32], 4); + b64_from_24bit(alt_result[12], alt_result[33], alt_result[54], 4); + b64_from_24bit(alt_result[34], alt_result[55], alt_result[13], 4); + b64_from_24bit(alt_result[56], alt_result[14], alt_result[35], 4); + b64_from_24bit(alt_result[15], alt_result[36], alt_result[57], 4); + b64_from_24bit(alt_result[37], alt_result[58], alt_result[16], 4); + b64_from_24bit(alt_result[59], alt_result[17], alt_result[38], 4); + b64_from_24bit(alt_result[18], alt_result[39], alt_result[60], 4); + b64_from_24bit(alt_result[40], alt_result[61], alt_result[19], 4); + b64_from_24bit(alt_result[62], alt_result[20], alt_result[41], 4); + b64_from_24bit(0, 0, alt_result[63], 2); + + if (buflen <= 0) { + errno = ERANGE; + buffer = NULL; + } else + *cp = '\0'; /* Terminate the string. */ + + /* Clear the buffer for the intermediate result so that people + attaching to processes or reading core dumps cannot get any + information. We do it in this way to clear correct_words[] + inside the SHA512 implementation as well. */ + sha512_init_ctx(&ctx); + sha512_finish_ctx(&ctx, alt_result); + memset(temp_result, '\0', sizeof(temp_result)); + memset(p_bytes, '\0', key_len); + memset(s_bytes, '\0', salt_len); + memset(&ctx, '\0', sizeof(ctx)); + memset(&alt_ctx, '\0', sizeof(alt_ctx)); + if (copied_key != NULL) + memset(copied_key, '\0', key_len); + if (copied_salt != NULL) + memset(copied_salt, '\0', salt_len); + + return buffer; +} + +/* This entry point is equivalent to the `crypt' function in Unix + libcs. */ +char *sha512_crypt(const char *key, const char *salt) +{ + /* We don't want to have an arbitrary limit in the size of the + password. We can compute an upper bound for the size of the + result in advance and so we can prepare the buffer we pass to + `sha512_crypt_r'. */ + static char *buffer; + static int buflen; + int needed = (sizeof(sha512_salt_prefix) - 1 + + sizeof(sha512_rounds_prefix) + 9 + 1 + + strlen(salt) + 1 + 86 + 1); + + if (buflen < needed) { + char *new_buffer = (char *)realloc(buffer, needed); + if (new_buffer == NULL) + return NULL; + + buffer = new_buffer; + buflen = needed; + } + + return sha512_crypt_r(key, salt, buffer, buflen); +} + +#ifdef TEST +static const struct { + const char *input; + const char result[64]; +} tests[] = { + /* Test vectors from FIPS 180-2: appendix C.1. */ + { + "abc", + "\xdd\xaf\x35\xa1\x93\x61\x7a\xba\xcc\x41\x73\x49\xae\x20\x41\x31" + "\x12\xe6\xfa\x4e\x89\xa9\x7e\xa2\x0a\x9e\xee\xe6\x4b\x55\xd3\x9a" + "\x21\x92\x99\x2a\x27\x4f\xc1\xa8\x36\xba\x3c\x23\xa3\xfe\xeb\xbd" + "\x45\x4d\x44\x23\x64\x3c\xe8\x0e\x2a\x9a\xc9\x4f\xa5\x4c\xa4\x9f"}, + /* Test vectors from FIPS 180-2: appendix C.2. */ + { + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + "\x8e\x95\x9b\x75\xda\xe3\x13\xda\x8c\xf4\xf7\x28\x14\xfc\x14\x3f" + "\x8f\x77\x79\xc6\xeb\x9f\x7f\xa1\x72\x99\xae\xad\xb6\x88\x90\x18" + "\x50\x1d\x28\x9e\x49\x00\xf7\xe4\x33\x1b\x99\xde\xc4\xb5\x43\x3a" + "\xc7\xd3\x29\xee\xb6\xdd\x26\x54\x5e\x96\xe5\x5b\x87\x4b\xe9\x09"}, + /* Test vectors from the NESSIE project. */ + { + "", "\xcf\x83\xe1\x35\x7e\xef\xb8\xbd\xf1\x54\x28\x50\xd6\x6d\x80\x07" + "\xd6\x20\xe4\x05\x0b\x57\x15\xdc\x83\xf4\xa9\x21\xd3\x6c\xe9\xce" + "\x47\xd0\xd1\x3c\x5d\x85\xf2\xb0\xff\x83\x18\xd2\x87\x7e\xec\x2f" + "\x63\xb9\x31\xbd\x47\x41\x7a\x81\xa5\x38\x32\x7a\xf9\x27\xda\x3e"}, + { + "a", "\x1f\x40\xfc\x92\xda\x24\x16\x94\x75\x09\x79\xee\x6c\xf5\x82\xf2" + "\xd5\xd7\xd2\x8e\x18\x33\x5d\xe0\x5a\xbc\x54\xd0\x56\x0e\x0f\x53" + "\x02\x86\x0c\x65\x2b\xf0\x8d\x56\x02\x52\xaa\x5e\x74\x21\x05\x46" + "\xf3\x69\xfb\xbb\xce\x8c\x12\xcf\xc7\x95\x7b\x26\x52\xfe\x9a\x75"}, + { + "message digest", + "\x10\x7d\xbf\x38\x9d\x9e\x9f\x71\xa3\xa9\x5f\x6c\x05\x5b\x92\x51" + "\xbc\x52\x68\xc2\xbe\x16\xd6\xc1\x34\x92\xea\x45\xb0\x19\x9f\x33" + "\x09\xe1\x64\x55\xab\x1e\x96\x11\x8e\x8a\x90\x5d\x55\x97\xb7\x20" + "\x38\xdd\xb3\x72\xa8\x98\x26\x04\x6d\xe6\x66\x87\xbb\x42\x0e\x7c"}, + { + "abcdefghijklmnopqrstuvwxyz", + "\x4d\xbf\xf8\x6c\xc2\xca\x1b\xae\x1e\x16\x46\x8a\x05\xcb\x98\x81" + "\xc9\x7f\x17\x53\xbc\xe3\x61\x90\x34\x89\x8f\xaa\x1a\xab\xe4\x29" + "\x95\x5a\x1b\xf8\xec\x48\x3d\x74\x21\xfe\x3c\x16\x46\x61\x3a\x59" + "\xed\x54\x41\xfb\x0f\x32\x13\x89\xf7\x7f\x48\xa8\x79\xc7\xb1\xf1"}, + { + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "\x20\x4a\x8f\xc6\xdd\xa8\x2f\x0a\x0c\xed\x7b\xeb\x8e\x08\xa4\x16" + "\x57\xc1\x6e\xf4\x68\xb2\x28\xa8\x27\x9b\xe3\x31\xa7\x03\xc3\x35" + "\x96\xfd\x15\xc1\x3b\x1b\x07\xf9\xaa\x1d\x3b\xea\x57\x78\x9c\xa0" + "\x31\xad\x85\xc7\xa7\x1d\xd7\x03\x54\xec\x63\x12\x38\xca\x34\x45"}, + { + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "\x1e\x07\xbe\x23\xc2\x6a\x86\xea\x37\xea\x81\x0c\x8e\xc7\x80\x93" + "\x52\x51\x5a\x97\x0e\x92\x53\xc2\x6f\x53\x6c\xfc\x7a\x99\x96\xc4" + "\x5c\x83\x70\x58\x3e\x0a\x78\xfa\x4a\x90\x04\x1d\x71\xa4\xce\xab" + "\x74\x23\xf1\x9c\x71\xb9\xd5\xa3\xe0\x12\x49\xf0\xbe\xbd\x58\x94"}, + { + "123456789012345678901234567890123456789012345678901234567890" + "12345678901234567890", + "\x72\xec\x1e\xf1\x12\x4a\x45\xb0\x47\xe8\xb7\xc7\x5a\x93\x21\x95" + "\x13\x5b\xb6\x1d\xe2\x4e\xc0\xd1\x91\x40\x42\x24\x6e\x0a\xec\x3a" + "\x23\x54\xe0\x93\xd7\x6f\x30\x48\xb4\x56\x76\x43\x46\x90\x0c\xb1" + "\x30\xd2\xa4\xfd\x5d\xd1\x6a\xbb\x5e\x30\xbc\xb8\x50\xde\xe8\x43"} +}; + +#define ntests (sizeof (tests) / sizeof (tests[0])) + +static const struct { + const char *salt; + const char *input; + const char *expected; +} tests2[] = { + { + "$6$saltstring", "Hello world!", + "$6$saltstring$svn8UoSVapNtMuq1ukKS4tPQd8iKwSMHWjl/O817G3uBnIFNjnQJu" + "esI68u4OTLiBFdcbYEdFCoEOfaS35inz1"}, { + "$6$rounds=10000$saltstringsaltstring", "Hello world!", + "$6$rounds=10000$saltstringsaltst$OW1/O6BYHV6BcXZu8QVeXbDWra3Oeqh0sb" + "HbbMCVNSnCM/UrjmM0Dp8vOuZeHBy/YTBmSK6H9qs/y3RnOaw5v."}, { + "$6$rounds=5000$toolongsaltstring", "This is just a test", + "$6$rounds=5000$toolongsaltstrin$lQ8jolhgVRVhY4b5pZKaysCLi0QBxGoNeKQ" + "zQ3glMhwllF7oGDZxUhx1yxdYcz/e1JSbq3y6JMxxl8audkUEm0"}, { + "$6$rounds=1400$anotherlongsaltstring", + "a very much longer text to encrypt. This one even stretches over more" + "than one line.", + "$6$rounds=1400$anotherlongsalts$POfYwTEok97VWcjxIiSOjiykti.o/pQs.wP" + "vMxQ6Fm7I6IoYN3CmLs66x9t0oSwbtEW7o7UmJEiDwGqd8p4ur1"}, { + "$6$rounds=77777$short", + "we have a short salt string but not a short password", + "$6$rounds=77777$short$WuQyW2YR.hBNpjjRhpYD/ifIw05xdfeEyQoMxIXbkvr0g" + "ge1a1x3yRULJ5CCaUeOxFmtlcGZelFl5CxtgfiAc0"}, { + "$6$rounds=123456$asaltof16chars..", "a short string", + "$6$rounds=123456$asaltof16chars..$BtCwjqMJGx5hrJhZywWvt0RLE8uZ4oPwc" + "elCjmw2kSYu.Ec6ycULevoBK25fs2xXgMNrCzIMVcgEJAstJeonj1"}, { +"$6$rounds=10$roundstoolow", "the minimum number is still observed", + "$6$rounds=1000$roundstoolow$kUMsbe306n21p9R.FRkW3IGn.S9NPN0x50YhH1x" + "hLsPuWGsUSklZt58jaTfF4ZEQpyUNGc0dqbpBYYBaHHrsX."},}; +#define ntests2 (sizeof (tests2) / sizeof (tests2[0])) + +int main(void) +{ + struct sha512_ctx ctx; + char sum[64]; + int result = 0; + int cnt; + + for (cnt = 0; cnt < (int)ntests; ++cnt) { + sha512_init_ctx(&ctx); + sha512_process_bytes(tests[cnt].input, strlen(tests[cnt].input), &ctx); + sha512_finish_ctx(&ctx, sum); + if (memcmp(tests[cnt].result, sum, 64) != 0) { + printf("test %d run %d failed\n", cnt, 1); + result = 1; + } + + sha512_init_ctx(&ctx); + for (int i = 0; tests[cnt].input[i] != '\0'; ++i) + sha512_process_bytes(&tests[cnt].input[i], 1, &ctx); + sha512_finish_ctx(&ctx, sum); + if (memcmp(tests[cnt].result, sum, 64) != 0) { + printf("test %d run %d failed\n", cnt, 2); + result = 1; + } + } + + /* Test vector from FIPS 180-2: appendix C.3. */ + char buf[1000]; + memset(buf, 'a', sizeof(buf)); + sha512_init_ctx(&ctx); + for (int i = 0; i < 1000; ++i) + sha512_process_bytes(buf, sizeof(buf), &ctx); + sha512_finish_ctx(&ctx, sum); + static const char expected[64] = + "\xe7\x18\x48\x3d\x0c\xe7\x69\x64\x4e\x2e\x42\xc7\xbc\x15\xb4\x63" + "\x8e\x1f\x98\xb1\x3b\x20\x44\x28\x56\x32\xa8\x03\xaf\xa9\x73\xeb" + "\xde\x0f\xf2\x44\x87\x7e\xa6\x0a\x4c\xb0\x43\x2c\xe5\x77\xc3\x1b" + "\xeb\x00\x9c\x5c\x2c\x49\xaa\x2e\x4e\xad\xb2\x17\xad\x8c\xc0\x9b"; + if (memcmp(expected, sum, 64) != 0) { + printf("test %d failed\n", cnt); + result = 1; + } + + for (cnt = 0; cnt < ntests2; ++cnt) { + char *cp = sha512_crypt(tests2[cnt].input, tests2[cnt].salt); + + if (strcmp(cp, tests2[cnt].expected) != 0) { + printf("test %d: expected \"%s\", got \"%s\"\n", + cnt, tests2[cnt].expected, cp); + result = 1; + } + } + + if (result == 0) + puts("all tests OK"); + + return result; +} +#endif diff --git a/contrib/syslinux-4.02/com32/libutil/unbase64.c b/contrib/syslinux-4.02/com32/libutil/unbase64.c new file mode 100644 index 0000000..3cbf3fb --- /dev/null +++ b/contrib/syslinux-4.02/com32/libutil/unbase64.c @@ -0,0 +1,76 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2005-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. + * + * ----------------------------------------------------------------------- */ + +/* + * unbase64.c + * + * Convert a string in base64 format to a byte array. + */ + +#include <string.h> +#include <base64.h> + +static const unsigned char _base64chars[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +size_t unbase64(unsigned char *buffer, size_t bufsiz, const char *txt) +{ + unsigned int bits = 0; + int nbits = 0; + char base64tbl[256]; + int i; + char v; + size_t nbytes = 0; + + memset(base64tbl, -1, sizeof base64tbl); + + for (i = 0; _base64chars[i]; i++) { + base64tbl[_base64chars[i]] = i; + } + + /* Also support filesystem safe alternate base64 encoding */ + base64tbl['.'] = 62; + base64tbl['-'] = 62; + base64tbl['_'] = 63; + + while (*txt) { + if ((v = base64tbl[(unsigned char)*txt]) >= 0) { + bits <<= 6; + bits += v; + nbits += 6; + if (nbits >= 8) { + if (nbytes < bufsiz) + *buffer++ = (bits >> (nbits - 8)); + nbytes++; + nbits -= 8; + } + } + txt++; + } + + return nbytes; +} diff --git a/contrib/syslinux-4.02/com32/lua/COPYRIGHT b/contrib/syslinux-4.02/com32/lua/COPYRIGHT new file mode 100644 index 0000000..3a53e74 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/COPYRIGHT @@ -0,0 +1,34 @@ +Lua License +----------- + +Lua is licensed under the terms of the MIT license reproduced below. +This means that Lua is free software and can be used for both academic +and commercial purposes at absolutely no cost. + +For details and rationale, see http://www.lua.org/license.html . + +=============================================================================== + +Copyright (C) 1994-2008 Lua.org, PUC-Rio. + +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. + +=============================================================================== + +(end of COPYRIGHT) diff --git a/contrib/syslinux-4.02/com32/lua/HISTORY b/contrib/syslinux-4.02/com32/lua/HISTORY new file mode 100644 index 0000000..ce0c95b --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/HISTORY @@ -0,0 +1,183 @@ +HISTORY for Lua 5.1 + +* Changes from version 5.0 to 5.1 + ------------------------------- + Language: + + new module system. + + new semantics for control variables of fors. + + new semantics for setn/getn. + + new syntax/semantics for varargs. + + new long strings and comments. + + new `mod' operator (`%') + + new length operator #t + + metatables for all types + API: + + new functions: lua_createtable, lua_get(set)field, lua_push(to)integer. + + user supplies memory allocator (lua_open becomes lua_newstate). + + luaopen_* functions must be called through Lua. + Implementation: + + new configuration scheme via luaconf.h. + + incremental garbage collection. + + better handling of end-of-line in the lexer. + + fully reentrant parser (new Lua function `load') + + better support for 64-bit machines. + + native loadlib support for Mac OS X. + + standard distribution in only one library (lualib.a merged into lua.a) + +* Changes from version 4.0 to 5.0 + ------------------------------- + Language: + + lexical scoping. + + Lua coroutines. + + standard libraries now packaged in tables. + + tags replaced by metatables and tag methods replaced by metamethods, + stored in metatables. + + proper tail calls. + + each function can have its own global table, which can be shared. + + new __newindex metamethod, called when we insert a new key into a table. + + new block comments: --[[ ... ]]. + + new generic for. + + new weak tables. + + new boolean type. + + new syntax "local function". + + (f()) returns the first value returned by f. + + {f()} fills a table with all values returned by f. + + \n ignored in [[\n . + + fixed and-or priorities. + + more general syntax for function definition (e.g. function a.x.y:f()...end). + + more general syntax for function calls (e.g. (print or write)(9)). + + new functions (time/date, tmpfile, unpack, require, load*, etc.). + API: + + chunks are loaded by using lua_load; new luaL_loadfile and luaL_loadbuffer. + + introduced lightweight userdata, a simple "void*" without a metatable. + + new error handling protocol: the core no longer prints error messages; + all errors are reported to the caller on the stack. + + new lua_atpanic for host cleanup. + + new, signal-safe, hook scheme. + Implementation: + + new license: MIT. + + new, faster, register-based virtual machine. + + support for external multithreading and coroutines. + + new and consistent error message format. + + the core no longer needs "stdio.h" for anything (except for a single + use of sprintf to convert numbers to strings). + + lua.c now runs the environment variable LUA_INIT, if present. It can + be "@filename", to run a file, or the chunk itself. + + support for user extensions in lua.c. + sample implementation given for command line editing. + + new dynamic loading library, active by default on several platforms. + + safe garbage-collector metamethods. + + precompiled bytecodes checked for integrity (secure binary dostring). + + strings are fully aligned. + + position capture in string.find. + + read('*l') can read lines with embedded zeros. + +* Changes from version 3.2 to 4.0 + ------------------------------- + Language: + + new "break" and "for" statements (both numerical and for tables). + + uniform treatment of globals: globals are now stored in a Lua table. + + improved error messages. + + no more '$debug': full speed *and* full debug information. + + new read form: read(N) for next N bytes. + + general read patterns now deprecated. + (still available with -DCOMPAT_READPATTERNS.) + + all return values are passed as arguments for the last function + (old semantics still available with -DLUA_COMPAT_ARGRET) + + garbage collection tag methods for tables now deprecated. + + there is now only one tag method for order. + API: + + New API: fully re-entrant, simpler, and more efficient. + + New debug API. + Implementation: + + faster than ever: cleaner virtual machine and new hashing algorithm. + + non-recursive garbage-collector algorithm. + + reduced memory usage for programs with many strings. + + improved treatment for memory allocation errors. + + improved support for 16-bit machines (we hope). + + code now compiles unmodified as both ANSI C and C++. + + numbers in bases other than 10 are converted using strtoul. + + new -f option in Lua to support #! scripts. + + luac can now combine text and binaries. + +* Changes from version 3.1 to 3.2 + ------------------------------- + + redirected all output in Lua's core to _ERRORMESSAGE and _ALERT. + + increased limit on the number of constants and globals per function + (from 2^16 to 2^24). + + debugging info (lua_debug and hooks) moved into lua_state and new API + functions provided to get and set this info. + + new debug lib gives full debugging access within Lua. + + new table functions "foreachi", "sort", "tinsert", "tremove", "getn". + + new io functions "flush", "seek". + +* Changes from version 3.0 to 3.1 + ------------------------------- + + NEW FEATURE: anonymous functions with closures (via "upvalues"). + + new syntax: + - local variables in chunks. + - better scope control with DO block END. + - constructors can now be also written: { record-part; list-part }. + - more general syntax for function calls and lvalues, e.g.: + f(x).y=1 + o:f(x,y):g(z) + f"string" is sugar for f("string") + + strings may now contain arbitrary binary data (e.g., embedded zeros). + + major code re-organization and clean-up; reduced module interdependecies. + + no arbitrary limits on the total number of constants and globals. + + support for multiple global contexts. + + better syntax error messages. + + new traversal functions "foreach" and "foreachvar". + + the default for numbers is now double. + changing it to use floats or longs is easy. + + complete debug information stored in pre-compiled chunks. + + sample interpreter now prompts user when run interactively, and also + handles control-C interruptions gracefully. + +* Changes from version 2.5 to 3.0 + ------------------------------- + + NEW CONCEPT: "tag methods". + Tag methods replace fallbacks as the meta-mechanism for extending the + semantics of Lua. Whereas fallbacks had a global nature, tag methods + work on objects having the same tag (e.g., groups of tables). + Existing code that uses fallbacks should work without change. + + new, general syntax for constructors {[exp] = exp, ... }. + + support for handling variable number of arguments in functions (varargs). + + support for conditional compilation ($if ... $else ... $end). + + cleaner semantics in API simplifies host code. + + better support for writing libraries (auxlib.h). + + better type checking and error messages in the standard library. + + luac can now also undump. + +* Changes from version 2.4 to 2.5 + ------------------------------- + + io and string libraries are now based on pattern matching; + the old libraries are still available for compatibility + + dofile and dostring can now return values (via return statement) + + better support for 16- and 64-bit machines + + expanded documentation, with more examples + +* Changes from version 2.2 to 2.4 + ------------------------------- + + external compiler creates portable binary files that can be loaded faster + + interface for debugging and profiling + + new "getglobal" fallback + + new functions for handling references to Lua objects + + new functions in standard lib + + only one copy of each string is stored + + expanded documentation, with more examples + +* Changes from version 2.1 to 2.2 + ------------------------------- + + functions now may be declared with any "lvalue" as a name + + garbage collection of functions + + support for pipes + +* Changes from version 1.1 to 2.1 + ------------------------------- + + object-oriented support + + fallbacks + + simplified syntax for tables + + many internal improvements + +(end of HISTORY) diff --git a/contrib/syslinux-4.02/com32/lua/INSTALL b/contrib/syslinux-4.02/com32/lua/INSTALL new file mode 100644 index 0000000..17eb8ae --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/INSTALL @@ -0,0 +1,99 @@ +INSTALL for Lua 5.1 + +* Building Lua + ------------ + Lua is built in the src directory, but the build process can be + controlled from the top-level Makefile. + + Building Lua on Unix systems should be very easy. First do "make" and + see if your platform is listed. If so, just do "make xxx", where xxx + is your platform name. The platforms currently supported are: + aix ansi bsd freebsd generic linux macosx mingw posix solaris + + If your platform is not listed, try the closest one or posix, generic, + ansi, in this order. + + See below for customization instructions and for instructions on how + to build with other Windows compilers. + + If you want to check that Lua has been built correctly, do "make test" + after building Lua. Also, have a look at the example programs in test. + +* Installing Lua + -------------- + Once you have built Lua, you may want to install it in an official + place in your system. In this case, do "make install". The official + place and the way to install files are defined in Makefile. You must + have the right permissions to install files. + + If you want to build and install Lua in one step, do "make xxx install", + where xxx is your platform name. + + If you want to install Lua locally, then do "make local". This will + create directories bin, include, lib, man, and install Lua there as + follows: + + bin: lua luac + include: lua.h luaconf.h lualib.h lauxlib.h lua.hpp + lib: liblua.a + man/man1: lua.1 luac.1 + + These are the only directories you need for development. + + There are man pages for lua and luac, in both nroff and html, and a + reference manual in html in doc, some sample code in test, and some + useful stuff in etc. You don't need these directories for development. + + If you want to install Lua locally, but in some other directory, do + "make install INSTALL_TOP=xxx", where xxx is your chosen directory. + + See below for instructions for Windows and other systems. + +* Customization + ------------- + Three things can be customized by editing a file: + - Where and how to install Lua -- edit Makefile. + - How to build Lua -- edit src/Makefile. + - Lua features -- edit src/luaconf.h. + + You don't actually need to edit the Makefiles because you may set the + relevant variables when invoking make. + + On the other hand, if you need to select some Lua features, you'll need + to edit src/luaconf.h. The edited file will be the one installed, and + it will be used by any Lua clients that you build, to ensure consistency. + + We strongly recommend that you enable dynamic loading. This is done + automatically for all platforms listed above that have this feature + (and also Windows). See src/luaconf.h and also src/Makefile. + +* Building Lua on Windows and other systems + ----------------------------------------- + If you're not using the usual Unix tools, then the instructions for + building Lua depend on the compiler you use. You'll need to create + projects (or whatever your compiler uses) for building the library, + the interpreter, and the compiler, as follows: + + library: lapi.c lcode.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c + lmem.c lobject.c lopcodes.c lparser.c lstate.c lstring.c + ltable.c ltm.c lundump.c lvm.c lzio.c + lauxlib.c lbaselib.c ldblib.c liolib.c lmathlib.c loslib.c + ltablib.c lstrlib.c loadlib.c linit.c + + interpreter: library, lua.c + + compiler: library, luac.c print.c + + If you use Visual Studio .NET, you can use etc/luavs.bat in its + "Command Prompt". + + If all you want is to build the Lua interpreter, you may put all .c files + in a single project, except for luac.c and print.c. Or just use etc/all.c. + + To use Lua as a library in your own programs, you'll need to know how to + create and use libraries with your compiler. + + As mentioned above, you may edit luaconf.h to select some features before + building Lua. + +(end of INSTALL) diff --git a/contrib/syslinux-4.02/com32/lua/Makefile-orig b/contrib/syslinux-4.02/com32/lua/Makefile-orig new file mode 100644 index 0000000..fec2011 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/Makefile-orig @@ -0,0 +1,120 @@ +# makefile for installing Lua +# see INSTALL for installation instructions +# see src/Makefile and src/luaconf.h for further customization + +# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT ======================= + +# Your platform. See PLATS for possible values. +PLAT= none + +# Where to install. The installation starts in the src directory, so take care +# if INSTALL_TOP is not an absolute path. (Man pages are installed from the +# doc directory.) You may want to make these paths consistent with LUA_ROOT, +# LUA_LDIR, and LUA_CDIR in luaconf.h (and also with etc/lua.pc). +# +INSTALL_TOP= /usr/local +INSTALL_BIN= $(INSTALL_TOP)/bin +INSTALL_INC= $(INSTALL_TOP)/include +INSTALL_LIB= $(INSTALL_TOP)/lib +INSTALL_MAN= $(INSTALL_TOP)/man/man1 +INSTALL_LMOD= $(INSTALL_TOP)/share/lua/$V +INSTALL_CMOD= $(INSTALL_TOP)/lib/lua/$V + +# How to install. If you don't have "install" (unlikely) then get install-sh at +# http://dev.w3.org/cvsweb/libwww/config/install-sh +# or use cp instead. +INSTALL_EXEC= $(INSTALL) -p -m 0755 +INSTALL_DATA= $(INSTALL) -p -m 0644 + +# Utilities. +INSTALL= install +MKDIR= mkdir + +# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE ========= + +# Convenience platforms targets. +PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris + +# What to install. +TO_BIN= lua luac +TO_INC= lua.h luaconf.h lualib.h lauxlib.h ../etc/lua.hpp +TO_LIB= liblua.a +TO_MAN= lua.1 luac.1 + +# Lua version and release. +V= 5.1 +R= 5.1.3 + +all: $(PLAT) + +$(PLATS) clean: + cd src && $(MAKE) $@ + +test: dummy + src/lua test/hello.lua + +install: dummy + cd src && $(MKDIR) -p $(INSTALL_BIN) $(INSTALL_INC) $(INSTALL_LIB) $(INSTALL_MAN) $(INSTALL_LMOD) $(INSTALL_CMOD) + cd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN) + cd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC) + cd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB) + cd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN) + +local: + $(MAKE) install INSTALL_TOP=.. + +none: + @echo "Please do" + @echo " make PLATFORM" + @echo "where PLATFORM is one of these:" + @echo " $(PLATS)" + @echo "See INSTALL for complete instructions." + +# make may get confused with test/ and INSTALL in a case-insensitive OS +dummy: + +# echo config parameters +echo: + @echo "" + @echo "These are the parameters currently set in src/Makefile to build Lua $R:" + @echo "" + @cd src && $(MAKE) -s echo + @echo "" + @echo "These are the parameters currently set in Makefile to install Lua $R:" + @echo "" + @echo "PLAT = $(PLAT)" + @echo "INSTALL_TOP = $(INSTALL_TOP)" + @echo "INSTALL_BIN = $(INSTALL_BIN)" + @echo "INSTALL_INC = $(INSTALL_INC)" + @echo "INSTALL_LIB = $(INSTALL_LIB)" + @echo "INSTALL_MAN = $(INSTALL_MAN)" + @echo "INSTALL_LMOD = $(INSTALL_LMOD)" + @echo "INSTALL_CMOD = $(INSTALL_CMOD)" + @echo "INSTALL_EXEC = $(INSTALL_EXEC)" + @echo "INSTALL_DATA = $(INSTALL_DATA)" + @echo "" + @echo "See also src/luaconf.h ." + @echo "" + +# echo private config parameters +pecho: + @echo "V = $(V)" + @echo "R = $(R)" + @echo "TO_BIN = $(TO_BIN)" + @echo "TO_INC = $(TO_INC)" + @echo "TO_LIB = $(TO_LIB)" + @echo "TO_MAN = $(TO_MAN)" + +# echo config parameters as Lua code +# uncomment the last sed expression if you want nil instead of empty strings +lecho: + @echo "-- installation parameters for Lua $R" + @echo "VERSION = '$V'" + @echo "RELEASE = '$R'" + @$(MAKE) echo | grep = | sed -e 's/= /= "/' -e 's/$$/"/' #-e 's/""/nil/' + @echo "-- EOF" + +# list targets that do not create files (but not all makes understand .PHONY) +.PHONY: all $(PLATS) clean test install local none dummy echo pecho lecho + +# (end of Makefile) diff --git a/contrib/syslinux-4.02/com32/lua/README b/contrib/syslinux-4.02/com32/lua/README new file mode 100644 index 0000000..11b4dff --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/README @@ -0,0 +1,37 @@ +README for Lua 5.1 + +See INSTALL for installation instructions. +See HISTORY for a summary of changes since the last released version. + +* What is Lua? + ------------ + Lua is a powerful, light-weight programming language designed for extending + applications. Lua is also frequently used as a general-purpose, stand-alone + language. Lua is free software. + + For complete information, visit Lua's web site at http://www.lua.org/ . + For an executive summary, see http://www.lua.org/about.html . + + Lua has been used in many different projects around the world. + For a short list, see http://www.lua.org/uses.html . + +* Availability + ------------ + Lua is freely available for both academic and commercial purposes. + See COPYRIGHT and http://www.lua.org/license.html for details. + Lua can be downloaded at http://www.lua.org/download.html . + +* Installation + ------------ + Lua is implemented in pure ANSI C, and compiles unmodified in all known + platforms that have an ANSI C compiler. In most Unix-like platforms, simply + do "make" with a suitable target. See INSTALL for detailed instructions. + +* Origin + ------ + Lua is developed at Lua.org, a laboratory of the Department of Computer + Science of PUC-Rio (the Pontifical Catholic University of Rio de Janeiro + in Brazil). + For more information about the authors, see http://www.lua.org/authors.html . + +(end of README) diff --git a/contrib/syslinux-4.02/com32/lua/doc/amazon.gif b/contrib/syslinux-4.02/com32/lua/doc/amazon.gif Binary files differnew file mode 100644 index 0000000..f2586d5 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/doc/amazon.gif diff --git a/contrib/syslinux-4.02/com32/lua/doc/contents.html b/contrib/syslinux-4.02/com32/lua/doc/contents.html new file mode 100644 index 0000000..8e58e18 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/doc/contents.html @@ -0,0 +1,499 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<HTML> +<HEAD> +<TITLE>Lua 5.1 Reference Manual - contents</TITLE> +<LINK REL="stylesheet" TYPE="text/css" HREF="lua.css"> +<META HTTP-EQUIV="content-type" CONTENT="text/html; charset=iso-8859-1"> +<STYLE TYPE="text/css"> +ul { + list-style-type: none ; + list-style-position: outside ; +} +</STYLE> +</HEAD> + +<BODY> + +<HR> +<H1> +<A HREF="http://www.lua.org/"><IMG SRC="logo.gif" ALT="" BORDER=0></A> +Lua 5.1 Reference Manual +</H1> + +This is an online version of +<BLOCKQUOTE> +<A HREF="http://www.amazon.com/exec/obidos/ASIN/8590379833/lua-indexmanual-20"> +<IMG SRC="cover.png" ALT="" TITLE="buy from Amazon" BORDER=1 ALIGN="left" HSPACE=12> +</A> +<B>Lua 5.1 Reference Manual</B> +<BR>by R. Ierusalimschy, L. H. de Figueiredo, W. Celes +<BR>Lua.org, August 2006 +<BR>ISBN 85-903798-3-3 +<BR><A HREF="http://www.amazon.com/exec/obidos/ASIN/8590379833/lua-indexmanual-20"> +<IMG SRC="amazon.gif" ALT="[Buy from Amazon]" BORDER=0></A> +<BR CLEAR="all"> +</BLOCKQUOTE> +<P> + +Buy a copy of this book and +<A HREF="http://www.lua.org/donations.html">help to support</A> +the Lua project. +<P> + +The reference manual is the official definition of the Lua language. +For a complete introduction to Lua programming, see the book +<A HREF="http://www.lua.org/docs.html#books">Programming in Lua</A>. +<P> + +<A HREF="manual.html">start</A> +· +<A HREF="#contents">contents</A> +· +<A HREF="#index">index</A> +· +<A HREF="http://www.lua.org/manual/5.1/pt/">português</A> +· +<A HREF="http://www.lua.org/manual/5.1/es/">español</A> +<HR> +<SMALL> +Copyright © 2006-2008 Lua.org, PUC-Rio. +Freely available under the terms of the +<a href="http://www.lua.org/license.html#5">Lua license</a>. +</SMALL> +<P> + +<H2><A NAME="contents">Contents</A></H2> +<UL style="padding: 0"> +<LI><A HREF="manual.html">1 - Introduction</A> +<P> +<LI><A HREF="manual.html#2">2 - The Language</A> +<UL> +<LI><A HREF="manual.html#2.1">2.1 - Lexical Conventions</A> +<LI><A HREF="manual.html#2.2">2.2 - Values and Types</A> +<UL> +<LI><A HREF="manual.html#2.2.1">2.2.1 - Coercion</A> +</UL> +<LI><A HREF="manual.html#2.3">2.3 - Variables</A> +<LI><A HREF="manual.html#2.4">2.4 - Statements</A> +<UL> +<LI><A HREF="manual.html#2.4.1">2.4.1 - Chunks</A> +<LI><A HREF="manual.html#2.4.2">2.4.2 - Blocks</A> +<LI><A HREF="manual.html#2.4.3">2.4.3 - Assignment</A> +<LI><A HREF="manual.html#2.4.4">2.4.4 - Control Structures</A> +<LI><A HREF="manual.html#2.4.5">2.4.5 - For Statement</A> +<LI><A HREF="manual.html#2.4.6">2.4.6 - Function Calls as Statements</A> +<LI><A HREF="manual.html#2.4.7">2.4.7 - Local Declarations</A> +</UL> +<LI><A HREF="manual.html#2.5">2.5 - Expressions</A> +<UL> +<LI><A HREF="manual.html#2.5.1">2.5.1 - Arithmetic Operators</A> +<LI><A HREF="manual.html#2.5.2">2.5.2 - Relational Operators</A> +<LI><A HREF="manual.html#2.5.3">2.5.3 - Logical Operators</A> +<LI><A HREF="manual.html#2.5.4">2.5.4 - Concatenation</A> +<LI><A HREF="manual.html#2.5.5">2.5.5 - The Length Operator</A> +<LI><A HREF="manual.html#2.5.6">2.5.6 - Precedence</A> +<LI><A HREF="manual.html#2.5.7">2.5.7 - Table Constructors</A> +<LI><A HREF="manual.html#2.5.8">2.5.8 - Function Calls</A> +<LI><A HREF="manual.html#2.5.9">2.5.9 - Function Definitions</A> +</UL> +<LI><A HREF="manual.html#2.6">2.6 - Visibility Rules</A> +<LI><A HREF="manual.html#2.7">2.7 - Error Handling</A> +<LI><A HREF="manual.html#2.8">2.8 - Metatables</A> +<LI><A HREF="manual.html#2.9">2.9 - Environments</A> +<LI><A HREF="manual.html#2.10">2.10 - Garbage Collection</A> +<UL> +<LI><A HREF="manual.html#2.10.1">2.10.1 - Garbage-Collection Metamethods</A> +<LI><A HREF="manual.html#2.10.2">2.10.2 - Weak Tables</A> +</UL> +<LI><A HREF="manual.html#2.11">2.11 - Coroutines</A> +</UL> +<P> +<LI><A HREF="manual.html#3">3 - The Application Program Interface</A> +<UL> +<LI><A HREF="manual.html#3.1">3.1 - The Stack</A> +<LI><A HREF="manual.html#3.2">3.2 - Stack Size</A> +<LI><A HREF="manual.html#3.3">3.3 - Pseudo-Indices</A> +<LI><A HREF="manual.html#3.4">3.4 - C Closures</A> +<LI><A HREF="manual.html#3.5">3.5 - Registry</A> +<LI><A HREF="manual.html#3.6">3.6 - Error Handling in C</A> +<LI><A HREF="manual.html#3.7">3.7 - Functions and Types</A> +<LI><A HREF="manual.html#3.8">3.8 - The Debug Interface</A> +</UL> +<P> +<LI><A HREF="manual.html#4">4 - The Auxiliary Library</A> +<UL> +<LI><A HREF="manual.html#4.1">4.1 - Functions and Types</A> +</UL> +<P> +<LI><A HREF="manual.html#5">5 - Standard Libraries</A> +<UL> +<LI><A HREF="manual.html#5.1">5.1 - Basic Functions</A> +<LI><A HREF="manual.html#5.2">5.2 - Coroutine Manipulation</A> +<LI><A HREF="manual.html#5.3">5.3 - Modules</A> +<LI><A HREF="manual.html#5.4">5.4 - String Manipulation</A> +<UL> +<LI><A HREF="manual.html#5.4.1">5.4.1 - Patterns</A> +</UL> +<LI><A HREF="manual.html#5.5">5.5 - Table Manipulation</A> +<LI><A HREF="manual.html#5.6">5.6 - Mathematical Functions</A> +<LI><A HREF="manual.html#5.7">5.7 - Input and Output Facilities</A> +<LI><A HREF="manual.html#5.8">5.8 - Operating System Facilities</A> +<LI><A HREF="manual.html#5.9">5.9 - The Debug Library</A> +</UL> +<P> +<LI><A HREF="manual.html#6">6 - Lua Stand-alone</A> +<P> +<LI><A HREF="manual.html#7">7 - Incompatibilities with the Previous Version</A> +<UL> +<LI><A HREF="manual.html#7.1">7.1 - Changes in the Language</A> +<LI><A HREF="manual.html#7.2">7.2 - Changes in the Libraries</A> +<LI><A HREF="manual.html#7.3">7.3 - Changes in the API</A> +</UL> +<P> +<LI><A HREF="manual.html#8">8 - The Complete Syntax of Lua</A> +</UL> + +<H2><A NAME="index">Index</A></H2> +<TABLE WIDTH="100%"> +<TR VALIGN="top"> +<TD> +<H3><A NAME="functions">Lua functions</A></H3> +<A HREF="manual.html#pdf-_G">_G</A><BR> +<A HREF="manual.html#pdf-_VERSION">_VERSION</A><BR> +<A HREF="manual.html#pdf-assert">assert</A><BR> +<A HREF="manual.html#pdf-collectgarbage">collectgarbage</A><BR> +<A HREF="manual.html#pdf-dofile">dofile</A><BR> +<A HREF="manual.html#pdf-error">error</A><BR> +<A HREF="manual.html#pdf-getfenv">getfenv</A><BR> +<A HREF="manual.html#pdf-getmetatable">getmetatable</A><BR> +<A HREF="manual.html#pdf-ipairs">ipairs</A><BR> +<A HREF="manual.html#pdf-load">load</A><BR> +<A HREF="manual.html#pdf-loadfile">loadfile</A><BR> +<A HREF="manual.html#pdf-loadstring">loadstring</A><BR> +<A HREF="manual.html#pdf-module">module</A><BR> +<A HREF="manual.html#pdf-next">next</A><BR> +<A HREF="manual.html#pdf-pairs">pairs</A><BR> +<A HREF="manual.html#pdf-pcall">pcall</A><BR> +<A HREF="manual.html#pdf-print">print</A><BR> +<A HREF="manual.html#pdf-rawequal">rawequal</A><BR> +<A HREF="manual.html#pdf-rawget">rawget</A><BR> +<A HREF="manual.html#pdf-rawset">rawset</A><BR> +<A HREF="manual.html#pdf-require">require</A><BR> +<A HREF="manual.html#pdf-select">select</A><BR> +<A HREF="manual.html#pdf-setfenv">setfenv</A><BR> +<A HREF="manual.html#pdf-setmetatable">setmetatable</A><BR> +<A HREF="manual.html#pdf-tonumber">tonumber</A><BR> +<A HREF="manual.html#pdf-tostring">tostring</A><BR> +<A HREF="manual.html#pdf-type">type</A><BR> +<A HREF="manual.html#pdf-unpack">unpack</A><BR> +<A HREF="manual.html#pdf-xpcall">xpcall</A><BR> +<P> + +<A HREF="manual.html#pdf-coroutine.create">coroutine.create</A><BR> +<A HREF="manual.html#pdf-coroutine.resume">coroutine.resume</A><BR> +<A HREF="manual.html#pdf-coroutine.running">coroutine.running</A><BR> +<A HREF="manual.html#pdf-coroutine.status">coroutine.status</A><BR> +<A HREF="manual.html#pdf-coroutine.wrap">coroutine.wrap</A><BR> +<A HREF="manual.html#pdf-coroutine.yield">coroutine.yield</A><BR> +<P> + +<A HREF="manual.html#pdf-debug.debug">debug.debug</A><BR> +<A HREF="manual.html#pdf-debug.getfenv">debug.getfenv</A><BR> +<A HREF="manual.html#pdf-debug.gethook">debug.gethook</A><BR> +<A HREF="manual.html#pdf-debug.getinfo">debug.getinfo</A><BR> +<A HREF="manual.html#pdf-debug.getlocal">debug.getlocal</A><BR> +<A HREF="manual.html#pdf-debug.getmetatable">debug.getmetatable</A><BR> +<A HREF="manual.html#pdf-debug.getregistry">debug.getregistry</A><BR> +<A HREF="manual.html#pdf-debug.getupvalue">debug.getupvalue</A><BR> +<A HREF="manual.html#pdf-debug.setfenv">debug.setfenv</A><BR> +<A HREF="manual.html#pdf-debug.sethook">debug.sethook</A><BR> +<A HREF="manual.html#pdf-debug.setlocal">debug.setlocal</A><BR> +<A HREF="manual.html#pdf-debug.setmetatable">debug.setmetatable</A><BR> +<A HREF="manual.html#pdf-debug.setupvalue">debug.setupvalue</A><BR> +<A HREF="manual.html#pdf-debug.traceback">debug.traceback</A><BR> + +</TD> +<TD> +<H3> </H3> +<A HREF="manual.html#pdf-file:close">file:close</A><BR> +<A HREF="manual.html#pdf-file:flush">file:flush</A><BR> +<A HREF="manual.html#pdf-file:lines">file:lines</A><BR> +<A HREF="manual.html#pdf-file:read">file:read</A><BR> +<A HREF="manual.html#pdf-file:seek">file:seek</A><BR> +<A HREF="manual.html#pdf-file:setvbuf">file:setvbuf</A><BR> +<A HREF="manual.html#pdf-file:write">file:write</A><BR> +<P> + +<A HREF="manual.html#pdf-io.close">io.close</A><BR> +<A HREF="manual.html#pdf-io.flush">io.flush</A><BR> +<A HREF="manual.html#pdf-io.input">io.input</A><BR> +<A HREF="manual.html#pdf-io.lines">io.lines</A><BR> +<A HREF="manual.html#pdf-io.open">io.open</A><BR> +<A HREF="manual.html#pdf-io.output">io.output</A><BR> +<A HREF="manual.html#pdf-io.popen">io.popen</A><BR> +<A HREF="manual.html#pdf-io.read">io.read</A><BR> +<A HREF="manual.html#pdf-io.stderr">io.stderr</A><BR> +<A HREF="manual.html#pdf-io.stdin">io.stdin</A><BR> +<A HREF="manual.html#pdf-io.stdout">io.stdout</A><BR> +<A HREF="manual.html#pdf-io.tmpfile">io.tmpfile</A><BR> +<A HREF="manual.html#pdf-io.type">io.type</A><BR> +<A HREF="manual.html#pdf-io.write">io.write</A><BR> +<P> + +<A HREF="manual.html#pdf-math.abs">math.abs</A><BR> +<A HREF="manual.html#pdf-math.acos">math.acos</A><BR> +<A HREF="manual.html#pdf-math.asin">math.asin</A><BR> +<A HREF="manual.html#pdf-math.atan">math.atan</A><BR> +<A HREF="manual.html#pdf-math.atan2">math.atan2</A><BR> +<A HREF="manual.html#pdf-math.ceil">math.ceil</A><BR> +<A HREF="manual.html#pdf-math.cos">math.cos</A><BR> +<A HREF="manual.html#pdf-math.cosh">math.cosh</A><BR> +<A HREF="manual.html#pdf-math.deg">math.deg</A><BR> +<A HREF="manual.html#pdf-math.exp">math.exp</A><BR> +<A HREF="manual.html#pdf-math.floor">math.floor</A><BR> +<A HREF="manual.html#pdf-math.fmod">math.fmod</A><BR> +<A HREF="manual.html#pdf-math.frexp">math.frexp</A><BR> +<A HREF="manual.html#pdf-math.huge">math.huge</A><BR> +<A HREF="manual.html#pdf-math.ldexp">math.ldexp</A><BR> +<A HREF="manual.html#pdf-math.log">math.log</A><BR> +<A HREF="manual.html#pdf-math.log10">math.log10</A><BR> +<A HREF="manual.html#pdf-math.max">math.max</A><BR> +<A HREF="manual.html#pdf-math.min">math.min</A><BR> +<A HREF="manual.html#pdf-math.modf">math.modf</A><BR> +<A HREF="manual.html#pdf-math.pi">math.pi</A><BR> +<A HREF="manual.html#pdf-math.pow">math.pow</A><BR> +<A HREF="manual.html#pdf-math.rad">math.rad</A><BR> +<A HREF="manual.html#pdf-math.random">math.random</A><BR> +<A HREF="manual.html#pdf-math.randomseed">math.randomseed</A><BR> +<A HREF="manual.html#pdf-math.sin">math.sin</A><BR> +<A HREF="manual.html#pdf-math.sinh">math.sinh</A><BR> +<A HREF="manual.html#pdf-math.sqrt">math.sqrt</A><BR> +<A HREF="manual.html#pdf-math.tan">math.tan</A><BR> +<A HREF="manual.html#pdf-math.tanh">math.tanh</A><BR> +<P> + +<A HREF="manual.html#pdf-os.clock">os.clock</A><BR> +<A HREF="manual.html#pdf-os.date">os.date</A><BR> +<A HREF="manual.html#pdf-os.difftime">os.difftime</A><BR> +<A HREF="manual.html#pdf-os.execute">os.execute</A><BR> +<A HREF="manual.html#pdf-os.exit">os.exit</A><BR> +<A HREF="manual.html#pdf-os.getenv">os.getenv</A><BR> +<A HREF="manual.html#pdf-os.remove">os.remove</A><BR> +<A HREF="manual.html#pdf-os.rename">os.rename</A><BR> +<A HREF="manual.html#pdf-os.setlocale">os.setlocale</A><BR> +<A HREF="manual.html#pdf-os.time">os.time</A><BR> +<A HREF="manual.html#pdf-os.tmpname">os.tmpname</A><BR> +<P> + +<A HREF="manual.html#pdf-package.cpath">package.cpath</A><BR> +<A HREF="manual.html#pdf-package.loaded">package.loaded</A><BR> +<A HREF="manual.html#pdf-package.loaders">package.loaders</A><BR> +<A HREF="manual.html#pdf-package.loadlib">package.loadlib</A><BR> +<A HREF="manual.html#pdf-package.path">package.path</A><BR> +<A HREF="manual.html#pdf-package.preload">package.preload</A><BR> +<A HREF="manual.html#pdf-package.seeall">package.seeall</A><BR> +<P> + +<A HREF="manual.html#pdf-string.byte">string.byte</A><BR> +<A HREF="manual.html#pdf-string.char">string.char</A><BR> +<A HREF="manual.html#pdf-string.dump">string.dump</A><BR> +<A HREF="manual.html#pdf-string.find">string.find</A><BR> +<A HREF="manual.html#pdf-string.format">string.format</A><BR> +<A HREF="manual.html#pdf-string.gmatch">string.gmatch</A><BR> +<A HREF="manual.html#pdf-string.gsub">string.gsub</A><BR> +<A HREF="manual.html#pdf-string.len">string.len</A><BR> +<A HREF="manual.html#pdf-string.lower">string.lower</A><BR> +<A HREF="manual.html#pdf-string.match">string.match</A><BR> +<A HREF="manual.html#pdf-string.rep">string.rep</A><BR> +<A HREF="manual.html#pdf-string.reverse">string.reverse</A><BR> +<A HREF="manual.html#pdf-string.sub">string.sub</A><BR> +<A HREF="manual.html#pdf-string.upper">string.upper</A><BR> +<P> + +<A HREF="manual.html#pdf-table.concat">table.concat</A><BR> +<A HREF="manual.html#pdf-table.insert">table.insert</A><BR> +<A HREF="manual.html#pdf-table.maxn">table.maxn</A><BR> +<A HREF="manual.html#pdf-table.remove">table.remove</A><BR> +<A HREF="manual.html#pdf-table.sort">table.sort</A><BR> + +</TD> +<TD> +<H3>C API</H3> +<A HREF="manual.html#lua_Alloc">lua_Alloc</A><BR> +<A HREF="manual.html#lua_CFunction">lua_CFunction</A><BR> +<A HREF="manual.html#lua_Debug">lua_Debug</A><BR> +<A HREF="manual.html#lua_Hook">lua_Hook</A><BR> +<A HREF="manual.html#lua_Integer">lua_Integer</A><BR> +<A HREF="manual.html#lua_Number">lua_Number</A><BR> +<A HREF="manual.html#lua_Reader">lua_Reader</A><BR> +<A HREF="manual.html#lua_State">lua_State</A><BR> +<A HREF="manual.html#lua_Writer">lua_Writer</A><BR> +<P> + +<A HREF="manual.html#lua_atpanic">lua_atpanic</A><BR> +<A HREF="manual.html#lua_call">lua_call</A><BR> +<A HREF="manual.html#lua_checkstack">lua_checkstack</A><BR> +<A HREF="manual.html#lua_close">lua_close</A><BR> +<A HREF="manual.html#lua_concat">lua_concat</A><BR> +<A HREF="manual.html#lua_cpcall">lua_cpcall</A><BR> +<A HREF="manual.html#lua_createtable">lua_createtable</A><BR> +<A HREF="manual.html#lua_dump">lua_dump</A><BR> +<A HREF="manual.html#lua_equal">lua_equal</A><BR> +<A HREF="manual.html#lua_error">lua_error</A><BR> +<A HREF="manual.html#lua_gc">lua_gc</A><BR> +<A HREF="manual.html#lua_getallocf">lua_getallocf</A><BR> +<A HREF="manual.html#lua_getfenv">lua_getfenv</A><BR> +<A HREF="manual.html#lua_getfield">lua_getfield</A><BR> +<A HREF="manual.html#lua_getglobal">lua_getglobal</A><BR> +<A HREF="manual.html#lua_gethook">lua_gethook</A><BR> +<A HREF="manual.html#lua_gethookcount">lua_gethookcount</A><BR> +<A HREF="manual.html#lua_gethookmask">lua_gethookmask</A><BR> +<A HREF="manual.html#lua_getinfo">lua_getinfo</A><BR> +<A HREF="manual.html#lua_getlocal">lua_getlocal</A><BR> +<A HREF="manual.html#lua_getmetatable">lua_getmetatable</A><BR> +<A HREF="manual.html#lua_getstack">lua_getstack</A><BR> +<A HREF="manual.html#lua_gettable">lua_gettable</A><BR> +<A HREF="manual.html#lua_gettop">lua_gettop</A><BR> +<A HREF="manual.html#lua_getupvalue">lua_getupvalue</A><BR> +<A HREF="manual.html#lua_insert">lua_insert</A><BR> +<A HREF="manual.html#lua_isboolean">lua_isboolean</A><BR> +<A HREF="manual.html#lua_iscfunction">lua_iscfunction</A><BR> +<A HREF="manual.html#lua_isfunction">lua_isfunction</A><BR> +<A HREF="manual.html#lua_islightuserdata">lua_islightuserdata</A><BR> +<A HREF="manual.html#lua_isnil">lua_isnil</A><BR> +<A HREF="manual.html#lua_isnone">lua_isnone</A><BR> +<A HREF="manual.html#lua_isnoneornil">lua_isnoneornil</A><BR> +<A HREF="manual.html#lua_isnumber">lua_isnumber</A><BR> +<A HREF="manual.html#lua_isstring">lua_isstring</A><BR> +<A HREF="manual.html#lua_istable">lua_istable</A><BR> +<A HREF="manual.html#lua_isthread">lua_isthread</A><BR> +<A HREF="manual.html#lua_isuserdata">lua_isuserdata</A><BR> +<A HREF="manual.html#lua_lessthan">lua_lessthan</A><BR> +<A HREF="manual.html#lua_load">lua_load</A><BR> +<A HREF="manual.html#lua_newstate">lua_newstate</A><BR> +<A HREF="manual.html#lua_newtable">lua_newtable</A><BR> +<A HREF="manual.html#lua_newthread">lua_newthread</A><BR> +<A HREF="manual.html#lua_newuserdata">lua_newuserdata</A><BR> +<A HREF="manual.html#lua_next">lua_next</A><BR> +<A HREF="manual.html#lua_objlen">lua_objlen</A><BR> +<A HREF="manual.html#lua_pcall">lua_pcall</A><BR> +<A HREF="manual.html#lua_pop">lua_pop</A><BR> +<A HREF="manual.html#lua_pushboolean">lua_pushboolean</A><BR> +<A HREF="manual.html#lua_pushcclosure">lua_pushcclosure</A><BR> +<A HREF="manual.html#lua_pushcfunction">lua_pushcfunction</A><BR> +<A HREF="manual.html#lua_pushfstring">lua_pushfstring</A><BR> +<A HREF="manual.html#lua_pushinteger">lua_pushinteger</A><BR> +<A HREF="manual.html#lua_pushlightuserdata">lua_pushlightuserdata</A><BR> +<A HREF="manual.html#lua_pushliteral">lua_pushliteral</A><BR> +<A HREF="manual.html#lua_pushlstring">lua_pushlstring</A><BR> +<A HREF="manual.html#lua_pushnil">lua_pushnil</A><BR> +<A HREF="manual.html#lua_pushnumber">lua_pushnumber</A><BR> +<A HREF="manual.html#lua_pushstring">lua_pushstring</A><BR> +<A HREF="manual.html#lua_pushthread">lua_pushthread</A><BR> +<A HREF="manual.html#lua_pushvalue">lua_pushvalue</A><BR> +<A HREF="manual.html#lua_pushvfstring">lua_pushvfstring</A><BR> +<A HREF="manual.html#lua_rawequal">lua_rawequal</A><BR> +<A HREF="manual.html#lua_rawget">lua_rawget</A><BR> +<A HREF="manual.html#lua_rawgeti">lua_rawgeti</A><BR> +<A HREF="manual.html#lua_rawset">lua_rawset</A><BR> +<A HREF="manual.html#lua_rawseti">lua_rawseti</A><BR> +<A HREF="manual.html#lua_register">lua_register</A><BR> +<A HREF="manual.html#lua_remove">lua_remove</A><BR> +<A HREF="manual.html#lua_replace">lua_replace</A><BR> +<A HREF="manual.html#lua_resume">lua_resume</A><BR> +<A HREF="manual.html#lua_setallocf">lua_setallocf</A><BR> +<A HREF="manual.html#lua_setfenv">lua_setfenv</A><BR> +<A HREF="manual.html#lua_setfield">lua_setfield</A><BR> +<A HREF="manual.html#lua_setglobal">lua_setglobal</A><BR> +<A HREF="manual.html#lua_sethook">lua_sethook</A><BR> +<A HREF="manual.html#lua_setlocal">lua_setlocal</A><BR> +<A HREF="manual.html#lua_setmetatable">lua_setmetatable</A><BR> +<A HREF="manual.html#lua_settable">lua_settable</A><BR> +<A HREF="manual.html#lua_settop">lua_settop</A><BR> +<A HREF="manual.html#lua_setupvalue">lua_setupvalue</A><BR> +<A HREF="manual.html#lua_status">lua_status</A><BR> +<A HREF="manual.html#lua_toboolean">lua_toboolean</A><BR> +<A HREF="manual.html#lua_tocfunction">lua_tocfunction</A><BR> +<A HREF="manual.html#lua_tointeger">lua_tointeger</A><BR> +<A HREF="manual.html#lua_tolstring">lua_tolstring</A><BR> +<A HREF="manual.html#lua_tonumber">lua_tonumber</A><BR> +<A HREF="manual.html#lua_topointer">lua_topointer</A><BR> +<A HREF="manual.html#lua_tostring">lua_tostring</A><BR> +<A HREF="manual.html#lua_tothread">lua_tothread</A><BR> +<A HREF="manual.html#lua_touserdata">lua_touserdata</A><BR> +<A HREF="manual.html#lua_type">lua_type</A><BR> +<A HREF="manual.html#lua_typename">lua_typename</A><BR> +<A HREF="manual.html#lua_upvalueindex">lua_upvalueindex</A><BR> +<A HREF="manual.html#lua_xmove">lua_xmove</A><BR> +<A HREF="manual.html#lua_yield">lua_yield</A><BR> + +</TD> +<TD> +<H3>auxiliary library</H3> +<A HREF="manual.html#luaL_Buffer">luaL_Buffer</A><BR> +<A HREF="manual.html#luaL_Reg">luaL_Reg</A><BR> +<P> + +<A HREF="manual.html#luaL_addchar">luaL_addchar</A><BR> +<A HREF="manual.html#luaL_addlstring">luaL_addlstring</A><BR> +<A HREF="manual.html#luaL_addsize">luaL_addsize</A><BR> +<A HREF="manual.html#luaL_addstring">luaL_addstring</A><BR> +<A HREF="manual.html#luaL_addvalue">luaL_addvalue</A><BR> +<A HREF="manual.html#luaL_argcheck">luaL_argcheck</A><BR> +<A HREF="manual.html#luaL_argerror">luaL_argerror</A><BR> +<A HREF="manual.html#luaL_buffinit">luaL_buffinit</A><BR> +<A HREF="manual.html#luaL_callmeta">luaL_callmeta</A><BR> +<A HREF="manual.html#luaL_checkany">luaL_checkany</A><BR> +<A HREF="manual.html#luaL_checkint">luaL_checkint</A><BR> +<A HREF="manual.html#luaL_checkinteger">luaL_checkinteger</A><BR> +<A HREF="manual.html#luaL_checklong">luaL_checklong</A><BR> +<A HREF="manual.html#luaL_checklstring">luaL_checklstring</A><BR> +<A HREF="manual.html#luaL_checknumber">luaL_checknumber</A><BR> +<A HREF="manual.html#luaL_checkoption">luaL_checkoption</A><BR> +<A HREF="manual.html#luaL_checkstack">luaL_checkstack</A><BR> +<A HREF="manual.html#luaL_checkstring">luaL_checkstring</A><BR> +<A HREF="manual.html#luaL_checktype">luaL_checktype</A><BR> +<A HREF="manual.html#luaL_checkudata">luaL_checkudata</A><BR> +<A HREF="manual.html#luaL_dofile">luaL_dofile</A><BR> +<A HREF="manual.html#luaL_dostring">luaL_dostring</A><BR> +<A HREF="manual.html#luaL_error">luaL_error</A><BR> +<A HREF="manual.html#luaL_getmetafield">luaL_getmetafield</A><BR> +<A HREF="manual.html#luaL_getmetatable">luaL_getmetatable</A><BR> +<A HREF="manual.html#luaL_gsub">luaL_gsub</A><BR> +<A HREF="manual.html#luaL_loadbuffer">luaL_loadbuffer</A><BR> +<A HREF="manual.html#luaL_loadfile">luaL_loadfile</A><BR> +<A HREF="manual.html#luaL_loadstring">luaL_loadstring</A><BR> +<A HREF="manual.html#luaL_newmetatable">luaL_newmetatable</A><BR> +<A HREF="manual.html#luaL_newstate">luaL_newstate</A><BR> +<A HREF="manual.html#luaL_openlibs">luaL_openlibs</A><BR> +<A HREF="manual.html#luaL_optint">luaL_optint</A><BR> +<A HREF="manual.html#luaL_optinteger">luaL_optinteger</A><BR> +<A HREF="manual.html#luaL_optlong">luaL_optlong</A><BR> +<A HREF="manual.html#luaL_optlstring">luaL_optlstring</A><BR> +<A HREF="manual.html#luaL_optnumber">luaL_optnumber</A><BR> +<A HREF="manual.html#luaL_optstring">luaL_optstring</A><BR> +<A HREF="manual.html#luaL_prepbuffer">luaL_prepbuffer</A><BR> +<A HREF="manual.html#luaL_pushresult">luaL_pushresult</A><BR> +<A HREF="manual.html#luaL_ref">luaL_ref</A><BR> +<A HREF="manual.html#luaL_register">luaL_register</A><BR> +<A HREF="manual.html#luaL_typename">luaL_typename</A><BR> +<A HREF="manual.html#luaL_typerror">luaL_typerror</A><BR> +<A HREF="manual.html#luaL_unref">luaL_unref</A><BR> +<A HREF="manual.html#luaL_where">luaL_where</A><BR> + +</TD> +</TR> +</TABLE> +<P> + +<HR> +<SMALL> +Last update: +Sat Jan 19 13:24:29 BRST 2008 +</SMALL> +<!-- +Last change: revised for Lua 5.1.3 +--> + +</BODY> +</HTML> diff --git a/contrib/syslinux-4.02/com32/lua/doc/cover.png b/contrib/syslinux-4.02/com32/lua/doc/cover.png Binary files differnew file mode 100644 index 0000000..2dbb198 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/doc/cover.png diff --git a/contrib/syslinux-4.02/com32/lua/doc/logo.gif b/contrib/syslinux-4.02/com32/lua/doc/logo.gif Binary files differnew file mode 100644 index 0000000..2f5e4ac --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/doc/logo.gif diff --git a/contrib/syslinux-4.02/com32/lua/doc/lua.1 b/contrib/syslinux-4.02/com32/lua/doc/lua.1 new file mode 100644 index 0000000..24809cc --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/doc/lua.1 @@ -0,0 +1,163 @@ +.\" $Id: lua.man,v 1.11 2006/01/06 16:03:34 lhf Exp $ +.TH LUA 1 "$Date: 2006/01/06 16:03:34 $" +.SH NAME +lua \- Lua interpreter +.SH SYNOPSIS +.B lua +[ +.I options +] +[ +.I script +[ +.I args +] +] +.SH DESCRIPTION +.B lua +is the stand-alone Lua interpreter. +It loads and executes Lua programs, +either in textual source form or +in precompiled binary form. +(Precompiled binaries are output by +.BR luac , +the Lua compiler.) +.B lua +can be used as a batch interpreter and also interactively. +.LP +The given +.I options +(see below) +are executed and then +the Lua program in file +.I script +is loaded and executed. +The given +.I args +are available to +.I script +as strings in a global table named +.BR arg . +If these arguments contain spaces or other characters special to the shell, +then they should be quoted +(but note that the quotes will be removed by the shell). +The arguments in +.B arg +start at 0, +which contains the string +.RI ' script '. +The index of the last argument is stored in +.BR arg.n . +The arguments given in the command line before +.IR script , +including the name of the interpreter, +are available in negative indices in +.BR arg . +.LP +At the very start, +before even handling the command line, +.B lua +executes the contents of the environment variable +.BR LUA_INIT , +if it is defined. +If the value of +.B LUA_INIT +is of the form +.RI '@ filename ', +then +.I filename +is executed. +Otherwise, the string is assumed to be a Lua statement and is executed. +.LP +Options start with +.B '\-' +and are described below. +You can use +.B "'\--'" +to signal the end of options. +.LP +If no arguments are given, +then +.B "\-v \-i" +is assumed when the standard input is a terminal; +otherwise, +.B "\-" +is assumed. +.LP +In interactive mode, +.B lua +prompts the user, +reads lines from the standard input, +and executes them as they are read. +If a line does not contain a complete statement, +then a secondary prompt is displayed and +lines are read until a complete statement is formed or +a syntax error is found. +So, one way to interrupt the reading of an incomplete statement is +to force a syntax error: +adding a +.B ';' +in the middle of a statement is a sure way of forcing a syntax error +(except inside multiline strings and comments; these must be closed explicitly). +If a line starts with +.BR '=' , +then +.B lua +displays the values of all the expressions in the remainder of the +line. The expressions must be separated by commas. +The primary prompt is the value of the global variable +.BR _PROMPT , +if this value is a string; +otherwise, the default prompt is used. +Similarly, the secondary prompt is the value of the global variable +.BR _PROMPT2 . +So, +to change the prompts, +set the corresponding variable to a string of your choice. +You can do that after calling the interpreter +or on the command line +(but in this case you have to be careful with quotes +if the prompt string contains a space; otherwise you may confuse the shell.) +The default prompts are "> " and ">> ". +.SH OPTIONS +.TP +.B \- +load and execute the standard input as a file, +that is, +not interactively, +even when the standard input is a terminal. +.TP +.BI \-e " stat" +execute statement +.IR stat . +You need to quote +.I stat +if it contains spaces, quotes, +or other characters special to the shell. +.TP +.B \-i +enter interactive mode after +.I script +is executed. +.TP +.BI \-l " name" +call +.BI require(' name ') +before executing +.IR script . +Typically used to load libraries. +.TP +.B \-v +show version information. +.SH "SEE ALSO" +.BR luac (1) +.br +http://www.lua.org/ +.SH DIAGNOSTICS +Error messages should be self explanatory. +.SH AUTHORS +R. Ierusalimschy, +L. H. de Figueiredo, +and +W. Celes +.\" EOF diff --git a/contrib/syslinux-4.02/com32/lua/doc/lua.css b/contrib/syslinux-4.02/com32/lua/doc/lua.css new file mode 100644 index 0000000..039cf11 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/doc/lua.css @@ -0,0 +1,41 @@ +body { + color: #000000 ; + background-color: #FFFFFF ; + font-family: sans-serif ; + text-align: justify ; + margin-right: 20px ; + margin-left: 20px ; +} + +h1, h2, h3, h4 { + font-weight: normal ; + font-style: italic ; +} + +a:link { + color: #000080 ; + background-color: inherit ; + text-decoration: none ; +} + +a:visited { + background-color: inherit ; + text-decoration: none ; +} + +a:link:hover, a:visited:hover { + color: #000080 ; + background-color: #E0E0FF ; +} + +a:link:active, a:visited:active { + color: #FF0000 ; +} + +hr { + border: 0 ; + height: 1px ; + color: #a0a0a0 ; + background-color: #a0a0a0 ; +} + diff --git a/contrib/syslinux-4.02/com32/lua/doc/lua.html b/contrib/syslinux-4.02/com32/lua/doc/lua.html new file mode 100644 index 0000000..1d435ab --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/doc/lua.html @@ -0,0 +1,172 @@ +<!-- $Id: lua.man,v 1.11 2006/01/06 16:03:34 lhf Exp $ --> +<HTML> +<HEAD> +<TITLE>LUA man page</TITLE> +<LINK REL="stylesheet" TYPE="text/css" HREF="lua.css"> +</HEAD> + +<BODY BGCOLOR="#FFFFFF"> + +<H2>NAME</H2> +lua - Lua interpreter +<H2>SYNOPSIS</H2> +<B>lua</B> +[ +<I>options</I> +] +[ +<I>script</I> +[ +<I>args</I> +] +] +<H2>DESCRIPTION</H2> +<B>lua</B> +is the stand-alone Lua interpreter. +It loads and executes Lua programs, +either in textual source form or +in precompiled binary form. +(Precompiled binaries are output by +<B>luac</B>, +the Lua compiler.) +<B>lua</B> +can be used as a batch interpreter and also interactively. +<P> +The given +<I>options</I> +(see below) +are executed and then +the Lua program in file +<I>script</I> +is loaded and executed. +The given +<I>args</I> +are available to +<I>script</I> +as strings in a global table named +<B>arg</B>. +If these arguments contain spaces or other characters special to the shell, +then they should be quoted +(but note that the quotes will be removed by the shell). +The arguments in +<B>arg</B> +start at 0, +which contains the string +'<I>script</I>'. +The index of the last argument is stored in +<B>arg.n</B>. +The arguments given in the command line before +<I>script</I>, +including the name of the interpreter, +are available in negative indices in +<B>arg</B>. +<P> +At the very start, +before even handling the command line, +<B>lua</B> +executes the contents of the environment variable +<B>LUA_INIT</B>, +if it is defined. +If the value of +<B>LUA_INIT</B> +is of the form +'@<I>filename</I>', +then +<I>filename</I> +is executed. +Otherwise, the string is assumed to be a Lua statement and is executed. +<P> +Options start with +<B>'-'</B> +and are described below. +You can use +<B>'--'</B> +to signal the end of options. +<P> +If no arguments are given, +then +<B>"-v -i"</B> +is assumed when the standard input is a terminal; +otherwise, +<B>"-"</B> +is assumed. +<P> +In interactive mode, +<B>lua</B> +prompts the user, +reads lines from the standard input, +and executes them as they are read. +If a line does not contain a complete statement, +then a secondary prompt is displayed and +lines are read until a complete statement is formed or +a syntax error is found. +So, one way to interrupt the reading of an incomplete statement is +to force a syntax error: +adding a +<B>';'</B> +in the middle of a statement is a sure way of forcing a syntax error +(except inside multiline strings and comments; these must be closed explicitly). +If a line starts with +<B>'='</B>, +then +<B>lua</B> +displays the values of all the expressions in the remainder of the +line. The expressions must be separated by commas. +The primary prompt is the value of the global variable +<B>_PROMPT</B>, +if this value is a string; +otherwise, the default prompt is used. +Similarly, the secondary prompt is the value of the global variable +<B>_PROMPT2</B>. +So, +to change the prompts, +set the corresponding variable to a string of your choice. +You can do that after calling the interpreter +or on the command line +(but in this case you have to be careful with quotes +if the prompt string contains a space; otherwise you may confuse the shell.) +The default prompts are "> " and ">> ". +<H2>OPTIONS</H2> +<P> +<B>-</B> +load and execute the standard input as a file, +that is, +not interactively, +even when the standard input is a terminal. +<P> +<B>-e </B><I>stat</I> +execute statement +<I>stat</I>. +You need to quote +<I>stat </I> +if it contains spaces, quotes, +or other characters special to the shell. +<P> +<B>-i</B> +enter interactive mode after +<I>script</I> +is executed. +<P> +<B>-l </B><I>name</I> +call +<B>require</B>('<I>name</I>') +before executing +<I>script</I>. +Typically used to load libraries. +<P> +<B>-v</B> +show version information. +<H2>SEE ALSO</H2> +<B>luac</B>(1) +<BR> +<A HREF="http://www.lua.org/">http://www.lua.org/</A> +<H2>DIAGNOSTICS</H2> +Error messages should be self explanatory. +<H2>AUTHORS</H2> +R. Ierusalimschy, +L. H. de Figueiredo, +and +W. Celes +<!-- EOF --> +</BODY> +</HTML> diff --git a/contrib/syslinux-4.02/com32/lua/doc/luac.1 b/contrib/syslinux-4.02/com32/lua/doc/luac.1 new file mode 100644 index 0000000..d814678 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/doc/luac.1 @@ -0,0 +1,136 @@ +.\" $Id: luac.man,v 1.28 2006/01/06 16:03:34 lhf Exp $ +.TH LUAC 1 "$Date: 2006/01/06 16:03:34 $" +.SH NAME +luac \- Lua compiler +.SH SYNOPSIS +.B luac +[ +.I options +] [ +.I filenames +] +.SH DESCRIPTION +.B luac +is the Lua compiler. +It translates programs written in the Lua programming language +into binary files that can be later loaded and executed. +.LP +The main advantages of precompiling chunks are: +faster loading, +protecting source code from accidental user changes, +and +off-line syntax checking. +.LP +Pre-compiling does not imply faster execution +because in Lua chunks are always compiled into bytecodes before being executed. +.B luac +simply allows those bytecodes to be saved in a file for later execution. +.LP +Pre-compiled chunks are not necessarily smaller than the corresponding source. +The main goal in pre-compiling is faster loading. +.LP +The binary files created by +.B luac +are portable only among architectures with the same word size and byte order. +.LP +.B luac +produces a single output file containing the bytecodes +for all source files given. +By default, +the output file is named +.BR luac.out , +but you can change this with the +.B \-o +option. +.LP +In the command line, +you can mix +text files containing Lua source and +binary files containing precompiled chunks. +This is useful to combine several precompiled chunks, +even from different (but compatible) platforms, +into a single precompiled chunk. +.LP +You can use +.B "'\-'" +to indicate the standard input as a source file +and +.B "'\--'" +to signal the end of options +(that is, +all remaining arguments will be treated as files even if they start with +.BR "'\-'" ). +.LP +The internal format of the binary files produced by +.B luac +is likely to change when a new version of Lua is released. +So, +save the source files of all Lua programs that you precompile. +.LP +.SH OPTIONS +Options must be separate. +.TP +.B \-l +produce a listing of the compiled bytecode for Lua's virtual machine. +Listing bytecodes is useful to learn about Lua's virtual machine. +If no files are given, then +.B luac +loads +.B luac.out +and lists its contents. +.TP +.BI \-o " file" +output to +.IR file , +instead of the default +.BR luac.out . +(You can use +.B "'\-'" +for standard output, +but not on platforms that open standard output in text mode.) +The output file may be a source file because +all files are loaded before the output file is written. +Be careful not to overwrite precious files. +.TP +.B \-p +load files but do not generate any output file. +Used mainly for syntax checking and for testing precompiled chunks: +corrupted files will probably generate errors when loaded. +Lua always performs a thorough integrity test on precompiled chunks. +Bytecode that passes this test is completely safe, +in the sense that it will not break the interpreter. +However, +there is no guarantee that such code does anything sensible. +(None can be given, because the halting problem is unsolvable.) +If no files are given, then +.B luac +loads +.B luac.out +and tests its contents. +No messages are displayed if the file passes the integrity test. +.TP +.B \-s +strip debug information before writing the output file. +This saves some space in very large chunks, +but if errors occur when running a stripped chunk, +then the error messages may not contain the full information they usually do. +For instance, +line numbers and names of local variables are lost. +.TP +.B \-v +show version information. +.SH FILES +.TP 15 +.B luac.out +default output file +.SH "SEE ALSO" +.BR lua (1) +.br +http://www.lua.org/ +.SH DIAGNOSTICS +Error messages should be self explanatory. +.SH AUTHORS +L. H. de Figueiredo, +R. Ierusalimschy and +W. Celes +.\" EOF diff --git a/contrib/syslinux-4.02/com32/lua/doc/luac.html b/contrib/syslinux-4.02/com32/lua/doc/luac.html new file mode 100644 index 0000000..179ffe8 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/doc/luac.html @@ -0,0 +1,145 @@ +<!-- $Id: luac.man,v 1.28 2006/01/06 16:03:34 lhf Exp $ --> +<HTML> +<HEAD> +<TITLE>LUAC man page</TITLE> +<LINK REL="stylesheet" TYPE="text/css" HREF="lua.css"> +</HEAD> + +<BODY BGCOLOR="#FFFFFF"> + +<H2>NAME</H2> +luac - Lua compiler +<H2>SYNOPSIS</H2> +<B>luac</B> +[ +<I>options</I> +] [ +<I>filenames</I> +] +<H2>DESCRIPTION</H2> +<B>luac</B> +is the Lua compiler. +It translates programs written in the Lua programming language +into binary files that can be later loaded and executed. +<P> +The main advantages of precompiling chunks are: +faster loading, +protecting source code from accidental user changes, +and +off-line syntax checking. +<P> +Precompiling does not imply faster execution +because in Lua chunks are always compiled into bytecodes before being executed. +<B>luac</B> +simply allows those bytecodes to be saved in a file for later execution. +<P> +Precompiled chunks are not necessarily smaller than the corresponding source. +The main goal in precompiling is faster loading. +<P> +The binary files created by +<B>luac</B> +are portable only among architectures with the same word size and byte order. +<P> +<B>luac</B> +produces a single output file containing the bytecodes +for all source files given. +By default, +the output file is named +<B>luac.out</B>, +but you can change this with the +<B>-o</B> +option. +<P> +In the command line, +you can mix +text files containing Lua source and +binary files containing precompiled chunks. +This is useful because several precompiled chunks, +even from different (but compatible) platforms, +can be combined into a single precompiled chunk. +<P> +You can use +<B>'-'</B> +to indicate the standard input as a source file +and +<B>'--'</B> +to signal the end of options +(that is, +all remaining arguments will be treated as files even if they start with +<B>'-'</B>). +<P> +The internal format of the binary files produced by +<B>luac</B> +is likely to change when a new version of Lua is released. +So, +save the source files of all Lua programs that you precompile. +<P> +<H2>OPTIONS</H2> +Options must be separate. +<P> +<B>-l</B> +produce a listing of the compiled bytecode for Lua's virtual machine. +Listing bytecodes is useful to learn about Lua's virtual machine. +If no files are given, then +<B>luac</B> +loads +<B>luac.out</B> +and lists its contents. +<P> +<B>-o </B><I>file</I> +output to +<I>file</I>, +instead of the default +<B>luac.out</B>. +(You can use +<B>'-'</B> +for standard output, +but not on platforms that open standard output in text mode.) +The output file may be a source file because +all files are loaded before the output file is written. +Be careful not to overwrite precious files. +<P> +<B>-p</B> +load files but do not generate any output file. +Used mainly for syntax checking and for testing precompiled chunks: +corrupted files will probably generate errors when loaded. +Lua always performs a thorough integrity test on precompiled chunks. +Bytecode that passes this test is completely safe, +in the sense that it will not break the interpreter. +However, +there is no guarantee that such code does anything sensible. +(None can be given, because the halting problem is unsolvable.) +If no files are given, then +<B>luac</B> +loads +<B>luac.out</B> +and tests its contents. +No messages are displayed if the file passes the integrity test. +<P> +<B>-s</B> +strip debug information before writing the output file. +This saves some space in very large chunks, +but if errors occur when running a stripped chunk, +then the error messages may not contain the full information they usually do. +For instance, +line numbers and names of local variables are lost. +<P> +<B>-v</B> +show version information. +<H2>FILES</H2> +<P> +<B>luac.out</B> +default output file +<H2>SEE ALSO</H2> +<B>lua</B>(1) +<BR> +<A HREF="http://www.lua.org/">http://www.lua.org/</A> +<H2>DIAGNOSTICS</H2> +Error messages should be self explanatory. +<H2>AUTHORS</H2> +L. H. de Figueiredo, +R. Ierusalimschy and +W. Celes +<!-- EOF --> +</BODY> +</HTML> diff --git a/contrib/syslinux-4.02/com32/lua/doc/manual.css b/contrib/syslinux-4.02/com32/lua/doc/manual.css new file mode 100644 index 0000000..eed5afd --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/doc/manual.css @@ -0,0 +1,13 @@ +h3 code { + font-family: inherit ; +} + +pre { + font-size: 105% ; +} + +span.apii { + float: right ; + font-family: inherit ; +} + diff --git a/contrib/syslinux-4.02/com32/lua/doc/manual.html b/contrib/syslinux-4.02/com32/lua/doc/manual.html new file mode 100644 index 0000000..b125c13 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/doc/manual.html @@ -0,0 +1,8764 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> + +<head> +<title>Lua 5.1 Reference Manual</title> +<link rel="stylesheet" href="lua.css"> +<link rel="stylesheet" href="manual.css"> +<META HTTP-EQUIV="content-type" CONTENT="text/html; charset=iso-8859-1"> +</head> + +<body> + +<hr> +<h1> +<a href="http://www.lua.org/"><img src="logo.gif" alt="" border="0"></a> +Lua 5.1 Reference Manual +</h1> + +by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes +<p> +<small> +Copyright © 2006-2008 Lua.org, PUC-Rio. +Freely available under the terms of the +<a href="http://www.lua.org/license.html#5">Lua license</a>. +</small> +<hr> +<p> + +<a href="contents.html#contents">contents</A> +· +<a href="contents.html#index">index</A> + +<!-- ====================================================================== --> +<p> + +<!-- $Id: manual.of,v 1.45 2008/01/19 00:17:30 roberto Exp $ --> + + + + +<h1>1 - <a name="1">Introduction</a></h1> + +<p> +Lua is an extension programming language designed to support +general procedural programming with data description +facilities. +It also offers good support for object-oriented programming, +functional programming, and data-driven programming. +Lua is intended to be used as a powerful, light-weight +scripting language for any program that needs one. +Lua is implemented as a library, written in <em>clean</em> C +(that is, in the common subset of ANSI C and C++). + + +<p> +Being an extension language, Lua has no notion of a "main" program: +it only works <em>embedded</em> in a host client, +called the <em>embedding program</em> or simply the <em>host</em>. +This host program can invoke functions to execute a piece of Lua code, +can write and read Lua variables, +and can register C functions to be called by Lua code. +Through the use of C functions, Lua can be augmented to cope with +a wide range of different domains, +thus creating customized programming languages sharing a syntactical framework. +The Lua distribution includes a sample host program called <code>lua</code>, +which uses the Lua library to offer a complete, stand-alone Lua interpreter. + + +<p> +Lua is free software, +and is provided as usual with no guarantees, +as stated in its license. +The implementation described in this manual is available +at Lua's official web site, <code>www.lua.org</code>. + + +<p> +Like any other reference manual, +this document is dry in places. +For a discussion of the decisions behind the design of Lua, +see the technical papers available at Lua's web site. +For a detailed introduction to programming in Lua, +see Roberto's book, <em>Programming in Lua (Second Edition)</em>. + + + +<h1>2 - <a name="2">The Language</a></h1> + +<p> +This section describes the lexis, the syntax, and the semantics of Lua. +In other words, +this section describes +which tokens are valid, +how they can be combined, +and what their combinations mean. + + +<p> +The language constructs will be explained using the usual extended BNF notation, +in which +{<em>a</em>} means 0 or more <em>a</em>'s, and +[<em>a</em>] means an optional <em>a</em>. +Non-terminals are shown like non-terminal, +keywords are shown like <b>kword</b>, +and other terminal symbols are shown like `<b>=</b>´. +The complete syntax of Lua can be found at the end of this manual. + + + +<h2>2.1 - <a name="2.1">Lexical Conventions</a></h2> + +<p> +<em>Names</em> +(also called <em>identifiers</em>) +in Lua can be any string of letters, +digits, and underscores, +not beginning with a digit. +This coincides with the definition of names in most languages. +(The definition of letter depends on the current locale: +any character considered alphabetic by the current locale +can be used in an identifier.) +Identifiers are used to name variables and table fields. + + +<p> +The following <em>keywords</em> are reserved +and cannot be used as names: + + +<pre> + and break do else elseif + end false for function if + in local nil not or + repeat return then true until while +</pre> + +<p> +Lua is a case-sensitive language: +<code>and</code> is a reserved word, but <code>And</code> and <code>AND</code> +are two different, valid names. +As a convention, names starting with an underscore followed by +uppercase letters (such as <code>_VERSION</code>) +are reserved for internal global variables used by Lua. + + +<p> +The following strings denote other tokens: + +<pre> + + - * / % ^ # + == ~= <= >= < > = + ( ) { } [ ] + ; : , . .. ... +</pre> + +<p> +<em>Literal strings</em> +can be delimited by matching single or double quotes, +and can contain the following C-like escape sequences: +'<code>\a</code>' (bell), +'<code>\b</code>' (backspace), +'<code>\f</code>' (form feed), +'<code>\n</code>' (newline), +'<code>\r</code>' (carriage return), +'<code>\t</code>' (horizontal tab), +'<code>\v</code>' (vertical tab), +'<code>\\</code>' (backslash), +'<code>\"</code>' (quotation mark [double quote]), +and '<code>\'</code>' (apostrophe [single quote]). +Moreover, a backslash followed by a real newline +results in a newline in the string. +A character in a string may also be specified by its numerical value +using the escape sequence <code>\<em>ddd</em></code>, +where <em>ddd</em> is a sequence of up to three decimal digits. +(Note that if a numerical escape is to be followed by a digit, +it must be expressed using exactly three digits.) +Strings in Lua may contain any 8-bit value, including embedded zeros, +which can be specified as '<code>\0</code>'. + + +<p> +To put a double (single) quote, a newline, a backslash, +a carriage return, +or an embedded zero +inside a literal string enclosed by double (single) quotes +you must use an escape sequence. +Any other character may be directly inserted into the literal. +(Some control characters may cause problems for the file system, +but Lua has no problem with them.) + + +<p> +Literal strings can also be defined using a long format +enclosed by <em>long brackets</em>. +We define an <em>opening long bracket of level <em>n</em></em> as an opening +square bracket followed by <em>n</em> equal signs followed by another +opening square bracket. +So, an opening long bracket of level 0 is written as <code>[[</code>, +an opening long bracket of level 1 is written as <code>[=[</code>, +and so on. +A <em>closing long bracket</em> is defined similarly; +for instance, a closing long bracket of level 4 is written as <code>]====]</code>. +A long string starts with an opening long bracket of any level and +ends at the first closing long bracket of the same level. +Literals in this bracketed form may run for several lines, +do not interpret any escape sequences, +and ignore long brackets of any other level. +They may contain anything except a closing bracket of the proper level. + + +<p> +For convenience, +when the opening long bracket is immediately followed by a newline, +the newline is not included in the string. +As an example, in a system using ASCII +(in which '<code>a</code>' is coded as 97, +newline is coded as 10, and '<code>1</code>' is coded as 49), +the five literals below denote the same string: + +<pre> + a = 'alo\n123"' + a = "alo\n123\"" + a = '\97lo\10\04923"' + a = [[alo + 123"]] + a = [==[ + alo + 123"]==] +</pre> + +<p> +A <em>numerical constant</em> may be written with an optional decimal part +and an optional decimal exponent. +Lua also accepts integer hexadecimal constants, +by prefixing them with <code>0x</code>. +Examples of valid numerical constants are + +<pre> + 3 3.0 3.1416 314.16e-2 0.31416E1 0xff 0x56 +</pre> + +<p> +A <em>comment</em> starts with a double hyphen (<code>--</code>) +anywhere outside a string. +If the text immediately after <code>--</code> is not an opening long bracket, +the comment is a <em>short comment</em>, +which runs until the end of the line. +Otherwise, it is a <em>long comment</em>, +which runs until the corresponding closing long bracket. +Long comments are frequently used to disable code temporarily. + + + + + +<h2>2.2 - <a name="2.2">Values and Types</a></h2> + +<p> +Lua is a <em>dynamically typed language</em>. +This means that +variables do not have types; only values do. +There are no type definitions in the language. +All values carry their own type. + + +<p> +All values in Lua are <em>first-class values</em>. +This means that all values can be stored in variables, +passed as arguments to other functions, and returned as results. + + +<p> +There are eight basic types in Lua: +<em>nil</em>, <em>boolean</em>, <em>number</em>, +<em>string</em>, <em>function</em>, <em>userdata</em>, +<em>thread</em>, and <em>table</em>. +<em>Nil</em> is the type of the value <b>nil</b>, +whose main property is to be different from any other value; +it usually represents the absence of a useful value. +<em>Boolean</em> is the type of the values <b>false</b> and <b>true</b>. +Both <b>nil</b> and <b>false</b> make a condition false; +any other value makes it true. +<em>Number</em> represents real (double-precision floating-point) numbers. +(It is easy to build Lua interpreters that use other +internal representations for numbers, +such as single-precision float or long integers; +see file <code>luaconf.h</code>.) +<em>String</em> represents arrays of characters. + +Lua is 8-bit clean: +strings may contain any 8-bit character, +including embedded zeros ('<code>\0</code>') (see <a href="#2.1">§2.1</a>). + + +<p> +Lua can call (and manipulate) functions written in Lua and +functions written in C +(see <a href="#2.5.8">§2.5.8</a>). + + +<p> +The type <em>userdata</em> is provided to allow arbitrary C data to +be stored in Lua variables. +This type corresponds to a block of raw memory +and has no pre-defined operations in Lua, +except assignment and identity test. +However, by using <em>metatables</em>, +the programmer can define operations for userdata values +(see <a href="#2.8">§2.8</a>). +Userdata values cannot be created or modified in Lua, +only through the C API. +This guarantees the integrity of data owned by the host program. + + +<p> +The type <em>thread</em> represents independent threads of execution +and it is used to implement coroutines (see <a href="#2.11">§2.11</a>). +Do not confuse Lua threads with operating-system threads. +Lua supports coroutines on all systems, +even those that do not support threads. + + +<p> +The type <em>table</em> implements associative arrays, +that is, arrays that can be indexed not only with numbers, +but with any value (except <b>nil</b>). +Tables can be <em>heterogeneous</em>; +that is, they can contain values of all types (except <b>nil</b>). +Tables are the sole data structuring mechanism in Lua; +they may be used to represent ordinary arrays, +symbol tables, sets, records, graphs, trees, etc. +To represent records, Lua uses the field name as an index. +The language supports this representation by +providing <code>a.name</code> as syntactic sugar for <code>a["name"]</code>. +There are several convenient ways to create tables in Lua +(see <a href="#2.5.7">§2.5.7</a>). + + +<p> +Like indices, +the value of a table field can be of any type (except <b>nil</b>). +In particular, +because functions are first-class values, +table fields may contain functions. +Thus tables may also carry <em>methods</em> (see <a href="#2.5.9">§2.5.9</a>). + + +<p> +Tables, functions, threads, and (full) userdata values are <em>objects</em>: +variables do not actually <em>contain</em> these values, +only <em>references</em> to them. +Assignment, parameter passing, and function returns +always manipulate references to such values; +these operations do not imply any kind of copy. + + +<p> +The library function <a href="#pdf-type"><code>type</code></a> returns a string describing the type +of a given value. + + + +<h3>2.2.1 - <a name="2.2.1">Coercion</a></h3> + +<p> +Lua provides automatic conversion between +string and number values at run time. +Any arithmetic operation applied to a string tries to convert +this string to a number, following the usual conversion rules. +Conversely, whenever a number is used where a string is expected, +the number is converted to a string, in a reasonable format. +For complete control over how numbers are converted to strings, +use the <code>format</code> function from the string library +(see <a href="#pdf-string.format"><code>string.format</code></a>). + + + + + + + +<h2>2.3 - <a name="2.3">Variables</a></h2> + +<p> +Variables are places that store values. + +There are three kinds of variables in Lua: +global variables, local variables, and table fields. + + +<p> +A single name can denote a global variable or a local variable +(or a function's formal parameter, +which is a particular kind of local variable): + +<pre> + var ::= Name +</pre><p> +Name denotes identifiers, as defined in <a href="#2.1">§2.1</a>. + + +<p> +Any variable is assumed to be global unless explicitly declared +as a local (see <a href="#2.4.7">§2.4.7</a>). +Local variables are <em>lexically scoped</em>: +local variables can be freely accessed by functions +defined inside their scope (see <a href="#2.6">§2.6</a>). + + +<p> +Before the first assignment to a variable, its value is <b>nil</b>. + + +<p> +Square brackets are used to index a table: + +<pre> + var ::= prefixexp `<b>[</b>´ exp `<b>]</b>´ +</pre><p> +The meaning of accesses to global variables +and table fields can be changed via metatables. +An access to an indexed variable <code>t[i]</code> is equivalent to +a call <code>gettable_event(t,i)</code>. +(See <a href="#2.8">§2.8</a> for a complete description of the +<code>gettable_event</code> function. +This function is not defined or callable in Lua. +We use it here only for explanatory purposes.) + + +<p> +The syntax <code>var.Name</code> is just syntactic sugar for +<code>var["Name"]</code>: + +<pre> + var ::= prefixexp `<b>.</b>´ Name +</pre> + +<p> +All global variables live as fields in ordinary Lua tables, +called <em>environment tables</em> or simply +<em>environments</em> (see <a href="#2.9">§2.9</a>). +Each function has its own reference to an environment, +so that all global variables in this function +will refer to this environment table. +When a function is created, +it inherits the environment from the function that created it. +To get the environment table of a Lua function, +you call <a href="#pdf-getfenv"><code>getfenv</code></a>. +To replace it, +you call <a href="#pdf-setfenv"><code>setfenv</code></a>. +(You can only manipulate the environment of C functions +through the debug library; (see <a href="#5.9">§5.9</a>).) + + +<p> +An access to a global variable <code>x</code> +is equivalent to <code>_env.x</code>, +which in turn is equivalent to + +<pre> + gettable_event(_env, "x") +</pre><p> +where <code>_env</code> is the environment of the running function. +(See <a href="#2.8">§2.8</a> for a complete description of the +<code>gettable_event</code> function. +This function is not defined or callable in Lua. +Similarly, the <code>_env</code> variable is not defined in Lua. +We use them here only for explanatory purposes.) + + + + + +<h2>2.4 - <a name="2.4">Statements</a></h2> + +<p> +Lua supports an almost conventional set of statements, +similar to those in Pascal or C. +This set includes +assignment, control structures, function calls, +and variable declarations. + + + +<h3>2.4.1 - <a name="2.4.1">Chunks</a></h3> + +<p> +The unit of execution of Lua is called a <em>chunk</em>. +A chunk is simply a sequence of statements, +which are executed sequentially. +Each statement can be optionally followed by a semicolon: + +<pre> + chunk ::= {stat [`<b>;</b>´]} +</pre><p> +There are no empty statements and thus '<code>;;</code>' is not legal. + + +<p> +Lua handles a chunk as the body of an anonymous function +with a variable number of arguments +(see <a href="#2.5.9">§2.5.9</a>). +As such, chunks can define local variables, +receive arguments, and return values. + + +<p> +A chunk may be stored in a file or in a string inside the host program. +When a chunk is executed, first it is pre-compiled into instructions for +a virtual machine, +and then the compiled code is executed +by an interpreter for the virtual machine. + + +<p> +Chunks may also be pre-compiled into binary form; +see program <code>luac</code> for details. +Programs in source and compiled forms are interchangeable; +Lua automatically detects the file type and acts accordingly. + + + + + + +<h3>2.4.2 - <a name="2.4.2">Blocks</a></h3><p> +A block is a list of statements; +syntactically, a block is the same as a chunk: + +<pre> + block ::= chunk +</pre> + +<p> +A block may be explicitly delimited to produce a single statement: + +<pre> + stat ::= <b>do</b> block <b>end</b> +</pre><p> +Explicit blocks are useful +to control the scope of variable declarations. +Explicit blocks are also sometimes used to +add a <b>return</b> or <b>break</b> statement in the middle +of another block (see <a href="#2.4.4">§2.4.4</a>). + + + + + +<h3>2.4.3 - <a name="2.4.3">Assignment</a></h3> + +<p> +Lua allows multiple assignment. +Therefore, the syntax for assignment +defines a list of variables on the left side +and a list of expressions on the right side. +The elements in both lists are separated by commas: + +<pre> + stat ::= varlist `<b>=</b>´ explist + varlist ::= var {`<b>,</b>´ var} + explist ::= exp {`<b>,</b>´ exp} +</pre><p> +Expressions are discussed in <a href="#2.5">§2.5</a>. + + +<p> +Before the assignment, +the list of values is <em>adjusted</em> to the length of +the list of variables. +If there are more values than needed, +the excess values are thrown away. +If there are fewer values than needed, +the list is extended with as many <b>nil</b>'s as needed. +If the list of expressions ends with a function call, +then all values returned by this call enter in the list of values, +before the adjustment +(except when the call is enclosed in parentheses; see <a href="#2.5">§2.5</a>). + + +<p> +The assignment statement first evaluates all its expressions +and only then are the assignments performed. +Thus the code + +<pre> + i = 3 + i, a[i] = i+1, 20 +</pre><p> +sets <code>a[3]</code> to 20, without affecting <code>a[4]</code> +because the <code>i</code> in <code>a[i]</code> is evaluated (to 3) +before it is assigned 4. +Similarly, the line + +<pre> + x, y = y, x +</pre><p> +exchanges the values of <code>x</code> and <code>y</code>. + + +<p> +The meaning of assignments to global variables +and table fields can be changed via metatables. +An assignment to an indexed variable <code>t[i] = val</code> is equivalent to +<code>settable_event(t,i,val)</code>. +(See <a href="#2.8">§2.8</a> for a complete description of the +<code>settable_event</code> function. +This function is not defined or callable in Lua. +We use it here only for explanatory purposes.) + + +<p> +An assignment to a global variable <code>x = val</code> +is equivalent to the assignment +<code>_env.x = val</code>, +which in turn is equivalent to + +<pre> + settable_event(_env, "x", val) +</pre><p> +where <code>_env</code> is the environment of the running function. +(The <code>_env</code> variable is not defined in Lua. +We use it here only for explanatory purposes.) + + + + + +<h3>2.4.4 - <a name="2.4.4">Control Structures</a></h3><p> +The control structures +<b>if</b>, <b>while</b>, and <b>repeat</b> have the usual meaning and +familiar syntax: + + + + +<pre> + stat ::= <b>while</b> exp <b>do</b> block <b>end</b> + stat ::= <b>repeat</b> block <b>until</b> exp + stat ::= <b>if</b> exp <b>then</b> block {<b>elseif</b> exp <b>then</b> block} [<b>else</b> block] <b>end</b> +</pre><p> +Lua also has a <b>for</b> statement, in two flavors (see <a href="#2.4.5">§2.4.5</a>). + + +<p> +The condition expression of a +control structure may return any value. +Both <b>false</b> and <b>nil</b> are considered false. +All values different from <b>nil</b> and <b>false</b> are considered true +(in particular, the number 0 and the empty string are also true). + + +<p> +In the <b>repeat</b>–<b>until</b> loop, +the inner block does not end at the <b>until</b> keyword, +but only after the condition. +So, the condition can refer to local variables +declared inside the loop block. + + +<p> +The <b>return</b> statement is used to return values +from a function or a chunk (which is just a function). + +Functions and chunks may return more than one value, +so the syntax for the <b>return</b> statement is + +<pre> + stat ::= <b>return</b> [explist] +</pre> + +<p> +The <b>break</b> statement is used to terminate the execution of a +<b>while</b>, <b>repeat</b>, or <b>for</b> loop, +skipping to the next statement after the loop: + + +<pre> + stat ::= <b>break</b> +</pre><p> +A <b>break</b> ends the innermost enclosing loop. + + +<p> +The <b>return</b> and <b>break</b> +statements can only be written as the <em>last</em> statement of a block. +If it is really necessary to <b>return</b> or <b>break</b> in the +middle of a block, +then an explicit inner block can be used, +as in the idioms +<code>do return end</code> and <code>do break end</code>, +because now <b>return</b> and <b>break</b> are the last statements in +their (inner) blocks. + + + + + +<h3>2.4.5 - <a name="2.4.5">For Statement</a></h3> + +<p> + +The <b>for</b> statement has two forms: +one numeric and one generic. + + +<p> +The numeric <b>for</b> loop repeats a block of code while a +control variable runs through an arithmetic progression. +It has the following syntax: + +<pre> + stat ::= <b>for</b> Name `<b>=</b>´ exp `<b>,</b>´ exp [`<b>,</b>´ exp] <b>do</b> block <b>end</b> +</pre><p> +The <em>block</em> is repeated for <em>name</em> starting at the value of +the first <em>exp</em>, until it passes the second <em>exp</em> by steps of the +third <em>exp</em>. +More precisely, a <b>for</b> statement like + +<pre> + for v = <em>e1</em>, <em>e2</em>, <em>e3</em> do <em>block</em> end +</pre><p> +is equivalent to the code: + +<pre> + do + local <em>var</em>, <em>limit</em>, <em>step</em> = tonumber(<em>e1</em>), tonumber(<em>e2</em>), tonumber(<em>e3</em>) + if not (<em>var</em> and <em>limit</em> and <em>step</em>) then error() end + while (<em>step</em> > 0 and <em>var</em> <= <em>limit</em>) or (<em>step</em> <= 0 and <em>var</em> >= <em>limit</em>) do + local v = <em>var</em> + <em>block</em> + <em>var</em> = <em>var</em> + <em>step</em> + end + end +</pre><p> +Note the following: + +<ul> + +<li> +All three control expressions are evaluated only once, +before the loop starts. +They must all result in numbers. +</li> + +<li> +<code><em>var</em></code>, <code><em>limit</em></code>, and <code><em>step</em></code> are invisible variables. +The names are here for explanatory purposes only. +</li> + +<li> +If the third expression (the step) is absent, +then a step of 1 is used. +</li> + +<li> +You can use <b>break</b> to exit a <b>for</b> loop. +</li> + +<li> +The loop variable <code>v</code> is local to the loop; +you cannot use its value after the <b>for</b> ends or is broken. +If you need this value, +assign it to another variable before breaking or exiting the loop. +</li> + +</ul> + +<p> +The generic <b>for</b> statement works over functions, +called <em>iterators</em>. +On each iteration, the iterator function is called to produce a new value, +stopping when this new value is <b>nil</b>. +The generic <b>for</b> loop has the following syntax: + +<pre> + stat ::= <b>for</b> namelist <b>in</b> explist <b>do</b> block <b>end</b> + namelist ::= Name {`<b>,</b>´ Name} +</pre><p> +A <b>for</b> statement like + +<pre> + for <em>var_1</em>, ···, <em>var_n</em> in <em>explist</em> do <em>block</em> end +</pre><p> +is equivalent to the code: + +<pre> + do + local <em>f</em>, <em>s</em>, <em>var</em> = <em>explist</em> + while true do + local <em>var_1</em>, ···, <em>var_n</em> = <em>f</em>(<em>s</em>, <em>var</em>) + <em>var</em> = <em>var_1</em> + if <em>var</em> == nil then break end + <em>block</em> + end + end +</pre><p> +Note the following: + +<ul> + +<li> +<code><em>explist</em></code> is evaluated only once. +Its results are an <em>iterator</em> function, +a <em>state</em>, +and an initial value for the first <em>iterator variable</em>. +</li> + +<li> +<code><em>f</em></code>, <code><em>s</em></code>, and <code><em>var</em></code> are invisible variables. +The names are here for explanatory purposes only. +</li> + +<li> +You can use <b>break</b> to exit a <b>for</b> loop. +</li> + +<li> +The loop variables <code><em>var_i</em></code> are local to the loop; +you cannot use their values after the <b>for</b> ends. +If you need these values, +then assign them to other variables before breaking or exiting the loop. +</li> + +</ul> + + + + +<h3>2.4.6 - <a name="2.4.6">Function Calls as Statements</a></h3><p> +To allow possible side-effects, +function calls can be executed as statements: + +<pre> + stat ::= functioncall +</pre><p> +In this case, all returned values are thrown away. +Function calls are explained in <a href="#2.5.8">§2.5.8</a>. + + + + + +<h3>2.4.7 - <a name="2.4.7">Local Declarations</a></h3><p> +Local variables may be declared anywhere inside a block. +The declaration may include an initial assignment: + +<pre> + stat ::= <b>local</b> namelist [`<b>=</b>´ explist] +</pre><p> +If present, an initial assignment has the same semantics +of a multiple assignment (see <a href="#2.4.3">§2.4.3</a>). +Otherwise, all variables are initialized with <b>nil</b>. + + +<p> +A chunk is also a block (see <a href="#2.4.1">§2.4.1</a>), +and so local variables can be declared in a chunk outside any explicit block. +The scope of such local variables extends until the end of the chunk. + + +<p> +The visibility rules for local variables are explained in <a href="#2.6">§2.6</a>. + + + + + + + +<h2>2.5 - <a name="2.5">Expressions</a></h2> + +<p> +The basic expressions in Lua are the following: + +<pre> + exp ::= prefixexp + exp ::= <b>nil</b> | <b>false</b> | <b>true</b> + exp ::= Number + exp ::= String + exp ::= function + exp ::= tableconstructor + exp ::= `<b>...</b>´ + exp ::= exp binop exp + exp ::= unop exp + prefixexp ::= var | functioncall | `<b>(</b>´ exp `<b>)</b>´ +</pre> + +<p> +Numbers and literal strings are explained in <a href="#2.1">§2.1</a>; +variables are explained in <a href="#2.3">§2.3</a>; +function definitions are explained in <a href="#2.5.9">§2.5.9</a>; +function calls are explained in <a href="#2.5.8">§2.5.8</a>; +table constructors are explained in <a href="#2.5.7">§2.5.7</a>. +Vararg expressions, +denoted by three dots ('<code>...</code>'), can only be used when +directly inside a vararg function; +they are explained in <a href="#2.5.9">§2.5.9</a>. + + +<p> +Binary operators comprise arithmetic operators (see <a href="#2.5.1">§2.5.1</a>), +relational operators (see <a href="#2.5.2">§2.5.2</a>), logical operators (see <a href="#2.5.3">§2.5.3</a>), +and the concatenation operator (see <a href="#2.5.4">§2.5.4</a>). +Unary operators comprise the unary minus (see <a href="#2.5.1">§2.5.1</a>), +the unary <b>not</b> (see <a href="#2.5.3">§2.5.3</a>), +and the unary <em>length operator</em> (see <a href="#2.5.5">§2.5.5</a>). + + +<p> +Both function calls and vararg expressions may result in multiple values. +If the expression is used as a statement (see <a href="#2.4.6">§2.4.6</a>) +(only possible for function calls), +then its return list is adjusted to zero elements, +thus discarding all returned values. +If the expression is used as the last (or the only) element +of a list of expressions, +then no adjustment is made +(unless the call is enclosed in parentheses). +In all other contexts, +Lua adjusts the result list to one element, +discarding all values except the first one. + + +<p> +Here are some examples: + +<pre> + f() -- adjusted to 0 results + g(f(), x) -- f() is adjusted to 1 result + g(x, f()) -- g gets x plus all results from f() + a,b,c = f(), x -- f() is adjusted to 1 result (c gets nil) + a,b = ... -- a gets the first vararg parameter, b gets + -- the second (both a and b may get nil if there + -- is no corresponding vararg parameter) + + a,b,c = x, f() -- f() is adjusted to 2 results + a,b,c = f() -- f() is adjusted to 3 results + return f() -- returns all results from f() + return ... -- returns all received vararg parameters + return x,y,f() -- returns x, y, and all results from f() + {f()} -- creates a list with all results from f() + {...} -- creates a list with all vararg parameters + {f(), nil} -- f() is adjusted to 1 result +</pre> + +<p> +An expression enclosed in parentheses always results in only one value. +Thus, +<code>(f(x,y,z))</code> is always a single value, +even if <code>f</code> returns several values. +(The value of <code>(f(x,y,z))</code> is the first value returned by <code>f</code> +or <b>nil</b> if <code>f</code> does not return any values.) + + + +<h3>2.5.1 - <a name="2.5.1">Arithmetic Operators</a></h3><p> +Lua supports the usual arithmetic operators: +the binary <code>+</code> (addition), +<code>-</code> (subtraction), <code>*</code> (multiplication), +<code>/</code> (division), <code>%</code> (modulo), and <code>^</code> (exponentiation); +and unary <code>-</code> (negation). +If the operands are numbers, or strings that can be converted to +numbers (see <a href="#2.2.1">§2.2.1</a>), +then all operations have the usual meaning. +Exponentiation works for any exponent. +For instance, <code>x^(-0.5)</code> computes the inverse of the square root of <code>x</code>. +Modulo is defined as + +<pre> + a % b == a - math.floor(a/b)*b +</pre><p> +That is, it is the remainder of a division that rounds +the quotient towards minus infinity. + + + + + +<h3>2.5.2 - <a name="2.5.2">Relational Operators</a></h3><p> +The relational operators in Lua are + +<pre> + == ~= < > <= >= +</pre><p> +These operators always result in <b>false</b> or <b>true</b>. + + +<p> +Equality (<code>==</code>) first compares the type of its operands. +If the types are different, then the result is <b>false</b>. +Otherwise, the values of the operands are compared. +Numbers and strings are compared in the usual way. +Objects (tables, userdata, threads, and functions) +are compared by <em>reference</em>: +two objects are considered equal only if they are the <em>same</em> object. +Every time you create a new object +(a table, userdata, thread, or function), +this new object is different from any previously existing object. + + +<p> +You can change the way that Lua compares tables and userdata +by using the "eq" metamethod (see <a href="#2.8">§2.8</a>). + + +<p> +The conversion rules of <a href="#2.2.1">§2.2.1</a> +<em>do not</em> apply to equality comparisons. +Thus, <code>"0"==0</code> evaluates to <b>false</b>, +and <code>t[0]</code> and <code>t["0"]</code> denote different +entries in a table. + + +<p> +The operator <code>~=</code> is exactly the negation of equality (<code>==</code>). + + +<p> +The order operators work as follows. +If both arguments are numbers, then they are compared as such. +Otherwise, if both arguments are strings, +then their values are compared according to the current locale. +Otherwise, Lua tries to call the "lt" or the "le" +metamethod (see <a href="#2.8">§2.8</a>). + + + + + +<h3>2.5.3 - <a name="2.5.3">Logical Operators</a></h3><p> +The logical operators in Lua are +<b>and</b>, <b>or</b>, and <b>not</b>. +Like the control structures (see <a href="#2.4.4">§2.4.4</a>), +all logical operators consider both <b>false</b> and <b>nil</b> as false +and anything else as true. + + +<p> +The negation operator <b>not</b> always returns <b>false</b> or <b>true</b>. +The conjunction operator <b>and</b> returns its first argument +if this value is <b>false</b> or <b>nil</b>; +otherwise, <b>and</b> returns its second argument. +The disjunction operator <b>or</b> returns its first argument +if this value is different from <b>nil</b> and <b>false</b>; +otherwise, <b>or</b> returns its second argument. +Both <b>and</b> and <b>or</b> use short-cut evaluation; +that is, +the second operand is evaluated only if necessary. +Here are some examples: + +<pre> + 10 or 20 --> 10 + 10 or error() --> 10 + nil or "a" --> "a" + nil and 10 --> nil + false and error() --> false + false and nil --> false + false or nil --> nil + 10 and 20 --> 20 +</pre><p> +(In this manual, +--> indicates the result of the preceding expression.) + + + + + +<h3>2.5.4 - <a name="2.5.4">Concatenation</a></h3><p> +The string concatenation operator in Lua is +denoted by two dots ('<code>..</code>'). +If both operands are strings or numbers, then they are converted to +strings according to the rules mentioned in <a href="#2.2.1">§2.2.1</a>. +Otherwise, the "concat" metamethod is called (see <a href="#2.8">§2.8</a>). + + + + + +<h3>2.5.5 - <a name="2.5.5">The Length Operator</a></h3> + +<p> +The length operator is denoted by the unary operator <code>#</code>. +The length of a string is its number of bytes +(that is, the usual meaning of string length when each +character is one byte). + + +<p> +The length of a table <code>t</code> is defined to be any +integer index <code>n</code> +such that <code>t[n]</code> is not <b>nil</b> and <code>t[n+1]</code> is <b>nil</b>; +moreover, if <code>t[1]</code> is <b>nil</b>, <code>n</code> may be zero. +For a regular array, with non-nil values from 1 to a given <code>n</code>, +its length is exactly that <code>n</code>, +the index of its last value. +If the array has "holes" +(that is, <b>nil</b> values between other non-nil values), +then <code>#t</code> may be any of the indices that +directly precedes a <b>nil</b> value +(that is, it may consider any such <b>nil</b> value as the end of +the array). + + + + + +<h3>2.5.6 - <a name="2.5.6">Precedence</a></h3><p> +Operator precedence in Lua follows the table below, +from lower to higher priority: + +<pre> + or + and + < > <= >= ~= == + .. + + - + * / % + not # - (unary) + ^ +</pre><p> +As usual, +you can use parentheses to change the precedences of an expression. +The concatenation ('<code>..</code>') and exponentiation ('<code>^</code>') +operators are right associative. +All other binary operators are left associative. + + + + + +<h3>2.5.7 - <a name="2.5.7">Table Constructors</a></h3><p> +Table constructors are expressions that create tables. +Every time a constructor is evaluated, a new table is created. +Constructors can be used to create empty tables, +or to create a table and initialize some of its fields. +The general syntax for constructors is + +<pre> + tableconstructor ::= `<b>{</b>´ [fieldlist] `<b>}</b>´ + fieldlist ::= field {fieldsep field} [fieldsep] + field ::= `<b>[</b>´ exp `<b>]</b>´ `<b>=</b>´ exp | Name `<b>=</b>´ exp | exp + fieldsep ::= `<b>,</b>´ | `<b>;</b>´ +</pre> + +<p> +Each field of the form <code>[exp1] = exp2</code> adds to the new table an entry +with key <code>exp1</code> and value <code>exp2</code>. +A field of the form <code>name = exp</code> is equivalent to +<code>["name"] = exp</code>. +Finally, fields of the form <code>exp</code> are equivalent to +<code>[i] = exp</code>, where <code>i</code> are consecutive numerical integers, +starting with 1. +Fields in the other formats do not affect this counting. +For example, + +<pre> + a = { [f(1)] = g; "x", "y"; x = 1, f(x), [30] = 23; 45 } +</pre><p> +is equivalent to + +<pre> + do + local t = {} + t[f(1)] = g + t[1] = "x" -- 1st exp + t[2] = "y" -- 2nd exp + t.x = 1 -- t["x"] = 1 + t[3] = f(x) -- 3rd exp + t[30] = 23 + t[4] = 45 -- 4th exp + a = t + end +</pre> + +<p> +If the last field in the list has the form <code>exp</code> +and the expression is a function call or a vararg expression, +then all values returned by this expression enter the list consecutively +(see <a href="#2.5.8">§2.5.8</a>). +To avoid this, +enclose the function call (or the vararg expression) +in parentheses (see <a href="#2.5">§2.5</a>). + + +<p> +The field list may have an optional trailing separator, +as a convenience for machine-generated code. + + + + + +<h3>2.5.8 - <a name="2.5.8">Function Calls</a></h3><p> +A function call in Lua has the following syntax: + +<pre> + functioncall ::= prefixexp args +</pre><p> +In a function call, +first prefixexp and args are evaluated. +If the value of prefixexp has type <em>function</em>, +then this function is called +with the given arguments. +Otherwise, the prefixexp "call" metamethod is called, +having as first parameter the value of prefixexp, +followed by the original call arguments +(see <a href="#2.8">§2.8</a>). + + +<p> +The form + +<pre> + functioncall ::= prefixexp `<b>:</b>´ Name args +</pre><p> +can be used to call "methods". +A call <code>v:name(<em>args</em>)</code> +is syntactic sugar for <code>v.name(v,<em>args</em>)</code>, +except that <code>v</code> is evaluated only once. + + +<p> +Arguments have the following syntax: + +<pre> + args ::= `<b>(</b>´ [explist] `<b>)</b>´ + args ::= tableconstructor + args ::= String +</pre><p> +All argument expressions are evaluated before the call. +A call of the form <code>f{<em>fields</em>}</code> is +syntactic sugar for <code>f({<em>fields</em>})</code>; +that is, the argument list is a single new table. +A call of the form <code>f'<em>string</em>'</code> +(or <code>f"<em>string</em>"</code> or <code>f[[<em>string</em>]]</code>) +is syntactic sugar for <code>f('<em>string</em>')</code>; +that is, the argument list is a single literal string. + + +<p> +As an exception to the free-format syntax of Lua, +you cannot put a line break before the '<code>(</code>' in a function call. +This restriction avoids some ambiguities in the language. +If you write + +<pre> + a = f + (g).x(a) +</pre><p> +Lua would see that as a single statement, <code>a = f(g).x(a)</code>. +So, if you want two statements, you must add a semi-colon between them. +If you actually want to call <code>f</code>, +you must remove the line break before <code>(g)</code>. + + +<p> +A call of the form <code>return</code> <em>functioncall</em> is called +a <em>tail call</em>. +Lua implements <em>proper tail calls</em> +(or <em>proper tail recursion</em>): +in a tail call, +the called function reuses the stack entry of the calling function. +Therefore, there is no limit on the number of nested tail calls that +a program can execute. +However, a tail call erases any debug information about the +calling function. +Note that a tail call only happens with a particular syntax, +where the <b>return</b> has one single function call as argument; +this syntax makes the calling function return exactly +the returns of the called function. +So, none of the following examples are tail calls: + +<pre> + return (f(x)) -- results adjusted to 1 + return 2 * f(x) + return x, f(x) -- additional results + f(x); return -- results discarded + return x or f(x) -- results adjusted to 1 +</pre> + + + + +<h3>2.5.9 - <a name="2.5.9">Function Definitions</a></h3> + +<p> +The syntax for function definition is + +<pre> + function ::= <b>function</b> funcbody + funcbody ::= `<b>(</b>´ [parlist] `<b>)</b>´ block <b>end</b> +</pre> + +<p> +The following syntactic sugar simplifies function definitions: + +<pre> + stat ::= <b>function</b> funcname funcbody + stat ::= <b>local</b> <b>function</b> Name funcbody + funcname ::= Name {`<b>.</b>´ Name} [`<b>:</b>´ Name] +</pre><p> +The statement + +<pre> + function f () <em>body</em> end +</pre><p> +translates to + +<pre> + f = function () <em>body</em> end +</pre><p> +The statement + +<pre> + function t.a.b.c.f () <em>body</em> end +</pre><p> +translates to + +<pre> + t.a.b.c.f = function () <em>body</em> end +</pre><p> +The statement + +<pre> + local function f () <em>body</em> end +</pre><p> +translates to + +<pre> + local f; f = function () <em>body</em> end +</pre><p> +<em>not</em> to + +<pre> + local f = function () <em>body</em> end +</pre><p> +(This only makes a difference when the body of the function +contains references to <code>f</code>.) + + +<p> +A function definition is an executable expression, +whose value has type <em>function</em>. +When Lua pre-compiles a chunk, +all its function bodies are pre-compiled too. +Then, whenever Lua executes the function definition, +the function is <em>instantiated</em> (or <em>closed</em>). +This function instance (or <em>closure</em>) +is the final value of the expression. +Different instances of the same function +may refer to different external local variables +and may have different environment tables. + + +<p> +Parameters act as local variables that are +initialized with the argument values: + +<pre> + parlist ::= namelist [`<b>,</b>´ `<b>...</b>´] | `<b>...</b>´ +</pre><p> +When a function is called, +the list of arguments is adjusted to +the length of the list of parameters, +unless the function is a variadic or <em>vararg function</em>, +which is +indicated by three dots ('<code>...</code>') at the end of its parameter list. +A vararg function does not adjust its argument list; +instead, it collects all extra arguments and supplies them +to the function through a <em>vararg expression</em>, +which is also written as three dots. +The value of this expression is a list of all actual extra arguments, +similar to a function with multiple results. +If a vararg expression is used inside another expression +or in the middle of a list of expressions, +then its return list is adjusted to one element. +If the expression is used as the last element of a list of expressions, +then no adjustment is made +(unless the call is enclosed in parentheses). + + +<p> +As an example, consider the following definitions: + +<pre> + function f(a, b) end + function g(a, b, ...) end + function r() return 1,2,3 end +</pre><p> +Then, we have the following mapping from arguments to parameters and +to the vararg expression: + +<pre> + CALL PARAMETERS + + f(3) a=3, b=nil + f(3, 4) a=3, b=4 + f(3, 4, 5) a=3, b=4 + f(r(), 10) a=1, b=10 + f(r()) a=1, b=2 + + g(3) a=3, b=nil, ... --> (nothing) + g(3, 4) a=3, b=4, ... --> (nothing) + g(3, 4, 5, 8) a=3, b=4, ... --> 5 8 + g(5, r()) a=5, b=1, ... --> 2 3 +</pre> + +<p> +Results are returned using the <b>return</b> statement (see <a href="#2.4.4">§2.4.4</a>). +If control reaches the end of a function +without encountering a <b>return</b> statement, +then the function returns with no results. + + +<p> +The <em>colon</em> syntax +is used for defining <em>methods</em>, +that is, functions that have an implicit extra parameter <code>self</code>. +Thus, the statement + +<pre> + function t.a.b.c:f (<em>params</em>) <em>body</em> end +</pre><p> +is syntactic sugar for + +<pre> + t.a.b.c.f = function (self, <em>params</em>) <em>body</em> end +</pre> + + + + + + +<h2>2.6 - <a name="2.6">Visibility Rules</a></h2> + +<p> + +Lua is a lexically scoped language. +The scope of variables begins at the first statement <em>after</em> +their declaration and lasts until the end of the innermost block that +includes the declaration. +Consider the following example: + +<pre> + x = 10 -- global variable + do -- new block + local x = x -- new 'x', with value 10 + print(x) --> 10 + x = x+1 + do -- another block + local x = x+1 -- another 'x' + print(x) --> 12 + end + print(x) --> 11 + end + print(x) --> 10 (the global one) +</pre> + +<p> +Notice that, in a declaration like <code>local x = x</code>, +the new <code>x</code> being declared is not in scope yet, +and so the second <code>x</code> refers to the outside variable. + + +<p> +Because of the lexical scoping rules, +local variables can be freely accessed by functions +defined inside their scope. +A local variable used by an inner function is called +an <em>upvalue</em>, or <em>external local variable</em>, +inside the inner function. + + +<p> +Notice that each execution of a <b>local</b> statement +defines new local variables. +Consider the following example: + +<pre> + a = {} + local x = 20 + for i=1,10 do + local y = 0 + a[i] = function () y=y+1; return x+y end + end +</pre><p> +The loop creates ten closures +(that is, ten instances of the anonymous function). +Each of these closures uses a different <code>y</code> variable, +while all of them share the same <code>x</code>. + + + + + +<h2>2.7 - <a name="2.7">Error Handling</a></h2> + +<p> +Because Lua is an embedded extension language, +all Lua actions start from C code in the host program +calling a function from the Lua library (see <a href="#lua_pcall"><code>lua_pcall</code></a>). +Whenever an error occurs during Lua compilation or execution, +control returns to C, +which can take appropriate measures +(such as printing an error message). + + +<p> +Lua code can explicitly generate an error by calling the +<a href="#pdf-error"><code>error</code></a> function. +If you need to catch errors in Lua, +you can use the <a href="#pdf-pcall"><code>pcall</code></a> function. + + + + + +<h2>2.8 - <a name="2.8">Metatables</a></h2> + +<p> +Every value in Lua may have a <em>metatable</em>. +This <em>metatable</em> is an ordinary Lua table +that defines the behavior of the original value +under certain special operations. +You can change several aspects of the behavior +of operations over a value by setting specific fields in its metatable. +For instance, when a non-numeric value is the operand of an addition, +Lua checks for a function in the field <code>"__add"</code> in its metatable. +If it finds one, +Lua calls this function to perform the addition. + + +<p> +We call the keys in a metatable <em>events</em> +and the values <em>metamethods</em>. +In the previous example, the event is <code>"add"</code> +and the metamethod is the function that performs the addition. + + +<p> +You can query the metatable of any value +through the <a href="#pdf-getmetatable"><code>getmetatable</code></a> function. + + +<p> +You can replace the metatable of tables +through the <a href="#pdf-setmetatable"><code>setmetatable</code></a> +function. +You cannot change the metatable of other types from Lua +(except using the debug library); +you must use the C API for that. + + +<p> +Tables and full userdata have individual metatables +(although multiple tables and userdata can share their metatables); +values of all other types share one single metatable per type. +So, there is one single metatable for all numbers, +one for all strings, etc. + + +<p> +A metatable may control how an object behaves in arithmetic operations, +order comparisons, concatenation, length operation, and indexing. +A metatable can also define a function to be called when a userdata +is garbage collected. +For each of these operations Lua associates a specific key +called an <em>event</em>. +When Lua performs one of these operations over a value, +it checks whether this value has a metatable with the corresponding event. +If so, the value associated with that key (the metamethod) +controls how Lua will perform the operation. + + +<p> +Metatables control the operations listed next. +Each operation is identified by its corresponding name. +The key for each operation is a string with its name prefixed by +two underscores, '<code>__</code>'; +for instance, the key for operation "add" is the +string <code>"__add"</code>. +The semantics of these operations is better explained by a Lua function +describing how the interpreter executes the operation. + + +<p> +The code shown here in Lua is only illustrative; +the real behavior is hard coded in the interpreter +and it is much more efficient than this simulation. +All functions used in these descriptions +(<a href="#pdf-rawget"><code>rawget</code></a>, <a href="#pdf-tonumber"><code>tonumber</code></a>, etc.) +are described in <a href="#5.1">§5.1</a>. +In particular, to retrieve the metamethod of a given object, +we use the expression + +<pre> + metatable(obj)[event] +</pre><p> +This should be read as + +<pre> + rawget(getmetatable(obj) or {}, event) +</pre><p> + +That is, the access to a metamethod does not invoke other metamethods, +and the access to objects with no metatables does not fail +(it simply results in <b>nil</b>). + + + +<ul> + +<li><b>"add":</b> +the <code>+</code> operation. + + + +<p> +The function <code>getbinhandler</code> below defines how Lua chooses a handler +for a binary operation. +First, Lua tries the first operand. +If its type does not define a handler for the operation, +then Lua tries the second operand. + +<pre> + function getbinhandler (op1, op2, event) + return metatable(op1)[event] or metatable(op2)[event] + end +</pre><p> +By using this function, +the behavior of the <code>op1 + op2</code> is + +<pre> + function add_event (op1, op2) + local o1, o2 = tonumber(op1), tonumber(op2) + if o1 and o2 then -- both operands are numeric? + return o1 + o2 -- '+' here is the primitive 'add' + else -- at least one of the operands is not numeric + local h = getbinhandler(op1, op2, "__add") + if h then + -- call the handler with both operands + return (h(op1, op2)) + else -- no handler available: default behavior + error(···) + end + end + end +</pre><p> +</li> + +<li><b>"sub":</b> +the <code>-</code> operation. + +Behavior similar to the "add" operation. +</li> + +<li><b>"mul":</b> +the <code>*</code> operation. + +Behavior similar to the "add" operation. +</li> + +<li><b>"div":</b> +the <code>/</code> operation. + +Behavior similar to the "add" operation. +</li> + +<li><b>"mod":</b> +the <code>%</code> operation. + +Behavior similar to the "add" operation, +with the operation +<code>o1 - floor(o1/o2)*o2</code> as the primitive operation. +</li> + +<li><b>"pow":</b> +the <code>^</code> (exponentiation) operation. + +Behavior similar to the "add" operation, +with the function <code>pow</code> (from the C math library) +as the primitive operation. +</li> + +<li><b>"unm":</b> +the unary <code>-</code> operation. + + +<pre> + function unm_event (op) + local o = tonumber(op) + if o then -- operand is numeric? + return -o -- '-' here is the primitive 'unm' + else -- the operand is not numeric. + -- Try to get a handler from the operand + local h = metatable(op).__unm + if h then + -- call the handler with the operand + return (h(op)) + else -- no handler available: default behavior + error(···) + end + end + end +</pre><p> +</li> + +<li><b>"concat":</b> +the <code>..</code> (concatenation) operation. + + +<pre> + function concat_event (op1, op2) + if (type(op1) == "string" or type(op1) == "number") and + (type(op2) == "string" or type(op2) == "number") then + return op1 .. op2 -- primitive string concatenation + else + local h = getbinhandler(op1, op2, "__concat") + if h then + return (h(op1, op2)) + else + error(···) + end + end + end +</pre><p> +</li> + +<li><b>"len":</b> +the <code>#</code> operation. + + +<pre> + function len_event (op) + if type(op) == "string" then + return strlen(op) -- primitive string length + elseif type(op) == "table" then + return #op -- primitive table length + else + local h = metatable(op).__len + if h then + -- call the handler with the operand + return (h(op)) + else -- no handler available: default behavior + error(···) + end + end + end +</pre><p> +See <a href="#2.5.5">§2.5.5</a> for a description of the length of a table. +</li> + +<li><b>"eq":</b> +the <code>==</code> operation. + +The function <code>getcomphandler</code> defines how Lua chooses a metamethod +for comparison operators. +A metamethod only is selected when both objects +being compared have the same type +and the same metamethod for the selected operation. + +<pre> + function getcomphandler (op1, op2, event) + if type(op1) ~= type(op2) then return nil end + local mm1 = metatable(op1)[event] + local mm2 = metatable(op2)[event] + if mm1 == mm2 then return mm1 else return nil end + end +</pre><p> +The "eq" event is defined as follows: + +<pre> + function eq_event (op1, op2) + if type(op1) ~= type(op2) then -- different types? + return false -- different objects + end + if op1 == op2 then -- primitive equal? + return true -- objects are equal + end + -- try metamethod + local h = getcomphandler(op1, op2, "__eq") + if h then + return (h(op1, op2)) + else + return false + end + end +</pre><p> +<code>a ~= b</code> is equivalent to <code>not (a == b)</code>. +</li> + +<li><b>"lt":</b> +the <code><</code> operation. + + +<pre> + function lt_event (op1, op2) + if type(op1) == "number" and type(op2) == "number" then + return op1 < op2 -- numeric comparison + elseif type(op1) == "string" and type(op2) == "string" then + return op1 < op2 -- lexicographic comparison + else + local h = getcomphandler(op1, op2, "__lt") + if h then + return (h(op1, op2)) + else + error(···); + end + end + end +</pre><p> +<code>a > b</code> is equivalent to <code>b < a</code>. +</li> + +<li><b>"le":</b> +the <code><=</code> operation. + + +<pre> + function le_event (op1, op2) + if type(op1) == "number" and type(op2) == "number" then + return op1 <= op2 -- numeric comparison + elseif type(op1) == "string" and type(op2) == "string" then + return op1 <= op2 -- lexicographic comparison + else + local h = getcomphandler(op1, op2, "__le") + if h then + return (h(op1, op2)) + else + h = getcomphandler(op1, op2, "__lt") + if h then + return not h(op2, op1) + else + error(···); + end + end + end + end +</pre><p> +<code>a >= b</code> is equivalent to <code>b <= a</code>. +Note that, in the absence of a "le" metamethod, +Lua tries the "lt", assuming that <code>a <= b</code> is +equivalent to <code>not (b < a)</code>. +</li> + +<li><b>"index":</b> +The indexing access <code>table[key]</code>. + + +<pre> + function gettable_event (table, key) + local h + if type(table) == "table" then + local v = rawget(table, key) + if v ~= nil then return v end + h = metatable(table).__index + if h == nil then return nil end + else + h = metatable(table).__index + if h == nil then + error(···); + end + end + if type(h) == "function" then + return (h(table, key)) -- call the handler + else return h[key] -- or repeat operation on it + end + end +</pre><p> +</li> + +<li><b>"newindex":</b> +The indexing assignment <code>table[key] = value</code>. + + +<pre> + function settable_event (table, key, value) + local h + if type(table) == "table" then + local v = rawget(table, key) + if v ~= nil then rawset(table, key, value); return end + h = metatable(table).__newindex + if h == nil then rawset(table, key, value); return end + else + h = metatable(table).__newindex + if h == nil then + error(···); + end + end + if type(h) == "function" then + h(table, key,value) -- call the handler + else h[key] = value -- or repeat operation on it + end + end +</pre><p> +</li> + +<li><b>"call":</b> +called when Lua calls a value. + + +<pre> + function function_event (func, ...) + if type(func) == "function" then + return func(...) -- primitive call + else + local h = metatable(func).__call + if h then + return h(func, ...) + else + error(···) + end + end + end +</pre><p> +</li> + +</ul> + + + + +<h2>2.9 - <a name="2.9">Environments</a></h2> + +<p> +Besides metatables, +objects of types thread, function, and userdata +have another table associated with them, +called their <em>environment</em>. +Like metatables, environments are regular tables and +multiple objects can share the same environment. + + +<p> +Environments associated with userdata have no meaning for Lua. +It is only a convenience feature for programmers to associate a table to +a userdata. + + +<p> +Environments associated with threads are called +<em>global environments</em>. +They are used as the default environment for their threads and +non-nested functions created by the thread +(through <a href="#pdf-loadfile"><code>loadfile</code></a>, <a href="#pdf-loadstring"><code>loadstring</code></a> or <a href="#pdf-load"><code>load</code></a>) +and can be directly accessed by C code (see <a href="#3.3">§3.3</a>). + + +<p> +Environments associated with C functions can be directly +accessed by C code (see <a href="#3.3">§3.3</a>). +They are used as the default environment for other C functions +created by the function. + + +<p> +Environments associated with Lua functions are used to resolve +all accesses to global variables within the function (see <a href="#2.3">§2.3</a>). +They are used as the default environment for other Lua functions +created by the function. + + +<p> +You can change the environment of a Lua function or the +running thread by calling <a href="#pdf-setfenv"><code>setfenv</code></a>. +You can get the environment of a Lua function or the running thread +by calling <a href="#pdf-getfenv"><code>getfenv</code></a>. +To manipulate the environment of other objects +(userdata, C functions, other threads) you must +use the C API. + + + + + +<h2>2.10 - <a name="2.10">Garbage Collection</a></h2> + +<p> +Lua performs automatic memory management. +This means that +you have to worry neither about allocating memory for new objects +nor about freeing it when the objects are no longer needed. +Lua manages memory automatically by running +a <em>garbage collector</em> from time to time +to collect all <em>dead objects</em> +(that is, these objects that are no longer accessible from Lua). +All objects in Lua are subject to automatic management: +tables, userdata, functions, threads, and strings. + + +<p> +Lua implements an incremental mark-and-sweep collector. +It uses two numbers to control its garbage-collection cycles: +the <em>garbage-collector pause</em> and +the <em>garbage-collector step multiplier</em>. + + +<p> +The garbage-collector pause +controls how long the collector waits before starting a new cycle. +Larger values make the collector less aggressive. +Values smaller than 1 mean the collector will not wait to +start a new cycle. +A value of 2 means that the collector waits for the total memory in use +to double before starting a new cycle. + + +<p> +The step multiplier +controls the relative speed of the collector relative to +memory allocation. +Larger values make the collector more aggressive but also increase +the size of each incremental step. +Values smaller than 1 make the collector too slow and +may result in the collector never finishing a cycle. +The default, 2, means that the collector runs at "twice" +the speed of memory allocation. + + +<p> +You can change these numbers by calling <a href="#lua_gc"><code>lua_gc</code></a> in C +or <a href="#pdf-collectgarbage"><code>collectgarbage</code></a> in Lua. +Both get percentage points as arguments +(so an argument of 100 means a real value of 1). +With these functions you can also control +the collector directly (e.g., stop and restart it). + + + +<h3>2.10.1 - <a name="2.10.1">Garbage-Collection Metamethods</a></h3> + +<p> +Using the C API, +you can set garbage-collector metamethods for userdata (see <a href="#2.8">§2.8</a>). +These metamethods are also called <em>finalizers</em>. +Finalizers allow you to coordinate Lua's garbage collection +with external resource management +(such as closing files, network or database connections, +or freeing your own memory). + + +<p> +Garbage userdata with a field <code>__gc</code> in their metatables are not +collected immediately by the garbage collector. +Instead, Lua puts them in a list. +After the collection, +Lua does the equivalent of the following function +for each userdata in that list: + +<pre> + function gc_event (udata) + local h = metatable(udata).__gc + if h then + h(udata) + end + end +</pre> + +<p> +At the end of each garbage-collection cycle, +the finalizers for userdata are called in <em>reverse</em> +order of their creation, +among those collected in that cycle. +That is, the first finalizer to be called is the one associated +with the userdata created last in the program. +The userdata itself is freed only in the next garbage-collection cycle. + + + + + +<h3>2.10.2 - <a name="2.10.2">Weak Tables</a></h3> + +<p> +A <em>weak table</em> is a table whose elements are +<em>weak references</em>. +A weak reference is ignored by the garbage collector. +In other words, +if the only references to an object are weak references, +then the garbage collector will collect this object. + + +<p> +A weak table can have weak keys, weak values, or both. +A table with weak keys allows the collection of its keys, +but prevents the collection of its values. +A table with both weak keys and weak values allows the collection of +both keys and values. +In any case, if either the key or the value is collected, +the whole pair is removed from the table. +The weakness of a table is controlled by the +<code>__mode</code> field of its metatable. +If the <code>__mode</code> field is a string containing the character '<code>k</code>', +the keys in the table are weak. +If <code>__mode</code> contains '<code>v</code>', +the values in the table are weak. + + +<p> +After you use a table as a metatable, +you should not change the value of its field <code>__mode</code>. +Otherwise, the weak behavior of the tables controlled by this +metatable is undefined. + + + + + + + +<h2>2.11 - <a name="2.11">Coroutines</a></h2> + +<p> +Lua supports coroutines, +also called <em>collaborative multithreading</em>. +A coroutine in Lua represents an independent thread of execution. +Unlike threads in multithread systems, however, +a coroutine only suspends its execution by explicitly calling +a yield function. + + +<p> +You create a coroutine with a call to <a href="#pdf-coroutine.create"><code>coroutine.create</code></a>. +Its sole argument is a function +that is the main function of the coroutine. +The <code>create</code> function only creates a new coroutine and +returns a handle to it (an object of type <em>thread</em>); +it does not start the coroutine execution. + + +<p> +When you first call <a href="#pdf-coroutine.resume"><code>coroutine.resume</code></a>, +passing as its first argument +the thread returned by <a href="#pdf-coroutine.create"><code>coroutine.create</code></a>, +the coroutine starts its execution, +at the first line of its main function. +Extra arguments passed to <a href="#pdf-coroutine.resume"><code>coroutine.resume</code></a> are passed on +to the coroutine main function. +After the coroutine starts running, +it runs until it terminates or <em>yields</em>. + + +<p> +A coroutine can terminate its execution in two ways: +normally, when its main function returns +(explicitly or implicitly, after the last instruction); +and abnormally, if there is an unprotected error. +In the first case, <a href="#pdf-coroutine.resume"><code>coroutine.resume</code></a> returns <b>true</b>, +plus any values returned by the coroutine main function. +In case of errors, <a href="#pdf-coroutine.resume"><code>coroutine.resume</code></a> returns <b>false</b> +plus an error message. + + +<p> +A coroutine yields by calling <a href="#pdf-coroutine.yield"><code>coroutine.yield</code></a>. +When a coroutine yields, +the corresponding <a href="#pdf-coroutine.resume"><code>coroutine.resume</code></a> returns immediately, +even if the yield happens inside nested function calls +(that is, not in the main function, +but in a function directly or indirectly called by the main function). +In the case of a yield, <a href="#pdf-coroutine.resume"><code>coroutine.resume</code></a> also returns <b>true</b>, +plus any values passed to <a href="#pdf-coroutine.yield"><code>coroutine.yield</code></a>. +The next time you resume the same coroutine, +it continues its execution from the point where it yielded, +with the call to <a href="#pdf-coroutine.yield"><code>coroutine.yield</code></a> returning any extra +arguments passed to <a href="#pdf-coroutine.resume"><code>coroutine.resume</code></a>. + + +<p> +Like <a href="#pdf-coroutine.create"><code>coroutine.create</code></a>, +the <a href="#pdf-coroutine.wrap"><code>coroutine.wrap</code></a> function also creates a coroutine, +but instead of returning the coroutine itself, +it returns a function that, when called, resumes the coroutine. +Any arguments passed to this function +go as extra arguments to <a href="#pdf-coroutine.resume"><code>coroutine.resume</code></a>. +<a href="#pdf-coroutine.wrap"><code>coroutine.wrap</code></a> returns all the values returned by <a href="#pdf-coroutine.resume"><code>coroutine.resume</code></a>, +except the first one (the boolean error code). +Unlike <a href="#pdf-coroutine.resume"><code>coroutine.resume</code></a>, +<a href="#pdf-coroutine.wrap"><code>coroutine.wrap</code></a> does not catch errors; +any error is propagated to the caller. + + +<p> +As an example, +consider the following code: + +<pre> + function foo (a) + print("foo", a) + return coroutine.yield(2*a) + end + + co = coroutine.create(function (a,b) + print("co-body", a, b) + local r = foo(a+1) + print("co-body", r) + local r, s = coroutine.yield(a+b, a-b) + print("co-body", r, s) + return b, "end" + end) + + print("main", coroutine.resume(co, 1, 10)) + print("main", coroutine.resume(co, "r")) + print("main", coroutine.resume(co, "x", "y")) + print("main", coroutine.resume(co, "x", "y")) +</pre><p> +When you run it, it produces the following output: + +<pre> + co-body 1 10 + foo 2 + + main true 4 + co-body r + main true 11 -9 + co-body x y + main true 10 end + main false cannot resume dead coroutine +</pre> + + + + +<h1>3 - <a name="3">The Application Program Interface</a></h1> + +<p> + +This section describes the C API for Lua, that is, +the set of C functions available to the host program to communicate +with Lua. +All API functions and related types and constants +are declared in the header file <a name="pdf-lua.h"><code>lua.h</code></a>. + + +<p> +Even when we use the term "function", +any facility in the API may be provided as a macro instead. +All such macros use each of their arguments exactly once +(except for the first argument, which is always a Lua state), +and so do not generate any hidden side-effects. + + +<p> +As in most C libraries, +the Lua API functions do not check their arguments for validity or consistency. +However, you can change this behavior by compiling Lua +with a proper definition for the macro <a name="pdf-luai_apicheck"><code>luai_apicheck</code></a>, +in file <code>luaconf.h</code>. + + + +<h2>3.1 - <a name="3.1">The Stack</a></h2> + +<p> +Lua uses a <em>virtual stack</em> to pass values to and from C. +Each element in this stack represents a Lua value +(<b>nil</b>, number, string, etc.). + + +<p> +Whenever Lua calls C, the called function gets a new stack, +which is independent of previous stacks and of stacks of +C functions that are still active. +This stack initially contains any arguments to the C function +and it is where the C function pushes its results +to be returned to the caller (see <a href="#lua_CFunction"><code>lua_CFunction</code></a>). + + +<p> +For convenience, +most query operations in the API do not follow a strict stack discipline. +Instead, they can refer to any element in the stack +by using an <em>index</em>: +A positive index represents an <em>absolute</em> stack position +(starting at 1); +a negative index represents an <em>offset</em> relative to the top of the stack. +More specifically, if the stack has <em>n</em> elements, +then index 1 represents the first element +(that is, the element that was pushed onto the stack first) +and +index <em>n</em> represents the last element; +index -1 also represents the last element +(that is, the element at the top) +and index <em>-n</em> represents the first element. +We say that an index is <em>valid</em> +if it lies between 1 and the stack top +(that is, if <code>1 ≤ abs(index) ≤ top</code>). + + + + + + +<h2>3.2 - <a name="3.2">Stack Size</a></h2> + +<p> +When you interact with Lua API, +you are responsible for ensuring consistency. +In particular, +<em>you are responsible for controlling stack overflow</em>. +You can use the function <a href="#lua_checkstack"><code>lua_checkstack</code></a> +to grow the stack size. + + +<p> +Whenever Lua calls C, +it ensures that at least <a name="pdf-LUA_MINSTACK"><code>LUA_MINSTACK</code></a> stack positions are available. +<code>LUA_MINSTACK</code> is defined as 20, +so that usually you do not have to worry about stack space +unless your code has loops pushing elements onto the stack. + + +<p> +Most query functions accept as indices any value inside the +available stack space, that is, indices up to the maximum stack size +you have set through <a href="#lua_checkstack"><code>lua_checkstack</code></a>. +Such indices are called <em>acceptable indices</em>. +More formally, we define an <em>acceptable index</em> +as follows: + +<pre> + (index < 0 && abs(index) <= top) || + (index > 0 && index <= stackspace) +</pre><p> +Note that 0 is never an acceptable index. + + + + + +<h2>3.3 - <a name="3.3">Pseudo-Indices</a></h2> + +<p> +Unless otherwise noted, +any function that accepts valid indices can also be called with +<em>pseudo-indices</em>, +which represent some Lua values that are accessible to C code +but which are not in the stack. +Pseudo-indices are used to access the thread environment, +the function environment, +the registry, +and the upvalues of a C function (see <a href="#3.4">§3.4</a>). + + +<p> +The thread environment (where global variables live) is +always at pseudo-index <a name="pdf-LUA_GLOBALSINDEX"><code>LUA_GLOBALSINDEX</code></a>. +The environment of the running C function is always +at pseudo-index <a name="pdf-LUA_ENVIRONINDEX"><code>LUA_ENVIRONINDEX</code></a>. + + +<p> +To access and change the value of global variables, +you can use regular table operations over an environment table. +For instance, to access the value of a global variable, do + +<pre> + lua_getfield(L, LUA_GLOBALSINDEX, varname); +</pre> + + + + +<h2>3.4 - <a name="3.4">C Closures</a></h2> + +<p> +When a C function is created, +it is possible to associate some values with it, +thus creating a <em>C closure</em>; +these values are called <em>upvalues</em> and are +accessible to the function whenever it is called +(see <a href="#lua_pushcclosure"><code>lua_pushcclosure</code></a>). + + +<p> +Whenever a C function is called, +its upvalues are located at specific pseudo-indices. +These pseudo-indices are produced by the macro +<a name="lua_upvalueindex"><code>lua_upvalueindex</code></a>. +The first value associated with a function is at position +<code>lua_upvalueindex(1)</code>, and so on. +Any access to <code>lua_upvalueindex(<em>n</em>)</code>, +where <em>n</em> is greater than the number of upvalues of the +current function, +produces an acceptable (but invalid) index. + + + + + +<h2>3.5 - <a name="3.5">Registry</a></h2> + +<p> +Lua provides a <em>registry</em>, +a pre-defined table that can be used by any C code to +store whatever Lua value it needs to store. +This table is always located at pseudo-index +<a name="pdf-LUA_REGISTRYINDEX"><code>LUA_REGISTRYINDEX</code></a>. +Any C library can store data into this table, +but it should take care to choose keys different from those used +by other libraries, to avoid collisions. +Typically, you should use as key a string containing your library name +or a light userdata with the address of a C object in your code. + + +<p> +The integer keys in the registry are used by the reference mechanism, +implemented by the auxiliary library, +and therefore should not be used for other purposes. + + + + + +<h2>3.6 - <a name="3.6">Error Handling in C</a></h2> + +<p> +Internally, Lua uses the C <code>longjmp</code> facility to handle errors. +(You can also choose to use exceptions if you use C++; +see file <code>luaconf.h</code>.) +When Lua faces any error +(such as memory allocation errors, type errors, syntax errors, +and runtime errors) +it <em>raises</em> an error; +that is, it does a long jump. +A <em>protected environment</em> uses <code>setjmp</code> +to set a recover point; +any error jumps to the most recent active recover point. + + +<p> +Most functions in the API may throw an error, +for instance due to a memory allocation error. +The documentation for each function indicates whether +it can throw errors. + + +<p> +Inside a C function you can throw an error by calling <a href="#lua_error"><code>lua_error</code></a>. + + + + + +<h2>3.7 - <a name="3.7">Functions and Types</a></h2> + +<p> +Here we list all functions and types from the C API in +alphabetical order. +Each function has an indicator like this: +<span class="apii">[-o, +p, <em>x</em>]</span> + + +<p> +The first field, <code>o</code>, +is how many elements the function pops from the stack. +The second field, <code>p</code>, +is how many elements the function pushes onto the stack. +(Any function always pushes its results after popping its arguments.) +A field in the form <code>x|y</code> means the function may push (or pop) +<code>x</code> or <code>y</code> elements, +depending on the situation; +an interrogation mark '<code>?</code>' means that +we cannot know how many elements the function pops/pushes +by looking only at its arguments +(e.g., they may depend on what is on the stack). +The third field, <code>x</code>, +tells whether the function may throw errors: +'<code>-</code>' means the function never throws any error; +'<code>m</code>' means the function may throw an error +only due to not enough memory; +'<code>e</code>' means the function may throw other kinds of errors; +'<code>v</code>' means the function may throw an error on purpose. + + + +<hr><h3><a name="lua_Alloc"><code>lua_Alloc</code></a></h3> +<pre>typedef void * (*lua_Alloc) (void *ud, + void *ptr, + size_t osize, + size_t nsize);</pre> + +<p> +The type of the memory-allocation function used by Lua states. +The allocator function must provide a +functionality similar to <code>realloc</code>, +but not exactly the same. +Its arguments are +<code>ud</code>, an opaque pointer passed to <a href="#lua_newstate"><code>lua_newstate</code></a>; +<code>ptr</code>, a pointer to the block being allocated/reallocated/freed; +<code>osize</code>, the original size of the block; +<code>nsize</code>, the new size of the block. +<code>ptr</code> is <code>NULL</code> if and only if <code>osize</code> is zero. +When <code>nsize</code> is zero, the allocator must return <code>NULL</code>; +if <code>osize</code> is not zero, +it should free the block pointed to by <code>ptr</code>. +When <code>nsize</code> is not zero, the allocator returns <code>NULL</code> +if and only if it cannot fill the request. +When <code>nsize</code> is not zero and <code>osize</code> is zero, +the allocator should behave like <code>malloc</code>. +When <code>nsize</code> and <code>osize</code> are not zero, +the allocator behaves like <code>realloc</code>. +Lua assumes that the allocator never fails when +<code>osize >= nsize</code>. + + +<p> +Here is a simple implementation for the allocator function. +It is used in the auxiliary library by <a href="#luaL_newstate"><code>luaL_newstate</code></a>. + +<pre> + static void *l_alloc (void *ud, void *ptr, size_t osize, + size_t nsize) { + (void)ud; (void)osize; /* not used */ + if (nsize == 0) { + free(ptr); + return NULL; + } + else + return realloc(ptr, nsize); + } +</pre><p> +This code assumes +that <code>free(NULL)</code> has no effect and that +<code>realloc(NULL, size)</code> is equivalent to <code>malloc(size)</code>. +ANSI C ensures both behaviors. + + + + + +<hr><h3><a name="lua_atpanic"><code>lua_atpanic</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf);</pre> + +<p> +Sets a new panic function and returns the old one. + + +<p> +If an error happens outside any protected environment, +Lua calls a <em>panic function</em> +and then calls <code>exit(EXIT_FAILURE)</code>, +thus exiting the host application. +Your panic function may avoid this exit by +never returning (e.g., doing a long jump). + + +<p> +The panic function can access the error message at the top of the stack. + + + + + +<hr><h3><a name="lua_call"><code>lua_call</code></a></h3><p> +<span class="apii">[-(nargs + 1), +nresults, <em>e</em>]</span> +<pre>void lua_call (lua_State *L, int nargs, int nresults);</pre> + +<p> +Calls a function. + + +<p> +To call a function you must use the following protocol: +first, the function to be called is pushed onto the stack; +then, the arguments to the function are pushed +in direct order; +that is, the first argument is pushed first. +Finally you call <a href="#lua_call"><code>lua_call</code></a>; +<code>nargs</code> is the number of arguments that you pushed onto the stack. +All arguments and the function value are popped from the stack +when the function is called. +The function results are pushed onto the stack when the function returns. +The number of results is adjusted to <code>nresults</code>, +unless <code>nresults</code> is <a name="pdf-LUA_MULTRET"><code>LUA_MULTRET</code></a>. +In this case, <em>all</em> results from the function are pushed. +Lua takes care that the returned values fit into the stack space. +The function results are pushed onto the stack in direct order +(the first result is pushed first), +so that after the call the last result is on the top of the stack. + + +<p> +Any error inside the called function is propagated upwards +(with a <code>longjmp</code>). + + +<p> +The following example shows how the host program may do the +equivalent to this Lua code: + +<pre> + a = f("how", t.x, 14) +</pre><p> +Here it is in C: + +<pre> + lua_getfield(L, LUA_GLOBALSINDEX, "f"); /* function to be called */ + lua_pushstring(L, "how"); /* 1st argument */ + lua_getfield(L, LUA_GLOBALSINDEX, "t"); /* table to be indexed */ + lua_getfield(L, -1, "x"); /* push result of t.x (2nd arg) */ + lua_remove(L, -2); /* remove 't' from the stack */ + lua_pushinteger(L, 14); /* 3rd argument */ + lua_call(L, 3, 1); /* call 'f' with 3 arguments and 1 result */ + lua_setfield(L, LUA_GLOBALSINDEX, "a"); /* set global 'a' */ +</pre><p> +Note that the code above is "balanced": +at its end, the stack is back to its original configuration. +This is considered good programming practice. + + + + + +<hr><h3><a name="lua_CFunction"><code>lua_CFunction</code></a></h3> +<pre>typedef int (*lua_CFunction) (lua_State *L);</pre> + +<p> +Type for C functions. + + +<p> +In order to communicate properly with Lua, +a C function must use the following protocol, +which defines the way parameters and results are passed: +a C function receives its arguments from Lua in its stack +in direct order (the first argument is pushed first). +So, when the function starts, +<code>lua_gettop(L)</code> returns the number of arguments received by the function. +The first argument (if any) is at index 1 +and its last argument is at index <code>lua_gettop(L)</code>. +To return values to Lua, a C function just pushes them onto the stack, +in direct order (the first result is pushed first), +and returns the number of results. +Any other value in the stack below the results will be properly +discarded by Lua. +Like a Lua function, a C function called by Lua can also return +many results. + + +<p> +As an example, the following function receives a variable number +of numerical arguments and returns their average and sum: + +<pre> + static int foo (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + lua_Number sum = 0; + int i; + for (i = 1; i <= n; i++) { + if (!lua_isnumber(L, i)) { + lua_pushstring(L, "incorrect argument"); + lua_error(L); + } + sum += lua_tonumber(L, i); + } + lua_pushnumber(L, sum/n); /* first result */ + lua_pushnumber(L, sum); /* second result */ + return 2; /* number of results */ + } +</pre> + + + + +<hr><h3><a name="lua_checkstack"><code>lua_checkstack</code></a></h3><p> +<span class="apii">[-0, +0, <em>m</em>]</span> +<pre>int lua_checkstack (lua_State *L, int extra);</pre> + +<p> +Ensures that there are at least <code>extra</code> free stack slots in the stack. +It returns false if it cannot grow the stack to that size. +This function never shrinks the stack; +if the stack is already larger than the new size, +it is left unchanged. + + + + + +<hr><h3><a name="lua_close"><code>lua_close</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>void lua_close (lua_State *L);</pre> + +<p> +Destroys all objects in the given Lua state +(calling the corresponding garbage-collection metamethods, if any) +and frees all dynamic memory used by this state. +On several platforms, you may not need to call this function, +because all resources are naturally released when the host program ends. +On the other hand, long-running programs, +such as a daemon or a web server, +might need to release states as soon as they are not needed, +to avoid growing too large. + + + + + +<hr><h3><a name="lua_concat"><code>lua_concat</code></a></h3><p> +<span class="apii">[-n, +1, <em>e</em>]</span> +<pre>void lua_concat (lua_State *L, int n);</pre> + +<p> +Concatenates the <code>n</code> values at the top of the stack, +pops them, and leaves the result at the top. +If <code>n</code> is 1, the result is the single value on the stack +(that is, the function does nothing); +if <code>n</code> is 0, the result is the empty string. +Concatenation is performed following the usual semantics of Lua +(see <a href="#2.5.4">§2.5.4</a>). + + + + + +<hr><h3><a name="lua_cpcall"><code>lua_cpcall</code></a></h3><p> +<span class="apii">[-0, +(0|1), <em>-</em>]</span> +<pre>int lua_cpcall (lua_State *L, lua_CFunction func, void *ud);</pre> + +<p> +Calls the C function <code>func</code> in protected mode. +<code>func</code> starts with only one element in its stack, +a light userdata containing <code>ud</code>. +In case of errors, +<a href="#lua_cpcall"><code>lua_cpcall</code></a> returns the same error codes as <a href="#lua_pcall"><code>lua_pcall</code></a>, +plus the error object on the top of the stack; +otherwise, it returns zero, and does not change the stack. +All values returned by <code>func</code> are discarded. + + + + + +<hr><h3><a name="lua_createtable"><code>lua_createtable</code></a></h3><p> +<span class="apii">[-0, +1, <em>m</em>]</span> +<pre>void lua_createtable (lua_State *L, int narr, int nrec);</pre> + +<p> +Creates a new empty table and pushes it onto the stack. +The new table has space pre-allocated +for <code>narr</code> array elements and <code>nrec</code> non-array elements. +This pre-allocation is useful when you know exactly how many elements +the table will have. +Otherwise you can use the function <a href="#lua_newtable"><code>lua_newtable</code></a>. + + + + + +<hr><h3><a name="lua_dump"><code>lua_dump</code></a></h3><p> +<span class="apii">[-0, +0, <em>m</em>]</span> +<pre>int lua_dump (lua_State *L, lua_Writer writer, void *data);</pre> + +<p> +Dumps a function as a binary chunk. +Receives a Lua function on the top of the stack +and produces a binary chunk that, +if loaded again, +results in a function equivalent to the one dumped. +As it produces parts of the chunk, +<a href="#lua_dump"><code>lua_dump</code></a> calls function <code>writer</code> (see <a href="#lua_Writer"><code>lua_Writer</code></a>) +with the given <code>data</code> +to write them. + + +<p> +The value returned is the error code returned by the last +call to the writer; +0 means no errors. + + +<p> +This function does not pop the Lua function from the stack. + + + + + +<hr><h3><a name="lua_equal"><code>lua_equal</code></a></h3><p> +<span class="apii">[-0, +0, <em>e</em>]</span> +<pre>int lua_equal (lua_State *L, int index1, int index2);</pre> + +<p> +Returns 1 if the two values in acceptable indices <code>index1</code> and +<code>index2</code> are equal, +following the semantics of the Lua <code>==</code> operator +(that is, may call metamethods). +Otherwise returns 0. +Also returns 0 if any of the indices is non valid. + + + + + +<hr><h3><a name="lua_error"><code>lua_error</code></a></h3><p> +<span class="apii">[-1, +0, <em>v</em>]</span> +<pre>int lua_error (lua_State *L);</pre> + +<p> +Generates a Lua error. +The error message (which can actually be a Lua value of any type) +must be on the stack top. +This function does a long jump, +and therefore never returns. +(see <a href="#luaL_error"><code>luaL_error</code></a>). + + + + + +<hr><h3><a name="lua_gc"><code>lua_gc</code></a></h3><p> +<span class="apii">[-0, +0, <em>e</em>]</span> +<pre>int lua_gc (lua_State *L, int what, int data);</pre> + +<p> +Controls the garbage collector. + + +<p> +This function performs several tasks, +according to the value of the parameter <code>what</code>: + +<ul> + +<li><b><code>LUA_GCSTOP</code>:</b> +stops the garbage collector. +</li> + +<li><b><code>LUA_GCRESTART</code>:</b> +restarts the garbage collector. +</li> + +<li><b><code>LUA_GCCOLLECT</code>:</b> +performs a full garbage-collection cycle. +</li> + +<li><b><code>LUA_GCCOUNT</code>:</b> +returns the current amount of memory (in Kbytes) in use by Lua. +</li> + +<li><b><code>LUA_GCCOUNTB</code>:</b> +returns the remainder of dividing the current amount of bytes of +memory in use by Lua by 1024. +</li> + +<li><b><code>LUA_GCSTEP</code>:</b> +performs an incremental step of garbage collection. +The step "size" is controlled by <code>data</code> +(larger values mean more steps) in a non-specified way. +If you want to control the step size +you must experimentally tune the value of <code>data</code>. +The function returns 1 if the step finished a +garbage-collection cycle. +</li> + +<li><b><code>LUA_GCSETPAUSE</code>:</b> +sets <code>data</code>/100 as the new value +for the <em>pause</em> of the collector (see <a href="#2.10">§2.10</a>). +The function returns the previous value of the pause. +</li> + +<li><b><code>LUA_GCSETSTEPMUL</code>:</b> +sets <code>data</code>/100 as the new value for the <em>step multiplier</em> of +the collector (see <a href="#2.10">§2.10</a>). +The function returns the previous value of the step multiplier. +</li> + +</ul> + + + + +<hr><h3><a name="lua_getallocf"><code>lua_getallocf</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>lua_Alloc lua_getallocf (lua_State *L, void **ud);</pre> + +<p> +Returns the memory-allocation function of a given state. +If <code>ud</code> is not <code>NULL</code>, Lua stores in <code>*ud</code> the +opaque pointer passed to <a href="#lua_newstate"><code>lua_newstate</code></a>. + + + + + +<hr><h3><a name="lua_getfenv"><code>lua_getfenv</code></a></h3><p> +<span class="apii">[-0, +1, <em>-</em>]</span> +<pre>void lua_getfenv (lua_State *L, int index);</pre> + +<p> +Pushes onto the stack the environment table of +the value at the given index. + + + + + +<hr><h3><a name="lua_getfield"><code>lua_getfield</code></a></h3><p> +<span class="apii">[-0, +1, <em>e</em>]</span> +<pre>void lua_getfield (lua_State *L, int index, const char *k);</pre> + +<p> +Pushes onto the stack the value <code>t[k]</code>, +where <code>t</code> is the value at the given valid index. +As in Lua, this function may trigger a metamethod +for the "index" event (see <a href="#2.8">§2.8</a>). + + + + + +<hr><h3><a name="lua_getglobal"><code>lua_getglobal</code></a></h3><p> +<span class="apii">[-0, +1, <em>e</em>]</span> +<pre>void lua_getglobal (lua_State *L, const char *name);</pre> + +<p> +Pushes onto the stack the value of the global <code>name</code>. +It is defined as a macro: + +<pre> + #define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, s) +</pre> + + + + +<hr><h3><a name="lua_getmetatable"><code>lua_getmetatable</code></a></h3><p> +<span class="apii">[-0, +(0|1), <em>-</em>]</span> +<pre>int lua_getmetatable (lua_State *L, int index);</pre> + +<p> +Pushes onto the stack the metatable of the value at the given +acceptable index. +If the index is not valid, +or if the value does not have a metatable, +the function returns 0 and pushes nothing on the stack. + + + + + +<hr><h3><a name="lua_gettable"><code>lua_gettable</code></a></h3><p> +<span class="apii">[-1, +1, <em>e</em>]</span> +<pre>void lua_gettable (lua_State *L, int index);</pre> + +<p> +Pushes onto the stack the value <code>t[k]</code>, +where <code>t</code> is the value at the given valid index +and <code>k</code> is the value at the top of the stack. + + +<p> +This function pops the key from the stack +(putting the resulting value in its place). +As in Lua, this function may trigger a metamethod +for the "index" event (see <a href="#2.8">§2.8</a>). + + + + + +<hr><h3><a name="lua_gettop"><code>lua_gettop</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>int lua_gettop (lua_State *L);</pre> + +<p> +Returns the index of the top element in the stack. +Because indices start at 1, +this result is equal to the number of elements in the stack +(and so 0 means an empty stack). + + + + + +<hr><h3><a name="lua_insert"><code>lua_insert</code></a></h3><p> +<span class="apii">[-1, +1, <em>-</em>]</span> +<pre>void lua_insert (lua_State *L, int index);</pre> + +<p> +Moves the top element into the given valid index, +shifting up the elements above this index to open space. +Cannot be called with a pseudo-index, +because a pseudo-index is not an actual stack position. + + + + + +<hr><h3><a name="lua_Integer"><code>lua_Integer</code></a></h3> +<pre>typedef ptrdiff_t lua_Integer;</pre> + +<p> +The type used by the Lua API to represent integral values. + + +<p> +By default it is a <code>ptrdiff_t</code>, +which is usually the largest signed integral type the machine handles +"comfortably". + + + + + +<hr><h3><a name="lua_isboolean"><code>lua_isboolean</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>int lua_isboolean (lua_State *L, int index);</pre> + +<p> +Returns 1 if the value at the given acceptable index has type boolean, +and 0 otherwise. + + + + + +<hr><h3><a name="lua_iscfunction"><code>lua_iscfunction</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>int lua_iscfunction (lua_State *L, int index);</pre> + +<p> +Returns 1 if the value at the given acceptable index is a C function, +and 0 otherwise. + + + + + +<hr><h3><a name="lua_isfunction"><code>lua_isfunction</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>int lua_isfunction (lua_State *L, int index);</pre> + +<p> +Returns 1 if the value at the given acceptable index is a function +(either C or Lua), and 0 otherwise. + + + + + +<hr><h3><a name="lua_islightuserdata"><code>lua_islightuserdata</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>int lua_islightuserdata (lua_State *L, int index);</pre> + +<p> +Returns 1 if the value at the given acceptable index is a light userdata, +and 0 otherwise. + + + + + +<hr><h3><a name="lua_isnil"><code>lua_isnil</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>int lua_isnil (lua_State *L, int index);</pre> + +<p> +Returns 1 if the value at the given acceptable index is <b>nil</b>, +and 0 otherwise. + + + + + +<hr><h3><a name="lua_isnone"><code>lua_isnone</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>int lua_isnone (lua_State *L, int index);</pre> + +<p> +Returns 1 if the given acceptable index is not valid +(that is, it refers to an element outside the current stack), +and 0 otherwise. + + + + + +<hr><h3><a name="lua_isnoneornil"><code>lua_isnoneornil</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>int lua_isnoneornil (lua_State *L, int index);</pre> + +<p> +Returns 1 if the given acceptable index is not valid +(that is, it refers to an element outside the current stack) +or if the value at this index is <b>nil</b>, +and 0 otherwise. + + + + + +<hr><h3><a name="lua_isnumber"><code>lua_isnumber</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>int lua_isnumber (lua_State *L, int index);</pre> + +<p> +Returns 1 if the value at the given acceptable index is a number +or a string convertible to a number, +and 0 otherwise. + + + + + +<hr><h3><a name="lua_isstring"><code>lua_isstring</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>int lua_isstring (lua_State *L, int index);</pre> + +<p> +Returns 1 if the value at the given acceptable index is a string +or a number (which is always convertible to a string), +and 0 otherwise. + + + + + +<hr><h3><a name="lua_istable"><code>lua_istable</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>int lua_istable (lua_State *L, int index);</pre> + +<p> +Returns 1 if the value at the given acceptable index is a table, +and 0 otherwise. + + + + + +<hr><h3><a name="lua_isthread"><code>lua_isthread</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>int lua_isthread (lua_State *L, int index);</pre> + +<p> +Returns 1 if the value at the given acceptable index is a thread, +and 0 otherwise. + + + + + +<hr><h3><a name="lua_isuserdata"><code>lua_isuserdata</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>int lua_isuserdata (lua_State *L, int index);</pre> + +<p> +Returns 1 if the value at the given acceptable index is a userdata +(either full or light), and 0 otherwise. + + + + + +<hr><h3><a name="lua_lessthan"><code>lua_lessthan</code></a></h3><p> +<span class="apii">[-0, +0, <em>e</em>]</span> +<pre>int lua_lessthan (lua_State *L, int index1, int index2);</pre> + +<p> +Returns 1 if the value at acceptable index <code>index1</code> is smaller +than the value at acceptable index <code>index2</code>, +following the semantics of the Lua <code><</code> operator +(that is, may call metamethods). +Otherwise returns 0. +Also returns 0 if any of the indices is non valid. + + + + + +<hr><h3><a name="lua_load"><code>lua_load</code></a></h3><p> +<span class="apii">[-0, +1, <em>-</em>]</span> +<pre>int lua_load (lua_State *L, + lua_Reader reader, + void *data, + const char *chunkname);</pre> + +<p> +Loads a Lua chunk. +If there are no errors, +<a href="#lua_load"><code>lua_load</code></a> pushes the compiled chunk as a Lua +function on top of the stack. +Otherwise, it pushes an error message. +The return values of <a href="#lua_load"><code>lua_load</code></a> are: + +<ul> + +<li><b>0:</b> no errors;</li> + +<li><b><a name="pdf-LUA_ERRSYNTAX"><code>LUA_ERRSYNTAX</code></a>:</b> +syntax error during pre-compilation;</li> + +<li><b><a href="#pdf-LUA_ERRMEM"><code>LUA_ERRMEM</code></a>:</b> +memory allocation error.</li> + +</ul> + +<p> +This function only loads a chunk; +it does not run it. + + +<p> +<a href="#lua_load"><code>lua_load</code></a> automatically detects whether the chunk is text or binary, +and loads it accordingly (see program <code>luac</code>). + + +<p> +The <a href="#lua_load"><code>lua_load</code></a> function uses a user-supplied <code>reader</code> function +to read the chunk (see <a href="#lua_Reader"><code>lua_Reader</code></a>). +The <code>data</code> argument is an opaque value passed to the reader function. + + +<p> +The <code>chunkname</code> argument gives a name to the chunk, +which is used for error messages and in debug information (see <a href="#3.8">§3.8</a>). + + + + + +<hr><h3><a name="lua_newstate"><code>lua_newstate</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>lua_State *lua_newstate (lua_Alloc f, void *ud);</pre> + +<p> +Creates a new, independent state. +Returns <code>NULL</code> if cannot create the state +(due to lack of memory). +The argument <code>f</code> is the allocator function; +Lua does all memory allocation for this state through this function. +The second argument, <code>ud</code>, is an opaque pointer that Lua +simply passes to the allocator in every call. + + + + + +<hr><h3><a name="lua_newtable"><code>lua_newtable</code></a></h3><p> +<span class="apii">[-0, +1, <em>m</em>]</span> +<pre>void lua_newtable (lua_State *L);</pre> + +<p> +Creates a new empty table and pushes it onto the stack. +It is equivalent to <code>lua_createtable(L, 0, 0)</code>. + + + + + +<hr><h3><a name="lua_newthread"><code>lua_newthread</code></a></h3><p> +<span class="apii">[-0, +1, <em>m</em>]</span> +<pre>lua_State *lua_newthread (lua_State *L);</pre> + +<p> +Creates a new thread, pushes it on the stack, +and returns a pointer to a <a href="#lua_State"><code>lua_State</code></a> that represents this new thread. +The new state returned by this function shares with the original state +all global objects (such as tables), +but has an independent execution stack. + + +<p> +There is no explicit function to close or to destroy a thread. +Threads are subject to garbage collection, +like any Lua object. + + + + + +<hr><h3><a name="lua_newuserdata"><code>lua_newuserdata</code></a></h3><p> +<span class="apii">[-0, +1, <em>m</em>]</span> +<pre>void *lua_newuserdata (lua_State *L, size_t size);</pre> + +<p> +This function allocates a new block of memory with the given size, +pushes onto the stack a new full userdata with the block address, +and returns this address. + + +<p> +Userdata represent C values in Lua. +A <em>full userdata</em> represents a block of memory. +It is an object (like a table): +you must create it, it can have its own metatable, +and you can detect when it is being collected. +A full userdata is only equal to itself (under raw equality). + + +<p> +When Lua collects a full userdata with a <code>gc</code> metamethod, +Lua calls the metamethod and marks the userdata as finalized. +When this userdata is collected again then +Lua frees its corresponding memory. + + + + + +<hr><h3><a name="lua_next"><code>lua_next</code></a></h3><p> +<span class="apii">[-1, +(2|0), <em>e</em>]</span> +<pre>int lua_next (lua_State *L, int index);</pre> + +<p> +Pops a key from the stack, +and pushes a key-value pair from the table at the given index +(the "next" pair after the given key). +If there are no more elements in the table, +then <a href="#lua_next"><code>lua_next</code></a> returns 0 (and pushes nothing). + + +<p> +A typical traversal looks like this: + +<pre> + /* table is in the stack at index 't' */ + lua_pushnil(L); /* first key */ + while (lua_next(L, t) != 0) { + /* uses 'key' (at index -2) and 'value' (at index -1) */ + printf("%s - %s\n", + lua_typename(L, lua_type(L, -2)), + lua_typename(L, lua_type(L, -1))); + /* removes 'value'; keeps 'key' for next iteration */ + lua_pop(L, 1); + } +</pre> + +<p> +While traversing a table, +do not call <a href="#lua_tolstring"><code>lua_tolstring</code></a> directly on a key, +unless you know that the key is actually a string. +Recall that <a href="#lua_tolstring"><code>lua_tolstring</code></a> <em>changes</em> +the value at the given index; +this confuses the next call to <a href="#lua_next"><code>lua_next</code></a>. + + + + + +<hr><h3><a name="lua_Number"><code>lua_Number</code></a></h3> +<pre>typedef double lua_Number;</pre> + +<p> +The type of numbers in Lua. +By default, it is double, but that can be changed in <code>luaconf.h</code>. + + +<p> +Through the configuration file you can change +Lua to operate with another type for numbers (e.g., float or long). + + + + + +<hr><h3><a name="lua_objlen"><code>lua_objlen</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>size_t lua_objlen (lua_State *L, int index);</pre> + +<p> +Returns the "length" of the value at the given acceptable index: +for strings, this is the string length; +for tables, this is the result of the length operator ('<code>#</code>'); +for userdata, this is the size of the block of memory allocated +for the userdata; +for other values, it is 0. + + + + + +<hr><h3><a name="lua_pcall"><code>lua_pcall</code></a></h3><p> +<span class="apii">[-(nargs + 1), +(nresults|1), <em>-</em>]</span> +<pre>int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc);</pre> + +<p> +Calls a function in protected mode. + + +<p> +Both <code>nargs</code> and <code>nresults</code> have the same meaning as +in <a href="#lua_call"><code>lua_call</code></a>. +If there are no errors during the call, +<a href="#lua_pcall"><code>lua_pcall</code></a> behaves exactly like <a href="#lua_call"><code>lua_call</code></a>. +However, if there is any error, +<a href="#lua_pcall"><code>lua_pcall</code></a> catches it, +pushes a single value on the stack (the error message), +and returns an error code. +Like <a href="#lua_call"><code>lua_call</code></a>, +<a href="#lua_pcall"><code>lua_pcall</code></a> always removes the function +and its arguments from the stack. + + +<p> +If <code>errfunc</code> is 0, +then the error message returned on the stack +is exactly the original error message. +Otherwise, <code>errfunc</code> is the stack index of an +<em>error handler function</em>. +(In the current implementation, this index cannot be a pseudo-index.) +In case of runtime errors, +this function will be called with the error message +and its return value will be the message returned on the stack by <a href="#lua_pcall"><code>lua_pcall</code></a>. + + +<p> +Typically, the error handler function is used to add more debug +information to the error message, such as a stack traceback. +Such information cannot be gathered after the return of <a href="#lua_pcall"><code>lua_pcall</code></a>, +since by then the stack has unwound. + + +<p> +The <a href="#lua_pcall"><code>lua_pcall</code></a> function returns 0 in case of success +or one of the following error codes +(defined in <code>lua.h</code>): + +<ul> + +<li><b><a name="pdf-LUA_ERRRUN"><code>LUA_ERRRUN</code></a>:</b> +a runtime error. +</li> + +<li><b><a name="pdf-LUA_ERRMEM"><code>LUA_ERRMEM</code></a>:</b> +memory allocation error. +For such errors, Lua does not call the error handler function. +</li> + +<li><b><a name="pdf-LUA_ERRERR"><code>LUA_ERRERR</code></a>:</b> +error while running the error handler function. +</li> + +</ul> + + + + +<hr><h3><a name="lua_pop"><code>lua_pop</code></a></h3><p> +<span class="apii">[-n, +0, <em>-</em>]</span> +<pre>void lua_pop (lua_State *L, int n);</pre> + +<p> +Pops <code>n</code> elements from the stack. + + + + + +<hr><h3><a name="lua_pushboolean"><code>lua_pushboolean</code></a></h3><p> +<span class="apii">[-0, +1, <em>-</em>]</span> +<pre>void lua_pushboolean (lua_State *L, int b);</pre> + +<p> +Pushes a boolean value with value <code>b</code> onto the stack. + + + + + +<hr><h3><a name="lua_pushcclosure"><code>lua_pushcclosure</code></a></h3><p> +<span class="apii">[-n, +1, <em>m</em>]</span> +<pre>void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);</pre> + +<p> +Pushes a new C closure onto the stack. + + +<p> +When a C function is created, +it is possible to associate some values with it, +thus creating a C closure (see <a href="#3.4">§3.4</a>); +these values are then accessible to the function whenever it is called. +To associate values with a C function, +first these values should be pushed onto the stack +(when there are multiple values, the first value is pushed first). +Then <a href="#lua_pushcclosure"><code>lua_pushcclosure</code></a> +is called to create and push the C function onto the stack, +with the argument <code>n</code> telling how many values should be +associated with the function. +<a href="#lua_pushcclosure"><code>lua_pushcclosure</code></a> also pops these values from the stack. + + + + + +<hr><h3><a name="lua_pushcfunction"><code>lua_pushcfunction</code></a></h3><p> +<span class="apii">[-0, +1, <em>m</em>]</span> +<pre>void lua_pushcfunction (lua_State *L, lua_CFunction f);</pre> + +<p> +Pushes a C function onto the stack. +This function receives a pointer to a C function +and pushes onto the stack a Lua value of type <code>function</code> that, +when called, invokes the corresponding C function. + + +<p> +Any function to be registered in Lua must +follow the correct protocol to receive its parameters +and return its results (see <a href="#lua_CFunction"><code>lua_CFunction</code></a>). + + +<p> +<code>lua_pushcfunction</code> is defined as a macro: + +<pre> + #define lua_pushcfunction(L,f) lua_pushcclosure(L,f,0) +</pre> + + + + +<hr><h3><a name="lua_pushfstring"><code>lua_pushfstring</code></a></h3><p> +<span class="apii">[-0, +1, <em>m</em>]</span> +<pre>const char *lua_pushfstring (lua_State *L, const char *fmt, ...);</pre> + +<p> +Pushes onto the stack a formatted string +and returns a pointer to this string. +It is similar to the C function <code>sprintf</code>, +but has some important differences: + +<ul> + +<li> +You do not have to allocate space for the result: +the result is a Lua string and Lua takes care of memory allocation +(and deallocation, through garbage collection). +</li> + +<li> +The conversion specifiers are quite restricted. +There are no flags, widths, or precisions. +The conversion specifiers can only be +'<code>%%</code>' (inserts a '<code>%</code>' in the string), +'<code>%s</code>' (inserts a zero-terminated string, with no size restrictions), +'<code>%f</code>' (inserts a <a href="#lua_Number"><code>lua_Number</code></a>), +'<code>%p</code>' (inserts a pointer as a hexadecimal numeral), +'<code>%d</code>' (inserts an <code>int</code>), and +'<code>%c</code>' (inserts an <code>int</code> as a character). +</li> + +</ul> + + + + +<hr><h3><a name="lua_pushinteger"><code>lua_pushinteger</code></a></h3><p> +<span class="apii">[-0, +1, <em>-</em>]</span> +<pre>void lua_pushinteger (lua_State *L, lua_Integer n);</pre> + +<p> +Pushes a number with value <code>n</code> onto the stack. + + + + + +<hr><h3><a name="lua_pushlightuserdata"><code>lua_pushlightuserdata</code></a></h3><p> +<span class="apii">[-0, +1, <em>-</em>]</span> +<pre>void lua_pushlightuserdata (lua_State *L, void *p);</pre> + +<p> +Pushes a light userdata onto the stack. + + +<p> +Userdata represent C values in Lua. +A <em>light userdata</em> represents a pointer. +It is a value (like a number): +you do not create it, it has no individual metatable, +and it is not collected (as it was never created). +A light userdata is equal to "any" +light userdata with the same C address. + + + + + +<hr><h3><a name="lua_pushliteral"><code>lua_pushliteral</code></a></h3><p> +<span class="apii">[-0, +1, <em>m</em>]</span> +<pre>void lua_pushliteral (lua_State *L, const char *s);</pre> + +<p> +This macro is equivalent to <a href="#lua_pushlstring"><code>lua_pushlstring</code></a>, +but can be used only when <code>s</code> is a literal string. +In these cases, it automatically provides the string length. + + + + + +<hr><h3><a name="lua_pushlstring"><code>lua_pushlstring</code></a></h3><p> +<span class="apii">[-0, +1, <em>m</em>]</span> +<pre>void lua_pushlstring (lua_State *L, const char *s, size_t len);</pre> + +<p> +Pushes the string pointed to by <code>s</code> with size <code>len</code> +onto the stack. +Lua makes (or reuses) an internal copy of the given string, +so the memory at <code>s</code> can be freed or reused immediately after +the function returns. +The string can contain embedded zeros. + + + + + +<hr><h3><a name="lua_pushnil"><code>lua_pushnil</code></a></h3><p> +<span class="apii">[-0, +1, <em>-</em>]</span> +<pre>void lua_pushnil (lua_State *L);</pre> + +<p> +Pushes a nil value onto the stack. + + + + + +<hr><h3><a name="lua_pushnumber"><code>lua_pushnumber</code></a></h3><p> +<span class="apii">[-0, +1, <em>-</em>]</span> +<pre>void lua_pushnumber (lua_State *L, lua_Number n);</pre> + +<p> +Pushes a number with value <code>n</code> onto the stack. + + + + + +<hr><h3><a name="lua_pushstring"><code>lua_pushstring</code></a></h3><p> +<span class="apii">[-0, +1, <em>m</em>]</span> +<pre>void lua_pushstring (lua_State *L, const char *s);</pre> + +<p> +Pushes the zero-terminated string pointed to by <code>s</code> +onto the stack. +Lua makes (or reuses) an internal copy of the given string, +so the memory at <code>s</code> can be freed or reused immediately after +the function returns. +The string cannot contain embedded zeros; +it is assumed to end at the first zero. + + + + + +<hr><h3><a name="lua_pushthread"><code>lua_pushthread</code></a></h3><p> +<span class="apii">[-0, +1, <em>-</em>]</span> +<pre>int lua_pushthread (lua_State *L);</pre> + +<p> +Pushes the thread represented by <code>L</code> onto the stack. +Returns 1 if this thread is the main thread of its state. + + + + + +<hr><h3><a name="lua_pushvalue"><code>lua_pushvalue</code></a></h3><p> +<span class="apii">[-0, +1, <em>-</em>]</span> +<pre>void lua_pushvalue (lua_State *L, int index);</pre> + +<p> +Pushes a copy of the element at the given valid index +onto the stack. + + + + + +<hr><h3><a name="lua_pushvfstring"><code>lua_pushvfstring</code></a></h3><p> +<span class="apii">[-0, +1, <em>m</em>]</span> +<pre>const char *lua_pushvfstring (lua_State *L, + const char *fmt, + va_list argp);</pre> + +<p> +Equivalent to <a href="#lua_pushfstring"><code>lua_pushfstring</code></a>, except that it receives a <code>va_list</code> +instead of a variable number of arguments. + + + + + +<hr><h3><a name="lua_rawequal"><code>lua_rawequal</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>int lua_rawequal (lua_State *L, int index1, int index2);</pre> + +<p> +Returns 1 if the two values in acceptable indices <code>index1</code> and +<code>index2</code> are primitively equal +(that is, without calling metamethods). +Otherwise returns 0. +Also returns 0 if any of the indices are non valid. + + + + + +<hr><h3><a name="lua_rawget"><code>lua_rawget</code></a></h3><p> +<span class="apii">[-1, +1, <em>-</em>]</span> +<pre>void lua_rawget (lua_State *L, int index);</pre> + +<p> +Similar to <a href="#lua_gettable"><code>lua_gettable</code></a>, but does a raw access +(i.e., without metamethods). + + + + + +<hr><h3><a name="lua_rawgeti"><code>lua_rawgeti</code></a></h3><p> +<span class="apii">[-0, +1, <em>-</em>]</span> +<pre>void lua_rawgeti (lua_State *L, int index, int n);</pre> + +<p> +Pushes onto the stack the value <code>t[n]</code>, +where <code>t</code> is the value at the given valid index. +The access is raw; +that is, it does not invoke metamethods. + + + + + +<hr><h3><a name="lua_rawset"><code>lua_rawset</code></a></h3><p> +<span class="apii">[-2, +0, <em>m</em>]</span> +<pre>void lua_rawset (lua_State *L, int index);</pre> + +<p> +Similar to <a href="#lua_settable"><code>lua_settable</code></a>, but does a raw assignment +(i.e., without metamethods). + + + + + +<hr><h3><a name="lua_rawseti"><code>lua_rawseti</code></a></h3><p> +<span class="apii">[-1, +0, <em>m</em>]</span> +<pre>void lua_rawseti (lua_State *L, int index, int n);</pre> + +<p> +Does the equivalent of <code>t[n] = v</code>, +where <code>t</code> is the value at the given valid index +and <code>v</code> is the value at the top of the stack. + + +<p> +This function pops the value from the stack. +The assignment is raw; +that is, it does not invoke metamethods. + + + + + +<hr><h3><a name="lua_Reader"><code>lua_Reader</code></a></h3> +<pre>typedef const char * (*lua_Reader) (lua_State *L, + void *data, + size_t *size);</pre> + +<p> +The reader function used by <a href="#lua_load"><code>lua_load</code></a>. +Every time it needs another piece of the chunk, +<a href="#lua_load"><code>lua_load</code></a> calls the reader, +passing along its <code>data</code> parameter. +The reader must return a pointer to a block of memory +with a new piece of the chunk +and set <code>size</code> to the block size. +The block must exist until the reader function is called again. +To signal the end of the chunk, the reader must return <code>NULL</code>. +The reader function may return pieces of any size greater than zero. + + + + + +<hr><h3><a name="lua_register"><code>lua_register</code></a></h3><p> +<span class="apii">[-0, +0, <em>e</em>]</span> +<pre>void lua_register (lua_State *L, + const char *name, + lua_CFunction f);</pre> + +<p> +Sets the C function <code>f</code> as the new value of global <code>name</code>. +It is defined as a macro: + +<pre> + #define lua_register(L,n,f) \ + (lua_pushcfunction(L, f), lua_setglobal(L, n)) +</pre> + + + + +<hr><h3><a name="lua_remove"><code>lua_remove</code></a></h3><p> +<span class="apii">[-1, +0, <em>-</em>]</span> +<pre>void lua_remove (lua_State *L, int index);</pre> + +<p> +Removes the element at the given valid index, +shifting down the elements above this index to fill the gap. +Cannot be called with a pseudo-index, +because a pseudo-index is not an actual stack position. + + + + + +<hr><h3><a name="lua_replace"><code>lua_replace</code></a></h3><p> +<span class="apii">[-1, +0, <em>-</em>]</span> +<pre>void lua_replace (lua_State *L, int index);</pre> + +<p> +Moves the top element into the given position (and pops it), +without shifting any element +(therefore replacing the value at the given position). + + + + + +<hr><h3><a name="lua_resume"><code>lua_resume</code></a></h3><p> +<span class="apii">[-?, +?, <em>-</em>]</span> +<pre>int lua_resume (lua_State *L, int narg);</pre> + +<p> +Starts and resumes a coroutine in a given thread. + + +<p> +To start a coroutine, you first create a new thread +(see <a href="#lua_newthread"><code>lua_newthread</code></a>); +then you push onto its stack the main function plus any arguments; +then you call <a href="#lua_resume"><code>lua_resume</code></a>, +with <code>narg</code> being the number of arguments. +This call returns when the coroutine suspends or finishes its execution. +When it returns, the stack contains all values passed to <a href="#lua_yield"><code>lua_yield</code></a>, +or all values returned by the body function. +<a href="#lua_resume"><code>lua_resume</code></a> returns +<a href="#pdf-LUA_YIELD"><code>LUA_YIELD</code></a> if the coroutine yields, +0 if the coroutine finishes its execution +without errors, +or an error code in case of errors (see <a href="#lua_pcall"><code>lua_pcall</code></a>). +In case of errors, +the stack is not unwound, +so you can use the debug API over it. +The error message is on the top of the stack. +To restart a coroutine, you put on its stack only the values to +be passed as results from <code>yield</code>, +and then call <a href="#lua_resume"><code>lua_resume</code></a>. + + + + + +<hr><h3><a name="lua_setallocf"><code>lua_setallocf</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);</pre> + +<p> +Changes the allocator function of a given state to <code>f</code> +with user data <code>ud</code>. + + + + + +<hr><h3><a name="lua_setfenv"><code>lua_setfenv</code></a></h3><p> +<span class="apii">[-1, +0, <em>-</em>]</span> +<pre>int lua_setfenv (lua_State *L, int index);</pre> + +<p> +Pops a table from the stack and sets it as +the new environment for the value at the given index. +If the value at the given index is +neither a function nor a thread nor a userdata, +<a href="#lua_setfenv"><code>lua_setfenv</code></a> returns 0. +Otherwise it returns 1. + + + + + +<hr><h3><a name="lua_setfield"><code>lua_setfield</code></a></h3><p> +<span class="apii">[-1, +0, <em>e</em>]</span> +<pre>void lua_setfield (lua_State *L, int index, const char *k);</pre> + +<p> +Does the equivalent to <code>t[k] = v</code>, +where <code>t</code> is the value at the given valid index +and <code>v</code> is the value at the top of the stack. + + +<p> +This function pops the value from the stack. +As in Lua, this function may trigger a metamethod +for the "newindex" event (see <a href="#2.8">§2.8</a>). + + + + + +<hr><h3><a name="lua_setglobal"><code>lua_setglobal</code></a></h3><p> +<span class="apii">[-1, +0, <em>e</em>]</span> +<pre>void lua_setglobal (lua_State *L, const char *name);</pre> + +<p> +Pops a value from the stack and +sets it as the new value of global <code>name</code>. +It is defined as a macro: + +<pre> + #define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, s) +</pre> + + + + +<hr><h3><a name="lua_setmetatable"><code>lua_setmetatable</code></a></h3><p> +<span class="apii">[-1, +0, <em>-</em>]</span> +<pre>int lua_setmetatable (lua_State *L, int index);</pre> + +<p> +Pops a table from the stack and +sets it as the new metatable for the value at the given +acceptable index. + + + + + +<hr><h3><a name="lua_settable"><code>lua_settable</code></a></h3><p> +<span class="apii">[-2, +0, <em>e</em>]</span> +<pre>void lua_settable (lua_State *L, int index);</pre> + +<p> +Does the equivalent to <code>t[k] = v</code>, +where <code>t</code> is the value at the given valid index, +<code>v</code> is the value at the top of the stack, +and <code>k</code> is the value just below the top. + + +<p> +This function pops both the key and the value from the stack. +As in Lua, this function may trigger a metamethod +for the "newindex" event (see <a href="#2.8">§2.8</a>). + + + + + +<hr><h3><a name="lua_settop"><code>lua_settop</code></a></h3><p> +<span class="apii">[-?, +?, <em>-</em>]</span> +<pre>void lua_settop (lua_State *L, int index);</pre> + +<p> +Accepts any acceptable index, or 0, +and sets the stack top to this index. +If the new top is larger than the old one, +then the new elements are filled with <b>nil</b>. +If <code>index</code> is 0, then all stack elements are removed. + + + + + +<hr><h3><a name="lua_State"><code>lua_State</code></a></h3> +<pre>typedef struct lua_State lua_State;</pre> + +<p> +Opaque structure that keeps the whole state of a Lua interpreter. +The Lua library is fully reentrant: +it has no global variables. +All information about a state is kept in this structure. + + +<p> +A pointer to this state must be passed as the first argument to +every function in the library, except to <a href="#lua_newstate"><code>lua_newstate</code></a>, +which creates a Lua state from scratch. + + + + + +<hr><h3><a name="lua_status"><code>lua_status</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>int lua_status (lua_State *L);</pre> + +<p> +Returns the status of the thread <code>L</code>. + + +<p> +The status can be 0 for a normal thread, +an error code if the thread finished its execution with an error, +or <a name="pdf-LUA_YIELD"><code>LUA_YIELD</code></a> if the thread is suspended. + + + + + +<hr><h3><a name="lua_toboolean"><code>lua_toboolean</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>int lua_toboolean (lua_State *L, int index);</pre> + +<p> +Converts the Lua value at the given acceptable index to a C boolean +value (0 or 1). +Like all tests in Lua, +<a href="#lua_toboolean"><code>lua_toboolean</code></a> returns 1 for any Lua value +different from <b>false</b> and <b>nil</b>; +otherwise it returns 0. +It also returns 0 when called with a non-valid index. +(If you want to accept only actual boolean values, +use <a href="#lua_isboolean"><code>lua_isboolean</code></a> to test the value's type.) + + + + + +<hr><h3><a name="lua_tocfunction"><code>lua_tocfunction</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>lua_CFunction lua_tocfunction (lua_State *L, int index);</pre> + +<p> +Converts a value at the given acceptable index to a C function. +That value must be a C function; +otherwise, returns <code>NULL</code>. + + + + + +<hr><h3><a name="lua_tointeger"><code>lua_tointeger</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>lua_Integer lua_tointeger (lua_State *L, int index);</pre> + +<p> +Converts the Lua value at the given acceptable index +to the signed integral type <a href="#lua_Integer"><code>lua_Integer</code></a>. +The Lua value must be a number or a string convertible to a number +(see <a href="#2.2.1">§2.2.1</a>); +otherwise, <a href="#lua_tointeger"><code>lua_tointeger</code></a> returns 0. + + +<p> +If the number is not an integer, +it is truncated in some non-specified way. + + + + + +<hr><h3><a name="lua_tolstring"><code>lua_tolstring</code></a></h3><p> +<span class="apii">[-0, +0, <em>m</em>]</span> +<pre>const char *lua_tolstring (lua_State *L, int index, size_t *len);</pre> + +<p> +Converts the Lua value at the given acceptable index to a C string. +If <code>len</code> is not <code>NULL</code>, +it also sets <code>*len</code> with the string length. +The Lua value must be a string or a number; +otherwise, the function returns <code>NULL</code>. +If the value is a number, +then <a href="#lua_tolstring"><code>lua_tolstring</code></a> also +<em>changes the actual value in the stack to a string</em>. +(This change confuses <a href="#lua_next"><code>lua_next</code></a> +when <a href="#lua_tolstring"><code>lua_tolstring</code></a> is applied to keys during a table traversal.) + + +<p> +<a href="#lua_tolstring"><code>lua_tolstring</code></a> returns a fully aligned pointer +to a string inside the Lua state. +This string always has a zero ('<code>\0</code>') +after its last character (as in C), +but may contain other zeros in its body. +Because Lua has garbage collection, +there is no guarantee that the pointer returned by <a href="#lua_tolstring"><code>lua_tolstring</code></a> +will be valid after the corresponding value is removed from the stack. + + + + + +<hr><h3><a name="lua_tonumber"><code>lua_tonumber</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>lua_Number lua_tonumber (lua_State *L, int index);</pre> + +<p> +Converts the Lua value at the given acceptable index +to the C type <a href="#lua_Number"><code>lua_Number</code></a> (see <a href="#lua_Number"><code>lua_Number</code></a>). +The Lua value must be a number or a string convertible to a number +(see <a href="#2.2.1">§2.2.1</a>); +otherwise, <a href="#lua_tonumber"><code>lua_tonumber</code></a> returns 0. + + + + + +<hr><h3><a name="lua_topointer"><code>lua_topointer</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>const void *lua_topointer (lua_State *L, int index);</pre> + +<p> +Converts the value at the given acceptable index to a generic +C pointer (<code>void*</code>). +The value may be a userdata, a table, a thread, or a function; +otherwise, <a href="#lua_topointer"><code>lua_topointer</code></a> returns <code>NULL</code>. +Different objects will give different pointers. +There is no way to convert the pointer back to its original value. + + +<p> +Typically this function is used only for debug information. + + + + + +<hr><h3><a name="lua_tostring"><code>lua_tostring</code></a></h3><p> +<span class="apii">[-0, +0, <em>m</em>]</span> +<pre>const char *lua_tostring (lua_State *L, int index);</pre> + +<p> +Equivalent to <a href="#lua_tolstring"><code>lua_tolstring</code></a> with <code>len</code> equal to <code>NULL</code>. + + + + + +<hr><h3><a name="lua_tothread"><code>lua_tothread</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>lua_State *lua_tothread (lua_State *L, int index);</pre> + +<p> +Converts the value at the given acceptable index to a Lua thread +(represented as <code>lua_State*</code>). +This value must be a thread; +otherwise, the function returns <code>NULL</code>. + + + + + +<hr><h3><a name="lua_touserdata"><code>lua_touserdata</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>void *lua_touserdata (lua_State *L, int index);</pre> + +<p> +If the value at the given acceptable index is a full userdata, +returns its block address. +If the value is a light userdata, +returns its pointer. +Otherwise, returns <code>NULL</code>. + + + + + +<hr><h3><a name="lua_type"><code>lua_type</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>int lua_type (lua_State *L, int index);</pre> + +<p> +Returns the type of the value in the given acceptable index, +or <code>LUA_TNONE</code> for a non-valid index +(that is, an index to an "empty" stack position). +The types returned by <a href="#lua_type"><code>lua_type</code></a> are coded by the following constants +defined in <code>lua.h</code>: +<code>LUA_TNIL</code>, +<code>LUA_TNUMBER</code>, +<code>LUA_TBOOLEAN</code>, +<code>LUA_TSTRING</code>, +<code>LUA_TTABLE</code>, +<code>LUA_TFUNCTION</code>, +<code>LUA_TUSERDATA</code>, +<code>LUA_TTHREAD</code>, +and +<code>LUA_TLIGHTUSERDATA</code>. + + + + + +<hr><h3><a name="lua_typename"><code>lua_typename</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>const char *lua_typename (lua_State *L, int tp);</pre> + +<p> +Returns the name of the type encoded by the value <code>tp</code>, +which must be one the values returned by <a href="#lua_type"><code>lua_type</code></a>. + + + + + +<hr><h3><a name="lua_Writer"><code>lua_Writer</code></a></h3> +<pre>typedef int (*lua_Writer) (lua_State *L, + const void* p, + size_t sz, + void* ud);</pre> + +<p> +The type of the writer function used by <a href="#lua_dump"><code>lua_dump</code></a>. +Every time it produces another piece of chunk, +<a href="#lua_dump"><code>lua_dump</code></a> calls the writer, +passing along the buffer to be written (<code>p</code>), +its size (<code>sz</code>), +and the <code>data</code> parameter supplied to <a href="#lua_dump"><code>lua_dump</code></a>. + + +<p> +The writer returns an error code: +0 means no errors; +any other value means an error and stops <a href="#lua_dump"><code>lua_dump</code></a> from +calling the writer again. + + + + + +<hr><h3><a name="lua_xmove"><code>lua_xmove</code></a></h3><p> +<span class="apii">[-?, +?, <em>-</em>]</span> +<pre>void lua_xmove (lua_State *from, lua_State *to, int n);</pre> + +<p> +Exchange values between different threads of the <em>same</em> global state. + + +<p> +This function pops <code>n</code> values from the stack <code>from</code>, +and pushes them onto the stack <code>to</code>. + + + + + +<hr><h3><a name="lua_yield"><code>lua_yield</code></a></h3><p> +<span class="apii">[-?, +?, <em>-</em>]</span> +<pre>int lua_yield (lua_State *L, int nresults);</pre> + +<p> +Yields a coroutine. + + +<p> +This function should only be called as the +return expression of a C function, as follows: + +<pre> + return lua_yield (L, nresults); +</pre><p> +When a C function calls <a href="#lua_yield"><code>lua_yield</code></a> in that way, +the running coroutine suspends its execution, +and the call to <a href="#lua_resume"><code>lua_resume</code></a> that started this coroutine returns. +The parameter <code>nresults</code> is the number of values from the stack +that are passed as results to <a href="#lua_resume"><code>lua_resume</code></a>. + + + + + + + +<h2>3.8 - <a name="3.8">The Debug Interface</a></h2> + +<p> +Lua has no built-in debugging facilities. +Instead, it offers a special interface +by means of functions and <em>hooks</em>. +This interface allows the construction of different +kinds of debuggers, profilers, and other tools +that need "inside information" from the interpreter. + + + +<hr><h3><a name="lua_Debug"><code>lua_Debug</code></a></h3> +<pre>typedef struct lua_Debug { + int event; + const char *name; /* (n) */ + const char *namewhat; /* (n) */ + const char *what; /* (S) */ + const char *source; /* (S) */ + int currentline; /* (l) */ + int nups; /* (u) number of upvalues */ + int linedefined; /* (S) */ + int lastlinedefined; /* (S) */ + char short_src[LUA_IDSIZE]; /* (S) */ + /* private part */ + <em>other fields</em> +} lua_Debug;</pre> + +<p> +A structure used to carry different pieces of +information about an active function. +<a href="#lua_getstack"><code>lua_getstack</code></a> fills only the private part +of this structure, for later use. +To fill the other fields of <a href="#lua_Debug"><code>lua_Debug</code></a> with useful information, +call <a href="#lua_getinfo"><code>lua_getinfo</code></a>. + + +<p> +The fields of <a href="#lua_Debug"><code>lua_Debug</code></a> have the following meaning: + +<ul> + +<li><b><code>source</code>:</b> +If the function was defined in a string, +then <code>source</code> is that string. +If the function was defined in a file, +then <code>source</code> starts with a '<code>@</code>' followed by the file name. +</li> + +<li><b><code>short_src</code>:</b> +a "printable" version of <code>source</code>, to be used in error messages. +</li> + +<li><b><code>linedefined</code>:</b> +the line number where the definition of the function starts. +</li> + +<li><b><code>lastlinedefined</code>:</b> +the line number where the definition of the function ends. +</li> + +<li><b><code>what</code>:</b> +the string <code>"Lua"</code> if the function is a Lua function, +<code>"C"</code> if it is a C function, +<code>"main"</code> if it is the main part of a chunk, +and <code>"tail"</code> if it was a function that did a tail call. +In the latter case, +Lua has no other information about the function. +</li> + +<li><b><code>currentline</code>:</b> +the current line where the given function is executing. +When no line information is available, +<code>currentline</code> is set to -1. +</li> + +<li><b><code>name</code>:</b> +a reasonable name for the given function. +Because functions in Lua are first-class values, +they do not have a fixed name: +some functions may be the value of multiple global variables, +while others may be stored only in a table field. +The <code>lua_getinfo</code> function checks how the function was +called to find a suitable name. +If it cannot find a name, +then <code>name</code> is set to <code>NULL</code>. +</li> + +<li><b><code>namewhat</code>:</b> +explains the <code>name</code> field. +The value of <code>namewhat</code> can be +<code>"global"</code>, <code>"local"</code>, <code>"method"</code>, +<code>"field"</code>, <code>"upvalue"</code>, or <code>""</code> (the empty string), +according to how the function was called. +(Lua uses the empty string when no other option seems to apply.) +</li> + +<li><b><code>nups</code>:</b> +the number of upvalues of the function. +</li> + +</ul> + + + + +<hr><h3><a name="lua_gethook"><code>lua_gethook</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>lua_Hook lua_gethook (lua_State *L);</pre> + +<p> +Returns the current hook function. + + + + + +<hr><h3><a name="lua_gethookcount"><code>lua_gethookcount</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>int lua_gethookcount (lua_State *L);</pre> + +<p> +Returns the current hook count. + + + + + +<hr><h3><a name="lua_gethookmask"><code>lua_gethookmask</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>int lua_gethookmask (lua_State *L);</pre> + +<p> +Returns the current hook mask. + + + + + +<hr><h3><a name="lua_getinfo"><code>lua_getinfo</code></a></h3><p> +<span class="apii">[-(0|1), +(0|1|2), <em>m</em>]</span> +<pre>int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);</pre> + +<p> +Returns information about a specific function or function invocation. + + +<p> +To get information about a function invocation, +the parameter <code>ar</code> must be a valid activation record that was +filled by a previous call to <a href="#lua_getstack"><code>lua_getstack</code></a> or +given as argument to a hook (see <a href="#lua_Hook"><code>lua_Hook</code></a>). + + +<p> +To get information about a function you push it onto the stack +and start the <code>what</code> string with the character '<code>></code>'. +(In that case, +<code>lua_getinfo</code> pops the function in the top of the stack.) +For instance, to know in which line a function <code>f</code> was defined, +you can write the following code: + +<pre> + lua_Debug ar; + lua_getfield(L, LUA_GLOBALSINDEX, "f"); /* get global 'f' */ + lua_getinfo(L, ">S", &ar); + printf("%d\n", ar.linedefined); +</pre> + +<p> +Each character in the string <code>what</code> +selects some fields of the structure <code>ar</code> to be filled or +a value to be pushed on the stack: + +<ul> + +<li><b>'<code>n</code>':</b> fills in the field <code>name</code> and <code>namewhat</code>; +</li> + +<li><b>'<code>S</code>':</b> +fills in the fields <code>source</code>, <code>short_src</code>, +<code>linedefined</code>, <code>lastlinedefined</code>, and <code>what</code>; +</li> + +<li><b>'<code>l</code>':</b> fills in the field <code>currentline</code>; +</li> + +<li><b>'<code>u</code>':</b> fills in the field <code>nups</code>; +</li> + +<li><b>'<code>f</code>':</b> +pushes onto the stack the function that is +running at the given level; +</li> + +<li><b>'<code>L</code>':</b> +pushes onto the stack a table whose indices are the +numbers of the lines that are valid on the function. +(A <em>valid line</em> is a line with some associated code, +that is, a line where you can put a break point. +Non-valid lines include empty lines and comments.) +</li> + +</ul> + +<p> +This function returns 0 on error +(for instance, an invalid option in <code>what</code>). + + + + + +<hr><h3><a name="lua_getlocal"><code>lua_getlocal</code></a></h3><p> +<span class="apii">[-0, +(0|1), <em>-</em>]</span> +<pre>const char *lua_getlocal (lua_State *L, lua_Debug *ar, int n);</pre> + +<p> +Gets information about a local variable of a given activation record. +The parameter <code>ar</code> must be a valid activation record that was +filled by a previous call to <a href="#lua_getstack"><code>lua_getstack</code></a> or +given as argument to a hook (see <a href="#lua_Hook"><code>lua_Hook</code></a>). +The index <code>n</code> selects which local variable to inspect +(1 is the first parameter or active local variable, and so on, +until the last active local variable). +<a href="#lua_getlocal"><code>lua_getlocal</code></a> pushes the variable's value onto the stack +and returns its name. + + +<p> +Variable names starting with '<code>(</code>' (open parentheses) +represent internal variables +(loop control variables, temporaries, and C function locals). + + +<p> +Returns <code>NULL</code> (and pushes nothing) +when the index is greater than +the number of active local variables. + + + + + +<hr><h3><a name="lua_getstack"><code>lua_getstack</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>int lua_getstack (lua_State *L, int level, lua_Debug *ar);</pre> + +<p> +Get information about the interpreter runtime stack. + + +<p> +This function fills parts of a <a href="#lua_Debug"><code>lua_Debug</code></a> structure with +an identification of the <em>activation record</em> +of the function executing at a given level. +Level 0 is the current running function, +whereas level <em>n+1</em> is the function that has called level <em>n</em>. +When there are no errors, <a href="#lua_getstack"><code>lua_getstack</code></a> returns 1; +when called with a level greater than the stack depth, +it returns 0. + + + + + +<hr><h3><a name="lua_getupvalue"><code>lua_getupvalue</code></a></h3><p> +<span class="apii">[-0, +(0|1), <em>-</em>]</span> +<pre>const char *lua_getupvalue (lua_State *L, int funcindex, int n);</pre> + +<p> +Gets information about a closure's upvalue. +(For Lua functions, +upvalues are the external local variables that the function uses, +and that are consequently included in its closure.) +<a href="#lua_getupvalue"><code>lua_getupvalue</code></a> gets the index <code>n</code> of an upvalue, +pushes the upvalue's value onto the stack, +and returns its name. +<code>funcindex</code> points to the closure in the stack. +(Upvalues have no particular order, +as they are active through the whole function. +So, they are numbered in an arbitrary order.) + + +<p> +Returns <code>NULL</code> (and pushes nothing) +when the index is greater than the number of upvalues. +For C functions, this function uses the empty string <code>""</code> +as a name for all upvalues. + + + + + +<hr><h3><a name="lua_Hook"><code>lua_Hook</code></a></h3> +<pre>typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);</pre> + +<p> +Type for debugging hook functions. + + +<p> +Whenever a hook is called, its <code>ar</code> argument has its field +<code>event</code> set to the specific event that triggered the hook. +Lua identifies these events with the following constants: +<a name="pdf-LUA_HOOKCALL"><code>LUA_HOOKCALL</code></a>, <a name="pdf-LUA_HOOKRET"><code>LUA_HOOKRET</code></a>, +<a name="pdf-LUA_HOOKTAILRET"><code>LUA_HOOKTAILRET</code></a>, <a name="pdf-LUA_HOOKLINE"><code>LUA_HOOKLINE</code></a>, +and <a name="pdf-LUA_HOOKCOUNT"><code>LUA_HOOKCOUNT</code></a>. +Moreover, for line events, the field <code>currentline</code> is also set. +To get the value of any other field in <code>ar</code>, +the hook must call <a href="#lua_getinfo"><code>lua_getinfo</code></a>. +For return events, <code>event</code> may be <code>LUA_HOOKRET</code>, +the normal value, or <code>LUA_HOOKTAILRET</code>. +In the latter case, Lua is simulating a return from +a function that did a tail call; +in this case, it is useless to call <a href="#lua_getinfo"><code>lua_getinfo</code></a>. + + +<p> +While Lua is running a hook, it disables other calls to hooks. +Therefore, if a hook calls back Lua to execute a function or a chunk, +this execution occurs without any calls to hooks. + + + + + +<hr><h3><a name="lua_sethook"><code>lua_sethook</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>int lua_sethook (lua_State *L, lua_Hook f, int mask, int count);</pre> + +<p> +Sets the debugging hook function. + + +<p> +Argument <code>f</code> is the hook function. +<code>mask</code> specifies on which events the hook will be called: +it is formed by a bitwise or of the constants +<a name="pdf-LUA_MASKCALL"><code>LUA_MASKCALL</code></a>, +<a name="pdf-LUA_MASKRET"><code>LUA_MASKRET</code></a>, +<a name="pdf-LUA_MASKLINE"><code>LUA_MASKLINE</code></a>, +and <a name="pdf-LUA_MASKCOUNT"><code>LUA_MASKCOUNT</code></a>. +The <code>count</code> argument is only meaningful when the mask +includes <code>LUA_MASKCOUNT</code>. +For each event, the hook is called as explained below: + +<ul> + +<li><b>The call hook:</b> is called when the interpreter calls a function. +The hook is called just after Lua enters the new function, +before the function gets its arguments. +</li> + +<li><b>The return hook:</b> is called when the interpreter returns from a function. +The hook is called just before Lua leaves the function. +You have no access to the values to be returned by the function. +</li> + +<li><b>The line hook:</b> is called when the interpreter is about to +start the execution of a new line of code, +or when it jumps back in the code (even to the same line). +(This event only happens while Lua is executing a Lua function.) +</li> + +<li><b>The count hook:</b> is called after the interpreter executes every +<code>count</code> instructions. +(This event only happens while Lua is executing a Lua function.) +</li> + +</ul> + +<p> +A hook is disabled by setting <code>mask</code> to zero. + + + + + +<hr><h3><a name="lua_setlocal"><code>lua_setlocal</code></a></h3><p> +<span class="apii">[-(0|1), +0, <em>-</em>]</span> +<pre>const char *lua_setlocal (lua_State *L, lua_Debug *ar, int n);</pre> + +<p> +Sets the value of a local variable of a given activation record. +Parameters <code>ar</code> and <code>n</code> are as in <a href="#lua_getlocal"><code>lua_getlocal</code></a> +(see <a href="#lua_getlocal"><code>lua_getlocal</code></a>). +<a href="#lua_setlocal"><code>lua_setlocal</code></a> assigns the value at the top of the stack +to the variable and returns its name. +It also pops the value from the stack. + + +<p> +Returns <code>NULL</code> (and pops nothing) +when the index is greater than +the number of active local variables. + + + + + +<hr><h3><a name="lua_setupvalue"><code>lua_setupvalue</code></a></h3><p> +<span class="apii">[-(0|1), +0, <em>-</em>]</span> +<pre>const char *lua_setupvalue (lua_State *L, int funcindex, int n);</pre> + +<p> +Sets the value of a closure's upvalue. +It assigns the value at the top of the stack +to the upvalue and returns its name. +It also pops the value from the stack. +Parameters <code>funcindex</code> and <code>n</code> are as in the <a href="#lua_getupvalue"><code>lua_getupvalue</code></a> +(see <a href="#lua_getupvalue"><code>lua_getupvalue</code></a>). + + +<p> +Returns <code>NULL</code> (and pops nothing) +when the index is greater than the number of upvalues. + + + + + + + +<h1>4 - <a name="4">The Auxiliary Library</a></h1> + +<p> + +The <em>auxiliary library</em> provides several convenient functions +to interface C with Lua. +While the basic API provides the primitive functions for all +interactions between C and Lua, +the auxiliary library provides higher-level functions for some +common tasks. + + +<p> +All functions from the auxiliary library +are defined in header file <code>lauxlib.h</code> and +have a prefix <code>luaL_</code>. + + +<p> +All functions in the auxiliary library are built on +top of the basic API, +and so they provide nothing that cannot be done with this API. + + +<p> +Several functions in the auxiliary library are used to +check C function arguments. +Their names are always <code>luaL_check*</code> or <code>luaL_opt*</code>. +All of these functions throw an error if the check is not satisfied. +Because the error message is formatted for arguments +(e.g., "<code>bad argument #1</code>"), +you should not use these functions for other stack values. + + + +<h2>4.1 - <a name="4.1">Functions and Types</a></h2> + +<p> +Here we list all functions and types from the auxiliary library +in alphabetical order. + + + +<hr><h3><a name="luaL_addchar"><code>luaL_addchar</code></a></h3><p> +<span class="apii">[-0, +0, <em>m</em>]</span> +<pre>void luaL_addchar (luaL_Buffer *B, char c);</pre> + +<p> +Adds the character <code>c</code> to the buffer <code>B</code> +(see <a href="#luaL_Buffer"><code>luaL_Buffer</code></a>). + + + + + +<hr><h3><a name="luaL_addlstring"><code>luaL_addlstring</code></a></h3><p> +<span class="apii">[-0, +0, <em>m</em>]</span> +<pre>void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l);</pre> + +<p> +Adds the string pointed to by <code>s</code> with length <code>l</code> to +the buffer <code>B</code> +(see <a href="#luaL_Buffer"><code>luaL_Buffer</code></a>). +The string may contain embedded zeros. + + + + + +<hr><h3><a name="luaL_addsize"><code>luaL_addsize</code></a></h3><p> +<span class="apii">[-0, +0, <em>m</em>]</span> +<pre>void luaL_addsize (luaL_Buffer *B, size_t n);</pre> + +<p> +Adds to the buffer <code>B</code> (see <a href="#luaL_Buffer"><code>luaL_Buffer</code></a>) +a string of length <code>n</code> previously copied to the +buffer area (see <a href="#luaL_prepbuffer"><code>luaL_prepbuffer</code></a>). + + + + + +<hr><h3><a name="luaL_addstring"><code>luaL_addstring</code></a></h3><p> +<span class="apii">[-0, +0, <em>m</em>]</span> +<pre>void luaL_addstring (luaL_Buffer *B, const char *s);</pre> + +<p> +Adds the zero-terminated string pointed to by <code>s</code> +to the buffer <code>B</code> +(see <a href="#luaL_Buffer"><code>luaL_Buffer</code></a>). +The string may not contain embedded zeros. + + + + + +<hr><h3><a name="luaL_addvalue"><code>luaL_addvalue</code></a></h3><p> +<span class="apii">[-1, +0, <em>m</em>]</span> +<pre>void luaL_addvalue (luaL_Buffer *B);</pre> + +<p> +Adds the value at the top of the stack +to the buffer <code>B</code> +(see <a href="#luaL_Buffer"><code>luaL_Buffer</code></a>). +Pops the value. + + +<p> +This is the only function on string buffers that can (and must) +be called with an extra element on the stack, +which is the value to be added to the buffer. + + + + + +<hr><h3><a name="luaL_argcheck"><code>luaL_argcheck</code></a></h3><p> +<span class="apii">[-0, +0, <em>v</em>]</span> +<pre>void luaL_argcheck (lua_State *L, + int cond, + int narg, + const char *extramsg);</pre> + +<p> +Checks whether <code>cond</code> is true. +If not, raises an error with the following message, +where <code>func</code> is retrieved from the call stack: + +<pre> + bad argument #<narg> to <func> (<extramsg>) +</pre> + + + + +<hr><h3><a name="luaL_argerror"><code>luaL_argerror</code></a></h3><p> +<span class="apii">[-0, +0, <em>v</em>]</span> +<pre>int luaL_argerror (lua_State *L, int narg, const char *extramsg);</pre> + +<p> +Raises an error with the following message, +where <code>func</code> is retrieved from the call stack: + +<pre> + bad argument #<narg> to <func> (<extramsg>) +</pre> + +<p> +This function never returns, +but it is an idiom to use it in C functions +as <code>return luaL_argerror(<em>args</em>)</code>. + + + + + +<hr><h3><a name="luaL_Buffer"><code>luaL_Buffer</code></a></h3> +<pre>typedef struct luaL_Buffer luaL_Buffer;</pre> + +<p> +Type for a <em>string buffer</em>. + + +<p> +A string buffer allows C code to build Lua strings piecemeal. +Its pattern of use is as follows: + +<ul> + +<li>First you declare a variable <code>b</code> of type <a href="#luaL_Buffer"><code>luaL_Buffer</code></a>.</li> + +<li>Then you initialize it with a call <code>luaL_buffinit(L, &b)</code>.</li> + +<li> +Then you add string pieces to the buffer calling any of +the <code>luaL_add*</code> functions. +</li> + +<li> +You finish by calling <code>luaL_pushresult(&b)</code>. +This call leaves the final string on the top of the stack. +</li> + +</ul> + +<p> +During its normal operation, +a string buffer uses a variable number of stack slots. +So, while using a buffer, you cannot assume that you know where +the top of the stack is. +You can use the stack between successive calls to buffer operations +as long as that use is balanced; +that is, +when you call a buffer operation, +the stack is at the same level +it was immediately after the previous buffer operation. +(The only exception to this rule is <a href="#luaL_addvalue"><code>luaL_addvalue</code></a>.) +After calling <a href="#luaL_pushresult"><code>luaL_pushresult</code></a> the stack is back to its +level when the buffer was initialized, +plus the final string on its top. + + + + + +<hr><h3><a name="luaL_buffinit"><code>luaL_buffinit</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>void luaL_buffinit (lua_State *L, luaL_Buffer *B);</pre> + +<p> +Initializes a buffer <code>B</code>. +This function does not allocate any space; +the buffer must be declared as a variable +(see <a href="#luaL_Buffer"><code>luaL_Buffer</code></a>). + + + + + +<hr><h3><a name="luaL_callmeta"><code>luaL_callmeta</code></a></h3><p> +<span class="apii">[-0, +(0|1), <em>e</em>]</span> +<pre>int luaL_callmeta (lua_State *L, int obj, const char *e);</pre> + +<p> +Calls a metamethod. + + +<p> +If the object at index <code>obj</code> has a metatable and this +metatable has a field <code>e</code>, +this function calls this field and passes the object as its only argument. +In this case this function returns 1 and pushes onto the +stack the value returned by the call. +If there is no metatable or no metamethod, +this function returns 0 (without pushing any value on the stack). + + + + + +<hr><h3><a name="luaL_checkany"><code>luaL_checkany</code></a></h3><p> +<span class="apii">[-0, +0, <em>v</em>]</span> +<pre>void luaL_checkany (lua_State *L, int narg);</pre> + +<p> +Checks whether the function has an argument +of any type (including <b>nil</b>) at position <code>narg</code>. + + + + + +<hr><h3><a name="luaL_checkint"><code>luaL_checkint</code></a></h3><p> +<span class="apii">[-0, +0, <em>v</em>]</span> +<pre>int luaL_checkint (lua_State *L, int narg);</pre> + +<p> +Checks whether the function argument <code>narg</code> is a number +and returns this number cast to an <code>int</code>. + + + + + +<hr><h3><a name="luaL_checkinteger"><code>luaL_checkinteger</code></a></h3><p> +<span class="apii">[-0, +0, <em>v</em>]</span> +<pre>lua_Integer luaL_checkinteger (lua_State *L, int narg);</pre> + +<p> +Checks whether the function argument <code>narg</code> is a number +and returns this number cast to a <a href="#lua_Integer"><code>lua_Integer</code></a>. + + + + + +<hr><h3><a name="luaL_checklong"><code>luaL_checklong</code></a></h3><p> +<span class="apii">[-0, +0, <em>v</em>]</span> +<pre>long luaL_checklong (lua_State *L, int narg);</pre> + +<p> +Checks whether the function argument <code>narg</code> is a number +and returns this number cast to a <code>long</code>. + + + + + +<hr><h3><a name="luaL_checklstring"><code>luaL_checklstring</code></a></h3><p> +<span class="apii">[-0, +0, <em>v</em>]</span> +<pre>const char *luaL_checklstring (lua_State *L, int narg, size_t *l);</pre> + +<p> +Checks whether the function argument <code>narg</code> is a string +and returns this string; +if <code>l</code> is not <code>NULL</code> fills <code>*l</code> +with the string's length. + + +<p> +This function uses <a href="#lua_tolstring"><code>lua_tolstring</code></a> to get its result, +so all conversions and caveats of that function apply here. + + + + + +<hr><h3><a name="luaL_checknumber"><code>luaL_checknumber</code></a></h3><p> +<span class="apii">[-0, +0, <em>v</em>]</span> +<pre>lua_Number luaL_checknumber (lua_State *L, int narg);</pre> + +<p> +Checks whether the function argument <code>narg</code> is a number +and returns this number. + + + + + +<hr><h3><a name="luaL_checkoption"><code>luaL_checkoption</code></a></h3><p> +<span class="apii">[-0, +0, <em>v</em>]</span> +<pre>int luaL_checkoption (lua_State *L, + int narg, + const char *def, + const char *const lst[]);</pre> + +<p> +Checks whether the function argument <code>narg</code> is a string and +searches for this string in the array <code>lst</code> +(which must be NULL-terminated). +Returns the index in the array where the string was found. +Raises an error if the argument is not a string or +if the string cannot be found. + + +<p> +If <code>def</code> is not <code>NULL</code>, +the function uses <code>def</code> as a default value when +there is no argument <code>narg</code> or if this argument is <b>nil</b>. + + +<p> +This is a useful function for mapping strings to C enums. +(The usual convention in Lua libraries is +to use strings instead of numbers to select options.) + + + + + +<hr><h3><a name="luaL_checkstack"><code>luaL_checkstack</code></a></h3><p> +<span class="apii">[-0, +0, <em>v</em>]</span> +<pre>void luaL_checkstack (lua_State *L, int sz, const char *msg);</pre> + +<p> +Grows the stack size to <code>top + sz</code> elements, +raising an error if the stack cannot grow to that size. +<code>msg</code> is an additional text to go into the error message. + + + + + +<hr><h3><a name="luaL_checkstring"><code>luaL_checkstring</code></a></h3><p> +<span class="apii">[-0, +0, <em>v</em>]</span> +<pre>const char *luaL_checkstring (lua_State *L, int narg);</pre> + +<p> +Checks whether the function argument <code>narg</code> is a string +and returns this string. + + +<p> +This function uses <a href="#lua_tolstring"><code>lua_tolstring</code></a> to get its result, +so all conversions and caveats of that function apply here. + + + + + +<hr><h3><a name="luaL_checktype"><code>luaL_checktype</code></a></h3><p> +<span class="apii">[-0, +0, <em>v</em>]</span> +<pre>void luaL_checktype (lua_State *L, int narg, int t);</pre> + +<p> +Checks whether the function argument <code>narg</code> has type <code>t</code>. +See <a href="#lua_type"><code>lua_type</code></a> for the encoding of types for <code>t</code>. + + + + + +<hr><h3><a name="luaL_checkudata"><code>luaL_checkudata</code></a></h3><p> +<span class="apii">[-0, +0, <em>v</em>]</span> +<pre>void *luaL_checkudata (lua_State *L, int narg, const char *tname);</pre> + +<p> +Checks whether the function argument <code>narg</code> is a userdata +of the type <code>tname</code> (see <a href="#luaL_newmetatable"><code>luaL_newmetatable</code></a>). + + + + + +<hr><h3><a name="luaL_dofile"><code>luaL_dofile</code></a></h3><p> +<span class="apii">[-0, +?, <em>m</em>]</span> +<pre>int luaL_dofile (lua_State *L, const char *filename);</pre> + +<p> +Loads and runs the given file. +It is defined as the following macro: + +<pre> + (luaL_loadfile(L, filename) || lua_pcall(L, 0, LUA_MULTRET, 0)) +</pre><p> +It returns 0 if there are no errors +or 1 in case of errors. + + + + + +<hr><h3><a name="luaL_dostring"><code>luaL_dostring</code></a></h3><p> +<span class="apii">[-0, +?, <em>m</em>]</span> +<pre>int luaL_dostring (lua_State *L, const char *str);</pre> + +<p> +Loads and runs the given string. +It is defined as the following macro: + +<pre> + (luaL_loadstring(L, str) || lua_pcall(L, 0, LUA_MULTRET, 0)) +</pre><p> +It returns 0 if there are no errors +or 1 in case of errors. + + + + + +<hr><h3><a name="luaL_error"><code>luaL_error</code></a></h3><p> +<span class="apii">[-0, +0, <em>v</em>]</span> +<pre>int luaL_error (lua_State *L, const char *fmt, ...);</pre> + +<p> +Raises an error. +The error message format is given by <code>fmt</code> +plus any extra arguments, +following the same rules of <a href="#lua_pushfstring"><code>lua_pushfstring</code></a>. +It also adds at the beginning of the message the file name and +the line number where the error occurred, +if this information is available. + + +<p> +This function never returns, +but it is an idiom to use it in C functions +as <code>return luaL_error(<em>args</em>)</code>. + + + + + +<hr><h3><a name="luaL_getmetafield"><code>luaL_getmetafield</code></a></h3><p> +<span class="apii">[-0, +(0|1), <em>m</em>]</span> +<pre>int luaL_getmetafield (lua_State *L, int obj, const char *e);</pre> + +<p> +Pushes onto the stack the field <code>e</code> from the metatable +of the object at index <code>obj</code>. +If the object does not have a metatable, +or if the metatable does not have this field, +returns 0 and pushes nothing. + + + + + +<hr><h3><a name="luaL_getmetatable"><code>luaL_getmetatable</code></a></h3><p> +<span class="apii">[-0, +1, <em>-</em>]</span> +<pre>void luaL_getmetatable (lua_State *L, const char *tname);</pre> + +<p> +Pushes onto the stack the metatable associated with name <code>tname</code> +in the registry (see <a href="#luaL_newmetatable"><code>luaL_newmetatable</code></a>). + + + + + +<hr><h3><a name="luaL_gsub"><code>luaL_gsub</code></a></h3><p> +<span class="apii">[-0, +1, <em>m</em>]</span> +<pre>const char *luaL_gsub (lua_State *L, + const char *s, + const char *p, + const char *r);</pre> + +<p> +Creates a copy of string <code>s</code> by replacing +any occurrence of the string <code>p</code> +with the string <code>r</code>. +Pushes the resulting string on the stack and returns it. + + + + + +<hr><h3><a name="luaL_loadbuffer"><code>luaL_loadbuffer</code></a></h3><p> +<span class="apii">[-0, +1, <em>m</em>]</span> +<pre>int luaL_loadbuffer (lua_State *L, + const char *buff, + size_t sz, + const char *name);</pre> + +<p> +Loads a buffer as a Lua chunk. +This function uses <a href="#lua_load"><code>lua_load</code></a> to load the chunk in the +buffer pointed to by <code>buff</code> with size <code>sz</code>. + + +<p> +This function returns the same results as <a href="#lua_load"><code>lua_load</code></a>. +<code>name</code> is the chunk name, +used for debug information and error messages. + + + + + +<hr><h3><a name="luaL_loadfile"><code>luaL_loadfile</code></a></h3><p> +<span class="apii">[-0, +1, <em>m</em>]</span> +<pre>int luaL_loadfile (lua_State *L, const char *filename);</pre> + +<p> +Loads a file as a Lua chunk. +This function uses <a href="#lua_load"><code>lua_load</code></a> to load the chunk in the file +named <code>filename</code>. +If <code>filename</code> is <code>NULL</code>, +then it loads from the standard input. +The first line in the file is ignored if it starts with a <code>#</code>. + + +<p> +This function returns the same results as <a href="#lua_load"><code>lua_load</code></a>, +but it has an extra error code <a name="pdf-LUA_ERRFILE"><code>LUA_ERRFILE</code></a> +if it cannot open/read the file. + + +<p> +As <a href="#lua_load"><code>lua_load</code></a>, this function only loads the chunk; +it does not run it. + + + + + +<hr><h3><a name="luaL_loadstring"><code>luaL_loadstring</code></a></h3><p> +<span class="apii">[-0, +1, <em>m</em>]</span> +<pre>int luaL_loadstring (lua_State *L, const char *s);</pre> + +<p> +Loads a string as a Lua chunk. +This function uses <a href="#lua_load"><code>lua_load</code></a> to load the chunk in +the zero-terminated string <code>s</code>. + + +<p> +This function returns the same results as <a href="#lua_load"><code>lua_load</code></a>. + + +<p> +Also as <a href="#lua_load"><code>lua_load</code></a>, this function only loads the chunk; +it does not run it. + + + + + +<hr><h3><a name="luaL_newmetatable"><code>luaL_newmetatable</code></a></h3><p> +<span class="apii">[-0, +1, <em>m</em>]</span> +<pre>int luaL_newmetatable (lua_State *L, const char *tname);</pre> + +<p> +If the registry already has the key <code>tname</code>, +returns 0. +Otherwise, +creates a new table to be used as a metatable for userdata, +adds it to the registry with key <code>tname</code>, +and returns 1. + + +<p> +In both cases pushes onto the stack the final value associated +with <code>tname</code> in the registry. + + + + + +<hr><h3><a name="luaL_newstate"><code>luaL_newstate</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>lua_State *luaL_newstate (void);</pre> + +<p> +Creates a new Lua state. +It calls <a href="#lua_newstate"><code>lua_newstate</code></a> with an +allocator based on the standard C <code>realloc</code> function +and then sets a panic function (see <a href="#lua_atpanic"><code>lua_atpanic</code></a>) that prints +an error message to the standard error output in case of fatal +errors. + + +<p> +Returns the new state, +or <code>NULL</code> if there is a memory allocation error. + + + + + +<hr><h3><a name="luaL_openlibs"><code>luaL_openlibs</code></a></h3><p> +<span class="apii">[-0, +0, <em>m</em>]</span> +<pre>void luaL_openlibs (lua_State *L);</pre> + +<p> +Opens all standard Lua libraries into the given state. + + + + + +<hr><h3><a name="luaL_optint"><code>luaL_optint</code></a></h3><p> +<span class="apii">[-0, +0, <em>v</em>]</span> +<pre>int luaL_optint (lua_State *L, int narg, int d);</pre> + +<p> +If the function argument <code>narg</code> is a number, +returns this number cast to an <code>int</code>. +If this argument is absent or is <b>nil</b>, +returns <code>d</code>. +Otherwise, raises an error. + + + + + +<hr><h3><a name="luaL_optinteger"><code>luaL_optinteger</code></a></h3><p> +<span class="apii">[-0, +0, <em>v</em>]</span> +<pre>lua_Integer luaL_optinteger (lua_State *L, + int narg, + lua_Integer d);</pre> + +<p> +If the function argument <code>narg</code> is a number, +returns this number cast to a <a href="#lua_Integer"><code>lua_Integer</code></a>. +If this argument is absent or is <b>nil</b>, +returns <code>d</code>. +Otherwise, raises an error. + + + + + +<hr><h3><a name="luaL_optlong"><code>luaL_optlong</code></a></h3><p> +<span class="apii">[-0, +0, <em>v</em>]</span> +<pre>long luaL_optlong (lua_State *L, int narg, long d);</pre> + +<p> +If the function argument <code>narg</code> is a number, +returns this number cast to a <code>long</code>. +If this argument is absent or is <b>nil</b>, +returns <code>d</code>. +Otherwise, raises an error. + + + + + +<hr><h3><a name="luaL_optlstring"><code>luaL_optlstring</code></a></h3><p> +<span class="apii">[-0, +0, <em>v</em>]</span> +<pre>const char *luaL_optlstring (lua_State *L, + int narg, + const char *d, + size_t *l);</pre> + +<p> +If the function argument <code>narg</code> is a string, +returns this string. +If this argument is absent or is <b>nil</b>, +returns <code>d</code>. +Otherwise, raises an error. + + +<p> +If <code>l</code> is not <code>NULL</code>, +fills the position <code>*l</code> with the results's length. + + + + + +<hr><h3><a name="luaL_optnumber"><code>luaL_optnumber</code></a></h3><p> +<span class="apii">[-0, +0, <em>v</em>]</span> +<pre>lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number d);</pre> + +<p> +If the function argument <code>narg</code> is a number, +returns this number. +If this argument is absent or is <b>nil</b>, +returns <code>d</code>. +Otherwise, raises an error. + + + + + +<hr><h3><a name="luaL_optstring"><code>luaL_optstring</code></a></h3><p> +<span class="apii">[-0, +0, <em>v</em>]</span> +<pre>const char *luaL_optstring (lua_State *L, + int narg, + const char *d);</pre> + +<p> +If the function argument <code>narg</code> is a string, +returns this string. +If this argument is absent or is <b>nil</b>, +returns <code>d</code>. +Otherwise, raises an error. + + + + + +<hr><h3><a name="luaL_prepbuffer"><code>luaL_prepbuffer</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>char *luaL_prepbuffer (luaL_Buffer *B);</pre> + +<p> +Returns an address to a space of size <a name="pdf-LUAL_BUFFERSIZE"><code>LUAL_BUFFERSIZE</code></a> +where you can copy a string to be added to buffer <code>B</code> +(see <a href="#luaL_Buffer"><code>luaL_Buffer</code></a>). +After copying the string into this space you must call +<a href="#luaL_addsize"><code>luaL_addsize</code></a> with the size of the string to actually add +it to the buffer. + + + + + +<hr><h3><a name="luaL_pushresult"><code>luaL_pushresult</code></a></h3><p> +<span class="apii">[-?, +1, <em>m</em>]</span> +<pre>void luaL_pushresult (luaL_Buffer *B);</pre> + +<p> +Finishes the use of buffer <code>B</code> leaving the final string on +the top of the stack. + + + + + +<hr><h3><a name="luaL_ref"><code>luaL_ref</code></a></h3><p> +<span class="apii">[-1, +0, <em>m</em>]</span> +<pre>int luaL_ref (lua_State *L, int t);</pre> + +<p> +Creates and returns a <em>reference</em>, +in the table at index <code>t</code>, +for the object at the top of the stack (and pops the object). + + +<p> +A reference is a unique integer key. +As long as you do not manually add integer keys into table <code>t</code>, +<a href="#luaL_ref"><code>luaL_ref</code></a> ensures the uniqueness of the key it returns. +You can retrieve an object referred by reference <code>r</code> +by calling <code>lua_rawgeti(L, t, r)</code>. +Function <a href="#luaL_unref"><code>luaL_unref</code></a> frees a reference and its associated object. + + +<p> +If the object at the top of the stack is <b>nil</b>, +<a href="#luaL_ref"><code>luaL_ref</code></a> returns the constant <a name="pdf-LUA_REFNIL"><code>LUA_REFNIL</code></a>. +The constant <a name="pdf-LUA_NOREF"><code>LUA_NOREF</code></a> is guaranteed to be different +from any reference returned by <a href="#luaL_ref"><code>luaL_ref</code></a>. + + + + + +<hr><h3><a name="luaL_Reg"><code>luaL_Reg</code></a></h3> +<pre>typedef struct luaL_Reg { + const char *name; + lua_CFunction func; +} luaL_Reg;</pre> + +<p> +Type for arrays of functions to be registered by +<a href="#luaL_register"><code>luaL_register</code></a>. +<code>name</code> is the function name and <code>func</code> is a pointer to +the function. +Any array of <a href="#luaL_Reg"><code>luaL_Reg</code></a> must end with an sentinel entry +in which both <code>name</code> and <code>func</code> are <code>NULL</code>. + + + + + +<hr><h3><a name="luaL_register"><code>luaL_register</code></a></h3><p> +<span class="apii">[-(0|1), +1, <em>m</em>]</span> +<pre>void luaL_register (lua_State *L, + const char *libname, + const luaL_Reg *l);</pre> + +<p> +Opens a library. + + +<p> +When called with <code>libname</code> equal to <code>NULL</code>, +it simply registers all functions in the list <code>l</code> +(see <a href="#luaL_Reg"><code>luaL_Reg</code></a>) into the table on the top of the stack. + + +<p> +When called with a non-null <code>libname</code>, +<code>luaL_register</code> creates a new table <code>t</code>, +sets it as the value of the global variable <code>libname</code>, +sets it as the value of <code>package.loaded[libname]</code>, +and registers on it all functions in the list <code>l</code>. +If there is a table in <code>package.loaded[libname]</code> or in +variable <code>libname</code>, +reuses this table instead of creating a new one. + + +<p> +In any case the function leaves the table +on the top of the stack. + + + + + +<hr><h3><a name="luaL_typename"><code>luaL_typename</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>const char *luaL_typename (lua_State *L, int index);</pre> + +<p> +Returns the name of the type of the value at the given index. + + + + + +<hr><h3><a name="luaL_typerror"><code>luaL_typerror</code></a></h3><p> +<span class="apii">[-0, +0, <em>v</em>]</span> +<pre>int luaL_typerror (lua_State *L, int narg, const char *tname);</pre> + +<p> +Generates an error with a message like the following: + +<pre> + <em>location</em>: bad argument <em>narg</em> to '<em>func</em>' (<em>tname</em> expected, got <em>rt</em>) +</pre><p> +where <code><em>location</em></code> is produced by <a href="#luaL_where"><code>luaL_where</code></a>, +<code><em>func</em></code> is the name of the current function, +and <code><em>rt</em></code> is the type name of the actual argument. + + + + + +<hr><h3><a name="luaL_unref"><code>luaL_unref</code></a></h3><p> +<span class="apii">[-0, +0, <em>-</em>]</span> +<pre>void luaL_unref (lua_State *L, int t, int ref);</pre> + +<p> +Releases reference <code>ref</code> from the table at index <code>t</code> +(see <a href="#luaL_ref"><code>luaL_ref</code></a>). +The entry is removed from the table, +so that the referred object can be collected. +The reference <code>ref</code> is also freed to be used again. + + +<p> +If <code>ref</code> is <a href="#pdf-LUA_NOREF"><code>LUA_NOREF</code></a> or <a href="#pdf-LUA_REFNIL"><code>LUA_REFNIL</code></a>, +<a href="#luaL_unref"><code>luaL_unref</code></a> does nothing. + + + + + +<hr><h3><a name="luaL_where"><code>luaL_where</code></a></h3><p> +<span class="apii">[-0, +1, <em>m</em>]</span> +<pre>void luaL_where (lua_State *L, int lvl);</pre> + +<p> +Pushes onto the stack a string identifying the current position +of the control at level <code>lvl</code> in the call stack. +Typically this string has the following format: + +<pre> + <em>chunkname</em>:<em>currentline</em>: +</pre><p> +Level 0 is the running function, +level 1 is the function that called the running function, +etc. + + +<p> +This function is used to build a prefix for error messages. + + + + + + + +<h1>5 - <a name="5">Standard Libraries</a></h1> + +<p> +The standard Lua libraries provide useful functions +that are implemented directly through the C API. +Some of these functions provide essential services to the language +(e.g., <a href="#pdf-type"><code>type</code></a> and <a href="#pdf-getmetatable"><code>getmetatable</code></a>); +others provide access to "outside" services (e.g., I/O); +and others could be implemented in Lua itself, +but are quite useful or have critical performance requirements that +deserve an implementation in C (e.g., <a href="#pdf-table.sort"><code>table.sort</code></a>). + + +<p> +All libraries are implemented through the official C API +and are provided as separate C modules. +Currently, Lua has the following standard libraries: + +<ul> + +<li>basic library;</li> + +<li>package library;</li> + +<li>string manipulation;</li> + +<li>table manipulation;</li> + +<li>mathematical functions (sin, log, etc.);</li> + +<li>input and output;</li> + +<li>operating system facilities;</li> + +<li>debug facilities.</li> + +</ul><p> +Except for the basic and package libraries, +each library provides all its functions as fields of a global table +or as methods of its objects. + + +<p> +To have access to these libraries, +the C host program should call the <a href="#luaL_openlibs"><code>luaL_openlibs</code></a> function, +which opens all standard libraries. +Alternatively, +it can open them individually by calling +<a name="pdf-luaopen_base"><code>luaopen_base</code></a> (for the basic library), +<a name="pdf-luaopen_package"><code>luaopen_package</code></a> (for the package library), +<a name="pdf-luaopen_string"><code>luaopen_string</code></a> (for the string library), +<a name="pdf-luaopen_table"><code>luaopen_table</code></a> (for the table library), +<a name="pdf-luaopen_math"><code>luaopen_math</code></a> (for the mathematical library), +<a name="pdf-luaopen_io"><code>luaopen_io</code></a> (for the I/O library), +<a name="pdf-luaopen_os"><code>luaopen_os</code></a> (for the Operating System library), +and <a name="pdf-luaopen_debug"><code>luaopen_debug</code></a> (for the debug library). +These functions are declared in <a name="pdf-lualib.h"><code>lualib.h</code></a> +and should not be called directly: +you must call them like any other Lua C function, +e.g., by using <a href="#lua_call"><code>lua_call</code></a>. + + + +<h2>5.1 - <a name="5.1">Basic Functions</a></h2> + +<p> +The basic library provides some core functions to Lua. +If you do not include this library in your application, +you should check carefully whether you need to provide +implementations for some of its facilities. + + +<p> +<hr><h3><a name="pdf-assert"><code>assert (v [, message])</code></a></h3> +Issues an error when +the value of its argument <code>v</code> is false (i.e., <b>nil</b> or <b>false</b>); +otherwise, returns all its arguments. +<code>message</code> is an error message; +when absent, it defaults to "assertion failed!" + + + + +<p> +<hr><h3><a name="pdf-collectgarbage"><code>collectgarbage (opt [, arg])</code></a></h3> + + +<p> +This function is a generic interface to the garbage collector. +It performs different functions according to its first argument, <code>opt</code>: + +<ul> + +<li><b>"stop":</b> +stops the garbage collector. +</li> + +<li><b>"restart":</b> +restarts the garbage collector. +</li> + +<li><b>"collect":</b> +performs a full garbage-collection cycle. +</li> + +<li><b>"count":</b> +returns the total memory in use by Lua (in Kbytes). +</li> + +<li><b>"step":</b> +performs a garbage-collection step. +The step "size" is controlled by <code>arg</code> +(larger values mean more steps) in a non-specified way. +If you want to control the step size +you must experimentally tune the value of <code>arg</code>. +Returns <b>true</b> if the step finished a collection cycle. +</li> + +<li><b>"setpause":</b> +sets <code>arg</code>/100 as the new value for the <em>pause</em> of +the collector (see <a href="#2.10">§2.10</a>). +</li> + +<li><b>"setstepmul":</b> +sets <code>arg</code>/100 as the new value for the <em>step multiplier</em> of +the collector (see <a href="#2.10">§2.10</a>). +</li> + +</ul> + + + +<p> +<hr><h3><a name="pdf-dofile"><code>dofile (filename)</code></a></h3> +Opens the named file and executes its contents as a Lua chunk. +When called without arguments, +<code>dofile</code> executes the contents of the standard input (<code>stdin</code>). +Returns all values returned by the chunk. +In case of errors, <code>dofile</code> propagates the error +to its caller (that is, <code>dofile</code> does not run in protected mode). + + + + +<p> +<hr><h3><a name="pdf-error"><code>error (message [, level])</code></a></h3> +Terminates the last protected function called +and returns <code>message</code> as the error message. +Function <code>error</code> never returns. + + +<p> +Usually, <code>error</code> adds some information about the error position +at the beginning of the message. +The <code>level</code> argument specifies how to get the error position. +With level 1 (the default), the error position is where the +<code>error</code> function was called. +Level 2 points the error to where the function +that called <code>error</code> was called; and so on. +Passing a level 0 avoids the addition of error position information +to the message. + + + + +<p> +<hr><h3><a name="pdf-_G"><code>_G</code></a></h3> +A global variable (not a function) that +holds the global environment (that is, <code>_G._G = _G</code>). +Lua itself does not use this variable; +changing its value does not affect any environment, +nor vice-versa. +(Use <a href="#pdf-setfenv"><code>setfenv</code></a> to change environments.) + + + + +<p> +<hr><h3><a name="pdf-getfenv"><code>getfenv ([f])</code></a></h3> +Returns the current environment in use by the function. +<code>f</code> can be a Lua function or a number +that specifies the function at that stack level: +Level 1 is the function calling <code>getfenv</code>. +If the given function is not a Lua function, +or if <code>f</code> is 0, +<code>getfenv</code> returns the global environment. +The default for <code>f</code> is 1. + + + + +<p> +<hr><h3><a name="pdf-getmetatable"><code>getmetatable (object)</code></a></h3> + + +<p> +If <code>object</code> does not have a metatable, returns <b>nil</b>. +Otherwise, +if the object's metatable has a <code>"__metatable"</code> field, +returns the associated value. +Otherwise, returns the metatable of the given object. + + + + +<p> +<hr><h3><a name="pdf-ipairs"><code>ipairs (t)</code></a></h3> + + +<p> +Returns three values: an iterator function, the table <code>t</code>, and 0, +so that the construction + +<pre> + for i,v in ipairs(t) do <em>body</em> end +</pre><p> +will iterate over the pairs (<code>1,t[1]</code>), (<code>2,t[2]</code>), ···, +up to the first integer key absent from the table. + + + + +<p> +<hr><h3><a name="pdf-load"><code>load (func [, chunkname])</code></a></h3> + + +<p> +Loads a chunk using function <code>func</code> to get its pieces. +Each call to <code>func</code> must return a string that concatenates +with previous results. +A return of <b>nil</b> (or no value) signals the end of the chunk. + + +<p> +If there are no errors, +returns the compiled chunk as a function; +otherwise, returns <b>nil</b> plus the error message. +The environment of the returned function is the global environment. + + +<p> +<code>chunkname</code> is used as the chunk name for error messages +and debug information. +When absent, +it defaults to "<code>=(load)</code>". + + + + +<p> +<hr><h3><a name="pdf-loadfile"><code>loadfile ([filename])</code></a></h3> + + +<p> +Similar to <a href="#pdf-load"><code>load</code></a>, +but gets the chunk from file <code>filename</code> +or from the standard input, +if no file name is given. + + + + +<p> +<hr><h3><a name="pdf-loadstring"><code>loadstring (string [, chunkname])</code></a></h3> + + +<p> +Similar to <a href="#pdf-load"><code>load</code></a>, +but gets the chunk from the given string. + + +<p> +To load and run a given string, use the idiom + +<pre> + assert(loadstring(s))() +</pre> + +<p> +When absent, +<code>chunkname</code> defaults to the given string. + + + + +<p> +<hr><h3><a name="pdf-next"><code>next (table [, index])</code></a></h3> + + +<p> +Allows a program to traverse all fields of a table. +Its first argument is a table and its second argument +is an index in this table. +<code>next</code> returns the next index of the table +and its associated value. +When called with <b>nil</b> as its second argument, +<code>next</code> returns an initial index +and its associated value. +When called with the last index, +or with <b>nil</b> in an empty table, +<code>next</code> returns <b>nil</b>. +If the second argument is absent, then it is interpreted as <b>nil</b>. +In particular, +you can use <code>next(t)</code> to check whether a table is empty. + + +<p> +The order in which the indices are enumerated is not specified, +<em>even for numeric indices</em>. +(To traverse a table in numeric order, +use a numerical <b>for</b> or the <a href="#pdf-ipairs"><code>ipairs</code></a> function.) + + +<p> +The behavior of <code>next</code> is <em>undefined</em> if, +during the traversal, +you assign any value to a non-existent field in the table. +You may however modify existing fields. +In particular, you may clear existing fields. + + + + +<p> +<hr><h3><a name="pdf-pairs"><code>pairs (t)</code></a></h3> + + +<p> +Returns three values: the <a href="#pdf-next"><code>next</code></a> function, the table <code>t</code>, and <b>nil</b>, +so that the construction + +<pre> + for k,v in pairs(t) do <em>body</em> end +</pre><p> +will iterate over all key–value pairs of table <code>t</code>. + + +<p> +See function <a href="#pdf-next"><code>next</code></a> for the caveats of modifying +the table during its traversal. + + + + +<p> +<hr><h3><a name="pdf-pcall"><code>pcall (f, arg1, ···)</code></a></h3> + + +<p> +Calls function <code>f</code> with +the given arguments in <em>protected mode</em>. +This means that any error inside <code>f</code> is not propagated; +instead, <code>pcall</code> catches the error +and returns a status code. +Its first result is the status code (a boolean), +which is true if the call succeeds without errors. +In such case, <code>pcall</code> also returns all results from the call, +after this first result. +In case of any error, <code>pcall</code> returns <b>false</b> plus the error message. + + + + +<p> +<hr><h3><a name="pdf-print"><code>print (···)</code></a></h3> +Receives any number of arguments, +and prints their values to <code>stdout</code>, +using the <a href="#pdf-tostring"><code>tostring</code></a> function to convert them to strings. +<code>print</code> is not intended for formatted output, +but only as a quick way to show a value, +typically for debugging. +For formatted output, use <a href="#pdf-string.format"><code>string.format</code></a>. + + + + +<p> +<hr><h3><a name="pdf-rawequal"><code>rawequal (v1, v2)</code></a></h3> +Checks whether <code>v1</code> is equal to <code>v2</code>, +without invoking any metamethod. +Returns a boolean. + + + + +<p> +<hr><h3><a name="pdf-rawget"><code>rawget (table, index)</code></a></h3> +Gets the real value of <code>table[index]</code>, +without invoking any metamethod. +<code>table</code> must be a table; +<code>index</code> may be any value. + + + + +<p> +<hr><h3><a name="pdf-rawset"><code>rawset (table, index, value)</code></a></h3> +Sets the real value of <code>table[index]</code> to <code>value</code>, +without invoking any metamethod. +<code>table</code> must be a table, +<code>index</code> any value different from <b>nil</b>, +and <code>value</code> any Lua value. + + +<p> +This function returns <code>table</code>. + + + + +<p> +<hr><h3><a name="pdf-select"><code>select (index, ···)</code></a></h3> + + +<p> +If <code>index</code> is a number, +returns all arguments after argument number <code>index</code>. +Otherwise, <code>index</code> must be the string <code>"#"</code>, +and <code>select</code> returns the total number of extra arguments it received. + + + + +<p> +<hr><h3><a name="pdf-setfenv"><code>setfenv (f, table)</code></a></h3> + + +<p> +Sets the environment to be used by the given function. +<code>f</code> can be a Lua function or a number +that specifies the function at that stack level: +Level 1 is the function calling <code>setfenv</code>. +<code>setfenv</code> returns the given function. + + +<p> +As a special case, when <code>f</code> is 0 <code>setfenv</code> changes +the environment of the running thread. +In this case, <code>setfenv</code> returns no values. + + + + +<p> +<hr><h3><a name="pdf-setmetatable"><code>setmetatable (table, metatable)</code></a></h3> + + +<p> +Sets the metatable for the given table. +(You cannot change the metatable of other types from Lua, only from C.) +If <code>metatable</code> is <b>nil</b>, +removes the metatable of the given table. +If the original metatable has a <code>"__metatable"</code> field, +raises an error. + + +<p> +This function returns <code>table</code>. + + + + +<p> +<hr><h3><a name="pdf-tonumber"><code>tonumber (e [, base])</code></a></h3> +Tries to convert its argument to a number. +If the argument is already a number or a string convertible +to a number, then <code>tonumber</code> returns this number; +otherwise, it returns <b>nil</b>. + + +<p> +An optional argument specifies the base to interpret the numeral. +The base may be any integer between 2 and 36, inclusive. +In bases above 10, the letter '<code>A</code>' (in either upper or lower case) +represents 10, '<code>B</code>' represents 11, and so forth, +with '<code>Z</code>' representing 35. +In base 10 (the default), the number may have a decimal part, +as well as an optional exponent part (see <a href="#2.1">§2.1</a>). +In other bases, only unsigned integers are accepted. + + + + +<p> +<hr><h3><a name="pdf-tostring"><code>tostring (e)</code></a></h3> +Receives an argument of any type and +converts it to a string in a reasonable format. +For complete control of how numbers are converted, +use <a href="#pdf-string.format"><code>string.format</code></a>. + + +<p> +If the metatable of <code>e</code> has a <code>"__tostring"</code> field, +then <code>tostring</code> calls the corresponding value +with <code>e</code> as argument, +and uses the result of the call as its result. + + + + +<p> +<hr><h3><a name="pdf-type"><code>type (v)</code></a></h3> +Returns the type of its only argument, coded as a string. +The possible results of this function are +"<code>nil</code>" (a string, not the value <b>nil</b>), +"<code>number</code>", +"<code>string</code>", +"<code>boolean</code>", +"<code>table</code>", +"<code>function</code>", +"<code>thread</code>", +and "<code>userdata</code>". + + + + +<p> +<hr><h3><a name="pdf-unpack"><code>unpack (list [, i [, j]])</code></a></h3> +Returns the elements from the given table. +This function is equivalent to + +<pre> + return list[i], list[i+1], ···, list[j] +</pre><p> +except that the above code can be written only for a fixed number +of elements. +By default, <code>i</code> is 1 and <code>j</code> is the length of the list, +as defined by the length operator (see <a href="#2.5.5">§2.5.5</a>). + + + + +<p> +<hr><h3><a name="pdf-_VERSION"><code>_VERSION</code></a></h3> +A global variable (not a function) that +holds a string containing the current interpreter version. +The current contents of this variable is "<code>Lua 5.1</code>". + + + + +<p> +<hr><h3><a name="pdf-xpcall"><code>xpcall (f, err)</code></a></h3> + + +<p> +This function is similar to <a href="#pdf-pcall"><code>pcall</code></a>, +except that you can set a new error handler. + + +<p> +<code>xpcall</code> calls function <code>f</code> in protected mode, +using <code>err</code> as the error handler. +Any error inside <code>f</code> is not propagated; +instead, <code>xpcall</code> catches the error, +calls the <code>err</code> function with the original error object, +and returns a status code. +Its first result is the status code (a boolean), +which is true if the call succeeds without errors. +In this case, <code>xpcall</code> also returns all results from the call, +after this first result. +In case of any error, +<code>xpcall</code> returns <b>false</b> plus the result from <code>err</code>. + + + + + + + +<h2>5.2 - <a name="5.2">Coroutine Manipulation</a></h2> + +<p> +The operations related to coroutines comprise a sub-library of +the basic library and come inside the table <a name="pdf-coroutine"><code>coroutine</code></a>. +See <a href="#2.11">§2.11</a> for a general description of coroutines. + + +<p> +<hr><h3><a name="pdf-coroutine.create"><code>coroutine.create (f)</code></a></h3> + + +<p> +Creates a new coroutine, with body <code>f</code>. +<code>f</code> must be a Lua function. +Returns this new coroutine, +an object with type <code>"thread"</code>. + + + + +<p> +<hr><h3><a name="pdf-coroutine.resume"><code>coroutine.resume (co [, val1, ···])</code></a></h3> + + +<p> +Starts or continues the execution of coroutine <code>co</code>. +The first time you resume a coroutine, +it starts running its body. +The values <code>val1</code>, ··· are passed +as the arguments to the body function. +If the coroutine has yielded, +<code>resume</code> restarts it; +the values <code>val1</code>, ··· are passed +as the results from the yield. + + +<p> +If the coroutine runs without any errors, +<code>resume</code> returns <b>true</b> plus any values passed to <code>yield</code> +(if the coroutine yields) or any values returned by the body function +(if the coroutine terminates). +If there is any error, +<code>resume</code> returns <b>false</b> plus the error message. + + + + +<p> +<hr><h3><a name="pdf-coroutine.running"><code>coroutine.running ()</code></a></h3> + + +<p> +Returns the running coroutine, +or <b>nil</b> when called by the main thread. + + + + +<p> +<hr><h3><a name="pdf-coroutine.status"><code>coroutine.status (co)</code></a></h3> + + +<p> +Returns the status of coroutine <code>co</code>, as a string: +<code>"running"</code>, +if the coroutine is running (that is, it called <code>status</code>); +<code>"suspended"</code>, if the coroutine is suspended in a call to <code>yield</code>, +or if it has not started running yet; +<code>"normal"</code> if the coroutine is active but not running +(that is, it has resumed another coroutine); +and <code>"dead"</code> if the coroutine has finished its body function, +or if it has stopped with an error. + + + + +<p> +<hr><h3><a name="pdf-coroutine.wrap"><code>coroutine.wrap (f)</code></a></h3> + + +<p> +Creates a new coroutine, with body <code>f</code>. +<code>f</code> must be a Lua function. +Returns a function that resumes the coroutine each time it is called. +Any arguments passed to the function behave as the +extra arguments to <code>resume</code>. +Returns the same values returned by <code>resume</code>, +except the first boolean. +In case of error, propagates the error. + + + + +<p> +<hr><h3><a name="pdf-coroutine.yield"><code>coroutine.yield (···)</code></a></h3> + + +<p> +Suspends the execution of the calling coroutine. +The coroutine cannot be running a C function, +a metamethod, or an iterator. +Any arguments to <code>yield</code> are passed as extra results to <code>resume</code>. + + + + + + + +<h2>5.3 - <a name="5.3">Modules</a></h2> + +<p> +The package library provides basic +facilities for loading and building modules in Lua. +It exports two of its functions directly in the global environment: +<a href="#pdf-require"><code>require</code></a> and <a href="#pdf-module"><code>module</code></a>. +Everything else is exported in a table <a name="pdf-package"><code>package</code></a>. + + +<p> +<hr><h3><a name="pdf-module"><code>module (name [, ···])</code></a></h3> + + +<p> +Creates a module. +If there is a table in <code>package.loaded[name]</code>, +this table is the module. +Otherwise, if there is a global table <code>t</code> with the given name, +this table is the module. +Otherwise creates a new table <code>t</code> and +sets it as the value of the global <code>name</code> and +the value of <code>package.loaded[name]</code>. +This function also initializes <code>t._NAME</code> with the given name, +<code>t._M</code> with the module (<code>t</code> itself), +and <code>t._PACKAGE</code> with the package name +(the full module name minus last component; see below). +Finally, <code>module</code> sets <code>t</code> as the new environment +of the current function and the new value of <code>package.loaded[name]</code>, +so that <a href="#pdf-require"><code>require</code></a> returns <code>t</code>. + + +<p> +If <code>name</code> is a compound name +(that is, one with components separated by dots), +<code>module</code> creates (or reuses, if they already exist) +tables for each component. +For instance, if <code>name</code> is <code>a.b.c</code>, +then <code>module</code> stores the module table in field <code>c</code> of +field <code>b</code> of global <code>a</code>. + + +<p> +This function may receive optional <em>options</em> after +the module name, +where each option is a function to be applied over the module. + + + + +<p> +<hr><h3><a name="pdf-require"><code>require (modname)</code></a></h3> + + +<p> +Loads the given module. +The function starts by looking into the <a href="#pdf-package.loaded"><code>package.loaded</code></a> table +to determine whether <code>modname</code> is already loaded. +If it is, then <code>require</code> returns the value stored +at <code>package.loaded[modname]</code>. +Otherwise, it tries to find a <em>loader</em> for the module. + + +<p> +To find a loader, +<code>require</code> is guided by the <a href="#pdf-package.loaders"><code>package.loaders</code></a> array. +By changing this array, +we can change how <code>require</code> looks for a module. +The following explanation is based on the default configuration +for <a href="#pdf-package.loaders"><code>package.loaders</code></a>. + + +<p> +First <code>require</code> queries <code>package.preload[modname]</code>. +If it has a value, +this value (which should be a function) is the loader. +Otherwise <code>require</code> searches for a Lua loader using the +path stored in <a href="#pdf-package.path"><code>package.path</code></a>. +If that also fails, it searches for a C loader using the +path stored in <a href="#pdf-package.cpath"><code>package.cpath</code></a>. +If that also fails, +it tries an <em>all-in-one</em> loader (see <a href="#pdf-package.loaders"><code>package.loaders</code></a>). + + +<p> +Once a loader is found, +<code>require</code> calls the loader with a single argument, <code>modname</code>. +If the loader returns any value, +<code>require</code> assigns the returned value to <code>package.loaded[modname]</code>. +If the loader returns no value and +has not assigned any value to <code>package.loaded[modname]</code>, +then <code>require</code> assigns <b>true</b> to this entry. +In any case, <code>require</code> returns the +final value of <code>package.loaded[modname]</code>. + + +<p> +If there is any error loading or running the module, +or if it cannot find any loader for the module, +then <code>require</code> signals an error. + + + + +<p> +<hr><h3><a name="pdf-package.cpath"><code>package.cpath</code></a></h3> + + +<p> +The path used by <a href="#pdf-require"><code>require</code></a> to search for a C loader. + + +<p> +Lua initializes the C path <a href="#pdf-package.cpath"><code>package.cpath</code></a> in the same way +it initializes the Lua path <a href="#pdf-package.path"><code>package.path</code></a>, +using the environment variable <a name="pdf-LUA_CPATH"><code>LUA_CPATH</code></a> +or a default path defined in <code>luaconf.h</code>. + + + + +<p> + +<hr><h3><a name="pdf-package.loaded"><code>package.loaded</code></a></h3> + + +<p> +A table used by <a href="#pdf-require"><code>require</code></a> to control which +modules are already loaded. +When you require a module <code>modname</code> and +<code>package.loaded[modname]</code> is not false, +<a href="#pdf-require"><code>require</code></a> simply returns the value stored there. + + + + +<p> +<hr><h3><a name="pdf-package.loaders"><code>package.loaders</code></a></h3> + + +<p> +A table used by <a href="#pdf-require"><code>require</code></a> to control how to load modules. + + +<p> +Each entry in this table is a <em>searcher function</em>. +When looking for a module, +<a href="#pdf-require"><code>require</code></a> calls each of these searchers in ascending order, +with the module name (the argument given to <a href="#pdf-require"><code>require</code></a>) as its +sole parameter. +The function may return another function (the module <em>loader</em>) +or a string explaining why it did not find that module +(or <b>nil</b> if it has nothing to say). +Lua initializes this table with four functions. + + +<p> +The first searcher simply looks for a loader in the +<a href="#pdf-package.preload"><code>package.preload</code></a> table. + + +<p> +The second searcher looks for a loader as a Lua library, +using the path stored at <a href="#pdf-package.path"><code>package.path</code></a>. +A path is a sequence of <em>templates</em> separated by semicolons. +For each template, +the searcher will change each interrogation +mark in the template by <code>filename</code>, +which is the module name with each dot replaced by a +"directory separator" (such as "<code>/</code>" in Unix); +then it will try to open the resulting file name. +So, for instance, if the Lua path is the string + +<pre> + "./?.lua;./?.lc;/usr/local/?/init.lua" +</pre><p> +the search for a Lua file for module <code>foo</code> +will try to open the files +<code>./foo.lua</code>, <code>./foo.lc</code>, and +<code>/usr/local/foo/init.lua</code>, in that order. + + +<p> +The third searcher looks for a loader as a C library, +using the path given by the variable <a href="#pdf-package.cpath"><code>package.cpath</code></a>. +For instance, +if the C path is the string + +<pre> + "./?.so;./?.dll;/usr/local/?/init.so" +</pre><p> +the searcher for module <code>foo</code> +will try to open the files <code>./foo.so</code>, <code>./foo.dll</code>, +and <code>/usr/local/foo/init.so</code>, in that order. +Once it finds a C library, +this searcher first uses a dynamic link facility to link the +application with the library. +Then it tries to find a C function inside the library to +be used as the loader. +The name of this C function is the string "<code>luaopen_</code>" +concatenated with a copy of the module name where each dot +is replaced by an underscore. +Moreover, if the module name has a hyphen, +its prefix up to (and including) the first hyphen is removed. +For instance, if the module name is <code>a.v1-b.c</code>, +the function name will be <code>luaopen_b_c</code>. + + +<p> +The fourth searcher tries an <em>all-in-one loader</em>. +It searches the C path for a library for +the root name of the given module. +For instance, when requiring <code>a.b.c</code>, +it will search for a C library for <code>a</code>. +If found, it looks into it for an open function for +the submodule; +in our example, that would be <code>luaopen_a_b_c</code>. +With this facility, a package can pack several C submodules +into one single library, +with each submodule keeping its original open function. + + + + +<p> +<hr><h3><a name="pdf-package.loadlib"><code>package.loadlib (libname, funcname)</code></a></h3> + + +<p> +Dynamically links the host program with the C library <code>libname</code>. +Inside this library, looks for a function <code>funcname</code> +and returns this function as a C function. +(So, <code>funcname</code> must follow the protocol (see <a href="#lua_CFunction"><code>lua_CFunction</code></a>)). + + +<p> +This is a low-level function. +It completely bypasses the package and module system. +Unlike <a href="#pdf-require"><code>require</code></a>, +it does not perform any path searching and +does not automatically adds extensions. +<code>libname</code> must be the complete file name of the C library, +including if necessary a path and extension. +<code>funcname</code> must be the exact name exported by the C library +(which may depend on the C compiler and linker used). + + +<p> +This function is not supported by ANSI C. +As such, it is only available on some platforms +(Windows, Linux, Mac OS X, Solaris, BSD, +plus other Unix systems that support the <code>dlfcn</code> standard). + + + + +<p> +<hr><h3><a name="pdf-package.path"><code>package.path</code></a></h3> + + +<p> +The path used by <a href="#pdf-require"><code>require</code></a> to search for a Lua loader. + + +<p> +At start-up, Lua initializes this variable with +the value of the environment variable <a name="pdf-LUA_PATH"><code>LUA_PATH</code></a> or +with a default path defined in <code>luaconf.h</code>, +if the environment variable is not defined. +Any "<code>;;</code>" in the value of the environment variable +is replaced by the default path. + + + + +<p> +<hr><h3><a name="pdf-package.preload"><code>package.preload</code></a></h3> + + +<p> +A table to store loaders for specific modules +(see <a href="#pdf-require"><code>require</code></a>). + + + + +<p> +<hr><h3><a name="pdf-package.seeall"><code>package.seeall (module)</code></a></h3> + + +<p> +Sets a metatable for <code>module</code> with +its <code>__index</code> field referring to the global environment, +so that this module inherits values +from the global environment. +To be used as an option to function <a href="#pdf-module"><code>module</code></a>. + + + + + + + +<h2>5.4 - <a name="5.4">String Manipulation</a></h2> + +<p> +This library provides generic functions for string manipulation, +such as finding and extracting substrings, and pattern matching. +When indexing a string in Lua, the first character is at position 1 +(not at 0, as in C). +Indices are allowed to be negative and are interpreted as indexing backwards, +from the end of the string. +Thus, the last character is at position -1, and so on. + + +<p> +The string library provides all its functions inside the table +<a name="pdf-string"><code>string</code></a>. +It also sets a metatable for strings +where the <code>__index</code> field points to the <code>string</code> table. +Therefore, you can use the string functions in object-oriented style. +For instance, <code>string.byte(s, i)</code> +can be written as <code>s:byte(i)</code>. + + +<p> +<hr><h3><a name="pdf-string.byte"><code>string.byte (s [, i [, j]])</code></a></h3> +Returns the internal numerical codes of the characters <code>s[i]</code>, +<code>s[i+1]</code>, ···, <code>s[j]</code>. +The default value for <code>i</code> is 1; +the default value for <code>j</code> is <code>i</code>. + + +<p> +Note that numerical codes are not necessarily portable across platforms. + + + + +<p> +<hr><h3><a name="pdf-string.char"><code>string.char (···)</code></a></h3> +Receives zero or more integers. +Returns a string with length equal to the number of arguments, +in which each character has the internal numerical code equal +to its corresponding argument. + + +<p> +Note that numerical codes are not necessarily portable across platforms. + + + + +<p> +<hr><h3><a name="pdf-string.dump"><code>string.dump (function)</code></a></h3> + + +<p> +Returns a string containing a binary representation of the given function, +so that a later <a href="#pdf-loadstring"><code>loadstring</code></a> on this string returns +a copy of the function. +<code>function</code> must be a Lua function without upvalues. + + + + +<p> +<hr><h3><a name="pdf-string.find"><code>string.find (s, pattern [, init [, plain]])</code></a></h3> +Looks for the first match of +<code>pattern</code> in the string <code>s</code>. +If it finds a match, then <code>find</code> returns the indices of <code>s</code> +where this occurrence starts and ends; +otherwise, it returns <b>nil</b>. +A third, optional numerical argument <code>init</code> specifies +where to start the search; +its default value is 1 and may be negative. +A value of <b>true</b> as a fourth, optional argument <code>plain</code> +turns off the pattern matching facilities, +so the function does a plain "find substring" operation, +with no characters in <code>pattern</code> being considered "magic". +Note that if <code>plain</code> is given, then <code>init</code> must be given as well. + + +<p> +If the pattern has captures, +then in a successful match +the captured values are also returned, +after the two indices. + + + + +<p> +<hr><h3><a name="pdf-string.format"><code>string.format (formatstring, ···)</code></a></h3> +Returns a formatted version of its variable number of arguments +following the description given in its first argument (which must be a string). +The format string follows the same rules as the <code>printf</code> family of +standard C functions. +The only differences are that the options/modifiers +<code>*</code>, <code>l</code>, <code>L</code>, <code>n</code>, <code>p</code>, +and <code>h</code> are not supported +and that there is an extra option, <code>q</code>. +The <code>q</code> option formats a string in a form suitable to be safely read +back by the Lua interpreter: +the string is written between double quotes, +and all double quotes, newlines, embedded zeros, +and backslashes in the string +are correctly escaped when written. +For instance, the call + +<pre> + string.format('%q', 'a string with "quotes" and \n new line') +</pre><p> +will produce the string: + +<pre> + "a string with \"quotes\" and \ + new line" +</pre> + +<p> +The options <code>c</code>, <code>d</code>, <code>E</code>, <code>e</code>, <code>f</code>, +<code>g</code>, <code>G</code>, <code>i</code>, <code>o</code>, <code>u</code>, <code>X</code>, and <code>x</code> all +expect a number as argument, +whereas <code>q</code> and <code>s</code> expect a string. + + +<p> +This function does not accept string values +containing embedded zeros, +except as arguments to the <code>q</code> option. + + + + +<p> +<hr><h3><a name="pdf-string.gmatch"><code>string.gmatch (s, pattern)</code></a></h3> +Returns an iterator function that, +each time it is called, +returns the next captures from <code>pattern</code> over string <code>s</code>. +If <code>pattern</code> specifies no captures, +then the whole match is produced in each call. + + +<p> +As an example, the following loop + +<pre> + s = "hello world from Lua" + for w in string.gmatch(s, "%a+") do + print(w) + end +</pre><p> +will iterate over all the words from string <code>s</code>, +printing one per line. +The next example collects all pairs <code>key=value</code> from the +given string into a table: + +<pre> + t = {} + s = "from=world, to=Lua" + for k, v in string.gmatch(s, "(%w+)=(%w+)") do + t[k] = v + end +</pre> + +<p> +For this function, a '<code>^</code>' at the start of a pattern does not +work as an anchor, as this would prevent the iteration. + + + + +<p> +<hr><h3><a name="pdf-string.gsub"><code>string.gsub (s, pattern, repl [, n])</code></a></h3> +Returns a copy of <code>s</code> +in which all (or the first <code>n</code>, if given) +occurrences of the <code>pattern</code> have been +replaced by a replacement string specified by <code>repl</code>, +which may be a string, a table, or a function. +<code>gsub</code> also returns, as its second value, +the total number of matches that occurred. + + +<p> +If <code>repl</code> is a string, then its value is used for replacement. +The character <code>%</code> works as an escape character: +any sequence in <code>repl</code> of the form <code>%<em>n</em></code>, +with <em>n</em> between 1 and 9, +stands for the value of the <em>n</em>-th captured substring (see below). +The sequence <code>%0</code> stands for the whole match. +The sequence <code>%%</code> stands for a single <code>%</code>. + + +<p> +If <code>repl</code> is a table, then the table is queried for every match, +using the first capture as the key; +if the pattern specifies no captures, +then the whole match is used as the key. + + +<p> +If <code>repl</code> is a function, then this function is called every time a +match occurs, with all captured substrings passed as arguments, +in order; +if the pattern specifies no captures, +then the whole match is passed as a sole argument. + + +<p> +If the value returned by the table query or by the function call +is a string or a number, +then it is used as the replacement string; +otherwise, if it is <b>false</b> or <b>nil</b>, +then there is no replacement +(that is, the original match is kept in the string). + + +<p> +Here are some examples: + +<pre> + x = string.gsub("hello world", "(%w+)", "%1 %1") + --> x="hello hello world world" + + x = string.gsub("hello world", "%w+", "%0 %0", 1) + --> x="hello hello world" + + x = string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1") + --> x="world hello Lua from" + + x = string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv) + --> x="home = /home/roberto, user = roberto" + + x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s) + return loadstring(s)() + end) + --> x="4+5 = 9" + + local t = {name="lua", version="5.1"} + x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t) + --> x="lua-5.1.tar.gz" +</pre> + + + +<p> +<hr><h3><a name="pdf-string.len"><code>string.len (s)</code></a></h3> +Receives a string and returns its length. +The empty string <code>""</code> has length 0. +Embedded zeros are counted, +so <code>"a\000bc\000"</code> has length 5. + + + + +<p> +<hr><h3><a name="pdf-string.lower"><code>string.lower (s)</code></a></h3> +Receives a string and returns a copy of this string with all +uppercase letters changed to lowercase. +All other characters are left unchanged. +The definition of what an uppercase letter is depends on the current locale. + + + + +<p> +<hr><h3><a name="pdf-string.match"><code>string.match (s, pattern [, init])</code></a></h3> +Looks for the first <em>match</em> of +<code>pattern</code> in the string <code>s</code>. +If it finds one, then <code>match</code> returns +the captures from the pattern; +otherwise it returns <b>nil</b>. +If <code>pattern</code> specifies no captures, +then the whole match is returned. +A third, optional numerical argument <code>init</code> specifies +where to start the search; +its default value is 1 and may be negative. + + + + +<p> +<hr><h3><a name="pdf-string.rep"><code>string.rep (s, n)</code></a></h3> +Returns a string that is the concatenation of <code>n</code> copies of +the string <code>s</code>. + + + + +<p> +<hr><h3><a name="pdf-string.reverse"><code>string.reverse (s)</code></a></h3> +Returns a string that is the string <code>s</code> reversed. + + + + +<p> +<hr><h3><a name="pdf-string.sub"><code>string.sub (s, i [, j])</code></a></h3> +Returns the substring of <code>s</code> that +starts at <code>i</code> and continues until <code>j</code>; +<code>i</code> and <code>j</code> may be negative. +If <code>j</code> is absent, then it is assumed to be equal to -1 +(which is the same as the string length). +In particular, +the call <code>string.sub(s,1,j)</code> returns a prefix of <code>s</code> +with length <code>j</code>, +and <code>string.sub(s, -i)</code> returns a suffix of <code>s</code> +with length <code>i</code>. + + + + +<p> +<hr><h3><a name="pdf-string.upper"><code>string.upper (s)</code></a></h3> +Receives a string and returns a copy of this string with all +lowercase letters changed to uppercase. +All other characters are left unchanged. +The definition of what a lowercase letter is depends on the current locale. + + + +<h3>5.4.1 - <a name="5.4.1">Patterns</a></h3> + + +<h4>Character Class:</h4><p> +A <em>character class</em> is used to represent a set of characters. +The following combinations are allowed in describing a character class: + +<ul> + +<li><b><em>x</em>:</b> +(where <em>x</em> is not one of the <em>magic characters</em> +<code>^$()%.[]*+-?</code>) +represents the character <em>x</em> itself. +</li> + +<li><b><code>.</code>:</b> (a dot) represents all characters.</li> + +<li><b><code>%a</code>:</b> represents all letters.</li> + +<li><b><code>%c</code>:</b> represents all control characters.</li> + +<li><b><code>%d</code>:</b> represents all digits.</li> + +<li><b><code>%l</code>:</b> represents all lowercase letters.</li> + +<li><b><code>%p</code>:</b> represents all punctuation characters.</li> + +<li><b><code>%s</code>:</b> represents all space characters.</li> + +<li><b><code>%u</code>:</b> represents all uppercase letters.</li> + +<li><b><code>%w</code>:</b> represents all alphanumeric characters.</li> + +<li><b><code>%x</code>:</b> represents all hexadecimal digits.</li> + +<li><b><code>%z</code>:</b> represents the character with representation 0.</li> + +<li><b><code>%<em>x</em></code>:</b> (where <em>x</em> is any non-alphanumeric character) +represents the character <em>x</em>. +This is the standard way to escape the magic characters. +Any punctuation character (even the non magic) +can be preceded by a '<code>%</code>' +when used to represent itself in a pattern. +</li> + +<li><b><code>[<em>set</em>]</code>:</b> +represents the class which is the union of all +characters in <em>set</em>. +A range of characters may be specified by +separating the end characters of the range with a '<code>-</code>'. +All classes <code>%</code><em>x</em> described above may also be used as +components in <em>set</em>. +All other characters in <em>set</em> represent themselves. +For example, <code>[%w_]</code> (or <code>[_%w]</code>) +represents all alphanumeric characters plus the underscore, +<code>[0-7]</code> represents the octal digits, +and <code>[0-7%l%-]</code> represents the octal digits plus +the lowercase letters plus the '<code>-</code>' character. + + +<p> +The interaction between ranges and classes is not defined. +Therefore, patterns like <code>[%a-z]</code> or <code>[a-%%]</code> +have no meaning. +</li> + +<li><b><code>[^<em>set</em>]</code>:</b> +represents the complement of <em>set</em>, +where <em>set</em> is interpreted as above. +</li> + +</ul><p> +For all classes represented by single letters (<code>%a</code>, <code>%c</code>, etc.), +the corresponding uppercase letter represents the complement of the class. +For instance, <code>%S</code> represents all non-space characters. + + +<p> +The definitions of letter, space, and other character groups +depend on the current locale. +In particular, the class <code>[a-z]</code> may not be equivalent to <code>%l</code>. + + + + + +<h4>Pattern Item:</h4><p> +A <em>pattern item</em> may be + +<ul> + +<li> +a single character class, +which matches any single character in the class; +</li> + +<li> +a single character class followed by '<code>*</code>', +which matches 0 or more repetitions of characters in the class. +These repetition items will always match the longest possible sequence; +</li> + +<li> +a single character class followed by '<code>+</code>', +which matches 1 or more repetitions of characters in the class. +These repetition items will always match the longest possible sequence; +</li> + +<li> +a single character class followed by '<code>-</code>', +which also matches 0 or more repetitions of characters in the class. +Unlike '<code>*</code>', +these repetition items will always match the <em>shortest</em> possible sequence; +</li> + +<li> +a single character class followed by '<code>?</code>', +which matches 0 or 1 occurrence of a character in the class; +</li> + +<li> +<code>%<em>n</em></code>, for <em>n</em> between 1 and 9; +such item matches a substring equal to the <em>n</em>-th captured string +(see below); +</li> + +<li> +<code>%b<em>xy</em></code>, where <em>x</em> and <em>y</em> are two distinct characters; +such item matches strings that start with <em>x</em>, end with <em>y</em>, +and where the <em>x</em> and <em>y</em> are <em>balanced</em>. +This means that, if one reads the string from left to right, +counting <em>+1</em> for an <em>x</em> and <em>-1</em> for a <em>y</em>, +the ending <em>y</em> is the first <em>y</em> where the count reaches 0. +For instance, the item <code>%b()</code> matches expressions with +balanced parentheses. +</li> + +</ul> + + + + +<h4>Pattern:</h4><p> +A <em>pattern</em> is a sequence of pattern items. +A '<code>^</code>' at the beginning of a pattern anchors the match at the +beginning of the subject string. +A '<code>$</code>' at the end of a pattern anchors the match at the +end of the subject string. +At other positions, +'<code>^</code>' and '<code>$</code>' have no special meaning and represent themselves. + + + + + +<h4>Captures:</h4><p> +A pattern may contain sub-patterns enclosed in parentheses; +they describe <em>captures</em>. +When a match succeeds, the substrings of the subject string +that match captures are stored (<em>captured</em>) for future use. +Captures are numbered according to their left parentheses. +For instance, in the pattern <code>"(a*(.)%w(%s*))"</code>, +the part of the string matching <code>"a*(.)%w(%s*)"</code> is +stored as the first capture (and therefore has number 1); +the character matching "<code>.</code>" is captured with number 2, +and the part matching "<code>%s*</code>" has number 3. + + +<p> +As a special case, the empty capture <code>()</code> captures +the current string position (a number). +For instance, if we apply the pattern <code>"()aa()"</code> on the +string <code>"flaaap"</code>, there will be two captures: 3 and 5. + + +<p> +A pattern cannot contain embedded zeros. Use <code>%z</code> instead. + + + + + + + + + + + +<h2>5.5 - <a name="5.5">Table Manipulation</a></h2><p> +This library provides generic functions for table manipulation. +It provides all its functions inside the table <a name="pdf-table"><code>table</code></a>. + + +<p> +Most functions in the table library assume that the table +represents an array or a list. +For these functions, when we talk about the "length" of a table +we mean the result of the length operator. + + +<p> +<hr><h3><a name="pdf-table.concat"><code>table.concat (table [, sep [, i [, j]]])</code></a></h3> +Given an array where all elements are strings or numbers, +returns <code>table[i]..sep..table[i+1] ··· sep..table[j]</code>. +The default value for <code>sep</code> is the empty string, +the default for <code>i</code> is 1, +and the default for <code>j</code> is the length of the table. +If <code>i</code> is greater than <code>j</code>, returns the empty string. + + + + +<p> +<hr><h3><a name="pdf-table.insert"><code>table.insert (table, [pos,] value)</code></a></h3> + + +<p> +Inserts element <code>value</code> at position <code>pos</code> in <code>table</code>, +shifting up other elements to open space, if necessary. +The default value for <code>pos</code> is <code>n+1</code>, +where <code>n</code> is the length of the table (see <a href="#2.5.5">§2.5.5</a>), +so that a call <code>table.insert(t,x)</code> inserts <code>x</code> at the end +of table <code>t</code>. + + + + +<p> +<hr><h3><a name="pdf-table.maxn"><code>table.maxn (table)</code></a></h3> + + +<p> +Returns the largest positive numerical index of the given table, +or zero if the table has no positive numerical indices. +(To do its job this function does a linear traversal of +the whole table.) + + + + +<p> +<hr><h3><a name="pdf-table.remove"><code>table.remove (table [, pos])</code></a></h3> + + +<p> +Removes from <code>table</code> the element at position <code>pos</code>, +shifting down other elements to close the space, if necessary. +Returns the value of the removed element. +The default value for <code>pos</code> is <code>n</code>, +where <code>n</code> is the length of the table, +so that a call <code>table.remove(t)</code> removes the last element +of table <code>t</code>. + + + + +<p> +<hr><h3><a name="pdf-table.sort"><code>table.sort (table [, comp])</code></a></h3> +Sorts table elements in a given order, <em>in-place</em>, +from <code>table[1]</code> to <code>table[n]</code>, +where <code>n</code> is the length of the table. +If <code>comp</code> is given, +then it must be a function that receives two table elements, +and returns true +when the first is less than the second +(so that <code>not comp(a[i+1],a[i])</code> will be true after the sort). +If <code>comp</code> is not given, +then the standard Lua operator <code><</code> is used instead. + + +<p> +The sort algorithm is not stable; +that is, elements considered equal by the given order +may have their relative positions changed by the sort. + + + + + + + +<h2>5.6 - <a name="5.6">Mathematical Functions</a></h2> + +<p> +This library is an interface to the standard C math library. +It provides all its functions inside the table <a name="pdf-math"><code>math</code></a>. + + +<p> +<hr><h3><a name="pdf-math.abs"><code>math.abs (x)</code></a></h3> + + +<p> +Returns the absolute value of <code>x</code>. + + + + +<p> +<hr><h3><a name="pdf-math.acos"><code>math.acos (x)</code></a></h3> + + +<p> +Returns the arc cosine of <code>x</code> (in radians). + + + + +<p> +<hr><h3><a name="pdf-math.asin"><code>math.asin (x)</code></a></h3> + + +<p> +Returns the arc sine of <code>x</code> (in radians). + + + + +<p> +<hr><h3><a name="pdf-math.atan"><code>math.atan (x)</code></a></h3> + + +<p> +Returns the arc tangent of <code>x</code> (in radians). + + + + +<p> +<hr><h3><a name="pdf-math.atan2"><code>math.atan2 (y, x)</code></a></h3> + + +<p> +Returns the arc tangent of <code>y/x</code> (in radians), +but uses the signs of both parameters to find the +quadrant of the result. +(It also handles correctly the case of <code>x</code> being zero.) + + + + +<p> +<hr><h3><a name="pdf-math.ceil"><code>math.ceil (x)</code></a></h3> + + +<p> +Returns the smallest integer larger than or equal to <code>x</code>. + + + + +<p> +<hr><h3><a name="pdf-math.cos"><code>math.cos (x)</code></a></h3> + + +<p> +Returns the cosine of <code>x</code> (assumed to be in radians). + + + + +<p> +<hr><h3><a name="pdf-math.cosh"><code>math.cosh (x)</code></a></h3> + + +<p> +Returns the hyperbolic cosine of <code>x</code>. + + + + +<p> +<hr><h3><a name="pdf-math.deg"><code>math.deg (x)</code></a></h3> + + +<p> +Returns the angle <code>x</code> (given in radians) in degrees. + + + + +<p> +<hr><h3><a name="pdf-math.exp"><code>math.exp (x)</code></a></h3> + + +<p> +Returns the value <em>e<sup>x</sup></em>. + + + + +<p> +<hr><h3><a name="pdf-math.floor"><code>math.floor (x)</code></a></h3> + + +<p> +Returns the largest integer smaller than or equal to <code>x</code>. + + + + +<p> +<hr><h3><a name="pdf-math.fmod"><code>math.fmod (x, y)</code></a></h3> + + +<p> +Returns the remainder of the division of <code>x</code> by <code>y</code>. + + + + +<p> +<hr><h3><a name="pdf-math.frexp"><code>math.frexp (x)</code></a></h3> + + +<p> +Returns <code>m</code> and <code>e</code> such that <em>x = m2<sup>e</sup></em>, +<code>e</code> is an integer and the absolute value of <code>m</code> is +in the range <em>[0.5, 1)</em> +(or zero when <code>x</code> is zero). + + + + +<p> +<hr><h3><a name="pdf-math.huge"><code>math.huge</code></a></h3> + + +<p> +The value <code>HUGE_VAL</code>, +a value larger than or equal to any other numerical value. + + + + +<p> +<hr><h3><a name="pdf-math.ldexp"><code>math.ldexp (m, e)</code></a></h3> + + +<p> +Returns <em>m2<sup>e</sup></em> (<code>e</code> should be an integer). + + + + +<p> +<hr><h3><a name="pdf-math.log"><code>math.log (x)</code></a></h3> + + +<p> +Returns the natural logarithm of <code>x</code>. + + + + +<p> +<hr><h3><a name="pdf-math.log10"><code>math.log10 (x)</code></a></h3> + + +<p> +Returns the base-10 logarithm of <code>x</code>. + + + + +<p> +<hr><h3><a name="pdf-math.max"><code>math.max (x, ···)</code></a></h3> + + +<p> +Returns the maximum value among its arguments. + + + + +<p> +<hr><h3><a name="pdf-math.min"><code>math.min (x, ···)</code></a></h3> + + +<p> +Returns the minimum value among its arguments. + + + + +<p> +<hr><h3><a name="pdf-math.modf"><code>math.modf (x)</code></a></h3> + + +<p> +Returns two numbers, +the integral part of <code>x</code> and the fractional part of <code>x</code>. + + + + +<p> +<hr><h3><a name="pdf-math.pi"><code>math.pi</code></a></h3> + + +<p> +The value of <em>pi</em>. + + + + +<p> +<hr><h3><a name="pdf-math.pow"><code>math.pow (x, y)</code></a></h3> + + +<p> +Returns <em>x<sup>y</sup></em>. +(You can also use the expression <code>x^y</code> to compute this value.) + + + + +<p> +<hr><h3><a name="pdf-math.rad"><code>math.rad (x)</code></a></h3> + + +<p> +Returns the angle <code>x</code> (given in degrees) in radians. + + + + +<p> +<hr><h3><a name="pdf-math.random"><code>math.random ([m [, n]])</code></a></h3> + + +<p> +This function is an interface to the simple +pseudo-random generator function <code>rand</code> provided by ANSI C. +(No guarantees can be given for its statistical properties.) + + +<p> +When called without arguments, +returns a uniform pseudo-random real number +in the range <em>[0,1)</em>. +When called with an integer number <code>m</code>, +<code>math.random</code> returns +a uniform pseudo-random integer in the range <em>[1, m]</em>. +When called with two integer numbers <code>m</code> and <code>n</code>, +<code>math.random</code> returns a uniform pseudo-random +integer in the range <em>[m, n]</em>. + + + + +<p> +<hr><h3><a name="pdf-math.randomseed"><code>math.randomseed (x)</code></a></h3> + + +<p> +Sets <code>x</code> as the "seed" +for the pseudo-random generator: +equal seeds produce equal sequences of numbers. + + + + +<p> +<hr><h3><a name="pdf-math.sin"><code>math.sin (x)</code></a></h3> + + +<p> +Returns the sine of <code>x</code> (assumed to be in radians). + + + + +<p> +<hr><h3><a name="pdf-math.sinh"><code>math.sinh (x)</code></a></h3> + + +<p> +Returns the hyperbolic sine of <code>x</code>. + + + + +<p> +<hr><h3><a name="pdf-math.sqrt"><code>math.sqrt (x)</code></a></h3> + + +<p> +Returns the square root of <code>x</code>. +(You can also use the expression <code>x^0.5</code> to compute this value.) + + + + +<p> +<hr><h3><a name="pdf-math.tan"><code>math.tan (x)</code></a></h3> + + +<p> +Returns the tangent of <code>x</code> (assumed to be in radians). + + + + +<p> +<hr><h3><a name="pdf-math.tanh"><code>math.tanh (x)</code></a></h3> + + +<p> +Returns the hyperbolic tangent of <code>x</code>. + + + + + + + +<h2>5.7 - <a name="5.7">Input and Output Facilities</a></h2> + +<p> +The I/O library provides two different styles for file manipulation. +The first one uses implicit file descriptors; +that is, there are operations to set a default input file and a +default output file, +and all input/output operations are over these default files. +The second style uses explicit file descriptors. + + +<p> +When using implicit file descriptors, +all operations are supplied by table <a name="pdf-io"><code>io</code></a>. +When using explicit file descriptors, +the operation <a href="#pdf-io.open"><code>io.open</code></a> returns a file descriptor +and then all operations are supplied as methods of the file descriptor. + + +<p> +The table <code>io</code> also provides +three predefined file descriptors with their usual meanings from C: +<a name="pdf-io.stdin"><code>io.stdin</code></a>, <a name="pdf-io.stdout"><code>io.stdout</code></a>, and <a name="pdf-io.stderr"><code>io.stderr</code></a>. +The I/O library never closes these files. + + +<p> +Unless otherwise stated, +all I/O functions return <b>nil</b> on failure +(plus an error message as a second result and +a system-dependent error code as a third result) +and some value different from <b>nil</b> on success. + + +<p> +<hr><h3><a name="pdf-io.close"><code>io.close ([file])</code></a></h3> + + +<p> +Equivalent to <code>file:close()</code>. +Without a <code>file</code>, closes the default output file. + + + + +<p> +<hr><h3><a name="pdf-io.flush"><code>io.flush ()</code></a></h3> + + +<p> +Equivalent to <code>file:flush</code> over the default output file. + + + + +<p> +<hr><h3><a name="pdf-io.input"><code>io.input ([file])</code></a></h3> + + +<p> +When called with a file name, it opens the named file (in text mode), +and sets its handle as the default input file. +When called with a file handle, +it simply sets this file handle as the default input file. +When called without parameters, +it returns the current default input file. + + +<p> +In case of errors this function raises the error, +instead of returning an error code. + + + + +<p> +<hr><h3><a name="pdf-io.lines"><code>io.lines ([filename])</code></a></h3> + + +<p> +Opens the given file name in read mode +and returns an iterator function that, +each time it is called, +returns a new line from the file. +Therefore, the construction + +<pre> + for line in io.lines(filename) do <em>body</em> end +</pre><p> +will iterate over all lines of the file. +When the iterator function detects the end of file, +it returns <b>nil</b> (to finish the loop) and automatically closes the file. + + +<p> +The call <code>io.lines()</code> (with no file name) is equivalent +to <code>io.input():lines()</code>; +that is, it iterates over the lines of the default input file. +In this case it does not close the file when the loop ends. + + + + +<p> +<hr><h3><a name="pdf-io.open"><code>io.open (filename [, mode])</code></a></h3> + + +<p> +This function opens a file, +in the mode specified in the string <code>mode</code>. +It returns a new file handle, +or, in case of errors, <b>nil</b> plus an error message. + + +<p> +The <code>mode</code> string can be any of the following: + +<ul> +<li><b>"r":</b> read mode (the default);</li> +<li><b>"w":</b> write mode;</li> +<li><b>"a":</b> append mode;</li> +<li><b>"r+":</b> update mode, all previous data is preserved;</li> +<li><b>"w+":</b> update mode, all previous data is erased;</li> +<li><b>"a+":</b> append update mode, previous data is preserved, + writing is only allowed at the end of file.</li> +</ul><p> +The <code>mode</code> string may also have a '<code>b</code>' at the end, +which is needed in some systems to open the file in binary mode. +This string is exactly what is used in the +standard C function <code>fopen</code>. + + + + +<p> +<hr><h3><a name="pdf-io.output"><code>io.output ([file])</code></a></h3> + + +<p> +Similar to <a href="#pdf-io.input"><code>io.input</code></a>, but operates over the default output file. + + + + +<p> +<hr><h3><a name="pdf-io.popen"><code>io.popen (prog [, mode])</code></a></h3> + + +<p> +Starts program <code>prog</code> in a separated process and returns +a file handle that you can use to read data from this program +(if <code>mode</code> is <code>"r"</code>, the default) +or to write data to this program +(if <code>mode</code> is <code>"w"</code>). + + +<p> +This function is system dependent and is not available +on all platforms. + + + + +<p> +<hr><h3><a name="pdf-io.read"><code>io.read (···)</code></a></h3> + + +<p> +Equivalent to <code>io.input():read</code>. + + + + +<p> +<hr><h3><a name="pdf-io.tmpfile"><code>io.tmpfile ()</code></a></h3> + + +<p> +Returns a handle for a temporary file. +This file is opened in update mode +and it is automatically removed when the program ends. + + + + +<p> +<hr><h3><a name="pdf-io.type"><code>io.type (obj)</code></a></h3> + + +<p> +Checks whether <code>obj</code> is a valid file handle. +Returns the string <code>"file"</code> if <code>obj</code> is an open file handle, +<code>"closed file"</code> if <code>obj</code> is a closed file handle, +or <b>nil</b> if <code>obj</code> is not a file handle. + + + + +<p> +<hr><h3><a name="pdf-io.write"><code>io.write (···)</code></a></h3> + + +<p> +Equivalent to <code>io.output():write</code>. + + + + +<p> +<hr><h3><a name="pdf-file:close"><code>file:close ()</code></a></h3> + + +<p> +Closes <code>file</code>. +Note that files are automatically closed when +their handles are garbage collected, +but that takes an unpredictable amount of time to happen. + + + + +<p> +<hr><h3><a name="pdf-file:flush"><code>file:flush ()</code></a></h3> + + +<p> +Saves any written data to <code>file</code>. + + + + +<p> +<hr><h3><a name="pdf-file:lines"><code>file:lines ()</code></a></h3> + + +<p> +Returns an iterator function that, +each time it is called, +returns a new line from the file. +Therefore, the construction + +<pre> + for line in file:lines() do <em>body</em> end +</pre><p> +will iterate over all lines of the file. +(Unlike <a href="#pdf-io.lines"><code>io.lines</code></a>, this function does not close the file +when the loop ends.) + + + + +<p> +<hr><h3><a name="pdf-file:read"><code>file:read (···)</code></a></h3> + + +<p> +Reads the file <code>file</code>, +according to the given formats, which specify what to read. +For each format, +the function returns a string (or a number) with the characters read, +or <b>nil</b> if it cannot read data with the specified format. +When called without formats, +it uses a default format that reads the entire next line +(see below). + + +<p> +The available formats are + +<ul> + +<li><b>"*n":</b> +reads a number; +this is the only format that returns a number instead of a string. +</li> + +<li><b>"*a":</b> +reads the whole file, starting at the current position. +On end of file, it returns the empty string. +</li> + +<li><b>"*l":</b> +reads the next line (skipping the end of line), +returning <b>nil</b> on end of file. +This is the default format. +</li> + +<li><b><em>number</em>:</b> +reads a string with up to this number of characters, +returning <b>nil</b> on end of file. +If number is zero, +it reads nothing and returns an empty string, +or <b>nil</b> on end of file. +</li> + +</ul> + + + +<p> +<hr><h3><a name="pdf-file:seek"><code>file:seek ([whence] [, offset])</code></a></h3> + + +<p> +Sets and gets the file position, +measured from the beginning of the file, +to the position given by <code>offset</code> plus a base +specified by the string <code>whence</code>, as follows: + +<ul> +<li><b>"set":</b> base is position 0 (beginning of the file);</li> +<li><b>"cur":</b> base is current position;</li> +<li><b>"end":</b> base is end of file;</li> +</ul><p> +In case of success, function <code>seek</code> returns the final file position, +measured in bytes from the beginning of the file. +If this function fails, it returns <b>nil</b>, +plus a string describing the error. + + +<p> +The default value for <code>whence</code> is <code>"cur"</code>, +and for <code>offset</code> is 0. +Therefore, the call <code>file:seek()</code> returns the current +file position, without changing it; +the call <code>file:seek("set")</code> sets the position to the +beginning of the file (and returns 0); +and the call <code>file:seek("end")</code> sets the position to the +end of the file, and returns its size. + + + + +<p> +<hr><h3><a name="pdf-file:setvbuf"><code>file:setvbuf (mode [, size])</code></a></h3> + + +<p> +Sets the buffering mode for an output file. +There are three available modes: + +<ul> + +<li><b>"no":</b> +no buffering; the result of any output operation appears immediately. +</li> + +<li><b>"full":</b> +full buffering; output operation is performed only +when the buffer is full (or when you explicitly <code>flush</code> the file +(see <a href="#pdf-io.flush"><code>io.flush</code></a>)). +</li> + +<li><b>"line":</b> +line buffering; output is buffered until a newline is output +or there is any input from some special files +(such as a terminal device). +</li> + +</ul><p> +For the last two cases, <code>size</code> +specifies the size of the buffer, in bytes. +The default is an appropriate size. + + + + +<p> +<hr><h3><a name="pdf-file:write"><code>file:write (···)</code></a></h3> + + +<p> +Writes the value of each of its arguments to +the <code>file</code>. +The arguments must be strings or numbers. +To write other values, +use <a href="#pdf-tostring"><code>tostring</code></a> or <a href="#pdf-string.format"><code>string.format</code></a> before <code>write</code>. + + + + + + + +<h2>5.8 - <a name="5.8">Operating System Facilities</a></h2> + +<p> +This library is implemented through table <a name="pdf-os"><code>os</code></a>. + + +<p> +<hr><h3><a name="pdf-os.clock"><code>os.clock ()</code></a></h3> + + +<p> +Returns an approximation of the amount in seconds of CPU time +used by the program. + + + + +<p> +<hr><h3><a name="pdf-os.date"><code>os.date ([format [, time]])</code></a></h3> + + +<p> +Returns a string or a table containing date and time, +formatted according to the given string <code>format</code>. + + +<p> +If the <code>time</code> argument is present, +this is the time to be formatted +(see the <a href="#pdf-os.time"><code>os.time</code></a> function for a description of this value). +Otherwise, <code>date</code> formats the current time. + + +<p> +If <code>format</code> starts with '<code>!</code>', +then the date is formatted in Coordinated Universal Time. +After this optional character, +if <code>format</code> is the string "<code>*t</code>", +then <code>date</code> returns a table with the following fields: +<code>year</code> (four digits), <code>month</code> (1--12), <code>day</code> (1--31), +<code>hour</code> (0--23), <code>min</code> (0--59), <code>sec</code> (0--61), +<code>wday</code> (weekday, Sunday is 1), +<code>yday</code> (day of the year), +and <code>isdst</code> (daylight saving flag, a boolean). + + +<p> +If <code>format</code> is not "<code>*t</code>", +then <code>date</code> returns the date as a string, +formatted according to the same rules as the C function <code>strftime</code>. + + +<p> +When called without arguments, +<code>date</code> returns a reasonable date and time representation that depends on +the host system and on the current locale +(that is, <code>os.date()</code> is equivalent to <code>os.date("%c")</code>). + + + + +<p> +<hr><h3><a name="pdf-os.difftime"><code>os.difftime (t2, t1)</code></a></h3> + + +<p> +Returns the number of seconds from time <code>t1</code> to time <code>t2</code>. +In POSIX, Windows, and some other systems, +this value is exactly <code>t2</code><em>-</em><code>t1</code>. + + + + +<p> +<hr><h3><a name="pdf-os.execute"><code>os.execute ([command])</code></a></h3> + + +<p> +This function is equivalent to the C function <code>system</code>. +It passes <code>command</code> to be executed by an operating system shell. +It returns a status code, which is system-dependent. +If <code>command</code> is absent, then it returns nonzero if a shell is available +and zero otherwise. + + + + +<p> +<hr><h3><a name="pdf-os.exit"><code>os.exit ([code])</code></a></h3> + + +<p> +Calls the C function <code>exit</code>, +with an optional <code>code</code>, +to terminate the host program. +The default value for <code>code</code> is the success code. + + + + +<p> +<hr><h3><a name="pdf-os.getenv"><code>os.getenv (varname)</code></a></h3> + + +<p> +Returns the value of the process environment variable <code>varname</code>, +or <b>nil</b> if the variable is not defined. + + + + +<p> +<hr><h3><a name="pdf-os.remove"><code>os.remove (filename)</code></a></h3> + + +<p> +Deletes the file or directory with the given name. +Directories must be empty to be removed. +If this function fails, it returns <b>nil</b>, +plus a string describing the error. + + + + +<p> +<hr><h3><a name="pdf-os.rename"><code>os.rename (oldname, newname)</code></a></h3> + + +<p> +Renames file or directory named <code>oldname</code> to <code>newname</code>. +If this function fails, it returns <b>nil</b>, +plus a string describing the error. + + + + +<p> +<hr><h3><a name="pdf-os.setlocale"><code>os.setlocale (locale [, category])</code></a></h3> + + +<p> +Sets the current locale of the program. +<code>locale</code> is a string specifying a locale; +<code>category</code> is an optional string describing which category to change: +<code>"all"</code>, <code>"collate"</code>, <code>"ctype"</code>, +<code>"monetary"</code>, <code>"numeric"</code>, or <code>"time"</code>; +the default category is <code>"all"</code>. +The function returns the name of the new locale, +or <b>nil</b> if the request cannot be honored. + + +<p> +If <code>locale</code> is the empty string, +the current locale is set to an implementation-defined native locale. +If <code>locale</code> is the string "<code>C</code>", +the current locale is set to the standard C locale. + + +<p> +When called with <b>nil</b> as the first argument, +this function only returns the name of the current locale +for the given category. + + + + +<p> +<hr><h3><a name="pdf-os.time"><code>os.time ([table])</code></a></h3> + + +<p> +Returns the current time when called without arguments, +or a time representing the date and time specified by the given table. +This table must have fields <code>year</code>, <code>month</code>, and <code>day</code>, +and may have fields <code>hour</code>, <code>min</code>, <code>sec</code>, and <code>isdst</code> +(for a description of these fields, see the <a href="#pdf-os.date"><code>os.date</code></a> function). + + +<p> +The returned value is a number, whose meaning depends on your system. +In POSIX, Windows, and some other systems, this number counts the number +of seconds since some given start time (the "epoch"). +In other systems, the meaning is not specified, +and the number returned by <code>time</code> can be used only as an argument to +<code>date</code> and <code>difftime</code>. + + + + +<p> +<hr><h3><a name="pdf-os.tmpname"><code>os.tmpname ()</code></a></h3> + + +<p> +Returns a string with a file name that can +be used for a temporary file. +The file must be explicitly opened before its use +and explicitly removed when no longer needed. + + + + + + + +<h2>5.9 - <a name="5.9">The Debug Library</a></h2> + +<p> +This library provides +the functionality of the debug interface to Lua programs. +You should exert care when using this library. +The functions provided here should be used exclusively for debugging +and similar tasks, such as profiling. +Please resist the temptation to use them as a +usual programming tool: +they can be very slow. +Moreover, several of these functions +violate some assumptions about Lua code +(e.g., that variables local to a function +cannot be accessed from outside or +that userdata metatables cannot be changed by Lua code) +and therefore can compromise otherwise secure code. + + +<p> +All functions in this library are provided +inside the <a name="pdf-debug"><code>debug</code></a> table. +All functions that operate over a thread +have an optional first argument which is the +thread to operate over. +The default is always the current thread. + + +<p> +<hr><h3><a name="pdf-debug.debug"><code>debug.debug ()</code></a></h3> + + +<p> +Enters an interactive mode with the user, +running each string that the user enters. +Using simple commands and other debug facilities, +the user can inspect global and local variables, +change their values, evaluate expressions, and so on. +A line containing only the word <code>cont</code> finishes this function, +so that the caller continues its execution. + + +<p> +Note that commands for <code>debug.debug</code> are not lexically nested +within any function, and so have no direct access to local variables. + + + + +<p> +<hr><h3><a name="pdf-debug.getfenv"><code>debug.getfenv (o)</code></a></h3> +Returns the environment of object <code>o</code>. + + + + +<p> +<hr><h3><a name="pdf-debug.gethook"><code>debug.gethook ([thread])</code></a></h3> + + +<p> +Returns the current hook settings of the thread, as three values: +the current hook function, the current hook mask, +and the current hook count +(as set by the <a href="#pdf-debug.sethook"><code>debug.sethook</code></a> function). + + + + +<p> +<hr><h3><a name="pdf-debug.getinfo"><code>debug.getinfo ([thread,] function [, what])</code></a></h3> + + +<p> +Returns a table with information about a function. +You can give the function directly, +or you can give a number as the value of <code>function</code>, +which means the function running at level <code>function</code> of the call stack +of the given thread: +level 0 is the current function (<code>getinfo</code> itself); +level 1 is the function that called <code>getinfo</code>; +and so on. +If <code>function</code> is a number larger than the number of active functions, +then <code>getinfo</code> returns <b>nil</b>. + + +<p> +The returned table may contain all the fields returned by <a href="#lua_getinfo"><code>lua_getinfo</code></a>, +with the string <code>what</code> describing which fields to fill in. +The default for <code>what</code> is to get all information available, +except the table of valid lines. +If present, +the option '<code>f</code>' +adds a field named <code>func</code> with the function itself. +If present, +the option '<code>L</code>' +adds a field named <code>activelines</code> with the table of +valid lines. + + +<p> +For instance, the expression <code>debug.getinfo(1,"n").name</code> returns +a table with a name for the current function, +if a reasonable name can be found, +and the expression <code>debug.getinfo(print)</code> +returns a table with all available information +about the <a href="#pdf-print"><code>print</code></a> function. + + + + +<p> +<hr><h3><a name="pdf-debug.getlocal"><code>debug.getlocal ([thread,] level, local)</code></a></h3> + + +<p> +This function returns the name and the value of the local variable +with index <code>local</code> of the function at level <code>level</code> of the stack. +(The first parameter or local variable has index 1, and so on, +until the last active local variable.) +The function returns <b>nil</b> if there is no local +variable with the given index, +and raises an error when called with a <code>level</code> out of range. +(You can call <a href="#pdf-debug.getinfo"><code>debug.getinfo</code></a> to check whether the level is valid.) + + +<p> +Variable names starting with '<code>(</code>' (open parentheses) +represent internal variables +(loop control variables, temporaries, and C function locals). + + + + +<p> +<hr><h3><a name="pdf-debug.getmetatable"><code>debug.getmetatable (object)</code></a></h3> + + +<p> +Returns the metatable of the given <code>object</code> +or <b>nil</b> if it does not have a metatable. + + + + +<p> +<hr><h3><a name="pdf-debug.getregistry"><code>debug.getregistry ()</code></a></h3> + + +<p> +Returns the registry table (see <a href="#3.5">§3.5</a>). + + + + +<p> +<hr><h3><a name="pdf-debug.getupvalue"><code>debug.getupvalue (func, up)</code></a></h3> + + +<p> +This function returns the name and the value of the upvalue +with index <code>up</code> of the function <code>func</code>. +The function returns <b>nil</b> if there is no upvalue with the given index. + + + + +<p> +<hr><h3><a name="pdf-debug.setfenv"><code>debug.setfenv (object, table)</code></a></h3> + + +<p> +Sets the environment of the given <code>object</code> to the given <code>table</code>. +Returns <code>object</code>. + + + + +<p> +<hr><h3><a name="pdf-debug.sethook"><code>debug.sethook ([thread,] hook, mask [, count])</code></a></h3> + + +<p> +Sets the given function as a hook. +The string <code>mask</code> and the number <code>count</code> describe +when the hook will be called. +The string mask may have the following characters, +with the given meaning: + +<ul> +<li><b><code>"c"</code>:</b> the hook is called every time Lua calls a function;</li> +<li><b><code>"r"</code>:</b> the hook is called every time Lua returns from a function;</li> +<li><b><code>"l"</code>:</b> the hook is called every time Lua enters a new line of code.</li> +</ul><p> +With a <code>count</code> different from zero, +the hook is called after every <code>count</code> instructions. + + +<p> +When called without arguments, +<a href="#pdf-debug.sethook"><code>debug.sethook</code></a> turns off the hook. + + +<p> +When the hook is called, its first parameter is a string +describing the event that has triggered its call: +<code>"call"</code>, <code>"return"</code> (or <code>"tail return"</code>), +<code>"line"</code>, and <code>"count"</code>. +For line events, +the hook also gets the new line number as its second parameter. +Inside a hook, +you can call <code>getinfo</code> with level 2 to get more information about +the running function +(level 0 is the <code>getinfo</code> function, +and level 1 is the hook function), +unless the event is <code>"tail return"</code>. +In this case, Lua is only simulating the return, +and a call to <code>getinfo</code> will return invalid data. + + + + +<p> +<hr><h3><a name="pdf-debug.setlocal"><code>debug.setlocal ([thread,] level, local, value)</code></a></h3> + + +<p> +This function assigns the value <code>value</code> to the local variable +with index <code>local</code> of the function at level <code>level</code> of the stack. +The function returns <b>nil</b> if there is no local +variable with the given index, +and raises an error when called with a <code>level</code> out of range. +(You can call <code>getinfo</code> to check whether the level is valid.) +Otherwise, it returns the name of the local variable. + + + + +<p> +<hr><h3><a name="pdf-debug.setmetatable"><code>debug.setmetatable (object, table)</code></a></h3> + + +<p> +Sets the metatable for the given <code>object</code> to the given <code>table</code> +(which can be <b>nil</b>). + + + + +<p> +<hr><h3><a name="pdf-debug.setupvalue"><code>debug.setupvalue (func, up, value)</code></a></h3> + + +<p> +This function assigns the value <code>value</code> to the upvalue +with index <code>up</code> of the function <code>func</code>. +The function returns <b>nil</b> if there is no upvalue +with the given index. +Otherwise, it returns the name of the upvalue. + + + + +<p> +<hr><h3><a name="pdf-debug.traceback"><code>debug.traceback ([thread,] [message] [, level])</code></a></h3> + + +<p> +Returns a string with a traceback of the call stack. +An optional <code>message</code> string is appended +at the beginning of the traceback. +An optional <code>level</code> number tells at which level +to start the traceback +(default is 1, the function calling <code>traceback</code>). + + + + + + + +<h1>6 - <a name="6">Lua Stand-alone</a></h1> + +<p> +Although Lua has been designed as an extension language, +to be embedded in a host C program, +it is also frequently used as a stand-alone language. +An interpreter for Lua as a stand-alone language, +called simply <code>lua</code>, +is provided with the standard distribution. +The stand-alone interpreter includes +all standard libraries, including the debug library. +Its usage is: + +<pre> + lua [options] [script [args]] +</pre><p> +The options are: + +<ul> +<li><b><code>-e <em>stat</em></code>:</b> executes string <em>stat</em>;</li> +<li><b><code>-l <em>mod</em></code>:</b> "requires" <em>mod</em>;</li> +<li><b><code>-i</code>:</b> enters interactive mode after running <em>script</em>;</li> +<li><b><code>-v</code>:</b> prints version information;</li> +<li><b><code>--</code>:</b> stops handling options;</li> +<li><b><code>-</code>:</b> executes <code>stdin</code> as a file and stops handling options.</li> +</ul><p> +After handling its options, <code>lua</code> runs the given <em>script</em>, +passing to it the given <em>args</em> as string arguments. +When called without arguments, +<code>lua</code> behaves as <code>lua -v -i</code> +when the standard input (<code>stdin</code>) is a terminal, +and as <code>lua -</code> otherwise. + + +<p> +Before running any argument, +the interpreter checks for an environment variable <a name="pdf-LUA_INIT"><code>LUA_INIT</code></a>. +If its format is <code>@<em>filename</em></code>, +then <code>lua</code> executes the file. +Otherwise, <code>lua</code> executes the string itself. + + +<p> +All options are handled in order, except <code>-i</code>. +For instance, an invocation like + +<pre> + $ lua -e'a=1' -e 'print(a)' script.lua +</pre><p> +will first set <code>a</code> to 1, then print the value of <code>a</code> (which is '<code>1</code>'), +and finally run the file <code>script.lua</code> with no arguments. +(Here <code>$</code> is the shell prompt. Your prompt may be different.) + + +<p> +Before starting to run the script, +<code>lua</code> collects all arguments in the command line +in a global table called <code>arg</code>. +The script name is stored at index 0, +the first argument after the script name goes to index 1, +and so on. +Any arguments before the script name +(that is, the interpreter name plus the options) +go to negative indices. +For instance, in the call + +<pre> + $ lua -la b.lua t1 t2 +</pre><p> +the interpreter first runs the file <code>a.lua</code>, +then creates a table + +<pre> + arg = { [-2] = "lua", [-1] = "-la", + [0] = "b.lua", + [1] = "t1", [2] = "t2" } +</pre><p> +and finally runs the file <code>b.lua</code>. +The script is called with <code>arg[1]</code>, <code>arg[2]</code>, ··· +as arguments; +it can also access these arguments with the vararg expression '<code>...</code>'. + + +<p> +In interactive mode, +if you write an incomplete statement, +the interpreter waits for its completion +by issuing a different prompt. + + +<p> +If the global variable <a name="pdf-_PROMPT"><code>_PROMPT</code></a> contains a string, +then its value is used as the prompt. +Similarly, if the global variable <a name="pdf-_PROMPT2"><code>_PROMPT2</code></a> contains a string, +its value is used as the secondary prompt +(issued during incomplete statements). +Therefore, both prompts can be changed directly on the command line +or in any Lua programs by assigning to <code>_PROMPT</code>. +See the next example: + +<pre> + $ lua -e"_PROMPT='myprompt> '" -i +</pre><p> +(The outer pair of quotes is for the shell, +the inner pair is for Lua.) +Note the use of <code>-i</code> to enter interactive mode; +otherwise, +the program would just end silently +right after the assignment to <code>_PROMPT</code>. + + +<p> +To allow the use of Lua as a +script interpreter in Unix systems, +the stand-alone interpreter skips +the first line of a chunk if it starts with <code>#</code>. +Therefore, Lua scripts can be made into executable programs +by using <code>chmod +x</code> and the <code>#!</code> form, +as in + +<pre> + #!/usr/local/bin/lua +</pre><p> +(Of course, +the location of the Lua interpreter may be different in your machine. +If <code>lua</code> is in your <code>PATH</code>, +then + +<pre> + #!/usr/bin/env lua +</pre><p> +is a more portable solution.) + + + +<h1>7 - <a name="7">Incompatibilities with the Previous Version</a></h1> + +<p> +Here we list the incompatibilities that you may find when moving a program +from Lua 5.0 to Lua 5.1. +You can avoid most of the incompatibilities compiling Lua with +appropriate options (see file <code>luaconf.h</code>). +However, +all these compatibility options will be removed in the next version of Lua. + + + +<h2>7.1 - <a name="7.1">Changes in the Language</a></h2> +<ul> + +<li> +The vararg system changed from the pseudo-argument <code>arg</code> with a +table with the extra arguments to the vararg expression. +(See compile-time option <code>LUA_COMPAT_VARARG</code> in <code>luaconf.h</code>.) +</li> + +<li> +There was a subtle change in the scope of the implicit +variables of the <b>for</b> statement and for the <b>repeat</b> statement. +</li> + +<li> +The long string/long comment syntax (<code>[[<em>string</em>]]</code>) +does not allow nesting. +You can use the new syntax (<code>[=[<em>string</em>]=]</code>) in these cases. +(See compile-time option <code>LUA_COMPAT_LSTR</code> in <code>luaconf.h</code>.) +</li> + +</ul> + + + + +<h2>7.2 - <a name="7.2">Changes in the Libraries</a></h2> +<ul> + +<li> +Function <code>string.gfind</code> was renamed <a href="#pdf-string.gmatch"><code>string.gmatch</code></a>. +(See compile-time option <code>LUA_COMPAT_GFIND</code> in <code>luaconf.h</code>.) +</li> + +<li> +When <a href="#pdf-string.gsub"><code>string.gsub</code></a> is called with a function as its +third argument, +whenever this function returns <b>nil</b> or <b>false</b> the +replacement string is the whole match, +instead of the empty string. +</li> + +<li> +Function <code>table.setn</code> was deprecated. +Function <code>table.getn</code> corresponds +to the new length operator (<code>#</code>); +use the operator instead of the function. +(See compile-time option <code>LUA_COMPAT_GETN</code> in <code>luaconf.h</code>.) +</li> + +<li> +Function <code>loadlib</code> was renamed <a href="#pdf-package.loadlib"><code>package.loadlib</code></a>. +(See compile-time option <code>LUA_COMPAT_LOADLIB</code> in <code>luaconf.h</code>.) +</li> + +<li> +Function <code>math.mod</code> was renamed <a href="#pdf-math.fmod"><code>math.fmod</code></a>. +(See compile-time option <code>LUA_COMPAT_MOD</code> in <code>luaconf.h</code>.) +</li> + +<li> +Functions <code>table.foreach</code> and <code>table.foreachi</code> are deprecated. +You can use a for loop with <code>pairs</code> or <code>ipairs</code> instead. +</li> + +<li> +There were substantial changes in function <a href="#pdf-require"><code>require</code></a> due to +the new module system. +However, the new behavior is mostly compatible with the old, +but <code>require</code> gets the path from <a href="#pdf-package.path"><code>package.path</code></a> instead +of from <code>LUA_PATH</code>. +</li> + +<li> +Function <a href="#pdf-collectgarbage"><code>collectgarbage</code></a> has different arguments. +Function <code>gcinfo</code> is deprecated; +use <code>collectgarbage("count")</code> instead. +</li> + +</ul> + + + + +<h2>7.3 - <a name="7.3">Changes in the API</a></h2> +<ul> + +<li> +The <code>luaopen_*</code> functions (to open libraries) +cannot be called directly, +like a regular C function. +They must be called through Lua, +like a Lua function. +</li> + +<li> +Function <code>lua_open</code> was replaced by <a href="#lua_newstate"><code>lua_newstate</code></a> to +allow the user to set a memory-allocation function. +You can use <a href="#luaL_newstate"><code>luaL_newstate</code></a> from the standard library to +create a state with a standard allocation function +(based on <code>realloc</code>). +</li> + +<li> +Functions <code>luaL_getn</code> and <code>luaL_setn</code> +(from the auxiliary library) are deprecated. +Use <a href="#lua_objlen"><code>lua_objlen</code></a> instead of <code>luaL_getn</code> +and nothing instead of <code>luaL_setn</code>. +</li> + +<li> +Function <code>luaL_openlib</code> was replaced by <a href="#luaL_register"><code>luaL_register</code></a>. +</li> + +<li> +Function <code>luaL_checkudata</code> now throws an error when the given value +is not a userdata of the expected type. +(In Lua 5.0 it returned <code>NULL</code>.) +</li> + +</ul> + + + + +<h1>8 - <a name="8">The Complete Syntax of Lua</a></h1> + +<p> +Here is the complete syntax of Lua in extended BNF. +(It does not describe operator precedences.) + + + + +<pre> + + chunk ::= {stat [`<b>;</b>´]} [laststat [`<b>;</b>´]] + + block ::= chunk + + stat ::= varlist `<b>=</b>´ explist | + functioncall | + <b>do</b> block <b>end</b> | + <b>while</b> exp <b>do</b> block <b>end</b> | + <b>repeat</b> block <b>until</b> exp | + <b>if</b> exp <b>then</b> block {<b>elseif</b> exp <b>then</b> block} [<b>else</b> block] <b>end</b> | + <b>for</b> Name `<b>=</b>´ exp `<b>,</b>´ exp [`<b>,</b>´ exp] <b>do</b> block <b>end</b> | + <b>for</b> namelist <b>in</b> explist <b>do</b> block <b>end</b> | + <b>function</b> funcname funcbody | + <b>local</b> <b>function</b> Name funcbody | + <b>local</b> namelist [`<b>=</b>´ explist] + + laststat ::= <b>return</b> [explist] | <b>break</b> + + funcname ::= Name {`<b>.</b>´ Name} [`<b>:</b>´ Name] + + varlist ::= var {`<b>,</b>´ var} + + var ::= Name | prefixexp `<b>[</b>´ exp `<b>]</b>´ | prefixexp `<b>.</b>´ Name + + namelist ::= Name {`<b>,</b>´ Name} + + explist ::= {exp `<b>,</b>´} exp + + exp ::= <b>nil</b> | <b>false</b> | <b>true</b> | Number | String | `<b>...</b>´ | function | + prefixexp | tableconstructor | exp binop exp | unop exp + + prefixexp ::= var | functioncall | `<b>(</b>´ exp `<b>)</b>´ + + functioncall ::= prefixexp args | prefixexp `<b>:</b>´ Name args + + args ::= `<b>(</b>´ [explist] `<b>)</b>´ | tableconstructor | String + + function ::= <b>function</b> funcbody + + funcbody ::= `<b>(</b>´ [parlist] `<b>)</b>´ block <b>end</b> + + parlist ::= namelist [`<b>,</b>´ `<b>...</b>´] | `<b>...</b>´ + + tableconstructor ::= `<b>{</b>´ [fieldlist] `<b>}</b>´ + + fieldlist ::= field {fieldsep field} [fieldsep] + + field ::= `<b>[</b>´ exp `<b>]</b>´ `<b>=</b>´ exp | Name `<b>=</b>´ exp | exp + + fieldsep ::= `<b>,</b>´ | `<b>;</b>´ + + binop ::= `<b>+</b>´ | `<b>-</b>´ | `<b>*</b>´ | `<b>/</b>´ | `<b>^</b>´ | `<b>%</b>´ | `<b>..</b>´ | + `<b><</b>´ | `<b><=</b>´ | `<b>></b>´ | `<b>>=</b>´ | `<b>==</b>´ | `<b>~=</b>´ | + <b>and</b> | <b>or</b> + + unop ::= `<b>-</b>´ | <b>not</b> | `<b>#</b>´ + +</pre> + +<p> + + + + + + + +<HR> +<SMALL> +Last update: +Fri Jan 18 22:32:24 BRST 2008 +</SMALL> +<!-- +Last change: revised for Lua 5.1.3 +--> + +</body></html> + diff --git a/contrib/syslinux-4.02/com32/lua/doc/readme.html b/contrib/syslinux-4.02/com32/lua/doc/readme.html new file mode 100644 index 0000000..972fadd --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/doc/readme.html @@ -0,0 +1,40 @@ +<HTML> +<HEAD> +<TITLE>Lua documentation</TITLE> +<LINK REL="stylesheet" TYPE="text/css" HREF="lua.css"> +</HEAD> + +<BODY> + +<HR> +<H1> +<A HREF="http://www.lua.org/"><IMG SRC="logo.gif" ALT="Lua" BORDER=0></A> +Documentation +</H1> + +This is the documentation included in the source distribution of Lua 5.1.3. + +<UL> +<LI><A HREF="contents.html">Reference manual</A> +<LI><A HREF="lua.html">lua man page</A> +<LI><A HREF="luac.html">luac man page</A> +<LI><A HREF="../README">lua/README</A> +<LI><A HREF="../etc/README">lua/etc/README</A> +<LI><A HREF="../test/README">lua/test/README</A> +</UL> + +Lua's +<A HREF="http://www.lua.org/">official web site</A> +contains updated documentation, +especially the +<A HREF="http://www.lua.org/manual/5.1/">reference manual</A>. +<P> + +<HR> +<SMALL> +Last update: +Wed Dec 19 13:59:14 BRST 2007 +</SMALL> + +</BODY> +</HTML> diff --git a/contrib/syslinux-4.02/com32/lua/doc/syslinux.asc b/contrib/syslinux-4.02/com32/lua/doc/syslinux.asc new file mode 100644 index 0000000..64dc18c --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/doc/syslinux.asc @@ -0,0 +1,286 @@ +Syslinux LUA User Guide +======================= +Marcel Ritter <Marcel.Ritter@rrze.uni-erlangen.de> + +Invocation +---------- + +Running +lua.c32+ only results in an interactive shell. +...................................................... +KERNEL lua.c32 +...................................................... + +By using the +APPEND+ parameter you can specify a lua +script to be executed: +...................................................... +KERNEL lua.c32 +APPEND /testit.lua +...................................................... + +Modules +------- + +SYSLINUX +~~~~~~~~ + +.syslinux.version() + +Returns version string + +.syslinux.derivative() + +Returns running Syslinux's derivative (ISOLINUX, PXELINUX or SYSLINUX). +See com32/lua/test/syslinux-derivative.lua for an example. + +.syslinux.sleep(s) + +Sleep for +s+ seconds + +.syslinux.msleep(ms) + +Sleep for +ms+ milliseconds + +.run_command(command) + +Execute syslinux command line +command+. + +_Example_: +...................................................... + syslinux.run_command("memdisk initrd=/dos/BIOS/FSC-P7935-108.img raw") +...................................................... + +.run_default() + +FIXME + +.local_boot() + +FIXME + +.final_cleanup() + +FIXME + +.boot_linux(kernel, cmdline, [mem_limit], [videomode]) + +FIXME + +.run_kernel_image(kernel, cmdline, ipappend_flags, type) + +FIXME + +.loadfile(filname) + +Load file +filename+ (via TFTP) + +.filesize(file) + +Return size of +file+ (loaded by loadfile()) + +.filename(file) + +Return name of +file+ (loaded by loadfile()) + +.in itramfs_init() + +Return empty initramfs object + +.initramfs_load_archive(initramfs, filename) + +Load contents of +filename+ into +initramfs+. Initialize ++initramfs+ with initramfs_init() before use. + +.initramfs_add_file(initramfs, file) + +Adds +file+ to +initramfs+. +initramfs+ needs to be +initialized, +file+ has been loaded by loadfile(). + +_Example_: +...................................................... + -- get nice output + printf = function(s,...) + return io.write(s:format(...)) + end -- function + + kernel = syslinux.loadfile("/SuSE-11.1/x86_64/linux") + + printf("Filename/size: %s %d\n", syslinux.filename(kernel), syslinux.filesize(kernel)) + + initrd = syslinux.loadfile("/SuSE-11.1/x86_64/initrd") + + printf("Filename/size: %s %d\n", syslinux.filename(initrd), syslinux.filesize(initrd)) + + initrd = syslinux.initramfs_init() + syslinux.initramfs_load_archive(initrd, "/SuSE-11.1/x86_64/initrd"); + + syslinux.boot_it(kernel, initrd, "init=/bin/bash") + + syslinux.sleep(20) + +...................................................... + + + +DMI +~~~ + +.dmi_supported() + +Returns +true+ if DMI is supported on machine, +false+ otherwise. + +.dmi_gettable() + +Returns a list if key-value pairs. The key is one of the DMI property strings: +FIXME list + +_Example_: +...................................................... + if (dmi.supported()) then + + dmitable = dmi.gettable() + + for k,v in pairs(dmitable) do + print(k, v) + end + + print(dmitable["system.manufacturer"]) + print(dmitable["system.product_name"]) + print(dmitable["bios.bios_revision"]) + + if ( string.match(dmitable["system.product_name"], "ESPRIMO P7935") ) then + print("Matches") + syslinux.run_command("memdisk initrd=/dos/BIOS/FSC-P7935-108.img raw") + else + print("Does not match") + syslinux.run_command("memdisk initrd=/dos/BIOS/FSC-P7935-108.img raw") + end + + end + +...................................................... + + +PCI +~~~ + +.pci_getinfo() + +Return list of value pairs (device_index, device) of all PCI devices. + +.pci_getidlist(filename) + +Load a tab separated list of PCI IDs and their description. +Sample files can be found here: http://pciids.sourceforge.net/ + + +_Example_: +...................................................... +-- get nice output +printf = function(s,...) + return io.write(s:format(...)) + end + +-- get device info +pciinfo = pci.getinfo() + +-- get plain text device description +pciids = pci.getidlist("/pci.ids") + +-- list all pci busses +for dind,device in pairs(pciinfo) do + + -- search for device description + search = string.format("%04x%04x", device['vendor'], device['product']) + + printf(" %04x:%04x:%04x:%04x = ", device['vendor'], device['product'], + device['sub_vendor'], device['sub_product']) + + if ( pciids[search] ) then + printf("%s\n", pciids[search]) + else + printf("Unknown\n") + end +end + +-- print(pciids["8086"]) +-- print(pciids["10543009"]) +-- print(pciids["00700003"]) +-- print(pciids["0070e817"]) +-- print(pciids["1002437a1002437a"]) +...................................................... + + +VESA +~~~~ + +.getmodes() + +Return list of available VESA modes. + +_Example_: +...................................................... + -- get nice output + printf = function(s,...) + return io.write(s:format(...)) + end + + -- list available vesa modes + -- only one supported right now, not of much use + modes = vesa.getmodes() + + for mind,mode in pairs(modes) do + printf("%04x: %dx%dx%d\n", mode['mode'], mode['hres'], mode['vres'], mode['bpp']) + end +...................................................... + + +.setmode() + +Set (only currently supported) VESA mode. + +.load_background(filename) + +Load +filename+ from TFTP, and use it as background image. + +_Example_: +...................................................... + -- get nice output + printf = function(s,...) + return io.write(s:format(...)) + end + + -- lets go to graphics land + vesa.setmode() + + printf("Hello World! - VESA mode") + + -- some text to display "typing style" + textline=[[ + From syslinux GSOC 2009 home page: + + Finish the Lua engine + + We already have a Lua interpreter integrated with the Syslinux build. However, right now it is not very useful. We need to create a set of bindings to the Syslinux functionality, and have an array of documentation and examples so users can use them. + + This is not a documentation project, but the documentation deliverable will be particularly important for this one, since the intended target is system administrators, not developers. + ]] + + + -- do display loop + -- keep in mind: background change will not erase text! + while ( true ) do + + vesa.load_background("/background1.jpg") + + syslinux.sleep(1) + + for i = 1, #textline do + local c = textline:sub(i,i) + printf("%s", c) + syslinux.msleep(200) + end + + syslinux.sleep(10) + +...................................................... + diff --git a/contrib/syslinux-4.02/com32/lua/etc/Makefile b/contrib/syslinux-4.02/com32/lua/etc/Makefile new file mode 100644 index 0000000..6d00008 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/etc/Makefile @@ -0,0 +1,44 @@ +# makefile for Lua etc + +TOP= .. +LIB= $(TOP)/src +INC= $(TOP)/src +BIN= $(TOP)/src +SRC= $(TOP)/src +TST= $(TOP)/test + +CC= gcc +CFLAGS= -O2 -Wall -I$(INC) $(MYCFLAGS) +MYCFLAGS= +MYLDFLAGS= -Wl,-E +MYLIBS= -lm +#MYLIBS= -lm -Wl,-E -ldl -lreadline -lhistory -lncurses +RM= rm -f + +default: + @echo 'Please choose a target: min noparser one strict clean' + +min: min.c + $(CC) $(CFLAGS) $@.c -L$(LIB) -llua $(MYLIBS) + echo 'print"Hello there!"' | ./a.out + +noparser: noparser.o + $(CC) noparser.o $(SRC)/lua.o -L$(LIB) -llua $(MYLIBS) + $(BIN)/luac $(TST)/hello.lua + -./a.out luac.out + -./a.out -e'a=1' + +one: + $(CC) $(CFLAGS) all.c $(MYLIBS) + ./a.out $(TST)/hello.lua + +strict: + -$(BIN)/lua -e 'print(a);b=2' + -$(BIN)/lua -lstrict -e 'print(a)' + -$(BIN)/lua -e 'function f() b=2 end f()' + -$(BIN)/lua -lstrict -e 'function f() b=2 end f()' + +clean: + $(RM) a.out core core.* *.o luac.out + +.PHONY: default min noparser one strict clean diff --git a/contrib/syslinux-4.02/com32/lua/etc/README b/contrib/syslinux-4.02/com32/lua/etc/README new file mode 100644 index 0000000..5149fc9 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/etc/README @@ -0,0 +1,37 @@ +This directory contains some useful files and code. +Unlike the code in ../src, everything here is in the public domain. + +If any of the makes fail, you're probably not using the same libraries +used to build Lua. Set MYLIBS in Makefile accordingly. + +all.c + Full Lua interpreter in a single file. + Do "make one" for a demo. + +lua.hpp + Lua header files for C++ using 'extern "C"'. + +lua.ico + A Lua icon for Windows (and web sites: save as favicon.ico). + Drawn by hand by Markus Gritsch <gritsch@iue.tuwien.ac.at>. + +lua.pc + pkg-config data for Lua + +luavs.bat + Script to build Lua under "Visual Studio .NET Command Prompt". + Run it from the toplevel as etc\luavs.bat. + +min.c + A minimal Lua interpreter. + Good for learning and for starting your own. + Do "make min" for a demo. + +noparser.c + Linking with noparser.o avoids loading the parsing modules in lualib.a. + Do "make noparser" for a demo. + +strict.lua + Traps uses of undeclared global variables. + Do "make strict" for a demo. + diff --git a/contrib/syslinux-4.02/com32/lua/etc/all.c b/contrib/syslinux-4.02/com32/lua/etc/all.c new file mode 100644 index 0000000..dab68fa --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/etc/all.c @@ -0,0 +1,38 @@ +/* +* all.c -- Lua core, libraries and interpreter in a single file +*/ + +#define luaall_c + +#include "lapi.c" +#include "lcode.c" +#include "ldebug.c" +#include "ldo.c" +#include "ldump.c" +#include "lfunc.c" +#include "lgc.c" +#include "llex.c" +#include "lmem.c" +#include "lobject.c" +#include "lopcodes.c" +#include "lparser.c" +#include "lstate.c" +#include "lstring.c" +#include "ltable.c" +#include "ltm.c" +#include "lundump.c" +#include "lvm.c" +#include "lzio.c" + +#include "lauxlib.c" +#include "lbaselib.c" +#include "ldblib.c" +#include "liolib.c" +#include "linit.c" +#include "lmathlib.c" +#include "loadlib.c" +#include "loslib.c" +#include "lstrlib.c" +#include "ltablib.c" + +#include "lua.c" diff --git a/contrib/syslinux-4.02/com32/lua/etc/lua.hpp b/contrib/syslinux-4.02/com32/lua/etc/lua.hpp new file mode 100644 index 0000000..ec417f5 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/etc/lua.hpp @@ -0,0 +1,9 @@ +// lua.hpp +// Lua header files for C++ +// <<extern "C">> not supplied automatically because Lua also compiles as C++ + +extern "C" { +#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" +} diff --git a/contrib/syslinux-4.02/com32/lua/etc/lua.ico b/contrib/syslinux-4.02/com32/lua/etc/lua.ico Binary files differnew file mode 100644 index 0000000..ccbabc4 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/etc/lua.ico diff --git a/contrib/syslinux-4.02/com32/lua/etc/lua.pc b/contrib/syslinux-4.02/com32/lua/etc/lua.pc new file mode 100644 index 0000000..19a5c91 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/etc/lua.pc @@ -0,0 +1,31 @@ +# lua.pc -- pkg-config data for Lua + +# vars from install Makefile + +# grep '^V=' ../Makefile +V= 5.1 +# grep '^R=' ../Makefile +R= 5.1.3 + +# grep '^INSTALL_.*=' ../Makefile | sed 's/INSTALL_TOP/prefix/' +prefix= /usr/local +INSTALL_BIN= ${prefix}/bin +INSTALL_INC= ${prefix}/include +INSTALL_LIB= ${prefix}/lib +INSTALL_MAN= ${prefix}/man/man1 +INSTALL_LMOD= ${prefix}/share/lua/${V} +INSTALL_CMOD= ${prefix}/lib/lua/${V} + +# canonical vars +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: Lua +Description: An Extensible Extension Language +Version: ${R} +Requires: +Libs: -L${libdir} -llua -lm +Cflags: -I${includedir} + +# (end of lua.pc) diff --git a/contrib/syslinux-4.02/com32/lua/etc/luavs.bat b/contrib/syslinux-4.02/com32/lua/etc/luavs.bat new file mode 100644 index 0000000..08c2bed --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/etc/luavs.bat @@ -0,0 +1,28 @@ +@rem Script to build Lua under "Visual Studio .NET Command Prompt".
+@rem Do not run from this directory; run it from the toplevel: etc\luavs.bat .
+@rem It creates lua51.dll, lua51.lib, lua.exe, and luac.exe in src.
+@rem (contributed by David Manura and Mike Pall)
+
+@setlocal
+@set MYCOMPILE=cl /nologo /MD /O2 /W3 /c /D_CRT_SECURE_NO_DEPRECATE
+@set MYLINK=link /nologo
+@set MYMT=mt /nologo
+
+cd src
+%MYCOMPILE% /DLUA_BUILD_AS_DLL l*.c
+del lua.obj luac.obj
+%MYLINK% /DLL /out:lua51.dll l*.obj
+if exist lua51.dll.manifest^
+ %MYMT% -manifest lua51.dll.manifest -outputresource:lua51.dll;2
+%MYCOMPILE% /DLUA_BUILD_AS_DLL lua.c
+%MYLINK% /out:lua.exe lua.obj lua51.lib
+if exist lua.exe.manifest^
+ %MYMT% -manifest lua.exe.manifest -outputresource:lua.exe
+%MYCOMPILE% l*.c print.c
+del lua.obj linit.obj lbaselib.obj ldblib.obj liolib.obj lmathlib.obj^
+ loslib.obj ltablib.obj lstrlib.obj loadlib.obj
+%MYLINK% /out:luac.exe *.obj
+if exist luac.exe.manifest^
+ %MYMT% -manifest luac.exe.manifest -outputresource:luac.exe
+del *.obj *.manifest
+cd ..
diff --git a/contrib/syslinux-4.02/com32/lua/etc/min.c b/contrib/syslinux-4.02/com32/lua/etc/min.c new file mode 100644 index 0000000..6a85a4d --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/etc/min.c @@ -0,0 +1,39 @@ +/* +* min.c -- a minimal Lua interpreter +* loads stdin only with minimal error handling. +* no interaction, and no standard library, only a "print" function. +*/ + +#include <stdio.h> + +#include "lua.h" +#include "lauxlib.h" + +static int print(lua_State *L) +{ + int n=lua_gettop(L); + int i; + for (i=1; i<=n; i++) + { + if (i>1) printf("\t"); + if (lua_isstring(L,i)) + printf("%s",lua_tostring(L,i)); + else if (lua_isnil(L,i)) + printf("%s","nil"); + else if (lua_isboolean(L,i)) + printf("%s",lua_toboolean(L,i) ? "true" : "false"); + else + printf("%s:%p",luaL_typename(L,i),lua_topointer(L,i)); + } + printf("\n"); + return 0; +} + +int main(void) +{ + lua_State *L=lua_open(); + lua_register(L,"print",print); + if (luaL_dofile(L,NULL)!=0) fprintf(stderr,"%s\n",lua_tostring(L,-1)); + lua_close(L); + return 0; +} diff --git a/contrib/syslinux-4.02/com32/lua/etc/noparser.c b/contrib/syslinux-4.02/com32/lua/etc/noparser.c new file mode 100644 index 0000000..13ba546 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/etc/noparser.c @@ -0,0 +1,50 @@ +/* +* The code below can be used to make a Lua core that does not contain the +* parsing modules (lcode, llex, lparser), which represent 35% of the total core. +* You'll only be able to load binary files and strings, precompiled with luac. +* (Of course, you'll have to build luac with the original parsing modules!) +* +* To use this module, simply compile it ("make noparser" does that) and list +* its object file before the Lua libraries. The linker should then not load +* the parsing modules. To try it, do "make luab". +* +* If you also want to avoid the dump module (ldump.o), define NODUMP. +* #define NODUMP +*/ + +#define LUA_CORE + +#include "llex.h" +#include "lparser.h" +#include "lzio.h" + +LUAI_FUNC void luaX_init (lua_State *L) { + UNUSED(L); +} + +LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { + UNUSED(z); + UNUSED(buff); + UNUSED(name); + lua_pushliteral(L,"parser not loaded"); + lua_error(L); + return NULL; +} + +#ifdef NODUMP +#include "lundump.h" + +LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip) { + UNUSED(f); + UNUSED(w); + UNUSED(data); + UNUSED(strip); +#if 1 + UNUSED(L); + return 0; +#else + lua_pushliteral(L,"dumper not loaded"); + lua_error(L); +#endif +} +#endif diff --git a/contrib/syslinux-4.02/com32/lua/etc/strict.lua b/contrib/syslinux-4.02/com32/lua/etc/strict.lua new file mode 100644 index 0000000..604619d --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/etc/strict.lua @@ -0,0 +1,41 @@ +-- +-- strict.lua +-- checks uses of undeclared global variables +-- All global variables must be 'declared' through a regular assignment +-- (even assigning nil will do) in a main chunk before being used +-- anywhere or assigned to inside a function. +-- + +local getinfo, error, rawset, rawget = debug.getinfo, error, rawset, rawget + +local mt = getmetatable(_G) +if mt == nil then + mt = {} + setmetatable(_G, mt) +end + +mt.__declared = {} + +local function what () + local d = getinfo(3, "S") + return d and d.what or "C" +end + +mt.__newindex = function (t, n, v) + if not mt.__declared[n] then + local w = what() + if w ~= "main" and w ~= "C" then + error("assign to undeclared variable '"..n.."'", 2) + end + mt.__declared[n] = true + end + rawset(t, n, v) +end + +mt.__index = function (t, n) + if not mt.__declared[n] and what() ~= "C" then + error("variable '"..n.."' is not declared", 2) + end + return rawget(t, n) +end + diff --git a/contrib/syslinux-4.02/com32/lua/src/Makefile b/contrib/syslinux-4.02/com32/lua/src/Makefile new file mode 100644 index 0000000..d31c9bd --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/Makefile @@ -0,0 +1,71 @@ +## ----------------------------------------------------------------------- +## +## Copyright 2001-2009 H. Peter Anvin - All Rights Reserved +## Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, +## Boston MA 02110-1301, USA; either version 2 of the License, or +## (at your option) any later version; incorporated herein by reference. +## +## ----------------------------------------------------------------------- + +## +## Lua Makefile +## + +topdir = ../../.. +include ../../MCONFIG + +LIBS = ../../lib/libcom32.a $(LIBGCC) +LNXLIBS = + +# Temporarily allow warnings not being treated as errors +GCCWARN += -Wno-error + +MODULES = lua.c32 +TESTFILES = + +OBJS = lua.o + +LIBLUA = liblua.a + +LIBLUA_OBJS := lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o +LIBLUA_OBJS += lgc.o llex.o lmem.o lobject.o lopcodes.o lparser.o +LIBLUA_OBJS += lstate.o lstring.o ltable.o ltm.o lvm.o lzio.o lundump.o +LIBLUA_OBJS += syslinux.o + +LIBLUA_OBJS += lauxlib.o lbaselib.o ldblib.o ltablib.o +LIBLUA_OBJS += lstrlib.o loadlib.o linit.o +LIBLUA_OBJS += liolib.o +LIBLUA_OBJS += dmi.o + +LIBLUA_OBJS += pci.o +LIBLUA_OBJS += vesa.o + +CFLAGS += -DLUA_ANSI + +all: $(MODULES) $(TESTFILES) + +$(LIBLUA) : $(LIBLUA_OBJS) + rm -f $@ + $(AR) cq $@ $^ + $(RANLIB) $@ + +lua.elf : $(OBJS) $(LIBLUA) $(LIBS) $(C_LIBS) + $(LD) $(LDFLAGS) -o $@ $^ + +tidy dist: + rm -f *.o *.lo *.a *.lst *.elf .*.d *.tmp + +clean: tidy + rm -f *.lnx + +spotless: clean + rm -f *.lss *.c32 *.com + rm -f *~ \#* + +install: + +-include .*.d diff --git a/contrib/syslinux-4.02/com32/lua/src/Makefile-orig b/contrib/syslinux-4.02/com32/lua/src/Makefile-orig new file mode 100644 index 0000000..e4a3cd6 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/Makefile-orig @@ -0,0 +1,182 @@ +# makefile for building Lua +# see ../INSTALL for installation instructions +# see ../Makefile and luaconf.h for further customization + +# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT ======================= + +# Your platform. See PLATS for possible values. +PLAT= none + +CC= gcc +CFLAGS= -O2 -Wall $(MYCFLAGS) +AR= ar rcu +RANLIB= ranlib +RM= rm -f +LIBS= -lm $(MYLIBS) + +MYCFLAGS= +MYLDFLAGS= +MYLIBS= + +# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE ========= + +PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris + +LUA_A= liblua.a +CORE_O= lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \ + lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o \ + lundump.o lvm.o lzio.o +LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \ + lstrlib.o loadlib.o linit.o + +LUA_T= lua +LUA_O= lua.o + +LUAC_T= luac +LUAC_O= luac.o print.o + +ALL_O= $(CORE_O) $(LIB_O) $(LUA_O) $(LUAC_O) +ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T) +ALL_A= $(LUA_A) + +default: $(PLAT) + +all: $(ALL_T) + +o: $(ALL_O) + +a: $(ALL_A) + +$(LUA_A): $(CORE_O) $(LIB_O) + $(AR) $@ $? + $(RANLIB) $@ + +$(LUA_T): $(LUA_O) $(LUA_A) + $(CC) -o $@ $(MYLDFLAGS) $(LUA_O) $(LUA_A) $(LIBS) + +$(LUAC_T): $(LUAC_O) $(LUA_A) + $(CC) -o $@ $(MYLDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS) + +clean: + $(RM) $(ALL_T) $(ALL_O) + +depend: + @$(CC) $(CFLAGS) -MM l*.c print.c + +echo: + @echo "PLAT = $(PLAT)" + @echo "CC = $(CC)" + @echo "CFLAGS = $(CFLAGS)" + @echo "AR = $(AR)" + @echo "RANLIB = $(RANLIB)" + @echo "RM = $(RM)" + @echo "MYCFLAGS = $(MYCFLAGS)" + @echo "MYLDFLAGS = $(MYLDFLAGS)" + @echo "MYLIBS = $(MYLIBS)" + +# convenience targets for popular platforms + +none: + @echo "Please choose a platform:" + @echo " $(PLATS)" + +aix: + $(MAKE) all CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-ldl" MYLDFLAGS="-brtl -bexpall" + +ansi: + $(MAKE) all MYCFLAGS=-DLUA_ANSI + +bsd: + $(MAKE) all MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-Wl,-E" + +freebsd: + $(MAKE) all MYCFLAGS="-DLUA_USE_LINUX" MYLIBS="-Wl,-E -lreadline" + +generic: + $(MAKE) all MYCFLAGS= + +linux: + $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses" + +macosx: + $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-lreadline" +# use this on Mac OS X 10.3- +# $(MAKE) all MYCFLAGS=-DLUA_USE_MACOSX + +mingw: + $(MAKE) "LUA_A=lua51.dll" "LUA_T=lua.exe" \ + "AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \ + "MYCFLAGS=-DLUA_BUILD_AS_DLL" "MYLIBS=" "MYLDFLAGS=-s" lua.exe + $(MAKE) "LUAC_T=luac.exe" luac.exe + +posix: + $(MAKE) all MYCFLAGS=-DLUA_USE_POSIX + +solaris: + $(MAKE) all MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-ldl" + +# list targets that do not create files (but not all makes understand .PHONY) +.PHONY: all $(PLATS) default o a clean depend echo none + +# DO NOT DELETE + +lapi.o: lapi.c lua.h luaconf.h lapi.h lobject.h llimits.h ldebug.h \ + lstate.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h \ + lundump.h lvm.h +lauxlib.o: lauxlib.c lua.h luaconf.h lauxlib.h +lbaselib.o: lbaselib.c lua.h luaconf.h lauxlib.h lualib.h +lcode.o: lcode.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \ + lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h lgc.h \ + ltable.h +ldblib.o: ldblib.c lua.h luaconf.h lauxlib.h lualib.h +ldebug.o: ldebug.c lua.h luaconf.h lapi.h lobject.h llimits.h lcode.h \ + llex.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h \ + lfunc.h lstring.h lgc.h ltable.h lvm.h +ldo.o: ldo.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \ + lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lparser.h lstring.h \ + ltable.h lundump.h lvm.h +ldump.o: ldump.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h \ + lzio.h lmem.h lundump.h +lfunc.o: lfunc.c lua.h luaconf.h lfunc.h lobject.h llimits.h lgc.h lmem.h \ + lstate.h ltm.h lzio.h +lgc.o: lgc.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \ + lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h +linit.o: linit.c lua.h luaconf.h lualib.h lauxlib.h +liolib.o: liolib.c lua.h luaconf.h lauxlib.h lualib.h +llex.o: llex.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h ltm.h \ + lzio.h lmem.h llex.h lparser.h lstring.h lgc.h ltable.h +lmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h +lmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \ + ltm.h lzio.h lmem.h ldo.h +loadlib.o: loadlib.c lua.h luaconf.h lauxlib.h lualib.h +lobject.o: lobject.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h \ + ltm.h lzio.h lmem.h lstring.h lgc.h lvm.h +lopcodes.o: lopcodes.c lopcodes.h llimits.h lua.h luaconf.h +loslib.o: loslib.c lua.h luaconf.h lauxlib.h lualib.h +lparser.o: lparser.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \ + lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h \ + lfunc.h lstring.h lgc.h ltable.h +lstate.o: lstate.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \ + ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h llex.h lstring.h ltable.h +lstring.o: lstring.c lua.h luaconf.h lmem.h llimits.h lobject.h lstate.h \ + ltm.h lzio.h lstring.h lgc.h +lstrlib.o: lstrlib.c lua.h luaconf.h lauxlib.h lualib.h +ltable.o: ltable.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \ + ltm.h lzio.h lmem.h ldo.h lgc.h ltable.h +ltablib.o: ltablib.c lua.h luaconf.h lauxlib.h lualib.h +ltm.o: ltm.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h lzio.h \ + lmem.h lstring.h lgc.h ltable.h +lua.o: lua.c lua.h luaconf.h lauxlib.h lualib.h +luac.o: luac.c lua.h luaconf.h lauxlib.h ldo.h lobject.h llimits.h \ + lstate.h ltm.h lzio.h lmem.h lfunc.h lopcodes.h lstring.h lgc.h \ + lundump.h +lundump.o: lundump.c lua.h luaconf.h ldebug.h lstate.h lobject.h \ + llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h lundump.h +lvm.o: lvm.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \ + lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h ltable.h lvm.h +lzio.o: lzio.c lua.h luaconf.h llimits.h lmem.h lstate.h lobject.h ltm.h \ + lzio.h +print.o: print.c ldebug.h lstate.h lua.h luaconf.h lobject.h llimits.h \ + ltm.h lzio.h lmem.h lopcodes.h lundump.h + +# (end of Makefile) diff --git a/contrib/syslinux-4.02/com32/lua/src/dmi.c b/contrib/syslinux-4.02/com32/lua/src/dmi.c new file mode 100644 index 0000000..d030533 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/dmi.c @@ -0,0 +1,301 @@ +#include <stdlib.h> +#include <string.h> + +#define ldmilib_c /* Define the library */ + +/* Include the Lua API header files */ +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +#include "dmi/dmi.h" + +static int dmi_gettable(lua_State *L) +{ + s_dmi dmi; + + lua_newtable(L); + + if ( ! dmi_iterate(&dmi) ) { + printf("No DMI Structure found\n"); + return -1; + } + + parse_dmitable(&dmi); + + /* bios */ + lua_pushstring(L, "bios.vendor"); + lua_pushstring(L, dmi.bios.vendor); + lua_settable(L,-3); + + lua_pushstring(L, "bios.version"); + lua_pushstring(L, dmi.bios.version); + lua_settable(L,-3); + + lua_pushstring(L, "bios.release_date"); + lua_pushstring(L, dmi.bios.release_date); + lua_settable(L,-3); + + lua_pushstring(L, "bios.bios_revision"); + lua_pushstring(L, dmi.bios.bios_revision); + lua_settable(L,-3); + + lua_pushstring(L, "bios.firmware_revision"); + lua_pushstring(L, dmi.bios.firmware_revision); + lua_settable(L,-3); + + lua_pushstring(L, "bios.address"); + lua_pushnumber(L, dmi.bios.address); + lua_settable(L,-3); + + lua_pushstring(L, "bios.runtime_size"); + lua_pushnumber(L, dmi.bios.runtime_size); + lua_settable(L,-3); + + lua_pushstring(L, "bios.runtime_size_unit"); + lua_pushstring(L, dmi.bios.runtime_size_unit); + lua_settable(L,-3); + + lua_pushstring(L, "bios.rom_size"); + lua_pushnumber(L, dmi.bios.rom_size); + lua_settable(L,-3); + + lua_pushstring(L, "bios.rom_size_unit"); + lua_pushstring(L, dmi.bios.rom_size_unit); + lua_settable(L,-3); + + /* system */ + lua_pushstring(L, "system.manufacturer"); + lua_pushstring(L, dmi.system.manufacturer); + lua_settable(L,-3); + + lua_pushstring(L, "system.product_name"); + lua_pushstring(L, dmi.system.product_name); + lua_settable(L,-3); + + lua_pushstring(L, "system.version"); + lua_pushstring(L, dmi.system.version); + lua_settable(L,-3); + + lua_pushstring(L, "system.serial"); + lua_pushstring(L, dmi.system.serial); + lua_settable(L,-3); + + lua_pushstring(L, "system.uuid"); + lua_pushstring(L, dmi.system.uuid); + lua_settable(L,-3); + + lua_pushstring(L, "system.wakeup_type"); + lua_pushstring(L, dmi.system.wakeup_type); + lua_settable(L,-3); + + lua_pushstring(L, "system.sku_number"); + lua_pushstring(L, dmi.system.sku_number); + lua_settable(L,-3); + + lua_pushstring(L, "system.family"); + lua_pushstring(L, dmi.system.family); + lua_settable(L,-3); + + /* base_board */ + lua_pushstring(L, "base_board.manufacturer"); + lua_pushstring(L, dmi.base_board.manufacturer); + lua_settable(L,-3); + + lua_pushstring(L, "base_board.product_name"); + lua_pushstring(L, dmi.base_board.product_name); + lua_settable(L,-3); + + lua_pushstring(L, "base_board.version"); + lua_pushstring(L, dmi.base_board.version); + lua_settable(L,-3); + + lua_pushstring(L, "base_board.serial"); + lua_pushstring(L, dmi.base_board.serial); + lua_settable(L,-3); + + lua_pushstring(L, "base_board.asset_tag"); + lua_pushstring(L, dmi.base_board.asset_tag); + lua_settable(L,-3); + + lua_pushstring(L, "base_board.location"); + lua_pushstring(L, dmi.base_board.location); + lua_settable(L,-3); + + lua_pushstring(L, "base_board.type"); + lua_pushstring(L, dmi.base_board.type); + lua_settable(L,-3); + + /* chassis */ + lua_pushstring(L, "chassis.manufacturer"); + lua_pushstring(L, dmi.chassis.manufacturer); + lua_settable(L,-3); + + lua_pushstring(L, "chassis.type"); + lua_pushstring(L, dmi.chassis.type); + lua_settable(L,-3); + + lua_pushstring(L, "chassis.lock"); + lua_pushstring(L, dmi.chassis.lock); + lua_settable(L,-3); + + lua_pushstring(L, "chassis.version"); + lua_pushstring(L, dmi.chassis.version); + lua_settable(L,-3); + + lua_pushstring(L, "chassis.serial"); + lua_pushstring(L, dmi.chassis.serial); + lua_settable(L,-3); + + lua_pushstring(L, "chassis.asset_tag"); + lua_pushstring(L, dmi.chassis.asset_tag); + lua_settable(L,-3); + + lua_pushstring(L, "chassis.boot_up_state"); + lua_pushstring(L, dmi.chassis.boot_up_state); + lua_settable(L,-3); + + lua_pushstring(L, "chassis.power_supply_state"); + lua_pushstring(L, dmi.chassis.power_supply_state); + lua_settable(L,-3); + + lua_pushstring(L, "chassis.thermal_state"); + lua_pushstring(L, dmi.chassis.thermal_state); + lua_settable(L,-3); + + lua_pushstring(L, "chassis.security_status"); + lua_pushstring(L, dmi.chassis.security_status); + lua_settable(L,-3); + + lua_pushstring(L, "chassis.oem_information"); + lua_pushstring(L, dmi.chassis.oem_information); + lua_settable(L,-3); + + lua_pushstring(L, "chassis.height"); + lua_pushnumber(L, dmi.chassis.height); + lua_settable(L,-3); + + lua_pushstring(L, "chassis.nb_power_cords"); + lua_pushnumber(L, dmi.chassis.nb_power_cords); + lua_settable(L,-3); + + /* processor */ + lua_pushstring(L, "processor.socket_designation"); + lua_pushstring(L, dmi.processor.socket_designation); + lua_settable(L,-3); + + lua_pushstring(L, "processor.type"); + lua_pushstring(L, dmi.processor.type); + lua_settable(L,-3); + + lua_pushstring(L, "processor.family"); + lua_pushstring(L, dmi.processor.family); + lua_settable(L,-3); + + lua_pushstring(L, "processor.manufacturer"); + lua_pushstring(L, dmi.processor.manufacturer); + lua_settable(L,-3); + + lua_pushstring(L, "processor.version"); + lua_pushstring(L, dmi.processor.version); + lua_settable(L,-3); + + lua_pushstring(L, "processor.external_clock"); + lua_pushnumber(L, dmi.processor.external_clock); + lua_settable(L,-3); + + lua_pushstring(L, "processor.max_speed"); + lua_pushnumber(L, dmi.processor.max_speed); + lua_settable(L,-3); + + lua_pushstring(L, "processor.current_speed"); + lua_pushnumber(L, dmi.processor.current_speed); + lua_settable(L,-3); + + lua_pushstring(L, "processor.signature.type"); + lua_pushnumber(L, dmi.processor.signature.type); + lua_settable(L,-3); + + lua_pushstring(L, "processor.signature.family"); + lua_pushnumber(L, dmi.processor.signature.family); + lua_settable(L,-3); + + lua_pushstring(L, "processor.signature.model"); + lua_pushnumber(L, dmi.processor.signature.model); + lua_settable(L,-3); + + lua_pushstring(L, "processor.signature.stepping"); + lua_pushnumber(L, dmi.processor.signature.stepping); + lua_settable(L,-3); + + lua_pushstring(L, "processor.signature.minor_stepping"); + lua_pushnumber(L, dmi.processor.signature.minor_stepping); + lua_settable(L,-3); + + lua_pushstring(L, "processor.voltage_mv"); + lua_pushnumber(L, dmi.processor.voltage_mv); + lua_settable(L,-3); + + lua_pushstring(L, "processor.status"); + lua_pushstring(L, dmi.processor.status); + lua_settable(L,-3); + + lua_pushstring(L, "processor.upgrade"); + lua_pushstring(L, dmi.processor.upgrade); + lua_settable(L,-3); + + lua_pushstring(L, "processor.cache1"); + lua_pushstring(L, dmi.processor.cache1); + lua_settable(L,-3); + + lua_pushstring(L, "processor.cache2"); + lua_pushstring(L, dmi.processor.cache2); + lua_settable(L,-3); + + lua_pushstring(L, "processor.cache3"); + lua_pushstring(L, dmi.processor.cache3); + lua_settable(L,-3); + + lua_pushstring(L, "processor.serial"); + lua_pushstring(L, dmi.processor.serial); + lua_settable(L,-3); + + lua_pushstring(L, "processor.part_number"); + lua_pushstring(L, dmi.processor.part_number); + lua_settable(L,-3); + + lua_pushstring(L, "processor.id"); + lua_pushstring(L, dmi.processor.id); + lua_settable(L,-3); + + /* set global variable: lua_setglobal(L, "dmitable"); */ + + /* return number of return values on stack */ + return 1; +} + + +static int dmi_supported(lua_State *L) +{ + s_dmi dmi; + + if ( dmi_iterate(&dmi) ) { + lua_pushboolean(L, 1); + } else { + lua_pushboolean(L, 0); + } + return 1; +} + + +static const luaL_Reg dmilib[] = { + {"gettable", dmi_gettable}, + {"supported", dmi_supported}, + {NULL, NULL} +}; + + +LUALIB_API int luaopen_dmi (lua_State *L) { + luaL_openlib(L, LUA_DMILIBNAME, dmilib, 0); + return 1; +} + diff --git a/contrib/syslinux-4.02/com32/lua/src/lapi.c b/contrib/syslinux-4.02/com32/lua/src/lapi.c new file mode 100644 index 0000000..d7e8931 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lapi.c @@ -0,0 +1,1085 @@ +/* +** $Id: lapi.c,v 2.55.1.3 2008/01/03 15:20:39 roberto Exp $ +** Lua API +** See Copyright Notice in lua.h +*/ + + +#include <assert.h> +#include <math.h> +#include <stdarg.h> +#include <string.h> + +#define lapi_c +#define LUA_CORE + +#include "lua.h" + +#include "lapi.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lundump.h" +#include "lvm.h" + + + +const char lua_ident[] = + "$Lua: " LUA_RELEASE " " LUA_COPYRIGHT " $\n" + "$Authors: " LUA_AUTHORS " $\n" + "$URL: www.lua.org $\n"; + + + +#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base)) + +#define api_checkvalidindex(L, i) api_check(L, (i) != luaO_nilobject) + +#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;} + + + +static TValue *index2adr (lua_State *L, int idx) { + if (idx > 0) { + TValue *o = L->base + (idx - 1); + api_check(L, idx <= L->ci->top - L->base); + if (o >= L->top) return cast(TValue *, luaO_nilobject); + else return o; + } + else if (idx > LUA_REGISTRYINDEX) { + api_check(L, idx != 0 && -idx <= L->top - L->base); + return L->top + idx; + } + else switch (idx) { /* pseudo-indices */ + case LUA_REGISTRYINDEX: return registry(L); + case LUA_ENVIRONINDEX: { + Closure *func = curr_func(L); + sethvalue(L, &L->env, func->c.env); + return &L->env; + } + case LUA_GLOBALSINDEX: return gt(L); + default: { + Closure *func = curr_func(L); + idx = LUA_GLOBALSINDEX - idx; + return (idx <= func->c.nupvalues) + ? &func->c.upvalue[idx-1] + : cast(TValue *, luaO_nilobject); + } + } +} + + +static Table *getcurrenv (lua_State *L) { + if (L->ci == L->base_ci) /* no enclosing function? */ + return hvalue(gt(L)); /* use global table as environment */ + else { + Closure *func = curr_func(L); + return func->c.env; + } +} + + +void luaA_pushobject (lua_State *L, const TValue *o) { + setobj2s(L, L->top, o); + api_incr_top(L); +} + + +LUA_API int lua_checkstack (lua_State *L, int size) { + int res; + lua_lock(L); + if ((L->top - L->base + size) > LUAI_MAXCSTACK) + res = 0; /* stack overflow */ + else { + luaD_checkstack(L, size); + if (L->ci->top < L->top + size) + L->ci->top = L->top + size; + res = 1; + } + lua_unlock(L); + return res; +} + + +LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { + int i; + if (from == to) return; + lua_lock(to); + api_checknelems(from, n); + api_check(from, G(from) == G(to)); + api_check(from, to->ci->top - to->top >= n); + from->top -= n; + for (i = 0; i < n; i++) { + setobj2s(to, to->top++, from->top + i); + } + lua_unlock(to); +} + + +LUA_API void lua_setlevel (lua_State *from, lua_State *to) { + to->nCcalls = from->nCcalls; +} + + +LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { + lua_CFunction old; + lua_lock(L); + old = G(L)->panic; + G(L)->panic = panicf; + lua_unlock(L); + return old; +} + + +LUA_API lua_State *lua_newthread (lua_State *L) { + lua_State *L1; + lua_lock(L); + luaC_checkGC(L); + L1 = luaE_newthread(L); + setthvalue(L, L->top, L1); + api_incr_top(L); + lua_unlock(L); + luai_userstatethread(L, L1); + return L1; +} + + + +/* +** basic stack manipulation +*/ + + +LUA_API int lua_gettop (lua_State *L) { + return cast_int(L->top - L->base); +} + + +LUA_API void lua_settop (lua_State *L, int idx) { + lua_lock(L); + if (idx >= 0) { + api_check(L, idx <= L->stack_last - L->base); + while (L->top < L->base + idx) + setnilvalue(L->top++); + L->top = L->base + idx; + } + else { + api_check(L, -(idx+1) <= (L->top - L->base)); + L->top += idx+1; /* `subtract' index (index is negative) */ + } + lua_unlock(L); +} + + +LUA_API void lua_remove (lua_State *L, int idx) { + StkId p; + lua_lock(L); + p = index2adr(L, idx); + api_checkvalidindex(L, p); + while (++p < L->top) setobjs2s(L, p-1, p); + L->top--; + lua_unlock(L); +} + + +LUA_API void lua_insert (lua_State *L, int idx) { + StkId p; + StkId q; + lua_lock(L); + p = index2adr(L, idx); + api_checkvalidindex(L, p); + for (q = L->top; q>p; q--) setobjs2s(L, q, q-1); + setobjs2s(L, p, L->top); + lua_unlock(L); +} + + +LUA_API void lua_replace (lua_State *L, int idx) { + StkId o; + lua_lock(L); + /* explicit test for incompatible code */ + if (idx == LUA_ENVIRONINDEX && L->ci == L->base_ci) + luaG_runerror(L, "no calling environment"); + api_checknelems(L, 1); + o = index2adr(L, idx); + api_checkvalidindex(L, o); + if (idx == LUA_ENVIRONINDEX) { + Closure *func = curr_func(L); + api_check(L, ttistable(L->top - 1)); + func->c.env = hvalue(L->top - 1); + luaC_barrier(L, func, L->top - 1); + } + else { + setobj(L, o, L->top - 1); + if (idx < LUA_GLOBALSINDEX) /* function upvalue? */ + luaC_barrier(L, curr_func(L), L->top - 1); + } + L->top--; + lua_unlock(L); +} + + +LUA_API void lua_pushvalue (lua_State *L, int idx) { + lua_lock(L); + setobj2s(L, L->top, index2adr(L, idx)); + api_incr_top(L); + lua_unlock(L); +} + + + +/* +** access functions (stack -> C) +*/ + + +LUA_API int lua_type (lua_State *L, int idx) { + StkId o = index2adr(L, idx); + return (o == luaO_nilobject) ? LUA_TNONE : ttype(o); +} + + +LUA_API const char *lua_typename (lua_State *L, int t) { + UNUSED(L); + return (t == LUA_TNONE) ? "no value" : luaT_typenames[t]; +} + + +LUA_API int lua_iscfunction (lua_State *L, int idx) { + StkId o = index2adr(L, idx); + return iscfunction(o); +} + + +LUA_API int lua_isnumber (lua_State *L, int idx) { + TValue n; + const TValue *o = index2adr(L, idx); + return tonumber(o, &n); +} + + +LUA_API int lua_isstring (lua_State *L, int idx) { + int t = lua_type(L, idx); + return (t == LUA_TSTRING || t == LUA_TNUMBER); +} + + +LUA_API int lua_isuserdata (lua_State *L, int idx) { + const TValue *o = index2adr(L, idx); + return (ttisuserdata(o) || ttislightuserdata(o)); +} + + +LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { + StkId o1 = index2adr(L, index1); + StkId o2 = index2adr(L, index2); + return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 + : luaO_rawequalObj(o1, o2); +} + + +LUA_API int lua_equal (lua_State *L, int index1, int index2) { + StkId o1, o2; + int i; + lua_lock(L); /* may call tag method */ + o1 = index2adr(L, index1); + o2 = index2adr(L, index2); + i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2); + lua_unlock(L); + return i; +} + + +LUA_API int lua_lessthan (lua_State *L, int index1, int index2) { + StkId o1, o2; + int i; + lua_lock(L); /* may call tag method */ + o1 = index2adr(L, index1); + o2 = index2adr(L, index2); + i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 + : luaV_lessthan(L, o1, o2); + lua_unlock(L); + return i; +} + + + +LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { + TValue n; + const TValue *o = index2adr(L, idx); + if (tonumber(o, &n)) + return nvalue(o); + else + return 0; +} + + +LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) { + TValue n; + const TValue *o = index2adr(L, idx); + if (tonumber(o, &n)) { + lua_Integer res; + lua_Number num = nvalue(o); + lua_number2integer(res, num); + return res; + } + else + return 0; +} + + +LUA_API int lua_toboolean (lua_State *L, int idx) { + const TValue *o = index2adr(L, idx); + return !l_isfalse(o); +} + + +LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { + StkId o = index2adr(L, idx); + if (!ttisstring(o)) { + lua_lock(L); /* `luaV_tostring' may create a new string */ + if (!luaV_tostring(L, o)) { /* conversion failed? */ + if (len != NULL) *len = 0; + lua_unlock(L); + return NULL; + } + luaC_checkGC(L); + o = index2adr(L, idx); /* previous call may reallocate the stack */ + lua_unlock(L); + } + if (len != NULL) *len = tsvalue(o)->len; + return svalue(o); +} + + +LUA_API size_t lua_objlen (lua_State *L, int idx) { + StkId o = index2adr(L, idx); + switch (ttype(o)) { + case LUA_TSTRING: return tsvalue(o)->len; + case LUA_TUSERDATA: return uvalue(o)->len; + case LUA_TTABLE: return luaH_getn(hvalue(o)); + case LUA_TNUMBER: { + size_t l; + lua_lock(L); /* `luaV_tostring' may create a new string */ + l = (luaV_tostring(L, o) ? tsvalue(o)->len : 0); + lua_unlock(L); + return l; + } + default: return 0; + } +} + + +LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { + StkId o = index2adr(L, idx); + return (!iscfunction(o)) ? NULL : clvalue(o)->c.f; +} + + +LUA_API void *lua_touserdata (lua_State *L, int idx) { + StkId o = index2adr(L, idx); + switch (ttype(o)) { + case LUA_TUSERDATA: return (rawuvalue(o) + 1); + case LUA_TLIGHTUSERDATA: return pvalue(o); + default: return NULL; + } +} + + +LUA_API lua_State *lua_tothread (lua_State *L, int idx) { + StkId o = index2adr(L, idx); + return (!ttisthread(o)) ? NULL : thvalue(o); +} + + +LUA_API const void *lua_topointer (lua_State *L, int idx) { + StkId o = index2adr(L, idx); + switch (ttype(o)) { + case LUA_TTABLE: return hvalue(o); + case LUA_TFUNCTION: return clvalue(o); + case LUA_TTHREAD: return thvalue(o); + case LUA_TUSERDATA: + case LUA_TLIGHTUSERDATA: + return lua_touserdata(L, idx); + default: return NULL; + } +} + + + +/* +** push functions (C -> stack) +*/ + + +LUA_API void lua_pushnil (lua_State *L) { + lua_lock(L); + setnilvalue(L->top); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { + lua_lock(L); + setnvalue(L->top, n); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { + lua_lock(L); + setnvalue(L->top, cast_num(n)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { + lua_lock(L); + luaC_checkGC(L); + setsvalue2s(L, L->top, luaS_newlstr(L, s, len)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushstring (lua_State *L, const char *s) { + if (s == NULL) + lua_pushnil(L); + else + lua_pushlstring(L, s, strlen(s)); +} + + +LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, + va_list argp) { + const char *ret; + lua_lock(L); + luaC_checkGC(L); + ret = luaO_pushvfstring(L, fmt, argp); + lua_unlock(L); + return ret; +} + + +LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { + const char *ret; + va_list argp; + lua_lock(L); + luaC_checkGC(L); + va_start(argp, fmt); + ret = luaO_pushvfstring(L, fmt, argp); + va_end(argp); + lua_unlock(L); + return ret; +} + + +LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { + Closure *cl; + lua_lock(L); + luaC_checkGC(L); + api_checknelems(L, n); + cl = luaF_newCclosure(L, n, getcurrenv(L)); + cl->c.f = fn; + L->top -= n; + while (n--) + setobj2n(L, &cl->c.upvalue[n], L->top+n); + setclvalue(L, L->top, cl); + lua_assert(iswhite(obj2gco(cl))); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushboolean (lua_State *L, int b) { + lua_lock(L); + setbvalue(L->top, (b != 0)); /* ensure that true is 1 */ + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { + lua_lock(L); + setpvalue(L->top, p); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API int lua_pushthread (lua_State *L) { + lua_lock(L); + setthvalue(L, L->top, L); + api_incr_top(L); + lua_unlock(L); + return (G(L)->mainthread == L); +} + + + +/* +** get functions (Lua -> stack) +*/ + + +LUA_API void lua_gettable (lua_State *L, int idx) { + StkId t; + lua_lock(L); + t = index2adr(L, idx); + api_checkvalidindex(L, t); + luaV_gettable(L, t, L->top - 1, L->top - 1); + lua_unlock(L); +} + + +LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { + StkId t; + TValue key; + lua_lock(L); + t = index2adr(L, idx); + api_checkvalidindex(L, t); + setsvalue(L, &key, luaS_new(L, k)); + luaV_gettable(L, t, &key, L->top); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_rawget (lua_State *L, int idx) { + StkId t; + lua_lock(L); + t = index2adr(L, idx); + api_check(L, ttistable(t)); + setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); + lua_unlock(L); +} + + +LUA_API void lua_rawgeti (lua_State *L, int idx, int n) { + StkId o; + lua_lock(L); + o = index2adr(L, idx); + api_check(L, ttistable(o)); + setobj2s(L, L->top, luaH_getnum(hvalue(o), n)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { + lua_lock(L); + luaC_checkGC(L); + sethvalue(L, L->top, luaH_new(L, narray, nrec)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API int lua_getmetatable (lua_State *L, int objindex) { + const TValue *obj; + Table *mt = NULL; + int res; + lua_lock(L); + obj = index2adr(L, objindex); + switch (ttype(obj)) { + case LUA_TTABLE: + mt = hvalue(obj)->metatable; + break; + case LUA_TUSERDATA: + mt = uvalue(obj)->metatable; + break; + default: + mt = G(L)->mt[ttype(obj)]; + break; + } + if (mt == NULL) + res = 0; + else { + sethvalue(L, L->top, mt); + api_incr_top(L); + res = 1; + } + lua_unlock(L); + return res; +} + + +LUA_API void lua_getfenv (lua_State *L, int idx) { + StkId o; + lua_lock(L); + o = index2adr(L, idx); + api_checkvalidindex(L, o); + switch (ttype(o)) { + case LUA_TFUNCTION: + sethvalue(L, L->top, clvalue(o)->c.env); + break; + case LUA_TUSERDATA: + sethvalue(L, L->top, uvalue(o)->env); + break; + case LUA_TTHREAD: + setobj2s(L, L->top, gt(thvalue(o))); + break; + default: + setnilvalue(L->top); + break; + } + api_incr_top(L); + lua_unlock(L); +} + + +/* +** set functions (stack -> Lua) +*/ + + +LUA_API void lua_settable (lua_State *L, int idx) { + StkId t; + lua_lock(L); + api_checknelems(L, 2); + t = index2adr(L, idx); + api_checkvalidindex(L, t); + luaV_settable(L, t, L->top - 2, L->top - 1); + L->top -= 2; /* pop index and value */ + lua_unlock(L); +} + + +LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { + StkId t; + TValue key; + lua_lock(L); + api_checknelems(L, 1); + t = index2adr(L, idx); + api_checkvalidindex(L, t); + setsvalue(L, &key, luaS_new(L, k)); + luaV_settable(L, t, &key, L->top - 1); + L->top--; /* pop value */ + lua_unlock(L); +} + + +LUA_API void lua_rawset (lua_State *L, int idx) { + StkId t; + lua_lock(L); + api_checknelems(L, 2); + t = index2adr(L, idx); + api_check(L, ttistable(t)); + setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); + luaC_barriert(L, hvalue(t), L->top-1); + L->top -= 2; + lua_unlock(L); +} + + +LUA_API void lua_rawseti (lua_State *L, int idx, int n) { + StkId o; + lua_lock(L); + api_checknelems(L, 1); + o = index2adr(L, idx); + api_check(L, ttistable(o)); + setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1); + luaC_barriert(L, hvalue(o), L->top-1); + L->top--; + lua_unlock(L); +} + + +LUA_API int lua_setmetatable (lua_State *L, int objindex) { + TValue *obj; + Table *mt; + lua_lock(L); + api_checknelems(L, 1); + obj = index2adr(L, objindex); + api_checkvalidindex(L, obj); + if (ttisnil(L->top - 1)) + mt = NULL; + else { + api_check(L, ttistable(L->top - 1)); + mt = hvalue(L->top - 1); + } + switch (ttype(obj)) { + case LUA_TTABLE: { + hvalue(obj)->metatable = mt; + if (mt) + luaC_objbarriert(L, hvalue(obj), mt); + break; + } + case LUA_TUSERDATA: { + uvalue(obj)->metatable = mt; + if (mt) + luaC_objbarrier(L, rawuvalue(obj), mt); + break; + } + default: { + G(L)->mt[ttype(obj)] = mt; + break; + } + } + L->top--; + lua_unlock(L); + return 1; +} + + +LUA_API int lua_setfenv (lua_State *L, int idx) { + StkId o; + int res = 1; + lua_lock(L); + api_checknelems(L, 1); + o = index2adr(L, idx); + api_checkvalidindex(L, o); + api_check(L, ttistable(L->top - 1)); + switch (ttype(o)) { + case LUA_TFUNCTION: + clvalue(o)->c.env = hvalue(L->top - 1); + break; + case LUA_TUSERDATA: + uvalue(o)->env = hvalue(L->top - 1); + break; + case LUA_TTHREAD: + sethvalue(L, gt(thvalue(o)), hvalue(L->top - 1)); + break; + default: + res = 0; + break; + } + if (res) luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); + L->top--; + lua_unlock(L); + return res; +} + + +/* +** `load' and `call' functions (run Lua code) +*/ + + +#define adjustresults(L,nres) \ + { if (nres == LUA_MULTRET && L->top >= L->ci->top) L->ci->top = L->top; } + + +#define checkresults(L,na,nr) \ + api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na))) + + +LUA_API void lua_call (lua_State *L, int nargs, int nresults) { + StkId func; + lua_lock(L); + api_checknelems(L, nargs+1); + checkresults(L, nargs, nresults); + func = L->top - (nargs+1); + luaD_call(L, func, nresults); + adjustresults(L, nresults); + lua_unlock(L); +} + + + +/* +** Execute a protected call. +*/ +struct CallS { /* data to `f_call' */ + StkId func; + int nresults; +}; + + +static void f_call (lua_State *L, void *ud) { + struct CallS *c = cast(struct CallS *, ud); + luaD_call(L, c->func, c->nresults); +} + + + +LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) { + struct CallS c; + int status; + ptrdiff_t func; + lua_lock(L); + api_checknelems(L, nargs+1); + checkresults(L, nargs, nresults); + if (errfunc == 0) + func = 0; + else { + StkId o = index2adr(L, errfunc); + api_checkvalidindex(L, o); + func = savestack(L, o); + } + c.func = L->top - (nargs+1); /* function to be called */ + c.nresults = nresults; + status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); + adjustresults(L, nresults); + lua_unlock(L); + return status; +} + + +/* +** Execute a protected C call. +*/ +struct CCallS { /* data to `f_Ccall' */ + lua_CFunction func; + void *ud; +}; + + +static void f_Ccall (lua_State *L, void *ud) { + struct CCallS *c = cast(struct CCallS *, ud); + Closure *cl; + cl = luaF_newCclosure(L, 0, getcurrenv(L)); + cl->c.f = c->func; + setclvalue(L, L->top, cl); /* push function */ + api_incr_top(L); + setpvalue(L->top, c->ud); /* push only argument */ + api_incr_top(L); + luaD_call(L, L->top - 2, 0); +} + + +LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) { + struct CCallS c; + int status; + lua_lock(L); + c.func = func; + c.ud = ud; + status = luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0); + lua_unlock(L); + return status; +} + + +LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, + const char *chunkname) { + ZIO z; + int status; + lua_lock(L); + if (!chunkname) chunkname = "?"; + luaZ_init(L, &z, reader, data); + status = luaD_protectedparser(L, &z, chunkname); + lua_unlock(L); + return status; +} + + +LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) { + int status; + TValue *o; + lua_lock(L); + api_checknelems(L, 1); + o = L->top - 1; + if (isLfunction(o)) + status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0); + else + status = 1; + lua_unlock(L); + return status; +} + + +LUA_API int lua_status (lua_State *L) { + return L->status; +} + + +/* +** Garbage-collection function +*/ + +LUA_API int lua_gc (lua_State *L, int what, int data) { + int res = 0; + global_State *g; + lua_lock(L); + g = G(L); + switch (what) { + case LUA_GCSTOP: { + g->GCthreshold = MAX_LUMEM; + break; + } + case LUA_GCRESTART: { + g->GCthreshold = g->totalbytes; + break; + } + case LUA_GCCOLLECT: { + luaC_fullgc(L); + break; + } + case LUA_GCCOUNT: { + /* GC values are expressed in Kbytes: #bytes/2^10 */ + res = cast_int(g->totalbytes >> 10); + break; + } + case LUA_GCCOUNTB: { + res = cast_int(g->totalbytes & 0x3ff); + break; + } + case LUA_GCSTEP: { + lu_mem a = (cast(lu_mem, data) << 10); + if (a <= g->totalbytes) + g->GCthreshold = g->totalbytes - a; + else + g->GCthreshold = 0; + while (g->GCthreshold <= g->totalbytes) + luaC_step(L); + if (g->gcstate == GCSpause) /* end of cycle? */ + res = 1; /* signal it */ + break; + } + case LUA_GCSETPAUSE: { + res = g->gcpause; + g->gcpause = data; + break; + } + case LUA_GCSETSTEPMUL: { + res = g->gcstepmul; + g->gcstepmul = data; + break; + } + default: res = -1; /* invalid option */ + } + lua_unlock(L); + return res; +} + + + +/* +** miscellaneous functions +*/ + + +LUA_API int lua_error (lua_State *L) { + lua_lock(L); + api_checknelems(L, 1); + luaG_errormsg(L); + lua_unlock(L); + return 0; /* to avoid warnings */ +} + + +LUA_API int lua_next (lua_State *L, int idx) { + StkId t; + int more; + lua_lock(L); + t = index2adr(L, idx); + api_check(L, ttistable(t)); + more = luaH_next(L, hvalue(t), L->top - 1); + if (more) { + api_incr_top(L); + } + else /* no more elements */ + L->top -= 1; /* remove key */ + lua_unlock(L); + return more; +} + + +LUA_API void lua_concat (lua_State *L, int n) { + lua_lock(L); + api_checknelems(L, n); + if (n >= 2) { + luaC_checkGC(L); + luaV_concat(L, n, cast_int(L->top - L->base) - 1); + L->top -= (n-1); + } + else if (n == 0) { /* push empty string */ + setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); + api_incr_top(L); + } + /* else n == 1; nothing to do */ + lua_unlock(L); +} + + +LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { + lua_Alloc f; + lua_lock(L); + if (ud) *ud = G(L)->ud; + f = G(L)->frealloc; + lua_unlock(L); + return f; +} + + +LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) { + lua_lock(L); + G(L)->ud = ud; + G(L)->frealloc = f; + lua_unlock(L); +} + + +LUA_API void *lua_newuserdata (lua_State *L, size_t size) { + Udata *u; + lua_lock(L); + luaC_checkGC(L); + u = luaS_newudata(L, size, getcurrenv(L)); + setuvalue(L, L->top, u); + api_incr_top(L); + lua_unlock(L); + return u + 1; +} + + + + +static const char *aux_upvalue (StkId fi, int n, TValue **val) { + Closure *f; + if (!ttisfunction(fi)) return NULL; + f = clvalue(fi); + if (f->c.isC) { + if (!(1 <= n && n <= f->c.nupvalues)) return NULL; + *val = &f->c.upvalue[n-1]; + return ""; + } + else { + Proto *p = f->l.p; + if (!(1 <= n && n <= p->sizeupvalues)) return NULL; + *val = f->l.upvals[n-1]->v; + return getstr(p->upvalues[n-1]); + } +} + + +LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { + const char *name; + TValue *val; + lua_lock(L); + name = aux_upvalue(index2adr(L, funcindex), n, &val); + if (name) { + setobj2s(L, L->top, val); + api_incr_top(L); + } + lua_unlock(L); + return name; +} + + +LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { + const char *name; + TValue *val; + StkId fi; + lua_lock(L); + fi = index2adr(L, funcindex); + api_checknelems(L, 1); + name = aux_upvalue(fi, n, &val); + if (name) { + L->top--; + setobj(L, val, L->top); + luaC_barrier(L, clvalue(fi), L->top); + } + lua_unlock(L); + return name; +} + diff --git a/contrib/syslinux-4.02/com32/lua/src/lapi.h b/contrib/syslinux-4.02/com32/lua/src/lapi.h new file mode 100644 index 0000000..2c3fab2 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lapi.h @@ -0,0 +1,16 @@ +/* +** $Id: lapi.h,v 2.2.1.1 2007/12/27 13:02:25 roberto Exp $ +** Auxiliary functions from Lua API +** See Copyright Notice in lua.h +*/ + +#ifndef lapi_h +#define lapi_h + + +#include "lobject.h" + + +LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o); + +#endif diff --git a/contrib/syslinux-4.02/com32/lua/src/lauxlib.c b/contrib/syslinux-4.02/com32/lua/src/lauxlib.c new file mode 100644 index 0000000..58d196c --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lauxlib.c @@ -0,0 +1,656 @@ +/* +** $Id: lauxlib.c,v 1.159.1.3 2008/01/21 13:20:51 roberto Exp $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#include <ctype.h> +#include <errno.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + + +/* This file uses only the official API of Lua. +** Any function declared here could be written as an application function. +*/ + +#define lauxlib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" + + +#define FREELIST_REF 0 /* free list of references */ + + +/* convert a stack index to positive */ +#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ + lua_gettop(L) + (i) + 1) + + +/* +** {====================================================== +** Error-report functions +** ======================================================= +*/ + + +LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { + lua_Debug ar; + if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ + return luaL_error(L, "bad argument #%d (%s)", narg, extramsg); + lua_getinfo(L, "n", &ar); + if (strcmp(ar.namewhat, "method") == 0) { + narg--; /* do not count `self' */ + if (narg == 0) /* error is in the self argument itself? */ + return luaL_error(L, "calling " LUA_QS " on bad self (%s)", + ar.name, extramsg); + } + if (ar.name == NULL) + ar.name = "?"; + return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)", + narg, ar.name, extramsg); +} + + +LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) { + const char *msg = lua_pushfstring(L, "%s expected, got %s", + tname, luaL_typename(L, narg)); + return luaL_argerror(L, narg, msg); +} + + +static void tag_error (lua_State *L, int narg, int tag) { + luaL_typerror(L, narg, lua_typename(L, tag)); +} + + +LUALIB_API void luaL_where (lua_State *L, int level) { + lua_Debug ar; + if (lua_getstack(L, level, &ar)) { /* check function at level */ + lua_getinfo(L, "Sl", &ar); /* get info about it */ + if (ar.currentline > 0) { /* is there info? */ + lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline); + return; + } + } + lua_pushliteral(L, ""); /* else, no information available... */ +} + + +LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { + va_list argp; + va_start(argp, fmt); + luaL_where(L, 1); + lua_pushvfstring(L, fmt, argp); + va_end(argp); + lua_concat(L, 2); + return lua_error(L); +} + +/* }====================================================== */ + + +LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def, + const char *const lst[]) { + const char *name = (def) ? luaL_optstring(L, narg, def) : + luaL_checkstring(L, narg); + int i; + for (i=0; lst[i]; i++) + if (strcmp(lst[i], name) == 0) + return i; + return luaL_argerror(L, narg, + lua_pushfstring(L, "invalid option " LUA_QS, name)); +} + + +LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { + lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */ + if (!lua_isnil(L, -1)) /* name already in use? */ + return 0; /* leave previous value on top, but return 0 */ + lua_pop(L, 1); + lua_newtable(L); /* create metatable */ + lua_pushvalue(L, -1); + lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */ + return 1; +} + + +LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { + void *p = lua_touserdata(L, ud); + if (p != NULL) { /* value is a userdata? */ + if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ + lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */ + if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */ + lua_pop(L, 2); /* remove both metatables */ + return p; + } + } + } + luaL_typerror(L, ud, tname); /* else error */ + return NULL; /* to avoid warnings */ +} + + +LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) { + if (!lua_checkstack(L, space)) + luaL_error(L, "stack overflow (%s)", mes); +} + + +LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) { + if (lua_type(L, narg) != t) + tag_error(L, narg, t); +} + + +LUALIB_API void luaL_checkany (lua_State *L, int narg) { + if (lua_type(L, narg) == LUA_TNONE) + luaL_argerror(L, narg, "value expected"); +} + + +LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) { + const char *s = lua_tolstring(L, narg, len); + if (!s) tag_error(L, narg, LUA_TSTRING); + return s; +} + + +LUALIB_API const char *luaL_optlstring (lua_State *L, int narg, + const char *def, size_t *len) { + if (lua_isnoneornil(L, narg)) { + if (len) + *len = (def ? strlen(def) : 0); + return def; + } + else return luaL_checklstring(L, narg, len); +} + + +LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) { + lua_Number d = lua_tonumber(L, narg); + if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ + tag_error(L, narg, LUA_TNUMBER); + return d; +} + + +LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) { + return luaL_opt(L, luaL_checknumber, narg, def); +} + + +LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) { + lua_Integer d = lua_tointeger(L, narg); + if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ + tag_error(L, narg, LUA_TNUMBER); + return d; +} + + +LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg, + lua_Integer def) { + return luaL_opt(L, luaL_checkinteger, narg, def); +} + + +LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { + if (!lua_getmetatable(L, obj)) /* no metatable? */ + return 0; + lua_pushstring(L, event); + lua_rawget(L, -2); + if (lua_isnil(L, -1)) { + lua_pop(L, 2); /* remove metatable and metafield */ + return 0; + } + else { + lua_remove(L, -2); /* remove only metatable */ + return 1; + } +} + + +LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { + obj = abs_index(L, obj); + if (!luaL_getmetafield(L, obj, event)) /* no metafield? */ + return 0; + lua_pushvalue(L, obj); + lua_call(L, 1, 1); + return 1; +} + + +LUALIB_API void (luaL_register) (lua_State *L, const char *libname, + const luaL_Reg *l) { + luaI_openlib(L, libname, l, 0); +} + + +static int libsize (const luaL_Reg *l) { + int size = 0; + for (; l->name; l++) size++; + return size; +} + + +LUALIB_API void luaI_openlib (lua_State *L, const char *libname, + const luaL_Reg *l, int nup) { + if (libname) { + int size = libsize(l); + /* check whether lib already exists */ + luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); + lua_getfield(L, -1, libname); /* get _LOADED[libname] */ + if (!lua_istable(L, -1)) { /* not found? */ + lua_pop(L, 1); /* remove previous result */ + /* try global variable (and create one if it does not exist) */ + if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL) + luaL_error(L, "name conflict for module " LUA_QS, libname); + lua_pushvalue(L, -1); + lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */ + } + lua_remove(L, -2); /* remove _LOADED table */ + lua_insert(L, -(nup+1)); /* move library table to below upvalues */ + } + for (; l->name; l++) { + int i; + for (i=0; i<nup; i++) /* copy upvalues to the top */ + lua_pushvalue(L, -nup); + lua_pushcclosure(L, l->func, nup); + lua_setfield(L, -(nup+2), l->name); + } + lua_pop(L, nup); /* remove upvalues */ +} + + + +/* +** {====================================================== +** getn-setn: size for arrays +** ======================================================= +*/ + +#if defined(LUA_COMPAT_GETN) + +static int checkint (lua_State *L, int topop) { + int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1; + lua_pop(L, topop); + return n; +} + + +static void getsizes (lua_State *L) { + lua_getfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); + if (lua_isnil(L, -1)) { /* no `size' table? */ + lua_pop(L, 1); /* remove nil */ + lua_newtable(L); /* create it */ + lua_pushvalue(L, -1); /* `size' will be its own metatable */ + lua_setmetatable(L, -2); + lua_pushliteral(L, "kv"); + lua_setfield(L, -2, "__mode"); /* metatable(N).__mode = "kv" */ + lua_pushvalue(L, -1); + lua_setfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); /* store in register */ + } +} + + +LUALIB_API void luaL_setn (lua_State *L, int t, int n) { + t = abs_index(L, t); + lua_pushliteral(L, "n"); + lua_rawget(L, t); + if (checkint(L, 1) >= 0) { /* is there a numeric field `n'? */ + lua_pushliteral(L, "n"); /* use it */ + lua_pushinteger(L, n); + lua_rawset(L, t); + } + else { /* use `sizes' */ + getsizes(L); + lua_pushvalue(L, t); + lua_pushinteger(L, n); + lua_rawset(L, -3); /* sizes[t] = n */ + lua_pop(L, 1); /* remove `sizes' */ + } +} + + +LUALIB_API int luaL_getn (lua_State *L, int t) { + int n; + t = abs_index(L, t); + lua_pushliteral(L, "n"); /* try t.n */ + lua_rawget(L, t); + if ((n = checkint(L, 1)) >= 0) return n; + getsizes(L); /* else try sizes[t] */ + lua_pushvalue(L, t); + lua_rawget(L, -2); + if ((n = checkint(L, 2)) >= 0) return n; + return (int)lua_objlen(L, t); +} + +#endif + +/* }====================================================== */ + + + +LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, + const char *r) { + const char *wild; + size_t l = strlen(p); + luaL_Buffer b; + luaL_buffinit(L, &b); + while ((wild = strstr(s, p)) != NULL) { + luaL_addlstring(&b, s, wild - s); /* push prefix */ + luaL_addstring(&b, r); /* push replacement in place of pattern */ + s = wild + l; /* continue after `p' */ + } + luaL_addstring(&b, s); /* push last suffix */ + luaL_pushresult(&b); + return lua_tostring(L, -1); +} + + +LUALIB_API const char *luaL_findtable (lua_State *L, int idx, + const char *fname, int szhint) { + const char *e; + lua_pushvalue(L, idx); + do { + e = strchr(fname, '.'); + if (e == NULL) e = fname + strlen(fname); + lua_pushlstring(L, fname, e - fname); + lua_rawget(L, -2); + if (lua_isnil(L, -1)) { /* no such field? */ + lua_pop(L, 1); /* remove this nil */ + lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ + lua_pushlstring(L, fname, e - fname); + lua_pushvalue(L, -2); + lua_settable(L, -4); /* set new table into field */ + } + else if (!lua_istable(L, -1)) { /* field has a non-table value? */ + lua_pop(L, 2); /* remove table and value */ + return fname; /* return problematic part of the name */ + } + lua_remove(L, -2); /* remove previous table */ + fname = e + 1; + } while (*e == '.'); + return NULL; +} + + + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + + +#define bufflen(B) ((B)->p - (B)->buffer) +#define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B))) + +#define LIMIT (LUA_MINSTACK/2) + + +static int emptybuffer (luaL_Buffer *B) { + size_t l = bufflen(B); + if (l == 0) return 0; /* put nothing on stack */ + else { + lua_pushlstring(B->L, B->buffer, l); + B->p = B->buffer; + B->lvl++; + return 1; + } +} + + +static void adjuststack (luaL_Buffer *B) { + if (B->lvl > 1) { + lua_State *L = B->L; + int toget = 1; /* number of levels to concat */ + size_t toplen = lua_strlen(L, -1); + do { + size_t l = lua_strlen(L, -(toget+1)); + if (B->lvl - toget + 1 >= LIMIT || toplen > l) { + toplen += l; + toget++; + } + else break; + } while (toget < B->lvl); + lua_concat(L, toget); + B->lvl = B->lvl - toget + 1; + } +} + + +LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) { + if (emptybuffer(B)) + adjuststack(B); + return B->buffer; +} + + +LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { + while (l--) + luaL_addchar(B, *s++); +} + + +LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { + luaL_addlstring(B, s, strlen(s)); +} + + +LUALIB_API void luaL_pushresult (luaL_Buffer *B) { + emptybuffer(B); + lua_concat(B->L, B->lvl); + B->lvl = 1; +} + + +LUALIB_API void luaL_addvalue (luaL_Buffer *B) { + lua_State *L = B->L; + size_t vl; + const char *s = lua_tolstring(L, -1, &vl); + if (vl <= bufffree(B)) { /* fit into buffer? */ + memcpy(B->p, s, vl); /* put it there */ + B->p += vl; + lua_pop(L, 1); /* remove from stack */ + } + else { + if (emptybuffer(B)) + lua_insert(L, -2); /* put buffer before new value */ + B->lvl++; /* add new value into B stack */ + adjuststack(B); + } +} + + +LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { + B->L = L; + B->p = B->buffer; + B->lvl = 0; +} + +/* }====================================================== */ + + +LUALIB_API int luaL_ref (lua_State *L, int t) { + int ref; + t = abs_index(L, t); + if (lua_isnil(L, -1)) { + lua_pop(L, 1); /* remove from stack */ + return LUA_REFNIL; /* `nil' has a unique fixed reference */ + } + lua_rawgeti(L, t, FREELIST_REF); /* get first free element */ + ref = (int)lua_tointeger(L, -1); /* ref = t[FREELIST_REF] */ + lua_pop(L, 1); /* remove it from stack */ + if (ref != 0) { /* any free element? */ + lua_rawgeti(L, t, ref); /* remove it from list */ + lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */ + } + else { /* no free elements */ + ref = (int)lua_objlen(L, t); + ref++; /* create new reference */ + } + lua_rawseti(L, t, ref); + return ref; +} + + +LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { + if (ref >= 0) { + t = abs_index(L, t); + lua_rawgeti(L, t, FREELIST_REF); + lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */ + lua_pushinteger(L, ref); + lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */ + } +} + + + +/* +** {====================================================== +** Load functions +** ======================================================= +*/ + +typedef struct LoadF { + int extraline; + FILE *f; + char buff[LUAL_BUFFERSIZE]; +} LoadF; + + +static const char *getF (lua_State *L, void *ud, size_t *size) { + LoadF *lf = (LoadF *)ud; + (void)L; + if (lf->extraline) { + lf->extraline = 0; + *size = 1; + return "\n"; + } + if (feof(lf->f)) return NULL; + *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); + return (*size > 0) ? lf->buff : NULL; +} + + +static int errfile (lua_State *L, const char *what, int fnameindex) { + const char *serr = strerror(errno); + const char *filename = lua_tostring(L, fnameindex) + 1; + lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); + lua_remove(L, fnameindex); + return LUA_ERRFILE; +} + + +LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { + LoadF lf; + int status, readstatus; +#if 0 + int c; +#endif + int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ + lf.extraline = 0; + if (filename == NULL) { + lua_pushliteral(L, "=stdin"); + lf.f = stdin; + } + else { + lua_pushfstring(L, "@%s", filename); + lf.f = fopen(filename, "r"); + if (lf.f == NULL) return errfile(L, "open", fnameindex); + } +#if 0 + c = getc(lf.f); + if (c == '#') { /* Unix exec. file? */ + lf.extraline = 1; + while ((c = getc(lf.f)) != EOF && c != '\n') ; /* skip first line */ + if (c == '\n') c = getc(lf.f); + } + if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ + lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ + if (lf.f == NULL) return errfile(L, "reopen", fnameindex); + /* skip eventual `#!...' */ + while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ; + lf.extraline = 0; + } + ungetc(c, lf.f); +#endif + status = lua_load(L, getF, &lf, lua_tostring(L, -1)); + readstatus = ferror(lf.f); + if (filename) fclose(lf.f); /* close file (even in case of errors) */ + if (readstatus) { + lua_settop(L, fnameindex); /* ignore results from `lua_load' */ + return errfile(L, "read", fnameindex); + } + lua_remove(L, fnameindex); + return status; +} + + +typedef struct LoadS { + const char *s; + size_t size; +} LoadS; + + +static const char *getS (lua_State *L, void *ud, size_t *size) { + LoadS *ls = (LoadS *)ud; + (void)L; + if (ls->size == 0) return NULL; + *size = ls->size; + ls->size = 0; + return ls->s; +} + + +LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size, + const char *name) { + LoadS ls; + ls.s = buff; + ls.size = size; + return lua_load(L, getS, &ls, name); +} + + +LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) { + return luaL_loadbuffer(L, s, strlen(s), s); +} + + + +/* }====================================================== */ + + +static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { + (void)ud; + (void)osize; + if (nsize == 0) { + free(ptr); + return NULL; + } + else + return realloc(ptr, nsize); +} + + +static int panic (lua_State *L) { + (void)L; /* to avoid warnings */ + fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n", + lua_tostring(L, -1)); + return 0; +} + + +LUALIB_API lua_State *luaL_newstate (void) { + lua_State *L = lua_newstate(l_alloc, NULL); + if (L) lua_atpanic(L, &panic); + return L; +} + diff --git a/contrib/syslinux-4.02/com32/lua/src/lauxlib.h b/contrib/syslinux-4.02/com32/lua/src/lauxlib.h new file mode 100644 index 0000000..3425823 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lauxlib.h @@ -0,0 +1,174 @@ +/* +** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lauxlib_h +#define lauxlib_h + + +#include <stddef.h> +#include <stdio.h> + +#include "lua.h" + + +#if defined(LUA_COMPAT_GETN) +LUALIB_API int (luaL_getn) (lua_State *L, int t); +LUALIB_API void (luaL_setn) (lua_State *L, int t, int n); +#else +#define luaL_getn(L,i) ((int)lua_objlen(L, i)) +#define luaL_setn(L,i,j) ((void)0) /* no op! */ +#endif + +#if defined(LUA_COMPAT_OPENLIB) +#define luaI_openlib luaL_openlib +#endif + + +/* extra error code for `luaL_load' */ +#define LUA_ERRFILE (LUA_ERRERR+1) + + +typedef struct luaL_Reg { + const char *name; + lua_CFunction func; +} luaL_Reg; + + + +LUALIB_API void (luaI_openlib) (lua_State *L, const char *libname, + const luaL_Reg *l, int nup); +LUALIB_API void (luaL_register) (lua_State *L, const char *libname, + const luaL_Reg *l); +LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); +LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); +LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname); +LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); +LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, + size_t *l); +LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg, + const char *def, size_t *l); +LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg); +LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def); + +LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); +LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, + lua_Integer def); + +LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); +LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); +LUALIB_API void (luaL_checkany) (lua_State *L, int narg); + +LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); +LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); + +LUALIB_API void (luaL_where) (lua_State *L, int lvl); +LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); + +LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, + const char *const lst[]); + +LUALIB_API int (luaL_ref) (lua_State *L, int t); +LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); + +LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename); +LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, + const char *name); +LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); + +LUALIB_API lua_State *(luaL_newstate) (void); + + +LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, + const char *r); + +LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, + const char *fname, int szhint); + + + + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + +#define luaL_argcheck(L, cond,numarg,extramsg) \ + ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) +#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) +#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) +#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) +#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) +#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) +#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) + +#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) + +#define luaL_dofile(L, fn) \ + (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_dostring(L, s) \ + (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) + +#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + + + +typedef struct luaL_Buffer { + char *p; /* current position in buffer */ + int lvl; /* number of strings in the stack (level) */ + lua_State *L; + char buffer[LUAL_BUFFERSIZE]; +} luaL_Buffer; + +#define luaL_addchar(B,c) \ + ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ + (*(B)->p++ = (char)(c))) + +/* compatibility only */ +#define luaL_putchar(B,c) luaL_addchar(B,c) + +#define luaL_addsize(B,n) ((B)->p += (n)) + +LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); +LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B); +LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); +LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); +LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); +LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); + + +/* }====================================================== */ + + +/* compatibility with ref system */ + +/* pre-defined references */ +#define LUA_NOREF (-2) +#define LUA_REFNIL (-1) + +#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \ + (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0)) + +#define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref)) + +#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref)) + + +#define luaL_reg luaL_Reg + +#endif + + diff --git a/contrib/syslinux-4.02/com32/lua/src/lbaselib.c b/contrib/syslinux-4.02/com32/lua/src/lbaselib.c new file mode 100644 index 0000000..eb06bce --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lbaselib.c @@ -0,0 +1,651 @@ +/* +** $Id: lbaselib.c,v 1.191.1.4 2008/01/20 13:53:22 roberto Exp $ +** Basic library +** See Copyright Notice in lua.h +*/ + + + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define lbaselib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + + +/* +** If your system does not support `stdout', you can just remove this function. +** If you need, you can define your own `print' function, following this +** model but changing `fputs' to put the strings at a proper place +** (a console window or a log file, for instance). +*/ +static int luaB_print (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + int i; + lua_getglobal(L, "tostring"); + for (i=1; i<=n; i++) { + const char *s; + lua_pushvalue(L, -1); /* function to be called */ + lua_pushvalue(L, i); /* value to print */ + lua_call(L, 1, 1); + s = lua_tostring(L, -1); /* get result */ + if (s == NULL) + return luaL_error(L, LUA_QL("tostring") " must return a string to " + LUA_QL("print")); + if (i>1) fputs("\t", stdout); + fputs(s, stdout); + lua_pop(L, 1); /* pop result */ + } + fputs("\n", stdout); + return 0; +} + + +static int luaB_tonumber (lua_State *L) { + int base = luaL_optint(L, 2, 10); + if (base == 10) { /* standard conversion */ + luaL_checkany(L, 1); + if (lua_isnumber(L, 1)) { + lua_pushnumber(L, lua_tonumber(L, 1)); + return 1; + } + } + else { + const char *s1 = luaL_checkstring(L, 1); + char *s2; + unsigned long n; + luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); + n = strtoul(s1, &s2, base); + if (s1 != s2) { /* at least one valid digit? */ + while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */ + if (*s2 == '\0') { /* no invalid trailing characters? */ + lua_pushnumber(L, (lua_Number)n); + return 1; + } + } + } + lua_pushnil(L); /* else not a number */ + return 1; +} + + +static int luaB_error (lua_State *L) { + int level = luaL_optint(L, 2, 1); + lua_settop(L, 1); + if (lua_isstring(L, 1) && level > 0) { /* add extra information? */ + luaL_where(L, level); + lua_pushvalue(L, 1); + lua_concat(L, 2); + } + return lua_error(L); +} + + +static int luaB_getmetatable (lua_State *L) { + luaL_checkany(L, 1); + if (!lua_getmetatable(L, 1)) { + lua_pushnil(L); + return 1; /* no metatable */ + } + luaL_getmetafield(L, 1, "__metatable"); + return 1; /* returns either __metatable field (if present) or metatable */ +} + + +static int luaB_setmetatable (lua_State *L) { + int t = lua_type(L, 2); + luaL_checktype(L, 1, LUA_TTABLE); + luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, + "nil or table expected"); + if (luaL_getmetafield(L, 1, "__metatable")) + luaL_error(L, "cannot change a protected metatable"); + lua_settop(L, 2); + lua_setmetatable(L, 1); + return 1; +} + + +static void getfunc (lua_State *L, int opt) { + if (lua_isfunction(L, 1)) lua_pushvalue(L, 1); + else { + lua_Debug ar; + int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1); + luaL_argcheck(L, level >= 0, 1, "level must be non-negative"); + if (lua_getstack(L, level, &ar) == 0) + luaL_argerror(L, 1, "invalid level"); + lua_getinfo(L, "f", &ar); + if (lua_isnil(L, -1)) + luaL_error(L, "no function environment for tail call at level %d", + level); + } +} + + +static int luaB_getfenv (lua_State *L) { + getfunc(L, 1); + if (lua_iscfunction(L, -1)) /* is a C function? */ + lua_pushvalue(L, LUA_GLOBALSINDEX); /* return the thread's global env. */ + else + lua_getfenv(L, -1); + return 1; +} + + +static int luaB_setfenv (lua_State *L) { + luaL_checktype(L, 2, LUA_TTABLE); + getfunc(L, 0); + lua_pushvalue(L, 2); + if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) { + /* change environment of current thread */ + lua_pushthread(L); + lua_insert(L, -2); + lua_setfenv(L, -2); + return 0; + } + else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0) + luaL_error(L, + LUA_QL("setfenv") " cannot change environment of given object"); + return 1; +} + + +static int luaB_rawequal (lua_State *L) { + luaL_checkany(L, 1); + luaL_checkany(L, 2); + lua_pushboolean(L, lua_rawequal(L, 1, 2)); + return 1; +} + + +static int luaB_rawget (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checkany(L, 2); + lua_settop(L, 2); + lua_rawget(L, 1); + return 1; +} + +static int luaB_rawset (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checkany(L, 2); + luaL_checkany(L, 3); + lua_settop(L, 3); + lua_rawset(L, 1); + return 1; +} + + +static int luaB_gcinfo (lua_State *L) { + lua_pushinteger(L, lua_getgccount(L)); + return 1; +} + + +static int luaB_collectgarbage (lua_State *L) { + static const char *const opts[] = {"stop", "restart", "collect", + "count", "step", "setpause", "setstepmul", NULL}; + static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, + LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL}; + int o = luaL_checkoption(L, 1, "collect", opts); + int ex = luaL_optint(L, 2, 0); + int res = lua_gc(L, optsnum[o], ex); + switch (optsnum[o]) { + case LUA_GCCOUNT: { + int b = lua_gc(L, LUA_GCCOUNTB, 0); + lua_pushnumber(L, res + ((lua_Number)b/1024)); + return 1; + } + case LUA_GCSTEP: { + lua_pushboolean(L, res); + return 1; + } + default: { + lua_pushnumber(L, res); + return 1; + } + } +} + + +static int luaB_type (lua_State *L) { + luaL_checkany(L, 1); + lua_pushstring(L, luaL_typename(L, 1)); + return 1; +} + + +static int luaB_next (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 2); /* create a 2nd argument if there isn't one */ + if (lua_next(L, 1)) + return 2; + else { + lua_pushnil(L); + return 1; + } +} + + +static int luaB_pairs (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ + lua_pushvalue(L, 1); /* state, */ + lua_pushnil(L); /* and initial value */ + return 3; +} + + +static int ipairsaux (lua_State *L) { + int i = luaL_checkint(L, 2); + luaL_checktype(L, 1, LUA_TTABLE); + i++; /* next value */ + lua_pushinteger(L, i); + lua_rawgeti(L, 1, i); + return (lua_isnil(L, -1)) ? 0 : 2; +} + + +static int luaB_ipairs (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ + lua_pushvalue(L, 1); /* state, */ + lua_pushinteger(L, 0); /* and initial value */ + return 3; +} + + +static int load_aux (lua_State *L, int status) { + if (status == 0) /* OK? */ + return 1; + else { + lua_pushnil(L); + lua_insert(L, -2); /* put before error message */ + return 2; /* return nil plus error message */ + } +} + + +static int luaB_loadstring (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + const char *chunkname = luaL_optstring(L, 2, s); + return load_aux(L, luaL_loadbuffer(L, s, l, chunkname)); +} + + +static int luaB_loadfile (lua_State *L) { + const char *fname = luaL_optstring(L, 1, NULL); + return load_aux(L, luaL_loadfile(L, fname)); +} + + +/* +** Reader for generic `load' function: `lua_load' uses the +** stack for internal stuff, so the reader cannot change the +** stack top. Instead, it keeps its resulting string in a +** reserved slot inside the stack. +*/ +static const char *generic_reader (lua_State *L, void *ud, size_t *size) { + (void)ud; /* to avoid warnings */ + luaL_checkstack(L, 2, "too many nested functions"); + lua_pushvalue(L, 1); /* get function */ + lua_call(L, 0, 1); /* call it */ + if (lua_isnil(L, -1)) { + *size = 0; + return NULL; + } + else if (lua_isstring(L, -1)) { + lua_replace(L, 3); /* save string in a reserved stack slot */ + return lua_tolstring(L, 3, size); + } + else luaL_error(L, "reader function must return a string"); + return NULL; /* to avoid warnings */ +} + + +static int luaB_load (lua_State *L) { + int status; + const char *cname = luaL_optstring(L, 2, "=(load)"); + luaL_checktype(L, 1, LUA_TFUNCTION); + lua_settop(L, 3); /* function, eventual name, plus one reserved slot */ + status = lua_load(L, generic_reader, NULL, cname); + return load_aux(L, status); +} + + +static int luaB_dofile (lua_State *L) { + const char *fname = luaL_optstring(L, 1, NULL); + int n = lua_gettop(L); + if (luaL_loadfile(L, fname) != 0) lua_error(L); + lua_call(L, 0, LUA_MULTRET); + return lua_gettop(L) - n; +} + + +static int luaB_assert (lua_State *L) { + luaL_checkany(L, 1); + if (!lua_toboolean(L, 1)) + return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); + return lua_gettop(L); +} + + +static int luaB_unpack (lua_State *L) { + int i, e, n; + luaL_checktype(L, 1, LUA_TTABLE); + i = luaL_optint(L, 2, 1); + e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1)); + n = e - i + 1; /* number of elements */ + if (n <= 0) return 0; /* empty range */ + luaL_checkstack(L, n, "table too big to unpack"); + for (; i<=e; i++) /* push arg[i...e] */ + lua_rawgeti(L, 1, i); + return n; +} + + +static int luaB_select (lua_State *L) { + int n = lua_gettop(L); + if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { + lua_pushinteger(L, n-1); + return 1; + } + else { + int i = luaL_checkint(L, 1); + if (i < 0) i = n + i; + else if (i > n) i = n; + luaL_argcheck(L, 1 <= i, 1, "index out of range"); + return n - i; + } +} + + +static int luaB_pcall (lua_State *L) { + int status; + luaL_checkany(L, 1); + status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0); + lua_pushboolean(L, (status == 0)); + lua_insert(L, 1); + return lua_gettop(L); /* return status + all results */ +} + + +static int luaB_xpcall (lua_State *L) { + int status; + luaL_checkany(L, 2); + lua_settop(L, 2); + lua_insert(L, 1); /* put error function under function to be called */ + status = lua_pcall(L, 0, LUA_MULTRET, 1); + lua_pushboolean(L, (status == 0)); + lua_replace(L, 1); + return lua_gettop(L); /* return status + all results */ +} + + +static int luaB_tostring (lua_State *L) { + luaL_checkany(L, 1); + if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */ + return 1; /* use its value */ + switch (lua_type(L, 1)) { + case LUA_TNUMBER: + lua_pushstring(L, lua_tostring(L, 1)); + break; + case LUA_TSTRING: + lua_pushvalue(L, 1); + break; + case LUA_TBOOLEAN: + lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false")); + break; + case LUA_TNIL: + lua_pushliteral(L, "nil"); + break; + default: + lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1)); + break; + } + return 1; +} + + +static int luaB_newproxy (lua_State *L) { + lua_settop(L, 1); + lua_newuserdata(L, 0); /* create proxy */ + if (lua_toboolean(L, 1) == 0) + return 1; /* no metatable */ + else if (lua_isboolean(L, 1)) { + lua_newtable(L); /* create a new metatable `m' ... */ + lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */ + lua_pushboolean(L, 1); + lua_rawset(L, lua_upvalueindex(1)); /* weaktable[m] = true */ + } + else { + int validproxy = 0; /* to check if weaktable[metatable(u)] == true */ + if (lua_getmetatable(L, 1)) { + lua_rawget(L, lua_upvalueindex(1)); + validproxy = lua_toboolean(L, -1); + lua_pop(L, 1); /* remove value */ + } + luaL_argcheck(L, validproxy, 1, "boolean or proxy expected"); + lua_getmetatable(L, 1); /* metatable is valid; get it */ + } + lua_setmetatable(L, 2); + return 1; +} + + +static const luaL_Reg base_funcs[] = { + {"assert", luaB_assert}, + {"collectgarbage", luaB_collectgarbage}, + {"dofile", luaB_dofile}, + {"error", luaB_error}, + {"gcinfo", luaB_gcinfo}, + {"getfenv", luaB_getfenv}, + {"getmetatable", luaB_getmetatable}, + {"loadfile", luaB_loadfile}, + {"load", luaB_load}, + {"loadstring", luaB_loadstring}, + {"next", luaB_next}, + {"pcall", luaB_pcall}, + {"print", luaB_print}, + {"rawequal", luaB_rawequal}, + {"rawget", luaB_rawget}, + {"rawset", luaB_rawset}, + {"select", luaB_select}, + {"setfenv", luaB_setfenv}, + {"setmetatable", luaB_setmetatable}, + {"tonumber", luaB_tonumber}, + {"tostring", luaB_tostring}, + {"type", luaB_type}, + {"unpack", luaB_unpack}, + {"xpcall", luaB_xpcall}, + {NULL, NULL} +}; + + +/* +** {====================================================== +** Coroutine library +** ======================================================= +*/ + +#define CO_RUN 0 /* running */ +#define CO_SUS 1 /* suspended */ +#define CO_NOR 2 /* 'normal' (it resumed another coroutine) */ +#define CO_DEAD 3 + +static const char *const statnames[] = + {"running", "suspended", "normal", "dead"}; + +static int costatus (lua_State *L, lua_State *co) { + if (L == co) return CO_RUN; + switch (lua_status(co)) { + case LUA_YIELD: + return CO_SUS; + case 0: { + lua_Debug ar; + if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ + return CO_NOR; /* it is running */ + else if (lua_gettop(co) == 0) + return CO_DEAD; + else + return CO_SUS; /* initial state */ + } + default: /* some error occured */ + return CO_DEAD; + } +} + + +static int luaB_costatus (lua_State *L) { + lua_State *co = lua_tothread(L, 1); + luaL_argcheck(L, co, 1, "coroutine expected"); + lua_pushstring(L, statnames[costatus(L, co)]); + return 1; +} + + +static int auxresume (lua_State *L, lua_State *co, int narg) { + int status = costatus(L, co); + if (!lua_checkstack(co, narg)) + luaL_error(L, "too many arguments to resume"); + if (status != CO_SUS) { + lua_pushfstring(L, "cannot resume %s coroutine", statnames[status]); + return -1; /* error flag */ + } + lua_xmove(L, co, narg); + lua_setlevel(L, co); + status = lua_resume(co, narg); + if (status == 0 || status == LUA_YIELD) { + int nres = lua_gettop(co); + if (!lua_checkstack(L, nres)) + luaL_error(L, "too many results to resume"); + lua_xmove(co, L, nres); /* move yielded values */ + return nres; + } + else { + lua_xmove(co, L, 1); /* move error message */ + return -1; /* error flag */ + } +} + + +static int luaB_coresume (lua_State *L) { + lua_State *co = lua_tothread(L, 1); + int r; + luaL_argcheck(L, co, 1, "coroutine expected"); + r = auxresume(L, co, lua_gettop(L) - 1); + if (r < 0) { + lua_pushboolean(L, 0); + lua_insert(L, -2); + return 2; /* return false + error message */ + } + else { + lua_pushboolean(L, 1); + lua_insert(L, -(r + 1)); + return r + 1; /* return true + `resume' returns */ + } +} + + +static int luaB_auxwrap (lua_State *L) { + lua_State *co = lua_tothread(L, lua_upvalueindex(1)); + int r = auxresume(L, co, lua_gettop(L)); + if (r < 0) { + if (lua_isstring(L, -1)) { /* error object is a string? */ + luaL_where(L, 1); /* add extra info */ + lua_insert(L, -2); + lua_concat(L, 2); + } + lua_error(L); /* propagate error */ + } + return r; +} + + +static int luaB_cocreate (lua_State *L) { + lua_State *NL = lua_newthread(L); + luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, + "Lua function expected"); + lua_pushvalue(L, 1); /* move function to top */ + lua_xmove(L, NL, 1); /* move function from L to NL */ + return 1; +} + + +static int luaB_cowrap (lua_State *L) { + luaB_cocreate(L); + lua_pushcclosure(L, luaB_auxwrap, 1); + return 1; +} + + +static int luaB_yield (lua_State *L) { + return lua_yield(L, lua_gettop(L)); +} + + +static int luaB_corunning (lua_State *L) { + if (lua_pushthread(L)) + lua_pushnil(L); /* main thread is not a coroutine */ + return 1; +} + + +static const luaL_Reg co_funcs[] = { + {"create", luaB_cocreate}, + {"resume", luaB_coresume}, + {"running", luaB_corunning}, + {"status", luaB_costatus}, + {"wrap", luaB_cowrap}, + {"yield", luaB_yield}, + {NULL, NULL} +}; + +/* }====================================================== */ + + +static void auxopen (lua_State *L, const char *name, + lua_CFunction f, lua_CFunction u) { + lua_pushcfunction(L, u); + lua_pushcclosure(L, f, 1); + lua_setfield(L, -2, name); +} + + +static void base_open (lua_State *L) { + /* set global _G */ + lua_pushvalue(L, LUA_GLOBALSINDEX); + lua_setglobal(L, "_G"); + /* open lib into global table */ + luaL_register(L, "_G", base_funcs); + lua_pushliteral(L, LUA_VERSION); + lua_setglobal(L, "_VERSION"); /* set global _VERSION */ + /* `ipairs' and `pairs' need auxliliary functions as upvalues */ + auxopen(L, "ipairs", luaB_ipairs, ipairsaux); + auxopen(L, "pairs", luaB_pairs, luaB_next); + /* `newproxy' needs a weaktable as upvalue */ + lua_createtable(L, 0, 1); /* new table `w' */ + lua_pushvalue(L, -1); /* `w' will be its own metatable */ + lua_setmetatable(L, -2); + lua_pushliteral(L, "kv"); + lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */ + lua_pushcclosure(L, luaB_newproxy, 1); + lua_setglobal(L, "newproxy"); /* set global `newproxy' */ +} + + +LUALIB_API int luaopen_base (lua_State *L) { + base_open(L); + luaL_register(L, LUA_COLIBNAME, co_funcs); + return 2; +} + diff --git a/contrib/syslinux-4.02/com32/lua/src/lcode.c b/contrib/syslinux-4.02/com32/lua/src/lcode.c new file mode 100644 index 0000000..cff626b --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lcode.c @@ -0,0 +1,839 @@ +/* +** $Id: lcode.c,v 2.25.1.3 2007/12/28 15:32:23 roberto Exp $ +** Code generator for Lua +** See Copyright Notice in lua.h +*/ + + +#include <stdlib.h> + +#define lcode_c +#define LUA_CORE + +#include "lua.h" + +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "lgc.h" +#include "llex.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "ltable.h" + + +#define hasjumps(e) ((e)->t != (e)->f) + + +static int isnumeral(expdesc *e) { + return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP); +} + + +void luaK_nil (FuncState *fs, int from, int n) { + Instruction *previous; + if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ + if (fs->pc == 0) { /* function start? */ + if (from >= fs->nactvar) + return; /* positions are already clean */ + } + else { + previous = &fs->f->code[fs->pc-1]; + if (GET_OPCODE(*previous) == OP_LOADNIL) { + int pfrom = GETARG_A(*previous); + int pto = GETARG_B(*previous); + if (pfrom <= from && from <= pto+1) { /* can connect both? */ + if (from+n-1 > pto) + SETARG_B(*previous, from+n-1); + return; + } + } + } + } + luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */ +} + + +int luaK_jump (FuncState *fs) { + int jpc = fs->jpc; /* save list of jumps to here */ + int j; + fs->jpc = NO_JUMP; + j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); + luaK_concat(fs, &j, jpc); /* keep them on hold */ + return j; +} + + +void luaK_ret (FuncState *fs, int first, int nret) { + luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); +} + + +static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { + luaK_codeABC(fs, op, A, B, C); + return luaK_jump(fs); +} + + +static void fixjump (FuncState *fs, int pc, int dest) { + Instruction *jmp = &fs->f->code[pc]; + int offset = dest-(pc+1); + lua_assert(dest != NO_JUMP); + if (abs(offset) > MAXARG_sBx) + luaX_syntaxerror(fs->ls, "control structure too long"); + SETARG_sBx(*jmp, offset); +} + + +/* +** returns current `pc' and marks it as a jump target (to avoid wrong +** optimizations with consecutive instructions not in the same basic block). +*/ +int luaK_getlabel (FuncState *fs) { + fs->lasttarget = fs->pc; + return fs->pc; +} + + +static int getjump (FuncState *fs, int pc) { + int offset = GETARG_sBx(fs->f->code[pc]); + if (offset == NO_JUMP) /* point to itself represents end of list */ + return NO_JUMP; /* end of list */ + else + return (pc+1)+offset; /* turn offset into absolute position */ +} + + +static Instruction *getjumpcontrol (FuncState *fs, int pc) { + Instruction *pi = &fs->f->code[pc]; + if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) + return pi-1; + else + return pi; +} + + +/* +** check whether list has any jump that do not produce a value +** (or produce an inverted value) +*/ +static int need_value (FuncState *fs, int list) { + for (; list != NO_JUMP; list = getjump(fs, list)) { + Instruction i = *getjumpcontrol(fs, list); + if (GET_OPCODE(i) != OP_TESTSET) return 1; + } + return 0; /* not found */ +} + + +static int patchtestreg (FuncState *fs, int node, int reg) { + Instruction *i = getjumpcontrol(fs, node); + if (GET_OPCODE(*i) != OP_TESTSET) + return 0; /* cannot patch other instructions */ + if (reg != NO_REG && reg != GETARG_B(*i)) + SETARG_A(*i, reg); + else /* no register to put value or register already has the value */ + *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); + + return 1; +} + + +static void removevalues (FuncState *fs, int list) { + for (; list != NO_JUMP; list = getjump(fs, list)) + patchtestreg(fs, list, NO_REG); +} + + +static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, + int dtarget) { + while (list != NO_JUMP) { + int next = getjump(fs, list); + if (patchtestreg(fs, list, reg)) + fixjump(fs, list, vtarget); + else + fixjump(fs, list, dtarget); /* jump to default target */ + list = next; + } +} + + +static void dischargejpc (FuncState *fs) { + patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); + fs->jpc = NO_JUMP; +} + + +void luaK_patchlist (FuncState *fs, int list, int target) { + if (target == fs->pc) + luaK_patchtohere(fs, list); + else { + lua_assert(target < fs->pc); + patchlistaux(fs, list, target, NO_REG, target); + } +} + + +void luaK_patchtohere (FuncState *fs, int list) { + luaK_getlabel(fs); + luaK_concat(fs, &fs->jpc, list); +} + + +void luaK_concat (FuncState *fs, int *l1, int l2) { + if (l2 == NO_JUMP) return; + else if (*l1 == NO_JUMP) + *l1 = l2; + else { + int list = *l1; + int next; + while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ + list = next; + fixjump(fs, list, l2); + } +} + + +void luaK_checkstack (FuncState *fs, int n) { + int newstack = fs->freereg + n; + if (newstack > fs->f->maxstacksize) { + if (newstack >= MAXSTACK) + luaX_syntaxerror(fs->ls, "function or expression too complex"); + fs->f->maxstacksize = cast_byte(newstack); + } +} + + +void luaK_reserveregs (FuncState *fs, int n) { + luaK_checkstack(fs, n); + fs->freereg += n; +} + + +static void freereg (FuncState *fs, int reg) { + if (!ISK(reg) && reg >= fs->nactvar) { + fs->freereg--; + lua_assert(reg == fs->freereg); + } +} + + +static void freeexp (FuncState *fs, expdesc *e) { + if (e->k == VNONRELOC) + freereg(fs, e->u.s.info); +} + + +static int addk (FuncState *fs, TValue *k, TValue *v) { + lua_State *L = fs->L; + TValue *idx = luaH_set(L, fs->h, k); + Proto *f = fs->f; + int oldsize = f->sizek; + if (ttisnumber(idx)) { + lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v)); + return cast_int(nvalue(idx)); + } + else { /* constant not found; create a new entry */ + setnvalue(idx, cast_num(fs->nk)); + luaM_growvector(L, f->k, fs->nk, f->sizek, TValue, + MAXARG_Bx, "constant table overflow"); + while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); + setobj(L, &f->k[fs->nk], v); + luaC_barrier(L, f, v); + return fs->nk++; + } +} + + +int luaK_stringK (FuncState *fs, TString *s) { + TValue o; + setsvalue(fs->L, &o, s); + return addk(fs, &o, &o); +} + + +int luaK_numberK (FuncState *fs, lua_Number r) { + TValue o; + setnvalue(&o, r); + return addk(fs, &o, &o); +} + + +static int boolK (FuncState *fs, int b) { + TValue o; + setbvalue(&o, b); + return addk(fs, &o, &o); +} + + +static int nilK (FuncState *fs) { + TValue k, v; + setnilvalue(&v); + /* cannot use nil as key; instead use table itself to represent nil */ + sethvalue(fs->L, &k, fs->h); + return addk(fs, &k, &v); +} + + +void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { + if (e->k == VCALL) { /* expression is an open function call? */ + SETARG_C(getcode(fs, e), nresults+1); + } + else if (e->k == VVARARG) { + SETARG_B(getcode(fs, e), nresults+1); + SETARG_A(getcode(fs, e), fs->freereg); + luaK_reserveregs(fs, 1); + } +} + + +void luaK_setoneret (FuncState *fs, expdesc *e) { + if (e->k == VCALL) { /* expression is an open function call? */ + e->k = VNONRELOC; + e->u.s.info = GETARG_A(getcode(fs, e)); + } + else if (e->k == VVARARG) { + SETARG_B(getcode(fs, e), 2); + e->k = VRELOCABLE; /* can relocate its simple result */ + } +} + + +void luaK_dischargevars (FuncState *fs, expdesc *e) { + switch (e->k) { + case VLOCAL: { + e->k = VNONRELOC; + break; + } + case VUPVAL: { + e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0); + e->k = VRELOCABLE; + break; + } + case VGLOBAL: { + e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info); + e->k = VRELOCABLE; + break; + } + case VINDEXED: { + freereg(fs, e->u.s.aux); + freereg(fs, e->u.s.info); + e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux); + e->k = VRELOCABLE; + break; + } + case VVARARG: + case VCALL: { + luaK_setoneret(fs, e); + break; + } + default: break; /* there is one value available (somewhere) */ + } +} + + +static int code_label (FuncState *fs, int A, int b, int jump) { + luaK_getlabel(fs); /* those instructions may be jump targets */ + return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump); +} + + +static void discharge2reg (FuncState *fs, expdesc *e, int reg) { + luaK_dischargevars(fs, e); + switch (e->k) { + case VNIL: { + luaK_nil(fs, reg, 1); + break; + } + case VFALSE: case VTRUE: { + luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); + break; + } + case VK: { + luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info); + break; + } + case VKNUM: { + luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval)); + break; + } + case VRELOCABLE: { + Instruction *pc = &getcode(fs, e); + SETARG_A(*pc, reg); + break; + } + case VNONRELOC: { + if (reg != e->u.s.info) + luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0); + break; + } + default: { + lua_assert(e->k == VVOID || e->k == VJMP); + return; /* nothing to do... */ + } + } + e->u.s.info = reg; + e->k = VNONRELOC; +} + + +static void discharge2anyreg (FuncState *fs, expdesc *e) { + if (e->k != VNONRELOC) { + luaK_reserveregs(fs, 1); + discharge2reg(fs, e, fs->freereg-1); + } +} + + +static void exp2reg (FuncState *fs, expdesc *e, int reg) { + discharge2reg(fs, e, reg); + if (e->k == VJMP) + luaK_concat(fs, &e->t, e->u.s.info); /* put this jump in `t' list */ + if (hasjumps(e)) { + int final; /* position after whole expression */ + int p_f = NO_JUMP; /* position of an eventual LOAD false */ + int p_t = NO_JUMP; /* position of an eventual LOAD true */ + if (need_value(fs, e->t) || need_value(fs, e->f)) { + int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); + p_f = code_label(fs, reg, 0, 1); + p_t = code_label(fs, reg, 1, 0); + luaK_patchtohere(fs, fj); + } + final = luaK_getlabel(fs); + patchlistaux(fs, e->f, final, reg, p_f); + patchlistaux(fs, e->t, final, reg, p_t); + } + e->f = e->t = NO_JUMP; + e->u.s.info = reg; + e->k = VNONRELOC; +} + + +void luaK_exp2nextreg (FuncState *fs, expdesc *e) { + luaK_dischargevars(fs, e); + freeexp(fs, e); + luaK_reserveregs(fs, 1); + exp2reg(fs, e, fs->freereg - 1); +} + + +int luaK_exp2anyreg (FuncState *fs, expdesc *e) { + luaK_dischargevars(fs, e); + if (e->k == VNONRELOC) { + if (!hasjumps(e)) return e->u.s.info; /* exp is already in a register */ + if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */ + exp2reg(fs, e, e->u.s.info); /* put value on it */ + return e->u.s.info; + } + } + luaK_exp2nextreg(fs, e); /* default */ + return e->u.s.info; +} + + +void luaK_exp2val (FuncState *fs, expdesc *e) { + if (hasjumps(e)) + luaK_exp2anyreg(fs, e); + else + luaK_dischargevars(fs, e); +} + + +int luaK_exp2RK (FuncState *fs, expdesc *e) { + luaK_exp2val(fs, e); + switch (e->k) { + case VKNUM: + case VTRUE: + case VFALSE: + case VNIL: { + if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */ + e->u.s.info = (e->k == VNIL) ? nilK(fs) : + (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) : + boolK(fs, (e->k == VTRUE)); + e->k = VK; + return RKASK(e->u.s.info); + } + else break; + } + case VK: { + if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */ + return RKASK(e->u.s.info); + else break; + } + default: break; + } + /* not a constant in the right range: put it in a register */ + return luaK_exp2anyreg(fs, e); +} + + +void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { + switch (var->k) { + case VLOCAL: { + freeexp(fs, ex); + exp2reg(fs, ex, var->u.s.info); + return; + } + case VUPVAL: { + int e = luaK_exp2anyreg(fs, ex); + luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0); + break; + } + case VGLOBAL: { + int e = luaK_exp2anyreg(fs, ex); + luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info); + break; + } + case VINDEXED: { + int e = luaK_exp2RK(fs, ex); + luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e); + break; + } + default: { + lua_assert(0); /* invalid var kind to store */ + break; + } + } + freeexp(fs, ex); +} + + +void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { + int func; + luaK_exp2anyreg(fs, e); + freeexp(fs, e); + func = fs->freereg; + luaK_reserveregs(fs, 2); + luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key)); + freeexp(fs, key); + e->u.s.info = func; + e->k = VNONRELOC; +} + + +static void invertjump (FuncState *fs, expdesc *e) { + Instruction *pc = getjumpcontrol(fs, e->u.s.info); + lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && + GET_OPCODE(*pc) != OP_TEST); + SETARG_A(*pc, !(GETARG_A(*pc))); +} + + +static int jumponcond (FuncState *fs, expdesc *e, int cond) { + if (e->k == VRELOCABLE) { + Instruction ie = getcode(fs, e); + if (GET_OPCODE(ie) == OP_NOT) { + fs->pc--; /* remove previous OP_NOT */ + return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); + } + /* else go through */ + } + discharge2anyreg(fs, e); + freeexp(fs, e); + return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond); +} + + +void luaK_goiftrue (FuncState *fs, expdesc *e) { + int pc; /* pc of last jump */ + luaK_dischargevars(fs, e); + switch (e->k) { + case VK: case VKNUM: case VTRUE: { + pc = NO_JUMP; /* always true; do nothing */ + break; + } + case VFALSE: { + pc = luaK_jump(fs); /* always jump */ + break; + } + case VJMP: { + invertjump(fs, e); + pc = e->u.s.info; + break; + } + default: { + pc = jumponcond(fs, e, 0); + break; + } + } + luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ + luaK_patchtohere(fs, e->t); + e->t = NO_JUMP; +} + + +static void luaK_goiffalse (FuncState *fs, expdesc *e) { + int pc; /* pc of last jump */ + luaK_dischargevars(fs, e); + switch (e->k) { + case VNIL: case VFALSE: { + pc = NO_JUMP; /* always false; do nothing */ + break; + } + case VTRUE: { + pc = luaK_jump(fs); /* always jump */ + break; + } + case VJMP: { + pc = e->u.s.info; + break; + } + default: { + pc = jumponcond(fs, e, 1); + break; + } + } + luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ + luaK_patchtohere(fs, e->f); + e->f = NO_JUMP; +} + + +static void codenot (FuncState *fs, expdesc *e) { + luaK_dischargevars(fs, e); + switch (e->k) { + case VNIL: case VFALSE: { + e->k = VTRUE; + break; + } + case VK: case VKNUM: case VTRUE: { + e->k = VFALSE; + break; + } + case VJMP: { + invertjump(fs, e); + break; + } + case VRELOCABLE: + case VNONRELOC: { + discharge2anyreg(fs, e); + freeexp(fs, e); + e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0); + e->k = VRELOCABLE; + break; + } + default: { + lua_assert(0); /* cannot happen */ + break; + } + } + /* interchange true and false lists */ + { int temp = e->f; e->f = e->t; e->t = temp; } + removevalues(fs, e->f); + removevalues(fs, e->t); +} + + +void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { + t->u.s.aux = luaK_exp2RK(fs, k); + t->k = VINDEXED; +} + + +static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { + lua_Number v1, v2, r; + if (!isnumeral(e1) || !isnumeral(e2)) return 0; + v1 = e1->u.nval; + v2 = e2->u.nval; + switch (op) { + case OP_ADD: r = luai_numadd(v1, v2); break; + case OP_SUB: r = luai_numsub(v1, v2); break; + case OP_MUL: r = luai_nummul(v1, v2); break; + case OP_DIV: + if (v2 == 0) return 0; /* do not attempt to divide by 0 */ + r = luai_numdiv(v1, v2); break; + case OP_MOD: + if (v2 == 0) return 0; /* do not attempt to divide by 0 */ + r = luai_nummod(v1, v2); break; + case OP_POW: r = luai_numpow(v1, v2); break; + case OP_UNM: r = luai_numunm(v1); break; + case OP_LEN: return 0; /* no constant folding for 'len' */ + default: lua_assert(0); r = 0; break; + } + if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */ + e1->u.nval = r; + return 1; +} + + +static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { + if (constfolding(op, e1, e2)) + return; + else { + int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0; + int o1 = luaK_exp2RK(fs, e1); + if (o1 > o2) { + freeexp(fs, e1); + freeexp(fs, e2); + } + else { + freeexp(fs, e2); + freeexp(fs, e1); + } + e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2); + e1->k = VRELOCABLE; + } +} + + +static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1, + expdesc *e2) { + int o1 = luaK_exp2RK(fs, e1); + int o2 = luaK_exp2RK(fs, e2); + freeexp(fs, e2); + freeexp(fs, e1); + if (cond == 0 && op != OP_EQ) { + int temp; /* exchange args to replace by `<' or `<=' */ + temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ + cond = 1; + } + e1->u.s.info = condjump(fs, op, cond, o1, o2); + e1->k = VJMP; +} + + +void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { + expdesc e2; + e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; + switch (op) { + case OPR_MINUS: { + if (!isnumeral(e)) + luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */ + codearith(fs, OP_UNM, e, &e2); + break; + } + case OPR_NOT: codenot(fs, e); break; + case OPR_LEN: { + luaK_exp2anyreg(fs, e); /* cannot operate on constants */ + codearith(fs, OP_LEN, e, &e2); + break; + } + default: lua_assert(0); + } +} + + +void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { + switch (op) { + case OPR_AND: { + luaK_goiftrue(fs, v); + break; + } + case OPR_OR: { + luaK_goiffalse(fs, v); + break; + } + case OPR_CONCAT: { + luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ + break; + } + case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: + case OPR_MOD: case OPR_POW: { + if (!isnumeral(v)) luaK_exp2RK(fs, v); + break; + } + default: { + luaK_exp2RK(fs, v); + break; + } + } +} + + +void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { + switch (op) { + case OPR_AND: { + lua_assert(e1->t == NO_JUMP); /* list must be closed */ + luaK_dischargevars(fs, e2); + luaK_concat(fs, &e2->f, e1->f); + *e1 = *e2; + break; + } + case OPR_OR: { + lua_assert(e1->f == NO_JUMP); /* list must be closed */ + luaK_dischargevars(fs, e2); + luaK_concat(fs, &e2->t, e1->t); + *e1 = *e2; + break; + } + case OPR_CONCAT: { + luaK_exp2val(fs, e2); + if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { + lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1); + freeexp(fs, e1); + SETARG_B(getcode(fs, e2), e1->u.s.info); + e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info; + } + else { + luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ + codearith(fs, OP_CONCAT, e1, e2); + } + break; + } + case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break; + case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break; + case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break; + case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break; + case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break; + case OPR_POW: codearith(fs, OP_POW, e1, e2); break; + case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break; + case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break; + case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break; + case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break; + case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break; + case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break; + default: lua_assert(0); + } +} + + +void luaK_fixline (FuncState *fs, int line) { + fs->f->lineinfo[fs->pc - 1] = line; +} + + +static int luaK_code (FuncState *fs, Instruction i, int line) { + Proto *f = fs->f; + dischargejpc(fs); /* `pc' will change */ + /* put new instruction in code array */ + luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, + MAX_INT, "code size overflow"); + f->code[fs->pc] = i; + /* save corresponding line information */ + luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int, + MAX_INT, "code size overflow"); + f->lineinfo[fs->pc] = line; + return fs->pc++; +} + + +int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { + lua_assert(getOpMode(o) == iABC); + lua_assert(getBMode(o) != OpArgN || b == 0); + lua_assert(getCMode(o) != OpArgN || c == 0); + return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline); +} + + +int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { + lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); + lua_assert(getCMode(o) == OpArgN); + return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline); +} + + +void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { + int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; + int b = (tostore == LUA_MULTRET) ? 0 : tostore; + lua_assert(tostore != 0); + if (c <= MAXARG_C) + luaK_codeABC(fs, OP_SETLIST, base, b, c); + else { + luaK_codeABC(fs, OP_SETLIST, base, b, 0); + luaK_code(fs, cast(Instruction, c), fs->ls->lastline); + } + fs->freereg = base + 1; /* free registers with list values */ +} + diff --git a/contrib/syslinux-4.02/com32/lua/src/lcode.h b/contrib/syslinux-4.02/com32/lua/src/lcode.h new file mode 100644 index 0000000..b941c60 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lcode.h @@ -0,0 +1,76 @@ +/* +** $Id: lcode.h,v 1.48.1.1 2007/12/27 13:02:25 roberto Exp $ +** Code generator for Lua +** See Copyright Notice in lua.h +*/ + +#ifndef lcode_h +#define lcode_h + +#include "llex.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" + + +/* +** Marks the end of a patch list. It is an invalid value both as an absolute +** address, and as a list link (would link an element to itself). +*/ +#define NO_JUMP (-1) + + +/* +** grep "ORDER OPR" if you change these enums +*/ +typedef enum BinOpr { + OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW, + OPR_CONCAT, + OPR_NE, OPR_EQ, + OPR_LT, OPR_LE, OPR_GT, OPR_GE, + OPR_AND, OPR_OR, + OPR_NOBINOPR +} BinOpr; + + +typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; + + +#define getcode(fs,e) ((fs)->f->code[(e)->u.s.info]) + +#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) + +#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) + +LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); +LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); +LUAI_FUNC void luaK_fixline (FuncState *fs, int line); +LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); +LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); +LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); +LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); +LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r); +LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); +LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); +LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); +LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); +LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); +LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); +LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); +LUAI_FUNC int luaK_jump (FuncState *fs); +LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); +LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); +LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); +LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); +LUAI_FUNC int luaK_getlabel (FuncState *fs); +LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v); +LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); +LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2); +LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); + + +#endif diff --git a/contrib/syslinux-4.02/com32/lua/src/ldblib.c b/contrib/syslinux-4.02/com32/lua/src/ldblib.c new file mode 100644 index 0000000..67de122 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/ldblib.c @@ -0,0 +1,397 @@ +/* +** $Id: ldblib.c,v 1.104.1.3 2008/01/21 13:11:21 roberto Exp $ +** Interface from Lua to its debug API +** See Copyright Notice in lua.h +*/ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define ldblib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + +static int db_getregistry (lua_State *L) { + lua_pushvalue(L, LUA_REGISTRYINDEX); + return 1; +} + + +static int db_getmetatable (lua_State *L) { + luaL_checkany(L, 1); + if (!lua_getmetatable(L, 1)) { + lua_pushnil(L); /* no metatable */ + } + return 1; +} + + +static int db_setmetatable (lua_State *L) { + int t = lua_type(L, 2); + luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, + "nil or table expected"); + lua_settop(L, 2); + lua_pushboolean(L, lua_setmetatable(L, 1)); + return 1; +} + + +static int db_getfenv (lua_State *L) { + lua_getfenv(L, 1); + return 1; +} + + +static int db_setfenv (lua_State *L) { + luaL_checktype(L, 2, LUA_TTABLE); + lua_settop(L, 2); + if (lua_setfenv(L, 1) == 0) + luaL_error(L, LUA_QL("setfenv") + " cannot change environment of given object"); + return 1; +} + + +static void settabss (lua_State *L, const char *i, const char *v) { + lua_pushstring(L, v); + lua_setfield(L, -2, i); +} + + +static void settabsi (lua_State *L, const char *i, int v) { + lua_pushinteger(L, v); + lua_setfield(L, -2, i); +} + + +static lua_State *getthread (lua_State *L, int *arg) { + if (lua_isthread(L, 1)) { + *arg = 1; + return lua_tothread(L, 1); + } + else { + *arg = 0; + return L; + } +} + + +static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) { + if (L == L1) { + lua_pushvalue(L, -2); + lua_remove(L, -3); + } + else + lua_xmove(L1, L, 1); + lua_setfield(L, -2, fname); +} + + +static int db_getinfo (lua_State *L) { + lua_Debug ar; + int arg; + lua_State *L1 = getthread(L, &arg); + const char *options = luaL_optstring(L, arg+2, "flnSu"); + if (lua_isnumber(L, arg+1)) { + if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) { + lua_pushnil(L); /* level out of range */ + return 1; + } + } + else if (lua_isfunction(L, arg+1)) { + lua_pushfstring(L, ">%s", options); + options = lua_tostring(L, -1); + lua_pushvalue(L, arg+1); + lua_xmove(L, L1, 1); + } + else + return luaL_argerror(L, arg+1, "function or level expected"); + if (!lua_getinfo(L1, options, &ar)) + return luaL_argerror(L, arg+2, "invalid option"); + lua_createtable(L, 0, 2); + if (strchr(options, 'S')) { + settabss(L, "source", ar.source); + settabss(L, "short_src", ar.short_src); + settabsi(L, "linedefined", ar.linedefined); + settabsi(L, "lastlinedefined", ar.lastlinedefined); + settabss(L, "what", ar.what); + } + if (strchr(options, 'l')) + settabsi(L, "currentline", ar.currentline); + if (strchr(options, 'u')) + settabsi(L, "nups", ar.nups); + if (strchr(options, 'n')) { + settabss(L, "name", ar.name); + settabss(L, "namewhat", ar.namewhat); + } + if (strchr(options, 'L')) + treatstackoption(L, L1, "activelines"); + if (strchr(options, 'f')) + treatstackoption(L, L1, "func"); + return 1; /* return table */ +} + + +static int db_getlocal (lua_State *L) { + int arg; + lua_State *L1 = getthread(L, &arg); + lua_Debug ar; + const char *name; + if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ + return luaL_argerror(L, arg+1, "level out of range"); + name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2)); + if (name) { + lua_xmove(L1, L, 1); + lua_pushstring(L, name); + lua_pushvalue(L, -2); + return 2; + } + else { + lua_pushnil(L); + return 1; + } +} + + +static int db_setlocal (lua_State *L) { + int arg; + lua_State *L1 = getthread(L, &arg); + lua_Debug ar; + if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ + return luaL_argerror(L, arg+1, "level out of range"); + luaL_checkany(L, arg+3); + lua_settop(L, arg+3); + lua_xmove(L, L1, 1); + lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2))); + return 1; +} + + +static int auxupvalue (lua_State *L, int get) { + const char *name; + int n = luaL_checkint(L, 2); + luaL_checktype(L, 1, LUA_TFUNCTION); + if (lua_iscfunction(L, 1)) return 0; /* cannot touch C upvalues from Lua */ + name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); + if (name == NULL) return 0; + lua_pushstring(L, name); + lua_insert(L, -(get+1)); + return get + 1; +} + + +static int db_getupvalue (lua_State *L) { + return auxupvalue(L, 1); +} + + +static int db_setupvalue (lua_State *L) { + luaL_checkany(L, 3); + return auxupvalue(L, 0); +} + + + +static const char KEY_HOOK = 'h'; + + +static void hookf (lua_State *L, lua_Debug *ar) { + static const char *const hooknames[] = + {"call", "return", "line", "count", "tail return"}; + lua_pushlightuserdata(L, (void *)&KEY_HOOK); + lua_rawget(L, LUA_REGISTRYINDEX); + lua_pushlightuserdata(L, L); + lua_rawget(L, -2); + if (lua_isfunction(L, -1)) { + lua_pushstring(L, hooknames[(int)ar->event]); + if (ar->currentline >= 0) + lua_pushinteger(L, ar->currentline); + else lua_pushnil(L); + lua_assert(lua_getinfo(L, "lS", ar)); + lua_call(L, 2, 0); + } +} + + +static int makemask (const char *smask, int count) { + int mask = 0; + if (strchr(smask, 'c')) mask |= LUA_MASKCALL; + if (strchr(smask, 'r')) mask |= LUA_MASKRET; + if (strchr(smask, 'l')) mask |= LUA_MASKLINE; + if (count > 0) mask |= LUA_MASKCOUNT; + return mask; +} + + +static char *unmakemask (int mask, char *smask) { + int i = 0; + if (mask & LUA_MASKCALL) smask[i++] = 'c'; + if (mask & LUA_MASKRET) smask[i++] = 'r'; + if (mask & LUA_MASKLINE) smask[i++] = 'l'; + smask[i] = '\0'; + return smask; +} + + +static void gethooktable (lua_State *L) { + lua_pushlightuserdata(L, (void *)&KEY_HOOK); + lua_rawget(L, LUA_REGISTRYINDEX); + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + lua_createtable(L, 0, 1); + lua_pushlightuserdata(L, (void *)&KEY_HOOK); + lua_pushvalue(L, -2); + lua_rawset(L, LUA_REGISTRYINDEX); + } +} + + +static int db_sethook (lua_State *L) { + int arg, mask, count; + lua_Hook func; + lua_State *L1 = getthread(L, &arg); + if (lua_isnoneornil(L, arg+1)) { + lua_settop(L, arg+1); + func = NULL; mask = 0; count = 0; /* turn off hooks */ + } + else { + const char *smask = luaL_checkstring(L, arg+2); + luaL_checktype(L, arg+1, LUA_TFUNCTION); + count = luaL_optint(L, arg+3, 0); + func = hookf; mask = makemask(smask, count); + } + gethooktable(L); + lua_pushlightuserdata(L, L1); + lua_pushvalue(L, arg+1); + lua_rawset(L, -3); /* set new hook */ + lua_pop(L, 1); /* remove hook table */ + lua_sethook(L1, func, mask, count); /* set hooks */ + return 0; +} + + +static int db_gethook (lua_State *L) { + int arg; + lua_State *L1 = getthread(L, &arg); + char buff[5]; + int mask = lua_gethookmask(L1); + lua_Hook hook = lua_gethook(L1); + if (hook != NULL && hook != hookf) /* external hook? */ + lua_pushliteral(L, "external hook"); + else { + gethooktable(L); + lua_pushlightuserdata(L, L1); + lua_rawget(L, -2); /* get hook */ + lua_remove(L, -2); /* remove hook table */ + } + lua_pushstring(L, unmakemask(mask, buff)); + lua_pushinteger(L, lua_gethookcount(L1)); + return 3; +} + + +static int db_debug (lua_State *L) { + for (;;) { + char buffer[250]; + fputs("lua_debug> ", stderr); + if (fgets(buffer, sizeof(buffer), stdin) == 0 || + strcmp(buffer, "cont\n") == 0) + return 0; + if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") || + lua_pcall(L, 0, 0, 0)) { + fputs(lua_tostring(L, -1), stderr); + fputs("\n", stderr); + } + lua_settop(L, 0); /* remove eventual returns */ + } +} + + +#define LEVELS1 12 /* size of the first part of the stack */ +#define LEVELS2 10 /* size of the second part of the stack */ + +static int db_errorfb (lua_State *L) { + int level; + int firstpart = 1; /* still before eventual `...' */ + int arg; + lua_State *L1 = getthread(L, &arg); + lua_Debug ar; + if (lua_isnumber(L, arg+2)) { + level = (int)lua_tointeger(L, arg+2); + lua_pop(L, 1); + } + else + level = (L == L1) ? 1 : 0; /* level 0 may be this own function */ + if (lua_gettop(L) == arg) + lua_pushliteral(L, ""); + else if (!lua_isstring(L, arg+1)) return 1; /* message is not a string */ + else lua_pushliteral(L, "\n"); + lua_pushliteral(L, "stack traceback:"); + while (lua_getstack(L1, level++, &ar)) { + if (level > LEVELS1 && firstpart) { + /* no more than `LEVELS2' more levels? */ + if (!lua_getstack(L1, level+LEVELS2, &ar)) + level--; /* keep going */ + else { + lua_pushliteral(L, "\n\t..."); /* too many levels */ + while (lua_getstack(L1, level+LEVELS2, &ar)) /* find last levels */ + level++; + } + firstpart = 0; + continue; + } + lua_pushliteral(L, "\n\t"); + lua_getinfo(L1, "Snl", &ar); + lua_pushfstring(L, "%s:", ar.short_src); + if (ar.currentline > 0) + lua_pushfstring(L, "%d:", ar.currentline); + if (*ar.namewhat != '\0') /* is there a name? */ + lua_pushfstring(L, " in function " LUA_QS, ar.name); + else { + if (*ar.what == 'm') /* main? */ + lua_pushfstring(L, " in main chunk"); + else if (*ar.what == 'C' || *ar.what == 't') + lua_pushliteral(L, " ?"); /* C function or tail call */ + else + lua_pushfstring(L, " in function <%s:%d>", + ar.short_src, ar.linedefined); + } + lua_concat(L, lua_gettop(L) - arg); + } + lua_concat(L, lua_gettop(L) - arg); + return 1; +} + + +static const luaL_Reg dblib[] = { + {"debug", db_debug}, + {"getfenv", db_getfenv}, + {"gethook", db_gethook}, + {"getinfo", db_getinfo}, + {"getlocal", db_getlocal}, + {"getregistry", db_getregistry}, + {"getmetatable", db_getmetatable}, + {"getupvalue", db_getupvalue}, + {"setfenv", db_setfenv}, + {"sethook", db_sethook}, + {"setlocal", db_setlocal}, + {"setmetatable", db_setmetatable}, + {"setupvalue", db_setupvalue}, + {"traceback", db_errorfb}, + {NULL, NULL} +}; + + +LUALIB_API int luaopen_debug (lua_State *L) { + luaL_register(L, LUA_DBLIBNAME, dblib); + return 1; +} + diff --git a/contrib/syslinux-4.02/com32/lua/src/ldebug.c b/contrib/syslinux-4.02/com32/lua/src/ldebug.c new file mode 100644 index 0000000..9eac4a9 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/ldebug.c @@ -0,0 +1,622 @@ +/* +** $Id: ldebug.c,v 2.29.1.3 2007/12/28 15:32:23 roberto Exp $ +** Debug Interface +** See Copyright Notice in lua.h +*/ + + +#include <stdarg.h> +#include <stddef.h> +#include <string.h> + + +#define ldebug_c +#define LUA_CORE + +#include "lua.h" + +#include "lapi.h" +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lvm.h" + + + +static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); + + +static int currentpc (lua_State *L, CallInfo *ci) { + if (!isLua(ci)) return -1; /* function is not a Lua function? */ + if (ci == L->ci) + ci->savedpc = L->savedpc; + return pcRel(ci->savedpc, ci_func(ci)->l.p); +} + + +static int currentline (lua_State *L, CallInfo *ci) { + int pc = currentpc(L, ci); + if (pc < 0) + return -1; /* only active lua functions have current-line information */ + else + return getline(ci_func(ci)->l.p, pc); +} + + +/* +** this function can be called asynchronous (e.g. during a signal) +*/ +LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { + if (func == NULL || mask == 0) { /* turn off hooks? */ + mask = 0; + func = NULL; + } + L->hook = func; + L->basehookcount = count; + resethookcount(L); + L->hookmask = cast_byte(mask); + return 1; +} + + +LUA_API lua_Hook lua_gethook (lua_State *L) { + return L->hook; +} + + +LUA_API int lua_gethookmask (lua_State *L) { + return L->hookmask; +} + + +LUA_API int lua_gethookcount (lua_State *L) { + return L->basehookcount; +} + + +LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { + int status; + CallInfo *ci; + lua_lock(L); + for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) { + level--; + if (f_isLua(ci)) /* Lua function? */ + level -= ci->tailcalls; /* skip lost tail calls */ + } + if (level == 0 && ci > L->base_ci) { /* level found? */ + status = 1; + ar->i_ci = cast_int(ci - L->base_ci); + } + else if (level < 0) { /* level is of a lost tail call? */ + status = 1; + ar->i_ci = 0; + } + else status = 0; /* no such level */ + lua_unlock(L); + return status; +} + + +static Proto *getluaproto (CallInfo *ci) { + return (isLua(ci) ? ci_func(ci)->l.p : NULL); +} + + +static const char *findlocal (lua_State *L, CallInfo *ci, int n) { + const char *name; + Proto *fp = getluaproto(ci); + if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL) + return name; /* is a local variable in a Lua function */ + else { + StkId limit = (ci == L->ci) ? L->top : (ci+1)->func; + if (limit - ci->base >= n && n > 0) /* is 'n' inside 'ci' stack? */ + return "(*temporary)"; + else + return NULL; + } +} + + +LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { + CallInfo *ci = L->base_ci + ar->i_ci; + const char *name = findlocal(L, ci, n); + lua_lock(L); + if (name) + luaA_pushobject(L, ci->base + (n - 1)); + lua_unlock(L); + return name; +} + + +LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { + CallInfo *ci = L->base_ci + ar->i_ci; + const char *name = findlocal(L, ci, n); + lua_lock(L); + if (name) + setobjs2s(L, ci->base + (n - 1), L->top - 1); + L->top--; /* pop value */ + lua_unlock(L); + return name; +} + + +static void funcinfo (lua_Debug *ar, Closure *cl) { + if (cl->c.isC) { + ar->source = "=[C]"; + ar->linedefined = -1; + ar->lastlinedefined = -1; + ar->what = "C"; + } + else { + ar->source = getstr(cl->l.p->source); + ar->linedefined = cl->l.p->linedefined; + ar->lastlinedefined = cl->l.p->lastlinedefined; + ar->what = (ar->linedefined == 0) ? "main" : "Lua"; + } + luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); +} + + +static void info_tailcall (lua_Debug *ar) { + ar->name = ar->namewhat = ""; + ar->what = "tail"; + ar->lastlinedefined = ar->linedefined = ar->currentline = -1; + ar->source = "=(tail call)"; + luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); + ar->nups = 0; +} + + +static void collectvalidlines (lua_State *L, Closure *f) { + if (f == NULL || f->c.isC) { + setnilvalue(L->top); + } + else { + Table *t = luaH_new(L, 0, 0); + int *lineinfo = f->l.p->lineinfo; + int i; + for (i=0; i<f->l.p->sizelineinfo; i++) + setbvalue(luaH_setnum(L, t, lineinfo[i]), 1); + sethvalue(L, L->top, t); + } + incr_top(L); +} + + +static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, + Closure *f, CallInfo *ci) { + int status = 1; + if (f == NULL) { + info_tailcall(ar); + return status; + } + for (; *what; what++) { + switch (*what) { + case 'S': { + funcinfo(ar, f); + break; + } + case 'l': { + ar->currentline = (ci) ? currentline(L, ci) : -1; + break; + } + case 'u': { + ar->nups = f->c.nupvalues; + break; + } + case 'n': { + ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL; + if (ar->namewhat == NULL) { + ar->namewhat = ""; /* not found */ + ar->name = NULL; + } + break; + } + case 'L': + case 'f': /* handled by lua_getinfo */ + break; + default: status = 0; /* invalid option */ + } + } + return status; +} + + +LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { + int status; + Closure *f = NULL; + CallInfo *ci = NULL; + lua_lock(L); + if (*what == '>') { + StkId func = L->top - 1; + luai_apicheck(L, ttisfunction(func)); + what++; /* skip the '>' */ + f = clvalue(func); + L->top--; /* pop function */ + } + else if (ar->i_ci != 0) { /* no tail call? */ + ci = L->base_ci + ar->i_ci; + lua_assert(ttisfunction(ci->func)); + f = clvalue(ci->func); + } + status = auxgetinfo(L, what, ar, f, ci); + if (strchr(what, 'f')) { + if (f == NULL) setnilvalue(L->top); + else setclvalue(L, L->top, f); + incr_top(L); + } + if (strchr(what, 'L')) + collectvalidlines(L, f); + lua_unlock(L); + return status; +} + + +/* +** {====================================================== +** Symbolic Execution and code checker +** ======================================================= +*/ + +#define check(x) if (!(x)) return 0; + +#define checkjump(pt,pc) check(0 <= pc && pc < pt->sizecode) + +#define checkreg(pt,reg) check((reg) < (pt)->maxstacksize) + + + +static int precheck (const Proto *pt) { + check(pt->maxstacksize <= MAXSTACK); + lua_assert(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize); + lua_assert(!(pt->is_vararg & VARARG_NEEDSARG) || + (pt->is_vararg & VARARG_HASARG)); + check(pt->sizeupvalues <= pt->nups); + check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0); + check(GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN); + return 1; +} + + +#define checkopenop(pt,pc) luaG_checkopenop((pt)->code[(pc)+1]) + +int luaG_checkopenop (Instruction i) { + switch (GET_OPCODE(i)) { + case OP_CALL: + case OP_TAILCALL: + case OP_RETURN: + case OP_SETLIST: { + check(GETARG_B(i) == 0); + return 1; + } + default: return 0; /* invalid instruction after an open call */ + } +} + + +static int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) { + switch (mode) { + case OpArgN: check(r == 0); break; + case OpArgU: break; + case OpArgR: checkreg(pt, r); break; + case OpArgK: + check(ISK(r) ? INDEXK(r) < pt->sizek : r < pt->maxstacksize); + break; + } + return 1; +} + + +static Instruction symbexec (const Proto *pt, int lastpc, int reg) { + int pc; + int last; /* stores position of last instruction that changed `reg' */ + last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */ + check(precheck(pt)); + for (pc = 0; pc < lastpc; pc++) { + Instruction i = pt->code[pc]; + OpCode op = GET_OPCODE(i); + int a = GETARG_A(i); + int b = 0; + int c = 0; + check(op < NUM_OPCODES); + checkreg(pt, a); + switch (getOpMode(op)) { + case iABC: { + b = GETARG_B(i); + c = GETARG_C(i); + check(checkArgMode(pt, b, getBMode(op))); + check(checkArgMode(pt, c, getCMode(op))); + break; + } + case iABx: { + b = GETARG_Bx(i); + if (getBMode(op) == OpArgK) check(b < pt->sizek); + break; + } + case iAsBx: { + b = GETARG_sBx(i); + if (getBMode(op) == OpArgR) { + int dest = pc+1+b; + check(0 <= dest && dest < pt->sizecode); + if (dest > 0) { + /* cannot jump to a setlist count */ + Instruction d = pt->code[dest-1]; + check(!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)); + } + } + break; + } + } + if (testAMode(op)) { + if (a == reg) last = pc; /* change register `a' */ + } + if (testTMode(op)) { + check(pc+2 < pt->sizecode); /* check skip */ + check(GET_OPCODE(pt->code[pc+1]) == OP_JMP); + } + switch (op) { + case OP_LOADBOOL: { + check(c == 0 || pc+2 < pt->sizecode); /* check its jump */ + break; + } + case OP_LOADNIL: { + if (a <= reg && reg <= b) + last = pc; /* set registers from `a' to `b' */ + break; + } + case OP_GETUPVAL: + case OP_SETUPVAL: { + check(b < pt->nups); + break; + } + case OP_GETGLOBAL: + case OP_SETGLOBAL: { + check(ttisstring(&pt->k[b])); + break; + } + case OP_SELF: { + checkreg(pt, a+1); + if (reg == a+1) last = pc; + break; + } + case OP_CONCAT: { + check(b < c); /* at least two operands */ + break; + } + case OP_TFORLOOP: { + check(c >= 1); /* at least one result (control variable) */ + checkreg(pt, a+2+c); /* space for results */ + if (reg >= a+2) last = pc; /* affect all regs above its base */ + break; + } + case OP_FORLOOP: + case OP_FORPREP: + checkreg(pt, a+3); + /* go through */ + case OP_JMP: { + int dest = pc+1+b; + /* not full check and jump is forward and do not skip `lastpc'? */ + if (reg != NO_REG && pc < dest && dest <= lastpc) + pc += b; /* do the jump */ + break; + } + case OP_CALL: + case OP_TAILCALL: { + if (b != 0) { + checkreg(pt, a+b-1); + } + c--; /* c = num. returns */ + if (c == LUA_MULTRET) { + check(checkopenop(pt, pc)); + } + else if (c != 0) + checkreg(pt, a+c-1); + if (reg >= a) last = pc; /* affect all registers above base */ + break; + } + case OP_RETURN: { + b--; /* b = num. returns */ + if (b > 0) checkreg(pt, a+b-1); + break; + } + case OP_SETLIST: { + if (b > 0) checkreg(pt, a + b); + if (c == 0) pc++; + break; + } + case OP_CLOSURE: { + int nup, j; + check(b < pt->sizep); + nup = pt->p[b]->nups; + check(pc + nup < pt->sizecode); + for (j = 1; j <= nup; j++) { + OpCode op1 = GET_OPCODE(pt->code[pc + j]); + check(op1 == OP_GETUPVAL || op1 == OP_MOVE); + } + if (reg != NO_REG) /* tracing? */ + pc += nup; /* do not 'execute' these pseudo-instructions */ + break; + } + case OP_VARARG: { + check((pt->is_vararg & VARARG_ISVARARG) && + !(pt->is_vararg & VARARG_NEEDSARG)); + b--; + if (b == LUA_MULTRET) check(checkopenop(pt, pc)); + checkreg(pt, a+b-1); + break; + } + default: break; + } + } + return pt->code[last]; +} + +#undef check +#undef checkjump +#undef checkreg + +/* }====================================================== */ + + +int luaG_checkcode (const Proto *pt) { + return (symbexec(pt, pt->sizecode, NO_REG) != 0); +} + + +static const char *kname (Proto *p, int c) { + if (ISK(c) && ttisstring(&p->k[INDEXK(c)])) + return svalue(&p->k[INDEXK(c)]); + else + return "?"; +} + + +static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos, + const char **name) { + if (isLua(ci)) { /* a Lua function? */ + Proto *p = ci_func(ci)->l.p; + int pc = currentpc(L, ci); + Instruction i; + *name = luaF_getlocalname(p, stackpos+1, pc); + if (*name) /* is a local? */ + return "local"; + i = symbexec(p, pc, stackpos); /* try symbolic execution */ + lua_assert(pc != -1); + switch (GET_OPCODE(i)) { + case OP_GETGLOBAL: { + int g = GETARG_Bx(i); /* global index */ + lua_assert(ttisstring(&p->k[g])); + *name = svalue(&p->k[g]); + return "global"; + } + case OP_MOVE: { + int a = GETARG_A(i); + int b = GETARG_B(i); /* move from `b' to `a' */ + if (b < a) + return getobjname(L, ci, b, name); /* get name for `b' */ + break; + } + case OP_GETTABLE: { + int k = GETARG_C(i); /* key index */ + *name = kname(p, k); + return "field"; + } + case OP_GETUPVAL: { + int u = GETARG_B(i); /* upvalue index */ + *name = p->upvalues ? getstr(p->upvalues[u]) : "?"; + return "upvalue"; + } + case OP_SELF: { + int k = GETARG_C(i); /* key index */ + *name = kname(p, k); + return "method"; + } + default: break; + } + } + return NULL; /* no useful name found */ +} + + +static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { + Instruction i; + if ((isLua(ci) && ci->tailcalls > 0) || !isLua(ci - 1)) + return NULL; /* calling function is not Lua (or is unknown) */ + ci--; /* calling function */ + i = ci_func(ci)->l.p->code[currentpc(L, ci)]; + if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL || + GET_OPCODE(i) == OP_TFORLOOP) + return getobjname(L, ci, GETARG_A(i), name); + else + return NULL; /* no useful name can be found */ +} + + +/* only ANSI way to check whether a pointer points to an array */ +static int isinstack (CallInfo *ci, const TValue *o) { + StkId p; + for (p = ci->base; p < ci->top; p++) + if (o == p) return 1; + return 0; +} + + +void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { + const char *name = NULL; + const char *t = luaT_typenames[ttype(o)]; + const char *kind = (isinstack(L->ci, o)) ? + getobjname(L, L->ci, cast_int(o - L->base), &name) : + NULL; + if (kind) + luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", + op, kind, name, t); + else + luaG_runerror(L, "attempt to %s a %s value", op, t); +} + + +void luaG_concaterror (lua_State *L, StkId p1, StkId p2) { + if (ttisstring(p1) || ttisnumber(p1)) p1 = p2; + lua_assert(!ttisstring(p1) && !ttisnumber(p1)); + luaG_typeerror(L, p1, "concatenate"); +} + + +void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { + TValue temp; + if (luaV_tonumber(p1, &temp) == NULL) + p2 = p1; /* first operand is wrong */ + luaG_typeerror(L, p2, "perform arithmetic on"); +} + + +int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { + const char *t1 = luaT_typenames[ttype(p1)]; + const char *t2 = luaT_typenames[ttype(p2)]; + if (t1[2] == t2[2]) + luaG_runerror(L, "attempt to compare two %s values", t1); + else + luaG_runerror(L, "attempt to compare %s with %s", t1, t2); + return 0; +} + + +static void addinfo (lua_State *L, const char *msg) { + CallInfo *ci = L->ci; + if (isLua(ci)) { /* is Lua code? */ + char buff[LUA_IDSIZE]; /* add file:line information */ + int line = currentline(L, ci); + luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE); + luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); + } +} + + +void luaG_errormsg (lua_State *L) { + if (L->errfunc != 0) { /* is there an error handling function? */ + StkId errfunc = restorestack(L, L->errfunc); + if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR); + setobjs2s(L, L->top, L->top - 1); /* move argument */ + setobjs2s(L, L->top - 1, errfunc); /* push function */ + incr_top(L); + luaD_call(L, L->top - 2, 1); /* call it */ + } + luaD_throw(L, LUA_ERRRUN); +} + + +void luaG_runerror (lua_State *L, const char *fmt, ...) { + va_list argp; + va_start(argp, fmt); + addinfo(L, luaO_pushvfstring(L, fmt, argp)); + va_end(argp); + luaG_errormsg(L); +} + diff --git a/contrib/syslinux-4.02/com32/lua/src/ldebug.h b/contrib/syslinux-4.02/com32/lua/src/ldebug.h new file mode 100644 index 0000000..ba28a97 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/ldebug.h @@ -0,0 +1,33 @@ +/* +** $Id: ldebug.h,v 2.3.1.1 2007/12/27 13:02:25 roberto Exp $ +** Auxiliary functions from Debug Interface module +** See Copyright Notice in lua.h +*/ + +#ifndef ldebug_h +#define ldebug_h + + +#include "lstate.h" + + +#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) + +#define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) + +#define resethookcount(L) (L->hookcount = L->basehookcount) + + +LUAI_FUNC void luaG_typeerror (lua_State *L, const TValue *o, + const char *opname); +LUAI_FUNC void luaG_concaterror (lua_State *L, StkId p1, StkId p2); +LUAI_FUNC void luaG_aritherror (lua_State *L, const TValue *p1, + const TValue *p2); +LUAI_FUNC int luaG_ordererror (lua_State *L, const TValue *p1, + const TValue *p2); +LUAI_FUNC void luaG_runerror (lua_State *L, const char *fmt, ...); +LUAI_FUNC void luaG_errormsg (lua_State *L); +LUAI_FUNC int luaG_checkcode (const Proto *pt); +LUAI_FUNC int luaG_checkopenop (Instruction i); + +#endif diff --git a/contrib/syslinux-4.02/com32/lua/src/ldo.c b/contrib/syslinux-4.02/com32/lua/src/ldo.c new file mode 100644 index 0000000..8de05f7 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/ldo.c @@ -0,0 +1,518 @@ +/* +** $Id: ldo.c,v 2.38.1.3 2008/01/18 22:31:22 roberto Exp $ +** Stack and Call structure of Lua +** See Copyright Notice in lua.h +*/ + + +#include <setjmp.h> +#include <stdlib.h> +#include <string.h> + +#define ldo_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lundump.h" +#include "lvm.h" +#include "lzio.h" + + + + +/* +** {====================================================== +** Error-recovery functions +** ======================================================= +*/ + + +/* chain list of long jump buffers */ +struct lua_longjmp { + struct lua_longjmp *previous; + luai_jmpbuf b; + volatile int status; /* error code */ +}; + + +void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { + switch (errcode) { + case LUA_ERRMEM: { + setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG)); + break; + } + case LUA_ERRERR: { + setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); + break; + } + case LUA_ERRSYNTAX: + case LUA_ERRRUN: { + setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ + break; + } + } + L->top = oldtop + 1; +} + + +static void restore_stack_limit (lua_State *L) { + lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); + if (L->size_ci > LUAI_MAXCALLS) { /* there was an overflow? */ + int inuse = cast_int(L->ci - L->base_ci); + if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */ + luaD_reallocCI(L, LUAI_MAXCALLS); + } +} + + +static void resetstack (lua_State *L, int status) { + L->ci = L->base_ci; + L->base = L->ci->base; + luaF_close(L, L->base); /* close eventual pending closures */ + luaD_seterrorobj(L, status, L->base); + L->nCcalls = L->baseCcalls; + L->allowhook = 1; + restore_stack_limit(L); + L->errfunc = 0; + L->errorJmp = NULL; +} + + +void luaD_throw (lua_State *L, int errcode) { + if (L->errorJmp) { + L->errorJmp->status = errcode; + LUAI_THROW(L, L->errorJmp); + } + else { + L->status = cast_byte(errcode); + if (G(L)->panic) { + resetstack(L, errcode); + lua_unlock(L); + G(L)->panic(L); + } + exit(EXIT_FAILURE); + } +} + + +int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { + struct lua_longjmp lj; + lj.status = 0; + lj.previous = L->errorJmp; /* chain new error handler */ + L->errorJmp = &lj; + LUAI_TRY(L, &lj, + (*f)(L, ud); + ); + L->errorJmp = lj.previous; /* restore old error handler */ + return lj.status; +} + +/* }====================================================== */ + + +static void correctstack (lua_State *L, TValue *oldstack) { + CallInfo *ci; + GCObject *up; + L->top = (L->top - oldstack) + L->stack; + for (up = L->openupval; up != NULL; up = up->gch.next) + gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; + for (ci = L->base_ci; ci <= L->ci; ci++) { + ci->top = (ci->top - oldstack) + L->stack; + ci->base = (ci->base - oldstack) + L->stack; + ci->func = (ci->func - oldstack) + L->stack; + } + L->base = (L->base - oldstack) + L->stack; +} + + +void luaD_reallocstack (lua_State *L, int newsize) { + TValue *oldstack = L->stack; + int realsize = newsize + 1 + EXTRA_STACK; + lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); + luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue); + L->stacksize = realsize; + L->stack_last = L->stack+newsize; + correctstack(L, oldstack); +} + + +void luaD_reallocCI (lua_State *L, int newsize) { + CallInfo *oldci = L->base_ci; + luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo); + L->size_ci = newsize; + L->ci = (L->ci - oldci) + L->base_ci; + L->end_ci = L->base_ci + L->size_ci - 1; +} + + +void luaD_growstack (lua_State *L, int n) { + if (n <= L->stacksize) /* double size is enough? */ + luaD_reallocstack(L, 2*L->stacksize); + else + luaD_reallocstack(L, L->stacksize + n); +} + + +static CallInfo *growCI (lua_State *L) { + if (L->size_ci > LUAI_MAXCALLS) /* overflow while handling overflow? */ + luaD_throw(L, LUA_ERRERR); + else { + luaD_reallocCI(L, 2*L->size_ci); + if (L->size_ci > LUAI_MAXCALLS) + luaG_runerror(L, "stack overflow"); + } + return ++L->ci; +} + + +void luaD_callhook (lua_State *L, int event, int line) { + lua_Hook hook = L->hook; + if (hook && L->allowhook) { + ptrdiff_t top = savestack(L, L->top); + ptrdiff_t ci_top = savestack(L, L->ci->top); + lua_Debug ar; + ar.event = event; + ar.currentline = line; + if (event == LUA_HOOKTAILRET) + ar.i_ci = 0; /* tail call; no debug information about it */ + else + ar.i_ci = cast_int(L->ci - L->base_ci); + luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ + L->ci->top = L->top + LUA_MINSTACK; + lua_assert(L->ci->top <= L->stack_last); + L->allowhook = 0; /* cannot call hooks inside a hook */ + lua_unlock(L); + (*hook)(L, &ar); + lua_lock(L); + lua_assert(!L->allowhook); + L->allowhook = 1; + L->ci->top = restorestack(L, ci_top); + L->top = restorestack(L, top); + } +} + + +static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { + int i; + int nfixargs = p->numparams; + Table *htab = NULL; + StkId base, fixed; + for (; actual < nfixargs; ++actual) + setnilvalue(L->top++); +#if defined(LUA_COMPAT_VARARG) + if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */ + int nvar = actual - nfixargs; /* number of extra arguments */ + lua_assert(p->is_vararg & VARARG_HASARG); + luaC_checkGC(L); + htab = luaH_new(L, nvar, 1); /* create `arg' table */ + for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */ + setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i); + /* store counter in field `n' */ + setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar)); + } +#endif + /* move fixed parameters to final position */ + fixed = L->top - actual; /* first fixed argument */ + base = L->top; /* final position of first argument */ + for (i=0; i<nfixargs; i++) { + setobjs2s(L, L->top++, fixed+i); + setnilvalue(fixed+i); + } + /* add `arg' parameter */ + if (htab) { + sethvalue(L, L->top++, htab); + lua_assert(iswhite(obj2gco(htab))); + } + return base; +} + + +static StkId tryfuncTM (lua_State *L, StkId func) { + const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL); + StkId p; + ptrdiff_t funcr = savestack(L, func); + if (!ttisfunction(tm)) + luaG_typeerror(L, func, "call"); + /* Open a hole inside the stack at `func' */ + for (p = L->top; p > func; p--) setobjs2s(L, p, p-1); + incr_top(L); + func = restorestack(L, funcr); /* previous call may change stack */ + setobj2s(L, func, tm); /* tag method is the new function to be called */ + return func; +} + + + +#define inc_ci(L) \ + ((L->ci == L->end_ci) ? growCI(L) : \ + (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci)) + + +int luaD_precall (lua_State *L, StkId func, int nresults) { + LClosure *cl; + ptrdiff_t funcr; + if (!ttisfunction(func)) /* `func' is not a function? */ + func = tryfuncTM(L, func); /* check the `function' tag method */ + funcr = savestack(L, func); + cl = &clvalue(func)->l; + L->ci->savedpc = L->savedpc; + if (!cl->isC) { /* Lua function? prepare its call */ + CallInfo *ci; + StkId st, base; + Proto *p = cl->p; + luaD_checkstack(L, p->maxstacksize); + func = restorestack(L, funcr); + if (!p->is_vararg) { /* no varargs? */ + base = func + 1; + if (L->top > base + p->numparams) + L->top = base + p->numparams; + } + else { /* vararg function */ + int nargs = cast_int(L->top - func) - 1; + base = adjust_varargs(L, p, nargs); + func = restorestack(L, funcr); /* previous call may change the stack */ + } + ci = inc_ci(L); /* now `enter' new function */ + ci->func = func; + L->base = ci->base = base; + ci->top = L->base + p->maxstacksize; + lua_assert(ci->top <= L->stack_last); + L->savedpc = p->code; /* starting point */ + ci->tailcalls = 0; + ci->nresults = nresults; + for (st = L->top; st < ci->top; st++) + setnilvalue(st); + L->top = ci->top; + if (L->hookmask & LUA_MASKCALL) { + L->savedpc++; /* hooks assume 'pc' is already incremented */ + luaD_callhook(L, LUA_HOOKCALL, -1); + L->savedpc--; /* correct 'pc' */ + } + return PCRLUA; + } + else { /* if is a C function, call it */ + CallInfo *ci; + int n; + luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ + ci = inc_ci(L); /* now `enter' new function */ + ci->func = restorestack(L, funcr); + L->base = ci->base = ci->func + 1; + ci->top = L->top + LUA_MINSTACK; + lua_assert(ci->top <= L->stack_last); + ci->nresults = nresults; + if (L->hookmask & LUA_MASKCALL) + luaD_callhook(L, LUA_HOOKCALL, -1); + lua_unlock(L); + n = (*curr_func(L)->c.f)(L); /* do the actual call */ + lua_lock(L); + if (n < 0) /* yielding? */ + return PCRYIELD; + else { + luaD_poscall(L, L->top - n); + return PCRC; + } + } +} + + +static StkId callrethooks (lua_State *L, StkId firstResult) { + ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */ + luaD_callhook(L, LUA_HOOKRET, -1); + if (f_isLua(L->ci)) { /* Lua function? */ + while ((L->hookmask & LUA_MASKRET) && L->ci->tailcalls--) /* tail calls */ + luaD_callhook(L, LUA_HOOKTAILRET, -1); + } + return restorestack(L, fr); +} + + +int luaD_poscall (lua_State *L, StkId firstResult) { + StkId res; + int wanted, i; + CallInfo *ci; + if (L->hookmask & LUA_MASKRET) + firstResult = callrethooks(L, firstResult); + ci = L->ci--; + res = ci->func; /* res == final position of 1st result */ + wanted = ci->nresults; + L->base = (ci - 1)->base; /* restore base */ + L->savedpc = (ci - 1)->savedpc; /* restore savedpc */ + /* move results to correct place */ + for (i = wanted; i != 0 && firstResult < L->top; i--) + setobjs2s(L, res++, firstResult++); + while (i-- > 0) + setnilvalue(res++); + L->top = res; + return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */ +} + + +/* +** Call a function (C or Lua). The function to be called is at *func. +** The arguments are on the stack, right after the function. +** When returns, all the results are on the stack, starting at the original +** function position. +*/ +void luaD_call (lua_State *L, StkId func, int nResults) { + if (++L->nCcalls >= LUAI_MAXCCALLS) { + if (L->nCcalls == LUAI_MAXCCALLS) + luaG_runerror(L, "C stack overflow"); + else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) + luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ + } + if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */ + luaV_execute(L, 1); /* call it */ + L->nCcalls--; + luaC_checkGC(L); +} + + +static void resume (lua_State *L, void *ud) { + StkId firstArg = cast(StkId, ud); + CallInfo *ci = L->ci; + if (L->status == 0) { /* start coroutine? */ + lua_assert(ci == L->base_ci && firstArg > L->base); + if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA) + return; + } + else { /* resuming from previous yield */ + lua_assert(L->status == LUA_YIELD); + L->status = 0; + if (!f_isLua(ci)) { /* `common' yield? */ + /* finish interrupted execution of `OP_CALL' */ + lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL || + GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL); + if (luaD_poscall(L, firstArg)) /* complete it... */ + L->top = L->ci->top; /* and correct top if not multiple results */ + } + else /* yielded inside a hook: just continue its execution */ + L->base = L->ci->base; + } + luaV_execute(L, cast_int(L->ci - L->base_ci)); +} + + +static int resume_error (lua_State *L, const char *msg) { + L->top = L->ci->base; + setsvalue2s(L, L->top, luaS_new(L, msg)); + incr_top(L); + lua_unlock(L); + return LUA_ERRRUN; +} + + +LUA_API int lua_resume (lua_State *L, int nargs) { + int status; + lua_lock(L); + if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci)) + return resume_error(L, "cannot resume non-suspended coroutine"); + if (L->nCcalls >= LUAI_MAXCCALLS) + return resume_error(L, "C stack overflow"); + luai_userstateresume(L, nargs); + lua_assert(L->errfunc == 0); + L->baseCcalls = ++L->nCcalls; + status = luaD_rawrunprotected(L, resume, L->top - nargs); + if (status != 0) { /* error? */ + L->status = cast_byte(status); /* mark thread as `dead' */ + luaD_seterrorobj(L, status, L->top); + L->ci->top = L->top; + } + else { + lua_assert(L->nCcalls == L->baseCcalls); + status = L->status; + } + --L->nCcalls; + lua_unlock(L); + return status; +} + + +LUA_API int lua_yield (lua_State *L, int nresults) { + luai_userstateyield(L, nresults); + lua_lock(L); + if (L->nCcalls > L->baseCcalls) + luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); + L->base = L->top - nresults; /* protect stack slots below */ + L->status = LUA_YIELD; + lua_unlock(L); + return -1; +} + + +int luaD_pcall (lua_State *L, Pfunc func, void *u, + ptrdiff_t old_top, ptrdiff_t ef) { + int status; + unsigned short oldnCcalls = L->nCcalls; + ptrdiff_t old_ci = saveci(L, L->ci); + lu_byte old_allowhooks = L->allowhook; + ptrdiff_t old_errfunc = L->errfunc; + L->errfunc = ef; + status = luaD_rawrunprotected(L, func, u); + if (status != 0) { /* an error occurred? */ + StkId oldtop = restorestack(L, old_top); + luaF_close(L, oldtop); /* close eventual pending closures */ + luaD_seterrorobj(L, status, oldtop); + L->nCcalls = oldnCcalls; + L->ci = restoreci(L, old_ci); + L->base = L->ci->base; + L->savedpc = L->ci->savedpc; + L->allowhook = old_allowhooks; + restore_stack_limit(L); + } + L->errfunc = old_errfunc; + return status; +} + + + +/* +** Execute a protected parser. +*/ +struct SParser { /* data to `f_parser' */ + ZIO *z; + Mbuffer buff; /* buffer to be used by the scanner */ + const char *name; +}; + +static void f_parser (lua_State *L, void *ud) { + int i; + Proto *tf; + Closure *cl; + struct SParser *p = cast(struct SParser *, ud); + int c = luaZ_lookahead(p->z); + luaC_checkGC(L); + tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z, + &p->buff, p->name); + cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L))); + cl->l.p = tf; + for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */ + cl->l.upvals[i] = luaF_newupval(L); + setclvalue(L, L->top, cl); + incr_top(L); +} + + +int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) { + struct SParser p; + int status; + p.z = z; p.name = name; + luaZ_initbuffer(L, &p.buff); + status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); + luaZ_freebuffer(L, &p.buff); + return status; +} + + diff --git a/contrib/syslinux-4.02/com32/lua/src/ldo.h b/contrib/syslinux-4.02/com32/lua/src/ldo.h new file mode 100644 index 0000000..98fddac --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/ldo.h @@ -0,0 +1,57 @@ +/* +** $Id: ldo.h,v 2.7.1.1 2007/12/27 13:02:25 roberto Exp $ +** Stack and Call structure of Lua +** See Copyright Notice in lua.h +*/ + +#ifndef ldo_h +#define ldo_h + + +#include "lobject.h" +#include "lstate.h" +#include "lzio.h" + + +#define luaD_checkstack(L,n) \ + if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \ + luaD_growstack(L, n); \ + else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); + + +#define incr_top(L) {luaD_checkstack(L,1); L->top++;} + +#define savestack(L,p) ((char *)(p) - (char *)L->stack) +#define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) + +#define saveci(L,p) ((char *)(p) - (char *)L->base_ci) +#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n))) + + +/* results from luaD_precall */ +#define PCRLUA 0 /* initiated a call to a Lua function */ +#define PCRC 1 /* did a call to a C function */ +#define PCRYIELD 2 /* C funtion yielded */ + + +/* type of protected functions, to be ran by `runprotected' */ +typedef void (*Pfunc) (lua_State *L, void *ud); + +LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name); +LUAI_FUNC void luaD_callhook (lua_State *L, int event, int line); +LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); +LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); +LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, + ptrdiff_t oldtop, ptrdiff_t ef); +LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult); +LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize); +LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); +LUAI_FUNC void luaD_growstack (lua_State *L, int n); + +LUAI_FUNC void luaD_throw (lua_State *L, int errcode); +LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); + +LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop); + +#endif + diff --git a/contrib/syslinux-4.02/com32/lua/src/ldump.c b/contrib/syslinux-4.02/com32/lua/src/ldump.c new file mode 100644 index 0000000..c9d3d48 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/ldump.c @@ -0,0 +1,164 @@ +/* +** $Id: ldump.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ +** save precompiled Lua chunks +** See Copyright Notice in lua.h +*/ + +#include <stddef.h> + +#define ldump_c +#define LUA_CORE + +#include "lua.h" + +#include "lobject.h" +#include "lstate.h" +#include "lundump.h" + +typedef struct { + lua_State* L; + lua_Writer writer; + void* data; + int strip; + int status; +} DumpState; + +#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D) +#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) + +static void DumpBlock(const void* b, size_t size, DumpState* D) +{ + if (D->status==0) + { + lua_unlock(D->L); + D->status=(*D->writer)(D->L,b,size,D->data); + lua_lock(D->L); + } +} + +static void DumpChar(int y, DumpState* D) +{ + char x=(char)y; + DumpVar(x,D); +} + +static void DumpInt(int x, DumpState* D) +{ + DumpVar(x,D); +} + +static void DumpNumber(lua_Number x, DumpState* D) +{ + DumpVar(x,D); +} + +static void DumpVector(const void* b, int n, size_t size, DumpState* D) +{ + DumpInt(n,D); + DumpMem(b,n,size,D); +} + +static void DumpString(const TString* s, DumpState* D) +{ + if (s==NULL || getstr(s)==NULL) + { + size_t size=0; + DumpVar(size,D); + } + else + { + size_t size=s->tsv.len+1; /* include trailing '\0' */ + DumpVar(size,D); + DumpBlock(getstr(s),size,D); + } +} + +#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D) + +static void DumpFunction(const Proto* f, const TString* p, DumpState* D); + +static void DumpConstants(const Proto* f, DumpState* D) +{ + int i,n=f->sizek; + DumpInt(n,D); + for (i=0; i<n; i++) + { + const TValue* o=&f->k[i]; + DumpChar(ttype(o),D); + switch (ttype(o)) + { + case LUA_TNIL: + break; + case LUA_TBOOLEAN: + DumpChar(bvalue(o),D); + break; + case LUA_TNUMBER: + DumpNumber(nvalue(o),D); + break; + case LUA_TSTRING: + DumpString(rawtsvalue(o),D); + break; + default: + lua_assert(0); /* cannot happen */ + break; + } + } + n=f->sizep; + DumpInt(n,D); + for (i=0; i<n; i++) DumpFunction(f->p[i],f->source,D); +} + +static void DumpDebug(const Proto* f, DumpState* D) +{ + int i,n; + n= (D->strip) ? 0 : f->sizelineinfo; + DumpVector(f->lineinfo,n,sizeof(int),D); + n= (D->strip) ? 0 : f->sizelocvars; + DumpInt(n,D); + for (i=0; i<n; i++) + { + DumpString(f->locvars[i].varname,D); + DumpInt(f->locvars[i].startpc,D); + DumpInt(f->locvars[i].endpc,D); + } + n= (D->strip) ? 0 : f->sizeupvalues; + DumpInt(n,D); + for (i=0; i<n; i++) DumpString(f->upvalues[i],D); +} + +static void DumpFunction(const Proto* f, const TString* p, DumpState* D) +{ + DumpString((f->source==p || D->strip) ? NULL : f->source,D); + DumpInt(f->linedefined,D); + DumpInt(f->lastlinedefined,D); + DumpChar(f->nups,D); + DumpChar(f->numparams,D); + DumpChar(f->is_vararg,D); + DumpChar(f->maxstacksize,D); + DumpCode(f,D); + DumpConstants(f,D); + DumpDebug(f,D); +} + +static void DumpHeader(DumpState* D) +{ + char h[LUAC_HEADERSIZE]; + luaU_header(h); + DumpBlock(h,LUAC_HEADERSIZE,D); +} + +/* +** dump Lua function as precompiled chunk +*/ +int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip) +{ + DumpState D; + D.L=L; + D.writer=w; + D.data=data; + D.strip=strip; + D.status=0; + DumpHeader(&D); + DumpFunction(f,NULL,&D); + return D.status; +} diff --git a/contrib/syslinux-4.02/com32/lua/src/lfunc.c b/contrib/syslinux-4.02/com32/lua/src/lfunc.c new file mode 100644 index 0000000..813e88f --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lfunc.c @@ -0,0 +1,174 @@ +/* +** $Id: lfunc.c,v 2.12.1.2 2007/12/28 14:58:43 roberto Exp $ +** Auxiliary functions to manipulate prototypes and closures +** See Copyright Notice in lua.h +*/ + + +#include <stddef.h> + +#define lfunc_c +#define LUA_CORE + +#include "lua.h" + +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" + + + +Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) { + Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems))); + luaC_link(L, obj2gco(c), LUA_TFUNCTION); + c->c.isC = 1; + c->c.env = e; + c->c.nupvalues = cast_byte(nelems); + return c; +} + + +Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e) { + Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); + luaC_link(L, obj2gco(c), LUA_TFUNCTION); + c->l.isC = 0; + c->l.env = e; + c->l.nupvalues = cast_byte(nelems); + while (nelems--) c->l.upvals[nelems] = NULL; + return c; +} + + +UpVal *luaF_newupval (lua_State *L) { + UpVal *uv = luaM_new(L, UpVal); + luaC_link(L, obj2gco(uv), LUA_TUPVAL); + uv->v = &uv->u.value; + setnilvalue(uv->v); + return uv; +} + + +UpVal *luaF_findupval (lua_State *L, StkId level) { + global_State *g = G(L); + GCObject **pp = &L->openupval; + UpVal *p; + UpVal *uv; + while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) { + lua_assert(p->v != &p->u.value); + if (p->v == level) { /* found a corresponding upvalue? */ + if (isdead(g, obj2gco(p))) /* is it dead? */ + changewhite(obj2gco(p)); /* ressurect it */ + return p; + } + pp = &p->next; + } + uv = luaM_new(L, UpVal); /* not found: create a new one */ + uv->tt = LUA_TUPVAL; + uv->marked = luaC_white(g); + uv->v = level; /* current value lives in the stack */ + uv->next = *pp; /* chain it in the proper position */ + *pp = obj2gco(uv); + uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ + uv->u.l.next = g->uvhead.u.l.next; + uv->u.l.next->u.l.prev = uv; + g->uvhead.u.l.next = uv; + lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); + return uv; +} + + +static void unlinkupval (UpVal *uv) { + lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); + uv->u.l.next->u.l.prev = uv->u.l.prev; /* remove from `uvhead' list */ + uv->u.l.prev->u.l.next = uv->u.l.next; +} + + +void luaF_freeupval (lua_State *L, UpVal *uv) { + if (uv->v != &uv->u.value) /* is it open? */ + unlinkupval(uv); /* remove from open list */ + luaM_free(L, uv); /* free upvalue */ +} + + +void luaF_close (lua_State *L, StkId level) { + UpVal *uv; + global_State *g = G(L); + while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) { + GCObject *o = obj2gco(uv); + lua_assert(!isblack(o) && uv->v != &uv->u.value); + L->openupval = uv->next; /* remove from `open' list */ + if (isdead(g, o)) + luaF_freeupval(L, uv); /* free upvalue */ + else { + unlinkupval(uv); + setobj(L, &uv->u.value, uv->v); + uv->v = &uv->u.value; /* now current value lives here */ + luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */ + } + } +} + + +Proto *luaF_newproto (lua_State *L) { + Proto *f = luaM_new(L, Proto); + luaC_link(L, obj2gco(f), LUA_TPROTO); + f->k = NULL; + f->sizek = 0; + f->p = NULL; + f->sizep = 0; + f->code = NULL; + f->sizecode = 0; + f->sizelineinfo = 0; + f->sizeupvalues = 0; + f->nups = 0; + f->upvalues = NULL; + f->numparams = 0; + f->is_vararg = 0; + f->maxstacksize = 0; + f->lineinfo = NULL; + f->sizelocvars = 0; + f->locvars = NULL; + f->linedefined = 0; + f->lastlinedefined = 0; + f->source = NULL; + return f; +} + + +void luaF_freeproto (lua_State *L, Proto *f) { + luaM_freearray(L, f->code, f->sizecode, Instruction); + luaM_freearray(L, f->p, f->sizep, Proto *); + luaM_freearray(L, f->k, f->sizek, TValue); + luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); + luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); + luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *); + luaM_free(L, f); +} + + +void luaF_freeclosure (lua_State *L, Closure *c) { + int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) : + sizeLclosure(c->l.nupvalues); + luaM_freemem(L, c, size); +} + + +/* +** Look for n-th local variable at line `line' in function `func'. +** Returns NULL if not found. +*/ +const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { + int i; + for (i = 0; i<f->sizelocvars && f->locvars[i].startpc <= pc; i++) { + if (pc < f->locvars[i].endpc) { /* is variable active? */ + local_number--; + if (local_number == 0) + return getstr(f->locvars[i].varname); + } + } + return NULL; /* not found */ +} + diff --git a/contrib/syslinux-4.02/com32/lua/src/lfunc.h b/contrib/syslinux-4.02/com32/lua/src/lfunc.h new file mode 100644 index 0000000..a68cf51 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lfunc.h @@ -0,0 +1,34 @@ +/* +** $Id: lfunc.h,v 2.4.1.1 2007/12/27 13:02:25 roberto Exp $ +** Auxiliary functions to manipulate prototypes and closures +** See Copyright Notice in lua.h +*/ + +#ifndef lfunc_h +#define lfunc_h + + +#include "lobject.h" + + +#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \ + cast(int, sizeof(TValue)*((n)-1))) + +#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ + cast(int, sizeof(TValue *)*((n)-1))) + + +LUAI_FUNC Proto *luaF_newproto (lua_State *L); +LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e); +LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e); +LUAI_FUNC UpVal *luaF_newupval (lua_State *L); +LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); +LUAI_FUNC void luaF_close (lua_State *L, StkId level); +LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); +LUAI_FUNC void luaF_freeclosure (lua_State *L, Closure *c); +LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv); +LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, + int pc); + + +#endif diff --git a/contrib/syslinux-4.02/com32/lua/src/lgc.c b/contrib/syslinux-4.02/com32/lua/src/lgc.c new file mode 100644 index 0000000..d9e0b78 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lgc.c @@ -0,0 +1,711 @@ +/* +** $Id: lgc.c,v 2.38.1.1 2007/12/27 13:02:25 roberto Exp $ +** Garbage Collector +** See Copyright Notice in lua.h +*/ + +#include <string.h> + +#define lgc_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" + + +#define GCSTEPSIZE 1024u +#define GCSWEEPMAX 40 +#define GCSWEEPCOST 10 +#define GCFINALIZECOST 100 + + +#define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS)) + +#define makewhite(g,x) \ + ((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g))) + +#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) +#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT) + +#define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT) + + +#define isfinalized(u) testbit((u)->marked, FINALIZEDBIT) +#define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT) + + +#define KEYWEAK bitmask(KEYWEAKBIT) +#define VALUEWEAK bitmask(VALUEWEAKBIT) + + + +#define markvalue(g,o) { checkconsistency(o); \ + if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); } + +#define markobject(g,t) { if (iswhite(obj2gco(t))) \ + reallymarkobject(g, obj2gco(t)); } + + +#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause) + + +static void removeentry (Node *n) { + lua_assert(ttisnil(gval(n))); + if (iscollectable(gkey(n))) + setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */ +} + + +static void reallymarkobject (global_State *g, GCObject *o) { + lua_assert(iswhite(o) && !isdead(g, o)); + white2gray(o); + switch (o->gch.tt) { + case LUA_TSTRING: { + return; + } + case LUA_TUSERDATA: { + Table *mt = gco2u(o)->metatable; + gray2black(o); /* udata are never gray */ + if (mt) markobject(g, mt); + markobject(g, gco2u(o)->env); + return; + } + case LUA_TUPVAL: { + UpVal *uv = gco2uv(o); + markvalue(g, uv->v); + if (uv->v == &uv->u.value) /* closed? */ + gray2black(o); /* open upvalues are never black */ + return; + } + case LUA_TFUNCTION: { + gco2cl(o)->c.gclist = g->gray; + g->gray = o; + break; + } + case LUA_TTABLE: { + gco2h(o)->gclist = g->gray; + g->gray = o; + break; + } + case LUA_TTHREAD: { + gco2th(o)->gclist = g->gray; + g->gray = o; + break; + } + case LUA_TPROTO: { + gco2p(o)->gclist = g->gray; + g->gray = o; + break; + } + default: lua_assert(0); + } +} + + +static void marktmu (global_State *g) { + GCObject *u = g->tmudata; + if (u) { + do { + u = u->gch.next; + makewhite(g, u); /* may be marked, if left from previous GC */ + reallymarkobject(g, u); + } while (u != g->tmudata); + } +} + + +/* move `dead' udata that need finalization to list `tmudata' */ +size_t luaC_separateudata (lua_State *L, int all) { + global_State *g = G(L); + size_t deadmem = 0; + GCObject **p = &g->mainthread->next; + GCObject *curr; + while ((curr = *p) != NULL) { + if (!(iswhite(curr) || all) || isfinalized(gco2u(curr))) + p = &curr->gch.next; /* don't bother with them */ + else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) { + markfinalized(gco2u(curr)); /* don't need finalization */ + p = &curr->gch.next; + } + else { /* must call its gc method */ + deadmem += sizeudata(gco2u(curr)); + markfinalized(gco2u(curr)); + *p = curr->gch.next; + /* link `curr' at the end of `tmudata' list */ + if (g->tmudata == NULL) /* list is empty? */ + g->tmudata = curr->gch.next = curr; /* creates a circular list */ + else { + curr->gch.next = g->tmudata->gch.next; + g->tmudata->gch.next = curr; + g->tmudata = curr; + } + } + } + return deadmem; +} + + +static int traversetable (global_State *g, Table *h) { + int i; + int weakkey = 0; + int weakvalue = 0; + const TValue *mode; + if (h->metatable) + markobject(g, h->metatable); + mode = gfasttm(g, h->metatable, TM_MODE); + if (mode && ttisstring(mode)) { /* is there a weak mode? */ + weakkey = (strchr(svalue(mode), 'k') != NULL); + weakvalue = (strchr(svalue(mode), 'v') != NULL); + if (weakkey || weakvalue) { /* is really weak? */ + h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */ + h->marked |= cast_byte((weakkey << KEYWEAKBIT) | + (weakvalue << VALUEWEAKBIT)); + h->gclist = g->weak; /* must be cleared after GC, ... */ + g->weak = obj2gco(h); /* ... so put in the appropriate list */ + } + } + if (weakkey && weakvalue) return 1; + if (!weakvalue) { + i = h->sizearray; + while (i--) + markvalue(g, &h->array[i]); + } + i = sizenode(h); + while (i--) { + Node *n = gnode(h, i); + lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n))); + if (ttisnil(gval(n))) + removeentry(n); /* remove empty entries */ + else { + lua_assert(!ttisnil(gkey(n))); + if (!weakkey) markvalue(g, gkey(n)); + if (!weakvalue) markvalue(g, gval(n)); + } + } + return weakkey || weakvalue; +} + + +/* +** All marks are conditional because a GC may happen while the +** prototype is still being created +*/ +static void traverseproto (global_State *g, Proto *f) { + int i; + if (f->source) stringmark(f->source); + for (i=0; i<f->sizek; i++) /* mark literals */ + markvalue(g, &f->k[i]); + for (i=0; i<f->sizeupvalues; i++) { /* mark upvalue names */ + if (f->upvalues[i]) + stringmark(f->upvalues[i]); + } + for (i=0; i<f->sizep; i++) { /* mark nested protos */ + if (f->p[i]) + markobject(g, f->p[i]); + } + for (i=0; i<f->sizelocvars; i++) { /* mark local-variable names */ + if (f->locvars[i].varname) + stringmark(f->locvars[i].varname); + } +} + + + +static void traverseclosure (global_State *g, Closure *cl) { + markobject(g, cl->c.env); + if (cl->c.isC) { + int i; + for (i=0; i<cl->c.nupvalues; i++) /* mark its upvalues */ + markvalue(g, &cl->c.upvalue[i]); + } + else { + int i; + lua_assert(cl->l.nupvalues == cl->l.p->nups); + markobject(g, cl->l.p); + for (i=0; i<cl->l.nupvalues; i++) /* mark its upvalues */ + markobject(g, cl->l.upvals[i]); + } +} + + +static void checkstacksizes (lua_State *L, StkId max) { + int ci_used = cast_int(L->ci - L->base_ci); /* number of `ci' in use */ + int s_used = cast_int(max - L->stack); /* part of stack in use */ + if (L->size_ci > LUAI_MAXCALLS) /* handling overflow? */ + return; /* do not touch the stacks */ + if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci) + luaD_reallocCI(L, L->size_ci/2); /* still big enough... */ + condhardstacktests(luaD_reallocCI(L, ci_used + 1)); + if (4*s_used < L->stacksize && + 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize) + luaD_reallocstack(L, L->stacksize/2); /* still big enough... */ + condhardstacktests(luaD_reallocstack(L, s_used)); +} + + +static void traversestack (global_State *g, lua_State *l) { + StkId o, lim; + CallInfo *ci; + markvalue(g, gt(l)); + lim = l->top; + for (ci = l->base_ci; ci <= l->ci; ci++) { + lua_assert(ci->top <= l->stack_last); + if (lim < ci->top) lim = ci->top; + } + for (o = l->stack; o < l->top; o++) + markvalue(g, o); + for (; o <= lim; o++) + setnilvalue(o); + checkstacksizes(l, lim); +} + + +/* +** traverse one gray object, turning it to black. +** Returns `quantity' traversed. +*/ +static l_mem propagatemark (global_State *g) { + GCObject *o = g->gray; + lua_assert(isgray(o)); + gray2black(o); + switch (o->gch.tt) { + case LUA_TTABLE: { + Table *h = gco2h(o); + g->gray = h->gclist; + if (traversetable(g, h)) /* table is weak? */ + black2gray(o); /* keep it gray */ + return sizeof(Table) + sizeof(TValue) * h->sizearray + + sizeof(Node) * sizenode(h); + } + case LUA_TFUNCTION: { + Closure *cl = gco2cl(o); + g->gray = cl->c.gclist; + traverseclosure(g, cl); + return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) : + sizeLclosure(cl->l.nupvalues); + } + case LUA_TTHREAD: { + lua_State *th = gco2th(o); + g->gray = th->gclist; + th->gclist = g->grayagain; + g->grayagain = o; + black2gray(o); + traversestack(g, th); + return sizeof(lua_State) + sizeof(TValue) * th->stacksize + + sizeof(CallInfo) * th->size_ci; + } + case LUA_TPROTO: { + Proto *p = gco2p(o); + g->gray = p->gclist; + traverseproto(g, p); + return sizeof(Proto) + sizeof(Instruction) * p->sizecode + + sizeof(Proto *) * p->sizep + + sizeof(TValue) * p->sizek + + sizeof(int) * p->sizelineinfo + + sizeof(LocVar) * p->sizelocvars + + sizeof(TString *) * p->sizeupvalues; + } + default: lua_assert(0); return 0; + } +} + + +static size_t propagateall (global_State *g) { + size_t m = 0; + while (g->gray) m += propagatemark(g); + return m; +} + + +/* +** The next function tells whether a key or value can be cleared from +** a weak table. Non-collectable objects are never removed from weak +** tables. Strings behave as `values', so are never removed too. for +** other objects: if really collected, cannot keep them; for userdata +** being finalized, keep them in keys, but not in values +*/ +static int iscleared (const TValue *o, int iskey) { + if (!iscollectable(o)) return 0; + if (ttisstring(o)) { + stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */ + return 0; + } + return iswhite(gcvalue(o)) || + (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o)))); +} + + +/* +** clear collected entries from weaktables +*/ +static void cleartable (GCObject *l) { + while (l) { + Table *h = gco2h(l); + int i = h->sizearray; + lua_assert(testbit(h->marked, VALUEWEAKBIT) || + testbit(h->marked, KEYWEAKBIT)); + if (testbit(h->marked, VALUEWEAKBIT)) { + while (i--) { + TValue *o = &h->array[i]; + if (iscleared(o, 0)) /* value was collected? */ + setnilvalue(o); /* remove value */ + } + } + i = sizenode(h); + while (i--) { + Node *n = gnode(h, i); + if (!ttisnil(gval(n)) && /* non-empty entry? */ + (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) { + setnilvalue(gval(n)); /* remove value ... */ + removeentry(n); /* remove entry from table */ + } + } + l = h->gclist; + } +} + + +static void freeobj (lua_State *L, GCObject *o) { + switch (o->gch.tt) { + case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; + case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break; + case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; + case LUA_TTABLE: luaH_free(L, gco2h(o)); break; + case LUA_TTHREAD: { + lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread); + luaE_freethread(L, gco2th(o)); + break; + } + case LUA_TSTRING: { + G(L)->strt.nuse--; + luaM_freemem(L, o, sizestring(gco2ts(o))); + break; + } + case LUA_TUSERDATA: { + luaM_freemem(L, o, sizeudata(gco2u(o))); + break; + } + default: lua_assert(0); + } +} + + + +#define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) + + +static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { + GCObject *curr; + global_State *g = G(L); + int deadmask = otherwhite(g); + while ((curr = *p) != NULL && count-- > 0) { + if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */ + sweepwholelist(L, &gco2th(curr)->openupval); + if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */ + lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT)); + makewhite(g, curr); /* make it white (for next cycle) */ + p = &curr->gch.next; + } + else { /* must erase `curr' */ + lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT)); + *p = curr->gch.next; + if (curr == g->rootgc) /* is the first element of the list? */ + g->rootgc = curr->gch.next; /* adjust first */ + freeobj(L, curr); + } + } + return p; +} + + +static void checkSizes (lua_State *L) { + global_State *g = G(L); + /* check size of string hash */ + if (g->strt.nuse < cast(lu_int32, g->strt.size/4) && + g->strt.size > MINSTRTABSIZE*2) + luaS_resize(L, g->strt.size/2); /* table is too big */ + /* check size of buffer */ + if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */ + size_t newsize = luaZ_sizebuffer(&g->buff) / 2; + luaZ_resizebuffer(L, &g->buff, newsize); + } +} + + +static void GCTM (lua_State *L) { + global_State *g = G(L); + GCObject *o = g->tmudata->gch.next; /* get first element */ + Udata *udata = rawgco2u(o); + const TValue *tm; + /* remove udata from `tmudata' */ + if (o == g->tmudata) /* last element? */ + g->tmudata = NULL; + else + g->tmudata->gch.next = udata->uv.next; + udata->uv.next = g->mainthread->next; /* return it to `root' list */ + g->mainthread->next = o; + makewhite(g, o); + tm = fasttm(L, udata->uv.metatable, TM_GC); + if (tm != NULL) { + lu_byte oldah = L->allowhook; + lu_mem oldt = g->GCthreshold; + L->allowhook = 0; /* stop debug hooks during GC tag method */ + g->GCthreshold = 2*g->totalbytes; /* avoid GC steps */ + setobj2s(L, L->top, tm); + setuvalue(L, L->top+1, udata); + L->top += 2; + luaD_call(L, L->top - 2, 0); + L->allowhook = oldah; /* restore hooks */ + g->GCthreshold = oldt; /* restore threshold */ + } +} + + +/* +** Call all GC tag methods +*/ +void luaC_callGCTM (lua_State *L) { + while (G(L)->tmudata) + GCTM(L); +} + + +void luaC_freeall (lua_State *L) { + global_State *g = G(L); + int i; + g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT); /* mask to collect all elements */ + sweepwholelist(L, &g->rootgc); + for (i = 0; i < g->strt.size; i++) /* free all string lists */ + sweepwholelist(L, &g->strt.hash[i]); +} + + +static void markmt (global_State *g) { + int i; + for (i=0; i<NUM_TAGS; i++) + if (g->mt[i]) markobject(g, g->mt[i]); +} + + +/* mark root set */ +static void markroot (lua_State *L) { + global_State *g = G(L); + g->gray = NULL; + g->grayagain = NULL; + g->weak = NULL; + markobject(g, g->mainthread); + /* make global table be traversed before main stack */ + markvalue(g, gt(g->mainthread)); + markvalue(g, registry(L)); + markmt(g); + g->gcstate = GCSpropagate; +} + + +static void remarkupvals (global_State *g) { + UpVal *uv; + for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { + lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); + if (isgray(obj2gco(uv))) + markvalue(g, uv->v); + } +} + + +static void atomic (lua_State *L) { + global_State *g = G(L); + size_t udsize; /* total size of userdata to be finalized */ + /* remark occasional upvalues of (maybe) dead threads */ + remarkupvals(g); + /* traverse objects cautch by write barrier and by 'remarkupvals' */ + propagateall(g); + /* remark weak tables */ + g->gray = g->weak; + g->weak = NULL; + lua_assert(!iswhite(obj2gco(g->mainthread))); + markobject(g, L); /* mark running thread */ + markmt(g); /* mark basic metatables (again) */ + propagateall(g); + /* remark gray again */ + g->gray = g->grayagain; + g->grayagain = NULL; + propagateall(g); + udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */ + marktmu(g); /* mark `preserved' userdata */ + udsize += propagateall(g); /* remark, to propagate `preserveness' */ + cleartable(g->weak); /* remove collected objects from weak tables */ + /* flip current white */ + g->currentwhite = cast_byte(otherwhite(g)); + g->sweepstrgc = 0; + g->sweepgc = &g->rootgc; + g->gcstate = GCSsweepstring; + g->estimate = g->totalbytes - udsize; /* first estimate */ +} + + +static l_mem singlestep (lua_State *L) { + global_State *g = G(L); + /*lua_checkmemory(L);*/ + switch (g->gcstate) { + case GCSpause: { + markroot(L); /* start a new collection */ + return 0; + } + case GCSpropagate: { + if (g->gray) + return propagatemark(g); + else { /* no more `gray' objects */ + atomic(L); /* finish mark phase */ + return 0; + } + } + case GCSsweepstring: { + lu_mem old = g->totalbytes; + sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]); + if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */ + g->gcstate = GCSsweep; /* end sweep-string phase */ + lua_assert(old >= g->totalbytes); + g->estimate -= old - g->totalbytes; + return GCSWEEPCOST; + } + case GCSsweep: { + lu_mem old = g->totalbytes; + g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); + if (*g->sweepgc == NULL) { /* nothing more to sweep? */ + checkSizes(L); + g->gcstate = GCSfinalize; /* end sweep phase */ + } + lua_assert(old >= g->totalbytes); + g->estimate -= old - g->totalbytes; + return GCSWEEPMAX*GCSWEEPCOST; + } + case GCSfinalize: { + if (g->tmudata) { + GCTM(L); + if (g->estimate > GCFINALIZECOST) + g->estimate -= GCFINALIZECOST; + return GCFINALIZECOST; + } + else { + g->gcstate = GCSpause; /* end collection */ + g->gcdept = 0; + return 0; + } + } + default: lua_assert(0); return 0; + } +} + + +void luaC_step (lua_State *L) { + global_State *g = G(L); + l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; + if (lim == 0) + lim = (MAX_LUMEM-1)/2; /* no limit */ + g->gcdept += g->totalbytes - g->GCthreshold; + do { + lim -= singlestep(L); + if (g->gcstate == GCSpause) + break; + } while (lim > 0); + if (g->gcstate != GCSpause) { + if (g->gcdept < GCSTEPSIZE) + g->GCthreshold = g->totalbytes + GCSTEPSIZE; /* - lim/g->gcstepmul;*/ + else { + g->gcdept -= GCSTEPSIZE; + g->GCthreshold = g->totalbytes; + } + } + else { + lua_assert(g->totalbytes >= g->estimate); + setthreshold(g); + } +} + + +void luaC_fullgc (lua_State *L) { + global_State *g = G(L); + if (g->gcstate <= GCSpropagate) { + /* reset sweep marks to sweep all elements (returning them to white) */ + g->sweepstrgc = 0; + g->sweepgc = &g->rootgc; + /* reset other collector lists */ + g->gray = NULL; + g->grayagain = NULL; + g->weak = NULL; + g->gcstate = GCSsweepstring; + } + lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate); + /* finish any pending sweep phase */ + while (g->gcstate != GCSfinalize) { + lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep); + singlestep(L); + } + markroot(L); + while (g->gcstate != GCSpause) { + singlestep(L); + } + setthreshold(g); +} + + +void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { + global_State *g = G(L); + lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); + lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); + lua_assert(ttype(&o->gch) != LUA_TTABLE); + /* must keep invariant? */ + if (g->gcstate == GCSpropagate) + reallymarkobject(g, v); /* restore invariant */ + else /* don't mind */ + makewhite(g, o); /* mark as white just to avoid other barriers */ +} + + +void luaC_barrierback (lua_State *L, Table *t) { + global_State *g = G(L); + GCObject *o = obj2gco(t); + lua_assert(isblack(o) && !isdead(g, o)); + lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); + black2gray(o); /* make table gray (again) */ + t->gclist = g->grayagain; + g->grayagain = o; +} + + +void luaC_link (lua_State *L, GCObject *o, lu_byte tt) { + global_State *g = G(L); + o->gch.next = g->rootgc; + g->rootgc = o; + o->gch.marked = luaC_white(g); + o->gch.tt = tt; +} + + +void luaC_linkupval (lua_State *L, UpVal *uv) { + global_State *g = G(L); + GCObject *o = obj2gco(uv); + o->gch.next = g->rootgc; /* link upvalue into `rootgc' list */ + g->rootgc = o; + if (isgray(o)) { + if (g->gcstate == GCSpropagate) { + gray2black(o); /* closed upvalues need barrier */ + luaC_barrier(L, uv, uv->v); + } + else { /* sweep phase: sweep it (turning it into white) */ + makewhite(g, o); + lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); + } + } +} + diff --git a/contrib/syslinux-4.02/com32/lua/src/lgc.h b/contrib/syslinux-4.02/com32/lua/src/lgc.h new file mode 100644 index 0000000..5a8dc60 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lgc.h @@ -0,0 +1,110 @@ +/* +** $Id: lgc.h,v 2.15.1.1 2007/12/27 13:02:25 roberto Exp $ +** Garbage Collector +** See Copyright Notice in lua.h +*/ + +#ifndef lgc_h +#define lgc_h + + +#include "lobject.h" + + +/* +** Possible states of the Garbage Collector +*/ +#define GCSpause 0 +#define GCSpropagate 1 +#define GCSsweepstring 2 +#define GCSsweep 3 +#define GCSfinalize 4 + + +/* +** some userful bit tricks +*/ +#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) +#define setbits(x,m) ((x) |= (m)) +#define testbits(x,m) ((x) & (m)) +#define bitmask(b) (1<<(b)) +#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) +#define l_setbit(x,b) setbits(x, bitmask(b)) +#define resetbit(x,b) resetbits(x, bitmask(b)) +#define testbit(x,b) testbits(x, bitmask(b)) +#define set2bits(x,b1,b2) setbits(x, (bit2mask(b1, b2))) +#define reset2bits(x,b1,b2) resetbits(x, (bit2mask(b1, b2))) +#define test2bits(x,b1,b2) testbits(x, (bit2mask(b1, b2))) + + + +/* +** Layout for bit use in `marked' field: +** bit 0 - object is white (type 0) +** bit 1 - object is white (type 1) +** bit 2 - object is black +** bit 3 - for userdata: has been finalized +** bit 3 - for tables: has weak keys +** bit 4 - for tables: has weak values +** bit 5 - object is fixed (should not be collected) +** bit 6 - object is "super" fixed (only the main thread) +*/ + + +#define WHITE0BIT 0 +#define WHITE1BIT 1 +#define BLACKBIT 2 +#define FINALIZEDBIT 3 +#define KEYWEAKBIT 3 +#define VALUEWEAKBIT 4 +#define FIXEDBIT 5 +#define SFIXEDBIT 6 +#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) + + +#define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) +#define isblack(x) testbit((x)->gch.marked, BLACKBIT) +#define isgray(x) (!isblack(x) && !iswhite(x)) + +#define otherwhite(g) (g->currentwhite ^ WHITEBITS) +#define isdead(g,v) ((v)->gch.marked & otherwhite(g) & WHITEBITS) + +#define changewhite(x) ((x)->gch.marked ^= WHITEBITS) +#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) + +#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) + +#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) + + +#define luaC_checkGC(L) { \ + condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \ + if (G(L)->totalbytes >= G(L)->GCthreshold) \ + luaC_step(L); } + + +#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ + luaC_barrierf(L,obj2gco(p),gcvalue(v)); } + +#define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t))) \ + luaC_barrierback(L,t); } + +#define luaC_objbarrier(L,p,o) \ + { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ + luaC_barrierf(L,obj2gco(p),obj2gco(o)); } + +#define luaC_objbarriert(L,t,o) \ + { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); } + +LUAI_FUNC size_t luaC_separateudata (lua_State *L, int all); +LUAI_FUNC void luaC_callGCTM (lua_State *L); +LUAI_FUNC void luaC_freeall (lua_State *L); +LUAI_FUNC void luaC_step (lua_State *L); +LUAI_FUNC void luaC_fullgc (lua_State *L); +LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt); +LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv); +LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); +LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t); + + +#endif diff --git a/contrib/syslinux-4.02/com32/lua/src/linit.c b/contrib/syslinux-4.02/com32/lua/src/linit.c new file mode 100644 index 0000000..3f15fd0 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/linit.c @@ -0,0 +1,44 @@ +/* +** $Id: linit.c,v 1.14.1.1 2007/12/27 13:02:25 roberto Exp $ +** Initialization of libraries for lua.c +** See Copyright Notice in lua.h +*/ + + +#define linit_c +#define LUA_LIB + +#include "lua.h" + +#include "lualib.h" +#include "lauxlib.h" + + +static const luaL_Reg lualibs[] = { + {"", luaopen_base}, + {LUA_LOADLIBNAME, luaopen_package}, + {LUA_TABLIBNAME, luaopen_table}, + {LUA_IOLIBNAME, luaopen_io}, +// {LUA_OSLIBNAME, luaopen_os}, + {LUA_STRLIBNAME, luaopen_string}, +#if !defined LUA_NUMBER_INTEGRAL + {LUA_MATHLIBNAME, luaopen_math}, +#endif + {LUA_PCILIBNAME, luaopen_pci}, + {LUA_DBLIBNAME, luaopen_debug}, + {LUA_DMILIBNAME, luaopen_dmi}, + {LUA_SYSLINUXLIBNAME, luaopen_syslinux}, + {LUA_VESALIBNAME, luaopen_vesa}, + {NULL, NULL} +}; + + +LUALIB_API void luaL_openlibs (lua_State *L) { + const luaL_Reg *lib = lualibs; + for (; lib->func; lib++) { + lua_pushcfunction(L, lib->func); + lua_pushstring(L, lib->name); + lua_call(L, 1, 0); + } +} + diff --git a/contrib/syslinux-4.02/com32/lua/src/liolib.c b/contrib/syslinux-4.02/com32/lua/src/liolib.c new file mode 100644 index 0000000..d979f45 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/liolib.c @@ -0,0 +1,560 @@ +/* +** $Id: liolib.c,v 2.73.1.3 2008/01/18 17:47:43 roberto Exp $ +** Standard I/O (and system) library +** See Copyright Notice in lua.h +*/ + + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define liolib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + +#define IO_INPUT 1 +#define IO_OUTPUT 2 + + +static const char *const fnames[] = {"input", "output"}; + + +static int pushresult (lua_State *L, int i, const char *filename) { + int en = errno; /* calls to Lua API may change this value */ + if (i) { + lua_pushboolean(L, 1); + return 1; + } + else { + lua_pushnil(L); + if (filename) + lua_pushfstring(L, "%s: %s", filename, strerror(en)); + else + lua_pushfstring(L, "%s", strerror(en)); + lua_pushinteger(L, en); + return 3; + } +} + + +static void fileerror (lua_State *L, int arg, const char *filename) { + lua_pushfstring(L, "%s: %s", filename, strerror(errno)); + luaL_argerror(L, arg, lua_tostring(L, -1)); +} + + +#define tofilep(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE)) + + +static int io_type (lua_State *L) { + void *ud; + luaL_checkany(L, 1); + ud = lua_touserdata(L, 1); + lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE); + if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1)) + lua_pushnil(L); /* not a file */ + else if (*((FILE **)ud) == NULL) + lua_pushliteral(L, "closed file"); + else + lua_pushliteral(L, "file"); + return 1; +} + + +static FILE *tofile (lua_State *L) { + FILE **f = tofilep(L); + if (*f == NULL) + luaL_error(L, "attempt to use a closed file"); + return *f; +} + + + +/* +** When creating file handles, always creates a `closed' file handle +** before opening the actual file; so, if there is a memory error, the +** file is not left opened. +*/ +static FILE **newfile (lua_State *L) { + FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *)); + *pf = NULL; /* file handle is currently `closed' */ + luaL_getmetatable(L, LUA_FILEHANDLE); + lua_setmetatable(L, -2); + return pf; +} + + +/* +** function to (not) close the standard files stdin, stdout, and stderr +*/ +static int io_noclose (lua_State *L) { + lua_pushnil(L); + lua_pushliteral(L, "cannot close standard file"); + return 2; +} + + +/* +** function to close 'popen' files +*/ +static int io_pclose (lua_State *L) { + FILE **p = tofilep(L); + int ok = lua_pclose(L, *p); + *p = NULL; + return pushresult(L, ok, NULL); +} + + +/* +** function to close regular files +*/ +static int io_fclose (lua_State *L) { + FILE **p = tofilep(L); + int ok = (fclose(*p) == 0); + *p = NULL; + return pushresult(L, ok, NULL); +} + + +static int aux_close (lua_State *L) { + lua_getfenv(L, 1); + lua_getfield(L, -1, "__close"); + return (lua_tocfunction(L, -1))(L); +} + + +static int io_close (lua_State *L) { + if (lua_isnone(L, 1)) + lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT); + tofile(L); /* make sure argument is a file */ + return aux_close(L); +} + + +static int io_gc (lua_State *L) { + FILE *f = *tofilep(L); + /* ignore closed files */ + if (f != NULL) + aux_close(L); + return 0; +} + + +static int io_tostring (lua_State *L) { + FILE *f = *tofilep(L); + if (f == NULL) + lua_pushliteral(L, "file (closed)"); + else + lua_pushfstring(L, "file (%p)", f); + return 1; +} + + +static int io_open (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + FILE **pf = newfile(L); + *pf = fopen(filename, mode); + return (*pf == NULL) ? pushresult(L, 0, filename) : 1; +} + + +/* +** this function has a separated environment, which defines the +** correct __close for 'popen' files +*/ +static int io_popen (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + FILE **pf = newfile(L); + *pf = lua_popen(L, filename, mode); + return (*pf == NULL) ? pushresult(L, 0, filename) : 1; +} + + +#if 0 +static int io_tmpfile (lua_State *L) { + FILE **pf = newfile(L); + *pf = tmpfile(); + return (*pf == NULL) ? pushresult(L, 0, NULL) : 1; +} +#endif + + +static FILE *getiofile (lua_State *L, int findex) { + FILE *f; + lua_rawgeti(L, LUA_ENVIRONINDEX, findex); + f = *(FILE **)lua_touserdata(L, -1); + if (f == NULL) + luaL_error(L, "standard %s file is closed", fnames[findex - 1]); + return f; +} + + +static int g_iofile (lua_State *L, int f, const char *mode) { + if (!lua_isnoneornil(L, 1)) { + const char *filename = lua_tostring(L, 1); + if (filename) { + FILE **pf = newfile(L); + *pf = fopen(filename, mode); + if (*pf == NULL) + fileerror(L, 1, filename); + } + else { + tofile(L); /* check that it's a valid file handle */ + lua_pushvalue(L, 1); + } + lua_rawseti(L, LUA_ENVIRONINDEX, f); + } + /* return current value */ + lua_rawgeti(L, LUA_ENVIRONINDEX, f); + return 1; +} + + +static int io_input (lua_State *L) { + return g_iofile(L, IO_INPUT, "r"); +} + + +static int io_output (lua_State *L) { + return g_iofile(L, IO_OUTPUT, "w"); +} + + +static int io_readline (lua_State *L); + + +static void aux_lines (lua_State *L, int idx, int toclose) { + lua_pushvalue(L, idx); + lua_pushboolean(L, toclose); /* close/not close file when finished */ + lua_pushcclosure(L, io_readline, 2); +} + + +static int f_lines (lua_State *L) { + tofile(L); /* check that it's a valid file handle */ + aux_lines(L, 1, 0); + return 1; +} + + +static int io_lines (lua_State *L) { + if (lua_isnoneornil(L, 1)) { /* no arguments? */ + /* will iterate over default input */ + lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT); + return f_lines(L); + } + else { + const char *filename = luaL_checkstring(L, 1); + FILE **pf = newfile(L); + *pf = fopen(filename, "r"); + if (*pf == NULL) + fileerror(L, 1, filename); + aux_lines(L, lua_gettop(L), 1); + return 1; + } +} + + +/* +** {====================================================== +** READ +** ======================================================= +*/ + +#if 0 +static int read_number (lua_State *L, FILE *f) { + lua_Number d; + if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) { + lua_pushnumber(L, d); + return 1; + } + else return 0; /* read fails */ +} + + +static int test_eof (lua_State *L, FILE *f) { + int c = getc(f); + ungetc(c, f); + lua_pushlstring(L, NULL, 0); + return (c != EOF); +} +#endif + + +static int read_line (lua_State *L, FILE *f) { + luaL_Buffer b; + luaL_buffinit(L, &b); + for (;;) { + size_t l; + char *p = luaL_prepbuffer(&b); + if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ + luaL_pushresult(&b); /* close buffer */ + return (lua_objlen(L, -1) > 0); /* check whether read something */ + } + l = strlen(p); + if (l == 0 || p[l-1] != '\n') + luaL_addsize(&b, l); + else { + luaL_addsize(&b, l - 1); /* do not include `eol' */ + luaL_pushresult(&b); /* close buffer */ + return 1; /* read at least an `eol' */ + } + } +} + +#if 0 /* Not used */ +static int read_chars (lua_State *L, FILE *f, size_t n) { + size_t rlen; /* how much to read */ + size_t nr; /* number of chars actually read */ + luaL_Buffer b; + luaL_buffinit(L, &b); + rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ + do { + char *p = luaL_prepbuffer(&b); + if (rlen > n) rlen = n; /* cannot read more than asked */ + nr = fread(p, sizeof(char), rlen, f); + luaL_addsize(&b, nr); + n -= nr; /* still have to read `n' chars */ + } while (n > 0 && nr == rlen); /* until end of count or eof */ + luaL_pushresult(&b); /* close buffer */ + return (n == 0 || lua_objlen(L, -1) > 0); +} +#endif + +#if 0 +static int g_read (lua_State *L, FILE *f, int first) { + int nargs = lua_gettop(L) - 1; + int success; + int n; + clearerr(f); + if (nargs == 0) { /* no arguments? */ + success = read_line(L, f); + n = first+1; /* to return 1 result */ + } + else { /* ensure stack space for all results and for auxlib's buffer */ + luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments"); + success = 1; + for (n = first; nargs-- && success; n++) { + if (lua_type(L, n) == LUA_TNUMBER) { + size_t l = (size_t)lua_tointeger(L, n); + success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); + } + else { + const char *p = lua_tostring(L, n); + luaL_argcheck(L, p && p[0] == '*', n, "invalid option"); + switch (p[1]) { + case 'n': /* number */ + success = read_number(L, f); + break; + case 'l': /* line */ + success = read_line(L, f); + break; + case 'a': /* file */ + read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */ + success = 1; /* always success */ + break; + default: + return luaL_argerror(L, n, "invalid format"); + } + } + } + } + if (ferror(f)) + return pushresult(L, 0, NULL); + if (!success) { + lua_pop(L, 1); /* remove last result */ + lua_pushnil(L); /* push nil instead */ + } + return n - first; +} + + +static int io_read (lua_State *L) { + return g_read(L, getiofile(L, IO_INPUT), 1); +} + + +static int f_read (lua_State *L) { + return g_read(L, tofile(L), 2); +} +#endif + + +static int io_readline (lua_State *L) { + FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1)); + int sucess; + if (f == NULL) /* file is already closed? */ + luaL_error(L, "file is already closed"); + sucess = read_line(L, f); + if (ferror(f)) + return luaL_error(L, "%s", strerror(errno)); + if (sucess) return 1; + else { /* EOF */ + if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */ + lua_settop(L, 0); + lua_pushvalue(L, lua_upvalueindex(1)); + aux_close(L); /* close it */ + } + return 0; + } +} + +/* }====================================================== */ + + +static int g_write (lua_State *L, FILE *f, int arg) { + int nargs = lua_gettop(L) - 1; + int status = 1; + for (; nargs--; arg++) { + if (lua_type(L, arg) == LUA_TNUMBER) { + /* optimization: could be done exactly as for strings */ + status = status && + fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; + } + else { + size_t l; + const char *s = luaL_checklstring(L, arg, &l); + status = status && (fwrite(s, sizeof(char), l, f) == l); + } + } + return pushresult(L, status, NULL); +} + + +static int io_write (lua_State *L) { + return g_write(L, getiofile(L, IO_OUTPUT), 1); +} + + +static int f_write (lua_State *L) { + return g_write(L, tofile(L), 2); +} + +#if 0 +static int f_seek (lua_State *L) { + static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; + static const char *const modenames[] = {"set", "cur", "end", NULL}; + FILE *f = tofile(L); + int op = luaL_checkoption(L, 2, "cur", modenames); + long offset = luaL_optlong(L, 3, 0); + op = fseek(f, offset, mode[op]); + if (op) + return pushresult(L, 0, NULL); /* error */ + else { + lua_pushinteger(L, ftell(f)); + return 1; + } +} +#endif + + +#if 0 +static int f_setvbuf (lua_State *L) { + static const int mode[] = {_IONBF, _IOFBF, _IOLBF}; + static const char *const modenames[] = {"no", "full", "line", NULL}; + FILE *f = tofile(L); + int op = luaL_checkoption(L, 2, NULL, modenames); + lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); + int res = setvbuf(f, NULL, mode[op], sz); + return pushresult(L, res == 0, NULL); +} +#endif + + +static int io_flush (lua_State *L) { + return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); +} + + +static int f_flush (lua_State *L) { + return pushresult(L, fflush(tofile(L)) == 0, NULL); +} + + +static const luaL_Reg iolib[] = { + {"close", io_close}, + {"flush", io_flush}, + {"input", io_input}, + {"lines", io_lines}, + {"open", io_open}, + {"output", io_output}, + {"popen", io_popen}, +/* {"read", io_read}, */ +/* {"tmpfile", io_tmpfile}, */ + {"type", io_type}, + {"write", io_write}, + {NULL, NULL} +}; + + +static const luaL_Reg flib[] = { + {"close", io_close}, + {"flush", f_flush}, + {"lines", f_lines}, +/* {"read", f_read}, */ +/* {"seek", f_seek}, */ +/* {"setvbuf", f_setvbuf}, */ + {"write", f_write}, + {"__gc", io_gc}, + {"__tostring", io_tostring}, + {NULL, NULL} +}; + + +static void createmeta (lua_State *L) { + luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ + lua_pushvalue(L, -1); /* push metatable */ + lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ + luaL_register(L, NULL, flib); /* file methods */ +} + + +static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) { + *newfile(L) = f; + if (k > 0) { + lua_pushvalue(L, -1); + lua_rawseti(L, LUA_ENVIRONINDEX, k); + } + lua_pushvalue(L, -2); /* copy environment */ + lua_setfenv(L, -2); /* set it */ + lua_setfield(L, -3, fname); +} + + +static void newfenv (lua_State *L, lua_CFunction cls) { + lua_createtable(L, 0, 1); + lua_pushcfunction(L, cls); + lua_setfield(L, -2, "__close"); +} + + +LUALIB_API int luaopen_io (lua_State *L) { + createmeta(L); + /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */ + newfenv(L, io_fclose); + lua_replace(L, LUA_ENVIRONINDEX); + /* open library */ + luaL_register(L, LUA_IOLIBNAME, iolib); + /* create (and set) default files */ + newfenv(L, io_noclose); /* close function for default files */ + createstdfile(L, stdin, IO_INPUT, "stdin"); + createstdfile(L, stdout, IO_OUTPUT, "stdout"); + createstdfile(L, stderr, 0, "stderr"); + lua_pop(L, 1); /* pop environment for default files */ + lua_getfield(L, -1, "popen"); + newfenv(L, io_pclose); /* create environment for 'popen' */ + lua_setfenv(L, -2); /* set fenv for 'popen' */ + lua_pop(L, 1); /* pop 'popen' */ + return 1; +} + diff --git a/contrib/syslinux-4.02/com32/lua/src/llex.c b/contrib/syslinux-4.02/com32/lua/src/llex.c new file mode 100644 index 0000000..73f01f1 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/llex.c @@ -0,0 +1,461 @@ +/* +** $Id: llex.c,v 2.20.1.1 2007/12/27 13:02:25 roberto Exp $ +** Lexical Analyzer +** See Copyright Notice in lua.h +*/ + + +#include <ctype.h> +//#include <locale.h> +#include <string.h> + +#define llex_c +#define LUA_CORE + +#include "lua.h" + +#include "ldo.h" +#include "llex.h" +#include "lobject.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "lzio.h" + + + +#define next(ls) (ls->current = zgetc(ls->z)) + + + + +#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') + + +/* ORDER RESERVED */ +const char *const luaX_tokens [] = { + "and", "break", "do", "else", "elseif", + "end", "false", "for", "function", "if", + "in", "local", "nil", "not", "or", "repeat", + "return", "then", "true", "until", "while", + "..", "...", "==", ">=", "<=", "~=", + "<number>", "<name>", "<string>", "<eof>", + NULL +}; + + +#define save_and_next(ls) (save(ls, ls->current), next(ls)) + + +static void save (LexState *ls, int c) { + Mbuffer *b = ls->buff; + if (b->n + 1 > b->buffsize) { + size_t newsize; + if (b->buffsize >= MAX_SIZET/2) + luaX_lexerror(ls, "lexical element too long", 0); + newsize = b->buffsize * 2; + luaZ_resizebuffer(ls->L, b, newsize); + } + b->buffer[b->n++] = cast(char, c); +} + + +void luaX_init (lua_State *L) { + int i; + for (i=0; i<NUM_RESERVED; i++) { + TString *ts = luaS_new(L, luaX_tokens[i]); + luaS_fix(ts); /* reserved words are never collected */ + lua_assert(strlen(luaX_tokens[i])+1 <= TOKEN_LEN); + ts->tsv.reserved = cast_byte(i+1); /* reserved word */ + } +} + + +#define MAXSRC 80 + + +const char *luaX_token2str (LexState *ls, int token) { + if (token < FIRST_RESERVED) { + lua_assert(token == cast(unsigned char, token)); + return (iscntrl(token)) ? luaO_pushfstring(ls->L, "char(%d)", token) : + luaO_pushfstring(ls->L, "%c", token); + } + else + return luaX_tokens[token-FIRST_RESERVED]; +} + + +static const char *txtToken (LexState *ls, int token) { + switch (token) { + case TK_NAME: + case TK_STRING: + case TK_NUMBER: + save(ls, '\0'); + return luaZ_buffer(ls->buff); + default: + return luaX_token2str(ls, token); + } +} + + +void luaX_lexerror (LexState *ls, const char *msg, int token) { + char buff[MAXSRC]; + luaO_chunkid(buff, getstr(ls->source), MAXSRC); + msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg); + if (token) + luaO_pushfstring(ls->L, "%s near " LUA_QS, msg, txtToken(ls, token)); + luaD_throw(ls->L, LUA_ERRSYNTAX); +} + + +void luaX_syntaxerror (LexState *ls, const char *msg) { + luaX_lexerror(ls, msg, ls->t.token); +} + + +TString *luaX_newstring (LexState *ls, const char *str, size_t l) { + lua_State *L = ls->L; + TString *ts = luaS_newlstr(L, str, l); + TValue *o = luaH_setstr(L, ls->fs->h, ts); /* entry for `str' */ + if (ttisnil(o)) + setbvalue(o, 1); /* make sure `str' will not be collected */ + return ts; +} + + +static void inclinenumber (LexState *ls) { + int old = ls->current; + lua_assert(currIsNewline(ls)); + next(ls); /* skip `\n' or `\r' */ + if (currIsNewline(ls) && ls->current != old) + next(ls); /* skip `\n\r' or `\r\n' */ + if (++ls->linenumber >= MAX_INT) + luaX_syntaxerror(ls, "chunk has too many lines"); +} + + +void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) { + ls->decpoint = '.'; + ls->L = L; + ls->lookahead.token = TK_EOS; /* no look-ahead token */ + ls->z = z; + ls->fs = NULL; + ls->linenumber = 1; + ls->lastline = 1; + ls->source = source; + luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ + next(ls); /* read first char */ +} + + + +/* +** ======================================================= +** LEXICAL ANALYZER +** ======================================================= +*/ + + + +static int check_next (LexState *ls, const char *set) { + if (!strchr(set, ls->current)) + return 0; + save_and_next(ls); + return 1; +} + + +static void buffreplace (LexState *ls, char from, char to) { + size_t n = luaZ_bufflen(ls->buff); + char *p = luaZ_buffer(ls->buff); + while (n--) + if (p[n] == from) p[n] = to; +} + + +static void trydecpoint (LexState *ls, SemInfo *seminfo) { + /* format error: try to update decimal point separator */ + //struct lconv *cv = localeconv(); + char old = ls->decpoint; + //ls->decpoint = (cv ? cv->decimal_point[0] : '.'); + buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */ + if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) { + /* format error with correct decimal point: no more options */ + buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ + luaX_lexerror(ls, "malformed number", TK_NUMBER); + } +} + + +/* LUA_NUMBER */ +static void read_numeral (LexState *ls, SemInfo *seminfo) { + lua_assert(isdigit(ls->current)); + do { + save_and_next(ls); + } while (isdigit(ls->current) || ls->current == '.'); + if (check_next(ls, "Ee")) /* `E'? */ + check_next(ls, "+-"); /* optional exponent sign */ + while (isalnum(ls->current) || ls->current == '_') + save_and_next(ls); + save(ls, '\0'); + buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ + if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */ + trydecpoint(ls, seminfo); /* try to update decimal point separator */ +} + + +static int skip_sep (LexState *ls) { + int count = 0; + int s = ls->current; + lua_assert(s == '[' || s == ']'); + save_and_next(ls); + while (ls->current == '=') { + save_and_next(ls); + count++; + } + return (ls->current == s) ? count : (-count) - 1; +} + + +static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { + int cont = 0; + (void)(cont); /* avoid warnings when `cont' is not used */ + save_and_next(ls); /* skip 2nd `[' */ + if (currIsNewline(ls)) /* string starts with a newline? */ + inclinenumber(ls); /* skip it */ + for (;;) { + switch (ls->current) { + case EOZ: + luaX_lexerror(ls, (seminfo) ? "unfinished long string" : + "unfinished long comment", TK_EOS); + break; /* to avoid warnings */ +#if defined(LUA_COMPAT_LSTR) + case '[': { + if (skip_sep(ls) == sep) { + save_and_next(ls); /* skip 2nd `[' */ + cont++; +#if LUA_COMPAT_LSTR == 1 + if (sep == 0) + luaX_lexerror(ls, "nesting of [[...]] is deprecated", '['); +#endif + } + break; + } +#endif + case ']': { + if (skip_sep(ls) == sep) { + save_and_next(ls); /* skip 2nd `]' */ +#if defined(LUA_COMPAT_LSTR) && LUA_COMPAT_LSTR == 2 + cont--; + if (sep == 0 && cont >= 0) break; +#endif + goto endloop; + } + break; + } + case '\n': + case '\r': { + save(ls, '\n'); + inclinenumber(ls); + if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ + break; + } + default: { + if (seminfo) save_and_next(ls); + else next(ls); + } + } + } endloop: + if (seminfo) + seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep), + luaZ_bufflen(ls->buff) - 2*(2 + sep)); +} + + +static void read_string (LexState *ls, int del, SemInfo *seminfo) { + save_and_next(ls); + while (ls->current != del) { + switch (ls->current) { + case EOZ: + luaX_lexerror(ls, "unfinished string", TK_EOS); + continue; /* to avoid warnings */ + case '\n': + case '\r': + luaX_lexerror(ls, "unfinished string", TK_STRING); + continue; /* to avoid warnings */ + case '\\': { + int c; + next(ls); /* do not save the `\' */ + switch (ls->current) { + case 'a': c = '\a'; break; + case 'b': c = '\b'; break; + case 'f': c = '\f'; break; + case 'n': c = '\n'; break; + case 'r': c = '\r'; break; + case 't': c = '\t'; break; + case 'v': c = '\v'; break; + case '\n': /* go through */ + case '\r': save(ls, '\n'); inclinenumber(ls); continue; + case EOZ: continue; /* will raise an error next loop */ + default: { + if (!isdigit(ls->current)) + save_and_next(ls); /* handles \\, \", \', and \? */ + else { /* \xxx */ + int i = 0; + c = 0; + do { + c = 10*c + (ls->current-'0'); + next(ls); + } while (++i<3 && isdigit(ls->current)); + if (c > UCHAR_MAX) + luaX_lexerror(ls, "escape sequence too large", TK_STRING); + save(ls, c); + } + continue; + } + } + save(ls, c); + next(ls); + continue; + } + default: + save_and_next(ls); + } + } + save_and_next(ls); /* skip delimiter */ + seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1, + luaZ_bufflen(ls->buff) - 2); +} + + +static int llex (LexState *ls, SemInfo *seminfo) { + luaZ_resetbuffer(ls->buff); + for (;;) { + switch (ls->current) { + case '\n': + case '\r': { + inclinenumber(ls); + continue; + } + case '-': { + next(ls); + if (ls->current != '-') return '-'; + /* else is a comment */ + next(ls); + if (ls->current == '[') { + int sep = skip_sep(ls); + luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */ + if (sep >= 0) { + read_long_string(ls, NULL, sep); /* long comment */ + luaZ_resetbuffer(ls->buff); + continue; + } + } + /* else short comment */ + while (!currIsNewline(ls) && ls->current != EOZ) + next(ls); + continue; + } + case '[': { + int sep = skip_sep(ls); + if (sep >= 0) { + read_long_string(ls, seminfo, sep); + return TK_STRING; + } + else if (sep == -1) return '['; + else luaX_lexerror(ls, "invalid long string delimiter", TK_STRING); + } + case '=': { + next(ls); + if (ls->current != '=') return '='; + else { next(ls); return TK_EQ; } + } + case '<': { + next(ls); + if (ls->current != '=') return '<'; + else { next(ls); return TK_LE; } + } + case '>': { + next(ls); + if (ls->current != '=') return '>'; + else { next(ls); return TK_GE; } + } + case '~': { + next(ls); + if (ls->current != '=') return '~'; + else { next(ls); return TK_NE; } + } + case '"': + case '\'': { + read_string(ls, ls->current, seminfo); + return TK_STRING; + } + case '.': { + save_and_next(ls); + if (check_next(ls, ".")) { + if (check_next(ls, ".")) + return TK_DOTS; /* ... */ + else return TK_CONCAT; /* .. */ + } + else if (!isdigit(ls->current)) return '.'; + else { + read_numeral(ls, seminfo); + return TK_NUMBER; + } + } + case EOZ: { + return TK_EOS; + } + default: { + if (isspace(ls->current)) { + lua_assert(!currIsNewline(ls)); + next(ls); + continue; + } + else if (isdigit(ls->current)) { + read_numeral(ls, seminfo); + return TK_NUMBER; + } + else if (isalpha(ls->current) || ls->current == '_') { + /* identifier or reserved word */ + TString *ts; + do { + save_and_next(ls); + } while (isalnum(ls->current) || ls->current == '_'); + ts = luaX_newstring(ls, luaZ_buffer(ls->buff), + luaZ_bufflen(ls->buff)); + if (ts->tsv.reserved > 0) /* reserved word? */ + return ts->tsv.reserved - 1 + FIRST_RESERVED; + else { + seminfo->ts = ts; + return TK_NAME; + } + } + else { + int c = ls->current; + next(ls); + return c; /* single-char tokens (+ - / ...) */ + } + } + } + } +} + + +void luaX_next (LexState *ls) { + ls->lastline = ls->linenumber; + if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */ + ls->t = ls->lookahead; /* use this one */ + ls->lookahead.token = TK_EOS; /* and discharge it */ + } + else + ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */ +} + + +void luaX_lookahead (LexState *ls) { + lua_assert(ls->lookahead.token == TK_EOS); + ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); +} + diff --git a/contrib/syslinux-4.02/com32/lua/src/llex.h b/contrib/syslinux-4.02/com32/lua/src/llex.h new file mode 100644 index 0000000..a9201ce --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/llex.h @@ -0,0 +1,81 @@ +/* +** $Id: llex.h,v 1.58.1.1 2007/12/27 13:02:25 roberto Exp $ +** Lexical Analyzer +** See Copyright Notice in lua.h +*/ + +#ifndef llex_h +#define llex_h + +#include "lobject.h" +#include "lzio.h" + + +#define FIRST_RESERVED 257 + +/* maximum length of a reserved word */ +#define TOKEN_LEN (sizeof("function")/sizeof(char)) + + +/* +* WARNING: if you change the order of this enumeration, +* grep "ORDER RESERVED" +*/ +enum RESERVED { + /* terminal symbols denoted by reserved words */ + TK_AND = FIRST_RESERVED, TK_BREAK, + TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, + TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, + TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, + /* other terminal symbols */ + TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, + TK_NAME, TK_STRING, TK_EOS +}; + +/* number of reserved words */ +#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) + + +/* array with token `names' */ +LUAI_DATA const char *const luaX_tokens []; + + +typedef union { + lua_Number r; + TString *ts; +} SemInfo; /* semantics information */ + + +typedef struct Token { + int token; + SemInfo seminfo; +} Token; + + +typedef struct LexState { + int current; /* current character (charint) */ + int linenumber; /* input line counter */ + int lastline; /* line of last token `consumed' */ + Token t; /* current token */ + Token lookahead; /* look ahead token */ + struct FuncState *fs; /* `FuncState' is private to the parser */ + struct lua_State *L; + ZIO *z; /* input stream */ + Mbuffer *buff; /* buffer for tokens */ + TString *source; /* current source name */ + char decpoint; /* locale decimal point */ +} LexState; + + +LUAI_FUNC void luaX_init (lua_State *L); +LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, + TString *source); +LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); +LUAI_FUNC void luaX_next (LexState *ls); +LUAI_FUNC void luaX_lookahead (LexState *ls); +LUAI_FUNC void luaX_lexerror (LexState *ls, const char *msg, int token); +LUAI_FUNC void luaX_syntaxerror (LexState *ls, const char *s); +LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); + + +#endif diff --git a/contrib/syslinux-4.02/com32/lua/src/llimits.h b/contrib/syslinux-4.02/com32/lua/src/llimits.h new file mode 100644 index 0000000..ca8dcb7 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/llimits.h @@ -0,0 +1,128 @@ +/* +** $Id: llimits.h,v 1.69.1.1 2007/12/27 13:02:25 roberto Exp $ +** Limits, basic types, and some other `installation-dependent' definitions +** See Copyright Notice in lua.h +*/ + +#ifndef llimits_h +#define llimits_h + + +#include <limits.h> +#include <stddef.h> + + +#include "lua.h" + + +typedef LUAI_UINT32 lu_int32; + +typedef LUAI_UMEM lu_mem; + +typedef LUAI_MEM l_mem; + + + +/* chars used as small naturals (so that `char' is reserved for characters) */ +typedef unsigned char lu_byte; + + +#define MAX_SIZET ((size_t)(~(size_t)0)-2) + +#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2) + + +#define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */ + +/* +** conversion of pointer to integer +** this is for hashing only; there is no problem if the integer +** cannot hold the whole pointer value +*/ +#define IntPoint(p) ((unsigned int)(lu_mem)(p)) + + + +/* type to ensure maximum alignment */ +typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; + + +/* result of a `usual argument conversion' over lua_Number */ +typedef LUAI_UACNUMBER l_uacNumber; + + +/* internal assertions for in-house debugging */ +#ifdef lua_assert + +#define check_exp(c,e) (lua_assert(c), (e)) +#define api_check(l,e) lua_assert(e) + +#else + +#define lua_assert(c) ((void)0) +#define check_exp(c,e) (e) +#define api_check luai_apicheck + +#endif + + +#ifndef UNUSED +#define UNUSED(x) ((void)(x)) /* to avoid warnings */ +#endif + + +#ifndef cast +#define cast(t, exp) ((t)(exp)) +#endif + +#define cast_byte(i) cast(lu_byte, (i)) +#define cast_num(i) cast(lua_Number, (i)) +#define cast_int(i) cast(int, (i)) + + + +/* +** type for virtual-machine instructions +** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) +*/ +typedef lu_int32 Instruction; + + + +/* maximum stack for a Lua function */ +#define MAXSTACK 250 + + + +/* minimum size for the string table (must be power of 2) */ +#ifndef MINSTRTABSIZE +#define MINSTRTABSIZE 32 +#endif + + +/* minimum size for string buffer */ +#ifndef LUA_MINBUFFER +#define LUA_MINBUFFER 32 +#endif + + +#ifndef lua_lock +#define lua_lock(L) ((void) 0) +#define lua_unlock(L) ((void) 0) +#endif + +#ifndef luai_threadyield +#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} +#endif + + +/* +** macro to control inclusion of some hard tests on stack reallocation +*/ +#ifndef HARDSTACKTESTS +#define condhardstacktests(x) ((void)0) +#else +#define condhardstacktests(x) x +#endif + +#endif diff --git a/contrib/syslinux-4.02/com32/lua/src/lmathlib.c b/contrib/syslinux-4.02/com32/lua/src/lmathlib.c new file mode 100644 index 0000000..ccae8ed --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lmathlib.c @@ -0,0 +1,265 @@ +/* +** $Id: lmathlib.c,v 1.67.1.1 2007/12/27 13:02:25 roberto Exp $ +** Standard mathematical library +** See Copyright Notice in lua.h +*/ + + +#include <stdlib.h> +#include <math.h> + +#define lmathlib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#undef PI +#define PI (3.14159265358979323846) +#define RADIANS_PER_DEGREE (PI/180.0) + + + +static int math_abs (lua_State *L) { + lua_pushnumber(L, fabs(luaL_checknumber(L, 1))); + return 1; +} + +static int math_sin (lua_State *L) { + lua_pushnumber(L, sin(luaL_checknumber(L, 1))); + return 1; +} + +static int math_sinh (lua_State *L) { + lua_pushnumber(L, sinh(luaL_checknumber(L, 1))); + return 1; +} + +static int math_cos (lua_State *L) { + lua_pushnumber(L, cos(luaL_checknumber(L, 1))); + return 1; +} + +static int math_cosh (lua_State *L) { + lua_pushnumber(L, cosh(luaL_checknumber(L, 1))); + return 1; +} + +static int math_tan (lua_State *L) { + lua_pushnumber(L, tan(luaL_checknumber(L, 1))); + return 1; +} + +static int math_tanh (lua_State *L) { + lua_pushnumber(L, tanh(luaL_checknumber(L, 1))); + return 1; +} + +static int math_asin (lua_State *L) { + lua_pushnumber(L, asin(luaL_checknumber(L, 1))); + return 1; +} + +static int math_acos (lua_State *L) { + lua_pushnumber(L, acos(luaL_checknumber(L, 1))); + return 1; +} + +static int math_atan (lua_State *L) { + lua_pushnumber(L, atan(luaL_checknumber(L, 1))); + return 1; +} + +static int math_atan2 (lua_State *L) { + lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); + return 1; +} + +static int math_ceil (lua_State *L) { + lua_pushnumber(L, ceil(luaL_checknumber(L, 1))); + return 1; +} + +static int math_floor (lua_State *L) { + lua_pushnumber(L, floor(luaL_checknumber(L, 1))); + return 1; +} + +static int math_fmod (lua_State *L) { + lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); + return 1; +} + +static int math_modf (lua_State *L) { + double ip; + double fp = modf(luaL_checknumber(L, 1), &ip); + lua_pushnumber(L, ip); + lua_pushnumber(L, fp); + return 2; +} + +static int math_sqrt (lua_State *L) { + lua_pushnumber(L, sqrt(luaL_checknumber(L, 1))); + return 1; +} + +static int math_pow (lua_State *L) { + lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); + return 1; +} + +static int math_log (lua_State *L) { + lua_pushnumber(L, log(luaL_checknumber(L, 1))); + return 1; +} + +static int math_log10 (lua_State *L) { + lua_pushnumber(L, log10(luaL_checknumber(L, 1))); + return 1; +} + +static int math_exp (lua_State *L) { + lua_pushnumber(L, exp(luaL_checknumber(L, 1))); + return 1; +} + +static int math_deg (lua_State *L) { + lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE); + return 1; +} + +static int math_rad (lua_State *L) { + lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE); + return 1; +} + +static int math_frexp (lua_State *L) { + int e; + lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e)); + lua_pushinteger(L, e); + return 2; +} + +static int math_ldexp (lua_State *L) { + lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2))); + return 1; +} + + + +static int math_min (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + lua_Number dmin = luaL_checknumber(L, 1); + int i; + for (i=2; i<=n; i++) { + lua_Number d = luaL_checknumber(L, i); + if (d < dmin) + dmin = d; + } + lua_pushnumber(L, dmin); + return 1; +} + + +static int math_max (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + lua_Number dmax = luaL_checknumber(L, 1); + int i; + for (i=2; i<=n; i++) { + lua_Number d = luaL_checknumber(L, i); + if (d > dmax) + dmax = d; + } + lua_pushnumber(L, dmax); + return 1; +} + + +static int math_random (lua_State *L) { + /* the `%' avoids the (rare) case of r==1, and is needed also because on + some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */ + lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX; + switch (lua_gettop(L)) { /* check number of arguments */ + case 0: { /* no arguments */ + lua_pushnumber(L, r); /* Number between 0 and 1 */ + break; + } + case 1: { /* only upper limit */ + int u = luaL_checkint(L, 1); + luaL_argcheck(L, 1<=u, 1, "interval is empty"); + lua_pushnumber(L, floor(r*u)+1); /* int between 1 and `u' */ + break; + } + case 2: { /* lower and upper limits */ + int l = luaL_checkint(L, 1); + int u = luaL_checkint(L, 2); + luaL_argcheck(L, l<=u, 2, "interval is empty"); + lua_pushnumber(L, floor(r*(u-l+1))+l); /* int between `l' and `u' */ + break; + } + default: return luaL_error(L, "wrong number of arguments"); + } + return 1; +} + + +static int math_randomseed (lua_State *L) { + srand(luaL_checkint(L, 1)); + return 0; +} + + +static const luaL_Reg mathlib[] = { + {"abs", math_abs}, + {"acos", math_acos}, + {"asin", math_asin}, + {"atan2", math_atan2}, + {"atan", math_atan}, + {"ceil", math_ceil}, + {"cosh", math_cosh}, + {"cos", math_cos}, + {"deg", math_deg}, + {"exp", math_exp}, + {"floor", math_floor}, + {"fmod", math_fmod}, + {"frexp", math_frexp}, + {"ldexp", math_ldexp}, + {"log10", math_log10}, + {"log", math_log}, + {"max", math_max}, + {"min", math_min}, + {"modf", math_modf}, + {"pow", math_pow}, + {"rad", math_rad}, + {"random", math_random}, + {"randomseed", math_randomseed}, + {"sinh", math_sinh}, + {"sin", math_sin}, + {"sqrt", math_sqrt}, + {"tanh", math_tanh}, + {"tan", math_tan}, + {NULL, NULL} +}; + + +/* +** Open math library +*/ +LUALIB_API int luaopen_math (lua_State *L) { + luaL_register(L, LUA_MATHLIBNAME, mathlib); + lua_pushnumber(L, PI); + lua_setfield(L, -2, "pi"); +#if !defined LUA_NUMBER_INTEGRAL + lua_pushnumber(L, HUGE_VAL); + lua_setfield(L, -2, "huge"); +#endif +#if defined(LUA_COMPAT_MOD) + lua_getfield(L, -1, "fmod"); + lua_setfield(L, -2, "mod"); +#endif + return 1; +} + diff --git a/contrib/syslinux-4.02/com32/lua/src/lmem.c b/contrib/syslinux-4.02/com32/lua/src/lmem.c new file mode 100644 index 0000000..ae7d8c9 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lmem.c @@ -0,0 +1,86 @@ +/* +** $Id: lmem.c,v 1.70.1.1 2007/12/27 13:02:25 roberto Exp $ +** Interface to Memory Manager +** See Copyright Notice in lua.h +*/ + + +#include <stddef.h> + +#define lmem_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" + + + +/* +** About the realloc function: +** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); +** (`osize' is the old size, `nsize' is the new size) +** +** Lua ensures that (ptr == NULL) iff (osize == 0). +** +** * frealloc(ud, NULL, 0, x) creates a new block of size `x' +** +** * frealloc(ud, p, x, 0) frees the block `p' +** (in this specific case, frealloc must return NULL). +** particularly, frealloc(ud, NULL, 0, 0) does nothing +** (which is equivalent to free(NULL) in ANSI C) +** +** frealloc returns NULL if it cannot create or reallocate the area +** (any reallocation to an equal or smaller size cannot fail!) +*/ + + + +#define MINSIZEARRAY 4 + + +void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, + int limit, const char *errormsg) { + void *newblock; + int newsize; + if (*size >= limit/2) { /* cannot double it? */ + if (*size >= limit) /* cannot grow even a little? */ + luaG_runerror(L, errormsg); + newsize = limit; /* still have at least one free place */ + } + else { + newsize = (*size)*2; + if (newsize < MINSIZEARRAY) + newsize = MINSIZEARRAY; /* minimum size */ + } + newblock = luaM_reallocv(L, block, *size, newsize, size_elems); + *size = newsize; /* update only when everything else is OK */ + return newblock; +} + + +void *luaM_toobig (lua_State *L) { + luaG_runerror(L, "memory allocation error: block too big"); + return NULL; /* to avoid warnings */ +} + + + +/* +** generic allocation routine. +*/ +void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { + global_State *g = G(L); + lua_assert((osize == 0) == (block == NULL)); + block = (*g->frealloc)(g->ud, block, osize, nsize); + if (block == NULL && nsize > 0) + luaD_throw(L, LUA_ERRMEM); + lua_assert((nsize == 0) == (block == NULL)); + g->totalbytes = (g->totalbytes - osize) + nsize; + return block; +} + diff --git a/contrib/syslinux-4.02/com32/lua/src/lmem.h b/contrib/syslinux-4.02/com32/lua/src/lmem.h new file mode 100644 index 0000000..7c2dcb3 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lmem.h @@ -0,0 +1,49 @@ +/* +** $Id: lmem.h,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ +** Interface to Memory Manager +** See Copyright Notice in lua.h +*/ + +#ifndef lmem_h +#define lmem_h + + +#include <stddef.h> + +#include "llimits.h" +#include "lua.h" + +#define MEMERRMSG "not enough memory" + + +#define luaM_reallocv(L,b,on,n,e) \ + ((cast(size_t, (n)+1) <= MAX_SIZET/(e)) ? /* +1 to avoid warnings */ \ + luaM_realloc_(L, (b), (on)*(e), (n)*(e)) : \ + luaM_toobig(L)) + +#define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) +#define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) +#define luaM_freearray(L, b, n, t) luaM_reallocv(L, (b), n, 0, sizeof(t)) + +#define luaM_malloc(L,t) luaM_realloc_(L, NULL, 0, (t)) +#define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) +#define luaM_newvector(L,n,t) \ + cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) + +#define luaM_growvector(L,v,nelems,size,t,limit,e) \ + if ((nelems)+1 > (size)) \ + ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e))) + +#define luaM_reallocvector(L, v,oldn,n,t) \ + ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) + + +LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, + size_t size); +LUAI_FUNC void *luaM_toobig (lua_State *L); +LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, + size_t size_elem, int limit, + const char *errormsg); + +#endif + diff --git a/contrib/syslinux-4.02/com32/lua/src/loadlib.c b/contrib/syslinux-4.02/com32/lua/src/loadlib.c new file mode 100644 index 0000000..b6f4cc6 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/loadlib.c @@ -0,0 +1,665 @@ +/* +** $Id: loadlib.c,v 1.52.1.2 2007/12/28 14:58:43 roberto Exp $ +** Dynamic library loader for Lua +** See Copyright Notice in lua.h +** +** This module contains an implementation of loadlib for Unix systems +** that have dlfcn, an implementation for Darwin (Mac OS X), an +** implementation for Windows, and a stub for other systems. +*/ + + +#include <stdlib.h> +#include <string.h> + + +#define loadlib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* prefix for open functions in C libraries */ +#define LUA_POF "luaopen_" + +/* separator for open functions in C libraries */ +#define LUA_OFSEP "_" + + +#define LIBPREFIX "LOADLIB: " + +#define POF LUA_POF +#define LIB_FAIL "open" + + +/* error codes for ll_loadfunc */ +#define ERRLIB 1 +#define ERRFUNC 2 + +#define setprogdir(L) ((void)0) + + +static void ll_unloadlib (void *lib); +static void *ll_load (lua_State *L, const char *path); +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym); + + + +#if defined(LUA_DL_DLOPEN) +/* +** {======================================================================== +** This is an implementation of loadlib based on the dlfcn interface. +** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD, +** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least +** as an emulation layer on top of native functions. +** ========================================================================= +*/ + +#include <dlfcn.h> + +static void ll_unloadlib (void *lib) { + dlclose(lib); +} + + +static void *ll_load (lua_State *L, const char *path) { + void *lib = dlopen(path, RTLD_NOW); + if (lib == NULL) lua_pushstring(L, dlerror()); + return lib; +} + + +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { + lua_CFunction f = (lua_CFunction)dlsym(lib, sym); + if (f == NULL) lua_pushstring(L, dlerror()); + return f; +} + +/* }====================================================== */ + + + +#elif defined(LUA_DL_DLL) +/* +** {====================================================================== +** This is an implementation of loadlib for Windows using native functions. +** ======================================================================= +*/ + +#include <windows.h> + + +#undef setprogdir + +static void setprogdir (lua_State *L) { + char buff[MAX_PATH + 1]; + char *lb; + DWORD nsize = sizeof(buff)/sizeof(char); + DWORD n = GetModuleFileNameA(NULL, buff, nsize); + if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL) + luaL_error(L, "unable to get ModuleFileName"); + else { + *lb = '\0'; + luaL_gsub(L, lua_tostring(L, -1), LUA_EXECDIR, buff); + lua_remove(L, -2); /* remove original string */ + } +} + + +static void pusherror (lua_State *L) { + int error = GetLastError(); + char buffer[128]; + if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, error, 0, buffer, sizeof(buffer), NULL)) + lua_pushstring(L, buffer); + else + lua_pushfstring(L, "system error %d\n", error); +} + +static void ll_unloadlib (void *lib) { + FreeLibrary((HINSTANCE)lib); +} + + +static void *ll_load (lua_State *L, const char *path) { + HINSTANCE lib = LoadLibraryA(path); + if (lib == NULL) pusherror(L); + return lib; +} + + +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { + lua_CFunction f = (lua_CFunction)GetProcAddress((HINSTANCE)lib, sym); + if (f == NULL) pusherror(L); + return f; +} + +/* }====================================================== */ + + + +#elif defined(LUA_DL_DYLD) +/* +** {====================================================================== +** Native Mac OS X / Darwin Implementation +** ======================================================================= +*/ + +#include <mach-o/dyld.h> + + +/* Mac appends a `_' before C function names */ +#undef POF +#define POF "_" LUA_POF + + +static void pusherror (lua_State *L) { + const char *err_str; + const char *err_file; + NSLinkEditErrors err; + int err_num; + NSLinkEditError(&err, &err_num, &err_file, &err_str); + lua_pushstring(L, err_str); +} + + +static const char *errorfromcode (NSObjectFileImageReturnCode ret) { + switch (ret) { + case NSObjectFileImageInappropriateFile: + return "file is not a bundle"; + case NSObjectFileImageArch: + return "library is for wrong CPU type"; + case NSObjectFileImageFormat: + return "bad format"; + case NSObjectFileImageAccess: + return "cannot access file"; + case NSObjectFileImageFailure: + default: + return "unable to load library"; + } +} + + +static void ll_unloadlib (void *lib) { + NSUnLinkModule((NSModule)lib, NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES); +} + + +static void *ll_load (lua_State *L, const char *path) { + NSObjectFileImage img; + NSObjectFileImageReturnCode ret; + /* this would be a rare case, but prevents crashing if it happens */ + if(!_dyld_present()) { + lua_pushliteral(L, "dyld not present"); + return NULL; + } + ret = NSCreateObjectFileImageFromFile(path, &img); + if (ret == NSObjectFileImageSuccess) { + NSModule mod = NSLinkModule(img, path, NSLINKMODULE_OPTION_PRIVATE | + NSLINKMODULE_OPTION_RETURN_ON_ERROR); + NSDestroyObjectFileImage(img); + if (mod == NULL) pusherror(L); + return mod; + } + lua_pushstring(L, errorfromcode(ret)); + return NULL; +} + + +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { + NSSymbol nss = NSLookupSymbolInModule((NSModule)lib, sym); + if (nss == NULL) { + lua_pushfstring(L, "symbol " LUA_QS " not found", sym); + return NULL; + } + return (lua_CFunction)NSAddressOfSymbol(nss); +} + +/* }====================================================== */ + + + +#else +/* +** {====================================================== +** Fallback for other systems +** ======================================================= +*/ + +#undef LIB_FAIL +#define LIB_FAIL "absent" + + +#define DLMSG "dynamic libraries not enabled; check your Lua installation" + + +static void ll_unloadlib (void *lib) { + (void)lib; /* to avoid warnings */ +} + + +static void *ll_load (lua_State *L, const char *path) { + (void)path; /* to avoid warnings */ + lua_pushliteral(L, DLMSG); + return NULL; +} + + +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { + (void)lib; (void)sym; /* to avoid warnings */ + lua_pushliteral(L, DLMSG); + return NULL; +} + +/* }====================================================== */ +#endif + + + +static void **ll_register (lua_State *L, const char *path) { + void **plib; + lua_pushfstring(L, "%s%s", LIBPREFIX, path); + lua_gettable(L, LUA_REGISTRYINDEX); /* check library in registry? */ + if (!lua_isnil(L, -1)) /* is there an entry? */ + plib = (void **)lua_touserdata(L, -1); + else { /* no entry yet; create one */ + lua_pop(L, 1); + plib = (void **)lua_newuserdata(L, sizeof(const void *)); + *plib = NULL; + luaL_getmetatable(L, "_LOADLIB"); + lua_setmetatable(L, -2); + lua_pushfstring(L, "%s%s", LIBPREFIX, path); + lua_pushvalue(L, -2); + lua_settable(L, LUA_REGISTRYINDEX); + } + return plib; +} + + +/* +** __gc tag method: calls library's `ll_unloadlib' function with the lib +** handle +*/ +static int gctm (lua_State *L) { + void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB"); + if (*lib) ll_unloadlib(*lib); + *lib = NULL; /* mark library as closed */ + return 0; +} + + +static int ll_loadfunc (lua_State *L, const char *path, const char *sym) { + void **reg = ll_register(L, path); + if (*reg == NULL) *reg = ll_load(L, path); + if (*reg == NULL) + return ERRLIB; /* unable to load library */ + else { + lua_CFunction f = ll_sym(L, *reg, sym); + if (f == NULL) + return ERRFUNC; /* unable to find function */ + lua_pushcfunction(L, f); + return 0; /* return function */ + } +} + + +static int ll_loadlib (lua_State *L) { + const char *path = luaL_checkstring(L, 1); + const char *init = luaL_checkstring(L, 2); + int stat = ll_loadfunc(L, path, init); + if (stat == 0) /* no errors? */ + return 1; /* return the loaded function */ + else { /* error; error message is on stack top */ + lua_pushnil(L); + lua_insert(L, -2); + lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init"); + return 3; /* return nil, error message, and where */ + } +} + + + +/* +** {====================================================== +** 'require' function +** ======================================================= +*/ + + +static int readable (const char *filename) { + FILE *f = fopen(filename, "r"); /* try to open file */ + if (f == NULL) return 0; /* open failed */ + fclose(f); + return 1; +} + + +static const char *pushnexttemplate (lua_State *L, const char *path) { + const char *l; + while (*path == *LUA_PATHSEP) path++; /* skip separators */ + if (*path == '\0') return NULL; /* no more templates */ + l = strchr(path, *LUA_PATHSEP); /* find next separator */ + if (l == NULL) l = path + strlen(path); + lua_pushlstring(L, path, l - path); /* template */ + return l; +} + + +static const char *findfile (lua_State *L, const char *name, + const char *pname) { + const char *path; + name = luaL_gsub(L, name, ".", LUA_DIRSEP); + lua_getfield(L, LUA_ENVIRONINDEX, pname); + path = lua_tostring(L, -1); + if (path == NULL) + luaL_error(L, LUA_QL("package.%s") " must be a string", pname); + lua_pushliteral(L, ""); /* error accumulator */ + while ((path = pushnexttemplate(L, path)) != NULL) { + const char *filename; + filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name); + lua_remove(L, -2); /* remove path template */ + if (readable(filename)) /* does file exist and is readable? */ + return filename; /* return that file name */ + lua_pushfstring(L, "\n\tno file " LUA_QS, filename); + lua_remove(L, -2); /* remove file name */ + lua_concat(L, 2); /* add entry to possible error message */ + } + return NULL; /* not found */ +} + + +static void loaderror (lua_State *L, const char *filename) { + luaL_error(L, "error loading module " LUA_QS " from file " LUA_QS ":\n\t%s", + lua_tostring(L, 1), filename, lua_tostring(L, -1)); +} + + +static int loader_Lua (lua_State *L) { + const char *filename; + const char *name = luaL_checkstring(L, 1); + filename = findfile(L, name, "path"); + if (filename == NULL) return 1; /* library not found in this path */ + if (luaL_loadfile(L, filename) != 0) + loaderror(L, filename); + return 1; /* library loaded successfully */ +} + + +static const char *mkfuncname (lua_State *L, const char *modname) { + const char *funcname; + const char *mark = strchr(modname, *LUA_IGMARK); + if (mark) modname = mark + 1; + funcname = luaL_gsub(L, modname, ".", LUA_OFSEP); + funcname = lua_pushfstring(L, POF"%s", funcname); + lua_remove(L, -2); /* remove 'gsub' result */ + return funcname; +} + + +static int loader_C (lua_State *L) { + const char *funcname; + const char *name = luaL_checkstring(L, 1); + const char *filename = findfile(L, name, "cpath"); + if (filename == NULL) return 1; /* library not found in this path */ + funcname = mkfuncname(L, name); + if (ll_loadfunc(L, filename, funcname) != 0) + loaderror(L, filename); + return 1; /* library loaded successfully */ +} + + +static int loader_Croot (lua_State *L) { + const char *funcname; + const char *filename; + const char *name = luaL_checkstring(L, 1); + const char *p = strchr(name, '.'); + int stat; + if (p == NULL) return 0; /* is root */ + lua_pushlstring(L, name, p - name); + filename = findfile(L, lua_tostring(L, -1), "cpath"); + if (filename == NULL) return 1; /* root not found */ + funcname = mkfuncname(L, name); + if ((stat = ll_loadfunc(L, filename, funcname)) != 0) { + if (stat != ERRFUNC) loaderror(L, filename); /* real error */ + lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS, + name, filename); + return 1; /* function not found */ + } + return 1; +} + + +static int loader_preload (lua_State *L) { + const char *name = luaL_checkstring(L, 1); + lua_getfield(L, LUA_ENVIRONINDEX, "preload"); + if (!lua_istable(L, -1)) + luaL_error(L, LUA_QL("package.preload") " must be a table"); + lua_getfield(L, -1, name); + if (lua_isnil(L, -1)) /* not found? */ + lua_pushfstring(L, "\n\tno field package.preload['%s']", name); + return 1; +} + + +static const int sentinel_ = 0; +#define sentinel ((void *)&sentinel_) + + +static int ll_require (lua_State *L) { + const char *name = luaL_checkstring(L, 1); + int i; + lua_settop(L, 1); /* _LOADED table will be at index 2 */ + lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); + lua_getfield(L, 2, name); + if (lua_toboolean(L, -1)) { /* is it there? */ + if (lua_touserdata(L, -1) == sentinel) /* check loops */ + luaL_error(L, "loop or previous error loading module " LUA_QS, name); + return 1; /* package is already loaded */ + } + /* else must load it; iterate over available loaders */ + lua_getfield(L, LUA_ENVIRONINDEX, "loaders"); + if (!lua_istable(L, -1)) + luaL_error(L, LUA_QL("package.loaders") " must be a table"); + lua_pushliteral(L, ""); /* error message accumulator */ + for (i=1; ; i++) { + lua_rawgeti(L, -2, i); /* get a loader */ + if (lua_isnil(L, -1)) + luaL_error(L, "module " LUA_QS " not found:%s", + name, lua_tostring(L, -2)); + lua_pushstring(L, name); + lua_call(L, 1, 1); /* call it */ + if (lua_isfunction(L, -1)) /* did it find module? */ + break; /* module loaded successfully */ + else if (lua_isstring(L, -1)) /* loader returned error message? */ + lua_concat(L, 2); /* accumulate it */ + else + lua_pop(L, 1); + } + lua_pushlightuserdata(L, sentinel); + lua_setfield(L, 2, name); /* _LOADED[name] = sentinel */ + lua_pushstring(L, name); /* pass name as argument to module */ + lua_call(L, 1, 1); /* run loaded module */ + if (!lua_isnil(L, -1)) /* non-nil return? */ + lua_setfield(L, 2, name); /* _LOADED[name] = returned value */ + lua_getfield(L, 2, name); + if (lua_touserdata(L, -1) == sentinel) { /* module did not set a value? */ + lua_pushboolean(L, 1); /* use true as result */ + lua_pushvalue(L, -1); /* extra copy to be returned */ + lua_setfield(L, 2, name); /* _LOADED[name] = true */ + } + return 1; +} + +/* }====================================================== */ + + + +/* +** {====================================================== +** 'module' function +** ======================================================= +*/ + + +static void setfenv (lua_State *L) { + lua_Debug ar; + lua_getstack(L, 1, &ar); + lua_getinfo(L, "f", &ar); + lua_pushvalue(L, -2); + lua_setfenv(L, -2); + lua_pop(L, 1); +} + + +static void dooptions (lua_State *L, int n) { + int i; + for (i = 2; i <= n; i++) { + lua_pushvalue(L, i); /* get option (a function) */ + lua_pushvalue(L, -2); /* module */ + lua_call(L, 1, 0); + } +} + + +static void modinit (lua_State *L, const char *modname) { + const char *dot; + lua_pushvalue(L, -1); + lua_setfield(L, -2, "_M"); /* module._M = module */ + lua_pushstring(L, modname); + lua_setfield(L, -2, "_NAME"); + dot = strrchr(modname, '.'); /* look for last dot in module name */ + if (dot == NULL) dot = modname; + else dot++; + /* set _PACKAGE as package name (full module name minus last part) */ + lua_pushlstring(L, modname, dot - modname); + lua_setfield(L, -2, "_PACKAGE"); +} + + +static int ll_module (lua_State *L) { + const char *modname = luaL_checkstring(L, 1); + int loaded = lua_gettop(L) + 1; /* index of _LOADED table */ + lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); + lua_getfield(L, loaded, modname); /* get _LOADED[modname] */ + if (!lua_istable(L, -1)) { /* not found? */ + lua_pop(L, 1); /* remove previous result */ + /* try global variable (and create one if it does not exist) */ + if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, 1) != NULL) + return luaL_error(L, "name conflict for module " LUA_QS, modname); + lua_pushvalue(L, -1); + lua_setfield(L, loaded, modname); /* _LOADED[modname] = new table */ + } + /* check whether table already has a _NAME field */ + lua_getfield(L, -1, "_NAME"); + if (!lua_isnil(L, -1)) /* is table an initialized module? */ + lua_pop(L, 1); + else { /* no; initialize it */ + lua_pop(L, 1); + modinit(L, modname); + } + lua_pushvalue(L, -1); + setfenv(L); + dooptions(L, loaded - 1); + return 0; +} + + +static int ll_seeall (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + if (!lua_getmetatable(L, 1)) { + lua_createtable(L, 0, 1); /* create new metatable */ + lua_pushvalue(L, -1); + lua_setmetatable(L, 1); + } + lua_pushvalue(L, LUA_GLOBALSINDEX); + lua_setfield(L, -2, "__index"); /* mt.__index = _G */ + return 0; +} + + +/* }====================================================== */ + + + +/* auxiliary mark (for internal use) */ +#define AUXMARK "\1" + +static void setpath (lua_State *L, const char *fieldname, const char *envname, + const char *def) { + const char *path = /*getenv(envname)*/ NULL; + (void)envname; /* Shut up gcc */ + if (path == NULL) /* no environment variable? */ + lua_pushstring(L, def); /* use default */ + else { + /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */ + path = luaL_gsub(L, path, LUA_PATHSEP LUA_PATHSEP, + LUA_PATHSEP AUXMARK LUA_PATHSEP); + luaL_gsub(L, path, AUXMARK, def); + lua_remove(L, -2); + } + setprogdir(L); + lua_setfield(L, -2, fieldname); +} + + +static const luaL_Reg pk_funcs[] = { + {"loadlib", ll_loadlib}, + {"seeall", ll_seeall}, + {NULL, NULL} +}; + + +static const luaL_Reg ll_funcs[] = { + {"module", ll_module}, + {"require", ll_require}, + {NULL, NULL} +}; + + +static const lua_CFunction loaders[] = + {loader_preload, loader_Lua, loader_C, loader_Croot, NULL}; + + +LUALIB_API int luaopen_package (lua_State *L) { + int i; + /* create new type _LOADLIB */ + luaL_newmetatable(L, "_LOADLIB"); + lua_pushcfunction(L, gctm); + lua_setfield(L, -2, "__gc"); + /* create `package' table */ + luaL_register(L, LUA_LOADLIBNAME, pk_funcs); +#if defined(LUA_COMPAT_LOADLIB) + lua_getfield(L, -1, "loadlib"); + lua_setfield(L, LUA_GLOBALSINDEX, "loadlib"); +#endif + lua_pushvalue(L, -1); + lua_replace(L, LUA_ENVIRONINDEX); + /* create `loaders' table */ + lua_createtable(L, 0, sizeof(loaders)/sizeof(loaders[0]) - 1); + /* fill it with pre-defined loaders */ + for (i=0; loaders[i] != NULL; i++) { + lua_pushcfunction(L, loaders[i]); + lua_rawseti(L, -2, i+1); + } + lua_setfield(L, -2, "loaders"); /* put it in field `loaders' */ + setpath(L, "path", LUA_PATH, LUA_PATH_DEFAULT); /* set field `path' */ + setpath(L, "cpath", LUA_CPATH, LUA_CPATH_DEFAULT); /* set field `cpath' */ + /* store config information */ + lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n" + LUA_EXECDIR "\n" LUA_IGMARK); + lua_setfield(L, -2, "config"); + /* set field `loaded' */ + luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 2); + lua_setfield(L, -2, "loaded"); + /* set field `preload' */ + lua_newtable(L); + lua_setfield(L, -2, "preload"); + lua_pushvalue(L, LUA_GLOBALSINDEX); + luaL_register(L, NULL, ll_funcs); /* open lib into global table */ + lua_pop(L, 1); + return 1; /* return 'package' table */ +} + diff --git a/contrib/syslinux-4.02/com32/lua/src/lobject.c b/contrib/syslinux-4.02/com32/lua/src/lobject.c new file mode 100644 index 0000000..4ff5073 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lobject.c @@ -0,0 +1,214 @@ +/* +** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $ +** Some generic functions over Lua objects +** See Copyright Notice in lua.h +*/ + +#include <ctype.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define lobject_c +#define LUA_CORE + +#include "lua.h" + +#include "ldo.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "lvm.h" + + + +const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL}; + + +/* +** converts an integer to a "floating point byte", represented as +** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if +** eeeee != 0 and (xxx) otherwise. +*/ +int luaO_int2fb (unsigned int x) { + int e = 0; /* expoent */ + while (x >= 16) { + x = (x+1) >> 1; + e++; + } + if (x < 8) return x; + else return ((e+1) << 3) | (cast_int(x) - 8); +} + + +/* converts back */ +int luaO_fb2int (int x) { + int e = (x >> 3) & 31; + if (e == 0) return x; + else return ((x & 7)+8) << (e - 1); +} + + +int luaO_log2 (unsigned int x) { + static const lu_byte log_2[256] = { + 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 + }; + int l = -1; + while (x >= 256) { l += 8; x >>= 8; } + return l + log_2[x]; + +} + + +int luaO_rawequalObj (const TValue *t1, const TValue *t2) { + if (ttype(t1) != ttype(t2)) return 0; + else switch (ttype(t1)) { + case LUA_TNIL: + return 1; + case LUA_TNUMBER: + return luai_numeq(nvalue(t1), nvalue(t2)); + case LUA_TBOOLEAN: + return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */ + case LUA_TLIGHTUSERDATA: + return pvalue(t1) == pvalue(t2); + default: + lua_assert(iscollectable(t1)); + return gcvalue(t1) == gcvalue(t2); + } +} + + +int luaO_str2d (const char *s, lua_Number *result) { + char *endptr; + *result = lua_str2number(s, &endptr); + if (endptr == s) return 0; /* conversion failed */ + if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */ + *result = cast_num(strtoul(s, &endptr, 16)); + if (*endptr == '\0') return 1; /* most common case */ + while (isspace(cast(unsigned char, *endptr))) endptr++; + if (*endptr != '\0') return 0; /* invalid trailing characters? */ + return 1; +} + + + +static void pushstr (lua_State *L, const char *str) { + setsvalue2s(L, L->top, luaS_new(L, str)); + incr_top(L); +} + + +/* this function handles only `%d', `%c', %f, %p, and `%s' formats */ +const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { + int n = 1; + pushstr(L, ""); + for (;;) { + const char *e = strchr(fmt, '%'); + if (e == NULL) break; + setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt)); + incr_top(L); + switch (*(e+1)) { + case 's': { + const char *s = va_arg(argp, char *); + if (s == NULL) s = "(null)"; + pushstr(L, s); + break; + } + case 'c': { + char buff[2]; + buff[0] = cast(char, va_arg(argp, int)); + buff[1] = '\0'; + pushstr(L, buff); + break; + } + case 'd': { + setnvalue(L->top, cast_num(va_arg(argp, int))); + incr_top(L); + break; + } + case 'f': { + setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber))); + incr_top(L); + break; + } + case 'p': { + char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */ + sprintf(buff, "%p", va_arg(argp, void *)); + pushstr(L, buff); + break; + } + case '%': { + pushstr(L, "%"); + break; + } + default: { + char buff[3]; + buff[0] = '%'; + buff[1] = *(e+1); + buff[2] = '\0'; + pushstr(L, buff); + break; + } + } + n += 2; + fmt = e+2; + } + pushstr(L, fmt); + luaV_concat(L, n+1, cast_int(L->top - L->base) - 1); + L->top -= n; + return svalue(L->top - 1); +} + + +const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { + const char *msg; + va_list argp; + va_start(argp, fmt); + msg = luaO_pushvfstring(L, fmt, argp); + va_end(argp); + return msg; +} + + +void luaO_chunkid (char *out, const char *source, size_t bufflen) { + if (*source == '=') { + strncpy(out, source+1, bufflen); /* remove first char */ + out[bufflen-1] = '\0'; /* ensures null termination */ + } + else { /* out = "source", or "...source" */ + if (*source == '@') { + size_t l; + source++; /* skip the `@' */ + bufflen -= sizeof(" '...' "); + l = strlen(source); + strcpy(out, ""); + if (l > bufflen) { + source += (l-bufflen); /* get last part of file name */ + strcat(out, "..."); + } + strcat(out, source); + } + else { /* out = [string "string"] */ + size_t len = strcspn(source, "\n\r"); /* stop at first newline */ + bufflen -= sizeof(" [string \"...\"] "); + if (len > bufflen) len = bufflen; + strcpy(out, "[string \""); + if (source[len] != '\0') { /* must truncate? */ + strncat(out, source, len); + strcat(out, "..."); + } + else + strcat(out, source); + strcat(out, "\"]"); + } + } +} diff --git a/contrib/syslinux-4.02/com32/lua/src/lobject.h b/contrib/syslinux-4.02/com32/lua/src/lobject.h new file mode 100644 index 0000000..e7199df --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lobject.h @@ -0,0 +1,381 @@ +/* +** $Id: lobject.h,v 2.20.1.1 2007/12/27 13:02:25 roberto Exp $ +** Type definitions for Lua objects +** See Copyright Notice in lua.h +*/ + + +#ifndef lobject_h +#define lobject_h + + +#include <stdarg.h> + + +#include "llimits.h" +#include "lua.h" + + +/* tags for values visible from Lua */ +#define LAST_TAG LUA_TTHREAD + +#define NUM_TAGS (LAST_TAG+1) + + +/* +** Extra tags for non-values +*/ +#define LUA_TPROTO (LAST_TAG+1) +#define LUA_TUPVAL (LAST_TAG+2) +#define LUA_TDEADKEY (LAST_TAG+3) + + +/* +** Union of all collectable objects +*/ +typedef union GCObject GCObject; + + +/* +** Common Header for all collectable objects (in macro form, to be +** included in other objects) +*/ +#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked + + +/* +** Common header in struct form +*/ +typedef struct GCheader { + CommonHeader; +} GCheader; + + + + +/* +** Union of all Lua values +*/ +typedef union { + GCObject *gc; + void *p; + lua_Number n; + int b; +} Value; + + +/* +** Tagged Values +*/ + +#define TValuefields Value value; int tt + +typedef struct lua_TValue { + TValuefields; +} TValue; + + +/* Macros to test type */ +#define ttisnil(o) (ttype(o) == LUA_TNIL) +#define ttisnumber(o) (ttype(o) == LUA_TNUMBER) +#define ttisstring(o) (ttype(o) == LUA_TSTRING) +#define ttistable(o) (ttype(o) == LUA_TTABLE) +#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION) +#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN) +#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA) +#define ttisthread(o) (ttype(o) == LUA_TTHREAD) +#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA) + +/* Macros to access values */ +#define ttype(o) ((o)->tt) +#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc) +#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p) +#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n) +#define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts) +#define tsvalue(o) (&rawtsvalue(o)->tsv) +#define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u) +#define uvalue(o) (&rawuvalue(o)->uv) +#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl) +#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h) +#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b) +#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th) + +#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) + +/* +** for internal debug only +*/ +#define checkconsistency(obj) \ + lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt)) + +#define checkliveness(g,obj) \ + lua_assert(!iscollectable(obj) || \ + ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc))) + + +/* Macros to set values */ +#define setnilvalue(obj) ((obj)->tt=LUA_TNIL) + +#define setnvalue(obj,x) \ + { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; } + +#define setpvalue(obj,x) \ + { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } + +#define setbvalue(obj,x) \ + { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; } + +#define setsvalue(L,obj,x) \ + { TValue *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \ + checkliveness(G(L),i_o); } + +#define setuvalue(L,obj,x) \ + { TValue *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \ + checkliveness(G(L),i_o); } + +#define setthvalue(L,obj,x) \ + { TValue *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \ + checkliveness(G(L),i_o); } + +#define setclvalue(L,obj,x) \ + { TValue *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \ + checkliveness(G(L),i_o); } + +#define sethvalue(L,obj,x) \ + { TValue *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \ + checkliveness(G(L),i_o); } + +#define setptvalue(L,obj,x) \ + { TValue *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \ + checkliveness(G(L),i_o); } + + + + +#define setobj(L,obj1,obj2) \ + { const TValue *o2=(obj2); TValue *o1=(obj1); \ + o1->value = o2->value; o1->tt=o2->tt; \ + checkliveness(G(L),o1); } + + +/* +** different types of sets, according to destination +*/ + +/* from stack to (same) stack */ +#define setobjs2s setobj +/* to stack (not from same stack) */ +#define setobj2s setobj +#define setsvalue2s setsvalue +#define sethvalue2s sethvalue +#define setptvalue2s setptvalue +/* from table to same table */ +#define setobjt2t setobj +/* to table */ +#define setobj2t setobj +/* to new object */ +#define setobj2n setobj +#define setsvalue2n setsvalue + +#define setttype(obj, tt) (ttype(obj) = (tt)) + + +#define iscollectable(o) (ttype(o) >= LUA_TSTRING) + + + +typedef TValue *StkId; /* index to stack elements */ + + +/* +** String headers for string table +*/ +typedef union TString { + L_Umaxalign dummy; /* ensures maximum alignment for strings */ + struct { + CommonHeader; + lu_byte reserved; + unsigned int hash; + size_t len; + } tsv; +} TString; + + +#define getstr(ts) cast(const char *, (ts) + 1) +#define svalue(o) getstr(tsvalue(o)) + + + +typedef union Udata { + L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ + struct { + CommonHeader; + struct Table *metatable; + struct Table *env; + size_t len; + } uv; +} Udata; + + + + +/* +** Function Prototypes +*/ +typedef struct Proto { + CommonHeader; + TValue *k; /* constants used by the function */ + Instruction *code; + struct Proto **p; /* functions defined inside the function */ + int *lineinfo; /* map from opcodes to source lines */ + struct LocVar *locvars; /* information about local variables */ + TString **upvalues; /* upvalue names */ + TString *source; + int sizeupvalues; + int sizek; /* size of `k' */ + int sizecode; + int sizelineinfo; + int sizep; /* size of `p' */ + int sizelocvars; + int linedefined; + int lastlinedefined; + GCObject *gclist; + lu_byte nups; /* number of upvalues */ + lu_byte numparams; + lu_byte is_vararg; + lu_byte maxstacksize; +} Proto; + + +/* masks for new-style vararg */ +#define VARARG_HASARG 1 +#define VARARG_ISVARARG 2 +#define VARARG_NEEDSARG 4 + + +typedef struct LocVar { + TString *varname; + int startpc; /* first point where variable is active */ + int endpc; /* first point where variable is dead */ +} LocVar; + + + +/* +** Upvalues +*/ + +typedef struct UpVal { + CommonHeader; + TValue *v; /* points to stack or to its own value */ + union { + TValue value; /* the value (when closed) */ + struct { /* double linked list (when open) */ + struct UpVal *prev; + struct UpVal *next; + } l; + } u; +} UpVal; + + +/* +** Closures +*/ + +#define ClosureHeader \ + CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \ + struct Table *env + +typedef struct CClosure { + ClosureHeader; + lua_CFunction f; + TValue upvalue[1]; +} CClosure; + + +typedef struct LClosure { + ClosureHeader; + struct Proto *p; + UpVal *upvals[1]; +} LClosure; + + +typedef union Closure { + CClosure c; + LClosure l; +} Closure; + + +#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC) +#define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC) + + +/* +** Tables +*/ + +typedef union TKey { + struct { + TValuefields; + struct Node *next; /* for chaining */ + } nk; + TValue tvk; +} TKey; + + +typedef struct Node { + TValue i_val; + TKey i_key; +} Node; + + +typedef struct Table { + CommonHeader; + lu_byte flags; /* 1<<p means tagmethod(p) is not present */ + lu_byte lsizenode; /* log2 of size of `node' array */ + struct Table *metatable; + TValue *array; /* array part */ + Node *node; + Node *lastfree; /* any free position is before this position */ + GCObject *gclist; + int sizearray; /* size of `array' array */ +} Table; + + + +/* +** `module' operation for hashing (size is always a power of 2) +*/ +#define lmod(s,size) \ + (check_exp((size&(size-1))==0, (cast(int, (s) & ((size)-1))))) + + +#define twoto(x) (1<<(x)) +#define sizenode(t) (twoto((t)->lsizenode)) + + +#define luaO_nilobject (&luaO_nilobject_) + +LUAI_DATA const TValue luaO_nilobject_; + +#define ceillog2(x) (luaO_log2((x)-1) + 1) + +LUAI_FUNC int luaO_log2 (unsigned int x); +LUAI_FUNC int luaO_int2fb (unsigned int x); +LUAI_FUNC int luaO_fb2int (int x); +LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2); +LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result); +LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, + va_list argp); +LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); +LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len); + + +#endif + diff --git a/contrib/syslinux-4.02/com32/lua/src/lopcodes.c b/contrib/syslinux-4.02/com32/lua/src/lopcodes.c new file mode 100644 index 0000000..4cc7452 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lopcodes.c @@ -0,0 +1,102 @@ +/* +** $Id: lopcodes.c,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ +** See Copyright Notice in lua.h +*/ + + +#define lopcodes_c +#define LUA_CORE + + +#include "lopcodes.h" + + +/* ORDER OP */ + +const char *const luaP_opnames[NUM_OPCODES+1] = { + "MOVE", + "LOADK", + "LOADBOOL", + "LOADNIL", + "GETUPVAL", + "GETGLOBAL", + "GETTABLE", + "SETGLOBAL", + "SETUPVAL", + "SETTABLE", + "NEWTABLE", + "SELF", + "ADD", + "SUB", + "MUL", + "DIV", + "MOD", + "POW", + "UNM", + "NOT", + "LEN", + "CONCAT", + "JMP", + "EQ", + "LT", + "LE", + "TEST", + "TESTSET", + "CALL", + "TAILCALL", + "RETURN", + "FORLOOP", + "FORPREP", + "TFORLOOP", + "SETLIST", + "CLOSE", + "CLOSURE", + "VARARG", + NULL +}; + + +#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) + +const lu_byte luaP_opmodes[NUM_OPCODES] = { +/* T A B C mode opcode */ + opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ + ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */ + ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ + ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */ + ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ + ,opmode(0, 0, OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */ + ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ + ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ + ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */ + ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */ + ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */ + ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ + ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ + ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ + ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */ + ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ + ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ + ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ + ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ + ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TFORLOOP */ + ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ + ,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */ + ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ + ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ +}; + diff --git a/contrib/syslinux-4.02/com32/lua/src/lopcodes.h b/contrib/syslinux-4.02/com32/lua/src/lopcodes.h new file mode 100644 index 0000000..41224d6 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lopcodes.h @@ -0,0 +1,268 @@ +/* +** $Id: lopcodes.h,v 1.125.1.1 2007/12/27 13:02:25 roberto Exp $ +** Opcodes for Lua virtual machine +** See Copyright Notice in lua.h +*/ + +#ifndef lopcodes_h +#define lopcodes_h + +#include "llimits.h" + + +/*=========================================================================== + We assume that instructions are unsigned numbers. + All instructions have an opcode in the first 6 bits. + Instructions can have the following fields: + `A' : 8 bits + `B' : 9 bits + `C' : 9 bits + `Bx' : 18 bits (`B' and `C' together) + `sBx' : signed Bx + + A signed argument is represented in excess K; that is, the number + value is the unsigned value minus K. K is exactly the maximum value + for that argument (so that -max is represented by 0, and +max is + represented by 2*max), which is half the maximum for the corresponding + unsigned argument. +===========================================================================*/ + + +enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ + + +/* +** size and position of opcode arguments. +*/ +#define SIZE_C 9 +#define SIZE_B 9 +#define SIZE_Bx (SIZE_C + SIZE_B) +#define SIZE_A 8 + +#define SIZE_OP 6 + +#define POS_OP 0 +#define POS_A (POS_OP + SIZE_OP) +#define POS_C (POS_A + SIZE_A) +#define POS_B (POS_C + SIZE_C) +#define POS_Bx POS_C + + +/* +** limits for opcode arguments. +** we use (signed) int to manipulate most arguments, +** so they must fit in LUAI_BITSINT-1 bits (-1 for sign) +*/ +#if SIZE_Bx < LUAI_BITSINT-1 +#define MAXARG_Bx ((1<<SIZE_Bx)-1) +#define MAXARG_sBx (MAXARG_Bx>>1) /* `sBx' is signed */ +#else +#define MAXARG_Bx MAX_INT +#define MAXARG_sBx MAX_INT +#endif + + +#define MAXARG_A ((1<<SIZE_A)-1) +#define MAXARG_B ((1<<SIZE_B)-1) +#define MAXARG_C ((1<<SIZE_C)-1) + + +/* creates a mask with `n' 1 bits at position `p' */ +#define MASK1(n,p) ((~((~(Instruction)0)<<n))<<p) + +/* creates a mask with `n' 0 bits at position `p' */ +#define MASK0(n,p) (~MASK1(n,p)) + +/* +** the following macros help to manipulate instructions +*/ + +#define GET_OPCODE(i) (cast(OpCode, ((i)>>POS_OP) & MASK1(SIZE_OP,0))) +#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ + ((cast(Instruction, o)<<POS_OP)&MASK1(SIZE_OP,POS_OP)))) + +#define GETARG_A(i) (cast(int, ((i)>>POS_A) & MASK1(SIZE_A,0))) +#define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ + ((cast(Instruction, u)<<POS_A)&MASK1(SIZE_A,POS_A)))) + +#define GETARG_B(i) (cast(int, ((i)>>POS_B) & MASK1(SIZE_B,0))) +#define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ + ((cast(Instruction, b)<<POS_B)&MASK1(SIZE_B,POS_B)))) + +#define GETARG_C(i) (cast(int, ((i)>>POS_C) & MASK1(SIZE_C,0))) +#define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \ + ((cast(Instruction, b)<<POS_C)&MASK1(SIZE_C,POS_C)))) + +#define GETARG_Bx(i) (cast(int, ((i)>>POS_Bx) & MASK1(SIZE_Bx,0))) +#define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \ + ((cast(Instruction, b)<<POS_Bx)&MASK1(SIZE_Bx,POS_Bx)))) + +#define GETARG_sBx(i) (GETARG_Bx(i)-MAXARG_sBx) +#define SETARG_sBx(i,b) SETARG_Bx((i),cast(unsigned int, (b)+MAXARG_sBx)) + + +#define CREATE_ABC(o,a,b,c) ((cast(Instruction, o)<<POS_OP) \ + | (cast(Instruction, a)<<POS_A) \ + | (cast(Instruction, b)<<POS_B) \ + | (cast(Instruction, c)<<POS_C)) + +#define CREATE_ABx(o,a,bc) ((cast(Instruction, o)<<POS_OP) \ + | (cast(Instruction, a)<<POS_A) \ + | (cast(Instruction, bc)<<POS_Bx)) + + +/* +** Macros to operate RK indices +*/ + +/* this bit 1 means constant (0 means register) */ +#define BITRK (1 << (SIZE_B - 1)) + +/* test whether value is a constant */ +#define ISK(x) ((x) & BITRK) + +/* gets the index of the constant */ +#define INDEXK(r) ((int)(r) & ~BITRK) + +#define MAXINDEXRK (BITRK - 1) + +/* code a constant index as a RK value */ +#define RKASK(x) ((x) | BITRK) + + +/* +** invalid register that fits in 8 bits +*/ +#define NO_REG MAXARG_A + + +/* +** R(x) - register +** Kst(x) - constant (in constant table) +** RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x) +*/ + + +/* +** grep "ORDER OP" if you change these enums +*/ + +typedef enum { +/*---------------------------------------------------------------------- +name args description +------------------------------------------------------------------------*/ +OP_MOVE,/* A B R(A) := R(B) */ +OP_LOADK,/* A Bx R(A) := Kst(Bx) */ +OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */ +OP_LOADNIL,/* A B R(A) := ... := R(B) := nil */ +OP_GETUPVAL,/* A B R(A) := UpValue[B] */ + +OP_GETGLOBAL,/* A Bx R(A) := Gbl[Kst(Bx)] */ +OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */ + +OP_SETGLOBAL,/* A Bx Gbl[Kst(Bx)] := R(A) */ +OP_SETUPVAL,/* A B UpValue[B] := R(A) */ +OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */ + +OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */ + +OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */ + +OP_ADD,/* A B C R(A) := RK(B) + RK(C) */ +OP_SUB,/* A B C R(A) := RK(B) - RK(C) */ +OP_MUL,/* A B C R(A) := RK(B) * RK(C) */ +OP_DIV,/* A B C R(A) := RK(B) / RK(C) */ +OP_MOD,/* A B C R(A) := RK(B) % RK(C) */ +OP_POW,/* A B C R(A) := RK(B) ^ RK(C) */ +OP_UNM,/* A B R(A) := -R(B) */ +OP_NOT,/* A B R(A) := not R(B) */ +OP_LEN,/* A B R(A) := length of R(B) */ + +OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */ + +OP_JMP,/* sBx pc+=sBx */ + +OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ +OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ +OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ + +OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ +OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ + +OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ +OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ +OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ + +OP_FORLOOP,/* A sBx R(A)+=R(A+2); + if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/ +OP_FORPREP,/* A sBx R(A)-=R(A+2); pc+=sBx */ + +OP_TFORLOOP,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); + if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++ */ +OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */ + +OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/ +OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ + +OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */ +} OpCode; + + +#define NUM_OPCODES (cast(int, OP_VARARG) + 1) + + + +/*=========================================================================== + Notes: + (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1, + and can be 0: OP_CALL then sets `top' to last_result+1, so + next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'. + + (*) In OP_VARARG, if (B == 0) then use actual number of varargs and + set top (like in OP_CALL with C == 0). + + (*) In OP_RETURN, if (B == 0) then return up to `top' + + (*) In OP_SETLIST, if (B == 0) then B = `top'; + if (C == 0) then next `instruction' is real C + + (*) For comparisons, A specifies what condition the test should accept + (true or false). + + (*) All `skips' (pc++) assume that next instruction is a jump +===========================================================================*/ + + +/* +** masks for instruction properties. The format is: +** bits 0-1: op mode +** bits 2-3: C arg mode +** bits 4-5: B arg mode +** bit 6: instruction set register A +** bit 7: operator is a test +*/ + +enum OpArgMask { + OpArgN, /* argument is not used */ + OpArgU, /* argument is used */ + OpArgR, /* argument is a register or a jump offset */ + OpArgK /* argument is a constant or register/constant */ +}; + +LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES]; + +#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3)) +#define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3)) +#define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3)) +#define testAMode(m) (luaP_opmodes[m] & (1 << 6)) +#define testTMode(m) (luaP_opmodes[m] & (1 << 7)) + + +LUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ + + +/* number of list items to accumulate before a SETLIST instruction */ +#define LFIELDS_PER_FLUSH 50 + + +#endif diff --git a/contrib/syslinux-4.02/com32/lua/src/loslib.c b/contrib/syslinux-4.02/com32/lua/src/loslib.c new file mode 100644 index 0000000..740ad0d --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/loslib.c @@ -0,0 +1,247 @@ +/* +** $Id: loslib.c,v 1.19.1.3 2008/01/18 16:38:18 roberto Exp $ +** Standard Operating System library +** See Copyright Notice in lua.h +*/ + + +#include <errno.h> +#include <locale.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#define loslib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +static int os_pushresult (lua_State *L, int i, const char *filename) { + int en = errno; /* calls to Lua API may change this value */ + if (i) { + lua_pushboolean(L, 1); + return 1; + } + else { + lua_pushnil(L); + lua_pushfstring(L, "%s: %s", filename, strerror(en)); + lua_pushinteger(L, en); + return 3; + } +} + + +static int os_execute (lua_State *L) { + lua_pushinteger(L, system(luaL_optstring(L, 1, NULL))); + return 1; +} + + +static int os_remove (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + return os_pushresult(L, remove(filename) == 0, filename); +} + + +static int os_rename (lua_State *L) { + const char *fromname = luaL_checkstring(L, 1); + const char *toname = luaL_checkstring(L, 2); + return os_pushresult(L, rename(fromname, toname) == 0, fromname); +} + + +static int os_tmpname (lua_State *L) { + char buff[LUA_TMPNAMBUFSIZE]; + int err; + lua_tmpnam(buff, err); + if (err) + return luaL_error(L, "unable to generate a unique filename"); + lua_pushstring(L, buff); + return 1; +} + + +static int os_getenv (lua_State *L) { + lua_pushstring(L, /*getenv(luaL_checkstring(L, 1))*/); /* if NULL push nil */ + return 1; +} + + +static int os_clock (lua_State *L) { + lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC); + return 1; +} + + +/* +** {====================================================== +** Time/Date operations +** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S, +** wday=%w+1, yday=%j, isdst=? } +** ======================================================= +*/ + +static void setfield (lua_State *L, const char *key, int value) { + lua_pushinteger(L, value); + lua_setfield(L, -2, key); +} + +static void setboolfield (lua_State *L, const char *key, int value) { + if (value < 0) /* undefined? */ + return; /* does not set field */ + lua_pushboolean(L, value); + lua_setfield(L, -2, key); +} + +static int getboolfield (lua_State *L, const char *key) { + int res; + lua_getfield(L, -1, key); + res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1); + lua_pop(L, 1); + return res; +} + + +static int getfield (lua_State *L, const char *key, int d) { + int res; + lua_getfield(L, -1, key); + if (lua_isnumber(L, -1)) + res = (int)lua_tointeger(L, -1); + else { + if (d < 0) + return luaL_error(L, "field " LUA_QS " missing in date table", key); + res = d; + } + lua_pop(L, 1); + return res; +} + + +static int os_date (lua_State *L) { + const char *s = luaL_optstring(L, 1, "%c"); + time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL)); + struct tm *stm; + if (*s == '!') { /* UTC? */ + stm = gmtime(&t); + s++; /* skip `!' */ + } + else + stm = localtime(&t); + if (stm == NULL) /* invalid date? */ + lua_pushnil(L); + else if (strcmp(s, "*t") == 0) { + lua_createtable(L, 0, 9); /* 9 = number of fields */ + setfield(L, "sec", stm->tm_sec); + setfield(L, "min", stm->tm_min); + setfield(L, "hour", stm->tm_hour); + setfield(L, "day", stm->tm_mday); + setfield(L, "month", stm->tm_mon+1); + setfield(L, "year", stm->tm_year+1900); + setfield(L, "wday", stm->tm_wday+1); + setfield(L, "yday", stm->tm_yday+1); + setboolfield(L, "isdst", stm->tm_isdst); + } + else { + char cc[3]; + luaL_Buffer b; + cc[0] = '%'; cc[2] = '\0'; + luaL_buffinit(L, &b); + for (; *s; s++) { + if (*s != '%' || *(s + 1) == '\0') /* no conversion specifier? */ + luaL_addchar(&b, *s); + else { + size_t reslen; + char buff[200]; /* should be big enough for any conversion result */ + cc[1] = *(++s); + reslen = strftime(buff, sizeof(buff), cc, stm); + luaL_addlstring(&b, buff, reslen); + } + } + luaL_pushresult(&b); + } + return 1; +} + + +static int os_time (lua_State *L) { + time_t t; + if (lua_isnoneornil(L, 1)) /* called without args? */ + t = time(NULL); /* get current time */ + else { + struct tm ts; + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 1); /* make sure table is at the top */ + ts.tm_sec = getfield(L, "sec", 0); + ts.tm_min = getfield(L, "min", 0); + ts.tm_hour = getfield(L, "hour", 12); + ts.tm_mday = getfield(L, "day", -1); + ts.tm_mon = getfield(L, "month", -1) - 1; + ts.tm_year = getfield(L, "year", -1) - 1900; + ts.tm_isdst = getboolfield(L, "isdst"); + t = mktime(&ts); + } + if (t == (time_t)(-1)) + lua_pushnil(L); + else + lua_pushnumber(L, (lua_Number)t); + return 1; +} + + +#if !defined LUA_NUMBER_INTEGRAL +static int os_difftime (lua_State *L) { + lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), + (time_t)(luaL_optnumber(L, 2, 0)))); + return 1; +} +#endif + +/* }====================================================== */ + + +static int os_setlocale (lua_State *L) { + static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, + LC_NUMERIC, LC_TIME}; + static const char *const catnames[] = {"all", "collate", "ctype", "monetary", + "numeric", "time", NULL}; + const char *l = luaL_optstring(L, 1, NULL); + int op = luaL_checkoption(L, 2, "all", catnames); + lua_pushstring(L, setlocale(cat[op], l)); + return 1; +} + + +static int os_exit (lua_State *L) { + exit(luaL_optint(L, 1, EXIT_SUCCESS)); +} + +static const luaL_Reg syslib[] = { + {"clock", os_clock}, + {"date", os_date}, +#if !defined LUA_NUMBER_INTEGRAL + {"difftime", os_difftime}, +#endif + {"execute", os_execute}, + {"exit", os_exit}, + {"getenv", os_getenv}, + {"remove", os_remove}, + {"rename", os_rename}, + {"setlocale", os_setlocale}, + {"time", os_time}, + {"tmpname", os_tmpname}, + {NULL, NULL} +}; + +/* }====================================================== */ + + + +LUALIB_API int luaopen_os (lua_State *L) { + luaL_register(L, LUA_OSLIBNAME, syslib); + return 1; +} + diff --git a/contrib/syslinux-4.02/com32/lua/src/lparser.c b/contrib/syslinux-4.02/com32/lua/src/lparser.c new file mode 100644 index 0000000..1e2a9a8 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lparser.c @@ -0,0 +1,1339 @@ +/* +** $Id: lparser.c,v 2.42.1.3 2007/12/28 15:32:23 roberto Exp $ +** Lua Parser +** See Copyright Notice in lua.h +*/ + + +#include <string.h> + +#define lparser_c +#define LUA_CORE + +#include "lua.h" + +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "llex.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" + + + +#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) + +#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]]) + +#define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m) + + +/* +** nodes for block list (list of active blocks) +*/ +typedef struct BlockCnt { + struct BlockCnt *previous; /* chain */ + int breaklist; /* list of jumps out of this loop */ + lu_byte nactvar; /* # active locals outside the breakable structure */ + lu_byte upval; /* true if some variable in the block is an upvalue */ + lu_byte isbreakable; /* true if `block' is a loop */ +} BlockCnt; + + + +/* +** prototypes for recursive non-terminal functions +*/ +static void chunk (LexState *ls); +static void expr (LexState *ls, expdesc *v); + + +static void anchor_token (LexState *ls) { + if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) { + TString *ts = ls->t.seminfo.ts; + luaX_newstring(ls, getstr(ts), ts->tsv.len); + } +} + + +static void error_expected (LexState *ls, int token) { + luaX_syntaxerror(ls, + luaO_pushfstring(ls->L, LUA_QS " expected", luaX_token2str(ls, token))); +} + + +static void errorlimit (FuncState *fs, int limit, const char *what) { + const char *msg = (fs->f->linedefined == 0) ? + luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) : + luaO_pushfstring(fs->L, "function at line %d has more than %d %s", + fs->f->linedefined, limit, what); + luaX_lexerror(fs->ls, msg, 0); +} + + +static int testnext (LexState *ls, int c) { + if (ls->t.token == c) { + luaX_next(ls); + return 1; + } + else return 0; +} + + +static void check (LexState *ls, int c) { + if (ls->t.token != c) + error_expected(ls, c); +} + +static void checknext (LexState *ls, int c) { + check(ls, c); + luaX_next(ls); +} + + +#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } + + + +static void check_match (LexState *ls, int what, int who, int where) { + if (!testnext(ls, what)) { + if (where == ls->linenumber) + error_expected(ls, what); + else { + luaX_syntaxerror(ls, luaO_pushfstring(ls->L, + LUA_QS " expected (to close " LUA_QS " at line %d)", + luaX_token2str(ls, what), luaX_token2str(ls, who), where)); + } + } +} + + +static TString *str_checkname (LexState *ls) { + TString *ts; + check(ls, TK_NAME); + ts = ls->t.seminfo.ts; + luaX_next(ls); + return ts; +} + + +static void init_exp (expdesc *e, expkind k, int i) { + e->f = e->t = NO_JUMP; + e->k = k; + e->u.s.info = i; +} + + +static void codestring (LexState *ls, expdesc *e, TString *s) { + init_exp(e, VK, luaK_stringK(ls->fs, s)); +} + + +static void checkname(LexState *ls, expdesc *e) { + codestring(ls, e, str_checkname(ls)); +} + + +static int registerlocalvar (LexState *ls, TString *varname) { + FuncState *fs = ls->fs; + Proto *f = fs->f; + int oldsize = f->sizelocvars; + luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, + LocVar, SHRT_MAX, "too many local variables"); + while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; + f->locvars[fs->nlocvars].varname = varname; + luaC_objbarrier(ls->L, f, varname); + return fs->nlocvars++; +} + + +#define new_localvarliteral(ls,v,n) \ + new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char))-1), n) + + +static void new_localvar (LexState *ls, TString *name, int n) { + FuncState *fs = ls->fs; + luaY_checklimit(fs, fs->nactvar+n+1, LUAI_MAXVARS, "local variables"); + fs->actvar[fs->nactvar+n] = cast(unsigned short, registerlocalvar(ls, name)); +} + + +static void adjustlocalvars (LexState *ls, int nvars) { + FuncState *fs = ls->fs; + fs->nactvar = cast_byte(fs->nactvar + nvars); + for (; nvars; nvars--) { + getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc; + } +} + + +static void removevars (LexState *ls, int tolevel) { + FuncState *fs = ls->fs; + while (fs->nactvar > tolevel) + getlocvar(fs, --fs->nactvar).endpc = fs->pc; +} + + +static int indexupvalue (FuncState *fs, TString *name, expdesc *v) { + int i; + Proto *f = fs->f; + int oldsize = f->sizeupvalues; + for (i=0; i<f->nups; i++) { + if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->u.s.info) { + lua_assert(f->upvalues[i] == name); + return i; + } + } + /* new one */ + luaY_checklimit(fs, f->nups + 1, LUAI_MAXUPVALUES, "upvalues"); + luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues, + TString *, MAX_INT, ""); + while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL; + f->upvalues[f->nups] = name; + luaC_objbarrier(fs->L, f, name); + lua_assert(v->k == VLOCAL || v->k == VUPVAL); + fs->upvalues[f->nups].k = cast_byte(v->k); + fs->upvalues[f->nups].info = cast_byte(v->u.s.info); + return f->nups++; +} + + +static int searchvar (FuncState *fs, TString *n) { + int i; + for (i=fs->nactvar-1; i >= 0; i--) { + if (n == getlocvar(fs, i).varname) + return i; + } + return -1; /* not found */ +} + + +static void markupval (FuncState *fs, int level) { + BlockCnt *bl = fs->bl; + while (bl && bl->nactvar > level) bl = bl->previous; + if (bl) bl->upval = 1; +} + + +static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { + if (fs == NULL) { /* no more levels? */ + init_exp(var, VGLOBAL, NO_REG); /* default is global variable */ + return VGLOBAL; + } + else { + int v = searchvar(fs, n); /* look up at current level */ + if (v >= 0) { + init_exp(var, VLOCAL, v); + if (!base) + markupval(fs, v); /* local will be used as an upval */ + return VLOCAL; + } + else { /* not found at current level; try upper one */ + if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL) + return VGLOBAL; + var->u.s.info = indexupvalue(fs, n, var); /* else was LOCAL or UPVAL */ + var->k = VUPVAL; /* upvalue in this level */ + return VUPVAL; + } + } +} + + +static void singlevar (LexState *ls, expdesc *var) { + TString *varname = str_checkname(ls); + FuncState *fs = ls->fs; + if (singlevaraux(fs, varname, var, 1) == VGLOBAL) + var->u.s.info = luaK_stringK(fs, varname); /* info points to global name */ +} + + +static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { + FuncState *fs = ls->fs; + int extra = nvars - nexps; + if (hasmultret(e->k)) { + extra++; /* includes call itself */ + if (extra < 0) extra = 0; + luaK_setreturns(fs, e, extra); /* last exp. provides the difference */ + if (extra > 1) luaK_reserveregs(fs, extra-1); + } + else { + if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ + if (extra > 0) { + int reg = fs->freereg; + luaK_reserveregs(fs, extra); + luaK_nil(fs, reg, extra); + } + } +} + + +static void enterlevel (LexState *ls) { + if (++ls->L->nCcalls > LUAI_MAXCCALLS) + luaX_lexerror(ls, "chunk has too many syntax levels", 0); +} + + +#define leavelevel(ls) ((ls)->L->nCcalls--) + + +static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) { + bl->breaklist = NO_JUMP; + bl->isbreakable = isbreakable; + bl->nactvar = fs->nactvar; + bl->upval = 0; + bl->previous = fs->bl; + fs->bl = bl; + lua_assert(fs->freereg == fs->nactvar); +} + + +static void leaveblock (FuncState *fs) { + BlockCnt *bl = fs->bl; + fs->bl = bl->previous; + removevars(fs->ls, bl->nactvar); + if (bl->upval) + luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); + /* a block either controls scope or breaks (never both) */ + lua_assert(!bl->isbreakable || !bl->upval); + lua_assert(bl->nactvar == fs->nactvar); + fs->freereg = fs->nactvar; /* free registers */ + luaK_patchtohere(fs, bl->breaklist); +} + + +static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { + FuncState *fs = ls->fs; + Proto *f = fs->f; + int oldsize = f->sizep; + int i; + luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, + MAXARG_Bx, "constant table overflow"); + while (oldsize < f->sizep) f->p[oldsize++] = NULL; + f->p[fs->np++] = func->f; + luaC_objbarrier(ls->L, f, func->f); + init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1)); + for (i=0; i<func->f->nups; i++) { + OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; + luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0); + } +} + + +static void open_func (LexState *ls, FuncState *fs) { + lua_State *L = ls->L; + Proto *f = luaF_newproto(L); + fs->f = f; + fs->prev = ls->fs; /* linked list of funcstates */ + fs->ls = ls; + fs->L = L; + ls->fs = fs; + fs->pc = 0; + fs->lasttarget = -1; + fs->jpc = NO_JUMP; + fs->freereg = 0; + fs->nk = 0; + fs->np = 0; + fs->nlocvars = 0; + fs->nactvar = 0; + fs->bl = NULL; + f->source = ls->source; + f->maxstacksize = 2; /* registers 0/1 are always valid */ + fs->h = luaH_new(L, 0, 0); + /* anchor table of constants and prototype (to avoid being collected) */ + sethvalue2s(L, L->top, fs->h); + incr_top(L); + setptvalue2s(L, L->top, f); + incr_top(L); +} + + +static void close_func (LexState *ls) { + lua_State *L = ls->L; + FuncState *fs = ls->fs; + Proto *f = fs->f; + removevars(ls, 0); + luaK_ret(fs, 0, 0); /* final return */ + luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); + f->sizecode = fs->pc; + luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); + f->sizelineinfo = fs->pc; + luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue); + f->sizek = fs->nk; + luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *); + f->sizep = fs->np; + luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); + f->sizelocvars = fs->nlocvars; + luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *); + f->sizeupvalues = f->nups; + lua_assert(luaG_checkcode(f)); + lua_assert(fs->bl == NULL); + ls->fs = fs->prev; + L->top -= 2; /* remove table and prototype from the stack */ + /* last token read was anchored in defunct function; must reanchor it */ + if (fs) anchor_token(ls); +} + + +Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { + struct LexState lexstate; + struct FuncState funcstate; + lexstate.buff = buff; + luaX_setinput(L, &lexstate, z, luaS_new(L, name)); + open_func(&lexstate, &funcstate); + funcstate.f->is_vararg = VARARG_ISVARARG; /* main func. is always vararg */ + luaX_next(&lexstate); /* read first token */ + chunk(&lexstate); + check(&lexstate, TK_EOS); + close_func(&lexstate); + lua_assert(funcstate.prev == NULL); + lua_assert(funcstate.f->nups == 0); + lua_assert(lexstate.fs == NULL); + return funcstate.f; +} + + + +/*============================================================*/ +/* GRAMMAR RULES */ +/*============================================================*/ + + +static void field (LexState *ls, expdesc *v) { + /* field -> ['.' | ':'] NAME */ + FuncState *fs = ls->fs; + expdesc key; + luaK_exp2anyreg(fs, v); + luaX_next(ls); /* skip the dot or colon */ + checkname(ls, &key); + luaK_indexed(fs, v, &key); +} + + +static void yindex (LexState *ls, expdesc *v) { + /* index -> '[' expr ']' */ + luaX_next(ls); /* skip the '[' */ + expr(ls, v); + luaK_exp2val(ls->fs, v); + checknext(ls, ']'); +} + + +/* +** {====================================================================== +** Rules for Constructors +** ======================================================================= +*/ + + +struct ConsControl { + expdesc v; /* last list item read */ + expdesc *t; /* table descriptor */ + int nh; /* total number of `record' elements */ + int na; /* total number of array elements */ + int tostore; /* number of array elements pending to be stored */ +}; + + +static void recfield (LexState *ls, struct ConsControl *cc) { + /* recfield -> (NAME | `['exp1`]') = exp1 */ + FuncState *fs = ls->fs; + int reg = ls->fs->freereg; + expdesc key, val; + int rkkey; + if (ls->t.token == TK_NAME) { + luaY_checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); + checkname(ls, &key); + } + else /* ls->t.token == '[' */ + yindex(ls, &key); + cc->nh++; + checknext(ls, '='); + rkkey = luaK_exp2RK(fs, &key); + expr(ls, &val); + luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, rkkey, luaK_exp2RK(fs, &val)); + fs->freereg = reg; /* free registers */ +} + + +static void closelistfield (FuncState *fs, struct ConsControl *cc) { + if (cc->v.k == VVOID) return; /* there is no list item */ + luaK_exp2nextreg(fs, &cc->v); + cc->v.k = VVOID; + if (cc->tostore == LFIELDS_PER_FLUSH) { + luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); /* flush */ + cc->tostore = 0; /* no more items pending */ + } +} + + +static void lastlistfield (FuncState *fs, struct ConsControl *cc) { + if (cc->tostore == 0) return; + if (hasmultret(cc->v.k)) { + luaK_setmultret(fs, &cc->v); + luaK_setlist(fs, cc->t->u.s.info, cc->na, LUA_MULTRET); + cc->na--; /* do not count last expression (unknown number of elements) */ + } + else { + if (cc->v.k != VVOID) + luaK_exp2nextreg(fs, &cc->v); + luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); + } +} + + +static void listfield (LexState *ls, struct ConsControl *cc) { + expr(ls, &cc->v); + luaY_checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); + cc->na++; + cc->tostore++; +} + + +static void constructor (LexState *ls, expdesc *t) { + /* constructor -> ?? */ + FuncState *fs = ls->fs; + int line = ls->linenumber; + int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); + struct ConsControl cc; + cc.na = cc.nh = cc.tostore = 0; + cc.t = t; + init_exp(t, VRELOCABLE, pc); + init_exp(&cc.v, VVOID, 0); /* no value (yet) */ + luaK_exp2nextreg(ls->fs, t); /* fix it at stack top (for gc) */ + checknext(ls, '{'); + do { + lua_assert(cc.v.k == VVOID || cc.tostore > 0); + if (ls->t.token == '}') break; + closelistfield(fs, &cc); + switch(ls->t.token) { + case TK_NAME: { /* may be listfields or recfields */ + luaX_lookahead(ls); + if (ls->lookahead.token != '=') /* expression? */ + listfield(ls, &cc); + else + recfield(ls, &cc); + break; + } + case '[': { /* constructor_item -> recfield */ + recfield(ls, &cc); + break; + } + default: { /* constructor_part -> listfield */ + listfield(ls, &cc); + break; + } + } + } while (testnext(ls, ',') || testnext(ls, ';')); + check_match(ls, '}', '{', line); + lastlistfield(fs, &cc); + SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ + SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */ +} + +/* }====================================================================== */ + + + +static void parlist (LexState *ls) { + /* parlist -> [ param { `,' param } ] */ + FuncState *fs = ls->fs; + Proto *f = fs->f; + int nparams = 0; + f->is_vararg = 0; + if (ls->t.token != ')') { /* is `parlist' not empty? */ + do { + switch (ls->t.token) { + case TK_NAME: { /* param -> NAME */ + new_localvar(ls, str_checkname(ls), nparams++); + break; + } + case TK_DOTS: { /* param -> `...' */ + luaX_next(ls); +#if defined(LUA_COMPAT_VARARG) + /* use `arg' as default name */ + new_localvarliteral(ls, "arg", nparams++); + f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG; +#endif + f->is_vararg |= VARARG_ISVARARG; + break; + } + default: luaX_syntaxerror(ls, "<name> or " LUA_QL("...") " expected"); + } + } while (!f->is_vararg && testnext(ls, ',')); + } + adjustlocalvars(ls, nparams); + f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG)); + luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ +} + + +static void body (LexState *ls, expdesc *e, int needself, int line) { + /* body -> `(' parlist `)' chunk END */ + FuncState new_fs; + open_func(ls, &new_fs); + new_fs.f->linedefined = line; + checknext(ls, '('); + if (needself) { + new_localvarliteral(ls, "self", 0); + adjustlocalvars(ls, 1); + } + parlist(ls); + checknext(ls, ')'); + chunk(ls); + new_fs.f->lastlinedefined = ls->linenumber; + check_match(ls, TK_END, TK_FUNCTION, line); + close_func(ls); + pushclosure(ls, &new_fs, e); +} + + +static int explist1 (LexState *ls, expdesc *v) { + /* explist1 -> expr { `,' expr } */ + int n = 1; /* at least one expression */ + expr(ls, v); + while (testnext(ls, ',')) { + luaK_exp2nextreg(ls->fs, v); + expr(ls, v); + n++; + } + return n; +} + + +static void funcargs (LexState *ls, expdesc *f) { + FuncState *fs = ls->fs; + expdesc args; + int base, nparams; + int line = ls->linenumber; + switch (ls->t.token) { + case '(': { /* funcargs -> `(' [ explist1 ] `)' */ + if (line != ls->lastline) + luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)"); + luaX_next(ls); + if (ls->t.token == ')') /* arg list is empty? */ + args.k = VVOID; + else { + explist1(ls, &args); + luaK_setmultret(fs, &args); + } + check_match(ls, ')', '(', line); + break; + } + case '{': { /* funcargs -> constructor */ + constructor(ls, &args); + break; + } + case TK_STRING: { /* funcargs -> STRING */ + codestring(ls, &args, ls->t.seminfo.ts); + luaX_next(ls); /* must use `seminfo' before `next' */ + break; + } + default: { + luaX_syntaxerror(ls, "function arguments expected"); + return; + } + } + lua_assert(f->k == VNONRELOC); + base = f->u.s.info; /* base register for call */ + if (hasmultret(args.k)) + nparams = LUA_MULTRET; /* open call */ + else { + if (args.k != VVOID) + luaK_exp2nextreg(fs, &args); /* close last argument */ + nparams = fs->freereg - (base+1); + } + init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2)); + luaK_fixline(fs, line); + fs->freereg = base+1; /* call remove function and arguments and leaves + (unless changed) one result */ +} + + + + +/* +** {====================================================================== +** Expression parsing +** ======================================================================= +*/ + + +static void prefixexp (LexState *ls, expdesc *v) { + /* prefixexp -> NAME | '(' expr ')' */ + switch (ls->t.token) { + case '(': { + int line = ls->linenumber; + luaX_next(ls); + expr(ls, v); + check_match(ls, ')', '(', line); + luaK_dischargevars(ls->fs, v); + return; + } + case TK_NAME: { + singlevar(ls, v); + return; + } + default: { + luaX_syntaxerror(ls, "unexpected symbol"); + return; + } + } +} + + +static void primaryexp (LexState *ls, expdesc *v) { + /* primaryexp -> + prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */ + FuncState *fs = ls->fs; + prefixexp(ls, v); + for (;;) { + switch (ls->t.token) { + case '.': { /* field */ + field(ls, v); + break; + } + case '[': { /* `[' exp1 `]' */ + expdesc key; + luaK_exp2anyreg(fs, v); + yindex(ls, &key); + luaK_indexed(fs, v, &key); + break; + } + case ':': { /* `:' NAME funcargs */ + expdesc key; + luaX_next(ls); + checkname(ls, &key); + luaK_self(fs, v, &key); + funcargs(ls, v); + break; + } + case '(': case TK_STRING: case '{': { /* funcargs */ + luaK_exp2nextreg(fs, v); + funcargs(ls, v); + break; + } + default: return; + } + } +} + + +static void simpleexp (LexState *ls, expdesc *v) { + /* simpleexp -> NUMBER | STRING | NIL | true | false | ... | + constructor | FUNCTION body | primaryexp */ + switch (ls->t.token) { + case TK_NUMBER: { + init_exp(v, VKNUM, 0); + v->u.nval = ls->t.seminfo.r; + break; + } + case TK_STRING: { + codestring(ls, v, ls->t.seminfo.ts); + break; + } + case TK_NIL: { + init_exp(v, VNIL, 0); + break; + } + case TK_TRUE: { + init_exp(v, VTRUE, 0); + break; + } + case TK_FALSE: { + init_exp(v, VFALSE, 0); + break; + } + case TK_DOTS: { /* vararg */ + FuncState *fs = ls->fs; + check_condition(ls, fs->f->is_vararg, + "cannot use " LUA_QL("...") " outside a vararg function"); + fs->f->is_vararg &= ~VARARG_NEEDSARG; /* don't need 'arg' */ + init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); + break; + } + case '{': { /* constructor */ + constructor(ls, v); + return; + } + case TK_FUNCTION: { + luaX_next(ls); + body(ls, v, 0, ls->linenumber); + return; + } + default: { + primaryexp(ls, v); + return; + } + } + luaX_next(ls); +} + + +static UnOpr getunopr (int op) { + switch (op) { + case TK_NOT: return OPR_NOT; + case '-': return OPR_MINUS; + case '#': return OPR_LEN; + default: return OPR_NOUNOPR; + } +} + + +static BinOpr getbinopr (int op) { + switch (op) { + case '+': return OPR_ADD; + case '-': return OPR_SUB; + case '*': return OPR_MUL; + case '/': return OPR_DIV; + case '%': return OPR_MOD; + case '^': return OPR_POW; + case TK_CONCAT: return OPR_CONCAT; + case TK_NE: return OPR_NE; + case TK_EQ: return OPR_EQ; + case '<': return OPR_LT; + case TK_LE: return OPR_LE; + case '>': return OPR_GT; + case TK_GE: return OPR_GE; + case TK_AND: return OPR_AND; + case TK_OR: return OPR_OR; + default: return OPR_NOBINOPR; + } +} + + +static const struct { + lu_byte left; /* left priority for each binary operator */ + lu_byte right; /* right priority */ +} priority[] = { /* ORDER OPR */ + {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `/' `%' */ + {10, 9}, {5, 4}, /* power and concat (right associative) */ + {3, 3}, {3, 3}, /* equality and inequality */ + {3, 3}, {3, 3}, {3, 3}, {3, 3}, /* order */ + {2, 2}, {1, 1} /* logical (and/or) */ +}; + +#define UNARY_PRIORITY 8 /* priority for unary operators */ + + +/* +** subexpr -> (simpleexp | unop subexpr) { binop subexpr } +** where `binop' is any binary operator with a priority higher than `limit' +*/ +static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) { + BinOpr op; + UnOpr uop; + enterlevel(ls); + uop = getunopr(ls->t.token); + if (uop != OPR_NOUNOPR) { + luaX_next(ls); + subexpr(ls, v, UNARY_PRIORITY); + luaK_prefix(ls->fs, uop, v); + } + else simpleexp(ls, v); + /* expand while operators have priorities higher than `limit' */ + op = getbinopr(ls->t.token); + while (op != OPR_NOBINOPR && priority[op].left > limit) { + expdesc v2; + BinOpr nextop; + luaX_next(ls); + luaK_infix(ls->fs, op, v); + /* read sub-expression with higher priority */ + nextop = subexpr(ls, &v2, priority[op].right); + luaK_posfix(ls->fs, op, v, &v2); + op = nextop; + } + leavelevel(ls); + return op; /* return first untreated operator */ +} + + +static void expr (LexState *ls, expdesc *v) { + subexpr(ls, v, 0); +} + +/* }==================================================================== */ + + + +/* +** {====================================================================== +** Rules for Statements +** ======================================================================= +*/ + + +static int block_follow (int token) { + switch (token) { + case TK_ELSE: case TK_ELSEIF: case TK_END: + case TK_UNTIL: case TK_EOS: + return 1; + default: return 0; + } +} + + +static void block (LexState *ls) { + /* block -> chunk */ + FuncState *fs = ls->fs; + BlockCnt bl; + enterblock(fs, &bl, 0); + chunk(ls); + lua_assert(bl.breaklist == NO_JUMP); + leaveblock(fs); +} + + +/* +** structure to chain all variables in the left-hand side of an +** assignment +*/ +struct LHS_assign { + struct LHS_assign *prev; + expdesc v; /* variable (global, local, upvalue, or indexed) */ +}; + + +/* +** check whether, in an assignment to a local variable, the local variable +** is needed in a previous assignment (to a table). If so, save original +** local value in a safe place and use this safe copy in the previous +** assignment. +*/ +static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { + FuncState *fs = ls->fs; + int extra = fs->freereg; /* eventual position to save local variable */ + int conflict = 0; + for (; lh; lh = lh->prev) { + if (lh->v.k == VINDEXED) { + if (lh->v.u.s.info == v->u.s.info) { /* conflict? */ + conflict = 1; + lh->v.u.s.info = extra; /* previous assignment will use safe copy */ + } + if (lh->v.u.s.aux == v->u.s.info) { /* conflict? */ + conflict = 1; + lh->v.u.s.aux = extra; /* previous assignment will use safe copy */ + } + } + } + if (conflict) { + luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0); /* make copy */ + luaK_reserveregs(fs, 1); + } +} + + +static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { + expdesc e; + check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, + "syntax error"); + if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ + struct LHS_assign nv; + nv.prev = lh; + primaryexp(ls, &nv.v); + if (nv.v.k == VLOCAL) + check_conflict(ls, lh, &nv.v); + luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls, + "variables in assignment"); + assignment(ls, &nv, nvars+1); + } + else { /* assignment -> `=' explist1 */ + int nexps; + checknext(ls, '='); + nexps = explist1(ls, &e); + if (nexps != nvars) { + adjust_assign(ls, nvars, nexps, &e); + if (nexps > nvars) + ls->fs->freereg -= nexps - nvars; /* remove extra values */ + } + else { + luaK_setoneret(ls->fs, &e); /* close last expression */ + luaK_storevar(ls->fs, &lh->v, &e); + return; /* avoid default */ + } + } + init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ + luaK_storevar(ls->fs, &lh->v, &e); +} + + +static int cond (LexState *ls) { + /* cond -> exp */ + expdesc v; + expr(ls, &v); /* read condition */ + if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */ + luaK_goiftrue(ls->fs, &v); + return v.f; +} + + +static void breakstat (LexState *ls) { + FuncState *fs = ls->fs; + BlockCnt *bl = fs->bl; + int upval = 0; + while (bl && !bl->isbreakable) { + upval |= bl->upval; + bl = bl->previous; + } + if (!bl) + luaX_syntaxerror(ls, "no loop to break"); + if (upval) + luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); + luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); +} + + +static void whilestat (LexState *ls, int line) { + /* whilestat -> WHILE cond DO block END */ + FuncState *fs = ls->fs; + int whileinit; + int condexit; + BlockCnt bl; + luaX_next(ls); /* skip WHILE */ + whileinit = luaK_getlabel(fs); + condexit = cond(ls); + enterblock(fs, &bl, 1); + checknext(ls, TK_DO); + block(ls); + luaK_patchlist(fs, luaK_jump(fs), whileinit); + check_match(ls, TK_END, TK_WHILE, line); + leaveblock(fs); + luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ +} + + +static void repeatstat (LexState *ls, int line) { + /* repeatstat -> REPEAT block UNTIL cond */ + int condexit; + FuncState *fs = ls->fs; + int repeat_init = luaK_getlabel(fs); + BlockCnt bl1, bl2; + enterblock(fs, &bl1, 1); /* loop block */ + enterblock(fs, &bl2, 0); /* scope block */ + luaX_next(ls); /* skip REPEAT */ + chunk(ls); + check_match(ls, TK_UNTIL, TK_REPEAT, line); + condexit = cond(ls); /* read condition (inside scope block) */ + if (!bl2.upval) { /* no upvalues? */ + leaveblock(fs); /* finish scope */ + luaK_patchlist(ls->fs, condexit, repeat_init); /* close the loop */ + } + else { /* complete semantics when there are upvalues */ + breakstat(ls); /* if condition then break */ + luaK_patchtohere(ls->fs, condexit); /* else... */ + leaveblock(fs); /* finish scope... */ + luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init); /* and repeat */ + } + leaveblock(fs); /* finish loop */ +} + + +static int exp1 (LexState *ls) { + expdesc e; + int k; + expr(ls, &e); + k = e.k; + luaK_exp2nextreg(ls->fs, &e); + return k; +} + + +static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { + /* forbody -> DO block */ + BlockCnt bl; + FuncState *fs = ls->fs; + int prep, endfor; + adjustlocalvars(ls, 3); /* control variables */ + checknext(ls, TK_DO); + prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs); + enterblock(fs, &bl, 0); /* scope for declared variables */ + adjustlocalvars(ls, nvars); + luaK_reserveregs(fs, nvars); + block(ls); + leaveblock(fs); /* end of scope for declared variables */ + luaK_patchtohere(fs, prep); + endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) : + luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars); + luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */ + luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1); +} + + +static void fornum (LexState *ls, TString *varname, int line) { + /* fornum -> NAME = exp1,exp1[,exp1] forbody */ + FuncState *fs = ls->fs; + int base = fs->freereg; + new_localvarliteral(ls, "(for index)", 0); + new_localvarliteral(ls, "(for limit)", 1); + new_localvarliteral(ls, "(for step)", 2); + new_localvar(ls, varname, 3); + checknext(ls, '='); + exp1(ls); /* initial value */ + checknext(ls, ','); + exp1(ls); /* limit */ + if (testnext(ls, ',')) + exp1(ls); /* optional step */ + else { /* default step = 1 */ + luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1)); + luaK_reserveregs(fs, 1); + } + forbody(ls, base, line, 1, 1); +} + + +static void forlist (LexState *ls, TString *indexname) { + /* forlist -> NAME {,NAME} IN explist1 forbody */ + FuncState *fs = ls->fs; + expdesc e; + int nvars = 0; + int line; + int base = fs->freereg; + /* create control variables */ + new_localvarliteral(ls, "(for generator)", nvars++); + new_localvarliteral(ls, "(for state)", nvars++); + new_localvarliteral(ls, "(for control)", nvars++); + /* create declared variables */ + new_localvar(ls, indexname, nvars++); + while (testnext(ls, ',')) + new_localvar(ls, str_checkname(ls), nvars++); + checknext(ls, TK_IN); + line = ls->linenumber; + adjust_assign(ls, 3, explist1(ls, &e), &e); + luaK_checkstack(fs, 3); /* extra space to call generator */ + forbody(ls, base, line, nvars - 3, 0); +} + + +static void forstat (LexState *ls, int line) { + /* forstat -> FOR (fornum | forlist) END */ + FuncState *fs = ls->fs; + TString *varname; + BlockCnt bl; + enterblock(fs, &bl, 1); /* scope for loop and control variables */ + luaX_next(ls); /* skip `for' */ + varname = str_checkname(ls); /* first variable name */ + switch (ls->t.token) { + case '=': fornum(ls, varname, line); break; + case ',': case TK_IN: forlist(ls, varname); break; + default: luaX_syntaxerror(ls, LUA_QL("=") " or " LUA_QL("in") " expected"); + } + check_match(ls, TK_END, TK_FOR, line); + leaveblock(fs); /* loop scope (`break' jumps to this point) */ +} + + +static int test_then_block (LexState *ls) { + /* test_then_block -> [IF | ELSEIF] cond THEN block */ + int condexit; + luaX_next(ls); /* skip IF or ELSEIF */ + condexit = cond(ls); + checknext(ls, TK_THEN); + block(ls); /* `then' part */ + return condexit; +} + + +static void ifstat (LexState *ls, int line) { + /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ + FuncState *fs = ls->fs; + int flist; + int escapelist = NO_JUMP; + flist = test_then_block(ls); /* IF cond THEN block */ + while (ls->t.token == TK_ELSEIF) { + luaK_concat(fs, &escapelist, luaK_jump(fs)); + luaK_patchtohere(fs, flist); + flist = test_then_block(ls); /* ELSEIF cond THEN block */ + } + if (ls->t.token == TK_ELSE) { + luaK_concat(fs, &escapelist, luaK_jump(fs)); + luaK_patchtohere(fs, flist); + luaX_next(ls); /* skip ELSE (after patch, for correct line info) */ + block(ls); /* `else' part */ + } + else + luaK_concat(fs, &escapelist, flist); + luaK_patchtohere(fs, escapelist); + check_match(ls, TK_END, TK_IF, line); +} + + +static void localfunc (LexState *ls) { + expdesc v, b; + FuncState *fs = ls->fs; + new_localvar(ls, str_checkname(ls), 0); + init_exp(&v, VLOCAL, fs->freereg); + luaK_reserveregs(fs, 1); + adjustlocalvars(ls, 1); + body(ls, &b, 0, ls->linenumber); + luaK_storevar(fs, &v, &b); + /* debug information will only see the variable after this point! */ + getlocvar(fs, fs->nactvar - 1).startpc = fs->pc; +} + + +static void localstat (LexState *ls) { + /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */ + int nvars = 0; + int nexps; + expdesc e; + do { + new_localvar(ls, str_checkname(ls), nvars++); + } while (testnext(ls, ',')); + if (testnext(ls, '=')) + nexps = explist1(ls, &e); + else { + e.k = VVOID; + nexps = 0; + } + adjust_assign(ls, nvars, nexps, &e); + adjustlocalvars(ls, nvars); +} + + +static int funcname (LexState *ls, expdesc *v) { + /* funcname -> NAME {field} [`:' NAME] */ + int needself = 0; + singlevar(ls, v); + while (ls->t.token == '.') + field(ls, v); + if (ls->t.token == ':') { + needself = 1; + field(ls, v); + } + return needself; +} + + +static void funcstat (LexState *ls, int line) { + /* funcstat -> FUNCTION funcname body */ + int needself; + expdesc v, b; + luaX_next(ls); /* skip FUNCTION */ + needself = funcname(ls, &v); + body(ls, &b, needself, line); + luaK_storevar(ls->fs, &v, &b); + luaK_fixline(ls->fs, line); /* definition `happens' in the first line */ +} + + +static void exprstat (LexState *ls) { + /* stat -> func | assignment */ + FuncState *fs = ls->fs; + struct LHS_assign v; + primaryexp(ls, &v.v); + if (v.v.k == VCALL) /* stat -> func */ + SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */ + else { /* stat -> assignment */ + v.prev = NULL; + assignment(ls, &v, 1); + } +} + + +static void retstat (LexState *ls) { + /* stat -> RETURN explist */ + FuncState *fs = ls->fs; + expdesc e; + int first, nret; /* registers with returned values */ + luaX_next(ls); /* skip RETURN */ + if (block_follow(ls->t.token) || ls->t.token == ';') + first = nret = 0; /* return no values */ + else { + nret = explist1(ls, &e); /* optional return values */ + if (hasmultret(e.k)) { + luaK_setmultret(fs, &e); + if (e.k == VCALL && nret == 1) { /* tail call? */ + SET_OPCODE(getcode(fs,&e), OP_TAILCALL); + lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar); + } + first = fs->nactvar; + nret = LUA_MULTRET; /* return all values */ + } + else { + if (nret == 1) /* only one single value? */ + first = luaK_exp2anyreg(fs, &e); + else { + luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */ + first = fs->nactvar; /* return all `active' values */ + lua_assert(nret == fs->freereg - first); + } + } + } + luaK_ret(fs, first, nret); +} + + +static int statement (LexState *ls) { + int line = ls->linenumber; /* may be needed for error messages */ + switch (ls->t.token) { + case TK_IF: { /* stat -> ifstat */ + ifstat(ls, line); + return 0; + } + case TK_WHILE: { /* stat -> whilestat */ + whilestat(ls, line); + return 0; + } + case TK_DO: { /* stat -> DO block END */ + luaX_next(ls); /* skip DO */ + block(ls); + check_match(ls, TK_END, TK_DO, line); + return 0; + } + case TK_FOR: { /* stat -> forstat */ + forstat(ls, line); + return 0; + } + case TK_REPEAT: { /* stat -> repeatstat */ + repeatstat(ls, line); + return 0; + } + case TK_FUNCTION: { + funcstat(ls, line); /* stat -> funcstat */ + return 0; + } + case TK_LOCAL: { /* stat -> localstat */ + luaX_next(ls); /* skip LOCAL */ + if (testnext(ls, TK_FUNCTION)) /* local function? */ + localfunc(ls); + else + localstat(ls); + return 0; + } + case TK_RETURN: { /* stat -> retstat */ + retstat(ls); + return 1; /* must be last statement */ + } + case TK_BREAK: { /* stat -> breakstat */ + luaX_next(ls); /* skip BREAK */ + breakstat(ls); + return 1; /* must be last statement */ + } + default: { + exprstat(ls); + return 0; /* to avoid warnings */ + } + } +} + + +static void chunk (LexState *ls) { + /* chunk -> { stat [`;'] } */ + int islast = 0; + enterlevel(ls); + while (!islast && !block_follow(ls->t.token)) { + islast = statement(ls); + testnext(ls, ';'); + lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && + ls->fs->freereg >= ls->fs->nactvar); + ls->fs->freereg = ls->fs->nactvar; /* free registers */ + } + leavelevel(ls); +} + +/* }====================================================================== */ diff --git a/contrib/syslinux-4.02/com32/lua/src/lparser.h b/contrib/syslinux-4.02/com32/lua/src/lparser.h new file mode 100644 index 0000000..18836af --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lparser.h @@ -0,0 +1,82 @@ +/* +** $Id: lparser.h,v 1.57.1.1 2007/12/27 13:02:25 roberto Exp $ +** Lua Parser +** See Copyright Notice in lua.h +*/ + +#ifndef lparser_h +#define lparser_h + +#include "llimits.h" +#include "lobject.h" +#include "lzio.h" + + +/* +** Expression descriptor +*/ + +typedef enum { + VVOID, /* no value */ + VNIL, + VTRUE, + VFALSE, + VK, /* info = index of constant in `k' */ + VKNUM, /* nval = numerical value */ + VLOCAL, /* info = local register */ + VUPVAL, /* info = index of upvalue in `upvalues' */ + VGLOBAL, /* info = index of table; aux = index of global name in `k' */ + VINDEXED, /* info = table register; aux = index register (or `k') */ + VJMP, /* info = instruction pc */ + VRELOCABLE, /* info = instruction pc */ + VNONRELOC, /* info = result register */ + VCALL, /* info = instruction pc */ + VVARARG /* info = instruction pc */ +} expkind; + +typedef struct expdesc { + expkind k; + union { + struct { int info, aux; } s; + lua_Number nval; + } u; + int t; /* patch list of `exit when true' */ + int f; /* patch list of `exit when false' */ +} expdesc; + + +typedef struct upvaldesc { + lu_byte k; + lu_byte info; +} upvaldesc; + + +struct BlockCnt; /* defined in lparser.c */ + + +/* state needed to generate code for a given function */ +typedef struct FuncState { + Proto *f; /* current function header */ + Table *h; /* table to find (and reuse) elements in `k' */ + struct FuncState *prev; /* enclosing function */ + struct LexState *ls; /* lexical state */ + struct lua_State *L; /* copy of the Lua state */ + struct BlockCnt *bl; /* chain of current blocks */ + int pc; /* next position to code (equivalent to `ncode') */ + int lasttarget; /* `pc' of last `jump target' */ + int jpc; /* list of pending jumps to `pc' */ + int freereg; /* first free register */ + int nk; /* number of elements in `k' */ + int np; /* number of elements in `p' */ + short nlocvars; /* number of elements in `locvars' */ + lu_byte nactvar; /* number of active local variables */ + upvaldesc upvalues[LUAI_MAXUPVALUES]; /* upvalues */ + unsigned short actvar[LUAI_MAXVARS]; /* declared-variable stack */ +} FuncState; + + +LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, + const char *name); + + +#endif diff --git a/contrib/syslinux-4.02/com32/lua/src/lstate.c b/contrib/syslinux-4.02/com32/lua/src/lstate.c new file mode 100644 index 0000000..4313b83 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lstate.c @@ -0,0 +1,214 @@ +/* +** $Id: lstate.c,v 2.36.1.2 2008/01/03 15:20:39 roberto Exp $ +** Global State +** See Copyright Notice in lua.h +*/ + + +#include <stddef.h> + +#define lstate_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "llex.h" +#include "lmem.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" + + +#define state_size(x) (sizeof(x) + LUAI_EXTRASPACE) +#define fromstate(l) (cast(lu_byte *, (l)) - LUAI_EXTRASPACE) +#define tostate(l) (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE)) + + +/* +** Main thread combines a thread state and the global state +*/ +typedef struct LG { + lua_State l; + global_State g; +} LG; + + + +static void stack_init (lua_State *L1, lua_State *L) { + /* initialize CallInfo array */ + L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo); + L1->ci = L1->base_ci; + L1->size_ci = BASIC_CI_SIZE; + L1->end_ci = L1->base_ci + L1->size_ci - 1; + /* initialize stack array */ + L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue); + L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; + L1->top = L1->stack; + L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; + /* initialize first ci */ + L1->ci->func = L1->top; + setnilvalue(L1->top++); /* `function' entry for this `ci' */ + L1->base = L1->ci->base = L1->top; + L1->ci->top = L1->top + LUA_MINSTACK; +} + + +static void freestack (lua_State *L, lua_State *L1) { + luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo); + luaM_freearray(L, L1->stack, L1->stacksize, TValue); +} + + +/* +** open parts that may cause memory-allocation errors +*/ +static void f_luaopen (lua_State *L, void *ud) { + global_State *g = G(L); + UNUSED(ud); + stack_init(L, L); /* init stack */ + sethvalue(L, gt(L), luaH_new(L, 0, 2)); /* table of globals */ + sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */ + luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ + luaT_init(L); + luaX_init(L); + luaS_fix(luaS_newliteral(L, MEMERRMSG)); + g->GCthreshold = 4*g->totalbytes; +} + + +static void preinit_state (lua_State *L, global_State *g) { + G(L) = g; + L->stack = NULL; + L->stacksize = 0; + L->errorJmp = NULL; + L->hook = NULL; + L->hookmask = 0; + L->basehookcount = 0; + L->allowhook = 1; + resethookcount(L); + L->openupval = NULL; + L->size_ci = 0; + L->nCcalls = L->baseCcalls = 0; + L->status = 0; + L->base_ci = L->ci = NULL; + L->savedpc = NULL; + L->errfunc = 0; + setnilvalue(gt(L)); +} + + +static void close_state (lua_State *L) { + global_State *g = G(L); + luaF_close(L, L->stack); /* close all upvalues for this thread */ + luaC_freeall(L); /* collect all objects */ + lua_assert(g->rootgc == obj2gco(L)); + lua_assert(g->strt.nuse == 0); + luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *); + luaZ_freebuffer(L, &g->buff); + freestack(L, L); + lua_assert(g->totalbytes == sizeof(LG)); + (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0); +} + + +lua_State *luaE_newthread (lua_State *L) { + lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State))); + luaC_link(L, obj2gco(L1), LUA_TTHREAD); + preinit_state(L1, G(L)); + stack_init(L1, L); /* init stack */ + setobj2n(L, gt(L1), gt(L)); /* share table of globals */ + L1->hookmask = L->hookmask; + L1->basehookcount = L->basehookcount; + L1->hook = L->hook; + resethookcount(L1); + lua_assert(iswhite(obj2gco(L1))); + return L1; +} + + +void luaE_freethread (lua_State *L, lua_State *L1) { + luaF_close(L1, L1->stack); /* close all upvalues for this thread */ + lua_assert(L1->openupval == NULL); + luai_userstatefree(L1); + freestack(L, L1); + luaM_freemem(L, fromstate(L1), state_size(lua_State)); +} + + +LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { + int i; + lua_State *L; + global_State *g; + void *l = (*f)(ud, NULL, 0, state_size(LG)); + if (l == NULL) return NULL; + L = tostate(l); + g = &((LG *)L)->g; + L->next = NULL; + L->tt = LUA_TTHREAD; + g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); + L->marked = luaC_white(g); + set2bits(L->marked, FIXEDBIT, SFIXEDBIT); + preinit_state(L, g); + g->frealloc = f; + g->ud = ud; + g->mainthread = L; + g->uvhead.u.l.prev = &g->uvhead; + g->uvhead.u.l.next = &g->uvhead; + g->GCthreshold = 0; /* mark it as unfinished state */ + g->strt.size = 0; + g->strt.nuse = 0; + g->strt.hash = NULL; + setnilvalue(registry(L)); + luaZ_initbuffer(L, &g->buff); + g->panic = NULL; + g->gcstate = GCSpause; + g->rootgc = obj2gco(L); + g->sweepstrgc = 0; + g->sweepgc = &g->rootgc; + g->gray = NULL; + g->grayagain = NULL; + g->weak = NULL; + g->tmudata = NULL; + g->totalbytes = sizeof(LG); + g->gcpause = LUAI_GCPAUSE; + g->gcstepmul = LUAI_GCMUL; + g->gcdept = 0; + for (i=0; i<NUM_TAGS; i++) g->mt[i] = NULL; + if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) { + /* memory allocation error: free partial state */ + close_state(L); + L = NULL; + } + else + luai_userstateopen(L); + return L; +} + + +static void callallgcTM (lua_State *L, void *ud) { + UNUSED(ud); + luaC_callGCTM(L); /* call GC metamethods for all udata */ +} + + +LUA_API void lua_close (lua_State *L) { + L = G(L)->mainthread; /* only the main thread can be closed */ + lua_lock(L); + luaF_close(L, L->stack); /* close all upvalues for this thread */ + luaC_separateudata(L, 1); /* separate udata that have GC metamethods */ + L->errfunc = 0; /* no error function during GC metamethods */ + do { /* repeat until no more errors */ + L->ci = L->base_ci; + L->base = L->top = L->ci->base; + L->nCcalls = L->baseCcalls = 0; + } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0); + lua_assert(G(L)->tmudata == NULL); + luai_userstateclose(L); + close_state(L); +} + diff --git a/contrib/syslinux-4.02/com32/lua/src/lstate.h b/contrib/syslinux-4.02/com32/lua/src/lstate.h new file mode 100644 index 0000000..3bc575b --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lstate.h @@ -0,0 +1,169 @@ +/* +** $Id: lstate.h,v 2.24.1.2 2008/01/03 15:20:39 roberto Exp $ +** Global State +** See Copyright Notice in lua.h +*/ + +#ifndef lstate_h +#define lstate_h + +#include "lua.h" + +#include "lobject.h" +#include "ltm.h" +#include "lzio.h" + + + +struct lua_longjmp; /* defined in ldo.c */ + + +/* table of globals */ +#define gt(L) (&L->l_gt) + +/* registry */ +#define registry(L) (&G(L)->l_registry) + + +/* extra stack space to handle TM calls and some other extras */ +#define EXTRA_STACK 5 + + +#define BASIC_CI_SIZE 8 + +#define BASIC_STACK_SIZE (2*LUA_MINSTACK) + + + +typedef struct stringtable { + GCObject **hash; + lu_int32 nuse; /* number of elements */ + int size; +} stringtable; + + +/* +** informations about a call +*/ +typedef struct CallInfo { + StkId base; /* base for this function */ + StkId func; /* function index in the stack */ + StkId top; /* top for this function */ + const Instruction *savedpc; + int nresults; /* expected number of results from this function */ + int tailcalls; /* number of tail calls lost under this entry */ +} CallInfo; + + + +#define curr_func(L) (clvalue(L->ci->func)) +#define ci_func(ci) (clvalue((ci)->func)) +#define f_isLua(ci) (!ci_func(ci)->c.isC) +#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci)) + + +/* +** `global state', shared by all threads of this state +*/ +typedef struct global_State { + stringtable strt; /* hash table for strings */ + lua_Alloc frealloc; /* function to reallocate memory */ + void *ud; /* auxiliary data to `frealloc' */ + lu_byte currentwhite; + lu_byte gcstate; /* state of garbage collector */ + int sweepstrgc; /* position of sweep in `strt' */ + GCObject *rootgc; /* list of all collectable objects */ + GCObject **sweepgc; /* position of sweep in `rootgc' */ + GCObject *gray; /* list of gray objects */ + GCObject *grayagain; /* list of objects to be traversed atomically */ + GCObject *weak; /* list of weak tables (to be cleared) */ + GCObject *tmudata; /* last element of list of userdata to be GC */ + Mbuffer buff; /* temporary buffer for string concatentation */ + lu_mem GCthreshold; + lu_mem totalbytes; /* number of bytes currently allocated */ + lu_mem estimate; /* an estimate of number of bytes actually in use */ + lu_mem gcdept; /* how much GC is `behind schedule' */ + int gcpause; /* size of pause between successive GCs */ + int gcstepmul; /* GC `granularity' */ + lua_CFunction panic; /* to be called in unprotected errors */ + TValue l_registry; + struct lua_State *mainthread; + UpVal uvhead; /* head of double-linked list of all open upvalues */ + struct Table *mt[NUM_TAGS]; /* metatables for basic types */ + TString *tmname[TM_N]; /* array with tag-method names */ +} global_State; + + +/* +** `per thread' state +*/ +struct lua_State { + CommonHeader; + lu_byte status; + StkId top; /* first free slot in the stack */ + StkId base; /* base of current function */ + global_State *l_G; + CallInfo *ci; /* call info for current function */ + const Instruction *savedpc; /* `savedpc' of current function */ + StkId stack_last; /* last free slot in the stack */ + StkId stack; /* stack base */ + CallInfo *end_ci; /* points after end of ci array*/ + CallInfo *base_ci; /* array of CallInfo's */ + int stacksize; + int size_ci; /* size of array `base_ci' */ + unsigned short nCcalls; /* number of nested C calls */ + unsigned short baseCcalls; /* nested C calls when resuming coroutine */ + lu_byte hookmask; + lu_byte allowhook; + int basehookcount; + int hookcount; + lua_Hook hook; + TValue l_gt; /* table of globals */ + TValue env; /* temporary place for environments */ + GCObject *openupval; /* list of open upvalues in this stack */ + GCObject *gclist; + struct lua_longjmp *errorJmp; /* current error recover point */ + ptrdiff_t errfunc; /* current error handling function (stack index) */ +}; + + +#define G(L) (L->l_G) + + +/* +** Union of all collectable objects +*/ +union GCObject { + GCheader gch; + union TString ts; + union Udata u; + union Closure cl; + struct Table h; + struct Proto p; + struct UpVal uv; + struct lua_State th; /* thread */ +}; + + +/* macros to convert a GCObject into a specific value */ +#define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts)) +#define gco2ts(o) (&rawgco2ts(o)->tsv) +#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) +#define gco2u(o) (&rawgco2u(o)->uv) +#define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl)) +#define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) +#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) +#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) +#define ngcotouv(o) \ + check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv)) +#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) + +/* macro to convert any Lua object into a GCObject */ +#define obj2gco(v) (cast(GCObject *, (v))) + + +LUAI_FUNC lua_State *luaE_newthread (lua_State *L); +LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); + +#endif + diff --git a/contrib/syslinux-4.02/com32/lua/src/lstring.c b/contrib/syslinux-4.02/com32/lua/src/lstring.c new file mode 100644 index 0000000..4911315 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lstring.c @@ -0,0 +1,111 @@ +/* +** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ +** String table (keeps all strings handled by Lua) +** See Copyright Notice in lua.h +*/ + + +#include <string.h> + +#define lstring_c +#define LUA_CORE + +#include "lua.h" + +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" + + + +void luaS_resize (lua_State *L, int newsize) { + GCObject **newhash; + stringtable *tb; + int i; + if (G(L)->gcstate == GCSsweepstring) + return; /* cannot resize during GC traverse */ + newhash = luaM_newvector(L, newsize, GCObject *); + tb = &G(L)->strt; + for (i=0; i<newsize; i++) newhash[i] = NULL; + /* rehash */ + for (i=0; i<tb->size; i++) { + GCObject *p = tb->hash[i]; + while (p) { /* for each node in the list */ + GCObject *next = p->gch.next; /* save next */ + unsigned int h = gco2ts(p)->hash; + int h1 = lmod(h, newsize); /* new position */ + lua_assert(cast_int(h%newsize) == lmod(h, newsize)); + p->gch.next = newhash[h1]; /* chain it */ + newhash[h1] = p; + p = next; + } + } + luaM_freearray(L, tb->hash, tb->size, TString *); + tb->size = newsize; + tb->hash = newhash; +} + + +static TString *newlstr (lua_State *L, const char *str, size_t l, + unsigned int h) { + TString *ts; + stringtable *tb; + if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char)) + luaM_toobig(L); + ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString))); + ts->tsv.len = l; + ts->tsv.hash = h; + ts->tsv.marked = luaC_white(G(L)); + ts->tsv.tt = LUA_TSTRING; + ts->tsv.reserved = 0; + memcpy(ts+1, str, l*sizeof(char)); + ((char *)(ts+1))[l] = '\0'; /* ending 0 */ + tb = &G(L)->strt; + h = lmod(h, tb->size); + ts->tsv.next = tb->hash[h]; /* chain new entry */ + tb->hash[h] = obj2gco(ts); + tb->nuse++; + if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) + luaS_resize(L, tb->size*2); /* too crowded */ + return ts; +} + + +TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { + GCObject *o; + unsigned int h = cast(unsigned int, l); /* seed */ + size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */ + size_t l1; + for (l1=l; l1>=step; l1-=step) /* compute hash */ + h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1])); + for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)]; + o != NULL; + o = o->gch.next) { + TString *ts = rawgco2ts(o); + if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) { + /* string may be dead */ + if (isdead(G(L), o)) changewhite(o); + return ts; + } + } + return newlstr(L, str, l, h); /* not found */ +} + + +Udata *luaS_newudata (lua_State *L, size_t s, Table *e) { + Udata *u; + if (s > MAX_SIZET - sizeof(Udata)) + luaM_toobig(L); + u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata))); + u->uv.marked = luaC_white(G(L)); /* is not finalized */ + u->uv.tt = LUA_TUSERDATA; + u->uv.len = s; + u->uv.metatable = NULL; + u->uv.env = e; + /* chain it on udata list (after main thread) */ + u->uv.next = G(L)->mainthread->next; + G(L)->mainthread->next = obj2gco(u); + return u; +} + diff --git a/contrib/syslinux-4.02/com32/lua/src/lstring.h b/contrib/syslinux-4.02/com32/lua/src/lstring.h new file mode 100644 index 0000000..73a2ff8 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lstring.h @@ -0,0 +1,31 @@ +/* +** $Id: lstring.h,v 1.43.1.1 2007/12/27 13:02:25 roberto Exp $ +** String table (keep all strings handled by Lua) +** See Copyright Notice in lua.h +*/ + +#ifndef lstring_h +#define lstring_h + + +#include "lgc.h" +#include "lobject.h" +#include "lstate.h" + + +#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char)) + +#define sizeudata(u) (sizeof(union Udata)+(u)->len) + +#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s))) +#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ + (sizeof(s)/sizeof(char))-1)) + +#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) + +LUAI_FUNC void luaS_resize (lua_State *L, int newsize); +LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); +LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); + + +#endif diff --git a/contrib/syslinux-4.02/com32/lua/src/lstrlib.c b/contrib/syslinux-4.02/com32/lua/src/lstrlib.c new file mode 100644 index 0000000..1613cc9 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lstrlib.c @@ -0,0 +1,870 @@ +/* +** $Id: lstrlib.c,v 1.132.1.3 2007/12/28 15:32:23 roberto Exp $ +** Standard library for string operations and pattern-matching +** See Copyright Notice in lua.h +*/ + + +#include <ctype.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define lstrlib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* macro to `unsign' a character */ +#define uchar(c) ((unsigned char)(c)) + + + +static int str_len (lua_State *L) { + size_t l; + luaL_checklstring(L, 1, &l); + lua_pushinteger(L, l); + return 1; +} + + +static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) { + /* relative string position: negative means back from end */ + return (pos>=0) ? pos : (ptrdiff_t)len+pos+1; +} + + +static int str_sub (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l); + ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l); + if (start < 1) start = 1; + if (end > (ptrdiff_t)l) end = (ptrdiff_t)l; + if (start <= end) + lua_pushlstring(L, s+start-1, end-start+1); + else lua_pushliteral(L, ""); + return 1; +} + + +static int str_reverse (lua_State *L) { + size_t l; + luaL_Buffer b; + const char *s = luaL_checklstring(L, 1, &l); + luaL_buffinit(L, &b); + while (l--) luaL_addchar(&b, s[l]); + luaL_pushresult(&b); + return 1; +} + + +static int str_lower (lua_State *L) { + size_t l; + size_t i; + luaL_Buffer b; + const char *s = luaL_checklstring(L, 1, &l); + luaL_buffinit(L, &b); + for (i=0; i<l; i++) + luaL_addchar(&b, tolower(uchar(s[i]))); + luaL_pushresult(&b); + return 1; +} + + +static int str_upper (lua_State *L) { + size_t l; + size_t i; + luaL_Buffer b; + const char *s = luaL_checklstring(L, 1, &l); + luaL_buffinit(L, &b); + for (i=0; i<l; i++) + luaL_addchar(&b, toupper(uchar(s[i]))); + luaL_pushresult(&b); + return 1; +} + +static int str_rep (lua_State *L) { + size_t l; + luaL_Buffer b; + const char *s = luaL_checklstring(L, 1, &l); + int n = luaL_checkint(L, 2); + luaL_buffinit(L, &b); + while (n-- > 0) + luaL_addlstring(&b, s, l); + luaL_pushresult(&b); + return 1; +} + + +static int str_byte (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l); + ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l); + int n, i; + if (posi <= 0) posi = 1; + if ((size_t)pose > l) pose = l; + if (posi > pose) return 0; /* empty interval; return no values */ + n = (int)(pose - posi + 1); + if (posi + n <= pose) /* overflow? */ + luaL_error(L, "string slice too long"); + luaL_checkstack(L, n, "string slice too long"); + for (i=0; i<n; i++) + lua_pushinteger(L, uchar(s[posi+i-1])); + return n; +} + + +static int str_char (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + int i; + luaL_Buffer b; + luaL_buffinit(L, &b); + for (i=1; i<=n; i++) { + int c = luaL_checkint(L, i); + luaL_argcheck(L, uchar(c) == c, i, "invalid value"); + luaL_addchar(&b, uchar(c)); + } + luaL_pushresult(&b); + return 1; +} + + +static int writer (lua_State *L, const void* b, size_t size, void* B) { + (void)L; + luaL_addlstring((luaL_Buffer*) B, (const char *)b, size); + return 0; +} + + +static int str_dump (lua_State *L) { + luaL_Buffer b; + luaL_checktype(L, 1, LUA_TFUNCTION); + lua_settop(L, 1); + luaL_buffinit(L,&b); + if (lua_dump(L, writer, &b) != 0) + luaL_error(L, "unable to dump given function"); + luaL_pushresult(&b); + return 1; +} + + + +/* +** {====================================================== +** PATTERN MATCHING +** ======================================================= +*/ + + +#define CAP_UNFINISHED (-1) +#define CAP_POSITION (-2) + +typedef struct MatchState { + const char *src_init; /* init of source string */ + const char *src_end; /* end (`\0') of source string */ + lua_State *L; + int level; /* total number of captures (finished or unfinished) */ + struct { + const char *init; + ptrdiff_t len; + } capture[LUA_MAXCAPTURES]; +} MatchState; + + +#define L_ESC '%' +#define SPECIALS "^$*+?.([%-" + + +static int check_capture (MatchState *ms, int l) { + l -= '1'; + if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED) + return luaL_error(ms->L, "invalid capture index"); + return l; +} + + +static int capture_to_close (MatchState *ms) { + int level = ms->level; + for (level--; level>=0; level--) + if (ms->capture[level].len == CAP_UNFINISHED) return level; + return luaL_error(ms->L, "invalid pattern capture"); +} + + +static const char *classend (MatchState *ms, const char *p) { + switch (*p++) { + case L_ESC: { + if (*p == '\0') + luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")"); + return p+1; + } + case '[': { + if (*p == '^') p++; + do { /* look for a `]' */ + if (*p == '\0') + luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")"); + if (*(p++) == L_ESC && *p != '\0') + p++; /* skip escapes (e.g. `%]') */ + } while (*p != ']'); + return p+1; + } + default: { + return p; + } + } +} + + +static int match_class (int c, int cl) { + int res; + switch (tolower(cl)) { + case 'a' : res = isalpha(c); break; + case 'c' : res = iscntrl(c); break; + case 'd' : res = isdigit(c); break; + case 'l' : res = islower(c); break; + case 'p' : res = ispunct(c); break; + case 's' : res = isspace(c); break; + case 'u' : res = isupper(c); break; + case 'w' : res = isalnum(c); break; + case 'x' : res = isxdigit(c); break; + case 'z' : res = (c == 0); break; + default: return (cl == c); + } + return (islower(cl) ? res : !res); +} + + +static int matchbracketclass (int c, const char *p, const char *ec) { + int sig = 1; + if (*(p+1) == '^') { + sig = 0; + p++; /* skip the `^' */ + } + while (++p < ec) { + if (*p == L_ESC) { + p++; + if (match_class(c, uchar(*p))) + return sig; + } + else if ((*(p+1) == '-') && (p+2 < ec)) { + p+=2; + if (uchar(*(p-2)) <= c && c <= uchar(*p)) + return sig; + } + else if (uchar(*p) == c) return sig; + } + return !sig; +} + + +static int singlematch (int c, const char *p, const char *ep) { + switch (*p) { + case '.': return 1; /* matches any char */ + case L_ESC: return match_class(c, uchar(*(p+1))); + case '[': return matchbracketclass(c, p, ep-1); + default: return (uchar(*p) == c); + } +} + + +static const char *match (MatchState *ms, const char *s, const char *p); + + +static const char *matchbalance (MatchState *ms, const char *s, + const char *p) { + if (*p == 0 || *(p+1) == 0) + luaL_error(ms->L, "unbalanced pattern"); + if (*s != *p) return NULL; + else { + int b = *p; + int e = *(p+1); + int cont = 1; + while (++s < ms->src_end) { + if (*s == e) { + if (--cont == 0) return s+1; + } + else if (*s == b) cont++; + } + } + return NULL; /* string ends out of balance */ +} + + +static const char *max_expand (MatchState *ms, const char *s, + const char *p, const char *ep) { + ptrdiff_t i = 0; /* counts maximum expand for item */ + while ((s+i)<ms->src_end && singlematch(uchar(*(s+i)), p, ep)) + i++; + /* keeps trying to match with the maximum repetitions */ + while (i>=0) { + const char *res = match(ms, (s+i), ep+1); + if (res) return res; + i--; /* else didn't match; reduce 1 repetition to try again */ + } + return NULL; +} + + +static const char *min_expand (MatchState *ms, const char *s, + const char *p, const char *ep) { + for (;;) { + const char *res = match(ms, s, ep+1); + if (res != NULL) + return res; + else if (s<ms->src_end && singlematch(uchar(*s), p, ep)) + s++; /* try with one more repetition */ + else return NULL; + } +} + + +static const char *start_capture (MatchState *ms, const char *s, + const char *p, int what) { + const char *res; + int level = ms->level; + if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures"); + ms->capture[level].init = s; + ms->capture[level].len = what; + ms->level = level+1; + if ((res=match(ms, s, p)) == NULL) /* match failed? */ + ms->level--; /* undo capture */ + return res; +} + + +static const char *end_capture (MatchState *ms, const char *s, + const char *p) { + int l = capture_to_close(ms); + const char *res; + ms->capture[l].len = s - ms->capture[l].init; /* close capture */ + if ((res = match(ms, s, p)) == NULL) /* match failed? */ + ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ + return res; +} + + +static const char *match_capture (MatchState *ms, const char *s, int l) { + size_t len; + l = check_capture(ms, l); + len = ms->capture[l].len; + if ((size_t)(ms->src_end-s) >= len && + memcmp(ms->capture[l].init, s, len) == 0) + return s+len; + else return NULL; +} + + +static const char *match (MatchState *ms, const char *s, const char *p) { + init: /* using goto's to optimize tail recursion */ + switch (*p) { + case '(': { /* start capture */ + if (*(p+1) == ')') /* position capture? */ + return start_capture(ms, s, p+2, CAP_POSITION); + else + return start_capture(ms, s, p+1, CAP_UNFINISHED); + } + case ')': { /* end capture */ + return end_capture(ms, s, p+1); + } + case L_ESC: { + switch (*(p+1)) { + case 'b': { /* balanced string? */ + s = matchbalance(ms, s, p+2); + if (s == NULL) return NULL; + p+=4; goto init; /* else return match(ms, s, p+4); */ + } + case 'f': { /* frontier? */ + const char *ep; char previous; + p += 2; + if (*p != '[') + luaL_error(ms->L, "missing " LUA_QL("[") " after " + LUA_QL("%%f") " in pattern"); + ep = classend(ms, p); /* points to what is next */ + previous = (s == ms->src_init) ? '\0' : *(s-1); + if (matchbracketclass(uchar(previous), p, ep-1) || + !matchbracketclass(uchar(*s), p, ep-1)) return NULL; + p=ep; goto init; /* else return match(ms, s, ep); */ + } + default: { + if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */ + s = match_capture(ms, s, uchar(*(p+1))); + if (s == NULL) return NULL; + p+=2; goto init; /* else return match(ms, s, p+2) */ + } + goto dflt; /* case default */ + } + } + } + case '\0': { /* end of pattern */ + return s; /* match succeeded */ + } + case '$': { + if (*(p+1) == '\0') /* is the `$' the last char in pattern? */ + return (s == ms->src_end) ? s : NULL; /* check end of string */ + else goto dflt; + } + default: dflt: { /* it is a pattern item */ + const char *ep = classend(ms, p); /* points to what is next */ + int m = s<ms->src_end && singlematch(uchar(*s), p, ep); + switch (*ep) { + case '?': { /* optional */ + const char *res; + if (m && ((res=match(ms, s+1, ep+1)) != NULL)) + return res; + p=ep+1; goto init; /* else return match(ms, s, ep+1); */ + } + case '*': { /* 0 or more repetitions */ + return max_expand(ms, s, p, ep); + } + case '+': { /* 1 or more repetitions */ + return (m ? max_expand(ms, s+1, p, ep) : NULL); + } + case '-': { /* 0 or more repetitions (minimum) */ + return min_expand(ms, s, p, ep); + } + default: { + if (!m) return NULL; + s++; p=ep; goto init; /* else return match(ms, s+1, ep); */ + } + } + } + } +} + + + +static const char *lmemfind (const char *s1, size_t l1, + const char *s2, size_t l2) { + if (l2 == 0) return s1; /* empty strings are everywhere */ + else if (l2 > l1) return NULL; /* avoids a negative `l1' */ + else { + const char *init; /* to search for a `*s2' inside `s1' */ + l2--; /* 1st char will be checked by `memchr' */ + l1 = l1-l2; /* `s2' cannot be found after that */ + while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { + init++; /* 1st char is already checked */ + if (memcmp(init, s2+1, l2) == 0) + return init-1; + else { /* correct `l1' and `s1' to try again */ + l1 -= init-s1; + s1 = init; + } + } + return NULL; /* not found */ + } +} + + +static void push_onecapture (MatchState *ms, int i, const char *s, + const char *e) { + if (i >= ms->level) { + if (i == 0) /* ms->level == 0, too */ + lua_pushlstring(ms->L, s, e - s); /* add whole match */ + else + luaL_error(ms->L, "invalid capture index"); + } + else { + ptrdiff_t l = ms->capture[i].len; + if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); + if (l == CAP_POSITION) + lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1); + else + lua_pushlstring(ms->L, ms->capture[i].init, l); + } +} + + +static int push_captures (MatchState *ms, const char *s, const char *e) { + int i; + int nlevels = (ms->level == 0 && s) ? 1 : ms->level; + luaL_checkstack(ms->L, nlevels, "too many captures"); + for (i = 0; i < nlevels; i++) + push_onecapture(ms, i, s, e); + return nlevels; /* number of strings pushed */ +} + + +static int str_find_aux (lua_State *L, int find) { + size_t l1, l2; + const char *s = luaL_checklstring(L, 1, &l1); + const char *p = luaL_checklstring(L, 2, &l2); + ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1; + if (init < 0) init = 0; + else if ((size_t)(init) > l1) init = (ptrdiff_t)l1; + if (find && (lua_toboolean(L, 4) || /* explicit request? */ + strpbrk(p, SPECIALS) == NULL)) { /* or no special characters? */ + /* do a plain search */ + const char *s2 = lmemfind(s+init, l1-init, p, l2); + if (s2) { + lua_pushinteger(L, s2-s+1); + lua_pushinteger(L, s2-s+l2); + return 2; + } + } + else { + MatchState ms; + int anchor = (*p == '^') ? (p++, 1) : 0; + const char *s1=s+init; + ms.L = L; + ms.src_init = s; + ms.src_end = s+l1; + do { + const char *res; + ms.level = 0; + if ((res=match(&ms, s1, p)) != NULL) { + if (find) { + lua_pushinteger(L, s1-s+1); /* start */ + lua_pushinteger(L, res-s); /* end */ + return push_captures(&ms, NULL, 0) + 2; + } + else + return push_captures(&ms, s1, res); + } + } while (s1++ < ms.src_end && !anchor); + } + lua_pushnil(L); /* not found */ + return 1; +} + + +static int str_find (lua_State *L) { + return str_find_aux(L, 1); +} + + +static int str_match (lua_State *L) { + return str_find_aux(L, 0); +} + + +static int gmatch_aux (lua_State *L) { + MatchState ms; + size_t ls; + const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); + const char *p = lua_tostring(L, lua_upvalueindex(2)); + const char *src; + ms.L = L; + ms.src_init = s; + ms.src_end = s+ls; + for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); + src <= ms.src_end; + src++) { + const char *e; + ms.level = 0; + if ((e = match(&ms, src, p)) != NULL) { + lua_Integer newstart = e-s; + if (e == src) newstart++; /* empty match? go at least one position */ + lua_pushinteger(L, newstart); + lua_replace(L, lua_upvalueindex(3)); + return push_captures(&ms, src, e); + } + } + return 0; /* not found */ +} + + +static int gmatch (lua_State *L) { + luaL_checkstring(L, 1); + luaL_checkstring(L, 2); + lua_settop(L, 2); + lua_pushinteger(L, 0); + lua_pushcclosure(L, gmatch_aux, 3); + return 1; +} + + +static int gfind_nodef (lua_State *L) { + return luaL_error(L, LUA_QL("string.gfind") " was renamed to " + LUA_QL("string.gmatch")); +} + + +static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, + const char *e) { + size_t l, i; + const char *news = lua_tolstring(ms->L, 3, &l); + for (i = 0; i < l; i++) { + if (news[i] != L_ESC) + luaL_addchar(b, news[i]); + else { + i++; /* skip ESC */ + if (!isdigit(uchar(news[i]))) + luaL_addchar(b, news[i]); + else if (news[i] == '0') + luaL_addlstring(b, s, e - s); + else { + push_onecapture(ms, news[i] - '1', s, e); + luaL_addvalue(b); /* add capture to accumulated result */ + } + } + } +} + + +static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, + const char *e) { + lua_State *L = ms->L; + switch (lua_type(L, 3)) { + case LUA_TNUMBER: + case LUA_TSTRING: { + add_s(ms, b, s, e); + return; + } + case LUA_TFUNCTION: { + int n; + lua_pushvalue(L, 3); + n = push_captures(ms, s, e); + lua_call(L, n, 1); + break; + } + case LUA_TTABLE: { + push_onecapture(ms, 0, s, e); + lua_gettable(L, 3); + break; + } + } + if (!lua_toboolean(L, -1)) { /* nil or false? */ + lua_pop(L, 1); + lua_pushlstring(L, s, e - s); /* keep original text */ + } + else if (!lua_isstring(L, -1)) + luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); + luaL_addvalue(b); /* add result to accumulator */ +} + + +static int str_gsub (lua_State *L) { + size_t srcl; + const char *src = luaL_checklstring(L, 1, &srcl); + const char *p = luaL_checkstring(L, 2); + int tr = lua_type(L, 3); + int max_s = luaL_optint(L, 4, srcl+1); + int anchor = (*p == '^') ? (p++, 1) : 0; + int n = 0; + MatchState ms; + luaL_Buffer b; + luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || + tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, + "string/function/table expected"); + luaL_buffinit(L, &b); + ms.L = L; + ms.src_init = src; + ms.src_end = src+srcl; + while (n < max_s) { + const char *e; + ms.level = 0; + e = match(&ms, src, p); + if (e) { + n++; + add_value(&ms, &b, src, e); + } + if (e && e>src) /* non empty match? */ + src = e; /* skip it */ + else if (src < ms.src_end) + luaL_addchar(&b, *src++); + else break; + if (anchor) break; + } + luaL_addlstring(&b, src, ms.src_end-src); + luaL_pushresult(&b); + lua_pushinteger(L, n); /* number of substitutions */ + return 2; +} + +/* }====================================================== */ + + +/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ +#define MAX_ITEM 512 +/* valid flags in a format specification */ +#define FLAGS "-+ #0" +/* +** maximum size of each format specification (such as '%-099.99d') +** (+10 accounts for %99.99x plus margin of error) +*/ +#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10) + + +static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { + size_t l; + const char *s = luaL_checklstring(L, arg, &l); + luaL_addchar(b, '"'); + while (l--) { + switch (*s) { + case '"': case '\\': case '\n': { + luaL_addchar(b, '\\'); + luaL_addchar(b, *s); + break; + } + case '\r': { + luaL_addlstring(b, "\\r", 2); + break; + } + case '\0': { + luaL_addlstring(b, "\\000", 4); + break; + } + default: { + luaL_addchar(b, *s); + break; + } + } + s++; + } + luaL_addchar(b, '"'); +} + +static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { + const char *p = strfrmt; + while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ + if ((size_t)(p - strfrmt) >= sizeof(FLAGS)) + luaL_error(L, "invalid format (repeated flags)"); + if (isdigit(uchar(*p))) p++; /* skip width */ + if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ + if (*p == '.') { + p++; + if (isdigit(uchar(*p))) p++; /* skip precision */ + if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ + } + if (isdigit(uchar(*p))) + luaL_error(L, "invalid format (width or precision too long)"); + *(form++) = '%'; + strncpy(form, strfrmt, p - strfrmt + 1); + form += p - strfrmt + 1; + *form = '\0'; + return p; +} + + +static void addintlen (char *form) { + size_t l = strlen(form); + char spec = form[l - 1]; + strcpy(form + l - 1, LUA_INTFRMLEN); + form[l + sizeof(LUA_INTFRMLEN) - 2] = spec; + form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0'; +} + + +static int str_format (lua_State *L) { + int arg = 1; + size_t sfl; + const char *strfrmt = luaL_checklstring(L, arg, &sfl); + const char *strfrmt_end = strfrmt+sfl; + luaL_Buffer b; + luaL_buffinit(L, &b); + while (strfrmt < strfrmt_end) { + if (*strfrmt != L_ESC) + luaL_addchar(&b, *strfrmt++); + else if (*++strfrmt == L_ESC) + luaL_addchar(&b, *strfrmt++); /* %% */ + else { /* format item */ + char form[MAX_FORMAT]; /* to store the format (`%...') */ + char buff[MAX_ITEM]; /* to store the formatted item */ + arg++; + strfrmt = scanformat(L, strfrmt, form); + switch (*strfrmt++) { + case 'c': { + sprintf(buff, form, (int)luaL_checknumber(L, arg)); + break; + } + case 'd': case 'i': { + addintlen(form); + sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg)); + break; + } + case 'o': case 'u': case 'x': case 'X': { + addintlen(form); + sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg)); + break; + } +#if !defined LUA_NUMBER_INTEGRAL + case 'e': case 'E': case 'f': + case 'g': case 'G': { + sprintf(buff, form, (double)luaL_checknumber(L, arg)); + break; + } +#endif + case 'q': { + addquoted(L, &b, arg); + continue; /* skip the 'addsize' at the end */ + } + case 's': { + size_t l; + const char *s = luaL_checklstring(L, arg, &l); + if (!strchr(form, '.') && l >= 100) { + /* no precision and string is too long to be formatted; + keep original string */ + lua_pushvalue(L, arg); + luaL_addvalue(&b); + continue; /* skip the `addsize' at the end */ + } + else { + sprintf(buff, form, s); + break; + } + } + default: { /* also treat cases `pnLlh' */ + return luaL_error(L, "invalid option " LUA_QL("%%%c") " to " + LUA_QL("format"), *(strfrmt - 1)); + } + } + luaL_addlstring(&b, buff, strlen(buff)); + } + } + luaL_pushresult(&b); + return 1; +} + + +static const luaL_Reg strlib[] = { + {"byte", str_byte}, + {"char", str_char}, + {"dump", str_dump}, + {"find", str_find}, + {"format", str_format}, + {"gfind", gfind_nodef}, + {"gmatch", gmatch}, + {"gsub", str_gsub}, + {"len", str_len}, + {"lower", str_lower}, + {"match", str_match}, + {"rep", str_rep}, + {"reverse", str_reverse}, + {"sub", str_sub}, + {"upper", str_upper}, + {NULL, NULL} +}; + + +static void createmetatable (lua_State *L) { + lua_createtable(L, 0, 1); /* create metatable for strings */ + lua_pushliteral(L, ""); /* dummy string */ + lua_pushvalue(L, -2); + lua_setmetatable(L, -2); /* set string metatable */ + lua_pop(L, 1); /* pop dummy string */ + lua_pushvalue(L, -2); /* string library... */ + lua_setfield(L, -2, "__index"); /* ...is the __index metamethod */ + lua_pop(L, 1); /* pop metatable */ +} + + +/* +** Open string library +*/ +LUALIB_API int luaopen_string (lua_State *L) { + luaL_register(L, LUA_STRLIBNAME, strlib); +#if defined(LUA_COMPAT_GFIND) + lua_getfield(L, -1, "gmatch"); + lua_setfield(L, -2, "gfind"); +#endif + createmetatable(L); + return 1; +} + diff --git a/contrib/syslinux-4.02/com32/lua/src/ltable.c b/contrib/syslinux-4.02/com32/lua/src/ltable.c new file mode 100644 index 0000000..ec84f4f --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/ltable.c @@ -0,0 +1,588 @@ +/* +** $Id: ltable.c,v 2.32.1.2 2007/12/28 15:32:23 roberto Exp $ +** Lua tables (hash) +** See Copyright Notice in lua.h +*/ + + +/* +** Implementation of tables (aka arrays, objects, or hash tables). +** Tables keep its elements in two parts: an array part and a hash part. +** Non-negative integer keys are all candidates to be kept in the array +** part. The actual size of the array is the largest `n' such that at +** least half the slots between 0 and n are in use. +** Hash uses a mix of chained scatter table with Brent's variation. +** A main invariant of these tables is that, if an element is not +** in its main position (i.e. the `original' position that its hash gives +** to it), then the colliding element is in its own main position. +** Hence even when the load factor reaches 100%, performance remains good. +*/ + +#include <math.h> +#include <string.h> + +#define ltable_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "ltable.h" + + +/* +** max size of array part is 2^MAXBITS +*/ +#if LUAI_BITSINT > 26 +#define MAXBITS 26 +#else +#define MAXBITS (LUAI_BITSINT-2) +#endif + +#define MAXASIZE (1 << MAXBITS) + + +#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) + +#define hashstr(t,str) hashpow2(t, (str)->tsv.hash) +#define hashboolean(t,p) hashpow2(t, p) + + +/* +** for some types, it is better to avoid modulus by power of 2, as +** they tend to have many 2 factors. +*/ +#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) + + +#define hashpointer(t,p) hashmod(t, IntPoint(p)) + + +/* +** number of ints inside a lua_Number +*/ +#define numints cast_int(sizeof(lua_Number)/sizeof(int)) + + + +#define dummynode (&dummynode_) + +static const Node dummynode_ = { + {{NULL}, LUA_TNIL}, /* value */ + {{{NULL}, LUA_TNIL, NULL}} /* key */ +}; + + +/* +** hash for lua_Numbers +*/ +static Node *hashnum (const Table *t, lua_Number n) { + unsigned int a[numints]; + int i; + if (luai_numeq(n, 0)) /* avoid problems with -0 */ + return gnode(t, 0); + memcpy(a, &n, sizeof(a)); + for (i = 1; i < numints; i++) a[0] += a[i]; + return hashmod(t, a[0]); +} + + + +/* +** returns the `main' position of an element in a table (that is, the index +** of its hash value) +*/ +static Node *mainposition (const Table *t, const TValue *key) { + switch (ttype(key)) { + case LUA_TNUMBER: + return hashnum(t, nvalue(key)); + case LUA_TSTRING: + return hashstr(t, rawtsvalue(key)); + case LUA_TBOOLEAN: + return hashboolean(t, bvalue(key)); + case LUA_TLIGHTUSERDATA: + return hashpointer(t, pvalue(key)); + default: + return hashpointer(t, gcvalue(key)); + } +} + + +/* +** returns the index for `key' if `key' is an appropriate key to live in +** the array part of the table, -1 otherwise. +*/ +static int arrayindex (const TValue *key) { + if (ttisnumber(key)) { + lua_Number n = nvalue(key); + int k; + lua_number2int(k, n); + if (luai_numeq(cast_num(k), n)) + return k; + } + return -1; /* `key' did not match some condition */ +} + + +/* +** returns the index of a `key' for table traversals. First goes all +** elements in the array part, then elements in the hash part. The +** beginning of a traversal is signalled by -1. +*/ +static int findindex (lua_State *L, Table *t, StkId key) { + int i; + if (ttisnil(key)) return -1; /* first iteration */ + i = arrayindex(key); + if (0 < i && i <= t->sizearray) /* is `key' inside array part? */ + return i-1; /* yes; that's the index (corrected to C) */ + else { + Node *n = mainposition(t, key); + do { /* check whether `key' is somewhere in the chain */ + /* key may be dead already, but it is ok to use it in `next' */ + if (luaO_rawequalObj(key2tval(n), key) || + (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) && + gcvalue(gkey(n)) == gcvalue(key))) { + i = cast_int(n - gnode(t, 0)); /* key index in hash table */ + /* hash elements are numbered after array ones */ + return i + t->sizearray; + } + else n = gnext(n); + } while (n); + luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */ + return 0; /* to avoid warnings */ + } +} + + +int luaH_next (lua_State *L, Table *t, StkId key) { + int i = findindex(L, t, key); /* find original element */ + for (i++; i < t->sizearray; i++) { /* try first array part */ + if (!ttisnil(&t->array[i])) { /* a non-nil value? */ + setnvalue(key, cast_num(i+1)); + setobj2s(L, key+1, &t->array[i]); + return 1; + } + } + for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */ + if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ + setobj2s(L, key, key2tval(gnode(t, i))); + setobj2s(L, key+1, gval(gnode(t, i))); + return 1; + } + } + return 0; /* no more elements */ +} + + +/* +** {============================================================= +** Rehash +** ============================================================== +*/ + + +static int computesizes (int nums[], int *narray) { + int i; + int twotoi; /* 2^i */ + int a = 0; /* number of elements smaller than 2^i */ + int na = 0; /* number of elements to go to array part */ + int n = 0; /* optimal size for array part */ + for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) { + if (nums[i] > 0) { + a += nums[i]; + if (a > twotoi/2) { /* more than half elements present? */ + n = twotoi; /* optimal size (till now) */ + na = a; /* all elements smaller than n will go to array part */ + } + } + if (a == *narray) break; /* all elements already counted */ + } + *narray = n; + lua_assert(*narray/2 <= na && na <= *narray); + return na; +} + + +static int countint (const TValue *key, int *nums) { + int k = arrayindex(key); + if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */ + nums[ceillog2(k)]++; /* count as such */ + return 1; + } + else + return 0; +} + + +static int numusearray (const Table *t, int *nums) { + int lg; + int ttlg; /* 2^lg */ + int ause = 0; /* summation of `nums' */ + int i = 1; /* count to traverse all array keys */ + for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) { /* for each slice */ + int lc = 0; /* counter */ + int lim = ttlg; + if (lim > t->sizearray) { + lim = t->sizearray; /* adjust upper limit */ + if (i > lim) + break; /* no more elements to count */ + } + /* count elements in range (2^(lg-1), 2^lg] */ + for (; i <= lim; i++) { + if (!ttisnil(&t->array[i-1])) + lc++; + } + nums[lg] += lc; + ause += lc; + } + return ause; +} + + +static int numusehash (const Table *t, int *nums, int *pnasize) { + int totaluse = 0; /* total number of elements */ + int ause = 0; /* summation of `nums' */ + int i = sizenode(t); + while (i--) { + Node *n = &t->node[i]; + if (!ttisnil(gval(n))) { + ause += countint(key2tval(n), nums); + totaluse++; + } + } + *pnasize += ause; + return totaluse; +} + + +static void setarrayvector (lua_State *L, Table *t, int size) { + int i; + luaM_reallocvector(L, t->array, t->sizearray, size, TValue); + for (i=t->sizearray; i<size; i++) + setnilvalue(&t->array[i]); + t->sizearray = size; +} + + +static void setnodevector (lua_State *L, Table *t, int size) { + int lsize; + if (size == 0) { /* no elements to hash part? */ + t->node = cast(Node *, dummynode); /* use common `dummynode' */ + lsize = 0; + } + else { + int i; + lsize = ceillog2(size); + if (lsize > MAXBITS) + luaG_runerror(L, "table overflow"); + size = twoto(lsize); + t->node = luaM_newvector(L, size, Node); + for (i=0; i<size; i++) { + Node *n = gnode(t, i); + gnext(n) = NULL; + setnilvalue(gkey(n)); + setnilvalue(gval(n)); + } + } + t->lsizenode = cast_byte(lsize); + t->lastfree = gnode(t, size); /* all positions are free */ +} + + +static void resize (lua_State *L, Table *t, int nasize, int nhsize) { + int i; + int oldasize = t->sizearray; + int oldhsize = t->lsizenode; + Node *nold = t->node; /* save old hash ... */ + if (nasize > oldasize) /* array part must grow? */ + setarrayvector(L, t, nasize); + /* create new hash part with appropriate size */ + setnodevector(L, t, nhsize); + if (nasize < oldasize) { /* array part must shrink? */ + t->sizearray = nasize; + /* re-insert elements from vanishing slice */ + for (i=nasize; i<oldasize; i++) { + if (!ttisnil(&t->array[i])) + setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]); + } + /* shrink array */ + luaM_reallocvector(L, t->array, oldasize, nasize, TValue); + } + /* re-insert elements from hash part */ + for (i = twoto(oldhsize) - 1; i >= 0; i--) { + Node *old = nold+i; + if (!ttisnil(gval(old))) + setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old)); + } + if (nold != dummynode) + luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */ +} + + +void luaH_resizearray (lua_State *L, Table *t, int nasize) { + int nsize = (t->node == dummynode) ? 0 : sizenode(t); + resize(L, t, nasize, nsize); +} + + +static void rehash (lua_State *L, Table *t, const TValue *ek) { + int nasize, na; + int nums[MAXBITS+1]; /* nums[i] = number of keys between 2^(i-1) and 2^i */ + int i; + int totaluse; + for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */ + nasize = numusearray(t, nums); /* count keys in array part */ + totaluse = nasize; /* all those keys are integer keys */ + totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */ + /* count extra key */ + nasize += countint(ek, nums); + totaluse++; + /* compute new size for array part */ + na = computesizes(nums, &nasize); + /* resize the table to new computed sizes */ + resize(L, t, nasize, totaluse - na); +} + + + +/* +** }============================================================= +*/ + + +Table *luaH_new (lua_State *L, int narray, int nhash) { + Table *t = luaM_new(L, Table); + luaC_link(L, obj2gco(t), LUA_TTABLE); + t->metatable = NULL; + t->flags = cast_byte(~0); + /* temporary values (kept only if some malloc fails) */ + t->array = NULL; + t->sizearray = 0; + t->lsizenode = 0; + t->node = cast(Node *, dummynode); + setarrayvector(L, t, narray); + setnodevector(L, t, nhash); + return t; +} + + +void luaH_free (lua_State *L, Table *t) { + if (t->node != dummynode) + luaM_freearray(L, t->node, sizenode(t), Node); + luaM_freearray(L, t->array, t->sizearray, TValue); + luaM_free(L, t); +} + + +static Node *getfreepos (Table *t) { + while (t->lastfree-- > t->node) { + if (ttisnil(gkey(t->lastfree))) + return t->lastfree; + } + return NULL; /* could not find a free place */ +} + + + +/* +** inserts a new key into a hash table; first, check whether key's main +** position is free. If not, check whether colliding node is in its main +** position or not: if it is not, move colliding node to an empty place and +** put new key in its main position; otherwise (colliding node is in its main +** position), new key goes to an empty position. +*/ +static TValue *newkey (lua_State *L, Table *t, const TValue *key) { + Node *mp = mainposition(t, key); + if (!ttisnil(gval(mp)) || mp == dummynode) { + Node *othern; + Node *n = getfreepos(t); /* get a free place */ + if (n == NULL) { /* cannot find a free place? */ + rehash(L, t, key); /* grow table */ + return luaH_set(L, t, key); /* re-insert key into grown table */ + } + lua_assert(n != dummynode); + othern = mainposition(t, key2tval(mp)); + if (othern != mp) { /* is colliding node out of its main position? */ + /* yes; move colliding node into free position */ + while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ + gnext(othern) = n; /* redo the chain with `n' in place of `mp' */ + *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ + gnext(mp) = NULL; /* now `mp' is free */ + setnilvalue(gval(mp)); + } + else { /* colliding node is in its own main position */ + /* new node will go into free position */ + gnext(n) = gnext(mp); /* chain new position */ + gnext(mp) = n; + mp = n; + } + } + gkey(mp)->value = key->value; gkey(mp)->tt = key->tt; + luaC_barriert(L, t, key); + lua_assert(ttisnil(gval(mp))); + return gval(mp); +} + + +/* +** search function for integers +*/ +const TValue *luaH_getnum (Table *t, int key) { + /* (1 <= key && key <= t->sizearray) */ + if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) + return &t->array[key-1]; + else { + lua_Number nk = cast_num(key); + Node *n = hashnum(t, nk); + do { /* check whether `key' is somewhere in the chain */ + if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk)) + return gval(n); /* that's it */ + else n = gnext(n); + } while (n); + return luaO_nilobject; + } +} + + +/* +** search function for strings +*/ +const TValue *luaH_getstr (Table *t, TString *key) { + Node *n = hashstr(t, key); + do { /* check whether `key' is somewhere in the chain */ + if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key) + return gval(n); /* that's it */ + else n = gnext(n); + } while (n); + return luaO_nilobject; +} + + +/* +** main search function +*/ +const TValue *luaH_get (Table *t, const TValue *key) { + switch (ttype(key)) { + case LUA_TNIL: return luaO_nilobject; + case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key)); + case LUA_TNUMBER: { + int k; + lua_Number n = nvalue(key); + lua_number2int(k, n); + if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */ + return luaH_getnum(t, k); /* use specialized version */ + /* else go through */ + } + default: { + Node *n = mainposition(t, key); + do { /* check whether `key' is somewhere in the chain */ + if (luaO_rawequalObj(key2tval(n), key)) + return gval(n); /* that's it */ + else n = gnext(n); + } while (n); + return luaO_nilobject; + } + } +} + + +TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { + const TValue *p = luaH_get(t, key); + t->flags = 0; + if (p != luaO_nilobject) + return cast(TValue *, p); + else { + if (ttisnil(key)) luaG_runerror(L, "table index is nil"); + else if (ttisnumber(key) && luai_numisnan(nvalue(key))) + luaG_runerror(L, "table index is NaN"); + return newkey(L, t, key); + } +} + + +TValue *luaH_setnum (lua_State *L, Table *t, int key) { + const TValue *p = luaH_getnum(t, key); + if (p != luaO_nilobject) + return cast(TValue *, p); + else { + TValue k; + setnvalue(&k, cast_num(key)); + return newkey(L, t, &k); + } +} + + +TValue *luaH_setstr (lua_State *L, Table *t, TString *key) { + const TValue *p = luaH_getstr(t, key); + if (p != luaO_nilobject) + return cast(TValue *, p); + else { + TValue k; + setsvalue(L, &k, key); + return newkey(L, t, &k); + } +} + + +static int unbound_search (Table *t, unsigned int j) { + unsigned int i = j; /* i is zero or a present index */ + j++; + /* find `i' and `j' such that i is present and j is not */ + while (!ttisnil(luaH_getnum(t, j))) { + i = j; + j *= 2; + if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ + /* table was built with bad purposes: resort to linear search */ + i = 1; + while (!ttisnil(luaH_getnum(t, i))) i++; + return i - 1; + } + } + /* now do a binary search between them */ + while (j - i > 1) { + unsigned int m = (i+j)/2; + if (ttisnil(luaH_getnum(t, m))) j = m; + else i = m; + } + return i; +} + + +/* +** Try to find a boundary in table `t'. A `boundary' is an integer index +** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil). +*/ +int luaH_getn (Table *t) { + unsigned int j = t->sizearray; + if (j > 0 && ttisnil(&t->array[j - 1])) { + /* there is a boundary in the array part: (binary) search for it */ + unsigned int i = 0; + while (j - i > 1) { + unsigned int m = (i+j)/2; + if (ttisnil(&t->array[m - 1])) j = m; + else i = m; + } + return i; + } + /* else must find a boundary in hash part */ + else if (t->node == dummynode) /* hash part is empty? */ + return j; /* that is easy... */ + else return unbound_search(t, j); +} + + + +#if defined(LUA_DEBUG) + +Node *luaH_mainposition (const Table *t, const TValue *key) { + return mainposition(t, key); +} + +int luaH_isdummy (Node *n) { return n == dummynode; } + +#endif diff --git a/contrib/syslinux-4.02/com32/lua/src/ltable.h b/contrib/syslinux-4.02/com32/lua/src/ltable.h new file mode 100644 index 0000000..f5b9d5e --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/ltable.h @@ -0,0 +1,40 @@ +/* +** $Id: ltable.h,v 2.10.1.1 2007/12/27 13:02:25 roberto Exp $ +** Lua tables (hash) +** See Copyright Notice in lua.h +*/ + +#ifndef ltable_h +#define ltable_h + +#include "lobject.h" + + +#define gnode(t,i) (&(t)->node[i]) +#define gkey(n) (&(n)->i_key.nk) +#define gval(n) (&(n)->i_val) +#define gnext(n) ((n)->i_key.nk.next) + +#define key2tval(n) (&(n)->i_key.tvk) + + +LUAI_FUNC const TValue *luaH_getnum (Table *t, int key); +LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key); +LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); +LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key); +LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); +LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key); +LUAI_FUNC Table *luaH_new (lua_State *L, int narray, int lnhash); +LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize); +LUAI_FUNC void luaH_free (lua_State *L, Table *t); +LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); +LUAI_FUNC int luaH_getn (Table *t); + + +#if defined(LUA_DEBUG) +LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); +LUAI_FUNC int luaH_isdummy (Node *n); +#endif + + +#endif diff --git a/contrib/syslinux-4.02/com32/lua/src/ltablib.c b/contrib/syslinux-4.02/com32/lua/src/ltablib.c new file mode 100644 index 0000000..06f1c37 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/ltablib.c @@ -0,0 +1,279 @@ +/* +** $Id: ltablib.c,v 1.38.1.2 2007/12/28 15:32:23 roberto Exp $ +** Library for Table Manipulation +** See Copyright Notice in lua.h +*/ + + +#include <stddef.h> + +#define ltablib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) + + +static int foreachi (lua_State *L) { + int i; + int n = aux_getn(L, 1); + luaL_checktype(L, 2, LUA_TFUNCTION); + for (i=1; i <= n; i++) { + lua_pushvalue(L, 2); /* function */ + lua_pushinteger(L, i); /* 1st argument */ + lua_rawgeti(L, 1, i); /* 2nd argument */ + lua_call(L, 2, 1); + if (!lua_isnil(L, -1)) + return 1; + lua_pop(L, 1); /* remove nil result */ + } + return 0; +} + + +static int foreach (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checktype(L, 2, LUA_TFUNCTION); + lua_pushnil(L); /* first key */ + while (lua_next(L, 1)) { + lua_pushvalue(L, 2); /* function */ + lua_pushvalue(L, -3); /* key */ + lua_pushvalue(L, -3); /* value */ + lua_call(L, 2, 1); + if (!lua_isnil(L, -1)) + return 1; + lua_pop(L, 2); /* remove value and result */ + } + return 0; +} + + +static int maxn (lua_State *L) { + lua_Number max = 0; + luaL_checktype(L, 1, LUA_TTABLE); + lua_pushnil(L); /* first key */ + while (lua_next(L, 1)) { + lua_pop(L, 1); /* remove value */ + if (lua_type(L, -1) == LUA_TNUMBER) { + lua_Number v = lua_tonumber(L, -1); + if (v > max) max = v; + } + } + lua_pushnumber(L, max); + return 1; +} + + +static int getn (lua_State *L) { + lua_pushinteger(L, aux_getn(L, 1)); + return 1; +} + + +static int setn (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); +#ifndef luaL_setn + luaL_setn(L, 1, luaL_checkint(L, 2)); +#else + luaL_error(L, LUA_QL("setn") " is obsolete"); +#endif + lua_pushvalue(L, 1); + return 1; +} + + +static int tinsert (lua_State *L) { + int e = aux_getn(L, 1) + 1; /* first empty element */ + int pos; /* where to insert new element */ + switch (lua_gettop(L)) { + case 2: { /* called with only 2 arguments */ + pos = e; /* insert new element at the end */ + break; + } + case 3: { + int i; + pos = luaL_checkint(L, 2); /* 2nd argument is the position */ + if (pos > e) e = pos; /* `grow' array if necessary */ + for (i = e; i > pos; i--) { /* move up elements */ + lua_rawgeti(L, 1, i-1); + lua_rawseti(L, 1, i); /* t[i] = t[i-1] */ + } + break; + } + default: { + return luaL_error(L, "wrong number of arguments to " LUA_QL("insert")); + } + } + luaL_setn(L, 1, e); /* new size */ + lua_rawseti(L, 1, pos); /* t[pos] = v */ + return 0; +} + + +static int tremove (lua_State *L) { + int e = aux_getn(L, 1); + int pos = luaL_optint(L, 2, e); + if (!(1 <= pos && pos <= e)) /* position is outside bounds? */ + return 0; /* nothing to remove */ + luaL_setn(L, 1, e - 1); /* t.n = n-1 */ + lua_rawgeti(L, 1, pos); /* result = t[pos] */ + for ( ;pos<e; pos++) { + lua_rawgeti(L, 1, pos+1); + lua_rawseti(L, 1, pos); /* t[pos] = t[pos+1] */ + } + lua_pushnil(L); + lua_rawseti(L, 1, e); /* t[e] = nil */ + return 1; +} + + +static int tconcat (lua_State *L) { + luaL_Buffer b; + size_t lsep; + int i, last; + const char *sep = luaL_optlstring(L, 2, "", &lsep); + luaL_checktype(L, 1, LUA_TTABLE); + i = luaL_optint(L, 3, 1); + last = luaL_opt(L, luaL_checkint, 4, luaL_getn(L, 1)); + luaL_buffinit(L, &b); + for (; i <= last; i++) { + lua_rawgeti(L, 1, i); + luaL_argcheck(L, lua_isstring(L, -1), 1, "table contains non-strings"); + luaL_addvalue(&b); + if (i != last) + luaL_addlstring(&b, sep, lsep); + } + luaL_pushresult(&b); + return 1; +} + + + +/* +** {====================================================== +** Quicksort +** (based on `Algorithms in MODULA-3', Robert Sedgewick; +** Addison-Wesley, 1993.) +*/ + + +static void set2 (lua_State *L, int i, int j) { + lua_rawseti(L, 1, i); + lua_rawseti(L, 1, j); +} + +static int sort_comp (lua_State *L, int a, int b) { + if (!lua_isnil(L, 2)) { /* function? */ + int res; + lua_pushvalue(L, 2); + lua_pushvalue(L, a-1); /* -1 to compensate function */ + lua_pushvalue(L, b-2); /* -2 to compensate function and `a' */ + lua_call(L, 2, 1); + res = lua_toboolean(L, -1); + lua_pop(L, 1); + return res; + } + else /* a < b? */ + return lua_lessthan(L, a, b); +} + +static void auxsort (lua_State *L, int l, int u) { + while (l < u) { /* for tail recursion */ + int i, j; + /* sort elements a[l], a[(l+u)/2] and a[u] */ + lua_rawgeti(L, 1, l); + lua_rawgeti(L, 1, u); + if (sort_comp(L, -1, -2)) /* a[u] < a[l]? */ + set2(L, l, u); /* swap a[l] - a[u] */ + else + lua_pop(L, 2); + if (u-l == 1) break; /* only 2 elements */ + i = (l+u)/2; + lua_rawgeti(L, 1, i); + lua_rawgeti(L, 1, l); + if (sort_comp(L, -2, -1)) /* a[i]<a[l]? */ + set2(L, i, l); + else { + lua_pop(L, 1); /* remove a[l] */ + lua_rawgeti(L, 1, u); + if (sort_comp(L, -1, -2)) /* a[u]<a[i]? */ + set2(L, i, u); + else + lua_pop(L, 2); + } + if (u-l == 2) break; /* only 3 elements */ + lua_rawgeti(L, 1, i); /* Pivot */ + lua_pushvalue(L, -1); + lua_rawgeti(L, 1, u-1); + set2(L, i, u-1); + /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */ + i = l; j = u-1; + for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */ + /* repeat ++i until a[i] >= P */ + while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { + if (i>u) luaL_error(L, "invalid order function for sorting"); + lua_pop(L, 1); /* remove a[i] */ + } + /* repeat --j until a[j] <= P */ + while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { + if (j<l) luaL_error(L, "invalid order function for sorting"); + lua_pop(L, 1); /* remove a[j] */ + } + if (j<i) { + lua_pop(L, 3); /* pop pivot, a[i], a[j] */ + break; + } + set2(L, i, j); + } + lua_rawgeti(L, 1, u-1); + lua_rawgeti(L, 1, i); + set2(L, u-1, i); /* swap pivot (a[u-1]) with a[i] */ + /* a[l..i-1] <= a[i] == P <= a[i+1..u] */ + /* adjust so that smaller half is in [j..i] and larger one in [l..u] */ + if (i-l < u-i) { + j=l; i=i-1; l=i+2; + } + else { + j=i+1; i=u; u=j-2; + } + auxsort(L, j, i); /* call recursively the smaller one */ + } /* repeat the routine for the larger one */ +} + +static int sort (lua_State *L) { + int n = aux_getn(L, 1); + luaL_checkstack(L, 40, ""); /* assume array is smaller than 2^40 */ + if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ + luaL_checktype(L, 2, LUA_TFUNCTION); + lua_settop(L, 2); /* make sure there is two arguments */ + auxsort(L, 1, n); + return 0; +} + +/* }====================================================== */ + + +static const luaL_Reg tab_funcs[] = { + {"concat", tconcat}, + {"foreach", foreach}, + {"foreachi", foreachi}, + {"getn", getn}, + {"maxn", maxn}, + {"insert", tinsert}, + {"remove", tremove}, + {"setn", setn}, + {"sort", sort}, + {NULL, NULL} +}; + + +LUALIB_API int luaopen_table (lua_State *L) { + luaL_register(L, LUA_TABLIBNAME, tab_funcs); + return 1; +} + diff --git a/contrib/syslinux-4.02/com32/lua/src/ltm.c b/contrib/syslinux-4.02/com32/lua/src/ltm.c new file mode 100644 index 0000000..c27f0f6 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/ltm.c @@ -0,0 +1,75 @@ +/* +** $Id: ltm.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ +** Tag methods +** See Copyright Notice in lua.h +*/ + + +#include <string.h> + +#define ltm_c +#define LUA_CORE + +#include "lua.h" + +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" + + + +const char *const luaT_typenames[] = { + "nil", "boolean", "userdata", "number", + "string", "table", "function", "userdata", "thread", + "proto", "upval" +}; + + +void luaT_init (lua_State *L) { + static const char *const luaT_eventname[] = { /* ORDER TM */ + "__index", "__newindex", + "__gc", "__mode", "__eq", + "__add", "__sub", "__mul", "__div", "__mod", + "__pow", "__unm", "__len", "__lt", "__le", + "__concat", "__call" + }; + int i; + for (i=0; i<TM_N; i++) { + G(L)->tmname[i] = luaS_new(L, luaT_eventname[i]); + luaS_fix(G(L)->tmname[i]); /* never collect these names */ + } +} + + +/* +** function to be used with macro "fasttm": optimized for absence of +** tag methods +*/ +const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { + const TValue *tm = luaH_getstr(events, ename); + lua_assert(event <= TM_EQ); + if (ttisnil(tm)) { /* no tag method? */ + events->flags |= cast_byte(1u<<event); /* cache this fact */ + return NULL; + } + else return tm; +} + + +const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) { + Table *mt; + switch (ttype(o)) { + case LUA_TTABLE: + mt = hvalue(o)->metatable; + break; + case LUA_TUSERDATA: + mt = uvalue(o)->metatable; + break; + default: + mt = G(L)->mt[ttype(o)]; + } + return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); +} + diff --git a/contrib/syslinux-4.02/com32/lua/src/ltm.h b/contrib/syslinux-4.02/com32/lua/src/ltm.h new file mode 100644 index 0000000..64343b7 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/ltm.h @@ -0,0 +1,54 @@ +/* +** $Id: ltm.h,v 2.6.1.1 2007/12/27 13:02:25 roberto Exp $ +** Tag methods +** See Copyright Notice in lua.h +*/ + +#ifndef ltm_h +#define ltm_h + + +#include "lobject.h" + + +/* +* WARNING: if you change the order of this enumeration, +* grep "ORDER TM" +*/ +typedef enum { + TM_INDEX, + TM_NEWINDEX, + TM_GC, + TM_MODE, + TM_EQ, /* last tag method with `fast' access */ + TM_ADD, + TM_SUB, + TM_MUL, + TM_DIV, + TM_MOD, + TM_POW, + TM_UNM, + TM_LEN, + TM_LT, + TM_LE, + TM_CONCAT, + TM_CALL, + TM_N /* number of elements in the enum */ +} TMS; + + + +#define gfasttm(g,et,e) ((et) == NULL ? NULL : \ + ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) + +#define fasttm(l,et,e) gfasttm(G(l), et, e) + +LUAI_DATA const char *const luaT_typenames[]; + + +LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); +LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, + TMS event); +LUAI_FUNC void luaT_init (lua_State *L); + +#endif diff --git a/contrib/syslinux-4.02/com32/lua/src/lua.c b/contrib/syslinux-4.02/com32/lua/src/lua.c new file mode 100644 index 0000000..0d2d16c --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lua.c @@ -0,0 +1,396 @@ +/* +** $Id: lua.c,v 1.160.1.2 2007/12/28 15:32:23 roberto Exp $ +** Lua stand-alone interpreter +** See Copyright Notice in lua.h +*/ + + +//#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <console.h> +#define lua_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + +static lua_State *globalL = NULL; + +static const char *progname = LUA_PROGNAME; + + +#if 0 + +static void lstop (lua_State *L, lua_Debug *ar) { + (void)ar; /* unused arg. */ + lua_sethook(L, NULL, 0, 0); + luaL_error(L, "interrupted!"); +} + +static void laction (int i) { + signal(i, SIG_DFL); /* if another SIGINT happens before lstop, + terminate process (default action) */ + lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); +} +#endif + +static void print_usage (void) { + fprintf(stderr, + "usage: %s [options] [script [args]].\n" + "Available options are:\n" + " -e stat execute string " LUA_QL("stat") "\n" + " -l name require library " LUA_QL("name") "\n" + " -i enter interactive mode after executing " LUA_QL("script") "\n" + " -v show version information\n" + " -- stop handling options\n" + " - execute stdin and stop handling options\n" + , + progname); + fflush(stderr); +} + + +static void l_message (const char *pname, const char *msg) { + if (pname) fprintf(stderr, "%s: ", pname); + fprintf(stderr, "%s\n", msg); + fflush(stderr); +} + + +static int report (lua_State *L, int status) { + if (status && !lua_isnil(L, -1)) { + const char *msg = lua_tostring(L, -1); + if (msg == NULL) msg = "(error object is not a string)"; + l_message(progname, msg); + lua_pop(L, 1); + } + return status; +} + + +static int traceback (lua_State *L) { + if (!lua_isstring(L, 1)) /* 'message' not a string? */ + return 1; /* keep it intact */ + lua_getfield(L, LUA_GLOBALSINDEX, "debug"); + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + return 1; + } + lua_getfield(L, -1, "traceback"); + if (!lua_isfunction(L, -1)) { + lua_pop(L, 2); + return 1; + } + lua_pushvalue(L, 1); /* pass error message */ + lua_pushinteger(L, 2); /* skip this function and traceback */ + lua_call(L, 2, 1); /* call debug.traceback */ + return 1; +} + + +static int docall (lua_State *L, int narg, int clear) { + int status; + int base = lua_gettop(L) - narg; /* function index */ + lua_pushcfunction(L, traceback); /* push traceback function */ + lua_insert(L, base); /* put it under chunk and args */ + /* signal(SIGINT, laction);*/ + status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base); +/* signal(SIGINT, SIG_DFL);*/ + lua_remove(L, base); /* remove traceback function */ + /* force a complete garbage collection in case of errors */ + if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0); + return status; +} + + +static void print_version (void) { + l_message(NULL, LUA_RELEASE " " LUA_COPYRIGHT); +} + + +static int getargs (lua_State *L, char **argv, int n) { + int narg; + int i; + int argc = 0; + while (argv[argc]) argc++; /* count total number of arguments */ + narg = argc - (n + 1); /* number of arguments to the script */ + luaL_checkstack(L, narg + 3, "too many arguments to script"); + for (i=n+1; i < argc; i++) + lua_pushstring(L, argv[i]); + lua_createtable(L, narg, n + 1); + for (i=0; i < argc; i++) { + lua_pushstring(L, argv[i]); + lua_rawseti(L, -2, i - n); + } + return narg; +} + + +static int dofile (lua_State *L, const char *name) { + int status = luaL_loadfile(L, name) || docall(L, 0, 1); + return report(L, status); +} + + +static int dostring (lua_State *L, const char *s, const char *name) { + int status = luaL_loadbuffer(L, s, strlen(s), name) || docall(L, 0, 1); + return report(L, status); +} + + +static int dolibrary (lua_State *L, const char *name) { + lua_getglobal(L, "require"); + lua_pushstring(L, name); + return report(L, docall(L, 1, 1)); +} + + +static const char *get_prompt (lua_State *L, int firstline) { + const char *p; + lua_getfield(L, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2"); + p = lua_tostring(L, -1); + if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2); + lua_pop(L, 1); /* remove global */ + return p; +} + + +static int incomplete (lua_State *L, int status) { + if (status == LUA_ERRSYNTAX) { + size_t lmsg; + const char *msg = lua_tolstring(L, -1, &lmsg); + const char *tp = msg + lmsg - (sizeof(LUA_QL("<eof>")) - 1); + if (strstr(msg, LUA_QL("<eof>")) == tp) { + lua_pop(L, 1); + return 1; + } + } + return 0; /* else... */ +} + + +static int pushline (lua_State *L, int firstline) { + char buffer[LUA_MAXINPUT]; + char *b = buffer; + size_t l; + const char *prmt = get_prompt(L, firstline); + if (lua_readline(L, b, prmt) == 0) + return 0; /* no input */ + l = strlen(b); + if (l > 0 && b[l-1] == '\n') /* line ends with newline? */ + b[l-1] = '\0'; /* remove it */ + if (firstline && b[0] == '=') /* first line starts with `=' ? */ + lua_pushfstring(L, "return %s", b+1); /* change it to `return' */ + else + lua_pushstring(L, b); + lua_freeline(L, b); + return 1; +} + + +static int loadline (lua_State *L) { + int status; + lua_settop(L, 0); + if (!pushline(L, 1)) + return -1; /* no input */ + for (;;) { /* repeat until gets a complete line */ + status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin"); + if (!incomplete(L, status)) break; /* cannot try to add lines? */ + if (!pushline(L, 0)) /* no more input? */ + return -1; + lua_pushliteral(L, "\n"); /* add a new line... */ + lua_insert(L, -2); /* ...between the two lines */ + lua_concat(L, 3); /* join them */ + } + lua_saveline(L, 1); + lua_remove(L, 1); /* remove line */ + return status; +} + + +static void dotty (lua_State *L) { + int status; + const char *oldprogname = progname; + progname = NULL; + while ((status = loadline(L)) != -1) { + if (status == 0) status = docall(L, 0, 0); + report(L, status); + if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */ + lua_getglobal(L, "print"); + lua_insert(L, 1); + if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0) + l_message(progname, lua_pushfstring(L, + "error calling " LUA_QL("print") " (%s)", + lua_tostring(L, -1))); + } + } + lua_settop(L, 0); /* clear stack */ + fputs("\n", stdout); + fflush(stdout); + progname = oldprogname; +} + + +static int handle_script (lua_State *L, char **argv, int n) { + int status; + const char *fname; + int narg = getargs(L, argv, n); /* collect arguments */ + lua_setglobal(L, "arg"); + fname = argv[n]; + if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0) + fname = NULL; /* stdin */ + status = luaL_loadfile(L, fname); + lua_insert(L, -(narg+1)); + if (status == 0) + status = docall(L, narg, 0); + else + lua_pop(L, narg); + return report(L, status); +} + + +/* check that argument has no extra characters at the end */ +#define notail(x) {if ((x)[2] != '\0') return -1;} + + +static int collectargs (char **argv, int *pi, int *pv, int *pe) { + int i; + for (i = 1; argv[i] != NULL; i++) { + if (argv[i][0] != '-') /* not an option? */ + return i; + switch (argv[i][1]) { /* option */ + case '-': + notail(argv[i]); + return (argv[i+1] != NULL ? i+1 : 0); + case '\0': + return i; + case 'i': + notail(argv[i]); + *pi = 1; /* go through */ + case 'v': + notail(argv[i]); + *pv = 1; + break; + case 'e': + *pe = 1; /* go through */ + case 'l': + if (argv[i][2] == '\0') { + i++; + if (argv[i] == NULL) return -1; + } + break; + default: return -1; /* invalid option */ + } + } + return 0; +} + + +static int runargs (lua_State *L, char **argv, int n) { + int i; + for (i = 1; i < n; i++) { + if (argv[i] == NULL) continue; + lua_assert(argv[i][0] == '-'); + switch (argv[i][1]) { /* option */ + case 'e': { + const char *chunk = argv[i] + 2; + if (*chunk == '\0') chunk = argv[++i]; + lua_assert(chunk != NULL); + if (dostring(L, chunk, "=(command line)") != 0) + return 1; + break; + } + case 'l': { + const char *filename = argv[i] + 2; + if (*filename == '\0') filename = argv[++i]; + lua_assert(filename != NULL); + if (dolibrary(L, filename)) + return 1; /* stop if file fails */ + break; + } + default: break; + } + } + return 0; +} + + +static int handle_luainit (lua_State *L) { + const char *init = /*getenv(LUA_INIT)*/ NULL; + if (init == NULL) return 0; /* status OK */ + else if (init[0] == '@') + return dofile(L, init+1); + else + return dostring(L, init, "=" LUA_INIT); +} + + +struct Smain { + int argc; + char **argv; + int status; +}; + + +static int pmain (lua_State *L) { + struct Smain *s = (struct Smain *)lua_touserdata(L, 1); + char **argv = s->argv; + int script; + int has_i = 0, has_v = 0, has_e = 0; + globalL = L; + if (argv[0] && argv[0][0]) progname = argv[0]; + lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */ + luaL_openlibs(L); /* open libraries */ + lua_gc(L, LUA_GCRESTART, 0); + s->status = handle_luainit(L); + if (s->status != 0) return 0; + script = collectargs(argv, &has_i, &has_v, &has_e); + if (script < 0) { /* invalid args? */ + print_usage(); + s->status = 1; + return 0; + } + if (has_v) print_version(); + s->status = runargs(L, argv, (script > 0) ? script : s->argc); + if (s->status != 0) return 0; + if (script) + s->status = handle_script(L, argv, script); + if (s->status != 0) return 0; + if (has_i) + dotty(L); + else if (script == 0 && !has_e && !has_v) { + if (lua_stdin_is_tty()) { + print_version(); + dotty(L); + } + else dofile(L, NULL); /* executes stdin as a file */ + } + return 0; +} + + +int main (int argc, char **argv) { + int status; + struct Smain s; + + openconsole(&dev_stdcon_r, &dev_stdcon_w); + + lua_State *L = lua_open(); /* create state */ + if (L == NULL) { + l_message(argv[0], "cannot create state: not enough memory"); + return EXIT_FAILURE; + } + s.argc = argc; + s.argv = argv; + status = lua_cpcall(L, &pmain, &s); + report(L, status); + lua_close(L); + return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS; +} + diff --git a/contrib/syslinux-4.02/com32/lua/src/lua.h b/contrib/syslinux-4.02/com32/lua/src/lua.h new file mode 100644 index 0000000..3b325a9 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lua.h @@ -0,0 +1,391 @@ +/* +** $Id: lua.h,v 1.218.1.4 2008/01/03 15:41:15 roberto Exp $ +** Lua - An Extensible Extension Language +** Lua.org, PUC-Rio, Brazil (http://www.lua.org) +** See Copyright Notice at the end of this file +*/ + + +#ifndef lua_h +#define lua_h + +#include <stdarg.h> +#include <stddef.h> + + +#include "luaconf.h" + +#define feof(x) 0 +#define ferror(x) 0 + + +#define LUA_VERSION "Lua 5.1" +#define LUA_RELEASE "Lua 5.1.3" +#define LUA_VERSION_NUM 501 +#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio" +#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" + + +/* mark for precompiled code (`<esc>Lua') */ +#define LUA_SIGNATURE "\033Lua" + +/* option for multiple returns in `lua_pcall' and `lua_call' */ +#define LUA_MULTRET (-1) + + +/* +** pseudo-indices +*/ +#define LUA_REGISTRYINDEX (-10000) +#define LUA_ENVIRONINDEX (-10001) +#define LUA_GLOBALSINDEX (-10002) +#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) + + +/* thread status; 0 is OK */ +#define LUA_YIELD 1 +#define LUA_ERRRUN 2 +#define LUA_ERRSYNTAX 3 +#define LUA_ERRMEM 4 +#define LUA_ERRERR 5 + + +typedef struct lua_State lua_State; + +typedef int (*lua_CFunction) (lua_State *L); + + +/* +** functions that read/write blocks when loading/dumping Lua chunks +*/ +typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); + +typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud); + + +/* +** prototype for memory-allocation functions +*/ +typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); + + +/* +** basic types +*/ +#define LUA_TNONE (-1) + +#define LUA_TNIL 0 +#define LUA_TBOOLEAN 1 +#define LUA_TLIGHTUSERDATA 2 +#define LUA_TNUMBER 3 +#define LUA_TSTRING 4 +#define LUA_TTABLE 5 +#define LUA_TFUNCTION 6 +#define LUA_TUSERDATA 7 +#define LUA_TTHREAD 8 + + + +/* minimum Lua stack available to a C function */ +#define LUA_MINSTACK 20 + + +/* +** generic extra include file +*/ +#if defined(LUA_USER_H) +#include LUA_USER_H +#endif + + +/* type of numbers in Lua */ +typedef LUA_NUMBER lua_Number; + + +/* type for integer functions */ +typedef LUA_INTEGER lua_Integer; + + + +/* +** state manipulation +*/ +LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); +LUA_API void (lua_close) (lua_State *L); +LUA_API lua_State *(lua_newthread) (lua_State *L); + +LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); + + +/* +** basic stack manipulation +*/ +LUA_API int (lua_gettop) (lua_State *L); +LUA_API void (lua_settop) (lua_State *L, int idx); +LUA_API void (lua_pushvalue) (lua_State *L, int idx); +LUA_API void (lua_remove) (lua_State *L, int idx); +LUA_API void (lua_insert) (lua_State *L, int idx); +LUA_API void (lua_replace) (lua_State *L, int idx); +LUA_API int (lua_checkstack) (lua_State *L, int sz); + +LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); + + +/* +** access functions (stack -> C) +*/ + +LUA_API int (lua_isnumber) (lua_State *L, int idx); +LUA_API int (lua_isstring) (lua_State *L, int idx); +LUA_API int (lua_iscfunction) (lua_State *L, int idx); +LUA_API int (lua_isuserdata) (lua_State *L, int idx); +LUA_API int (lua_type) (lua_State *L, int idx); +LUA_API const char *(lua_typename) (lua_State *L, int tp); + +LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2); +LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); +LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2); + +LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx); +LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx); +LUA_API int (lua_toboolean) (lua_State *L, int idx); +LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); +LUA_API size_t (lua_objlen) (lua_State *L, int idx); +LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); +LUA_API void *(lua_touserdata) (lua_State *L, int idx); +LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); +LUA_API const void *(lua_topointer) (lua_State *L, int idx); + + +/* +** push functions (C -> stack) +*/ +LUA_API void (lua_pushnil) (lua_State *L); +LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); +LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); +LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l); +LUA_API void (lua_pushstring) (lua_State *L, const char *s); +LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, + va_list argp); +LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); +LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); +LUA_API void (lua_pushboolean) (lua_State *L, int b); +LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); +LUA_API int (lua_pushthread) (lua_State *L); + + +/* +** get functions (Lua -> stack) +*/ +LUA_API void (lua_gettable) (lua_State *L, int idx); +LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); +LUA_API void (lua_rawget) (lua_State *L, int idx); +LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n); +LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); +LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); +LUA_API int (lua_getmetatable) (lua_State *L, int objindex); +LUA_API void (lua_getfenv) (lua_State *L, int idx); + + +/* +** set functions (stack -> Lua) +*/ +LUA_API void (lua_settable) (lua_State *L, int idx); +LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); +LUA_API void (lua_rawset) (lua_State *L, int idx); +LUA_API void (lua_rawseti) (lua_State *L, int idx, int n); +LUA_API int (lua_setmetatable) (lua_State *L, int objindex); +LUA_API int (lua_setfenv) (lua_State *L, int idx); + + +/* +** `load' and `call' functions (load and run Lua code) +*/ +LUA_API void (lua_call) (lua_State *L, int nargs, int nresults); +LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); +LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud); +LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, + const char *chunkname); + +LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); + + +/* +** coroutine functions +*/ +LUA_API int (lua_yield) (lua_State *L, int nresults); +LUA_API int (lua_resume) (lua_State *L, int narg); +LUA_API int (lua_status) (lua_State *L); + +/* +** garbage-collection function and options +*/ + +#define LUA_GCSTOP 0 +#define LUA_GCRESTART 1 +#define LUA_GCCOLLECT 2 +#define LUA_GCCOUNT 3 +#define LUA_GCCOUNTB 4 +#define LUA_GCSTEP 5 +#define LUA_GCSETPAUSE 6 +#define LUA_GCSETSTEPMUL 7 + +LUA_API int (lua_gc) (lua_State *L, int what, int data); + + +/* +** miscellaneous functions +*/ + +LUA_API int (lua_error) (lua_State *L); + +LUA_API int (lua_next) (lua_State *L, int idx); + +LUA_API void (lua_concat) (lua_State *L, int n); + +LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); +LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); + + + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + +#define lua_pop(L,n) lua_settop(L, -(n)-1) + +#define lua_newtable(L) lua_createtable(L, 0, 0) + +#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) + +#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) + +#define lua_strlen(L,i) lua_objlen(L, (i)) + +#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) +#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) +#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) +#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) +#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) +#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) +#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) +#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) + +#define lua_pushliteral(L, s) \ + lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) + +#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s)) +#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s)) + +#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) + + + +/* +** compatibility macros and functions +*/ + +#define lua_open() luaL_newstate() + +#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX) + +#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0) + +#define lua_Chunkreader lua_Reader +#define lua_Chunkwriter lua_Writer + + +/* hack */ +LUA_API void lua_setlevel (lua_State *from, lua_State *to); + + +/* +** {====================================================================== +** Debug API +** ======================================================================= +*/ + + +/* +** Event codes +*/ +#define LUA_HOOKCALL 0 +#define LUA_HOOKRET 1 +#define LUA_HOOKLINE 2 +#define LUA_HOOKCOUNT 3 +#define LUA_HOOKTAILRET 4 + + +/* +** Event masks +*/ +#define LUA_MASKCALL (1 << LUA_HOOKCALL) +#define LUA_MASKRET (1 << LUA_HOOKRET) +#define LUA_MASKLINE (1 << LUA_HOOKLINE) +#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) + +typedef struct lua_Debug lua_Debug; /* activation record */ + + +/* Functions to be called by the debuger in specific events */ +typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); + + +LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar); +LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); +LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n); +LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n); + +LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count); +LUA_API lua_Hook lua_gethook (lua_State *L); +LUA_API int lua_gethookmask (lua_State *L); +LUA_API int lua_gethookcount (lua_State *L); + + +struct lua_Debug { + int event; + const char *name; /* (n) */ + const char *namewhat; /* (n) `global', `local', `field', `method' */ + const char *what; /* (S) `Lua', `C', `main', `tail' */ + const char *source; /* (S) */ + int currentline; /* (l) */ + int nups; /* (u) number of upvalues */ + int linedefined; /* (S) */ + int lastlinedefined; /* (S) */ + char short_src[LUA_IDSIZE]; /* (S) */ + /* private part */ + int i_ci; /* active function */ +}; + +/* }====================================================================== */ + + +/****************************************************************************** +* Copyright (C) 1994-2008 Lua.org, PUC-Rio. 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. +******************************************************************************/ + + +#endif diff --git a/contrib/syslinux-4.02/com32/lua/src/luac.c b/contrib/syslinux-4.02/com32/lua/src/luac.c new file mode 100644 index 0000000..d070173 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/luac.c @@ -0,0 +1,200 @@ +/* +** $Id: luac.c,v 1.54 2006/06/02 17:37:11 lhf Exp $ +** Lua compiler (saves bytecodes to files; also list bytecodes) +** See Copyright Notice in lua.h +*/ + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define luac_c +#define LUA_CORE + +#include "lua.h" +#include "lauxlib.h" + +#include "ldo.h" +#include "lfunc.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstring.h" +#include "lundump.h" + +#define PROGNAME "luac" /* default program name */ +#define OUTPUT PROGNAME ".out" /* default output file */ + +static int listing=0; /* list bytecodes? */ +static int dumping=1; /* dump bytecodes? */ +static int stripping=0; /* strip debug information? */ +static char Output[]={ OUTPUT }; /* default output file name */ +static const char* output=Output; /* actual output file name */ +static const char* progname=PROGNAME; /* actual program name */ + +static void fatal(const char* message) +{ + fprintf(stderr,"%s: %s\n",progname,message); + exit(EXIT_FAILURE); +} + +static void cannot(const char* what) +{ + fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno)); + exit(EXIT_FAILURE); +} + +static void usage(const char* message) +{ + if (*message=='-') + fprintf(stderr,"%s: unrecognized option " LUA_QS "\n",progname,message); + else + fprintf(stderr,"%s: %s\n",progname,message); + fprintf(stderr, + "usage: %s [options] [filenames].\n" + "Available options are:\n" + " - process stdin\n" + " -l list\n" + " -o name output to file " LUA_QL("name") " (default is \"%s\")\n" + " -p parse only\n" + " -s strip debug information\n" + " -v show version information\n" + " -- stop handling options\n", + progname,Output); + exit(EXIT_FAILURE); +} + +#define IS(s) (strcmp(argv[i],s)==0) + +static int doargs(int argc, char* argv[]) +{ + int i; + int version=0; + if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0]; + for (i=1; i<argc; i++) + { + if (*argv[i]!='-') /* end of options; keep it */ + break; + else if (IS("--")) /* end of options; skip it */ + { + ++i; + if (version) ++version; + break; + } + else if (IS("-")) /* end of options; use stdin */ + break; + else if (IS("-l")) /* list */ + ++listing; + else if (IS("-o")) /* output file */ + { + output=argv[++i]; + if (output==NULL || *output==0) usage(LUA_QL("-o") " needs argument"); + if (IS("-")) output=NULL; + } + else if (IS("-p")) /* parse only */ + dumping=0; + else if (IS("-s")) /* strip debug information */ + stripping=1; + else if (IS("-v")) /* show version */ + ++version; + else /* unknown option */ + usage(argv[i]); + } + if (i==argc && (listing || !dumping)) + { + dumping=0; + argv[--i]=Output; + } + if (version) + { + printf("%s %s\n",LUA_RELEASE,LUA_COPYRIGHT); + if (version==argc-1) exit(EXIT_SUCCESS); + } + return i; +} + +#define toproto(L,i) (clvalue(L->top+(i))->l.p) + +static const Proto* combine(lua_State* L, int n) +{ + if (n==1) + return toproto(L,-1); + else + { + int i,pc; + Proto* f=luaF_newproto(L); + setptvalue2s(L,L->top,f); incr_top(L); + f->source=luaS_newliteral(L,"=(" PROGNAME ")"); + f->maxstacksize=1; + pc=2*n+1; + f->code=luaM_newvector(L,pc,Instruction); + f->sizecode=pc; + f->p=luaM_newvector(L,n,Proto*); + f->sizep=n; + pc=0; + for (i=0; i<n; i++) + { + f->p[i]=toproto(L,i-n-1); + f->code[pc++]=CREATE_ABx(OP_CLOSURE,0,i); + f->code[pc++]=CREATE_ABC(OP_CALL,0,1,1); + } + f->code[pc++]=CREATE_ABC(OP_RETURN,0,1,0); + return f; + } +} + +static int writer(lua_State* L, const void* p, size_t size, void* u) +{ + UNUSED(L); + return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0); +} + +struct Smain { + int argc; + char** argv; +}; + +static int pmain(lua_State* L) +{ + struct Smain* s = (struct Smain*)lua_touserdata(L, 1); + int argc=s->argc; + char** argv=s->argv; + const Proto* f; + int i; + if (!lua_checkstack(L,argc)) fatal("too many input files"); + for (i=0; i<argc; i++) + { + const char* filename=IS("-") ? NULL : argv[i]; + if (luaL_loadfile(L,filename)!=0) fatal(lua_tostring(L,-1)); + } + f=combine(L,argc); + if (listing) luaU_print(f,listing>1); + if (dumping) + { + FILE* D= (output==NULL) ? stdout : fopen(output,"wb"); + if (D==NULL) cannot("open"); + lua_lock(L); + luaU_dump(L,f,writer,D,stripping); + lua_unlock(L); + if (ferror(D)) cannot("write"); + if (fclose(D)) cannot("close"); + } + return 0; +} + +int main(int argc, char* argv[]) +{ + lua_State* L; + struct Smain s; + int i=doargs(argc,argv); + argc-=i; argv+=i; + if (argc<=0) usage("no input files given"); + L=lua_open(); + if (L==NULL) fatal("not enough memory for state"); + s.argc=argc; + s.argv=argv; + if (lua_cpcall(L,pmain,&s)!=0) fatal(lua_tostring(L,-1)); + lua_close(L); + return EXIT_SUCCESS; +} diff --git a/contrib/syslinux-4.02/com32/lua/src/luaconf.h b/contrib/syslinux-4.02/com32/lua/src/luaconf.h new file mode 100644 index 0000000..d285251 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/luaconf.h @@ -0,0 +1,817 @@ +/* +** $Id: luaconf.h,v 1.82.1.6 2008/01/18 17:07:48 roberto Exp $ +** Configuration file for Lua +** See Copyright Notice in lua.h +*/ + + +#ifndef lconfig_h +#define lconfig_h + +#include <limits.h> +#include <stddef.h> + + +/* +** ================================================================== +** Search for "@@" to find all configurable definitions. +** =================================================================== +*/ + + +/* +@@ LUA_ANSI controls the use of non-ansi features. +** CHANGE it (define it) if you want Lua to avoid the use of any +** non-ansi feature or library. +*/ +#if defined(__STRICT_ANSI__) +#define LUA_ANSI +#endif + + +#if !defined(LUA_ANSI) && defined(_WIN32) +#define LUA_WIN +#endif + +#if defined(LUA_USE_LINUX) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ +#define LUA_USE_READLINE /* needs some extra libraries */ +#endif + +#if defined(LUA_USE_MACOSX) +#define LUA_USE_POSIX +#define LUA_DL_DYLD /* does not need extra library */ +#endif + + + +/* +@@ LUA_USE_POSIX includes all functionallity listed as X/Open System +@* Interfaces Extension (XSI). +** CHANGE it (define it) if your system is XSI compatible. +*/ +#if defined(LUA_USE_POSIX) +#define LUA_USE_MKSTEMP +#define LUA_USE_ISATTY +#define LUA_USE_POPEN +#define LUA_USE_ULONGJMP +#endif + + +/* +@@ LUA_PATH and LUA_CPATH are the names of the environment variables that +@* Lua check to set its paths. +@@ LUA_INIT is the name of the environment variable that Lua +@* checks for initialization code. +** CHANGE them if you want different names. +*/ +#define LUA_PATH "LUA_PATH" +#define LUA_CPATH "LUA_CPATH" +#define LUA_INIT "LUA_INIT" + + +/* +@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for +@* Lua libraries. +@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for +@* C libraries. +** CHANGE them if your machine has a non-conventional directory +** hierarchy or if you want to install your libraries in +** non-conventional directories. +*/ +#if defined(_WIN32) +/* +** In Windows, any exclamation mark ('!') in the path is replaced by the +** path of the directory of the executable file of the current process. +*/ +#define LUA_LDIR "!\\lua\\" +#define LUA_CDIR "!\\" +#define LUA_PATH_DEFAULT \ + ".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua" +#define LUA_CPATH_DEFAULT \ + ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll" + +#else +#define LUA_ROOT "/usr/local/" +#define LUA_LDIR LUA_ROOT "share/lua/5.1/" +#define LUA_CDIR LUA_ROOT "lib/lua/5.1/" +#define LUA_PATH_DEFAULT \ + "./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua" +#define LUA_CPATH_DEFAULT \ + "./?.so;" LUA_CDIR"?.so;" LUA_CDIR"loadall.so" +#endif + + +/* +@@ LUA_DIRSEP is the directory separator (for submodules). +** CHANGE it if your machine does not use "/" as the directory separator +** and is not Windows. (On Windows Lua automatically uses "\".) +*/ +#if defined(_WIN32) +#define LUA_DIRSEP "\\" +#else +#define LUA_DIRSEP "/" +#endif + + +/* +@@ LUA_PATHSEP is the character that separates templates in a path. +@@ LUA_PATH_MARK is the string that marks the substitution points in a +@* template. +@@ LUA_EXECDIR in a Windows path is replaced by the executable's +@* directory. +@@ LUA_IGMARK is a mark to ignore all before it when bulding the +@* luaopen_ function name. +** CHANGE them if for some reason your system cannot use those +** characters. (E.g., if one of those characters is a common character +** in file/directory names.) Probably you do not need to change them. +*/ +#define LUA_PATHSEP ";" +#define LUA_PATH_MARK "?" +#define LUA_EXECDIR "!" +#define LUA_IGMARK "-" + + +/* +@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger. +** CHANGE that if ptrdiff_t is not adequate on your machine. (On most +** machines, ptrdiff_t gives a good choice between int or long.) +*/ + +/* Changed to long for use with integral Lua numbers. */ +#define LUA_INTEGER long + +/* +@@ LUA_API is a mark for all core API functions. +@@ LUALIB_API is a mark for all standard library functions. +** CHANGE them if you need to define those functions in some special way. +** For instance, if you want to create one Windows DLL with the core and +** the libraries, you may want to use the following definition (define +** LUA_BUILD_AS_DLL to get it). +*/ +#if defined(LUA_BUILD_AS_DLL) + +#if defined(LUA_CORE) || defined(LUA_LIB) +#define LUA_API __declspec(dllexport) +#else +#define LUA_API __declspec(dllimport) +#endif + +#else + +#define LUA_API extern + +#endif + +/* more often than not the libs go together with the core */ +#define LUALIB_API LUA_API + + +/* +@@ LUAI_FUNC is a mark for all extern functions that are not to be +@* exported to outside modules. +@@ LUAI_DATA is a mark for all extern (const) variables that are not to +@* be exported to outside modules. +** CHANGE them if you need to mark them in some special way. Elf/gcc +** (versions 3.2 and later) mark them as "hidden" to optimize access +** when Lua is compiled as a shared library. +*/ +#if defined(luaall_c) +#define LUAI_FUNC static +#define LUAI_DATA /* empty */ + +#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ + defined(__ELF__) +#define LUAI_FUNC __attribute__((visibility("hidden"))) extern +#define LUAI_DATA LUAI_FUNC + +#else +#define LUAI_FUNC extern +#define LUAI_DATA extern +#endif + + + +/* +@@ LUA_QL describes how error messages quote program elements. +** CHANGE it if you want a different appearance. +*/ +#define LUA_QL(x) "'" x "'" +#define LUA_QS LUA_QL("%s") + + +/* +@@ LUA_IDSIZE gives the maximum size for the description of the source +@* of a function in debug information. +** CHANGE it if you want a different size. +*/ +#define LUA_IDSIZE 60 + + +/* +** {================================================================== +** Stand-alone configuration +** =================================================================== +*/ + +#if defined(lua_c) || defined(luaall_c) + +/* +@@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that +@* is, whether we're running lua interactively). +** CHANGE it if you have a better definition for non-POSIX/non-Windows +** systems. +*/ +#if defined(LUA_USE_ISATTY) +#include <unistd.h> +#define lua_stdin_is_tty() isatty(0) +#elif defined(LUA_WIN) +#include <io.h> +#include <stdio.h> +#define lua_stdin_is_tty() _isatty(_fileno(stdin)) +#else +#define lua_stdin_is_tty() 1 /* assume stdin is a tty */ +#endif + + +/* +@@ LUA_PROMPT is the default prompt used by stand-alone Lua. +@@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua. +** CHANGE them if you want different prompts. (You can also change the +** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.) +*/ +#define LUA_PROMPT "> " +#define LUA_PROMPT2 ">> " + + +/* +@@ LUA_PROGNAME is the default name for the stand-alone Lua program. +** CHANGE it if your stand-alone interpreter has a different name and +** your system is not able to detect that name automatically. +*/ +#define LUA_PROGNAME "lua" + + +/* +@@ LUA_MAXINPUT is the maximum length for an input line in the +@* stand-alone interpreter. +** CHANGE it if you need longer lines. +*/ +#define LUA_MAXINPUT 512 + + +/* +@@ lua_readline defines how to show a prompt and then read a line from +@* the standard input. +@@ lua_saveline defines how to "save" a read line in a "history". +@@ lua_freeline defines how to free a line read by lua_readline. +** CHANGE them if you want to improve this functionality (e.g., by using +** GNU readline and history facilities). +*/ +#if defined(LUA_USE_READLINE) +#include <stdio.h> +#include <readline/readline.h> +#include <readline/history.h> +#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) +#define lua_saveline(L,idx) \ + if (lua_strlen(L,idx) > 0) /* non-empty line? */ \ + add_history(lua_tostring(L, idx)); /* add it to history */ +#define lua_freeline(L,b) ((void)L, free(b)) +#else +#define lua_readline(L,b,p) \ + ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ + fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ +#define lua_saveline(L,idx) { (void)L; (void)idx; } +#define lua_freeline(L,b) { (void)L; (void)b; } +#endif + +#endif + +/* }================================================================== */ + + +/* +@@ LUAI_GCPAUSE defines the default pause between garbage-collector cycles +@* as a percentage. +** CHANGE it if you want the GC to run faster or slower (higher values +** mean larger pauses which mean slower collection.) You can also change +** this value dynamically. +*/ +#define LUAI_GCPAUSE 200 /* 200% (wait memory to double before next GC) */ + + +/* +@@ LUAI_GCMUL defines the default speed of garbage collection relative to +@* memory allocation as a percentage. +** CHANGE it if you want to change the granularity of the garbage +** collection. (Higher values mean coarser collections. 0 represents +** infinity, where each step performs a full collection.) You can also +** change this value dynamically. +*/ +#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ + + + +/* +@@ LUA_COMPAT_GETN controls compatibility with old getn behavior. +** CHANGE it (define it) if you want exact compatibility with the +** behavior of setn/getn in Lua 5.0. +*/ +#undef LUA_COMPAT_GETN + +/* +@@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib. +** CHANGE it to undefined as soon as you do not need a global 'loadlib' +** function (the function is still available as 'package.loadlib'). +*/ +#undef LUA_COMPAT_LOADLIB + +/* +@@ LUA_COMPAT_VARARG controls compatibility with old vararg feature. +** CHANGE it to undefined as soon as your programs use only '...' to +** access vararg parameters (instead of the old 'arg' table). +*/ +#define LUA_COMPAT_VARARG + +/* +@@ LUA_COMPAT_MOD controls compatibility with old math.mod function. +** CHANGE it to undefined as soon as your programs use 'math.fmod' or +** the new '%' operator instead of 'math.mod'. +*/ +#define LUA_COMPAT_MOD + +/* +@@ LUA_COMPAT_LSTR controls compatibility with old long string nesting +@* facility. +** CHANGE it to 2 if you want the old behaviour, or undefine it to turn +** off the advisory error when nesting [[...]]. +*/ +#define LUA_COMPAT_LSTR 1 + +/* +@@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name. +** CHANGE it to undefined as soon as you rename 'string.gfind' to +** 'string.gmatch'. +*/ +#define LUA_COMPAT_GFIND + +/* +@@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib' +@* behavior. +** CHANGE it to undefined as soon as you replace to 'luaL_register' +** your uses of 'luaL_openlib' +*/ +#define LUA_COMPAT_OPENLIB + + + +/* +@@ luai_apicheck is the assert macro used by the Lua-C API. +** CHANGE luai_apicheck if you want Lua to perform some checks in the +** parameters it gets from API calls. This may slow down the interpreter +** a bit, but may be quite useful when debugging C code that interfaces +** with Lua. A useful redefinition is to use assert.h. +*/ +#if defined(LUA_USE_APICHECK) +#include <assert.h> +#define luai_apicheck(L,o) { (void)L; assert(o); } +#else +#define luai_apicheck(L,o) { (void)L; } +#endif + + +/* +@@ LUAI_BITSINT defines the number of bits in an int. +** CHANGE here if Lua cannot automatically detect the number of bits of +** your machine. Probably you do not need to change this. +*/ +/* avoid overflows in comparison */ +#if INT_MAX-20 < 32760 +#define LUAI_BITSINT 16 +#elif INT_MAX > 2147483640L +/* int has at least 32 bits */ +#define LUAI_BITSINT 32 +#else +#error "you must define LUA_BITSINT with number of bits in an integer" +#endif + + +/* +@@ LUAI_UINT32 is an unsigned integer with at least 32 bits. +@@ LUAI_INT32 is an signed integer with at least 32 bits. +@@ LUAI_UMEM is an unsigned integer big enough to count the total +@* memory used by Lua. +@@ LUAI_MEM is a signed integer big enough to count the total memory +@* used by Lua. +** CHANGE here if for some weird reason the default definitions are not +** good enough for your machine. (The definitions in the 'else' +** part always works, but may waste space on machines with 64-bit +** longs.) Probably you do not need to change this. +*/ +#if LUAI_BITSINT >= 32 +#define LUAI_UINT32 unsigned int +#define LUAI_INT32 int +#define LUAI_MAXINT32 INT_MAX +#define LUAI_UMEM size_t +#define LUAI_MEM ptrdiff_t +#else +/* 16-bit ints */ +#define LUAI_UINT32 unsigned long +#define LUAI_INT32 long +#define LUAI_MAXINT32 LONG_MAX +#define LUAI_UMEM unsigned long +#define LUAI_MEM long +#endif + + +/* +@@ LUAI_MAXCALLS limits the number of nested calls. +** CHANGE it if you need really deep recursive calls. This limit is +** arbitrary; its only purpose is to stop infinite recursion before +** exhausting memory. +*/ +#define LUAI_MAXCALLS 20000 + + +/* +@@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function +@* can use. +** CHANGE it if you need lots of (Lua) stack space for your C +** functions. This limit is arbitrary; its only purpose is to stop C +** functions to consume unlimited stack space. +*/ +#define LUAI_MCS_AUX ((int)(INT_MAX / (4*sizeof(LUA_NUMBER)))) +#define LUAI_MAXCSTACK (LUAI_MCS_AUX > SHRT_MAX ? SHRT_MAX : LUAI_MCS_AUX) + + + +/* +** {================================================================== +** CHANGE (to smaller values) the following definitions if your system +** has a small C stack. (Or you may want to change them to larger +** values if your system has a large C stack and these limits are +** too rigid for you.) Some of these constants control the size of +** stack-allocated arrays used by the compiler or the interpreter, while +** others limit the maximum number of recursive calls that the compiler +** or the interpreter can perform. Values too large may cause a C stack +** overflow for some forms of deep constructs. +** =================================================================== +*/ + + +/* +@@ LUAI_MAXCCALLS is the maximum depth for nested C calls (short) and +@* syntactical nested non-terminals in a program. +*/ +#define LUAI_MAXCCALLS 200 + + +/* +@@ LUAI_MAXVARS is the maximum number of local variables per function +@* (must be smaller than 250). +*/ +#define LUAI_MAXVARS 200 + + +/* +@@ LUAI_MAXUPVALUES is the maximum number of upvalues per function +@* (must be smaller than 250). +*/ +#define LUAI_MAXUPVALUES 60 + + +/* +@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. +*/ +#define LUAL_BUFFERSIZE BUFSIZ + +/* }================================================================== */ + + + + +/* +** {================================================================== +@@ LUA_NUMBER is the type of numbers in Lua. +** CHANGE the following definitions only if you want to build Lua +** with a number type different from double. You may also need to +** change lua_number2int & lua_number2integer. +** =================================================================== +*/ + +/* Define LUA_NUMBER_INTEGRAL to produce a system that uses no + floating point operations by changing the type of Lua numbers from + double to long. It implements division and modulus so that + + x == (x / y) * y + x % y. + + The exponentiation function returns zero for negative exponents. + Defining LUA_NUMBER_INTEGRAL also removes the difftime function, + and the math module should not be used. The string.format function + no longer handles the floating point directives %e, %E, %f, %g, and + %G. */ + +#define LUA_NUMBER_INTEGRAL +#if defined LUA_NUMBER_INTEGRAL +#define LUA_NUMBER long +#else +#define LUA_NUMBER_DOUBLE +#define LUA_NUMBER double +#endif + +/* +@@ LUAI_UACNUMBER is the result of an 'usual argument conversion' +@* over a number. +*/ +#define LUAI_UACNUMBER LUA_NUMBER + + +/* +@@ LUA_NUMBER_SCAN is the format for reading numbers. +@@ LUA_NUMBER_FMT is the format for writing numbers. +@@ lua_number2str converts a number to a string. +@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. +@@ lua_str2number converts a string to a number. +*/ +#if defined LUA_NUMBER_INTEGRAL +#define LUA_NUMBER_SCAN "%ld" +#define LUA_NUMBER_FMT "%ld" +#else +#define LUA_NUMBER_SCAN "%lf" +#define LUA_NUMBER_FMT "%.14g" +#endif +#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) +#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ +#if defined LUA_NUMBER_INTEGRAL +#define lua_str2number(s,p) strtol((s), (p), 10) +#else +#define lua_str2number(s,p) strtod((s), (p)) +#endif + + +/* +@@ The luai_num* macros define the primitive operations over numbers. +*/ +#if defined(LUA_CORE) +#include <math.h> +#define luai_numadd(a,b) ((a)+(b)) +#define luai_numsub(a,b) ((a)-(b)) +#define luai_nummul(a,b) ((a)*(b)) +#if defined LUA_NUMBER_INTEGRAL +#define luai_numdiv(a,b) \ + (-1/2? \ + (a)/(b): \ + (((a)<0)==((b)<0)||(a)%(b)==0? \ + (a)/(b): \ + (a)/(b)-1)) +#define luai_nummod(a,b) \ + (-1/2? \ + (a)%(b): \ + (((a)<0)==((b)<0)||(a)%(b)==0? \ + (a)%(b): \ + (a)%(b)+(b))) +#define luai_lnumdiv(a,b) \ + ((b)==0? \ + (luaG_runerror(L,"divide by zero"),0): \ + luai_numdiv(a,b)) +#define luai_lnummod(a,b) \ + ((b)==0? \ + (luaG_runerror(L,"modulo by zero"),0): \ + luai_nummod(a,b)) +LUA_NUMBER luai_ipow(LUA_NUMBER, LUA_NUMBER); +#define luai_numpow(a,b) (luai_ipow(a,b)) +#else +#define luai_numdiv(a,b) ((a)/(b)) +#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b)) +#define luai_lnumdiv(a,b) (luai_numdiv(a,b)) +#define luai_lnummod(a,b) (luai_nummod(a,b)) +#define luai_numpow(a,b) (pow(a,b)) +#endif +#define luai_numunm(a) (-(a)) +#define luai_numeq(a,b) ((a)==(b)) +#define luai_numlt(a,b) ((a)<(b)) +#define luai_numle(a,b) ((a)<=(b)) +#define luai_numisnan(a) (!luai_numeq((a), (a))) +#endif + + +/* +@@ lua_number2int is a macro to convert lua_Number to int. +@@ lua_number2integer is a macro to convert lua_Number to lua_Integer. +** CHANGE them if you know a faster way to convert a lua_Number to +** int (with any rounding method and without throwing errors) in your +** system. In Pentium machines, a naive typecast from double to int +** in C is extremely slow, so any alternative is worth trying. +*/ + +/* On a Pentium, resort to a trick */ +#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \ + (defined(__i386) || defined (_M_IX86) || defined(__i386__)) + +/* On a Microsoft compiler, use assembler */ +#if defined(_MSC_VER) + +#define lua_number2int(i,d) __asm fld d __asm fistp i +#define lua_number2integer(i,n) lua_number2int(i, n) + +/* the next trick should work on any Pentium, but sometimes clashes + with a DirectX idiosyncrasy */ +#else + +union luai_Cast { double l_d; long l_l; }; +#define lua_number2int(i,d) \ + { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; } +#define lua_number2integer(i,n) lua_number2int(i, n) + +#endif + + +/* this option always works, but may be slow */ +#else +#define lua_number2int(i,d) ((i)=(int)(d)) +#define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) + +#endif + +/* }================================================================== */ + + +/* +@@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment. +** CHANGE it if your system requires alignments larger than double. (For +** instance, if your system supports long doubles and they must be +** aligned in 16-byte boundaries, then you should add long double in the +** union.) Probably you do not need to change this. +*/ +#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; } + + +/* +@@ LUAI_THROW/LUAI_TRY define how Lua does exception handling. +** CHANGE them if you prefer to use longjmp/setjmp even with C++ +** or if want/don't to use _longjmp/_setjmp instead of regular +** longjmp/setjmp. By default, Lua handles errors with exceptions when +** compiling as C++ code, with _longjmp/_setjmp when asked to use them, +** and with longjmp/setjmp otherwise. +*/ +#if defined(__cplusplus) +/* C++ exceptions */ +#define LUAI_THROW(L,c) throw(c) +#define LUAI_TRY(L,c,a) try { a } catch(...) \ + { if ((c)->status == 0) (c)->status = -1; } +#define luai_jmpbuf int /* dummy variable */ + +#elif defined(LUA_USE_ULONGJMP) +/* in Unix, try _longjmp/_setjmp (more efficient) */ +#define LUAI_THROW(L,c) _longjmp((c)->b, 1) +#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } +#define luai_jmpbuf jmp_buf + +#else +/* default handling with long jumps */ +#define LUAI_THROW(L,c) longjmp((c)->b, 1) +#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } +#define luai_jmpbuf jmp_buf + +#endif + + +/* +@@ LUA_MAXCAPTURES is the maximum number of captures that a pattern +@* can do during pattern-matching. +** CHANGE it if you need more captures. This limit is arbitrary. +*/ +#define LUA_MAXCAPTURES 32 + + +/* +@@ lua_tmpnam is the function that the OS library uses to create a +@* temporary name. +@@ LUA_TMPNAMBUFSIZE is the maximum size of a name created by lua_tmpnam. +** CHANGE them if you have an alternative to tmpnam (which is considered +** insecure) or if you want the original tmpnam anyway. By default, Lua +** uses tmpnam except when POSIX is available, where it uses mkstemp. +*/ +#if defined(loslib_c) || defined(luaall_c) + +#if defined(LUA_USE_MKSTEMP) +#include <unistd.h> +#define LUA_TMPNAMBUFSIZE 32 +#define lua_tmpnam(b,e) { \ + strcpy(b, "/tmp/lua_XXXXXX"); \ + e = mkstemp(b); \ + if (e != -1) close(e); \ + e = (e == -1); } + +#else +#define LUA_TMPNAMBUFSIZE L_tmpnam +#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } +#endif + +#endif + + +/* +@@ lua_popen spawns a new process connected to the current one through +@* the file streams. +** CHANGE it if you have a way to implement it in your system. +*/ +#if defined(LUA_USE_POPEN) + +#define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) +#define lua_pclose(L,file) ((void)L, (pclose(file) != -1)) + +#elif defined(LUA_WIN) + +#define lua_popen(L,c,m) ((void)L, _popen(c,m)) +#define lua_pclose(L,file) ((void)L, (_pclose(file) != -1)) + +#else + +#define lua_popen(L,c,m) ((void)((void)c, m), \ + luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) +#define lua_pclose(L,file) ((void)((void)L, file), 0) + +#endif + +/* +@@ LUA_DL_* define which dynamic-library system Lua should use. +** CHANGE here if Lua has problems choosing the appropriate +** dynamic-library system for your platform (either Windows' DLL, Mac's +** dyld, or Unix's dlopen). If your system is some kind of Unix, there +** is a good chance that it has dlopen, so LUA_DL_DLOPEN will work for +** it. To use dlopen you also need to adapt the src/Makefile (probably +** adding -ldl to the linker options), so Lua does not select it +** automatically. (When you change the makefile to add -ldl, you must +** also add -DLUA_USE_DLOPEN.) +** If you do not want any kind of dynamic library, undefine all these +** options. +** By default, _WIN32 gets LUA_DL_DLL and MAC OS X gets LUA_DL_DYLD. +*/ +#if defined(LUA_USE_DLOPEN) +#define LUA_DL_DLOPEN +#endif + +#if defined(LUA_WIN) +#define LUA_DL_DLL +#endif + + +/* +@@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State +@* (the data goes just *before* the lua_State pointer). +** CHANGE (define) this if you really need that. This value must be +** a multiple of the maximum alignment required for your machine. +*/ +#define LUAI_EXTRASPACE 0 + + +/* +@@ luai_userstate* allow user-specific actions on threads. +** CHANGE them if you defined LUAI_EXTRASPACE and need to do something +** extra when a thread is created/deleted/resumed/yielded. +*/ +#define luai_userstateopen(L) ((void)L) +#define luai_userstateclose(L) ((void)L) +#define luai_userstatethread(L,L1) ((void)L) +#define luai_userstatefree(L) ((void)L) +#define luai_userstateresume(L,n) ((void)L) +#define luai_userstateyield(L,n) ((void)L) + + +/* +@@ LUA_INTFRMLEN is the length modifier for integer conversions +@* in 'string.format'. +@@ LUA_INTFRM_T is the integer type correspoding to the previous length +@* modifier. +** CHANGE them if your system supports long long or does not support long. +*/ + +#if defined(LUA_USELONGLONG) + +#define LUA_INTFRMLEN "ll" +#define LUA_INTFRM_T long long + +#else + +#define LUA_INTFRMLEN "l" +#define LUA_INTFRM_T long + +#endif + + + +/* =================================================================== */ + +/* +** Local configuration. You can use this space to add your redefinitions +** without modifying the main part of the file. +*/ + + + +#endif + diff --git a/contrib/syslinux-4.02/com32/lua/src/lualib.h b/contrib/syslinux-4.02/com32/lua/src/lualib.h new file mode 100644 index 0000000..e169a0f --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lualib.h @@ -0,0 +1,65 @@ +/* +** $Id: lualib.h,v 1.36.1.1 2007/12/27 13:02:25 roberto Exp $ +** Lua standard libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lualib_h +#define lualib_h + +#include "lua.h" + + +/* Key to file-handle type */ +#define LUA_FILEHANDLE "FILE*" + + +#define LUA_COLIBNAME "coroutine" +LUALIB_API int (luaopen_base) (lua_State *L); + +#define LUA_TABLIBNAME "table" +LUALIB_API int (luaopen_table) (lua_State *L); + +#define LUA_IOLIBNAME "io" +LUALIB_API int (luaopen_io) (lua_State *L); + +#define LUA_OSLIBNAME "os" +LUALIB_API int (luaopen_os) (lua_State *L); + +#define LUA_STRLIBNAME "string" +LUALIB_API int (luaopen_string) (lua_State *L); + +#define LUA_MATHLIBNAME "math" +LUALIB_API int (luaopen_math) (lua_State *L); + +#define LUA_PCILIBNAME "pci" +LUALIB_API int (luaopen_pci) (lua_State *L); + +#define LUA_DBLIBNAME "debug" +LUALIB_API int (luaopen_debug) (lua_State *L); + +#define LUA_LOADLIBNAME "package" +LUALIB_API int (luaopen_package) (lua_State *L); + +#define LUA_SYSLINUXLIBNAME "syslinux" +LUALIB_API int (luaopen_syslinux) (lua_State *L); + +#define LUA_DMILIBNAME "dmi" +LUALIB_API int (luaopen_dmi) (lua_State *L); + +#define LUA_VESALIBNAME "vesa" +LUALIB_API int (luaopen_vesa) (lua_State *L); + + +/* open all previous libraries */ +LUALIB_API void (luaL_openlibs) (lua_State *L); + + + +#ifndef lua_assert +#define lua_assert(x) ((void)0) +#endif + + +#endif diff --git a/contrib/syslinux-4.02/com32/lua/src/lundump.c b/contrib/syslinux-4.02/com32/lua/src/lundump.c new file mode 100644 index 0000000..731c064 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lundump.c @@ -0,0 +1,225 @@ +/* +** $Id: lundump.c,v 2.7.1.2 2008/01/18 16:39:11 roberto Exp $ +** load precompiled Lua chunks +** See Copyright Notice in lua.h +*/ + +#include <string.h> + +#define lundump_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstring.h" +#include "lundump.h" +#include "lzio.h" + +typedef struct { + lua_State* L; + ZIO* Z; + Mbuffer* b; + const char* name; +} LoadState; + +#ifdef LUAC_TRUST_BINARIES +#define IF(c,s) +#define error(S,s) +#else +#define IF(c,s) if (c) error(S,s) + +static void error(LoadState* S, const char* why) +{ + luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why); + luaD_throw(S->L,LUA_ERRSYNTAX); +} +#endif + +#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) +#define LoadByte(S) (lu_byte)LoadChar(S) +#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) +#define LoadVector(S,b,n,size) LoadMem(S,b,n,size) + +static void LoadBlock(LoadState* S, void* b, size_t size) +{ + size_t r=luaZ_read(S->Z,b,size); + UNUSED(r); + IF (r!=0, "unexpected end"); +} + +static int LoadChar(LoadState* S) +{ + char x; + LoadVar(S,x); + return x; +} + +static int LoadInt(LoadState* S) +{ + int x; + LoadVar(S,x); + IF (x<0, "bad integer"); + return x; +} + +static lua_Number LoadNumber(LoadState* S) +{ + lua_Number x; + LoadVar(S,x); + return x; +} + +static TString* LoadString(LoadState* S) +{ + size_t size; + LoadVar(S,size); + if (size==0) + return NULL; + else + { + char* s=luaZ_openspace(S->L,S->b,size); + LoadBlock(S,s,size); + return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ + } +} + +static void LoadCode(LoadState* S, Proto* f) +{ + int n=LoadInt(S); + f->code=luaM_newvector(S->L,n,Instruction); + f->sizecode=n; + LoadVector(S,f->code,n,sizeof(Instruction)); +} + +static Proto* LoadFunction(LoadState* S, TString* p); + +static void LoadConstants(LoadState* S, Proto* f) +{ + int i,n; + n=LoadInt(S); + f->k=luaM_newvector(S->L,n,TValue); + f->sizek=n; + for (i=0; i<n; i++) setnilvalue(&f->k[i]); + for (i=0; i<n; i++) + { + TValue* o=&f->k[i]; + int t=LoadChar(S); + switch (t) + { + case LUA_TNIL: + setnilvalue(o); + break; + case LUA_TBOOLEAN: + setbvalue(o,LoadChar(S)); + break; + case LUA_TNUMBER: + setnvalue(o,LoadNumber(S)); + break; + case LUA_TSTRING: + setsvalue2n(S->L,o,LoadString(S)); + break; + default: + error(S,"bad constant"); + break; + } + } + n=LoadInt(S); + f->p=luaM_newvector(S->L,n,Proto*); + f->sizep=n; + for (i=0; i<n; i++) f->p[i]=NULL; + for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source); +} + +static void LoadDebug(LoadState* S, Proto* f) +{ + int i,n; + n=LoadInt(S); + f->lineinfo=luaM_newvector(S->L,n,int); + f->sizelineinfo=n; + LoadVector(S,f->lineinfo,n,sizeof(int)); + n=LoadInt(S); + f->locvars=luaM_newvector(S->L,n,LocVar); + f->sizelocvars=n; + for (i=0; i<n; i++) f->locvars[i].varname=NULL; + for (i=0; i<n; i++) + { + f->locvars[i].varname=LoadString(S); + f->locvars[i].startpc=LoadInt(S); + f->locvars[i].endpc=LoadInt(S); + } + n=LoadInt(S); + f->upvalues=luaM_newvector(S->L,n,TString*); + f->sizeupvalues=n; + for (i=0; i<n; i++) f->upvalues[i]=NULL; + for (i=0; i<n; i++) f->upvalues[i]=LoadString(S); +} + +static Proto* LoadFunction(LoadState* S, TString* p) +{ + Proto* f=luaF_newproto(S->L); + setptvalue2s(S->L,S->L->top,f); incr_top(S->L); + f->source=LoadString(S); if (f->source==NULL) f->source=p; + f->linedefined=LoadInt(S); + f->lastlinedefined=LoadInt(S); + f->nups=LoadByte(S); + f->numparams=LoadByte(S); + f->is_vararg=LoadByte(S); + f->maxstacksize=LoadByte(S); + LoadCode(S,f); + LoadConstants(S,f); + LoadDebug(S,f); + IF (!luaG_checkcode(f), "bad code"); + S->L->top--; + return f; +} + +static void LoadHeader(LoadState* S) +{ + char h[LUAC_HEADERSIZE]; + char s[LUAC_HEADERSIZE]; + luaU_header(h); + LoadBlock(S,s,LUAC_HEADERSIZE); + IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header"); +} + +/* +** load precompiled chunk +*/ +Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name) +{ + LoadState S; + if (*name=='@' || *name=='=') + S.name=name+1; + else if (*name==LUA_SIGNATURE[0]) + S.name="binary string"; + else + S.name=name; + S.L=L; + S.Z=Z; + S.b=buff; + LoadHeader(&S); + return LoadFunction(&S,luaS_newliteral(L,"=?")); +} + +/* +* make header +*/ +void luaU_header (char* h) +{ + int x=1; + memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1); + h+=sizeof(LUA_SIGNATURE)-1; + *h++=(char)LUAC_VERSION; + *h++=(char)LUAC_FORMAT; + *h++=(char)*(char*)&x; /* endianness */ + *h++=(char)sizeof(int); + *h++=(char)sizeof(size_t); + *h++=(char)sizeof(Instruction); + *h++=(char)sizeof(lua_Number); + *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */ +} diff --git a/contrib/syslinux-4.02/com32/lua/src/lundump.h b/contrib/syslinux-4.02/com32/lua/src/lundump.h new file mode 100644 index 0000000..c80189d --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lundump.h @@ -0,0 +1,36 @@ +/* +** $Id: lundump.h,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ +** load precompiled Lua chunks +** See Copyright Notice in lua.h +*/ + +#ifndef lundump_h +#define lundump_h + +#include "lobject.h" +#include "lzio.h" + +/* load one chunk; from lundump.c */ +LUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name); + +/* make header; from lundump.c */ +LUAI_FUNC void luaU_header (char* h); + +/* dump one chunk; from ldump.c */ +LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip); + +#ifdef luac_c +/* print one chunk; from print.c */ +LUAI_FUNC void luaU_print (const Proto* f, int full); +#endif + +/* for header of binary files -- this is Lua 5.1 */ +#define LUAC_VERSION 0x51 + +/* for header of binary files -- this is the official format */ +#define LUAC_FORMAT 0 + +/* size of header of binary files */ +#define LUAC_HEADERSIZE 12 + +#endif diff --git a/contrib/syslinux-4.02/com32/lua/src/lvm.c b/contrib/syslinux-4.02/com32/lua/src/lvm.c new file mode 100644 index 0000000..e65ccc8 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lvm.c @@ -0,0 +1,783 @@ +/* +** $Id: lvm.c,v 2.63.1.3 2007/12/28 15:32:23 roberto Exp $ +** Lua virtual machine +** See Copyright Notice in lua.h +*/ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define lvm_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lvm.h" + + +#if defined LUA_NUMBER_INTEGRAL +LUA_NUMBER luai_ipow(LUA_NUMBER a, LUA_NUMBER b) { + if (b < 0) + return 0; + else if (b == 0) + return 1; + else { + LUA_NUMBER c = 1; + for (;;) { + if (b & 1) + c *= a; + b = b >> 1; + if (b == 0) + return c; + a *= a; + } + } +} +#endif + +/* limit for table tag-method chains (to avoid loops) */ +#define MAXTAGLOOP 100 + + +const TValue *luaV_tonumber (const TValue *obj, TValue *n) { + lua_Number num; + if (ttisnumber(obj)) return obj; + if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) { + setnvalue(n, num); + return n; + } + else + return NULL; +} + + +int luaV_tostring (lua_State *L, StkId obj) { + if (!ttisnumber(obj)) + return 0; + else { + char s[LUAI_MAXNUMBER2STR]; + lua_Number n = nvalue(obj); + lua_number2str(s, n); + setsvalue2s(L, obj, luaS_new(L, s)); + return 1; + } +} + + +static void traceexec (lua_State *L, const Instruction *pc) { + lu_byte mask = L->hookmask; + const Instruction *oldpc = L->savedpc; + L->savedpc = pc; + if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) { + resethookcount(L); + luaD_callhook(L, LUA_HOOKCOUNT, -1); + } + if (mask & LUA_MASKLINE) { + Proto *p = ci_func(L->ci)->l.p; + int npc = pcRel(pc, p); + int newline = getline(p, npc); + /* call linehook when enter a new function, when jump back (loop), + or when enter a new line */ + if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p))) + luaD_callhook(L, LUA_HOOKLINE, newline); + } +} + + +static void callTMres (lua_State *L, StkId res, const TValue *f, + const TValue *p1, const TValue *p2) { + ptrdiff_t result = savestack(L, res); + setobj2s(L, L->top, f); /* push function */ + setobj2s(L, L->top+1, p1); /* 1st argument */ + setobj2s(L, L->top+2, p2); /* 2nd argument */ + luaD_checkstack(L, 3); + L->top += 3; + luaD_call(L, L->top - 3, 1); + res = restorestack(L, result); + L->top--; + setobjs2s(L, res, L->top); +} + + + +static void callTM (lua_State *L, const TValue *f, const TValue *p1, + const TValue *p2, const TValue *p3) { + setobj2s(L, L->top, f); /* push function */ + setobj2s(L, L->top+1, p1); /* 1st argument */ + setobj2s(L, L->top+2, p2); /* 2nd argument */ + setobj2s(L, L->top+3, p3); /* 3th argument */ + luaD_checkstack(L, 4); + L->top += 4; + luaD_call(L, L->top - 4, 0); +} + + +void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { + int loop; + for (loop = 0; loop < MAXTAGLOOP; loop++) { + const TValue *tm; + if (ttistable(t)) { /* `t' is a table? */ + Table *h = hvalue(t); + const TValue *res = luaH_get(h, key); /* do a primitive get */ + if (!ttisnil(res) || /* result is no nil? */ + (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ + setobj2s(L, val, res); + return; + } + /* else will try the tag method */ + } + else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) + luaG_typeerror(L, t, "index"); + if (ttisfunction(tm)) { + callTMres(L, val, tm, t, key); + return; + } + t = tm; /* else repeat with `tm' */ + } + luaG_runerror(L, "loop in gettable"); +} + + +void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { + int loop; + for (loop = 0; loop < MAXTAGLOOP; loop++) { + const TValue *tm; + if (ttistable(t)) { /* `t' is a table? */ + Table *h = hvalue(t); + TValue *oldval = luaH_set(L, h, key); /* do a primitive set */ + if (!ttisnil(oldval) || /* result is no nil? */ + (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ + setobj2t(L, oldval, val); + luaC_barriert(L, h, val); + return; + } + /* else will try the tag method */ + } + else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) + luaG_typeerror(L, t, "index"); + if (ttisfunction(tm)) { + callTM(L, tm, t, key, val); + return; + } + t = tm; /* else repeat with `tm' */ + } + luaG_runerror(L, "loop in settable"); +} + + +static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2, + StkId res, TMS event) { + const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ + if (ttisnil(tm)) + tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ + if (ttisnil(tm)) return 0; + callTMres(L, res, tm, p1, p2); + return 1; +} + + +static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2, + TMS event) { + const TValue *tm1 = fasttm(L, mt1, event); + const TValue *tm2; + if (tm1 == NULL) return NULL; /* no metamethod */ + if (mt1 == mt2) return tm1; /* same metatables => same metamethods */ + tm2 = fasttm(L, mt2, event); + if (tm2 == NULL) return NULL; /* no metamethod */ + if (luaO_rawequalObj(tm1, tm2)) /* same metamethods? */ + return tm1; + return NULL; +} + + +static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2, + TMS event) { + const TValue *tm1 = luaT_gettmbyobj(L, p1, event); + const TValue *tm2; + if (ttisnil(tm1)) return -1; /* no metamethod? */ + tm2 = luaT_gettmbyobj(L, p2, event); + if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */ + return -1; + callTMres(L, L->top, tm1, p1, p2); + return !l_isfalse(L->top); +} + + +static int l_strcmp (const TString *ls, const TString *rs) { + const char *l = getstr(ls); + size_t ll = ls->tsv.len; + const char *r = getstr(rs); + size_t lr = rs->tsv.len; + for (;;) { +// int temp = strcoll(l, r); + int temp = strcmp(l, r); + if (temp != 0) return temp; + else { /* strings are equal up to a `\0' */ + size_t len = strlen(l); /* index of first `\0' in both strings */ + if (len == lr) /* r is finished? */ + return (len == ll) ? 0 : 1; + else if (len == ll) /* l is finished? */ + return -1; /* l is smaller than r (because r is not finished) */ + /* both strings longer than `len'; go on comparing (after the `\0') */ + len++; + l += len; ll -= len; r += len; lr -= len; + } + } +} + + +int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { + int res; + if (ttype(l) != ttype(r)) + return luaG_ordererror(L, l, r); + else if (ttisnumber(l)) + return luai_numlt(nvalue(l), nvalue(r)); + else if (ttisstring(l)) + return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; + else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) + return res; + return luaG_ordererror(L, l, r); +} + + +static int lessequal (lua_State *L, const TValue *l, const TValue *r) { + int res; + if (ttype(l) != ttype(r)) + return luaG_ordererror(L, l, r); + else if (ttisnumber(l)) + return luai_numle(nvalue(l), nvalue(r)); + else if (ttisstring(l)) + return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; + else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ + return res; + else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */ + return !res; + return luaG_ordererror(L, l, r); +} + + +int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) { + const TValue *tm; + lua_assert(ttype(t1) == ttype(t2)); + switch (ttype(t1)) { + case LUA_TNIL: return 1; + case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); + case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ + case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); + case LUA_TUSERDATA: { + if (uvalue(t1) == uvalue(t2)) return 1; + tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, + TM_EQ); + break; /* will try TM */ + } + case LUA_TTABLE: { + if (hvalue(t1) == hvalue(t2)) return 1; + tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); + break; /* will try TM */ + } + default: return gcvalue(t1) == gcvalue(t2); + } + if (tm == NULL) return 0; /* no TM? */ + callTMres(L, L->top, tm, t1, t2); /* call TM */ + return !l_isfalse(L->top); +} + + +void luaV_concat (lua_State *L, int total, int last) { + do { + StkId top = L->base + last + 1; + int n = 2; /* number of elements handled in this pass (at least 2) */ + if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { + if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) + luaG_concaterror(L, top-2, top-1); + } else if (tsvalue(top-1)->len == 0) /* second op is empty? */ + (void)tostring(L, top - 2); /* result is first op (as string) */ + else { + /* at least two string values; get as many as possible */ + size_t tl = tsvalue(top-1)->len; + char *buffer; + int i; + /* collect total length */ + for (n = 1; n < total && tostring(L, top-n-1); n++) { + size_t l = tsvalue(top-n-1)->len; + if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow"); + tl += l; + } + buffer = luaZ_openspace(L, &G(L)->buff, tl); + tl = 0; + for (i=n; i>0; i--) { /* concat all strings */ + size_t l = tsvalue(top-i)->len; + memcpy(buffer+tl, svalue(top-i), l); + tl += l; + } + setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); + } + total -= n-1; /* got `n' strings to create 1 new */ + last -= n-1; + } while (total > 1); /* repeat until only 1 result left */ +} + + +static void Arith (lua_State *L, StkId ra, const TValue *rb, + const TValue *rc, TMS op) { + TValue tempb, tempc; + const TValue *b, *c; + if ((b = luaV_tonumber(rb, &tempb)) != NULL && + (c = luaV_tonumber(rc, &tempc)) != NULL) { + lua_Number nb = nvalue(b), nc = nvalue(c); + switch (op) { + case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break; + case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break; + case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break; + case TM_DIV: setnvalue(ra, luai_lnumdiv(nb, nc)); break; + case TM_MOD: setnvalue(ra, luai_lnummod(nb, nc)); break; + case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break; + case TM_UNM: setnvalue(ra, luai_numunm(nb)); break; + default: lua_assert(0); break; + } + } + else if (!call_binTM(L, rb, rc, ra, op)) + luaG_aritherror(L, rb, rc); +} + + + +/* +** some macros for common tasks in `luaV_execute' +*/ + +#define runtime_check(L, c) { if (!(c)) break; } + +#define RA(i) (base+GETARG_A(i)) +/* to be used after possible stack reallocation */ +#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i)) +#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i)) +#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ + ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) +#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ + ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) +#define KBx(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i)) + + +#define dojump(L,pc,i) {(pc) += (i); luai_threadyield(L);} + + +#define Protect(x) { L->savedpc = pc; {x;}; base = L->base; } + + +#define arith_op(op,tm) { \ + TValue *rb = RKB(i); \ + TValue *rc = RKC(i); \ + if (ttisnumber(rb) && ttisnumber(rc)) { \ + lua_Number nb = nvalue(rb), nc = nvalue(rc); \ + setnvalue(ra, op(nb, nc)); \ + } \ + else \ + Protect(Arith(L, ra, rb, rc, tm)); \ + } + + + +void luaV_execute (lua_State *L, int nexeccalls) { + LClosure *cl; + StkId base; + TValue *k; + const Instruction *pc; + reentry: /* entry point */ + lua_assert(isLua(L->ci)); + pc = L->savedpc; + cl = &clvalue(L->ci->func)->l; + base = L->base; + k = cl->p->k; + /* main loop of interpreter */ + for (;;) { + const Instruction i = *pc++; + StkId ra; + if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && + (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { + traceexec(L, pc); + if (L->status == LUA_YIELD) { /* did hook yield? */ + L->savedpc = pc - 1; + return; + } + base = L->base; + } + /* warning!! several calls may realloc the stack and invalidate `ra' */ + ra = RA(i); + lua_assert(base == L->base && L->base == L->ci->base); + lua_assert(base <= L->top && L->top <= L->stack + L->stacksize); + lua_assert(L->top == L->ci->top || luaG_checkopenop(i)); + switch (GET_OPCODE(i)) { + case OP_MOVE: { + setobjs2s(L, ra, RB(i)); + continue; + } + case OP_LOADK: { + setobj2s(L, ra, KBx(i)); + continue; + } + case OP_LOADBOOL: { + setbvalue(ra, GETARG_B(i)); + if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ + continue; + } + case OP_LOADNIL: { + TValue *rb = RB(i); + do { + setnilvalue(rb--); + } while (rb >= ra); + continue; + } + case OP_GETUPVAL: { + int b = GETARG_B(i); + setobj2s(L, ra, cl->upvals[b]->v); + continue; + } + case OP_GETGLOBAL: { + TValue g; + TValue *rb = KBx(i); + sethvalue(L, &g, cl->env); + lua_assert(ttisstring(rb)); + Protect(luaV_gettable(L, &g, rb, ra)); + continue; + } + case OP_GETTABLE: { + Protect(luaV_gettable(L, RB(i), RKC(i), ra)); + continue; + } + case OP_SETGLOBAL: { + TValue g; + sethvalue(L, &g, cl->env); + lua_assert(ttisstring(KBx(i))); + Protect(luaV_settable(L, &g, KBx(i), ra)); + continue; + } + case OP_SETUPVAL: { + UpVal *uv = cl->upvals[GETARG_B(i)]; + setobj(L, uv->v, ra); + luaC_barrier(L, uv, ra); + continue; + } + case OP_SETTABLE: { + Protect(luaV_settable(L, ra, RKB(i), RKC(i))); + continue; + } + case OP_NEWTABLE: { + int b = GETARG_B(i); + int c = GETARG_C(i); + sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); + Protect(luaC_checkGC(L)); + continue; + } + case OP_SELF: { + StkId rb = RB(i); + setobjs2s(L, ra+1, rb); + Protect(luaV_gettable(L, rb, RKC(i), ra)); + continue; + } + case OP_ADD: { + arith_op(luai_numadd, TM_ADD); + continue; + } + case OP_SUB: { + arith_op(luai_numsub, TM_SUB); + continue; + } + case OP_MUL: { + arith_op(luai_nummul, TM_MUL); + continue; + } + case OP_DIV: { + arith_op(luai_lnumdiv, TM_DIV); + continue; + } + case OP_MOD: { + arith_op(luai_lnummod, TM_MOD); + continue; + } + case OP_POW: { + arith_op(luai_numpow, TM_POW); + continue; + } + case OP_UNM: { + TValue *rb = RB(i); + if (ttisnumber(rb)) { + lua_Number nb = nvalue(rb); + setnvalue(ra, luai_numunm(nb)); + } + else { + Protect(Arith(L, ra, rb, rb, TM_UNM)); + } + continue; + } + case OP_NOT: { + int res = l_isfalse(RB(i)); /* next assignment may change this value */ + setbvalue(ra, res); + continue; + } + case OP_LEN: { + const TValue *rb = RB(i); + switch (ttype(rb)) { + case LUA_TTABLE: { + setnvalue(ra, cast_num(luaH_getn(hvalue(rb)))); + break; + } + case LUA_TSTRING: { + setnvalue(ra, cast_num(tsvalue(rb)->len)); + break; + } + default: { /* try metamethod */ + Protect( + if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN)) + luaG_typeerror(L, rb, "get length of"); + ) + } + } + continue; + } + case OP_CONCAT: { + int b = GETARG_B(i); + int c = GETARG_C(i); + Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L)); + setobjs2s(L, RA(i), base+b); + continue; + } + case OP_JMP: { + dojump(L, pc, GETARG_sBx(i)); + continue; + } + case OP_EQ: { + TValue *rb = RKB(i); + TValue *rc = RKC(i); + Protect( + if (equalobj(L, rb, rc) == GETARG_A(i)) + dojump(L, pc, GETARG_sBx(*pc)); + ) + pc++; + continue; + } + case OP_LT: { + Protect( + if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i)) + dojump(L, pc, GETARG_sBx(*pc)); + ) + pc++; + continue; + } + case OP_LE: { + Protect( + if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i)) + dojump(L, pc, GETARG_sBx(*pc)); + ) + pc++; + continue; + } + case OP_TEST: { + if (l_isfalse(ra) != GETARG_C(i)) + dojump(L, pc, GETARG_sBx(*pc)); + pc++; + continue; + } + case OP_TESTSET: { + TValue *rb = RB(i); + if (l_isfalse(rb) != GETARG_C(i)) { + setobjs2s(L, ra, rb); + dojump(L, pc, GETARG_sBx(*pc)); + } + pc++; + continue; + } + case OP_CALL: { + int b = GETARG_B(i); + int nresults = GETARG_C(i) - 1; + if (b != 0) L->top = ra+b; /* else previous instruction set top */ + L->savedpc = pc; + switch (luaD_precall(L, ra, nresults)) { + case PCRLUA: { + nexeccalls++; + goto reentry; /* restart luaV_execute over new Lua function */ + } + case PCRC: { + /* it was a C function (`precall' called it); adjust results */ + if (nresults >= 0) L->top = L->ci->top; + base = L->base; + continue; + } + default: { + return; /* yield */ + } + } + } + case OP_TAILCALL: { + int b = GETARG_B(i); + if (b != 0) L->top = ra+b; /* else previous instruction set top */ + L->savedpc = pc; + lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); + switch (luaD_precall(L, ra, LUA_MULTRET)) { + case PCRLUA: { + /* tail call: put new frame in place of previous one */ + CallInfo *ci = L->ci - 1; /* previous frame */ + int aux; + StkId func = ci->func; + StkId pfunc = (ci+1)->func; /* previous function index */ + if (L->openupval) luaF_close(L, ci->base); + L->base = ci->base = ci->func + ((ci+1)->base - pfunc); + for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */ + setobjs2s(L, func+aux, pfunc+aux); + ci->top = L->top = func+aux; /* correct top */ + lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize); + ci->savedpc = L->savedpc; + ci->tailcalls++; /* one more call lost */ + L->ci--; /* remove new frame */ + goto reentry; + } + case PCRC: { /* it was a C function (`precall' called it) */ + base = L->base; + continue; + } + default: { + return; /* yield */ + } + } + } + case OP_RETURN: { + int b = GETARG_B(i); + if (b != 0) L->top = ra+b-1; + if (L->openupval) luaF_close(L, base); + L->savedpc = pc; + b = luaD_poscall(L, ra); + if (--nexeccalls == 0) /* was previous function running `here'? */ + return; /* no: return */ + else { /* yes: continue its execution */ + if (b) L->top = L->ci->top; + lua_assert(isLua(L->ci)); + lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL); + goto reentry; + } + } + case OP_FORLOOP: { + lua_Number step = nvalue(ra+2); + lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */ + lua_Number limit = nvalue(ra+1); + if (luai_numlt(0, step) ? luai_numle(idx, limit) + : luai_numle(limit, idx)) { + dojump(L, pc, GETARG_sBx(i)); /* jump back */ + setnvalue(ra, idx); /* update internal index... */ + setnvalue(ra+3, idx); /* ...and external index */ + } + continue; + } + case OP_FORPREP: { + const TValue *init = ra; + const TValue *plimit = ra+1; + const TValue *pstep = ra+2; + L->savedpc = pc; /* next steps may throw errors */ + if (!tonumber(init, ra)) + luaG_runerror(L, LUA_QL("for") " initial value must be a number"); + else if (!tonumber(plimit, ra+1)) + luaG_runerror(L, LUA_QL("for") " limit must be a number"); + else if (!tonumber(pstep, ra+2)) + luaG_runerror(L, LUA_QL("for") " step must be a number"); + setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep))); + dojump(L, pc, GETARG_sBx(i)); + continue; + } + case OP_TFORLOOP: { + StkId cb = ra + 3; /* call base */ + setobjs2s(L, cb+2, ra+2); + setobjs2s(L, cb+1, ra+1); + setobjs2s(L, cb, ra); + L->top = cb+3; /* func. + 2 args (state and index) */ + Protect(luaD_call(L, cb, GETARG_C(i))); + L->top = L->ci->top; + cb = RA(i) + 3; /* previous call may change the stack */ + if (!ttisnil(cb)) { /* continue loop? */ + setobjs2s(L, cb-1, cb); /* save control variable */ + dojump(L, pc, GETARG_sBx(*pc)); /* jump back */ + } + pc++; + continue; + } + case OP_SETLIST: { + int n = GETARG_B(i); + int c = GETARG_C(i); + int last; + Table *h; + if (n == 0) { + n = cast_int(L->top - ra) - 1; + L->top = L->ci->top; + } + if (c == 0) c = cast_int(*pc++); + runtime_check(L, ttistable(ra)); + h = hvalue(ra); + last = ((c-1)*LFIELDS_PER_FLUSH) + n; + if (last > h->sizearray) /* needs more space? */ + luaH_resizearray(L, h, last); /* pre-alloc it at once */ + for (; n > 0; n--) { + TValue *val = ra+n; + setobj2t(L, luaH_setnum(L, h, last--), val); + luaC_barriert(L, h, val); + } + continue; + } + case OP_CLOSE: { + luaF_close(L, ra); + continue; + } + case OP_CLOSURE: { + Proto *p; + Closure *ncl; + int nup, j; + p = cl->p->p[GETARG_Bx(i)]; + nup = p->nups; + ncl = luaF_newLclosure(L, nup, cl->env); + ncl->l.p = p; + for (j=0; j<nup; j++, pc++) { + if (GET_OPCODE(*pc) == OP_GETUPVAL) + ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)]; + else { + lua_assert(GET_OPCODE(*pc) == OP_MOVE); + ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc)); + } + } + setclvalue(L, ra, ncl); + Protect(luaC_checkGC(L)); + continue; + } + case OP_VARARG: { + int b = GETARG_B(i) - 1; + int j; + CallInfo *ci = L->ci; + int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1; + if (b == LUA_MULTRET) { + Protect(luaD_checkstack(L, n)); + ra = RA(i); /* previous call may change the stack */ + b = n; + L->top = ra + n; + } + for (j = 0; j < b; j++) { + if (j < n) { + setobjs2s(L, ra + j, ci->base - n + j); + } + else { + setnilvalue(ra + j); + } + } + continue; + } + } + } +} + diff --git a/contrib/syslinux-4.02/com32/lua/src/lvm.h b/contrib/syslinux-4.02/com32/lua/src/lvm.h new file mode 100644 index 0000000..bfe4f56 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lvm.h @@ -0,0 +1,36 @@ +/* +** $Id: lvm.h,v 2.5.1.1 2007/12/27 13:02:25 roberto Exp $ +** Lua virtual machine +** See Copyright Notice in lua.h +*/ + +#ifndef lvm_h +#define lvm_h + + +#include "ldo.h" +#include "lobject.h" +#include "ltm.h" + + +#define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o))) + +#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \ + (((o) = luaV_tonumber(o,n)) != NULL)) + +#define equalobj(L,o1,o2) \ + (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2)) + + +LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); +LUAI_FUNC int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2); +LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n); +LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj); +LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, + StkId val); +LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, + StkId val); +LUAI_FUNC void luaV_execute (lua_State *L, int nexeccalls); +LUAI_FUNC void luaV_concat (lua_State *L, int total, int last); + +#endif diff --git a/contrib/syslinux-4.02/com32/lua/src/lzio.c b/contrib/syslinux-4.02/com32/lua/src/lzio.c new file mode 100644 index 0000000..293edd5 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lzio.c @@ -0,0 +1,82 @@ +/* +** $Id: lzio.c,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ +** a generic input stream interface +** See Copyright Notice in lua.h +*/ + + +#include <string.h> + +#define lzio_c +#define LUA_CORE + +#include "lua.h" + +#include "llimits.h" +#include "lmem.h" +#include "lstate.h" +#include "lzio.h" + + +int luaZ_fill (ZIO *z) { + size_t size; + lua_State *L = z->L; + const char *buff; + lua_unlock(L); + buff = z->reader(L, z->data, &size); + lua_lock(L); + if (buff == NULL || size == 0) return EOZ; + z->n = size - 1; + z->p = buff; + return char2int(*(z->p++)); +} + + +int luaZ_lookahead (ZIO *z) { + if (z->n == 0) { + if (luaZ_fill(z) == EOZ) + return EOZ; + else { + z->n++; /* luaZ_fill removed first byte; put back it */ + z->p--; + } + } + return char2int(*z->p); +} + + +void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { + z->L = L; + z->reader = reader; + z->data = data; + z->n = 0; + z->p = NULL; +} + + +/* --------------------------------------------------------------- read --- */ +size_t luaZ_read (ZIO *z, void *b, size_t n) { + while (n) { + size_t m; + if (luaZ_lookahead(z) == EOZ) + return n; /* return number of missing bytes */ + m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ + memcpy(b, z->p, m); + z->n -= m; + z->p += m; + b = (char *)b + m; + n -= m; + } + return 0; +} + +/* ------------------------------------------------------------------------ */ +char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) { + if (n > buff->buffsize) { + if (n < LUA_MINBUFFER) n = LUA_MINBUFFER; + luaZ_resizebuffer(L, buff, n); + } + return buff->buffer; +} + + diff --git a/contrib/syslinux-4.02/com32/lua/src/lzio.h b/contrib/syslinux-4.02/com32/lua/src/lzio.h new file mode 100644 index 0000000..51d695d --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/lzio.h @@ -0,0 +1,67 @@ +/* +** $Id: lzio.h,v 1.21.1.1 2007/12/27 13:02:25 roberto Exp $ +** Buffered streams +** See Copyright Notice in lua.h +*/ + + +#ifndef lzio_h +#define lzio_h + +#include "lua.h" + +#include "lmem.h" + + +#define EOZ (-1) /* end of stream */ + +typedef struct Zio ZIO; + +#define char2int(c) cast(int, cast(unsigned char, (c))) + +#define zgetc(z) (((z)->n--)>0 ? char2int(*(z)->p++) : luaZ_fill(z)) + +typedef struct Mbuffer { + char *buffer; + size_t n; + size_t buffsize; +} Mbuffer; + +#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) + +#define luaZ_buffer(buff) ((buff)->buffer) +#define luaZ_sizebuffer(buff) ((buff)->buffsize) +#define luaZ_bufflen(buff) ((buff)->n) + +#define luaZ_resetbuffer(buff) ((buff)->n = 0) + + +#define luaZ_resizebuffer(L, buff, size) \ + (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \ + (buff)->buffsize = size) + +#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) + + +LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n); +LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, + void *data); +LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */ +LUAI_FUNC int luaZ_lookahead (ZIO *z); + + + +/* --------- Private Part ------------------ */ + +struct Zio { + size_t n; /* bytes still unread */ + const char *p; /* current position in buffer */ + lua_Reader reader; + void* data; /* additional data */ + lua_State *L; /* Lua state (for reader) */ +}; + + +LUAI_FUNC int luaZ_fill (ZIO *z); + +#endif diff --git a/contrib/syslinux-4.02/com32/lua/src/pci.c b/contrib/syslinux-4.02/com32/lua/src/pci.c new file mode 100644 index 0000000..b9c1605 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/pci.c @@ -0,0 +1,183 @@ +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> + +#define lpcilib_c /* Define the library */ + +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +#include <sys/pci.h> + + +static int pci_getinfo(lua_State *L) +{ + struct pci_domain *pci_domain; + struct pci_device *pci_device; + int pci_dev = 1; + + pci_domain = pci_scan(); + + lua_newtable(L); /* list of busses */ + + for_each_pci_func(pci_device, pci_domain) { + lua_pushnumber(L, pci_dev++); + + lua_newtable(L); /* device infos */ + + lua_pushstring(L, "bus"); + lua_pushnumber(L, __pci_bus); + lua_settable(L,-3); + + lua_pushstring(L, "slot"); + lua_pushnumber(L, __pci_slot); + lua_settable(L,-3); + + lua_pushstring(L, "func"); + lua_pushnumber(L, __pci_func); + lua_settable(L,-3); + + lua_pushstring(L, "vendor"); + lua_pushnumber(L, pci_device->vendor); + lua_settable(L,-3); + + lua_pushstring(L, "product"); + lua_pushnumber(L, pci_device->product); + lua_settable(L,-3); + + lua_pushstring(L, "sub_vendor"); + lua_pushnumber(L, pci_device->sub_vendor); + lua_settable(L,-3); + + lua_pushstring(L, "sub_product"); + lua_pushnumber(L, pci_device->sub_product); + lua_settable(L,-3); + + lua_settable(L,-3); /* end device infos */ + } + + return 1; +} + +/* searching the next char that is not a space */ +static char *skipspace(char *p) +{ + while (*p && *p <= ' ') + p++; + + return p; +} + +/* removing any \n found in a string */ +static void remove_eol(char *string) +{ + int j = strlen(string); + int i = 0; + for(i = 0; i < j; i++) if(string[i] == '\n') string[i] = 0; +} + + +/* Try to match any pci device to the appropriate kernel module */ +/* it uses the modules.pcimap from the boot device*/ +static int pci_getidlist(lua_State *L) +{ + const char *pciidfile; + char line[1024]; + char vendor[255]; + char vendor_id[5]; + char product[255]; + char productvendor[9]; + char productvendorsub[17]; + FILE *f; + + if (lua_gettop(L) == 1) { + pciidfile = luaL_checkstring(L, 1); + } else { + pciidfile = "pci.ids"; + } + + lua_newtable(L); /* list of vendors */ + + /* Opening the pci.ids from the boot device*/ + f=fopen(pciidfile,"r"); + if (!f) + return -1; + + /* 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] == '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') { + + /* the 4th first chars are the vendor_id */ + strlcpy(vendor_id,line,4); + + /* the vendor name is the next field*/ + vendor_id[4]=0; + strlcpy(vendor,skipspace(strstr(line," ")),255); + remove_eol(vendor); + + /* ffff is an invalid vendor id */ + if (strstr(vendor_id,"ffff")) break; + + lua_pushstring(L, vendor_id); + lua_pushstring(L, vendor); + lua_settable(L,-3); + + /* if we have a tab + a char, it means this is a product id */ + } else if ((line[0] == '\t') && (line[1] != '\t')) { + + /* the product name the second field */ + strlcpy(product,skipspace(strstr(line," ")),255); + remove_eol(product); + + /* the 4th first chars are the vendor_id */ + strlcpy(productvendor,vendor_id,4); + /* the product id is first field */ + strlcpy(productvendor+4,&line[1],4); + productvendor[8]=0; + + lua_pushstring(L, productvendor); + lua_pushstring(L, product); + lua_settable(L,-3); + + /* if we have two tabs, it means this is a sub product */ + } else if ((line[0] == '\t') && (line[1] == '\t')) { + + /* the product name is last field */ + strlcpy(product,skipspace(strstr(line," ")),255); + strlcpy(product,skipspace(strstr(product," ")),255); + remove_eol(product); + + strlcpy(productvendorsub, productvendor,8); + strlcpy(productvendorsub+8, &line[2],4); + strlcpy(productvendorsub+12, &line[7],4); + productvendorsub[16]=0; + + lua_pushstring(L, productvendorsub); + lua_pushstring(L, product); + lua_settable(L,-3); + + } + } + fclose(f); + return(1); +} + +static const luaL_reg pcilib[] = { + {"getinfo", pci_getinfo}, + {"getidlist", pci_getidlist}, + {NULL, NULL} +}; + +/* This defines a function that opens up your library. */ + +LUALIB_API int luaopen_pci (lua_State *L) { + luaL_openlib(L, LUA_PCILIBNAME, pcilib, 0); + return 1; +} + diff --git a/contrib/syslinux-4.02/com32/lua/src/print.c b/contrib/syslinux-4.02/com32/lua/src/print.c new file mode 100644 index 0000000..e240cfc --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/print.c @@ -0,0 +1,227 @@ +/* +** $Id: print.c,v 1.55a 2006/05/31 13:30:05 lhf Exp $ +** print bytecodes +** See Copyright Notice in lua.h +*/ + +#include <ctype.h> +#include <stdio.h> + +#define luac_c +#define LUA_CORE + +#include "ldebug.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lundump.h" + +#define PrintFunction luaU_print + +#define Sizeof(x) ((int)sizeof(x)) +#define VOID(p) ((const void*)(p)) + +static void PrintString(const TString* ts) +{ + const char* s=getstr(ts); + size_t i,n=ts->tsv.len; + putchar('"'); + for (i=0; i<n; i++) + { + int c=s[i]; + switch (c) + { + case '"': printf("\\\""); break; + case '\\': printf("\\\\"); break; + case '\a': printf("\\a"); break; + case '\b': printf("\\b"); break; + case '\f': printf("\\f"); break; + case '\n': printf("\\n"); break; + case '\r': printf("\\r"); break; + case '\t': printf("\\t"); break; + case '\v': printf("\\v"); break; + default: if (isprint((unsigned char)c)) + putchar(c); + else + printf("\\%03u",(unsigned char)c); + } + } + putchar('"'); +} + +static void PrintConstant(const Proto* f, int i) +{ + const TValue* o=&f->k[i]; + switch (ttype(o)) + { + case LUA_TNIL: + printf("nil"); + break; + case LUA_TBOOLEAN: + printf(bvalue(o) ? "true" : "false"); + break; + case LUA_TNUMBER: + printf(LUA_NUMBER_FMT,nvalue(o)); + break; + case LUA_TSTRING: + PrintString(rawtsvalue(o)); + break; + default: /* cannot happen */ + printf("? type=%d",ttype(o)); + break; + } +} + +static void PrintCode(const Proto* f) +{ + const Instruction* code=f->code; + int pc,n=f->sizecode; + for (pc=0; pc<n; pc++) + { + Instruction i=code[pc]; + OpCode o=GET_OPCODE(i); + int a=GETARG_A(i); + int b=GETARG_B(i); + int c=GETARG_C(i); + int bx=GETARG_Bx(i); + int sbx=GETARG_sBx(i); + int line=getline(f,pc); + printf("\t%d\t",pc+1); + if (line>0) printf("[%d]\t",line); else printf("[-]\t"); + printf("%-9s\t",luaP_opnames[o]); + switch (getOpMode(o)) + { + case iABC: + printf("%d",a); + if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (-1-INDEXK(b)) : b); + if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (-1-INDEXK(c)) : c); + break; + case iABx: + if (getBMode(o)==OpArgK) printf("%d %d",a,-1-bx); else printf("%d %d",a,bx); + break; + case iAsBx: + if (o==OP_JMP) printf("%d",sbx); else printf("%d %d",a,sbx); + break; + } + switch (o) + { + case OP_LOADK: + printf("\t; "); PrintConstant(f,bx); + break; + case OP_GETUPVAL: + case OP_SETUPVAL: + printf("\t; %s", (f->sizeupvalues>0) ? getstr(f->upvalues[b]) : "-"); + break; + case OP_GETGLOBAL: + case OP_SETGLOBAL: + printf("\t; %s",svalue(&f->k[bx])); + break; + case OP_GETTABLE: + case OP_SELF: + if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); } + break; + case OP_SETTABLE: + case OP_ADD: + case OP_SUB: + case OP_MUL: + case OP_DIV: + case OP_POW: + case OP_EQ: + case OP_LT: + case OP_LE: + if (ISK(b) || ISK(c)) + { + printf("\t; "); + if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-"); + printf(" "); + if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-"); + } + break; + case OP_JMP: + case OP_FORLOOP: + case OP_FORPREP: + printf("\t; to %d",sbx+pc+2); + break; + case OP_CLOSURE: + printf("\t; %p",VOID(f->p[bx])); + break; + case OP_SETLIST: + if (c==0) printf("\t; %d",(int)code[++pc]); + else printf("\t; %d",c); + break; + default: + break; + } + printf("\n"); + } +} + +#define SS(x) (x==1)?"":"s" +#define S(x) x,SS(x) + +static void PrintHeader(const Proto* f) +{ + const char* s=getstr(f->source); + if (*s=='@' || *s=='=') + s++; + else if (*s==LUA_SIGNATURE[0]) + s="(bstring)"; + else + s="(string)"; + printf("\n%s <%s:%d,%d> (%d instruction%s, %d bytes at %p)\n", + (f->linedefined==0)?"main":"function",s, + f->linedefined,f->lastlinedefined, + S(f->sizecode),f->sizecode*Sizeof(Instruction),VOID(f)); + printf("%d%s param%s, %d slot%s, %d upvalue%s, ", + f->numparams,f->is_vararg?"+":"",SS(f->numparams), + S(f->maxstacksize),S(f->nups)); + printf("%d local%s, %d constant%s, %d function%s\n", + S(f->sizelocvars),S(f->sizek),S(f->sizep)); +} + +static void PrintConstants(const Proto* f) +{ + int i,n=f->sizek; + printf("constants (%d) for %p:\n",n,VOID(f)); + for (i=0; i<n; i++) + { + printf("\t%d\t",i+1); + PrintConstant(f,i); + printf("\n"); + } +} + +static void PrintLocals(const Proto* f) +{ + int i,n=f->sizelocvars; + printf("locals (%d) for %p:\n",n,VOID(f)); + for (i=0; i<n; i++) + { + printf("\t%d\t%s\t%d\t%d\n", + i,getstr(f->locvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1); + } +} + +static void PrintUpvalues(const Proto* f) +{ + int i,n=f->sizeupvalues; + printf("upvalues (%d) for %p:\n",n,VOID(f)); + if (f->upvalues==NULL) return; + for (i=0; i<n; i++) + { + printf("\t%d\t%s\n",i,getstr(f->upvalues[i])); + } +} + +void PrintFunction(const Proto* f, int full) +{ + int i,n=f->sizep; + PrintHeader(f); + PrintCode(f); + if (full) + { + PrintConstants(f); + PrintLocals(f); + PrintUpvalues(f); + } + for (i=0; i<n; i++) PrintFunction(f->p[i],full); +} diff --git a/contrib/syslinux-4.02/com32/lua/src/syslinux.c b/contrib/syslinux-4.02/com32/lua/src/syslinux.c new file mode 100644 index 0000000..fa54d7f --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/syslinux.c @@ -0,0 +1,472 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <syslinux/boot.h> + +#define lnetlib_c /* Define the library */ + +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +#include "syslinux/boot.h" +#include "syslinux/loadfile.h" +#include "syslinux/linux.h" +#include "syslinux/config.h" + +int __parse_argv(char ***argv, const char *str); + +#define SYSLINUX_FILE "syslinux_file" + +typedef struct syslinux_file { + char *data; + char *name; + size_t size; +} syslinux_file; + +/* + * Most code taken from: + * com32/modules/linux.c + */ + +/* Find the last instance of a particular command line argument + (which should include the final =; do not use for boolean arguments) */ +static char *find_argument(char **argv, const char *argument) +{ + int la = strlen(argument); + char **arg; + char *ptr = NULL; + + for (arg = argv; *arg; arg++) { + if (!memcmp(*arg, argument, la)) + ptr = *arg + la; + } + + return ptr; +} + +/* Get a value with a potential suffix (k/m/g/t/p/e) */ +static unsigned long long suffix_number(const char *str) +{ + char *ep; + unsigned long long v; + int shift; + + v = strtoull(str, &ep, 0); + switch (*ep | 0x20) { + case 'k': + shift = 10; + break; + case 'm': + shift = 20; + break; + case 'g': + shift = 30; + break; + case 't': + shift = 40; + break; + case 'p': + shift = 50; + break; + case 'e': + shift = 60; + break; + default: + shift = 0; + break; + } + v <<= shift; + + return v; +} + +/* Truncate to 32 bits, with saturate */ +static inline uint32_t saturate32(unsigned long long v) +{ + return (v > 0xffffffff) ? 0xffffffff : (uint32_t) v; +} + +/* Stitch together the command line from a set of argv's */ +static char *make_cmdline(char **argv) +{ + char **arg; + size_t bytes; + char *cmdline, *p; + + bytes = 1; /* Just in case we have a zero-entry cmdline */ + for (arg = argv; *arg; arg++) { + bytes += strlen(*arg) + 1; + } + + p = cmdline = malloc(bytes); + if (!cmdline) + return NULL; + + for (arg = argv; *arg; arg++) { + int len = strlen(*arg); + memcpy(p, *arg, len); + p[len] = ' '; + p += len + 1; + } + + if (p > cmdline) + p--; /* Remove the last space */ + *p = '\0'; + + return cmdline; +} + +static int sl_run_command(lua_State * L) +{ + const char *cmd = luaL_checkstring(L, 1); /* Reads the string parameter */ + syslinux_run_command(cmd); + return 0; +} + +/* do default boot */ +static int sl_run_default(lua_State * L) +{ + syslinux_run_default(); + return 0; +} + +/* do local boot */ +static int sl_local_boot(lua_State * L) +{ + uint16_t flags = luaL_checkint(L, 1); + syslinux_local_boot(flags); + return 0; +} + +static int sl_final_cleanup(lua_State * L) +{ + uint16_t flags = luaL_checkint(L, 1); + syslinux_local_boot(flags); + return 0; +} + +/* boot linux kernel and initrd */ +static int sl_boot_linux(lua_State * L) +{ + const char *kernel = luaL_checkstring(L, 1); + const char *cmdline = luaL_optstring(L, 2, ""); + char *initrd; + void *kernel_data, *file_data; + size_t kernel_len, file_len; + struct initramfs *initramfs; + char *newcmdline; + uint32_t mem_limit = luaL_optint(L, 3, 0); + uint16_t video_mode = luaL_optint(L, 4, 0); +// int ret, i; + int ret; + char **argv, **argp, *arg, *p; + + ret = __parse_argv(&argv, cmdline); + + newcmdline = malloc(strlen(kernel) + 12); + if (!newcmdline) + printf("Mem alloc failed: cmdline\n"); + + strcpy(newcmdline, "BOOT_IMAGE="); + strcpy(newcmdline + strlen(newcmdline), kernel); + argv[0] = newcmdline; + argp = argv; + + /* DEBUG + for (i=0; i<ret; i++) + printf("%d: %s\n", i, argv[i]); + */ + + newcmdline = make_cmdline(argp); + if (!newcmdline) + printf("Creating command line failed!\n"); + + /* DEBUG + printf("Command line: %s\n", newcmdline); + msleep(1000); + */ + + /* Look for specific command-line arguments we care about */ + if ((arg = find_argument(argp, "mem="))) + mem_limit = saturate32(suffix_number(arg)); + + if ((arg = find_argument(argp, "vga="))) { + switch (arg[0] | 0x20) { + case 'a': /* "ask" */ + video_mode = 0xfffd; + break; + case 'e': /* "ext" */ + video_mode = 0xfffe; + break; + case 'n': /* "normal" */ + video_mode = 0xffff; + break; + default: + video_mode = strtoul(arg, NULL, 0); + break; + } + } + + printf("Loading kernel %s...\n", kernel); + if (loadfile(kernel, &kernel_data, &kernel_len)) + printf("failed!\n"); + else + printf("ok\n"); + + initramfs = initramfs_init(); + if (!initramfs) + printf("Initializing initrd failed!\n"); + + if ((arg = find_argument(argp, "initrd="))) { + do { + p = strchr(arg, ','); + if (p) + *p = '\0'; + + initrd = arg; + printf("Loading initrd %s... ", initrd); + if (initramfs_load_archive(initramfs, initrd)) { + printf("failed!\n"); + } + printf("ok\n"); + + if (p) + *p++ = ','; + } while ((arg = p)); + } + + if (!loadfile("/testfile1", &file_data, &file_len)) { + if (initramfs_add_file(initramfs, file_data, file_len, file_len, + "/testfile1", 0, 0755)) + printf("Adding extra file failed\n"); + } else + printf("Loading extra file failed\n"); + + /* DEBUG + msleep(10000); + */ + + ret = syslinux_boot_linux(kernel_data, kernel_len, initramfs, newcmdline); + + printf("syslinux_boot_linux returned %d\n", ret); + + return 0; +} + +/* sleep for sec seconds */ +static int sl_sleep(lua_State * L) +{ + unsigned int sec = luaL_checkint(L, 1); + sleep(sec); + return 0; +} + +/* sleep for msec milliseconds */ +static int sl_msleep(lua_State * L) +{ + unsigned int msec = luaL_checkint(L, 1); + msleep(msec); + return 0; +} + +static int sl_run_kernel_image(lua_State * L) +{ + const char *filename = luaL_checkstring(L, 1); + const char *cmdline = luaL_checkstring(L, 2); + uint32_t ipappend_flags = luaL_checkint(L, 3); + uint32_t type = luaL_checkint(L, 4); + + syslinux_run_kernel_image(filename, cmdline, ipappend_flags, type); + return 0; +} + +static int sl_loadfile(lua_State * L) +{ + const char *filename = luaL_checkstring(L, 1); + syslinux_file *file; + + void *file_data; + size_t file_len; + + if (loadfile(filename, &file_data, &file_len)) { + lua_pushstring(L, "Could not load file"); + lua_error(L); + } + + file = malloc(sizeof(syslinux_file)); + file->name = filename; + file->size = file_len; + file->data = file_data; + + lua_pushlightuserdata(L, file); + luaL_getmetatable(L, SYSLINUX_FILE); + lua_setmetatable(L, -2); + + return 1; +} + +static int sl_filesize(lua_State * L) +{ + const syslinux_file *file = luaL_checkudata(L, 1, SYSLINUX_FILE); + + lua_pushinteger(L, file->size); + + return 1; +} + +static int sl_filename(lua_State * L) +{ + const syslinux_file *file = luaL_checkudata(L, 1, SYSLINUX_FILE); + + lua_pushstring(L, file->name); + + return 1; +} + +static int sl_initramfs_init(lua_State * L) +{ + struct initramfs *initramfs; + + initramfs = initramfs_init(); + if (!initramfs) + printf("Initializing initrd failed!\n"); + + lua_pushlightuserdata(L, initramfs); + luaL_getmetatable(L, SYSLINUX_FILE); + lua_setmetatable(L, -2); + + return 1; +} + +static int sl_initramfs_load_archive(lua_State * L) +{ + const struct initramfs *initramfs = luaL_checkudata(L, 1, SYSLINUX_FILE); + const char *filename = luaL_checkstring(L, 2); + + if (initramfs_load_archive(initramfs, filename)) { + printf("failed!\n"); + } + + return 0; +} + +static int sl_initramfs_add_file(lua_State * L) +{ + const struct initramfs *initramfs = luaL_checkudata(L, 1, SYSLINUX_FILE); + const char *filename = luaL_checkstring(L, 2); + void *file_data; + size_t file_len = 0; + + if (initramfs_add_file(initramfs, file_data, file_len, file_len, + "/testfile1", 0, 0755)) + + return 0; +} + +static int sl_boot_it(lua_State * L) +{ + const syslinux_file *kernel = luaL_checkudata(L, 1, SYSLINUX_FILE); + const struct initramfs *initramfs = luaL_checkudata(L, 2, SYSLINUX_FILE); + const char *cmdline = luaL_optstring(L, 3, ""); + uint32_t mem_limit = luaL_optint(L, 4, 0); + uint16_t video_mode = luaL_optint(L, 5, 0); + int ret; + + ret = syslinux_boot_linux(kernel->data, kernel->size, initramfs, cmdline); + + return 0; +} + +static int sl_derivative(lua_State * L) +{ + const struct syslinux_version *sv; + + sv = syslinux_version(); + + switch (sv->filesystem) { + case SYSLINUX_FS_SYSLINUX: + lua_pushstring(L, "SYSLINUX"); + break; + case SYSLINUX_FS_PXELINUX: + lua_pushstring(L, "PXELINUX"); + break; + case SYSLINUX_FS_ISOLINUX: + lua_pushstring(L, "ISOLINUX"); + break; + case SYSLINUX_FS_UNKNOWN: + default: + lua_pushstring(L, "Unknown Syslinux derivative"); + break; + } + + return 1; +} + +static int sl_version(lua_State * L) +{ + const struct syslinux_version *sv; + + sv = syslinux_version(); + lua_pushstring(L, sv->version_string); + + return 1; +} + +static const luaL_reg syslinuxlib[] = { + {"run_command", sl_run_command}, + {"run_default", sl_run_default}, + {"local_boot", sl_local_boot}, + {"final_cleanup", sl_final_cleanup}, + {"boot_linux", sl_boot_linux}, + {"run_kernel_image", sl_run_kernel_image}, + {"sleep", sl_sleep}, + {"msleep", sl_msleep}, + {"loadfile", sl_loadfile}, + {"filesize", sl_filesize}, + {"filename", sl_filename}, + {"initramfs_init", sl_initramfs_init}, + {"initramfs_load_archive", sl_initramfs_load_archive}, + {"initramfs_add_file", sl_initramfs_add_file}, + {"boot_it", sl_boot_it}, + {"derivative", sl_derivative}, + {"version", sl_version}, + {NULL, NULL} +}; + +/* This defines a function that opens up your library. */ + +LUALIB_API int luaopen_syslinux(lua_State * L) +{ + + luaL_newmetatable(L, SYSLINUX_FILE); + + luaL_openlib(L, LUA_SYSLINUXLIBNAME, syslinuxlib, 0); + return 1; +} diff --git a/contrib/syslinux-4.02/com32/lua/src/vesa.c b/contrib/syslinux-4.02/com32/lua/src/vesa.c new file mode 100644 index 0000000..6f34820 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/vesa.c @@ -0,0 +1,148 @@ +#include <stdlib.h> +#include <string.h> + +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +#include "../../include/console.h" +#include "../../lib/sys/vesa/vesa.h" +#include "../../lib/sys/vesa/video.h" + +int vesacon_load_background(const char *filename); + +static int __constfunc is_power_of_2(unsigned int x) +{ + return x && !(x & (x-1)); +} + +static int vesacon_paged_mode_ok(const struct vesa_mode_info *mi) +{ + int i; + + if (!is_power_of_2(mi->win_size) || + !is_power_of_2(mi->win_grain) || + mi->win_grain > mi->win_size) + return 0; /* Impossible... */ + + for (i = 0; i < 2; i++) { + if ((mi->win_attr[i] & 0x05) == 0x05 && mi->win_seg[i]) + return 1; /* Usable window */ + } + + return 0; /* Nope... */ +} + +static int vesa_getmodes(lua_State *L) +{ + com32sys_t rm; + uint16_t mode, bestmode, *mode_ptr; + struct vesa_general_info *gi; + struct vesa_mode_info *mi; + enum vesa_pixel_format bestpxf; + int nmode = 1; + + /* Allocate space in the bounce buffer for these structures */ + gi = &((struct vesa_info *)__com32.cs_bounce)->gi; + mi = &((struct vesa_info *)__com32.cs_bounce)->mi; + + memset(&rm, 0, sizeof rm); + memset(gi, 0, sizeof *gi); + + gi->signature = VBE2_MAGIC; /* Get VBE2 extended data */ + rm.eax.w[0] = 0x4F00; /* Get SVGA general information */ + rm.edi.w[0] = OFFS(gi); + rm.es = SEG(gi); + __intcall(0x10, &rm, &rm); + + if ( rm.eax.w[0] != 0x004F ) + return -1; /* Function call failed */ + if ( gi->signature != VESA_MAGIC ) + return -2; /* No magic */ + if ( gi->version < 0x0102 ) + return -3; /* VESA 1.2+ required */ + + lua_newtable(L); /* list of modes */ + + /* Copy general info */ + memcpy(&__vesa_info.gi, gi, sizeof *gi); + + /* Search for a 640x480 mode with a suitable color and memory model... */ + + mode_ptr = GET_PTR(gi->video_mode_ptr); + bestmode = 0; + bestpxf = PXF_NONE; + + while ((mode = *mode_ptr++) != 0xFFFF) { + mode &= 0x1FF; /* The rest are attributes of sorts */ + + printf("Found mode: 0x%04x (%dx%dx%d)\n", mode, mi->h_res, mi->v_res, mi->bpp); + + memset(mi, 0, sizeof *mi); + rm.eax.w[0] = 0x4F01; /* Get SVGA mode information */ + rm.ecx.w[0] = mode; + rm.edi.w[0] = OFFS(mi); + rm.es = SEG(mi); + __intcall(0x10, &rm, &rm); + + /* Must be a supported mode */ + if ( rm.eax.w[0] != 0x004f ) + continue; + + lua_pushnumber(L, nmode++); + lua_newtable(L); /* mode info */ + + lua_pushstring(L, "mode"); + lua_pushnumber(L, mode); + lua_settable(L,-3); + + lua_pushstring(L, "hres"); + lua_pushnumber(L, mi->h_res); + lua_settable(L,-3); + + lua_pushstring(L, "vres"); + lua_pushnumber(L, mi->v_res); + lua_settable(L,-3); + + lua_pushstring(L, "bpp"); + lua_pushnumber(L, mi->bpp); + lua_settable(L,-3); + + lua_settable(L, -3); /* add to mode list */ + + } + + return 1; +} + + +static int vesa_setmode(lua_State *L) +{ + openconsole(&dev_rawcon_r, &dev_vesaserial_w); + + return 0; +} + + +static int vesa_load_background(lua_State *L) +{ + const char *filename = luaL_checkstring(L, 1); + + vesacon_load_background(filename); + + return 0; +} + +static const luaL_reg vesalib[] = { + {"getmodes", vesa_getmodes}, + {"setmode", vesa_setmode}, + {"load_background", vesa_load_background}, + {NULL, NULL} +}; + +/* This defines a function that opens up your library. */ + +LUALIB_API int luaopen_vesa (lua_State *L) { + luaL_openlib(L, LUA_VESALIBNAME, vesalib, 0); + return 1; +} + diff --git a/contrib/syslinux-4.02/com32/lua/test/README b/contrib/syslinux-4.02/com32/lua/test/README new file mode 100644 index 0000000..0c7f38b --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/test/README @@ -0,0 +1,26 @@ +These are simple tests for Lua. Some of them contain useful code. +They are meant to be run to make sure Lua is built correctly and also +to be read, to see how Lua programs look. + +Here is a one-line summary of each program: + + bisect.lua bisection method for solving non-linear equations + cf.lua temperature conversion table (celsius to farenheit) + echo.lua echo command line arguments + env.lua environment variables as automatic global variables + factorial.lua factorial without recursion + fib.lua fibonacci function with cache + fibfor.lua fibonacci numbers with coroutines and generators + globals.lua report global variable usage + hello.lua the first program in every language + life.lua Conway's Game of Life + luac.lua bare-bones luac + printf.lua an implementation of printf + readonly.lua make global variables readonly + sieve.lua the sieve of of Eratosthenes programmed with coroutines + sort.lua two implementations of a sort function + table.lua make table, grouping all data for the same item + trace-calls.lua trace calls + trace-globals.lua trace assigments to global variables + xd.lua hex dump + diff --git a/contrib/syslinux-4.02/com32/lua/test/bisect.lua b/contrib/syslinux-4.02/com32/lua/test/bisect.lua new file mode 100644 index 0000000..f91e69b --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/test/bisect.lua @@ -0,0 +1,27 @@ +-- bisection method for solving non-linear equations + +delta=1e-6 -- tolerance + +function bisect(f,a,b,fa,fb) + local c=(a+b)/2 + io.write(n," c=",c," a=",a," b=",b,"\n") + if c==a or c==b or math.abs(a-b)<delta then return c,b-a end + n=n+1 + local fc=f(c) + if fa*fc<0 then return bisect(f,a,c,fa,fc) else return bisect(f,c,b,fc,fb) end +end + +-- find root of f in the inverval [a,b]. needs f(a)*f(b)<0 +function solve(f,a,b) + n=0 + local z,e=bisect(f,a,b,f(a),f(b)) + io.write(string.format("after %d steps, root is %.17g with error %.1e, f=%.1e\n",n,z,e,f(z))) +end + +-- our function +function f(x) + return x*x*x-x-1 +end + +-- find zero in [1,2] +solve(f,1,2) diff --git a/contrib/syslinux-4.02/com32/lua/test/cf.lua b/contrib/syslinux-4.02/com32/lua/test/cf.lua new file mode 100644 index 0000000..8cda54b --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/test/cf.lua @@ -0,0 +1,16 @@ +-- temperature conversion table (celsius to farenheit) + +for c0=-20,50-1,10 do + io.write("C ") + for c=c0,c0+10-1 do + io.write(string.format("%3.0f ",c)) + end + io.write("\n") + + io.write("F ") + for c=c0,c0+10-1 do + f=(9/5)*c+32 + io.write(string.format("%3.0f ",f)) + end + io.write("\n\n") +end diff --git a/contrib/syslinux-4.02/com32/lua/test/dmi.lua b/contrib/syslinux-4.02/com32/lua/test/dmi.lua new file mode 100644 index 0000000..0f5526c --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/test/dmi.lua @@ -0,0 +1,21 @@ +if (dmi.supported()) then + + dmitable = dmi.gettable() + + for k,v in pairs(dmitable) do + print(k, v) + end + + print(dmitable["system.manufacturer"]) + print(dmitable["system.product_name"]) + print(dmitable["bios.bios_revision"]) + + if ( string.match(dmitable["system.product_name"], "ESPRIMO P7935") ) then + print("Matches") + syslinux.run_command("memdisk initrd=/dos/BIOS/FSC-P7935-108.img raw") + else + print("Does not match") + end + +end + diff --git a/contrib/syslinux-4.02/com32/lua/test/echo.lua b/contrib/syslinux-4.02/com32/lua/test/echo.lua new file mode 100644 index 0000000..4313439 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/test/echo.lua @@ -0,0 +1,5 @@ +-- echo command line arguments + +for i=0,table.getn(arg) do + print(i,arg[i]) +end diff --git a/contrib/syslinux-4.02/com32/lua/test/env.lua b/contrib/syslinux-4.02/com32/lua/test/env.lua new file mode 100644 index 0000000..9e62a57 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/test/env.lua @@ -0,0 +1,7 @@ +-- read environment variables as if they were global variables + +local f=function (t,i) return os.getenv(i) end +setmetatable(getfenv(),{__index=f}) + +-- an example +print(a,USER,PATH) diff --git a/contrib/syslinux-4.02/com32/lua/test/factorial.lua b/contrib/syslinux-4.02/com32/lua/test/factorial.lua new file mode 100644 index 0000000..7c4cf0f --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/test/factorial.lua @@ -0,0 +1,32 @@ +-- function closures are powerful + +-- traditional fixed-point operator from functional programming +Y = function (g) + local a = function (f) return f(f) end + return a(function (f) + return g(function (x) + local c=f(f) + return c(x) + end) + end) +end + + +-- factorial without recursion +F = function (f) + return function (n) + if n == 0 then return 1 + else return n*f(n-1) end + end + end + +factorial = Y(F) -- factorial is the fixed point of F + +-- now test it +function test(x) + io.write(x,"! = ",factorial(x),"\n") +end + +for n=0,16 do + test(n) +end diff --git a/contrib/syslinux-4.02/com32/lua/test/fib.lua b/contrib/syslinux-4.02/com32/lua/test/fib.lua new file mode 100644 index 0000000..97a921b --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/test/fib.lua @@ -0,0 +1,40 @@ +-- fibonacci function with cache + +-- very inefficient fibonacci function +function fib(n) + N=N+1 + if n<2 then + return n + else + return fib(n-1)+fib(n-2) + end +end + +-- a general-purpose value cache +function cache(f) + local c={} + return function (x) + local y=c[x] + if not y then + y=f(x) + c[x]=y + end + return y + end +end + +-- run and time it +function test(s,f) + N=0 + local c=os.clock() + local v=f(n) + local t=os.clock()-c + print(s,n,v,t,N) +end + +n=arg[1] or 24 -- for other values, do lua fib.lua XX +n=tonumber(n) +print("","n","value","time","evals") +test("plain",fib) +fib=cache(fib) +test("cached",fib) diff --git a/contrib/syslinux-4.02/com32/lua/test/fibfor.lua b/contrib/syslinux-4.02/com32/lua/test/fibfor.lua new file mode 100644 index 0000000..8bbba39 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/test/fibfor.lua @@ -0,0 +1,13 @@ +-- example of for with generator functions + +function generatefib (n) + return coroutine.wrap(function () + local a,b = 1, 1 + while a <= n do + coroutine.yield(a) + a, b = b, a+b + end + end) +end + +for i in generatefib(1000) do print(i) end diff --git a/contrib/syslinux-4.02/com32/lua/test/globals.lua b/contrib/syslinux-4.02/com32/lua/test/globals.lua new file mode 100644 index 0000000..d4c20e1 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/test/globals.lua @@ -0,0 +1,13 @@ +-- reads luac listings and reports global variable usage +-- lines where a global is written to are marked with "*" +-- typical usage: luac -p -l file.lua | lua globals.lua | sort | lua table.lua + +while 1 do + local s=io.read() + if s==nil then break end + local ok,_,l,op,g=string.find(s,"%[%-?(%d*)%]%s*([GS])ETGLOBAL.-;%s+(.*)$") + if ok then + if op=="S" then op="*" else op="" end + io.write(g,"\t",l,op,"\n") + end +end diff --git a/contrib/syslinux-4.02/com32/lua/test/hello.lua b/contrib/syslinux-4.02/com32/lua/test/hello.lua new file mode 100644 index 0000000..0925498 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/test/hello.lua @@ -0,0 +1,3 @@ +-- the first program in every language + +io.write("Hello world, from ",_VERSION,"!\n") diff --git a/contrib/syslinux-4.02/com32/lua/test/life.lua b/contrib/syslinux-4.02/com32/lua/test/life.lua new file mode 100644 index 0000000..911d9fe --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/test/life.lua @@ -0,0 +1,111 @@ +-- life.lua +-- original by Dave Bollinger <DBollinger@compuserve.com> posted to lua-l +-- modified to use ANSI terminal escape sequences +-- modified to use for instead of while + +local write=io.write + +ALIVE="¥" DEAD="þ" +ALIVE="O" DEAD="-" + +function delay() -- NOTE: SYSTEM-DEPENDENT, adjust as necessary + for i=1,10000 do end + -- local i=os.clock()+1 while(os.clock()<i) do end +end + +function ARRAY2D(w,h) + local t = {w=w,h=h} + for y=1,h do + t[y] = {} + for x=1,w do + t[y][x]=0 + end + end + return t +end + +_CELLS = {} + +-- give birth to a "shape" within the cell array +function _CELLS:spawn(shape,left,top) + for y=0,shape.h-1 do + for x=0,shape.w-1 do + self[top+y][left+x] = shape[y*shape.w+x+1] + end + end +end + +-- run the CA and produce the next generation +function _CELLS:evolve(next) + local ym1,y,yp1,yi=self.h-1,self.h,1,self.h + while yi > 0 do + local xm1,x,xp1,xi=self.w-1,self.w,1,self.w + while xi > 0 do + local sum = self[ym1][xm1] + self[ym1][x] + self[ym1][xp1] + + self[y][xm1] + self[y][xp1] + + self[yp1][xm1] + self[yp1][x] + self[yp1][xp1] + next[y][x] = ((sum==2) and self[y][x]) or ((sum==3) and 1) or 0 + xm1,x,xp1,xi = x,xp1,xp1+1,xi-1 + end + ym1,y,yp1,yi = y,yp1,yp1+1,yi-1 + end +end + +-- output the array to screen +function _CELLS:draw() + local out="" -- accumulate to reduce flicker + for y=1,self.h do + for x=1,self.w do + out=out..(((self[y][x]>0) and ALIVE) or DEAD) + end + out=out.."\n" + end + write(out) +end + +-- constructor +function CELLS(w,h) + local c = ARRAY2D(w,h) + c.spawn = _CELLS.spawn + c.evolve = _CELLS.evolve + c.draw = _CELLS.draw + return c +end + +-- +-- shapes suitable for use with spawn() above +-- +HEART = { 1,0,1,1,0,1,1,1,1; w=3,h=3 } +GLIDER = { 0,0,1,1,0,1,0,1,1; w=3,h=3 } +EXPLODE = { 0,1,0,1,1,1,1,0,1,0,1,0; w=3,h=4 } +FISH = { 0,1,1,1,1,1,0,0,0,1,0,0,0,0,1,1,0,0,1,0; w=5,h=4 } +BUTTERFLY = { 1,0,0,0,1,0,1,1,1,0,1,0,0,0,1,1,0,1,0,1,1,0,0,0,1; w=5,h=5 } + +-- the main routine +function LIFE(w,h) + -- create two arrays + local thisgen = CELLS(w,h) + local nextgen = CELLS(w,h) + + -- create some life + -- about 1000 generations of fun, then a glider steady-state + thisgen:spawn(GLIDER,5,4) + thisgen:spawn(EXPLODE,25,10) + thisgen:spawn(FISH,4,12) + + -- run until break + local gen=1 + write("\027[2J") -- ANSI clear screen + while 1 do + thisgen:evolve(nextgen) + thisgen,nextgen = nextgen,thisgen + write("\027[H") -- ANSI home cursor + thisgen:draw() + write("Life - generation ",gen,"\n") + gen=gen+1 + if gen>2000 then break end + --delay() -- no delay + end +end + +LIFE(40,20) diff --git a/contrib/syslinux-4.02/com32/lua/test/luac.lua b/contrib/syslinux-4.02/com32/lua/test/luac.lua new file mode 100644 index 0000000..96a0a97 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/test/luac.lua @@ -0,0 +1,7 @@ +-- bare-bones luac in Lua +-- usage: lua luac.lua file.lua + +assert(arg[1]~=nil and arg[2]==nil,"usage: lua luac.lua file.lua") +f=assert(io.open("luac.out","wb")) +assert(f:write(string.dump(assert(loadfile(arg[1]))))) +assert(f:close()) diff --git a/contrib/syslinux-4.02/com32/lua/test/pci.lua b/contrib/syslinux-4.02/com32/lua/test/pci.lua new file mode 100644 index 0000000..8d7f7d4 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/test/pci.lua @@ -0,0 +1,34 @@ +-- get nice output +printf = function(s,...) + return io.write(s:format(...)) + end + +-- get device info +pciinfo = pci.getinfo() + +-- get plain text device description +pciids = pci.getidlist("/pci.ids") + +-- list all pci busses +for dind,device in pairs(pciinfo) do + + -- search for device description + search = string.format("%04x%04x", device['vendor'], device['product']) + + printf(" %04x:%04x:%04x:%04x = ", device['vendor'], device['product'], + device['sub_vendor'], device['sub_product']) + + if ( pciids[search] ) then + printf("%s\n", pciids[search]) + else + printf("Unknown\n") + end +end + +-- print(pciids["8086"]) +-- print(pciids["10543009"]) +-- print(pciids["00700003"]) +-- print(pciids["0070e817"]) +-- print(pciids["1002437a1002437a"]) + + diff --git a/contrib/syslinux-4.02/com32/lua/test/printf.lua b/contrib/syslinux-4.02/com32/lua/test/printf.lua new file mode 100644 index 0000000..58c63ff --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/test/printf.lua @@ -0,0 +1,7 @@ +-- an implementation of printf + +function printf(...) + io.write(string.format(...)) +end + +printf("Hello %s from %s on %s\n",os.getenv"USER" or "there",_VERSION,os.date()) diff --git a/contrib/syslinux-4.02/com32/lua/test/readonly.lua b/contrib/syslinux-4.02/com32/lua/test/readonly.lua new file mode 100644 index 0000000..85c0b4e --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/test/readonly.lua @@ -0,0 +1,12 @@ +-- make global variables readonly + +local f=function (t,i) error("cannot redefine global variable `"..i.."'",2) end +local g={} +local G=getfenv() +setmetatable(g,{__index=G,__newindex=f}) +setfenv(1,g) + +-- an example +rawset(g,"x",3) +x=2 +y=1 -- cannot redefine `y' diff --git a/contrib/syslinux-4.02/com32/lua/test/sieve.lua b/contrib/syslinux-4.02/com32/lua/test/sieve.lua new file mode 100644 index 0000000..0871bb2 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/test/sieve.lua @@ -0,0 +1,29 @@ +-- the sieve of of Eratosthenes programmed with coroutines +-- typical usage: lua -e N=1000 sieve.lua | column + +-- generate all the numbers from 2 to n +function gen (n) + return coroutine.wrap(function () + for i=2,n do coroutine.yield(i) end + end) +end + +-- filter the numbers generated by `g', removing multiples of `p' +function filter (p, g) + return coroutine.wrap(function () + while 1 do + local n = g() + if n == nil then return end + if math.mod(n, p) ~= 0 then coroutine.yield(n) end + end + end) +end + +N=N or 1000 -- from command line +x = gen(N) -- generate primes up to N +while 1 do + local n = x() -- pick a number until done + if n == nil then break end + print(n) -- must be a prime number + x = filter(n, x) -- now remove its multiples +end diff --git a/contrib/syslinux-4.02/com32/lua/test/sort.lua b/contrib/syslinux-4.02/com32/lua/test/sort.lua new file mode 100644 index 0000000..0bcb15f --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/test/sort.lua @@ -0,0 +1,66 @@ +-- two implementations of a sort function +-- this is an example only. Lua has now a built-in function "sort" + +-- extracted from Programming Pearls, page 110 +function qsort(x,l,u,f) + if l<u then + local m=math.random(u-(l-1))+l-1 -- choose a random pivot in range l..u + x[l],x[m]=x[m],x[l] -- swap pivot to first position + local t=x[l] -- pivot value + m=l + local i=l+1 + while i<=u do + -- invariant: x[l+1..m] < t <= x[m+1..i-1] + if f(x[i],t) then + m=m+1 + x[m],x[i]=x[i],x[m] -- swap x[i] and x[m] + end + i=i+1 + end + x[l],x[m]=x[m],x[l] -- swap pivot to a valid place + -- x[l+1..m-1] < x[m] <= x[m+1..u] + qsort(x,l,m-1,f) + qsort(x,m+1,u,f) + end +end + +function selectionsort(x,n,f) + local i=1 + while i<=n do + local m,j=i,i+1 + while j<=n do + if f(x[j],x[m]) then m=j end + j=j+1 + end + x[i],x[m]=x[m],x[i] -- swap x[i] and x[m] + i=i+1 + end +end + +function show(m,x) + io.write(m,"\n\t") + local i=1 + while x[i] do + io.write(x[i]) + i=i+1 + if x[i] then io.write(",") end + end + io.write("\n") +end + +function testsorts(x) + local n=1 + while x[n] do n=n+1 end; n=n-1 -- count elements + show("original",x) + qsort(x,1,n,function (x,y) return x<y end) + show("after quicksort",x) + selectionsort(x,n,function (x,y) return x>y end) + show("after reverse selection sort",x) + qsort(x,1,n,function (x,y) return x<y end) + show("after quicksort again",x) +end + +-- array to be sorted +x={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"} + +testsorts(x) diff --git a/contrib/syslinux-4.02/com32/lua/test/syslinux-derivative.lua b/contrib/syslinux-4.02/com32/lua/test/syslinux-derivative.lua new file mode 100644 index 0000000..fbdf5d5 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/test/syslinux-derivative.lua @@ -0,0 +1,38 @@ +-- get nice output +printf = function(s,...) + return io.write(s:format(...)) + end + +-- get syslinux derivative (ISOLINUX, PXELINUX, SYSLINUX) +derivative = syslinux.derivative() + +printf("Run specific command depending on the Syslinux derivate:\n") +printf("--------------------------------------------------------\n\n") +printf(" Detected Syslinux derivative: %s\n", derivative) + +if derivative == "SYSLINUX" then + -- swap internal (hd1) hard drive with USB stick (hd0) + commandline = 'chain.c32 hd1 swap' +elseif derivative == "ISOLINUX" then + -- boot first hard drive + commandline = 'chain.c32 hd0' +elseif derivative == "PXELINUX" then + -- boot first hard drive + commandline = 'chain.c32 hd0' +else + printf("Do nothing\n") + return 1 +end + +printf("\n commandline for derivative: %s\n\n", commandline) + + +-- Count down from 7 +for time = 7, 1, -1 do + printf(" Boot in %d second(s)... \r", time) + syslinux.sleep(1) +end + +-- Boot +syslinux.run_command(commandline) + diff --git a/contrib/syslinux-4.02/com32/lua/test/syslinux.lua b/contrib/syslinux-4.02/com32/lua/test/syslinux.lua new file mode 100644 index 0000000..3f72ebe --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/test/syslinux.lua @@ -0,0 +1 @@ +syslinux.run_command("memdisk initrd=/dos/BIOS/FSC-P7935-108.img raw") diff --git a/contrib/syslinux-4.02/com32/lua/test/table.lua b/contrib/syslinux-4.02/com32/lua/test/table.lua new file mode 100644 index 0000000..235089c --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/test/table.lua @@ -0,0 +1,12 @@ +-- make table, grouping all data for the same item +-- input is 2 columns (item, data) + +local A +while 1 do + local l=io.read() + if l==nil then break end + local _,_,a,b=string.find(l,'"?([_%w]+)"?%s*(.*)$') + if a~=A then A=a io.write("\n",a,":") end + io.write(" ",b) +end +io.write("\n") diff --git a/contrib/syslinux-4.02/com32/lua/test/trace-calls.lua b/contrib/syslinux-4.02/com32/lua/test/trace-calls.lua new file mode 100644 index 0000000..6d7a7b3 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/test/trace-calls.lua @@ -0,0 +1,32 @@ +-- trace calls +-- example: lua -ltrace-calls bisect.lua + +local level=0 + +local function hook(event) + local t=debug.getinfo(3) + io.write(level," >>> ",string.rep(" ",level)) + if t~=nil and t.currentline>=0 then io.write(t.short_src,":",t.currentline," ") end + t=debug.getinfo(2) + if event=="call" then + level=level+1 + else + level=level-1 if level<0 then level=0 end + end + if t.what=="main" then + if event=="call" then + io.write("begin ",t.short_src) + else + io.write("end ",t.short_src) + end + elseif t.what=="Lua" then +-- table.foreach(t,print) + io.write(event," ",t.name or "(Lua)"," <",t.linedefined,":",t.short_src,">") + else + io.write(event," ",t.name or "(C)"," [",t.what,"] ") + end + io.write("\n") +end + +debug.sethook(hook,"cr") +level=0 diff --git a/contrib/syslinux-4.02/com32/lua/test/trace-globals.lua b/contrib/syslinux-4.02/com32/lua/test/trace-globals.lua new file mode 100644 index 0000000..295e670 --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/test/trace-globals.lua @@ -0,0 +1,38 @@ +-- trace assigments to global variables + +do + -- a tostring that quotes strings. note the use of the original tostring. + local _tostring=tostring + local tostring=function(a) + if type(a)=="string" then + return string.format("%q",a) + else + return _tostring(a) + end + end + + local log=function (name,old,new) + local t=debug.getinfo(3,"Sl") + local line=t.currentline + io.write(t.short_src) + if line>=0 then io.write(":",line) end + io.write(": ",name," is now ",tostring(new)," (was ",tostring(old),")","\n") + end + + local g={} + local set=function (t,name,value) + log(name,g[name],value) + g[name]=value + end + setmetatable(getfenv(),{__index=g,__newindex=set}) +end + +-- an example + +a=1 +b=2 +a=10 +b=20 +b=nil +b=200 +print(a,b,c) diff --git a/contrib/syslinux-4.02/com32/lua/test/vesa.lua b/contrib/syslinux-4.02/com32/lua/test/vesa.lua new file mode 100644 index 0000000..8913acc --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/test/vesa.lua @@ -0,0 +1,55 @@ +-- get nice output +printf = function(s,...) + return io.write(s:format(...)) + end + +-- list available vesa modes +-- only one supported right now, not of much use +modes = vesa.getmodes() + +for mind,mode in pairs(modes) do + printf("%04x: %dx%dx%d\n", mode['mode'], mode['hres'], mode['vres'], mode['bpp']) +end + +printf("Hello World! - text mode") + +-- lets go to graphics land +vesa.setmode() + +printf("Hello World! - VESA mode") + +syslinux.sleep(1) + +-- some text to display "typing style" +textline=[[ + +From syslinux GSOC 2009 home page: + +Finish the Lua engine + +We already have a Lua interpreter integrated with the Syslinux build. However, right now it is not very useful. We need to create a set of bindings to the Syslinux functionality, and have an array of documentation and examples so users can use them. + +This is not a documentation project, but the documentation deliverable will be particularly important for this one, since the intended target is system administrators, not developers. +]] + + +-- do display loop +-- keep in mind: background change will not erase text! +while ( true ) do + +vesa.load_background("/PXE-RRZE_small.jpg") + +syslinux.sleep(1) + +for i = 1, #textline do + local c = textline:sub(i,i) + printf("%s", c) + syslinux.msleep(200) +end + +syslinux.sleep(10) + +vesa.load_background("/sample2.jpg") +syslinux.sleep(10) + +end diff --git a/contrib/syslinux-4.02/com32/lua/test/xd.lua b/contrib/syslinux-4.02/com32/lua/test/xd.lua new file mode 100644 index 0000000..ebc3eff --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/test/xd.lua @@ -0,0 +1,14 @@ +-- hex dump +-- usage: lua xd.lua < file + +local offset=0 +while true do + local s=io.read(16) + if s==nil then return end + io.write(string.format("%08X ",offset)) + string.gsub(s,"(.)", + function (c) io.write(string.format("%02X ",string.byte(c))) end) + io.write(string.rep(" ",3*(16-string.len(s)))) + io.write(" ",string.gsub(s,"%c","."),"\n") + offset=offset+16 +end diff --git a/contrib/syslinux-4.02/com32/mboot/Makefile b/contrib/syslinux-4.02/com32/mboot/Makefile new file mode 100644 index 0000000..7e6c2e9 --- /dev/null +++ b/contrib/syslinux-4.02/com32/mboot/Makefile @@ -0,0 +1,46 @@ +## ----------------------------------------------------------------------- +## +## Copyright 2001-2009 H. Peter Anvin - All Rights Reserved +## Copyright 2009 Intel Corporation; author: H. Peter Anvin +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, +## Boston MA 02110-1301, USA; either version 2 of the License, or +## (at your option) any later version; incorporated herein by reference. +## +## ----------------------------------------------------------------------- + +## +## Multiboot module +## + +topdir = ../.. +include ../MCONFIG + +LIBS = ../libutil/libutil_com.a ../lib/libcom32.a $(LIBGCC) +LNXLIBS = ../libutil/libutil_lnx.a + +MODULES = mboot.c32 +TESTFILES = + +OBJS = mboot.o map.o mem.o initvesa.o apm.o solaris.o syslinux.o + +all: $(MODULES) $(TESTFILES) + +mboot.elf : $(OBJS) $(LIBS) $(C_LIBS) + $(LD) $(LDFLAGS) -o $@ $^ + +tidy dist: + rm -f *.o *.lo *.a *.lst *.elf .*.d *.tmp + +clean: tidy + rm -f *.lnx + +spotless: clean + rm -f *.lss *.c32 *.com + rm -f *~ \#* + +install: + +-include .*.d diff --git a/contrib/syslinux-4.02/com32/mboot/apm.c b/contrib/syslinux-4.02/com32/mboot/apm.c new file mode 100644 index 0000000..3f48af7 --- /dev/null +++ b/contrib/syslinux-4.02/com32/mboot/apm.c @@ -0,0 +1,86 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * Based on code from the Linux kernel: + * + * Copyright (C) 1991, 1992 Linus Torvalds + * Copyright 2007 rPath, Inc. - All Rights Reserved + * + * Original APM BIOS checking by Stephen Rothwell, May 1994 + * (sfr@canb.auug.org.au) + * + * This file is part of the Linux kernel, and is made available under + * the terms of the GNU General Public License version 2. + * + * ----------------------------------------------------------------------- */ + +/* + * apm.c + * + * APM information for Multiboot + */ + +#include "mboot.h" +#include <com32.h> + +void mboot_apm(void) +{ + static struct apm_info apm; + com32sys_t ireg, oreg; + + memset(&ireg, 0, sizeof ireg); + + ireg.eax.w[0] = 0x5300; + __intcall(0x15, &ireg, &oreg); + + if (oreg.eflags.l & EFLAGS_CF) + return; /* No APM BIOS */ + + if (oreg.ebx.w[0] != 0x504d) + return; /* No "PM" signature */ + + if (!(oreg.ecx.w[0] & 0x02)) + return; /* 32 bits not supported */ + + /* Disconnect first, just in case */ + ireg.eax.b[0] = 0x04; + __intcall(0x15, &ireg, &oreg); + + /* 32-bit connect */ + ireg.eax.b[0] = 0x03; + __intcall(0x15, &ireg, &oreg); + + apm.cseg = oreg.eax.w[0]; + apm.offset = oreg.ebx.l; + apm.cseg_16 = oreg.ecx.w[0]; + apm.dseg_16 = oreg.edx.w[0]; + apm.cseg_len = oreg.esi.w[0]; + apm.cseg_16_len = oreg.esi.w[1]; + apm.dseg_16_len = oreg.edi.w[0]; + + /* Redo the installation check as the 32-bit connect; + some BIOSes return different flags this way... */ + + ireg.eax.b[0] = 0x00; + __intcall(0x15, &ireg, &oreg); + + if ((oreg.eflags.l & EFLAGS_CF) || (oreg.ebx.w[0] != 0x504d)) { + /* Failure with 32-bit connect, try to disconect and ignore */ + ireg.eax.b[0] = 0x04; + __intcall(0x15, &ireg, NULL); + return; + } + + apm.version = oreg.eax.w[0]; + + mbinfo.apm_table = map_data(&apm, sizeof apm, 4, false); + if (mbinfo.apm_table) + mbinfo.flags |= MB_INFO_APM_TABLE; +} diff --git a/contrib/syslinux-4.02/com32/mboot/initvesa.c b/contrib/syslinux-4.02/com32/mboot/initvesa.c new file mode 100644 index 0000000..cf2707d --- /dev/null +++ b/contrib/syslinux-4.02/com32/mboot/initvesa.c @@ -0,0 +1,226 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1999-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * initvesa.c + * + * Query the VESA BIOS and select a 640x480x32 mode with local mapping + * support, if one exists. + */ + +#include <inttypes.h> +#include <com32.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> + +#include "vesa.h" +#include "mboot.h" + +struct vesa_info vesa_info; + +void set_graphics_mode(const struct multiboot_header *mbh, + struct multiboot_info *mbi) +{ + com32sys_t rm; + uint16_t mode, bestmode, *mode_ptr; + struct vesa_general_info *gi; + struct vesa_mode_info *mi; + int pxf, bestpxf; + int wantx, wanty; + int err, besterr; + bool better; + addr_t viaddr; + + /* Only do this if requested by the OS image */ + if (!(mbh->flags & MULTIBOOT_VIDEO_MODE) || mbh->mode_type != 0) + return; + + /* Allocate space in the bounce buffer for these structures */ + gi = &((struct vesa_info *)__com32.cs_bounce)->gi; + mi = &((struct vesa_info *)__com32.cs_bounce)->mi; + + memset(&rm, 0, sizeof rm); + memset(gi, 0, sizeof *gi); + + gi->signature = VBE2_MAGIC; /* Get VBE2 extended data */ + rm.eax.w[0] = 0x4F00; /* Get SVGA general information */ + rm.edi.w[0] = OFFS(gi); + rm.es = SEG(gi); + __intcall(0x10, &rm, &rm); + + if (rm.eax.w[0] != 0x004F) + return; /* Function call failed */ + if (gi->signature != VESA_MAGIC) + return; /* No magic */ + if (gi->version < 0x0102) + return; /* VESA 1.2+ required */ + + memcpy(&vesa_info.gi, gi, sizeof *gi); + + /* Search for a suitable mode with a suitable color and memory model... */ + + mode_ptr = GET_PTR(gi->video_mode_ptr); + bestmode = 0; + bestpxf = 0; + wantx = mbh->width ? mbh->width : 0xffff; + wanty = mbh->height ? mbh->height : 0xffff; + besterr = wantx + wanty; + + while ((mode = *mode_ptr++) != 0xFFFF) { + mode &= 0x1FF; /* The rest are attributes of sorts */ + + memset(mi, 0, sizeof *mi); + rm.eax.w[0] = 0x4F01; /* Get SVGA mode information */ + rm.ecx.w[0] = mode; + rm.edi.w[0] = OFFS(mi); + rm.es = SEG(mi); + __intcall(0x10, &rm, &rm); + + /* Must be a supported mode */ + if (rm.eax.w[0] != 0x004f) + continue; + + /* Must be an LFB color graphics mode supported by the hardware. + + The bits tested are: + 7 - linear frame buffer + 4 - graphics mode + 3 - color mode + 1 - mode information available (mandatory in VBE 1.2+) + 0 - mode supported by hardware + */ + if ((mi->mode_attr & 0x009b) != 0x009b) + continue; + + /* We don't support multibank (interlaced memory) modes */ + /* + * Note: The Bochs VESA BIOS (vbe.c 1.58 2006/08/19) violates the + * specification which states that banks == 1 for unbanked modes; + * fortunately it does report bank_size == 0 for those. + */ + if (mi->banks > 1 && mi->bank_size) + continue; + + /* Must either be a packed-pixel mode or a direct color mode + (depending on VESA version ); must be a supported pixel format */ + + if (mi->bpp == 32 && + (mi->memory_layout == 4 || + (mi->memory_layout == 6 && mi->rpos == 16 && mi->gpos == 8 && + mi->bpos == 0))) + pxf = 32; + else if (mi->bpp == 24 && + (mi->memory_layout == 4 || + (mi->memory_layout == 6 && mi->rpos == 16 && mi->gpos == 8 && + mi->bpos == 0))) + pxf = 24; + else if (mi->bpp == 16 && + (mi->memory_layout == 4 || + (mi->memory_layout == 6 && mi->rpos == 11 && mi->gpos == 5 && + mi->bpos == 0))) + pxf = 16; + else if (mi->bpp == 15 && + (mi->memory_layout == 4 || + (mi->memory_layout == 6 && mi->rpos == 10 && mi->gpos == 5 && + mi->bpos == 0))) + pxf = 15; + else + continue; + + better = false; + err = abs(mi->h_res - wantx) + abs(mi->v_res - wanty); + +#define IS_GOOD(mi, bestx, besty) \ + ((mi)->h_res >= (bestx) && (mi)->v_res >= (besty)) + + if (!bestpxf) + better = true; + else if (!IS_GOOD(&vesa_info.mi, wantx, wanty) && + IS_GOOD(mi, wantx, wanty)) + /* This matches criteria, which the previous one didn't */ + better = true; + else if (IS_GOOD(&vesa_info.mi, wantx, wanty) && + !IS_GOOD(mi, wantx, wanty)) + /* This doesn't match criteria, and the previous one did */ + better = false; + else if (err < besterr) + better = true; + else if (err == besterr && (pxf == (int)mbh->depth || pxf > bestpxf)) + better = true; + + if (better) { + bestmode = mode; + bestpxf = pxf; + memcpy(&vesa_info.mi, mi, sizeof *mi); + } + } + + if (!bestpxf) + return; /* No mode found */ + + mi = &vesa_info.mi; + mode = bestmode; + + /* Now set video mode */ + rm.eax.w[0] = 0x4F02; /* Set SVGA video mode */ + mode |= 0x4000; /* Request linear framebuffer */ + rm.ebx.w[0] = mode; + __intcall(0x10, &rm, &rm); + if (rm.eax.w[0] != 0x004F) + return; /* Failed to set mode */ + + mbi->flags |= MB_INFO_VIDEO_INFO; + mbi->vbe_mode = mode; + viaddr = map_data(&vesa_info, sizeof vesa_info, 4, 0); + mbi->vbe_control_info = viaddr + offsetof(struct vesa_info, gi); + mbi->vbe_mode_info = viaddr + offsetof(struct vesa_info, mi); + + /* Get the VBE 2.x PM entry point if supported */ + rm.eax.w[0] = 0x4F0A; + rm.ebx.w[0] = 0; + __intcall(0x10, &rm, &rm); + if (rm.eax.w[0] == 0x004F) { + mbi->vbe_interface_seg = rm.es; + mbi->vbe_interface_off = rm.edi.w[0]; + mbi->vbe_interface_len = rm.ecx.w[0]; + } + + /* Tell syslinux we changed video mode */ + rm.eax.w[0] = 0x0017; /* Report video mode change */ + /* In theory this should be: + + rm.ebx.w[0] = (mi->mode_attr & 4) ? 0x0007 : 0x000f; + + However, that would assume all systems that claim to handle text + output in VESA modes actually do that... */ + rm.ebx.w[0] = 0x000f; + rm.ecx.w[0] = vesa_info.mi.h_res; + rm.edx.w[0] = vesa_info.mi.v_res; + __intcall(0x22, &rm, NULL); +} diff --git a/contrib/syslinux-4.02/com32/mboot/map.c b/contrib/syslinux-4.02/com32/mboot/map.c new file mode 100644 index 0000000..0a71d4c --- /dev/null +++ b/contrib/syslinux-4.02/com32/mboot/map.c @@ -0,0 +1,353 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * map.c + * + * Functions that deal with the memory map of various objects + */ + +#include "mboot.h" + +static struct syslinux_movelist *ml = NULL; +static struct syslinux_memmap *mmap = NULL, *amap = NULL; +static addr_t mboot_high_water_mark = 0x100000; + +/* + * Note: although there is no such thing in the spec, at least Xen makes + * assumptions as to where in the memory space Grub would have loaded + * certain things. To support that, if "high" is set, then allocate this + * at an address strictly above any previous allocations. + * + * As a precaution, this also pads the data with zero up to the next + * alignment datum. + */ +addr_t map_data(const void *data, size_t len, size_t align, int flags) +{ + addr_t start = (flags & MAP_HIGH) ? mboot_high_water_mark : 0x2000; + addr_t pad = (flags & MAP_NOPAD) ? 0 : -len & (align - 1); + addr_t xlen = len + pad; + + if (syslinux_memmap_find(amap, SMT_FREE, &start, &xlen, align) || + syslinux_add_memmap(&amap, start, len + pad, SMT_ALLOC) || + syslinux_add_movelist(&ml, start, (addr_t) data, len) || + (pad && syslinux_add_memmap(&mmap, start + len, pad, SMT_ZERO))) { + printf("Cannot map %zu bytes\n", len + pad); + return 0; + } + + dprintf("Mapping 0x%08x bytes (%#x pad) at 0x%08x\n", len, pad, start); + + if (start + len + pad > mboot_high_water_mark) + mboot_high_water_mark = start + len + pad; + + return start; +} + +addr_t map_string(const char *string) +{ + if (!string) + return 0; + else + return map_data(string, strlen(string) + 1, 1, 0); +} + +int init_map(void) +{ + /* + * Note: mmap is the memory map (containing free and zeroed regions) + * needed by syslinux_shuffle_boot_pm(); amap is a map where we keep + * track ourselves which target memory ranges have already been + * allocated. + */ + mmap = syslinux_memory_map(); + amap = syslinux_dup_memmap(mmap); + if (!mmap || !amap) { + error("Failed to allocate initial memory map!\n"); + return -1; + } +#if DEBUG + dprintf("Initial memory map:\n"); + syslinux_dump_memmap(stdout, mmap); +#endif + + return 0; +} + +struct multiboot_header *map_image(void *ptr, size_t len) +{ + struct multiboot_header *mbh; + int mbh_len; + char *cptr = ptr; + Elf32_Ehdr *eh = ptr; + Elf32_Phdr *ph; + Elf32_Shdr *sh; + unsigned int i, mbh_offset; + uint32_t bad_flags; + + /* + * Search for the multiboot header... + */ + mbh_len = 0; + for (mbh_offset = 0; mbh_offset < MULTIBOOT_SEARCH; mbh_offset += 4) { + mbh = (struct multiboot_header *)((char *)ptr + mbh_offset); + if (mbh->magic != MULTIBOOT_MAGIC) + continue; + if (mbh->magic + mbh->flags + mbh->checksum) + continue; + if (mbh->flags & MULTIBOOT_VIDEO_MODE) + mbh_len = 48; + else if (mbh->flags & MULTIBOOT_AOUT_KLUDGE) + mbh_len = 32; + else + mbh_len = 12; + + if (mbh_offset + mbh_len > len) + mbh_len = 0; /* Invalid... */ + else + break; /* Found something... */ + } + + if (mbh_len) { + bad_flags = mbh->flags & MULTIBOOT_UNSUPPORTED; + if (bad_flags) { + printf("Unsupported Multiboot flags set: %#x\n", bad_flags); + return NULL; + } + } + + if (len < sizeof(Elf32_Ehdr) || + memcmp(eh->e_ident, "\x7f" "ELF\1\1\1", 6) || + (eh->e_machine != EM_386 && eh->e_machine != EM_486 && + eh->e_machine != EM_X86_64) || + eh->e_version != EV_CURRENT || + eh->e_ehsize < sizeof(Elf32_Ehdr) || eh->e_ehsize >= len || + eh->e_phentsize < sizeof(Elf32_Phdr) || + !eh->e_phnum || eh->e_phoff + eh->e_phentsize * eh->e_phnum > len) + eh = NULL; /* No valid ELF header found */ + + /* Is this a Solaris kernel? */ + if (!set.solaris && eh && kernel_is_solaris(eh)) + opt.solaris = true; + + /* + * Note: the Multiboot Specification implies that AOUT_KLUDGE should + * have precedence over the ELF header. However, Grub disagrees, and + * Grub is "the reference bootloader" for the Multiboot Specification. + * This is insane, since it makes the AOUT_KLUDGE bit functionally + * useless, but at least Solaris apparently depends on this behavior. + */ + if (eh && !(opt.aout && mbh_len && (mbh->flags & MULTIBOOT_AOUT_KLUDGE))) { + regs.eip = eh->e_entry; /* Can be overridden further down... */ + + ph = (Elf32_Phdr *) (cptr + eh->e_phoff); + + for (i = 0; i < eh->e_phnum; i++) { + if (ph->p_type == PT_LOAD || ph->p_type == PT_PHDR) { + /* + * This loads at p_paddr, which matches Grub. However, if + * e_entry falls within the p_vaddr range of this PHDR, then + * adjust it to match the p_paddr range... this is how Grub + * behaves, so it's by definition correct (it doesn't have to + * make sense...) + */ + addr_t addr = ph->p_paddr; + addr_t msize = ph->p_memsz; + addr_t dsize = min(msize, ph->p_filesz); + + if (eh->e_entry >= ph->p_vaddr + && eh->e_entry < ph->p_vaddr + msize) + regs.eip = eh->e_entry + (ph->p_paddr - ph->p_vaddr); + + dprintf("Segment at 0x%08x data 0x%08x len 0x%08x\n", + addr, dsize, msize); + + if (syslinux_memmap_type(amap, addr, msize) != SMT_FREE) { + printf + ("Memory segment at 0x%08x (len 0x%08x) is unavailable\n", + addr, msize); + return NULL; /* Memory region unavailable */ + } + + /* Mark this region as allocated in the available map */ + if (syslinux_add_memmap(&amap, addr, msize, SMT_ALLOC)) { + error("Overlapping segments found in ELF header\n"); + return NULL; + } + + if (ph->p_filesz) { + /* Data present region. Create a move entry for it. */ + if (syslinux_add_movelist + (&ml, addr, (addr_t) cptr + ph->p_offset, dsize)) { + error("Failed to map PHDR data\n"); + return NULL; + } + } + if (msize > dsize) { + /* Zero-filled region. Mark as a zero region in the memory map. */ + if (syslinux_add_memmap + (&mmap, addr + dsize, msize - dsize, SMT_ZERO)) { + error("Failed to map PHDR zero region\n"); + return NULL; + } + } + if (addr + msize > mboot_high_water_mark) + mboot_high_water_mark = addr + msize; + } else { + /* Ignore this program header */ + } + + ph = (Elf32_Phdr *) ((char *)ph + eh->e_phentsize); + } + + /* Load the ELF symbol table */ + if (eh->e_shoff) { + addr_t addr, len; + + sh = (Elf32_Shdr *) ((char *)eh + eh->e_shoff); + + len = eh->e_shentsize * eh->e_shnum; + /* + * Align this, but don't pad -- in general this means a bunch of + * smaller sections gets packed into a single page. + */ + addr = map_data(sh, len, 4096, MAP_HIGH | MAP_NOPAD); + if (!addr) { + error("Failed to map symbol table\n"); + return NULL; + } + + mbinfo.flags |= MB_INFO_ELF_SHDR; + mbinfo.syms.e.addr = addr; + mbinfo.syms.e.num = eh->e_shnum; + mbinfo.syms.e.size = eh->e_shentsize; + mbinfo.syms.e.shndx = eh->e_shstrndx; + + for (i = 0; i < eh->e_shnum; i++) { + addr_t align; + + if (!sh[i].sh_size) + continue; /* Empty section */ + if (sh[i].sh_flags & SHF_ALLOC) + continue; /* SHF_ALLOC sections should have PHDRs */ + + align = sh[i].sh_addralign ? sh[i].sh_addralign : 0; + addr = map_data((char *)ptr + sh[i].sh_offset, sh[i].sh_size, + align, MAP_HIGH); + if (!addr) { + error("Failed to map symbol section\n"); + return NULL; + } + sh[i].sh_addr = addr; + } + } + } else if (mbh_len && (mbh->flags & MULTIBOOT_AOUT_KLUDGE)) { + /* + * a.out kludge thing... + */ + char *data_ptr; + addr_t data_len, bss_len; + addr_t bss_addr; + + regs.eip = mbh->entry_addr; + + data_ptr = (char *)mbh - (mbh->header_addr - mbh->load_addr); + + if (mbh->load_end_addr) + data_len = mbh->load_end_addr - mbh->load_addr; + else + data_len = len - mbh_offset + (mbh->header_addr - mbh->load_addr); + + bss_addr = mbh->load_addr + data_len; + + if (mbh->bss_end_addr) + bss_len = mbh->bss_end_addr - mbh->load_end_addr; + else + bss_len = 0; + + if (syslinux_memmap_type(amap, mbh->load_addr, data_len + bss_len) + != SMT_FREE) { + printf("Memory segment at 0x%08x (len 0x%08x) is unavailable\n", + mbh->load_addr, data_len + bss_len); + return NULL; /* Memory region unavailable */ + } + if (syslinux_add_memmap(&amap, mbh->load_addr, + data_len + bss_len, SMT_ALLOC)) { + error("Failed to claim a.out address space!\n"); + return NULL; + } + if (data_len) + if (syslinux_add_movelist(&ml, mbh->load_addr, (addr_t) data_ptr, + data_len)) { + error("Failed to map a.out data\n"); + return NULL; + } + if (bss_len) + if (syslinux_add_memmap + (&mmap, bss_addr, bss_len, SMT_ZERO)) { + error("Failed to map a.out bss\n"); + return NULL; + } + if (bss_addr + bss_len > mboot_high_water_mark) + mboot_high_water_mark = bss_addr + bss_len; + } else { + error + ("Invalid Multiboot image: neither ELF header nor a.out kludge found\n"); + return NULL; + } + + return mbh; +} + +/* + * Set up a stack. This isn't actually required by the spec, but it seems + * like a prudent thing to do. Also, put enough zeros at the top of the + * stack that something that looks for an ELF invocation record will know + * there isn't one. + */ +static void mboot_map_stack(void) +{ + addr_t start, len; + + if (syslinux_memmap_largest(amap, SMT_FREE, &start, &len) || len < 64) + return; /* Not much we can do, here... */ + + regs.esp = (start + len - 32) & ~15; + dprintf("Mapping stack at 0x%08x\n", regs.esp); + syslinux_add_memmap(&mmap, regs.esp, 32, SMT_ZERO); +} + +void mboot_run(int bootflags) +{ + mboot_map_stack(); + + dprintf("Running, eip = 0x%08x, ebx = 0x%08x\n", regs.eip, regs.ebx); + + regs.eax = MULTIBOOT_VALID; + syslinux_shuffle_boot_pm(ml, mmap, bootflags, ®s); +} diff --git a/contrib/syslinux-4.02/com32/mboot/mb_header.h b/contrib/syslinux-4.02/com32/mboot/mb_header.h new file mode 100644 index 0000000..c026d30 --- /dev/null +++ b/contrib/syslinux-4.02/com32/mboot/mb_header.h @@ -0,0 +1,88 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000 Free Software Foundation, Inc. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef MBOOT_MB_HEADER_H +#define MBOOT_MB_HEADER_H + +#include <inttypes.h> + +/* + * MultiBoot Header description + */ + +struct multiboot_header { + /* Must be MULTIBOOT_MAGIC - see below. */ + uint32_t magic; + + /* Feature flags - see below. */ + uint32_t flags; + + /* + * Checksum + * + * The above fields plus this one must equal 0 mod 2^32. + */ + uint32_t checksum; + + /* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */ + uint32_t header_addr; + uint32_t load_addr; + uint32_t load_end_addr; + uint32_t bss_end_addr; + uint32_t entry_addr; + + /* These are only valid if MULTIBOOT_VIDEO_MODE is set. */ + uint32_t mode_type; + uint32_t width; + uint32_t height; + uint32_t depth; +}; + +/* + * The entire multiboot_header must be contained + * within the first MULTIBOOT_SEARCH bytes of the kernel image. + */ +#define MULTIBOOT_SEARCH 8192 + +/* Magic value identifying the multiboot_header. */ +#define MULTIBOOT_MAGIC 0x1BADB002 + +/* + * Features flags for 'flags'. + * If a boot loader sees a flag in MULTIBOOT_MUSTKNOW set + * and it doesn't understand it, it must fail. + */ +#define MULTIBOOT_MUSTKNOW 0x0000FFFF + +/* currently unsupported flags... this is a kind of version number. */ +#define MULTIBOOT_UNSUPPORTED 0x0000FFF8 + +/* Align all boot modules on i386 page (4KB) boundaries. */ +#define MULTIBOOT_PAGE_ALIGN 0x00000001 + +/* Must pass memory information to OS. */ +#define MULTIBOOT_MEMORY_INFO 0x00000002 + +/* Must pass video information to OS. */ +#define MULTIBOOT_VIDEO_MODE 0x00000004 + +/* This flag indicates the use of the address fields in the header. */ +#define MULTIBOOT_AOUT_KLUDGE 0x00010000 + +#endif /* MBOOT_MB_HEADER_H */ diff --git a/contrib/syslinux-4.02/com32/mboot/mb_info.h b/contrib/syslinux-4.02/com32/mboot/mb_info.h new file mode 100644 index 0000000..597a738 --- /dev/null +++ b/contrib/syslinux-4.02/com32/mboot/mb_info.h @@ -0,0 +1,207 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000 Free Software Foundation, Inc. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * The structure type "mod_list" is used by the "multiboot_info" structure. + */ + +#ifndef MBOOT_MB_INFO_H +#define MBOOT_MB_INFO_H + +#include <inttypes.h> + +struct mod_list { + /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */ + uint32_t mod_start; + uint32_t mod_end; + + /* Module command line */ + uint32_t cmdline; + + /* padding to take it to 16 bytes (must be zero) */ + uint32_t pad; +}; + +/* + * INT-15, AX=E820 style "AddressRangeDescriptor" + * ...with a "size" parameter on the front which is the structure size - 4, + * pointing to the next one, up until the full buffer length of the memory + * map has been reached. + */ + +struct AddrRangeDesc { + uint32_t size; + uint64_t BaseAddr; + uint64_t Length; + uint32_t Type; + /* unspecified optional padding... */ +} __attribute__ ((packed)); + +/* usable memory "Type", all others are reserved. */ +#define MB_ARD_MEMORY 1 + +/* Drive Info structure. */ +struct drive_info { + /* The size of this structure. */ + uint32_t size; + + /* The BIOS drive number. */ + uint8_t drive_number; + + /* The access mode (see below). */ + uint8_t drive_mode; + + /* The BIOS geometry. */ + uint16_t drive_cylinders; + uint8_t drive_heads; + uint8_t drive_sectors; + + /* The array of I/O ports used for the drive. */ + uint16_t drive_ports[0]; +}; + +/* Drive Mode. */ +#define MB_DI_CHS_MODE 0 +#define MB_DI_LBA_MODE 1 + +/* APM BIOS info. */ +struct apm_info { + uint16_t version; + uint16_t cseg; + uint32_t offset; + uint16_t cseg_16; + uint16_t dseg_16; + uint16_t cseg_len; + uint16_t cseg_16_len; + uint16_t dseg_16_len; +}; + +/* + * MultiBoot Info description + * + * This is the struct passed to the boot image. This is done by placing + * its address in the EAX register. + */ + +struct multiboot_info { + /* MultiBoot info version number */ + uint32_t flags; + + /* Available memory from BIOS */ + uint32_t mem_lower; + uint32_t mem_upper; + + /* "root" partition */ + uint32_t boot_device; + + /* Kernel command line */ + uint32_t cmdline; + + /* Boot-Module list */ + uint32_t mods_count; + uint32_t mods_addr; + + union { + struct { + /* (a.out) Kernel symbol table info */ + uint32_t tabsize; + uint32_t strsize; + uint32_t addr; + uint32_t pad; + } a; + struct { + /* (ELF) Kernel section header table */ + uint32_t num; + uint32_t size; + uint32_t addr; + uint32_t shndx; + } e; + } syms; + + /* Memory Mapping buffer */ + uint32_t mmap_length; + uint32_t mmap_addr; + + /* Drive Info buffer */ + uint32_t drives_length; + uint32_t drives_addr; + + /* ROM configuration table */ + uint32_t config_table; + + /* Boot Loader Name */ + uint32_t boot_loader_name; + + /* APM table */ + uint32_t apm_table; + + /* Video */ + uint32_t vbe_control_info; + uint32_t vbe_mode_info; + uint16_t vbe_mode; + uint16_t vbe_interface_seg; + uint16_t vbe_interface_off; + uint16_t vbe_interface_len; +}; + +/* + * Flags to be set in the 'flags' parameter above + */ + +/* is there basic lower/upper memory information? */ +#define MB_INFO_MEMORY 0x00000001 +/* is there a boot device set? */ +#define MB_INFO_BOOTDEV 0x00000002 +/* is the command-line defined? */ +#define MB_INFO_CMDLINE 0x00000004 +/* are there modules to do something with? */ +#define MB_INFO_MODS 0x00000008 + +/* These next two are mutually exclusive */ + +/* is there a symbol table loaded? */ +#define MB_INFO_AOUT_SYMS 0x00000010 +/* is there an ELF section header table? */ +#define MB_INFO_ELF_SHDR 0x00000020 + +/* is there a full memory map? */ +#define MB_INFO_MEM_MAP 0x00000040 + +/* Is there drive info? */ +#define MB_INFO_DRIVE_INFO 0x00000080 + +/* Is there a config table? */ +#define MB_INFO_CONFIG_TABLE 0x00000100 + +/* Is there a boot loader name? */ +#define MB_INFO_BOOT_LOADER_NAME 0x00000200 + +/* Is there a APM table? */ +#define MB_INFO_APM_TABLE 0x00000400 + +/* Is there video information? */ +#define MB_INFO_VIDEO_INFO 0x00000800 + +/* + * The following value must be present in the EAX register. + */ + +#define MULTIBOOT_VALID 0x2BADB002 + +#endif /* MBOOT_MB_INFO_H */ diff --git a/contrib/syslinux-4.02/com32/mboot/mboot.c b/contrib/syslinux-4.02/com32/mboot/mboot.c new file mode 100644 index 0000000..35450e0 --- /dev/null +++ b/contrib/syslinux-4.02/com32/mboot/mboot.c @@ -0,0 +1,247 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * mboot.c + * + * Module to load a multiboot kernel + */ + +#include "mboot.h" + +struct multiboot_info mbinfo; +struct syslinux_pm_regs regs; +struct my_options opt, set; + +struct module_data { + void *data; + size_t len; + const char *cmdline; +}; + +static int map_modules(struct module_data *modules, int nmodules) +{ + struct mod_list *mod_list; + addr_t map_list = 0; + size_t list_size = nmodules * sizeof *mod_list; + int i; + + mod_list = malloc(list_size); + if (!mod_list) { + printf("Failed to allocate module list\n"); + return -1; + } + + map_list = map_data(mod_list, list_size, 16, 0); + if (!map_list) { + printf("Cannot map module list\n"); + return -1; + } + + for (i = 0; i < nmodules; i++) { + addr_t mod_map = 0; + addr_t cmd_map = 0; + + dprintf("Module %d cmdline: \"%s\"\n", i, modules[i].cmdline); + + cmd_map = map_string(modules[i].cmdline); + + mod_map = map_data(modules[i].data, modules[i].len, 4096, MAP_HIGH); + if (!mod_map) { + printf("Failed to map module (memory fragmentation issue?)\n"); + return -1; + } + mod_list[i].mod_start = mod_map; + mod_list[i].mod_end = mod_map + modules[i].len; + mod_list[i].cmdline = cmd_map; + mod_list[i].pad = 0; + } + + mbinfo.flags |= MB_INFO_MODS; + mbinfo.mods_count = nmodules; + mbinfo.mods_addr = map_list; + return 0; +} + +static int get_modules(char **argv, struct module_data **mdp) +{ + char **argp, **argx; + struct module_data *mp; + int rv; + int module_count = 1; + int arglen; + const char module_separator[] = "---"; + + for (argp = argv; *argp; argp++) { + if (!strcmp(*argp, module_separator)) + module_count++; + } + + *mdp = mp = malloc(module_count * sizeof(struct module_data)); + if (!mp) { + error("Out of memory!\n"); + return -1; + } + + argp = argv; + while (*argp) { + /* Note: it seems Grub transparently decompresses all compressed files, + not just the primary kernel. */ + printf("Loading %s... ", *argp); + rv = zloadfile(*argp, &mp->data, &mp->len); + + if (rv) { + printf("failed!\n"); + return -1; + } + printf("ok\n"); + + /* + * Note: Grub includes the kernel filename in the command line, so we + * want to match that behavior. + */ + arglen = 0; + for (argx = argp; *argx && strcmp(*argx, module_separator); argx++) + arglen += strlen(*argx) + 1; + + if (arglen == 0) { + mp->cmdline = strdup(""); + } else { + char *p; + mp->cmdline = p = malloc(arglen); + for (; *argp && strcmp(*argp, module_separator); argp++) { + p = stpcpy(p, *argp); + *p++ = ' '; + } + *--p = '\0'; + } + mp++; + if (*argp) + argp++; /* Advance past module_separator */ + } + + return module_count; +} + +int main(int argc, char *argv[]) +{ + int nmodules; + struct module_data *modules; + struct multiboot_header *mbh; + bool keeppxe = false; + + openconsole(&dev_null_r, &dev_stdcon_w); + + (void)argc; /* Unused */ + argv++; + + while (*argv) { + bool v = true; + const char *p = *argv; + + if (!memcmp(p, "-no", 3)) { + v = false; + p += 3; + } + + if (!strcmp(p, "-solaris")) { + opt.solaris = v; + set.solaris = true; + } else if (!strcmp(p, "-aout")) { + opt.aout = v; + set.aout = true; + } else + break; + argv++; + } + + if (!*argv) { + error + ("Usage: mboot.c32 [opts] mboot_file args... [--- module args...]...\n" + "Options:\n" + " -solaris Enable Solaris DHCP information passing\n" + " -aout Use the \"a.out kludge\" if enabled, even for ELF\n" + " This matches the Multiboot spec, but differs from Grub\n"); + return 1; + } + + /* Load the files */ + nmodules = get_modules(argv, &modules); + if (nmodules < 1) { + error("No files found!\n"); + return 1; /* Failure */ + } + + if (init_map()) + return 1; /* Failed to allocate intitial map */ + + /* + * Map the primary image. This should be done before mapping anything + * else, since it will have fixed address requirements. + */ + mbh = map_image(modules[0].data, modules[0].len); + if (!mbh) + return 1; + + /* Map the mbinfo structure */ + regs.ebx = map_data(&mbinfo, sizeof mbinfo, 4, 0); + if (!regs.ebx) { + error("Failed to map Multiboot info structure!\n"); + return 1; + } + + /* Map the primary command line */ + if (modules[0].cmdline) { + mbinfo.cmdline = map_string(modules[0].cmdline); + dprintf("Main cmdline: \"%s\"\n", modules[0].cmdline); + if (mbinfo.cmdline) + mbinfo.flags |= MB_INFO_CMDLINE; + } + + /* Map auxilliary images */ + if (nmodules > 1) { + if (map_modules(modules + 1, nmodules - 1)) + return 1; + } + + /* Add auxilliary information */ + mboot_make_memmap(); + mboot_apm(); + mboot_syslinux_info(); + + if (opt.solaris) + mboot_solaris_dhcp_hack(); + + /* Set the graphics mode if requested */ + set_graphics_mode(mbh, &mbinfo); + + /* Run it */ + mboot_run(keeppxe ? 3 : 0); + error("mboot.c32: boot failed\n"); + return 1; +} diff --git a/contrib/syslinux-4.02/com32/mboot/mboot.h b/contrib/syslinux-4.02/com32/mboot/mboot.h new file mode 100644 index 0000000..da6ca2f --- /dev/null +++ b/contrib/syslinux-4.02/com32/mboot/mboot.h @@ -0,0 +1,98 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * mboot.h + * + * Module to load a multiboot kernel + */ + +#ifndef MBOOT_H + +#include <dprintf.h> +#include <stdio.h> +#include <stdlib.h> +#include <inttypes.h> +#include <stdbool.h> +#include <string.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <minmax.h> +#include <sys/stat.h> +#include <elf.h> +#include <console.h> + +#include <syslinux/loadfile.h> +#include <syslinux/movebits.h> +#include <syslinux/bootpm.h> +#include <syslinux/config.h> + +#include "mb_header.h" +#include "mb_info.h" + +static inline void error(const char *msg) +{ + fputs(msg, stderr); +} + +/* mboot.c */ +extern struct multiboot_info mbinfo; +extern struct syslinux_pm_regs regs; +extern struct my_options { + bool solaris; + bool aout; +} opt, set; + +/* map.c */ +#define MAP_HIGH 1 +#define MAP_NOPAD 2 +addr_t map_data(const void *data, size_t len, size_t align, int flags); +addr_t map_string(const char *string); +struct multiboot_header *map_image(void *ptr, size_t len); +void mboot_run(int bootflags); +int init_map(void); + +/* mem.c */ +void mboot_make_memmap(void); + +/* apm.c */ +void mboot_apm(void); + +/* solaris.c */ +bool kernel_is_solaris(const Elf32_Ehdr *); +void mboot_solaris_dhcp_hack(void); + +/* syslinux.c */ +void mboot_syslinux_info(void); + +/* initvesa.c */ +void set_graphics_mode(const struct multiboot_header *mbh, + struct multiboot_info *mbi); + +#endif /* MBOOT_H */ diff --git a/contrib/syslinux-4.02/com32/mboot/mem.c b/contrib/syslinux-4.02/com32/mboot/mem.c new file mode 100644 index 0000000..6a31fac --- /dev/null +++ b/contrib/syslinux-4.02/com32/mboot/mem.c @@ -0,0 +1,205 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2009 H. Peter Anvin - All Rights Reserved + * Copyright 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 + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * mem.c + * + * Obtain a memory map for a Multiboot OS + * + * This differs from the libcom32 memory map functions in that it doesn't + * attempt to filter out memory regions... + */ + +#include "mboot.h" +#include <com32.h> + +struct e820_entry { + uint64_t start; + uint64_t len; + uint32_t type; +}; + +#define RANGE_ALLOC_BLOCK 128 + +static int mboot_scan_memory(struct AddrRangeDesc **ardp, uint32_t * dosmem) +{ + com32sys_t ireg, oreg; + struct e820_entry *e820buf = __com32.cs_bounce; + struct AddrRangeDesc *ard; + size_t ard_count, ard_space; + + /* Use INT 12h to get DOS memory */ + __intcall(0x12, &__com32_zero_regs, &oreg); + *dosmem = oreg.eax.w[0] << 10; + if (*dosmem < 32 * 1024 || *dosmem > 640 * 1024) { + /* INT 12h reports nonsense... now what? */ + uint16_t ebda_seg = *(uint16_t *) 0x40e; + if (ebda_seg >= 0x8000 && ebda_seg < 0xa000) + *dosmem = ebda_seg << 4; + else + *dosmem = 640 * 1024; /* Hope for the best... */ + } + + /* Allocate initial space */ + *ardp = ard = malloc(RANGE_ALLOC_BLOCK * sizeof *ard); + if (!ard) + return 0; + + ard_count = 0; + ard_space = RANGE_ALLOC_BLOCK; + + /* First try INT 15h AX=E820h */ + memset(&ireg, 0, sizeof ireg); + ireg.eax.l = 0xe820; + ireg.edx.l = 0x534d4150; + /* ireg.ebx.l = 0; */ + ireg.ecx.l = sizeof(*e820buf); + ireg.es = SEG(e820buf); + ireg.edi.w[0] = OFFS(e820buf); + memset(e820buf, 0, sizeof *e820buf); + + do { + __intcall(0x15, &ireg, &oreg); + + if ((oreg.eflags.l & EFLAGS_CF) || + (oreg.eax.l != 0x534d4150) || (oreg.ecx.l < 20)) + break; + + if (ard_count >= ard_space) { + ard_space += RANGE_ALLOC_BLOCK; + *ardp = ard = realloc(ard, ard_space * sizeof *ard); + if (!ard) + return ard_count; + } + + ard[ard_count].size = 20; + ard[ard_count].BaseAddr = e820buf->start; + ard[ard_count].Length = e820buf->len; + ard[ard_count].Type = e820buf->type; + ard_count++; + + ireg.ebx.l = oreg.ebx.l; + } while (oreg.ebx.l); + + if (ard_count) + return ard_count; + + ard[0].size = 20; + ard[0].BaseAddr = 0; + ard[0].Length = *dosmem << 10; + ard[0].Type = 1; + + /* Next try INT 15h AX=E801h */ + ireg.eax.w[0] = 0xe801; + __intcall(0x15, &ireg, &oreg); + + if (!(oreg.eflags.l & EFLAGS_CF) && oreg.ecx.w[0]) { + ard[1].size = 20; + ard[1].BaseAddr = 1 << 20; + ard[1].Length = oreg.ecx.w[0] << 10; + ard[1].Type = 1; + + if (oreg.edx.w[0]) { + ard[2].size = 20; + ard[2].BaseAddr = 16 << 20; + ard[2].Length = oreg.edx.w[0] << 16; + ard[2].Type = 1; + return 3; + } else { + return 2; + } + } + + /* Finally try INT 15h AH=88h */ + ireg.eax.w[0] = 0x8800; + if (!(oreg.eflags.l & EFLAGS_CF) && oreg.eax.w[0]) { + ard[1].size = 20; + ard[1].BaseAddr = 1 << 20; + ard[1].Length = oreg.ecx.w[0] << 10; + ard[1].Type = 1; + return 2; + } + + return 1; /* ... problematic ... */ +} + +void mboot_make_memmap(void) +{ + int i, nmap; + struct AddrRangeDesc *ard; + uint32_t lowmem, highmem; + uint32_t highrsvd; + + /* Always report DOS memory as "lowmem", this may be overly conservative + (e.g. if we're dropping PXE), but it should be *safe*... */ + + nmap = mboot_scan_memory(&ard, &lowmem); + + highmem = 0x100000; + highrsvd = 0xfff00000; + +again: + for (i = 0; i < nmap; i++) { + uint64_t start, end; + + start = ard[i].BaseAddr; + end = start + ard[i].Length; + + if (end < start) + end = ~0ULL; + + if (start & 0xffffffff00000000ULL) + continue; /* Not interested in 64-bit memory */ + + if (start < highmem) + start = highmem; + + if (end <= start) + continue; + + if (ard[i].Type == 1 && start == highmem) { + highmem = end; + goto again; + } else if (ard[i].Type != 1 && start < highrsvd) + highrsvd = start; + } + + if (highmem > highrsvd) + highmem = highrsvd; + + mbinfo.mem_lower = lowmem >> 10; + mbinfo.mem_upper = (highmem - 0x100000) >> 10; + mbinfo.flags |= MB_INFO_MEMORY; + + /* The spec says this address should be +4, but Grub disagrees */ + mbinfo.mmap_addr = map_data(ard, nmap * sizeof *ard, 4, false); + if (mbinfo.mmap_addr) { + mbinfo.mmap_length = nmap * sizeof *ard; + mbinfo.flags |= MB_INFO_MEM_MAP; + } +} diff --git a/contrib/syslinux-4.02/com32/mboot/solaris.c b/contrib/syslinux-4.02/com32/mboot/solaris.c new file mode 100644 index 0000000..1b153dd --- /dev/null +++ b/contrib/syslinux-4.02/com32/mboot/solaris.c @@ -0,0 +1,62 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * solaris.c + * + * Solaris DHCP hack + * + * Solaris uses a nonstandard hack to pass DHCP information from a netboot. + */ + +#include "mboot.h" +#include <syslinux/pxe.h> +#include <syslinux/config.h> + +bool kernel_is_solaris(const Elf32_Ehdr *eh) +{ + return eh->e_ident[EI_OSABI] == 6; /* ABI == Solaris */ +} + +void mboot_solaris_dhcp_hack(void) +{ + void *dhcpdata; + size_t dhcplen; + + if (syslinux_derivative_info()->c.filesystem != SYSLINUX_FS_PXELINUX) + return; + + if (!pxe_get_cached_info(PXENV_PACKET_TYPE_DHCP_ACK, &dhcpdata, &dhcplen)) { + mbinfo.drives_addr = map_data(dhcpdata, dhcplen, 4, 0); + if (mbinfo.drives_addr) { + mbinfo.drives_length = dhcplen; + mbinfo.boot_device = 0x20ffffff; + mbinfo.flags = + (mbinfo.flags & ~MB_INFO_DRIVE_INFO) | MB_INFO_BOOTDEV; + } + } +} diff --git a/contrib/syslinux-4.02/com32/mboot/syslinux.c b/contrib/syslinux-4.02/com32/mboot/syslinux.c new file mode 100644 index 0000000..7de3853 --- /dev/null +++ b/contrib/syslinux-4.02/com32/mboot/syslinux.c @@ -0,0 +1,45 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2010 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * syslinux.c + * + * Syslinux-specific information for the kernel + */ + +#include <syslinux/config.h> +#include "mboot.h" + +void mboot_syslinux_info(void) +{ + const struct syslinux_version *sv; + + sv = syslinux_version(); + mbinfo.boot_loader_name = map_string(sv->version_string); + if (mbinfo.boot_loader_name) + mbinfo.flags |= MB_INFO_BOOT_LOADER_NAME; +} diff --git a/contrib/syslinux-4.02/com32/mboot/vesa.h b/contrib/syslinux-4.02/com32/mboot/vesa.h new file mode 100644 index 0000000..ecc084a --- /dev/null +++ b/contrib/syslinux-4.02/com32/mboot/vesa.h @@ -0,0 +1,100 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1999-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. + * + * ----------------------------------------------------------------------- */ + +#ifndef LIB_SYS_VESA_H +#define LIB_SYS_VESA_H + +#include <inttypes.h> +#include <com32.h> + +/* VESA General Information table */ +struct vesa_general_info { + uint32_t signature; /* Magic number = "VESA" */ + uint16_t version; + far_ptr_t vendor_string; + uint8_t capabilities[4]; + far_ptr_t video_mode_ptr; + uint16_t total_memory; + + uint16_t oem_software_rev; + far_ptr_t oem_vendor_name_ptr; + far_ptr_t oem_product_name_ptr; + far_ptr_t oem_product_rev_ptr; + + uint8_t reserved[222]; + uint8_t oem_data[256]; +} __attribute__ ((packed)); + +#define VESA_MAGIC ('V' + ('E' << 8) + ('S' << 16) + ('A' << 24)) +#define VBE2_MAGIC ('V' + ('B' << 8) + ('E' << 16) + ('2' << 24)) + +struct vesa_mode_info { + uint16_t mode_attr; + uint8_t win_attr[2]; + uint16_t win_grain; + uint16_t win_size; + uint16_t win_seg[2]; + far_ptr_t win_scheme; + uint16_t logical_scan; + + uint16_t h_res; + uint16_t v_res; + uint8_t char_width; + uint8_t char_height; + uint8_t memory_planes; + uint8_t bpp; + uint8_t banks; + uint8_t memory_layout; + uint8_t bank_size; + uint8_t image_pages; + uint8_t page_function; + + uint8_t rmask; + uint8_t rpos; + uint8_t gmask; + uint8_t gpos; + uint8_t bmask; + uint8_t bpos; + uint8_t resv_mask; + uint8_t resv_pos; + uint8_t dcm_info; + + uint8_t *lfb_ptr; /* Linear frame buffer address */ + uint8_t *offscreen_ptr; /* Offscreen memory address */ + uint16_t offscreen_size; + + uint8_t reserved[206]; +} __attribute__ ((packed)); + +struct vesa_info { + struct vesa_general_info gi; + struct vesa_mode_info mi; +}; + +extern struct vesa_info vesa_info; + +#endif /* LIB_SYS_VESA_H */ diff --git a/contrib/syslinux-4.02/com32/menu/Makefile b/contrib/syslinux-4.02/com32/menu/Makefile new file mode 100644 index 0000000..2a03272 --- /dev/null +++ b/contrib/syslinux-4.02/com32/menu/Makefile @@ -0,0 +1,49 @@ +## ----------------------------------------------------------------------- +## +## 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., 51 Franklin St, Fifth Floor, +## Boston MA 02110-1301, USA; either version 2 of the License, or +## (at your option) any later version; incorporated herein by reference. +## +## ----------------------------------------------------------------------- + +## +## Simple menu system +## + +topdir = ../.. +include ../MCONFIG + +LIBS = ../libutil/libutil_com.a ../lib/libcom32.a $(LIBGCC) +LNXLIBS = ../libutil/libutil_lnx.a + +MODULES = menu.c32 vesamenu.c32 +TESTFILES = + +COMMONOBJS = menumain.o readconfig.o passwd.o drain.o printmsg.o colors.o \ + background.o refstr.o execute.o + +all: $(MODULES) $(TESTFILES) + +menu.elf : menu.o $(COMMONOBJS) $(LIBS) $(C_LIBS) + $(LD) $(LDFLAGS) -o $@ $^ + +vesamenu.elf : vesamenu.o $(COMMONOBJS) $(LIBS) $(C_LIBS) + $(LD) $(LDFLAGS) -o $@ $^ + +tidy dist: + rm -f *.o *.lo *.a *.lst *.elf .*.d *.tmp + +clean: tidy + rm -f *.lnx + +spotless: clean + rm -f *.lss *.c32 *.com + rm -f *~ \#* + +install: + +-include .*.d diff --git a/contrib/syslinux-4.02/com32/menu/background.c b/contrib/syslinux-4.02/com32/menu/background.c new file mode 100644 index 0000000..2be0ede --- /dev/null +++ b/contrib/syslinux-4.02/com32/menu/background.c @@ -0,0 +1,26 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2008 H. Peter Anvin - All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +#include <consoles.h> +#include <string.h> +#include "menu.h" + +const char *current_background = NULL; + +void set_background(const char *new_background) +{ + if (!current_background || !new_background || + strcmp(current_background, new_background)) { + draw_background(new_background); + current_background = new_background; + } +} diff --git a/contrib/syslinux-4.02/com32/menu/colors.c b/contrib/syslinux-4.02/com32/menu/colors.c new file mode 100644 index 0000000..68732bd --- /dev/null +++ b/contrib/syslinux-4.02/com32/menu/colors.c @@ -0,0 +1,184 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-2008 H. Peter Anvin - All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <colortbl.h> +#include "menu.h" + +/* + * The color/attribute indexes (\1#X, \2#XX, \3#XXX) are as follows + * + * 00 - screen Rest of the screen + * 01 - border Border area + * 02 - title Title bar + * 03 - unsel Unselected menu item + * 04 - hotkey Unselected hotkey + * 05 - sel Selection bar + * 06 - hotsel Selected hotkey + * 07 - scrollbar Scroll bar + * 08 - tabmsg Press [Tab] message + * 09 - cmdmark Command line marker + * 10 - cmdline Command line + * 11 - pwdborder Password box border + * 12 - pwdheader Password box header + * 13 - pwdentry Password box contents + * 14 - timeout_msg Timeout message + * 15 - timeout Timeout counter + * 16 - help Current entry help text + * 17 - disabled Disabled menu item + */ + +static const struct color_table default_colors[] = { + {"screen", "37;40", 0x80ffffff, 0x00000000, SHADOW_NORMAL}, + {"border", "30;44", 0x40000000, 0x00000000, SHADOW_NORMAL}, + {"title", "1;36;44", 0xc00090f0, 0x00000000, SHADOW_NORMAL}, + {"unsel", "37;44", 0x90ffffff, 0x00000000, SHADOW_NORMAL}, + {"hotkey", "1;37;44", 0xffffffff, 0x00000000, SHADOW_NORMAL}, + {"sel", "7;37;40", 0xe0000000, 0x20ff8000, SHADOW_ALL}, + {"hotsel", "1;7;37;40", 0xe0400000, 0x20ff8000, SHADOW_ALL}, + {"scrollbar", "30;44", 0x40000000, 0x00000000, SHADOW_NORMAL}, + {"tabmsg", "31;40", 0x90ffff00, 0x00000000, SHADOW_NORMAL}, + {"cmdmark", "1;36;40", 0xc000ffff, 0x00000000, SHADOW_NORMAL}, + {"cmdline", "37;40", 0xc0ffffff, 0x00000000, SHADOW_NORMAL}, + {"pwdborder", "30;47", 0x80ffffff, 0x20ffffff, SHADOW_NORMAL}, + {"pwdheader", "31;47", 0x80ff8080, 0x20ffffff, SHADOW_NORMAL}, + {"pwdentry", "30;47", 0x80ffffff, 0x20ffffff, SHADOW_NORMAL}, + {"timeout_msg", "37;40", 0x80ffffff, 0x00000000, SHADOW_NORMAL}, + {"timeout", "1;37;40", 0xc0ffffff, 0x00000000, SHADOW_NORMAL}, + {"help", "37;40", 0xc0ffffff, 0x00000000, SHADOW_NORMAL}, + {"disabled", "1;30;44", 0x60cccccc, 0x00000000, SHADOW_NORMAL}, +}; + +#define NCOLORS (sizeof default_colors/sizeof default_colors[0]) +const int message_base_color = NCOLORS; +const int menu_color_table_size = NCOLORS + 256; + +/* Algorithmically generate the msgXX colors */ +void set_msg_colors_global(struct color_table *tbl, + unsigned int fg, unsigned int bg, + enum color_table_shadow shadow) +{ + struct color_table *cp = tbl + message_base_color; + unsigned int i; + unsigned int fga, bga; + unsigned int fgh, bgh; + unsigned int fg_idx, bg_idx; + unsigned int fg_rgb, bg_rgb; + + static const unsigned int pc2rgb[8] = + { 0x000000, 0x0000ff, 0x00ff00, 0x00ffff, 0xff0000, 0xff00ff, 0xffff00, + 0xffffff + }; + + /* Converting PC RGBI to sensible RGBA values is an "interesting" + proposition. This algorithm may need plenty of tweaking. */ + + fga = fg & 0xff000000; + fgh = ((fg >> 1) & 0xff000000) | 0x80000000; + + bga = bg & 0xff000000; + bgh = ((bg >> 1) & 0xff000000) | 0x80000000; + + for (i = 0; i < 256; i++) { + fg_idx = i & 15; + bg_idx = i >> 4; + + fg_rgb = pc2rgb[fg_idx & 7] & fg; + bg_rgb = pc2rgb[bg_idx & 7] & bg; + + if (fg_idx & 8) { + /* High intensity foreground */ + fg_rgb |= fgh; + } else { + fg_rgb |= fga; + } + + if (bg_idx == 0) { + /* Default black background, assume transparent */ + bg_rgb = 0; + } else if (bg_idx & 8) { + bg_rgb |= bgh; + } else { + bg_rgb |= bga; + } + + cp->argb_fg = fg_rgb; + cp->argb_bg = bg_rgb; + cp->shadow = shadow; + cp++; + } +} + +struct color_table *default_color_table(void) +{ + unsigned int i; + const struct color_table *dp; + struct color_table *cp; + struct color_table *color_table; + static const int pc2ansi[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; + static char msg_names[6 * 256]; + char *mp; + + color_table = calloc(NCOLORS + 256, sizeof(struct color_table)); + + dp = default_colors; + cp = color_table; + + for (i = 0; i < NCOLORS; i++) { + *cp = *dp; + cp->ansi = refstrdup(dp->ansi); + cp++; + dp++; + } + + mp = msg_names; + for (i = 0; i < 256; i++) { + cp->name = mp; + mp += sprintf(mp, "msg%02x", i) + 1; + + rsprintf(&cp->ansi, "%s3%d;4%d", (i & 8) ? "1;" : "", + pc2ansi[i & 7], pc2ansi[(i >> 4) & 7]); + cp++; + } + + /*** XXX: This needs to move to run_menu() ***/ + console_color_table = color_table; + console_color_table_size = NCOLORS + 256; + + set_msg_colors_global(color_table, MSG_COLORS_DEF_FG, + MSG_COLORS_DEF_BG, MSG_COLORS_DEF_SHADOW); + + return color_table; +} + +struct color_table *copy_color_table(const struct color_table *master) +{ + const struct color_table *dp; + struct color_table *color_table, *cp; + unsigned int i; + + color_table = calloc(NCOLORS + 256, sizeof(struct color_table)); + + dp = master; + cp = color_table; + + for (i = 0; i < NCOLORS + 256; i++) { + *cp = *dp; + cp->ansi = refstr_get(dp->ansi); + cp++; + dp++; + } + + return color_table; +} diff --git a/contrib/syslinux-4.02/com32/menu/drain.c b/contrib/syslinux-4.02/com32/menu/drain.c new file mode 100644 index 0000000..60efd35 --- /dev/null +++ b/contrib/syslinux-4.02/com32/menu/drain.c @@ -0,0 +1,25 @@ +#include <stdio.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <sys/cpu.h> + +void drain_keyboard(void) +{ + /* Prevent "ghost typing" and keyboard buffer snooping */ + volatile char junk; + int rv; + + do { + rv = read(0, (char *)&junk, 1); + } while (rv > 0); + + junk = 0; + + cli(); + *(volatile uint8_t *)0x419 = 0; /* Alt-XXX keyboard area */ + *(volatile uint16_t *)0x41a = 0x1e; /* Keyboard buffer empty */ + *(volatile uint16_t *)0x41c = 0x1e; + memset((void *)0x41e, 0, 32); /* Clear the actual keyboard buffer */ + sti(); +} diff --git a/contrib/syslinux-4.02/com32/menu/execute.c b/contrib/syslinux-4.02/com32/menu/execute.c new file mode 100644 index 0000000..c2de735 --- /dev/null +++ b/contrib/syslinux-4.02/com32/menu/execute.c @@ -0,0 +1,69 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-2008 H. Peter Anvin - All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +#include <stdlib.h> +#include <string.h> +#include <com32.h> +#include "menu.h" + +void execute(const char *cmdline, enum kernel_type type) +{ + com32sys_t ireg; + const char *p, *const *pp; + char *q = __com32.cs_bounce; + const char *kernel, *args; + + memset(&ireg, 0, sizeof ireg); + + kernel = q; + p = cmdline; + while (*p && !my_isspace(*p)) { + *q++ = *p++; + } + *q++ = '\0'; + + args = q; + while (*p && my_isspace(*p)) + p++; + + strcpy(q, p); + + if (kernel[0] == '.' && type == KT_NONE) { + /* It might be a type specifier */ + enum kernel_type type = KT_NONE; + for (pp = kernel_types; *pp; pp++, type++) { + if (!strcmp(kernel + 1, *pp)) { + execute(p, type); /* Strip the type specifier and retry */ + } + } + } + + if (type == KT_LOCALBOOT) { + ireg.eax.w[0] = 0x0014; /* Local boot */ + ireg.edx.w[0] = strtoul(kernel, NULL, 0); + } else { + if (type < KT_KERNEL) + type = KT_KERNEL; + + ireg.eax.w[0] = 0x0016; /* Run kernel image */ + ireg.esi.w[0] = OFFS(kernel); + ireg.ds = SEG(kernel); + ireg.ebx.w[0] = OFFS(args); + ireg.es = SEG(args); + ireg.edx.l = type - KT_KERNEL; + /* ireg.ecx.l = 0; *//* We do ipappend "manually" */ + } + + __intcall(0x22, &ireg, NULL); + + /* If this returns, something went bad; return to menu */ +} diff --git a/contrib/syslinux-4.02/com32/menu/menu.c b/contrib/syslinux-4.02/com32/menu/menu.c new file mode 100644 index 0000000..8f7af4d --- /dev/null +++ b/contrib/syslinux-4.02/com32/menu/menu.c @@ -0,0 +1,44 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-2008 H. Peter Anvin - All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * menu.c + * + * Simple menu system which displays a list and allows the user to select + * a command line and/or edit it. + */ + +#include <consoles.h> +#include "menu.h" + +int draw_background(const char *arg) +{ + /* Nothing to do... */ + (void)arg; + return 0; +} + +void set_resolution(int x, int y) +{ + (void)x; + (void)y; +} + +void local_cursor_enable(bool enabled) +{ + (void)enabled; +} + +void start_console(void) +{ + console_ansi_raw(); +} diff --git a/contrib/syslinux-4.02/com32/menu/menu.h b/contrib/syslinux-4.02/com32/menu/menu.h new file mode 100644 index 0000000..36c5669 --- /dev/null +++ b/contrib/syslinux-4.02/com32/menu/menu.h @@ -0,0 +1,234 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-2008 H. Peter Anvin - All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * menu.h + * + * Header file for the simple menu system + */ + +#ifndef MENU_H +#define MENU_H + +#include <time.h> +#include <sys/time.h> +#include <sys/times.h> +#include <inttypes.h> +#include <unistd.h> +#include <colortbl.h> +#include <stdbool.h> +#include "refstr.h" + +/* #define DEBUG 1 */ +#include <dprintf.h> + +#ifndef CLK_TCK +# define CLK_TCK sysconf(_SC_CLK_TCK) +#endif + +struct menu; + +/* Note: the _UNRES variants must always be immediately after their + "normal" versions. */ +enum menu_action { + MA_NONE, /* Undefined value */ + MA_CMD, /* Execute a command */ + MA_DISABLED, /* Disabled menu entry */ + MA_SUBMENU, /* This is a submenu entry */ + MA_GOTO, /* Go to another menu */ + MA_GOTO_UNRES, /* Unresolved go to */ + MA_QUIT, /* Quit to CLI */ + MA_EXIT, /* Exit to higher-level menu */ + MA_EXIT_UNRES, /* Unresolved exit */ + MA_HELP, /* Show help text */ +}; + +struct menu_entry { + struct menu *menu; /* Parent menu */ + const char *displayname; + const char *label; + const char *passwd; + char *helptext; + const char *cmdline; + const char *background; + struct menu *submenu; + struct menu_entry *next; /* Linked list of all labels across menus */ + int entry; /* Entry number inside menu */ + enum menu_action action; + unsigned char hotkey; + bool immediate; /* Hotkey action does not require Enter */ + bool save; /* Save this entry if selected */ +}; + +static inline bool is_disabled(struct menu_entry *me) +{ + return me->action == MA_DISABLED; +} + +enum kernel_type { + /* Meta-types for internal use */ + KT_NONE, + KT_LOCALBOOT, + + /* The ones we can pass off to SYSLINUX, in order */ + KT_KERNEL, /* Undefined type */ + KT_LINUX, /* Linux kernel */ + KT_BOOT, /* Bootstrap program */ + KT_BSS, /* Boot sector with patch */ + KT_PXE, /* PXE NBP */ + KT_FDIMAGE, /* Floppy disk image */ + KT_COMBOOT, /* COMBOOT image */ + KT_COM32, /* COM32 image */ + KT_CONFIG, /* Configuration file */ +}; + +extern const char *const kernel_types[]; + +/* Configurable integer parameters */ +enum parameter_number { + P_WIDTH, + P_MARGIN, + P_PASSWD_MARGIN, + P_MENU_ROWS, + P_TABMSG_ROW, + P_CMDLINE_ROW, + P_END_ROW, + P_PASSWD_ROW, + P_TIMEOUT_ROW, + P_HELPMSG_ROW, + P_HELPMSGEND_ROW, + P_HSHIFT, + P_VSHIFT, + P_HIDDEN_ROW, + + NPARAMS +}; + +/* Configurable messages */ +enum message_number { + MSG_TITLE, + MSG_AUTOBOOT, + MSG_TAB, + MSG_NOTAB, + MSG_PASSPROMPT, + + MSG_COUNT +}; + +struct messages { + const char *name; /* Message configuration name */ + const char *defmsg; /* Default message text */ +}; + +struct menu_parameter { + const char *name; + int value; +}; + +extern const struct menu_parameter mparm[NPARAMS]; + +struct fkey_help { + const char *textname; + const char *background; +}; + +struct menu { + struct menu *next; /* Linked list of all menus */ + const char *label; /* Goto label for this menu */ + struct menu *parent; + struct menu_entry *parent_entry; /* Entry for self in parent */ + + struct menu_entry **menu_entries; + struct menu_entry *menu_hotkeys[256]; + + const char *messages[MSG_COUNT]; + int mparm[NPARAMS]; + + int nentries; + int nentries_space; + int defentry; + int timeout; + + bool allowedit; + bool immediate; /* MENU IMMEDIATE default for this menu */ + bool save; /* MENU SAVE default for this menu */ + + int curentry; + int curtop; + + const char *title; + const char *ontimeout; + const char *onerror; + const char *menu_master_passwd; + const char *menu_background; + + struct color_table *color_table; + + struct fkey_help fkeyhelp[12]; +}; + +extern struct menu *root_menu, *start_menu, *hide_menu, *menu_list; + +/* 2048 is the current definition inside syslinux */ +#define MAX_CMDLINE_LEN 2048 + +/* These are global parameters regardless of which menu we're displaying */ +extern int shiftkey; +extern int hiddenmenu; +extern int clearmenu; +extern long long totaltimeout; + +void parse_configs(char **argv); +int draw_background(const char *filename); +void set_resolution(int x, int y); +void start_console(void); +void local_cursor_enable(bool); + +static inline int my_isspace(char c) +{ + return (unsigned char)c <= ' '; +} + +int my_isxdigit(char c); +unsigned int hexval(char c); +unsigned int hexval2(const char *p); +uint32_t parse_argb(char **p); + +extern const int message_base_color, menu_color_table_size; +int mygetkey(clock_t timeout); +int show_message_file(const char *filename, const char *background); + +/* passwd.c */ +int passwd_compare(const char *passwd, const char *entry); + +/* colors.c */ +#define MSG_COLORS_DEF_FG 0x90ffffff +#define MSG_COLORS_DEF_BG 0x80ffffff +#define MSG_COLORS_DEF_SHADOW SHADOW_NORMAL +void set_msg_colors_global(struct color_table *tbl, + unsigned int fg, unsigned int bg, + enum color_table_shadow shadow); +struct color_table *default_color_table(void); +struct color_table *copy_color_table(const struct color_table *master); +extern const int message_base_color; + +/* background.c */ +extern const char *current_background; +void set_background(const char *new_background); + +/* execute.c */ +void execute(const char *cmdline, enum kernel_type type); + +/* drain.c */ +void drain_keyboard(void); + +#endif /* MENU_H */ diff --git a/contrib/syslinux-4.02/com32/menu/menumain.c b/contrib/syslinux-4.02/com32/menu/menumain.c new file mode 100644 index 0000000..06725f3 --- /dev/null +++ b/contrib/syslinux-4.02/com32/menu/menumain.c @@ -0,0 +1,1164 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * menumain.c + * + * Simple menu system which displays a list and allows the user to select + * a command line and/or edit it. + */ + +#include <ctype.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <consoles.h> +#include <getkey.h> +#include <minmax.h> +#include <setjmp.h> +#include <limits.h> +#include <com32.h> +#include <syslinux/adv.h> + +#include "menu.h" + +/* The symbol "cm" always refers to the current menu across this file... */ +static struct menu *cm; + +const struct menu_parameter mparm[NPARAMS] = { + [P_WIDTH] = {"width", 0}, + [P_MARGIN] = {"margin", 10}, + [P_PASSWD_MARGIN] = {"passwordmargin", 3}, + [P_MENU_ROWS] = {"rows", 12}, + [P_TABMSG_ROW] = {"tabmsgrow", 18}, + [P_CMDLINE_ROW] = {"cmdlinerow", 18}, + [P_END_ROW] = {"endrow", -1}, + [P_PASSWD_ROW] = {"passwordrow", 11}, + [P_TIMEOUT_ROW] = {"timeoutrow", 20}, + [P_HELPMSG_ROW] = {"helpmsgrow", 22}, + [P_HELPMSGEND_ROW] = {"helpmsgendrow", -1}, + [P_HSHIFT] = {"hshift", 0}, + [P_VSHIFT] = {"vshift", 0}, + [P_HIDDEN_ROW] = {"hiddenrow", -2}, +}; + +/* These macros assume "cm" is a pointer to the current menu */ +#define WIDTH (cm->mparm[P_WIDTH]) +#define MARGIN (cm->mparm[P_MARGIN]) +#define PASSWD_MARGIN (cm->mparm[P_PASSWD_MARGIN]) +#define MENU_ROWS (cm->mparm[P_MENU_ROWS]) +#define TABMSG_ROW (cm->mparm[P_TABMSG_ROW]+VSHIFT) +#define CMDLINE_ROW (cm->mparm[P_CMDLINE_ROW]+VSHIFT) +#define END_ROW (cm->mparm[P_END_ROW]) +#define PASSWD_ROW (cm->mparm[P_PASSWD_ROW]+VSHIFT) +#define TIMEOUT_ROW (cm->mparm[P_TIMEOUT_ROW]+VSHIFT) +#define HELPMSG_ROW (cm->mparm[P_HELPMSG_ROW]+VSHIFT) +#define HELPMSGEND_ROW (cm->mparm[P_HELPMSGEND_ROW]) +#define HSHIFT (cm->mparm[P_HSHIFT]) +#define VSHIFT (cm->mparm[P_VSHIFT]) +#define HIDDEN_ROW (cm->mparm[P_HIDDEN_ROW]) + +static char *pad_line(const char *text, int align, int width) +{ + static char buffer[MAX_CMDLINE_LEN]; + int n, p; + + if (width >= (int)sizeof buffer) + return NULL; /* Can't do it */ + + n = strlen(text); + if (n >= width) + n = width; + + memset(buffer, ' ', width); + buffer[width] = 0; + p = ((width - n) * align) >> 1; + memcpy(buffer + p, text, n); + + return buffer; +} + +/* Display an entry, with possible hotkey highlight. Assumes + that the current attribute is the non-hotkey one, and will + guarantee that as an exit condition as well. */ +static void +display_entry(const struct menu_entry *entry, const char *attrib, + const char *hotattrib, int width) +{ + const char *p = entry->displayname; + char marker; + + if (!p) + p = ""; + + switch (entry->action) { + case MA_SUBMENU: + marker = '>'; + break; + case MA_EXIT: + marker = '<'; + break; + default: + marker = 0; + break; + } + + if (marker) + width -= 2; + + while (width) { + if (*p) { + if (*p == '^') { + p++; + if (*p && ((unsigned char)*p & ~0x20) == entry->hotkey) { + fputs(hotattrib, stdout); + putchar(*p++); + fputs(attrib, stdout); + width--; + } + } else { + putchar(*p++); + width--; + } + } else { + putchar(' '); + width--; + } + } + + if (marker) { + putchar(' '); + putchar(marker); + } +} + +static void draw_row(int y, int sel, int top, int sbtop, int sbbot) +{ + int i = (y - 4 - VSHIFT) + top; + int dis = (i < cm->nentries) && is_disabled(cm->menu_entries[i]); + + printf("\033[%d;%dH\1#1\016x\017%s ", + y, MARGIN + 1 + HSHIFT, + (i == sel) ? "\1#5" : dis ? "\2#17" : "\1#3"); + + if (i >= cm->nentries) { + fputs(pad_line("", 0, WIDTH - 2 * MARGIN - 4), stdout); + } else { + display_entry(cm->menu_entries[i], + (i == sel) ? "\1#5" : dis ? "\2#17" : "\1#3", + (i == sel) ? "\1#6" : dis ? "\2#17" : "\1#4", + WIDTH - 2 * MARGIN - 4); + } + + if (cm->nentries <= MENU_ROWS) { + printf(" \1#1\016x\017"); + } else if (sbtop > 0) { + if (y >= sbtop && y <= sbbot) + printf(" \1#7\016a\017"); + else + printf(" \1#1\016x\017"); + } else { + putchar(' '); /* Don't modify the scrollbar */ + } +} + +static jmp_buf timeout_jump; + +int mygetkey(clock_t timeout) +{ + clock_t t0, t; + clock_t tto, to; + int key; + + if (!totaltimeout) + return get_key(stdin, timeout); + + for (;;) { + tto = min(totaltimeout, INT_MAX); + to = timeout ? min(tto, timeout) : tto; + + t0 = times(NULL); + key = get_key(stdin, to); + t = times(NULL) - t0; + + if (totaltimeout <= t) + longjmp(timeout_jump, 1); + + totaltimeout -= t; + + if (key != KEY_NONE) + return key; + + if (timeout) { + if (timeout <= t) + return KEY_NONE; + + timeout -= t; + } + } +} + +static int ask_passwd(const char *menu_entry) +{ + char user_passwd[WIDTH], *p; + int done; + int key; + int x; + int rv; + + printf("\033[%d;%dH\2#11\016l", PASSWD_ROW, PASSWD_MARGIN + 1); + for (x = 2; x <= WIDTH - 2 * PASSWD_MARGIN - 1; x++) + putchar('q'); + + printf("k\033[%d;%dHx", PASSWD_ROW + 1, PASSWD_MARGIN + 1); + for (x = 2; x <= WIDTH - 2 * PASSWD_MARGIN - 1; x++) + putchar(' '); + + printf("x\033[%d;%dHm", PASSWD_ROW + 2, PASSWD_MARGIN + 1); + for (x = 2; x <= WIDTH - 2 * PASSWD_MARGIN - 1; x++) + putchar('q'); + + printf("j\017\033[%d;%dH\2#12 %s \033[%d;%dH\2#13", + PASSWD_ROW, (WIDTH - (strlen(cm->messages[MSG_PASSPROMPT]) + 2)) / 2, + cm->messages[MSG_PASSPROMPT], PASSWD_ROW + 1, PASSWD_MARGIN + 3); + + drain_keyboard(); + + /* Actually allow user to type a password, then compare to the SHA1 */ + done = 0; + p = user_passwd; + + while (!done) { + key = mygetkey(0); + + switch (key) { + case KEY_ENTER: + case KEY_CTRL('J'): + done = 1; + break; + + case KEY_ESC: + case KEY_CTRL('C'): + p = user_passwd; /* No password entered */ + done = 1; + break; + + case KEY_BACKSPACE: + case KEY_DEL: + case KEY_DELETE: + if (p > user_passwd) { + printf("\b \b"); + p--; + } + break; + + case KEY_CTRL('U'): + while (p > user_passwd) { + printf("\b \b"); + p--; + } + break; + + default: + if (key >= ' ' && key <= 0xFF && + (p - user_passwd) < WIDTH - 2 * PASSWD_MARGIN - 5) { + *p++ = key; + putchar('*'); + } + break; + } + } + + if (p == user_passwd) + return 0; /* No password entered */ + + *p = '\0'; + + rv = (cm->menu_master_passwd && + passwd_compare(cm->menu_master_passwd, user_passwd)) + || (menu_entry && passwd_compare(menu_entry, user_passwd)); + + /* Clean up */ + memset(user_passwd, 0, WIDTH); + drain_keyboard(); + + return rv; +} + +static void draw_menu(int sel, int top, int edit_line) +{ + int x, y; + int sbtop = 0, sbbot = 0; + const char *tabmsg; + int tabmsg_len; + + if (cm->nentries > MENU_ROWS) { + int sblen = max(MENU_ROWS * MENU_ROWS / cm->nentries, 1); + sbtop = (MENU_ROWS - sblen + 1) * top / (cm->nentries - MENU_ROWS + 1); + sbbot = sbtop + sblen - 1; + sbtop += 4; + sbbot += 4; /* Starting row of scrollbar */ + } + + printf("\033[%d;%dH\1#1\016l", VSHIFT + 1, HSHIFT + MARGIN + 1); + for (x = 2 + HSHIFT; x <= (WIDTH - 2 * MARGIN - 1) + HSHIFT; x++) + putchar('q'); + + printf("k\033[%d;%dH\1#1x\017\1#2 %s \1#1\016x", + VSHIFT + 2, + HSHIFT + MARGIN + 1, pad_line(cm->title, 1, WIDTH - 2 * MARGIN - 4)); + + printf("\033[%d;%dH\1#1t", VSHIFT + 3, HSHIFT + MARGIN + 1); + for (x = 2 + HSHIFT; x <= (WIDTH - 2 * MARGIN - 1) + HSHIFT; x++) + putchar('q'); + fputs("u\017", stdout); + + for (y = 4 + VSHIFT; y < 4 + VSHIFT + MENU_ROWS; y++) + draw_row(y, sel, top, sbtop, sbbot); + + printf("\033[%d;%dH\1#1\016m", y, HSHIFT + MARGIN + 1); + for (x = 2 + HSHIFT; x <= (WIDTH - 2 * MARGIN - 1) + HSHIFT; x++) + putchar('q'); + fputs("j\017", stdout); + + if (edit_line && cm->allowedit && !cm->menu_master_passwd) + tabmsg = cm->messages[MSG_TAB]; + else + tabmsg = cm->messages[MSG_NOTAB]; + + tabmsg_len = strlen(tabmsg); + + printf("\1#8\033[%d;%dH%s", + TABMSG_ROW, 1 + HSHIFT + ((WIDTH - tabmsg_len) >> 1), tabmsg); + printf("\1#0\033[%d;1H", END_ROW); +} + +static void clear_screen(void) +{ + fputs("\033e\033%@\033)0\033(B\1#0\033[?25l\033[2J", stdout); +} + +static void display_help(const char *text) +{ + int row; + const char *p; + + if (!text) { + text = ""; + printf("\1#0\033[%d;1H", HELPMSG_ROW); + } else { + printf("\2#16\033[%d;1H", HELPMSG_ROW); + } + + for (p = text, row = HELPMSG_ROW; *p && row <= HELPMSGEND_ROW; p++) { + switch (*p) { + case '\r': + case '\f': + case '\v': + case '\033': + break; + case '\n': + printf("\033[K\033[%d;1H", ++row); + break; + default: + putchar(*p); + } + } + + fputs("\033[K", stdout); + + while (row <= HELPMSGEND_ROW) { + printf("\033[K\033[%d;1H", ++row); + } +} + +static void show_fkey(int key) +{ + int fkey; + + while (1) { + switch (key) { + case KEY_F1: + fkey = 0; + break; + case KEY_F2: + fkey = 1; + break; + case KEY_F3: + fkey = 2; + break; + case KEY_F4: + fkey = 3; + break; + case KEY_F5: + fkey = 4; + break; + case KEY_F6: + fkey = 5; + break; + case KEY_F7: + fkey = 6; + break; + case KEY_F8: + fkey = 7; + break; + case KEY_F9: + fkey = 8; + break; + case KEY_F10: + fkey = 9; + break; + case KEY_F11: + fkey = 10; + break; + case KEY_F12: + fkey = 11; + break; + default: + fkey = -1; + break; + } + + if (fkey == -1) + break; + + if (cm->fkeyhelp[fkey].textname) + key = show_message_file(cm->fkeyhelp[fkey].textname, + cm->fkeyhelp[fkey].background); + else + break; + } +} + +static const char *edit_cmdline(const char *input, int top) +{ + static char cmdline[MAX_CMDLINE_LEN]; + int key, len, prev_len, cursor; + int redraw = 1; /* We enter with the menu already drawn */ + + strlcpy(cmdline, input, MAX_CMDLINE_LEN); + cmdline[MAX_CMDLINE_LEN - 1] = '\0'; + + len = cursor = strlen(cmdline); + prev_len = 0; + + for (;;) { + if (redraw > 1) { + /* Clear and redraw whole screen */ + /* Enable ASCII on G0 and DEC VT on G1; do it in this order + to avoid confusing the Linux console */ + clear_screen(); + draw_menu(-1, top, 1); + prev_len = 0; + } + + if (redraw > 0) { + /* Redraw the command line */ + printf("\033[?25l\033[%d;1H\1#9> \2#10%s", + CMDLINE_ROW, pad_line(cmdline, 0, max(len, prev_len))); + printf("\2#10\033[%d;3H%s\033[?25h", + CMDLINE_ROW, pad_line(cmdline, 0, cursor)); + prev_len = len; + redraw = 0; + } + + key = mygetkey(0); + + switch (key) { + case KEY_CTRL('L'): + redraw = 2; + break; + + case KEY_ENTER: + case KEY_CTRL('J'): + return cmdline; + + case KEY_ESC: + case KEY_CTRL('C'): + return NULL; + + case KEY_BACKSPACE: + case KEY_DEL: + if (cursor) { + memmove(cmdline + cursor - 1, cmdline + cursor, + len - cursor + 1); + len--; + cursor--; + redraw = 1; + } + break; + + case KEY_CTRL('D'): + case KEY_DELETE: + if (cursor < len) { + memmove(cmdline + cursor, cmdline + cursor + 1, len - cursor); + len--; + redraw = 1; + } + break; + + case KEY_CTRL('U'): + if (len) { + len = cursor = 0; + cmdline[len] = '\0'; + redraw = 1; + } + break; + + case KEY_CTRL('W'): + if (cursor) { + int prevcursor = cursor; + + while (cursor && my_isspace(cmdline[cursor - 1])) + cursor--; + + while (cursor && !my_isspace(cmdline[cursor - 1])) + cursor--; + + memmove(cmdline + cursor, cmdline + prevcursor, + len - prevcursor + 1); + len -= (prevcursor - cursor); + redraw = 1; + } + break; + + case KEY_LEFT: + case KEY_CTRL('B'): + if (cursor) { + cursor--; + redraw = 1; + } + break; + + case KEY_RIGHT: + case KEY_CTRL('F'): + if (cursor < len) { + putchar(cmdline[cursor++]); + } + break; + + case KEY_CTRL('K'): + if (cursor < len) { + cmdline[len = cursor] = '\0'; + redraw = 1; + } + break; + + case KEY_HOME: + case KEY_CTRL('A'): + if (cursor) { + cursor = 0; + redraw = 1; + } + break; + + case KEY_END: + case KEY_CTRL('E'): + if (cursor != len) { + cursor = len; + redraw = 1; + } + break; + + case KEY_F1: + case KEY_F2: + case KEY_F3: + case KEY_F4: + case KEY_F5: + case KEY_F6: + case KEY_F7: + case KEY_F8: + case KEY_F9: + case KEY_F10: + case KEY_F11: + case KEY_F12: + show_fkey(key); + redraw = 1; + break; + + default: + if (key >= ' ' && key <= 0xFF && len < MAX_CMDLINE_LEN - 1) { + if (cursor == len) { + cmdline[len] = key; + cmdline[++len] = '\0'; + cursor++; + putchar(key); + prev_len++; + } else { + memmove(cmdline + cursor + 1, cmdline + cursor, + len - cursor + 1); + cmdline[cursor++] = key; + len++; + redraw = 1; + } + } + break; + } + } +} + +static inline int shift_is_held(void) +{ + uint8_t shift_bits = *(uint8_t *) 0x417; + + return !!(shift_bits & 0x5d); /* Caps/Scroll/Alt/Shift */ +} + +static void print_timeout_message(int tol, int row, const char *msg) +{ + static int last_msg_len = 0; + char buf[256]; + int nc = 0, nnc, padc; + const char *tp = msg; + char tc; + char *tq = buf; + + while ((size_t) (tq - buf) < (sizeof buf - 16) && (tc = *tp)) { + tp++; + if (tc == '#') { + nnc = sprintf(tq, "\2#15%d\2#14", tol); + tq += nnc; + nc += nnc - 8; /* 8 formatting characters */ + } else if (tc == '{') { + /* Deal with {singular[,dual],plural} constructs */ + struct { + const char *s, *e; + } tx[3]; + const char *tpp; + int n = 0; + + memset(tx, 0, sizeof tx); + + tx[0].s = tp; + + while (*tp && *tp != '}') { + if (*tp == ',' && n < 2) { + tx[n].e = tp; + n++; + tx[n].s = tp + 1; + } + tp++; + } + tx[n].e = tp; + + if (*tp) + tp++; /* Skip final bracket */ + + if (!tx[1].s) + tx[1] = tx[0]; + if (!tx[2].s) + tx[2] = tx[1]; + + /* Now [0] is singular, [1] is dual, and [2] is plural, + even if the user only specified some of them. */ + + switch (tol) { + case 1: + n = 0; + break; + case 2: + n = 1; + break; + default: + n = 2; + break; + } + + for (tpp = tx[n].s; tpp < tx[n].e; tpp++) { + if ((size_t) (tq - buf) < (sizeof buf)) { + *tq++ = *tpp; + nc++; + } + } + } else { + *tq++ = tc; + nc++; + } + } + *tq = '\0'; + + if (nc >= last_msg_len) { + padc = 0; + } else { + padc = (last_msg_len - nc + 1) >> 1; + } + + printf("\033[%d;%dH\2#14%*s%s%*s", row, + HSHIFT + 1 + ((WIDTH - nc) >> 1) - padc, + padc, "", buf, padc, ""); + + last_msg_len = nc; +} + +/* Set the background screen, etc. */ +static void prepare_screen_for_menu(void) +{ + console_color_table = cm->color_table; + console_color_table_size = menu_color_table_size; + set_background(cm->menu_background); +} + +static const char *do_hidden_menu(void) +{ + int key; + int timeout_left, this_timeout; + + clear_screen(); + + if (!setjmp(timeout_jump)) { + timeout_left = cm->timeout; + + while (!cm->timeout || timeout_left) { + int tol = timeout_left / CLK_TCK; + + print_timeout_message(tol, HIDDEN_ROW, cm->messages[MSG_AUTOBOOT]); + + this_timeout = min(timeout_left, CLK_TCK); + key = mygetkey(this_timeout); + + if (key != KEY_NONE) + return NULL; /* Key pressed */ + + timeout_left -= this_timeout; + } + } + + /* Clear the message from the screen */ + print_timeout_message(0, HIDDEN_ROW, ""); + + if (cm->ontimeout) + return cm->ontimeout; + else + return cm->menu_entries[cm->defentry]->cmdline; /* Default entry */ +} + +static const char *run_menu(void) +{ + int key; + int done = 0; + volatile int entry = cm->curentry; + int prev_entry = -1; + volatile int top = cm->curtop; + int prev_top = -1; + int clear = 1, to_clear; + const char *cmdline = NULL; + volatile clock_t key_timeout, timeout_left, this_timeout; + const struct menu_entry *me; + bool hotkey = false; + + /* Note: for both key_timeout and timeout == 0 means no limit */ + timeout_left = key_timeout = cm->timeout; + + /* If we're in shiftkey mode, exit immediately unless a shift key + is pressed */ + if (shiftkey && !shift_is_held()) { + return cm->menu_entries[cm->defentry]->cmdline; + } else { + shiftkey = 0; + } + + /* Do this before hiddenmenu handling, so we show the background */ + prepare_screen_for_menu(); + + /* Handle hiddenmenu */ + if (hiddenmenu) { + cmdline = do_hidden_menu(); + if (cmdline) + return cmdline; + + /* Otherwise display the menu now; the timeout has already been + cancelled, since the user pressed a key. */ + hiddenmenu = 0; + key_timeout = 0; + } + + /* Handle both local and global timeout */ + if (setjmp(timeout_jump)) { + entry = cm->defentry; + + if (top < 0 || top < entry - MENU_ROWS + 1) + top = max(0, entry - MENU_ROWS + 1); + else if (top > entry || top > max(0, cm->nentries - MENU_ROWS)) + top = min(entry, max(0, cm->nentries - MENU_ROWS)); + + draw_menu(cm->ontimeout ? -1 : entry, top, 1); + cmdline = + cm->ontimeout ? cm->ontimeout : cm->menu_entries[entry]->cmdline; + done = 1; + } + + while (!done) { + if (entry <= 0) { + entry = 0; + while (entry < cm->nentries && is_disabled(cm->menu_entries[entry])) + entry++; + } + if (entry >= cm->nentries) { + entry = cm->nentries - 1; + while (entry > 0 && is_disabled(cm->menu_entries[entry])) + entry--; + } + + me = cm->menu_entries[entry]; + + if (top < 0 || top < entry - MENU_ROWS + 1) + top = max(0, entry - MENU_ROWS + 1); + else if (top > entry || top > max(0, cm->nentries - MENU_ROWS)) + top = min(entry, max(0, cm->nentries - MENU_ROWS)); + + /* Start with a clear screen */ + if (clear) { + /* Clear and redraw whole screen */ + /* Enable ASCII on G0 and DEC VT on G1; do it in this order + to avoid confusing the Linux console */ + if (clear >= 2) + prepare_screen_for_menu(); + clear_screen(); + clear = 0; + prev_entry = prev_top = -1; + } + + if (top != prev_top) { + draw_menu(entry, top, 1); + display_help(me->helptext); + } else if (entry != prev_entry) { + draw_row(prev_entry - top + 4 + VSHIFT, entry, top, 0, 0); + draw_row(entry - top + 4 + VSHIFT, entry, top, 0, 0); + display_help(me->helptext); + } + + prev_entry = entry; + prev_top = top; + cm->curentry = entry; + cm->curtop = top; + + /* Cursor movement cancels timeout */ + if (entry != cm->defentry) + key_timeout = 0; + + if (key_timeout) { + int tol = timeout_left / CLK_TCK; + print_timeout_message(tol, TIMEOUT_ROW, cm->messages[MSG_AUTOBOOT]); + to_clear = 1; + } else { + to_clear = 0; + } + + if (hotkey && me->immediate) { + /* If the hotkey was flagged immediate, simulate pressing ENTER */ + key = KEY_ENTER; + } else { + this_timeout = min(min(key_timeout, timeout_left), + (clock_t) CLK_TCK); + key = mygetkey(this_timeout); + + if (key != KEY_NONE) { + timeout_left = key_timeout; + if (to_clear) + printf("\033[%d;1H\1#0\033[K", TIMEOUT_ROW); + } + } + + hotkey = false; + + switch (key) { + case KEY_NONE: /* Timeout */ + /* This is somewhat hacky, but this at least lets the user + know what's going on, and still deals with "phantom inputs" + e.g. on serial ports. + + Warning: a timeout will boot the default entry without any + password! */ + if (key_timeout) { + if (timeout_left <= this_timeout) + longjmp(timeout_jump, 1); + + timeout_left -= this_timeout; + } + break; + + case KEY_CTRL('L'): + clear = 1; + break; + + case KEY_ENTER: + case KEY_CTRL('J'): + key_timeout = 0; /* Cancels timeout */ + if (me->passwd) { + clear = 1; + done = ask_passwd(me->passwd); + } else { + done = 1; + } + cmdline = NULL; + if (done) { + switch (me->action) { + case MA_CMD: + cmdline = me->cmdline; + break; + case MA_SUBMENU: + case MA_GOTO: + case MA_EXIT: + done = 0; + clear = 2; + cm = me->submenu; + entry = cm->curentry; + top = cm->curtop; + break; + case MA_QUIT: + /* Quit menu system */ + done = 1; + clear = 1; + draw_row(entry - top + 4 + VSHIFT, -1, top, 0, 0); + break; + case MA_HELP: + key = show_message_file(me->cmdline, me->background); + /* If the exit was an F-key, display that help screen */ + show_fkey(key); + done = 0; + clear = 1; + break; + default: + done = 0; + break; + } + } + if (done && !me->passwd) { + /* Only save a new default if we don't have a password... */ + if (me->save && me->label) { + syslinux_setadv(ADV_MENUSAVE, strlen(me->label), me->label); + syslinux_adv_write(); + } + } + break; + + case KEY_UP: + case KEY_CTRL('P'): + while (entry > 0) { + entry--; + if (entry < top) + top -= MENU_ROWS; + if (!is_disabled(cm->menu_entries[entry])) + break; + } + break; + + case KEY_DOWN: + case KEY_CTRL('N'): + while (entry < cm->nentries - 1) { + entry++; + if (entry >= top + MENU_ROWS) + top += MENU_ROWS; + if (!is_disabled(cm->menu_entries[entry])) + break; + } + break; + + case KEY_PGUP: + case KEY_LEFT: + case KEY_CTRL('B'): + case '<': + entry -= MENU_ROWS; + top -= MENU_ROWS; + while (entry > 0 && is_disabled(cm->menu_entries[entry])) { + entry--; + if (entry < top) + top -= MENU_ROWS; + } + break; + + case KEY_PGDN: + case KEY_RIGHT: + case KEY_CTRL('F'): + case '>': + case ' ': + entry += MENU_ROWS; + top += MENU_ROWS; + while (entry < cm->nentries - 1 + && is_disabled(cm->menu_entries[entry])) { + entry++; + if (entry >= top + MENU_ROWS) + top += MENU_ROWS; + } + break; + + case '-': + while (entry > 0) { + entry--; + top--; + if (!is_disabled(cm->menu_entries[entry])) + break; + } + break; + + case '+': + while (entry < cm->nentries - 1) { + entry++; + top++; + if (!is_disabled(cm->menu_entries[entry])) + break; + } + break; + + case KEY_CTRL('A'): + case KEY_HOME: + top = entry = 0; + break; + + case KEY_CTRL('E'): + case KEY_END: + entry = cm->nentries - 1; + top = max(0, cm->nentries - MENU_ROWS); + break; + + case KEY_F1: + case KEY_F2: + case KEY_F3: + case KEY_F4: + case KEY_F5: + case KEY_F6: + case KEY_F7: + case KEY_F8: + case KEY_F9: + case KEY_F10: + case KEY_F11: + case KEY_F12: + show_fkey(key); + clear = 1; + break; + + case KEY_TAB: + if (cm->allowedit && me->action == MA_CMD) { + int ok = 1; + + key_timeout = 0; /* Cancels timeout */ + draw_row(entry - top + 4 + VSHIFT, -1, top, 0, 0); + + if (cm->menu_master_passwd) { + ok = ask_passwd(NULL); + clear_screen(); + draw_menu(-1, top, 0); + } else { + /* Erase [Tab] message and help text */ + printf("\033[%d;1H\1#0\033[K", TABMSG_ROW); + display_help(NULL); + } + + if (ok) { + cmdline = edit_cmdline(me->cmdline, top); + done = !!cmdline; + clear = 1; /* In case we hit [Esc] and done is null */ + } else { + draw_row(entry - top + 4 + VSHIFT, entry, top, 0, 0); + } + } + break; + case KEY_CTRL('C'): /* Ctrl-C */ + case KEY_ESC: /* Esc */ + if (cm->parent) { + cm = cm->parent; + clear = 2; + entry = cm->curentry; + top = cm->curtop; + } else if (cm->allowedit) { + done = 1; + clear = 1; + key_timeout = 0; + + draw_row(entry - top + 4 + VSHIFT, -1, top, 0, 0); + + if (cm->menu_master_passwd) + done = ask_passwd(NULL); + } + break; + default: + if (key > 0 && key < 0xFF) { + key &= ~0x20; /* Upper case */ + if (cm->menu_hotkeys[key]) { + key_timeout = 0; + entry = cm->menu_hotkeys[key]->entry; + /* Should we commit at this point? */ + hotkey = true; + } + } + break; + } + } + + printf("\033[?25h"); /* Show cursor */ + + /* Return the label name so localboot and ipappend work */ + return cmdline; +} + +int main(int argc, char *argv[]) +{ + const char *cmdline; + struct menu *m; + int rows, cols; + int i; + + (void)argc; + + parse_configs(argv + 1); + + /* + * We don't start the console until we have parsed the configuration + * file, since the configuration file might impact the console + * configuration, e.g. MENU RESOLUTION. + */ + start_console(); + if (getscreensize(1, &rows, &cols)) { + /* Unknown screen size? */ + rows = 24; + cols = 80; + } + + /* Some postprocessing for all menus */ + for (m = menu_list; m; m = m->next) { + if (!m->mparm[P_WIDTH]) + m->mparm[P_WIDTH] = cols; + + /* If anyone has specified negative parameters, consider them + relative to the bottom row of the screen. */ + for (i = 0; i < NPARAMS; i++) + if (m->mparm[i] < 0) + m->mparm[i] = max(m->mparm[i] + rows, 0); + } + + cm = start_menu; + + if (!cm->nentries) { + fputs("Initial menu has no LABEL entries!\n", stdout); + return 1; /* Error! */ + } + + for (;;) { + local_cursor_enable(true); + cmdline = run_menu(); + + if (clearmenu) + clear_screen(); + + local_cursor_enable(false); + printf("\033[?25h\033[%d;1H\033[0m", END_ROW); + + if (cmdline) { + execute(cmdline, KT_NONE); + if (cm->onerror) + execute(cm->onerror, KT_NONE); + } else { + return 0; /* Exit */ + } + } +} diff --git a/contrib/syslinux-4.02/com32/menu/passwd.c b/contrib/syslinux-4.02/com32/menu/passwd.c new file mode 100644 index 0000000..d5cfd08 --- /dev/null +++ b/contrib/syslinux-4.02/com32/menu/passwd.c @@ -0,0 +1,96 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-2008 H. Peter Anvin - All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +#include <string.h> +#include <xcrypt.h> +#include <sha1.h> +#include <base64.h> + +#include "menu.h" + +static int passwd_compare_sha1(const char *passwd, const char *entry) +{ + struct { + SHA1_CTX ctx; + unsigned char sha1[20], pwdsha1[20]; + } d; + const char *p; + int rv; + + SHA1Init(&d.ctx); + + if ((p = strchr(passwd + 3, '$'))) { + SHA1Update(&d.ctx, (void *)passwd + 3, p - (passwd + 3)); + p++; + } else { + p = passwd + 3; /* Assume no salt */ + } + + SHA1Update(&d.ctx, (void *)entry, strlen(entry)); + SHA1Final(d.sha1, &d.ctx); + + memset(d.pwdsha1, 0, 20); + unbase64(d.pwdsha1, 20, p); + + rv = !memcmp(d.sha1, d.pwdsha1, 20); + + memset(&d, 0, sizeof d); + return rv; +} + +static int passwd_compare_md5(const char *passwd, const char *entry) +{ + const char *crypted = crypt_md5(entry, passwd + 3); + int len = strlen(crypted); + + return !strncmp(crypted, passwd, len) && + (passwd[len] == '\0' || passwd[len] == '$'); +} + +static int passwd_compare_sha256(const char *passwd, const char *entry) +{ + const char *crypted = sha256_crypt(entry, passwd + 3); + int len = strlen(crypted); + + return !strncmp(crypted, passwd, len) && + (passwd[len] == '\0' || passwd[len] == '$'); +} + +static int passwd_compare_sha512(const char *passwd, const char *entry) +{ + const char *crypted = sha512_crypt(entry, passwd + 3); + int len = strlen(crypted); + + return !strncmp(crypted, passwd, len) && + (passwd[len] == '\0' || passwd[len] == '$'); +} + +int passwd_compare(const char *passwd, const char *entry) +{ + if (passwd[0] != '$' || !passwd[1] || passwd[2] != '$') { + /* Plaintext passwd, yuck! */ + return !strcmp(entry, passwd); + } else { + switch (passwd[1]) { + case '1': + return passwd_compare_md5(passwd, entry); + case '4': + return passwd_compare_sha1(passwd, entry); + case '5': + return passwd_compare_sha256(passwd, entry); + case '6': + return passwd_compare_sha512(passwd, entry); + default: + return 0; /* Unknown encryption algorithm -> false */ + } + } +} diff --git a/contrib/syslinux-4.02/com32/menu/printmsg.c b/contrib/syslinux-4.02/com32/menu/printmsg.c new file mode 100644 index 0000000..cfceac3 --- /dev/null +++ b/contrib/syslinux-4.02/com32/menu/printmsg.c @@ -0,0 +1,119 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-2008 H. Peter Anvin - All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +#include <ctype.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <consoles.h> +#include <getkey.h> +#include <minmax.h> +#include <setjmp.h> +#include <limits.h> +#include <sha1.h> +#include <base64.h> +#include <colortbl.h> +#ifdef __COM32__ +#include <com32.h> +#endif + +#include "menu.h" + +static int draw_message_file(const char *filename) +{ + FILE *f; + int ch; + enum msgname_state { + st_init, /* Base state */ + st_si_1, /* <SI> digit 1 */ + st_si_2, /* <SI> digit 2 */ + st_skipline, /* Skip until NL */ + } state = st_init; + int eof = 0; + int attr = 0; + + f = fopen(filename, "r"); + if (!f) + return -1; + + /* Clear screen, hide cursor, default attribute */ + printf("\033e\033%%@\033)0\033(B\3#%03d\033[?25l\033[2J\033[H", + message_base_color + 0x07); + + while (!eof && (ch = getc(f)) != EOF) { + switch (state) { + case st_init: + switch (ch) { + case '\f': + fputs("\033[2J\033[H", stdout); + break; + case 15: /* SI */ + state = st_si_1; + break; + case 24: + state = st_skipline; + break; + case 26: + eof = 1; + break; + case '\a': + case '\n': + case '\r': + putchar(ch); + break; + default: + if (ch >= 32) + putchar(ch); + break; + } + break; + + case st_si_1: + attr = hexval(ch) << 4; + state = st_si_2; + break; + + case st_si_2: + attr |= hexval(ch); + printf("\3#%03d", attr + message_base_color); + state = st_init; + break; + + case st_skipline: + if (ch == '\n') + state = st_init; + break; + } + } + + fclose(f); + return 0; +} + +int show_message_file(const char *filename, const char *background) +{ + int rv = KEY_NONE; + const char *old_background = NULL; + + if (background) { + old_background = current_background; + set_background(background); + } + + if (!(rv = draw_message_file(filename))) + rv = mygetkey(0); /* Wait for keypress */ + + if (old_background) + set_background(old_background); + + return rv; +} diff --git a/contrib/syslinux-4.02/com32/menu/readconfig.c b/contrib/syslinux-4.02/com32/menu/readconfig.c new file mode 100644 index 0000000..8c16fda --- /dev/null +++ b/contrib/syslinux-4.02/com32/menu/readconfig.c @@ -0,0 +1,1107 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +#include <stdio.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <minmax.h> +#include <alloca.h> +#include <inttypes.h> +#include <colortbl.h> +#include <com32.h> +#include <syslinux/adv.h> +#include <syslinux/config.h> + +#include "menu.h" + +/* Empty refstring */ +const char *empty_string; + +/* Root menu, starting menu, hidden menu, and list of all menus */ +struct menu *root_menu, *start_menu, *hide_menu, *menu_list; + +/* These are global parameters regardless of which menu we're displaying */ +int shiftkey = 0; /* Only display menu if shift key pressed */ +int hiddenmenu = 0; +int clearmenu = 0; +long long totaltimeout = 0; + +/* Keep track of global default */ +static int has_ui = 0; /* DEFAULT only counts if UI is found */ +static const char *globaldefault = NULL; +static bool menusave = false; /* True if there is any "menu save" */ + +/* Linked list of all entires, hidden or not; used by unlabel() */ +static struct menu_entry *all_entries; +static struct menu_entry **all_entries_end = &all_entries; + +static const struct messages messages[MSG_COUNT] = { + [MSG_AUTOBOOT] = {"autoboot", "Automatic boot in # second{,s}..."}, + [MSG_TAB] = {"tabmsg", "Press [Tab] to edit options"}, + [MSG_NOTAB] = {"notabmsg", ""}, + [MSG_PASSPROMPT] = {"passprompt", "Password required"}, +}; + +#define astrdup(x) ({ char *__x = (x); \ + size_t __n = strlen(__x) + 1; \ + char *__p = alloca(__n); \ + if ( __p ) memcpy(__p, __x, __n); \ + __p; }) + +/* Must match enum kernel_type */ +const char *const kernel_types[] = { + "none", + "localboot", + "kernel", + "linux", + "boot", + "bss", + "pxe", + "fdimage", + "comboot", + "com32", + "config", + NULL +}; + +/* + * Search the list of all menus for a specific label + */ +static struct menu *find_menu(const char *label) +{ + struct menu *m; + + for (m = menu_list; m; m = m->next) { + if (!strcmp(label, m->label)) + return m; + } + + return NULL; +} + +#define MAX_LINE 4096 + +static char *skipspace(char *p) +{ + while (*p && my_isspace(*p)) + p++; + + return p; +} + +/* Strip ^ from a string, returning a new reference to the same refstring + if none present */ +static const char *strip_caret(const char *str) +{ + const char *p, *r; + char *q; + int carets = 0; + + p = str; + for (;;) { + p = strchr(p, '^'); + if (!p) + break; + carets++; + p++; + } + + if (!carets) + return refstr_get(str); + + r = q = refstr_alloc(strlen(str) - carets); + for (p = str; *p; p++) + if (*p != '^') + *q++ = *p; + + *q = '\0'; /* refstr_alloc() already did this... */ + + return r; +} + +/* Check to see if we are at a certain keyword (case insensitive) */ +/* Returns a pointer to the first character past the keyword */ +static char *looking_at(char *line, const char *kwd) +{ + char *p = line; + const char *q = kwd; + + while (*p && *q && ((*p ^ *q) & ~0x20) == 0) { + p++; + q++; + } + + if (*q) + return NULL; /* Didn't see the keyword */ + + return my_isspace(*p) ? p : NULL; /* Must be EOL or whitespace */ +} + +static struct menu *new_menu(struct menu *parent, + struct menu_entry *parent_entry, const char *label) +{ + struct menu *m = calloc(1, sizeof(struct menu)); + int i; + + m->label = label; + m->title = refstr_get(empty_string); + + if (parent) { + /* Submenu */ + m->parent = parent; + m->parent_entry = parent_entry; + parent_entry->action = MA_SUBMENU; + parent_entry->submenu = m; + + for (i = 0; i < MSG_COUNT; i++) + m->messages[i] = refstr_get(parent->messages[i]); + + memcpy(m->mparm, parent->mparm, sizeof m->mparm); + + m->allowedit = parent->allowedit; + m->timeout = parent->timeout; + m->save = parent->save; + m->immediate = parent->immediate; + + m->ontimeout = refstr_get(parent->ontimeout); + m->onerror = refstr_get(parent->onerror); + m->menu_master_passwd = refstr_get(parent->menu_master_passwd); + m->menu_background = refstr_get(parent->menu_background); + + m->color_table = copy_color_table(parent->color_table); + + for (i = 0; i < 12; i++) { + m->fkeyhelp[i].textname = refstr_get(parent->fkeyhelp[i].textname); + m->fkeyhelp[i].background = + refstr_get(parent->fkeyhelp[i].background); + } + } else { + /* Root menu */ + for (i = 0; i < MSG_COUNT; i++) + m->messages[i] = refstrdup(messages[i].defmsg); + for (i = 0; i < NPARAMS; i++) + m->mparm[i] = mparm[i].value; + + m->allowedit = true; /* Allow edits of the command line */ + m->color_table = default_color_table(); + } + + m->next = menu_list; + menu_list = m; + + return m; +} + +struct labeldata { + const char *label; + const char *kernel; + enum kernel_type type; + const char *append; + const char *initrd; + const char *menulabel; + const char *passwd; + char *helptext; + unsigned int ipappend; + unsigned int menuhide; + unsigned int menudefault; + unsigned int menuseparator; + unsigned int menudisabled; + unsigned int menuindent; + enum menu_action action; + int save; + int immediate; + struct menu *submenu; +}; + +/* Menu currently being parsed */ +static struct menu *current_menu; + +static void clear_label_data(struct labeldata *ld) +{ + refstr_put(ld->label); + refstr_put(ld->kernel); + refstr_put(ld->append); + refstr_put(ld->initrd); + refstr_put(ld->menulabel); + refstr_put(ld->passwd); + + memset(ld, 0, sizeof *ld); +} + +static struct menu_entry *new_entry(struct menu *m) +{ + struct menu_entry *me; + + if (m->nentries >= m->nentries_space) { + if (!m->nentries_space) + m->nentries_space = 1; + else + m->nentries_space <<= 1; + + m->menu_entries = realloc(m->menu_entries, m->nentries_space * + sizeof(struct menu_entry *)); + } + + me = calloc(1, sizeof(struct menu_entry)); + me->menu = m; + me->entry = m->nentries; + m->menu_entries[m->nentries++] = me; + *all_entries_end = me; + all_entries_end = &me->next; + + return me; +} + +static void consider_for_hotkey(struct menu *m, struct menu_entry *me) +{ + const char *p = strchr(me->displayname, '^'); + + if (me->action != MA_DISABLED) { + if (p && p[1]) { + unsigned char hotkey = p[1] & ~0x20; + if (!m->menu_hotkeys[hotkey]) { + me->hotkey = hotkey; + m->menu_hotkeys[hotkey] = me; + } + } + } +} + +static void record(struct menu *m, struct labeldata *ld, const char *append) +{ + int i; + struct menu_entry *me; + const struct syslinux_ipappend_strings *ipappend; + + if (!ld->label) + return; /* Nothing defined */ + + /* Hidden entries are recorded on a special "hidden menu" */ + if (ld->menuhide) + m = hide_menu; + + if (ld->label) { + char ipoptions[4096], *ipp; + const char *a; + char *s; + + me = new_entry(m); + + me->displayname = ld->menulabel + ? refstr_get(ld->menulabel) : refstr_get(ld->label); + me->label = refstr_get(ld->label); + me->passwd = refstr_get(ld->passwd); + me->helptext = ld->helptext; + me->hotkey = 0; + me->action = ld->action ? ld->action : MA_CMD; + me->save = ld->save ? (ld->save > 0) : m->save; + me->immediate = ld->immediate ? (ld->immediate > 0) : m->immediate; + + if (ld->menuindent) { + const char *dn; + + rsprintf(&dn, "%*s%s", ld->menuindent, "", me->displayname); + refstr_put(me->displayname); + me->displayname = dn; + } + + if (ld->menuseparator) { + refstr_put(me->displayname); + me->displayname = refstr_get(empty_string); + } + + if (ld->menuseparator || ld->menudisabled) { + me->action = MA_DISABLED; + refstr_put(me->label); + me->label = NULL; + refstr_put(me->passwd); + me->passwd = NULL; + } + + if (ld->menulabel) + consider_for_hotkey(m, me); + + switch (me->action) { + case MA_CMD: + ipp = ipoptions; + *ipp = '\0'; + + if (ld->initrd) + ipp += sprintf(ipp, " initrd=%s", ld->initrd); + + if (ld->ipappend) { + ipappend = syslinux_ipappend_strings(); + for (i = 0; i < ipappend->count; i++) { + if ((ld->ipappend & (1U << i)) && ipappend->ptr[i] && + ipappend->ptr[i][0]) + ipp += sprintf(ipp, " %s", ipappend->ptr[i]); + } + } + + a = ld->append; + if (!a) + a = append; + if (!a || (a[0] == '-' && !a[1])) + a = ""; + s = a[0] ? " " : ""; + if (ld->type == KT_KERNEL) { + rsprintf(&me->cmdline, "%s%s%s%s", ld->kernel, s, a, ipoptions); + } else { + rsprintf(&me->cmdline, ".%s %s%s%s%s", + kernel_types[ld->type], ld->kernel, s, a, ipoptions); + } + break; + + case MA_GOTO_UNRES: + case MA_EXIT_UNRES: + me->cmdline = refstr_get(ld->kernel); + break; + + case MA_GOTO: + case MA_EXIT: + me->submenu = ld->submenu; + break; + + case MA_HELP: + me->cmdline = refstr_get(ld->kernel); + me->background = refstr_get(ld->append); + break; + + default: + break; + } + + if (ld->menudefault && me->action == MA_CMD) + m->defentry = m->nentries - 1; + } + + clear_label_data(ld); +} + +static struct menu *begin_submenu(const char *tag) +{ + struct menu_entry *me; + + if (!tag[0]) + tag = NULL; + + me = new_entry(current_menu); + me->displayname = refstrdup(tag); + return new_menu(current_menu, me, refstr_get(me->displayname)); +} + +static struct menu *end_submenu(void) +{ + return current_menu->parent ? current_menu->parent : current_menu; +} + +static struct menu_entry *find_label(const char *str) +{ + const char *p; + struct menu_entry *me; + int pos; + + p = str; + while (*p && !my_isspace(*p)) + p++; + + /* p now points to the first byte beyond the kernel name */ + pos = p - str; + + for (me = all_entries; me; me = me->next) { + if (!strncmp(str, me->label, pos) && !me->label[pos]) + return me; + } + + return NULL; +} + +static const char *unlabel(const char *str) +{ + /* Convert a CLI-style command line to an executable command line */ + const char *p; + const char *q; + struct menu_entry *me; + int pos; + + p = str; + while (*p && !my_isspace(*p)) + p++; + + /* p now points to the first byte beyond the kernel name */ + pos = p - str; + + for (me = all_entries; me; me = me->next) { + if (!strncmp(str, me->label, pos) && !me->label[pos]) { + /* Found matching label */ + rsprintf(&q, "%s%s", me->cmdline, p); + refstr_put(str); + return q; + } + } + + return str; +} + +static const char *refdup_word(char **p) +{ + char *sp = *p; + char *ep = sp; + + while (*ep && !my_isspace(*ep)) + ep++; + + *p = ep; + return refstrndup(sp, ep - sp); +} + +int my_isxdigit(char c) +{ + unsigned int uc = c; + + return (uc - '0') < 10 || ((uc | 0x20) - 'a') < 6; +} + +unsigned int hexval(char c) +{ + unsigned char uc = c | 0x20; + unsigned int v; + + v = uc - '0'; + if (v < 10) + return v; + + return uc - 'a' + 10; +} + +unsigned int hexval2(const char *p) +{ + return (hexval(p[0]) << 4) + hexval(p[1]); +} + +uint32_t parse_argb(char **p) +{ + char *sp = *p; + char *ep; + uint32_t argb; + size_t len, dl; + + if (*sp == '#') + sp++; + + ep = sp; + + while (my_isxdigit(*ep)) + ep++; + + *p = ep; + len = ep - sp; + + switch (len) { + case 3: /* #rgb */ + argb = + 0xff000000 + + (hexval(sp[0]) * 0x11 << 16) + + (hexval(sp[1]) * 0x11 << 8) + (hexval(sp[2]) * 0x11); + break; + case 4: /* #argb */ + argb = + (hexval(sp[0]) * 0x11 << 24) + + (hexval(sp[1]) * 0x11 << 16) + + (hexval(sp[2]) * 0x11 << 8) + (hexval(sp[3]) * 0x11); + break; + case 6: /* #rrggbb */ + case 9: /* #rrrgggbbb */ + case 12: /* #rrrrggggbbbb */ + dl = len / 3; + argb = + 0xff000000 + + (hexval2(sp + 0) << 16) + + (hexval2(sp + dl) << 8) + hexval2(sp + dl * 2); + break; + case 8: /* #aarrggbb */ + /* #aaarrrgggbbb is indistinguishable from #rrrrggggbbbb, + assume the latter is a more common format */ + case 16: /* #aaaarrrrggggbbbb */ + dl = len / 4; + argb = + (hexval2(sp + 0) << 24) + + (hexval2(sp + dl) << 16) + + (hexval2(sp + dl * 2) << 8) + hexval2(sp + dl * 3); + break; + default: + argb = 0xffff0000; /* Bright red (error indication) */ + break; + } + + return argb; +} + +/* + * Parser state. This is global so that including multiple + * files work as expected, which is that everything works the + * same way as if the files had been concatenated together. + */ +static const char *append = NULL; +static unsigned int ipappend = 0; +static struct labeldata ld; + +static int parse_one_config(const char *filename); + +static char *is_kernel_type(char *cmdstr, enum kernel_type *type) +{ + const char *const *p; + char *q; + enum kernel_type t = KT_NONE; + + for (p = kernel_types; *p; p++, t++) { + if ((q = looking_at(cmdstr, *p))) { + *type = t; + return q; + } + } + + return NULL; +} + +static char *is_message_name(char *cmdstr, enum message_number *msgnr) +{ + char *q; + enum message_number i; + + for (i = 0; i < MSG_COUNT; i++) { + if ((q = looking_at(cmdstr, messages[i].name))) { + *msgnr = i; + return q; + } + } + + return NULL; +} + +static char *is_fkey(char *cmdstr, int *fkeyno) +{ + char *q; + int no; + + if ((cmdstr[0] | 0x20) != 'f') + return NULL; + + no = strtoul(cmdstr + 1, &q, 10); + if (!my_isspace(*q)) + return NULL; + + if (no < 0 || no > 12) + return NULL; + + *fkeyno = (no == 0) ? 10 : no - 1; + return q; +} + +static void parse_config_file(FILE * f) +{ + char line[MAX_LINE], *p, *ep, ch; + enum kernel_type type = -1; + enum message_number msgnr = -1; + int fkeyno = 0; + struct menu *m = current_menu; + + while (fgets(line, sizeof line, f)) { + p = strchr(line, '\r'); + if (p) + *p = '\0'; + p = strchr(line, '\n'); + if (p) + *p = '\0'; + + p = skipspace(line); + + if (looking_at(p, "menu")) { + p = skipspace(p + 4); + + if (looking_at(p, "label")) { + if (ld.label) { + refstr_put(ld.menulabel); + ld.menulabel = refstrdup(skipspace(p + 5)); + } else if (m->parent_entry) { + refstr_put(m->parent_entry->displayname); + m->parent_entry->displayname = refstrdup(skipspace(p + 5)); + consider_for_hotkey(m->parent, m->parent_entry); + if (!m->title[0]) { + /* MENU LABEL -> MENU TITLE on submenu */ + refstr_put(m->title); + m->title = strip_caret(m->parent_entry->displayname); + } + } + } else if (looking_at(p, "title")) { + refstr_put(m->title); + m->title = refstrdup(skipspace(p + 5)); + if (m->parent_entry) { + /* MENU TITLE -> MENU LABEL on submenu */ + if (m->parent_entry->displayname == m->label) { + refstr_put(m->parent_entry->displayname); + m->parent_entry->displayname = refstr_get(m->title); + } + } + } else if (looking_at(p, "default")) { + if (ld.label) { + ld.menudefault = 1; + } else if (m->parent_entry) { + m->parent->defentry = m->parent_entry->entry; + } + } else if (looking_at(p, "hide")) { + ld.menuhide = 1; + } else if (looking_at(p, "passwd")) { + if (ld.label) { + refstr_put(ld.passwd); + ld.passwd = refstrdup(skipspace(p + 6)); + } else if (m->parent_entry) { + refstr_put(m->parent_entry->passwd); + m->parent_entry->passwd = refstrdup(skipspace(p + 6)); + } + } else if (looking_at(p, "shiftkey")) { + shiftkey = 1; + } else if (looking_at(p, "save")) { + menusave = true; + if (ld.label) + ld.save = 1; + else + m->save = true; + } else if (looking_at(p, "nosave")) { + if (ld.label) + ld.save = -1; + else + m->save = false; + } else if (looking_at(p, "immediate")) { + if (ld.label) + ld.immediate = 1; + else + m->immediate = true; + } else if (looking_at(p, "noimmediate")) { + if (ld.label) + ld.immediate = -1; + else + m->immediate = false; + } else if (looking_at(p, "onerror")) { + refstr_put(m->onerror); + m->onerror = refstrdup(skipspace(p + 7)); + } else if (looking_at(p, "master")) { + p = skipspace(p + 6); + if (looking_at(p, "passwd")) { + refstr_put(m->menu_master_passwd); + m->menu_master_passwd = refstrdup(skipspace(p + 6)); + } + } else if ((ep = looking_at(p, "include"))) { + goto do_include; + } else if ((ep = looking_at(p, "background"))) { + p = skipspace(ep); + refstr_put(m->menu_background); + m->menu_background = refdup_word(&p); + } else if ((ep = looking_at(p, "hidden"))) { + hiddenmenu = 1; + } else if ((ep = looking_at(p, "clear"))) { + clearmenu = 1; + } else if ((ep = is_message_name(p, &msgnr))) { + refstr_put(m->messages[msgnr]); + m->messages[msgnr] = refstrdup(skipspace(ep)); + } else if ((ep = looking_at(p, "color")) || + (ep = looking_at(p, "colour"))) { + int i; + struct color_table *cptr; + p = skipspace(ep); + cptr = m->color_table; + for (i = 0; i < menu_color_table_size; i++) { + if ((ep = looking_at(p, cptr->name))) { + p = skipspace(ep); + if (*p) { + if (looking_at(p, "*")) { + p++; + } else { + refstr_put(cptr->ansi); + cptr->ansi = refdup_word(&p); + } + + p = skipspace(p); + if (*p) { + if (looking_at(p, "*")) + p++; + else + cptr->argb_fg = parse_argb(&p); + + p = skipspace(p); + if (*p) { + if (looking_at(p, "*")) + p++; + else + cptr->argb_bg = parse_argb(&p); + + /* Parse a shadow mode */ + p = skipspace(p); + ch = *p | 0x20; + if (ch == 'n') /* none */ + cptr->shadow = SHADOW_NONE; + else if (ch == 's') /* std, standard */ + cptr->shadow = SHADOW_NORMAL; + else if (ch == 'a') /* all */ + cptr->shadow = SHADOW_ALL; + else if (ch == 'r') /* rev, reverse */ + cptr->shadow = SHADOW_REVERSE; + } + } + } + break; + } + cptr++; + } + } else if ((ep = looking_at(p, "msgcolor")) || + (ep = looking_at(p, "msgcolour"))) { + unsigned int fg_mask = MSG_COLORS_DEF_FG; + unsigned int bg_mask = MSG_COLORS_DEF_BG; + enum color_table_shadow shadow = MSG_COLORS_DEF_SHADOW; + + p = skipspace(ep); + if (*p) { + if (!looking_at(p, "*")) + fg_mask = parse_argb(&p); + + p = skipspace(p); + if (*p) { + if (!looking_at(p, "*")) + bg_mask = parse_argb(&p); + + p = skipspace(p); + switch (*p | 0x20) { + case 'n': + shadow = SHADOW_NONE; + break; + case 's': + shadow = SHADOW_NORMAL; + break; + case 'a': + shadow = SHADOW_ALL; + break; + case 'r': + shadow = SHADOW_REVERSE; + break; + default: + /* go with default */ + break; + } + } + } + set_msg_colors_global(m->color_table, fg_mask, bg_mask, shadow); + } else if (looking_at(p, "separator")) { + record(m, &ld, append); + ld.label = refstr_get(empty_string); + ld.menuseparator = 1; + record(m, &ld, append); + } else if (looking_at(p, "disable") || looking_at(p, "disabled")) { + ld.menudisabled = 1; + } else if (looking_at(p, "indent")) { + ld.menuindent = atoi(skipspace(p + 6)); + } else if (looking_at(p, "begin")) { + record(m, &ld, append); + m = current_menu = begin_submenu(skipspace(p + 5)); + } else if (looking_at(p, "end")) { + record(m, &ld, append); + m = current_menu = end_submenu(); + } else if (looking_at(p, "quit")) { + if (ld.label) + ld.action = MA_QUIT; + } else if (looking_at(p, "goto")) { + if (ld.label) { + ld.action = MA_GOTO_UNRES; + refstr_put(ld.kernel); + ld.kernel = refstrdup(skipspace(p + 4)); + } + } else if (looking_at(p, "exit")) { + p = skipspace(p + 4); + if (ld.label && m->parent) { + if (*p) { + /* This is really just a goto, except for the marker */ + ld.action = MA_EXIT_UNRES; + refstr_put(ld.kernel); + ld.kernel = refstrdup(p); + } else { + ld.action = MA_EXIT; + ld.submenu = m->parent; + } + } + } else if (looking_at(p, "start")) { + start_menu = m; + } else if (looking_at(p, "help")) { + if (ld.label) { + ld.action = MA_HELP; + p = skipspace(p + 4); + + refstr_put(ld.kernel); + ld.kernel = refdup_word(&p); + + if (ld.append) { + refstr_put(ld.append); + ld.append = NULL; + } + + if (*p) { + p = skipspace(p); + ld.append = refdup_word(&p); /* Background */ + } + } + } else if ((ep = looking_at(p, "resolution"))) { + int x, y; + x = strtoul(ep, &ep, 0); + y = strtoul(skipspace(ep), NULL, 0); + set_resolution(x, y); + } else { + /* Unknown, check for layout parameters */ + enum parameter_number mp; + for (mp = 0; mp < NPARAMS; mp++) { + if ((ep = looking_at(p, mparm[mp].name))) { + m->mparm[mp] = atoi(skipspace(ep)); + break; + } + } + } + } else if (looking_at(p, "text")) { + enum text_cmd { + TEXT_UNKNOWN, + TEXT_HELP + } cmd = TEXT_UNKNOWN; + int len = ld.helptext ? strlen(ld.helptext) : 0; + int xlen; + + p = skipspace(p + 4); + + if (looking_at(p, "help")) + cmd = TEXT_HELP; + + while (fgets(line, sizeof line, f)) { + p = skipspace(line); + if (looking_at(p, "endtext")) + break; + + xlen = strlen(line); + + switch (cmd) { + case TEXT_UNKNOWN: + break; + case TEXT_HELP: + ld.helptext = realloc(ld.helptext, len + xlen + 1); + memcpy(ld.helptext + len, line, xlen + 1); + len += xlen; + break; + } + } + } else if ((ep = is_fkey(p, &fkeyno))) { + p = skipspace(ep); + if (m->fkeyhelp[fkeyno].textname) { + refstr_put(m->fkeyhelp[fkeyno].textname); + m->fkeyhelp[fkeyno].textname = NULL; + } + if (m->fkeyhelp[fkeyno].background) { + refstr_put(m->fkeyhelp[fkeyno].background); + m->fkeyhelp[fkeyno].background = NULL; + } + + refstr_put(m->fkeyhelp[fkeyno].textname); + m->fkeyhelp[fkeyno].textname = refdup_word(&p); + if (*p) { + p = skipspace(p); + m->fkeyhelp[fkeyno].background = refdup_word(&p); + } + } else if ((ep = looking_at(p, "include"))) { +do_include: + { + const char *file; + p = skipspace(ep); + file = refdup_word(&p); + p = skipspace(p); + if (*p) { + record(m, &ld, append); + m = current_menu = begin_submenu(p); + parse_one_config(file); + record(m, &ld, append); + m = current_menu = end_submenu(); + } else { + parse_one_config(file); + } + refstr_put(file); + } + } else if (looking_at(p, "append")) { + const char *a = refstrdup(skipspace(p + 6)); + if (ld.label) { + refstr_put(ld.append); + ld.append = a; + } else { + refstr_put(append); + append = a; + } + } else if (looking_at(p, "initrd")) { + const char *a = refstrdup(skipspace(p + 6)); + if (ld.label) { + refstr_put(ld.initrd); + ld.initrd = a; + } else { + /* Ignore */ + } + } else if (looking_at(p, "label")) { + p = skipspace(p + 5); + record(m, &ld, append); + ld.label = refstrdup(p); + ld.kernel = refstrdup(p); + ld.type = KT_KERNEL; + ld.passwd = NULL; + ld.append = NULL; + ld.initrd = NULL; + ld.menulabel = NULL; + ld.helptext = NULL; + ld.ipappend = ipappend; + ld.menudefault = ld.menuhide = ld.menuseparator = + ld.menudisabled = ld.menuindent = 0; + } else if ((ep = is_kernel_type(p, &type))) { + if (ld.label) { + refstr_put(ld.kernel); + ld.kernel = refstrdup(skipspace(ep)); + ld.type = type; + } + } else if (looking_at(p, "timeout")) { + m->timeout = (atoi(skipspace(p + 7)) * CLK_TCK + 9) / 10; + } else if (looking_at(p, "totaltimeout")) { + totaltimeout = (atoll(skipspace(p + 13)) * CLK_TCK + 9) / 10; + } else if (looking_at(p, "ontimeout")) { + m->ontimeout = refstrdup(skipspace(p + 9)); + } else if (looking_at(p, "allowoptions")) { + m->allowedit = !!atoi(skipspace(p + 12)); + } else if (looking_at(p, "ipappend")) { + if (ld.label) + ld.ipappend = atoi(skipspace(p + 8)); + else + ipappend = atoi(skipspace(p + 8)); + } else if (looking_at(p, "default")) { + refstr_put(globaldefault); + globaldefault = refstrdup(skipspace(p + 7)); + } else if (looking_at(p, "ui")) { + has_ui = 1; + } + } +} + +static int parse_one_config(const char *filename) +{ + FILE *f; + + if (!strcmp(filename, "~")) + filename = syslinux_config_file(); + + dprintf("Opening config file: %s ", filename); + + f = fopen(filename, "r"); + dprintf("%s\n", f ? "ok" : "failed"); + + if (!f) + return -1; + + parse_config_file(f); + fclose(f); + + return 0; +} + +static void resolve_gotos(void) +{ + struct menu_entry *me; + struct menu *m; + + for (me = all_entries; me; me = me->next) { + if (me->action == MA_GOTO_UNRES || me->action == MA_EXIT_UNRES) { + m = find_menu(me->cmdline); + refstr_put(me->cmdline); + me->cmdline = NULL; + if (m) { + me->submenu = m; + me->action--; /* Drop the _UNRES */ + } else { + me->action = MA_DISABLED; + } + } + } +} + +void parse_configs(char **argv) +{ + const char *filename; + struct menu *m; + struct menu_entry *me; + + empty_string = refstrdup(""); + + /* Initialize defaults for the root and hidden menus */ + hide_menu = new_menu(NULL, NULL, refstrdup(".hidden")); + root_menu = new_menu(NULL, NULL, refstrdup(".top")); + start_menu = root_menu; + + /* Other initialization */ + memset(&ld, 0, sizeof(struct labeldata)); + + /* Actually process the files */ + current_menu = root_menu; + if (!*argv) { + parse_one_config("~"); + } else { + while ((filename = *argv++)) + parse_one_config(filename); + } + + /* On final EOF process the last label statement */ + record(current_menu, &ld, append); + + /* Common postprocessing */ + resolve_gotos(); + + /* Handle global default */ + if (has_ui && globaldefault) { + me = find_label(globaldefault); + if (me && me->menu != hide_menu) { + me->menu->defentry = me->entry; + start_menu = me->menu; + } + } + + /* If "menu save" is active, let the ADV override the global default */ + if (menusave) { + size_t len; + const char *lbl = syslinux_getadv(ADV_MENUSAVE, &len); + char *lstr; + if (lbl && len) { + lstr = refstr_alloc(len); + memcpy(lstr, lbl, len); /* refstr_alloc() adds the final null */ + me = find_label(lstr); + if (me && me->menu != hide_menu) { + me->menu->defentry = me->entry; + start_menu = me->menu; + } + refstr_put(lstr); + } + } + + /* Final per-menu initialization, with all labels known */ + for (m = menu_list; m; m = m->next) { + m->curentry = m->defentry; /* All menus start at their defaults */ + + if (m->ontimeout) + m->ontimeout = unlabel(m->ontimeout); + if (m->onerror) + m->onerror = unlabel(m->onerror); + } +} diff --git a/contrib/syslinux-4.02/com32/menu/refstr.c b/contrib/syslinux-4.02/com32/menu/refstr.c new file mode 100644 index 0000000..97ab1ed --- /dev/null +++ b/contrib/syslinux-4.02/com32/menu/refstr.c @@ -0,0 +1,105 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2008 H. Peter Anvin - All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * refstr.c + * + * Simple reference-counted strings + */ + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include "refstr.h" + +/* Allocate space for a refstring of len bytes, plus final null */ +/* The final null is inserted in the string; the rest is uninitialized. */ +char *refstr_alloc(size_t len) +{ + char *r = malloc(sizeof(unsigned int) + len + 1); + if (!r) + return NULL; + *(unsigned int *)r = 1; + r += sizeof(unsigned int); + r[len] = '\0'; + return r; +} + +const char *refstrndup(const char *str, size_t len) +{ + char *r; + + if (!str) + return NULL; + + len = strnlen(str, len); + r = refstr_alloc(len); + if (r) + memcpy(r, str, len); + return r; +} + +const char *refstrdup(const char *str) +{ + char *r; + size_t len; + + if (!str) + return NULL; + + len = strlen(str); + r = refstr_alloc(len); + if (r) + memcpy(r, str, len); + return r; +} + +int vrsprintf(const char **bufp, const char *fmt, va_list ap) +{ + va_list ap1; + int len; + char *p; + + va_copy(ap1, ap); + len = vsnprintf(NULL, 0, fmt, ap1); + va_end(ap1); + + *bufp = p = refstr_alloc(len); + if (!p) + return -1; + + return vsnprintf(p, len + 1, fmt, ap); +} + +int rsprintf(const char **bufp, const char *fmt, ...) +{ + int rv; + va_list ap; + + va_start(ap, fmt); + rv = vrsprintf(bufp, fmt, ap); + va_end(ap); + + return rv; +} + +void refstr_put(const char *r) +{ + unsigned int *ref; + + if (r) { + ref = (unsigned int *)r - 1; + + if (!--*ref) + free(ref); + } +} diff --git a/contrib/syslinux-4.02/com32/menu/refstr.h b/contrib/syslinux-4.02/com32/menu/refstr.h new file mode 100644 index 0000000..7001d40 --- /dev/null +++ b/contrib/syslinux-4.02/com32/menu/refstr.h @@ -0,0 +1,40 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2008 H. Peter Anvin - All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * refstr.h + * + * Simple reference-counted strings + */ + +#ifndef REFSTR_H +#define REFSTR_H + +#include <stddef.h> +#include <stdarg.h> + +static inline __attribute__ ((always_inline)) +const char *refstr_get(const char *r) +{ + if (r) + ((unsigned int *)r)[-1]++; + return r; +} + +void refstr_put(const char *); +char *refstr_alloc(size_t); +const char *refstrdup(const char *); +const char *refstrndup(const char *, size_t); +int rsprintf(const char **, const char *, ...); +int vrsprintf(const char **, const char *, va_list); + +#endif diff --git a/contrib/syslinux-4.02/com32/menu/vesamenu.c b/contrib/syslinux-4.02/com32/menu/vesamenu.c new file mode 100644 index 0000000..62e29bd --- /dev/null +++ b/contrib/syslinux-4.02/com32/menu/vesamenu.c @@ -0,0 +1,52 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * vesamenu.c + * + * Simple menu system which displays a list and allows the user to select + * a command line and/or edit it. + * + * VESA graphics version. + */ + +#include <stdio.h> +#include <console.h> +#include <syslinux/vesacon.h> + +#include "menu.h" + +int draw_background(const char *what) +{ + if (!what) + return vesacon_default_background(); + else if (what[0] == '#') + return vesacon_set_background(parse_argb((char **)&what)); + else + return vesacon_load_background(what); +} + +void set_resolution(int x, int y) +{ + vesacon_set_resolution(x, y); +} + +void local_cursor_enable(bool enabled) +{ + vesacon_cursor_enable(enabled); +} + +void start_console(void) +{ + openconsole(&dev_rawcon_r, &dev_vesaserial_w); +} diff --git a/contrib/syslinux-4.02/com32/modules/Makefile b/contrib/syslinux-4.02/com32/modules/Makefile new file mode 100644 index 0000000..2d47913 --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/Makefile @@ -0,0 +1,59 @@ +## ----------------------------------------------------------------------- +## +## Copyright 2001-2009 H. Peter Anvin - All Rights Reserved +## Copyright 2009 Intel Corporation; author: H. Peter Anvin +## +## 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. +## +## ----------------------------------------------------------------------- + +## +## COM32 standard modules +## + +topdir = ../.. +include ../MCONFIG + +MODULES = chain.c32 config.c32 ethersel.c32 dmitest.c32 cpuidtest.c32 \ + disk.c32 pcitest.c32 elf.c32 linux.c32 reboot.c32 pmload.c32 \ + meminfo.c32 sdi.c32 sanboot.c32 ifcpu64.c32 vesainfo.c32 \ + kbdmap.c32 cmd.c32 vpdtest.c32 host.c32 ls.c32 gpxecmd.c32 \ + ifcpu.c32 cpuid.c32 cat.c32 pwd.c32 ifplop.c32 whichsys.c32 + +TESTFILES = + +all: $(MODULES) $(TESTFILES) + +pcitest.elf : pcitest.o $(LIBS) $(C_LIBS) + $(LD) $(LDFLAGS) -o $@ $^ + +cpuidtest.elf : cpuidtest.o $(GPLLIB) $(LIBS) $(C_LIBS) + $(LD) $(LDFLAGS) -o $@ $^ + +.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) + $(LD) $(LDFLAGS) -o $@ $^ + +tidy dist: + rm -f *.o *.lo *.a *.lst *.elf .*.d *.tmp + +clean: tidy + rm -f *.lnx + +spotless: clean + rm -f *.lss *.c32 *.com + rm -f *~ \#* + +install: + +-include .*.d diff --git a/contrib/syslinux-4.02/com32/modules/cat.c b/contrib/syslinux-4.02/com32/modules/cat.c new file mode 100644 index 0000000..0a9514c --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/cat.c @@ -0,0 +1,33 @@ +#include <stdio.h> +#include <stdlib.h> +#include <console.h> + +int main(int argc, char *argv[]) +{ + FILE *f; + int i; + int len; + char buf[4096]; + + openconsole(&dev_stdcon_r, &dev_stdcon_w); + + if (argc < 2) { + fprintf(stderr, "Usage: %s filename...\n", argv[0]); + return 1; + } + + for (i = 1; i < argc; i++) { + f = fopen(argv[i], "r"); + if (!f) { + fprintf(stderr, "%s: %s: file not found\n", argv[0], argv[i]); + return 1; + } + + while ((len = fread(buf, 1, sizeof buf, f)) > 0) + fwrite(buf, 1, len, stdout); + + fclose(f); + } + + return 0; +} diff --git a/contrib/syslinux-4.02/com32/modules/chain.c b/contrib/syslinux-4.02/com32/modules/chain.c new file mode 100644 index 0000000..48a83d2 --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/chain.c @@ -0,0 +1,1826 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin + * Significant portions copyright (C) 2010 Shao Miller + * [partition iteration, GPT, "fs"] + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * chain.c + * + * Chainload a hard disk (currently rather braindead.) + * + * Usage: chain [options] + * chain hd<disk#> [<partition>] [options] + * chain fd<disk#> [options] + * chain mbr:<id> [<partition>] [options] + * chain guid:<guid> [<partition>] [options] + * chain label:<label> [<partition>] [options] + * chain boot [<partition>] [options] + * + * For example, "chain msdos=io.sys" will load DOS from the current Syslinux + * filesystem. "chain hd0 1" will boot the first partition on the first hard + * disk. + * + * When none of the "hdX", "fdX", "mbr:", "guid:", "label:", "boot" or "fs" + * options are specified, the default behaviour is equivalent to "boot". + * "boot" means to use the current Syslinux drive, and you can also specify + * a partition. + * + * The mbr: syntax means search all the hard disks until one with a + * specific MBR serial number (bytes 440-443) is found. + * + * Partitions 1-4 are primary, 5+ logical, 0 = boot MBR (default.) + * + * "fs" will use the current Syslinux filesystem as the boot drive/partition. + * When booting from PXELINUX, you will most likely wish to specify a disk. + * + * Options: + * + * file=<loader> + * loads the file <loader> **from the Syslinux filesystem** + * instead of loading the boot sector. + * + * seg=<segment> + * loads at and jumps to <seg>:0000 instead of 0000:7C00. + * + * isolinux=<loader> + * chainload another version/build of the ISOLINUX bootloader and patch + * the loader with appropriate parameters in memory. + * This avoids the need for the -eltorito-alt-boot parameter of mkisofs, + * when you want more than one ISOLINUX per CD/DVD. + * + * ntldr=<loader> + * equivalent to seg=0x2000 file=<loader> sethidden, + * used with WinNT's loaders + * + * cmldr=<loader> + * used with Recovery Console of Windows NT/2K/XP. + * same as ntldr=<loader> & "cmdcons\0" written to + * the system name field in the bootsector + * + * freedos=<loader> + * equivalent to seg=0x60 file=<loader> sethidden, + * used with FreeDOS' kernel.sys. + * + * msdos=<loader> + * pcdos=<loader> + * equivalent to seg=0x70 file=<loader> sethidden, + * used with DOS' io.sys. + * + * grub=<loader> + * same as seg=0x800 file=<loader> & jumping to seg 0x820, + * used with GRUB Legacy stage2 files. + * + * grubcfg=<filename> + * set an alternative config filename in stage2 of Grub Legacy, + * only applicable in combination with "grub=<loader>". + * + * grldr=<loader> + * pass the partition number to GRUB4DOS, + * used with GRUB4DOS' grldr. + * + * swap + * if the disk is not fd0/hd0, install a BIOS stub which swaps + * the drive numbers. + * + * hide + * change type of primary partitions with IDs 01, 04, 06, 07, + * 0b, 0c, or 0e to 1x, except for the selected partition, which + * is converted the other way. + * + * sethidden + * update the "hidden sectors" (partition offset) field in a + * FAT/NTFS boot sector. + * + * keeppxe + * keep the PXE and UNDI stacks in memory (PXELINUX only). + */ + +#include <com32.h> +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include <console.h> +#include <minmax.h> +#include <stdbool.h> +#include <dprintf.h> +#include <syslinux/loadfile.h> +#include <syslinux/bootrm.h> +#include <syslinux/config.h> +#include <syslinux/video.h> + +#define SECTOR 512 /* bytes/sector */ + +static struct options { + const char *loadfile; + uint16_t keeppxe; + uint16_t seg; + bool isolinux; + bool cmldr; + bool grub; + bool grldr; + const char *grubcfg; + bool swap; + bool hide; + bool sethidden; +} opt; + +struct data_area { + void *data; + addr_t base; + addr_t size; +}; + +static inline void error(const char *msg) +{ + fputs(msg, stderr); +} + +/* + * Call int 13h, but with retry on failure. Especially floppies need this. + */ +static 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 */ +} + +/* + * Query disk parameters and EBIOS availability for a particular disk. + */ +struct diskinfo { + int disk; + int ebios; /* EBIOS supported on this disk */ + int cbios; /* CHS geometry is valid */ + int head; + int sect; +} disk_info; + +static int get_disk_params(int disk) +{ + static com32sys_t getparm, parm, getebios, ebios; + + disk_info.disk = disk; + disk_info.ebios = disk_info.cbios = 0; + + /* 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); + + if (!(ebios.eflags.l & EFLAGS_CF) && + ebios.ebx.w[0] == 0xaa55 && (ebios.ecx.b[0] & 1)) { + disk_info.ebios = 1; + } + + /* Get disk parameters -- really only useful for + hard disks, but if we have a partitioned floppy + it's actually our best chance... */ + getparm.eax.b[1] = 0x08; + getparm.edx.b[0] = disk; + + __intcall(0x13, &getparm, &parm); + + if (parm.eflags.l & EFLAGS_CF) + return disk_info.ebios ? 0 : -1; + + disk_info.head = parm.edx.b[1] + 1; + disk_info.sect = parm.ecx.b[0] & 0x3f; + if (disk_info.sect == 0) { + disk_info.sect = 1; + } else { + disk_info.cbios = 1; /* Valid geometry */ + } + + return 0; +} + +/* + * 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; +}; + +/* Read count sectors from drive, starting at lba. Return a new buffer */ +static void *read_sectors(uint64_t lba, uint8_t count) +{ + com32sys_t inreg; + struct ebios_dapa *dapa = __com32.cs_bounce; + void *buf = (char *)__com32.cs_bounce + SECTOR; + void *data; + + if (!count) + /* Silly */ + return NULL; + + memset(&inreg, 0, sizeof inreg); + + if (disk_info.ebios) { + dapa->len = sizeof(*dapa); + dapa->count = count; + dapa->off = OFFS(buf); + dapa->seg = SEG(buf); + dapa->lba = lba; + + inreg.esi.w[0] = OFFS(dapa); + inreg.ds = SEG(dapa); + inreg.edx.b[0] = disk_info.disk; + inreg.eax.b[1] = 0x42; /* Extended read */ + } else { + unsigned int c, h, s, t; + + if (!disk_info.cbios) { + /* We failed to get the geometry */ + + if (lba) + return NULL; /* Can only read MBR */ + + s = 1; + h = 0; + c = 0; + } else { + s = (lba % disk_info.sect) + 1; + t = lba / disk_info.sect; /* Track = head*cyl */ + h = t % disk_info.head; + c = t / disk_info.head; + } + + if (s > 63 || h > 256 || c > 1023) + return NULL; + + inreg.eax.b[0] = count; + inreg.eax.b[1] = 0x02; /* Read */ + inreg.ecx.b[1] = c & 0xff; + inreg.ecx.b[0] = s + (c >> 6); + inreg.edx.b[1] = h; + inreg.edx.b[0] = disk_info.disk; + inreg.ebx.w[0] = OFFS(buf); + inreg.es = SEG(buf); + } + + if (int13_retry(&inreg, NULL)) + return NULL; + + data = malloc(count * SECTOR); + if (data) + memcpy(data, buf, count * SECTOR); + return data; +} + +static int write_sector(unsigned int lba, const void *data) +{ + com32sys_t inreg; + struct ebios_dapa *dapa = __com32.cs_bounce; + void *buf = (char *)__com32.cs_bounce + SECTOR; + + memcpy(buf, data, SECTOR); + memset(&inreg, 0, sizeof inreg); + + if (disk_info.ebios) { + dapa->len = sizeof(*dapa); + dapa->count = 1; /* 1 sector */ + dapa->off = OFFS(buf); + dapa->seg = SEG(buf); + dapa->lba = lba; + + inreg.esi.w[0] = OFFS(dapa); + inreg.ds = SEG(dapa); + inreg.edx.b[0] = disk_info.disk; + inreg.eax.w[0] = 0x4300; /* Extended write */ + } else { + unsigned int c, h, s, t; + + if (!disk_info.cbios) { + /* We failed to get the geometry */ + + if (lba) + return -1; /* Can only write MBR */ + + s = 1; + h = 0; + c = 0; + } else { + s = (lba % disk_info.sect) + 1; + t = lba / disk_info.sect; /* Track = head*cyl */ + h = t % disk_info.head; + c = t / disk_info.head; + } + + if (s > 63 || h > 256 || c > 1023) + return -1; + + inreg.eax.w[0] = 0x0301; /* Write one sector */ + inreg.ecx.b[1] = c & 0xff; + inreg.ecx.b[0] = s + (c >> 6); + inreg.edx.b[1] = h; + inreg.edx.b[0] = disk_info.disk; + inreg.ebx.w[0] = OFFS(buf); + inreg.es = SEG(buf); + } + + if (int13_retry(&inreg, NULL)) + return -1; + + return 0; /* ok */ +} + +static int write_verify_sector(unsigned int lba, const void *buf) +{ + char *rb; + int rv; + + rv = write_sector(lba, buf); + if (rv) + return rv; /* Write failure */ + rb = read_sectors(lba, 1); + if (!rb) + return -1; /* Readback failure */ + rv = memcmp(buf, rb, SECTOR); + free(rb); + return rv ? -1 : 0; +} + +/* + * CHS (cylinder, head, sector) value extraction macros. + * Taken from WinVBlock. Does not expand to an lvalue +*/ +#define chs_head(chs) chs[0] +#define chs_sector(chs) (chs[1] & 0x3F) +#define chs_cyl_high(chs) (((uint16_t)(chs[1] & 0xC0)) << 2) +#define chs_cyl_low(chs) ((uint16_t)chs[2]) +#define chs_cylinder(chs) (chs_cyl_high(chs) | chs_cyl_low(chs)) +typedef uint8_t chs[3]; + +/* A DOS partition table entry */ +struct part_entry { + uint8_t active_flag; /* 0x80 if "active" */ + chs start; + uint8_t ostype; + chs end; + uint32_t start_lba; + uint32_t length; +} __attribute__ ((packed)); + +static void mbr_part_dump(const struct part_entry *part) +{ + (void)part; + dprintf("Partition status _____ : 0x%.2x\n" + "Partition CHS start\n" + " Cylinder ___________ : 0x%.4x (%u)\n" + " Head _______________ : 0x%.2x (%u)\n" + " Sector _____________ : 0x%.2x (%u)\n" + "Partition type _______ : 0x%.2x\n" + "Partition CHS end\n" + " Cylinder ___________ : 0x%.4x (%u)\n" + " Head _______________ : 0x%.2x (%u)\n" + " Sector _____________ : 0x%.2x (%u)\n" + "Partition LBA start __ : 0x%.8x (%u)\n" + "Partition LBA count __ : 0x%.8x (%u)\n" + "-------------------------------\n", + part->active_flag, + chs_cylinder(part->start), + chs_cylinder(part->start), + chs_head(part->start), + chs_head(part->start), + chs_sector(part->start), + chs_sector(part->start), + part->ostype, + chs_cylinder(part->end), + chs_cylinder(part->end), + chs_head(part->end), + chs_head(part->end), + chs_sector(part->end), + chs_sector(part->end), + part->start_lba, + part->start_lba, + part->length, + part->length); +} + +/* A DOS MBR */ +struct mbr { + char code[440]; + uint32_t disk_sig; + char pad[2]; + struct part_entry table[4]; + uint16_t sig; +} __attribute__ ((packed)); +static const uint16_t mbr_sig_magic = 0xAA55; + +/* Search for a specific drive, based on the MBR signature; bytes 440-443 */ +static int find_disk(uint32_t mbr_sig) +{ + int drive; + bool is_me; + struct mbr *mbr; + + for (drive = 0x80; drive <= 0xff; drive++) { + if (get_disk_params(drive)) + continue; /* Drive doesn't exist */ + if (!(mbr = read_sectors(0, 1))) + continue; /* Cannot read sector */ + is_me = (mbr->disk_sig == mbr_sig); + free(mbr); + if (is_me) + return drive; + } + return -1; +} + +/* Forward declaration */ +struct disk_part_iter; + +/* Partition-/scheme-specific routine returning the next partition */ +typedef struct disk_part_iter *(*disk_part_iter_func) (struct disk_part_iter * + part); + +/* Contains details for a partition under examination */ +struct disk_part_iter { + /* The block holding the table we are part of */ + char *block; + /* The LBA for the beginning of data */ + uint64_t lba_data; + /* The partition number, as determined by our heuristic */ + int index; + /* The DOS partition record to pass, if applicable */ + const struct part_entry *record; + /* Function returning the next available partition */ + disk_part_iter_func next; + /* Partition-/scheme-specific details */ + union { + /* MBR specifics */ + int mbr_index; + /* EBR specifics */ + struct { + /* The first extended partition's start LBA */ + uint64_t lba_extended; + /* Any applicable parent, or NULL */ + struct disk_part_iter *parent; + /* The parent extended partition index */ + int parent_index; + } ebr; + /* GPT specifics */ + struct { + /* Real (not effective) index in the partition table */ + int index; + /* Current partition GUID */ + const struct guid *part_guid; + /* Current partition label */ + const char *part_label; + /* Count of entries in GPT */ + int parts; + /* Partition record size */ + uint32_t size; + } gpt; + } private; +}; + +static struct disk_part_iter *next_ebr_part(struct disk_part_iter *part) +{ + const struct part_entry *ebr_table; + const struct part_entry *parent_table = + ((const struct mbr *)part->private.ebr.parent->block)->table; + static const struct part_entry phony = {.start_lba = 0 }; + uint64_t ebr_lba; + + /* Don't look for a "next EBR" the first time around */ + if (part->private.ebr.parent_index >= 0) + /* Look at the linked list */ + ebr_table = ((const struct mbr *)part->block)->table + 1; + /* Do we need to look for an extended partition? */ + if (part->private.ebr.parent_index < 0 || !ebr_table->start_lba) { + /* Start looking for an extended partition in the MBR */ + while (++part->private.ebr.parent_index < 4) { + uint8_t type = parent_table[part->private.ebr.parent_index].ostype; + + if ((type == 0x05) || (type == 0x0F) || (type == 0x85)) + break; + } + if (part->private.ebr.parent_index == 4) + /* No extended partitions found */ + goto out_finished; + part->private.ebr.lba_extended = + parent_table[part->private.ebr.parent_index].start_lba; + ebr_table = &phony; + } + /* Load next EBR */ + ebr_lba = ebr_table->start_lba + part->private.ebr.lba_extended; + free(part->block); + part->block = read_sectors(ebr_lba, 1); + if (!part->block) { + error("Could not load EBR!\n"); + goto err_ebr; + } + ebr_table = ((const struct mbr *)part->block)->table; + dprintf("next_ebr_part:\n"); + mbr_part_dump(ebr_table); + + /* + * Sanity check entry: must not extend outside the + * extended partition. This is necessary since some OSes + * put crap in some entries. + */ + { + const struct mbr *mbr = + (const struct mbr *)part->private.ebr.parent->block; + const struct part_entry *extended = + mbr->table + part->private.ebr.parent_index; + + if (ebr_table[0].start_lba >= extended->start_lba + extended->length) { + dprintf("Insane logical partition!\n"); + goto err_insane; + } + } + /* Success */ + part->lba_data = ebr_table[0].start_lba + ebr_lba; + dprintf("Partition %d logical lba %u\n", part->index, part->lba_data); + part->index++; + part->record = ebr_table; + return part; + +err_insane: + + free(part->block); + part->block = NULL; +err_ebr: + +out_finished: + free(part->private.ebr.parent->block); + free(part->private.ebr.parent); + free(part->block); + free(part); + return NULL; +} + +static struct disk_part_iter *next_mbr_part(struct disk_part_iter *part) +{ + struct disk_part_iter *ebr_part; + /* Look at the partition table */ + struct part_entry *table = ((struct mbr *)part->block)->table; + + /* Look for data partitions */ + while (++part->private.mbr_index < 4) { + uint8_t type = table[part->private.mbr_index].ostype; + + if (type == 0x00 || type == 0x05 || type == 0x0F || type == 0x85) + /* Skip empty or extended partitions */ + continue; + if (!table[part->private.mbr_index].length) + /* Empty */ + continue; + break; + } + /* If we're currently the last partition, it's time for EBR processing */ + if (part->private.mbr_index == 4) { + /* Allocate another iterator for extended partitions */ + ebr_part = malloc(sizeof(*ebr_part)); + if (!ebr_part) { + error("Could not allocate extended partition iterator!\n"); + goto err_alloc; + } + /* Setup EBR iterator parameters */ + ebr_part->block = NULL; + ebr_part->index = 4; + ebr_part->record = NULL; + ebr_part->next = next_ebr_part; + ebr_part->private.ebr.parent = part; + /* Trigger an initial EBR load */ + ebr_part->private.ebr.parent_index = -1; + /* The EBR iterator is responsible for freeing us */ + return next_ebr_part(ebr_part); + } + dprintf("next_mbr_part:\n"); + mbr_part_dump(table + part->private.mbr_index); + + /* Update parameters to reflect this new partition. Re-use iterator */ + part->lba_data = table[part->private.mbr_index].start_lba; + dprintf("Partition %d primary lba %u\n", part->index, part->lba_data); + part->index++; + part->record = table + part->private.mbr_index; + return part; + + free(ebr_part); +err_alloc: + + free(part->block); + free(part); + return NULL; +} + +/* + * GUID + * Be careful with endianness, you must adjust it yourself + * iff you are directly using the fourth data chunk + */ +struct guid { + uint32_t data1; + uint16_t data2; + uint16_t data3; + uint64_t data4; +} __attribute__ ((packed)); + + /* + * This walk-map effectively reverses the little-endian + * portions of the GUID in the output text + */ +static const char guid_le_walk_map[] = { + 3, -1, -1, -1, 0, + 5, -1, 0, + 3, -1, 0, + 2, 1, 0, + 1, 1, 1, 1, 1, 1 +}; + +#if DEBUG +/* + * Fill a buffer with a textual GUID representation. + * The buffer must be >= char[37] and will be populated + * with an ASCII NUL C string terminator. + * Example: 11111111-2222-3333-4444-444444444444 + * Endian: LLLLLLLL-LLLL-LLLL-BBBB-BBBBBBBBBBBB + */ +static void guid_to_str(char *buf, const struct guid *id) +{ + unsigned int i = 0; + const char *walker = (const char *)id; + + while (i < sizeof(guid_le_walk_map)) { + walker += guid_le_walk_map[i]; + if (!guid_le_walk_map[i]) + *buf = '-'; + else { + *buf = ((*walker & 0xF0) >> 4) + '0'; + if (*buf > '9') + *buf += 'A' - '9' - 1; + buf++; + *buf = (*walker & 0x0F) + '0'; + if (*buf > '9') + *buf += 'A' - '9' - 1; + } + buf++; + i++; + } + *buf = 0; +} +#endif + +/* + * Create a GUID structure from a textual GUID representation. + * The input buffer must be >= 32 hexadecimal chars and be + * terminated with an ASCII NUL. Returns non-zero on failure. + * Example: 11111111-2222-3333-4444-444444444444 + * Endian: LLLLLLLL-LLLL-LLLL-BBBB-BBBBBBBBBBBB + */ +static int str_to_guid(const char *buf, struct guid *id) +{ + char guid_seq[sizeof(struct guid) * 2]; + unsigned int i = 0; + char *walker = (char *)id; + + while (*buf && i < sizeof(guid_seq)) { + switch (*buf) { + /* Skip these three characters */ + case '{': + case '}': + case '-': + break; + default: + /* Copy something useful to the temp. sequence */ + if ((*buf >= '0') && (*buf <= '9')) + guid_seq[i] = *buf - '0'; + else if ((*buf >= 'A') && (*buf <= 'F')) + guid_seq[i] = *buf - 'A' + 10; + else if ((*buf >= 'a') && (*buf <= 'f')) + guid_seq[i] = *buf - 'a' + 10; + else { + /* Or not */ + error("Illegal character in GUID!\n"); + return -1; + } + i++; + } + buf++; + } + /* Check for insufficient valid characters */ + if (i < sizeof(guid_seq)) { + error("Too few GUID characters!\n"); + return -1; + } + buf = guid_seq; + i = 0; + while (i < sizeof(guid_le_walk_map)) { + if (!guid_le_walk_map[i]) + i++; + walker += guid_le_walk_map[i]; + *walker = *buf << 4; + buf++; + *walker |= *buf; + buf++; + i++; + } + return 0; +} + +/* A GPT partition */ +struct gpt_part { + struct guid type; + struct guid uid; + uint64_t lba_first; + uint64_t lba_last; + uint64_t attribs; + char name[72]; +} __attribute__ ((packed)); + +static void gpt_part_dump(const struct gpt_part *gpt_part) +{ +#ifdef DEBUG + unsigned int i; + char guid_text[37]; + + dprintf("----------------------------------\n" + "GPT part. LBA first __ : 0x%.16llx\n" + "GPT part. LBA last ___ : 0x%.16llx\n" + "GPT part. attribs ____ : 0x%.16llx\n" + "GPT part. name _______ : '", + gpt_part->lba_first, gpt_part->lba_last, gpt_part->attribs); + for (i = 0; i < sizeof(gpt_part->name); i++) { + if (gpt_part->name[i]) + dprintf("%c", gpt_part->name[i]); + } + dprintf("'"); + guid_to_str(guid_text, &gpt_part->type); + dprintf("GPT part. type GUID __ : {%s}\n", guid_text); + guid_to_str(guid_text, &gpt_part->uid); + dprintf("GPT part. unique ID __ : {%s}\n", guid_text); +#endif + (void)gpt_part; +} + +/* A GPT header */ +struct gpt { + char sig[8]; + union { + struct { + uint16_t minor; + uint16_t major; + } fields __attribute__ ((packed)); + uint32_t uint32; + char raw[4]; + } rev __attribute__ ((packed)); + uint32_t hdr_size; + uint32_t chksum; + char reserved1[4]; + uint64_t lba_cur; + uint64_t lba_alt; + uint64_t lba_first_usable; + uint64_t lba_last_usable; + struct guid disk_guid; + uint64_t lba_table; + uint32_t part_count; + uint32_t part_size; + uint32_t table_chksum; + char reserved2[1]; +} __attribute__ ((packed)); +static const char gpt_sig_magic[] = "EFI PART"; + +#if DEBUG +static void gpt_dump(const struct gpt *gpt) +{ + char guid_text[37]; + + printf("GPT sig ______________ : '%8.8s'\n" + "GPT major revision ___ : 0x%.4x\n" + "GPT minor revision ___ : 0x%.4x\n" + "GPT header size ______ : 0x%.8x\n" + "GPT header checksum __ : 0x%.8x\n" + "GPT reserved _________ : '%4.4s'\n" + "GPT LBA current ______ : 0x%.16llx\n" + "GPT LBA alternative __ : 0x%.16llx\n" + "GPT LBA first usable _ : 0x%.16llx\n" + "GPT LBA last usable __ : 0x%.16llx\n" + "GPT LBA part. table __ : 0x%.16llx\n" + "GPT partition count __ : 0x%.8x\n" + "GPT partition size ___ : 0x%.8x\n" + "GPT part. table chksum : 0x%.8x\n", + gpt->sig, + gpt->rev.fields.major, + gpt->rev.fields.minor, + gpt->hdr_size, + gpt->chksum, + gpt->reserved1, + gpt->lba_cur, + gpt->lba_alt, + gpt->lba_first_usable, + gpt->lba_last_usable, + gpt->lba_table, gpt->part_count, gpt->part_size, gpt->table_chksum); + guid_to_str(guid_text, &gpt->disk_guid); + printf("GPT disk GUID ________ : {%s}\n", guid_text); +} +#endif + +static struct disk_part_iter *next_gpt_part(struct disk_part_iter *part) +{ + const struct gpt_part *gpt_part = NULL; + + while (++part->private.gpt.index < part->private.gpt.parts) { + gpt_part = + (const struct gpt_part *)(part->block + + (part->private.gpt.index * + part->private.gpt.size)); + if (!gpt_part->lba_first) + continue; + break; + } + /* Were we the last partition? */ + if (part->private.gpt.index == part->private.gpt.parts) { + goto err_last; + } + part->lba_data = gpt_part->lba_first; + part->private.gpt.part_guid = &gpt_part->uid; + part->private.gpt.part_label = gpt_part->name; + /* Update our index */ + part->index++; + gpt_part_dump(gpt_part); + + /* In a GPT scheme, we re-use the iterator */ + return part; + +err_last: + free(part->block); + free(part); + + return NULL; +} + +static struct disk_part_iter *get_first_partition(struct disk_part_iter *part) +{ + const struct gpt *gpt_candidate; + + /* + * Ignore any passed partition iterator. The caller should + * have passed NULL. Allocate a new partition iterator + */ + part = malloc(sizeof(*part)); + if (!part) { + error("Count not allocate partition iterator!\n"); + goto err_alloc_iter; + } + /* Read MBR */ + part->block = read_sectors(0, 2); + if (!part->block) { + error("Could not read two sectors!\n"); + goto err_read_mbr; + } + /* Check for an MBR */ + if (((struct mbr *)part->block)->sig != mbr_sig_magic) { + error("No MBR magic!\n"); + goto err_mbr; + } + /* Establish a pseudo-partition for the MBR (index 0) */ + part->index = 0; + part->record = NULL; + part->private.mbr_index = -1; + part->next = next_mbr_part; + /* Check for a GPT disk */ + gpt_candidate = (const struct gpt *)(part->block + SECTOR); + if (!memcmp(gpt_candidate->sig, gpt_sig_magic, sizeof(gpt_sig_magic))) { + /* LBA for partition table */ + uint64_t lba_table; + + /* It looks like one */ + /* TODO: Check checksum. Possibly try alternative GPT */ +#if DEBUG + puts("Looks like a GPT disk."); + gpt_dump(gpt_candidate); +#endif + /* TODO: Check table checksum (maybe) */ + /* Note relevant GPT details */ + part->next = next_gpt_part; + part->private.gpt.index = -1; + part->private.gpt.parts = gpt_candidate->part_count; + part->private.gpt.size = gpt_candidate->part_size; + lba_table = gpt_candidate->lba_table; + gpt_candidate = NULL; + /* Load the partition table */ + free(part->block); + part->block = + read_sectors(lba_table, + ((part->private.gpt.size * part->private.gpt.parts) + + SECTOR - 1) / SECTOR); + if (!part->block) { + error("Could not read GPT partition list!\n"); + goto err_gpt_table; + } + } + /* Return the pseudo-partition's next partition, which is real */ + return part->next(part); + +err_gpt_table: + +err_mbr: + + free(part->block); + part->block = NULL; +err_read_mbr: + + free(part); +err_alloc_iter: + + return NULL; +} + +/* + * Search for a specific drive/partition, based on the GPT GUID. + * We return the disk drive number if found, as well as populating the + * boot_part pointer with the matching partition, if applicable. + * If no matching partition is found or the GUID is a disk GUID, + * boot_part will be populated with NULL. If not matching disk is + * found, we return -1. + */ +static int find_by_guid(const struct guid *gpt_guid, + struct disk_part_iter **boot_part) +{ + int drive; + bool is_me; + struct gpt *header; + + for (drive = 0x80; drive <= 0xff; drive++) { + if (get_disk_params(drive)) + continue; /* Drive doesn't exist */ + if (!(header = read_sectors(1, 1))) + continue; /* Cannot read sector */ + if (memcmp(&header->sig, gpt_sig_magic, sizeof(gpt_sig_magic))) { + /* Not a GPT disk */ + free(header); + continue; + } +#if DEBUG + gpt_dump(header); +#endif + is_me = !memcmp(&header->disk_guid, &gpt_guid, sizeof(*gpt_guid)); + free(header); + if (!is_me) { + /* Check for a matching partition */ + boot_part[0] = get_first_partition(NULL); + while (boot_part[0]) { + is_me = + !memcmp(boot_part[0]->private.gpt.part_guid, gpt_guid, + sizeof(*gpt_guid)); + if (is_me) + break; + boot_part[0] = boot_part[0]->next(boot_part[0]); + } + } else + boot_part[0] = NULL; + if (is_me) + return drive; + } + return -1; +} + +/* + * Search for a specific partition, based on the GPT label. + * We return the disk drive number if found, as well as populating the + * boot_part pointer with the matching partition, if applicable. + * If no matching partition is found, boot_part will be populated with + * NULL and we return -1. + */ +static int find_by_label(const char *label, struct disk_part_iter **boot_part) +{ + int drive; + bool is_me; + + for (drive = 0x80; drive <= 0xff; drive++) { + if (get_disk_params(drive)) + continue; /* Drive doesn't exist */ + /* Check for a GPT disk */ + boot_part[0] = get_first_partition(NULL); + if (!(boot_part[0]->next == next_gpt_part)) { + /* Not a GPT disk */ + while (boot_part[0]) { + /* Run through until the end */ + boot_part[0] = boot_part[0]->next(boot_part[0]); + } + continue; + } + /* Check for a matching partition */ + while (boot_part[0]) { + char gpt_label[sizeof(((struct gpt_part *) NULL)->name)]; + const char *gpt_label_scanner = + boot_part[0]->private.gpt.part_label; + int j = 0; + + /* Re-write the GPT partition label as ASCII */ + while (gpt_label_scanner < + boot_part[0]->private.gpt.part_label + sizeof(gpt_label)) { + if ((gpt_label[j] = *gpt_label_scanner)) + j++; + gpt_label_scanner++; + } + if ((is_me = !strcmp(label, gpt_label))) + break; + boot_part[0] = boot_part[0]->next(boot_part[0]); + } + if (is_me) + return drive; + } + + return -1; +} + +static void do_boot(struct data_area *data, int ndata, + struct syslinux_rm_regs *regs) +{ + uint16_t *const bios_fbm = (uint16_t *) 0x413; + addr_t dosmem = *bios_fbm << 10; /* Technically a low bound */ + struct syslinux_memmap *mmap; + struct syslinux_movelist *mlist = NULL; + addr_t endimage; + uint8_t driveno = regs->edx.b[0]; + uint8_t swapdrive = driveno & 0x80; + int i; + + mmap = syslinux_memory_map(); + + if (!mmap) { + error("Cannot read system memory map\n"); + return; + } + + endimage = 0; + for (i = 0; i < ndata; i++) { + if (data[i].base + data[i].size > endimage) + endimage = data[i].base + data[i].size; + } + if (endimage > dosmem) + goto too_big; + + for (i = 0; i < ndata; i++) { + if (syslinux_add_movelist(&mlist, data[i].base, + (addr_t) data[i].data, data[i].size)) + goto enomem; + } + + if (opt.swap && driveno != swapdrive) { + static const uint8_t swapstub_master[] = { + /* The actual swap code */ + 0x53, /* 00: push bx */ + 0x0f, 0xb6, 0xda, /* 01: movzx bx,dl */ + 0x2e, 0x8a, 0x57, 0x60, /* 04: mov dl,[cs:bx+0x60] */ + 0x5b, /* 08: pop bx */ + 0xea, 0, 0, 0, 0, /* 09: jmp far 0:0 */ + 0x90, 0x90, /* 0E: nop; nop */ + /* Code to install this in the right location */ + /* Entry with DS = CS; ES = SI = 0; CX = 256 */ + 0x26, 0x66, 0x8b, 0x7c, 0x4c, /* 10: mov edi,[es:si+4*0x13] */ + 0x66, 0x89, 0x3e, 0x0a, 0x00, /* 15: mov [0x0A],edi */ + 0x26, 0x8b, 0x3e, 0x13, 0x04, /* 1A: mov di,[es:0x413] */ + 0x4f, /* 1F: dec di */ + 0x26, 0x89, 0x3e, 0x13, 0x04, /* 20: mov [es:0x413],di */ + 0x66, 0xc1, 0xe7, 0x16, /* 25: shl edi,16+6 */ + 0x26, 0x66, 0x89, 0x7c, 0x4c, /* 29: mov [es:si+4*0x13],edi */ + 0x66, 0xc1, 0xef, 0x10, /* 2E: shr edi,16 */ + 0x8e, 0xc7, /* 32: mov es,di */ + 0x31, 0xff, /* 34: xor di,di */ + 0xf3, 0x66, 0xa5, /* 36: rep movsd */ + 0xbe, 0, 0, /* 39: mov si,0 */ + 0xbf, 0, 0, /* 3C: mov di,0 */ + 0x8e, 0xde, /* 3F: mov ds,si */ + 0x8e, 0xc7, /* 41: mov es,di */ + 0x66, 0xb9, 0, 0, 0, 0, /* 43: mov ecx,0 */ + 0x66, 0xbe, 0, 0, 0, 0, /* 49: mov esi,0 */ + 0x66, 0xbf, 0, 0, 0, 0, /* 4F: mov edi,0 */ + 0xea, 0, 0, 0, 0, /* 55: jmp 0:0 */ + /* pad out to segment boundary */ + 0x90, 0x90, /* 5A: ... */ + 0x90, 0x90, 0x90, 0x90, /* 5C: ... */ + }; + static uint8_t swapstub[1024]; + uint8_t *p; + + /* Note: we can't rely on either INT 13h nor the dosmem + vector to be correct at this stage, so we have to use an + installer stub to put things in the right place. + Round the installer location to a 1K boundary so the only + possible overlap is the identity mapping. */ + endimage = (endimage + 1023) & ~1023; + + /* Create swap stub */ + memcpy(swapstub, swapstub_master, sizeof swapstub_master); + *(uint16_t *) & swapstub[0x3a] = regs->ds; + *(uint16_t *) & swapstub[0x3d] = regs->es; + *(uint32_t *) & swapstub[0x45] = regs->ecx.l; + *(uint32_t *) & swapstub[0x4b] = regs->esi.l; + *(uint32_t *) & swapstub[0x51] = regs->edi.l; + *(uint16_t *) & swapstub[0x56] = regs->ip; + *(uint16_t *) & swapstub[0x58] = regs->cs; + p = &swapstub[sizeof swapstub_master]; + + /* Mapping table; start out with identity mapping everything */ + for (i = 0; i < 256; i++) + p[i] = i; + + /* And the actual swap */ + p[driveno] = swapdrive; + p[swapdrive] = driveno; + + /* Adjust registers */ + regs->ds = regs->cs = endimage >> 4; + regs->es = regs->esi.l = 0; + regs->ecx.l = sizeof swapstub >> 2; + regs->ip = 0x10; /* Installer offset */ + regs->ebx.b[0] = regs->edx.b[0] = swapdrive; + + if (syslinux_add_movelist(&mlist, endimage, (addr_t) swapstub, + sizeof swapstub)) + goto enomem; + + endimage += sizeof swapstub; + } + + /* Tell the shuffler not to muck with this area... */ + syslinux_add_memmap(&mmap, endimage, 0xa0000 - endimage, SMT_RESERVED); + + /* Force text mode */ + syslinux_force_text_mode(); + + fputs("Booting...\n", stdout); + syslinux_shuffle_boot_rm(mlist, mmap, opt.keeppxe, regs); + error("Chainboot failed!\n"); + return; + +too_big: + error("Loader file too large\n"); + return; + +enomem: + error("Out of memory\n"); + return; +} + +static int hide_unhide(struct mbr *mbr, int part) +{ + int i; + struct part_entry *pt; + const uint16_t mask = + (1 << 0x01) | (1 << 0x04) | (1 << 0x06) | (1 << 0x07) | (1 << 0x0b) | (1 + << + 0x0c) + | (1 << 0x0e); + uint8_t t; + bool write_back = false; + + for (i = 1; i <= 4; i++) { + pt = mbr->table + i - 1; + t = pt->ostype; + if ((t <= 0x1f) && ((mask >> (t & ~0x10)) & 1)) { + /* It's a hideable partition type */ + if (i == part) + t &= ~0x10; /* unhide */ + else + t |= 0x10; /* hide */ + } + if (t != pt->ostype) { + write_back = true; + pt->ostype = t; + } + } + + if (write_back) + return write_verify_sector(0, mbr); + + return 0; /* ok */ +} + +static uint32_t get_file_lba(const char *filename) +{ + com32sys_t inregs; + uint32_t lba; + + /* Start with clean registers */ + memset(&inregs, 0, sizeof(com32sys_t)); + + /* Put the filename in the bounce buffer */ + strlcpy(__com32.cs_bounce, filename, __com32.cs_bounce_size); + + /* Call comapi_open() which returns a structure pointer in SI + * to a structure whose first member happens to be the LBA. + */ + inregs.eax.w[0] = 0x0006; + inregs.esi.w[0] = OFFS(__com32.cs_bounce); + inregs.es = SEG(__com32.cs_bounce); + __com32.cs_intcall(0x22, &inregs, &inregs); + + if ((inregs.eflags.l & EFLAGS_CF) || inregs.esi.w[0] == 0) { + return 0; /* Filename not found */ + } + + /* Since the first member is the LBA, we simply cast */ + lba = *((uint32_t *) MK_PTR(inregs.ds, inregs.esi.w[0])); + + /* Clean the registers for the next call */ + memset(&inregs, 0, sizeof(com32sys_t)); + + /* Put the filename in the bounce buffer */ + strlcpy(__com32.cs_bounce, filename, __com32.cs_bounce_size); + + /* Call comapi_close() to free the structure */ + inregs.eax.w[0] = 0x0008; + inregs.esi.w[0] = OFFS(__com32.cs_bounce); + inregs.es = SEG(__com32.cs_bounce); + __com32.cs_intcall(0x22, &inregs, &inregs); + + return lba; +} + +static void usage(void) +{ + static const char usage[] = "\ +Usage: chain.c32 [options]\n\ + chain.c32 hd<disk#> [<partition>] [options]\n\ + chain.c32 fd<disk#> [options]\n\ + chain.c32 mbr:<id> [<partition>] [options]\n\ + chain.c32 guid:<guid> [<partition>] [options]\n\ + chain.c32 label:<label> [<partition>] [options]\n\ + chain.c32 boot [<partition>] [options]\n\ + chain.c32 fs [options]\n\ +Options: file=<loader> Load and execute file, instead of boot sector\n\ + isolinux=<loader> Load another version of ISOLINUX\n\ + ntldr=<loader> Load Windows NTLDR, SETUPLDR.BIN or BOOTMGR\n\ + cmldr=<loader> Load Recovery Console of Windows NT/2K/XP/2003\n\ + freedos=<loader> Load FreeDOS KERNEL.SYS\n\ + msdos=<loader> Load MS-DOS IO.SYS\n\ + pcdos=<loader> Load PC-DOS IBMBIO.COM\n\ + grub=<loader> Load GRUB Legacy stage2\n\ + grubcfg=<filename> Set alternative config filename for GRUB Legacy\n\ + grldr=<loader> Load GRUB4DOS grldr\n\ + seg=<segment> Jump to <seg>:0000, instead of 0000:7C00\n\ + swap Swap drive numbers, if bootdisk is not fd0/hd0\n\ + hide Hide primary partitions, except selected partition\n\ + sethidden Set the FAT/NTFS hidden sectors field\n\ + keeppxe Keep the PXE and UNDI stacks in memory (PXELINUX)\n\ +See syslinux/com32/modules/chain.c for more information\n"; + error(usage); +} + +int main(int argc, char *argv[]) +{ + struct mbr *mbr = NULL; + char *p; + struct disk_part_iter *cur_part = NULL; + struct syslinux_rm_regs regs; + char *drivename, *partition; + int hd, drive, whichpart = 0; /* MBR by default */ + int i; + uint64_t fs_lba = 0; /* Syslinux partition */ + uint32_t file_lba = 0; + struct guid gpt_guid; + unsigned char *isolinux_bin; + uint32_t *checksum, *chkhead, *chktail; + struct data_area data[3]; + int ndata = 0; + addr_t load_base; + static const char cmldr_signature[8] = "cmdcons"; + + openconsole(&dev_null_r, &dev_stdcon_w); + + drivename = "boot"; + partition = NULL; + + /* Prepare the register set */ + memset(®s, 0, sizeof regs); + + for (i = 1; i < argc; i++) { + if (!strncmp(argv[i], "file=", 5)) { + opt.loadfile = argv[i] + 5; + } else if (!strncmp(argv[i], "seg=", 4)) { + uint32_t segval = strtoul(argv[i] + 4, NULL, 0); + if (segval < 0x50 || segval > 0x9f000) { + error("Invalid segment\n"); + goto bail; + } + opt.seg = segval; + } else if (!strncmp(argv[i], "isolinux=", 9)) { + opt.loadfile = argv[i] + 9; + opt.isolinux = true; + } else if (!strncmp(argv[i], "ntldr=", 6)) { + opt.seg = 0x2000; /* NTLDR wants this address */ + opt.loadfile = argv[i] + 6; + opt.sethidden = true; + } else if (!strncmp(argv[i], "cmldr=", 6)) { + opt.seg = 0x2000; /* CMLDR wants this address */ + opt.loadfile = argv[i] + 6; + opt.cmldr = true; + opt.sethidden = true; + } else if (!strncmp(argv[i], "freedos=", 8)) { + opt.seg = 0x60; /* FREEDOS wants this address */ + opt.loadfile = argv[i] + 8; + opt.sethidden = true; + } else if (!strncmp(argv[i], "msdos=", 6) || + !strncmp(argv[i], "pcdos=", 6)) { + opt.seg = 0x70; /* MS-DOS 2.0+ wants this address */ + opt.loadfile = argv[i] + 6; + opt.sethidden = true; + } else if (!strncmp(argv[i], "grub=", 5)) { + opt.seg = 0x800; /* stage2 wants this address */ + opt.loadfile = argv[i] + 5; + opt.grub = true; + } else if (!strncmp(argv[i], "grubcfg=", 8)) { + opt.grubcfg = argv[i] + 8; + } else if (!strncmp(argv[i], "grldr=", 6)) { + opt.loadfile = argv[i] + 6; + opt.grldr = true; + } else if (!strcmp(argv[i], "swap")) { + opt.swap = true; + } else if (!strcmp(argv[i], "noswap")) { + opt.swap = false; + } else if (!strcmp(argv[i], "hide")) { + opt.hide = true; + } else if (!strcmp(argv[i], "nohide")) { + opt.hide = false; + } else if (!strcmp(argv[i], "keeppxe")) { + opt.keeppxe = 3; + } else if (!strcmp(argv[i], "sethidden")) { + opt.sethidden = true; + } else if (!strcmp(argv[i], "nosethidden")) { + opt.sethidden = false; + } else if (((argv[i][0] == 'h' || argv[i][0] == 'f') + && argv[i][1] == 'd') + || !strncmp(argv[i], "mbr:", 4) + || !strncmp(argv[i], "mbr=", 4) + || !strncmp(argv[i], "guid:", 5) + || !strncmp(argv[i], "guid=", 5) + || !strncmp(argv[i], "label:", 6) + || !strncmp(argv[i], "label=", 6) + || !strcmp(argv[i], "boot") + || !strncmp(argv[i], "boot,", 5) + || !strcmp(argv[i], "fs")) { + drivename = argv[i]; + p = strchr(drivename, ','); + if (p) { + *p = '\0'; + partition = p + 1; + } else if (argv[i + 1] && argv[i + 1][0] >= '0' + && argv[i + 1][0] <= '9') { + partition = argv[++i]; + } + } else { + usage(); + goto bail; + } + } + + if (opt.grubcfg && !opt.grub) { + error("grubcfg=<filename> must be used together with grub=<loader>.\n"); + goto bail; + } + + if (opt.seg) { + regs.es = regs.cs = regs.ss = regs.ds = regs.fs = regs.gs = opt.seg; + } else { + regs.ip = regs.esp.l = 0x7c00; + } + + hd = 0; + if (!strncmp(drivename, "mbr", 3)) { + drive = find_disk(strtoul(drivename + 4, NULL, 0)); + if (drive == -1) { + error("Unable to find requested MBR signature\n"); + goto bail; + } + } else if (!strncmp(drivename, "guid", 4)) { + if (str_to_guid(drivename + 5, &gpt_guid)) + goto bail; + drive = find_by_guid(&gpt_guid, &cur_part); + if (drive == -1) { + error("Unable to find requested GPT disk/partition\n"); + goto bail; + } + } else if (!strncmp(drivename, "label", 5)) { + if (!drivename[6]) { + error("No label specified.\n"); + goto bail; + } + drive = find_by_label(drivename + 6, &cur_part); + if (drive == -1) { + error("Unable to find requested partition by label\n"); + goto bail; + } + } else if ((drivename[0] == 'h' || drivename[0] == 'f') && + drivename[1] == 'd') { + hd = drivename[0] == 'h'; + drivename += 2; + drive = (hd ? 0x80 : 0) | strtoul(drivename, NULL, 0); + } else if (!strcmp(drivename, "boot") || !strcmp(drivename, "fs")) { + const union syslinux_derivative_info *sdi; + + sdi = syslinux_derivative_info(); + if (sdi->c.filesystem == SYSLINUX_FS_PXELINUX) + drive = 0x80; /* Boot drive not available */ + else + drive = sdi->disk.drive_number; + if (!strcmp(drivename, "fs") + && (sdi->c.filesystem == SYSLINUX_FS_SYSLINUX + || sdi->c.filesystem == SYSLINUX_FS_EXTLINUX + || sdi->c.filesystem == SYSLINUX_FS_ISOLINUX)) + /* We should lookup the Syslinux partition number and use it */ + fs_lba = *sdi->disk.partoffset; + } else { + error("Unparsable drive specification\n"); + goto bail; + } + + /* DOS kernels want the drive number in BL instead of DL. Indulge them. */ + regs.ebx.b[0] = regs.edx.b[0] = drive; + + /* Get the disk geometry and disk access setup */ + if (get_disk_params(drive)) { + error("Cannot get disk parameters\n"); + goto bail; + } + + /* Get MBR */ + if (!(mbr = read_sectors(0, 1))) { + error("Cannot read Master Boot Record or sector 0\n"); + goto bail; + } + + if (partition) + whichpart = strtoul(partition, NULL, 0); + /* "guid:" or "label:" might have specified a partition */ + if (cur_part) + whichpart = cur_part->index; + + /* Boot the MBR by default */ + if (!cur_part && (whichpart || fs_lba)) { + /* Boot a partition, possibly the Syslinux partition itself */ + cur_part = get_first_partition(NULL); + while (cur_part) { + if ((cur_part->index == whichpart) + || (cur_part->lba_data == fs_lba)) + /* Found the partition to boot */ + break; + cur_part = cur_part->next(cur_part); + } + if (!cur_part) { + error("Requested partition not found!\n"); + goto bail; + } + whichpart = cur_part->index; + } + + if (!(drive & 0x80) && whichpart) { + error("Warning: Partitions of floppy devices may not work\n"); + } + + /* + * GRLDR of GRUB4DOS wants the partition number in DH: + * -1: whole drive (default) + * 0-3: primary partitions + * 4-*: logical partitions + */ + if (opt.grldr) + regs.edx.b[1] = whichpart - 1; + + if (opt.hide) { + if (whichpart < 1 || whichpart > 4) + error("WARNING: hide specified without a non-primary partition\n"); + if (hide_unhide(mbr, whichpart)) + error("WARNING: failed to write MBR for 'hide'\n"); + } + + /* Do the actual chainloading */ + load_base = opt.seg ? (opt.seg << 4) : 0x7c00; + + if (opt.loadfile) { + fputs("Loading the boot file...\n", stdout); + if (loadfile(opt.loadfile, &data[ndata].data, &data[ndata].size)) { + error("Failed to load the boot file\n"); + goto bail; + } + data[ndata].base = load_base; + load_base = 0x7c00; /* If we also load a boot sector */ + + /* Create boot info table: needed when you want to chainload + another version of ISOLINUX (or another bootlaoder that needs + the -boot-info-table switch of mkisofs) + (will only work when run from ISOLINUX) */ + if (opt.isolinux) { + const union syslinux_derivative_info *sdi; + sdi = syslinux_derivative_info(); + + if (sdi->c.filesystem == SYSLINUX_FS_ISOLINUX) { + /* Boot info table info (integers in little endian format) + + Offset Name Size Meaning + 8 bi_pvd 4 bytes LBA of primary volume descriptor + 12 bi_file 4 bytes LBA of boot file + 16 bi_length 4 bytes Boot file length in bytes + 20 bi_csum 4 bytes 32-bit checksum + 24 bi_reserved 40 bytes Reserved + + The 32-bit checksum is the sum of all the 32-bit words in the + boot file starting at byte offset 64. All linear block + addresses (LBAs) are given in CD sectors (normally 2048 bytes). + + LBA of primary volume descriptor should already be set to 16. + */ + + isolinux_bin = (unsigned char *)data[ndata].data; + + /* Get LBA address of bootfile */ + file_lba = get_file_lba(opt.loadfile); + + if (file_lba == 0) { + error("Failed to find LBA offset of the boot file\n"); + goto bail; + } + /* Set it */ + *((uint32_t *) & isolinux_bin[12]) = file_lba; + + /* Set boot file length */ + *((uint32_t *) & isolinux_bin[16]) = data[ndata].size; + + /* Calculate checksum */ + checksum = (uint32_t *) & isolinux_bin[20]; + chkhead = (uint32_t *) & isolinux_bin[64]; + chktail = (uint32_t *) & isolinux_bin[data[ndata].size & ~3]; + *checksum = 0; + while (chkhead < chktail) + *checksum += *chkhead++; + + /* + * Deal with possible fractional dword at the end; + * this *should* never happen... + */ + if (data[ndata].size & 3) { + uint32_t xword = 0; + memcpy(&xword, chkhead, data[ndata].size & 3); + *checksum += xword; + } + } else { + error + ("The isolinux= option is only valid when run from ISOLINUX\n"); + goto bail; + } + } + + if (opt.grub) { + /* Layout of stage2 file (from byte 0x0 to 0x270) */ + struct grub_stage2_patch_area { + /* 0x0 to 0x205 */ + char unknown[0x206]; + /* 0x206: compatibility version number major */ + uint8_t compat_version_major; + /* 0x207: compatibility version number minor */ + uint8_t compat_version_minor; + + /* 0x208: install_partition variable */ + struct { + /* 0x208: sub-partition in sub-partition part2 */ + uint8_t part3; + /* 0x209: sub-partition in top-level partition */ + uint8_t part2; + /* 0x20a: top-level partiton number */ + uint8_t part1; + /* 0x20b: BIOS drive number (must be 0) */ + uint8_t drive; + } __attribute__ ((packed)) install_partition; + + /* 0x20c: deprecated (historical reason only) */ + uint32_t saved_entryno; + /* 0x210: stage2_ID: will always be STAGE2_ID_STAGE2 = 0 in stage2 */ + uint8_t stage2_id; + /* 0x211: force LBA */ + uint8_t force_lba; + /* 0x212: version string (will probably be 0.97) */ + char version_string[5]; + /* 0x217: config filename */ + char config_file[89]; + /* 0x270: start of code (after jump from 0x200) */ + char codestart[1]; + } __attribute__ ((packed)) *stage2; + + if (data[ndata].size < sizeof(struct grub_stage2_patch_area)) { + error + ("The file specified by grub=<loader> is to small to be stage2 of GRUB Legacy.\n"); + goto bail; + } + + stage2 = data[ndata].data; + + /* + * Check the compatibility version number to see if we loaded a real + * stage2 file or a stage2 file that we support. + */ + if (stage2->compat_version_major != 3 + || stage2->compat_version_minor != 2) { + error + ("The file specified by grub=<loader> is not a supported stage2 GRUB Legacy binary\n"); + goto bail; + } + + /* jump 0x200 bytes into the loadfile */ + regs.ip = 0x200; + + /* + * GRUB Legacy wants the partition number in the install_partition + * variable, located at offset 0x208 of stage2. + * When GRUB Legacy is loaded, it is located at memory address 0x8208. + * + * It looks very similar to the "boot information format" of the + * Multiboot specification: + * http://www.gnu.org/software/grub/manual/multiboot/multiboot.html#Boot-information-format + * + * 0x208 = part3: sub-partition in sub-partition part2 + * 0x209 = part2: sub-partition in top-level partition + * 0x20a = part1: top-level partition number + * 0x20b = drive: BIOS drive number (must be 0) + * + * GRUB Legacy doesn't store the BIOS drive number at 0x20b, but at + * another location. + * + * Partition numbers always start from zero. + * Unused partition bytes must be set to 0xFF. + * + * We only care about top-level partition, so we only need to change + * "part1" to the appropriate value: + * -1: whole drive (default) (-1 = 0xFF) + * 0-3: primary partitions + * 4-*: logical partitions + */ + stage2->install_partition.part1 = whichpart - 1; + + /* + * Grub Legacy reserves 89 bytes (from 0x8217 to 0x826f) for the + * config filename. The filename passed via grubcfg= will overwrite + * the default config filename "/boot/grub/menu.lst". + */ + if (opt.grubcfg) { + if (strlen(opt.grubcfg) > sizeof(stage2->config_file) - 1) { + error + ("The config filename length can't exceed 88 characters.\n"); + goto bail; + } + + strcpy((char *)stage2->config_file, opt.grubcfg); + } + } + + ndata++; + } + + if (!opt.loadfile || data[0].base >= 0x7c00 + SECTOR) { + /* Actually read the boot sector */ + if (!cur_part) { + data[ndata].data = mbr; + } else if (!(data[ndata].data = read_sectors(cur_part->lba_data, 1))) { + error("Cannot read boot sector\n"); + goto bail; + } + data[ndata].size = SECTOR; + data[ndata].base = load_base; + + if (!opt.loadfile) { + const struct mbr *br = + (const struct mbr *)((char *)data[ndata].data + + data[ndata].size - sizeof(struct mbr)); + if (br->sig != mbr_sig_magic) { + error + ("Boot sector signature not found (unbootable disk/partition?)\n"); + goto bail; + } + } + /* + * To boot the Recovery Console of Windows NT/2K/XP we need to write + * the string "cmdcons\0" to memory location 0000:7C03. + * Memory location 0000:7C00 contains the bootsector of the partition. + */ + if (cur_part && opt.cmldr) { + memcpy((char *)data[ndata].data + 3, cmldr_signature, + sizeof cmldr_signature); + } + + /* + * Modify the hidden sectors (partition offset) copy in memory; + * this modifies the field used by FAT and NTFS filesystems, and + * possibly other boot loaders which use the same format. + */ + if (cur_part && opt.sethidden) { + *(uint32_t *) ((char *)data[ndata].data + 28) = cur_part->lba_data; + } + + ndata++; + } + + if (cur_part) { + if (cur_part->next == next_gpt_part) { + /* Do GPT hand-over, if applicable (as per syslinux/doc/gpt.txt) */ + struct part_entry *record; + /* Look at the GPT partition */ + const struct gpt_part *gp = (const struct gpt_part *) + (cur_part->block + + (cur_part->private.gpt.size * cur_part->private.gpt.index)); + /* Note the partition length */ + uint64_t lba_count = gp->lba_last - gp->lba_first + 1; + /* The length of the hand-over */ + int synth_size = + sizeof(struct part_entry) + sizeof(uint32_t) + + cur_part->private.gpt.size; + /* Will point to the partition record length in the hand-over */ + uint32_t *plen; + + /* Allocate the hand-over record */ + record = malloc(synth_size); + if (!record) { + error("Could not build GPT hand-over record!\n"); + goto bail; + } + /* Synthesize the record */ + memset(record, 0, synth_size); + record->active_flag = 0x80; + record->ostype = 0xED; + /* All bits set by default */ + record->start_lba = ~(uint32_t) 0; + record->length = ~(uint32_t) 0; + /* If these fit the precision, pass them on */ + if (cur_part->lba_data < record->start_lba) + record->start_lba = cur_part->lba_data; + if (lba_count < record->length) + record->length = lba_count; + /* Next comes the GPT partition record length */ + plen = (uint32_t *) (record + 1); + plen[0] = cur_part->private.gpt.size; + /* Next comes the GPT partition record copy */ + memcpy(plen + 1, gp, plen[0]); + cur_part->record = record; + + regs.eax.l = 0x54504721; /* '!GPT' */ + data[ndata].base = 0x7be; + data[ndata].size = synth_size; + data[ndata].data = (void *)record; + ndata++; + regs.esi.w[0] = 0x7be; + + dprintf("GPT handover:\n"); + mbr_part_dump(record); + gpt_part_dump((struct gpt_part *)(plen + 1)); + } else if (cur_part->record) { + /* MBR handover protocol */ + static struct part_entry handover_record; + + handover_record = *cur_part->record; + handover_record.start_lba = cur_part->lba_data; + + data[ndata].base = 0x7be; + data[ndata].size = sizeof handover_record; + data[ndata].data = &handover_record; + ndata++; + regs.esi.w[0] = 0x7be; + + dprintf("MBR handover:\n"); + mbr_part_dump(&handover_record); + } + } + + do_boot(data, ndata, ®s); + +bail: + if (cur_part) { + free(cur_part->block); + free((void *)cur_part->record); + } + free(cur_part); + free(mbr); + return 255; +} diff --git a/contrib/syslinux-4.02/com32/modules/cmd.c b/contrib/syslinux-4.02/com32/modules/cmd.c new file mode 100644 index 0000000..5d3f891 --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/cmd.c @@ -0,0 +1,26 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2008 Michael Brown - All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * cmd.c + * + * Execute arbitrary commands + */ + +#include <com32.h> +#include <syslinux/boot.h> + +int main(void) +{ + syslinux_run_command(__com32.cs_cmdline); + return -1; +} diff --git a/contrib/syslinux-4.02/com32/modules/config.c b/contrib/syslinux-4.02/com32/modules/config.c new file mode 100644 index 0000000..334a635 --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/config.c @@ -0,0 +1,39 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 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., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * config.c + * + * Loads a new configuration file + * + * Usage: config filename + */ + +#include <stdio.h> +#include <console.h> +#include <syslinux/boot.h> + +int main(int argc, char *argv[]) +{ + openconsole(&dev_null_r, &dev_stdcon_w); + + if (argc < 2 || argc > 3) { + fprintf(stderr, "Usage: config <filename> [<directory>]\n"); + return 1; + } + + syslinux_run_kernel_image(argv[1], argv[2] ? argv[2] : "", + 0, IMAGE_TYPE_CONFIG); + + fprintf(stderr, "config: %s: failed to load (missing file?)\n", argv[1]); + return 1; +} diff --git a/contrib/syslinux-4.02/com32/modules/cpuid.c b/contrib/syslinux-4.02/com32/modules/cpuid.c new file mode 100644 index 0000000..78cb3f5 --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/cpuid.c @@ -0,0 +1,60 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2010 Intel Corporation; author: H. Peter Anvin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/cpu.h> +#include <console.h> +#include <com32.h> + +static void dump_reg(const char *name, uint32_t val) +{ + int i; + + printf("%-3s : %10u 0x%08x ", name, val, val); + + for (i = 3; i >= 0; i--) { + uint8_t c = val >> (i*8); + putchar((c >= ' ' && c <= '~') ? c : '.'); + } + putchar('\n'); +} + +int main(int argc, char *argv[]) +{ + uint32_t leaf, counter; + uint32_t eax, ebx, ecx, edx; + + openconsole(&dev_null_r, &dev_stdcon_w); + + if (argc < 2 || argc > 4) { + printf("Usage: %s leaf [counter]\n", argv[0]); + exit(1); + } + + leaf = strtoul(argv[1], NULL, 0); + counter = (argc > 2) ? strtoul(argv[2], NULL, 0) : 0; + + if (!cpu_has_eflag(EFLAGS_ID)) { + printf("The CPUID instruction is not supported\n"); + exit(1); + } + + cpuid_count(leaf, counter, &eax, &ebx, &ecx, &edx); + + dump_reg("eax", eax); + dump_reg("ebx", ebx); + dump_reg("ecx", ecx); + dump_reg("edx", edx); + + return 0; +} diff --git a/contrib/syslinux-4.02/com32/modules/cpuidtest.c b/contrib/syslinux-4.02/com32/modules/cpuidtest.c new file mode 100644 index 0000000..b768885 --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/cpuidtest.c @@ -0,0 +1,138 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * 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. + * + * ----------------------------------------------------------------------- +*/ + +/* + * cpuidtest.c + * + * A CPUID demo program using libcom32 + */ + +#include <string.h> +#include <stdio.h> +#include <console.h> +#include "cpuid.h" + +char display_line; + +int main(void) +{ + s_cpu cpu; + openconsole(&dev_stdcon_r, &dev_stdcon_w); + + for (;;) { + detect_cpu(&cpu); + printf("Vendor = %s\n", cpu.vendor); + printf("Model = %s\n", cpu.model); + printf("Vendor ID = %d\n", cpu.vendor_id); + printf("Family = %d\n", cpu.family); + printf("Model ID = %d\n", cpu.model_id); + printf("Stepping = %d\n", cpu.stepping); + printf("Flags = "); + if (cpu.flags.fpu) + printf("fpu "); + if (cpu.flags.vme) + printf("vme "); + if (cpu.flags.de) + printf("de "); + if (cpu.flags.pse) + printf("pse "); + if (cpu.flags.tsc) + printf("tsc "); + if (cpu.flags.msr) + printf("msr "); + if (cpu.flags.pae) + printf("pae "); + if (cpu.flags.mce) + printf("mce "); + if (cpu.flags.cx8) + printf("cx8 "); + if (cpu.flags.apic) + printf("apic "); + if (cpu.flags.sep) + printf("sep "); + if (cpu.flags.mtrr) + printf("mtrr "); + if (cpu.flags.pge) + printf("pge "); + if (cpu.flags.mca) + printf("mca "); + if (cpu.flags.cmov) + printf("cmov "); + if (cpu.flags.pat) + printf("pat "); + if (cpu.flags.pse_36) + printf("pse_36 "); + if (cpu.flags.psn) + printf("psn "); + if (cpu.flags.clflsh) + printf("clflsh "); + if (cpu.flags.dts) + printf("dts "); + if (cpu.flags.acpi) + printf("acpi "); + if (cpu.flags.mmx) + printf("mmx "); + if (cpu.flags.sse) + printf("sse "); + if (cpu.flags.sse2) + printf("sse2 "); + if (cpu.flags.ss) + printf("ss "); + if (cpu.flags.htt) + printf("ht "); + if (cpu.flags.acc) + printf("acc "); + if (cpu.flags.syscall) + printf("syscall "); + if (cpu.flags.mp) + printf("mp "); + if (cpu.flags.nx) + printf("nx "); + if (cpu.flags.mmxext) + printf("mmxext "); + if (cpu.flags.lm) + printf("lm "); + if (cpu.flags.nowext) + printf("3dnowext "); + if (cpu.flags.now) + printf("3dnow! "); + if (cpu.flags.vmx) + printf("vmx "); + if (cpu.flags.svm) + printf("svm "); + printf("\n"); + printf("SMP = "); + if (cpu.flags.smp) + printf("yes\n"); + else + printf("no\n"); + break; + } + + return 0; +} diff --git a/contrib/syslinux-4.02/com32/modules/disk.c b/contrib/syslinux-4.02/com32/modules/disk.c new file mode 100644 index 0000000..ca4b598 --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/disk.c @@ -0,0 +1,62 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Pierre-Alexandre Meyer - All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +#include <stdio.h> +#include <console.h> +#include <stdlib.h> +#include <string.h> +#include <disk/geom.h> +#include <disk/util.h> +#include <disk/errno_disk.h> +#include <disk/error.h> + +int main(int argc, char *argv[]) +{ + struct driveinfo drive; + struct driveinfo *d = &drive; + + (void)argc; + (void)argv; + + openconsole(&dev_null_r, &dev_stdcon_w); + + for (int disk = 0x80; disk < 0xff; disk++) { + memset(d, 0, sizeof(struct driveinfo)); + d->disk = disk; + get_drive_parameters(d); + + /* Do not print output when drive does not exists */ + if (errno_disk == -1 || !d->cbios) + continue; + + if (errno_disk) { + get_error("reading disk"); + continue; + } + + printf("DISK 0x%X:\n", d->disk); + printf(" C/H/S: %d heads, %d cylinders\n", + d->legacy_max_head + 1, d->legacy_max_cylinder + 1); + printf(" %d sectors/track, %d drives\n", + d->legacy_sectors_per_track, d->legacy_max_drive); + printf(" EDD: ebios=%d, EDD version: %X\n", + d->ebios, d->edd_version); + printf(" %d heads, %d cylinders\n", + (int) d->edd_params.heads, (int) d->edd_params.cylinders); + printf(" %d sectors, %d bytes/sector, %d sectors/track\n", + (int) d->edd_params.sectors, (int) d->edd_params.bytes_per_sector, + (int) d->edd_params.sectors_per_track); + printf(" Host bus: %s, Interface type: %s\n\n", + d->edd_params.host_bus_type, d->edd_params.interface_type); + } + return 0; +} diff --git a/contrib/syslinux-4.02/com32/modules/dmi_utils.c b/contrib/syslinux-4.02/com32/modules/dmi_utils.c new file mode 100644 index 0000000..93cb265 --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/dmi_utils.c @@ -0,0 +1,71 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * 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 "stdio.h" +#include "dmi/dmi.h" + +void display_bios_characteristics(s_dmi * dmi) +{ + int i; + for (i = 0; i < BIOS_CHAR_NB_ELEMENTS; i++) { + if (((bool *) (&dmi->bios.characteristics))[i] == true) { + moreprintf("\t\t%s\n", bios_charac_strings[i]); + } + } + for (i = 0; i < BIOS_CHAR_X1_NB_ELEMENTS; i++) { + if (((bool *) (&dmi->bios.characteristics_x1))[i] == true) { + moreprintf("\t\t%s\n", bios_charac_x1_strings[i]); + } + } + + for (i = 0; i < BIOS_CHAR_X2_NB_ELEMENTS; i++) { + if (((bool *) (&dmi->bios.characteristics_x2))[i] == true) { + moreprintf("\t\t%s\n", bios_charac_x2_strings[i]); + } + } +} + +void display_base_board_features(s_dmi * dmi) +{ + int 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]); + } + } +} + +void display_processor_flags(s_dmi * dmi) +{ + int 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/contrib/syslinux-4.02/com32/modules/dmitest.c b/contrib/syslinux-4.02/com32/modules/dmitest.c new file mode 100644 index 0000000..b81d0ce --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/dmitest.c @@ -0,0 +1,224 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * 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. + * + * ----------------------------------------------------------------------- +*/ + +/* + * dmitest.c + * + * DMI demo program using libcom32 + */ + +#include <string.h> +#include <stdio.h> +#include <console.h> +#include "dmi/dmi.h" + +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); + moreprintf("\tVersion: %s\n", dmi->bios.version); + moreprintf("\tRelease: %s\n", dmi->bios.release_date); + moreprintf("\tBios Revision %s\n", dmi->bios.bios_revision); + moreprintf("\tFirmware Revision %s\n", dmi->bios.firmware_revision); + moreprintf("\tAddress: 0x%04X0\n", dmi->bios.address); + moreprintf("\tRuntime address: %u %s\n", dmi->bios.runtime_size, + dmi->bios.runtime_size_unit); + moreprintf("\tRom size: %u %s\n", dmi->bios.rom_size, + dmi->bios.rom_size_unit); + display_bios_characteristics(dmi); +} + +void display_system(s_dmi * dmi) +{ + moreprintf("\nSystem\n"); + moreprintf("\tManufacturer %s\n", dmi->system.manufacturer); + moreprintf("\tProduct Name %s\n", dmi->system.product_name); + moreprintf("\tVersion %s\n", dmi->system.version); + moreprintf("\tSerial %s\n", dmi->system.serial); + moreprintf("\tUUID %s\n", dmi->system.uuid); + moreprintf("\tWakeup Type %s\n", dmi->system.wakeup_type); + moreprintf("\tSKU Number %s\n", dmi->system.sku_number); + moreprintf("\tFamily %s\n", dmi->system.family); +} + +void display_base_board(s_dmi * dmi) +{ + moreprintf("Base board\n"); + moreprintf("\tManufacturer %s\n", dmi->base_board.manufacturer); + moreprintf("\tProduct Name %s\n", dmi->base_board.product_name); + moreprintf("\tVersion %s\n", dmi->base_board.version); + moreprintf("\tSerial %s\n", dmi->base_board.serial); + moreprintf("\tAsset Tag %s\n", dmi->base_board.asset_tag); + moreprintf("\tLocation %s\n", dmi->base_board.location); + moreprintf("\tType %s\n", dmi->base_board.type); + display_base_board_features(dmi); +} + +void display_chassis(s_dmi * dmi) +{ + moreprintf("\nChassis\n"); + moreprintf("\tManufacturer %s\n", dmi->chassis.manufacturer); + moreprintf("\tType %s\n", dmi->chassis.type); + moreprintf("\tLock %s\n", dmi->chassis.lock); + moreprintf("\tVersion %s\n", dmi->chassis.version); + moreprintf("\tSerial %s\n", dmi->chassis.serial); + moreprintf("\tAsset Tag %s\n", dmi->chassis.asset_tag); + moreprintf("\tBoot up state %s\n", dmi->chassis.boot_up_state); + moreprintf("\tPower supply state %s\n", dmi->chassis.power_supply_state); + moreprintf("\tThermal state %s\n", dmi->chassis.thermal_state); + moreprintf("\tSecurity Status %s\n", dmi->chassis.security_status); + moreprintf("\tOEM Information %s\n", dmi->chassis.oem_information); + moreprintf("\tHeight %u\n", dmi->chassis.height); + moreprintf("\tNB Power Cords %u\n", dmi->chassis.nb_power_cords); +} + +void display_cpu(s_dmi * dmi) +{ + moreprintf("\nCPU\n"); + moreprintf("\tSocket Designation %s\n", dmi->processor.socket_designation); + moreprintf("\tType %s\n", dmi->processor.type); + moreprintf("\tFamily %s\n", dmi->processor.family); + moreprintf("\tManufacturer %s\n", dmi->processor.manufacturer); + moreprintf("\tVersion %s\n", dmi->processor.version); + moreprintf("\tExternal Clock %u\n", dmi->processor.external_clock); + moreprintf("\tMax Speed %u\n", dmi->processor.max_speed); + moreprintf("\tCurrent Speed %u\n", dmi->processor.current_speed); + moreprintf("\tCpu Type %u\n", dmi->processor.signature.type); + moreprintf("\tCpu Family %u\n", dmi->processor.signature.family); + moreprintf("\tCpu Model %u\n", dmi->processor.signature.model); + moreprintf("\tCpu Stepping %u\n", dmi->processor.signature.stepping); + moreprintf("\tCpu Minor Stepping %u\n", + dmi->processor.signature.minor_stepping); + moreprintf("\tVoltage %d mV\n", dmi->processor.voltage_mv); + moreprintf("\tStatus %s\n", dmi->processor.status); + moreprintf("\tUpgrade %s\n", dmi->processor.upgrade); + moreprintf("\tCache L1 Handle %s\n", dmi->processor.cache1); + moreprintf("\tCache L2 Handle %s\n", dmi->processor.cache2); + moreprintf("\tCache L3 Handle %s\n", dmi->processor.cache3); + moreprintf("\tSerial %s\n", dmi->processor.serial); + moreprintf("\tPart Number %s\n", dmi->processor.part_number); + moreprintf("\tID %s\n", dmi->processor.id); + display_processor_flags(dmi); +} + +int main(void) +{ + char buffer[1024]; + s_dmi dmi; + openconsole(&dev_stdcon_r, &dev_stdcon_w); + + if (dmi_iterate(&dmi) == -ENODMITABLE) { + printf("No DMI Structure found\n"); + return -1; + } else { + printf("DMI %u.%u present.\n", dmi.dmitable.major_version, + dmi.dmitable.minor_version); + printf("%d structures occupying %d bytes.\n", dmi.dmitable.num, + dmi.dmitable.len); + printf("DMI table at 0x%08X.\n", dmi.dmitable.base); + } + + parse_dmitable(&dmi); + + for (;;) { + 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)) + break; + if (!strncmp(buffer, "system", 6)) + display_system(&dmi); + if (!strncmp(buffer, "chassis", 6)) + display_chassis(&dmi); + if (!strncmp(buffer, "base_board", 10)) + display_base_board(&dmi); + if (!strncmp(buffer, "cpu", 3)) + 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); + } + } + + return 0; +} diff --git a/contrib/syslinux-4.02/com32/modules/elf.c b/contrib/syslinux-4.02/com32/modules/elf.c new file mode 100644 index 0000000..182afa6 --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/elf.c @@ -0,0 +1,287 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * elf.c + * + * Module to load a protected-mode ELF kernel + */ + +#include <stdio.h> +#include <stdlib.h> +#include <inttypes.h> +#include <string.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <minmax.h> +#include <sys/stat.h> +#include <elf.h> +#include <console.h> +#include <dprintf.h> + +#include <syslinux/loadfile.h> +#include <syslinux/movebits.h> +#include <syslinux/bootpm.h> + +/* If we don't have this much memory for the stack, signal failure */ +#define MIN_STACK 512 + +static inline void error(const char *msg) +{ + fputs(msg, stderr); +} + +int boot_elf(void *ptr, size_t len, char **argv) +{ + char *cptr = ptr; + Elf32_Ehdr *eh = ptr; + Elf32_Phdr *ph; + unsigned int i; + struct syslinux_movelist *ml = NULL; + struct syslinux_memmap *mmap = NULL, *amap = NULL; + struct syslinux_pm_regs regs; + int argc; + addr_t argsize; + char **argp; + addr_t lstart, llen; + char *stack_frame = NULL; + addr_t stack_frame_size; + addr_t stack_pointer; + uint32_t *spp; + char *sfp; + addr_t sfa; + + memset(®s, 0, sizeof regs); + + /* + * Note: mmap is the memory map (containing free and zeroed regions) + * needed by syslinux_shuffle_boot_pm(); amap is a map where we keep + * track ourselves which target memory ranges have already been + * allocated. + */ + + if (len < sizeof(Elf32_Ehdr)) + goto bail; + + /* Must be ELF, 32-bit, littleendian, version 1 */ + if (memcmp(eh->e_ident, "\x7f" "ELF\1\1\1", 6)) + goto bail; + + /* Is this a worthwhile test? In particular x86-64 normally + would imply ELF64 support, which we could do as long as + the addresses are 32-bit addresses, and entry is 32 bits. + 64-bit addresses would take a lot more work. */ + if (eh->e_machine != EM_386 && eh->e_machine != EM_486 && + eh->e_machine != EM_X86_64) + goto bail; + + if (eh->e_version != EV_CURRENT) + goto bail; + + if (eh->e_ehsize < sizeof(Elf32_Ehdr) || eh->e_ehsize >= len) + goto bail; + + if (eh->e_phentsize < sizeof(Elf32_Phdr)) + goto bail; + + if (!eh->e_phnum) + goto bail; + + if (eh->e_phoff + eh->e_phentsize * eh->e_phnum > len) + goto bail; + + mmap = syslinux_memory_map(); + amap = syslinux_dup_memmap(mmap); + if (!mmap || !amap) + goto bail; + +#if DEBUG + dprintf("Initial memory map:\n"); + syslinux_dump_memmap(stdout, mmap); +#endif + + ph = (Elf32_Phdr *) (cptr + eh->e_phoff); + + for (i = 0; i < eh->e_phnum; i++) { + if (ph->p_type == PT_LOAD || ph->p_type == PT_PHDR) { + /* This loads at p_paddr, which is arguably the correct semantics. + The SysV spec says that SysV loads at p_vaddr (and thus Linux does, + too); that is, however, a major brainfuckage in the spec. */ + addr_t addr = ph->p_paddr; + addr_t msize = ph->p_memsz; + addr_t dsize = min(msize, ph->p_filesz); + + dprintf("Segment at 0x%08x data 0x%08x len 0x%08x\n", + addr, dsize, msize); + + if (syslinux_memmap_type(amap, addr, msize) != SMT_FREE) { + printf("Memory segment at 0x%08x (len 0x%08x) is unavailable\n", + addr, msize); + goto bail; /* Memory region unavailable */ + } + + /* Mark this region as allocated in the available map */ + if (syslinux_add_memmap(&amap, addr, dsize, SMT_ALLOC)) + goto bail; + + if (ph->p_filesz) { + /* Data present region. Create a move entry for it. */ + if (syslinux_add_movelist + (&ml, addr, (addr_t) cptr + ph->p_offset, dsize)) + goto bail; + } + if (msize > dsize) { + /* Zero-filled region. Mark as a zero region in the memory map. */ + if (syslinux_add_memmap + (&mmap, addr + dsize, msize - dsize, SMT_ZERO)) + goto bail; + } + } else { + /* Ignore this program header */ + } + + ph = (Elf32_Phdr *) ((char *)ph + eh->e_phentsize); + } + + /* Create the invocation record (initial stack frame) */ + + argsize = argc = 0; + for (argp = argv; *argp; argp++) { + dprintf("argv[%2d] = \"%s\"\n", argc, *argp); + argc++; + argsize += strlen(*argp) + 1; + } + + /* We need the argument strings, argument pointers, + argc, plus four zero-word terminators. */ + stack_frame_size = argsize + argc * sizeof(char *) + 5 * sizeof(long); + stack_frame_size = (stack_frame_size + 15) & ~15; + stack_frame = calloc(stack_frame_size, 1); + if (!stack_frame) + goto bail; + +#if DEBUG + dprintf("Right before syslinux_memmap_largest()...\n"); + syslinux_dump_memmap(stdout, amap); +#endif + + if (syslinux_memmap_largest(amap, SMT_FREE, &lstart, &llen)) + goto bail; /* NO free memory?! */ + + if (llen < stack_frame_size + MIN_STACK + 16) + goto bail; /* Insufficient memory */ + + /* Initial stack pointer address */ + stack_pointer = (lstart + llen - stack_frame_size) & ~15; + + dprintf("Stack frame at 0x%08x len 0x%08x\n", + stack_pointer, stack_frame_size); + + /* Create the stack frame. sfp is the pointer in current memory for + the next argument string, sfa is the address in its final resting place. + spp is the pointer into the argument array in current memory. */ + spp = (uint32_t *) stack_frame; + sfp = stack_frame + argc * sizeof(char *) + 5 * sizeof(long); + sfa = stack_pointer + argc * sizeof(char *) + 5 * sizeof(long); + + *spp++ = argc; + for (argp = argv; *argp; argp++) { + int bytes = strlen(*argp) + 1; /* Including final null */ + *spp++ = sfa; + memcpy(sfp, *argp, bytes); + sfp += bytes; + sfa += bytes; + } + /* Zero fields are aready taken care of by calloc() */ + + /* ... and we'll want to move it into the right place... */ +#if DEBUG + if (syslinux_memmap_type(amap, stack_pointer, stack_frame_size) + != SMT_FREE) { + dprintf("Stack frame area not free (how did that happen?)!\n"); + goto bail; /* Memory region unavailable */ + } +#endif + + if (syslinux_add_memmap(&amap, stack_pointer, stack_frame_size, SMT_ALLOC)) + goto bail; + + if (syslinux_add_movelist(&ml, stack_pointer, (addr_t) stack_frame, + stack_frame_size)) + goto bail; + + memset(®s, 0, sizeof regs); + regs.eip = eh->e_entry; + regs.esp = stack_pointer; + +#if DEBUG + dprintf("Final memory map:\n"); + syslinux_dump_memmap(stdout, mmap); + + dprintf("Final available map:\n"); + syslinux_dump_memmap(stdout, amap); + + dprintf("Movelist:\n"); + syslinux_dump_movelist(stdout, ml); +#endif + + /* This should not return... */ + fputs("Booting...\n", stdout); + syslinux_shuffle_boot_pm(ml, mmap, 0, ®s); + +bail: + if (stack_frame) + free(stack_frame); + syslinux_free_memmap(amap); + syslinux_free_memmap(mmap); + syslinux_free_movelist(ml); + + return -1; +} + +int main(int argc, char *argv[]) +{ + void *data; + size_t data_len; + + openconsole(&dev_null_r, &dev_stdcon_w); + + if (argc < 2) { + error("Usage: elf.c32 elf_file arguments...\n"); + return 1; + } + + if (zloadfile(argv[1], &data, &data_len)) { + error("Unable to load file\n"); + return 1; + } + + boot_elf(data, data_len, &argv[1]); + error("Invalid ELF file or insufficient memory\n"); + return 1; +} diff --git a/contrib/syslinux-4.02/com32/modules/ethersel.c b/contrib/syslinux-4.02/com32/modules/ethersel.c new file mode 100644 index 0000000..f586e83 --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/ethersel.c @@ -0,0 +1,210 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2005-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. + * + * ----------------------------------------------------------------------- */ + +/* + * ethersel.c + * + * Search for an Ethernet card with a known PCI signature, and run + * the corresponding Ethernet module. + * + * To use this, set up a syslinux config file like this: + * + * PROMPT 0 + * DEFAULT ethersel.c32 + * # DEV [DID xxxx:yyyy[/mask]] [RID zz-zz] [SID uuuu:vvvv[/mask]] commandline + * # ... + * + * DID = PCI device ID + * RID = Revision ID (range) + * SID = Subsystem ID + */ + +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <console.h> +#include <sys/pci.h> +#include <com32.h> +#include <syslinux/boot.h> +#include <syslinux/config.h> + +#ifdef DEBUG +# define dprintf printf +#else +# define dprintf(...) ((void)0) +#endif + +static char *skipspace(char *p) +{ + while (*p && *p <= ' ') + p++; + + return p; +} + +#define MAX_LINE 512 + +/* Check to see if we are at a certain keyword (case insensitive) */ +static int looking_at(const char *line, const char *kwd) +{ + const char *p = line; + const char *q = kwd; + + while (*p && *q && ((*p ^ *q) & ~0x20) == 0) { + p++; + q++; + } + + if (*q) + return 0; /* Didn't see the keyword */ + + return *p <= ' '; /* Must be EOL or whitespace */ +} + +static char *get_did(char *p, uint32_t * idptr, uint32_t * maskptr) +{ + unsigned long vid, did, m1, m2; + + *idptr = -1; + *maskptr = 0xffffffff; + + vid = strtoul(p, &p, 16); + if (*p != ':') + return p; /* Bogus ID */ + did = strtoul(p + 1, &p, 16); + + *idptr = (did << 16) + vid; + + if (*p == '/') { + m1 = strtoul(p + 1, &p, 16); + if (*p != ':') { + *maskptr = (m1 << 16) | 0xffff; + } else { + m2 = strtoul(p + 1, &p, 16); + *maskptr = (m1 << 16) | m2; + } + } + + return p; +} + +static char *get_rid_range(char *p, uint8_t * rid_min, uint8_t * rid_max) +{ + unsigned long r0, r1; + + p = skipspace(p + 3); + + r0 = strtoul(p, &p, 16); + if (*p == '-') { + r1 = strtoul(p + 1, &p, 16); + } else { + r1 = r0; + } + + *rid_min = r0; + *rid_max = r1; + + return p; +} + +static struct match *parse_config(const char *filename) +{ + char line[MAX_LINE], *p; + FILE *f; + struct match *list = NULL; + struct match **ep = &list; + struct match *m; + + if (!filename) + filename = syslinux_config_file(); + + f = fopen(filename, "r"); + if (!f) + return list; + + while (fgets(line, sizeof line, f)) { + p = skipspace(line); + + if (!looking_at(p, "#")) + continue; + p = skipspace(p + 1); + + if (!looking_at(p, "dev")) + continue; + p = skipspace(p + 3); + + m = malloc(sizeof(struct match)); + if (!m) + continue; + + memset(m, 0, sizeof *m); + m->rid_max = 0xff; + + for (;;) { + p = skipspace(p); + + if (looking_at(p, "did")) { + p = get_did(p + 3, &m->did, &m->did_mask); + } else if (looking_at(p, "sid")) { + p = get_did(p + 3, &m->sid, &m->sid_mask); + } else if (looking_at(p, "rid")) { + p = get_rid_range(p + 3, &m->rid_min, &m->rid_max); + } else { + char *e; + + e = strchr(p, '\n'); + if (*e) + *e = '\0'; + e = strchr(p, '\r'); + if (*e) + *e = '\0'; + + m->filename = strdup(p); + if (!m->filename) + m->did = -1; + break; /* Done with this line */ + } + } + + dprintf("DEV DID %08x/%08x SID %08x/%08x RID %02x-%02x CMD %s\n", + m->did, m->did_mask, m->sid, m->sid_mask, + m->rid_min, m->rid_max, m->filename); + + *ep = m; + ep = &m->next; + } + + return list; +} + +int main(int argc, char *argv[]) +{ + struct match *list, *match; + struct pci_domain *pci_domain; + + openconsole(&dev_null_r, &dev_stdcon_w); + pci_domain = pci_scan(); + + if (pci_domain) { + list = parse_config(argc < 2 ? NULL : argv[1]); + + match = find_pci_device(pci_domain, list); + + if (match) + syslinux_run_command(match->filename); + } + + /* On error, return to the command line */ + fputs("Error: no recognized network card found!\n", stderr); + return 1; +} diff --git a/contrib/syslinux-4.02/com32/modules/gpxecmd.c b/contrib/syslinux-4.02/com32/modules/gpxecmd.c new file mode 100644 index 0000000..057659b --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/gpxecmd.c @@ -0,0 +1,86 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2008 H. Peter Anvin - All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * gpxecmd.c + * + * Invoke an arbitrary gPXE command, if available. + */ + +#include <alloca.h> +#include <inttypes.h> +#include <stdio.h> +#include <console.h> +#include <com32.h> +#include <string.h> +#include <sys/gpxe.h> + +struct segoff16 { + uint16_t offs, seg; +}; + +struct s_PXENV_FILE_EXEC { + uint16_t Status; + struct segoff16 Command; +}; + +static void gpxecmd(const char **args) +{ + char *q; + struct s_PXENV_FILE_EXEC *fx; + com32sys_t reg; + + memset(®, 0, sizeof reg); + + fx = __com32.cs_bounce; + q = (char *)(fx + 1); + + fx->Status = 1; + fx->Command.offs = OFFS(q); + fx->Command.seg = SEG(q); + + while (*args) { + q = stpcpy(q, *args); + *q++ = ' '; + args++; + } + *--q = '\0'; + + memset(®, 0, sizeof reg); + reg.eax.w[0] = 0x0009; + reg.ebx.w[0] = 0x00e5; /* PXENV_FILE_EXEC */ + reg.edi.w[0] = OFFS(fx); + reg.es = SEG(fx); + + __intcall(0x22, ®, ®); + + /* This should not return... */ +} + +int main(int argc, const char *argv[]) +{ + openconsole(&dev_null_r, &dev_stdcon_w); + + if (argc < 2) { + printf("Usage: gpxecmd command...\n"); + return 1; + } + + if (!is_gpxe()) { + printf("gpxecmd: gPXE API not detected\n"); + return 1; + } + + gpxecmd(argv + 1); + + return 0; +} diff --git a/contrib/syslinux-4.02/com32/modules/host.c b/contrib/syslinux-4.02/com32/modules/host.c new file mode 100644 index 0000000..94ca876 --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/host.c @@ -0,0 +1,42 @@ +#include <stdio.h> +#include <console.h> +#include <string.h> +#include <netinet/in.h> +#include <com32.h> + +static struct in_addr dnsresolve(const char *hostname) +{ + com32sys_t regs; + struct in_addr addr; + + strcpy(__com32.cs_bounce, hostname); + + regs.eax.w[0] = 0x0010; + regs.es = SEG(__com32.cs_bounce); + regs.ebx.w[0] = OFFS(__com32.cs_bounce); + __intcall(0x22, ®s, ®s); + + addr.s_addr = regs.eax.l; + return addr; +} + +int main(int argc, char *argv[]) +{ + int i; + struct in_addr addr; + + openconsole(&dev_null_r, &dev_stdcon_w); + + for (i = 1; i < argc; i++) { + addr = dnsresolve(argv[i]); + + printf("%-39s %08X %d.%d.%d.%d\n", + argv[i], ntohl(addr.s_addr), + ((uint8_t *)&addr.s_addr)[0], + ((uint8_t *)&addr.s_addr)[1], + ((uint8_t *)&addr.s_addr)[2], + ((uint8_t *)&addr.s_addr)[3]); + } + + return 0; +} diff --git a/contrib/syslinux-4.02/com32/modules/ifcpu.c b/contrib/syslinux-4.02/com32/modules/ifcpu.c new file mode 100644 index 0000000..a28acc4 --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/ifcpu.c @@ -0,0 +1,169 @@ +/* ----------------------------------------------------------------------- * + * + * 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., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * ifcpu.c + * + */ + +#include <alloca.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <cpuid.h> +#include <unistd.h> +#include <syslinux/boot.h> +#include <com32.h> +#include <consoles.h> + +static inline void error(const char *msg) +{ + fputs(msg, stderr); +} + +static void usage(void) +{ + error("Run one command if system match some CPU features, another if it doesn't. \n" + "Usage: \n" + " label ifcpu \n" + " com32 ifcpu.c32 \n" + " append <option> <cpu_features> -- boot_entry_1 -- boot_entry_2 \n" + " label boot_entry_1 \n" + " kernel vmlinuz_entry1 \n" + " append ... \n" + " label boot_entry_2 \n" + " kernel vmlinuz_entry2 \n" + " append ... \n" + "\n" + "options could be :\n" + " debug : display some debugging messages \n" + " dry-run : just do the detection, don't boot \n" + "\n" + "cpu_features could be:\n" + " 64 : Processor is x86_64 compatible (lm cpu flag)\n" + " hvm : Processor features hardware virtualization (hvm or svm cpu flag)\n" + " multicore : Processor must be multi-core \n" + " smp : System must be multi-processor \n" + " pae : Processor features Physical Address Extension (PAE)\n" + "\n" + "if you want to match many cpu features, just separate them with a single space.\n"); +} + +/* XXX: this really should be librarized */ +static void boot_args(char **args) +{ + int len = 0, a = 0; + char **pp; + const char *p; + char c, *q, *str; + + for (pp = args; *pp; pp++) + len += strlen(*pp) + 1; + + q = str = alloca(len); + for (pp = args; *pp; pp++) { + p = *pp; + while ((c = *p++)) + *q++ = c; + *q++ = ' '; + a = 1; + } + q -= a; + *q = '\0'; + + if (!str[0]) + syslinux_run_default(); + else + syslinux_run_command(str); +} + +#define show_bool(mybool) mybool ? "found":"not found" + +int main(int argc, char *argv[]) +{ + char **args[3]; + int i=0; + int n=0; + bool hardware_matches = true; + bool multicore = false; + bool dryrun = false; + bool debug = false; + + s_cpu cpu; + console_ansi_raw(); + detect_cpu(&cpu); + + /* If no argument got passed, let's show the usage */ + if (argc == 1) { + usage(); + return -1; + } + + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "--")) { + argv[i] = NULL; + args[n++] = &argv[i + 1]; + } else if (!strcmp(argv[i], "64")) { + if (debug) + printf(" 64bit : %s on this system\n", + show_bool(cpu.flags.lm)); + hardware_matches = cpu.flags.lm && hardware_matches; + } else if (!strcmp(argv[i], "pae")) { + if (debug) + printf(" pae : %s on this system\n", + show_bool(cpu.flags.pae)); + hardware_matches = cpu.flags.pae && hardware_matches; + } else if (!strcmp(argv[i], "hvm")) { + if (debug) + printf(" hvm : %s on this system\n", + show_bool((cpu.flags.vmx || cpu.flags.svm))); + hardware_matches = (cpu.flags.vmx || cpu.flags.svm) + && hardware_matches; + } else if (!strcmp(argv[i], "multicore")) { + if (debug) + printf(" multicore : %d cores on this system\n", cpu.num_cores); + if (cpu.num_cores > 1) + multicore = true; + hardware_matches = multicore && hardware_matches; + } else if (!strcmp(argv[i], "smp")) { + if (debug) + printf(" smp : %s on this system\n", show_bool(cpu.flags.smp)); + hardware_matches = cpu.flags.smp && hardware_matches; + } else if (!strcmp(argv[i], "dry-run")) { + dryrun = true; + } else if (!strcmp(argv[i], "debug")) { + debug = true; + } + if (n >= 2) + break; + } + while (n < 2) { + args[n] = args[n - 1]; + n++; + } + if (debug) { + printf("\nBooting labels are : '%s' or '%s'\n", *args[0], *args[1]); + printf("Hardware requirements%smatch this system, let's booting '%s'\n", + hardware_matches ? " " : " doesn't ", + hardware_matches ? *args[0] : *args[1]); + printf("Sleeping 5sec before booting\n"); + if (!dryrun) + sleep(5); + } + + if (!dryrun) + boot_args(hardware_matches ? args[0] : args[1]); + else + printf("Dry-run mode, let's exiting\n"); + + return -1; +} diff --git a/contrib/syslinux-4.02/com32/modules/ifcpu64.c b/contrib/syslinux-4.02/com32/modules/ifcpu64.c new file mode 100644 index 0000000..e123922 --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/ifcpu64.c @@ -0,0 +1,125 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2008 H. Peter Anvin - All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * ifcpu64.c + * + * Run one command if the CPU has 64-bit support, and another if it doesn't. + * Eventually this and other features should get folded into some kind + * of scripting engine. + * + * Usage: + * + * label boot_kernel + * com32 ifcpu64.c32 + * append boot_kernel_64 [-- boot_kernel_32pae] -- boot_kernel_32 + * label boot_kernel_32 + * kernel vmlinuz_32 + * append ... + * label boot_kernel_64 + * kernel vmlinuz_64 + * append ... + */ + +#include <alloca.h> +#include <stdlib.h> +#include <string.h> +#include <cpuid.h> +#include <syslinux/boot.h> + +static bool __constfunc cpu_has_cpuid(void) +{ + return cpu_has_eflag(X86_EFLAGS_ID); +} + +static bool __constfunc cpu_has_level(uint32_t level) +{ + uint32_t group; + uint32_t limit; + + if (!cpu_has_cpuid()) + return false; + + group = level & 0xffff0000; + limit = cpuid_eax(group); + + if ((limit & 0xffff0000) != group) + return false; + + if (level > limit) + return false; + + return true; +} + +/* This only supports feature groups 0 and 1, corresponding to the + Intel and AMD EDX bit vectors. We can add more later if need be. */ +static bool __constfunc cpu_has_feature(int x) +{ + uint32_t level = ((x & 1) << 31) | 1; + + return cpu_has_level(level) && ((cpuid_edx(level) >> (x & 31) & 1)); +} + +/* XXX: this really should be librarized */ +static void boot_args(char **args) +{ + int len = 0, a = 0; + char **pp; + const char *p; + char c, *q, *str; + + for (pp = args; *pp; pp++) + len += strlen(*pp) + 1; + + q = str = alloca(len); + for (pp = args; *pp; pp++) { + p = *pp; + while ((c = *p++)) + *q++ = c; + *q++ = ' '; + a = 1; + } + q -= a; + *q = '\0'; + + if (!str[0]) + syslinux_run_default(); + else + syslinux_run_command(str); +} + +int main(int argc, char *argv[]) +{ + char **args[3]; + int i; + int n; + + args[0] = &argv[1]; + n = 1; + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "--")) { + argv[i] = NULL; + args[n++] = &argv[i + 1]; + } + if (n >= 3) + break; + } + while (n < 3) { + args[n] = args[n - 1]; + n++; + } + + boot_args(cpu_has_feature(X86_FEATURE_LM) ? args[0] : + cpu_has_feature(X86_FEATURE_PAE) ? args[1] : args[2]); + return -1; +} diff --git a/contrib/syslinux-4.02/com32/modules/ifplop.c b/contrib/syslinux-4.02/com32/modules/ifplop.c new file mode 100644 index 0000000..a846df8 --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/ifplop.c @@ -0,0 +1,170 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2010 Gert Hulselmans - All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * ifplop.c + * + * This COM32 module detects if the PLoP Boot Manager was used to boot a CDROM + * drive or USB drive, by checking for the presence of the PLoP INT13h hook. + * + * Usage: ifplop.c32 [<plop_detected>] -- [<plop_not_detected>] + * Examples: ifplop.c32 menu.c32 another.cfg -- plpbt hiddenusb usb1=2 + * You need to remove the ".bin" extension of the plpbt.bin file + * if you use it this way. + * ifplop.c32 plop_detected -- plop_not_detected + * + * A possible config file could be: + * + * =========================================================================== + * DEFAULT plopcheck + * + * # Check for the presence of PLoP (run by default) + * # When PLoP INT13h hook is found, run the first command (plop_detected) + * # When PLoP INT13h hook isn't found, run the second command (plop_not_detected) + * LABEL plopcheck + * COM32 ifplop.c32 + * APPEND plop_detected -- plop_not_detected + * + * # When PLoP INT13h hook was found, boot the menu system. + * # PLoP can have added USB 2.0 speed, so the entries we want to boot + * # will be read from disk much faster (supposing that we have a BIOS + * # that only supports USB 1.1 speed, but a mobo with USB 2.0 controllers). + * LABEL plop_detected + * COM32 menu.c32 + * APPEND another.cfg + * + * # PLoP INT13h hook wasn't found, so we boot PLoP, so it can add USB 2.0 support + * # When using "LINUX plpbt.bin", you don't need to remove the .bin extension. + * LABEL plop_not_detected + * LINUX plpbt.bin + * APPEND hiddenusb usb1=2 + * + * =========================================================================== + * + * Why is/can this module be useful? + * + * You may want to boot PLoP by default from Syslinux when you boot from your + * USB stick/drive: + * 1. PLoP can upgrade USB 1.1 speed offered by the BIOS to USB 2.0 speed + * if you have USB 2.0 controllers on your mobo. + * 2. Some BIOSes only can access the first 128GiB (137GB) on USB drives, while + * internal hard drives don't necessarily suffer from this 128GiB problem. + * Using PLoPs USB capabilities, you can access the whole drive. + * + * When you select the "USB" entry in PLoP, it will boot your USB stick/drive + * again and it will boot PLoP again when you have set booting PLoP as DEFAULT + * boot option in your Syslinux configuration file. + * + * By using ifplop.c32 you can specify which action you want to do the second + * time your USB stick/drive is booted. So you can load another config file or + * boot a large hard disk image or whatever you want. + * + * PLoP Boot Manager website: http://www.plop.at/en/bootmanager.html + */ + +#include <com32.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <alloca.h> +#include <console.h> +#include <syslinux/boot.h> + +static bool plop_INT13h_check(void) +{ + com32sys_t inregs, outregs; + + /* Prepare the register set */ + memset(&inregs, 0, sizeof inregs); + + /* + * Check if PLoP already has booted a CDROM or USB drive by checking + * for the presence of the PLoP INT13h hook. + * + * The following assembly code (NASM) can detect the PLoP INT13h hook: + * + * mov eax,'PoLP' ; Reverse of 'PLoP' + * mov ebp,'DKHC' ; Reverse of 'CHKD' + * int 13h + * cmp eax,' sey' ; Reverse of 'yes ' + * jz plop_INT13h_active + */ + + inregs.eax.l = 0x504c6f50; /* "PLoP" */ + inregs.ebp.l = 0x43484b44; /* "CHKD" */ + + __intcall(0x13, &inregs, &outregs); + + /* eax will contain "yes " if PLoP INT13h hook is available */ + if (outregs.eax.l == 0x79657320) + return true; + + return false; +} + +/* XXX: this really should be librarized */ +static void boot_args(char **args) +{ + int len = 0, a = 0; + char **pp; + const char *p; + char c, *q, *str; + + for (pp = args; *pp; pp++) + len += strlen(*pp) + 1; + + q = str = alloca(len); + for (pp = args; *pp; pp++) { + p = *pp; + while ((c = *p++)) + *q++ = c; + *q++ = ' '; + a = 1; + } + q -= a; + *q = '\0'; + + if (!str[0]) + syslinux_run_default(); + else + syslinux_run_command(str); +} + +int main(int argc, char *argv[]) +{ + char **args[2]; + int arg = 0; + + openconsole(&dev_null_r, &dev_stdcon_w); + + if (argc) + arg++; + args[0] = &argv[arg]; + args[1] = NULL; + while (arg < argc) { + if (!strcmp(argv[arg], "--")) { + argv[arg] = NULL; + args[1] = &argv[arg + 1]; + break; + } + arg++; + } + if (args[1] != NULL) { + boot_args(plop_INT13h_check()? args[0] : args[1]); + } else { + fprintf(stderr, + "Usage: ifplop.c32 [<plop_detected>] -- [<plop_not_detected>]\n" + "Example: ifplop.c32 menu.c32 another.cfg -- plpbt hiddenusb usb1=2\n"); + } + + return 0; +} diff --git a/contrib/syslinux-4.02/com32/modules/kbdmap.c b/contrib/syslinux-4.02/com32/modules/kbdmap.c new file mode 100644 index 0000000..f1c736d --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/kbdmap.c @@ -0,0 +1,54 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +#include <stdio.h> +#include <string.h> +#include <console.h> +#include <syslinux/loadfile.h> +#include <syslinux/keyboard.h> + +static inline void error(const char *msg) +{ + fputs(msg, stderr); +} + +int main(int argc, char *argv[]) +{ + const struct syslinux_keyboard_map *const kmap = syslinux_keyboard_map(); + size_t map_size; + void *kbdmap; + + openconsole(&dev_null_r, &dev_stdcon_w); + + if (argc != 2) { + error("Usage: kbdmap mapfile\n"); + return 1; + } + + if (kmap->version != 1) { + error("Syslinux core version mismatch\n"); + return 1; + } + + if (loadfile(argv[1], &kbdmap, &map_size)) { + error("Keyboard map file load error\n"); + return 1; + } + + if (map_size != kmap->length) { + error("Keyboard map file format error\n"); + return 1; + } + + memcpy(kmap->map, kbdmap, map_size); + return 0; +} diff --git a/contrib/syslinux-4.02/com32/modules/linux.c b/contrib/syslinux-4.02/com32/modules/linux.c new file mode 100644 index 0000000..b902ebc --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/linux.c @@ -0,0 +1,216 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * linux.c + * + * Sample module to load Linux kernels. This module can also create + * a file out of the DHCP return data if running under PXELINUX. + * + * If -dhcpinfo is specified, the DHCP info is written into the file + * /dhcpinfo.dat in the initramfs. + * + * Usage: linux.c32 [-dhcpinfo] kernel arguments... + */ + +#include <stdbool.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <console.h> +#include <syslinux/loadfile.h> +#include <syslinux/linux.h> +#include <syslinux/pxe.h> + +const char *progname = "linux.c32"; + +/* Find the last instance of a particular command line argument + (which should include the final =; do not use for boolean arguments) */ +static char *find_argument(char **argv, const char *argument) +{ + int la = strlen(argument); + char **arg; + char *ptr = NULL; + + for (arg = argv; *arg; arg++) { + if (!memcmp(*arg, argument, la)) + ptr = *arg + la; + } + + return ptr; +} + +/* Search for a boolean argument; return its position, or 0 if not present */ +static int find_boolean(char **argv, const char *argument) +{ + char **arg; + + for (arg = argv; *arg; arg++) { + if (!strcmp(*arg, argument)) + return (arg - argv) + 1; + } + + return 0; +} + +/* Stitch together the command line from a set of argv's */ +static char *make_cmdline(char **argv) +{ + char **arg; + size_t bytes; + char *cmdline, *p; + + bytes = 1; /* Just in case we have a zero-entry cmdline */ + for (arg = argv; *arg; arg++) { + bytes += strlen(*arg) + 1; + } + + p = cmdline = malloc(bytes); + if (!cmdline) + return NULL; + + for (arg = argv; *arg; arg++) { + int len = strlen(*arg); + memcpy(p, *arg, len); + p[len] = ' '; + p += len + 1; + } + + if (p > cmdline) + p--; /* Remove the last space */ + *p = '\0'; + + return cmdline; +} + +int main(int argc, char *argv[]) +{ + const char *kernel_name; + struct initramfs *initramfs; + char *cmdline; + char *boot_image; + void *kernel_data; + size_t kernel_len; + bool opt_dhcpinfo = false; + bool opt_quiet = false; + void *dhcpdata; + size_t dhcplen; + char **argp, *arg, *p; + + openconsole(&dev_null_r, &dev_stdcon_w); + + (void)argc; + argp = argv + 1; + + while ((arg = *argp) && arg[0] == '-') { + if (!strcmp("-dhcpinfo", arg)) { + opt_dhcpinfo = true; + } else { + fprintf(stderr, "%s: unknown option: %s\n", progname, arg); + return 1; + } + argp++; + } + + if (!arg) { + fprintf(stderr, "%s: missing kernel name\n", progname); + return 1; + } + + kernel_name = arg; + + boot_image = malloc(strlen(kernel_name) + 12); + if (!boot_image) + goto bail; + strcpy(boot_image, "BOOT_IMAGE="); + strcpy(boot_image + 11, kernel_name); + /* argp now points to the kernel name, and the command line follows. + Overwrite the kernel name with the BOOT_IMAGE= argument, and thus + we have the final argument. */ + *argp = boot_image; + + if (find_boolean(argp, "quiet")) + opt_quiet = true; + + if (!opt_quiet) + printf("Loading %s... ", kernel_name); + if (loadfile(kernel_name, &kernel_data, &kernel_len)) { + if (opt_quiet) + printf("Loading %s ", kernel_name); + printf("failed!\n"); + goto bail; + } + if (!opt_quiet) + printf("ok\n"); + + cmdline = make_cmdline(argp); + if (!cmdline) + goto bail; + + /* Initialize the initramfs chain */ + initramfs = initramfs_init(); + if (!initramfs) + goto bail; + + if ((arg = find_argument(argp, "initrd="))) { + do { + p = strchr(arg, ','); + if (p) + *p = '\0'; + + if (!opt_quiet) + printf("Loading %s... ", arg); + if (initramfs_load_archive(initramfs, arg)) { + if (opt_quiet) + printf("Loading %s ", kernel_name); + printf("failed!\n"); + goto bail; + } + if (!opt_quiet) + printf("ok\n"); + + if (p) + *p++ = ','; + } while ((arg = p)); + } + + /* Append the DHCP info */ + if (opt_dhcpinfo && + !pxe_get_cached_info(PXENV_PACKET_TYPE_DHCP_ACK, &dhcpdata, &dhcplen)) { + if (initramfs_add_file(initramfs, dhcpdata, dhcplen, dhcplen, + "/dhcpinfo.dat", 0, 0755)) + goto bail; + } + + /* This should not return... */ + syslinux_boot_linux(kernel_data, kernel_len, initramfs, cmdline); + +bail: + fprintf(stderr, "Kernel load failure (insufficient memory?)\n"); + return 1; +} diff --git a/contrib/syslinux-4.02/com32/modules/ls.c b/contrib/syslinux-4.02/com32/modules/ls.c new file mode 100644 index 0000000..c311621 --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/ls.c @@ -0,0 +1,177 @@ +/* + * Display directory contents + */ +#include <stdlib.h> +#include <stdio.h> +#include <console.h> +#include <string.h> +#include <com32.h> +#include <dirent.h> +#include <minmax.h> +#include <unistd.h> +#include <getkey.h> + +static int rows, cols; /* Screen parameters */ + +#define DIR_CHUNK 1024 + +static const char *type_str(int type) +{ + switch (type) { + case DT_FIFO: + return "[fif]"; + case DT_CHR: + return "[chr]"; + case DT_DIR: + return "[dir]"; + case DT_BLK: + return "[blk]"; + case DT_UNKNOWN: + case DT_REG: + return ""; + case DT_LNK: + return "[lnk]"; + case DT_SOCK: + return "[sck]"; + case DT_WHT: + return "[wht]"; + default: + return "[???]"; + } +} + +static void free_dirents(struct dirent **dex, size_t n_de) +{ + size_t i; + + for (i = 0; i < n_de; i++) + free(dex[i]); + + free(dex); +} + +static int compare_dirent(const void *p_de1, const void *p_de2) +{ + const struct dirent *de1 = *(const struct dirent **)p_de1; + const struct dirent *de2 = *(const struct dirent **)p_de2; + int ndir1, ndir2; + + ndir1 = de1->d_type != DT_DIR; + ndir2 = de2->d_type != DT_DIR; + + if (ndir1 != ndir2) + return ndir1 - ndir2; + + return strcmp(de1->d_name, de2->d_name); +} + +static int display_directory(const char *dirname) +{ + DIR *dir; + struct dirent *de; + struct dirent **dex = NULL; + size_t n_dex = 0, n_de = 0; + size_t i, j, k; + size_t nrows, ncols, perpage; + size_t endpage; + int maxlen = 0; + int pos, tpos, colwidth; + + dir = opendir(dirname); + if (!dir) { + printf("Unable to read directory: %s\n", dirname); + return -1; + } + + while ((de = readdir(dir)) != NULL) { + struct dirent *nde; + + if (n_de >= n_dex) { + struct dirent **ndex; + + ndex = realloc(dex, (n_dex + DIR_CHUNK) * sizeof *dex); + if (!ndex) + goto nomem; + + dex = ndex; + n_dex += DIR_CHUNK; + } + + nde = malloc(de->d_reclen); + if (!nde) + goto nomem; + + memcpy(nde, de, de->d_reclen); + dex[n_de++] = nde; + + maxlen = max(maxlen, de->d_reclen); + } + + closedir(dir); + + qsort(dex, n_de, sizeof *dex, compare_dirent); + + maxlen -= offsetof(struct dirent, d_name) + 1; + ncols = (cols + 2)/(maxlen + 8); + ncols = min(ncols, n_de); + ncols = max(ncols, 1U); + colwidth = (cols + 2)/ncols; + perpage = ncols * (rows - 1); + + for (i = 0; i < n_de; i += perpage) { + /* Rows on this page */ + endpage = min(i+perpage, n_de); + nrows = ((endpage-i) + ncols - 1)/ncols; + + for (j = 0; j < nrows; j++) { + pos = tpos = 0; + for (k = i+j; k < endpage; k += nrows) { + pos += printf("%*s%-5s %s", + (tpos - pos), "", + type_str(dex[k]->d_type), + dex[k]->d_name); + tpos += colwidth; + } + printf("\n"); + } + + if (endpage >= n_de) + break; + + get_key(stdin, 0); + } + + free_dirents(dex, n_de); + return 0; + +nomem: + closedir(dir); + printf("Out of memory error!\n"); + free_dirents(dex, n_de); + return -1; +} + +int main(int argc, char *argv[]) +{ + int rv; + + openconsole(&dev_rawcon_r, &dev_stdcon_w); + + if (getscreensize(1, &rows, &cols)) { + /* Unknown screen size? */ + rows = 24; + cols = 80; + } + + if (argc < 2) + rv = display_directory("."); + else if (argc == 2) + rv = display_directory(argv[1]); + else { + printf("Usage: %s directory\n", argv[0]); + rv = 1; + } + + return rv ? 1 : 0; +} + diff --git a/contrib/syslinux-4.02/com32/modules/meminfo.c b/contrib/syslinux-4.02/com32/modules/meminfo.c new file mode 100644 index 0000000..6e24f35 --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/meminfo.c @@ -0,0 +1,126 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2008 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * meminfo.c + * + * Dump the memory map of the system + */ +#include <inttypes.h> +#include <stdio.h> +#include <string.h> +#include <console.h> +#include <com32.h> + +struct e820_data { + uint64_t base; + uint64_t len; + uint32_t type; + uint32_t extattr; +} __attribute__ ((packed)); + +static const char *const e820_types[] = { + "usable", + "reserved", + "ACPI reclaim", + "ACPI NVS", + "unusable", +}; + +static void dump_e820(void) +{ + com32sys_t ireg, oreg; + struct e820_data ed; + uint32_t type; + + memset(&ireg, 0, sizeof ireg); + + ireg.eax.w[0] = 0xe820; + ireg.edx.l = 0x534d4150; + ireg.ecx.l = sizeof(struct e820_data); + ireg.edi.w[0] = OFFS(__com32.cs_bounce); + ireg.es = SEG(__com32.cs_bounce); + + memset(&ed, 0, sizeof ed); + ed.extattr = 1; + + do { + memcpy(__com32.cs_bounce, &ed, sizeof ed); + + __intcall(0x15, &ireg, &oreg); + if (oreg.eflags.l & EFLAGS_CF || + oreg.eax.l != 0x534d4150 || oreg.ecx.l < 20) + break; + + memcpy(&ed, __com32.cs_bounce, sizeof ed); + + if (oreg.ecx.l >= 24) { + /* ebx base length end type */ + printf("%8x %016llx %016llx %016llx %d [%x]", + ireg.ebx.l, ed.base, ed.len, ed.base + ed.len, ed.type, + ed.extattr); + } else { + /* ebx base length end */ + printf("%8x %016llx %016llx %016llx %d [-]", + ireg.ebx.l, ed.base, ed.len, ed.base + ed.len, ed.type); + ed.extattr = 1; + } + + type = ed.type - 1; + if (type < sizeof(e820_types) / sizeof(e820_types[0])) + printf(" %s", e820_types[type]); + + putchar('\n'); + + ireg.ebx.l = oreg.ebx.l; + } while (ireg.ebx.l); +} + +static void dump_legacy(void) +{ + com32sys_t ireg, oreg; + uint16_t dosram = *(uint16_t *) 0x413; + struct { + uint16_t offs, seg; + } *const ivt = (void *)0; + + memset(&ireg, 0, sizeof ireg); + + __intcall(0x12, &ireg, &oreg); + + printf + ("INT 15h = %04x:%04x DOS RAM: %dK (0x%05x) INT 12h: %dK (0x%05x)\n", + ivt[0x15].seg, ivt[0x15].offs, dosram, dosram << 10, oreg.eax.w[0], + oreg.eax.w[0] << 10); + + ireg.eax.b[1] = 0x88; + __intcall(0x15, &ireg, &oreg); + + printf("INT 15 88: 0x%04x (%uK) ", oreg.eax.w[0], oreg.eax.w[0]); + + ireg.eax.w[0] = 0xe801; + __intcall(0x15, &ireg, &oreg); + + printf("INT 15 E801: 0x%04x (%uK) 0x%04x (%uK)\n", + oreg.ecx.w[0], oreg.ecx.w[0], oreg.edx.w[0], oreg.edx.w[0] << 6); +} + +int main(void) +{ + openconsole(&dev_null_r, &dev_stdcon_w); + + dump_legacy(); + dump_e820(); + + return 0; +} diff --git a/contrib/syslinux-4.02/com32/modules/pcitest.c b/contrib/syslinux-4.02/com32/modules/pcitest.c new file mode 100644 index 0000000..672023a --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/pcitest.c @@ -0,0 +1,158 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * 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. + * + * ----------------------------------------------------------------------- +*/ + +/* + * pcitest.c + * + */ + +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <console.h> +#include <com32.h> +#include <sys/pci.h> +#include <stdbool.h> + +#ifdef DEBUG +# define dprintf printf +#else +# define dprintf(...) ((void)0) +#endif + +char display_line = 0; +#define moreprintf(...) \ + do { \ + display_line++; \ + if (display_line == 24) { \ + char tempbuf[10]; \ + display_line=0; \ + printf("Press Enter to continue\n"); \ + fgets(tempbuf, sizeof tempbuf, stdin); \ + } \ + printf ( __VA_ARGS__); \ + } while (0); + +void display_pci_devices(struct pci_domain *pci_domain) +{ + struct pci_device *pci_device; + char kernel_modules[LINUX_KERNEL_MODULE_SIZE * + MAX_KERNEL_MODULES_PER_PCI_DEVICE]; + + for_each_pci_func(pci_device, pci_domain) { + + 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); + } +} + +int main(int argc, char *argv[]) +{ + struct pci_domain *pci_domain; + int return_code = 0; + int nb_pci_devices = 0; + + (void)argc; + (void)argv; + + openconsole(&dev_stdcon_r, &dev_stdcon_w); + + /* Scanning to detect pci buses and devices */ + printf("PCI: Scanning PCI BUS\n"); + pci_domain = pci_scan(); + if (!pci_domain) { + printf("PCI: no devices found!\n"); + return 1; + } + + 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 */ + 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 file in current directory.\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 file in current directory.\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 */ + return_code = get_module_name_from_pcimap(pci_domain, "modules.pcimap"); + if (return_code == -ENOMODULESPCIMAP) { + printf("PCI: ERROR !\n"); + printf("PCI: Unable to open modules.pcimap file in current directory.\n"); + printf("PCI: Kernel Module names can't be computed.\n"); + } + + /* display the pci devices we found */ + display_pci_devices(pci_domain); + return 0; +} diff --git a/contrib/syslinux-4.02/com32/modules/pmload.c b/contrib/syslinux-4.02/com32/modules/pmload.c new file mode 100644 index 0000000..3064a94 --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/pmload.c @@ -0,0 +1,224 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * pmload.c + * + * Load a binary file and run it in protected mode. We give it + * an ELF-style invocation record, becase, why not? + * + * Usage: pmload.c32 filename address [arguments...] + */ + +#include <stdio.h> +#include <stdlib.h> +#include <inttypes.h> +#include <string.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <sys/stat.h> +#include <elf.h> +#include <console.h> +#include <dprintf.h> + +#include <syslinux/loadfile.h> +#include <syslinux/movebits.h> +#include <syslinux/bootpm.h> + +/* If we don't have this much memory for the stack, signal failure */ +#define MIN_STACK 512 + +static inline void error(const char *msg) +{ + fputs(msg, stderr); +} + +int boot_raw(void *ptr, size_t len, addr_t where, char **argv) +{ + struct syslinux_movelist *ml = NULL; + struct syslinux_memmap *mmap = NULL, *amap = NULL; + struct syslinux_pm_regs regs; + int argc; + addr_t argsize; + char **argp; + addr_t lstart, llen; + char *stack_frame = NULL; + addr_t stack_frame_size; + addr_t stack_pointer; + uint32_t *spp; + char *sfp; + addr_t sfa; + + memset(®s, 0, sizeof regs); + + mmap = syslinux_memory_map(); + amap = syslinux_dup_memmap(mmap); + if (!mmap || !amap) + goto bail; + +#if DEBUG + dprintf("Initial memory map:\n"); + syslinux_dump_memmap(stdout, mmap); +#endif + + dprintf("Segment at 0x%08x len 0x%08x\n", where, len); + + if (syslinux_memmap_type(amap, where, len) != SMT_FREE) { + printf("Memory segment at 0x%08x (len 0x%08x) is unavailable\n", + where, len); + goto bail; /* Memory region unavailable */ + } + + /* Mark this region as allocated in the available map */ + if (syslinux_add_memmap(&amap, where, len, SMT_ALLOC)) + goto bail; + + /* Data present region. Create a move entry for it. */ + if (syslinux_add_movelist(&ml, where, (addr_t) ptr, len)) + goto bail; + + /* Create the invocation record (initial stack frame) */ + + argsize = argc = 0; + for (argp = argv; *argp; argp++) { + dprintf("argv[%2d] = \"%s\"\n", argc, *argp); + argc++; + argsize += strlen(*argp) + 1; + } + + /* We need the argument strings, argument pointers, + argc, plus four zero-word terminators. */ + stack_frame_size = argsize + argc * sizeof(char *) + 5 * sizeof(long); + stack_frame_size = (stack_frame_size + 15) & ~15; + stack_frame = calloc(stack_frame_size, 1); + if (!stack_frame) + goto bail; + +#if DEBUG + dprintf("Right before syslinux_memmap_largest()...\n"); + syslinux_dump_memmap(stdout, amap); +#endif + + if (syslinux_memmap_largest(amap, SMT_FREE, &lstart, &llen)) + goto bail; /* NO free memory?! */ + + if (llen < stack_frame_size + MIN_STACK + 16) + goto bail; /* Insufficient memory */ + + /* Initial stack pointer address */ + stack_pointer = (lstart + llen - stack_frame_size) & ~15; + + dprintf("Stack frame at 0x%08x len 0x%08x\n", + stack_pointer, stack_frame_size); + + /* Create the stack frame. sfp is the pointer in current memory for + the next argument string, sfa is the address in its final resting place. + spp is the pointer into the argument array in current memory. */ + spp = (uint32_t *) stack_frame; + sfp = stack_frame + argc * sizeof(char *) + 5 * sizeof(long); + sfa = stack_pointer + argc * sizeof(char *) + 5 * sizeof(long); + + *spp++ = argc; + for (argp = argv; *argp; argp++) { + int bytes = strlen(*argp) + 1; /* Including final null */ + *spp++ = sfa; + memcpy(sfp, *argp, bytes); + sfp += bytes; + sfa += bytes; + } + /* Zero fields are aready taken care of by calloc() */ + + /* ... and we'll want to move it into the right place... */ +#if DEBUG + if (syslinux_memmap_type(amap, stack_pointer, stack_frame_size) + != SMT_FREE) { + dprintf("Stack frame area not free (how did that happen?)!\n"); + goto bail; /* Memory region unavailable */ + } +#endif + + if (syslinux_add_memmap(&amap, stack_pointer, stack_frame_size, SMT_ALLOC)) + goto bail; + + if (syslinux_add_movelist(&ml, stack_pointer, (addr_t) stack_frame, + stack_frame_size)) + goto bail; + + memset(®s, 0, sizeof regs); + regs.eip = where; + regs.esp = stack_pointer; + +#if DEBUG + dprintf("Final memory map:\n"); + syslinux_dump_memmap(stdout, mmap); + + dprintf("Final available map:\n"); + syslinux_dump_memmap(stdout, amap); + + dprintf("Movelist:\n"); + syslinux_dump_movelist(stdout, ml); +#endif + + /* This should not return... */ + fputs("Booting...\n", stdout); + syslinux_shuffle_boot_pm(ml, mmap, 0, ®s); + +bail: + if (stack_frame) + free(stack_frame); + syslinux_free_memmap(amap); + syslinux_free_memmap(mmap); + syslinux_free_movelist(ml); + + return -1; +} + +int main(int argc, char *argv[]) +{ + void *data; + size_t data_len; + addr_t where; + + openconsole(&dev_null_r, &dev_stdcon_w); + + if (argc < 3) { + error("Usage: pmload.c32 bin_file address arguments...\n"); + return 1; + } + + where = strtoul(argv[2], NULL, 0); + + if (loadfile(argv[1], &data, &data_len)) { + error("Unable to load file\n"); + return 1; + } + + boot_raw(data, data_len, where, &argv[1]); + error("Failed to boot, probably insufficient memory\n"); + return 1; +} diff --git a/contrib/syslinux-4.02/com32/modules/pwd.c b/contrib/syslinux-4.02/com32/modules/pwd.c new file mode 100644 index 0000000..880327d --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/pwd.c @@ -0,0 +1,51 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2010 Gene Cumm - 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. + * + * ----------------------------------------------------------------------- */ + +/* + * Display present (current) working directory + */ + +#include <errno.h> +#include <stdio.h> +#include <console.h> +#include <unistd.h> +#include <dirent.h> + +/* Size of path buffer string */ +#ifndef PATH_MAX +# ifdef NAME_MAX +# define PATH_MAX NAME_MAX +# elif FILENAME_MAX +# define PATH_MAX FILENAME_MAX +# else +# define PATH_MAX 256 +# endif /* NAME_MAX */ +#endif /* PATH_MAX */ + +int main(void) +{ + int rv = 0; + char pwd[PATH_MAX], *pwdptr; + + openconsole(&dev_rawcon_r, &dev_stdcon_w); + pwdptr = getcwd(pwd, PATH_MAX); + if (pwdptr) { + if (pwd[0] != 0) + puts(pwd); + else + puts("."); + } else { + rv = errno; + puts("ERROR: getcwd() returned NULL"); + } + return rv; +} diff --git a/contrib/syslinux-4.02/com32/modules/reboot.c b/contrib/syslinux-4.02/com32/modules/reboot.c new file mode 100644 index 0000000..a6d5647 --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/reboot.c @@ -0,0 +1,15 @@ +#include <syslinux/reboot.h> +#include <string.h> + +int main(int argc, char *argv[]) +{ + int warm = 0; + int i; + + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-w") || !strcmp(argv[i], "--warm")) + warm = 1; + } + + syslinux_reboot(warm); +} diff --git a/contrib/syslinux-4.02/com32/modules/sanboot.c b/contrib/syslinux-4.02/com32/modules/sanboot.c new file mode 100644 index 0000000..46df6bc --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/sanboot.c @@ -0,0 +1,89 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2008 H. Peter Anvin - All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * sanboot.c + * + * Invoke the gPXE "sanboot" command, if available. + */ + +#include <alloca.h> +#include <inttypes.h> +#include <stdio.h> +#include <console.h> +#include <com32.h> +#include <string.h> +#include <sys/gpxe.h> + +struct segoff16 { + uint16_t offs, seg; +}; + +struct s_PXENV_FILE_EXEC { + uint16_t Status; + struct segoff16 Command; +}; + +static void sanboot(const char **args) +{ + char *q; + struct s_PXENV_FILE_EXEC *fx; + com32sys_t reg; + + memset(®, 0, sizeof reg); + + fx = __com32.cs_bounce; + q = (char *)(fx + 1); + + fx->Status = 1; + fx->Command.offs = OFFS(q); + fx->Command.seg = SEG(q); + + q = stpcpy(q, "sanboot"); + + while (*args) { + *q++ = ' '; + q = stpcpy(q, *args); + args++; + } + + memset(®, 0, sizeof reg); + reg.eax.w[0] = 0x0009; + reg.ebx.w[0] = 0x00e5; /* PXENV_FILE_EXEC */ + reg.edi.w[0] = OFFS(fx); + reg.es = SEG(fx); + + __intcall(0x22, ®, ®); + + /* This should not return... */ +} + +int main(int argc, const char *argv[]) +{ + openconsole(&dev_null_r, &dev_stdcon_w); + + if (argc < 2) { + printf("Usage: sanboot rootpath\n"); + return 1; + } + + if (!is_gpxe()) { + printf("sanboot: gPXE API not detected\n"); + return 1; + } + + sanboot(argv + 1); + + /* sanboot() should not return... */ + printf("SAN boot failed.\n"); + return 1; +} diff --git a/contrib/syslinux-4.02/com32/modules/sdi.c b/contrib/syslinux-4.02/com32/modules/sdi.c new file mode 100644 index 0000000..69841d2 --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/sdi.c @@ -0,0 +1,187 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2008 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * sdi.c + * + * Loader for the Microsoft System Deployment Image (SDI) format. + * Based on a historical patch by Remi Lefevre. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <inttypes.h> +#include <string.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <minmax.h> +#include <sys/stat.h> +#include <console.h> +#include <dprintf.h> + +#include <syslinux/loadfile.h> +#include <syslinux/movebits.h> +#include <syslinux/bootrm.h> + +typedef uint8_t guid_t[16]; + +struct SDIHeader { + uint32_t Signature; + char Version[4]; + uint64_t MDBtype; + uint64_t BootCodeOffset; + uint64_t BootCodeSize; + uint64_t VendorID; + uint64_t DeviceID; + guid_t DeviceModel; + uint64_t DeviceRole; + uint64_t Reserved1; + guid_t RuntimeGUID; + uint64_t RuntimeOEMrev; + uint64_t Reserved2; + uint64_t PageAlignment; /* BLOB alignment value in pages */ + uint64_t Reserved3[48]; + uint64_t Checksum; +}; + +#define SDI_LOAD_ADDR (16 << 20) /* 16 MB */ +#define SDI_SIGNATURE ('$' + ('S' << 8) + ('D' << 16) + ('I' << 24)) + +static inline void error(const char *msg) +{ + fputs(msg, stderr); +} + +static int boot_sdi(void *ptr, size_t len) +{ + const struct SDIHeader *hdr = ptr; + struct syslinux_memmap *mmap = NULL, *amap = NULL; + struct syslinux_rm_regs regs; + struct syslinux_movelist *ml = NULL; + + /* **** Basic sanity checking **** */ + if (hdr->Signature != SDI_SIGNATURE) { + fputs("No $SDI signature in file\n", stdout); + goto bail; + } + if (memcmp(hdr->Version, "0001", 4)) { + int i; + fputs("Warning: unknown SDI version: ", stdout); + for (i = 0; i < 4; i++) + putchar(hdr->Version[i]); + putchar('\n'); + /* Then try anyway... */ + } + + /* **** Setup **** */ + mmap = syslinux_memory_map(); + amap = syslinux_dup_memmap(mmap); + if (!mmap || !amap) + goto bail; + + /* **** Map the BOOT BLOB to 0x7c00 **** */ + if (!hdr->BootCodeOffset) { + fputs("No BOOT BLOB in image\n", stdout); + goto bail; + } + if (!hdr->BootCodeSize) { + fputs("BOOT BLOB is empty\n", stdout); + goto bail; + } + if (len < hdr->BootCodeOffset + hdr->BootCodeSize) { + fputs("BOOT BLOB extends beyond file\n", stdout); + goto bail; + } + + if (syslinux_memmap_type(amap, 0x7c00, hdr->BootCodeSize) != SMT_FREE) { + fputs("BOOT BLOB too large for memory\n", stdout); + goto bail; + } + if (syslinux_add_memmap(&amap, 0x7c00, hdr->BootCodeSize, SMT_ALLOC)) + goto bail; + if (syslinux_add_movelist(&ml, 0x7c00, (addr_t) ptr + hdr->BootCodeOffset, + hdr->BootCodeSize)) + goto bail; + + /* **** Map the entire image to SDI_LOAD_ADDR **** */ + if (syslinux_memmap_type(amap, SDI_LOAD_ADDR, len) != SMT_FREE) { + fputs("Image too large for memory\n", stdout); + goto bail; + } + if (syslinux_add_memmap(&amap, SDI_LOAD_ADDR, len, SMT_ALLOC)) + goto bail; + if (syslinux_add_movelist(&ml, SDI_LOAD_ADDR, (addr_t) ptr, len)) + goto bail; + + /* **** Set up registers **** */ + memset(®s, 0, sizeof regs); + regs.ip = 0x7c00; + regs.esp.l = 0x7c00; + regs.edx.l = SDI_LOAD_ADDR | 0x41; + + fputs("Booting...\n", stdout); + syslinux_shuffle_boot_rm(ml, mmap, 0, ®s); + +bail: + syslinux_free_memmap(amap); + syslinux_free_memmap(mmap); + syslinux_free_movelist(ml); + return -1; +} + +/* + * Check that the sum of all bytes from first 512 bytes (SDI header) + * is 0 modulo 256. + */ +int has_valid_header(unsigned char *header) +{ + unsigned char checksum; + unsigned int i; + + checksum = 0; + for (i = 0; i < sizeof(struct SDIHeader); i++) + checksum += header[i]; + return (!checksum); +} + +int main(int argc, char *argv[]) +{ + void *data; + size_t data_len; + + openconsole(&dev_null_r, &dev_stdcon_w); + + if (argc != 2) { + error("Usage: sdi.c32 sdi_file\n"); + return 1; + } + + fputs("Loading ", stdout); + fputs(argv[1], stdout); + fputs("... ", stdout); + if (zloadfile(argv[1], &data, &data_len)) { + error("failed!\n"); + return 1; + } + fputs("ok\n", stdout); + + if (!has_valid_header(data)) { + error("SDI header is corrupted\n"); + return 1; + } + + boot_sdi(data, data_len); + error("Invalid SDI file or insufficient memory\n"); + return 1; +} diff --git a/contrib/syslinux-4.02/com32/modules/stubs/copydown.asm b/contrib/syslinux-4.02/com32/modules/stubs/copydown.asm new file mode 100644 index 0000000..e981348 --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/stubs/copydown.asm @@ -0,0 +1,11 @@ + bits 16 + rep movsd + mov si,0 + mov di,0 + mov ds,si + mov es,di + mov ecx,0 + mov esi,0 + mov edi,0 + jmp 0:0 + align 16 diff --git a/contrib/syslinux-4.02/com32/modules/stubs/swapstub.asm b/contrib/syslinux-4.02/com32/modules/stubs/swapstub.asm new file mode 100644 index 0000000..b670ce4 --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/stubs/swapstub.asm @@ -0,0 +1,33 @@ + bits 16 +swap: + push bx + movzx bx,dl + mov dl,[cs:bx+(table-$$)] + pop bx +.jmp: jmp 0:0 + nop + nop +install: + ;; DS = CS, ES = 0 + mov edi,[es:si+4*0x13] + mov [swap.jmp+1],edi + mov di,[es:0x413] + dec di + mov [es:0x413],di + shl edi,16+6 + mov [es:si+4*0x13],edi + shr edi,16 + mov es,di + xor di,di + rep movsd + mov si,0 + mov di,0 + mov ds,si + mov es,di + mov ecx,0 + mov esi,0 + mov edi,0 + jmp 0:0 + + align 16 +table: diff --git a/contrib/syslinux-4.02/com32/modules/vesainfo.c b/contrib/syslinux-4.02/com32/modules/vesainfo.c new file mode 100644 index 0000000..00181e4 --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/vesainfo.c @@ -0,0 +1,82 @@ +/* + * vesainfo.c + * + * Dump information about what VESA graphics modes are supported. + */ + +#include <string.h> +#include <stdio.h> +#include <console.h> +#include <com32.h> +#include <inttypes.h> +#include "../lib/sys/vesa/vesa.h" + +/* Wait for a keypress */ +static void wait_key(void) +{ + char ch; + while (fread(&ch, 1, 1, stdin) == 0) ; +} + +static void print_modes(void) +{ + static com32sys_t rm; + struct vesa_general_info *gi; + struct vesa_mode_info *mi; + uint16_t mode, *mode_ptr; + int lines; + + /* Allocate space in the bounce buffer for these structures */ + gi = &((struct vesa_info *)__com32.cs_bounce)->gi; + mi = &((struct vesa_info *)__com32.cs_bounce)->mi; + + gi->signature = VBE2_MAGIC; /* Get VBE2 extended data */ + rm.eax.w[0] = 0x4F00; /* Get SVGA general information */ + rm.edi.w[0] = OFFS(gi); + rm.es = SEG(gi); + __intcall(0x10, &rm, &rm); + + if (rm.eax.w[0] != 0x004F) { + printf("No VESA BIOS detected\n"); + return; + } else if (gi->signature != VESA_MAGIC) { + printf("VESA information structure has bad magic, trying anyway...\n"); + } + + printf("VBE version %d.%d\n" + "Mode attrib h_res v_res bpp layout rpos gpos bpos\n", + (gi->version >> 8) & 0xff, gi->version & 0xff); + + lines = 1; + + mode_ptr = GET_PTR(gi->video_mode_ptr); + + while ((mode = *mode_ptr++) != 0xFFFF) { + if (++lines >= 23) { + wait_key(); + lines = 0; + } + + rm.eax.w[0] = 0x4F01; /* Get SVGA mode information */ + rm.ecx.w[0] = mode; + rm.edi.w[0] = OFFS(mi); + rm.es = SEG(mi); + __intcall(0x10, &rm, &rm); + + /* Must be a supported mode */ + if (rm.eax.w[0] != 0x004f) + continue; + + printf("0x%04x 0x%04x %5u %5u %3u %6u %4u %4u %4u\n", + mode, mi->mode_attr, mi->h_res, mi->v_res, mi->bpp, + mi->memory_layout, mi->rpos, mi->gpos, mi->bpos); + } +} + +int main(void) +{ + openconsole(&dev_rawcon_r, &dev_stdcon_w); + + print_modes(); + return 0; +} diff --git a/contrib/syslinux-4.02/com32/modules/vpdtest.c b/contrib/syslinux-4.02/com32/modules/vpdtest.c new file mode 100644 index 0000000..1d50c68 --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/vpdtest.c @@ -0,0 +1,69 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- +*/ + +/* + * vpdtest.c + * + * VPD demo program using libcom32 + */ + +#include <string.h> +#include <stdio.h> +#include <console.h> +#include "vpd/vpd.h" + +int main(void) +{ + s_vpd vpd; + openconsole(&dev_stdcon_r, &dev_stdcon_w); + + if (vpd_decode(&vpd) == -ENOVPDTABLE) { + printf("No VPD Structure found\n"); + return -1; + } else { + printf("VPD present at address : 0x%s\n", vpd.base_address); + } + if (strlen(vpd.bios_build_id) > 0) + printf("Bios Build ID : %s\n", vpd.bios_build_id); + if (strlen(vpd.bios_release_date) > 0) + printf("Bios Release Date : %s\n", vpd.bios_release_date); + if (strlen(vpd.bios_version) > 0) + printf("Bios Version : %s\n", vpd.bios_version); + if (strlen(vpd.default_flash_filename) > 0) + printf("Default Flash Filename : %s\n", + vpd.default_flash_filename); + if (strlen(vpd.box_serial_number) > 0) + printf("Box Serial Number : %s\n", vpd.box_serial_number); + if (strlen(vpd.motherboard_serial_number) > 0) + printf("Motherboard Serial Number : %s\n", + vpd.motherboard_serial_number); + if (strlen(vpd.machine_type_model) > 0) + printf("Machine Type/Model : %s\n", vpd.machine_type_model); + + return 0; +} diff --git a/contrib/syslinux-4.02/com32/modules/whichsys.c b/contrib/syslinux-4.02/com32/modules/whichsys.c new file mode 100644 index 0000000..af133f2 --- /dev/null +++ b/contrib/syslinux-4.02/com32/modules/whichsys.c @@ -0,0 +1,128 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2010 Gert Hulselmans - All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * whichsys.c + * + * Detemine which command to execute, based on the Syslinux bootloader variant + * from which you run it. + * + * Usage: whichsys.c32 [-iso- command] [-pxe- command] [-sys- command] + * Examples: whichsys.c32 -iso- chain.c32 hd0 -sys- chain.c32 hd1 swap + * whichsys.c32 -iso- config iso.cfg -pxe- config pxe.cfg + * + */ + +#include <stdio.h> +#include <alloca.h> +#include <console.h> +#include <string.h> +#include <syslinux/boot.h> +#include "syslinux/config.h" + + +static struct syslinux_parameter { + char **arg[1]; + bool option; +} isolinux, pxelinux, syslinux; + +/* XXX: this really should be librarized */ +static void boot_args(char **args) +{ + int len = 0, a = 0; + char **pp; + const char *p; + char c, *q, *str; + + for (pp = args; *pp; pp++) + len += strlen(*pp) + 1; + + q = str = alloca(len); + for (pp = args; *pp; pp++) { + p = *pp; + while ((c = *p++)) + *q++ = c; + *q++ = ' '; + a = 1; + } + q -= a; + *q = '\0'; + + if (!str[0]) + syslinux_run_default(); + else + syslinux_run_command(str); +} + +static void usage(void) +{ + static const char usage[] = "\ +Usage: whichsys.c32 [-iso- command] [-pxe- command] [-sys- command]\n\ +Examples: whichsys.c32 -iso- chain.c32 hd0 -sys- chain.c32 hd1 swap\n\ + whichsys.c32 -iso- config iso.cfg -pxe- config pxe.cfg\n"; + fprintf(stderr, usage); +} + +int main(int argc, char *argv[]) +{ + const union syslinux_derivative_info *sdi; + + int arg = 0; + + openconsole(&dev_null_r, &dev_stdcon_w); + + /* If no argument got passed, let's show the usage */ + if (argc == 1) { + usage(); + return 0; + } + + arg++; + + while (arg < argc) { + if (!strcmp(argv[arg], "-iso-")) { + argv[arg] = NULL; + isolinux.arg[0] = &argv[arg + 1]; + isolinux.option = true; + } + if (!strcmp(argv[arg], "-pxe-")) { + argv[arg] = NULL; + pxelinux.arg[0] = &argv[arg + 1]; + pxelinux.option = true; + } + if (!strcmp(argv[arg], "-sys-")) { + argv[arg] = NULL; + syslinux.arg[0] = &argv[arg + 1]; + syslinux.option = true; + } + arg++; + } + + sdi = syslinux_derivative_info(); + + switch (sdi->c.filesystem) { + case SYSLINUX_FS_ISOLINUX: + isolinux.option ? boot_args(isolinux.arg[0]) : fprintf(stderr, "No command specified for ISOLINUX.\n\n"); usage(); + break; + case SYSLINUX_FS_PXELINUX: + pxelinux.option ? boot_args(pxelinux.arg[0]) : fprintf(stderr, "No command specified for PXELINUX.\n\n"); usage(); + break; + case SYSLINUX_FS_SYSLINUX: + syslinux.option ? boot_args(syslinux.arg[0]) : fprintf(stderr, "No command specified for SYSLINUX.\n\n"); usage(); + break; + case SYSLINUX_FS_UNKNOWN: + default: + fprintf(stderr, "Unknown Syslinux filesystem\n\n"); + } + + return -1; +} diff --git a/contrib/syslinux-4.02/com32/rosh/MCONFIG b/contrib/syslinux-4.02/com32/rosh/MCONFIG new file mode 100644 index 0000000..25c4139 --- /dev/null +++ b/contrib/syslinux-4.02/com32/rosh/MCONFIG @@ -0,0 +1,27 @@ +## -*- makefile -*- ------------------------------------------------------- +## +## Copyright 2008 H. Peter Anvin - All Rights Reserved +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, +## Boston MA 02110-1301, USA; either version 2 of the License, or +## (at your option) any later version; incorporated herein by reference. +## +## ----------------------------------------------------------------------- + +## +## COM32 GRC configurables +## + +## Include the COM32 common configurables +include ../MCONFIG + +# CFLAGS = $(GCCOPT) $(GCCWARN) -march=i386 \ +# -fomit-frame-pointer -D__COM32__ \ +# -nostdinc -iwithprefix include \ +# -I$(com32)/libutil/include -I$(com32)/include +# -g3 -dD + +# LNXCFLAGS = -I$(com32)/libutil/include $(GCCWARN) -O -g3 -D_GNU_SOURCE -dD +# -U__GNUC__ diff --git a/contrib/syslinux-4.02/com32/rosh/Makefile b/contrib/syslinux-4.02/com32/rosh/Makefile new file mode 100644 index 0000000..7bf5059 --- /dev/null +++ b/contrib/syslinux-4.02/com32/rosh/Makefile @@ -0,0 +1,38 @@ +## ----------------------------------------------------------------------- +## +## 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 MCONFIG + +rosh.o: rosh.h + +rosh.lo: rosh.h + +all: rosh.c32 + +tidy dist: + rm -f *.o *.lo *.a *.lst *.elf .*.d *.tmp + +clean: tidy + rm -f *.lnx + +spotless: clean + rm -f *.lss *.c32 *.com + rm -f *~ \#* + +install: + +-include .*.d diff --git a/contrib/syslinux-4.02/com32/rosh/rosh.c b/contrib/syslinux-4.02/com32/rosh/rosh.c new file mode 100644 index 0000000..bf1176f --- /dev/null +++ b/contrib/syslinux-4.02/com32/rosh/rosh.c @@ -0,0 +1,1178 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2008-2010 Gene Cumm - 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. + * + * ----------------------------------------------------------------------- */ + +/* + * rosh.c + * + * Read-Only shell; Simple shell system designed for SYSLINUX-derivitives. + * Provides minimal commands utilizing the console via stdout/stderr as the + * sole output devices. Designed to compile for Linux for testing/debugging. + */ + +/* + * ToDos: + * rosh_ls(): sorted; then multiple columns + */ + +/*#define DO_DEBUG 1 +//*/ +/* Uncomment the above line for debugging output; Comment to remove */ +/*#define DO_DEBUG2 1 +//*/ +/* Uncomment the above line for super-debugging output; Must have regular + * debugging enabled; Comment to remove. + */ +#include "rosh.h" + +#define APP_LONGNAME "Read-Only Shell" +#define APP_NAME "rosh" +#define APP_AUTHOR "Gene Cumm" +#define APP_YEAR "2010" +#define APP_VER "beta-b062" + +void rosh_version(void) +{ + printf("%s v %s; (c) %s %s.\n", APP_LONGNAME, APP_VER, APP_YEAR, + APP_AUTHOR); +} + +void print_beta(void) +{ + puts(rosh_beta_str); + ROSH_DEBUG("DO_DEBUG active\n"); + ROSH_DEBUG2("DO_DEBUG2 active\n"); +} + +/* Search a string for first non-space (' ') character, starting at ipos + * istr input string to parse + * ipos input position to start at + */ +int rosh_search_nonsp(const char *istr, const int ipos) +{ + int curpos; + char c; + + curpos = ipos; + c = istr[curpos]; + while (c && isspace(c)) + c = istr[++curpos]; + return curpos; +} + +/* Search a string for space (' '), returning the position of the next space + * or the '\0' at end of string + * istr input string to parse + * ipos input position to start at + */ +int rosh_search_sp(const char *istr, const int ipos) +{ + int curpos; + char c; + + curpos = ipos; + c = istr[curpos]; + while (c && !(isspace(c))) + c = istr[++curpos]; + return curpos; +} + +/* Parse a string for the first non-space string, returning the end position + * from src + * dest string to contain the first non-space string + * src string to parse + * ipos Position to start in src + */ +int rosh_parse_sp_1(char *dest, const char *src, const int ipos) +{ + int bpos, epos; /* beginning and ending position of source string + to copy to destination string */ + + bpos = 0; + epos = 0; +/* //HERE-error condition checking */ + bpos = rosh_search_nonsp(src, ipos); + epos = rosh_search_sp(src, bpos); + if (epos > bpos) { + memcpy(dest, src + bpos, epos - bpos); + if (dest[epos - bpos] != 0) + dest[epos - bpos] = 0; + } else { + epos = strlen(src); + dest[0] = 0; + } + return epos; +} + +/* Display help + * type Help type + * cmdstr Command string + */ +void rosh_help(int type, const char *cmdstr) +{ + const char *istr; + istr = cmdstr; + switch (type) { + case 2: + istr += rosh_search_nonsp(cmdstr, rosh_search_sp(cmdstr, 0)); + if ((cmdstr == NULL) || (strcmp(istr, "") == 0)) { + rosh_version(); + puts(rosh_help_str2); + } else { + switch (istr[0]) { + case 'l': + puts(rosh_help_ls_str); + break; + default: + printf(rosh_help_str_adv, istr); + } + } + break; + case 1: + default: + rosh_version(); + puts(rosh_help_str1); + } +} + +/* Handle most/all errors + * ierrno Input Error number + * cmdstr Command being executed to cause error + * filestr File/parameter causing error + */ +void rosh_error(const int ierrno, const char *cmdstr, const char *filestr) +{ + printf("--ERROR: %s '%s': ", cmdstr, filestr); + switch (ierrno) { + case 0: + puts("NO ERROR"); + break; + case ENOENT: + puts("not found"); + /* SYSLinux-3.72 COM32 API returns this for a + directory or empty file */ + ROSH_COM32(" (COM32) could be a directory or empty file\n"); + break; + case EIO: + puts("I/O Error"); + break; + case EBADF: + puts("Bad File Descriptor"); + break; + case EACCES: + puts("Access DENIED"); + break; + case ENOTDIR: + puts("not a directory"); + ROSH_COM32(" (COM32) could be directory\n"); + break; + case EISDIR: + puts("IS a directory"); + break; + case ENOSYS: + puts("not implemented"); + break; + default: + printf("returns error; errno=%d\n", ierrno); + } +} /* rosh_error */ + +/* Concatenate command line arguments into one string + * cmdstr Output command string + * argc Argument Count + * argv Argument Values + * barg Beginning Argument + */ +int rosh_argcat(char *cmdstr, const int argc, char *argv[], const int barg) +{ + int i, arglen, curpos; /* index, argument length, current position + in cmdstr */ + curpos = 0; + cmdstr[0] = '\0'; /* Nullify string just to be sure */ + for (i = barg; i < argc; i++) { + arglen = strlen(argv[i]); + /* Theoretically, this should never be met in SYSLINUX */ + if ((curpos + arglen) > (ROSH_CMD_SZ - 1)) + arglen = (ROSH_CMD_SZ - 1) - curpos; + memcpy(cmdstr + curpos, argv[i], arglen); + curpos += arglen; + if (curpos >= (ROSH_CMD_SZ - 1)) { + /* Hopefully, curpos should not be greater than + (ROSH_CMD_SZ - 1) */ + /* Still need a '\0' at the last character */ + cmdstr[(ROSH_CMD_SZ - 1)] = 0; + break; /* Escape out of the for() loop; + We can no longer process anything more */ + } else { + cmdstr[curpos] = ' '; + curpos += 1; + cmdstr[curpos] = 0; + } + } + /* If there's a ' ' at the end, remove it. This is normal unless + the maximum length is met/exceeded. */ + if (cmdstr[curpos - 1] == ' ') + cmdstr[--curpos] = 0; + return curpos; +} /* rosh_argcat */ + +/* + * Prints a lot of the data in a struct termios + */ +/* +void rosh_print_tc(struct termios *tio) +{ + printf(" -- termios: "); + printf(".c_iflag=%04X ", tio->c_iflag); + printf(".c_oflag=%04X ", tio->c_oflag); + printf(".c_cflag=%04X ", tio->c_cflag); + printf(".c_lflag=%04X ", tio->c_lflag); + printf(".c_cc[VTIME]='%d' ", tio->c_cc[VTIME]); + printf(".c_cc[VMIN]='%d'", tio->c_cc[VMIN]); + printf("\n"); +} +*/ + +/* + * Attempts to get a single key from the console + * returns key pressed + */ +int rosh_getkey(void) +{ + int inc; + + inc = KEY_NONE; + while (inc == KEY_NONE) + inc = get_key(stdin, 6000); + return inc; +} /* rosh_getkey */ + +/* + * Qualifies a filename relative to the working directory + * filestr Filename to qualify + * pwdstr working directory + * returns qualified file name string + */ +void rosh_qualify_filestr(char *filestr, const char *ifilstr, + const char *pwdstr) +{ + int filepos = 0; + if ((filestr) && (pwdstr) && (ifilstr)) { + if (ifilstr[0] != SEP) { + strcpy(filestr, pwdstr); + filepos = strlen(pwdstr); + if (filestr[filepos - 1] != SEP) + filestr[filepos++] = SEP; + } + strcpy(filestr + filepos, ifilstr); + ROSH_DEBUG("--'%s'\n", filestr); + } +} + +/* Concatenate multiple files to stdout + * cmdstr command string to process + */ +void rosh_cat(const char *cmdstr) +{ + FILE *f; + char filestr[ROSH_PATH_SZ]; + char buf[ROSH_BUF_SZ]; + int numrd; + int cmdpos; + + ROSH_DEBUG("CMD: '%s'\n", cmdstr); + /* Initialization */ + filestr[0] = 0; + cmdpos = 0; + /* skip the first word */ + cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); + cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); + while (strlen(filestr) > 0) { + printf("--File = '%s'\n", filestr); + f = fopen(filestr, "r"); + if (f != NULL) { + numrd = fread(buf, 1, ROSH_BUF_SZ, f); + while (numrd > 0) { + fwrite(buf, 1, numrd, stdout); + numrd = fread(buf, 1, ROSH_BUF_SZ, f); + } + fclose(f); + } else { + rosh_error(errno, "cat", filestr); + errno = 0; + } + cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); + } +} /* rosh_cat */ + +/* Change PWD (Present Working Directory) + * cmdstr command string to process + * ipwdstr Initial PWD + */ +void rosh_cd(const char *cmdstr, const char *ipwdstr) +{ + int rv; + char filestr[ROSH_PATH_SZ]; + int cmdpos; + ROSH_DEBUG("CMD: '%s'\n", cmdstr); + /* Initialization */ + filestr[0] = 0; + cmdpos = 0; + rv = 0; + /* skip the first word */ + cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); + cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); + if (strlen(filestr) != 0) + rv = chdir(filestr); + else + rv = chdir(ipwdstr); + if (rv != 0) { + rosh_error(errno, "cd", filestr); + errno = 0; + } else { +#ifdef DO_DEBUG + if (getcwd(filestr, ROSH_PATH_SZ)) + ROSH_DEBUG(" %s\n", filestr); +#endif /* DO_DEBUG */ + } +} /* rosh_cd */ + +/* Print the syslinux config file name + */ +void rosh_cfg(void) +{ + printf("CFG: '%s'\n", syslinux_config_file()); +} /* rosh_cfg */ + +/* Process optstr to optarr + * optstr option string to process + * optarr option array to populate + */ +void rosh_ls_arg_opt(const char *optstr, int *optarr) +{ + char *cpos; + cpos = strchr(optstr, 'l'); + if (cpos) { + optarr[0] = cpos - optstr; + } else { + optarr[0] = -1; + } + cpos = strchr(optstr, 'F'); + if (cpos) { + optarr[1] = cpos - optstr; + } else { + optarr[1] = -1; + } + cpos = strchr(optstr, 'i'); + if (cpos) { + optarr[2] = cpos - optstr; + } else { + optarr[2] = -1; + } +} /* rosh_ls_arg_opt */ + +/* Retrieve the size of a file argument + * filestr directory name of directory entry + * de directory entry + */ +int rosh_ls_de_size(const char *filestr, struct dirent *de) +{ + int de_size; + char filestr2[ROSH_PATH_SZ]; + int fd2, file2pos; + struct stat fdstat; + int status; + + filestr2[0] = 0; + file2pos = -1; + if (filestr) { + file2pos = strlen(filestr); + memcpy(filestr2, filestr, file2pos); + filestr2[file2pos] = '/'; + } + strcpy(filestr2 + file2pos + 1, de->d_name); + fd2 = open(filestr2, O_RDONLY); + status = fstat(fd2, &fdstat); + fd2 = close(fd2); + de_size = (int)fdstat.st_size; + return de_size; +} /* rosh_ls_de_size */ + +/* Retrieve the size and mode of a file + * filestr directory name of directory entry + * de directory entry + */ +int rosh_ls_de_size_mode(struct dirent *de, mode_t * st_mode) +{ + int de_size; +// char filestr2[ROSH_PATH_SZ]; +// int file2pos; + struct stat fdstat; + int status; + +/* filestr2[0] = 0; + file2pos = -1;*/ + fdstat.st_size = 0; + fdstat.st_mode = 0; +/* if (filestr) { + file2pos = strlen(filestr); + memcpy(filestr2, filestr, file2pos); + filestr2[file2pos] = '/'; + } + strcpy(filestr2 + file2pos + 1, de->d_name);*/ + status = stat(de->d_name, &fdstat); + ROSH_DEBUG2("\t--stat()=%d\terr=%d\n", status, errno); + if (errno) { + rosh_error(errno, "ls:szmd.stat", de->d_name); + errno = 0; + } + de_size = (int)fdstat.st_size; + *st_mode = fdstat.st_mode; + return de_size; +} /* rosh_ls_de_size_mode */ + +/* Returns the Inode number if fdstat contains it + * fdstat struct to extract inode from if not COM32, for now + */ +long rosh_ls_d_ino(struct stat *fdstat) +{ + long de_ino; +#ifdef __COM32__ + if (fdstat) + de_ino = -1; + else + de_ino = 0; +#else /* __COM32__ */ + de_ino = fdstat->st_ino; +#endif /* __COM32__ */ + return de_ino; +} + +/* Convert a d_type to a single char in human readable format + * d_type d_type to convert + * returns human readable single character; a space if other + */ +char rosh_d_type2char_human(unsigned char d_type) +{ + char ret; + switch (d_type) { + case DT_UNKNOWN: + ret = 'U'; + break; /* Unknown */ + case DT_FIFO: + ret = 'F'; + break; /* FIFO */ + case DT_CHR: + ret = 'C'; + break; /* Char Dev */ + case DT_DIR: + ret = 'D'; + break; /* Directory */ + case DT_BLK: + ret = 'B'; + break; /* Block Dev */ + case DT_REG: + ret = 'R'; + break; /* Regular File */ + case DT_LNK: + ret = 'L'; + break; /* Link, Symbolic */ + case DT_SOCK: + ret = 'S'; + break; /* Socket */ + case DT_WHT: + ret = 'W'; + break; /* UnionFS Whiteout */ + default: + ret = ' '; + } + return ret; +} /* rosh_d_type2char_human */ + +/* Convert a d_type to a single char by ls's prefix standards for -l + * d_type d_type to convert + * returns ls style single character; a space if other + */ +char rosh_d_type2char_lspre(unsigned char d_type) +{ + char ret; + switch (d_type) { + case DT_FIFO: + ret = 'p'; + break; + case DT_CHR: + ret = 'c'; + break; + case DT_DIR: + ret = 'd'; + break; + case DT_BLK: + ret = 'b'; + break; + case DT_REG: + ret = '-'; + break; + case DT_LNK: + ret = 'l'; + break; + case DT_SOCK: + ret = 's'; + break; + default: + ret = '?'; + } + return ret; +} /* rosh_d_type2char_lspre */ + +/* Convert a d_type to a single char by ls's classify (-F) suffix standards + * d_type d_type to convert + * returns ls style single character; a space if other + */ +char rosh_d_type2char_lssuf(unsigned char d_type) +{ + char ret; + switch (d_type) { + case DT_FIFO: + ret = '|'; + break; + case DT_DIR: + ret = '/'; + break; + case DT_LNK: + ret = '@'; + break; + case DT_SOCK: + ret = '='; + break; + default: + ret = ' '; + } + return ret; +} /* rosh_d_type2char_lssuf */ + +/* Converts data in the "other" place of st_mode to a ls-style string + * st_mode Mode in other to analyze + * st_mode_str string to hold converted string + */ +void rosh_st_mode_am2str(mode_t st_mode, char *st_mode_str) +{ + st_mode_str[0] = ((st_mode & S_IROTH) ? 'r' : '-'); + st_mode_str[1] = ((st_mode & S_IWOTH) ? 'w' : '-'); + st_mode_str[2] = ((st_mode & S_IXOTH) ? 'x' : '-'); +} + +/* Converts st_mode to an ls-style string + * st_mode mode to convert + * st_mode_str string to hold converted string + */ +void rosh_st_mode2str(mode_t st_mode, char *st_mode_str) +{ + st_mode_str[0] = rosh_d_type2char_lspre(IFTODT(st_mode)); + rosh_st_mode_am2str((st_mode & S_IRWXU) >> 6, st_mode_str + 1); + rosh_st_mode_am2str((st_mode & S_IRWXG) >> 3, st_mode_str + 4); + rosh_st_mode_am2str(st_mode & S_IRWXO, st_mode_str + 7); + st_mode_str[10] = 0; +} /* rosh_st_mode2str */ + +/* Output a single entry + * filestr directory name to list + * de directory entry + * optarr Array of options + */ +void rosh_ls_arg_dir_de(struct dirent *de, const int *optarr) +{ + int de_size; + mode_t st_mode; + char st_mode_str[11]; + st_mode = 0; + if (optarr[2] > -1) + printf("%10d ", (int)de->d_ino); + if (optarr[0] > -1) { + de_size = rosh_ls_de_size_mode(de, &st_mode); + rosh_st_mode2str(st_mode, st_mode_str); + ROSH_DEBUG2("%04X ", st_mode); + printf("%s %10d ", st_mode_str, de_size); + } + ROSH_DEBUG("'"); + printf("%s", de->d_name); + ROSH_DEBUG("'"); + if (optarr[1] > -1) + printf("%c", rosh_d_type2char_lssuf(de->d_type)); + printf("\n"); +} /* rosh_ls_arg_dir_de */ + +/* Output listing of a regular directory + * filestr directory name to list + * d the open DIR + * optarr Array of options + NOTE:This is where I could use qsort + */ +void rosh_ls_arg_dir(const char *filestr, DIR * d, const int *optarr) +{ + struct dirent *de; + int filepos; + + filepos = 0; + while ((de = readdir(d))) { + filepos++; + rosh_ls_arg_dir_de(de, optarr); + } + if (errno) + rosh_error(errno, "ls:arg_dir", filestr); + else if (filepos == 0) + ROSH_DEBUG("0 files found"); +} /* rosh_ls_arg_dir */ + +/* Simple directory listing for one argument (file/directory) based on + * filestr and pwdstr + * ifilstr input filename/directory name to list + * pwdstr Present Working Directory string + * optarr Option Array + */ +void rosh_ls_arg(const char *filestr, const int *optarr) +{ + struct stat fdstat; + int status; +// char filestr[ROSH_PATH_SZ]; +// int filepos; + DIR *d; + struct dirent de; + + /* Initialization; make filestr based on leading character of ifilstr + and pwdstr */ +// rosh_qualify_filestr(filestr, ifilstr, pwdstr); + fdstat.st_mode = 0; + fdstat.st_size = 0; + ROSH_DEBUG("\topt[0]=%d\topt[1]=%d\topt[2]=%d\n", optarr[0], optarr[1], + optarr[2]); + + /* Now, the real work */ + errno = 0; + status = stat(filestr, &fdstat); + if (status == 0) { + if (S_ISDIR(fdstat.st_mode)) { + ROSH_DEBUG("PATH '%s' is a directory\n", filestr); + d = opendir(filestr); + rosh_ls_arg_dir(filestr, d, optarr); + closedir(d); + } else { + de.d_ino = rosh_ls_d_ino(&fdstat); + de.d_type = (IFTODT(fdstat.st_mode)); + strcpy(de.d_name, filestr); + if (S_ISREG(fdstat.st_mode)) { + ROSH_DEBUG("PATH '%s' is a regular file\n", filestr); + } else { + ROSH_DEBUG("PATH '%s' is some other file\n", filestr); + } + rosh_ls_arg_dir_de(&de, optarr); +/* if (ifilstr[0] == SEP) + rosh_ls_arg_dir_de(NULL, &de, optarr); + else + rosh_ls_arg_dir_de(pwdstr, &de, optarr);*/ + } + } else { + rosh_error(errno, "ls", filestr); + errno = 0; + } + return; +} /* rosh_ls_arg */ + +/* Parse options that may be present in the cmdstr + * filestr Possible option string to parse + * optstr Current options + * returns 1 if filestr does not begin with '-' else 0 + */ +int rosh_ls_parse_opt(const char *filestr, char *optstr) +{ + int ret; + if (filestr[0] == '-') { + ret = 0; + if (optstr) + strcat(optstr, filestr + 1); + } else { + ret = 1; + } + ROSH_DEBUG("ParseOpt: '%s'\n\topt: '%s'\n\tret: %d\n", filestr, optstr, + ret); + return ret; +} /* rosh_ls_parse_opt */ + +/* List Directory based on cmdstr and pwdstr + * cmdstr command string to process + * pwdstr Present Working Directory string + */ +void rosh_ls(const char *cmdstr) +{ + char filestr[ROSH_PATH_SZ]; + char optstr[ROSH_OPT_SZ]; /* Options string */ + int cmdpos, tpos; /* Position within cmdstr, temp position */ + int numargs; /* number of non-option arguments */ + int argpos; /* number of non-option arguments processed */ + int optarr[3]; + + ROSH_DEBUG("CMD: '%s'\n", cmdstr); + /* Initialization */ + filestr[0] = 0; + optstr[0] = 0; + cmdpos = 0; + numargs = 0; + argpos = 0; + /* skip the first word */ + cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); + tpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); + /* If there are no real arguments, substitute PWD */ + if (strlen(filestr) == 0) { + strcpy(filestr, "."); + cmdpos = tpos; + } else { /* Parse for command line options */ + while (strlen(filestr) > 0) { + numargs += rosh_ls_parse_opt(filestr, optstr); + tpos = rosh_parse_sp_1(filestr, cmdstr, tpos); + } + if (numargs == 0) { + strcpy(filestr, "."); + cmdpos = tpos; + } else { + cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); + } + } +#ifdef DO_DEBUG + if (!strchr(optstr, 'l')) + strcat(optstr, "l"); +#endif /* DO_DEBUG */ + rosh_ls_arg_opt(optstr, optarr); + ROSH_DEBUG("\tfopt: '%s'\n", optstr); + while (strlen(filestr) > 0) { + if (rosh_ls_parse_opt(filestr, NULL)) { + rosh_ls_arg(filestr, optarr); + argpos++; + } + if (argpos < numargs) + cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); + else + break; + } +} /* rosh_ls */ + +/* Simple directory listing; calls rosh_ls() + * cmdstr command string to process + * pwdstr Present Working Directory string + */ +void rosh_dir(const char *cmdstr) +{ + ROSH_DEBUG(" dir implemented as ls\n"); + rosh_ls(cmdstr); +} /* rosh_dir */ + +/* Page through a buffer string + * buf Buffer to page through + */ +//HERE: minor pagination issue; sometimes prints 1 less than rows +void rosh_more_buf(char *buf, int buflen, int rows, int cols) +{ + char *bufp, *bufeol, *bufeol2; /* Pointer to current and next + end-of-line position in buffer */ + int bufpos, bufcnt; /* current position, count characters */ + char scrbuf[ROSH_SBUF_SZ]; + int inc; + int i, numln; /* Index, Number of lines */ + + (void)cols; + + bufpos = 0; + bufp = buf + bufpos; + bufeol = bufp; + numln = rows - 1; + ROSH_DEBUG("--(%d)\n", buflen); + while (bufpos < buflen) { + for (i = 0; i < numln; i++) { + bufeol2 = strchr(bufeol, '\n'); + if (bufeol2 == NULL) { + bufeol = buf + buflen; + i = numln; + } else { + i += ((bufeol2 - bufeol) / cols); + bufeol = bufeol2 + 1; + } + } + bufcnt = bufeol - bufp; + printf("--(%d/%d @%d)\n", bufcnt, buflen, bufpos); + memcpy(scrbuf, bufp, bufcnt); + scrbuf[bufcnt] = 0; + printf("%s", scrbuf); + bufp = bufeol; + bufpos += bufcnt; + if (bufpos == buflen) + break; + inc = rosh_getkey(); + numln = 1; + switch (inc) { + case KEY_CTRL('c'): + case 'q': + case 'Q': + bufpos = buflen; + break; + case ' ': + numln = rows - 1; + } + } +} /* rosh_more_buf */ + +/* Page through a single file using the open file stream + * fd File Descriptor + */ +void rosh_more_fd(int fd, int rows, int cols) +{ + struct stat fdstat; + int status; + char *buf; + int bufpos; + int numrd; + FILE *f; + + status = fstat(fd, &fdstat); + if (S_ISREG(fdstat.st_mode)) { + buf = malloc((int)fdstat.st_size); + if (buf != NULL) { + f = fdopen(fd, "r"); + bufpos = 0; + numrd = fread(buf, 1, (int)fdstat.st_size, f); + while (numrd > 0) { + bufpos += numrd; + numrd = fread(buf + bufpos, 1, + ((int)fdstat.st_size - bufpos), f); + } + fclose(f); + rosh_more_buf(buf, bufpos, rows, cols); + } + } else { + } + +} /* rosh_more_fd */ + +/* Page through a file like the more command + * cmdstr command string to process + * ipwdstr Initial PWD + */ +void rosh_more(const char *cmdstr) +{ + int fd; + char filestr[ROSH_PATH_SZ]; + int cmdpos; + int rows, cols; + + ROSH_DEBUG("CMD: '%s'\n", cmdstr); + /* Initialization */ + filestr[0] = 0; + cmdpos = 0; + if (getscreensize(1, &rows, &cols)) { + ROSH_DEBUG("getscreensize() fail; fall back\n"); + ROSH_DEBUG("\tROWS='%d'\tCOLS='%d'\n", rows, cols); + /* If either fail, go under normal size, just in case */ + if (!rows) + rows = 20; + if (!cols) + cols = 75; + } + ROSH_DEBUG("\tUSE ROWS='%d'\tCOLS='%d'\n", rows, cols); + + /* skip the first word */ + cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); + cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); + if (strlen(filestr) > 0) { + /* There is no need to mess up the console if we don't have a + file */ + rosh_console_raw(); + while (strlen(filestr) > 0) { + printf("--File = '%s'\n", filestr); + fd = open(filestr, O_RDONLY); + if (fd != -1) { + rosh_more_fd(fd, rows, cols); + close(fd); + } else { + rosh_error(errno, "more", filestr); + errno = 0; + } + cmdpos = rosh_parse_sp_1(filestr, cmdstr, cmdpos); + } + rosh_console_std(); + } +} /* rosh_more */ + +/* Page a file with rewind + * cmdstr command string to process + * pwdstr Present Working Directory string + * ipwdstr Initial PWD + */ +void rosh_less(const char *cmdstr) +{ + printf(" less implemented as more (for now)\n"); + rosh_more(cmdstr); +} /* rosh_less */ + +/* Show PWD + * cmdstr command string to process + */ +void rosh_pwd(const char *cmdstr) +{ + int istr; + char pwdstr[ROSH_PATH_SZ]; + if (cmdstr) + istr = 0; + ROSH_DEBUG("CMD: '%s'\n", cmdstr); + errno = 0; + if (getcwd(pwdstr, ROSH_PATH_SZ)) { + printf("%s\n", pwdstr); + } else { + rosh_error(errno, "pwd", ""); + errno = 0; + } + istr = htonl(*(int *)pwdstr); + ROSH_DEBUG2(" --%08X\n", istr); +} /* rosh_pwd */ + +/* Reboot + */ +void rosh_reboot(void) +{ +// char cmdstr[ROSH_CMD_SZ]; +// printf + syslinux_reboot(0); +} /* rosh_reboot */ + +/* Run a boot string, calling syslinux_run_command + * cmdstr command string to process + */ +void rosh_run(const char *cmdstr) +{ + int cmdpos; + char *cmdptr; + + cmdpos = 0; + ROSH_DEBUG("CMD: '%s'\n", cmdstr); + /* skip the first word */ + cmdpos = rosh_search_sp(cmdstr, cmdpos); + /* skip spaces */ + cmdpos = rosh_search_nonsp(cmdstr, cmdpos); + cmdptr = (char *)(cmdstr + cmdpos); + printf("--run: '%s'\n", cmdptr); + syslinux_run_command(cmdptr); +} /* rosh_run */ + +/* Process a single command string and call handling function + * cmdstr command string to process + * ipwdstr Initial Present Working Directory string + * returns Whether to exit prompt + */ +char rosh_command(const char *cmdstr, const char *ipwdstr) +{ + char do_exit; + char tstr[ROSH_CMD_SZ]; + int tlen; + do_exit = false; + ROSH_DEBUG("--cmd:'%s'\n", cmdstr); + tlen = rosh_parse_sp_1(tstr, cmdstr, 0); + switch (cmdstr[0]) { + case 'e': + case 'E': + case 'q': + case 'Q': + if ((strncasecmp("exit", tstr, tlen) == 0) || + (strncasecmp("quit", tstr, tlen) == 0)) + do_exit = true; + else + rosh_help(1, NULL); + break; + case 'c': + case 'C': /* run 'cd' 'cat' 'cfg' */ + switch (cmdstr[1]) { + case 'a': + case 'A': + if (strncasecmp("cat", tstr, tlen) == 0) + rosh_cat(cmdstr); + else + rosh_help(1, NULL); + break; + case 'd': + case 'D': + if (strncasecmp("cd", tstr, tlen) == 0) + rosh_cd(cmdstr, ipwdstr); + else + rosh_help(1, NULL); + break; + case 'f': + case 'F': + if (strncasecmp("cfg", tstr, tlen) == 0) + rosh_cfg(); + else + rosh_help(1, NULL); + break; + default: + rosh_help(1, NULL); + } + break; + case 'd': + case 'D': /* run 'dir' */ + if (strncasecmp("dir", tstr, tlen) == 0) + rosh_dir(cmdstr); + else + rosh_help(1, NULL); + break; + case 'h': + case 'H': + case '?': + if ((strncasecmp("help", tstr, tlen) == 0) || (tlen == 1)) + rosh_help(2, cmdstr); + else + rosh_help(1, NULL); + break; + case 'l': + case 'L': /* run 'ls' 'less' */ + switch (cmdstr[1]) { + case 0: + case ' ': + case 's': + case 'S': + if (strncasecmp("ls", tstr, tlen) == 0) + rosh_ls(cmdstr); + else + rosh_help(1, NULL); + break; + case 'e': + case 'E': + if (strncasecmp("less", tstr, tlen) == 0) + rosh_less(cmdstr); + else + rosh_help(1, NULL); + break; + default: + rosh_help(1, NULL); + } + break; + case 'm': + case 'M': + switch (cmdstr[1]) { + case 'a': + case 'A': + if (strncasecmp("man", tstr, tlen) == 0) + rosh_help(2, cmdstr); + else + rosh_help(1, NULL); + break; + case 'o': + case 'O': + if (strncasecmp("more", tstr, tlen) == 0) + rosh_more(cmdstr); + else + rosh_help(1, NULL); + break; + default: + rosh_help(1, NULL); + } + break; + case 'p': + case 'P': /* run 'pwd' */ + if (strncasecmp("pwd", tstr, tlen) == 0) + rosh_pwd(cmdstr); + else + rosh_help(1, NULL); + break; + case 'r': + case 'R': /* run 'run' */ + switch (cmdstr[1]) { + case 0: + case ' ': + case 'e': + case 'E': + if (strncasecmp("reboot", tstr, tlen) == 0) + rosh_reboot(); + else + rosh_help(1, NULL); + break; + case 'u': + case 'U': + if (strncasecmp("run", tstr, tlen) == 0) + rosh_run(cmdstr); + else + rosh_help(1, NULL); + break; + } + break; + case 'v': + case 'V': + if (strncasecmp("version", tstr, tlen) == 0) + rosh_version(); + else + rosh_help(1, NULL); + break; + case 0: + case '\n': + break; + default: + rosh_help(1, NULL); + } /* switch(cmdstr[0]) */ + return do_exit; +} /* rosh_command */ + +/* Process the prompt for commands as read from stdin and call rosh_command + * to process command line string + * icmdstr Initial command line string + * returns Exit status + */ +int rosh_prompt(const char *icmdstr) +{ + int rv; + char cmdstr[ROSH_CMD_SZ]; + char ipwdstr[ROSH_PATH_SZ]; + char do_exit; + char *c; + + rv = 0; + do_exit = false; + if (!getcwd(ipwdstr, ROSH_PATH_SZ)) + strcpy(ipwdstr, "./"); + if (icmdstr[0] != '\0') + do_exit = rosh_command(icmdstr, ipwdstr); + while (!(do_exit)) { + /* Extra preceeding newline */ + printf("\nrosh: "); + /* Read a line from console */ + if (fgets(cmdstr, ROSH_CMD_SZ, stdin)) { + /* remove newline from input string */ + c = strchr(cmdstr, '\n'); + *c = 0; + do_exit = rosh_command(cmdstr, ipwdstr); + } else { + do_exit = false; + } + } + return rv; +} + +int main(int argc, char *argv[]) +{ + int rv; + char cmdstr[ROSH_CMD_SZ]; + + /* Initialization */ + rv = 0; + rosh_console_std(); + if (argc != 1) { + rv = rosh_argcat(cmdstr, argc, argv, 1); + } else { + rosh_version(); + print_beta(); + cmdstr[0] = '\0'; + } + rv = rosh_prompt(cmdstr); + printf("--Exiting '%s'\n", APP_NAME); + return rv; +} diff --git a/contrib/syslinux-4.02/com32/rosh/rosh.h b/contrib/syslinux-4.02/com32/rosh/rosh.h new file mode 100644 index 0000000..a8edda6 --- /dev/null +++ b/contrib/syslinux-4.02/com32/rosh/rosh.h @@ -0,0 +1,228 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2008-2009 Gene Cumm - 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. + * + * ----------------------------------------------------------------------- */ + +/* + * rosh.h + * + * Read-Only shell; Header + */ + +/* + * History + * b034 Improve debug functions to simpler code + * b021 Move much PreProcessing stuff to rosh.h + * b018 Create rosh_debug() macro + * b012 Version of rosh.c at time of creating this file. + */ + +#ifndef ROSH_H +#define ROSH_H + +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> /* macro: true false */ +#include <string.h> /* strcpy() strlen() memcpy() strchr() */ +#include <sys/types.h> +#include <sys/stat.h> /* fstat() */ +#include <fcntl.h> /* open(); open mode macros */ +#include <dirent.h> /* fdopendir() opendir() readdir() closedir() DIR */ +#include <unistd.h> /* getcwd() */ +#include <errno.h> /* errno; error macros */ +#include <netinet/in.h> /* For htonl/ntohl/htons/ntohs */ +#include <ctype.h> /* isspace() */ + +#include <getkey.h> +#include <consoles.h> + +#ifdef DO_DEBUG +# define ROSH_DEBUG printf +/* define ROSH_DEBUG(f, ...) printf (f, ## __VA_ARGS__) */ +# ifdef DO_DEBUG2 +# define ROSH_DEBUG2 printf +# else /* DO_DEBUG2 */ + /* This forces a format argument into the function call */ +# define ROSH_DEBUG2(f, ...) ((void)0) +# endif /* DO_DEBUG2 */ +#else /* DO_DEBUG */ +# define ROSH_DEBUG(f, ...) ((void)0) +# define ROSH_DEBUG2(f, ...) ((void)0) +#endif /* DO_DEBUG */ + +#ifdef __COM32__ +#define ROSH_IS_COM32 1 +#include <console.h> /* openconsole() */ +#include <syslinux/config.h> /* Has info on the SYSLINUX variant */ +#include <syslinux/boot.h> /* syslinux_run_command() */ +#include <syslinux/reboot.h> +#define ROSH_COM32(f, ...) printf (f, ## __VA_ARGS__) +#define rosh_console_std() console_ansi_std() +#define rosh_console_raw() console_ansi_raw() + +int stat(const char *pathname, struct stat *buf) +{ + int fd, status, ret = -1; + DIR *d; + + d = opendir(pathname); + if (d != NULL) { + closedir(d); + ret = 0; + buf->st_mode = S_IFDIR | 0555; + buf->st_size = 0; + } else if ((errno == 0) || (errno == ENOENT) || (errno == ENOTDIR)) { + fd = open(pathname, O_RDONLY); + if (fd != 1) { + status = fstat(fd, buf); + close(fd); + ret = 0; + } + } + return ret; +} + +#else +# include <termios.h> +# define ROSH_IS_COM32 0 + +static inline char *syslinux_config_file(void) +{ + return ""; +} + +static inline int getscreensize(int fd, int *rows, int *cols) +{ + char *str; + int rv; + *rows = 0; + *cols = 0; + if (fd == 1) { + if (rows) { + str = getenv("LINES"); + if (str) + *rows = atoi(str); + } + if (cols) { + str = getenv("COLUMNS"); + if (str) + *cols = atoi(str); + } + } + if (!rows || !cols) + rv = -1; + else if (!*rows || !*cols) + rv = -2; + else + rv = 0; + return rv; +} + +/* + * Switches console over to raw input mode. Allows get_key to get just + * 1 key sequence (without delay or display) + */ +void rosh_console_raw(void) +{ + struct termios tio; + + console_ansi_raw(); /* Allows get_key to get just 1 key sequence + (w/o delay or display */ + /* Deal with the changes that haven't been replicated to ansiraw.c */ + tcgetattr(0, &tio); + tio.c_iflag &= ~IGNCR; + tcsetattr(0, TCSAFLUSH, &tio); +} + +/* + * Switches back to standard getline mode. + */ +void rosh_console_std(void) +{ + struct termios tio; + + console_ansi_std(); + tcgetattr(0, &tio); + tio.c_iflag |= ICRNL; + tio.c_iflag &= ~IGNCR; + tcsetattr(0, TCSANOW, &tio); +} + +void syslinux_reboot(int warm) +{ + printf("Test Reboot(%d)\n", warm); +} + +#define ROSH_COM32(f, ...) ((void)0) +#define syslinux_run_command(f) ((void)0) +#endif /* __COM32__ */ + +#define SEP '/' + +/* Size of buffer string */ +#define ROSH_BUF_SZ 16384 +/* Size of screen output buffer (80*40) //HERE */ +#define ROSH_SBUF_SZ ((80 + 2) * 40) + +/* Size of command buffer string */ +#ifdef MAX_CMDLINE_LEN +# define ROSH_CMD_SZ MAX_CMDLINE_LEN +#elif COMMAND_LINE_SIZE +# define ROSH_CMD_SZ COMMAND_LINE_SIZE +#else +# define ROSH_CMD_SZ_LG2 12 +# define ROSH_CMD_SZ (1 << ROSH_CMD_SZ_LG2) +#endif /* MAX_CMDLINE_LEN */ + +/* Size of path buffer string */ +#ifdef PATH_MAX +# define ROSH_PATH_SZ PATH_MAX +#elif NAME_MAX +# define ROSH_PATH_SZ NAME_MAX +#elif FILENAME_MAX +# define ROSH_PATH_SZ FILENAME_MAX +#else +# define ROSH_PATH_SZ_LG2 8 +# define ROSH_PATH_SZ (1 << ROSH_PATH_SZ_LG2) +#endif /* PATH_MAX */ + +#define ROSH_OPT_SZ 8 + +const char rosh_beta_str[] = + " ROSH is currently beta. Constructive feedback is appreciated"; + +const char rosh_cd_norun_str[] = + " -- cd (Change Directory) not implemented for use with run and exit.\n"; + +const char rosh_help_ls_str[] = "ls List contents of current directory\n\ + -l Long format\n\ + -i Inode; print Inode of file\n\ + -F Classify; Add a 1-character suffix to classify files"; + +const char rosh_help_str1[] = + "Commands: ? cat cd cfg dir exit help less ls man more pwd run quit ver"; + +const char rosh_help_str2[] = + "Commands: (short generally non-ambiguous abreviations are also allowed)\n\ + h HELP\n ALSO ? help man\n ALSO help <command>\n\ + cat Concatenate file to console\n cat <file>\n\ + cd Change to directory <dir>\n cd <dir>\n\ + less Page a file with rewind\n\ + ls List contents of current directory\n ls <dir>\n\ + ALSO l dir\n\ + more Page a file\n\ + pwd display Present Working Directory\n\ + run Run a program/kernel with options\n\ + r Reboot (if COM32)\n Also reboot\n\ + exit Exit to previous environment\n ALSO quit"; + +const char rosh_help_str_adv[] = "No additional help available for '%s'"; + +#endif /* Not ROSH_H */ diff --git a/contrib/syslinux-4.02/com32/samples/Makefile b/contrib/syslinux-4.02/com32/samples/Makefile new file mode 100644 index 0000000..bee2b99 --- /dev/null +++ b/contrib/syslinux-4.02/com32/samples/Makefile @@ -0,0 +1,38 @@ +## ----------------------------------------------------------------------- +## +## 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 ../MCONFIG + +all: hello.c32 resolv.c32 serialinfo.c32 \ + localboot.c32 \ + fancyhello.c32 fancyhello.lnx \ + keytest.c32 keytest.lnx \ + advdump.c32 entrydump.c32 + +tidy dist: + rm -f *.o *.lo *.a *.lst *.elf .*.d *.tmp + +clean: tidy + rm -f *.lnx + +spotless: clean + rm -f *.lss *.c32 *.com + rm -f *~ \#* + +install: # Don't install samples + +-include .*.d diff --git a/contrib/syslinux-4.02/com32/samples/advdump.c b/contrib/syslinux-4.02/com32/samples/advdump.c new file mode 100644 index 0000000..2c78641 --- /dev/null +++ b/contrib/syslinux-4.02/com32/samples/advdump.c @@ -0,0 +1,53 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-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. + * + * ----------------------------------------------------------------------- */ + +/* + * advdump.c + * + * Dump the contents of the syslinux ADV + */ + +#include <stdio.h> +#include <console.h> +#include <syslinux/adv.h> +#include <string.h> + +int main(void) +{ + uint8_t *p, *ep; + size_t s = syslinux_adv_size(); + char buf[256]; + + openconsole(&dev_stdcon_r, &dev_stdcon_w); + + p = syslinux_adv_ptr(); + + printf("ADV size: %zd bytes at %p\n", s, p); + + ep = p + s; /* Need at least opcode+len */ + while (p < ep - 1 && *p) { + int t = *p++; + int l = *p++; + + if (p + l > ep) + break; + + memcpy(buf, p, l); + buf[l] = '\0'; + + printf("ADV %3d: \"%s\"\n", t, buf); + + p += l; + } + + return 0; +} diff --git a/contrib/syslinux-4.02/com32/samples/entrydump.c b/contrib/syslinux-4.02/com32/samples/entrydump.c new file mode 100644 index 0000000..d50859f --- /dev/null +++ b/contrib/syslinux-4.02/com32/samples/entrydump.c @@ -0,0 +1,60 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * entry.c + * + * Dump the entry point registers + */ + +#include <string.h> +#include <stdio.h> +#include <inttypes.h> +#include <console.h> +#include <syslinux/config.h> + +struct stack_frame { + uint16_t gs, fs, es, ds; + uint32_t edi, esi, ebp, esp; + uint32_t ebx, edx, ecx, eax; + uint32_t eflags; + uint16_t ret_ip, ret_cs; + uint16_t pxe_ip, pxe_cs; +}; + +int main(void) +{ + const union syslinux_derivative_info *di; + const struct stack_frame *sf; + + openconsole(&dev_null_r, &dev_stdcon_w); + + di = syslinux_derivative_info(); + + if (di->c.filesystem != SYSLINUX_FS_PXELINUX) { + printf("Not running under PXELINUX (fs = %02x)\n", di->c.filesystem); + return 1; + } + + sf = (const struct stack_frame *)di->pxe.stack; + + printf("EAX: %08x EBX: %08x ECX: %08x EDX: %08x\n" + "ESP: %08x EBP: %08x ESI: %08x EDI: %08x\n" + "SS: %04x DS: %04x ES: %04x FS: %04x GS: %04x\n" + "EFLAGS: %08x RET: %04x:%04x PXE: %04x:%04x\n", + sf->eax, sf->ebx, sf->ecx, sf->edx, + sf->esp + 4, sf->ebp, sf->esi, sf->edi, + di->rr.r.fs, sf->ds, sf->es, sf->fs, sf->gs, + sf->eflags, sf->ret_cs, sf->ret_ip, sf->pxe_cs, sf->pxe_ip); + + return 0; +} diff --git a/contrib/syslinux-4.02/com32/samples/fancyhello.c b/contrib/syslinux-4.02/com32/samples/fancyhello.c new file mode 100644 index 0000000..850bff0 --- /dev/null +++ b/contrib/syslinux-4.02/com32/samples/fancyhello.c @@ -0,0 +1,42 @@ + +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * fancyhello.c + * + * Hello, World! using libcom32 and ANSI console; also possible to compile + * as a Linux application for testing. + */ + +#include <string.h> +#include <stdio.h> + +#include <consoles.h> /* Provided by libutil */ + +int main(void) +{ + char buffer[1024]; + + console_ansi_std(); + + printf("\033[1;33;44m *** \033[37mHello, World!\033[33m *** \033[0m\n"); + + for (;;) { + printf("\033[1;36m>\033[0m "); + fgets(buffer, sizeof buffer, stdin); + if (!strncmp(buffer, "exit", 4)) + break; + printf("\033[1m:\033[0m %s", buffer); + } + return 0; +} diff --git a/contrib/syslinux-4.02/com32/samples/hello.c b/contrib/syslinux-4.02/com32/samples/hello.c new file mode 100644 index 0000000..77e93ac --- /dev/null +++ b/contrib/syslinux-4.02/com32/samples/hello.c @@ -0,0 +1,35 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * hello.c + * + * Hello, World! using libcom32 + */ + +#include <string.h> +#include <stdio.h> +#include <console.h> + +int main(int argc, char *argv[]) +{ + int i; + + openconsole(&dev_stdcon_r, &dev_stdcon_w); + + printf("Hello, World!\n"); + + for (i = 1; i < argc; i++) + printf("%s%c", argv[i], (i == argc - 1) ? '\n' : ' '); + + return 0; +} diff --git a/contrib/syslinux-4.02/com32/samples/keytest.c b/contrib/syslinux-4.02/com32/samples/keytest.c new file mode 100644 index 0000000..b4f8f5b --- /dev/null +++ b/contrib/syslinux-4.02/com32/samples/keytest.c @@ -0,0 +1,81 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * keytest.c + * + * Test the key parsing library + */ + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <sys/times.h> + +#include <consoles.h> /* Provided by libutil */ +#include <getkey.h> + +static void cooked_keys(void) +{ + int key; + + printf("[cooked]"); + + for (;;) { + key = get_key(stdin, 0); + + if (key == 0x03) { + printf("[done]\n"); + exit(0); + } else if (key == '?') + return; + + if (key >= 0x20 && key < 0x100) { + putchar(key); + } else { + printf("[%04x]", key); + } + } +} + +static void raw_keys(void) +{ + int key; + + printf("[raw]"); + + for (;;) { + key = getc(stdin); + + if (key == 0x03) { + printf("[done]\n"); + exit(0); + } else if (key == '!') + return; + + printf("<%02x>", key); + } +} + +int main(void) +{ + console_ansi_raw(); + + printf("CLK_TCK = %d\n", (int)CLK_TCK); + printf("Press keys, end with Ctrl-C...\n"); + + for (;;) { + cooked_keys(); + raw_keys(); + } +} diff --git a/contrib/syslinux-4.02/com32/samples/localboot.c b/contrib/syslinux-4.02/com32/samples/localboot.c new file mode 100644 index 0000000..b6f992d --- /dev/null +++ b/contrib/syslinux-4.02/com32/samples/localboot.c @@ -0,0 +1,9 @@ +#include <syslinux/boot.h> +#include <stdlib.h> + +int main(int argc, char *argv[]) +{ + syslinux_local_boot(argc > 1 ? atoi(argv[1]) : 0); + + return 0; +} diff --git a/contrib/syslinux-4.02/com32/samples/resolv.c b/contrib/syslinux-4.02/com32/samples/resolv.c new file mode 100644 index 0000000..bd49d9f --- /dev/null +++ b/contrib/syslinux-4.02/com32/samples/resolv.c @@ -0,0 +1,66 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-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. + * + * ----------------------------------------------------------------------- */ + +/* + * resolv.c + * + * Resolve an IP address + */ + +#include <string.h> +#include <stdio.h> +#include <console.h> +#include <stdlib.h> +#include <com32.h> + +uint32_t resolv(const char *name) +{ + com32sys_t reg; + + strcpy((char *)__com32.cs_bounce, name); + + memset(®, 0, sizeof reg); + reg.eax.w[0] = 0x0010; + reg.ebx.w[0] = OFFS(__com32.cs_bounce); + reg.es = SEG(__com32.cs_bounce); + + __intcall(0x22, ®, ®); + + if (reg.eflags.l & EFLAGS_CF) + return 0; + else + return reg.eax.l; +} + +int main(int argc, char *argv[]) +{ + uint32_t ip; + + openconsole(&dev_null_r, &dev_stdcon_w); + + if (argc < 2) { + fputs("Usage: resolv hostname\n", stderr); + exit(1); + } + + ip = resolv(argv[1]); + + if (ip) { + printf("%s = %u.%u.%u.%u\n", argv[1], + (ip & 0xff), (ip >> 8) & 0xff, + (ip >> 16) & 0xff, (ip >> 24) & 0xff); + } else { + printf("%s not found\n", argv[1]); + } + + return 0; +} diff --git a/contrib/syslinux-4.02/com32/samples/serialinfo.c b/contrib/syslinux-4.02/com32/samples/serialinfo.c new file mode 100644 index 0000000..10d0252 --- /dev/null +++ b/contrib/syslinux-4.02/com32/samples/serialinfo.c @@ -0,0 +1,39 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-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. + * + * ----------------------------------------------------------------------- */ + +/* + * serialinfo.c + * + * Print serial port info + */ + +#include <string.h> +#include <stdio.h> +#include <console.h> +#include <syslinux/config.h> + +int main(void) +{ + const struct syslinux_serial_console_info *si; + + openconsole(&dev_null_r, &dev_stdcon_w); + + si = syslinux_serial_console_info(); + + printf("Serial port base: %#06x\n", si->iobase); + printf("Serial port divisor: %5d", si->divisor); + if (si->divisor) + printf(" (%d baud)", 115200 / si->divisor); + printf("\n" "Flow control bits: %#05x\n", si->flowctl); + + return 0; +} diff --git a/contrib/syslinux-4.02/com32/sysdump/Makefile b/contrib/syslinux-4.02/com32/sysdump/Makefile new file mode 100644 index 0000000..bffee3a --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/Makefile @@ -0,0 +1,60 @@ +## ----------------------------------------------------------------------- +## +## Copyright 2001-2008 H. Peter Anvin - All Rights Reserved +## Copyright 2010 Intel Corporation; author: H. Peter Anvin +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, +## Boston MA 02110-1301, USA; either version 2 of the License, or +## (at your option) any later version; incorporated herein by reference. +## +## ----------------------------------------------------------------------- + +## +## Simple menu system +## + +topdir = ../.. +include ../MCONFIG +-include $(topdir)/version.mk + +LIBS = ../libutil/libutil_com.a ../lib/libcom32.a $(LIBGCC) +LNXLIBS = ../libutil/libutil_lnx.a + +MODULES = sysdump.c32 +TESTFILES = + +SRCS = $(wildcard *.c) +OBJS = $(patsubst %.c,%.o,$(SRCS)) + +# The DATE is set on the make command line when building binaries for +# official release. Otherwise, substitute a hex string that is pretty much +# guaranteed to be unique to be unique from build to build. +ifndef HEXDATE +HEXDATE := $(shell $(PERL) $(topdir)/now.pl $(SRCS) $(wildcard *.h)) +endif +ifndef DATE +DATE := $(shell sh $(topdir)/gen-id.sh $(VERSION) $(HEXDATE)) +endif + +CFLAGS += -DDATE='"$(DATE)"' + +all: $(MODULES) $(TESTFILES) + +sysdump.elf : $(OBJS) $(LIBS) $(C_LIBS) + $(LD) $(LDFLAGS) -o $@ $^ + +tidy dist: + rm -f *.o *.lo *.a *.lst *.elf .*.d *.tmp + +clean: tidy + rm -f *.lnx + +spotless: clean + rm -f *.lss *.c32 *.com + rm -f *~ \#* + +install: + +-include .*.d diff --git a/contrib/syslinux-4.02/com32/sysdump/README b/contrib/syslinux-4.02/com32/sysdump/README new file mode 100644 index 0000000..2b82577 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/README @@ -0,0 +1,19 @@ +This is a very simple COMBOOT program which can be used to dump memory +regions over a serial port. To use it, type on the SYSLINUX command +line: + +memdump <port> <prefix> <start>,<len> <start>,<len>... + +For example: + +memdump 0 funnysystem- 0,0x600 0x9fc00,0x400 0xf0000,0x10000 + +... dumps three memory ranges (the standard BIOS memory ranges, often +useful) onto serial port 0. The <port> can either be in the range 0-3 +for the standard BIOS serial port, or the I/O address of the UART. + +The data is transferred using the YMODEM protocol; the Unix +implementation of this protocol is called "rb" and is part of the +"lrzsz" (or "rzsz") package. If one uses a terminal program like +Minicom, there is often a way to invoke it from inside the terminal +program; in Minicom, this is done with the Ctrl-A R control sequence. diff --git a/contrib/syslinux-4.02/com32/sysdump/acpi.c b/contrib/syslinux-4.02/com32/sysdump/acpi.c new file mode 100644 index 0000000..8671fc8 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/acpi.c @@ -0,0 +1,259 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2010 Intel Corporation; author: H. Peter Anvin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * Dump ACPI information + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include "sysdump.h" +#include "backend.h" +#include "rbtree.h" + +struct acpi_rsdp { + uint8_t magic[8]; /* "RSD PTR " */ + uint8_t csum; + char oemid[6]; + uint8_t rev; + uint32_t rsdt_addr; + uint32_t len; + uint64_t xsdt_addr; + uint8_t xcsum; + uint8_t rsvd[3]; +}; + +struct acpi_hdr { + char sig[4]; /* Signature */ + uint32_t len; + uint8_t rev; + uint8_t csum; + char oemid[6]; + char oemtblid[16]; + uint32_t oemrev; + uint32_t creatorid; + uint32_t creatorrev; +}; + +struct acpi_rsdt { + struct acpi_hdr hdr; + uint32_t entry[0]; +}; + +struct acpi_xsdt { + struct acpi_hdr hdr; + uint64_t entry[0]; +}; + +static struct rbtree *rb_types, *rb_addrs; + +static bool rb_has(struct rbtree **tree, uint64_t key) +{ + struct rbtree *node; + + node = rb_search(*tree, key); + if (node && node->key == key) + return true; + + node = malloc(sizeof *node); + if (node) { + node->key = key; + *tree = rb_insert(*tree, node); + } + return false; +} + +static inline bool addr_ok(uint64_t addr) +{ + /* We can only handle 32-bit addresses for now... */ + return addr <= 0xffffffff; +} + +enum tbl_errs { + ERR_NONE, /* No errors */ + ERR_CSUM, /* Invalid checksum */ + ERR_SIZE, /* Impossibly large table */ + ERR_NOSIG /* No signature */ +}; + +static uint8_t checksum_range(const void *start, uint32_t size) +{ + const uint8_t *p = start; + uint8_t csum = 0; + + while (size--) + csum += *p++; + + return csum; +} + +static enum tbl_errs is_valid_table(const void *ptr) +{ + const struct acpi_hdr *hdr = ptr; + + if (hdr->sig[0] == 0) + return ERR_NOSIG; + + if (hdr->len < 10 || hdr->len > (1 << 20)) { + /* Either insane or too large to dump */ + return ERR_SIZE; + } + + return checksum_range(hdr, hdr->len) == 0 ? ERR_NONE : ERR_CSUM; +} + +static const struct acpi_rsdp *scan_for_rsdp(uint32_t base, uint32_t end) +{ + for (base &= ~15; base < end-20; base += 16) { + const struct acpi_rsdp *rsdp = (const struct acpi_rsdp *)base; + + if (memcmp(rsdp->magic, "RSD PTR ", 8)) + continue; + + if (checksum_range(rsdp, 20)) + continue; + + if (rsdp->rev > 0) { + if (base + rsdp->len >= end || + checksum_range(rsdp, rsdp->len)) + continue; + } + + return rsdp; + } + + return NULL; +} + +static const struct acpi_rsdp *find_rsdp(void) +{ + uint32_t ebda; + const struct acpi_rsdp *rsdp; + + ebda = (*(uint16_t *)0x40e) << 4; + if (ebda >= 0x70000 && ebda < 0xa0000) { + rsdp = scan_for_rsdp(ebda, ebda+1024); + + if (rsdp) + return rsdp; + } + + return scan_for_rsdp(0xe0000, 0x100000); +} + +static void dump_table(struct backend *be, + const char name[], const void *ptr, uint32_t len) +{ + char namebuf[64]; + uint32_t name_key = *(uint32_t *)name; + + if (rb_has(&rb_addrs, (size_t)ptr)) + return; /* Already dumped this table */ + + if (!rb_has(&rb_types, name_key)) { + snprintf(namebuf, sizeof namebuf, "acpi/%4.4s", name); + cpio_mkdir(be, namebuf); + } + + snprintf(namebuf, sizeof namebuf, "acpi/%4.4s/%08x", name, (uint32_t)ptr); + cpio_hdr(be, MODE_FILE, len, namebuf); + + write_data(be, ptr, len); +} + +static void dump_rsdt(struct backend *be, const struct acpi_rsdp *rsdp) +{ + const struct acpi_rsdt *rsdt; + uint32_t i, n; + + rsdt = (const struct acpi_rsdt *)rsdp->rsdt_addr; + + if (memcmp(rsdt->hdr.sig, "RSDT", 4) || is_valid_table(rsdt) > ERR_CSUM) + return; + + dump_table(be, rsdt->hdr.sig, rsdt, rsdt->hdr.len); + + if (rsdt->hdr.len < 36) + return; + + n = (rsdt->hdr.len - 36) >> 2; + + for (i = 0; i < n; i++) { + const struct acpi_hdr *hdr = (const struct acpi_hdr *)(rsdt->entry[i]); + + if (is_valid_table(hdr) <= ERR_CSUM) + dump_table(be, hdr->sig, hdr, hdr->len); + } +} + +static void dump_xsdt(struct backend *be, const struct acpi_rsdp *rsdp) +{ + const struct acpi_xsdt *xsdt; + uint32_t rsdp_len = rsdp->rev > 0 ? rsdp->len : 20; + uint32_t i, n; + + if (rsdp_len < 34) + return; + + if (!addr_ok(rsdp->xsdt_addr)) + return; + + xsdt = (const struct acpi_xsdt *)(size_t)rsdp->xsdt_addr; + + if (memcmp(xsdt->hdr.sig, "XSDT", 4) || is_valid_table(xsdt) > ERR_CSUM) + return; + + dump_table(be, xsdt->hdr.sig, xsdt, xsdt->hdr.len); + + if (xsdt->hdr.len < 36) + return; + + n = (xsdt->hdr.len - 36) >> 3; + + for (i = 0; i < n; i++) { + const struct acpi_hdr *hdr; + if (addr_ok(xsdt->entry[i])) { + hdr = (const struct acpi_hdr *)(size_t)(xsdt->entry[i]); + + if (is_valid_table(hdr) <= ERR_CSUM) + dump_table(be, hdr->sig, hdr, hdr->len); + } + } +} + +void dump_acpi(struct backend *be) +{ + const struct acpi_rsdp *rsdp; + uint32_t rsdp_len; + + rsdp = find_rsdp(); + + printf("Dumping ACPI... "); + + if (!rsdp) + return; /* No ACPI information found */ + + cpio_mkdir(be, "acpi"); + + rsdp_len = rsdp->rev > 0 ? rsdp->len : 20; + + dump_table(be, "RSDP", rsdp, rsdp_len); + + dump_rsdt(be, rsdp); + dump_xsdt(be, rsdp); + + rb_destroy(rb_types); + rb_destroy(rb_addrs); + + printf("done.\n"); +} diff --git a/contrib/syslinux-4.02/com32/sysdump/backend.h b/contrib/syslinux-4.02/com32/sysdump/backend.h new file mode 100644 index 0000000..f2b3bc2 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/backend.h @@ -0,0 +1,55 @@ +#ifndef BACKEND_H +#define BACKEND_H + +#include <stddef.h> +#include <inttypes.h> +#include <stdbool.h> +#include <zlib.h> +#include "serial.h" + +/* Backend flags */ +#define BE_NEEDLEN 0x01 + +struct backend { + const char *name; + const char *helpmsg; + int minargs; + + size_t dbytes; + size_t zbytes; + const char **argv; + + uint32_t now; + + int (*write)(struct backend *); + + z_stream zstream; + char *outbuf; + size_t alloc; +}; + +/* zout.c */ +int init_data(struct backend *be, const char *argv[]); +int write_data(struct backend *be, const void *buf, size_t len); +int flush_data(struct backend *be); + +/* cpio.c */ +#define cpio_init init_data +int cpio_hdr(struct backend *be, uint32_t mode, size_t datalen, + const char *filename); +int cpio_mkdir(struct backend *be, const char *filename); +int cpio_writefile(struct backend *be, const char *filename, + const void *data, size_t len); +int cpio_close(struct backend *be); +#define MODE_FILE 0100644 +#define MODE_DIR 0040755 + +/* backends.c */ +struct backend *get_backend(const char *name); + +/* backends */ +extern struct backend be_tftp; +extern struct backend be_ymodem; +extern struct backend be_srec; + +#endif /* BACKEND_H */ diff --git a/contrib/syslinux-4.02/com32/sysdump/be_srec.c b/contrib/syslinux-4.02/com32/sysdump/be_srec.c new file mode 100644 index 0000000..fc69c88 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/be_srec.c @@ -0,0 +1,85 @@ +/* + * S-records dump routine -- dumps S-records on the console + */ + +#include <string.h> +#include <stdio.h> +#include <inttypes.h> +#include <minmax.h> +#include "backend.h" + +/* Write a single S-record */ +static int write_srecord(unsigned int len, unsigned int alen, + uint32_t addr, uint8_t type, const void *data) +{ + char buf[2+2+8+255*2+2+2]; + char *p = buf; + uint8_t csum; + const uint8_t *dptr = data; + unsigned int i; + + switch (alen) { + case 2: + addr &= 0xffff; + break; + case 3: + addr &= 0xffffff; + break; + case 4: + break; + } + + csum = (len+alen+1) + addr + (addr >> 8) + (addr >> 16) + (addr >> 24); + for (i = 0; i < len; i++) + csum += dptr[i]; + csum = 0xff-csum; + + p += sprintf(p, "S%c%02X%0*X", type, len+alen+1, alen*2, addr); + for (i = 0; i < len; i++) + p += sprintf(p, "%02X", dptr[i]); + p += sprintf(p, "%02X\n", csum); + + fputs(buf, stdout); + return 0; +} + +static int be_srec_write(struct backend *be) +{ + char name[33]; + const char *buf; + size_t len, chunk, offset, hdrlen; + + buf = be->outbuf; + len = be->zbytes; + + putchar('\n'); + + hdrlen = snprintf(name, sizeof name, "%.32s", + be->argv[0] ? be->argv[0] : ""); + + /* Write head record */ + write_srecord(hdrlen, 2, 0, '0', name); + + /* Write data records */ + offset = 0; + while (len) { + chunk = min(len, (size_t)32); + + write_srecord(chunk, 4, offset, '3', buf); + buf += chunk; + len -= chunk; + offset += chunk; + } + + /* Write termination record */ + write_srecord(0, 4, 0, '7', NULL); + + return 0; +} + +struct backend be_srec = { + .name = "srec", + .helpmsg = "[filename]", + .minargs = 0, + .write = be_srec_write, +}; diff --git a/contrib/syslinux-4.02/com32/sysdump/be_tftp.c b/contrib/syslinux-4.02/com32/sysdump/be_tftp.c new file mode 100644 index 0000000..36a91eb --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/be_tftp.c @@ -0,0 +1,178 @@ +/* + * TFTP data output backend + */ + +#include <string.h> +#include <stdio.h> +#include <syslinux/pxe.h> +#include <syslinux/config.h> +#include <netinet/in.h> +#include <sys/times.h> + +#include "backend.h" + +enum tftp_opcode { + TFTP_RRQ = 1, + TFTP_WRQ = 2, + TFTP_DATA = 3, + TFTP_ACK = 4, + TFTP_ERROR = 5, +}; + +struct tftp_state { + uint32_t my_ip; + uint32_t srv_ip; + uint32_t srv_gw; + uint16_t my_port; + uint16_t srv_port; + uint16_t seq; +}; + +#define RCV_BUF 2048 + +static int send_ack_packet(struct tftp_state *tftp, + const void *pkt, size_t len) +{ + com32sys_t ireg, oreg; + t_PXENV_UDP_WRITE *uw; + t_PXENV_UDP_READ *ur; + clock_t start; + static const clock_t timeouts[] = { + 2, 2, 3, 3, 4, 5, 6, 7, 9, 10, 12, 15, 18, 21, 26, 31, + 37, 44, 53, 64, 77, 92, 110, 132, 159, 191, 229, 0 + }; + const clock_t *timeout; + int err = -1; + + uw = lmalloc(sizeof *uw + len); + ur = lmalloc(sizeof *ur + RCV_BUF); + + memset(&ireg, 0, sizeof ireg); + ireg.eax.w[0] = 0x0009; + + for (timeout = timeouts ; *timeout ; timeout++) { + memset(uw, 0, sizeof uw); + memcpy(uw+1, pkt, len); + uw->ip = tftp->srv_ip; + uw->gw = tftp->srv_gw; + uw->src_port = tftp->my_port; + uw->dst_port = tftp->srv_port ? tftp->srv_port : htons(69); + uw->buffer_size = len; + uw->buffer = FAR_PTR(uw+1); + + ireg.ebx.w[0] = PXENV_UDP_WRITE; + ireg.es = SEG(uw); + ireg.edi.w[0] = OFFS(uw); + + __intcall(0x22, &ireg, &oreg); + + start = times(NULL); + + do { + memset(ur, 0, sizeof ur); + ur->src_ip = tftp->srv_ip; + ur->dest_ip = tftp->my_ip; + ur->s_port = tftp->srv_port; + ur->d_port = tftp->my_port; + ur->buffer_size = RCV_BUF; + ur->buffer = FAR_PTR(ur+1); + + ireg.ebx.w[0] = PXENV_UDP_READ; + ireg.es = SEG(ur); + ireg.edi.w[0] = OFFS(ur); + __intcall(0x22, &ireg, &oreg); + + if (!(oreg.eflags.l & EFLAGS_CF) && + ur->status == PXENV_STATUS_SUCCESS && + tftp->srv_ip == ur->src_ip && + (tftp->srv_port == 0 || + tftp->srv_port == ur->s_port)) { + uint16_t *xb = (uint16_t *)(ur+1); + if (ntohs(xb[0]) == TFTP_ACK && + ntohs(xb[1]) == tftp->seq) { + tftp->srv_port = ur->s_port; + err = 0; /* All good! */ + goto done; + } else if (ntohs(xb[1]) == TFTP_ERROR) { + goto done; + } + } + } while ((clock_t)(times(NULL) - start) < *timeout); + } + +done: + lfree(ur); + lfree(uw); + + return err; +} + +static int be_tftp_write(struct backend *be) +{ + static uint16_t local_port = 0x4000; + struct tftp_state tftp; + char buffer[512+4+6]; + int nlen; + const union syslinux_derivative_info *sdi = + syslinux_derivative_info(); + const char *data = be->outbuf; + size_t len = be->zbytes; + size_t chunk; + + tftp.my_ip = sdi->pxe.myip; + tftp.my_port = htons(local_port++); + tftp.srv_gw = ((tftp.srv_ip ^ tftp.my_ip) & sdi->pxe.ipinfo->netmask) + ? sdi->pxe.ipinfo->gateway : 0; + tftp.srv_port = 0; + tftp.seq = 0; + + if (be->argv[1]) { + tftp.srv_ip = pxe_dns(be->argv[1]); + if (!tftp.srv_ip) { + printf("\nUnable to resolve hostname: %s\n", be->argv[1]); + return -1; + } + } else { + tftp.srv_ip = sdi->pxe.ipinfo->serverip; + if (!tftp.srv_ip) { + printf("\nNo server IP address\n"); + return -1; + } + } + + printf("server %u.%u.%u.%u... ", + ((uint8_t *)&tftp.srv_ip)[0], + ((uint8_t *)&tftp.srv_ip)[1], + ((uint8_t *)&tftp.srv_ip)[2], + ((uint8_t *)&tftp.srv_ip)[3]); + + buffer[0] = 0; + buffer[1] = TFTP_WRQ; + nlen = strlcpy(buffer+2, be->argv[0], 512); + memcpy(buffer+3+nlen, "octet", 6); + + if (send_ack_packet(&tftp, buffer, 2+nlen+1+6)) + return -1; + + do { + chunk = len >= 512 ? 512 : len; + + buffer[1] = TFTP_DATA; + *((uint16_t *)(buffer+2)) = htons(++tftp.seq); + memcpy(buffer+4, data, chunk); + data += chunk; + len -= chunk; + + if (send_ack_packet(&tftp, buffer, chunk+4)) + return -1; + } while (chunk == 512); + + return 0; +} + +struct backend be_tftp = { + .name = "tftp", + .helpmsg = "filename [tftp_server]", + .minargs = 1, + .write = be_tftp_write, +}; diff --git a/contrib/syslinux-4.02/com32/sysdump/be_ymodem.c b/contrib/syslinux-4.02/com32/sysdump/be_ymodem.c new file mode 100644 index 0000000..316b3d4 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/be_ymodem.c @@ -0,0 +1,175 @@ +/* + * Ymodem send routine. Only supports 1K blocks and CRC mode. + */ + +#include <string.h> +#include <stdio.h> +#include <inttypes.h> +#include "backend.h" +#include "serial.h" + +enum { + SOH = 0x01, + STX = 0x02, + EOT = 0x04, + ACK = 0x06, + NAK = 0x15, + CAN = 0x18, +}; + +struct ymodem_state { + struct serial_if serial; + unsigned int seq, blocks; +}; + +/* + * Append a CRC16 to a block + */ +static void add_crc16(uint8_t * blk, int len) +{ + static const uint16_t crctab[256] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, + 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, + 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, + 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, + 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, + 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, + 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, + 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, + 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, + 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, + 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, + 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, + 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, + 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, + 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, + 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, + 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 + }; + uint16_t crc = 0; + + while (len--) + crc = crctab[(crc >> 8) ^ *blk++] ^ crc << 8; + + *blk++ = crc >> 8; + *blk = crc; +} + +static void send_ack(struct ymodem_state *ym, const uint8_t *blk, + size_t bytes); + +static void send_ack_blk(struct ymodem_state *ym, uint8_t *blk) +{ + printf("Sending block %u/%u...\r", ym->seq, ym->blocks); + + blk[0] = STX; + blk[1] = ym->seq++; + blk[2] = ~blk[1]; + add_crc16(blk+3, 1024); + + send_ack(ym, blk, 1024+5); +} + +static void send_ack(struct ymodem_state *ym, const uint8_t *blk, size_t bytes) +{ + uint8_t ack_buf; + + do { + serial_write(&ym->serial, blk, bytes); + + do { + serial_read(&ym->serial, &ack_buf, 1); + } while (ack_buf != ACK && ack_buf != NAK); + } while (ack_buf == NAK); +} + +static int be_ymodem_write(struct backend *be) +{ + static const uint8_t eot_buf = EOT; + uint8_t ack_buf; + uint8_t blk_buf[1024 + 5]; + struct ymodem_state ym; + const char *buf; + size_t len, chunk; + const char ymodem_banner[] = "Now begin Ymodem download...\r\n"; + + buf = be->outbuf; + len = be->zbytes; + + putchar('\n'); + + ym.seq = 0; + ym.blocks = (len+1023)/1024; + + /* Initialize serial port */ + if (serial_init(&ym.serial, &be->argv[1])) + return -1; + + /* Write banner */ + printf("Writing banner...\n"); + serial_write(&ym.serial, ymodem_banner, sizeof ymodem_banner-1); + + /* Wait for initial handshake */ + printf("Waiting for handshake...\n"); + do { + serial_read(&ym.serial, &ack_buf, 1); + } while (ack_buf != 'C'); + + /* Send filename block */ + memset(blk_buf, 0, sizeof blk_buf); + snprintf((char *)blk_buf+3, 1024, "%s%c%zu 0%o 0644", + be->argv[0], 0, be->zbytes, be->now); + send_ack_blk(&ym, blk_buf); + + while (len) { + chunk = len < 1024 ? len : 1024; + + memcpy(blk_buf+3, buf, chunk); + if (chunk < 1024) + memset(blk_buf+3+chunk, 0x1a, 1024-chunk); + + send_ack_blk(&ym, blk_buf); + buf += chunk; + len -= chunk; + } + + printf("\nSending EOT...\n"); + send_ack(&ym, &eot_buf, 1); + + printf("Waiting for handshake...\n"); + do { + serial_read(&ym.serial, &ack_buf, 1); + } while (ack_buf != 'C'); + ym.seq = 0; + + printf("Sending batch termination block...\n"); + memset(blk_buf+3, 0, 1024); + send_ack_blk(&ym, blk_buf); + + printf("Cleaning up... \n"); + serial_cleanup(&ym.serial); + + return 0; +} + +struct backend be_ymodem = { + .name = "ymodem", + .helpmsg = "filename [port [speed]]", + .minargs = 1, + .write = be_ymodem_write, +}; diff --git a/contrib/syslinux-4.02/com32/sysdump/cpio.c b/contrib/syslinux-4.02/com32/sysdump/cpio.c new file mode 100644 index 0000000..81d0d4b --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/cpio.c @@ -0,0 +1,75 @@ +/* + * cpio.c + * + * Write a compressed CPIO file + */ + +#include <stdio.h> +#include <string.h> +#include <inttypes.h> +#include <stdbool.h> +#include <zlib.h> +#include "backend.h" +#include "ctime.h" + +int cpio_pad(struct backend *be) +{ + static char pad[4]; /* Up to 4 zero bytes */ + if (be->dbytes & 3) + return write_data(be, pad, -be->dbytes & 3); + else + return 0; +} + +int cpio_hdr(struct backend *be, uint32_t mode, size_t datalen, + const char *filename) +{ + static uint32_t inode = 2; + char hdr[6+13*8+1]; + int nlen = strlen(filename)+1; + int rv = 0; + + cpio_pad(be); + + sprintf(hdr, "%06o%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x", + 070701, /* c_magic */ + inode++, /* c_ino */ + mode, /* c_mode */ + 0, /* c_uid */ + 0, /* c_gid */ + 1, /* c_nlink */ + be->now, /* c_mtime */ + datalen, /* c_filesize */ + 0, /* c_maj */ + 0, /* c_min */ + 0, /* c_rmaj */ + 0, /* c_rmin */ + nlen, /* c_namesize */ + 0); /* c_chksum */ + rv |= write_data(be, hdr, 6+13*8); + rv |= write_data(be, filename, nlen); + rv |= cpio_pad(be); + return rv; +} + +int cpio_mkdir(struct backend *be, const char *filename) +{ + return cpio_hdr(be, MODE_DIR, 0, filename); +} + +int cpio_writefile(struct backend *be, const char *filename, + const void *data, size_t len) +{ + int rv; + + rv = cpio_hdr(be, MODE_FILE, len, filename); + rv |= write_data(be, data, len); + rv |= cpio_pad(be); + + return rv; +} + +int cpio_close(struct backend *be) +{ + return cpio_hdr(be, 0, 0, "TRAILER!!!"); +} diff --git a/contrib/syslinux-4.02/com32/sysdump/cpuid.c b/contrib/syslinux-4.02/com32/sysdump/cpuid.c new file mode 100644 index 0000000..372a70d --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/cpuid.c @@ -0,0 +1,91 @@ +/* + * Dump CPUID information + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <com32.h> +#include <sys/cpu.h> +#include "sysdump.h" +#include "backend.h" + +struct cpuid_data { + uint32_t eax, ebx, ecx, edx; +}; + +struct cpuid_info { + uint32_t eax, ecx; + struct cpuid_data data; +}; + +static void get_cpuid(uint32_t eax, uint32_t ecx, struct cpuid_data *data) +{ + asm("pushl %%ebx ; cpuid ; movl %%ebx,%1 ; popl %%ebx" + : "=a" (data->eax), "=r" (data->ebx), + "=c" (data->ecx), "=d" (data->edx) + : "a" (eax), "c" (ecx)); +} + +#define CPUID_CHUNK 128 + +void dump_cpuid(struct backend *be) +{ + struct cpuid_info *buf = NULL; + int nentry, nalloc; + uint32_t region; + struct cpuid_data base_leaf; + uint32_t base, leaf, count; + struct cpuid_data invalid_leaf; + struct cpuid_data data; + + if (!cpu_has_eflag(EFLAGS_ID)) + return; + + printf("Dumping CPUID... "); + + nentry = nalloc = 0; + + /* Find out what the CPU returns for invalid leaves */ + get_cpuid(0, 0, &base_leaf); + get_cpuid(base_leaf.eax+1, 0, &invalid_leaf); + + for (region = 0 ; region <= 0xffff ; region++) { + base = region << 16; + + get_cpuid(base, 0, &base_leaf); + if (region && !memcmp(&base_leaf, &invalid_leaf, sizeof base_leaf)) + continue; + + if ((base_leaf.eax ^ base) & 0xffff0000) + continue; + + for (leaf = base ; leaf <= base_leaf.eax ; leaf++) { + get_cpuid(leaf, 0, &data); + count = 0; + + do { + if (nentry >= nalloc) { + nalloc += CPUID_CHUNK; + buf = realloc(buf, nalloc*sizeof *buf); + if (!buf) + return; /* FAILED */ + } + buf[nentry].eax = leaf; + buf[nentry].ecx = count; + buf[nentry].data = data; + nentry++; + count++; + + get_cpuid(leaf, count, &data); + } while (memcmp(&data, &buf[nentry-1].data, sizeof data) && + (data.eax | data.ebx | data.ecx | data.edx)); + } + } + + if (nentry) + cpio_writefile(be, "cpuid", buf, nentry*sizeof *buf); + free(buf); + + printf("done.\n"); +} diff --git a/contrib/syslinux-4.02/com32/sysdump/ctime.c b/contrib/syslinux-4.02/com32/sysdump/ctime.c new file mode 100644 index 0000000..56c8efb --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/ctime.c @@ -0,0 +1,77 @@ +#include <com32.h> +#include <string.h> +#include "ctime.h" + +static uint8_t frombcd(uint8_t v) +{ + uint8_t a = v & 0x0f; + uint8_t b = v >> 4; + + return a + b*10; +} + +uint32_t posix_time(void) +{ + /* Days from March 1 for a specific month, starting in March */ + static const unsigned int yday[12] = + { 0, 31, 61, 92, 122, 153, 184, 214, 245, 275, 306, 337 }; + com32sys_t ir, d0, d1, t0; + unsigned int c, y, mo, d, h, m, s; + uint32_t t; + + memset(&ir, 0, sizeof ir); + + ir.eax.b[1] = 0x04; + __intcall(0x1A, &ir, &d0); + + ir.eax.b[1] = 0x02; + __intcall(0x1A, &ir, &t0); + + ir.eax.b[1] = 0x04; + __intcall(0x1A, &ir, &d1); + + if (t0.ecx.b[1] < 0x12) + d0 = d1; + + c = frombcd(d0.ecx.b[1]); + y = frombcd(d0.ecx.b[0]); + mo = frombcd(d0.edx.b[1]); + d = frombcd(d0.edx.b[0]); + + h = frombcd(t0.ecx.b[1]); + m = frombcd(t0.ecx.b[0]); + s = frombcd(t0.edx.b[1]); + + /* We of course have no idea about the timezone, so ignore it */ + + /* + * Look for impossible dates... this code was written in 2010, so + * assume any century less than 20 is just broken. + */ + if (c < 20) + c = 20; + y += c*100; + + /* Consider Jan and Feb as the last months of the previous year */ + if (mo < 3) { + y--; + mo += 12; + } + + /* + * Just in case: if the month is nonsense, don't read off the end + * of the table... + */ + if (mo-3 > 11) + return 0; + + t = y*365 + y/4 - y/100 + y/400 + yday[mo-3] + d - 719469; + t *= 24; + t += h; + t *= 60; + t += m; + t *= 60; + t += s; + + return t; +} diff --git a/contrib/syslinux-4.02/com32/sysdump/ctime.h b/contrib/syslinux-4.02/com32/sysdump/ctime.h new file mode 100644 index 0000000..e646125 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/ctime.h @@ -0,0 +1,8 @@ +#ifndef CTIME_H +#define CTIME_H + +#include <inttypes.h> + +uint32_t posix_time(void); + +#endif /* CTIME_H */ diff --git a/contrib/syslinux-4.02/com32/sysdump/data.h b/contrib/syslinux-4.02/com32/sysdump/data.h new file mode 100644 index 0000000..deacf72 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/data.h @@ -0,0 +1,2 @@ +#ifndef DATA_H +#define DATA_H diff --git a/contrib/syslinux-4.02/com32/sysdump/dmi.c b/contrib/syslinux-4.02/com32/sysdump/dmi.c new file mode 100644 index 0000000..be4cce4 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/dmi.c @@ -0,0 +1,126 @@ +/* + * Dump DMI information in a way hopefully compatible with dmidecode + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include "sysdump.h" +#include "backend.h" + +struct dmi_header { + char signature[5]; + uint8_t csum; + uint16_t tbllen; + uint32_t tbladdr; + uint16_t nstruc; + uint8_t revision; + uint8_t reserved; +}; + +struct smbios_header { + char signature[4]; + uint8_t csum; + uint8_t len; + uint8_t major; + uint8_t minor; + uint16_t maxsize; + uint8_t revision; + uint8_t fmt[5]; + + struct dmi_header dmi; +}; + +static uint8_t checksum(const void *buf, size_t len) +{ + const uint8_t *p = buf; + uint8_t csum = 0; + + while (len--) + csum += *p++; + + return csum; +} + +static bool is_old_dmi(size_t dptr) +{ + const struct dmi_header *dmi = (void *)dptr; + + return !memcmp(dmi->signature, "_DMI_", 5) && + !checksum(dmi, 0x0f); + return false; +} + +static bool is_smbios(size_t dptr) +{ + const struct smbios_header *smb = (void *)dptr; + + return !memcmp(smb->signature, "_SM_", 4) && + !checksum(smb, smb->len) && + is_old_dmi(dptr+16); +} + +static void dump_smbios(struct backend *be, size_t dptr) +{ + const struct smbios_header *smb = (void *)dptr; + struct smbios_header smx = *smb; + char filename[32]; + + snprintf(filename, sizeof filename, "dmi/%05x.%08x", + dptr, smb->dmi.tbladdr); + cpio_hdr(be, MODE_FILE, smb->dmi.tbllen + 32, filename); + + /* + * Adjust the address of the smbios table to be 32, to + * make dmidecode happy. The checksum on the smbios table is unchanged, + * since it includes the checksum on the dmi table. + */ + smx.dmi.tbladdr = sizeof smx; + smx.dmi.csum -= checksum(&smx.dmi, 0x0f); + + write_data(be, &smx, sizeof smx); + write_data(be, (const void *)smb->dmi.tbladdr, smb->dmi.tbllen); +} + +static void dump_old_dmi(struct backend *be, size_t dptr) +{ + const struct dmi_header *dmi = (void *)dptr; + struct fake { + struct dmi_header dmi; + char pad[16]; + } fake; + char filename[32]; + + snprintf(filename, sizeof filename, "dmi/%05x.%08x", + dptr, dmi->tbladdr); + cpio_hdr(be, MODE_FILE, dmi->tbllen + 32, filename); + + /* + * Adjust the address of the smbios table to be 32, to + * make dmidecode happy. + */ + fake.dmi = *dmi; + memset(&fake.pad, 0, sizeof fake.pad); + fake.dmi.tbladdr = sizeof fake; + fake.dmi.csum -= checksum(&fake.dmi, 0x0f); + + write_data(be, &fake, sizeof fake); + write_data(be, (const void *)dmi->tbladdr, dmi->tbllen); +} + +void dump_dmi(struct backend *be) +{ + size_t dptr; + + cpio_mkdir(be, "dmi"); + + /* Search for _SM_ or _DMI_ structure */ + for (dptr = 0xf0000 ; dptr < 0x100000 ; dptr += 16) { + if (is_smbios(dptr)) { + dump_smbios(be, dptr); + dptr += 16; /* Skip the subsequent DMI header */ + } else if (is_old_dmi(dptr)) { + dump_old_dmi(be, dptr); + } + } +} diff --git a/contrib/syslinux-4.02/com32/sysdump/main.c b/contrib/syslinux-4.02/com32/sysdump/main.c new file mode 100644 index 0000000..d0d40a7 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/main.c @@ -0,0 +1,99 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2010 Intel Corporation; author: H. Peter Anvin + * + * 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 <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <stdbool.h> +#include <inttypes.h> +#include <dprintf.h> +#include <console.h> +#include <sys/cpu.h> +#include "../../version.h" +#include "backend.h" +#include "sysdump.h" + +const char program[] = "sysdump"; +const char version[] = "SYSDUMP " VERSION_STR " " DATE "\n"; + +__noreturn die(const char *msg) +{ + printf("%s: %s\n", program, msg); + exit(1); +} + +static void dump_all(struct backend *be, const char *argv[]) +{ + cpio_init(be, argv); + + cpio_writefile(be, "sysdump", version, sizeof version-1); + + dump_memory_map(be); + dump_memory(be); + dump_dmi(be); + dump_acpi(be); + dump_cpuid(be); + dump_pci(be); + dump_vesa_tables(be); + + cpio_close(be); + flush_data(be); +} + +static struct backend *backends[] = +{ + &be_tftp, + &be_ymodem, + &be_srec, + NULL +}; + +__noreturn usage(void) +{ + struct backend **bep, *be; + + printf("Usage:\n"); + for (bep = backends ; (be = *bep) ; bep++) + printf(" %s %s %s\n", program, be->name, be->helpmsg); + + exit(1); +} + +int main(int argc, char *argv[]) +{ + struct backend **bep, *be; + + openconsole(&dev_null_r, &dev_stdcon_w); + fputs(version, stdout); + + if (argc < 2) + usage(); + + for (bep = backends ; (be = *bep) ; bep++) { + if (!strcmp(be->name, argv[1])) + break; + } + + if (!be || argc < be->minargs + 2) + usage(); + + /* Do this as early as possible */ + snapshot_lowmem(); + + printf("Backend: %s\n", be->name); + + /* Do the actual data dump */ + dump_all(be, (const char **)argv + 2); + + return 0; +} diff --git a/contrib/syslinux-4.02/com32/sysdump/memmap.c b/contrib/syslinux-4.02/com32/sysdump/memmap.c new file mode 100644 index 0000000..251107d --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/memmap.c @@ -0,0 +1,85 @@ +/* + * Dump memory map information + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <com32.h> +#include "sysdump.h" +#include "backend.h" + +#define E820_CHUNK 128 +struct e820_info { + uint32_t ebx; + uint32_t len; + uint8_t data[24]; +}; + +static void dump_e820(struct backend *be) +{ + com32sys_t ireg, oreg; + struct e820_info *curr; + struct e820_info *buf, *p; + int nentry, nalloc; + + curr = lmalloc(sizeof *curr); + + buf = p = NULL; + nentry = nalloc = 0; + memset(&ireg, 0, sizeof ireg); + memset(&curr, 0, sizeof curr); + + ireg.eax.l = 0xe820; + ireg.edx.l = 0x534d4150; + ireg.ecx.l = sizeof curr->data; + ireg.es = SEG(curr->data); + ireg.edi.w[0] = OFFS(curr->data); + + do { + __intcall(0x15, &ireg, &oreg); + if ((oreg.eflags.l & EFLAGS_CF) || + oreg.eax.l != 0x534d4150) + break; + + if (nentry >= nalloc) { + nalloc += E820_CHUNK; + buf = realloc(buf, nalloc*sizeof *buf); + if (!buf) + return; /* FAILED */ + } + memcpy(buf[nentry].data, curr->data, sizeof curr->data); + buf[nentry].ebx = ireg.ebx.l; + buf[nentry].len = oreg.ecx.l; + nentry++; + + ireg.ebx.l = oreg.ebx.l; + } while (ireg.ebx.l); + + if (nentry) + cpio_writefile(be, "memmap/15e820", buf, nentry*sizeof *buf); + + free(buf); + lfree(curr); +} + +void dump_memory_map(struct backend *be) +{ + com32sys_t ireg, oreg; + + cpio_mkdir(be, "memmap"); + + memset(&ireg, 0, sizeof ireg); + __intcall(0x12, &ireg, &oreg); + cpio_writefile(be, "memmap/12", &oreg, sizeof oreg); + + ireg.eax.b[1] = 0x88; + __intcall(0x15, &ireg, &oreg); + cpio_writefile(be, "memmap/1588", &oreg, sizeof oreg); + + ireg.eax.w[0] = 0xe801; + __intcall(0x15, &ireg, &oreg); + cpio_writefile(be, "memmap/15e801", &oreg, sizeof oreg); + + dump_e820(be); +} diff --git a/contrib/syslinux-4.02/com32/sysdump/memory.c b/contrib/syslinux-4.02/com32/sysdump/memory.c new file mode 100644 index 0000000..6552e7f --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/memory.c @@ -0,0 +1,51 @@ +/* + * Dump memory + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <sys/cpu.h> +#include "sysdump.h" +#include "backend.h" + +static char *lowmem; +static size_t lowmem_len; + +void *zero_addr; /* Hack to keep gcc from complaining */ + +void snapshot_lowmem(void) +{ + extern void _start(void); + + lowmem_len = (size_t)_start; + lowmem = malloc(lowmem_len); + if (lowmem) { + printf("Snapshotting lowmem... "); + cli(); + memcpy(lowmem, zero_addr, lowmem_len); + sti(); + printf("ok\n"); + } +} + +static void dump_memory_range(struct backend *be, const void *where, + const void *addr, size_t len) +{ + char filename[32]; + + sprintf(filename, "memory/%08zx", (size_t)addr); + cpio_writefile(be, filename, where, len); +} + +void dump_memory(struct backend *be) +{ + printf("Dumping memory... "); + + cpio_mkdir(be, "memory"); + + if (lowmem) + dump_memory_range(be, lowmem, zero_addr, lowmem_len); + + printf("done.\n"); +} diff --git a/contrib/syslinux-4.02/com32/sysdump/pci.c b/contrib/syslinux-4.02/com32/sysdump/pci.c new file mode 100644 index 0000000..1d68727 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/pci.c @@ -0,0 +1,70 @@ +/* + * Dump PCI device headers + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <sys/pci.h> +#include "sysdump.h" +#include "backend.h" + +static void dump_pci_device(struct backend *be, pciaddr_t a, uint8_t hdrtype) +{ + unsigned int bus = pci_bus(a); + unsigned int dev = pci_dev(a); + unsigned int func = pci_func(a); + uint8_t data[256]; + unsigned int i; + char filename[32]; + + hdrtype &= 0x7f; + + printf("Scanning PCI bus... %02x:%02x.%x\r", bus, dev, func); + + /* Assume doing a full device dump is actually safe... */ + for (i = 0; i < sizeof data; i += 4) + *(uint32_t *)(data+i) = pci_readl(a + i); + + snprintf(filename, sizeof filename, "pci/%02x:%02x.%x", + bus, dev, func); + cpio_writefile(be, filename, data, sizeof data); +} + +void dump_pci(struct backend *be) +{ + int cfgtype; + unsigned int nbus, ndev, nfunc, maxfunc; + pciaddr_t a; + uint32_t did; + uint8_t hdrtype; + + cfgtype = pci_set_config_type(PCI_CFG_AUTO); + if (cfgtype == PCI_CFG_NONE) + return; + + cpio_mkdir(be, "pci"); + + for (nbus = 0; nbus < MAX_PCI_BUSES; nbus++) { + for (ndev = 0; ndev < MAX_PCI_DEVICES; ndev++) { + maxfunc = 1; /* Assume a single-function device */ + + for (nfunc = 0; nfunc < maxfunc; nfunc++) { + a = pci_mkaddr(nbus, ndev, nfunc, 0); + did = pci_readl(a); + + if (did == 0xffffffff || did == 0xffff0000 || + did == 0x0000ffff || did == 0x00000000) + continue; + + hdrtype = pci_readb(a + 0x0e); + if (hdrtype & 0x80) + maxfunc = MAX_PCI_FUNC; /* Multifunction device */ + + dump_pci_device(be, a, hdrtype); + } + } + } + + printf("Scanning PCI bus... done. \n"); +} diff --git a/contrib/syslinux-4.02/com32/sysdump/rbtree.c b/contrib/syslinux-4.02/com32/sysdump/rbtree.c new file mode 100644 index 0000000..1d10e09 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/rbtree.c @@ -0,0 +1,132 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1996-2009 The NASM Authors - All Rights Reserved + * See the file AUTHORS included with the NASM distribution for + * the specific copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following + * conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + * + * ----------------------------------------------------------------------- */ + +/* + * rbtree.c + * + * Simple implementation of a left-leaning red-black tree with 64-bit + * integer keys. The search operation will return the highest node <= + * the key; only search and insert are supported, but additional + * standard llrbtree operations can be coded up at will. + * + * See http://www.cs.princeton.edu/~rs/talks/LLRB/RedBlack.pdf for + * information about left-leaning red-black trees. + */ + +#include <stdlib.h> +#include "rbtree.h" + +struct rbtree *rb_search(struct rbtree *tree, uint64_t key) +{ + struct rbtree *best = NULL; + + while (tree) { + if (tree->key == key) + return tree; + else if (tree->key > key) + tree = tree->left; + else { + best = tree; + tree = tree->right; + } + } + return best; +} + +static bool is_red(struct rbtree *h) +{ + return h && h->red; +} + +static struct rbtree *rotate_left(struct rbtree *h) +{ + struct rbtree *x = h->right; + h->right = x->left; + x->left = h; + x->red = x->left->red; + x->left->red = true; + return x; +} + +static struct rbtree *rotate_right(struct rbtree *h) +{ + struct rbtree *x = h->left; + h->left = x->right; + x->right = h; + x->red = x->right->red; + x->right->red = true; + return x; +} + +static void color_flip(struct rbtree *h) +{ + h->red = !h->red; + h->left->red = !h->left->red; + h->right->red = !h->right->red; +} + +struct rbtree *rb_insert(struct rbtree *tree, struct rbtree *node) +{ + node->left = node->right = NULL; + node->red = false; + + if (!tree) { + node->red = true; + return node; + } + + if (is_red(tree->left) && is_red(tree->right)) + color_flip(tree); + + if (node->key < tree->key) + tree->left = rb_insert(tree->left, node); + else + tree->right = rb_insert(tree->right, node); + + if (is_red(tree->right)) + tree = rotate_left(tree); + + if (is_red(tree->left) && is_red(tree->left->left)) + tree = rotate_right(tree); + + return tree; +} + +void rb_destroy(struct rbtree *tree) +{ + if (tree->left) + rb_destroy(tree->left); + if (tree->right) + rb_destroy(tree->right); + free(tree); +} diff --git a/contrib/syslinux-4.02/com32/sysdump/rbtree.h b/contrib/syslinux-4.02/com32/sysdump/rbtree.h new file mode 100644 index 0000000..dcdcd6b --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/rbtree.h @@ -0,0 +1,53 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1996-2009 The NASM Authors - All Rights Reserved + * See the file AUTHORS included with the NASM distribution for + * the specific copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following + * conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + * + * ----------------------------------------------------------------------- */ + +#ifndef NASM_RBTREE_H +#define NASM_RBTREE_H + +#include <inttypes.h> +#include <stdbool.h> + +/* This structure should be embedded in a larger data structure; + the final output from rb_search() can then be converted back + to the larger data structure via container_of(). */ +struct rbtree { + uint64_t key; + struct rbtree *left, *right; + bool red; +}; + +struct rbtree *rb_insert(struct rbtree *, struct rbtree *); +struct rbtree *rb_search(struct rbtree *, uint64_t); +void rb_destroy(struct rbtree *); + +#endif /* NASM_RBTREE_H */ diff --git a/contrib/syslinux-4.02/com32/sysdump/serial.c b/contrib/syslinux-4.02/com32/sysdump/serial.c new file mode 100644 index 0000000..a398753 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/serial.c @@ -0,0 +1,169 @@ +#include <stdbool.h> +#include <stdlib.h> +#include <stdio.h> +#include <console.h> +#include <sys/io.h> +#include <sys/cpu.h> +#include <syslinux/config.h> + +#include "serial.h" + +enum { + THR = 0, + RBR = 0, + DLL = 0, + DLM = 1, + IER = 1, + IIR = 2, + FCR = 2, + LCR = 3, + MCR = 4, + LSR = 5, + MSR = 6, + SCR = 7, +}; + + +int serial_init(struct serial_if *sif, const char *argv[]) +{ + const struct syslinux_serial_console_info *sci + = syslinux_serial_console_info(); + uint16_t port; + unsigned int divisor; + uint8_t dll, dlm, lcr; + + if (!argv[0]) { + if (sci->iobase) { + port = sci->iobase; + } else { + printf("No port number specified and not using serial console!\n"); + return -1; + } + } else { + port = strtoul(argv[0], NULL, 0); + if (port <= 3) { + uint16_t addr = ((uint16_t *)0x400)[port]; + if (!addr) { + printf("No serial port address found!\n"); + return -1; + } + printf("Serial port %u is at 0x%04x\n", port, addr); + port = addr; + } + } + + sif->port = port; + sif->console = false; + + divisor = 1; /* Default speed = 115200 bps */ + + /* Check to see if this is the same as the serial console */ + if (port == sci->iobase) { + /* Overlaying the console... */ + sif->console = true; + + /* Default to already configured speed */ + divisor = sci->divisor; + + /* Shut down I/O to the console for the time being */ + openconsole(&dev_null_r, &dev_null_w); + } + + if (argv[0] && argv[1]) + divisor = 115200/strtoul(argv[1], NULL, 0); + + cli(); /* Just in case... */ + + /* Save old register settings */ + sif->old.lcr = inb(port + LCR); + sif->old.mcr = inb(port + MCR); + sif->old.iir = inb(port + IIR); + + /* Set speed */ + outb(0x83, port + LCR); /* Enable divisor access */ + sif->old.dll = inb(port + DLL); + sif->old.dlm = inb(port + DLM); + outb(divisor, port + DLL); + outb(divisor >> 8, port + DLM); + (void)inb(port + IER); /* Synchronize */ + + dll = inb(port + DLL); + dlm = inb(port + DLM); + lcr = inb(port + LCR); + outb(0x03, port + LCR); /* Enable data access, n81 */ + (void)inb(port + IER); /* Synchronize */ + sif->old.ier = inb(port + IER); + + /* Disable interrupts */ + outb(0, port + IER); + + sti(); + + if (dll != (uint8_t)divisor || + dlm != (uint8_t)(divisor >> 8) || + lcr != 0x83) { + serial_cleanup(sif); + printf("No serial port detected!\n"); + return -1; /* This doesn't look like a serial port */ + } + + /* Enable 16550A FIFOs if available */ + outb(0x01, port + FCR); /* Enable FIFO */ + (void)inb(port + IER); /* Synchronize */ + if (inb(port + IIR) < 0xc0) + outb(0x00, port + FCR); /* Disable FIFOs if non-functional */ + (void)inb(port + IER); /* Synchronize */ + + return 0; +} + +void serial_write(struct serial_if *sif, const void *data, size_t n) +{ + uint16_t port = sif->port; + const char *p = data; + uint8_t lsr; + + while (n--) { + do { + lsr = inb(port + LSR); + } while (!(lsr & 0x20)); + + outb(*p++, port + THR); + } +} + +void serial_read(struct serial_if *sif, void *data, size_t n) +{ + uint16_t port = sif->port; + char *p = data; + uint8_t lsr; + + while (n--) { + do { + lsr = inb(port + LSR); + } while (!(lsr & 0x01)); + + *p++ = inb(port + RBR); + } +} + +void serial_cleanup(struct serial_if *sif) +{ + uint16_t port = sif->port; + + outb(0x83, port + LCR); + (void)inb(port + IER); + outb(sif->old.dll, port + DLL); + outb(sif->old.dlm, port + DLM); + (void)inb(port + IER); + outb(sif->old.lcr & 0x7f, port + LCR); + (void)inb(port + IER); + outb(sif->old.mcr, port + MCR); + outb(sif->old.ier, port + IER); + if (sif->old.iir < 0xc0) + outb(0x00, port + FCR); /* Disable FIFOs */ + + /* Re-enable console messages, if we shut them down */ + if (sif->console) + openconsole(&dev_null_r, &dev_stdcon_w); +} diff --git a/contrib/syslinux-4.02/com32/sysdump/serial.h b/contrib/syslinux-4.02/com32/sysdump/serial.h new file mode 100644 index 0000000..356f2ce --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/serial.h @@ -0,0 +1,19 @@ +#ifndef SERIAL_H +#define SERIAL_H + +#include <stddef.h> + +struct serial_if { + uint16_t port; + bool console; + struct { + uint8_t dll, dlm, ier, iir, lcr, mcr; + } old; +}; + +int serial_init(struct serial_if *sif, const char *argv[]); +void serial_read(struct serial_if *sif, void *data, size_t n); +void serial_write(struct serial_if *sif, const void *data, size_t n); +void serial_cleanup(struct serial_if *sif); + +#endif /* SERIAL_H */ diff --git a/contrib/syslinux-4.02/com32/sysdump/srecsend.h b/contrib/syslinux-4.02/com32/sysdump/srecsend.h new file mode 100644 index 0000000..667be20 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/srecsend.h @@ -0,0 +1,9 @@ +#ifndef SRECSEND_H +#define SRECSEND_H + +#include "file.h" + +void send_srec(struct serial_if *, struct file_info *, + void (*)(void *, size_t, struct file_info *, size_t)); + +#endif /* SRECSEND_H */ diff --git a/contrib/syslinux-4.02/com32/sysdump/sysdump.h b/contrib/syslinux-4.02/com32/sysdump/sysdump.h new file mode 100644 index 0000000..a5b963f --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/sysdump.h @@ -0,0 +1,15 @@ +#ifndef SYSDUMP_H +#define SYSDUMP_H + +struct backend; + +void dump_memory_map(struct backend *); +void snapshot_lowmem(void); +void dump_memory(struct backend *); +void dump_dmi(struct backend *); +void dump_acpi(struct backend *); +void dump_cpuid(struct backend *); +void dump_pci(struct backend *); +void dump_vesa_tables(struct backend *); + +#endif /* SYSDUMP_H */ diff --git a/contrib/syslinux-4.02/com32/sysdump/vesa.c b/contrib/syslinux-4.02/com32/sysdump/vesa.c new file mode 100644 index 0000000..017f9e4 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/vesa.c @@ -0,0 +1,63 @@ +#include <string.h> +#include <stdio.h> +#include "../lib/sys/vesa/vesa.h" +#include "backend.h" +#include "sysdump.h" + +void dump_vesa_tables(struct backend *be) +{ + com32sys_t rm; + struct vesa_info *vip; + struct vesa_general_info *gip, gi; + struct vesa_mode_info *mip, mi; + uint16_t mode, *mode_ptr; + char modefile[64]; + + printf("Scanning VESA BIOS... "); + + /* Allocate space in the bounce buffer for these structures */ + vip = lmalloc(sizeof *vip); + gip = &vip->gi; + mip = &vip->mi; + + memset(&rm, 0, sizeof rm); + memset(gip, 0, sizeof *gip); + + gip->signature = VBE2_MAGIC; /* Get VBE2 extended data */ + rm.eax.w[0] = 0x4F00; /* Get SVGA general information */ + rm.edi.w[0] = OFFS(gip); + rm.es = SEG(gip); + __intcall(0x10, &rm, &rm); + memcpy(&gi, gip, sizeof gi); + + if (rm.eax.w[0] != 0x004F) + return; /* Function call failed */ + if (gi.signature != VESA_MAGIC) + return; /* No magic */ + + cpio_mkdir(be, "vesa"); + + cpio_writefile(be, "vesa/global.bin", &gi, sizeof gi); + + mode_ptr = GET_PTR(gi.video_mode_ptr); + while ((mode = *mode_ptr++) != 0xFFFF) { + memset(mip, 0, sizeof *mip); + rm.eax.w[0] = 0x4F01; /* Get SVGA mode information */ + rm.ecx.w[0] = mode; + rm.edi.w[0] = OFFS(mip); + rm.es = SEG(mip); + __intcall(0x10, &rm, &rm); + + /* Must be a supported mode */ + if (rm.eax.w[0] != 0x004f) + continue; + + memcpy(&mi, mip, sizeof mi); + + sprintf(modefile, "vesa/mode%04x.bin", mode); + cpio_writefile(be, modefile, &mi, sizeof mi); + } + + lfree(vip); + printf("done.\n"); +} diff --git a/contrib/syslinux-4.02/com32/sysdump/ymodem.txt b/contrib/syslinux-4.02/com32/sysdump/ymodem.txt new file mode 100644 index 0000000..2264ff7 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/ymodem.txt @@ -0,0 +1,2108 @@ + + + + - 1 - + + + + XMODEM/YMODEM PROTOCOL REFERENCE + A compendium of documents describing the + + XMODEM and YMODEM + + File Transfer Protocols + + + + + This document was formatted 10-14-88. + + + + + + + + Edited by Chuck Forsberg + + + + + + + + + + This file may be redistributed without restriction + provided the text is not altered. + + Please distribute as widely as possible. + + Questions to Chuck Forsberg + + + + + + Omen Technology Inc + The High Reliability Software + 17505-V Sauvie Island Road + Portland Oregon 97231 + VOICE: 503-621-3406 :VOICE + TeleGodzilla BBS: 503-621-3746 Speed 19200(Telebit PEP),2400,1200,300 + CompuServe: 70007,2304 + GEnie: CAF + UUCP: ...!tektronix!reed!omen!caf + + + + + + + + + + + + + + + - 2 - + + + + 1. TOWER OF BABEL + + A "YMODEM Tower of Babel" has descended on the microcomputing community + bringing with it confusion, frustration, bloated phone bills, and wasted + man hours. Sadly, I (Chuck Forsberg) am partly to blame for this mess. + + As author of the early 1980s batch and 1k XMODEM extensions, I assumed + readers of earlier versions of this document would implement as much of + the YMODEM protocol as their programming skills and computing environments + would permit. This proved a rather naive assumption as programmers + motivated by competitive pressure implemented as little of YMODEM as + possible. Some have taken whatever parts of YMODEM that appealed to them, + applied them to MODEM7 Batch, Telink, XMODEM or whatever, and called the + result YMODEM. + + Jeff Garbers (Crosstalk package development director) said it all: "With + protocols in the public domain, anyone who wants to dink around with them + can go ahead." [1] + + Documents containing altered examples derived from YMODEM.DOC have added + to the confusion. In one instance, some self styled rewriter of history + altered the heading in YMODEM.DOC's Figure 1 from "1024 byte Packets" to + "YMODEM/CRC File Transfer Protocol". None of the XMODEM and YMODEM + examples shown in that document were correct. + + To put an end to this confusion, we must make "perfectly clear" what + YMODEM stands for, as Ward Christensen defined it in his 1985 coining of + the term. + + To the majority of you who read, understood, and respected Ward's + definition of YMODEM, I apologize for the inconvenience. + + 1.1 Definitions + + ARC ARC is a program that compresses one or more files into an archive + and extracts files from such archives. + + XMODEM refers to the file transfer etiquette introduced by Ward + Christensen's 1977 MODEM.ASM program. The name XMODEM comes from + Keith Petersen's XMODEM.ASM program, an adaptation of MODEM.ASM + for Remote CP/M (RCPM) systems. It's also called the MODEM or + MODEM2 protocol. Some who are unaware of MODEM7's unusual batch + file mode call it MODEM7. Other aliases include "CP/M Users' + Group" and "TERM II FTP 3". The name XMODEM caught on partly + because it is distinctive and partly because of media interest in + + + __________ + + 1. Page C/12, PC-WEEK July 12, 1987 + + + + + Chapter 1 + + + + + + + + X/YMODEM Protocol Reference June 18 1988 3 + + + + bulletin board and RCPM systems where it was accessed with an + "XMODEM" command. This protocol is supported by every serious + communications program because of its universality, simplicity, + and reasonable performance. + + XMODEM/CRC replaces XMODEM's 1 byte checksum with a two byte Cyclical + Redundancy Check (CRC-16), giving modern error detection + protection. + + XMODEM-1k Refers to the XMODEM/CRC protocol with 1024 byte data blocks. + + YMODEM Refers to the XMODEM/CRC (optional 1k blocks) protocol with batch + transmission as described below. In a nutshell, YMODEM means + BATCH. + + YMODEM-g Refers to the streaming YMODEM variation described below. + + True YMODEM(TM) In an attempt to sort out the YMODEM Tower of Babel, Omen + Technology has trademarked the term True YMODEM(TM) to represent + the complete YMODEM protocol described in this document, including + pathname, length, and modification date transmitted in block 0. + Please contact Omen Technology about certifying programs for True + YMODEM(TM) compliance. + + ZMODEM uses familiar XMODEM/CRC and YMODEM technology in a new protocol + that provides reliability, throughput, file management, and user + amenities appropriate to contemporary data communications. + + ZOO Like ARC, ZOO is a program that compresses one or more files into + a "zoo archive". ZOO supports many different operating systems + including Unix and VMS. + + + + + + + + + + + + + + + + + + + + + + + + Chapter 1 + + + + + + + + X/YMODEM Protocol Reference June 18 1988 4 + + + + 2. YMODEM MINIMUM REQUIREMENTS + + All programs claiming to support YMODEM must meet the following minimum + requirements: + + + The sending program shall send the pathname (file name) in block 0. + + + The pathname shall be a null terminated ASCII string as described + below. + + For those who are too lazy to read the entire document: + + + Unless specifically requested, only the file name portion is + sent. + + + No drive letter is sent. + + + Systems that do not distinguish between upper and lower case + letters in filenames shall send the pathname in lower case only. + + + + The receiving program shall use this pathname for the received file + name, unless explicitly overridden. + + + When the receiving program receives this block and successfully + opened the output file, it shall acknowledge this block with an ACK + character and then proceed with a normal XMODEM file transfer + beginning with a "C" or NAK tranmsitted by the receiver. + + + The sending program shall use CRC-16 in response to a "C" pathname + nak, otherwise use 8 bit checksum. + + + The receiving program must accept any mixture of 128 and 1024 byte + blocks within each file it receives. Sending programs may + arbitrarily switch between 1024 and 128 byte blocks. + + + The sending program must not change the length of an unacknowledged + block. + + + At the end of each file, the sending program shall send EOT up to ten + times until it receives an ACK character. (This is part of the + XMODEM spec.) + + + The end of a transfer session shall be signified by a null (empty) + pathname, this pathname block shall be acknowledged the same as other + pathname blocks. + + Programs not meeting all of these requirements are not YMODEM compatible, + and shall not be described as supporting YMODEM. + + Meeting these MINIMUM requirements does not guarantee reliable file + + + + Chapter 2 + + + + + + + + X/YMODEM Protocol Reference June 18 1988 5 + + + + transfers under stress. Particular attention is called to XMODEM's single + character supervisory messages that are easily corrupted by transmission + errors. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Chapter 2 + + + + + + + + X/YMODEM Protocol Reference June 18 1988 6 + + + + 3. WHY YMODEM? + + Since its development half a decade ago, the Ward Christensen modem + protocol has enabled a wide variety of computer systems to interchange + data. There is hardly a communications program that doesn't at least + claim to support this protocol. + + Advances in computing, modems and networking have revealed a number of + weaknesses in the original protocol: + + + The short block length caused throughput to suffer when used with + timesharing systems, packet switched networks, satellite circuits, + and buffered (error correcting) modems. + + + The 8 bit arithmetic checksum and other aspects allowed line + impairments to interfere with dependable, accurate transfers. + + + Only one file could be sent per command. The file name had to be + given twice, first to the sending program and then again to the + receiving program. + + + The transmitted file could accumulate as many as 127 extraneous + bytes. + + + The modification date of the file was lost. + + A number of other protocols have been developed over the years, but none + have displaced XMODEM to date: + + + Lack of public domain documentation and example programs have kept + proprietary protocols such as Blast, Relay, and others tightly bound + to the fortunes of their suppliers. + + + Complexity discourages the widespread application of BISYNC, SDLC, + HDLC, X.25, and X.PC protocols. + + + Performance compromises and complexity have limited the popularity of + the Kermit protocol, which was developed to allow file transfers in + environments hostile to XMODEM. + + The XMODEM protocol extensions and YMODEM Batch address some of these + weaknesses while maintaining most of XMODEM's simplicity. + + YMODEM is supported by the public domain programs YAM (CP/M), + YAM(CP/M-86), YAM(CCPM-86), IMP (CP/M), KMD (CP/M), rz/sz (Unix, Xenix, + VMS, Berkeley Unix, Venix, Xenix, Coherent, IDRIS, Regulus). Commercial + implementations include MIRROR, and Professional-YAM.[1] Communications + + + + + + + + Chapter 3 + + + + + + + + X/YMODEM Protocol Reference June 18 1988 7 + + + + programs supporting these extensions have been in use since 1981. + + The 1k block length (XMODEM-1k) described below may be used in conjunction + with YMODEM Batch Protocol, or with single file transfers identical to the + XMODEM/CRC protocol except for minimal changes to support 1k blocks. + + Another extension is the YMODEM-g protocol. YMODEM-g provides batch + transfers with maximum throughput when used with end to end error + correcting media, such as X.PC and error correcting modems, including 9600 + bps units by TeleBit, U.S.Robotics, Hayes, Electronic Vaults, Data Race, + and others. + + To complete this tome, edited versions of Ward Christensen's original + protocol document and John Byrns's CRC-16 document are included for + reference. + + References to the MODEM or MODEM7 protocol have been changed to XMODEM to + accommodate the vernacular. In Australia, it is properly called the + Christensen Protocol. + + + 3.1 Some Messages from the Pioneer + + #: 130940 S0/Communications 25-Apr-85 18:38:47 + Sb: my protocol + Fm: Ward Christensen 76703,302 [2] + To: all + + Be aware the article[3] DID quote me correctly in terms of the phrases + like "not robust", etc. + + It was a quick hack I threw together, very unplanned (like everything I + do), to satisfy a personal need to communicate with "some other" people. + + ONLY the fact that it was done in 8/77, and that I put it in the public + domain immediately, made it become the standard that it is. + + + + + + + + __________________________________________________________________________ + + 1. Available for IBM PC,XT,AT, Unix and Xenix + + 2. Edited for typesetting appearance + + 3. Infoworld April 29 p. 16 + + + + + Chapter 3 + + + + + + + + X/YMODEM Protocol Reference June 18 1988 8 + + + + I think its time for me to + + (1) document it; (people call me and say "my product is going to include + it - what can I 'reference'", or "I'm writing a paper on it, what do I put + in the bibliography") and + + (2) propose an "incremental extension" to it, which might take "exactly" + the form of Chuck Forsberg's YAM protocol. He wrote YAM in C for CP/M and + put it in the public domain, and wrote a batch protocol for Unix[4] called + rb and sb (receive batch, send batch), which was basically XMODEM with + (a) a record 0 containing filename date time and size + (b) a 1K block size option + (c) CRC-16. + + He did some clever programming to detect false ACK or EOT, but basically + left them the same. + + People who suggest I make SIGNIFICANT changes to the protocol, such as + "full duplex", "multiple outstanding blocks", "multiple destinations", etc + etc don't understand that the incredible simplicity of the protocol is one + of the reasons it survived to this day in as many machines and programs as + it may be found in! + + Consider the PC-NET group back in '77 or so - documenting to beat the band + - THEY had a protocol, but it was "extremely complex", because it tried to + be "all things to all people" - i.e. send binary files on a 7-bit system, + etc. I was not that "benevolent". I (emphasize > I < ) had an 8-bit UART, + so "my protocol was an 8-bit protocol", and I would just say "sorry" to + people who were held back by 7-bit limitations. ... + + Block size: Chuck Forsberg created an extension of my protocol, called + YAM, which is also supported via his public domain programs for UNIX + called rb and sb - receive batch and send batch. They cleverly send a + "block 0" which contains the filename, date, time, and size. + Unfortunately, its UNIX style, and is a bit weird[5] - octal numbers, etc. + BUT, it is a nice way to overcome the kludgy "echo the chars of the name" + introduced with MODEM7. Further, chuck uses CRC-16 and optional 1K + blocks. Thus the record 0, 1K, and CRC, make it a "pretty slick new + protocol" which is not significantly different from my own. + + Also, there is a catchy name - YMODEM. That means to some that it is the + "next thing after XMODEM", and to others that it is the Y(am)MODEM + + + __________ + + 4. VAX/VMS versions of these programs are also available. + + 5. The file length, time, and file mode are optional. The pathname and + file length may be sent alone if desired. + + + + + Chapter 3 + + + + + + + + X/YMODEM Protocol Reference June 18 1988 9 + + + + protocol. I don't want to emphasize that too much - out of fear that + other mfgrs might think it is a "competitive" protocol, rather than an + "unaffiliated" protocol. Chuck is currently selling a much-enhanced + version of his CP/M-80 C program YAM, calling it Professional Yam, and its + for the PC - I'm using it right now. VERY slick! 32K capture buffer, + script, scrolling, previously captured text search, plus built-in commands + for just about everything - directory (sorted every which way), XMODEM, + YMODEM, KERMIT, and ASCII file upload/download, etc. You can program it + to "behave" with most any system - for example when trying a number for + CIS it detects the "busy" string back from the modem and substitutes a + diff phone # into the dialing string and branches back to try it. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Chapter 3 + + + + + + + + X/YMODEM Protocol Reference June 18 1988 10 + + + + 4. XMODEM PROTOCOL ENHANCEMENTS + + This chapter discusses the protocol extensions to Ward Christensen's 1982 + XMODEM protocol description document. + + The original document recommends the user be asked whether to continue + trying or abort after 10 retries. Most programs no longer ask the + operator whether he wishes to keep retrying. Virtually all correctable + errors are corrected within the first few retransmissions. If the line is + so bad that ten attempts are insufficient, there is a significant danger + of undetected errors. If the connection is that bad, it's better to + redial for a better connection, or mail a floppy disk. + + + 4.1 Graceful Abort + + The YAM and Professional-YAM X/YMODEM routines recognize a sequence of two + consecutive CAN (Hex 18) characters without modem errors (overrun, + framing, etc.) as a transfer abort command. This sequence is recognized + when is waiting for the beginning of a block or for an acknowledgement to + a block that has been sent. The check for two consecutive CAN characters + reduces the number of transfers aborted by line hits. YAM sends eight CAN + characters when it aborts an XMODEM, YMODEM, or ZMODEM protocol file + transfer. Pro-YAM then sends eight backspaces to delete the CAN + characters from the remote's keyboard input buffer, in case the remote had + already aborted the transfer and was awaiting a keyboarded command. + + + 4.2 CRC-16 Option + + The XMODEM protocol uses an optional two character CRC-16 instead of the + one character arithmetic checksum used by the original protocol and by + most commercial implementations. CRC-16 guarantees detection of all + single and double bit errors, all errors with an odd number of error + bits, all burst errors of length 16 or less, 99.9969% of all 17-bit error + bursts, and 99.9984 per cent of all possible longer error bursts. By + contrast, a double bit error, or a burst error of 9 bits or more can sneak + past the XMODEM protocol arithmetic checksum. + + The XMODEM/CRC protocol is similar to the XMODEM protocol, except that the + receiver specifies CRC-16 by sending C (Hex 43) instead of NAK when + requesting the FIRST block. A two byte CRC is sent in place of the one + byte arithmetic checksum. + + YAM's c option to the r command enables CRC-16 in single file reception, + corresponding to the original implementation in the MODEM7 series + programs. This remains the default because many commercial communications + programs and bulletin board systems still do not support CRC-16, + especially those written in Basic or Pascal. + + XMODEM protocol with CRC is accurate provided both sender and receiver + + + + Chapter 4 XMODEM Protocol Enhancements + + + + + + + + X/YMODEM Protocol Reference June 18 1988 11 + + + + both report a successful transmission. The protocol is robust in the + presence of characters lost by buffer overloading on timesharing systems. + + The single character ACK/NAK responses generated by the receiving program + adapt well to split speed modems, where the reverse channel is limited to + ten per cent or less of the main channel's speed. + + XMODEM and YMODEM are half duplex protocols which do not attempt to + transmit information and control signals in both directions at the same + time. This avoids buffer overrun problems that have been reported by + users attempting to exploit full duplex asynchronous file transfer + protocols such as Blast. + + Professional-YAM adds several proprietary logic enhancements to XMODEM's + error detection and recovery. These compatible enhancements eliminate + most of the bad file transfers other programs make when using the XMODEM + protocol under less than ideal conditions. + + + 4.3 XMODEM-1k 1024 Byte Block + + Disappointing throughput downloading from Unix with YMODEM[1] lead to the + development of 1024 byte blocks in 1982. 1024 byte blocks reduce the + effect of delays from timesharing systems, modems, and packet switched + networks on throughput by 87.5 per cent in addition to decreasing XMODEM's + 3 per cent overhead (block number, CRC, etc.). + + Some environments cannot accept 1024 byte bursts, including some networks + and minicomputer ports. The longer block length should be an option. + + The choice to use 1024 byte blocks is expressed to the sending program on + its command line or selection menu.[2] 1024 byte blocks improve throughput + in many applications. + + An STX (02) replaces the SOH (01) at the beginning of the transmitted + block to notify the receiver of the longer block length. The transmitted + block contains 1024 bytes of data. The receiver should be able to accept + any mixture of 128 and 1024 byte blocks. The block number (in the second + and third bytes of the block) is incremented by one for each block + regardless of the block length. + + The sender must not change between 128 and 1024 byte block lengths if it + has not received a valid ACK for the current block. Failure to observe + + + __________ + + 1. The name hadn't been coined yet, but the protocol was the same. + + 2. See "KMD/IMP Exceptions to YMODEM" below. + + + + + Chapter 4 XMODEM Protocol Enhancements + + + + + + + + X/YMODEM Protocol Reference June 18 1988 12 + + + + this restriction allows transmission errors to pass undetected. + + If 1024 byte blocks are being used, it is possible for a file to "grow" up + to the next multiple of 1024 bytes. This does not waste disk space if the + allocation granularity is 1k or greater. With YMODEM batch transmission, + the optional file length transmitted in the file name block allows the + receiver to discard the padding, preserving the exact file length and + contents. + + 1024 byte blocks may be used with batch file transmission or with single + file transmission. CRC-16 should be used with the k option to preserve + data integrity over phone lines. If a program wishes to enforce this + recommendation, it should cancel the transfer, then issue an informative + diagnostic message if the receiver requests checksum instead of CRC-16. + + Under no circumstances may a sending program use CRC-16 unless the + receiver commands CRC-16. + + Figure 1. XMODEM-1k Blocks + + SENDER RECEIVER + "sx -k foo.bar" + "foo.bar open x.x minutes" + C + STX 01 FE Data[1024] CRC CRC + ACK + STX 02 FD Data[1024] CRC CRC + ACK + STX 03 FC Data[1000] CPMEOF[24] CRC CRC + ACK + EOT + ACK + + Figure 2. Mixed 1024 and 128 byte Blocks + + SENDER RECEIVER + "sx -k foo.bar" + "foo.bar open x.x minutes" + C + STX 01 FE Data[1024] CRC CRC + ACK + STX 02 FD Data[1024] CRC CRC + ACK + SOH 03 FC Data[128] CRC CRC + ACK + SOH 04 FB Data[100] CPMEOF[28] CRC CRC + ACK + EOT + ACK + + + + + + Chapter 4 XMODEM Protocol Enhancements + + + + + + + + X/YMODEM Protocol Reference June 18 1988 13 + + + + 5. YMODEM Batch File Transmission + + The YMODEM Batch protocol is an extension to the XMODEM/CRC protocol that + allows 0 or more files to be transmitted with a single command. (Zero + files may be sent if none of the requested files is accessible.) The + design approach of the YMODEM Batch protocol is to use the normal routines + for sending and receiving XMODEM blocks in a layered fashion similar to + packet switching methods. + + Why was it necessary to design a new batch protocol when one already + existed in MODEM7?[1] The batch file mode used by MODEM7 is unsuitable + because it does not permit full pathnames, file length, file date, or + other attribute information to be transmitted. Such a restrictive design, + hastily implemented with only CP/M in mind, would not have permitted + extensions to current areas of personal computing such as Unix, DOS, and + object oriented systems. In addition, the MODEM7 batch file mode is + somewhat susceptible to transmission impairments. + + As in the case of single a file transfer, the receiver initiates batch + file transmission by sending a "C" character (for CRC-16). + + The sender opens the first file and sends block number 0 with the + following information.[2] + + Only the pathname (file name) part is required for batch transfers. + + To maintain upwards compatibility, all unused bytes in block 0 must be set + to null. + + Pathname The pathname (conventionally, the file name) is sent as a null + terminated ASCII string. This is the filename format used by the + handle oriented MSDOS(TM) functions and C library fopen functions. + An assembly language example follows: + DB 'foo.bar',0 + No spaces are included in the pathname. Normally only the file name + stem (no directory prefix) is transmitted unless the sender has + selected YAM's f option to send the full pathname. The source drive + (A:, B:, etc.) is not sent. + + Filename Considerations: + + + + __________ + + 1. The MODEM7 batch protocol transmitted CP/M FCB bytes f1...f8 and + t1...t3 one character at a time. The receiver echoed these bytes as + received, one at a time. + + 2. Only the data part of the block is described here. + + + + + Chapter 5 XMODEM Protocol Enhancements + + + + + + + + X/YMODEM Protocol Reference June 18 1988 14 + + + + + File names are forced to lower case unless the sending system + supports upper/lower case file names. This is a convenience for + users of systems (such as Unix) which store filenames in upper + and lower case. + + + The receiver should accommodate file names in lower and upper + case. + + + When transmitting files between different operating systems, + file names must be acceptable to both the sender and receiving + operating systems. + + If directories are included, they are delimited by /; i.e., + "subdir/foo" is acceptable, "subdir\foo" is not. + + Length The file length and each of the succeeding fields are optional.[3] + The length field is stored in the block as a decimal string counting + the number of data bytes in the file. The file length does not + include any CPMEOF (^Z) or other garbage characters used to pad the + last block. + + If the file being transmitted is growing during transmission, the + length field should be set to at least the final expected file + length, or not sent. + + The receiver stores the specified number of characters, discarding + any padding added by the sender to fill up the last block. + + Modification Date The mod date is optional, and the filename and length + may be sent without requiring the mod date to be sent. + + Iff the modification date is sent, a single space separates the + modification date from the file length. + + The mod date is sent as an octal number giving the time the contents + of the file were last changed, measured in seconds from Jan 1 1970 + Universal Coordinated Time (GMT). A date of 0 implies the + modification date is unknown and should be left as the date the file + is received. + + This standard format was chosen to eliminate ambiguities arising from + transfers between different time zones. + + + + + + __________ + + 3. Fields may not be skipped. + + + + + Chapter 5 XMODEM Protocol Enhancements + + + + + + + + X/YMODEM Protocol Reference June 18 1988 15 + + + + Mode Iff the file mode is sent, a single space separates the file mode + from the modification date. The file mode is stored as an octal + string. Unless the file originated from a Unix system, the file mode + is set to 0. rb(1) checks the file mode for the 0x8000 bit which + indicates a Unix type regular file. Files with the 0x8000 bit set + are assumed to have been sent from another Unix (or similar) system + which uses the same file conventions. Such files are not translated + in any way. + + + Serial Number Iff the serial number is sent, a single space separates the + serial number from the file mode. The serial number of the + transmitting program is stored as an octal string. Programs which do + not have a serial number should omit this field, or set it to 0. The + receiver's use of this field is optional. + + + Other Fields YMODEM was designed to allow additional header fields to be + added as above without creating compatibility problems with older + YMODEM programs. Please contact Omen Technology if other fields are + needed for special application requirements. + + The rest of the block is set to nulls. This is essential to preserve + upward compatibility.[4] + + If the filename block is received with a CRC or other error, a + retransmission is requested. After the filename block has been received, + it is ACK'ed if the write open is successful. If the file cannot be + opened for writing, the receiver cancels the transfer with CAN characters + as described above. + + The receiver then initiates transfer of the file contents with a "C" + character, according to the standard XMODEM/CRC protocol. + + After the file contents and XMODEM EOT have been transmitted and + acknowledged, the receiver again asks for the next pathname. + + Transmission of a null pathname terminates batch file transmission. + + Note that transmission of no files is not necessarily an error. This is + possible if none of the files requested of the sender could be opened for + reading. + + + + __________ + + 4. If, perchance, this information extends beyond 128 bytes (possible + with Unix 4.2 BSD extended file names), the block should be sent as a + 1k block as described above. + + + + + Chapter 5 XMODEM Protocol Enhancements + + + + + + + + X/YMODEM Protocol Reference June 18 1988 16 + + + + Most YMODEM receivers request CRC-16 by default. + + The Unix programs sz(1) and rz(1) included in the source code file + RZSZ.ZOO should answer other questions about YMODEM batch protocol. + + Figure 3. YMODEM Batch Transmission Session (1 file) + + SENDER RECEIVER + "sb foo.*<CR>" + "sending in batch mode etc." + C (command:rb) + SOH 00 FF foo.c NUL[123] CRC CRC + ACK + C + SOH 01 FE Data[128] CRC CRC + ACK + SOH 02 FC Data[128] CRC CRC + ACK + SOH 03 FB Data[100] CPMEOF[28] CRC CRC + ACK + EOT + NAK + EOT + ACK + C + SOH 00 FF NUL[128] CRC CRC + ACK + + Figure 7. YMODEM Header Information and Features + + _____________________________________________________________ + | Program | Length | Date | Mode | S/N | 1k-Blk | YMODEM-g | + |___________|________|______|______|_____|________|__________| + |Unix rz/sz | yes | yes | yes | no | yes | sb only | + |___________|________|______|______|_____|________|__________| + |VMS rb/sb | yes | no | no | no | yes | no | + |___________|________|______|______|_____|________|__________| + |Pro-YAM | yes | yes | no | yes | yes | yes | + |___________|________|______|______|_____|________|__________| + |CP/M YAM | no | no | no | no | yes | no | + |___________|________|______|______|_____|________|__________| + |KMD/IMP | ? | no | no | no | yes | no | + |___________|________|______|______|_____|________|__________| + + 5.1 KMD/IMP Exceptions to YMODEM + + KMD and IMP use a "CK" character sequence emitted by the receiver to + trigger the use of 1024 byte blocks as an alternative to specifying this + option to the sending program. This two character sequence generally + works well on single process micros in direct communication, provided the + programs rigorously adhere to all the XMODEM recommendations included + + + + Chapter 5 XMODEM Protocol Enhancements + + + + + + + + X/YMODEM Protocol Reference June 18 1988 17 + + + + Figure 4. YMODEM Batch Transmission Session (2 files) + + SENDER RECEIVER + "sb foo.c baz.c<CR>" + "sending in batch mode etc." + C (command:rb) + SOH 00 FF foo.c NUL[123] CRC CRC + ACK + C + SOH 01 FE Data[128] CRC CRC + ACK + SOH 02 FC Data[128] CRC CRC + ACK + SOH 03 FB Data[100] CPMEOF[28] CRC CRC + ACK + EOT + NAK + EOT + ACK + C + SOH 00 FF baz.c NUL[123] CRC CRC + ACK + C + SOH 01 FB Data[100] CPMEOF[28] CRC CRC + ACK + EOT + NAK + EOT + ACK + C + SOH 00 FF NUL[128] CRC CRC + ACK + + Figure 5. YMODEM Batch Transmission Session-1k Blocks + + SENDER RECEIVER + "sb -k foo.*<CR>" + "sending in batch mode etc." + C (command:rb) + SOH 00 FF foo.c NUL[123] CRC CRC + ACK + C + STX 01 FD Data[1024] CRC CRC + ACK + SOH 02 FC Data[128] CRC CRC + ACK + SOH 03 FB Data[100] CPMEOF[28] CRC CRC + ACK + EOT + NAK + EOT + + + + Chapter 5 XMODEM Protocol Enhancements + + + + + + + + X/YMODEM Protocol Reference June 18 1988 18 + + + + ACK + C + SOH 00 FF NUL[128] CRC CRC + ACK + + Figure 6. YMODEM Filename block transmitted by sz + + -rw-r--r-- 6347 Jun 17 1984 20:34 bbcsched.txt + + 00 0100FF62 62637363 6865642E 74787400 |...bbcsched.txt.| + 10 36333437 20333331 34373432 35313320 |6347 3314742513 | + 20 31303036 34340000 00000000 00000000 |100644..........| + 30 00000000 00000000 00000000 00000000 + 40 00000000 00000000 00000000 00000000 + 50 00000000 00000000 00000000 00000000 + 60 00000000 00000000 00000000 00000000 + 70 00000000 00000000 00000000 00000000 + 80 000000CA 56 + + herein. Programs with marginal XMODEM implementations do not fare so + well. Timesharing systems and packet switched networks can separate the + successive characters, rendering this method unreliable. + + Sending programs may detect the CK sequence if the operating enviornment + does not preclude reliable implementation. + + Instead of the standard YMODEM file length in decimal, KMD and IMP + transmit the CP/M record count in the last two bytes of the header block. + + + 6. YMODEM-g File Transmission + + Developing technology is providing phone line data transmission at ever + higher speeds using very specialized techniques. These high speed modems, + as well as session protocols such as X.PC, provide high speed, nearly + error free communications at the expense of considerably increased delay + time. + + This delay time is moderate compared to human interactions, but it + cripples the throughput of most error correcting protocols. + + The g option to YMODEM has proven effective under these circumstances. + The g option is driven by the receiver, which initiates the batch transfer + by transmitting a G instead of C. When the sender recognizes the G, it + bypasses the usual wait for an ACK to each transmitted block, sending + succeeding blocks at full speed, subject to XOFF/XON or other flow control + exerted by the medium. + + The sender expects an inital G to initiate the transmission of a + particular file, and also expects an ACK on the EOT sent at the end of + each file. This synchronization allows the receiver time to open and + + + + Chapter 6 XMODEM Protocol Enhancements + + + + + + + + X/YMODEM Protocol Reference June 18 1988 19 + + + + close files as necessary. + + If an error is detected in a YMODEM-g transfer, the receiver aborts the + transfer with the multiple CAN abort sequence. The ZMODEM protocol should + be used in applications that require both streaming throughput and error + recovery. + + Figure 8. YMODEM-g Transmission Session + + SENDER RECEIVER + "sb foo.*<CR>" + "sending in batch mode etc..." + G (command:rb -g) + SOH 00 FF foo.c NUL[123] CRC CRC + G + SOH 01 FE Data[128] CRC CRC + STX 02 FD Data[1024] CRC CRC + SOH 03 FC Data[128] CRC CRC + SOH 04 FB Data[100] CPMEOF[28] CRC CRC + EOT + ACK + G + SOH 00 FF NUL[128] CRC CRC + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Chapter 6 XMODEM Protocol Enhancements + + + + + + + + X/YMODEM Protocol Reference June 18 1988 20 + + + + 7. XMODEM PROTOCOL OVERVIEW + + 8/9/82 by Ward Christensen. + + I will maintain a master copy of this. Please pass on changes or + suggestions via CBBS/Chicago at (312) 545-8086, CBBS/CPMUG (312) 849-1132 + or by voice at (312) 849-6279. + + 7.1 Definitions + + <soh> 01H + <eot> 04H + <ack> 06H + <nak> 15H + <can> 18H + <C> 43H + + + 7.2 Transmission Medium Level Protocol + + Asynchronous, 8 data bits, no parity, one stop bit. + + The protocol imposes no restrictions on the contents of the data being + transmitted. No control characters are looked for in the 128-byte data + messages. Absolutely any kind of data may be sent - binary, ASCII, etc. + The protocol has not formally been adopted to a 7-bit environment for the + transmission of ASCII-only (or unpacked-hex) data , although it could be + simply by having both ends agree to AND the protocol-dependent data with + 7F hex before validating it. I specifically am referring to the checksum, + and the block numbers and their ones- complement. + + Those wishing to maintain compatibility of the CP/M file structure, i.e. + to allow modemming ASCII files to or from CP/M systems should follow this + data format: + + + ASCII tabs used (09H); tabs set every 8. + + + Lines terminated by CR/LF (0DH 0AH) + + + End-of-file indicated by ^Z, 1AH. (one or more) + + + Data is variable length, i.e. should be considered a continuous + stream of data bytes, broken into 128-byte chunks purely for the + purpose of transmission. + + + A CP/M "peculiarity": If the data ends exactly on a 128-byte + boundary, i.e. CR in 127, and LF in 128, a subsequent sector + containing the ^Z EOF character(s) is optional, but is preferred. + Some utilities or user programs still do not handle EOF without ^Zs. + + + + + + Chapter 7 Xmodem Protocol Overview + + + + + + + + X/YMODEM Protocol Reference June 18 1988 21 + + + + + The last block sent is no different from others, i.e. there is no + "short block". + Figure 9. XMODEM Message Block Level Protocol + + Each block of the transfer looks like: + <SOH><blk #><255-blk #><--128 data bytes--><cksum> + in which: + <SOH> = 01 hex + <blk #> = binary number, starts at 01 increments by 1, and + wraps 0FFH to 00H (not to 01) + <255-blk #> = blk # after going thru 8080 "CMA" instr, i.e. + each bit complemented in the 8-bit block number. + Formally, this is the "ones complement". + <cksum> = the sum of the data bytes only. Toss any carry. + + 7.3 File Level Protocol + + 7.3.1 Common_to_Both_Sender_and_Receiver + All errors are retried 10 times. For versions running with an operator + (i.e. NOT with XMODEM), a message is typed after 10 errors asking the + operator whether to "retry or quit". + + Some versions of the protocol use <can>, ASCII ^X, to cancel transmission. + This was never adopted as a standard, as having a single "abort" character + makes the transmission susceptible to false termination due to an <ack> + <nak> or <soh> being corrupted into a <can> and aborting transmission. + + The protocol may be considered "receiver driven", that is, the sender need + not automatically re-transmit, although it does in the current + implementations. + + + 7.3.2 Receive_Program_Considerations + The receiver has a 10-second timeout. It sends a <nak> every time it + times out. The receiver's first timeout, which sends a <nak>, signals the + transmitter to start. Optionally, the receiver could send a <nak> + immediately, in case the sender was ready. This would save the initial 10 + second timeout. However, the receiver MUST continue to timeout every 10 + seconds in case the sender wasn't ready. + + Once into a receiving a block, the receiver goes into a one-second timeout + for each character and the checksum. If the receiver wishes to <nak> a + block for any reason (invalid header, timeout receiving data), it must + wait for the line to clear. See "programming tips" for ideas + + Synchronizing: If a valid block number is received, it will be: 1) the + expected one, in which case everything is fine; or 2) a repeat of the + previously received block. This should be considered OK, and only + indicates that the receivers <ack> got glitched, and the sender re- + transmitted; 3) any other block number indicates a fatal loss of + synchronization, such as the rare case of the sender getting a line-glitch + + + + Chapter 7 Xmodem Protocol Overview + + + + + + + + X/YMODEM Protocol Reference June 18 1988 22 + + + + that looked like an <ack>. Abort the transmission, sending a <can> + + + 7.3.3 Sending_program_considerations + While waiting for transmission to begin, the sender has only a single very + long timeout, say one minute. In the current protocol, the sender has a + 10 second timeout before retrying. I suggest NOT doing this, and letting + the protocol be completely receiver-driven. This will be compatible with + existing programs. + + When the sender has no more data, it sends an <eot>, and awaits an <ack>, + resending the <eot> if it doesn't get one. Again, the protocol could be + receiver-driven, with the sender only having the high-level 1-minute + timeout to abort. + + + Here is a sample of the data flow, sending a 3-block message. It includes + the two most common line hits - a garbaged block, and an <ack> reply + getting garbaged. <xx> represents the checksum byte. + + Figure 10. Data flow including Error Recovery + + SENDER RECEIVER + times out after 10 seconds, + <--- <nak> + <soh> 01 FE -data- <xx> ---> + <--- <ack> + <soh> 02 FD -data- xx ---> (data gets line hit) + <--- <nak> + <soh> 02 FD -data- xx ---> + <--- <ack> + <soh> 03 FC -data- xx ---> + (ack gets garbaged) <--- <ack> + <soh> 03 FC -data- xx ---> <ack> + <eot> ---> + <--- <anything except ack> + <eot> ---> + <--- <ack> + (finished) + + 7.4 Programming Tips + + + The character-receive subroutine should be called with a parameter + specifying the number of seconds to wait. The receiver should first + call it with a time of 10, then <nak> and try again, 10 times. + + After receiving the <soh>, the receiver should call the character + receive subroutine with a 1-second timeout, for the remainder of the + message and the <cksum>. Since they are sent as a continuous stream, + timing out of this implies a serious like glitch that caused, say, + 127 characters to be seen instead of 128. + + + + Chapter 7 Xmodem Protocol Overview + + + + + + + + X/YMODEM Protocol Reference June 18 1988 23 + + + + + When the receiver wishes to <nak>, it should call a "PURGE" + subroutine, to wait for the line to clear. Recall the sender tosses + any characters in its UART buffer immediately upon completing sending + a block, to ensure no glitches were mis- interpreted. + + The most common technique is for "PURGE" to call the character + receive subroutine, specifying a 1-second timeout,[1] and looping + back to PURGE until a timeout occurs. The <nak> is then sent, + ensuring the other end will see it. + + + You may wish to add code recommended by John Mahr to your character + receive routine - to set an error flag if the UART shows framing + error, or overrun. This will help catch a few more glitches - the + most common of which is a hit in the high bits of the byte in two + consecutive bytes. The <cksum> comes out OK since counting in 1-byte + produces the same result of adding 80H + 80H as with adding 00H + + 00H. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + __________ + + 1. These times should be adjusted for use with timesharing systems. + + + + + Chapter 7 Xmodem Protocol Overview + + + + + + + + X/YMODEM Protocol Reference June 18 1988 24 + + + + 8. XMODEM/CRC Overview + + Original 1/13/85 by John Byrns -- CRC option. + + Please pass on any reports of errors in this document or suggestions for + improvement to me via Ward's/CBBS at (312) 849-1132, or by voice at (312) + 885-1105. + + The CRC used in the Modem Protocol is an alternate form of block check + which provides more robust error detection than the original checksum. + Andrew S. Tanenbaum says in his book, Computer Networks, that the CRC- + CCITT used by the Modem Protocol will detect all single and double bit + errors, all errors with an odd number of bits, all burst errors of length + 16 or less, 99.997% of 17-bit error bursts, and 99.998% of 18-bit and + longer bursts.[1] + + The changes to the Modem Protocol to replace the checksum with the CRC are + straight forward. If that were all that we did we would not be able to + communicate between a program using the old checksum protocol and one + using the new CRC protocol. An initial handshake was added to solve this + problem. The handshake allows a receiving program with CRC capability to + determine whether the sending program supports the CRC option, and to + switch it to CRC mode if it does. This handshake is designed so that it + will work properly with programs which implement only the original + protocol. A description of this handshake is presented in section 10. + + Figure 11. Message Block Level Protocol, CRC mode + + Each block of the transfer in CRC mode looks like: + <SOH><blk #><255-blk #><--128 data bytes--><CRC hi><CRC lo> + in which: + <SOH> = 01 hex + <blk #> = binary number, starts at 01 increments by 1, and + wraps 0FFH to 00H (not to 01) + <255-blk #> = ones complement of blk #. + <CRC hi> = byte containing the 8 hi order coefficients of the CRC. + <CRC lo> = byte containing the 8 lo order coefficients of the CRC. + + 8.1 CRC Calculation + + 8.1.1 Formal_Definition + To calculate the 16 bit CRC the message bits are considered to be the + coefficients of a polynomial. This message polynomial is first multiplied + by X^16 and then divided by the generator polynomial (X^16 + X^12 + X^5 + + + + __________ + + 1. This reliability figure is misleading because XMODEM's critical + supervisory functions are not protected by this CRC. + + + + + Chapter 8 Xmodem Protocol Overview + + + + + + + + X/YMODEM Protocol Reference June 18 1988 25 + + + + 1) using modulo two arithmetic. The remainder left after the division is + the desired CRC. Since a message block in the Modem Protocol is 128 bytes + or 1024 bits, the message polynomial will be of order X^1023. The hi order + bit of the first byte of the message block is the coefficient of X^1023 in + the message polynomial. The lo order bit of the last byte of the message + block is the coefficient of X^0 in the message polynomial. + + Figure 12. Example of CRC Calculation written in C + + The following XMODEM crc routine is taken from "rbsb.c". Please refer to + the source code for these programs (contained in RZSZ.ZOO) for usage. A + fast table driven version is also included in this file. + + /* update CRC */ + unsigned short + updcrc(c, crc) + register c; + register unsigned crc; + { + register count; + + for (count=8; --count>=0;) { + if (crc & 0x8000) { + crc <<= 1; + crc += (((c<<=1) & 0400) != 0); + crc ^= 0x1021; + } + else { + crc <<= 1; + crc += (((c<<=1) & 0400) != 0); + } + } + return crc; + } + + 8.2 CRC File Level Protocol Changes + + 8.2.1 Common_to_Both_Sender_and_Receiver + The only change to the File Level Protocol for the CRC option is the + initial handshake which is used to determine if both the sending and the + receiving programs support the CRC mode. All Modem Programs should support + the checksum mode for compatibility with older versions. A receiving + program that wishes to receive in CRC mode implements the mode setting + handshake by sending a <C> in place of the initial <nak>. If the sending + program supports CRC mode it will recognize the <C> and will set itself + into CRC mode, and respond by sending the first block as if a <nak> had + been received. If the sending program does not support CRC mode it will + not respond to the <C> at all. After the receiver has sent the <C> it will + wait up to 3 seconds for the <soh> that starts the first block. If it + receives a <soh> within 3 seconds it will assume the sender supports CRC + mode and will proceed with the file exchange in CRC mode. If no <soh> is + + + + Chapter 8 Xmodem Protocol Overview + + + + + + + + X/YMODEM Protocol Reference June 18 1988 26 + + + + received within 3 seconds the receiver will switch to checksum mode, send + a <nak>, and proceed in checksum mode. If the receiver wishes to use + checksum mode it should send an initial <nak> and the sending program + should respond to the <nak> as defined in the original Modem Protocol. + After the mode has been set by the initial <C> or <nak> the protocol + follows the original Modem Protocol and is identical whether the checksum + or CRC is being used. + + + 8.2.2 Receive_Program_Considerations + There are at least 4 things that can go wrong with the mode setting + handshake. + + 1. the initial <C> can be garbled or lost. + + 2. the initial <soh> can be garbled. + + 3. the initial <C> can be changed to a <nak>. + + 4. the initial <nak> from a receiver which wants to receive in checksum + can be changed to a <C>. + + The first problem can be solved if the receiver sends a second <C> after + it times out the first time. This process can be repeated several times. + It must not be repeated too many times before sending a <nak> and + switching to checksum mode or a sending program without CRC support may + time out and abort. Repeating the <C> will also fix the second problem if + the sending program cooperates by responding as if a <nak> were received + instead of ignoring the extra <C>. + + It is possible to fix problems 3 and 4 but probably not worth the trouble + since they will occur very infrequently. They could be fixed by switching + modes in either the sending or the receiving program after a large number + of successive <nak>s. This solution would risk other problems however. + + + 8.2.3 Sending_Program_Considerations + The sending program should start in the checksum mode. This will insure + compatibility with checksum only receiving programs. Anytime a <C> is + received before the first <nak> or <ack> the sending program should set + itself into CRC mode and respond as if a <nak> were received. The sender + should respond to additional <C>s as if they were <nak>s until the first + <ack> is received. This will assist the receiving program in determining + the correct mode when the <soh> is lost or garbled. After the first <ack> + is received the sending program should ignore <C>s. + + + + + + + + + + Chapter 8 Xmodem Protocol Overview + + + + + + + + X/YMODEM Protocol Reference June 18 1988 27 + + + + 8.3 Data Flow Examples with CRC Option + + Here is a data flow example for the case where the receiver requests + transmission in the CRC mode but the sender does not support the CRC + option. This example also includes various transmission errors. <xx> + represents the checksum byte. + + Figure 13. Data Flow: Receiver has CRC Option, Sender Doesn't + + SENDER RECEIVER + <--- <C> + times out after 3 seconds, + <--- <C> + times out after 3 seconds, + <--- <C> + times out after 3 seconds, + <--- <C> + times out after 3 seconds, + <--- <nak> + <soh> 01 FE -data- <xx> ---> + <--- <ack> + <soh> 02 FD -data- <xx> ---> (data gets line hit) + <--- <nak> + <soh> 02 FD -data- <xx> ---> + <--- <ack> + <soh> 03 FC -data- <xx> ---> + (ack gets garbaged) <--- <ack> + times out after 10 seconds, + <--- <nak> + <soh> 03 FC -data- <xx> ---> + <--- <ack> + <eot> ---> + <--- <ack> + + Here is a data flow example for the case where the receiver requests + transmission in the CRC mode and the sender supports the CRC option. This + example also includes various transmission errors. <xxxx> represents the + 2 CRC bytes. + + + + + + + + + + + + + + + + + Chapter 8 Xmodem Protocol Overview + + + + + + + + X/YMODEM Protocol Reference June 18 1988 28 + + + + Figure 14. Receiver and Sender Both have CRC Option + + SENDER RECEIVER + <--- <C> + <soh> 01 FE -data- <xxxx> ---> + <--- <ack> + <soh> 02 FD -data- <xxxx> ---> (data gets line hit) + <--- <nak> + <soh> 02 FD -data- <xxxx> ---> + <--- <ack> + <soh> 03 FC -data- <xxxx> ---> + (ack gets garbaged) <--- <ack> + times out after 10 seconds, + <--- <nak> + <soh> 03 FC -data- <xxxx> ---> + <--- <ack> + <eot> ---> + <--- <ack> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Chapter 8 Xmodem Protocol Overview + + + + + + + + X/YMODEM Protocol Reference June 18 1988 29 + + + + 9. MORE INFORMATION + + Please contact Omen Technology for troff source files and typeset copies + of this document. + + + 9.1 TeleGodzilla Bulletin Board + + More information may be obtained by calling TeleGodzilla at 503-621-3746. + Speed detection is automatic for 1200, 2400 and 19200(Telebit PEP) bps. + TrailBlazer modem users may issue the TeleGodzilla trailblazer command to + swith to 19200 bps once they have logged in. + + Interesting files include RZSZ.ZOO (C source code), YZMODEM.ZOO (Official + XMODEM, YMODEM, and ZMODEM protocol descriptions), ZCOMMEXE.ARC, + ZCOMMDOC.ARC, and ZCOMMHLP.ARC (PC-DOS shareware comm program with XMODEM, + True YMODEM(TM), ZMODEM, Kermit Sliding Windows, Telink, MODEM7 Batch, + script language, etc.). + + + 9.2 Unix UUCP Access + + UUCP sites can obtain the current version of this file with + uucp omen!/u/caf/public/ymodem.doc /tmp + A continually updated list of available files is stored in + /usr/spool/uucppublic/FILES. When retrieving these files with uucp, + remember that the destination directory on your system must be writeable + by anyone, or the UUCP transfer will fail. + + The following L.sys line calls TeleGodzilla (Pro-YAM in host operation). + TeleGodzilla determines the incoming speed automatically. + + In response to "Name Please:" uucico gives the Pro-YAM "link" command as a + user name. The password (Giznoid) controls access to the Xenix system + connected to the IBM PC's other serial port. Communications between + Pro-YAM and Xenix use 9600 bps; YAM converts this to the caller's speed. + + Finally, the calling uucico logs in as uucp. + + omen Any ACU 2400 1-503-621-3746 se:--se: link ord: Giznoid in:--in: uucp + + + + 10. REVISIONS + + 6-18-88 Further revised for clarity. Corrected block numbering in two + examples. + 10-27-87 Optional fields added for number of files remaining to be sent + and total number of bytes remaining to be sent. + 10-18-87 Flow control discussion added to 1024 byte block descritpion, + minor revisions for clarity per user comments. + + + + Chapter 10 Xmodem Protocol Overview + + + + + + + + X/YMODEM Protocol Reference June 18 1988 30 + + + + 8-03-87 Revised for clarity. + 5-31-1987 emphasizes minimum requirements for YMODEM, and updates + information on accessing files. + 9-11-1986 clarifies nomenclature and some minor points. + The April 15 1986 edition clarifies some points concerning CRC + calculations and spaces in the header. + + + 11. YMODEM Programs + + ZCOMM, A shareware little brother to Professional-YAM, is available as + ZCOMMEXE.ARC on TeleGodzilla and other bulletin board systems. ZCOMM may + be used to test YMODEM amd ZMODEM implementations. + + Unix programs supporting YMODEM are available on TeleGodzilla in RZSZ.ZOO. + This ZOO archive includes a ZCOMM/Pro-YAM/PowerCom script ZUPL.T to upload + a bootstrap program MINIRB.C, compile it, and then upload the rest of the + files using the compiled MINIRB. Most Unix like systems are supported, + including V7, Xenix, Sys III, 4.2 BSD, SYS V, Idris, Coherent, and + Regulus. + + A version for VAX-VMS is available in VRBSB.SHQ. + + Irv Hoff has added 1k blocks and basic YMODEM batch transfers to the KMD + and IMP series programs, which replace the XMODEM and MODEM7/MDM7xx series + respectively. Overlays are available for a wide variety of CP/M systems. + + Questions about Professional-YAM communications software may be directed + to: + Chuck Forsberg + Omen Technology Inc + 17505-V Sauvie Island Road + Portland Oregon 97231 + VOICE: 503-621-3406 :VOICE + Modem: 503-621-3746 Speed: 19200(Telebit PEP),2400,1200,300 + Usenet: ...!tektronix!reed!omen!caf + CompuServe: 70007,2304 + GEnie: CAF + + Unlike ZMODEM and Kermit, XMODEM and YMODEM place obstacles in the path of + a reliable high performance implementation, evidenced by poor reliability + under stress of the industry leaders' XMODEM and YMODEM programs. Omen + Technology provides consulting and other services to those wishing to + implement XMODEM, YMODEM, and ZMODEM with state of the art features and + reliability. + + + + + + + + + + Chapter 11 Xmodem Protocol Overview + + + + + + + + + + + + CONTENTS + + + 1. TOWER OF BABEL................................................... 2 + 1.1 Definitions................................................. 2 + + 2. YMODEM MINIMUM REQUIREMENTS...................................... 4 + + 3. WHY YMODEM?...................................................... 6 + 3.1 Some Messages from the Pioneer.............................. 7 + + 4. XMODEM PROTOCOL ENHANCEMENTS..................................... 10 + 4.1 Graceful Abort.............................................. 10 + 4.2 CRC-16 Option............................................... 10 + 4.3 XMODEM-1k 1024 Byte Block................................... 11 + + 5. YMODEM Batch File Transmission................................... 13 + 5.1 KMD/IMP Exceptions to YMODEM................................ 16 + + 6. YMODEM-g File Transmission....................................... 18 + + 7. XMODEM PROTOCOL OVERVIEW......................................... 20 + 7.1 Definitions................................................. 20 + 7.2 Transmission Medium Level Protocol.......................... 20 + 7.3 File Level Protocol......................................... 21 + 7.4 Programming Tips............................................ 22 + + 8. XMODEM/CRC Overview.............................................. 24 + 8.1 CRC Calculation............................................. 24 + 8.2 CRC File Level Protocol Changes............................. 25 + 8.3 Data Flow Examples with CRC Option.......................... 27 + + 9. MORE INFORMATION................................................. 29 + 9.1 TeleGodzilla Bulletin Board................................. 29 + 9.2 Unix UUCP Access............................................ 29 + + 10. REVISIONS........................................................ 29 + + 11. YMODEM Programs.................................................. 30 + + + + + + + + + + + + + + + + - i - + + + + + + + + + + + + + + + LIST OF FIGURES + + + Figure 1. XMODEM-1k Blocks.......................................... 12 + + Figure 2. Mixed 1024 and 128 byte Blocks............................ 12 + + Figure 3. YMODEM Batch Transmission Session (1 file)................ 16 + + Figure 4. YMODEM Batch Transmission Session (2 files)............... 16 + + Figure 5. YMODEM Batch Transmission Session-1k Blocks............... 16 + + Figure 6. YMODEM Filename block transmitted by sz................... 16 + + Figure 7. YMODEM Header Information and Features.................... 16 + + Figure 8. YMODEM-g Transmission Session............................. 19 + + Figure 9. XMODEM Message Block Level Protocol....................... 21 + + Figure 10. Data flow including Error Recovery........................ 22 + + Figure 11. Message Block Level Protocol, CRC mode.................... 24 + + Figure 12. Example of CRC Calculation written in C................... 25 + + Figure 13. Data Flow: Receiver has CRC Option, Sender Doesn't........ 27 + + Figure 14. Receiver and Sender Both have CRC Option.................. 28 + + + + + + + + + + + + + + + + + + + + + + - ii - diff --git a/contrib/syslinux-4.02/com32/sysdump/zout.c b/contrib/syslinux-4.02/com32/sysdump/zout.c new file mode 100644 index 0000000..ece934c --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/zout.c @@ -0,0 +1,99 @@ +/* + * Compress input and feed it to a block-oriented back end. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <inttypes.h> +#include <stdbool.h> +#include <zlib.h> +#include "backend.h" +#include "ctime.h" + +#define ALLOC_CHUNK 65536 + +int init_data(struct backend *be, const char *argv[]) +{ + be->now = posix_time(); + be->argv = argv; + + memset(&be->zstream, 0, sizeof be->zstream); + + be->zstream.next_out = NULL; + be->outbuf = NULL; + be->zstream.avail_out = be->alloc = 0; + be->dbytes = be->zbytes = 0; + + /* Initialize a gzip data stream */ + if (deflateInit2(&be->zstream, 9, Z_DEFLATED, + 16+15, 9, Z_DEFAULT_STRATEGY) < 0) + return -1; + + return 0; +} + +static int do_deflate(struct backend *be, int flush) +{ + int rv; + char *buf; + + while (1) { + rv = deflate(&be->zstream, flush); + be->zbytes = be->alloc - be->zstream.avail_out; + if (be->zstream.avail_out) + return rv; /* Not an issue of output space... */ + + buf = realloc(be->outbuf, be->alloc + ALLOC_CHUNK); + if (!buf) + return Z_MEM_ERROR; + be->outbuf = buf; + be->alloc += ALLOC_CHUNK; + be->zstream.next_out = (void *)(buf + be->zbytes); + be->zstream.avail_out = be->alloc - be->zbytes; + } +} + + +int write_data(struct backend *be, const void *buf, size_t len) +{ + int rv = Z_OK; + + be->zstream.next_in = (void *)buf; + be->zstream.avail_in = len; + + be->dbytes += len; + + while (be->zstream.avail_in) { + rv = do_deflate(be, Z_NO_FLUSH); + if (rv < 0) { + printf("do_deflate returned %d\n", rv); + return -1; + } + } + return 0; +} + +/* Output the data and shut down the stream */ +int flush_data(struct backend *be) +{ + int rv = Z_OK; + + while (rv != Z_STREAM_END) { + rv = do_deflate(be, Z_FINISH); + if (rv < 0) + return -1; + } + + printf("Uploading data, %u bytes... ", be->zbytes); + + if (be->write(be)) + return -1; + + free(be->outbuf); + be->outbuf = NULL; + be->dbytes = be->zbytes = be->alloc = 0; + + printf("done.\n"); + return 0; +} diff --git a/contrib/syslinux-4.02/com32/tools/.gitignore b/contrib/syslinux-4.02/com32/tools/.gitignore new file mode 100644 index 0000000..b5397de --- /dev/null +++ b/contrib/syslinux-4.02/com32/tools/.gitignore @@ -0,0 +1 @@ +/relocs diff --git a/contrib/syslinux-4.02/com32/tools/Makefile b/contrib/syslinux-4.02/com32/tools/Makefile new file mode 100644 index 0000000..e34296b --- /dev/null +++ b/contrib/syslinux-4.02/com32/tools/Makefile @@ -0,0 +1,30 @@ +## -*- makefile -*- ------------------------------------------------------ +## +## 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. +## +## ----------------------------------------------------------------------- + +topdir = ../.. +include $(topdir)/MCONFIG.build + +BINS = relocs + +all : $(BINS) + +relocs : relocs.o + $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) + +tidy dist clean spotless: + rm -f $(BINS) + rm -f *.o *.a .*.d + rm -f */*.o */*.a */.*.d + +install installer: + +-include .*.d */.*.d diff --git a/contrib/syslinux-4.02/com32/tools/relocs.c b/contrib/syslinux-4.02/com32/tools/relocs.c new file mode 100644 index 0000000..be57bf7 --- /dev/null +++ b/contrib/syslinux-4.02/com32/tools/relocs.c @@ -0,0 +1,693 @@ +/* + * This file is taken from the Linux kernel and is distributed under GPL v2. + */ +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <elf.h> +#include <byteswap.h> +#define USE_BSD +#include <endian.h> +#include <regex.h> +#include <sys/types.h> + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +static Elf32_Ehdr ehdr; +static unsigned long reloc_count, reloc_idx; +static unsigned long *relocs; + +struct section { + Elf32_Shdr shdr; + struct section *link; + Elf32_Sym *symtab; + Elf32_Rel *reltab; + char *strtab; +}; +static struct section *secs; + +static void die(char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + exit(1); +} + +/* + * Following symbols have been audited. Don't warn user about + * absolute relocations present w.r.t these symbols. + */ + +/* True absolute relocations */ + +static const char safe_abs_regex[] = +"^(__.*_len|__.*_dwords)$"; +static regex_t safe_abs_regex_c; + +static int is_safe_abs_reloc(const char *sym_name) +{ + return !regexec(&safe_abs_regex_c, sym_name, 0, NULL, 0); +} + +/* These are relative even though the linker marks them absolute */ + +static const char safe_rel_regex[] = +"^(__.*_start|__.*_end|_end|_[se](text|data))$"; +static regex_t safe_rel_regex_c; + +static int is_safe_rel_reloc(const char *sym_name) +{ + return !regexec(&safe_rel_regex_c, sym_name, 0, NULL, 0); +} + +static void regex_init(void) +{ + char errbuf[128]; + int err; + + err = regcomp(&safe_abs_regex_c, safe_abs_regex, + REG_EXTENDED|REG_NOSUB); + if (err) { + regerror(err, &safe_abs_regex_c, errbuf, sizeof errbuf); + die("%s", errbuf); + } + + err = regcomp(&safe_rel_regex_c, safe_rel_regex, + REG_EXTENDED|REG_NOSUB); + if (err) { + regerror(err, &safe_rel_regex_c, errbuf, sizeof errbuf); + die("%s", errbuf); + } +} + +static const char *sym_type(unsigned type) +{ + static const char *type_name[] = { +#define SYM_TYPE(X) [X] = #X + SYM_TYPE(STT_NOTYPE), + SYM_TYPE(STT_OBJECT), + SYM_TYPE(STT_FUNC), + SYM_TYPE(STT_SECTION), + SYM_TYPE(STT_FILE), + SYM_TYPE(STT_COMMON), + SYM_TYPE(STT_TLS), +#undef SYM_TYPE + }; + const char *name = "unknown sym type name"; + if (type < ARRAY_SIZE(type_name)) { + name = type_name[type]; + } + return name; +} + +static const char *sym_bind(unsigned bind) +{ + static const char *bind_name[] = { +#define SYM_BIND(X) [X] = #X + SYM_BIND(STB_LOCAL), + SYM_BIND(STB_GLOBAL), + SYM_BIND(STB_WEAK), +#undef SYM_BIND + }; + const char *name = "unknown sym bind name"; + if (bind < ARRAY_SIZE(bind_name)) { + name = bind_name[bind]; + } + return name; +} + +static const char *sym_visibility(unsigned visibility) +{ + static const char *visibility_name[] = { +#define SYM_VISIBILITY(X) [X] = #X + SYM_VISIBILITY(STV_DEFAULT), + SYM_VISIBILITY(STV_INTERNAL), + SYM_VISIBILITY(STV_HIDDEN), + SYM_VISIBILITY(STV_PROTECTED), +#undef SYM_VISIBILITY + }; + const char *name = "unknown sym visibility name"; + if (visibility < ARRAY_SIZE(visibility_name)) { + name = visibility_name[visibility]; + } + return name; +} + +static const char *rel_type(unsigned type) +{ + static const char *type_name[] = { +#define REL_TYPE(X) [X] = #X + REL_TYPE(R_386_NONE), + REL_TYPE(R_386_32), + REL_TYPE(R_386_PC32), + REL_TYPE(R_386_GOT32), + REL_TYPE(R_386_PLT32), + REL_TYPE(R_386_COPY), + REL_TYPE(R_386_GLOB_DAT), + REL_TYPE(R_386_JMP_SLOT), + REL_TYPE(R_386_RELATIVE), + REL_TYPE(R_386_GOTOFF), + REL_TYPE(R_386_GOTPC), +#undef REL_TYPE + }; + const char *name = NULL; + if (type < ARRAY_SIZE(type_name)) + name = type_name[type]; + if (!name) + name = "unknown"; + return name; +} + +static const char *sec_name(unsigned shndx) +{ + const char *sec_strtab; + const char *name; + sec_strtab = secs[ehdr.e_shstrndx].strtab; + name = "<noname>"; + if (shndx < ehdr.e_shnum) { + name = sec_strtab + secs[shndx].shdr.sh_name; + } + else if (shndx == SHN_ABS) { + name = "ABSOLUTE"; + } + else if (shndx == SHN_COMMON) { + name = "COMMON"; + } + return name; +} + +static const char *sym_name(const char *sym_strtab, Elf32_Sym *sym) +{ + const char *name; + name = "<noname>"; + if (sym->st_name) { + name = sym_strtab + sym->st_name; + } + else { + name = sec_name(secs[sym->st_shndx].shdr.sh_name); + } + return name; +} + + + +#if BYTE_ORDER == LITTLE_ENDIAN +#define le16_to_cpu(val) (val) +#define le32_to_cpu(val) (val) +#endif +#if BYTE_ORDER == BIG_ENDIAN +#define le16_to_cpu(val) bswap_16(val) +#define le32_to_cpu(val) bswap_32(val) +#endif + +static uint16_t elf16_to_cpu(uint16_t val) +{ + return le16_to_cpu(val); +} + +static uint32_t elf32_to_cpu(uint32_t val) +{ + return le32_to_cpu(val); +} + +static void read_ehdr(FILE *fp) +{ + if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1) { + die("Cannot read ELF header: %s\n", + strerror(errno)); + } + if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0) { + die("No ELF magic\n"); + } + if (ehdr.e_ident[EI_CLASS] != ELFCLASS32) { + die("Not a 32 bit executable\n"); + } + if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB) { + die("Not a LSB ELF executable\n"); + } + if (ehdr.e_ident[EI_VERSION] != EV_CURRENT) { + die("Unknown ELF version\n"); + } + /* Convert the fields to native endian */ + ehdr.e_type = elf16_to_cpu(ehdr.e_type); + ehdr.e_machine = elf16_to_cpu(ehdr.e_machine); + ehdr.e_version = elf32_to_cpu(ehdr.e_version); + ehdr.e_entry = elf32_to_cpu(ehdr.e_entry); + ehdr.e_phoff = elf32_to_cpu(ehdr.e_phoff); + ehdr.e_shoff = elf32_to_cpu(ehdr.e_shoff); + ehdr.e_flags = elf32_to_cpu(ehdr.e_flags); + ehdr.e_ehsize = elf16_to_cpu(ehdr.e_ehsize); + ehdr.e_phentsize = elf16_to_cpu(ehdr.e_phentsize); + ehdr.e_phnum = elf16_to_cpu(ehdr.e_phnum); + ehdr.e_shentsize = elf16_to_cpu(ehdr.e_shentsize); + ehdr.e_shnum = elf16_to_cpu(ehdr.e_shnum); + ehdr.e_shstrndx = elf16_to_cpu(ehdr.e_shstrndx); + + if ((ehdr.e_type != ET_EXEC) && (ehdr.e_type != ET_DYN)) { + die("Unsupported ELF header type\n"); + } + if (ehdr.e_machine != EM_386) { + die("Not for x86\n"); + } + if (ehdr.e_version != EV_CURRENT) { + die("Unknown ELF version\n"); + } + if (ehdr.e_ehsize != sizeof(Elf32_Ehdr)) { + die("Bad Elf header size\n"); + } + if (ehdr.e_phentsize != sizeof(Elf32_Phdr)) { + die("Bad program header entry\n"); + } + if (ehdr.e_shentsize != sizeof(Elf32_Shdr)) { + die("Bad section header entry\n"); + } + if (ehdr.e_shstrndx >= ehdr.e_shnum) { + die("String table index out of bounds\n"); + } +} + +static void read_shdrs(FILE *fp) +{ + int i; + Elf32_Shdr shdr; + + secs = calloc(ehdr.e_shnum, sizeof(struct section)); + if (!secs) { + die("Unable to allocate %d section headers\n", + ehdr.e_shnum); + } + if (fseek(fp, ehdr.e_shoff, SEEK_SET) < 0) { + die("Seek to %d failed: %s\n", + ehdr.e_shoff, strerror(errno)); + } + for (i = 0; i < ehdr.e_shnum; i++) { + struct section *sec = &secs[i]; + if (fread(&shdr, sizeof shdr, 1, fp) != 1) + die("Cannot read ELF section headers %d/%d: %s\n", + i, ehdr.e_shnum, strerror(errno)); + sec->shdr.sh_name = elf32_to_cpu(shdr.sh_name); + sec->shdr.sh_type = elf32_to_cpu(shdr.sh_type); + sec->shdr.sh_flags = elf32_to_cpu(shdr.sh_flags); + sec->shdr.sh_addr = elf32_to_cpu(shdr.sh_addr); + sec->shdr.sh_offset = elf32_to_cpu(shdr.sh_offset); + sec->shdr.sh_size = elf32_to_cpu(shdr.sh_size); + sec->shdr.sh_link = elf32_to_cpu(shdr.sh_link); + sec->shdr.sh_info = elf32_to_cpu(shdr.sh_info); + sec->shdr.sh_addralign = elf32_to_cpu(shdr.sh_addralign); + sec->shdr.sh_entsize = elf32_to_cpu(shdr.sh_entsize); + if (sec->shdr.sh_link < ehdr.e_shnum) + sec->link = &secs[sec->shdr.sh_link]; + } + +} + +static void read_strtabs(FILE *fp) +{ + int i; + for (i = 0; i < ehdr.e_shnum; i++) { + struct section *sec = &secs[i]; + if (sec->shdr.sh_type != SHT_STRTAB) { + continue; + } + sec->strtab = malloc(sec->shdr.sh_size); + if (!sec->strtab) { + die("malloc of %d bytes for strtab failed\n", + sec->shdr.sh_size); + } + if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) { + die("Seek to %d failed: %s\n", + sec->shdr.sh_offset, strerror(errno)); + } + if (fread(sec->strtab, 1, sec->shdr.sh_size, fp) + != sec->shdr.sh_size) { + die("Cannot read symbol table: %s\n", + strerror(errno)); + } + } +} + +static void read_symtabs(FILE *fp) +{ + int i,j; + for (i = 0; i < ehdr.e_shnum; i++) { + struct section *sec = &secs[i]; + if (sec->shdr.sh_type != SHT_SYMTAB) { + continue; + } + sec->symtab = malloc(sec->shdr.sh_size); + if (!sec->symtab) { + die("malloc of %d bytes for symtab failed\n", + sec->shdr.sh_size); + } + if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) { + die("Seek to %d failed: %s\n", + sec->shdr.sh_offset, strerror(errno)); + } + if (fread(sec->symtab, 1, sec->shdr.sh_size, fp) + != sec->shdr.sh_size) { + die("Cannot read symbol table: %s\n", + strerror(errno)); + } + for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Sym); j++) { + Elf32_Sym *sym = &sec->symtab[j]; + sym->st_name = elf32_to_cpu(sym->st_name); + sym->st_value = elf32_to_cpu(sym->st_value); + sym->st_size = elf32_to_cpu(sym->st_size); + sym->st_shndx = elf16_to_cpu(sym->st_shndx); + } + } +} + + +static void read_relocs(FILE *fp) +{ + int i,j; + for (i = 0; i < ehdr.e_shnum; i++) { + struct section *sec = &secs[i]; + if (sec->shdr.sh_type != SHT_REL) { + continue; + } + sec->reltab = malloc(sec->shdr.sh_size); + if (!sec->reltab) { + die("malloc of %d bytes for relocs failed\n", + sec->shdr.sh_size); + } + if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) { + die("Seek to %d failed: %s\n", + sec->shdr.sh_offset, strerror(errno)); + } + if (fread(sec->reltab, 1, sec->shdr.sh_size, fp) + != sec->shdr.sh_size) { + die("Cannot read symbol table: %s\n", + strerror(errno)); + } + for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) { + Elf32_Rel *rel = &sec->reltab[j]; + rel->r_offset = elf32_to_cpu(rel->r_offset); + rel->r_info = elf32_to_cpu(rel->r_info); + } + } +} + + +static void print_absolute_symbols(void) +{ + int i; + printf("Absolute symbols\n"); + printf(" Num: Value Size Type Bind Visibility Name\n"); + for (i = 0; i < ehdr.e_shnum; i++) { + struct section *sec = &secs[i]; + char *sym_strtab; + Elf32_Sym *sh_symtab; + int j; + + if (sec->shdr.sh_type != SHT_SYMTAB) { + continue; + } + sh_symtab = sec->symtab; + sym_strtab = sec->link->strtab; + for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Sym); j++) { + Elf32_Sym *sym; + const char *name; + sym = &sec->symtab[j]; + name = sym_name(sym_strtab, sym); + if (sym->st_shndx != SHN_ABS) { + continue; + } + printf("%5d %08x %5d %10s %10s %12s %s\n", + j, sym->st_value, sym->st_size, + sym_type(ELF32_ST_TYPE(sym->st_info)), + sym_bind(ELF32_ST_BIND(sym->st_info)), + sym_visibility(ELF32_ST_VISIBILITY(sym->st_other)), + name); + } + } + printf("\n"); +} + +static int print_absolute_relocs(FILE *f) +{ + int i, printed = 0; + + for (i = 0; i < ehdr.e_shnum; i++) { + struct section *sec = &secs[i]; + struct section *sec_applies, *sec_symtab; + char *sym_strtab; + Elf32_Sym *sh_symtab; + int j; + if (sec->shdr.sh_type != SHT_REL) { + continue; + } + sec_symtab = sec->link; + sec_applies = &secs[sec->shdr.sh_info]; + if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) { + continue; + } + sh_symtab = sec_symtab->symtab; + sym_strtab = sec_symtab->link->strtab; + for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) { + Elf32_Rel *rel; + Elf32_Sym *sym; + const char *name; + rel = &sec->reltab[j]; + sym = &sh_symtab[ELF32_R_SYM(rel->r_info)]; + name = sym_name(sym_strtab, sym); + if (sym->st_shndx != SHN_ABS) { + continue; + } + + /* Absolute symbols are not relocated if bzImage is + * loaded at a non-compiled address. Display a warning + * to user at compile time about the absolute + * relocations present. + * + * User need to audit the code to make sure + * some symbols which should have been section + * relative have not become absolute because of some + * linker optimization or wrong programming usage. + * + * Before warning check if this absolute symbol + * relocation is harmless. + */ + if (is_safe_abs_reloc(name) || + is_safe_rel_reloc(name)) + continue; + + if (!printed) { + fprintf(f, "Unknown absolute relocations present\n"); + fprintf(f, "Offset Info Type Sym.Value Sym.Name\n"); + printed = 1; + } + + fprintf(f, "%08x %08x %10s %08x %s\n", + rel->r_offset, + rel->r_info, + rel_type(ELF32_R_TYPE(rel->r_info)), + sym->st_value, + name); + } + } + + if (printed) + fputc('\n', f); + + return printed; +} + +static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym)) +{ + int i; + /* Walk through the relocations */ + for (i = 0; i < ehdr.e_shnum; i++) { + char *sym_strtab; + Elf32_Sym *sh_symtab; + struct section *sec_applies, *sec_symtab; + int j; + struct section *sec = &secs[i]; + + if (sec->shdr.sh_type != SHT_REL) { + continue; + } + sec_symtab = sec->link; + sec_applies = &secs[sec->shdr.sh_info]; + if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) { + continue; + } + sh_symtab = sec_symtab->symtab; + sym_strtab = sec_symtab->link->strtab; + for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) { + Elf32_Rel *rel; + Elf32_Sym *sym; + unsigned r_type; + rel = &sec->reltab[j]; + sym = &sh_symtab[ELF32_R_SYM(rel->r_info)]; + r_type = ELF32_R_TYPE(rel->r_info); + /* Don't visit relocations to absolute symbols */ + if (sym->st_shndx == SHN_ABS && + !is_safe_rel_reloc(sym_name(sym_strtab, sym))) + continue; + + switch (r_type) { + case R_386_NONE: + case R_386_PC32: + case R_386_GOTPC: + case R_386_GOTOFF: + case R_386_GOT32: + case R_386_PLT32: + /* Relative relocations don't need to + be adjusted */ + break; + case R_386_32: + /* Visit relocations that need adjustment */ + visit(rel, sym); + break; + default: + die("Unsupported relocation type: %s (%d)\n", + rel_type(r_type), r_type); + } + } + } +} + +static void count_reloc(Elf32_Rel *rel, Elf32_Sym *sym) +{ + (void)rel; (void)sym; + reloc_count += 1; +} + +static void collect_reloc(Elf32_Rel *rel, Elf32_Sym *sym) +{ + (void)sym; + + /* Remember the address that needs to be adjusted. */ + relocs[reloc_idx++] = rel->r_offset; +} + +static int cmp_relocs(const void *va, const void *vb) +{ + const unsigned long *a, *b; + a = va; b = vb; + return (*a == *b)? 0 : (*a > *b)? 1 : -1; +} + +static void emit_relocs(int as_text) +{ + int i; + /* Count how many relocations I have and allocate space for them. */ + reloc_count = 0; + walk_relocs(count_reloc); + relocs = malloc(reloc_count * sizeof(relocs[0])); + if (!relocs) { + die("malloc of %d entries for relocs failed\n", + reloc_count); + } + /* Collect up the relocations */ + reloc_idx = 0; + walk_relocs(collect_reloc); + + /* Order the relocations for more efficient processing */ + qsort(relocs, reloc_count, sizeof(relocs[0]), cmp_relocs); + + /* Print the relocations */ + if (as_text) { + /* Print the relocations in a form suitable that + * gas will like. + */ + printf(".section \".data.reloc\",\"a\"\n"); + printf(".balign 4\n"); + for (i = 0; i < reloc_count; i++) { + printf("\t .long 0x%08lx\n", relocs[i]); + } + printf("\n"); + } + else { + unsigned char buf[4]; + /* Now print each relocation */ + for (i = 0; i < reloc_count; i++) { + buf[0] = (relocs[i] >> 0) & 0xff; + buf[1] = (relocs[i] >> 8) & 0xff; + buf[2] = (relocs[i] >> 16) & 0xff; + buf[3] = (relocs[i] >> 24) & 0xff; + fwrite(buf, 4, 1, stdout); + } + /* Print a stop */ + memset(buf, 0, sizeof buf); + fwrite(buf, 4, 1, stdout); + } +} + +static void usage(void) +{ + die("relocs [--abs-syms |--abs-relocs | --text] vmlinux\n"); +} + +int main(int argc, char **argv) +{ + int show_absolute_syms, show_absolute_relocs; + int as_text; + const char *fname; + FILE *fp; + int i; + int err = 0; + + show_absolute_syms = 0; + show_absolute_relocs = 0; + as_text = 0; + fname = NULL; + for (i = 1; i < argc; i++) { + char *arg = argv[i]; + if (*arg == '-') { + if (strcmp(argv[1], "--abs-syms") == 0) { + show_absolute_syms = 1; + continue; + } + + if (strcmp(argv[1], "--abs-relocs") == 0) { + show_absolute_relocs = 1; + continue; + } + else if (strcmp(argv[1], "--text") == 0) { + as_text = 1; + continue; + } + } + else if (!fname) { + fname = arg; + continue; + } + usage(); + } + if (!fname) { + usage(); + } + + + regex_init(); + + fp = fopen(fname, "r"); + if (!fp) { + die("Cannot open %s: %s\n", + fname, strerror(errno)); + } + read_ehdr(fp); + read_shdrs(fp); + read_strtabs(fp); + read_symtabs(fp); + read_relocs(fp); + if (show_absolute_syms) { + print_absolute_symbols(); + return 0; + } + if (show_absolute_relocs) { + print_absolute_relocs(stdout); + return 0; + } + err = print_absolute_relocs(stderr); + emit_relocs(as_text); + return err; +} |